diff options
Diffstat (limited to 'engines')
262 files changed, 7724 insertions, 8891 deletions
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index c127faec28..7d86f3ef32 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -291,15 +291,18 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) } } - if (agdDesc == 0) { + if (agdDesc == 0) return Common::kNoGameDataFoundError; - } + + // If the GUI options were updated, we catch this here and update them in the users config + // file transparently. + Common::updateGameGUIOptions(agdDesc->guioptions | params.guioptions); debug(2, "Running %s", toGameDescriptor(*agdDesc, params.list).description().c_str()); - if (!createInstance(syst, engine, agdDesc)) { + if (!createInstance(syst, engine, agdDesc)) return Common::kNoGameDataFoundError; - } - return Common::kNoError; + else + return Common::kNoError; } struct SizeMD5 { diff --git a/engines/agi/agi.h b/engines/agi/agi.h index 7cf89fa592..14e1fd448b 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -993,7 +993,7 @@ public: bool predictiveDialog(void); private: - void printStatus(const char *message, ...); + void printStatus(const char *message, ...) GCC_PRINTF(2, 3); void printText2(int l, const char *msg, int foff, int xoff, int yoff, int len, int fg, int bg, bool checkerboard = false); void blitTextbox(const char *p, int y, int x, int len); void eraseTextbox(); diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp index ad2c264184..3461bb473e 100644 --- a/engines/agi/graphics.cpp +++ b/engines/agi/graphics.cpp @@ -846,7 +846,7 @@ void GfxMgr::setAGIPal(int p0) { //Chunks4-7 are duplicates of chunks0-3 - if (agipal.ioFailed()) { + if (agipal.eos() || agipal.err()) { warning("Couldn't read AGIPAL palette from '%s'. Not changing palette", filename); return; } diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index 97255097bc..7012174c20 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -1256,7 +1256,7 @@ cmd(restart_game) { int sel; g_sound->stopSound(); - sel = g_agi->getflag(fAutoRestart) ? 1 : + sel = g_agi->getflag(fAutoRestart) ? 0 : g_agi->selectionBox(" Restart game, or continue? \n\n\n", buttons); if (sel == 0) { diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index fb73c6b71f..5a39b663a5 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -133,7 +133,7 @@ bool IIgsEnvelope::read(Common::SeekableReadStream &stream) { seg[segNum].inc = stream.readUint16LE(); } - return !stream.ioFailed(); + return !(stream.eos() || stream.err()); } /** Reads an Apple IIGS wave information structure from the given stream. */ @@ -154,7 +154,7 @@ bool IIgsWaveInfo::read(Common::SeekableReadStream &stream, bool ignoreAddr) { if (ignoreAddr) addr = 0; - return !stream.ioFailed(); + return !(stream.eos() || stream.err()); } bool IIgsWaveInfo::finalize(Common::SeekableReadStream &uint8Wave) { @@ -219,7 +219,7 @@ bool IIgsInstrumentHeader::read(Common::SeekableReadStream &stream, bool ignoreA byte wac = stream.readByte(); // Read A wave count byte wbc = stream.readByte(); // Read B wave count oscList.read(stream, wac, ignoreAddr); // Read the oscillators - return (wac == wbc) && !stream.ioFailed(); // A and B wave counts must match + return (wac == wbc) && !(stream.eos() || stream.err()); // A and B wave counts must match } bool IIgsInstrumentHeader::finalize(Common::SeekableReadStream &uint8Wave) { @@ -1158,7 +1158,7 @@ bool SoundMgr::convertWave(Common::SeekableReadStream &source, int8 *dest, uint // Convert the wave from 8-bit unsigned to 8-bit signed format for (uint i = 0; i < length; i++) dest[i] = (int8) ((int) source.readByte() - 128); - return !source.ioFailed(); + return !(source.eos() || source.err()); } bool IIgsSoundMgr::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo) { diff --git a/engines/agi/wagparser.cpp b/engines/agi/wagparser.cpp index e6ed5345e0..d243439dff 100644 --- a/engines/agi/wagparser.cpp +++ b/engines/agi/wagparser.cpp @@ -70,7 +70,7 @@ bool WagProperty::read(Common::SeekableReadStream &stream) { _propNum = stream.readByte(); _propSize = stream.readUint16LE(); - if (stream.ioFailed()) { // Check that we got the whole header + if (stream.eos() || stream.err()) { // Check that we got the whole header _readOk = false; return _readOk; } diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index cdbeeecd8e..9903952577 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -33,6 +33,8 @@ #include "agos/agos.h" #include "agos/vga.h" +#include "graphics/surface.h" + #include "sound/mididrv.h" #include "sound/mods/protracker.h" #include "sound/audiocd.h" @@ -182,8 +184,6 @@ AGOSEngine::AGOSEngine(OSystem *syst) _subroutineList = 0; - _dxSurfacePitch = 0; - _recursionDepth = 0; _lastVgaTick = 0; @@ -490,12 +490,12 @@ AGOSEngine::AGOSEngine(OSystem *syst) _backGroundBuf = 0; _backBuf = 0; _scaleBuf = 0; + _window4BackScn = 0; + _window6BackScn = 0; _window3Flag = 0; _window4Flag = 0; _window6Flag = 0; - _window4BackScn = 0; - _window6BackScn = 0; _moveXMin = 0; _moveYMin = 0; @@ -580,26 +580,34 @@ Common::Error AGOSEngine::init() { syncSoundSettings(); // allocate buffers - _backGroundBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); + _backGroundBuf = new Graphics::Surface(); + _backGroundBuf->create(_screenWidth, _screenHeight, 1); if (getGameType() == GType_FF || getGameType() == GType_PP) { - _backBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); - _scaleBuf = (byte *)calloc(_screenWidth * _screenHeight, 1); + _backBuf = new Graphics::Surface(); + _backBuf->create(_screenWidth, _screenHeight, 1); + _scaleBuf = new Graphics::Surface(); + _scaleBuf->create(_screenWidth, _screenHeight, 1); } if (getGameType() == GType_SIMON2) { - _window4BackScn = (byte *)calloc(_screenWidth * _screenHeight, 1); + _window4BackScn = new Graphics::Surface(); + _window4BackScn->create(_screenWidth, _screenHeight, 1); } else if (getGameType() == GType_SIMON1) { - _window4BackScn = (byte *)calloc(_screenWidth * 134, 1); + _window4BackScn = new Graphics::Surface(); + _window4BackScn->create(_screenWidth, 134, 1); } else if (getGameType() == GType_WW || getGameType() == GType_ELVIRA2) { - _window4BackScn = (byte *)calloc(224 * 127, 1); + _window4BackScn = new Graphics::Surface(); + _window4BackScn->create(224, 127, 1); } else if (getGameType() == GType_ELVIRA1) { + _window4BackScn = new Graphics::Surface(); if (getPlatform() == Common::kPlatformAmiga && (getFeatures() & GF_DEMO)) { - _window4BackScn = (byte *)calloc(224 * 196, 1); + _window4BackScn->create(224, 196, 1); } else { - _window4BackScn = (byte *)calloc(224 * 144, 1); + _window4BackScn->create(224, 144, 1); } - _window6BackScn = (byte *)calloc(48 * 80, 1); + _window6BackScn = new Graphics::Surface(); + _window6BackScn->create(48, 80, 1); } setupGame(); diff --git a/engines/agos/agos.h b/engines/agos/agos.h index 405ee3622c..263811b78a 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -276,8 +276,6 @@ protected: Subroutine *_subroutineList; - uint16 _dxSurfacePitch; - uint8 _recursionDepth; uint32 _lastVgaTick; @@ -527,8 +525,6 @@ protected: uint8 _window3Flag; uint8 _window4Flag; uint8 _window6Flag; - byte *_window4BackScn; - byte *_window6BackScn; uint16 _moveXMin, _moveYMin; uint16 _moveXMax, _moveYMax; @@ -566,9 +562,11 @@ protected: byte _saveLoadType, _saveLoadSlot; char _saveLoadName[108]; - byte *_backGroundBuf; - byte *_backBuf; - byte *_scaleBuf; + Graphics::Surface *_backGroundBuf; + Graphics::Surface *_backBuf; + Graphics::Surface *_scaleBuf; + Graphics::Surface *_window4BackScn; + Graphics::Surface *_window6BackScn; Common::RandomSource _rnd; @@ -615,8 +613,8 @@ protected: void paletteFadeOut(byte *palPtr, uint num, uint size); - byte *allocateItem(uint size); - byte *allocateTable(uint size); + void *allocateItem(uint size); + void *allocateTable(uint size); void alignTableMem(); Child *findChildOfType(Item *i, uint child); @@ -673,7 +671,7 @@ protected: void uncompressText(byte *ptr); byte *uncompressToken(byte a, byte *ptr); - void showMessageFormat(const char *s, ...); + void showMessageFormat(const char *s, ...) GCC_PRINTF(2, 3); const byte *getStringPtrByID(uint16 stringId, bool upperCase = false); const byte *getLocalStringByID(uint16 stringId); uint getNextStringID(); @@ -1267,8 +1265,8 @@ protected: #ifdef ENABLE_PN class AGOSEngine_PN : public AGOSEngine { - struct stackframe { - struct stackframe *nextframe; + struct StackFrame { + StackFrame *nextframe; int16 flag[6]; int16 param[8]; int16 classnum; @@ -1278,7 +1276,7 @@ class AGOSEngine_PN : public AGOSEngine { int16 linenum; int16 process; jmp_buf *savearea; - stackframe() { memset(this, 0, sizeof(*this)); } + StackFrame() { memset(this, 0, sizeof(*this)); } }; @@ -1286,6 +1284,7 @@ class AGOSEngine_PN : public AGOSEngine { void demoSeq(); void introSeq(); void setupBoxes(); + int readfromline(); public: AGOSEngine_PN(OSystem *system); ~AGOSEngine_PN(); @@ -1299,10 +1298,10 @@ public: int actCallD(int n); void opn_opcode00(); - void opn_opcode01(); - void opn_opcode02(); - void opn_opcode03(); - void opn_opcode04(); + void opn_add(); + void opn_sub(); + void opn_mul(); + void opn_div(); void opn_opcode05(); void opn_opcode06(); void opn_opcode07(); @@ -1315,10 +1314,10 @@ public: void opn_opcode14(); void opn_opcode15(); void opn_opcode16(); - void opn_opcode17(); - void opn_opcode18(); - void opn_opcode19(); - void opn_opcode20(); + void opn_lt(); + void opn_gt(); + void opn_eq(); + void opn_neq(); void opn_opcode21(); void opn_opcode22(); void opn_opcode23(); @@ -1359,14 +1358,14 @@ public: void opn_opcode62(); void opn_opcode63(); - stackframe *_stackbase; + StackFrame *_stackbase; byte *_dataBase, *_textBase; uint32 _dataBaseSize, _textBaseSize; HitArea _invHitAreas[45]; - char _buffer[80]; + char _buffer[80]; char _inputline[61]; char _saveFile[20]; char _sb[80]; @@ -1392,7 +1391,7 @@ public: uint16 _objects; int16 _objectCountS; - int16 _bp; + int16 _bp; int16 _xofs; int16 _havinit; uint16 _seed; @@ -1977,7 +1976,7 @@ protected: virtual void printScreenText(uint vgaSpriteId, uint color, const char *stringPtr, int16 x, int16 y, int16 width); void printInteractText(uint16 num, const char *string); - void sendInteractText(uint16 num, const char *fmt, ...); + void sendInteractText(uint16 num, const char *fmt, ...) GCC_PRINTF(3, 4); void checkLinkBox(); void hyperLinkOn(uint16 x); diff --git a/engines/agos/charset-fontdata.cpp b/engines/agos/charset-fontdata.cpp index d23e772306..1cbc4f95dc 100644 --- a/engines/agos/charset-fontdata.cpp +++ b/engines/agos/charset-fontdata.cpp @@ -2090,7 +2090,7 @@ static const byte english_pnFont[] = { void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { const byte *src; byte color, *dst; - uint h, w, i; + uint dstPitch, h, w, i; if (_noOracleScroll) return; @@ -2100,7 +2100,8 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { Graphics::Surface *screen = _system->lockScreen(); if (getGameType() == GType_FF || getGameType() == GType_PP) { - dst = getBackGround() + y * _dxSurfacePitch + x + window->textColumnOffset; + dst = getBackGround(); + dstPitch = _backGroundBuf->pitch; h = 13; w = getFeebleFontSize(chr); @@ -2109,7 +2110,8 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { else src = feeble_windowFont + (chr - 32) * 13; } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { - dst = (byte *)screen->pixels + y * _dxSurfacePitch + x + window->textColumnOffset; + dst = (byte *)screen->pixels; + dstPitch = screen->pitch; h = 8; w = 6; @@ -2145,7 +2147,8 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { error("windowDrawChar: Unknown language %d", _language); } } else if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) { - dst = (byte *)screen->pixels + y * _dxSurfacePitch + x + window->textColumnOffset; + dst = (byte *)screen->pixels; + dstPitch = screen->pitch; h = 8; w = 6; @@ -2169,18 +2172,21 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { error("windowDrawChar: Unknown language %d", _language); } } else if (getGameType() == GType_ELVIRA1) { - dst = (byte *)screen->pixels + y * _dxSurfacePitch + x + window->textColumnOffset; + dst = (byte *)screen->pixels; + dstPitch = screen->pitch; h = 8; w = 6; src = english_elvira1Font + (chr - 32) * 8; } else { - dst = (byte *)screen->pixels + y * _dxSurfacePitch + x + window->textColumnOffset; + dst = (byte *)screen->pixels; + dstPitch = screen->pitch; h = 8; w = 8; src = english_pnFont + (chr - 32) * 8; } + dst += y * dstPitch + x + window->textColumnOffset; color = window->textColor; if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) @@ -2201,7 +2207,7 @@ void AGOSEngine::windowDrawChar(WindowBlock *window, uint x, uint y, byte chr) { b <<= 1; } while (++i != w); - dst += _dxSurfacePitch; + dst += dstPitch; } while (--h); _system->unlockScreen(); diff --git a/engines/agos/charset.cpp b/engines/agos/charset.cpp index c60640d761..5b0a694312 100644 --- a/engines/agos/charset.cpp +++ b/engines/agos/charset.cpp @@ -639,13 +639,13 @@ void AGOSEngine::windowScroll(WindowBlock *window) { w = window->width * 8; h = (window->height -1) * 8; - dst = (byte *)screen->pixels + window->y * _screenWidth + window->x * 8; - src = dst + 8 * _screenWidth; + dst = (byte *)screen->pixels + window->y * screen->pitch + window->x * 8; + src = dst + 8 * screen->pitch; do { memcpy(dst, src, w); - src += _screenWidth; - dst += _screenWidth; + src += screen->pitch; + dst += screen->pitch; } while (--h); _system->unlockScreen(); diff --git a/engines/agos/draw.cpp b/engines/agos/draw.cpp index 19520e66e9..45443aa335 100644 --- a/engines/agos/draw.cpp +++ b/engines/agos/draw.cpp @@ -35,18 +35,15 @@ namespace AGOS { byte *AGOSEngine::getBackBuf() { - _dxSurfacePitch = _screenWidth; - return _backBuf; + return (byte *)_backBuf->pixels; } byte *AGOSEngine::getBackGround() { - _dxSurfacePitch = _screenWidth; - return _backGroundBuf; + return (byte *)_backGroundBuf->pixels; } byte *AGOSEngine::getScaleBuf() { - _dxSurfacePitch = _screenWidth; - return _scaleBuf; + return (byte *)_scaleBuf->pixels; } void AGOSEngine_Feeble::animateSpritesByY() { @@ -166,7 +163,7 @@ void AGOSEngine::animateSprites() { _wallOn--; VC10_state state; - state.srcPtr = getBackGround() + 3 * _screenWidth + 3 * 16; + state.srcPtr = getBackGround() + 3 * _backGroundBuf->pitch + 3 * 16; state.height = state.draw_height = 127; state.width = state.draw_width = 14; state.y = 0; @@ -230,7 +227,7 @@ void AGOSEngine::animateSprites() { debug(0, "Using special wall"); uint8 color, h, len; - byte *dst = _window4BackScn; + byte *dst = (byte *)_window4BackScn->pixels; color = (_variableArray[293] & 1) ? 13 : 15; _wallOn = 2; @@ -260,7 +257,7 @@ void AGOSEngine::animateSprites() { } else if (getGameType() == GType_ELVIRA2 && _variableArray[71] & 2) { // Used by the Unholy Barrier spell uint8 color, h, len; - byte *dst = _window4BackScn; + byte *dst = (byte *)_window4BackScn->pixels; color = 1; _wallOn = 2; @@ -495,18 +492,18 @@ void AGOSEngine::saveBackGround(VgaSprite *vsp) { int16 y = vsp->y - _scrollY; if (_window3Flag == 1) { - animTable->srcPtr = (const byte *)_window4BackScn; + animTable->srcPtr = (const byte *)_window4BackScn->pixels; } else { int xoffs = (_videoWindows[vsp->windowNum * 4 + 0] * 2 + x) * 8; int yoffs = (_videoWindows[vsp->windowNum * 4 + 1] + y); - animTable->srcPtr = getBackGround() + xoffs + yoffs * _screenWidth; + animTable->srcPtr = getBackGround() + yoffs * _backGroundBuf->pitch + xoffs; } animTable->x = x; animTable->y = y; animTable->width = READ_BE_UINT16(ptr + 6) / 16; - if (vsp->flags & 40) { + if (vsp->flags & 0x40) { animTable->width++; } @@ -571,39 +568,39 @@ void AGOSEngine::displayBoxStars() { dst = (byte *)screen->pixels; - dst += (((_dxSurfacePitch / 4) * y_) * 4) + x_; + dst += (((screen->pitch / 4) * y_) * 4) + x_; - b = _dxSurfacePitch; + b = screen->pitch; dst[4] = color; dst[b+1] = color; dst[b+4] = color; dst[b+7] = color; - b += _dxSurfacePitch; + b += screen->pitch; dst[b+2] = color; dst[b+4] = color; dst[b+6] = color; - b += _dxSurfacePitch; + b += screen->pitch; dst[b+3] = color; dst[b+5] = color; - b += _dxSurfacePitch; + b += screen->pitch; dst[b] = color; dst[b+1] = color; dst[b+2] = color; dst[b+6] = color; dst[b+7] = color; dst[b+8] = color; - b += _dxSurfacePitch; + b += screen->pitch; dst[b+3] = color; dst[b+5] = color; - b += _dxSurfacePitch; + b += screen->pitch; dst[b+2] = color; dst[b+4] = color; dst[b+6] = color; - b += _dxSurfacePitch; + b += screen->pitch; dst[b+1] = color; dst[b+4] = color; dst[b+7] = color; - b += _dxSurfacePitch; + b += screen->pitch; dst[b+4] = color; } } while (ha++, --count); @@ -645,7 +642,7 @@ void AGOSEngine::scrollScreen() { } src = _scrollImage + y / 2; - decodeRow(dst, src + readUint32Wrapper(src), _scrollWidth, _dxSurfacePitch); + decodeRow(dst, src + readUint32Wrapper(src), _scrollWidth, _backGroundBuf->pitch); _scrollY += _scrollFlag; vcWriteVar(250, _scrollY); @@ -670,13 +667,19 @@ void AGOSEngine::scrollScreen() { src = _scrollImage + x / 2; else src = _scrollImage + x * 4; - decodeColumn(dst, src + readUint32Wrapper(src), _scrollHeight, _dxSurfacePitch); + decodeColumn(dst, src + readUint32Wrapper(src), _scrollHeight, _backGroundBuf->pitch); _scrollX += _scrollFlag; vcWriteVar(251, _scrollX); if (getGameType() == GType_SIMON2) { - memcpy(_window4BackScn, _backGroundBuf, _scrollHeight * _screenWidth); + src = getBackGround(); + dst = (byte *)_window4BackScn->pixels; + for (int i = 0; i < _scrollHeight; i++) { + memcpy(dst, src, _screenWidth); + src += _backGroundBuf->pitch; + dst += _window4BackScn->pitch; + } } else { fillBackFromBackGround(_scrollHeight, _screenWidth); } @@ -707,27 +710,53 @@ void AGOSEngine::clearSurfaces() { _system->fillScreen(0); if (_backBuf) { - memset(_backBuf, 0, _screenHeight * _screenWidth); + memset(getBackBuf(), 0, _backBuf->h * _backBuf->pitch); } } void AGOSEngine::fillBackFromBackGround(uint16 height, uint16 width) { - memcpy(_backBuf, _backGroundBuf, height * width); + byte *src = getBackGround(); + byte *dst = getBackBuf(); + for (int i = 0; i < height; i++) { + memcpy(dst, src, width); + src += _backGroundBuf->pitch; + dst += _backBuf->pitch; + } } void AGOSEngine::fillBackFromFront() { Graphics::Surface *screen = _system->lockScreen(); - memcpy(_backBuf, (byte *)screen->pixels, _screenHeight * _screenWidth); + byte *src = (byte *)screen->pixels; + byte *dst = getBackBuf(); + + for (int i = 0; i < _screenHeight; i++) { + memcpy(dst, src, _screenWidth); + src += screen->pitch; + dst += _backBuf->pitch; + } _system->unlockScreen(); } void AGOSEngine::fillBackGroundFromBack() { - memcpy(_backGroundBuf, _backBuf, _screenHeight * _screenWidth); + byte *src = getBackBuf(); + byte *dst = getBackGround(); + for (int i = 0; i < _screenHeight; i++) { + memcpy(dst, src, _screenWidth); + src += _backBuf->pitch; + dst += _backGroundBuf->pitch; + } } void AGOSEngine::fillBackGroundFromFront() { Graphics::Surface *screen = _system->lockScreen(); - memcpy(_backGroundBuf, (byte *)screen->pixels, _screenHeight * _screenWidth); + byte *src = (byte *)screen->pixels; + byte *dst = getBackGround(); + + for (int i = 0; i < _screenHeight; i++) { + memcpy(dst, src, _screenWidth); + src += screen->pitch; + dst += _backGroundBuf->pitch; + } _system->unlockScreen(); } @@ -756,8 +785,13 @@ void AGOSEngine::displayScreen() { Graphics::Surface *screen = _system->lockScreen(); if (getGameType() == GType_PP || getGameType() == GType_FF) { - memcpy((byte *)screen->pixels, getBackBuf(), _screenWidth * _screenHeight); - + byte *src = getBackBuf(); + byte *dst = (byte *)screen->pixels; + for (int i = 0; i < _screenHeight; i++) { + memcpy(dst, src, _screenWidth); + src += _backBuf->pitch; + dst += screen->pitch; + } if (getGameId() != GID_DIMP) fillBackFromBackGround(_screenHeight, _screenWidth); } else { @@ -767,12 +801,12 @@ void AGOSEngine::displayScreen() { uint16 srcWidth, width, height; byte *dst = (byte *)screen->pixels; - const byte *src = _window4BackScn; + const byte *src = (const byte *)_window4BackScn->pixels; if (_window3Flag == 1) { src = getBackGround(); } - dst += (_moveYMin + _videoWindows[17]) * _screenWidth; + dst += (_moveYMin + _videoWindows[17]) * screen->pitch; dst += (_videoWindows[16] * 16) + _moveXMin; src += (_videoWindows[18] * 16 * _moveYMin); @@ -785,7 +819,7 @@ void AGOSEngine::displayScreen() { for (; height > 0; height--) { memcpy(dst, src, width); - dst += _screenWidth; + dst += screen->pitch; src += srcWidth; } @@ -798,12 +832,12 @@ void AGOSEngine::displayScreen() { if (_window6Flag == 2) { _window6Flag = 0; - byte *src = _window6BackScn; - byte *dst = (byte *)screen->pixels + 16320; + byte *src = (byte *)_window6BackScn->pixels; + byte *dst = (byte *)screen->pixels + 51 * screen->pitch; for (int i = 0; i < 80; i++) { - memcpy(dst, src, 48); - dst += _screenWidth; - src += 48; + memcpy(dst, src, _window6BackScn->w); + dst += screen->pitch; + src += _window6BackScn->pitch; } } } diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp index ad7b079d53..cbb09e1ec7 100644 --- a/engines/agos/event.cpp +++ b/engines/agos/event.cpp @@ -367,12 +367,12 @@ void AGOSEngine::drawStuff(const byte *src, uint xoffs) { const uint8 y = (getPlatform() == Common::kPlatformAtariST) ? 132 : 135; Graphics::Surface *screen = _system->lockScreen(); - byte *dst = (byte *)screen->pixels + y * _screenWidth + xoffs; + byte *dst = (byte *)screen->pixels + y * screen->pitch + xoffs; for (uint h = 0; h < 6; h++) { memcpy(dst, src, 4); src += 4; - dst += _screenWidth; + dst += screen->pitch; } _system->unlockScreen(); @@ -484,7 +484,7 @@ void AGOSEngine::delay(uint amount) { _fastMode ^= 1; } else if (event.kbd.keycode == Common::KEYCODE_d) { _debugger->attach(); - } else if (event.kbd.keycode == Common::KEYCODE_u) { + } else if (event.kbd.keycode == Common::KEYCODE_s) { dumpAllSubroutines(); } else if (event.kbd.keycode == Common::KEYCODE_i) { dumpAllVgaImageFiles(); diff --git a/engines/agos/feeble.cpp b/engines/agos/feeble.cpp index 492d855614..89b6f6da27 100644 --- a/engines/agos/feeble.cpp +++ b/engines/agos/feeble.cpp @@ -161,21 +161,16 @@ void AGOSEngine_FeebleDemo::exitMenu() { playVideo("fbye1.smk", true); HitArea *ha; - while (!shouldQuit()) { + do { _lastHitArea = NULL; _lastHitArea3 = NULL; - while (!shouldQuit()) { - if (_lastHitArea3 != 0) - break; + while (!shouldQuit() && _lastHitArea3 == 0) { delay(1); } ha = _lastHitArea; - - if (ha != NULL && ha->id == 21) - break; - } + } while (!shouldQuit() && !(ha != NULL && ha->id == 21)); playVideo("fbye2.smk"); quitGame(); @@ -202,9 +197,7 @@ void AGOSEngine_FeebleDemo::filmMenu() { _lastHitArea = NULL; _lastHitArea3 = NULL; - while (!shouldQuit()) { - if (_lastHitArea3 != 0) - break; + while (!shouldQuit() && _lastHitArea3 == 0) { handleWobble(); delay(1); } @@ -287,25 +280,23 @@ void AGOSEngine_FeebleDemo::mainMenu() { startInteractiveVideo("mainmenu.smk"); - HitArea *ha; - while (!shouldQuit()) { + HitArea *ha = 0; + do { _lastHitArea = NULL; _lastHitArea3 = NULL; - while (!shouldQuit()) { - if (_lastHitArea3 != 0) - break; + while (_lastHitArea3 == 0) { + if (shouldQuit()) + return; handleText(); delay(1); } ha = _lastHitArea; + } while (ha == NULL || !(ha->id >= 1 && ha->id <= 6)); - if (ha == NULL) { - } else if (ha->id >= 1 && ha->id <= 6) { - break; - } - } + if (shouldQuit()) + return; stopInteractiveVideo(); @@ -384,11 +375,9 @@ void AGOSEngine_FeebleDemo::waitForSpace() { windowPutChar(_textWindow, *message); mouseOff(); - while (!shouldQuit()) { + do { delay(1); - if (_keyPressed.keycode == Common::KEYCODE_SPACE) - break; - } + } while (!shouldQuit() && (_keyPressed.keycode != Common::KEYCODE_SPACE)); _keyPressed.reset(); mouseOn(); } diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp index 4b2d2b3321..1b5a820260 100644 --- a/engines/agos/gfx.cpp +++ b/engines/agos/gfx.cpp @@ -272,13 +272,13 @@ void AGOSEngine_Feeble::scaleClip(int16 h, int16 w, int16 y, int16 x, int16 scro byte *src = getScaleBuf(); byte *dst = getBackBuf(); - dst += _dxSurfacePitch * dstRect.top + dstRect.left; + dst += dstRect.top * _backBuf->pitch + dstRect.left; for (int dstY = 0; dstY < scaledH; dstY++) { if (dstRect.top + dstY >= 0 && dstRect.top + dstY < _screenHeight) { int srcY = (dstY * h) / scaledH; - byte *srcPtr = src + _dxSurfacePitch * srcY; - byte *dstPtr = dst + _dxSurfacePitch * dstY; + byte *srcPtr = src + _scaleBuf->pitch * srcY; + byte *dstPtr = dst + _backBuf->pitch * dstY; for (int dstX = 0; dstX < scaledW; dstX++) { if (dstRect.left + dstX >= 0 && dstRect.left + dstX < _screenWidth) { int srcX = (dstX * w) / scaledW; @@ -292,12 +292,12 @@ void AGOSEngine_Feeble::scaleClip(int16 h, int16 w, int16 y, int16 x, int16 scro void AGOSEngine_Feeble::drawImage(VC10_state *state) { state->surf_addr = getBackBuf(); - state->surf_pitch = _dxSurfacePitch; + state->surf_pitch = _backBuf->pitch; if (state->flags & kDFCompressed) { if (state->flags & kDFScaled) { state->surf_addr = getScaleBuf(); - state->surf_pitch = _dxSurfacePitch; + state->surf_pitch = _scaleBuf->pitch; uint w, h; byte *src, *dst, *dstPtr; @@ -314,7 +314,7 @@ void AGOSEngine_Feeble::drawImage(VC10_state *state) { h = 0; do { *dst = *src; - dst += _screenWidth; + dst += state->surf_pitch; src++; } while (++h != state->draw_height); dstPtr++; @@ -330,7 +330,7 @@ void AGOSEngine_Feeble::drawImage(VC10_state *state) { } } else if (state->flags & kDFOverlayed) { state->surf_addr = getScaleBuf(); - state->surf_pitch = _dxSurfacePitch; + state->surf_pitch = _scaleBuf->pitch; state->surf_addr += (state->x + _scrollX) + (state->y + _scrollY) * state->surf_pitch; uint w, h; @@ -352,7 +352,7 @@ void AGOSEngine_Feeble::drawImage(VC10_state *state) { color = *src; if (color != 0) *dst = color; - dst += _screenWidth; + dst += state->surf_pitch; src++; } while (++h != state->draw_height); dstPtr++; @@ -406,7 +406,7 @@ void AGOSEngine_Feeble::drawImage(VC10_state *state) { color = *src; if (color) *dst = color; - dst += _screenWidth; + dst += state->surf_pitch; src++; } while (++h != state->draw_height); dstPtr++; @@ -425,7 +425,7 @@ void AGOSEngine_Feeble::drawImage(VC10_state *state) { color = *src; if ((state->flags & kDFNonTrans) || color != 0) *dst = color; - dst += _screenWidth; + dst += state->surf_pitch; src++; } while (++h != state->draw_height); dstPtr++; @@ -456,7 +456,7 @@ void AGOSEngine_Feeble::drawImage(VC10_state *state) { dst[count] = color; } } - dst += _screenWidth; + dst += state->surf_pitch; src += state->width; } while (--state->draw_height); } @@ -557,8 +557,8 @@ void AGOSEngine_Simon1::drawMaskedImage(VC10_state *state) { dst[count * 2 + 1] = src[count * 2 + 1]; } } - src += _screenWidth; - dst += _screenWidth; + src += state->surf2_pitch; + dst += state->surf_pitch; mask += state->width * 8; } while (--state->draw_height); } @@ -615,7 +615,7 @@ void AGOSEngine_Simon1::draw32ColorImage(VC10_state *state) { dst += 8; src += 5; } while (--count); - dstPtr += _screenWidth; + dstPtr += state->surf_pitch; } while (--state->draw_height); } else { src = state->srcPtr + (state->width * state->y_skip * 16) + (state->x_skip * 8); @@ -628,7 +628,7 @@ void AGOSEngine_Simon1::draw32ColorImage(VC10_state *state) { for (i = 0; i != state->draw_width; i++) if ((state->flags & kDFNonTrans) || src[i]) dst[i] = src[i] + state->paletteMod; - dst += _screenWidth; + dst += state->surf_pitch; src += state->width * 16; } while (--h); } @@ -648,10 +648,10 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { uint16 xoffs, yoffs; if (getGameType() == GType_SIMON2) { state->surf2_addr = getBackGround(); - state->surf2_pitch = _screenWidth; + state->surf2_pitch = _backGroundBuf->pitch; - state->surf_addr = _window4BackScn; - state->surf_pitch = _screenWidth; + state->surf_addr = (byte *)_window4BackScn->pixels; + state->surf_pitch = _window4BackScn->pitch; xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8; yoffs = (vlut[1] - _videoWindows[17] + state->y); @@ -665,9 +665,9 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { // The DOS Floppy demo was based off Waxworks engine if (_windowNum == 4 || (_windowNum >= 10 && _windowNum <= 27)) { state->surf2_addr = getBackGround(); - state->surf2_pitch = _screenWidth; + state->surf2_pitch = _backGroundBuf->pitch; - state->surf_addr = _window4BackScn; + state->surf_addr = (byte *)_window4BackScn->pixels; state->surf_pitch = _videoWindows[18] * 16; xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8; @@ -680,7 +680,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { _window4Flag = 1; } else { state->surf_addr = (byte *)screen->pixels; - state->surf_pitch = _screenWidth; + state->surf_pitch = screen->pitch; xoffs = (vlut[0] * 2 + state->x) * 8; yoffs = vlut[1] + state->y; @@ -689,16 +689,16 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { if (_windowNum == 3 || _windowNum == 4 || _windowNum >= 10) { if (_window3Flag == 1) { state->surf2_addr = getBackGround(); - state->surf2_pitch = _screenWidth; + state->surf2_pitch = _backGroundBuf->pitch; state->surf_addr = getBackGround(); - state->surf_pitch = _screenWidth; + state->surf_pitch = _backGroundBuf->pitch; } else { state->surf2_addr = getBackGround(); - state->surf2_pitch = _screenWidth; + state->surf2_pitch = _backGroundBuf->pitch; - state->surf_addr = _window4BackScn; - state->surf_pitch = _screenWidth; + state->surf_addr = (byte *)_window4BackScn->pixels; + state->surf_pitch = _window4BackScn->pitch; } xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8; @@ -711,10 +711,10 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { _window4Flag = 1; } else { state->surf2_addr = getBackGround(); - state->surf2_pitch = _screenWidth; + state->surf2_pitch = _backGroundBuf->pitch; state->surf_addr = (byte *)screen->pixels; - state->surf_pitch = _screenWidth; + state->surf_pitch = screen->pitch; xoffs = (vlut[0] * 2 + state->x) * 8; yoffs = vlut[1] + state->y; @@ -862,7 +862,7 @@ void AGOSEngine::drawImage(VC10_state *state) { uint16 xoffs = 0, yoffs = 0; if (getGameType() == GType_WW) { if (_windowNum == 4 || (_windowNum >= 10 && _windowNum <= 27)) { - state->surf_addr = _window4BackScn; + state->surf_addr = (byte *)_window4BackScn->pixels; state->surf_pitch = _videoWindows[18] * 16; xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8; @@ -875,14 +875,14 @@ void AGOSEngine::drawImage(VC10_state *state) { _window4Flag = 1; } else { state->surf_addr = (byte *)screen->pixels; - state->surf_pitch = _screenWidth; + state->surf_pitch = screen->pitch; xoffs = (vlut[0] * 2 + state->x) * 8; yoffs = vlut[1] + state->y; } } else if (getGameType() == GType_ELVIRA2) { if (_windowNum == 4 || _windowNum >= 10) { - state->surf_addr = _window4BackScn; + state->surf_addr = (byte *)_window4BackScn->pixels; state->surf_pitch = _videoWindows[18] * 16; xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8; @@ -895,26 +895,26 @@ void AGOSEngine::drawImage(VC10_state *state) { _window4Flag = 1; } else { state->surf_addr = (byte *)screen->pixels; - state->surf_pitch = _screenWidth; + state->surf_pitch = screen->pitch; xoffs = (vlut[0] * 2 + state->x) * 8; yoffs = vlut[1] + state->y; } } else if (getGameType() == GType_ELVIRA1) { if (_windowNum == 6) { - state->surf_addr = _window6BackScn; - state->surf_pitch = 48; + state->surf_addr = (byte *)_window6BackScn->pixels; + state->surf_pitch = _window6BackScn->pitch; xoffs = state->x * 8; yoffs = state->y; } else if (_windowNum == 2 || _windowNum == 3) { state->surf_addr = (byte *)screen->pixels; - state->surf_pitch = _screenWidth; + state->surf_pitch = screen->pitch; xoffs = (vlut[0] * 2 + state->x) * 8; yoffs = vlut[1] + state->y; } else { - state->surf_addr = _window4BackScn; + state->surf_addr = (byte *)_window4BackScn->pixels; state->surf_pitch = _videoWindows[18] * 16; xoffs = ((vlut[0] - _videoWindows[16]) * 2 + state->x) * 8; @@ -928,7 +928,7 @@ void AGOSEngine::drawImage(VC10_state *state) { } } else { state->surf_addr = (byte *)screen->pixels; - state->surf_pitch = _screenWidth; + state->surf_pitch = screen->pitch; xoffs = (vlut[0] * 2 + state->x) * 8; yoffs = vlut[1] + state->y; @@ -957,7 +957,7 @@ void AGOSEngine::drawImage(VC10_state *state) { void AGOSEngine::horizontalScroll(VC10_state *state) { const byte *src; byte *dst; - int w; + int dstPitch, w; if (getGameType() == GType_FF) _scrollXMax = state->width - 640; @@ -974,9 +974,11 @@ void AGOSEngine::horizontalScroll(VC10_state *state) { vcWriteVar(251, _scrollX); if (getGameType() == GType_SIMON2) { - dst = _window4BackScn; + dst = (byte *)_window4BackScn->pixels; + dstPitch = _window4BackScn->pitch; } else { dst = getBackBuf(); + dstPitch = _backBuf->pitch; } if (getGameType() == GType_FF) @@ -985,7 +987,7 @@ void AGOSEngine::horizontalScroll(VC10_state *state) { src = state->srcPtr + _scrollX * 4; for (w = 0; w < _screenWidth; w += 8) { - decodeColumn(dst, src + readUint32Wrapper(src), state->height, _dxSurfacePitch); + decodeColumn(dst, src + readUint32Wrapper(src), state->height, dstPitch); dst += 8; src += 4; } @@ -1015,7 +1017,7 @@ void AGOSEngine::verticalScroll(VC10_state *state) { src = state->srcPtr + _scrollY / 2; for (h = 0; h < _screenHeight; h += 8) { - decodeRow(dst, src + READ_LE_UINT32(src), state->width, _dxSurfacePitch); + decodeRow(dst, src + READ_LE_UINT32(src), state->width, _backBuf->pitch); dst += 8 * state->width; src += 4; } @@ -1366,21 +1368,21 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas uint height = _videoWindows[updateWindow * 4 + 3]; Graphics::Surface *screen = _system->lockScreen(); - byte *dst = getBackGround() + xoffs + yoffs * _screenWidth; + byte *dst = (byte *)_backGroundBuf->getBasePtr(xoffs, yoffs); byte *src = 0; uint srcWidth = 0; if (getGameType() == GType_SIMON2) { - src = _window4BackScn + xoffs + yoffs * 320; + src = (byte *)_window4BackScn->getBasePtr(xoffs, yoffs); srcWidth = 320; } else if (getGameType() == GType_SIMON1 && (getFeatures() & GF_DEMO)) { // The DOS Floppy demo was based off Waxworks engine if (updateWindow == 4 || updateWindow >= 10) { - src = _window4BackScn; + src = (byte *)_window4BackScn->pixels; srcWidth = _videoWindows[18] * 16; } else if (updateWindow == 3 || updateWindow == 9) { - src = (byte *)screen->pixels + xoffs + yoffs * _screenWidth; - srcWidth = _screenWidth; + src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs; + srcWidth = screen->pitch; } else { _system->unlockScreen(); _videoLockOut &= ~0x20; @@ -1388,14 +1390,14 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas } } else if (getGameType() == GType_SIMON1) { if (updateWindow == 4) { - src = _window4BackScn; + src = (byte *)_window4BackScn->pixels; srcWidth = _videoWindows[18] * 16; } else if (updateWindow >= 10) { - src = _window4BackScn + xoffs + yoffs * 320; + src = (byte *)_window4BackScn->pixels + xoffs + yoffs * 320; srcWidth = _videoWindows[18] * 16; } else if (updateWindow == 0) { - src = (byte *)screen->pixels + xoffs + yoffs * _screenWidth; - srcWidth = _screenWidth; + src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs; + srcWidth = screen->pitch; } else { _system->unlockScreen(); _videoLockOut &= ~0x20; @@ -1403,11 +1405,11 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas } } else if (getGameType() == GType_WW) { if (updateWindow == 4 || updateWindow >= 10) { - src = _window4BackScn; + src = (byte *)_window4BackScn->pixels; srcWidth = _videoWindows[18] * 16; } else if (updateWindow == 3 || updateWindow == 9) { - src = (byte *)screen->pixels + xoffs + yoffs * _screenWidth; - srcWidth = _screenWidth; + src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs; + srcWidth = screen->pitch; } else { _system->unlockScreen(); _videoLockOut &= ~0x20; @@ -1415,11 +1417,11 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas } } else if (getGameType() == GType_ELVIRA2) { if (updateWindow == 4 || updateWindow >= 10) { - src = _window4BackScn; + src = (byte *)_window4BackScn->pixels; srcWidth = _videoWindows[18] * 16; } else if (updateWindow == 3) { - src = (byte *)screen->pixels + xoffs + yoffs * _screenWidth; - srcWidth = _screenWidth; + src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs; + srcWidth = screen->pitch; } else { _system->unlockScreen(); _videoLockOut &= ~0x20; @@ -1428,25 +1430,25 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas } else if (getGameType() == GType_ELVIRA1) { if (updateWindow == 6) { _window6Flag = 1; - src = _window6BackScn; + src = (byte *)_window6BackScn->pixels; srcWidth = 48; } else if (updateWindow == 2 || updateWindow == 3) { - src = (byte *)screen->pixels + xoffs + yoffs * _screenWidth; - srcWidth = _screenWidth; + src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs; + srcWidth = screen->pitch; } else { - src = _window4BackScn; + src = (byte *)_window4BackScn->pixels; srcWidth = _videoWindows[18] * 16; } } else { - src = (byte *)screen->pixels + xoffs + yoffs * _screenWidth; - srcWidth = _screenWidth; + src = (byte *)screen->pixels + yoffs * screen->pitch + xoffs; + srcWidth = screen->pitch; } _boxStarHeight = height; for (; height > 0; height--) { memcpy(dst, src, width); - dst += _screenWidth; + dst += _backGroundBuf->pitch; src += srcWidth; } @@ -1455,15 +1457,15 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas dst = (byte *)screen->pixels + 48; memset(dst, color, 224); - dst = (byte *)screen->pixels + 132 * _screenWidth + 48; + dst = (byte *)screen->pixels + 132 * screen->pitch + 48; memset(dst, color, 224); } else if (getGameType() == GType_ELVIRA1 && updateWindow == 3 && _bottomPalette) { - dst = (byte *)screen->pixels + 133 * _screenWidth; - int size = 67 * _screenWidth; + dst = (byte *)screen->pixels + 133 * screen->pitch; - while (size--) { - *dst += 0x10; - dst++; + for (int h = 0; h < 67; h++) { + for (int w = 0; w < _screenWidth; w++) + dst[w] += 0x10; + dst += screen->pitch; } } @@ -1480,16 +1482,16 @@ void AGOSEngine::drawEdging() { Graphics::Surface *screen = _system->lockScreen(); - dst = (byte *)screen->pixels + 136 * _screenWidth; + dst = (byte *)screen->pixels + 136 * screen->pitch; uint8 len = 52; while (len--) { dst[0] = color; dst[319] = color; - dst += _screenWidth; + dst += screen->pitch; } - dst = (byte *)screen->pixels + 187 * _screenWidth; + dst = (byte *)screen->pixels + 187 * screen->pitch; memset(dst, color, _screenWidth); _system->unlockScreen(); diff --git a/engines/agos/icons.cpp b/engines/agos/icons.cpp index 0472b1192b..2fd93e64f2 100644 --- a/engines/agos/icons.cpp +++ b/engines/agos/icons.cpp @@ -211,15 +211,15 @@ void AGOSEngine_Simon2::drawIcon(WindowBlock *window, uint icon, uint x, uint y) dst += 110; dst += x; - dst += (y + window->y) * _dxSurfacePitch; + dst += (y + window->y) * screen->pitch; src = _iconFilePtr; src += READ_LE_UINT16(src + icon * 4 + 0); - decompressIcon(dst, src, 20, 10, 224, _dxSurfacePitch); + decompressIcon(dst, src, 20, 10, 224, screen->pitch); src = _iconFilePtr; src += READ_LE_UINT16(src + icon * 4 + 2); - decompressIcon(dst, src, 20, 10, 208, _dxSurfacePitch); + decompressIcon(dst, src, 20, 10, 208, screen->pitch); _system->unlockScreen(); @@ -236,17 +236,17 @@ void AGOSEngine_Simon1::drawIcon(WindowBlock *window, uint icon, uint x, uint y) dst = (byte *)screen->pixels; dst += (x + window->x) * 8; - dst += (y * 25 + window->y) * _dxSurfacePitch; + dst += (y * 25 + window->y) * screen->pitch; if (getPlatform() == Common::kPlatformAmiga) { src = _iconFilePtr; src += READ_BE_UINT32(src + icon * 4); uint8 color = (getFeatures() & GF_32COLOR) ? 224 : 240; - decompressIconPlanar(dst, src, 24, 12, color, _dxSurfacePitch); + decompressIconPlanar(dst, src, 24, 12, color, screen->pitch); } else { src = _iconFilePtr; src += READ_LE_UINT16(src + icon * 2); - decompressIcon(dst, src, 24, 12, 224, _dxSurfacePitch); + decompressIcon(dst, src, 24, 12, 224, screen->pitch); } _system->unlockScreen(); @@ -264,17 +264,17 @@ void AGOSEngine_Waxworks::drawIcon(WindowBlock *window, uint icon, uint x, uint dst = (byte *)screen->pixels; dst += (x + window->x) * 8; - dst += (y * 20 + window->y) * _dxSurfacePitch; + dst += (y * 20 + window->y) * screen->pitch; uint8 color = dst[0] & 0xF0; if (getPlatform() == Common::kPlatformAmiga) { src = _iconFilePtr; src += READ_BE_UINT32(src + icon * 4); - decompressIconPlanar(dst, src, 24, 10, color, _dxSurfacePitch); + decompressIconPlanar(dst, src, 24, 10, color, screen->pitch); } else { src = _iconFilePtr; src += READ_LE_UINT16(src + icon * 2); - decompressIcon(dst, src, 24, 10, color, _dxSurfacePitch); + decompressIcon(dst, src, 24, 10, color, screen->pitch); } _system->unlockScreen(); @@ -292,17 +292,17 @@ void AGOSEngine_Elvira2::drawIcon(WindowBlock *window, uint icon, uint x, uint y dst = (byte *)screen->pixels; dst += (x + window->x) * 8; - dst += (y * 8 + window->y) * _dxSurfacePitch; + dst += (y * 8 + window->y) * screen->pitch; uint color = dst[0] & 0xF0; if (getFeatures() & GF_PLANAR) { src = _iconFilePtr; src += READ_BE_UINT32(src + icon * 4); - decompressIconPlanar(dst, src, 24, 12, color, _dxSurfacePitch); + decompressIconPlanar(dst, src, 24, 12, color, screen->pitch); } else { src = _iconFilePtr; src += READ_LE_UINT16(src + icon * 2); - decompressIcon(dst, src, 24, 12, color, _dxSurfacePitch); + decompressIcon(dst, src, 24, 12, color, screen->pitch); } _system->unlockScreen(); @@ -320,16 +320,16 @@ void AGOSEngine_Elvira1::drawIcon(WindowBlock *window, uint icon, uint x, uint y dst = (byte *)screen->pixels; dst += (x + window->x) * 8; - dst += (y * 8 + window->y) * _dxSurfacePitch; + dst += (y * 8 + window->y) * screen->pitch; if (getFeatures() & GF_PLANAR) { src = _iconFilePtr; src += READ_BE_UINT16(src + icon * 2); - decompressIconPlanar(dst, src, 24, 12, 16, _dxSurfacePitch); + decompressIconPlanar(dst, src, 24, 12, 16, screen->pitch); } else { src = _iconFilePtr; src += icon * 288; - decompressIconPlanar(dst, src, 24, 12, 16, _dxSurfacePitch, false); + decompressIconPlanar(dst, src, 24, 12, 16, screen->pitch, false); } _system->unlockScreen(); @@ -344,14 +344,14 @@ void AGOSEngine::drawIcon(WindowBlock *window, uint icon, uint x, uint y) { _videoLockOut |= 0x8000; Graphics::Surface *screen = _system->lockScreen(); - dst = (byte *)screen->pixels + y * _dxSurfacePitch + x * 8; + dst = (byte *)screen->pixels + y * screen->pitch + x * 8; src = _iconFilePtr + icon * 146; if (icon == 0xFF) { // Draw Blank Icon for (int yp = 0; yp < 24; yp++) { memset(dst, 0, 24); - dst += _dxSurfacePitch; + dst += screen->pitch; } } else { uint8 palette[4]; @@ -364,7 +364,7 @@ void AGOSEngine::drawIcon(WindowBlock *window, uint icon, uint x, uint y) { uint32 v1 = (READ_BE_UINT16(src) << 8) | *(src + 4); uint32 v2 = (READ_BE_UINT16(src + 2) << 8) | *(src + 5); for (int xp = 0; xp < 24; ++xp, v1 >>= 1, v2 >>= 1) { - dst[yp * _screenWidth + (23 - xp)] = palette[((v1 & 1) << 1) | (v2 & 1)]; + dst[yp * screen->pitch + (23 - xp)] = palette[((v1 & 1) << 1) | (v2 & 1)]; } } } @@ -952,7 +952,7 @@ void AGOSEngine::drawArrow(uint16 x, uint16 y, int8 dir) { } Graphics::Surface *screen = _system->lockScreen(); - byte *dst = (byte *)screen->pixels + y * _screenWidth + x * 8; + byte *dst = (byte *)screen->pixels + y * screen->pitch + x * 8; for (h = 0; h < 19; h++) { for (w = 0; w < 16; w++) { @@ -960,7 +960,7 @@ void AGOSEngine::drawArrow(uint16 x, uint16 y, int8 dir) { } src += dir; - dst+= _screenWidth; + dst+= screen->pitch; } _system->unlockScreen(); @@ -1043,7 +1043,7 @@ static const byte hitBarData[12 * 7] = { // Personal Nightmare specific void AGOSEngine_PN::drawIconHitBar() { Graphics::Surface *screen = _system->lockScreen(); - byte *dst = (byte *)screen->pixels + 3 * _dxSurfacePitch + 6 * 8; + byte *dst = (byte *)screen->pixels + 3 * screen->pitch + 6 * 8; const byte *src = hitBarData; uint8 color = (getPlatform() == Common::kPlatformPC) ? 7 : 15; @@ -1058,7 +1058,7 @@ void AGOSEngine_PN::drawIconHitBar() { b <<= 1; } } - dst += _dxSurfacePitch; + dst += screen->pitch; } _system->unlockScreen(); diff --git a/engines/agos/items.cpp b/engines/agos/items.cpp index c439be3555..49792b99c5 100644 --- a/engines/agos/items.cpp +++ b/engines/agos/items.cpp @@ -41,7 +41,7 @@ Child *AGOSEngine::allocateChildBlock(Item *i, uint type, uint size) { return child; } -byte *AGOSEngine::allocateItem(uint size) { +void *AGOSEngine::allocateItem(uint size) { byte *item = new byte[size]; memset(item, 0, size); diff --git a/engines/agos/menus.cpp b/engines/agos/menus.cpp index 9e71849c6e..df837a5e16 100644 --- a/engines/agos/menus.cpp +++ b/engines/agos/menus.cpp @@ -170,7 +170,7 @@ void AGOSEngine::unlightMenuStrip() { mouseOff(); Graphics::Surface *screen = _system->lockScreen(); - src = (byte *)screen->pixels + 2832; + src = (byte *)screen->pixels + 8 * screen->pitch + 272; w = 48; h = 82; @@ -179,7 +179,7 @@ void AGOSEngine::unlightMenuStrip() { if (src[i] != 0) src[i] = 14; } - src += _dxSurfacePitch; + src += screen->pitch; } while (--h); for (i = 120; i != 130; i++) @@ -198,7 +198,7 @@ void AGOSEngine::lightMenuBox(uint hitarea) { mouseOff(); Graphics::Surface *screen = _system->lockScreen(); - src = (byte *)screen->pixels + ha->y * _dxSurfacePitch + ha->x; + src = (byte *)screen->pixels + ha->y * screen->pitch + ha->x; w = ha->width; h = ha->height; @@ -207,7 +207,7 @@ void AGOSEngine::lightMenuBox(uint hitarea) { if (src[i] == 14) src[i] = 15; } - src += _dxSurfacePitch; + src += screen->pitch; } while (--h); _system->unlockScreen(); diff --git a/engines/agos/oracle.cpp b/engines/agos/oracle.cpp index 88346fa9f8..e7192ea2ec 100644 --- a/engines/agos/oracle.cpp +++ b/engines/agos/oracle.cpp @@ -246,28 +246,28 @@ void AGOSEngine_Feeble::scrollOracleUp() { byte *src, *dst; uint16 w, h; - dst = getBackGround() + 103 * _screenWidth + 136; - src = getBackGround() + 106 * _screenWidth + 136; + dst = getBackGround() + 103 * _backGroundBuf->pitch + 136; + src = getBackGround() + 106 * _backGroundBuf->pitch + 136; for (h = 0; h < 21; h++) { for (w = 0; w < 360; w++) { if (dst[w] == 0 || dst[w] == 113 || dst[w] == 116 || dst[w] == 252) dst[w] = src[w]; } - dst += _screenWidth; - src += _screenWidth; + dst += _backGroundBuf->pitch; + src += _backGroundBuf->pitch; } for (h = 0; h < 80; h++) { memcpy(dst, src, 360); - dst += _screenWidth; - src += _screenWidth; + dst += _backGroundBuf->pitch; + src += _backGroundBuf->pitch; } for (h = 0; h < 3; h++) { memset(dst, 0, 360); - dst += _screenWidth; - src += _screenWidth; + dst += _backGroundBuf->pitch; + src += _backGroundBuf->pitch; } } @@ -275,13 +275,13 @@ void AGOSEngine_Feeble::scrollOracleDown() { byte *src, *dst; uint16 w, h; - src = getBackGround() + 203 * _screenWidth + 136; - dst = getBackGround() + 206 * _screenWidth + 136; + src = getBackGround() + 203 * _backGroundBuf->pitch + 136; + dst = getBackGround() + 206 * _backGroundBuf->pitch + 136; for (h = 0; h < 77; h++) { memcpy(dst, src, 360); - dst -= _screenWidth; - src -= _screenWidth; + dst -= _backGroundBuf->pitch; + src -= _backGroundBuf->pitch; } for (h = 0; h < 24; h++) { @@ -294,8 +294,8 @@ void AGOSEngine_Feeble::scrollOracleDown() { src[w] = 0; } } - dst -= _screenWidth; - src -= _screenWidth; + dst -= _backGroundBuf->pitch; + src -= _backGroundBuf->pitch; } } @@ -315,7 +315,7 @@ void AGOSEngine_Feeble::oracleLogo() { srcRect.bottom = 43; src = _iconFilePtr; - dst = getBackBuf() + _screenWidth * dstRect.top + dstRect.left; + dst = getBackBuf() + _backBuf->pitch * dstRect.top + dstRect.left; for (h = 0; h < dstRect.height(); h++) { for (w = 0; w < dstRect.width(); w++) { @@ -323,7 +323,7 @@ void AGOSEngine_Feeble::oracleLogo() { dst[w] = src[w]; } src += 336; - dst += _screenWidth; + dst += _backBuf->pitch; } } @@ -355,7 +355,7 @@ void AGOSEngine_Feeble::swapCharacterLogo() { srcRect.right = srcRect.left + 42; src = _iconFilePtr + srcRect.top * 336 + srcRect.left; - dst = getBackBuf() + _screenWidth * dstRect.top + dstRect.left; + dst = getBackBuf() + _backBuf->pitch * dstRect.top + dstRect.left; for (h = 0; h < dstRect.height(); h++) { for (w = 0; w < dstRect.width(); w++) { @@ -363,7 +363,7 @@ void AGOSEngine_Feeble::swapCharacterLogo() { dst[w] = src[w]; } src += 336; - dst += _screenWidth; + dst += _backBuf->pitch; } } @@ -506,14 +506,14 @@ void AGOSEngine_Feeble::windowBackSpace(WindowBlock *window) { x = window->x + window->textColumn; y = window->y + window->textRow; - dst = getBackGround() + _dxSurfacePitch * y + x; + dst = getBackGround() + _backGroundBuf->pitch * y + x; for (h = 0; h < 13; h++) { for (w = 0; w < 8; w++) { if (dst[w] == 113 || dst[w] == 116 || dst[w] == 252) dst[w] = 0; } - dst += _screenWidth; + dst += _backGroundBuf->pitch; } _videoLockOut &= ~0x8000; diff --git a/engines/agos/pn.cpp b/engines/agos/pn.cpp index fd88d63ec3..d92efa9077 100644 --- a/engines/agos/pn.cpp +++ b/engines/agos/pn.cpp @@ -269,16 +269,16 @@ void AGOSEngine_PN::processor() { _variableArray[16] = _quickshort[6]; _variableArray[17] = _quickshort[7]; _variableArray[19] = getptr(55L); + + // q indicates the process to run and is 0 the first time, + // but 1 later on (i.e., when we are "called" from badload()). setposition(q, 0); doline(0); } void AGOSEngine_PN::setqptrs() { - int a = 0; - - while (a < 11) { - _quickptr[a] = getlong(3L * a); - a++; + for (int i = 0; i < 11; ++i) { + _quickptr[i] = getlong(3 * i); } _quickptr[11] = getlong(58L); _quickptr[12] = getlong(61L); diff --git a/engines/agos/res_snd.cpp b/engines/agos/res_snd.cpp index 60c79b2324..e85440d8e1 100644 --- a/engines/agos/res_snd.cpp +++ b/engines/agos/res_snd.cpp @@ -332,7 +332,7 @@ void AGOSEngine::playSting(uint16 soundId) { mus_file.seek(soundId * 2, SEEK_SET); mus_offset = mus_file.readUint16LE(); - if (mus_file.ioFailed()) + if (mus_file.err()) error("playSting: Can't read sting %d offset", soundId); mus_file.seek(mus_offset, SEEK_SET); @@ -527,6 +527,7 @@ void AGOSEngine::loadSound(uint16 sound, int16 pan, int16 vol, uint16 type) { void AGOSEngine::loadSound(uint16 sound, uint16 freq, uint16 flags) { byte *dst; uint32 offs, size = 0; + uint32 rate = 8000; if (_curSfxFile == NULL) return; @@ -570,13 +571,23 @@ void AGOSEngine::loadSound(uint16 sound, uint16 freq, uint16 flags) { offs = READ_BE_UINT32(dst + 8); } - // TODO: Handle other sound flags and frequency + if (getGameType() == GType_PN) { + if (freq == 0) { + rate = 4600; + } else if (freq == 1) { + rate = 7400; + } else { + rate = 9400; + } + } + + // TODO: Handle other sound flags in Amiga/AtariST versions if (flags == 2 && _sound->isSfxActive()) { - _sound->queueSound(dst + offs, sound, size, 8000); + _sound->queueSound(dst + offs, sound, size, rate); } else { if (flags == 0) _sound->stopSfx(); - _sound->playRawData(dst + offs, sound, size, 8000); + _sound->playRawData(dst + offs, sound, size, rate); } } diff --git a/engines/agos/script_e1.cpp b/engines/agos/script_e1.cpp index 0080748699..df37a38a7c 100644 --- a/engines/agos/script_e1.cpp +++ b/engines/agos/script_e1.cpp @@ -532,7 +532,7 @@ void AGOSEngine_Elvira1::oe1_moveDirn() { void AGOSEngine_Elvira1::oe1_score() { // 90: score SubPlayer *p = (SubPlayer *)findChildOfType(me(), kPlayerType); - showMessageFormat("Your score is %ld.\n", p->score); + showMessageFormat("Your score is %d.\n", p->score); } void AGOSEngine_Elvira1::oe1_look() { diff --git a/engines/agos/script_pn.cpp b/engines/agos/script_pn.cpp index 62ca94e387..4f9aab2965 100644 --- a/engines/agos/script_pn.cpp +++ b/engines/agos/script_pn.cpp @@ -30,17 +30,21 @@ namespace AGOS { +enum { + kJmpClassNum = -1 +}; + #define OPCODE(x) _OPCODE(AGOSEngine_PN, x) void AGOSEngine_PN::setupOpcodes() { static const OpcodeEntryPN opcodes[] = { /* 00 */ OPCODE(opn_opcode00), - OPCODE(opn_opcode01), - OPCODE(opn_opcode02), - OPCODE(opn_opcode03), + OPCODE(opn_add), + OPCODE(opn_sub), + OPCODE(opn_mul), /* 04 */ - OPCODE(opn_opcode04), + OPCODE(opn_div), OPCODE(opn_opcode05), OPCODE(opn_opcode06), OPCODE(opn_opcode07), @@ -56,11 +60,11 @@ void AGOSEngine_PN::setupOpcodes() { OPCODE(opn_opcode15), /* 16 */ OPCODE(opn_opcode16), - OPCODE(opn_opcode17), - OPCODE(opn_opcode18), - OPCODE(opn_opcode19), + OPCODE(opn_lt), + OPCODE(opn_gt), + OPCODE(opn_eq), /* 20 */ - OPCODE(opn_opcode20), + OPCODE(opn_neq), OPCODE(opn_opcode21), OPCODE(opn_opcode22), OPCODE(opn_opcode23), @@ -122,13 +126,14 @@ void AGOSEngine_PN::setupOpcodes() { void AGOSEngine_PN::executeOpcode(int opcode) { OpcodeProcPN op = _opcodesPN[opcode].proc; - (this->*op) (); + (this->*op)(); } -#define readfromline() (_linct-- ? (int)*_workptr++ : readoverr()) - -int readoverr() { - error("readfromline: Internal Error - Line Over-run"); +int AGOSEngine_PN::readfromline() { + if (!_linct) + error("readfromline: Internal Error - Line Over-run"); + _linct--; + return *_workptr++; } // ----------------------------------------------------------------------- @@ -142,30 +147,30 @@ void AGOSEngine_PN::opn_opcode00() { setScriptReturn(true); } -void AGOSEngine_PN::opn_opcode01() { +void AGOSEngine_PN::opn_add() { uint8 *str = _workptr; int32 sp = varval() + varval(); _variableArray[12] = sp % 65536; _variableArray[13] = sp / 65536; if (sp > 65535) - sp=65535; + sp = 65535; writeval(str, (int)sp); setScriptReturn(true); } -void AGOSEngine_PN::opn_opcode02() { +void AGOSEngine_PN::opn_sub() { uint8 *str = _workptr; int32 sp = varval(); sp -= varval(); _variableArray[12] = sp % 65536; _variableArray[13] = sp / 65536; - if(sp < 0) + if (sp < 0) sp = 0; writeval(str, (int)sp); setScriptReturn(true); } -void AGOSEngine_PN::opn_opcode03() { +void AGOSEngine_PN::opn_mul() { uint8 *str = _workptr; int32 sp = varval() * varval(); _variableArray[12] = sp % 65536; @@ -176,12 +181,12 @@ void AGOSEngine_PN::opn_opcode03() { setScriptReturn(true); } -void AGOSEngine_PN::opn_opcode04() { +void AGOSEngine_PN::opn_div() { uint8 *str = _workptr; int32 sp = varval(); int32 sp2 = varval(); if (sp2 == 0) - error("Division by 0"); + error("opn_div: Division by 0"); sp = sp / sp2; _variableArray[12] = sp % 65536; _variableArray[13] = sp / 65536; @@ -234,7 +239,7 @@ void AGOSEngine_PN::opn_opcode12() { char bf[8]; int a = 0; sprintf(bf,"%d", varval()); - while(bf[a]) + while (bf[a]) pcf(bf[a++]); setScriptReturn(true); } @@ -243,7 +248,7 @@ void AGOSEngine_PN::opn_opcode13() { char bf[8]; int a = 0; sprintf(bf,"%d", varval()); - while(bf[a]) + while (bf[a]) pcf(bf[a++]); pcf((uint8)'\n'); setScriptReturn(true); @@ -271,25 +276,25 @@ void AGOSEngine_PN::opn_opcode16() { setScriptReturn((sp >= 0 && sp <= 4)); } -void AGOSEngine_PN::opn_opcode17() { +void AGOSEngine_PN::opn_lt() { int16 v1 = varval(); int16 v2 = varval(); setScriptReturn(v1 < v2); } -void AGOSEngine_PN::opn_opcode18() { +void AGOSEngine_PN::opn_gt() { int16 v1 = varval(); int16 v2 = varval(); setScriptReturn(v1 > v2); } -void AGOSEngine_PN::opn_opcode19() { +void AGOSEngine_PN::opn_eq() { int16 v1 = varval(); int16 v2 = varval(); setScriptReturn(v1 == v2); } -void AGOSEngine_PN::opn_opcode20() { +void AGOSEngine_PN::opn_neq() { int16 v1 = varval(); int16 v2 = varval(); setScriptReturn(v1 != v2); @@ -302,11 +307,10 @@ void AGOSEngine_PN::opn_opcode21() { void AGOSEngine_PN::opn_opcode22() { int pf[8]; - int a; - a = varval(); - funcentry(pf, a); + int n = varval(); + funcentry(pf, n); funccpy(pf); - setposition(a, 0); + setposition(n, 0); setScriptReturn(true); } @@ -315,19 +319,27 @@ void AGOSEngine_PN::opn_opcode23() { } void AGOSEngine_PN::opn_opcode24() { - popstack(-1); + popstack(kJmpClassNum); + // Jump back to the last doline, which will return 2-1=1. + // That value then is returned to actCallD, which once again + // returns it. In the end, this amounts to a setScriptReturn(true) + // (but possibly in a different level than the current one). longjmp(*(_stackbase->savearea), 2); setScriptReturn(false); } void AGOSEngine_PN::opn_opcode25() { - popstack(-1); + popstack(kJmpClassNum); + // Jump back to the last doline, which will return 1-1=0. + // That value then is returned to actCallD, which once again + // returns it. In the end, this amounts to a setScriptReturn(false) + // (but possibly in a different level than the current one). longjmp(*(_stackbase->savearea), 1); setScriptReturn(false); } void AGOSEngine_PN::opn_opcode26() { - while ((_stackbase->classnum != -1) && (_stackbase != NULL)) + while ((_stackbase != NULL) && (_stackbase->classnum != kJmpClassNum)) junkstack(); dumpstack(); setScriptReturn(true); @@ -347,6 +359,8 @@ void AGOSEngine_PN::opn_opcode28() { void AGOSEngine_PN::opn_opcode29() { popstack(varval()); + // Jump back to the last doline indicated by the top stackfram. + // The -1 tells it to simply go on with its business. longjmp(*(_stackbase->savearea), -1); setScriptReturn(false); } @@ -395,7 +409,8 @@ void AGOSEngine_PN::opn_opcode32() { char bf[60]; int a, slot; - if ((a = varval()) > 2) { + a = varval(); + if (a > 2) { setScriptReturn(true); return; } @@ -451,10 +466,8 @@ void AGOSEngine_PN::opn_opcode35() { } void AGOSEngine_PN::opn_opcode36() { - int ct = 0; - while (ct < _dataBase[57] + 1) - _wordcp[ct++] = 0; - ct = 1; + for (int i = 0; i < _dataBase[57] + 1; ++i) + _wordcp[i] = 0; if (isspace(*_inpp)) while ((*_inpp) && (isspace(*_inpp))) _inpp++; @@ -468,6 +481,8 @@ void AGOSEngine_PN::opn_opcode36() { setScriptReturn(true); return; } + + int ct = 1; while ((*_inpp != '.') && (*_inpp != ',') && (!isspace(*_inpp)) && (*_inpp != '\0') && (*_inpp!='"')) { if (ct < _dataBase[57]) @@ -734,37 +749,38 @@ int AGOSEngine_PN::varval() { int a; int b; - if ((a = readfromline()) < 247) { + a = readfromline(); + if (a < 247) { return a; } switch (a) { case 249: b = readfromline(); - return((int)(b + 256 * readfromline())); + return (int)(b + 256 * readfromline()); break; case 250: - return(readfromline()); + return readfromline(); case 251: - return((int)_variableArray[varval()]); + return (int)_variableArray[varval()]; case 252: b = varval(); - return((int)_dataBase[_quickptr[0] + b * _quickshort[0] + varval()]); + return (int)_dataBase[_quickptr[0] + b * _quickshort[0] + varval()]; case 254: b = varval(); - return((int)_dataBase[_quickptr[3] + b * _quickshort[2] + varval()]); + return (int)_dataBase[_quickptr[3] + b * _quickshort[2] + varval()]; case 247: b = varval(); - return((int)getptr(_quickptr[11] + (b * _quickshort[4]) + (2 * varval()))); + return (int)getptr(_quickptr[11] + (b * _quickshort[4]) + (2 * varval())); case 248: b = varval(); - return((int)getptr(_quickptr[12] + (b * _quickshort[5]) + (2 * varval()))); + return (int)getptr(_quickptr[12] + (b * _quickshort[5]) + (2 * varval())); case 253: b = varval(); - return(bitextract((int32)_quickptr[1] + b * _quickshort[1], varval())); + return bitextract((int32)_quickptr[1] + b * _quickshort[1], varval()); case 255: b = varval(); - return(bitextract((int32)_quickptr[4] + b * _quickshort[3], varval())); + return bitextract((int32)_quickptr[4] + b * _quickshort[3], varval()); default: error("VARVAL : Illegal code %d encountered", a); } @@ -834,10 +850,10 @@ void AGOSEngine_PN::setbitf(uint32 ptr, int offs, int val) { int AGOSEngine_PN::actCallD(int n) { int pf[8]; funcentry(pf, n); - addstack(-1); + addstack(kJmpClassNum); funccpy(pf); setposition(n, 0); - return(doline(1)); + return doline(1); } int AGOSEngine_PN::doaction() { @@ -859,47 +875,59 @@ int AGOSEngine_PN::doaction() { int AGOSEngine_PN::doline(int needsave) { int x; - jmp_buf *ljmpbuff = NULL; + jmp_buf *old_jmpbuf = NULL; jmp_buf *mybuf; mybuf = (jmp_buf *)malloc(sizeof(jmp_buf)); if (mybuf == NULL) error("doline: Out of memory - stack overflow"); - if ((x = setjmp(*mybuf)) > 0) { + x = setjmp(*mybuf); + // Looking at the longjmp calls below, x can be -1, 1 or 2 + // (and of course 0 when it returns directly, as always). + if (x > 0) { dumpstack(); - _cjmpbuff = ljmpbuff; + // Restore the active jmpbuf to its previous value, + // then return the longjmp value (will be 2-1=1 or 1-1=0). + _cjmpbuff = old_jmpbuf; free((char *)mybuf); return (x - 1); } if (x == -1) { + // Make this doline instance the active one (again). + // This is used to "return" over possibly multiple + // layers of nested script invocations. + // Kind of like throwing an exception. _cjmpbuff = mybuf; goto carryon; } - ljmpbuff = _cjmpbuff; + + // Remember the previous active jmpbuf (gets restored + // above when a longjmp with a positive param occurs). + old_jmpbuf = _cjmpbuff; _cjmpbuff = mybuf; if (needsave) _stackbase->savearea = mybuf; -nln: _linct = ((*_linebase) & 127) - 1; - _workptr = _linebase + 1; - if (*_linebase > 127) { - x = varval(); - if (x != (int)_variableArray[1]) - goto skipln; - } - -carryon: do { - x = doaction(); - } while (x && !shouldQuit()); + _linct = ((*_linebase) & 127) - 1; + _workptr = _linebase + 1; + if (*_linebase > 127) { + x = varval(); + if (x != (int)_variableArray[1]) + goto skipln; + } -skipln: _linebase += 127 & *_linebase; - _linembr++; +carryon: + do { + x = doaction(); + } while (x && !shouldQuit()); - if (!shouldQuit()) - goto nln; +skipln: + _linebase += 127 & *_linebase; + _linembr++; + } while (!shouldQuit()); return 0; } @@ -951,23 +979,15 @@ int AGOSEngine_PN::findset() { } void AGOSEngine_PN::funccpy(int *store) { - int a = 0; - int b = 24; - - while (a < 8) { - _variableArray[b++] = *store++; - a++; + for (int i = 24; i < 32; ++i) { + _variableArray[i] = *store++; } } void AGOSEngine_PN::funcentry(int *store, int procn) { - int ct = 0; - int nprm; - - nprm = _dataBase[getlong(_quickptr[6] + 3L * procn)]; - while (ct < nprm) { + int numParams = _dataBase[getlong(_quickptr[6] + 3 * procn)]; + for (int i = 0; i < numParams; ++i) { *store++ = varval(); - ct++; } } @@ -990,23 +1010,28 @@ int AGOSEngine_PN::gvwrd(uint8 *wptr, int mask) { int AGOSEngine_PN::setposition(int process, int line) { uint8 *ourptr; int np; - int ct = 0; - ourptr = _dataBase + getlong(_quickptr[6] + 3L * process); + int ct; + + ourptr = _dataBase + getlong(_quickptr[6] + 3 * process); np = *ourptr++; - while (ct < line) { + for (ct = 0; ct < line; ++ct) { ourptr += (127 & *ourptr); - ct++; } -x1: _linebase = ourptr; - _linct = (127 & (*ourptr)) - 1; - if (*ourptr++ > 127) { + + while (true) { + _linebase = ourptr; + _linct = (127 & *ourptr) - 1; + if (*ourptr++ <= 127) + break; + ct = varval(); - if (ct != (int)_variableArray[1]) { - ourptr += _linct - 1; - line++; - goto x1; - } + if (ct == (int)_variableArray[1]) + break; + + ourptr += _linct - 1; + line++; } + _linembr = line; _procnum = process; _variableArray[0] = process; @@ -1035,22 +1060,20 @@ int AGOSEngine_PN::wrdmatch(uint8 *word1, int mask1, uint8 *word2, int mask2) { // ----------------------------------------------------------------------- void AGOSEngine_PN::addstack(int type) { - struct stackframe *a; - int pt, ct = 0; + StackFrame *a; + int i; - a = (struct stackframe *)malloc(sizeof(struct stackframe)); + a = (StackFrame *)malloc(sizeof(StackFrame)); if (a == NULL) error("addstack: Out of memory - stack overflow"); a->nextframe = _stackbase; _stackbase = a; - pt = 0; - while (ct < 6) - a->flag[ct++] = _variableArray[pt++]; - ct = 0; - pt = 24; - while (ct < 8) - a->param[ct++] = _variableArray[pt++]; + + for (i = 0; i < 6; ++i) + a->flag[i] = _variableArray[i]; + for (i = 0; i < 8; ++i) + a->param[i] = _variableArray[24 + i]; a->classnum = type; a->ll = _linct; a->linenum = _linembr; @@ -1060,7 +1083,7 @@ void AGOSEngine_PN::addstack(int type) { } void AGOSEngine_PN::dumpstack() { - struct stackframe *a; + StackFrame *a; if (_stackbase == NULL) error("dumpstack: Stack underflow or unknown longjmp"); @@ -1071,20 +1094,20 @@ void AGOSEngine_PN::dumpstack() { } void AGOSEngine_PN::junkstack() { - struct stackframe *a; + StackFrame *a; if (_stackbase == NULL) error("junkstack: Stack underflow or unknown longjmp"); a = _stackbase->nextframe; - if (_stackbase->classnum == -1) + if (_stackbase->classnum == kJmpClassNum) free((char *)_stackbase->savearea); free((char *)_stackbase); _stackbase = a; } void AGOSEngine_PN::popstack(int type) { - int a = 0, b; + int i; while ((_stackbase != NULL) && (_stackbase->classnum != type)) junkstack(); @@ -1097,13 +1120,10 @@ void AGOSEngine_PN::popstack(int type) { _workptr = _stackbase->linpos; _procnum = _stackbase->process; _linembr = _stackbase->linenum; - b = 0; - while (a < 6) - _variableArray[b++] = _stackbase->flag[a++]; - b = 24; - a = 0; - while (a < 8) - _variableArray[b++] = _stackbase->param[a++]; + for (i = 0; i < 6; ++i) + _variableArray[i] = _stackbase->flag[i]; + for (i = 0; i < 8; ++i) + _variableArray[24 + i] = _stackbase->param[i]; } } // End of namespace AGOS diff --git a/engines/agos/string.cpp b/engines/agos/string.cpp index a466be796f..3773b1fa10 100644 --- a/engines/agos/string.cpp +++ b/engines/agos/string.cpp @@ -136,6 +136,20 @@ const byte *AGOSEngine::getStringPtrByID(uint16 stringId, bool upperCase) { strcpy((char *)dst, (const char *)stringPtr); } + // WORKAROUND bug #1538873: The French version of Simon 1 and the + // Polish version of Simon 2 used excess spaces, at the end of many + // messages, so we strip off those excess spaces. + if ((getGameType() == GType_SIMON1 && _language == Common::FR_FRA) || + (getGameType() == GType_SIMON2 && _language == Common::PL_POL)) { + uint16 len = strlen((const char *)dst) - 1; + + while (len && dst[len] == 32) { + dst[len] = 0; + len--; + } + + } + if (upperCase && *dst) { if (islower(*dst)) *dst = toupper(*dst); diff --git a/engines/agos/subroutine.cpp b/engines/agos/subroutine.cpp index 742ac48ac8..70ad3404f5 100644 --- a/engines/agos/subroutine.cpp +++ b/engines/agos/subroutine.cpp @@ -226,7 +226,7 @@ void AGOSEngine::alignTableMem() { } } -byte *AGOSEngine::allocateTable(uint size) { +void *AGOSEngine::allocateTable(uint size) { byte *org = _tablesHeapPtr; size = (size + 1) & ~1; diff --git a/engines/agos/verb.cpp b/engines/agos/verb.cpp index 2486f09626..8376ebb28e 100644 --- a/engines/agos/verb.cpp +++ b/engines/agos/verb.cpp @@ -967,7 +967,7 @@ void AGOSEngine::invertBox(HitArea *ha, byte a, byte b, byte c, byte d) { _videoLockOut |= 0x8000; Graphics::Surface *screen = _system->lockScreen(); - src = (byte *)screen->pixels + ha->y * _dxSurfacePitch + ha->x; + src = (byte *)screen->pixels + ha->y * screen->pitch + ha->x; // WORKAROUND: Hitareas for saved game names aren't adjusted for scrolling locations if (getGameType() == GType_SIMON2 && ha->id >= 208 && ha->id <= 213) { @@ -1019,7 +1019,7 @@ void AGOSEngine::invertBox(HitArea *ha, byte a, byte b, byte c, byte d) { } } } - src += _dxSurfacePitch; + src += screen->pitch; } while (--h); _system->unlockScreen(); diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp index eea53b9864..d37681508e 100644 --- a/engines/agos/vga.cpp +++ b/engines/agos/vga.cpp @@ -1182,11 +1182,13 @@ void AGOSEngine::vc31_setWindow() { void AGOSEngine::vc32_saveScreen() { if (getGameType() == GType_PN) { Graphics::Surface *screen = _system->lockScreen(); - byte *dst = getBackGround(); byte *src = (byte *)screen->pixels; - memcpy(dst, src, 64000); - + for (int i = 0; i < _screenHeight; i++) { + memcpy(dst, src, _screenWidth); + dst += _backGroundBuf->pitch; + src += screen->pitch; + } _system->unlockScreen(); } else { uint16 xoffs = _videoWindows[4 * 4 + 0] * 16; @@ -1194,12 +1196,12 @@ void AGOSEngine::vc32_saveScreen() { uint16 width = _videoWindows[4 * 4 + 2] * 16; uint16 height = _videoWindows[4 * 4 + 3]; - byte *dst = getBackGround() + xoffs + yoffs * _screenWidth; - byte *src = _window4BackScn; + byte *dst = (byte *)_backGroundBuf->getBasePtr(xoffs, yoffs); + byte *src = (byte *)_window4BackScn->pixels;; uint16 srcWidth = _videoWindows[4 * 4 + 2] * 16; for (; height > 0; height--) { memcpy(dst, src, width); - dst += _screenWidth; + dst += _backGroundBuf->pitch; src += srcWidth; } } @@ -1228,11 +1230,11 @@ void AGOSEngine::vc34_setMouseOff() { void AGOSEngine::clearVideoBackGround(uint16 num, uint16 color) { const uint16 *vlut = &_videoWindows[num * 4]; - byte *dst = getBackGround() + vlut[0] * 16 + vlut[1] * _dxSurfacePitch; + byte *dst = (byte *)_backGroundBuf->getBasePtr(vlut[0] * 16, vlut[1]); for (uint h = 0; h < vlut[3]; h++) { memset(dst, color, vlut[2] * 16); - dst += _screenWidth; + dst += _backGroundBuf->pitch; } } @@ -1250,14 +1252,18 @@ void AGOSEngine::clearVideoWindow(uint16 num, uint16 color) { if (getGameType() == GType_ELVIRA1 && num == 3) { Graphics::Surface *screen = _system->lockScreen(); - memset((byte *)screen->pixels, color, _screenWidth * _screenHeight); + byte *dst = (byte *)screen->pixels; + for (int i = 0; i < _screenHeight; i++) { + memset(dst, color, _screenWidth); + dst += screen->pitch; + } _system->unlockScreen(); } else if (num == 4) { const uint16 *vlut = &_videoWindows[num * 4]; uint16 xoffs = (vlut[0] - _videoWindows[16]) * 16; uint16 yoffs = (vlut[1] - _videoWindows[17]); uint16 dstWidth = _videoWindows[18] * 16; - byte *dst = _window4BackScn + xoffs + yoffs * dstWidth; + byte *dst = (byte *)_window4BackScn->pixels + xoffs + yoffs * dstWidth; setMoveRect(0, 0, vlut[2] * 16, vlut[3]); diff --git a/engines/agos/vga_e2.cpp b/engines/agos/vga_e2.cpp index 58d3329296..f6e6630d43 100644 --- a/engines/agos/vga_e2.cpp +++ b/engines/agos/vga_e2.cpp @@ -77,7 +77,7 @@ void AGOSEngine::vc45_setWindowPalette() { uint8 height = vlut[3]; if (num == 4) { - byte *dst = _window4BackScn; + byte *dst = (byte *)_window4BackScn->pixels; for (uint8 h = 0; h < height; h++) { for (uint8 w = 0; w < width; w++) { @@ -90,7 +90,7 @@ void AGOSEngine::vc45_setWindowPalette() { } } else { Graphics::Surface *screen = _system->lockScreen(); - byte *dst = (byte *)screen->pixels + vlut[0] * 16 + vlut[1] * _dxSurfacePitch; + byte *dst = (byte *)screen->getBasePtr(vlut[0] * 16, vlut[1]); if (getGameType() == GType_ELVIRA2 && num == 7) { dst -= 8; @@ -104,7 +104,7 @@ void AGOSEngine::vc45_setWindowPalette() { val |= color * 16; WRITE_LE_UINT16(dst + w * 2, val); } - dst += _dxSurfacePitch; + dst += screen->pitch; } _system->unlockScreen(); @@ -207,6 +207,7 @@ void AGOSEngine::vc53_dissolveIn() { uint16 speed = vcReadNextWord() + 1; byte *src, *dst, *srcOffs, *srcOffs2, *dstOffs, *dstOffs2; + int16 xoffs, yoffs; uint8 color = 0; // Only uses Video Window 4 @@ -218,18 +219,17 @@ void AGOSEngine::vc53_dissolveIn() { uint16 dissolveDelay = dissolveCheck * 2 / speed; uint16 dissolveCount = dissolveCheck * 2 / speed; - int16 xoffs = _videoWindows[num * 4 + 0] * 16; - int16 yoffs = _videoWindows[num * 4 + 1]; - int16 offs = xoffs + yoffs * _screenWidth; + int16 x = _videoWindows[num * 4 + 0] * 16; + int16 y = _videoWindows[num * 4 + 1]; uint16 count = dissolveCheck * 2; while (count--) { Graphics::Surface *screen = _system->lockScreen(); - byte *dstPtr = (byte *)screen->pixels + offs; + byte *dstPtr = (byte *)screen->pixels + x + y * screen->pitch; yoffs = _rnd.getRandomNumber(dissolveY); - dst = dstPtr + yoffs * _screenWidth; - src = _window4BackScn + yoffs * 224; + dst = dstPtr + yoffs * screen->pitch; + src = (byte *)_window4BackScn->pixels + yoffs * _window4BackScn->pitch; xoffs = _rnd.getRandomNumber(dissolveX); dst += xoffs; @@ -252,15 +252,15 @@ void AGOSEngine::vc53_dissolveIn() { dstOffs2 = dst; yoffs = (dissolveY - 1) * 2 - (yoffs * 2); - src = srcOffs + yoffs * 224; - dst = dstOffs + yoffs * _screenWidth; + src = srcOffs + yoffs * _window4BackScn->pitch; + dst = dstOffs + yoffs * screen->pitch; color = 0xF0; *dst &= color; *dst |= *src & 0xF; - dst = dstOffs2 + yoffs * _screenWidth; - src = srcOffs2 + yoffs * 224; + dst = dstOffs2 + yoffs * screen->pitch; + src = srcOffs2 + yoffs * _window4BackScn->pitch; *dst &= color; *dst |= *src & 0xF; @@ -284,6 +284,7 @@ void AGOSEngine::vc54_dissolveOut() { uint16 speed = vcReadNextWord() + 1; byte *dst, *dstOffs; + int16 xoffs, yoffs; uint16 dissolveX = _videoWindows[num * 4 + 2] * 8; uint16 dissolveY = (_videoWindows[num * 4 + 3] + 1) / 2; @@ -291,19 +292,18 @@ void AGOSEngine::vc54_dissolveOut() { uint16 dissolveDelay = dissolveCheck * 2 / speed; uint16 dissolveCount = dissolveCheck * 2 / speed; - int16 xoffs = _videoWindows[num * 4 + 0] * 16; - int16 yoffs = _videoWindows[num * 4 + 1]; - int16 offs = xoffs + yoffs * _screenWidth; + int16 x = _videoWindows[num * 4 + 0] * 16; + int16 y = _videoWindows[num * 4 + 1]; uint16 count = dissolveCheck * 2; while (count--) { Graphics::Surface *screen = _system->lockScreen(); - byte *dstPtr = (byte *)screen->pixels + offs; + byte *dstPtr = (byte *)screen->pixels + x + y * screen->pitch; color |= dstPtr[0] & 0xF0; yoffs = _rnd.getRandomNumber(dissolveY); xoffs = _rnd.getRandomNumber(dissolveX); - dst = dstPtr + xoffs + yoffs * _screenWidth; + dst = dstPtr + xoffs + yoffs * screen->pitch; *dst = color; dstOffs = dst; @@ -313,7 +313,7 @@ void AGOSEngine::vc54_dissolveOut() { *dst = color; yoffs = (dissolveY - 1) * 2 - (yoffs * 2); - dst = dstOffs + yoffs * _screenWidth; + dst = dstOffs + yoffs * screen->pitch; *dst = color; dst += xoffs; @@ -354,18 +354,22 @@ void AGOSEngine::vc55_moveBox() { } void AGOSEngine::vc56_fullScreen() { - Graphics::Surface *screen = _system->lockScreen(); + uint8 palette[1024]; + Graphics::Surface *screen = _system->lockScreen(); byte *dst = (byte *)screen->pixels; - byte *src = _curVgaFile2 + 32; - - memcpy(dst, src + 768, _screenHeight * _screenWidth); + byte *src = _curVgaFile2 + 800; + for (int i = 0; i < _screenHeight; i++) { + memcpy(dst, src, _screenWidth); + src += 320; + dst += screen->pitch; + } _system->unlockScreen(); //fullFade(); - uint8 palette[1024]; + src = _curVgaFile2 + 32; for (int i = 0; i < 256; i++) { palette[i * 4 + 0] = *src++ * 4; palette[i * 4 + 1] = *src++ * 4; diff --git a/engines/agos/vga_ff.cpp b/engines/agos/vga_ff.cpp index 58eb2f4cc0..14451a3dbe 100644 --- a/engines/agos/vga_ff.cpp +++ b/engines/agos/vga_ff.cpp @@ -70,7 +70,7 @@ int AGOSEngine::getScale(int16 y, int16 x) { void AGOSEngine::vc75_setScale() { _baseY = vcReadNextWord(); - _scale = (float)vcReadNextWord() / 1000000.; + _scale = vcReadNextWord() / 1000000.0f; } void AGOSEngine::vc76_setScaleXOffs() { diff --git a/engines/agos/vga_pn.cpp b/engines/agos/vga_pn.cpp index e84248bb4d..12846b08f1 100644 --- a/engines/agos/vga_pn.cpp +++ b/engines/agos/vga_pn.cpp @@ -129,7 +129,6 @@ void AGOSEngine::vc36_pause() { _keyPressed.reset(); windowPutChar(_windowArray[2], 13); - windowPutChar(_windowArray[2], 128); _wiped = oldWiped; _videoLockOut &= ~8; @@ -168,7 +167,7 @@ void AGOSEngine::vc48_specialEffect() { if (dst[w] == 15) dst[w] = 4; } - dst += _screenWidth; + dst += screen->pitch; } _system->unlockScreen(); } else if (num == 2) { diff --git a/engines/agos/vga_s2.cpp b/engines/agos/vga_s2.cpp index 28a383547f..e133427d76 100644 --- a/engines/agos/vga_s2.cpp +++ b/engines/agos/vga_s2.cpp @@ -28,6 +28,8 @@ #include "agos/agos.h" #include "agos/intern.h" +#include "graphics/surface.h" + namespace AGOS { void AGOSEngine_Simon2::setupVideoOpcodes(VgaOpcodeProc *op) { @@ -215,7 +217,7 @@ void AGOSEngine_Simon2::clearVideoWindow(uint16 num, uint16 color) { uint16 xoffs = vlut[0] * 16; uint16 yoffs = vlut[1]; uint16 dstWidth = _videoWindows[18] * 16; - byte *dst = _window4BackScn + xoffs + yoffs * dstWidth; + byte *dst = (byte *)_window4BackScn->pixels + xoffs + yoffs * dstWidth; setMoveRect(0, 0, vlut[2] * 16, vlut[3]); diff --git a/engines/agos/vga_ww.cpp b/engines/agos/vga_ww.cpp index 4f6d510fbf..e7f2ad7807 100644 --- a/engines/agos/vga_ww.cpp +++ b/engines/agos/vga_ww.cpp @@ -145,14 +145,20 @@ void AGOSEngine::vc61() { uint h, tmp; Graphics::Surface *screen = _system->lockScreen(); + dstPtr = (byte *)screen->pixels; if (a == 6) { src = _curVgaFile2 + 800; - dstPtr = (byte *)screen->pixels; - memcpy(dstPtr, src, 64000); + dst = dstPtr; + + for (int i = 0; i < _screenHeight; i++) { + memcpy(dst, src, _screenWidth); + src += 320; + dst += screen->pitch; + } + tmp = 4 - 1; } else { - dstPtr = (byte *)screen->pixels; tmp = a - 1; } @@ -160,15 +166,14 @@ void AGOSEngine::vc61() { while (tmp--) src += 1536 * 16 + 1712; - src += 800; if (a != 5) { - dst = dstPtr + 7448; + dst = dstPtr + 23 * screen->pitch + 88; for (h = 0; h < 177; h++) { memcpy(dst, src, 144); src += 144; - dst += _screenWidth; + dst += screen->pitch; } if (a != 6) { @@ -179,11 +184,11 @@ void AGOSEngine::vc61() { src = _curVgaFile2 + 9984 * 16 + 15344; } - dst = dstPtr + 50296; + dst = dstPtr + 157 * screen->pitch + 56; for (h = 0; h < 17; h++) { memcpy(dst, src, 208); src += 208; - dst += _screenWidth; + dst += screen->pitch; } _system->unlockScreen(); diff --git a/engines/agos/window.cpp b/engines/agos/window.cpp index 8737498e79..a578568a03 100644 --- a/engines/agos/window.cpp +++ b/engines/agos/window.cpp @@ -128,14 +128,14 @@ void AGOSEngine_Feeble::colorWindow(WindowBlock *window) { _videoLockOut |= 0x8000; - dst = getBackGround() + _dxSurfacePitch * window->y + window->x; + dst = getBackGround() + _backGroundBuf->pitch * window->y + window->x; for (h = 0; h < window->height; h++) { for (w = 0; w < window->width; w++) { if (dst[w] == 113 || dst[w] == 116 || dst[w] == 252) dst[w] = window->fillColor; } - dst += _screenWidth; + dst += _backGroundBuf->pitch; } _videoLockOut &= ~0x8000; @@ -171,7 +171,7 @@ void AGOSEngine::colorBlock(WindowBlock *window, uint16 x, uint16 y, uint16 w, u _videoLockOut |= 0x8000; Graphics::Surface *screen = _system->lockScreen(); - byte *dst = (byte *)screen->pixels + y * _screenWidth + x; + byte *dst = (byte *)screen->pixels + y * screen->pitch + x; uint8 color = window->fillColor; if (getGameType() == GType_ELVIRA2 || getGameType() == GType_WW) @@ -179,7 +179,7 @@ void AGOSEngine::colorBlock(WindowBlock *window, uint16 x, uint16 y, uint16 w, u do { memset(dst, color, w); - dst += _screenWidth; + dst += screen->pitch; } while (--h); _system->unlockScreen(); @@ -236,8 +236,8 @@ void AGOSEngine::restoreBlock(uint16 x, uint16 y, uint16 w, uint16 h) { dst = (byte *)screen->pixels; src = getBackGround(); - dst += y * _dxSurfacePitch; - src += y * _dxSurfacePitch; + dst += y * screen->pitch; + src += y * _backGroundBuf->pitch; uint8 paletteMod = 0; if (getGameType() == GType_ELVIRA1 && !(getFeatures() & GF_DEMO) && y >= 133) @@ -247,8 +247,8 @@ void AGOSEngine::restoreBlock(uint16 x, uint16 y, uint16 w, uint16 h) { for (i = x; i < w; i++) dst[i] = src[i] + paletteMod; y++; - dst += _dxSurfacePitch; - src += _dxSurfacePitch; + dst += screen->pitch; + src += _backGroundBuf->pitch; } _system->unlockScreen(); diff --git a/engines/cine/saveload.cpp b/engines/cine/saveload.cpp index ea0ff0079b..be1e19b229 100644 --- a/engines/cine/saveload.cpp +++ b/engines/cine/saveload.cpp @@ -49,7 +49,7 @@ bool loadChunkHeader(Common::SeekableReadStream &in, ChunkHeader &header) { header.id = in.readUint32BE(); header.version = in.readUint32BE(); header.size = in.readUint32BE(); - return !in.ioFailed(); + return !(in.eos() || in.err()); } /*! \brief Savegame format detector @@ -240,21 +240,21 @@ bool loadObjectTable(Common::SeekableReadStream &in) { in.read(objectTable[i].name, 20); objectTable[i].part = in.readUint16BE(); } - return !in.ioFailed(); + return !(in.eos() || in.err()); } bool loadZoneData(Common::SeekableReadStream &in) { for (int i = 0; i < 16; i++) { zoneData[i] = in.readUint16BE(); } - return !in.ioFailed(); + return !(in.eos() || in.err()); } bool loadCommandVariables(Common::SeekableReadStream &in) { for (int i = 0; i < 4; i++) { commandVar3[i] = in.readUint16BE(); } - return !in.ioFailed(); + return !(in.eos() || in.err()); } bool loadScreenParams(Common::SeekableReadStream &in) { @@ -265,7 +265,7 @@ bool loadScreenParams(Common::SeekableReadStream &in) { in.readUint16BE(); in.readUint16BE(); in.readUint16BE(); - return !in.ioFailed(); + return !(in.eos() || in.err()); } bool loadGlobalScripts(Common::SeekableReadStream &in) { @@ -273,7 +273,7 @@ bool loadGlobalScripts(Common::SeekableReadStream &in) { for (int i = 0; i < size; i++) { loadScriptFromSave(in, true); } - return !in.ioFailed(); + return !(in.eos() || in.err()); } bool loadObjectScripts(Common::SeekableReadStream &in) { @@ -281,7 +281,7 @@ bool loadObjectScripts(Common::SeekableReadStream &in) { for (int i = 0; i < size; i++) { loadScriptFromSave(in, false); } - return !in.ioFailed(); + return !(in.eos() || in.err()); } bool loadOverlayList(Common::SeekableReadStream &in) { @@ -289,7 +289,7 @@ bool loadOverlayList(Common::SeekableReadStream &in) { for (int i = 0; i < size; i++) { loadOverlayFromSave(in); } - return !in.ioFailed(); + return !(in.eos() || in.err()); } bool loadSeqList(Common::SeekableReadStream &in) { @@ -312,14 +312,14 @@ bool loadSeqList(Common::SeekableReadStream &in) { tmp.var1E = in.readSint16BE(); seqList.push_back(tmp); } - return !in.ioFailed(); + return !(in.eos() || in.err()); } bool loadZoneQuery(Common::SeekableReadStream &in) { for (int i = 0; i < 16; i++) { zoneQuery[i] = in.readUint16BE(); } - return !in.ioFailed(); + return !(in.eos() || in.err()); } void saveObjectTable(Common::OutSaveFile &out) { @@ -632,7 +632,7 @@ bool CineEngine::loadTempSaveOS(Common::SeekableReadStream &in) { warning("loadTempSaveOS: Loaded the savefile but didn't exhaust it completely. Something was left over"); } - return !in.ioFailed(); + return !(in.eos() || in.err()); } bool CineEngine::loadPlainSaveFW(Common::SeekableReadStream &in, CineSaveGameFormat saveGameFormat) { @@ -755,7 +755,7 @@ bool CineEngine::loadPlainSaveFW(Common::SeekableReadStream &in, CineSaveGameFor } } - return !in.ioFailed(); + return !(in.eos() || in.err()); } bool CineEngine::makeLoad(char *saveName) { diff --git a/engines/cine/script_fw.cpp b/engines/cine/script_fw.cpp index 0c92beb650..a9824674e6 100644 --- a/engines/cine/script_fw.cpp +++ b/engines/cine/script_fw.cpp @@ -1443,6 +1443,38 @@ int FWScript::o1_palRotate() { int FWScript::o1_break() { debugC(5, kCineDebugScript, "Line: %d: break", _line); + // WORKAROUND for bug #2669415 ("FW: half walking speed in a screen"). + // The problem was that in Amiga/Atari ST versions of Future Wars the + // walking speed has halved in a forest scene where a monk's robe hangs + // on a tree branch (Up and to the left from the medieval castle's front). + // + // Initialization script for the scene is PART02.PRC's 26th script (011_INIT) + // and the background used in the scene is L11.PI1. The difference between + // the PC version and the Amiga/Atari ST version of the script is that the + // PC version calls scripts 37 and 36 for handling movement of the character + // when Amiga/Atari ST version calls scripts 22 and 21 for the same purpose + // (Scripts 37 and 22 handle vertical movement, 36 and 21 the horizontal). + // + // The called scripts only differ functionally so that all BREAK opcodes have been + // doubled in the Amiga/Atari ST versions (i.e. one BREAK has become two BREAKs) + // and in script 21 after LABEL_25 there's an extra opcode that isn't in script 36: + // SET globalvars[251], 0. + // + // As a BREAK opcode stops the execution of a script it causes a pause and + // with the BREAKs doubled the pause is twice as long in the Amiga/Atari ST versions. + // Thus the longer pause is eliminated by running only one BREAK when several + // are designated (i.e. ignoring a BREAK if there's another BREAK after it). + // + // TODO: Check whether the speed is halved in any other scenes in Amiga/Atari ST versions under ScummVM + // TODO: Check whether the speed is halved when running the original executable under an emulator + if (g_cine->getGameType() == Cine::GType_FW && + (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) && + _pos < _script._size && _script.getByte(_pos) == (0x4F + 1) && // Is the next opcode a BREAK too? + scumm_stricmp(currentPrcName, "PART02.PRC") == 0 && + scumm_stricmp(renderer->getBgName(), "L11.PI1") == 0) { + return 0; + } + return 1; } diff --git a/engines/cine/texte.cpp b/engines/cine/texte.cpp index ffc36b4b1a..3dceae2fa4 100644 --- a/engines/cine/texte.cpp +++ b/engines/cine/texte.cpp @@ -37,8 +37,6 @@ const char **otherMessages; const char *defaultCommandPreposition; const char **commandPrepositionTable; -void generateMask(const byte *sprite, byte *mask, uint16 size, byte transparency); - /*! \brief Loads font data from the given file. * The number of characters used in the font varies between game versions: * 78 (Most PC, Amiga and Atari ST versions of Future Wars, but also Operation Stealth's Amiga demo), diff --git a/engines/cine/various.h b/engines/cine/various.h index bdbbc6fb86..1f9aa7dc78 100644 --- a/engines/cine/various.h +++ b/engines/cine/various.h @@ -80,8 +80,6 @@ extern int16 commandVar3[4]; extern char currentDatName[30]; extern uint16 musicIsPlaying; -void setTextWindow(uint16 param1, uint16 param2, uint16 param3, uint16 param4); - extern uint16 errorVar; extern byte menuVar; diff --git a/engines/cruise/actor.cpp b/engines/cruise/actor.cpp index 969be96573..845867409e 100644 --- a/engines/cruise/actor.cpp +++ b/engines/cruise/actor.cpp @@ -528,7 +528,7 @@ void valide_noeud(int16 table[], int16 p, int *nclick, int16 solution0[20 + 3][2 return; } - /****** COUPE LE CHEMIN ******/ + /****** Trim down any un-necessary walk points ******/ i++; d = 0; diff --git a/engines/cruise/cruise.cpp b/engines/cruise/cruise.cpp index 4656704cb8..3d3a44a36c 100644 --- a/engines/cruise/cruise.cpp +++ b/engines/cruise/cruise.cpp @@ -118,6 +118,7 @@ void CruiseEngine::initialize() { // video init stuff initSystem(); + gfxModuleData_Init(); // another bit of video init @@ -139,6 +140,14 @@ void CruiseEngine::initialize() { void CruiseEngine::deinitialise() { polyStructNorm.clear(); polyStructExp.clear(); + + // Clear any backgrounds + for (int i = 0; i < 8; ++i) { + if (backgroundScreens[i]) { + free(backgroundScreens[i]); + backgroundScreens[i] = NULL; + } + } } bool CruiseEngine::loadLanguageStrings() { diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp index 938e823fe9..e5864ebb31 100644 --- a/engines/cruise/cruise_main.cpp +++ b/engines/cruise/cruise_main.cpp @@ -35,13 +35,13 @@ namespace Cruise { +enum RelationType {RT_REL = 30, RT_MSG = 50}; + static int playerDontAskQuit; unsigned int timer = 0; gfxEntryStruct* linkedMsgList = NULL; -extern bool isBlack; - void drawBlackSolidBoxSmall() { // gfxModuleData.drawSolidBox(64,100,256,117,0); drawSolidBox(64, 100, 256, 117, 0); @@ -514,6 +514,7 @@ void CruiseEngine::initAllData(void) { strcpy(lastOverlay, "AUTO00"); _gameSpeed = GAME_FRAME_DELAY_1; + _speedFlag = false; return; } @@ -1025,8 +1026,8 @@ void callSubRelation(menuElementSubStruct *pMenuElement, int nOvl, int nObj) { } if ((obj2Ovl == nOvl) && (pHeader->obj2Number != -1) && (pHeader->obj2Number == nObj)) { -// int x = 60; -// int y = 60; + int x = 60; + int y = 60; objectParamsQuery params; memset(¶ms, 0, sizeof(objectParamsQuery)); // to remove warning @@ -1036,7 +1037,7 @@ void callSubRelation(menuElementSubStruct *pMenuElement, int nOvl, int nObj) { } if ((pHeader->obj2OldState == -1) || (params.state == pHeader->obj2OldState)) { - if (pHeader->type == 30) { // REL + if (pHeader->type == RT_REL) { // REL if (currentScriptPtr) { attacheNewScriptToTail(&relHead, ovlIdx, pHeader->id, 30, currentScriptPtr->scriptNumber, currentScriptPtr->overlayNumber, scriptType_REL); } else { @@ -1074,8 +1075,69 @@ void callSubRelation(menuElementSubStruct *pMenuElement, int nOvl, int nObj) { changeScriptParamInList(ovlIdx, pHeader->id, &relHead, 0, 9998); } } - } else if (pHeader->type == 50) { - ASSERT(0); + } else if (pHeader->type == RT_MSG) { + + if (pHeader->obj2Number >= 0) { + if ((pHeader->trackX !=-1) && (pHeader->trackY !=-1) && + (pHeader->trackX != 9999) && (pHeader->trackY != 9999)) { + x = pHeader->trackX - 100; + y = pHeader->trackY - 150; + } else if (params.scale >= 0) { + x = params.X - 100; + y = params.Y - 40; + } + + if (pHeader->obj2NewState != -1) { + objInit(obj2Ovl, pHeader->obj2Number, pHeader->obj2NewState); + } + } + + if ((pHeader->obj1Number >= 0) && (pHeader->obj1NewState != -1)) { + int obj1Ovl = pHeader->obj1Overlay; + if (!obj1Ovl) obj1Ovl = ovlIdx; + objInit(obj1Ovl, pHeader->obj1Number, pHeader->obj1NewState); + } + + if (currentScriptPtr) { + createTextObject(&cellHead, ovlIdx, pHeader->id, x, y, 200, findHighColor(), masterScreen, currentScriptPtr->overlayNumber, currentScriptPtr->scriptNumber); + } else { + createTextObject(&cellHead, ovlIdx, pHeader->id, x, y, 200, findHighColor(), masterScreen, 0, 0); + } + + userWait = 1; + autoOvl = ovlIdx; + autoMsg = pHeader->id; + + if ((narratorOvl > 0) && (pHeader->trackX != -1) && (pHeader->trackY != -1)) { + actorStruct *pTrack = findActor(&actorHead, narratorOvl, narratorIdx, 0); + + if (pTrack) { + objectParamsQuery naratorParams; + animationStart = false; + + if (pHeader->trackDirection == 9999) { + getMultipleObjectParam(narratorOvl, narratorIdx, &naratorParams); + pTrack->x_dest = naratorParams.X; + pTrack->y_dest = naratorParams.Y; + pTrack->endDirection = direction(naratorParams.X, naratorParams.Y, pHeader->trackX,pHeader->trackY, 0, 0); + } else if ((pHeader->trackX == 9999) && (pHeader->trackY == 9999)) { + getMultipleObjectParam(narratorOvl, narratorIdx, &naratorParams); + pTrack->x_dest = naratorParams.X; + pTrack->y_dest = naratorParams.Y; + pTrack->endDirection = pHeader->trackDirection; + } else { + pTrack->x_dest = pHeader->trackX; + pTrack->y_dest = pHeader->trackY; + pTrack->endDirection = pHeader->trackDirection; + } + + pTrack->flag = 1; + autoTrack = true; + userWait = 0; + userEnabled = 0; + freezeCell(&cellHead, ovlIdx, pHeader->id, 5, -1, 0, 9998); + } + } } } } @@ -1113,7 +1175,7 @@ void callRelation(menuElementSubStruct *pMenuElement, int nObj2) { if (pHeader->obj2Number == nObj2) { // REL - if (pHeader->type == 30) { + if (pHeader->type == RT_REL) { if (currentScriptPtr) { attacheNewScriptToTail(&relHead, ovlIdx, pHeader->id, 30, currentScriptPtr->scriptNumber, currentScriptPtr->overlayNumber, scriptType_REL); } else { @@ -1151,7 +1213,7 @@ void callRelation(menuElementSubStruct *pMenuElement, int nObj2) { changeScriptParamInList(ovlIdx, pHeader->id, &relHead, 0, 9998); } } - } else if (pHeader->type == 50) { // MSG + } else if (pHeader->type == RT_MSG) { // MSG int obj1Ovl = pHeader->obj1Overlay; if (!obj1Ovl) obj1Ovl = ovlIdx; @@ -1293,11 +1355,6 @@ int CruiseEngine::processInput(void) { buttonDown = 0; } - if (userDelay && !userWait) { - userDelay--; - return 0; - } - // Check for Exit 'X' key if (keyboardCode == Common::KEYCODE_x) return 1; @@ -1343,6 +1400,8 @@ int CruiseEngine::processInput(void) { // Check for left mouse button click or Space to end user waiting if ((keyboardCode == Common::KEYCODE_SPACE) || (button == MB_LEFT)) userWait = 0; + + keyboardCode = Common::KEYCODE_INVALID; return 0; } @@ -1567,11 +1626,14 @@ int currentMouseButton = 0; bool bFastMode = false; -void manageEvents() { +bool manageEvents() { Common::Event event; + bool result = false; Common::EventManager * eventMan = g_system->getEventManager(); - while (eventMan->pollEvent(event)) { + while (eventMan->pollEvent(event) && !result) { + result = true; + switch (event.type) { case Common::EVENT_LBUTTONDOWN: currentMouseButton |= MB_LEFT; @@ -1588,11 +1650,12 @@ void manageEvents() { case Common::EVENT_MOUSEMOVE: currentMouseX = event.mouse.x; currentMouseY = event.mouse.y; + result = false; break; case Common::EVENT_QUIT: case Common::EVENT_RTL: playerDontAskQuit = 1; - return; + break; case Common::EVENT_KEYUP: switch (event.kbd.keycode) { case Common::KEYCODE_ESCAPE: @@ -1612,72 +1675,6 @@ void manageEvents() { break; } - /* - * switch (event.kbd.keycode) { - * case '\n': - * case '\r': - * case 261: // Keypad 5 - * if (allowPlayerInput) { - * mouseLeft = 1; - * } - * break; - * case 27: // ESC - * if (allowPlayerInput) { - * mouseRight = 1; - * } - * break; - * case 282: // F1 - * if (allowPlayerInput) { - * playerCommand = 0; // EXAMINE - * makeCommandLine(); - * } - * break; - * case 283: // F2 - * if (allowPlayerInput) { - * playerCommand = 1; // TAKE - * makeCommandLine(); - * } - * break; - * case 284: // F3 - * if (allowPlayerInput) { - * playerCommand = 2; // INVENTORY - * makeCommandLine(); - * } - * break; - * case 285: // F4 - * if (allowPlayerInput) { - * playerCommand = 3; // USE - * makeCommandLine(); - * } - * break; - * case 286: // F5 - * if (allowPlayerInput) { - * playerCommand = 4; // ACTIVATE - * makeCommandLine(); - * } - * break; - * case 287: // F6 - * if (allowPlayerInput) { - * playerCommand = 5; // SPEAK - * makeCommandLine(); - * } - * break; - * case 290: // F9 - * if (allowPlayerInput && !inMenu) { - * makeActionMenu(); - * makeCommandLine(); - * } - * break; - * case 291: // F10 - * if (!disableSystemMenu && !inMenu) { - * g_cine->makeSystemMenu(); - * } - * break; - * default: - * //lastKeyStroke = event.kbd.keycode; - * break; - * } - * break; */ if (event.kbd.flags == Common::KBD_CTRL) { if (event.kbd.keycode == Common::KEYCODE_d) { // Start the debugger @@ -1694,17 +1691,10 @@ void manageEvents() { } } - /*if (count) { - * mouseData.left = mouseLeft; - * mouseData.right = mouseRight; - * mouseLeft = 0; - * mouseRight = 0; - * } - */ + return result; } void getMouseStatus(int16 *pMouseVar, int16 *pMouseX, int16 *pMouseButton, int16 *pMouseY) { - manageEvents(); *pMouseX = currentMouseX; *pMouseY = currentMouseY; *pMouseButton = currentMouseButton; @@ -1747,11 +1737,15 @@ void CruiseEngine::mainLoop(void) { if (!bFastMode) { // Delay for the specified amount of time, but still respond to events + bool skipEvents = false; + while (currentTick < lastTick + _gameSpeed) { g_system->delayMillis(10); currentTick = g_system->getMillis(); - manageEvents(); + if (!skipEvents) + skipEvents = manageEvents(); + if (playerDontAskQuit) break; if (_vm->getDebugger()->isAttached()) @@ -1784,35 +1778,35 @@ void CruiseEngine::mainLoop(void) { // t_start=Osystem_GetTicks(); // readKeyboard(); - bool isUserWait = userWait != 0; + bool isUserWait = userWait != 0; playerDontAskQuit = processInput(); if (playerDontAskQuit) break; - if (isUserWait && !userWait) { - // User waiting has ended - changeScriptParamInList(-1, -1, &procHead, 9999, 0); - changeScriptParamInList(-1, -1, &relHead, 9999, 0); - - mainDraw(0); - flipScreen(); - } - if (enableUser) { userEnabled = 1; enableUser = 0; } - if (userWait < 1) { - manageScripts(&relHead); - manageScripts(&procHead); + if (userDelay && !userWait) { + userDelay--; + continue; + } + + if (isUserWait & !userWait) { + // User waiting has ended + changeScriptParamInList(-1, -1, &procHead, 9999, 0); + changeScriptParamInList(-1, -1, &relHead, 9999, 0); + } + + manageScripts(&relHead); + manageScripts(&procHead); - removeFinishedScripts(&relHead); - removeFinishedScripts(&procHead); + removeFinishedScripts(&relHead); + removeFinishedScripts(&procHead); - processAnimation(); - } + processAnimation(); if (remdo) { // ASSERT(0); @@ -1837,10 +1831,8 @@ void CruiseEngine::mainLoop(void) { PCFadeFlag = 0; /*if (!PCFadeFlag)*/ - if (!isUserWait) { - mainDraw(0); - flipScreen(); - } + mainDraw(userWait); + flipScreen(); if (userEnabled && !userWait && !autoTrack) { if (currentActiveMenu == -1) { @@ -1849,7 +1841,7 @@ void CruiseEngine::mainLoop(void) { getMouseStatus(&main10, &mouseX, &mouseButton, &mouseY); - if (mouseX != oldMouseX && mouseY != oldMouseY) { + if (mouseX != oldMouseX || mouseY != oldMouseY) { int objectType; int newCursor1; int newCursor2; @@ -1874,38 +1866,9 @@ void CruiseEngine::mainLoop(void) { changeCursor(CURSOR_NORMAL); } - if (isUserWait) { - // User Wait handling - if (userWait == 1) { - // Initial step - do { - // Make sure any previous mouse press is released - getMouseStatus(&main10, &mouseX, &mouseButton, &mouseY); - } while (mouseButton != 0); - - ++userWait; -// mainDraw(0); -// flipScreen(); - } else { - // Standard handling -/* - manageScripts(&relHead); - manageScripts(&procHead); - - removeFinishedScripts(&relHead); - removeFinishedScripts(&procHead); -*/ - if (isBlack) { - // This is a bit of a hack to ensure that user waits directly after a palette fade - // have time to restore the palette before waiting starts - mainDraw(0); - flipScreen(); - } else { - // Draw the next screen - processAnimation(); - gfxModuleData_flipScreen(); - } - } + if (userWait == 1) { + // Waiting for press - original wait loop has been integrated into the + // main event loop continue; } diff --git a/engines/cruise/cruise_main.h b/engines/cruise/cruise_main.h index 86e8dc1591..d2e9350d70 100644 --- a/engines/cruise/cruise_main.h +++ b/engines/cruise/cruise_main.h @@ -96,7 +96,6 @@ void *mallocAndZero(int32 size); uint8 *mainProc14(uint16 overlay, uint16 idx); void printInfoBlackBox(const char *string); void waitForPlayerInput(void); -int initCt(const char * ctpName); void loadPackedFileToMem(int fileIdx, uint8 * buffer); int getNumObjectsByClass(int scriptIdx, int param); void resetFileEntryRange(int param1, int param2); @@ -108,7 +107,6 @@ void resetPtr2(scriptInstanceStruct * ptr); void getFileExtention(const char *name, char *buffer); void *allocAndZero(int size); void freeStuff2(void); -const char *getObjectName(int index, const char * string); void mainLoop(void); void getMouseStatus(int16 *pMouseVar, int16 *pMouseX, int16 *pMouseButton, int16 *pMouseY); bool testMask(int x, int y, unsigned char* pData, int stride); diff --git a/engines/cruise/ctp.cpp b/engines/cruise/ctp.cpp index be4639af4d..aa2a6c7772 100644 --- a/engines/cruise/ctp.cpp +++ b/engines/cruise/ctp.cpp @@ -106,7 +106,7 @@ void renderCTPWalkBox(int16 *walkboxData, int hotPointX, int hotPointY, int X, i int16 *destination; int startX = X - ((upscaleValue(hotPointX, scale) + 0x8000) >> 16); -// int startY = Y - ((upscaleValue(hotPointY, scale) + 0x8000) >> 16); + int startY = Y - ((upscaleValue(hotPointY, scale) + 0x8000) >> 16); numPoints = *(walkboxData++); @@ -117,7 +117,7 @@ void renderCTPWalkBox(int16 *walkboxData, int hotPointX, int hotPointY, int X, i int pointY = *(walkboxData++); int scaledX = ((upscaleValue(pointX, scale) + 0x8000) >> 16) + startX; - int scaledY = ((upscaleValue(pointY, scale) + 0x8000) >> 16) + startX; + int scaledY = ((upscaleValue(pointY, scale) + 0x8000) >> 16) + startY; *(destination++) = scaledX; *(destination++) = scaledY; @@ -209,9 +209,9 @@ int setNodeState(int nodeIdx, int nodeState) { int oldState = walkboxState[nodeIdx]; if (nodeState == -1) - return + return oldState; - walkboxState[nodeIdx] = nodeState; + walkboxState[nodeIdx] = nodeState; return oldState; } diff --git a/engines/cruise/font.cpp b/engines/cruise/font.cpp index d5010b2bf8..c1afba3c45 100644 --- a/engines/cruise/font.cpp +++ b/engines/cruise/font.cpp @@ -159,7 +159,9 @@ void initSystem(void) { switchPal = 0; masterScreen = 0; + changeCursor(CURSOR_NOMOUSE); changeCursor(CURSOR_NORMAL); + mouseOn(); strcpy(cmdLine, ""); @@ -242,7 +244,7 @@ int32 prepareWordRender(int32 inRightBorder_X, int16 wordSpacingWidth, if (character == '|' || !character) { finish = 1; } else { - if (charData) { + if (charData >= 0) { if (pixelCount + wordSpacingWidth + (int16)fontData[charData].charWidth >= inRightBorder_X) { finish = 1; diff --git a/engines/cruise/function.cpp b/engines/cruise/function.cpp index eab69c6846..6fe82f76d4 100644 --- a/engines/cruise/function.cpp +++ b/engines/cruise/function.cpp @@ -709,9 +709,7 @@ int16 Op_GetMouseButton(void) { getMouseStatus(&dummy, &mouseX, &mouseButton, &mouseY); - if (mouseButton) - return 1; - return 0; + return mouseButton; } int16 Op_AddCell(void) { @@ -828,7 +826,7 @@ int16 Op_Preload(void) { } int16 Op_LoadCt(void) { - return initCt((char*)popPtr()); + return initCt((const char *)popPtr()); } int16 Op_EndAnim(void) { diff --git a/engines/cruise/gfxModule.cpp b/engines/cruise/gfxModule.cpp index 50e6587d90..003a335e42 100644 --- a/engines/cruise/gfxModule.cpp +++ b/engines/cruise/gfxModule.cpp @@ -40,7 +40,6 @@ palEntry lpalette[256]; int palDirtyMin = 256; int palDirtyMax = -1; -bool isBlack = false; gfxModuleDataStruct gfxModuleData = { 0, // use Tandy @@ -218,6 +217,12 @@ void gfxCopyRect(const uint8 *sourceBuffer, int width, int height, byte *dest, i } } +void gfxModuleData_Init(void) { + memset(globalScreen, 0, 320 * 200); + memset(page00, 0, 320 * 200); + memset(page10, 0, 320 * 200); +} + void gfxModuleData_flipScreen(void) { memcpy(globalScreen, gfxModuleData.pPage00, 320 * 200); @@ -238,12 +243,6 @@ void flip() { g_system->setPalette(paletteRGBA + palDirtyMin*4, palDirtyMin, palDirtyMax - palDirtyMin + 1); palDirtyMin = 256; palDirtyMax = -1; - - isBlack = true; - for (i = 0; i < 256; ++i) { - isBlack = (lpalette[i].R == 0) && (lpalette[i].G == 0) && (lpalette[i].B == 0); - if (!isBlack) break; - } } g_system->copyRectToScreen(globalScreen, 320, 0, 0, 320, 200); diff --git a/engines/cruise/gfxModule.h b/engines/cruise/gfxModule.h index 4b06e62991..dc085d8b0d 100644 --- a/engines/cruise/gfxModule.h +++ b/engines/cruise/gfxModule.h @@ -56,6 +56,7 @@ void gfxCopyRect(const uint8 *sourceBuffer, int width, int height, byte *dest, i void gfxModuleData_gfxCopyScreen(const uint8 *sourcePtr, uint8 *destPtr); void convertGfxFromMode4(const uint8 *sourcePtr, int width, int height, uint8 *destPtr); void convertGfxFromMode5(const uint8 *sourcePtr, int width, int height, uint8 *destPtr); +void gfxModuleData_Init(void); void gfxModuleData_flipScreen(void); //void gfxModuleData_setPal(uint8 * ptr); void gfxModuleData_convertOldPalColor(uint16 oldColor, uint8 *pOutput); diff --git a/engines/cruise/menu.cpp b/engines/cruise/menu.cpp index 0e9ab55c82..54f686f32a 100644 --- a/engines/cruise/menu.cpp +++ b/engines/cruise/menu.cpp @@ -146,7 +146,7 @@ void updateMenuMouse(int mouseX, int mouseY, menuStruct *pMenu) { } } -void manageEvents(); +bool manageEvents(); int processMenu(menuStruct *pMenu) { int16 mouseX; diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp index d151950c5e..7fcc5ecb1b 100644 --- a/engines/cruise/saveload.cpp +++ b/engines/cruise/saveload.cpp @@ -898,11 +898,15 @@ Common::Error loadSavegameData(int saveGameIdx) { printf("Unsupported mono file load!\n"); ASSERT(0); //loadFileMode1(filesDatabase[j].subData.name,filesDatabase[j].subData.var4); - } else */{ + } else */ + if (strlen(filesDatabase[i].subData.name) > 0) { loadFileRange(filesDatabase[i].subData.name, filesDatabase[i].subData.index, i, j - i); - i = j - 1; + } else { + filesDatabase[i].subData.ptr = NULL; + filesDatabase[i].subData.ptrMask = NULL; } + i = j - 1; lowMemory = lowMemorySave; } } diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp index f59fa80e8d..99cf7c1193 100644 --- a/engines/gob/dataio.cpp +++ b/engines/gob/dataio.cpp @@ -488,6 +488,9 @@ int16 DataIO::openData(const char *path) { } bool DataIO::existData(const char *path) { + if (!path || (path[0] == '\0')) + return false; + int16 handle = openData(path); if (handle < 0) @@ -584,7 +587,7 @@ byte *DataIO::getData(const char *path) { } DataStream *DataIO::getDataStream(const char *path) { - if (!path || (path[0] == '\0') || !existData(path)) + if (!existData(path)) return 0; uint32 size = getDataSize(path); diff --git a/engines/gob/demos/demoplayer.cpp b/engines/gob/demos/demoplayer.cpp index 0229bb7515..7f65721ce5 100644 --- a/engines/gob/demos/demoplayer.cpp +++ b/engines/gob/demos/demoplayer.cpp @@ -222,7 +222,7 @@ void DemoPlayer::playVideoDoubled() { int16 key; bool end = false; while (_vm->_util->checkKey(key)) - if (key == 0x011B) + if (key == kKeyEscape) end = true; if (end) break; diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index 9426c01ef2..61c17b16f8 100644 --- a/engines/gob/detection.cpp +++ b/engines/gob/detection.cpp @@ -68,9 +68,11 @@ static const PlainGameDescriptor gobGames[] = { {"playtoons5", "Playtoons 5 - The Stone of Wakan"}, {"playtnck1", "Playtoons Construction Kit 1 - Monsters"}, {"playtnck2", "Playtoons Construction Kit 2 - Knights"}, + {"playtnck3", "Playtoons Construction Kit 3 - Far West"}, {"bambou", "Playtoons Limited Edition - Bambou le sauveur de la jungle"}, {"fascination", "Fascination"}, {"geisha", "Geisha"}, + {"magicstones", "The Land of the Magic Stones"}, {"adibou4", "Adibou v4"}, {"adibouunknown", "Adibou (not yet supported)"}, {0, 0} @@ -3438,6 +3440,24 @@ static const GOBGameDescription gameDescriptions[] = { "playtoons2", "", { + {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262}, + {"spirou.stk", 0, "5d9c7644d0c47840169b4d016765cc1a", 9816201}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoon, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons2", + "", + { {"playtoon.stk", 0, "55a85036dd93cce93532d8f743d90074", 17467154}, {"spirou.stk", 0, "e3e1b6148dd72fafc3637f1a8e5764f5", 9812043}, {0, 0, 0, 0} @@ -3541,7 +3561,6 @@ static const GOBGameDescription gameDescriptions[] = { kFeatures640, "intro2.stk", 0, 0 }, - { { "playtoons4", @@ -3560,6 +3579,24 @@ static const GOBGameDescription gameDescriptions[] = { kFeatures640, "intro2.stk", 0, 0 }, + { //Supplied by goodoldgeorg in bug report #2820006 + { + "playtoons4", + "", + { + {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, + {"manda.stk", 0, "69a79c9f61b2618e482726f2ff68078d", 6499208}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoon, + kFeatures640, + "intro2.stk", 0, 0 + }, { { "playtoons5", @@ -3634,6 +3671,42 @@ static const GOBGameDescription gameDescriptions[] = { }, { { + "playtnck3", + "", + { + {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, + {"dan.itk", 0, "9a8f62809eca5a52f429b5b6a8e70f8f", 2861056}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytnCk, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "magicstones", + "", + { + {"ed4.stk", 0, "98721a7cfdc5a358d7ac56b7c6d3ba3d", 541882}, + {"ed4cd.itk", 0, "0627a91d9a6f4772c33747ce752024c2", 606993908}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeMagicStones, + kFeatures800x600, + "ed4.stk", "main.obc", 0 + }, + { + { "adibou4", "", AD_ENTRY1s("intro.stk", "a3c35d19b2d28ea261d96321d208cb5a", 6021466), @@ -4189,6 +4262,20 @@ static const GOBGameDescription fallbackDescs[] = { }, { { + "magicstones", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeMagicStones, + kFeatures800x600, + "ed4.stk", "main.obc", 0 + }, + { + { "adibou4", "", AD_ENTRY1(0, 0), @@ -4241,8 +4328,9 @@ static const ADFileBasedFallback fileBased[] = { { &fallbackDescs[19], { "intro.stk", "bambou.itk", 0 } }, { &fallbackDescs[20], { "disk0.stk", "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, { &fallbackDescs[21], { "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, - { &fallbackDescs[22], { "adif41.stk", "adim41.stk", 0 } }, - { &fallbackDescs[23], { "coktelplayer.scn", 0 } }, + { &fallbackDescs[22], { "ed4.stk", 0 } }, + { &fallbackDescs[23], { "adif41.stk", "adim41.stk", 0 } }, + { &fallbackDescs[24], { "coktelplayer.scn", 0 } }, { 0, { 0 } } }; diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp index b3e5e7418c..fb3cb9bbcd 100644 --- a/engines/gob/draw.cpp +++ b/engines/gob/draw.cpp @@ -29,6 +29,7 @@ #include "gob/draw.h" #include "gob/global.h" #include "gob/util.h" +#include "gob/dataio.h" #include "gob/game.h" #include "gob/script.h" #include "gob/inter.h" @@ -60,7 +61,7 @@ Draw::Draw(GobEngine *vm) : _vm(vm) { _backDeltaX = 0; _backDeltaY = 0; - for (int i = 0; i < 8; i++) + for (int i = 0; i < kFontCount; i++) _fonts[i] = 0; _spritesArray.resize(SPRITES_COUNT); @@ -128,7 +129,7 @@ Draw::Draw(GobEngine *vm) : _vm(vm) { } Draw::~Draw() { - for (int i = 0; i < 8; i++) + for (int i = 0; i < kFontCount; i++) delete _fonts[i]; } @@ -346,6 +347,8 @@ int Draw::stringLength(const char *str, int16 fontIndex) { if ((fontIndex < 0) || (fontIndex > 7) || !_fonts[fontIndex]) return 0; + Font &font = *_fonts[fontIndex]; + int len = 0; if (_vm->_global->_language == 10) { @@ -355,16 +358,16 @@ int Draw::stringLength(const char *str, int16 fontIndex) { len += japaneseExtraCharLen[4]; i++; } else - len += _fonts[fontIndex]->itemWidth; + len += font.getCharWidth(); } } else { - if (_fonts[fontIndex]->extraData) - while (*str != 0) - len += *(_fonts[fontIndex]->extraData + (*str++ - _fonts[fontIndex]->startItem)); + if (!font.isMonospaced()) + while (*str != '\0') + len += font.getCharWidth(*str++); else - len = (strlen(str) * _fonts[fontIndex]->itemWidth); + len = strlen(str) * font.getCharWidth(); } @@ -372,14 +375,11 @@ int Draw::stringLength(const char *str, int16 fontIndex) { } void Draw::drawString(const char *str, int16 x, int16 y, int16 color1, int16 color2, - int16 transp, SurfaceDesc &dest, Video::FontDesc *font) { + int16 transp, SurfaceDesc &dest, const Font &font) { while (*str != '\0') { _vm->_video->drawLetter(*str, x, y, font, transp, color1, color2, dest); - if (!font->extraData) - x += font->itemWidth; - else - x += *(font->extraData + (*str - font->startItem)); + x += font.getCharWidth(*str); str++; } } @@ -407,23 +407,23 @@ void Draw::printTextCentered(int16 id, int16 left, int16 top, int16 right, if (str[0] == '\0') return; - int16 width = 0; - _transparency = 1; _destSpriteX = left; _destSpriteY = top; _fontIndex = fontIndex; _frontColor = color; _textToPrint = str; - if (_fonts[fontIndex]->extraData != 0) { - byte *data = _fonts[fontIndex]->extraData; - int length = strlen(str); - for (int i = 0; i < length; i++) - width += *(data + (str[i] - _fonts[_fontIndex]->startItem)); + Font &font = *_fonts[fontIndex]; + + int16 width = 0; + if (!font.isMonospaced()) { + const char *s = str; + while (*s != '\0') + width += font.getCharWidth(*s++); } else - width = strlen(str) * _fonts[fontIndex]->itemWidth; + width = strlen(str) * font.getCharWidth(); adjustCoords(1, &width, 0); _destSpriteX += (right - left + 1 - width) / 2; @@ -546,4 +546,24 @@ void Draw::wobble(SurfaceDesc &surfDesc) { delete[] offsets; } +Font *Draw::loadFont(const char *path) const { + if (!_vm->_dataIO->existData(path)) + return 0; + + byte *data = _vm->_dataIO->getData(path); + + return new Font(data); +} + +bool Draw::loadFont(int fontIndex, const char *path) { + if ((fontIndex < 0) || (fontIndex >= kFontCount)) + return false; + + delete _fonts[fontIndex]; + + _fonts[fontIndex] = loadFont(path); + + return _fonts[fontIndex] != 0; +} + } // End of namespace Gob diff --git a/engines/gob/draw.h b/engines/gob/draw.h index 26f78ce3b3..ba32df0c3e 100644 --- a/engines/gob/draw.h +++ b/engines/gob/draw.h @@ -45,6 +45,8 @@ namespace Gob { class Draw { public: + static const int kFontCount = 8; + struct FontToSprite { int8 sprite; int8 base; @@ -76,7 +78,7 @@ public: int16 _backDeltaY; FontToSprite _fontToSprite[4]; - Video::FontDesc *_fonts[8]; + Font *_fonts[kFontCount]; Common::Array<SurfaceDescPtr> _spritesArray; @@ -152,7 +154,7 @@ public: } int stringLength(const char *str, int16 fontIndex); void drawString(const char *str, int16 x, int16 y, int16 color1, int16 color2, - int16 transp, SurfaceDesc &dest, Video::FontDesc *font); + int16 transp, SurfaceDesc &dest, const Font &font); void printTextCentered(int16 id, int16 left, int16 top, int16 right, int16 bottom, const char *str, int16 fontIndex, int16 color); int32 getSpriteRectSize(int16 index); @@ -161,6 +163,9 @@ public: static const int16 _wobbleTable[360]; void wobble(SurfaceDesc &surfDesc); + Font *loadFont(const char *path) const; + bool loadFont(int fontIndex, const char *path); + virtual void initScreen() = 0; virtual void closeScreen() = 0; virtual void blitCursor() = 0; diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp index 94ee32a031..e2cfcb613d 100644 --- a/engines/gob/draw_v1.cpp +++ b/engines/gob/draw_v1.cpp @@ -33,6 +33,7 @@ #include "gob/util.h" #include "gob/game.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/scenery.h" #include "gob/inter.h" #include "gob/sound/sound.h" @@ -44,6 +45,12 @@ Draw_v1::Draw_v1(GobEngine *vm) : Draw(vm) { void Draw_v1::initScreen() { _backSurface = _vm->_video->initSurfDesc(_vm->_global->_videoMode, 320, 200, 0); + _frontSurface = _vm->_global->_primarySurfDesc; + + _cursorSprites = + _vm->_video->initSurfDesc(_vm->_global->_videoMode, 32, 16, 2); + _scummvmCursor = + _vm->_video->initSurfDesc(_vm->_global->_videoMode, 16, 16, SCUMMVM_CURSOR); } void Draw_v1::closeScreen() { @@ -58,7 +65,6 @@ void Draw_v1::blitCursor() { } void Draw_v1::animateCursor(int16 cursor) { - Game::Collision *ptr; int16 cursorIndex = cursor; int16 newX = 0, newY = 0; uint16 hotspotX = 0, hotspotY = 0; @@ -66,29 +72,10 @@ void Draw_v1::animateCursor(int16 cursor) { _showCursor = 2; if (cursorIndex == -1) { - cursorIndex = 0; - for (ptr = _vm->_game->_collisionAreas; ptr->left != 0xFFFF; ptr++) { - if (ptr->flags & 0xFFF0) - continue; - - if (ptr->left > _vm->_global->_inter_mouseX) - continue; - - if (ptr->right < _vm->_global->_inter_mouseX) - continue; - - if (ptr->top > _vm->_global->_inter_mouseY) - continue; + cursorIndex = + _vm->_game->_hotspots->findCursor(_vm->_global->_inter_mouseX, + _vm->_global->_inter_mouseY); - if (ptr->bottom < _vm->_global->_inter_mouseY) - continue; - - if ((ptr->flags & 0xF) < 3) - cursorIndex = 1; - else - cursorIndex = 3; - break; - } if (_cursorAnimLow[cursorIndex] == -1) cursorIndex = 1; } @@ -261,7 +248,7 @@ void Draw_v1::printTotText(int16 id) { _letterToPrint = (char) *ptr; spriteOperation(DRAW_DRAWLETTER); _destSpriteX += - _fonts[_fontIndex]->itemWidth; + _fonts[_fontIndex]->getCharWidth(); ptr++; } else { cmd = ptrEnd[17] & 0x7F; @@ -294,7 +281,7 @@ void Draw_v1::printTotText(int16 id) { spriteOperation(DRAW_PRINTTEXT); if (ptrEnd[17] & 0x80) { if (ptr[1] == ' ') { - _destSpriteX += _fonts[_fontIndex]->itemWidth; + _destSpriteX += _fonts[_fontIndex]->getCharWidth(); while (ptr[1] == ' ') ptr++; if (ptr[1] == 2) { @@ -303,10 +290,10 @@ void Draw_v1::printTotText(int16 id) { } } else if (ptr[1] == 2 && READ_LE_UINT16(ptr + 4) == _destSpriteY) { ptr += 5; - _destSpriteX += _fonts[_fontIndex]->itemWidth; + _destSpriteX += _fonts[_fontIndex]->getCharWidth(); } } else { - _destSpriteX = destSpriteX + _fonts[_fontIndex]->itemWidth; + _destSpriteX = destSpriteX + _fonts[_fontIndex]->getCharWidth(); } ptrEnd += 23; ptr++; @@ -317,7 +304,7 @@ void Draw_v1::printTotText(int16 id) { _renderFlags = savedFlags; if (_renderFlags & RENDERFLAG_COLLISIONS) - _vm->_game->checkCollisions(0, 0, 0, 0); + _vm->_game->_hotspots->check(0, 0); if ((_renderFlags & RENDERFLAG_CAPTUREPOP) && *_vm->_scenery->_pCaptureCounter != 0) { (*_vm->_scenery->_pCaptureCounter)--; @@ -354,6 +341,7 @@ void Draw_v1::spriteOperation(int16 operation) { } } + Font *font = 0; switch (operation) { case DRAW_BLITSURF: _vm->_video->drawSprite(*_spritesArray[_sourceSurface], @@ -415,20 +403,25 @@ void Draw_v1::spriteOperation(int16 operation) { break; case DRAW_PRINTTEXT: + font = _fonts[_fontIndex]; + if (!font) { + warning("Trying to print \"%s\" with undefined font %d", _textToPrint, _fontIndex); + break; + } + len = strlen(_textToPrint); dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, - _destSpriteX + len * _fonts[_fontIndex]->itemWidth - 1, - _destSpriteY + _fonts[_fontIndex]->itemHeight - 1); + _destSpriteX + len * font->getCharWidth() - 1, + _destSpriteY + font->getCharHeight() - 1); for (int i = 0; i < len; i++) { _vm->_video->drawLetter(_textToPrint[i], _destSpriteX, _destSpriteY, - _fonts[_fontIndex], - _transparency, + *font, _transparency, _frontColor, _backColor, *_spritesArray[_destSurface]); - _destSpriteX += _fonts[_fontIndex]->itemWidth; + _destSpriteX += font->getCharWidth(); } break; @@ -471,14 +464,19 @@ void Draw_v1::spriteOperation(int16 operation) { break; case DRAW_DRAWLETTER: + font = _fonts[_fontIndex]; + if (!font) { + warning("Trying to print \'%c\' with undefined font %d", _letterToPrint, _fontIndex); + break; + } + if (_fontToSprite[_fontIndex].sprite == -1) { dirtiedRect(_destSurface, _destSpriteX, _destSpriteY, - _destSpriteX + _fonts[_fontIndex]->itemWidth - 1, - _destSpriteY + _fonts[_fontIndex]->itemHeight - 1); + _destSpriteX + font->getCharWidth() - 1, + _destSpriteY + font->getCharHeight() - 1); _vm->_video->drawLetter(_letterToPrint, _destSpriteX, _destSpriteY, - _fonts[_fontIndex], - _transparency, + *font, _transparency, _frontColor, _backColor, *_spritesArray[_destSurface]); break; diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp index 2843456f42..8fe70589a7 100644 --- a/engines/gob/draw_v2.cpp +++ b/engines/gob/draw_v2.cpp @@ -34,6 +34,7 @@ #include "gob/game.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/scenery.h" #include "gob/inter.h" #include "gob/video.h" @@ -82,7 +83,6 @@ void Draw_v2::blitCursor() { } void Draw_v2::animateCursor(int16 cursor) { - Game::Collision *ptr; int16 cursorIndex = cursor; int16 newX = 0, newY = 0; uint16 hotspotX = 0, hotspotY = 0; @@ -91,32 +91,10 @@ void Draw_v2::animateCursor(int16 cursor) { // .-- _draw_animateCursorSUB1 --- if (cursorIndex == -1) { - cursorIndex = 0; - for (ptr = _vm->_game->_collisionAreas; ptr->left != 0xFFFF; ptr++) { - if ((ptr->flags & 0xF00) || (ptr->id & 0x4000)) - continue; - - if (ptr->left > _vm->_global->_inter_mouseX) - continue; - - if (ptr->right < _vm->_global->_inter_mouseX) - continue; - - if (ptr->top > _vm->_global->_inter_mouseY) - continue; - - if (ptr->bottom < _vm->_global->_inter_mouseY) - continue; - - if ((ptr->flags & 0xF000) == 0) { - if ((ptr->flags & 0xF) >= 3) { - cursorIndex = 3; - break; - } else if (((ptr->flags & 0xF0) != 0x10) && (cursorIndex == 0)) - cursorIndex = 1; - } else if (cursorIndex == 0) - cursorIndex = (ptr->flags >> 12) & 0xF; - } + cursorIndex = + _vm->_game->_hotspots->findCursor(_vm->_global->_inter_mouseX, + _vm->_global->_inter_mouseY); + if (_cursorAnimLow[cursorIndex] == -1) cursorIndex = 1; } @@ -393,22 +371,22 @@ void Draw_v2::printTotText(int16 id) { if ((((*ptr >= 1) && (*ptr <= 7)) || (*ptr == 10)) && (strPos != 0)) { str[MAX(strPos, strPos2)] = 0; strPosBak = strPos; - width = strlen(str) * _fonts[fontIndex]->itemWidth; + width = strlen(str) * _fonts[fontIndex]->getCharWidth(); adjustCoords(1, &width, 0); if (colCmd & 0x0F) { rectLeft = offX - 2; rectTop = offY - 2; rectRight = offX + width + 1; - rectBottom = _fonts[fontIndex]->itemHeight; + rectBottom = _fonts[fontIndex]->getCharHeight(); adjustCoords(1, &rectBottom, 0); rectBottom += offY + 1; adjustCoords(0, &rectLeft, &rectTop); adjustCoords(2, &rectRight, &rectBottom); if (colId != -1) - _vm->_game->addNewCollision(colId + 0xD000, rectLeft, rectTop, - rectRight, rectBottom, 2, 0, 0, 0); + _vm->_game->_hotspots->add(colId + 0xD000, rectLeft, rectTop, + rectRight, rectBottom, (uint16) Hotspots::kTypeClick, 0, 0, 0, 0); if (_needAdjust != 2) printTextCentered(colCmd & 0x0F, rectLeft + 4, rectTop + 4, @@ -426,9 +404,9 @@ void Draw_v2::printTotText(int16 id) { if (_needAdjust != 2) { if ((_destSpriteX >= destX) && (_destSpriteY >= destY) && - (((_fonts[_fontIndex]->itemHeight / 2) + _destSpriteY - 1) <= spriteBottom)) { + (((_fonts[_fontIndex]->getCharHeight() / 2) + _destSpriteY - 1) <= spriteBottom)) { while (((_destSpriteX + width - 1) > spriteRight) && (width > 0)) { - width -= _fonts[_fontIndex]->itemWidth / 2; + width -= _fonts[_fontIndex]->getCharWidth() / 2; str[strlen(str) - 1] = '\0'; } spriteOperation(DRAW_PRINTTEXT); @@ -441,8 +419,8 @@ void Draw_v2::printTotText(int16 id) { if (mask[strPos] == '\0') continue; - rectLeft = _fonts[fontIndex]->itemWidth; - rectTop = _fonts[fontIndex]->itemHeight; + rectLeft = _fonts[fontIndex]->getCharWidth(); + rectTop = _fonts[fontIndex]->getCharHeight(); adjustCoords(1, &rectLeft, &rectTop); _destSpriteX = strPos * rectLeft + offX; _spriteRight = _destSpriteX + rectLeft - 1; @@ -452,7 +430,7 @@ void Draw_v2::printTotText(int16 id) { } } - rectLeft = _fonts[_fontIndex]->itemWidth; + rectLeft = _fonts[_fontIndex]->getCharWidth(); adjustCoords(1, &rectLeft, 0); offX += strPosBak * rectLeft; strPos = 0; @@ -501,8 +479,8 @@ void Draw_v2::printTotText(int16 id) { rectBottom = destY + (int16)READ_LE_UINT16(ptr + 6); adjustCoords(2, &rectLeft, &rectTop); adjustCoords(2, &rectRight, &rectBottom); - _vm->_game->addNewCollision(colId + 0x0D000, rectLeft, rectTop, - rectRight, rectBottom, 2, 0, 0, 0); + _vm->_game->_hotspots->add(colId + 0x0D000, rectLeft, rectTop, + rectRight, rectBottom, (uint16) Hotspots::kTypeClick, 0, 0, 0, 0); ptr += 8; } break; @@ -604,7 +582,7 @@ void Draw_v2::printTotText(int16 id) { if (!(_renderFlags & RENDERFLAG_COLLISIONS)) return; - _vm->_game->checkCollisions(0, 0, 0, 0); + _vm->_game->_hotspots->check(0, 0); if (*_vm->_scenery->_pCaptureCounter != 0) { (*_vm->_scenery->_pCaptureCounter)--; @@ -620,8 +598,6 @@ void Draw_v2::spriteOperation(int16 operation) { int16 left; int16 ratio; Resource *resource; - // Always assigned to -1 in Game::loadTotFile() - int16 someHandle = -1; deltaVeto = (operation & 0x10) != 0; operation &= 0x0F; @@ -783,8 +759,13 @@ void Draw_v2::spriteOperation(int16 operation) { left = _destSpriteX; if ((_fontIndex >= 4) || (_fontToSprite[_fontIndex].sprite == -1)) { + Font *font = _fonts[_fontIndex]; + if (!font) { + warning("Trying to print \"%s\" with undefined font %d", _textToPrint, _fontIndex); + break; + } - if (!_fonts[_fontIndex]->extraData) { + if (font->isMonospaced()) { if (((int8) _textToPrint[0]) == -1) { _vm->validateLanguage(); @@ -792,26 +773,20 @@ void Draw_v2::spriteOperation(int16 operation) { len = *dataBuf++; for (int i = 0; i < len; i++, dataBuf += 2) { _vm->_video->drawLetter(READ_LE_UINT16(dataBuf), _destSpriteX, - _destSpriteY, _fonts[_fontIndex], _transparency, _frontColor, + _destSpriteY, *font, _transparency, _frontColor, _backColor, *_spritesArray[_destSurface]); } } else { drawString(_textToPrint, _destSpriteX, _destSpriteY, _frontColor, - _backColor, _transparency, *_spritesArray[_destSurface], - _fonts[_fontIndex]); - _destSpriteX += len * _fonts[_fontIndex]->itemWidth; + _backColor, _transparency, *_spritesArray[_destSurface], *font); + _destSpriteX += len * font->getCharWidth(); } } else { for (int i = 0; i < len; i++) { - if ((someHandle < 0) || (_textToPrint[i] != ' ')) { - _vm->_video->drawLetter(_textToPrint[i], _destSpriteX, - _destSpriteY, _fonts[_fontIndex], _transparency, - _frontColor, _backColor, *_spritesArray[_destSurface]); - _destSpriteX += *(_fonts[_fontIndex]->extraData + - (_textToPrint[i] - _fonts[_fontIndex]->startItem)); - } - else - _destSpriteX += _fonts[_fontIndex]->itemWidth; + _vm->_video->drawLetter(_textToPrint[i], _destSpriteX, + _destSpriteY, *font, _transparency, + _frontColor, _backColor, *_spritesArray[_destSurface]); + _destSpriteX += font->getCharWidth(_textToPrint[i]); } } @@ -835,7 +810,7 @@ void Draw_v2::spriteOperation(int16 operation) { } dirtiedRect(_destSurface, left, _destSpriteY, - _destSpriteX - 1, _destSpriteY + _fonts[_fontIndex]->itemHeight - 1); + _destSpriteX - 1, _destSpriteY + _fonts[_fontIndex]->getCharHeight() - 1); break; case DRAW_DRAWBAR: @@ -906,7 +881,7 @@ void Draw_v2::spriteOperation(int16 operation) { _sourceSurface = sourceSurface; if (operation == DRAW_PRINTTEXT) { - len = _fonts[_fontIndex]->itemWidth; + len = _fonts[_fontIndex]->getCharWidth(); adjustCoords(1, &len, 0); _destSpriteX += len * strlen(_textToPrint); } diff --git a/engines/gob/driver_vga.cpp b/engines/gob/driver_vga.cpp index aff971164f..c93962c206 100644 --- a/engines/gob/driver_vga.cpp +++ b/engines/gob/driver_vga.cpp @@ -70,24 +70,22 @@ void VGAVideoDriver::fillRect(SurfaceDesc &dest, int16 left, int16 top, } void VGAVideoDriver::drawLetter(unsigned char item, int16 x, int16 y, - Video::FontDesc *fontDesc, byte color1, byte color2, + const Font &font, byte color1, byte color2, byte transp, SurfaceDesc &dest) { - byte *src, *dst; uint16 data; - src = fontDesc->dataPtr + - (item - fontDesc->startItem) * (fontDesc->itemSize & 0xFF); - dst = dest.getVidMem() + x + dest.getWidth() * y; + const byte *src = font.getCharData(item); + byte *dst = dest.getVidMem() + x + dest.getWidth() * y; - int nWidth = fontDesc->itemWidth; + int nWidth = font.getCharWidth(); if (nWidth & 7) nWidth = (nWidth & 0xF8) + 8; nWidth >>= 3; - for (int i = 0; i < fontDesc->itemHeight; i++) { - int width = fontDesc->itemWidth; + for (int i = 0; i < font.getCharHeight(); i++) { + int width = font.getCharWidth(); for (int k = 0; k < nWidth; k++) { @@ -106,7 +104,7 @@ void VGAVideoDriver::drawLetter(unsigned char item, int16 x, int16 y, } - dst += dest.getWidth() - fontDesc->itemWidth; + dst += dest.getWidth() - font.getCharWidth(); } } diff --git a/engines/gob/driver_vga.h b/engines/gob/driver_vga.h index c50ea5c475..3102016cb5 100644 --- a/engines/gob/driver_vga.h +++ b/engines/gob/driver_vga.h @@ -41,7 +41,7 @@ public: void fillRect(SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, byte color); void drawLetter(unsigned char item, int16 x, int16 y, - Video::FontDesc *fontDesc, byte color1, byte color2, + const Font &font, byte color1, byte color2, byte transp, SurfaceDesc &dest); void drawSprite(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp); diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp index 5771ee9f76..d201019d08 100644 --- a/engines/gob/game.cpp +++ b/engines/gob/game.cpp @@ -29,14 +29,15 @@ #include "gob/game.h" #include "gob/helper.h" #include "gob/global.h" -#include "gob/util.h" #include "gob/dataio.h" #include "gob/variables.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/inter.h" #include "gob/draw.h" #include "gob/mult.h" +#include "gob/scenery.h" #include "gob/videoplayer.h" #include "gob/sound/sound.h" @@ -170,30 +171,14 @@ bool Environments::has(Resources *resources, uint8 startEnv, int16 except) const Game::Game(GobEngine *vm) : _vm(vm) { - _collisionAreas = 0; - _shouldPushColls = 0; - _captureCount = 0; - _collStackSize = 0; - - for (int i = 0; i < 5; i++) { - _collStack[i] = 0; - _collStackElemSizes[i] = 0; - } - _curTotFile[0] = 0; _totToLoad[0] = 0; _startTimeKey = 0; - _mouseButtons = 0; - - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; + _mouseButtons = kMouseButtonsNone; - _activeCollResId = 0; - _activeCollIndex = 0; _handleMouse = 0; _forceHandleMouse = 0; _menuLevel = 0; @@ -201,10 +186,7 @@ Game::Game(GobEngine *vm) : _vm(vm) { _preventScroll = false; _scrollHandleMouse = false; - _noCd = false; - _tempStr[0] = 0; - _collStr[0] = 0; _numEnvironments = 0; _curEnvironment = 0; @@ -212,19 +194,181 @@ Game::Game(GobEngine *vm) : _vm(vm) { _environments = new Environments(_vm); _script = new Script(_vm); _resources = new Resources(_vm); + _hotspots = new Hotspots(_vm); } Game::~Game() { delete _environments; delete _script; delete _resources; + delete _hotspots; } -void Game::freeCollision(int16 id) { - for (int i = 0; i < 250; i++) { - if (_collisionAreas[i].id == id) - _collisionAreas[i].left = 0xFFFF; +void Game::prepareStart() { + _vm->_global->_pPaletteDesc->unused2 = _vm->_draw->_unusedPalette2; + _vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1; + _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette; + + _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); + + _vm->_draw->initScreen(); + _vm->_video->fillRect(*_vm->_draw->_frontSurface, 0, 0, + _vm->_video->_surfWidth - 1, _vm->_video->_surfHeight - 1, 1); + + _vm->_util->setMousePos(152, 92); + _vm->_draw->_cursorX = _vm->_global->_inter_mouseX = 152; + _vm->_draw->_cursorY = _vm->_global->_inter_mouseY = 92; + + _vm->_draw->_invalidatedCount = 0; + _vm->_draw->_noInvalidated = true; + _vm->_draw->_applyPal = false; + _vm->_draw->_paletteCleared = false; + _vm->_draw->_cursorWidth = 16; + _vm->_draw->_cursorHeight = 16; + _vm->_draw->_transparentCursor = 1; + + for (int i = 0; i < 40; i++) { + _vm->_draw->_cursorAnimLow[i] = -1; + _vm->_draw->_cursorAnimDelays[i] = 0; + _vm->_draw->_cursorAnimHigh[i] = 0; } + + _vm->_draw->_renderFlags = 0; + _vm->_draw->_backDeltaX = 0; + _vm->_draw->_backDeltaY = 0; + + _startTimeKey = _vm->_util->getTimeKey(); +} + +void Game::playTot(int16 skipPlay) { + char savedTotName[20]; + int16 *oldCaptureCounter; + int16 *oldBreakFrom; + int16 *oldNestLevel; + int16 _captureCounter; + int16 breakFrom; + int16 nestLevel; + + oldNestLevel = _vm->_inter->_nestLevel; + oldBreakFrom = _vm->_inter->_breakFromLevel; + oldCaptureCounter = _vm->_scenery->_pCaptureCounter; + + _script->push(); + + _vm->_inter->_nestLevel = &nestLevel; + _vm->_inter->_breakFromLevel = &breakFrom; + _vm->_scenery->_pCaptureCounter = &_captureCounter; + strcpy(savedTotName, _curTotFile); + + if (skipPlay <= 0) { + while (!_vm->shouldQuit()) { + if (_vm->_inter->_variables) + _vm->_draw->animateCursor(4); + + if (skipPlay != -1) { + _vm->_inter->initControlVars(1); + + for (int i = 0; i < 4; i++) { + _vm->_draw->_fontToSprite[i].sprite = -1; + _vm->_draw->_fontToSprite[i].base = -1; + _vm->_draw->_fontToSprite[i].width = -1; + _vm->_draw->_fontToSprite[i].height = -1; + } + + _vm->_mult->initAll(); + _vm->_mult->zeroMultData(); + + _vm->_draw->_spritesArray[20] = _vm->_draw->_frontSurface; + _vm->_draw->_spritesArray[21] = _vm->_draw->_backSurface; + _vm->_draw->_cursorSpritesBack = _vm->_draw->_cursorSprites; + } else + _vm->_inter->initControlVars(0); + + _vm->_draw->_cursorHotspotXVar = -1; + _totToLoad[0] = 0; + + if ((_curTotFile[0] == 0) && (!_script->isLoaded())) + break; + + if (skipPlay == -2) { + _vm->_vidPlayer->primaryClose(); + skipPlay = 0; + } + + if (!_script->load(_curTotFile)) { + _vm->_draw->blitCursor(); + _vm->_inter->_terminate = 2; + break; + } + + _resources->load(_curTotFile); + + _vm->_global->_inter_animDataSize = _script->getAnimDataSize(); + if (!_vm->_inter->_variables) + _vm->_inter->allocateVars(_script->getVariablesCount() & 0xFFFF); + + _script->seek(_script->getFunctionOffset(TOTFile::kFunctionStart)); + + _vm->_inter->renewTimeInVars(); + + WRITE_VAR(13, _vm->_global->_useMouse); + WRITE_VAR(14, _vm->_global->_soundFlags); + WRITE_VAR(15, _vm->_global->_fakeVideoMode); + WRITE_VAR(16, _vm->_global->_language); + + _vm->_inter->callSub(2); + + if (_totToLoad[0] != 0) + _vm->_inter->_terminate = 0; + + _vm->_draw->blitInvalidated(); + + _script->unload(); + + _resources->unload(); + + for (int i = 0; i < *_vm->_scenery->_pCaptureCounter; i++) + capturePop(0); + + if (skipPlay != -1) { + _vm->_goblin->freeObjects(); + + _vm->_sound->blasterStop(0); + + for (int i = 0; i < Sound::kSoundsCount; i++) { + SoundDesc *sound = _vm->_sound->sampleGetBySlot(i); + + if (sound && + ((sound->getType() == SOUND_SND) || (sound->getType() == SOUND_WAV))) + _vm->_sound->sampleFree(sound); + } + } + + if (_totToLoad[0] == 0) + break; + + strcpy(_curTotFile, _totToLoad); + } + } else { + _vm->_inter->initControlVars(0); + _vm->_scenery->_pCaptureCounter = oldCaptureCounter; + _script->seek(_script->getFunctionOffset(skipPlay + 1)); + + _menuLevel++; + _vm->_inter->callSub(2); + _menuLevel--; + + if (_vm->_inter->_terminate != 0) + _vm->_inter->_terminate = 2; + } + + strcpy(_curTotFile, savedTotName); + + _vm->_inter->_nestLevel = oldNestLevel; + _vm->_inter->_breakFromLevel = oldBreakFrom; + _vm->_scenery->_pCaptureCounter = oldCaptureCounter; + + _script->pop(); } void Game::capturePush(int16 left, int16 top, int16 width, int16 height) { @@ -349,7 +493,7 @@ void Game::evaluateScroll(int16 x, int16 y) { } int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY, - int16 *pButtons, char handleMouse) { + MouseButtons *pButtons, char handleMouse) { _vm->_util->processInput(true); @@ -373,28 +517,17 @@ int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY, if (pMouseX && pMouseY && pButtons) { _vm->_util->getMouseState(pMouseX, pMouseY, pButtons); - if (*pButtons == 3) - *pButtons = 0; + if (*pButtons == kMouseButtonsBoth) + *pButtons = kMouseButtonsNone; } return _vm->_util->checkKey(); } -int16 Game::adjustKey(int16 key) { - if (key <= 0x60 || key >= 0x7B) - return key; - - return key - 0x20; -} - -void Game::start(void) { - _collisionAreas = new Collision[250]; - memset(_collisionAreas, 0, 250 * sizeof(Collision)); - +void Game::start() { prepareStart(); playTot(-2); - delete[] _collisionAreas; _vm->_draw->closeScreen(); for (int i = 0; i < SPRITES_COUNT; i++) @@ -406,6 +539,9 @@ void Game::start(void) { void Game::totSub(int8 flags, const char *newTotFile) { int8 curBackupPos; + if ((flags == 16) || (flags == 17)) + warning("Urban Stub: Game::totSub(), flags == %d", flags); + if (_numEnvironments >= Environments::kEnvironmentCount) return; @@ -417,13 +553,14 @@ void Game::totSub(int8 flags, const char *newTotFile) { _script = new Script(_vm); _resources = new Resources(_vm); + + if (flags & 0x80) + warning("Urban Stub: Game::totSub(), flags & 0x80"); + if (flags & 1) _vm->_inter->_variables = 0; strncpy0(_curTotFile, newTotFile, 9); -// if (_vm->getGameType() == kGameTypeGeisha) -// strcat(_curTotFile, ".0OT"); -// else strcat(_curTotFile, ".TOT"); if (_vm->_inter->_terminate != 0) { @@ -431,7 +568,7 @@ void Game::totSub(int8 flags, const char *newTotFile) { return; } - pushCollisions(0); + _hotspots->push(0, true); if (flags & 2) playTot(-1); @@ -441,7 +578,8 @@ void Game::totSub(int8 flags, const char *newTotFile) { if (_vm->_inter->_terminate != 2) _vm->_inter->_terminate = 0; - popCollisions(); + _hotspots->clear(); + _hotspots->pop(); if ((flags & 1) && _vm->_inter->_variables) { _vm->_inter->delocateVars(); @@ -489,13 +627,13 @@ void Game::switchTotSub(int16 index, int16 skipPlay) { return; } - pushCollisions(0); + _hotspots->push(0, true); playTot(skipPlay); if (_vm->_inter->_terminate != 2) _vm->_inter->_terminate = 0; - popCollisions(); + _hotspots->pop(); clearUnusedEnvironment(); @@ -504,87 +642,6 @@ void Game::switchTotSub(int16 index, int16 skipPlay) { _environments->get(_curEnvironment); } -void Game::setCollisions(byte arg_0) { - uint16 left; - uint16 top; - uint16 width; - uint16 height; - Collision *collArea; - - for (collArea = _collisionAreas; collArea->left != 0xFFFF; collArea++) { - if (((collArea->id & 0xC000) != 0x8000) || (collArea->funcSub == 0)) - continue; - - _script->call(collArea->funcSub); - - left = _script->readValExpr(); - top = _script->readValExpr(); - width = _script->readValExpr(); - height = _script->readValExpr(); - if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && - (left != 0xFFFF)) { - left += _vm->_draw->_backDeltaX; - top += _vm->_draw->_backDeltaY; - } - if (_vm->_draw->_needAdjust != 2) { - _vm->_draw->adjustCoords(0, &left, &top); - if ((collArea->flags & 0x0F) < 3) - _vm->_draw->adjustCoords(2, &width, &height); - else { - height &= 0xFFFE; - _vm->_draw->adjustCoords(2, 0, &height); - } - } - collArea->left = left; - collArea->top = top; - collArea->right = left + width - 1; - collArea->bottom = top + height - 1; - - _script->pop(); - } -} - -void Game::collSub(uint16 offset) { - int16 collStackSize; - - _script->call(offset); - - _shouldPushColls = 1; - collStackSize = _collStackSize; - - _vm->_inter->funcBlock(0); - - if (collStackSize != _collStackSize) - popCollisions(); - - _shouldPushColls = 0; - - _script->pop(); - - setCollisions(); -} - -void Game::collAreaSub(int16 index, int8 enter) { - uint16 collId; - - collId = _collisionAreas[index].id & 0xF000; - - if ((collId == 0xA000) || (collId == 0x9000)) { - if (enter == 0) - WRITE_VAR(17, _collisionAreas[index].id & 0x0FFF); - else - WRITE_VAR(17, -(_collisionAreas[index].id & 0x0FFF)); - } - - if (enter != 0) { - if (_collisionAreas[index].funcEnter != 0) - collSub(_collisionAreas[index].funcEnter); - } else { - if (_collisionAreas[index].funcLeave != 0) - collSub(_collisionAreas[index].funcLeave); - } -} - void Game::clearUnusedEnvironment() { if (!_environments->has(_script)) { delete _script; @@ -594,7 +651,6 @@ void Game::clearUnusedEnvironment() { delete _resources; _resources = 0; } - } } // End of namespace Gob diff --git a/engines/gob/game.h b/engines/gob/game.h index ead4a56492..d3a758f014 100644 --- a/engines/gob/game.h +++ b/engines/gob/game.h @@ -26,11 +26,14 @@ #ifndef GOB_GAME_H #define GOB_GAME_H +#include "gob/util.h" + namespace Gob { class Script; class Resources; class Variables; +class Hotspots; class Environments { public: @@ -67,53 +70,30 @@ private: class Game { public: - -#include "common/pack-start.h" // START STRUCT PACKING - - struct Collision { - int16 id; - uint16 left; - uint16 top; - uint16 right; - uint16 bottom; - int16 flags; - int16 key; - uint16 funcEnter; - uint16 funcLeave; - uint16 funcSub; - Script *script; - } PACKED_STRUCT; - - struct InputDesc { - int16 fontIndex; - int16 backColor; - int16 frontColor; - byte *ptr; - } PACKED_STRUCT; - -#include "common/pack-end.h" // END STRUCT PACKING - - Collision *_collisionAreas; - Collision *_collStack[5]; - - Script *_script; + Script *_script; Resources *_resources; + Hotspots *_hotspots; char _curTotFile[14]; char _totToLoad[20]; int32 _startTimeKey; - int16 _mouseButtons; + MouseButtons _mouseButtons; bool _noScroll; bool _preventScroll; bool _scrollHandleMouse; - bool _noCd; + byte _handleMouse; + char _forceHandleMouse; Game(GobEngine *vm); virtual ~Game(); + void prepareStart(); + + void playTot(int16 skipPlay); + void capturePush(int16 left, int16 top, int16 width, int16 height); void capturePop(char doDraw); @@ -122,60 +102,21 @@ public: void evaluateScroll(int16 x, int16 y); int16 checkKeys(int16 *pMousex = 0, int16 *pMouseY = 0, - int16 *pButtons = 0, char handleMouse = 0); - void start(void); - - virtual void totSub(int8 flags, const char *newTotFile); - virtual void switchTotSub(int16 index, int16 skipPlay); + MouseButtons *pButtons = 0, char handleMouse = 0); + void start(); - void freeCollision(int16 id); - - virtual void playTot(int16 skipPlay) = 0; - - virtual void clearCollisions(void) = 0; - virtual int16 addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub = 0) = 0; - virtual void collisionsBlock(void) = 0; - virtual int16 multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc *inpDesc, int16 *collResId, - int16 *collIndex, bool mono = true) = 0; - virtual int16 inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, - int16 *collIndex, bool mono = true) = 0; - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex) = 0; - - virtual void prepareStart(void) = 0; - - virtual void pushCollisions(char all) = 0; - virtual void popCollisions(void) = 0; + void totSub(int8 flags, const char *newTotFile); + void switchTotSub(int16 index, int16 skipPlay); protected: - int16 _lastCollKey; - int16 _lastCollAreaIndex; - int16 _lastCollId; - - int16 _activeCollResId; - int16 _activeCollIndex; - byte _handleMouse; - char _forceHandleMouse; uint32 _menuLevel; char _tempStr[256]; - int16 _collStackSize; - int16 _collStackElemSizes[5]; - - char _shouldPushColls; - // Capture Common::Rect _captureStack[20]; int16 _captureCount; - char _collStr[256]; - // For totSub() int8 _curEnvironment; int8 _numEnvironments; @@ -183,129 +124,9 @@ protected: GobEngine *_vm; - virtual int16 adjustKey(int16 key); - - void collAreaSub(int16 index, int8 enter); - - virtual void setCollisions(byte arg_0 = 1); - virtual void collSub(uint16 offset); - - virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex) = 0; - void clearUnusedEnvironment(); }; -class Game_v1 : public Game { -public: - virtual void playTot(int16 skipPlay); - - virtual void clearCollisions(void); - virtual int16 addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub = 0); - virtual void collisionsBlock(void); - virtual int16 multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc *inpDesc, int16 *collResId, - int16 *collIndex, bool mono = true); - virtual int16 inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, - int16 *collIndex, bool mono = true); - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex); - - virtual void prepareStart(void); - - virtual void pushCollisions(char all); - virtual void popCollisions(void); - - Game_v1(GobEngine *vm); - virtual ~Game_v1() {} - -protected: - virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex); -}; - -class Game_v2 : public Game_v1 { -public: - virtual void playTot(int16 skipPlay); - - virtual void clearCollisions(void); - virtual int16 addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub = 0); - virtual void collisionsBlock(void); - virtual int16 multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc *inpDesc, int16 *collResId, - int16 *collIndex, bool mono = true); - virtual int16 inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, - int16 *collIndex, bool mono = true); - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex); - - virtual void prepareStart(void); - - virtual void pushCollisions(char all); - virtual void popCollisions(void); - - Game_v2(GobEngine *vm); - virtual ~Game_v2() {} - -protected: - struct CollLast { - int16 key; - int16 id; - int16 areaIndex; - }; - - CollLast _collLasts[5]; - - virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex); -}; - -class Game_v6 : public Game_v2 { -public: - virtual void totSub(int8 flags, const char *newTotFile); - - virtual int16 addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub = 0); - - virtual void prepareStart(void); - - virtual void pushCollisions(char all); - - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex); - virtual void collisionsBlock(void); - - Game_v6(GobEngine *vm); - virtual ~Game_v6() {} - -protected: - uint32 _someTimeDly; - - virtual void setCollisions(byte arg_0 = 1); - virtual void collSub(uint16 offset); - - virtual int16 adjustKey(int16 key); - - virtual int16 checkMousePoint(int16 all, int16 *resId, int16 *resIndex); - - void collSubReenter(); -}; - -class Game_Fascination : public Game_v2 { -public: - virtual int16 checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex); - - Game_Fascination(GobEngine *vm); - virtual ~Game_Fascination() {} -}; - } // End of namespace Gob #endif // GOB_GAME_H diff --git a/engines/gob/game_fascin.cpp b/engines/gob/game_fascin.cpp deleted file mode 100644 index 38ad03f0f8..0000000000 --- a/engines/gob/game_fascin.cpp +++ /dev/null @@ -1,203 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/endian.h" -#include "common/stream.h" - -#include "gob/gob.h" -#include "gob/game.h" -#include "gob/global.h" -#include "gob/util.h" -#include "gob/dataio.h" -#include "gob/draw.h" -#include "gob/goblin.h" -#include "gob/inter.h" -#include "gob/mult.h" -#include "gob/scenery.h" -#include "gob/video.h" -#include "gob/videoplayer.h" -#include "gob/sound/sound.h" - -namespace Gob { - -Game_Fascination::Game_Fascination(GobEngine *vm) : Game_v2(vm) { -} - -int16 Game_Fascination::checkCollisions(byte handleMouse, int16 deltaTime, int16 *pResId, - int16 *pResIndex) { - int16 resIndex; - int16 key; - int16 oldIndex; - int16 oldId; - int16 newkey; - uint32 timeKey; - - _scrollHandleMouse = handleMouse != 0; - - if (deltaTime >= -1) { - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if (pResId != 0) - *pResId = 0; - - resIndex = 0; - - if ((_vm->_draw->_cursorIndex == -1) && - (handleMouse != 0) && (_lastCollKey == 0)) { - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - - if (handleMouse != 0) { - if ((handleMouse==1) && (_vm->_draw->_renderFlags & RENDERFLAG_UNKNOWN)) - warning("checkCollisions : RENDERFLAG_UNKNOWN - Unknown behavior"); - _vm->_draw->animateCursor(-1); - } - - timeKey = _vm->_util->getTimeKey(); - while (1) { - if (_vm->_inter->_terminate || _vm->shouldQuit()) { - if (handleMouse) - _vm->_draw->blitCursor(); - return 0; - } - - if (!_vm->_draw->_noInvalidated) { - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - else - _vm->_draw->blitInvalidated(); - _vm->_video->waitRetrace(); - } - - key = checkKeys(&_vm->_global->_inter_mouseX, - &_vm->_global->_inter_mouseY, &_mouseButtons, handleMouse); - - if ((handleMouse == 0) && (_mouseButtons != 0)) { - _vm->_util->waitMouseRelease(0); - key = 3; - } - - if (key != 0) { - - if (handleMouse & 1) - _vm->_draw->blitCursor(); - - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - if (key != 0) - return key; - } - - if (handleMouse != 0) { - if (_mouseButtons != 0) { - if (deltaTime > 0) { - _vm->_draw->animateCursor(2); - _vm->_util->delay(deltaTime); - } else if (handleMouse & 1) - _vm->_util->waitMouseRelease(1); - _vm->_draw->animateCursor(-1); - - if (pResId != 0) - *pResId = 0; - - key = checkMousePoint(0, pResId, &resIndex); - if (pResIndex != 0) - *pResIndex = resIndex; - - if ((key != 0) || ((pResId != 0) && (*pResId != 0))) { - if ((handleMouse & 1) && - ((deltaTime <= 0) || (_mouseButtons == 0))) - _vm->_draw->blitCursor(); - - if ((_lastCollKey != 0) && (key != _lastCollKey)) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - return key; - } - - if (handleMouse & 4) - return 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } else if ((_vm->_global->_inter_mouseX != _vm->_draw->_cursorX) || - (_vm->_global->_inter_mouseY != _vm->_draw->_cursorY)) { - - oldIndex = _lastCollAreaIndex; - oldId = _lastCollId; - newkey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if (newkey != _lastCollKey) { - if ((_lastCollKey != 0) && (oldId & 0x8000)) - collAreaSub(oldIndex, 0); - - _lastCollKey = newkey; - - if ((newkey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - } - } - - if ((deltaTime < 0) && (key == 0) && (_mouseButtons == 0)) { - uint32 curtime = _vm->_util->getTimeKey(); - if ((curtime + deltaTime) > timeKey) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - } - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - _vm->_util->delay(10); - } -} - -} // End of namespace Gob diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp deleted file mode 100644 index 87dc78e3b1..0000000000 --- a/engines/gob/game_v1.cpp +++ /dev/null @@ -1,1426 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/endian.h" -#include "common/stream.h" - -#include "gob/gob.h" -#include "gob/game.h" -#include "gob/helper.h" -#include "gob/global.h" -#include "gob/util.h" -#include "gob/dataio.h" -#include "gob/script.h" -#include "gob/resources.h" -#include "gob/draw.h" -#include "gob/inter.h" -#include "gob/mult.h" -#include "gob/video.h" -#include "gob/scenery.h" -#include "gob/sound/sound.h" - -namespace Gob { - -Game_v1::Game_v1(GobEngine *vm) : Game(vm) { -} - -void Game_v1::playTot(int16 skipPlay) { - int16 _captureCounter; - int16 breakFrom; - int16 nestLevel; - - int16 *oldNestLevel = _vm->_inter->_nestLevel; - int16 *oldBreakFrom = _vm->_inter->_breakFromLevel; - int16 *oldCaptureCounter = _vm->_scenery->_pCaptureCounter; - - _script->push(); - - _vm->_inter->_nestLevel = &nestLevel; - _vm->_inter->_breakFromLevel = &breakFrom; - _vm->_scenery->_pCaptureCounter = &_captureCounter; - - char savedTotName[20]; - strcpy(savedTotName, _curTotFile); - - if (skipPlay <= 0) { - while (!_vm->shouldQuit()) { - for (int i = 0; i < 4; i++) { - _vm->_draw->_fontToSprite[i].sprite = -1; - _vm->_draw->_fontToSprite[i].base = -1; - _vm->_draw->_fontToSprite[i].width = -1; - _vm->_draw->_fontToSprite[i].height = -1; - } - - if ((_vm->getPlatform() == Common::kPlatformMacintosh)|| - (_vm->getPlatform() == Common::kPlatformWindows)) - _vm->_sound->adlibStop(); - else - _vm->_sound->cdStop(); - - _vm->_draw->animateCursor(4); - _vm->_inter->initControlVars(1); - _vm->_mult->initAll(); - _vm->_mult->zeroMultData(); - - for (int i = 0; i < SPRITES_COUNT; i++) - _vm->_draw->freeSprite(i); - - _vm->_draw->_spritesArray[20] = _vm->_draw->_frontSurface; - _vm->_draw->_spritesArray[21] = _vm->_draw->_backSurface; - _vm->_draw->_spritesArray[23] = _vm->_draw->_cursorSprites; - - for (int i = 0; i < 20; i++) - freeSoundSlot(i); - - _totToLoad[0] = 0; - - if ((_curTotFile[0] == 0) && !_script->isLoaded()) - break; - - if (!_script->load(_curTotFile)) { - _vm->_draw->blitCursor(); - break; - } - - _resources->load(_curTotFile); - - _vm->_global->_inter_animDataSize = _script->getAnimDataSize(); - if (!_vm->_inter->_variables) - _vm->_inter->allocateVars(_script->getVariablesCount() & 0xFFFF); - - _script->seek(_script->getFunctionOffset(TOTFile::kFunctionStart)); - - _vm->_inter->renewTimeInVars(); - - WRITE_VAR(13, _vm->_global->_useMouse); - WRITE_VAR(14, _vm->_global->_soundFlags); - WRITE_VAR(15, _vm->_global->_videoMode); - WRITE_VAR(16, _vm->_global->_language); - - _vm->_inter->callSub(2); - _script->setFinished(false); - - if (_totToLoad[0] != 0) - _vm->_inter->_terminate = 0; - - _vm->_draw->blitInvalidated(); - - _script->unload(); - - _resources->unload(); - - for (int i = 0; i < *_vm->_scenery->_pCaptureCounter; i++) - capturePop(0); - - _vm->_mult->checkFreeMult(); - _vm->_mult->freeAll(); - - for (int i = 0; i < SPRITES_COUNT; i++) - _vm->_draw->freeSprite(i); - _vm->_sound->blasterStop(0); - - for (int i = 0; i < 20; i++) - freeSoundSlot(i); - - if (_totToLoad[0] == 0) - break; - - strcpy(_curTotFile, _totToLoad); - } - } - - strcpy(_curTotFile, savedTotName); - - _vm->_inter->_nestLevel = oldNestLevel; - _vm->_inter->_breakFromLevel = oldBreakFrom; - _vm->_scenery->_pCaptureCounter = oldCaptureCounter; - - _script->pop(); -} - -void Game_v1::clearCollisions() { - for (int i = 0; i < 250; i++) { - _collisionAreas[i].id = 0; - _collisionAreas[i].left = 0xFFFF; - } -} - -int16 Game_v1::addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub) { - Collision *ptr; - - debugC(5, kDebugCollisions, "addNewCollision"); - debugC(5, kDebugCollisions, "id = %X", id); - debugC(5, kDebugCollisions, "left = %d, top = %d, right = %d, bottom = %d", - left, top, right, bottom); - debugC(5, kDebugCollisions, "flags = %X, key = %X", flags, key); - debugC(5, kDebugCollisions, "funcEnter = %d, funcLeave = %d", - funcEnter, funcLeave); - - for (int i = 0; i < 250; i++) { - if (_collisionAreas[i].left != 0xFFFF) - continue; - - ptr = &_collisionAreas[i]; - ptr->id = id; - ptr->left = left; - ptr->top = top; - ptr->right = right; - ptr->bottom = bottom; - ptr->flags = flags; - ptr->key = key; - ptr->funcEnter = funcEnter; - ptr->funcLeave = funcLeave; - ptr->funcSub = funcSub; - ptr->script = 0; - - return i; - } - error("Game_v1::addNewCollision(): Collision array full"); - return 0; -} - -void Game_v1::pushCollisions(char all) { - Collision *srcPtr; - Collision *destPtr; - int16 size; - - debugC(1, kDebugCollisions, "pushCollisions"); - for (size = 0, srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if (all || (srcPtr->id & 0x8000)) - size++; - } - - destPtr = new Collision[size]; - _collStack[_collStackSize] = destPtr; - _collStackElemSizes[_collStackSize] = size; - _collStackSize++; - - for (srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if (all || (srcPtr->id & 0x8000)) { - memcpy(destPtr, srcPtr, sizeof(Collision)); - srcPtr->left = 0xFFFF; - destPtr++; - } - } -} - -void Game_v1::popCollisions(void) { - Collision *destPtr; - Collision *srcPtr; - - debugC(1, kDebugCollisions, "popCollision"); - - _collStackSize--; - for (destPtr = _collisionAreas; destPtr->left != 0xFFFF; destPtr++) - ; - - srcPtr = _collStack[_collStackSize]; - memcpy(destPtr, srcPtr, - _collStackElemSizes[_collStackSize] * sizeof(Collision)); - - delete[] _collStack[_collStackSize]; -} - -int16 Game_v1::checkCollisions(byte handleMouse, int16 deltaTime, - int16 *pResId, int16 *pResIndex) { - int16 resIndex; - int16 key; - int16 oldIndex; - int16 oldId; - uint32 timeKey; - bool firstIteration = true; - - if (deltaTime >= -1) { - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if (pResId != 0) - *pResId = 0; - - resIndex = 0; - - timeKey = _vm->_util->getTimeKey(); - - if ((_vm->_draw->_cursorIndex == -1) && (handleMouse != 0) && - (_lastCollKey == 0)) { - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); - _vm->_inter->funcBlock(0); - _script->pop(); - } - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - while (1) { - if (_vm->_inter->_terminate) { - if (handleMouse) - _vm->_draw->blitCursor(); - return 0; - } - - if (!_vm->_draw->_noInvalidated) { - if (handleMouse) - _vm->_draw->animateCursor(-1); - else - _vm->_draw->blitInvalidated(); - } - - // NOTE: the original asm does the below checkKeys call - // _before_ this check. However, that can cause keypresses to get lost - // since there's a return statement in this check. - // Additionally, I added a 'deltaTime == -1' check there, since - // when this function is called with deltaTime == -1 in inputArea, - // and the return value is then discarded. - if (deltaTime < 0) { - uint32 curtime = _vm->_util->getTimeKey(); - if ((deltaTime == -1) || (((curtime + deltaTime) > timeKey) && !firstIteration)) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - } - } - - key = checkKeys(&_vm->_global->_inter_mouseX, - &_vm->_global->_inter_mouseY, &_mouseButtons, handleMouse); - - if ((handleMouse == 0) && (_mouseButtons != 0)) { - _vm->_util->waitMouseRelease(0); - key = 3; - } - - if (key != 0) { - - if (handleMouse == 1) - _vm->_draw->blitCursor(); - - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); - _vm->_inter->funcBlock(0); - _script->pop(); - } - - _lastCollKey = 0; - if (key != 0) - return key; - } - - if (handleMouse != 0) { - if (_mouseButtons != 0) { - oldIndex = 0; - - _vm->_draw->animateCursor(2); - if (deltaTime <= 0) { - if (handleMouse == 1) - _vm->_util->waitMouseRelease(1); - } else if (deltaTime > 0) - _vm->_util->delay(deltaTime); - - _vm->_draw->animateCursor(-1); - if (pResId != 0) - *pResId = 0; - - key = checkMousePoint(0, pResId, &resIndex); - - if (pResIndex != 0) - *pResIndex = resIndex; - - if ((key != 0) || ((pResId != 0) && (*pResId != 0))) { - if ((handleMouse == 1) && - ((deltaTime <= 0) || (_mouseButtons == 0))) - _vm->_draw->blitCursor(); - - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - _lastCollKey = 0; - return key; - } - - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcLeave); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - - _lastCollKey = - checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - } else { - - if ((handleMouse != 0) && - ((_vm->_global->_inter_mouseX != _vm->_draw->_cursorX) || - (_vm->_global->_inter_mouseY != _vm->_draw->_cursorY))) { - oldIndex = _lastCollAreaIndex; - oldId = _lastCollId; - - key = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if (key != _lastCollKey) { - if ((_lastCollKey != 0) && ((oldId & 0x8000) != 0)) { - - _script->call(_collisionAreas[oldIndex].funcLeave); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - - _lastCollKey = key; - if ((_lastCollKey != 0) && ((_lastCollId & 0x8000) != 0)) { - - _script->call(_collisionAreas[_lastCollAreaIndex].funcEnter); - _vm->_inter->funcBlock(0); - _script->pop(); - - } - - } - } - } - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - if (deltaTime < -10) - _vm->_util->delay(10); - - firstIteration = false; - } -} - -void Game_v1::prepareStart(void) { - clearCollisions(); - - _vm->_global->_pPaletteDesc->unused2 = _vm->_draw->_unusedPalette2; - _vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1; - _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette; - - _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); - - _vm->_draw->initScreen(); - _vm->_video->fillRect(*_vm->_draw->_backSurface, 0, 0, 319, 199, 1); - _vm->_draw->_frontSurface = _vm->_global->_primarySurfDesc; - _vm->_video->fillRect(*_vm->_draw->_frontSurface, 0, 0, 319, 199, 1); - - _vm->_util->setMousePos(152, 92); - _vm->_draw->_cursorX = _vm->_global->_inter_mouseX = 152; - _vm->_draw->_cursorY = _vm->_global->_inter_mouseY = 92; - - _vm->_draw->_invalidatedCount = 0; - _vm->_draw->_noInvalidated = true; - _vm->_draw->_applyPal = false; - _vm->_draw->_paletteCleared = false; - _vm->_draw->_cursorWidth = 16; - _vm->_draw->_cursorHeight = 16; - _vm->_draw->_transparentCursor = 1; - - for (int i = 0; i < 40; i++) { - _vm->_draw->_cursorAnimLow[i] = -1; - _vm->_draw->_cursorAnimDelays[i] = 0; - _vm->_draw->_cursorAnimHigh[i] = 0; - } - - _vm->_draw->_cursorAnimLow[1] = 0; - _vm->_draw->_cursorSprites = - _vm->_video->initSurfDesc(_vm->_global->_videoMode, 32, 16, 2); - _vm->_draw->_scummvmCursor = - _vm->_video->initSurfDesc(_vm->_global->_videoMode, 16, 16, SCUMMVM_CURSOR); - _vm->_draw->_renderFlags = 0; - _vm->_draw->_backDeltaX = 0; - _vm->_draw->_backDeltaY = 0; - - _startTimeKey = _vm->_util->getTimeKey(); -} - -void Game_v1::collisionsBlock(void) { - InputDesc descArray[20]; - int16 array[250]; - byte count; - int16 collResId; - int16 curCmd; - int16 cmd; - int16 cmdHigh; - int16 key; - int16 flags; - uint16 left; - uint16 top; - uint16 width; - uint16 height; - int16 var_22; - int16 index; - int16 curEditIndex; - int16 deltaTime; - int16 descIndex2; - int16 stackPos2; - int16 descIndex; - int16 timeVal; - char *str; - int16 savedCollStackSize; - int16 i; - int16 counter; - int16 var_24; - int16 var_26; - int16 collStackPos; - Collision *collPtr; - uint32 timeKey; - - if (_shouldPushColls) - pushCollisions(1); - - collResId = -1; - _script->skip(1); - count = _script->readByte(); - _handleMouse = _script->readByte(); - deltaTime = 1000 * _script->readByte(); - descIndex2 = _script->readByte(); - stackPos2 = _script->readByte(); - descIndex = _script->readByte(); - - if ((stackPos2 != 0) || (descIndex != 0)) - deltaTime /= 100; - - timeVal = deltaTime; - _script->skip(1); - - uint32 startPos = _script->pos(); - - WRITE_VAR(16, 0); - var_22 = 0; - index = 0; - curEditIndex = 0; - - for (curCmd = 0; curCmd < count; curCmd++) { - array[curCmd] = 0; - cmd = _script->readByte(); - - if ((cmd & 0x40) != 0) { - cmd -= 0x40; - cmdHigh = _script->readByte(); - cmdHigh <<= 8; - } else - cmdHigh = 0; - - if ((cmd & 0x80) != 0) { - left = _script->readValExpr(); - top = _script->readValExpr(); - width = _script->readValExpr(); - height = _script->readValExpr(); - } else { - left = _script->readUint16(); - top = _script->readUint16(); - width = _script->readUint16(); - height = _script->readUint16(); - } - cmd &= 0x7F; - - debugC(1, kDebugCollisions, "collisionsBlock(%d)", cmd); - - switch (cmd) { - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - - _vm->_util->clearKeyBuf(); - var_22 = 1; - key = _script->readVarIndex(); - descArray[index].fontIndex = _script->readInt16(); - descArray[index].backColor = _script->readByte(); - descArray[index].frontColor = _script->readByte(); - - if ((cmd < 5) || (cmd > 8)) { - descArray[index].ptr = 0; - } else { - descArray[index].ptr = _script->getData() + _script->pos() + 2; - _script->skip(_script->readInt16()); - } - - if (left == 0xFFFF) - break; - - if ((cmd & 1) == 0) { - addNewCollision(curCmd + 0x8000, left, top, left + width * - _vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1, - top + height - 1, cmd, key, 0, _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - } else { - addNewCollision(curCmd + 0x8000, left, top, left + width * - _vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1, - top + height - 1, cmd, key, 0, 0); - } - index++; - break; - - case 21: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, _script->pos(), 0); - - _script->skip(_script->peekUint16(2) + 2); - break; - - case 20: - collResId = curCmd; - // Fall through to case 2 - - case 2: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, - top + height - 1, - (flags << 4) + cmdHigh + 2, key, 0, _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - break; - - case 0: - _script->skip(6); - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - cmd + cmdHigh, key, - startPos, _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - break; - - case 1: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - if (key == 0) - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmd + cmdHigh, key, - startPos, _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - break; - } - } - - _forceHandleMouse = 0; - _vm->_util->clearKeyBuf(); - - do { - if (var_22 != 0) { - key = multiEdit(deltaTime, index, &curEditIndex, - descArray, &_activeCollResId, &_activeCollIndex); - - if (key == 0x1C0D) { - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - if ((_collisionAreas[i].flags & 1) != 0) - continue; - - if ((_collisionAreas[i].flags & 0x0F) <= 2) - continue; - - collResId = _collisionAreas[i].id; - _activeCollResId = collResId; - collResId &= 0x7FFF; - _activeCollIndex = i; - break; - } - break; - } - } else - key = checkCollisions(_handleMouse, -deltaTime, - &_activeCollResId, &_activeCollIndex); - - if (((key & 0xFF) >= ' ') && ((key & 0xFF) <= 0xFF) && - ((key >> 8) > 1) && ((key >> 8) < 12)) - key = '0' + (((key >> 8) - 1) % 10) + (key & 0xFF00); - - if (_activeCollResId == 0) { - if (key != 0) { - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - if ((_collisionAreas[i].key == key) || - (_collisionAreas[i].key == 0x7FFF)) { - - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - - if (_activeCollResId == 0) { - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - if ((_collisionAreas[i].key & 0xFF00) != 0) - continue; - - if (_collisionAreas[i].key == 0) - continue; - - if ((adjustKey(key & 0xFF) == adjustKey(_collisionAreas[i].key)) || - (_collisionAreas[i].key == 0x7FFF)) { - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - } - } else { - - if ((deltaTime != 0) && (VAR(16) == 0)) { - if (stackPos2 != 0) { - collStackPos = 0; - collPtr = _collisionAreas; - - for (i = 0, collPtr = _collisionAreas; - collPtr->left != 0xFFFF; i++, collPtr++) { - - if ((collPtr->id & 0x8000) == 0) - continue; - - collStackPos++; - if (collStackPos != stackPos2) - continue; - - _activeCollResId = collPtr->id; - _activeCollIndex = i; - WRITE_VAR(2, _vm->_global->_inter_mouseX); - WRITE_VAR(3, _vm->_global->_inter_mouseY); - WRITE_VAR(4, _mouseButtons); - WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]); - - if (collPtr->funcLeave != 0) { - timeKey = _vm->_util->getTimeKey(); - - uint32 savedPos = _script->pos(); - - _script->seek(collPtr->funcLeave); - - _shouldPushColls = 1; - savedCollStackSize = _collStackSize; - _vm->_inter->funcBlock(0); - - if (savedCollStackSize != _collStackSize) - popCollisions(); - - _shouldPushColls = 0; - - _script->seek(savedPos); - - deltaTime = timeVal - - (_vm->_util->getTimeKey() - timeKey); - - if (deltaTime < 2) - deltaTime = 2; - } - - if (VAR(16) == 0) - _activeCollResId = 0; - break; - } - } else { - if (descIndex != 0) { - counter = 0; - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - counter++; - if (counter != descIndex) - continue; - - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } else { - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - } - } else { - if (descIndex2 != 0) { - counter = 0; - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - counter++; - if (counter != descIndex2) - continue; - - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - } - } - } - - if (_activeCollResId == 0) - continue; - - if (_collisionAreas[_activeCollIndex].funcLeave != 0) - continue; - - WRITE_VAR(2, _vm->_global->_inter_mouseX); - WRITE_VAR(3, _vm->_global->_inter_mouseY); - WRITE_VAR(4, _mouseButtons); - WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]); - - if (_collisionAreas[_activeCollIndex].funcEnter != 0) { - uint32 savedPos = _script->pos(); - - _script->seek(_collisionAreas[_activeCollIndex].funcEnter); - - _shouldPushColls = 1; - - collStackPos = _collStackSize; - _vm->_inter->funcBlock(0); - if (collStackPos != _collStackSize) - popCollisions(); - _shouldPushColls = 0; - - _script->seek(savedPos); - } - - WRITE_VAR(16, 0); - _activeCollResId = 0; - } - while ((_activeCollResId == 0) && !_vm->_inter->_terminate && !_vm->shouldQuit()); - - if (((uint16) _activeCollResId & ~0x8000) == collResId) { - collStackPos = 0; - var_24 = 0; - var_26 = 1; - for (i = 0; i < 250; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0x8000) == 0) - continue; - - if ((_collisionAreas[i].flags & 0x0F) < 3) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 10) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 8) { - char *ptr; - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - while ((ptr = strchr(_tempStr, ' ')) != 0) { - _vm->_util->cutFromStr(_tempStr, (ptr - _tempStr), 1); - ptr = strchr(_tempStr, ' '); - } - WRITE_VARO_STR(_collisionAreas[i].key, _tempStr); - } - - if (((_collisionAreas[i].flags & 0x0F) >= 5) && - ((_collisionAreas[i].flags & 0x0F) <= 8)) { - str = (char *) descArray[var_24].ptr; - - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->prepareStr(_tempStr); - - int16 pos = 0; - do { - strncpy0(_collStr, str, 255); - pos += strlen(str) + 1; - - str += strlen(str) + 1; - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->prepareStr(_collStr); - - if (strcmp(_tempStr, _collStr) == 0) { - WRITE_VAR(17, VAR(17) + 1); - WRITE_VAR(17 + var_26, 1); - break; - } - } while (READ_LE_UINT16(descArray[var_24].ptr - 2) > pos); - collStackPos++; - } else { - WRITE_VAR(17 + var_26, 2); - } - var_24++; - var_26++; - } - - if (collStackPos != (int16) VAR(17)) - WRITE_VAR(17, 0); - else - WRITE_VAR(17, 1); - } - - if (!_vm->_inter->_terminate) { - _script->seek(_collisionAreas[_activeCollIndex].funcLeave); - - WRITE_VAR(2, _vm->_global->_inter_mouseX); - WRITE_VAR(3, _vm->_global->_inter_mouseY); - WRITE_VAR(4, _mouseButtons); - - if (VAR(16) == 0) - WRITE_VAR(16, array[(uint16) _activeCollResId & ~0x8000]); - } else - _script->setFinished(true); - - for (curCmd = 0; curCmd < count; curCmd++) - freeCollision(curCmd + 0x8000); -} - -int16 Game_v1::multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc * inpDesc, int16 *collResId, int16 *collIndex, bool mono) { - Collision *collArea; - int16 descInd; - int16 key; - int16 found = -1; - int16 i; - - descInd = 0; - for (i = 0; i < 250; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0x8000) == 0) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - strncpy0(_tempStr, GET_VARO_STR(collArea->key), 255); - - _vm->_draw->_destSpriteX = collArea->left; - _vm->_draw->_destSpriteY = collArea->top; - _vm->_draw->_spriteRight = collArea->right - collArea->left + 1; - _vm->_draw->_spriteBottom = collArea->bottom - collArea->top + 1; - - _vm->_draw->_destSurface = 21; - - _vm->_draw->_backColor = inpDesc[descInd].backColor; - _vm->_draw->_frontColor = inpDesc[descInd].frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = inpDesc[descInd].fontIndex; - _vm->_draw->spriteOperation(DRAW_FILLRECT); - _vm->_draw->_destSpriteY += - ((collArea->bottom - collArea->top + 1) - 8) / 2; - - _vm->_draw->spriteOperation(DRAW_PRINTTEXT); - descInd++; - } - - for (i = 0; i < 40; i++) - WRITE_VAR_OFFSET(i * 4 + 0x44, 0); - - while (1) { - descInd = 0; - - for (i = 0; i < 250; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0x8000) == 0) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - if (descInd == *pCurPos) { - found = i; - break; - } - - descInd++; - } - - assert(found != -1); - - collArea = &_collisionAreas[found]; - - key = inputArea(collArea->left, collArea->top, - collArea->right - collArea->left + 1, - collArea->bottom - collArea->top + 1, - inpDesc[*pCurPos].backColor, inpDesc[*pCurPos].frontColor, - GET_VARO_STR(collArea->key), inpDesc[*pCurPos].fontIndex, - collArea->flags, &time, collResId, collIndex); - - if (_vm->_inter->_terminate) - return 0; - - switch (key) { - case 0: - if (*collResId == 0) - return 0; - - if ((_collisionAreas[*collIndex].flags & 0x0F) < 3) - return 0; - - if ((_collisionAreas[*collIndex].flags & 0x0F) > 10) - return 0; - - *pCurPos = 0; - for (i = 0; i < 250; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0x8000) == 0) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - if (i == *collIndex) - break; - - pCurPos[0]++; - } - break; - - case 0x3B00: - case 0x3C00: - case 0x3D00: - case 0x3E00: - case 0x3F00: - case 0x4000: - case 0x4100: - case 0x4200: - case 0x4300: - case 0x4400: - return key; - - case 0x1C0D: - - if (index == 1) - return key; - - if (*pCurPos == index - 1) { - *pCurPos = 0; - break; - } - - pCurPos[0]++; - break; - - case 0x5000: - if (index - 1 > *pCurPos) - pCurPos[0]++; - break; - - case 0x4800: - if (*pCurPos > 0) - pCurPos[0]--; - break; - } - } -} - -int16 Game_v1::inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, int16 *collIndex, bool mono) { - int16 handleMouse; - uint32 editSize; - Video::FontDesc *pFont; - char curSym; - int16 key; - const char *str1; - const char *str2; - int16 i; - uint32 pos; - int16 flag; - int16 savedKey; - - if ((_handleMouse != 0) && - ((_vm->_global->_useMouse != 0) || (_forceHandleMouse != 0))) - handleMouse = 1; - else - handleMouse = 0; - - pos = strlen(str); - pFont = _vm->_draw->_fonts[fontIndex]; - editSize = width / pFont->itemWidth; - - while (1) { - strncpy0(_tempStr, str, 254); - strcat(_tempStr, " "); - if (strlen(_tempStr) > editSize) - strncpy0(_tempStr, str, 255); - - _vm->_draw->_destSpriteX = xPos; - _vm->_draw->_destSpriteY = yPos; - _vm->_draw->_spriteRight = editSize * pFont->itemWidth; - _vm->_draw->_spriteBottom = height; - - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = backColor; - _vm->_draw->_frontColor = frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = fontIndex; - _vm->_draw->spriteOperation(DRAW_FILLRECT); - - _vm->_draw->_destSpriteY = yPos + (height - 8) / 2; - - _vm->_draw->spriteOperation(DRAW_PRINTTEXT); - if (pos == editSize) - pos--; - - curSym = _tempStr[pos]; - - flag = 1; - - while (1) { - _tempStr[0] = curSym; - _tempStr[1] = 0; - - _vm->_draw->_destSpriteX = xPos + pFont->itemWidth * pos; - _vm->_draw->_destSpriteY = yPos + height - 1; - _vm->_draw->_spriteRight = pFont->itemWidth; - _vm->_draw->_spriteBottom = 1; - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = frontColor; - _vm->_draw->spriteOperation(DRAW_FILLRECT); - - if (flag != 0) - key = checkCollisions(handleMouse, -1, collResId, collIndex); - flag = 0; - - key = checkCollisions(handleMouse, -300, collResId, collIndex); - - if (*pTotTime > 0) { - *pTotTime -= 300; - if (*pTotTime <= 1) { - key = 0; - *collResId = 0; - break; - } - } - - _tempStr[0] = curSym; - _tempStr[1] = 0; - _vm->_draw->_destSpriteX = xPos + pFont->itemWidth * pos; - _vm->_draw->_destSpriteY = yPos + height - 1; - _vm->_draw->_spriteRight = pFont->itemWidth; - _vm->_draw->_spriteBottom = 1; - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = backColor; - _vm->_draw->_frontColor = frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->spriteOperation(DRAW_FILLRECT); - - _vm->_draw->_destSpriteY = yPos + (height - 8) / 2; - _vm->_draw->spriteOperation(DRAW_PRINTTEXT); - - if ((key != 0) || (*collResId != 0)) - break; - - key = checkCollisions(handleMouse, -300, collResId, collIndex); - - if (*pTotTime > 0) { - *pTotTime -= 300; - if (*pTotTime <= 1) { - key = 0; - *collResId = 0; - break; - } - } - - if ((key != 0) || (*collResId != 0)) - break; - - if (_vm->_inter->_terminate) - return 0; - } - - if ((key == 0) || (*collResId != 0) || _vm->_inter->_terminate) - return 0; - - switch (key) { - case 0x4D00: // Right Arrow - if ((pos < strlen(str)) && (pos < (editSize - 1))) { - pos++; - continue; - } - return 0x5000; - - case 0x4B00: // Left Arrow - if (pos > 0) { - pos--; - continue; - } - return 0x4800; - - case 0xE08: // Backspace - if (pos > 0) { - _vm->_util->cutFromStr(str, pos - 1, 1); - pos--; - continue; - } - - case 0x5300: // Del - - if (pos >= strlen(str)) - continue; - - _vm->_util->cutFromStr(str, pos, 1); - continue; - - case 0x1C0D: // Enter - case 0x3B00: // F1 - case 0x3C00: // F2 - case 0x3D00: // F3 - case 0x3E00: // F4 - case 0x3F00: // F5 - case 0x4000: // F6 - case 0x4100: // F7 - case 0x4200: // F8 - case 0x4300: // F9 - case 0x4400: // F10 - case 0x4800: // Up arrow - case 0x5000: // Down arrow - return key; - - case 0x11B: // Escape - if (_vm->_global->_useMouse != 0) - continue; - - _forceHandleMouse = !_forceHandleMouse; - - if ((_handleMouse != 0) && - ((_vm->_global->_useMouse != 0) || (_forceHandleMouse != 0))) - handleMouse = 1; - else - handleMouse = 0; - - if (_vm->_global->_pressedKeys[1] == 0) - continue; - - while (_vm->_global->_pressedKeys[1] != 0) - ; - continue; - - default: - - savedKey = key; - key &= 0xFF; - - if (((inpType == 9) || (inpType == 10)) && - (key >= ' ') && (key <= 0xFF)) { - str1 = "0123456789-.,+ "; - str2 = "0123456789-,,+ "; - - if (((savedKey >> 8) > 1) && ((savedKey >> 8) < 12)) - key = ((savedKey >> 8) - 1) % 10 + '0'; - - for (i = 0; str1[i] != 0; i++) { - if (key == str1[i]) { - key = str2[i]; - break; - } - } - - if (i == (int16) strlen(str1)) - key = 0; - } - - if ((key >= ' ') && (key <= 0xFF)) { - if (editSize == strlen(str)) - _vm->_util->cutFromStr(str, strlen(str) - 1, 1); - - if ((key >= 'a') && (key <= 'z')) - key += ('A' - 'a'); - - pos++; - _tempStr[0] = key; - _tempStr[1] = 0; - - _vm->_util->insertStr(_tempStr, str, pos - 1); - } - - } - } -} - -int16 Game_v1::checkMousePoint(int16 all, int16 *resId, int16 *resIndex) { - Collision *ptr; - int16 i; - - if (resId != 0) - *resId = 0; - - *resIndex = 0; - - ptr = _collisionAreas; - for (i = 0; ptr->left != 0xFFFF; ptr++, i++) { - if (all) { - if ((ptr->flags & 0xF) > 1) - continue; - - if ((ptr->flags & 0xFF00) != 0) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - - *resIndex = i; - return ptr->key; - } else { - if ((ptr->flags & 0xFF00) != 0) - continue; - - if (((ptr->flags & 0xF) != 1) && ((ptr->flags & 0xF) != 2)) - continue; - - if ((((ptr->flags & 0xF0) >> 4) != (_mouseButtons - 1)) - && (((ptr->flags & 0xF0) >> 4) != 2)) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - *resIndex = i; - return ptr->key; - } - } - - if ((_mouseButtons != 1) && (all == 0)) - return 0x11B; - - return 0; -} - -} // End of namespace Gob diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp deleted file mode 100644 index 08184e73d0..0000000000 --- a/engines/gob/game_v2.cpp +++ /dev/null @@ -1,1563 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/endian.h" -#include "common/stream.h" - -#include "gob/gob.h" -#include "gob/game.h" -#include "gob/helper.h" -#include "gob/global.h" -#include "gob/util.h" -#include "gob/dataio.h" -#include "gob/script.h" -#include "gob/resources.h" -#include "gob/draw.h" -#include "gob/goblin.h" -#include "gob/inter.h" -#include "gob/mult.h" -#include "gob/scenery.h" -#include "gob/video.h" -#include "gob/videoplayer.h" -#include "gob/sound/sound.h" - -namespace Gob { - -Game_v2::Game_v2(GobEngine *vm) : Game_v1(vm) { -} - -void Game_v2::playTot(int16 skipPlay) { - char savedTotName[20]; - int16 *oldCaptureCounter; - int16 *oldBreakFrom; - int16 *oldNestLevel; - int16 _captureCounter; - int16 breakFrom; - int16 nestLevel; - - oldNestLevel = _vm->_inter->_nestLevel; - oldBreakFrom = _vm->_inter->_breakFromLevel; - oldCaptureCounter = _vm->_scenery->_pCaptureCounter; - - _script->push(); - - _vm->_inter->_nestLevel = &nestLevel; - _vm->_inter->_breakFromLevel = &breakFrom; - _vm->_scenery->_pCaptureCounter = &_captureCounter; - strcpy(savedTotName, _curTotFile); - - if (skipPlay <= 0) { - while (!_vm->shouldQuit()) { - if (_vm->_inter->_variables) - _vm->_draw->animateCursor(4); - - if (skipPlay != -1) { - _vm->_inter->initControlVars(1); - - for (int i = 0; i < 4; i++) { - _vm->_draw->_fontToSprite[i].sprite = -1; - _vm->_draw->_fontToSprite[i].base = -1; - _vm->_draw->_fontToSprite[i].width = -1; - _vm->_draw->_fontToSprite[i].height = -1; - } - - _vm->_mult->initAll(); - _vm->_mult->zeroMultData(); - - _vm->_draw->_spritesArray[20] = _vm->_draw->_frontSurface; - _vm->_draw->_spritesArray[21] = _vm->_draw->_backSurface; - _vm->_draw->_cursorSpritesBack = _vm->_draw->_cursorSprites; - } else - _vm->_inter->initControlVars(0); - - _vm->_draw->_cursorHotspotXVar = -1; - _totToLoad[0] = 0; - - if ((_curTotFile[0] == 0) && (!_script->isLoaded())) - break; - - if (skipPlay == -2) { - _vm->_vidPlayer->primaryClose(); - skipPlay = 0; - } - - if (!_script->load(_curTotFile)) { - _vm->_draw->blitCursor(); - _vm->_inter->_terminate = 2; - break; - } - - _resources->load(_curTotFile); - - _vm->_global->_inter_animDataSize = _script->getAnimDataSize(); - if (!_vm->_inter->_variables) - _vm->_inter->allocateVars(_script->getVariablesCount() & 0xFFFF); - - _script->seek(_script->getFunctionOffset(TOTFile::kFunctionStart)); - - _vm->_inter->renewTimeInVars(); - - WRITE_VAR(13, _vm->_global->_useMouse); - WRITE_VAR(14, _vm->_global->_soundFlags); - WRITE_VAR(15, _vm->_global->_fakeVideoMode); - WRITE_VAR(16, _vm->_global->_language); - - _vm->_inter->callSub(2); - - if (_totToLoad[0] != 0) - _vm->_inter->_terminate = 0; - - _vm->_draw->blitInvalidated(); - - _script->unload(); - - _resources->unload(); - - for (int i = 0; i < *_vm->_scenery->_pCaptureCounter; i++) - capturePop(0); - - if (skipPlay != -1) { - _vm->_goblin->freeObjects(); - - _vm->_sound->blasterStop(0); - - for (int i = 0; i < Sound::kSoundsCount; i++) { - SoundDesc *sound = _vm->_sound->sampleGetBySlot(i); - - if (sound && - ((sound->getType() == SOUND_SND) || (sound->getType() == SOUND_WAV))) - _vm->_sound->sampleFree(sound); - } - } - - if (_totToLoad[0] == 0) - break; - - strcpy(_curTotFile, _totToLoad); - } - } else { - _vm->_inter->initControlVars(0); - _vm->_scenery->_pCaptureCounter = oldCaptureCounter; - _script->seek(_script->getFunctionOffset(skipPlay + 1)); - - _menuLevel++; - _vm->_inter->callSub(2); - _menuLevel--; - - if (_vm->_inter->_terminate != 0) - _vm->_inter->_terminate = 2; - } - - strcpy(_curTotFile, savedTotName); - - _vm->_inter->_nestLevel = oldNestLevel; - _vm->_inter->_breakFromLevel = oldBreakFrom; - _vm->_scenery->_pCaptureCounter = oldCaptureCounter; - - _script->pop(); -} - -void Game_v2::clearCollisions() { - _lastCollKey = 0; - - for (int i = 0; i < 150; i++) - _collisionAreas[i].left = 0xFFFF; -} - -int16 Game_v2::addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub) { - Collision *ptr; - - debugC(5, kDebugCollisions, "addNewCollision"); - debugC(5, kDebugCollisions, "id = %X", id); - debugC(5, kDebugCollisions, "left = %d, top = %d, right = %d, bottom = %d", - left, top, right, bottom); - debugC(5, kDebugCollisions, "flags = %X, key = %X", flags, key); - debugC(5, kDebugCollisions, "funcEnter = %d, funcLeave = %d", - funcEnter, funcLeave); - - for (int i = 0; i < 150; i++) { - if ((_collisionAreas[i].left != 0xFFFF) && (_collisionAreas[i].id != id)) - continue; - - ptr = &_collisionAreas[i]; - ptr->id = id; - ptr->left = left; - ptr->top = top; - ptr->right = right; - ptr->bottom = bottom; - ptr->flags = flags; - ptr->key = key; - ptr->funcEnter = funcEnter; - ptr->funcLeave = funcLeave; - ptr->funcSub = funcSub; - ptr->script = 0; - - return i; - } - error("Game_v2::addNewCollision(): Collision array full"); - return 0; -} - -void Game_v2::pushCollisions(char all) { - Collision *srcPtr; - Collision *destPtr; - int16 size; - - debugC(1, kDebugCollisions, "pushCollisions"); - for (size = 0, srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) - if (all || (((uint16) srcPtr->id) >= 20)) - size++; - - destPtr = new Collision[size]; - _collStack[_collStackSize] = destPtr; - - if (_vm->_inter->_terminate) - return; - - _collStackElemSizes[_collStackSize] = size; - - if (_shouldPushColls != 0) - _collStackElemSizes[_collStackSize] |= 0x8000; - - _shouldPushColls = 0; - _collLasts[_collStackSize].key = _lastCollKey; - _collLasts[_collStackSize].id = _lastCollId; - _collLasts[_collStackSize].areaIndex = _lastCollAreaIndex; - _lastCollKey = 0; - _lastCollId = 0; - _lastCollAreaIndex = 0; - _collStackSize++; - - for (srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if (all || (((uint16) srcPtr->id) >= 20)) { - memcpy(destPtr, srcPtr, sizeof(Collision)); - srcPtr->left = 0xFFFF; - destPtr++; - } - } -} - -void Game_v2::popCollisions(void) { - Collision *destPtr; - Collision *srcPtr; - - debugC(1, kDebugCollisions, "popCollision"); - - _collStackSize--; - - _shouldPushColls = _collStackElemSizes[_collStackSize] & 0x8000 ? 1 : 0; - _collStackElemSizes[_collStackSize] &= 0x7FFF; - - _lastCollKey = _collLasts[_collStackSize].key; - _lastCollId = _collLasts[_collStackSize].id; - _lastCollAreaIndex = _collLasts[_collStackSize].areaIndex; - - for (destPtr = _collisionAreas; destPtr->left != 0xFFFF; destPtr++) - ; - - srcPtr = _collStack[_collStackSize]; - memcpy(destPtr, srcPtr, - _collStackElemSizes[_collStackSize] * sizeof(Collision)); - - delete[] _collStack[_collStackSize]; -} - -int16 Game_v2::checkCollisions(byte handleMouse, int16 deltaTime, int16 *pResId, - int16 *pResIndex) { - int16 resIndex; - int16 key; - int16 oldIndex; - int16 oldId; - int16 newkey; - uint32 timeKey; - - _scrollHandleMouse = handleMouse != 0; - - if (deltaTime >= -1) { - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if (pResId != 0) - *pResId = 0; - - resIndex = 0; - - if ((_vm->_draw->_cursorIndex == -1) && - (handleMouse != 0) && (_lastCollKey == 0)) { - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - timeKey = _vm->_util->getTimeKey(); - while (1) { - if (_vm->_inter->_terminate || _vm->shouldQuit()) { - if (handleMouse) - _vm->_draw->blitCursor(); - return 0; - } - - if (!_vm->_draw->_noInvalidated) { - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - else - _vm->_draw->blitInvalidated(); - _vm->_video->waitRetrace(); - } - - key = checkKeys(&_vm->_global->_inter_mouseX, - &_vm->_global->_inter_mouseY, &_mouseButtons, handleMouse); - - if ((handleMouse == 0) && (_mouseButtons != 0)) { - _vm->_util->waitMouseRelease(0); - key = 3; - } - - if (key != 0) { - - if (handleMouse & 1) - _vm->_draw->blitCursor(); - - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - if (key != 0) - return key; - } - - if (handleMouse != 0) { - if (_mouseButtons != 0) { - if (deltaTime > 0) { - _vm->_draw->animateCursor(2); - _vm->_util->delay(deltaTime); - } else if (handleMouse & 1) - _vm->_util->waitMouseRelease(1); - _vm->_draw->animateCursor(-1); - - if (pResId != 0) - *pResId = 0; - - key = checkMousePoint(0, pResId, &resIndex); - if (pResIndex != 0) - *pResIndex = resIndex; - - if ((key != 0) || ((pResId != 0) && (*pResId != 0))) { - if ((handleMouse & 1) && - ((deltaTime <= 0) || (_mouseButtons == 0))) - _vm->_draw->blitCursor(); - - if ((_lastCollKey != 0) && (key != _lastCollKey)) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - return key; - } - - if (handleMouse & 4) - return 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } else if ((_vm->_global->_inter_mouseX != _vm->_draw->_cursorX) || - (_vm->_global->_inter_mouseY != _vm->_draw->_cursorY)) { - - oldIndex = _lastCollAreaIndex; - oldId = _lastCollId; - newkey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if (newkey != _lastCollKey) { - if ((_lastCollKey != 0) && (oldId & 0x8000)) - collAreaSub(oldIndex, 0); - - _lastCollKey = newkey; - - if ((newkey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - } - } - - if ((deltaTime < 0) && (key == 0) && (_mouseButtons == 0)) { - uint32 curtime = _vm->_util->getTimeKey(); - if ((curtime + deltaTime) > timeKey) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - } - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - _vm->_util->delay(10); - } -} - -void Game_v2::prepareStart(void) { - clearCollisions(); - - _vm->_global->_pPaletteDesc->unused2 = _vm->_draw->_unusedPalette2; - _vm->_global->_pPaletteDesc->unused1 = _vm->_draw->_unusedPalette1; - _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette; - - _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); - - _vm->_draw->initScreen(); - _vm->_video->fillRect(*_vm->_draw->_frontSurface, 0, 0, - _vm->_video->_surfWidth - 1, _vm->_video->_surfHeight - 1, 1); - - _vm->_util->setMousePos(152, 92); - _vm->_draw->_cursorX = _vm->_global->_inter_mouseX = 152; - _vm->_draw->_cursorY = _vm->_global->_inter_mouseY = 92; - - _vm->_draw->_invalidatedCount = 0; - _vm->_draw->_noInvalidated = true; - _vm->_draw->_applyPal = false; - _vm->_draw->_paletteCleared = false; - _vm->_draw->_cursorWidth = 16; - _vm->_draw->_cursorHeight = 16; - _vm->_draw->_transparentCursor = 1; - - for (int i = 0; i < 40; i++) { - _vm->_draw->_cursorAnimLow[i] = -1; - _vm->_draw->_cursorAnimDelays[i] = 0; - _vm->_draw->_cursorAnimHigh[i] = 0; - } - - _vm->_draw->_renderFlags = 0; - _vm->_draw->_backDeltaX = 0; - _vm->_draw->_backDeltaY = 0; - - _startTimeKey = _vm->_util->getTimeKey(); -} - -void Game_v2::collisionsBlock(void) { - InputDesc descArray[20]; - int16 array[250]; - byte count; - int16 collResId; - int16 curCmd; - int16 cmd; - int16 cmdHigh; - int16 key; - int16 flags; - uint16 left; - uint16 top; - uint16 width; - uint16 height; - int16 var_1C; - int16 index; - int16 curEditIndex; - int16 deltaTime; - int16 stackPos2; - int16 descIndex; - int16 timeVal; - char *str; - int16 i; - int16 counter; - int16 var_24; - int16 var_26; - int16 collStackPos; - Collision *collPtr; - Collision *collArea; - int16 timeKey; - byte collAreaStart; - uint32 startPos; - uint32 offsetPos; - - if (_shouldPushColls) - pushCollisions(0); - - collAreaStart = 0; - while (_collisionAreas[collAreaStart].left != 0xFFFF) - collAreaStart++; - collArea = &_collisionAreas[collAreaStart]; - - _shouldPushColls = 0; - collResId = -1; - - _script->skip(1); - count = _script->readByte(); - - _handleMouse = _script->readByte(); - deltaTime = 1000 * _script->readByte(); - _script->skip(1); - stackPos2 = _script->readByte(); - descIndex = _script->readByte(); - - if ((stackPos2 != 0) || (descIndex != 0)) - deltaTime /= 100; - - timeVal = deltaTime; - _script->skip(1); - - startPos = _script->pos(); - WRITE_VAR(16, 0); - - var_1C = 0; - index = 0; - curEditIndex = 0; - - for (curCmd = 0; curCmd < count; curCmd++) { - array[curCmd] = 0; - cmd = _script->readByte(); - - if ((cmd & 0x40) != 0) { - cmd -= 0x40; - cmdHigh = _script->readByte(); - cmdHigh <<= 8; - } else - cmdHigh = 0; - - if ((cmd & 0x80) != 0) { - offsetPos = _script->pos(); - left = _script->readValExpr(); - top = _script->readValExpr(); - width = _script->readValExpr(); - height = _script->readValExpr(); - } else { - offsetPos = 0; - left = _script->readUint16(); - top = _script->readUint16(); - width = _script->readUint16(); - height = _script->readUint16(); - } - - if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { - left += _vm->_draw->_backDeltaX; - top += _vm->_draw->_backDeltaY; - } - - if (left != 0xFFFF) { - _vm->_draw->adjustCoords(0, &left, &top); - if (((cmd & 0x3F) < 20) && ((cmd & 0x3F) >= 3)) { - if (_vm->_draw->_needAdjust != 2) - height &= 0xFFFE; - _vm->_draw->adjustCoords(0, 0, &width); - } else - _vm->_draw->adjustCoords(0, &height, &width); - } - - cmd &= 0x7F; - debugC(1, kDebugCollisions, "collisionsBlock(%d)", cmd); - - switch (cmd) { - case 0: - _script->skip(6); - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - cmd + cmdHigh, key, startPos, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 1: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16(); - - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - - if (key == 0) - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmd + cmdHigh, key, startPos, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - break; - - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - _vm->_util->clearKeyBuf(); - var_1C = 1; - key = _script->readVarIndex(); - descArray[index].fontIndex = _script->readInt16(); - descArray[index].backColor = _script->readByte(); - descArray[index].frontColor = _script->readByte(); - - if ((cmd >= 5) && (cmd <= 8)) { - descArray[index].ptr = _script->getData() + _script->pos() + 2; - _script->skip(_script->peekUint16() + 2); - } else - descArray[index].ptr = 0; - - if (left == 0xFFFF) { - if ((cmd & 1) == 0) { - _script->skip(_script->peekUint16(2) + 2); - } - break; - } - - if ((cmd & 1) == 0) { - addNewCollision(curCmd + 0x8000, left, top, left + width * - _vm->_draw->_fonts[descArray[index].fontIndex]-> itemWidth - 1, - top + height - 1, cmd, key, 0, - _script->pos()); - - _script->skip(_script->peekUint16(2) + 2); - } else - addNewCollision(curCmd + 0x8000, left, top, left + width * - _vm->_draw->_fonts[descArray[index].fontIndex]-> itemWidth - 1, - top + height - 1, cmd, key, 0, 0); - - index++; - break; - - case 11: - _script->skip(6); - for (i = 0; i < 150; i++) { - if ((_collisionAreas[i].id & 0xF000) == 0xE000) { - _collisionAreas[i].id &= 0xBFFF; - _collisionAreas[i].funcEnter = - _script->pos(); - _collisionAreas[i].funcLeave = - _script->pos(); - } - } - _script->skip(_script->peekUint16(2) + 2); - break; - - case 12: - _script->skip(6); - for (i = 0; i < 150; i++) { - if ((_collisionAreas[i].id & 0xF000) == 0xD000) { - _collisionAreas[i].id &= 0xBFFF; - _collisionAreas[i].funcEnter = - _script->pos(); - _collisionAreas[i].funcLeave = - _script->pos(); - } - } - _script->skip(_script->peekUint16(2) + 2); - break; - - case 20: - collResId = curCmd; - // Fall through to case 2 - - case 2: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16(); - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, 0, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 21: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, - _script->pos(), 0, offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - } - } - - _forceHandleMouse = 0; - _vm->_util->clearKeyBuf(); - - do { - if (var_1C != 0) { - key = multiEdit(deltaTime, index, &curEditIndex, descArray, - &_activeCollResId, &_activeCollIndex); - - WRITE_VAR(55, curEditIndex); - if (key == 0x1C0D) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].flags & 1) != 0) - continue; - - if ((_collisionAreas[i].flags & 0x0F) <= 2) - continue; - - _activeCollResId = _collisionAreas[i].id; - collResId = _collisionAreas[i].id & 0x7FFF; - _activeCollIndex = i; - break; - } - break; - } - } else - key = checkCollisions(_handleMouse, -deltaTime, - &_activeCollResId, &_activeCollIndex); - - if (((key & 0xFF) >= ' ') && ((key & 0xFF) <= 0xFF) && - ((key >> 8) > 1) && ((key >> 8) < 12)) - key = '0' + (((key >> 8) - 1) % 10) + (key & 0xFF00); - - if (_activeCollResId == 0) { - if (key != 0) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].key == key) || - (_collisionAreas[i].key == 0x7FFF)) { - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - - if (_activeCollResId == 0) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].key & 0xFF00) != 0) - continue; - - if (_collisionAreas[i].key == 0) - continue; - - if ((adjustKey(key & 0xFF) == adjustKey(_collisionAreas[i].key)) || - (_collisionAreas[i].key == 0x7FFF)) { - _activeCollResId = _collisionAreas[i].id; - _activeCollIndex = i; - break; - } - } - } - } else if (deltaTime != 0) { - if (stackPos2 != 0) { - collStackPos = 0; - - for (i = 0, collPtr = collArea; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) != 0x8000) - continue; - - collStackPos++; - if (collStackPos != stackPos2) - continue; - - _activeCollResId = collPtr->id; - _activeCollIndex = i + collAreaStart; - _vm->_inter->storeMouse(); - if (VAR(16) != 0) - break; - - if ((_activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[_activeCollResId & 0xFFF]); - else - WRITE_VAR(16, _activeCollResId & 0xFFF); - - if (collPtr->funcLeave != 0) { - int16 collResIdBak = _activeCollResId; - int16 collIndexBak = _activeCollIndex; - - timeKey = _vm->_util->getTimeKey(); - collSub(collPtr->funcLeave); - - _activeCollResId = collResIdBak; - _activeCollIndex = collIndexBak; - - _vm->_inter->animPalette(); - - deltaTime = timeVal - (_vm->_util->getTimeKey() - timeKey); - - if (deltaTime < 2) - deltaTime = 2; - if (deltaTime > timeVal) - deltaTime = timeVal; - } - - if (VAR(16) == 0) - _activeCollResId = 0; - break; - } - } else { - if (descIndex != 0) { - - counter = 0; - for (i = 0, collPtr = collArea; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) == 0x8000) - if (++counter == descIndex) { - _activeCollResId = collPtr->id; - _activeCollIndex = i + collAreaStart; - break; - } - } - - } else { - - for (i = 0, collPtr = _collisionAreas; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) == 0x8000) { - _activeCollResId = collPtr->id; - _activeCollIndex = i; - break; - } - } - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) - collSub(_collisionAreas[_lastCollAreaIndex].funcLeave); - _lastCollKey = 0; - } - - } - } - } - - if ((_activeCollResId == 0) || - (_collisionAreas[_activeCollIndex].funcLeave != 0)) - continue; - - _vm->_inter->storeMouse(); - if ((_activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[_activeCollResId & 0xFFF]); - else - WRITE_VAR(16, _activeCollResId & 0xFFF); - - if (_collisionAreas[_activeCollIndex].funcEnter != 0) - collSub(_collisionAreas[_activeCollIndex].funcEnter); - - WRITE_VAR(16, 0); - _activeCollResId = 0; - } - while ((_activeCollResId == 0) && !_vm->_inter->_terminate && !_vm->shouldQuit()); - - if ((_activeCollResId & 0xFFF) == collResId) { - collStackPos = 0; - var_24 = 0; - var_26 = 1; - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0xC000) == 0x8000) - continue; - - if ((_collisionAreas[i].flags & 0x0F) < 3) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 10) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 8) { - char *ptr; - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - while ((ptr = strchr(_tempStr, ' '))) - _vm->_util->cutFromStr(_tempStr, (ptr - _tempStr), 1); - if (_vm->_language == 2) - while ((ptr = strchr(_tempStr, '.'))) - *ptr = ','; - WRITE_VARO_STR(_collisionAreas[i].key, _tempStr); - } - - if (((_collisionAreas[i].flags & 0x0F) >= 5) && - ((_collisionAreas[i].flags & 0x0F) <= 8)) { - str = (char *) descArray[var_24].ptr; - - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->prepareStr(_tempStr); - - int16 pos = 0; - do { - strncpy0(_collStr, str, 255); - pos += strlen(str) + 1; - - str += strlen(str) + 1; - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->prepareStr(_collStr); - - if (strcmp(_tempStr, _collStr) == 0) { - WRITE_VAR(17, VAR(17) + 1); - WRITE_VAR(17 + var_26, 1); - break; - } - } while (READ_LE_UINT16(descArray[var_24].ptr - 2) > pos); - collStackPos++; - } else { - WRITE_VAR(17 + var_26, 2); - } - var_24++; - var_26++; - } - - if (collStackPos != (int16) VAR(17)) - WRITE_VAR(17, 0); - else - WRITE_VAR(17, 1); - } - - if (_handleMouse == 1) - _vm->_draw->blitCursor(); - - if (!_vm->_inter->_terminate) { - _script->seek(_collisionAreas[_activeCollIndex].funcLeave); - - _vm->_inter->storeMouse(); - if (VAR(16) == 0) { - if ((_activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[_activeCollResId & 0xFFF]); - else - WRITE_VAR(16, _activeCollResId & 0xFFF); - } - } else - _script->setFinished(true); - - for (curCmd = 0; curCmd < count; curCmd++) - freeCollision(curCmd + 0x8000); - - for (i = 0; i < 150; i++) { - if (((_collisionAreas[i].id & 0xF000) == 0xA000) || - ((_collisionAreas[i].id & 0xF000) == 0x9000)) - _collisionAreas[i].id |= 0x4000; - } -} - -int16 Game_v2::multiEdit(int16 time, int16 index, int16 *pCurPos, - InputDesc * inpDesc, int16 *collResId, int16 *collIndex, bool mono) { - Collision *collArea; - int16 descInd; - int16 key; - int16 found = -1; - int16 i; - byte *fontExtraBak = 0; - int16 needAdjust = 0; - - descInd = 0; - for (i = 0; i < 150; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0xC000) != 0x8000) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - strncpy0(_tempStr, GET_VARO_STR(collArea->key), 255); - - _vm->_draw->_destSpriteX = collArea->left; - _vm->_draw->_destSpriteY = collArea->top; - _vm->_draw->_spriteRight = collArea->right - collArea->left + 1; - _vm->_draw->_spriteBottom = collArea->bottom - collArea->top + 1; - - _vm->_draw->_destSurface = 21; - - _vm->_draw->_backColor = inpDesc[descInd].backColor; - _vm->_draw->_frontColor = inpDesc[descInd].frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = inpDesc[descInd].fontIndex; - - if (mono) { - fontExtraBak = _vm->_draw->_fonts[_vm->_draw->_fontIndex]->extraData; - needAdjust = _vm->_draw->_needAdjust; - _vm->_draw->_needAdjust = 2; - _vm->_draw->_fonts[_vm->_draw->_fontIndex]->extraData = 0; - } - - _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10); - - _vm->_draw->_destSpriteY += ((collArea->bottom - collArea->top + 1) - - _vm->_draw->_fonts[_vm->_draw->_fontIndex]->itemHeight) / 2; - _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); - - if (mono) { - _vm->_draw->_needAdjust = needAdjust; - _vm->_draw->_fonts[_vm->_draw->_fontIndex]->extraData = fontExtraBak; - } - - descInd++; - } - - for (i = 0; i < 40; i++) - WRITE_VAR_OFFSET(i * 4 + 0x44, 0); - - while (1) { - descInd = 0; - - for (i = 0; i < 150; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0xC000) != 0x8000) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - if (descInd == *pCurPos) { - found = i; - break; - } - - descInd++; - } - - assert(found != -1); - - collArea = &_collisionAreas[found]; - - key = inputArea(collArea->left, collArea->top, - collArea->right - collArea->left + 1, - collArea->bottom - collArea->top + 1, - inpDesc[*pCurPos].backColor, inpDesc[*pCurPos].frontColor, - GET_VARO_STR(collArea->key), inpDesc[*pCurPos].fontIndex, - collArea->flags, &time, collResId, collIndex, mono); - - if (_vm->_inter->_terminate) - return 0; - - switch (key) { - case 0: - if (*collResId == 0) - return 0; - - if (_mouseButtons != 0) { - for (collArea = _collisionAreas, i = 0; - collArea->left != 0xFFFF; collArea++, i++) { - if ((collArea->flags & 0xF00)) - continue; - - if ((collArea->id & 0x4000)) - continue; - - if ((collArea->left > _vm->_global->_inter_mouseX) || - (collArea->right < _vm->_global->_inter_mouseX) || - (collArea->top > _vm->_global->_inter_mouseY) || - (collArea->bottom < _vm->_global->_inter_mouseY)) - continue; - - if ((collArea->id & 0xF000)) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - *collIndex = i; - } - } - - if ((_collisionAreas[*collIndex].flags & 0x0F) < 3) - return 0; - - if ((_collisionAreas[*collIndex].flags & 0x0F) > 10) - return 0; - - *pCurPos = 0; - for (i = 0; i < 150; i++) { - collArea = &_collisionAreas[i]; - - if (collArea->left == 0xFFFF) - continue; - - if ((collArea->id & 0xC000) != 0x8000) - continue; - - if ((collArea->flags & 0x0F) < 3) - continue; - - if ((collArea->flags & 0x0F) > 10) - continue; - - if (i != *collIndex) - pCurPos[0]++; - } - break; - - case 0x3B00: - case 0x3C00: - case 0x3D00: - case 0x3E00: - case 0x3F00: - case 0x4000: - case 0x4100: - case 0x4200: - case 0x4300: - case 0x4400: - return key; - - case 0x1C0D: - - if (index == 1) - return key; - - if (*pCurPos == index - 1) { - *pCurPos = 0; - break; - } - - pCurPos[0]++; - break; - - case 0x5000: - if (index - 1 > *pCurPos) - pCurPos[0]++; - break; - - case 0x4800: - if (*pCurPos > 0) - pCurPos[0]--; - break; - } - } -} - -int16 Game_v2::inputArea(int16 xPos, int16 yPos, int16 width, int16 height, - int16 backColor, int16 frontColor, char *str, int16 fontIndex, - char inpType, int16 *pTotTime, int16 *collResId, int16 *collIndex, bool mono) { - byte handleMouse; - uint32 editSize; - Video::FontDesc *pFont; - char curSym; - int16 key; - const char *str1; - const char *str2; - int16 i; - uint32 pos; - int16 flag; - int16 savedKey; - byte *fontExtraBak = 0; - int16 needAdjust = 0; - - if ((_handleMouse != 0) && - ((_vm->_global->_useMouse != 0) || (_forceHandleMouse != 0))) - handleMouse = 1; - else - handleMouse = 0; - - pos = strlen(str); - pFont = _vm->_draw->_fonts[fontIndex]; - editSize = (!mono && pFont->extraData) ? 0 : (width / pFont->itemWidth); - - while (1) { - strncpy0(_tempStr, str, 254); - strcat(_tempStr, " "); - if ((editSize != 0) && strlen(_tempStr) > editSize) - strncpy0(_tempStr, str, 255); - - if (mono) { - fontExtraBak = _vm->_draw->_fonts[fontIndex]->extraData; - needAdjust = _vm->_draw->_needAdjust; - _vm->_draw->_needAdjust = 2; - _vm->_draw->_fonts[fontIndex]->extraData = 0; - } - - _vm->_draw->_destSpriteX = xPos; - _vm->_draw->_destSpriteY = yPos; - _vm->_draw->_spriteRight = mono ? (editSize * pFont->itemWidth) : width; - _vm->_draw->_spriteBottom = height; - - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = backColor; - _vm->_draw->_frontColor = frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = fontIndex; - _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10 ); - - _vm->_draw->_destSpriteY = yPos + (height - pFont->itemHeight) / 2; - _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); - - if (mono) { - _vm->_draw->_needAdjust = needAdjust; - _vm->_draw->_fonts[fontIndex]->extraData = fontExtraBak; - } - - if ((editSize != 0) && (pos == editSize)) - pos--; - - curSym = _tempStr[pos]; - - flag = 1; - - if (_vm->_inter->_variables) - WRITE_VAR(56, pos); - - while (1) { - if (mono) { - fontExtraBak = _vm->_draw->_fonts[fontIndex]->extraData; - needAdjust = _vm->_draw->_needAdjust; - _vm->_draw->_needAdjust = 2; - _vm->_draw->_fonts[fontIndex]->extraData = 0; - } - - _tempStr[0] = curSym; - _tempStr[1] = 0; - - if (pFont->extraData) { - _vm->_draw->_destSpriteY = yPos; - _vm->_draw->_spriteBottom = height; - _vm->_draw->_spriteRight = 1; - - _vm->_draw->_destSpriteX = xPos; - for (uint32 j = 0; j < pos; j++) - _vm->_draw->_destSpriteX += pFont->extraData[str[j] - pFont->startItem]; - - } else { - _vm->_draw->_destSpriteX = xPos + pFont->itemWidth * pos; - _vm->_draw->_destSpriteY = yPos + height - 1; - _vm->_draw->_spriteRight = pFont->itemWidth; - _vm->_draw->_spriteBottom = 1; - } - - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = frontColor; - _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10); - - if (mono) { - _vm->_draw->_needAdjust = needAdjust; - _vm->_draw->_fonts[fontIndex]->extraData = fontExtraBak; - } - - if (flag != 0) { - key = checkCollisions(handleMouse, -1, collResId, collIndex); - if (key == 0) - key = checkCollisions(handleMouse, -300, collResId, collIndex); - flag = 0; - } else - key = checkCollisions(handleMouse, -300, collResId, collIndex); - - if (mono) { - fontExtraBak = _vm->_draw->_fonts[fontIndex]->extraData; - needAdjust = _vm->_draw->_needAdjust; - _vm->_draw->_needAdjust = 2; - _vm->_draw->_fonts[fontIndex]->extraData = 0; - } - - _tempStr[0] = curSym; - _tempStr[1] = 0; - - if (pFont->extraData) { - _vm->_draw->_destSpriteY = yPos; - _vm->_draw->_spriteBottom = height; - _vm->_draw->_spriteRight = 1; - - _vm->_draw->_destSpriteX = xPos; - for (uint32 j = 0; j < pos; j++) - _vm->_draw->_destSpriteX += pFont->extraData[str[j] - pFont->startItem]; - - } else { - _vm->_draw->_destSpriteX = xPos + pFont->itemWidth * pos; - _vm->_draw->_destSpriteY = yPos + height - 1; - _vm->_draw->_spriteRight = pFont->itemWidth; - _vm->_draw->_spriteBottom = 1; - } - - _vm->_draw->_destSurface = 21; - _vm->_draw->_backColor = backColor; - _vm->_draw->_frontColor = frontColor; - _vm->_draw->_textToPrint = _tempStr; - _vm->_draw->_transparency = 1; - _vm->_draw->_fontIndex = fontIndex; - _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10); - - _vm->_draw->_destSpriteY = yPos + (height - pFont->itemHeight) / 2; - _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); - - if (mono) { - _vm->_draw->_needAdjust = needAdjust; - _vm->_draw->_fonts[fontIndex]->extraData = fontExtraBak; - } - - if ((key != 0) || (*collResId != 0)) - break; - - key = checkCollisions(handleMouse, -300, collResId, collIndex); - - if ((key != 0) || (*collResId != 0) || - _vm->_inter->_terminate || _vm->shouldQuit()) - break; - - if (*pTotTime > 0) { - *pTotTime -= 600; - if (*pTotTime <= 1) { - key = 0; - *collResId = 0; - break; - } - } - } - - if ((key == 0) || (*collResId != 0) || - _vm->_inter->_terminate || _vm->shouldQuit()) - return 0; - - switch (key) { - case 0x4D00: // Right Arrow - if ((pos > strlen(str)) || (pos > (editSize - 1)) || (editSize == 0)) { - pos++; - continue; - } - return 0x5000; - - case 0x4B00: // Left Arrow - if (pos > 0) { - pos--; - continue; - } - return 0x4800; - - case 0xE08: // Backspace - if (pos > 0) { - _vm->_util->cutFromStr(str, pos - 1, 1); - pos--; - continue; - } else { - if (pos < strlen(str)) - _vm->_util->cutFromStr(str, pos, 1); - } - - case 0x5300: // Del - - if (pos >= strlen(str)) - continue; - - _vm->_util->cutFromStr(str, pos, 1); - continue; - - case 0x1C0D: // Enter - case 0x3B00: // F1 - case 0x3C00: // F2 - case 0x3D00: // F3 - case 0x3E00: // F4 - case 0x3F00: // F5 - case 0x4000: // F6 - case 0x4100: // F7 - case 0x4200: // F8 - case 0x4300: // F9 - case 0x4400: // F10 - case 0x4800: // Up arrow - case 0x5000: // Down arrow - return key; - - case 0x11B: // Escape - if (_vm->_global->_useMouse != 0) - continue; - - _forceHandleMouse = !_forceHandleMouse; - - if ((_handleMouse != 0) && - ((_vm->_global->_useMouse != 0) || (_forceHandleMouse != 0))) - handleMouse = 1; - else - handleMouse = 0; - - while (_vm->_global->_pressedKeys[1] != 0) - ; - continue; - - default: - - savedKey = key; - key &= 0xFF; - - if (((inpType == 9) || (inpType == 10)) && - (key >= ' ') && (key <= 0xFF)) { - str1 = "0123456789-.,+ "; - str2 = "0123456789-,,+ "; - - if ((((savedKey >> 8) > 1) && ((savedKey >> 8) < 12)) && - ((_vm->_global->_pressedKeys[42] != 0) || - (_vm->_global->_pressedKeys[56] != 0))) - key = ((savedKey >> 8) - 1) % 10 + '0'; - - for (i = 0; str1[i] != 0; i++) { - if (key == str1[i]) { - key = str2[i]; - break; - } - } - - if (i == (int16) strlen(str1)) - key = 0; - } - - if ((key >= ' ') && (key <= 0xFF)) { - if (editSize == 0) { - int length = _vm->_draw->stringLength(str, fontIndex) + - pFont->extraData[' ' - pFont->startItem] + - pFont->extraData[key - pFont->startItem]; - - if (length > width) - continue; - - if (((int32) strlen(str)) >= (_vm->_global->_inter_animDataSize * 4 - 1)) - continue; - - } else { - if (strlen(str) > editSize) - continue; - else if (editSize == strlen(str)) - _vm->_util->cutFromStr(str, strlen(str) - 1, 1); - } - - pos++; - _tempStr[0] = key; - _tempStr[1] = 0; - - _vm->_util->insertStr(_tempStr, str, pos - 1); - } - - } - } -} - -int16 Game_v2::checkMousePoint(int16 all, int16 *resId, int16 *resIndex) { - Collision *ptr; - int16 i; - - if (resId != 0) - *resId = 0; - - *resIndex = 0; - - ptr = _collisionAreas; - for (i = 0; ptr->left != 0xFFFF; ptr++, i++) { - if (ptr->id & 0x4000) - continue; - - if (all) { - if ((ptr->flags & 0xF) > 1) - continue; - - if ((ptr->flags & 0xF00) != 0) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - - *resIndex = i; - return ptr->key; - } else { - if ((ptr->flags & 0xF00) != 0) - continue; - - if ((ptr->flags & 0xF) < 1) - continue; - - if ((((ptr->flags & 0xF0) >> 4) != (_mouseButtons - 1)) && - (((ptr->flags & 0xF0) >> 4) != 2)) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - *resIndex = i; - if (((ptr->flags & 0xF) == 1) || ((ptr->flags & 0xF) == 2)) - return ptr->key; - return 0; - } - } - - if ((_mouseButtons != 1) && (all == 0)) - return 0x11B; - - return 0; -} - -} // End of namespace Gob diff --git a/engines/gob/game_v6.cpp b/engines/gob/game_v6.cpp deleted file mode 100644 index 8d40d41acc..0000000000 --- a/engines/gob/game_v6.cpp +++ /dev/null @@ -1,1114 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/endian.h" -#include "common/stream.h" -#include "common/file.h" - -#include "gob/gob.h" -#include "gob/game.h" -#include "gob/helper.h" -#include "gob/global.h" -#include "gob/script.h" -#include "gob/resources.h" -#include "gob/inter.h" -#include "gob/draw.h" - -namespace Gob { - -Game_v6::Game_v6(GobEngine *vm) : Game_v2(vm) { - _someTimeDly = 0; -} - -// flagbits: 5 = freeInterVariables, 6 = skipPlay -void Game_v6::totSub(int8 flags, const char *newTotFile) { - int8 curBackupPos; - - if ((flags == 16) || (flags == 17)) - warning("Urban Stub: Game_v6::totSub(), flags == %d", flags); - - if (_numEnvironments >= Environments::kEnvironmentCount) - return; - - _environments->set(_numEnvironments); - - curBackupPos = _curEnvironment; - _numEnvironments++; - _curEnvironment = _numEnvironments; - - _script = new Script(_vm); - _resources = new Resources(_vm); - - if (flags & 0x80) - warning("Urban Stub: Game_v6::totSub(), flags & 0x80"); - - if (flags & 5) - _vm->_inter->_variables = 0; - - strncpy0(_curTotFile, newTotFile, 9); - strcat(_curTotFile, ".TOT"); - - if (_vm->_inter->_terminate != 0) { - clearUnusedEnvironment(); - return; - } - - pushCollisions(0); - - if (flags & 6) - playTot(-1); - else - playTot(0); - - if (_vm->_inter->_terminate < 2) - _vm->_inter->_terminate = 0; - - clearCollisions(); - popCollisions(); - - if ((flags & 5) && _vm->_inter->_variables) { - _vm->_inter->delocateVars(); - } - - clearUnusedEnvironment(); - - _numEnvironments--; - _curEnvironment = curBackupPos; - _environments->get(_numEnvironments); -} - -int16 Game_v6::addNewCollision(int16 id, uint16 left, uint16 top, - uint16 right, uint16 bottom, int16 flags, int16 key, - uint16 funcEnter, uint16 funcLeave, uint16 funcSub) { - Collision *ptr; - - debugC(5, kDebugCollisions, "addNewCollision"); - debugC(5, kDebugCollisions, "id = %X", id); - debugC(5, kDebugCollisions, "left = %d, top = %d, right = %d, bottom = %d", - left, top, right, bottom); - debugC(5, kDebugCollisions, "flags = %X, key = %X", flags, key); - debugC(5, kDebugCollisions, "funcEnter = %d, funcLeave = %d", - funcEnter, funcLeave); - - for (int i = 0; i < 150; i++) { - if ((_collisionAreas[i].left != 0xFFFF) && (_collisionAreas[i].id != id)) - continue; - - ptr = &_collisionAreas[i]; - - if ((ptr->id & 0xBFFF) != (id & 0xBFFF)) - ptr->id = id; - - ptr->left = left; - ptr->top = top; - ptr->right = right; - ptr->bottom = bottom; - ptr->flags = flags; - ptr->key = key; - ptr->funcEnter = funcEnter; - ptr->funcLeave = funcLeave; - ptr->funcSub = funcSub; - ptr->script = _script; - - return i; - } - error("Game_v6::addNewCollision(): Collision array full"); - return 0; -} - -void Game_v6::prepareStart(void) { - _noCd = false; - - if (Common::File::exists("cd1.itk") && Common::File::exists("cd2.itk") && - Common::File::exists("cd3.itk") && Common::File::exists("cd4.itk")) { - _noCd = true; - } - - Game_v2::prepareStart(); -} - -void Game_v6::pushCollisions(char all) { - Collision *srcPtr; - Collision *destPtr; - int16 size; - - debugC(1, kDebugCollisions, "pushCollisions"); - for (size = 0, srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if ( (all == 1) || - ((all == 0) && (((uint16) srcPtr->id) >= 20)) || - ((all == 2) && (((srcPtr->id & 0xF000) == 0xD000) || - ((srcPtr->id & 0xF000) == 0x4000) || - ((srcPtr->id & 0xF000) == 0xE000)))) - size++; - } - - if (_collStackSize >= 5) - error("Game_v6::pushCollisions: _collStackSize == %d", _collStackSize); - - destPtr = new Collision[size]; - _collStack[_collStackSize] = destPtr; - - if (_vm->_inter->_terminate) - return; - - _collStackElemSizes[_collStackSize] = size; - - if (_shouldPushColls != 0) - _collStackElemSizes[_collStackSize] |= 0x8000; - - _shouldPushColls = 0; - _collLasts[_collStackSize].key = _lastCollKey; - _collLasts[_collStackSize].id = _lastCollId; - _collLasts[_collStackSize].areaIndex = _lastCollAreaIndex; - _lastCollKey = 0; - _lastCollId = 0; - _lastCollAreaIndex = 0; - _collStackSize++; - - for (srcPtr = _collisionAreas; srcPtr->left != 0xFFFF; srcPtr++) { - if ( (all == 1) || - ((all == 0) && (((uint16) srcPtr->id) >= 20)) || - ((all == 2) && (((srcPtr->id & 0xF000) == 0xD000) || - ((srcPtr->id & 0xF000) == 0x4000) || - ((srcPtr->id & 0xF000) == 0xE000)))) { - - memcpy(destPtr, srcPtr, sizeof(Collision)); - srcPtr->left = 0xFFFF; - destPtr++; - } - } -} - -int16 Game_v6::checkCollisions(byte handleMouse, int16 deltaTime, int16 *pResId, - int16 *pResIndex) { - int16 resIndex; - int16 key; - uint32 timeKey; - - _scrollHandleMouse = handleMouse != 0; - - if (deltaTime >= -1) { - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if (pResId != 0) - *pResId = 0; - - resIndex = 0; - - if ((_lastCollKey != 0) && - ( (_collisionAreas[_lastCollAreaIndex].id != _lastCollId) || - (_collisionAreas[_lastCollAreaIndex].key != _lastCollKey))) { - - _lastCollKey = 0; - _lastCollAreaIndex = 0; - _lastCollId = 0; - } - - if ((_vm->_draw->_cursorIndex == -1) && - (handleMouse != 0) && (_lastCollKey == 0)) { - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } - - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - timeKey = _vm->_util->getTimeKey(); - _vm->_draw->blitInvalidated(); - while (1) { - if (_vm->_inter->_terminate || _vm->shouldQuit()) { - if (handleMouse) - _vm->_draw->blitCursor(); - return 0; - } - - collSubReenter(); - if (!_vm->_draw->_noInvalidated) { - if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - else - _vm->_draw->blitInvalidated(); - _vm->_video->waitRetrace(); - } - - key = checkKeys(&_vm->_global->_inter_mouseX, - &_vm->_global->_inter_mouseY, &_mouseButtons, handleMouse); - - if ((handleMouse == 0) && (_mouseButtons != 0)) { - _vm->_util->waitMouseRelease(0); - key = 3; - } - - if (key != 0) { - - if (handleMouse & 1) - _vm->_draw->blitCursor(); - - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - if (key != 0) - return key; - - if (handleMouse) - _vm->_draw->animateCursor(-1); - } - - if (handleMouse != 0) { - if (_mouseButtons != 0) { - - if (deltaTime > 0) { - _vm->_draw->animateCursor(2); - _vm->_util->delay(deltaTime); - } else if (handleMouse & 1) - _vm->_util->waitMouseRelease(1); - - _vm->_draw->animateCursor(-1); - - if (pResId != 0) - *pResId = 0; - - key = checkMousePoint(0, pResId, &resIndex); - if (pResIndex != 0) - *pResIndex = resIndex; - - if ((key != 0) || ((pResId != 0) && (*pResId != 0))) { - if ((handleMouse & 1) && - ((deltaTime <= 0) || (_mouseButtons == 0))) - _vm->_draw->blitCursor(); - - if (key != _lastCollKey) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = 0; - return key; - } - - if (handleMouse & 4) - return 0; - - if (_lastCollKey != 0) - collAreaSub(_lastCollAreaIndex, 0); - - _lastCollKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); - } else - collSubReenter(); - } - - if ((deltaTime == -2) && (key == 0) && (_mouseButtons == 0)) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - - } else if (handleMouse != 0) - _vm->_draw->animateCursor(-1); - - if ((deltaTime < 0) && (key == 0) && (_mouseButtons == 0)) { - uint32 curtime = _vm->_util->getTimeKey(); - if ((curtime + deltaTime) > timeKey) { - if (pResId != 0) - *pResId = 0; - - if (pResIndex != 0) - *pResIndex = 0; - - return 0; - } - } - - _vm->_util->delay(10); - } -} - -void Game_v6::collisionsBlock(void) { - InputDesc descArray[20]; - int16 array[300]; - byte count; - int16 collResId; - int16 curCmd; - int16 cmd; - int16 cmdHigh; - int16 key; - int16 flags; - uint16 left; - uint16 top; - uint16 width; - uint16 height; - int16 deltaTime; - int16 stackPos2; - int16 descIndex; - int16 timeVal; - char *str; - int16 i; - int16 counter; - int16 var_24; - int16 var_26; - int16 collStackPos; - Collision *collPtr; - Collision *collArea; - byte collAreaStart; - int16 activeCollResId = 0; - int16 activeCollIndex = 0; - uint32 startPos; - uint32 offsetPos; - - if (_shouldPushColls) - pushCollisions(0); - - collAreaStart = 0; - while (_collisionAreas[collAreaStart].left != 0xFFFF) - collAreaStart++; - collArea = &_collisionAreas[collAreaStart]; - - _shouldPushColls = 0; - collResId = -1; - - _script->skip(1); - count = _script->readByte(); - - _handleMouse = _script->peekByte(0); - deltaTime = 1000 * _script->peekByte(1); - stackPos2 = _script->peekByte(3); - descIndex = _script->peekByte(4); - byte var_42 = _script->peekByte(5); - - if ((stackPos2 != 0) || (descIndex != 0)) { - deltaTime /= 100; - if (_script->peekByte(1) == 100) - deltaTime = 2; - } - - timeVal = deltaTime; - _script->skip(6); - - startPos = _script->pos(); - WRITE_VAR(16, 0); - - byte var_41 = 0; - int16 var_46 = 0; - int16 var_1C = 0; - int16 index = 0; - int16 curEditIndex = 0; - int right = 0, funcLeave = 0; - - for (curCmd = 0; curCmd < count; curCmd++) { - array[curCmd] = 0; - cmd = _script->readByte(); - - if ((cmd & 0x40) != 0) { - cmd -= 0x40; - cmdHigh = _script->readByte(); - cmdHigh <<= 8; - } else - cmdHigh = 0; - - if ((cmd & 0x80) != 0) { - offsetPos = _script->pos(); - left = _script->readValExpr(); - top = _script->readValExpr(); - width = _script->readValExpr(); - height = _script->readValExpr(); - } else { - offsetPos = 0; - left = _script->readUint16(); - top = _script->readUint16(); - width = _script->readUint16(); - height = _script->readUint16(); - } - - if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { - left += _vm->_draw->_backDeltaX; - top += _vm->_draw->_backDeltaY; - } - - if (left != 0xFFFF) { - _vm->_draw->adjustCoords(0, &left, &top); - if (((cmd & 0x3F) < 20) && ((cmd & 0x3F) >= 3)) { - if (_vm->_draw->_needAdjust != 2) - height &= 0xFFFE; - _vm->_draw->adjustCoords(0, 0, &width); - } else - _vm->_draw->adjustCoords(0, &height, &width); - } - - cmd &= 0x7F; - debugC(1, kDebugCollisions, "collisionsBlock(%d)", cmd); - - switch (cmd) { - case 0: - _script->skip(6); - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - cmd + cmdHigh, key, startPos, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 1: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16(); - - startPos = _script->pos(); - _script->skip(_script->peekUint16(2) + 2); - - if (key == 0) - key = curCmd + 0xA000; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmd + cmdHigh, key, startPos, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - _vm->_util->clearKeyBuf(); - var_1C = 1; - key = _script->readVarIndex(); - descArray[index].fontIndex = _script->readInt16(); - descArray[index].backColor = _script->readByte(); - descArray[index].frontColor = _script->readByte(); - - if ((cmd >= 5) && (cmd <= 8)) { - descArray[index].ptr = _script->getData() + _script->pos() + 2; - _script->skip(_script->peekUint16() + 2); - } else - descArray[index].ptr = 0; - - if (left == 0xFFFF) { - if ((cmd & 1) == 0) { - _script->skip(_script->peekUint16(2) + 2); - } - break; - } - - right = left + width - 1; - if (!_vm->_draw->_fonts[descArray[index].fontIndex]->extraData) - right = left + width * _vm->_draw->_fonts[descArray[index].fontIndex]->itemWidth - 1; - - funcLeave = 0; - if (!(cmd & 1)) - funcLeave = _script->pos(); - - addNewCollision(curCmd + 0x8000, left, top, right, - top + height - 1, cmd, key, 0, funcLeave, 0); - - if (!(cmd & 1)) { - _script->skip(_script->peekUint16(2) + 2); - } - - index++; - break; - - case 11: - _script->skip(6); - for (i = 0; i < 150; i++) { - if ((_collisionAreas[i].id & 0xF000) == 0xE000) { - _collisionAreas[i].id &= 0xBFFF; - _collisionAreas[i].funcEnter = - _script->pos(); - _collisionAreas[i].funcLeave = - _script->pos(); - } - } - _script->skip(_script->peekUint16(2) + 2); - break; - - case 12: - _script->skip(6); - for (i = 0; i < 150; i++) { - if ((_collisionAreas[i].id & 0xF000) == 0xD000) { - _collisionAreas[i].id &= 0xBFFF; - _collisionAreas[i].funcEnter = - _script->pos(); - _collisionAreas[i].funcLeave = - _script->pos(); - } - } - _script->skip(_script->peekUint16(2) + 2); - break; - - case 20: - collResId = curCmd; - // Fall through to case 2 - - case 2: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16(); - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, 0, - _script->pos(), offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - - case 21: - key = _script->readInt16(); - array[curCmd] = _script->readInt16(); - flags = _script->readInt16() & 3; - - addNewCollision(curCmd + 0x8000, left, top, - left + width - 1, top + height - 1, - (flags << 4) + cmdHigh + 2, key, - _script->pos(), 0, offsetPos); - - _script->skip(_script->peekUint16(2) + 2); - - break; - } - } - - if (var_42 != 0) - setCollisions(1); - - _forceHandleMouse = 0; - _vm->_util->clearKeyBuf(); - - do { - if (var_1C != 0) { - key = multiEdit(deltaTime, index, &curEditIndex, descArray, - &activeCollResId, &activeCollIndex, false); - - WRITE_VAR(55, curEditIndex); - if (key == 0x1C0D) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].flags & 1) != 0) - continue; - - if ((_collisionAreas[i].flags & 0x0F) <= 2) - continue; - - activeCollResId = _collisionAreas[i].id; - collResId = _collisionAreas[i].id & 0x7FFF; - activeCollIndex = i; - break; - } - break; - } - } else - key = checkCollisions(_handleMouse, -deltaTime, - &activeCollResId, &activeCollIndex); - - if (((key & 0xFF) >= ' ') && ((key & 0xFF) <= 0xFF) && - ((key >> 8) > 1) && ((key >> 8) < 12)) - key = '0' + (((key >> 8) - 1) % 10) + (key & 0xFF00); - - if (activeCollResId == 0) { - if (key != 0) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].key == key) || - (_collisionAreas[i].key == 0x7FFF)) { - activeCollResId = _collisionAreas[i].id; - activeCollIndex = i; - break; - } - } - - if (activeCollResId == 0) { - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - break; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].key & 0xFF00) != 0) - continue; - - if (_collisionAreas[i].key == 0) - continue; - - if (adjustKey(key & 0xFF) == adjustKey(_collisionAreas[i].key)) { - activeCollResId = _collisionAreas[i].id; - activeCollIndex = i; - break; - } - } - } - } else if (deltaTime != 0) { - if (stackPos2 != 0) { - collStackPos = 0; - - for (i = 0, collPtr = collArea; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) != 0x8000) - continue; - - collStackPos++; - if (collStackPos != stackPos2) - continue; - - activeCollResId = collPtr->id; - activeCollIndex = i + collAreaStart; - _vm->_inter->storeMouse(); - if (VAR(16) != 0) - break; - - if ((activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[activeCollResId & 0xFFF]); - else - WRITE_VAR(16, activeCollResId & 0xFFF); - - if (collPtr->funcLeave != 0) { - uint32 timeKey = _vm->_util->getTimeKey(); - collSub(collPtr->funcLeave); - - if (timeVal != 2) { - deltaTime = timeVal - (_vm->_util->getTimeKey() - timeKey); - - if ((deltaTime - var_46) < 3) { - var_46 -= (deltaTime - 3); - deltaTime = 3; - } else if (var_46 != 0) { - deltaTime -= var_46; - var_46 = 0; - } - - if (deltaTime > timeVal) - deltaTime = timeVal; - - } else - deltaTime = 2; - - } - - if (VAR(16) == 0) - activeCollResId = 0; - else - var_41 = 1; - - break; - } - } else { - if (descIndex != 0) { - - counter = 0; - for (i = 0, collPtr = collArea; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) == 0x8000) - if (++counter == descIndex) { - activeCollResId = collPtr->id; - activeCollIndex = i + collAreaStart; - break; - } - } - - } else { - - for (i = 0, collPtr = _collisionAreas; collPtr->left != 0xFFFF; i++, collPtr++) { - if ((collPtr->id & 0xF000) == 0x8000) { - activeCollResId = collPtr->id; - activeCollIndex = i; - break; - } - } - if ((_lastCollKey != 0) && - (_collisionAreas[_lastCollAreaIndex].funcLeave != 0)) - collSub(_collisionAreas[_lastCollAreaIndex].funcLeave); - - _lastCollKey = 0; - } - - } - } - } - - if (var_41 != 0) - break; - - if ((activeCollResId == 0) || - (_collisionAreas[activeCollIndex].funcLeave != 0)) - continue; - - _vm->_inter->storeMouse(); - if ((activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[activeCollResId & 0xFFF]); - else - WRITE_VAR(16, activeCollResId & 0xFFF); - - if (_collisionAreas[activeCollIndex].funcEnter != 0) - collSub(_collisionAreas[activeCollIndex].funcEnter); - - WRITE_VAR(16, 0); - activeCollResId = 0; - } - while ((activeCollResId == 0) && !_vm->_inter->_terminate && !_vm->shouldQuit()); - - if ((activeCollResId & 0xFFF) == collResId) { - collStackPos = 0; - var_24 = 0; - var_26 = 1; - for (i = 0; i < 150; i++) { - if (_collisionAreas[i].left == 0xFFFF) - continue; - - if ((_collisionAreas[i].id & 0xC000) != 0x8000) - continue; - - if ((_collisionAreas[i].flags & 0x0F) < 3) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 10) - continue; - - if ((_collisionAreas[i].flags & 0x0F) > 8) { - char *ptr; - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - while ((ptr = strchr(_tempStr, ' '))) - _vm->_util->cutFromStr(_tempStr, (ptr - _tempStr), 1); - if (_vm->_language == 2) - while ((ptr = strchr(_tempStr, '.'))) - *ptr = ','; - WRITE_VARO_STR(_collisionAreas[i].key, _tempStr); - } - - if (((_collisionAreas[i].flags & 0x0F) >= 5) && - ((_collisionAreas[i].flags & 0x0F) <= 8)) { - str = (char *) descArray[var_24].ptr; - - strncpy0(_tempStr, GET_VARO_STR(_collisionAreas[i].key), 255); - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->prepareStr(_tempStr); - - int16 pos = 0; - do { - strncpy0(_collStr, str, 255); - pos += strlen(str) + 1; - - str += strlen(str) + 1; - - if ((_collisionAreas[i].flags & 0x0F) < 7) - _vm->_util->prepareStr(_collStr); - - if (strcmp(_tempStr, _collStr) == 0) { - WRITE_VAR(17, VAR(17) + 1); - WRITE_VAR(17 + var_26, 1); - break; - } - } while (READ_LE_UINT16(descArray[var_24].ptr - 2) > pos); - collStackPos++; - } else { - WRITE_VAR(17 + var_26, 2); - } - var_24++; - var_26++; - } - - if (collStackPos != (int16) VAR(17)) - WRITE_VAR(17, 0); - else - WRITE_VAR(17, 1); - } - - if (_handleMouse == 1) - _vm->_draw->blitCursor(); - - if (!_vm->_inter->_terminate && (var_41 == 0)) { - _script->seek(_collisionAreas[activeCollIndex].funcLeave); - - _vm->_inter->storeMouse(); - if (VAR(16) == 0) { - if ((activeCollResId & 0xF000) == 0x8000) - WRITE_VAR(16, array[activeCollResId & 0xFFF]); - else - WRITE_VAR(16, activeCollResId & 0xFFF); - } - } else - _script->setFinished(true); - - for (curCmd = 0; curCmd < count; curCmd++) - freeCollision(curCmd + 0x8000); - - for (i = 0; i < 150; i++) { - if (((_collisionAreas[i].id & 0xF000) == 0xA000) || - ((_collisionAreas[i].id & 0xF000) == 0x9000)) - _collisionAreas[i].id |= 0x4000; - } -} - -void Game_v6::setCollisions(byte arg_0) { - for (Collision *collArea = _collisionAreas; collArea->left != 0xFFFF; collArea++) { - if (((collArea->id & 0xC000) != 0x8000) || (collArea->funcSub == 0)) - continue; - - if (arg_0 == 0) - if (collArea->flags & 0x80) - continue; - - Script *curScript = _script; - - _script = collArea->script; - if (!_script) - _script = curScript; - - _script->call(collArea->funcSub); - - int16 left = _script->readValExpr(); - int16 top = _script->readValExpr(); - int16 width = _script->readValExpr(); - int16 height = _script->readValExpr(); - uint16 flags = 0; - - if ((collArea->id & 0xF000) == 0xA000) - flags = _script->readValExpr(); - - if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && - (left != -1)) { - left += _vm->_draw->_backDeltaX; - top += _vm->_draw->_backDeltaY; - } - if (_vm->_draw->_needAdjust != 2) { - _vm->_draw->adjustCoords(0, &left, &top); - if ((collArea->flags & 0x0F) < 3) - _vm->_draw->adjustCoords(2, &width, &height); - else { - height &= 0xFFFE; - _vm->_draw->adjustCoords(2, 0, &height); - } - } - - if (left < 0) { - width += left; - left = 0; - } - - if (top < 0) { - height += top; - top = 0; - } - - collArea->left = left; - collArea->top = top; - collArea->right = left + width - 1; - collArea->bottom = top + height - 1; - - if ((collArea->id & 0xF000) == 0xA000) - collArea->flags = flags; - - _script->pop(); - - _script = curScript; - } -} - -void Game_v6::collSub(uint16 offset) { - int16 collStackSize; - - uint32 savedPos = _script->pos(); - - _script->seek(offset); - - _shouldPushColls = 1; - collStackSize = _collStackSize; - - _vm->_inter->funcBlock(0); - - if (collStackSize != _collStackSize) - popCollisions(); - - _shouldPushColls = 0; - - _script->seek(savedPos); - - if ((_vm->_util->getTimeKey() - _someTimeDly) > 500) - setCollisions(0); -} - -static const byte adjustTable[] = { - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, - 0x81, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, - 0x12, 0x12, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x04, 0x04, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x40, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, - 0x08, 0x08, 0x08, 0x40, 0x40, 0x40, 0x40, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -int16 Game_v6::adjustKey(int16 key) { - if (key == -1) - return -1; - - if (adjustTable[key & 0xFF] & 8) - return ((key & 0xFF) - 0x20); - - return key & 0xFF; -} - -int16 Game_v6::checkMousePoint(int16 all, int16 *resId, int16 *resIndex) { - Collision *ptr; - int16 i; - - if (resId != 0) - *resId = 0; - - *resIndex = 0; - - ptr = _collisionAreas; - for (i = 0; ptr->left != 0xFFFF; ptr++, i++) { - if (ptr->id & 0x4000) - continue; - - if (all) { - if ((ptr->flags & 0xF) > 1) - continue; - - if ((ptr->flags & 0xF00) != 0) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - - *resIndex = i; - return ptr->key; - } else { - if ((ptr->flags & 0xF00) != 0) - continue; - - if ((ptr->flags & 0xF) < 1) - continue; - - if ((((ptr->flags & 0x70) >> 4) != (_mouseButtons - 1)) && - (((ptr->flags & 0x70) >> 4) != 2)) - continue; - - if ((_vm->_global->_inter_mouseX < ptr->left) || - (_vm->_global->_inter_mouseX > ptr->right) || - (_vm->_global->_inter_mouseY < ptr->top) || - (_vm->_global->_inter_mouseY > ptr->bottom)) - continue; - - if (resId != 0) - *resId = ptr->id; - *resIndex = i; - if (((ptr->flags & 0xF) == 1) || ((ptr->flags & 0xF) == 2)) - return ptr->key; - return 0; - } - } - - if ((_mouseButtons != 1) && (all == 0)) - return 0x11B; - - return 0; -} - -void Game_v6::collSubReenter() { - int16 lastCollAreaIndex = _lastCollAreaIndex; - int16 lastCollId = _lastCollId; - int16 collKey = checkMousePoint(1, &_lastCollId, &_lastCollAreaIndex); - - if (collKey == _lastCollKey) - return; - - if ((_lastCollKey != 0) && (lastCollId & 0x8000)) - collAreaSub(lastCollAreaIndex, 0); - - _lastCollKey = collKey; - - if ((_lastCollKey != 0) && (_lastCollId & 0x8000)) - collAreaSub(_lastCollAreaIndex, 1); -} - -} // End of namespace Gob diff --git a/engines/gob/global.cpp b/engines/gob/global.cpp index 4165938966..2969ed0870 100644 --- a/engines/gob/global.cpp +++ b/engines/gob/global.cpp @@ -123,6 +123,8 @@ Global::Global(GobEngine *vm) : _vm(vm) { _inter_mouseY = 0; _speedFactor = 1; + + _noCd = false; } Global::~Global() { diff --git a/engines/gob/global.h b/engines/gob/global.h index 982ce113cb..7849490107 100644 --- a/engines/gob/global.h +++ b/engines/gob/global.h @@ -141,6 +141,8 @@ public: // Can be 1, 2 or 3 for normal, double and triple speed, respectively uint8 _speedFactor; + bool _noCd; + Global(GobEngine *vm); ~Global(); diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index e534464cce..fa4f04eab8 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -126,7 +126,7 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) { Common::addDebugChannel(kDebugSaveLoad, "SaveLoad", "Saving/Loading debug level"); Common::addDebugChannel(kDebugGraphics, "Graphics", "Graphics debug level"); Common::addDebugChannel(kDebugVideo, "Video", "IMD/VMD video debug level"); - Common::addDebugChannel(kDebugCollisions, "Collisions", "Collisions debug level"); + Common::addDebugChannel(kDebugHotspots, "Hotspots", "Hotspots debug level"); Common::addDebugChannel(kDebugDemo, "Demo", "Demo script debug level"); syst->getEventManager()->registerRandomSource(_rnd, "gob"); @@ -205,6 +205,10 @@ bool GobEngine::isBATDemo() const { return (_features & kFeaturesBATDemo) != 0; } +bool GobEngine::is800x600() const { + return (_features & kFeatures800x600) != 0; +} + bool GobEngine::isDemo() const { return (isSCNDemo() || isBATDemo()); } @@ -331,6 +335,7 @@ bool GobEngine::initGameParts() { _palAnim = new PalAnim(this); _vidPlayer = new VideoPlayer(this); _sound = new Sound(this); + _game = new Game(this); switch (_gameType) { case kGameTypeGeisha: @@ -341,7 +346,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_v1(this); _mult = new Mult_v1(this); _draw = new Draw_v1(this); - _game = new Game_v1(this); _map = new Map_v1(this); _goblin = new Goblin_v1(this); _scenery = new Scenery_v1(this); @@ -353,7 +357,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_Fascination(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_Fascination(this); _map = new Map_v2(this); _goblin = new Goblin_v2(this); _scenery = new Scenery_v2(this); @@ -367,7 +370,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_v2(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_v2(this); _map = new Map_v2(this); _goblin = new Goblin_v2(this); _scenery = new Scenery_v2(this); @@ -380,7 +382,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_Bargon(this); _mult = new Mult_v2(this); _draw = new Draw_Bargon(this); - _game = new Game_v2(this); _map = new Map_v2(this); _goblin = new Goblin_v2(this); _scenery = new Scenery_v2(this); @@ -394,7 +395,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_v3(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_v2(this); _map = new Map_v2(this); _goblin = new Goblin_v3(this); _scenery = new Scenery_v2(this); @@ -407,7 +407,6 @@ bool GobEngine::initGameParts() { _inter = new Inter_v3(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_v2(this); _map = new Map_v2(this); _goblin = new Goblin_v3(this); _scenery = new Scenery_v2(this); @@ -420,23 +419,18 @@ bool GobEngine::initGameParts() { _inter = new Inter_v4(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_v2(this); _map = new Map_v4(this); _goblin = new Goblin_v4(this); _scenery = new Scenery_v2(this); _saveLoad = new SaveLoad_v4(this, _targetName.c_str()); break; - case kGameTypePlaytoon: - case kGameTypePlaytnCk: - case kGameTypeBambou: case kGameTypeDynasty: _init = new Init_v3(this); _video = new Video_v2(this); _inter = new Inter_v5(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_v2(this); _map = new Map_v4(this); _goblin = new Goblin_v4(this); _scenery = new Scenery_v2(this); @@ -445,18 +439,32 @@ bool GobEngine::initGameParts() { case kGameTypeAdibou4: case kGameTypeUrban: - _init = new Init_v3(this); + _init = new Init_v6(this); _video = new Video_v6(this); _inter = new Inter_v6(this); _mult = new Mult_v2(this); _draw = new Draw_v2(this); - _game = new Game_v6(this); _map = new Map_v4(this); _goblin = new Goblin_v4(this); _scenery = new Scenery_v2(this); _saveLoad = new SaveLoad_v6(this, _targetName.c_str()); break; + case kGameTypePlaytoon: + case kGameTypePlaytnCk: + case kGameTypeBambou: + _init = new Init_v2(this); + _video = new Video_v2(this); +// _inter = new Inter_Playtoons(this); + _inter = new Inter_v6(this); + _mult = new Mult_v2(this); + _draw = new Draw_v2(this); + _map = new Map_v2(this); + _goblin = new Goblin_v2(this); + _scenery = new Scenery_v2(this); + _saveLoad = new SaveLoad_Playtoons(this); + break; + default: deinitGameParts(); return false; diff --git a/engines/gob/gob.h b/engines/gob/gob.h index 5d1cb3ecf2..02f6af51bf 100644 --- a/engines/gob/gob.h +++ b/engines/gob/gob.h @@ -108,6 +108,7 @@ enum GameType { kGameTypeBambou, kGameTypeFascination, kGameTypeGeisha, + kGameTypeMagicStones, kGameTypeAdibou4, kGameTypeAdibouUnknown }; @@ -119,7 +120,8 @@ enum Features { kFeaturesAdlib = 1 << 2, kFeatures640 = 1 << 3, kFeaturesSCNDemo = 1 << 4, - kFeaturesBATDemo = 1 << 5 + kFeaturesBATDemo = 1 << 5, + kFeatures800x600 = 1 << 6 }; enum { @@ -133,7 +135,7 @@ enum { kDebugSaveLoad = 1 << 7, kDebugGraphics = 1 << 8, kDebugVideo = 1 << 9, - kDebugCollisions = 1 << 10, + kDebugHotspots = 1 << 10, kDebugDemo = 1 << 11 }; @@ -216,6 +218,7 @@ public: bool hasAdlib() const; bool isSCNDemo() const; bool isBATDemo() const; + bool is800x600() const; bool isDemo() const; GobEngine(OSystem *syst); diff --git a/engines/gob/hotspots.cpp b/engines/gob/hotspots.cpp new file mode 100644 index 0000000000..b218634d4e --- /dev/null +++ b/engines/gob/hotspots.cpp @@ -0,0 +1,1976 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "gob/hotspots.h" +#include "gob/global.h" +#include "gob/helper.h" +#include "gob/draw.h" +#include "gob/game.h" +#include "gob/script.h" +#include "gob/inter.h" + +namespace Gob { + +Hotspots::Hotspot::Hotspot() { + clear(); +} + +Hotspots::Hotspot::Hotspot(uint16 i, + uint16 l, uint16 t, uint16 r, uint16 b, uint16 f, uint16 k, + uint16 enter, uint16 leave, uint16 pos) { + + id = i; + left = l; + top = t; + right = r; + bottom = b; + flags = f; + key = k; + funcEnter = enter; + funcLeave = leave; + funcPos = pos; + script = 0; +} + +void Hotspots::Hotspot::clear() { + id = 0; + left = 0xFFFF; + top = 0; + right = 0; + bottom = 0; + flags = 0; + key = 0; + funcEnter = 0; + funcLeave = 0; + funcPos = 0; + script = 0; +} + +Hotspots::Type Hotspots::Hotspot::getType() const { + return (Type) (flags & 0xF); +} + +MouseButtons Hotspots::Hotspot::getButton() const { + uint8 buttonBits = ((flags & 0x70) >> 4); + + if (buttonBits == 0) + return kMouseButtonsLeft; + if (buttonBits == 1) + return kMouseButtonsRight; + if (buttonBits == 2) + return kMouseButtonsAny; + + return kMouseButtonsNone; +} + +uint8 Hotspots::Hotspot::getWindow() const { + return (flags & 0x0F00) >> 8; +} + +uint8 Hotspots::Hotspot::getCursor() const { + return (flags & 0xF000) >> 12; +} + +uint8 Hotspots::Hotspot::getState(uint16 id) { + return (id & 0xF000) >> 12; +} + +uint8 Hotspots::Hotspot::getState() const { + return getState(id); +} + +bool Hotspots::Hotspot::isEnd() const { + return (left == 0xFFFF); +} + +bool Hotspots::Hotspot::isInput() const { + if (getType() < kTypeInput1NoLeave) + return false; + + if (getType() > kTypeInputFloatLeave) + return false; + + return true; +} + +bool Hotspots::Hotspot::isActiveInput() const { + if (isEnd()) + return false; + + if (!isFilledEnabled()) + return false; + + if (!isInput()) + return false; + + return true; +} + +bool Hotspots::Hotspot::isInputLeave() const { + if (!isInput()) + return false; + + if (!(getType() & 1)) + return true; + + return false; +} + +bool Hotspots::Hotspot::isFilled() const { + return getState() & kStateFilled; +} + +bool Hotspots::Hotspot::isFilledEnabled() const { + return (getState() & kStateFilledDisabled) == kStateFilled; +} + +bool Hotspots::Hotspot::isFilledNew() const { + return getState() == kStateFilled; +} + +bool Hotspots::Hotspot::isDisabled() const { + return getState() & kStateDisabled; +} + +bool Hotspots::Hotspot::isIn(uint16 x, uint16 y) const { + if (x < left) + return false; + if (x > right) + return false; + if (y < top) + return false; + if (y > bottom) + return false; + + return true; +} + +bool Hotspots::Hotspot::buttonMatch(MouseButtons button) const { + MouseButtons myButton = getButton(); + + if (myButton == kMouseButtonsAny) + // Any button allowed + return true; + + if (myButton == kMouseButtonsNone) + // No button allowed + return false; + + if (myButton == button) + // Exact match + return true; + + return false; +} + +void Hotspots::Hotspot::disable() { + id |= (kStateDisabled << 12); +} + +void Hotspots::Hotspot::enable() { + id &= ~(kStateDisabled << 12); +} + + +Hotspots::Hotspots(GobEngine *vm) : _vm(vm) { + _hotspots = new Hotspot[kHotspotCount]; + + _shouldPush = false; + + _currentKey = 0; + _currentIndex = 0; + _currentId = 0; +} + +Hotspots::~Hotspots() { + delete[] _hotspots; + + // Pop the whole stack and free each element's memory + while (!_stack.empty()) { + + StackEntry backup = _stack.pop(); + + delete[] backup.hotspots; + } +} + +void Hotspots::clear() { + _currentKey = 0; + + for (int i = 0; i < kHotspotCount; i++) + _hotspots[i].clear(); +} + +uint16 Hotspots::add(uint16 id, + uint16 left, uint16 top, uint16 right, uint16 bottom, + uint16 flags, uint16 key, + uint16 funcEnter, uint16 funcLeave, uint16 funcPos) { + + Hotspot hotspot(id, left, top, right, bottom, + flags, key, funcEnter, funcLeave, funcPos); + + return add(hotspot); +} + +uint16 Hotspots::add(const Hotspot &hotspot) { + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + // free space => add same id => update + if (! (spot.isEnd() || (spot.id == hotspot.id))) + continue; + + // When updating, keep disabled state intact + uint16 id = hotspot.id; + if ((spot.id & ~(kStateDisabled << 12)) == + (hotspot.id & ~(kStateDisabled << 12))) + id = spot.id; + + // Set + spot = hotspot; + spot.id = id; + + // Remember the current script + spot.script = _vm->_game->_script; + + debugC(1, kDebugHotspots, "Adding hotspot %03d: %3d+%3d+%3d+%3d - %04X, %04X, %04X - %5d, %5d, %5d", + i, spot.left, spot.top, spot.right, spot.bottom, + spot.id, spot.key, spot.flags, spot.funcEnter, spot.funcLeave, spot.funcPos); + + return i; + } + + error("Hotspots::add(): Hotspot array full"); + return 0xFFFF; +} + +void Hotspots::remove(uint16 id) { + for (int i = 0; i < kHotspotCount; i++) { + if (_hotspots[i].id == id) { + debugC(1, kDebugHotspots, "Removing hotspot %d: %X", i, id); + _hotspots[i].clear(); + } + } +} + +void Hotspots::removeState(uint8 state) { + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + if (spot.getState() == state) { + debugC(1, kDebugHotspots, "Removing hotspot %d: %X (by state %X)", i, spot.id, state); + spot.clear(); + } + } +} + +void Hotspots::recalculate(bool force) { + debugC(5, kDebugHotspots, "Recalculating hotspots"); + + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + if (!force && ((spot.flags & 0x80) != 0)) + // Not forcing a special hotspot + continue; + + if (spot.funcPos == 0) + // Simple coordinates don't need update + continue; + + // Setting the needed script + Script *curScript = _vm->_game->_script; + + _vm->_game->_script = spot.script; + if (!_vm->_game->_script) + _vm->_game->_script = curScript; + + // Calling the function that contains the positions + _vm->_game->_script->call(spot.funcPos); + + // Calculate positions + int16 left = _vm->_game->_script->readValExpr(); + int16 top = _vm->_game->_script->readValExpr(); + int16 width = _vm->_game->_script->readValExpr(); + int16 height = _vm->_game->_script->readValExpr(); + + // Re-read the flags too, if applicable + uint16 flags = 0; + if (spot.getState() == (kStateFilled | kStateType2)) + flags = _vm->_game->_script->readValExpr(); + + // Apply backDelta, if needed + if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != -1)) { + left += _vm->_draw->_backDeltaX; + top += _vm->_draw->_backDeltaY; + } + + // Clamping + if (left < 0) { + width += left; + left = 0; + } + if (top < 0) { + height += top; + top = 0; + } + + // Set the updated position + spot.left = left; + spot.top = top; + spot.right = left + width - 1; + spot.bottom = top + height - 1; + + if (spot.getState() == (kStateFilled | kStateType2)) + spot.flags = flags; + + // Return + _vm->_game->_script->pop(); + + _vm->_game->_script = curScript; + } +} + +void Hotspots::push(uint8 all, bool force) { + debugC(1, kDebugHotspots, "Pushing hotspots (%d, %d)", all, force); + + // Should we push at all? + if (!_shouldPush && !force) + return; + + // Count the hotspots + uint32 size = 0; + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + // Save all of them + if ( (all == 1) || + // Don't save the global ones + ((all == 0) && (spot.id >= 20)) || + // Only save disabled ones + ((all == 2) && ((spot.getState() == (kStateFilledDisabled | kStateType1)) || + (spot.getState() == (kStateDisabled)) || + (spot.getState() == (kStateFilledDisabled | kStateType2))))) { + size++; + } + + } + + StackEntry backup; + + backup.shouldPush = _shouldPush; + backup.size = size; + backup.key = _currentKey; + backup.id = _currentId; + backup.index = _currentIndex; + + backup.hotspots = new Hotspot[size]; + + // Copy the hotspots + Hotspot *destPtr = backup.hotspots; + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + Hotspot &spot = _hotspots[i]; + + // Save all of them + if ( (all == 1) || + // Don't save the global ones + ((all == 0) && (spot.id >= 20)) || + // Only save disabled ones + ((all == 2) && ((spot.getState() == (kStateFilledDisabled | kStateType1)) || + (spot.getState() == (kStateDisabled)) || + (spot.getState() == (kStateFilledDisabled | kStateType2))))) { + + memcpy(destPtr, &spot, sizeof(Hotspot)); + destPtr++; + + spot.clear(); + } + + } + + // Reset current state + _shouldPush = false; + _currentKey = 0; + _currentId = 0; + _currentIndex = 0; + + _stack.push(backup); +} + +void Hotspots::pop() { + debugC(1, kDebugHotspots, "Popping hotspots"); + + assert(!_stack.empty()); + + StackEntry backup = _stack.pop(); + + // Find the end of the filled hotspot space + int i; + Hotspot *destPtr = _hotspots; + for (i = 0; i < kHotspotCount; i++, destPtr++) + if (destPtr->isEnd()) + break; + + if (((uint32) (kHotspotCount - i)) < backup.size) + error("Hotspots::pop(): Not enough free space in the current Hotspot " + "array to pop %d elements (got %d)", backup.size, kHotspotCount - i); + + // Copy + memcpy(destPtr, backup.hotspots, backup.size * sizeof(Hotspot)); + + _shouldPush = backup.shouldPush; + _currentKey = backup.key; + _currentId = backup.id; + _currentIndex = backup.index; + + delete[] backup.hotspots; +} + +bool Hotspots::isValid(uint16 key, uint16 id, uint16 index) const { + if (index >= kHotspotCount) + return false; + + if (key == 0) + return false; + + if (!(Hotspot::getState(id) & kStateFilled)) + return false; + + return true; +} + +void Hotspots::call(uint16 offset) { + debugC(4, kDebugHotspots, "Calling hotspot function %d", offset); + + _vm->_game->_script->call(offset); + + _shouldPush = true; + + int16 stackSize = _stack.size(); + + _vm->_inter->funcBlock(0); + + while (stackSize != _stack.size()) + pop(); + + _shouldPush = false; + + _vm->_game->_script->pop(); + + recalculate(false); +} + +void Hotspots::enter(uint16 index) { + debugC(2, kDebugHotspots, "Entering hotspot %d", index); + + if (index >= kHotspotCount) { + warning("Hotspots::enter(): Index %d out of range", index); + return; + } + + Hotspot &spot = _hotspots[index]; + + // If requested, write the ID into a variable + if ((spot.getState() == (kStateFilled | kStateType1)) || + (spot.getState() == (kStateFilled | kStateType2))) + WRITE_VAR(17, -(spot.id & 0x0FFF)); + + if (spot.funcEnter != 0) + call(spot.funcEnter); +} + +void Hotspots::leave(uint16 index) { + debugC(2, kDebugHotspots, "Leaving hotspot %d", index); + + if (index >= kHotspotCount) { + warning("Hotspots::leave(): Index %d out of range", index); + return; + } + + Hotspot &spot = _hotspots[index]; + + // If requested, write the ID into a variable + if ((spot.getState() == (kStateFilled | kStateType1)) || + (spot.getState() == (kStateFilled | kStateType2))) + WRITE_VAR(17, spot.id & 0x0FFF); + + if (spot.funcLeave != 0) + call(spot.funcLeave); +} + +uint16 Hotspots::checkMouse(Type type, uint16 &id, uint16 &index) const { + id = 0; + index = 0; + + if (type == kTypeMove) { + // Check where the mouse was moved to + + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + const Hotspot &spot = _hotspots[i]; + + if (spot.isDisabled()) + // Only consider enabled hotspots + continue; + + if (spot.getType() > kTypeMove) + // Only consider click and move hotspots + continue; + + if (spot.getWindow() != 0) + // Only check the main window + continue; + + if (!spot.isIn(_vm->_global->_inter_mouseX, _vm->_global->_inter_mouseY)) + // If we're not in it, ignore it + continue; + + id = spot.id; + index = i; + + return spot.key; + } + + return 0; + + } else if (type == kTypeClick) { + // Check if something was clicked + + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + const Hotspot &spot = _hotspots[i]; + + if (spot.isDisabled()) + // Only consider enabled hotspots + continue; + + if (spot.getWindow() != 0) + // Only check the main window + continue; + + if (spot.getType() < kTypeMove) + // Only consider hotspots that can be clicked + continue; + + if (!spot.isIn(_vm->_global->_inter_mouseX, _vm->_global->_inter_mouseY)) + // If we're not in it, ignore it + continue; + + if (!spot.buttonMatch(_vm->_game->_mouseButtons)) + // Don't follow hotspots with button requirements we don't meet + continue; + + id = spot.id; + index = i; + + if ((spot.getType() == kTypeMove) || (spot.getType() == kTypeClick)) + // It's a move or click => return the key + return spot.key; + + // Otherwise, the key has a different meaning, so ignore it + return 0; + } + + if (_vm->_game->_mouseButtons != kMouseButtonsLeft) + // Let the right mouse button act as an escape key + return kKeyEscape; + + return 0; + + } + + return 0; +} + +bool Hotspots::checkHotspotChanged() { + uint16 key, id, index; + + // Get the current hotspot + key = checkMouse(kTypeMove, id, index); + + if (key == _currentKey) + // Nothing changed => nothing to do + return false; + + // Leave the old area + if (isValid(_currentKey, _currentId,_currentIndex)) + leave(_currentIndex); + + _currentKey = key; + _currentId = id; + _currentIndex = index; + + // Enter the new one + if (isValid(key, id, index)) + enter(index); + + return true; +} + +uint16 Hotspots::check(uint8 handleMouse, int16 delay, uint16 &id, uint16 &index) { + _vm->_game->_scrollHandleMouse = handleMouse != 0; + + if (delay >= -1) { + _currentKey = 0; + _currentId = 0; + _currentIndex = 0; + } + + id = 0; + index = 0; + + if (handleMouse) { + if ((_vm->_draw->_cursorIndex == -1) && (_currentKey == 0)) { + // Last know state: No hotspot hit. Look if that changed + + _currentKey = checkMouse(kTypeMove, _currentId, _currentIndex); + + if (isValid(_currentKey, _currentId, _currentIndex)) + enter(_currentIndex); + } + + _vm->_draw->animateCursor(-1); + } + + uint32 startTime = _vm->_util->getTimeKey(); + + // Update display + _vm->_draw->blitInvalidated(); + _vm->_video->waitRetrace(); + + uint16 key = 0; + while (key == 0) { + + if (_vm->_inter->_terminate || _vm->shouldQuit()) { + if (handleMouse) + _vm->_draw->blitCursor(); + return 0; + } + + // Anything changed? + checkHotspotChanged(); + + // Update display + if (!_vm->_draw->_noInvalidated) { + if (handleMouse) + _vm->_draw->animateCursor(-1); + else + _vm->_draw->blitInvalidated(); + _vm->_video->waitRetrace(); + } + + // Update keyboard and mouse state + key = _vm->_game->checkKeys(&_vm->_global->_inter_mouseX, + &_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons, handleMouse); + + if (!handleMouse && (_vm->_game->_mouseButtons != kMouseButtonsNone)) { + // We don't want any mouse input but got one => Wait till it went away + + _vm->_util->waitMouseRelease(0); + key = 3; + } + + if (key != 0) { + // Got a key press + + if (handleMouse & 1) + _vm->_draw->blitCursor(); + + id = 0; + index = 0; + + // Leave the current hotspot + if (isValid(_currentKey, _currentId, _currentIndex)) + leave(_currentIndex); + + _currentKey = 0; + break; + } + + if (handleMouse) { + + if (_vm->_game->_mouseButtons != kMouseButtonsNone) { + // Mouse button pressed + + if (delay > 0) { + // If a delay was requested, wait the specified time + + _vm->_draw->animateCursor(2); + _vm->_util->delay(delay); + } else if (handleMouse & 1) + _vm->_util->waitMouseRelease(1); + + _vm->_draw->animateCursor(-1); + + // Which region was clicked? + key = checkMouse(kTypeClick, id, index); + + if ((key != 0) || (id != 0)) { + // Got a valid region + + if ( (handleMouse & 1) && + ((delay <= 0) || (_vm->_game->_mouseButtons == kMouseButtonsNone))) + _vm->_draw->blitCursor(); + + // If the hotspot changed, leave the old one + if (key != _currentKey) + leave(_currentIndex); + + _currentKey = 0; + break; + } + + if (handleMouse & 4) + // Nothing further than one simple check was requested => return + return 0; + + // Leave the current area + if (_currentKey != 0) + leave(_currentIndex); + + // No click, but do we have a move event? If so, enter that hotspot + _currentKey = checkMouse(kTypeMove, _currentId, _currentIndex); + if (isValid(_currentKey, _currentId, _currentIndex)) + enter(_currentIndex); + + } else + // No mouse button pressed, check whether the position changed at least + checkHotspotChanged(); + } + + if ((delay == -2) && (key == 0) && + (_vm->_game->_mouseButtons == kMouseButtonsNone)) { + // Nothing found and no further handling requested. Return. + + id = 0; + index = 0; + break; + } + + if (handleMouse) + _vm->_draw->animateCursor(-1); + + if ((delay < 0) && (key == 0) && + (_vm->_game->_mouseButtons == kMouseButtonsNone)) { + + // Look if we've maybe reached the timeout + + uint32 curTime = _vm->_util->getTimeKey(); + if ((curTime + delay) > startTime) { + // If so, return + + id = 0; + index = 0; + break; + } + + } + + // Sleep for a short amount of time + _vm->_util->delay(10); + + } + + return key; +} + +uint16 Hotspots::check(uint8 handleMouse, int16 delay) { + uint16 id, index; + + // Check and ignore the id and index + return Hotspots::check(handleMouse, delay, id, index); +} + +uint16 Hotspots::updateInput(uint16 xPos, uint16 yPos, uint16 width, uint16 height, + uint16 backColor, uint16 frontColor, char *str, uint16 fontIndex, + Type type, int16 &duration, uint16 &id, uint16 &index) { + + if ((fontIndex >= Draw::kFontCount) || !_vm->_draw->_fonts[fontIndex]) { + warning("Hotspots::updateInput(): Invalid font specified: %d", fontIndex); + return 0; + } + + // Check if we need to consider mouse events + bool handleMouse = false; + if ( (_vm->_game->_handleMouse != 0) && + ((_vm->_global->_useMouse != 0) || (_vm->_game->_forceHandleMouse != 0))) + handleMouse = true; + + const Font &font = *_vm->_draw->_fonts[fontIndex]; + + // Current position in the string, preset to the end + uint32 pos = strlen(str); + /* Size of input field in characters. + * If the font is not monospaced, we can't know that */ + uint32 editSize = font.isMonospaced() ? (width / font.getCharWidth()) : 0; + + uint16 key = 0; + char tempStr[256]; + + while (1) { + // If we the edit field has enough space, add a space for the new character + strncpy0(tempStr, str, 254); + strcat(tempStr, " "); + if ((editSize != 0) && strlen(tempStr) > editSize) + strncpy0(tempStr, str, 255); + + // Clear input area + fillRect(xPos, yPos, + font.isMonospaced() ? (editSize * font.getCharWidth()) : width, height, + backColor); + + // Print the current string, vertically centered + printText(xPos, yPos + (height - font.getCharHeight()) / 2, + tempStr, fontIndex, frontColor); + + // If we've reached the end of the input field, set the cursor to the last character + if ((editSize != 0) && (pos == editSize)) + pos--; + + // The character under the cursor + char curSym = tempStr[pos]; + + if (_vm->_inter->_variables) + WRITE_VAR(56, pos); + + bool first = true; + while (1) { + tempStr[0] = curSym; + tempStr[1] = 0; + + // Draw cursor + uint16 cursorX, cursorY, cursorWidth, cursorHeight; + getTextCursorPos(font, str, pos, xPos, yPos, width, height, + cursorX, cursorY, cursorWidth, cursorHeight); + fillRect(cursorX, cursorY, cursorWidth, cursorHeight, frontColor); + + if (first) { + // The first time, purge old information too + key = check(handleMouse, -1, id, index); + + if (key == 0) + // We didn't catch any input, let's try again with a real timeout + key = check(handleMouse, -300, id, index); + + first = false; + } else + // Try to catch a character + key = check(handleMouse, -300, id, index); + + tempStr[0] = curSym; + tempStr[1] = 0; + + // Clear cursor + getTextCursorPos(font, str, pos, xPos, yPos, width, height, + cursorX, cursorY, cursorWidth, cursorHeight); + fillRect(cursorX, cursorY, cursorWidth, cursorHeight, backColor); + + // Print the current string, vertically centered + printText(cursorX, yPos + (height - font.getCharHeight()) / 2, + tempStr, fontIndex, frontColor); + + if ((key != 0) || (id != 0)) + // We did get a key, stop looking + break; + + // Try again + key = check(handleMouse, -300, id, index); + + if ((key != 0) || (id != 0) || + _vm->_inter->_terminate || _vm->shouldQuit()) + // We did get a key, stop looking + break; + + if (duration > 0) { + // Look if we reached the time limit + duration -= 600; + if (duration <= 1) { + // If so, abort + key = 0; + id = 0; + break; + } + } + } + + if ((key == 0) || (id != 0) || + _vm->_inter->_terminate || _vm->shouldQuit()) + // Got no key, or a region ID instead, return + return 0; + + switch (key) { + case kKeyRight: + // If possible, move the cursor right + if (((editSize != 0) && ((pos > strlen(str)) || (pos > (editSize - 1)))) || + ((editSize == 0) && (pos > strlen(str)))) { + pos++; + continue; + } + // Continue downwards instead + return kKeyDown; + + case kKeyLeft: + // If possible, move the cursor left + if (pos > 0) { + pos--; + continue; + } + // Continue upwards instead + return kKeyUp; + + case kKeyBackspace: + if (pos > 0) { + // Delete the character to the left + _vm->_util->cutFromStr(str, pos - 1, 1); + pos--; + continue; + } else { + if (pos < strlen(str)) + // Delete the character to the right + _vm->_util->cutFromStr(str, pos, 1); + } + + case kKeyDelete: + if (pos >= strlen(str)) + continue; + + // Delete the character to the right + _vm->_util->cutFromStr(str, pos, 1); + continue; + + case kKeyReturn: + case kKeyF1: + case kKeyF2: + case kKeyF3: + case kKeyF4: + case kKeyF5: + case kKeyF6: + case kKeyF7: + case kKeyF8: + case kKeyF9: + case kKeyF10: + case kKeyUp: + case kKeyDown: + return key; + + case kKeyEscape: + // If we got an escape event, wait until the mouse buttons have been released + if (_vm->_global->_useMouse != 0) + continue; + + _vm->_game->_forceHandleMouse = !_vm->_game->_forceHandleMouse; + + handleMouse = false; + if ( (_vm->_game->_handleMouse != 0) && + ((_vm->_global->_useMouse != 0) || (_vm->_game->_forceHandleMouse != 0))) + handleMouse = true; + + while (_vm->_global->_pressedKeys[1] != 0); + continue; + + default: + // Got a "normal" key + + uint16 savedKey = key; + + key &= 0xFF; + + if (((type == kTypeInputFloatNoLeave) || (type == kTypeInputFloatLeave)) && + (key >= ' ') && (key <= 0xFF)) { + + // Only allow character found in numerical floating values + + const char *str1 = "0123456789-.,+ "; + const char *str2 = "0123456789-,,+ "; + + if ((((savedKey >> 8) > 1) && ((savedKey >> 8) < 12)) && + ((_vm->_global->_pressedKeys[42] != 0) || + (_vm->_global->_pressedKeys[56] != 0))) + key = ((savedKey >> 8) - 1) % 10 + '0'; + + int i; + for (i = 0; str1[i] != 0; i++) { + if (key == str1[i]) { + key = str2[i]; + break; + } + } + + if (i == (int16) strlen(str1)) + key = 0; + } + + if ((key >= ' ') && (key <= 0xFF)) { + if (editSize == 0) { + // Length of the string + current character + next one + int length = _vm->_draw->stringLength(str, fontIndex) + + font.getCharWidth(' ') + font.getCharWidth(key); + + if (length > width) + // We're above the limit, ignore the key + continue; + + if (((int32) strlen(str)) >= (_vm->_global->_inter_animDataSize * 4 - 1)) + // Above the limit of character allowed in a string, ignore the key + continue; + + } else { + if (strlen(str) > editSize) + // We're over the upper character limit for this field + continue; + else if (editSize == strlen(str)) + // We've reached the upper limit, overwrite the last character + _vm->_util->cutFromStr(str, strlen(str) - 1, 1); + } + + // Advance cursor + pos++; + tempStr[0] = key; + tempStr[1] = 0; + + // Add character + _vm->_util->insertStr(tempStr, str, pos - 1); + } + + } + } +} + +uint16 Hotspots::handleInputs(int16 time, uint16 inputCount, uint16 &curInput, + InputDesc *inputs, uint16 &id, uint16 &index) { + + // Redraw all texts in all inputs we currently manage + updateAllTexts(inputs); + + for (int i = 0; i < 40; i++) + WRITE_VAR(17 + i, 0); + + while (1) { + // Find the hotspot index to our current input + uint16 hotspotIndex = inputToHotspot(curInput); + + assert(hotspotIndex != 0xFFFF); + + Hotspot inputSpot = _hotspots[hotspotIndex]; + + // Handle input events from that input field + uint16 key = updateInput(inputSpot.left, inputSpot.top, + inputSpot.right - inputSpot.left + 1, + inputSpot.bottom - inputSpot.top + 1, + inputs[curInput].backColor, inputs[curInput].frontColor, + GET_VARO_STR(inputSpot.key), inputs[curInput].fontIndex, + inputSpot.getType(), time, id, index); + + if (_vm->_inter->_terminate) + return 0; + + switch (key) { + case kKeyNone: + if (id == 0) + // No key and no hotspot => return + return 0; + + if (_vm->_game->_mouseButtons != kMouseButtonsNone) + // Clicked something, get the hotspot index + index = findClickedInput(index); + + if (!_hotspots[index].isInput()) + // It's no input, return + return 0; + + // Get the associated input index + curInput = hotspotToInput(index); + break; + + case kKeyF1: + case kKeyF2: + case kKeyF3: + case kKeyF4: + case kKeyF5: + case kKeyF6: + case kKeyF7: + case kKeyF8: + case kKeyF9: + case kKeyF10: + return key; + + case kKeyReturn: + // Just one input => return + if (inputCount == 1) + return kKeyReturn; + + // End of input chain reached => wrap + if (curInput == (inputCount - 1)) { + curInput = 0; + break; + } + + // Next input + curInput++; + break; + + case kKeyDown: + // Next input + if ((inputCount - 1) > curInput) + curInput++; + break; + + case kKeyUp: + // Previous input + if (curInput > 0) + curInput--; + break; + } + } +} + +void Hotspots::evaluateNew(uint16 i, uint16 *ids, InputDesc *inputs, + uint16 &inputId, bool &hasInput, uint16 &inputCount) { + + ids[i] = 0; + + // Type and window + byte type = _vm->_game->_script->readByte(); + byte window = 0; + + if ((type & 0x40) != 0) { + // Got a window ID + + type -= 0x40; + window = _vm->_game->_script->readByte(); + } + + // Coordinates + uint16 left, top, width, height, right, bottom; + uint32 funcPos = 0; + if ((type & 0x80) != 0) { + // Complex coordinate expressions + funcPos = _vm->_game->_script->pos(); + left = _vm->_game->_script->readValExpr(); + top = _vm->_game->_script->readValExpr(); + width = _vm->_game->_script->readValExpr(); + height = _vm->_game->_script->readValExpr(); + } else { + // Immediate values + funcPos = 0; + left = _vm->_game->_script->readUint16(); + top = _vm->_game->_script->readUint16(); + width = _vm->_game->_script->readUint16(); + height = _vm->_game->_script->readUint16(); + } + type &= 0x7F; + + // Apply global drawing offset + if ((_vm->_draw->_renderFlags & RENDERFLAG_CAPTUREPOP) && (left != 0xFFFF)) { + left += _vm->_draw->_backDeltaX; + top += _vm->_draw->_backDeltaY; + } + + right = left + width - 1; + bottom = top + height - 1; + + // Enabling the hotspots again + if ((type == kTypeEnable2) || (type == kTypeEnable1)) { + uint8 wantedState = 0; + if (type == kTypeEnable2) + wantedState = kStateFilledDisabled | kStateType2; + else + wantedState = kStateFilledDisabled | kStateType1; + + _vm->_game->_script->skip(6); + + for (int j = 0; j < kHotspotCount; j++) { + Hotspot &spot = _hotspots[j]; + + if (spot.getState() == wantedState) { + spot.enable(); + spot.funcEnter = _vm->_game->_script->pos(); + spot.funcLeave = _vm->_game->_script->pos(); + } + } + + _vm->_game->_script->skipBlock(); + + return; + } + + int16 key = 0; + int16 flags = 0; + Font *font = 0; + uint32 funcEnter = 0, funcLeave = 0; + + // Evaluate parameters for the new hotspot + switch (type) { + case kTypeNone: + _vm->_game->_script->skip(6); + + funcEnter = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + funcLeave = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + key = i + ((kStateFilled | kStateType2) << 12); + flags = type + (window << 8); + break; + + case kTypeMove: + key = _vm->_game->_script->readInt16(); + ids[i] = _vm->_game->_script->readInt16(); + flags = _vm->_game->_script->readInt16(); + + funcEnter = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + funcLeave = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + if (key == 0) + key = i + ((kStateFilled | kStateType2) << 12); + + flags = type + (window << 8) + (flags << 4); + break; + + case kTypeInput1NoLeave: + case kTypeInput1Leave: + case kTypeInput2NoLeave: + case kTypeInput2Leave: + case kTypeInput3NoLeave: + case kTypeInput3Leave: + case kTypeInputFloatNoLeave: + case kTypeInputFloatLeave: + hasInput = true; + + _vm->_util->clearKeyBuf(); + + // Input text parameters + key = _vm->_game->_script->readVarIndex(); + inputs[inputCount].fontIndex = _vm->_game->_script->readInt16(); + inputs[inputCount].backColor = _vm->_game->_script->readByte(); + inputs[inputCount].frontColor = _vm->_game->_script->readByte(); + inputs[inputCount].length = 0; + inputs[inputCount].str = 0; + + if ((type >= kTypeInput2NoLeave) && (type <= kTypeInput3Leave)) { + uint16 length = _vm->_game->_script->readUint16(); + + inputs[inputCount].str = + (const char *) (_vm->_game->_script->getData() + _vm->_game->_script->pos()); + + _vm->_game->_script->skip(length); + } + + if (left == 0xFFFF) { + if (!(type & 1)) + // No coordinates but a leave block => skip it + _vm->_game->_script->skipBlock(); + break; + } + + font = _vm->_draw->_fonts[inputs[inputCount].fontIndex]; + if (font->isMonospaced()) + right = left + width * font->getCharWidth() - 1; + + funcEnter = 0; + funcPos = 0; + funcLeave = 0; + if (!(type & 1)) { + // Got a leave + funcLeave = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + } + + flags = type; + + inputCount++; + break; + + case 20: + inputId = i; + // Fall through to case 2 + case kTypeClick: + key = _vm->_game->_script->readInt16(); + ids[i] = _vm->_game->_script->readInt16(); + flags = _vm->_game->_script->readInt16(); + + funcEnter = 0; + + funcLeave = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + flags = ((uint16) kTypeClick) + (window << 8) + (flags << 4); + break; + + case kTypeClickEnter: + key = _vm->_game->_script->readInt16(); + ids[i] = _vm->_game->_script->readInt16(); + flags = _vm->_game->_script->readInt16() & 3; + + funcEnter = _vm->_game->_script->pos(); + _vm->_game->_script->skipBlock(); + + funcLeave = 0; + + flags = ((uint16) kTypeClick) + (window << 8) + (flags << 4); + break; + } + + // Add the new hotspot + add(i | (kStateFilled << 12), left, top, right, bottom, + flags, key, funcEnter, funcLeave, funcPos); +} + +bool Hotspots::evaluateFind(uint16 key, int16 timeVal, const uint16 *ids, + uint16 hotspotIndex1, uint16 hotspotIndex2, uint16 endIndex, + int16 &duration, uint16 &id, uint16 &index, bool &finished) { + + if (id != 0) + // We already found a hotspot, nothing to do + return true; + + if (key != 0) { + // We've got a key + + // Find the hotspot with that key associated + findKey(key, id, index); + if (id != 0) + // Found it + return true; + + // Try it case insensitively + findKeyCaseInsensitive(key, id, index); + if (id != 0) + // Found it + return true; + + return false; + } + + if (duration != 0) { + // We've got a time duration + + if (hotspotIndex1 != 0) { + finished = + leaveNthPlain(hotspotIndex1, endIndex, timeVal, ids, id, index, duration); + } else if (hotspotIndex2 != 0) { + findNthPlain(hotspotIndex2, endIndex, id, index); + } else { + findNthPlain(0, 0, id, index); + + // Leave the current hotspot + if ((_currentKey != 0) && (_hotspots[_currentIndex].funcLeave != 0)) + call(_hotspots[_currentIndex].funcLeave); + + _currentKey = 0; + } + + if (id != 0) + return true; + + return false; + } + + return false; +} + +void Hotspots::evaluate() { + InputDesc inputs[20]; + uint16 ids[kHotspotCount]; + + // Push all local hotspots + push(0); + + // Find the current end of the hotspot block + uint16 endIndex = 0; + while (!_hotspots[endIndex].isEnd()) + endIndex++; + + _shouldPush = false; + + _vm->_game->_script->skip(1); + + // Number of new hotspots + byte count = _vm->_game->_script->readByte(); + + // Parameters of this block + _vm->_game->_handleMouse = _vm->_game->_script->peekByte(0); + int16 duration = _vm->_game->_script->peekByte(1); + byte hotspotIndex1 = _vm->_game->_script->peekByte(3); + byte hotspotIndex2 = _vm->_game->_script->peekByte(4); + bool needRecalculation = _vm->_game->_script->peekByte(5) != 0; + + // Seconds -> Milliseconds + duration *= 1000; + + if ((hotspotIndex1 != 0) || (hotspotIndex2 != 0)) { + duration /= 100; + if (_vm->_game->_script->peekByte(1) == 100) + duration = 2; + } + + int16 timeVal = duration; + + _vm->_game->_script->skip(6); + + setCurrentHotspot(0, 0); + + bool finishedDuration = false; + + uint16 id = 0; + uint16 inputId = 0xFFFF; + uint16 index = 0; + + bool hasInput = false; + uint16 inputCount = 0; + + // Adding new hotspots + for (uint16 i = 0; i < count; i++) + evaluateNew(i, ids, inputs, inputId, hasInput, inputCount); + + // Recalculate all hotspots if requested + if (needRecalculation) + recalculate(true); + + _vm->_game->_forceHandleMouse = 0; + _vm->_util->clearKeyBuf(); + + while ((id == 0) && !_vm->_inter->_terminate && !_vm->shouldQuit()) { + uint16 key = 0; + if (hasInput) { + // Input + + uint16 curInput = 0; + + key = handleInputs(duration, inputCount, curInput, inputs, id, index); + + // Notify the script of the current input index + WRITE_VAR(17 + 38, curInput); + if (key == kKeyReturn) { + // Return pressed, invoke input leave + findFirstInputLeave(id, inputId, index); + break; + } + } else + // Normal move or click check + key = check(_vm->_game->_handleMouse, -duration, id, index); + + key = convertSpecialKey(key); + + // Try to find a fitting hotspot + Hotspots::evaluateFind(key, timeVal, ids, hotspotIndex1, hotspotIndex2, endIndex, + duration, id, index, finishedDuration); + + if (finishedDuration) + break; + + if ((id == 0) || (_hotspots[index].funcLeave != 0)) + // We don't have a new ID, but haven't yet handled the leave function + continue; + + _vm->_inter->storeMouse(); + + setCurrentHotspot(ids, id); + + // Enter it + if (_hotspots[index].funcEnter != 0) + call(_hotspots[index].funcEnter); + + setCurrentHotspot(0, 0); + id = 0; + } + + if ((id & 0xFFF) == inputId) + matchInputStrings(inputs); + + if (_vm->_game->_handleMouse == 1) + _vm->_draw->blitCursor(); + + if (!_vm->_inter->_terminate && (!finishedDuration)) { + _vm->_game->_script->seek(_hotspots[index].funcLeave); + + _vm->_inter->storeMouse(); + if (getCurrentHotspot() == 0) { + // No hotspot currently handled, now we'll handle the newly found one + + setCurrentHotspot(ids, id); + } + } else + _vm->_game->_script->setFinished(true); + + for (int i = 0; i < count; i++) + // Remove all local hotspots + remove(i + (kStateFilled << 12)); + + for (int i = 0; i < kHotspotCount; i++) { + Hotspot &spot = _hotspots[i]; + + // Disable the ones still there + if ((spot.getState() == (kStateFilled | kStateType1)) || + (spot.getState() == (kStateFilled | kStateType2))) + spot.disable(); + } + +} + +int16 Hotspots::findCursor(uint16 x, uint16 y) const { + int16 cursor = 0; + + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + const Hotspot &spot = _hotspots[i]; + + if ((spot.getWindow() != 0) || spot.isDisabled()) + // Ignore disabled and non-main-windowed hotspots + continue; + + if (!spot.isIn(x, y)) + // We're not in that hotspot, ignore it + continue; + + if (spot.getCursor() == 0) { + // Hotspot doesn't itself specify a cursor... + if (spot.getType() >= kTypeInput1NoLeave) { + // ...but the type has a generic one + cursor = 3; + break; + } else if ((spot.getButton() != kMouseButtonsRight) && (cursor == 0)) + // ...but there's a generic "click" cursor + cursor = 1; + } else if (cursor == 0) + // Hotspot had an attached cursor index + cursor = spot.getCursor(); + } + + return cursor; +} + +uint16 Hotspots::inputToHotspot(uint16 input) const { + uint16 inputIndex = 0; + for (int i = 0; i < kHotspotCount; i++) { + const Hotspot &spot = _hotspots[i]; + + if (!spot.isActiveInput()) + // Not an active input + continue; + + if (inputIndex == input) + // We've found our input + return i; + + // Next one + inputIndex++; + } + + // None found + return 0xFFFF; +} + +uint16 Hotspots::hotspotToInput(uint16 hotspot) const { + uint16 input = 0; + + for (int i = 0; i < kHotspotCount; i++) { + const Hotspot &spot = _hotspots[i]; + + if (!spot.isActiveInput()) + // Not an active input + continue; + + if (i == hotspot) + // We've found our hotspot + break; + + // Next one + input++; + } + + return input; +} + +uint16 Hotspots::findClickedInput(uint16 index) const { + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + const Hotspot &spot = _hotspots[i]; + + if (spot.getWindow() != 0) + // Ignore other windows + continue; + + if (spot.isDisabled()) + // Ignore disabled hotspots + continue; + + if (!spot.isIn(_vm->_global->_inter_mouseX, _vm->_global->_inter_mouseY)) + // This one wasn't it + continue; + + if (spot.getCursor() != 0) + // This one specifies a cursor, so we don't want it + continue; + + if (!spot.isInput()) + // It's no input + continue; + + index = i; + break; + } + + return index; +} + +bool Hotspots::findFirstInputLeave(uint16 &id, uint16 &inputId, uint16 &index) const { + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + const Hotspot &spot = _hotspots[i]; + + if (!spot.isFilledEnabled()) + // Not filled or disabled + continue; + + if (!spot.isInputLeave()) + // Not an input with a leave function + continue; + + id = spot.id; + inputId = spot.id & 0x7FFF; + index = i; + return true; + } + + return false; +} + +bool Hotspots::findKey(uint16 key, uint16 &id, uint16 &index) const { + id = 0; + index = 0; + + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + const Hotspot &spot = _hotspots[i]; + + if (!spot.isFilledEnabled()) + // Not filled or disabled + continue; + + // Key match Catch all + if ((spot.key == key) || (spot.key == 0x7FFF)) { + id = spot.id; + index = i; + return true; + } + } + + return false; +} + +bool Hotspots::findKeyCaseInsensitive(uint16 key, uint16 &id, uint16 &index) const { + id = 0; + index = 0; + + for (int i = 0; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + const Hotspot &spot = _hotspots[i]; + + if (!spot.isFilledEnabled()) + // Not filled or disabled, ignore + continue; + + if ((spot.key & 0xFF00) != 0) + continue; + + if (spot.key == 0) + // No associated key, ignore + continue; + + // Compare + if (toupper(key & 0xFF) == toupper(spot.key)) { + id = spot.id; + index = i; + return true; + } + } + + return false; +} + +bool Hotspots::findNthPlain(uint16 n, uint16 startIndex, uint16 &id, uint16 &index) const { + id = 0; + index = 0; + + uint16 counter = 0; + for (int i = startIndex; (i < kHotspotCount) && !_hotspots[i].isEnd(); i++) { + const Hotspot &spot = _hotspots[i]; + + if (!spot.isFilledNew()) + // Not filled, ignore + continue; + + if (++counter != n) + // Not yet the one we want + continue; + + id = spot.id; + index = i; + return true; + } + + return false; +} + +bool Hotspots::leaveNthPlain(uint16 n, uint16 startIndex, int16 timeVal, const uint16 *ids, + uint16 &id, uint16 &index, int16 &duration) { + + id = 0; + index = 0; + + if (!findNthPlain(n, startIndex, id, index)) + // Doesn't exist + return false; + + _vm->_inter->storeMouse(); + + if (getCurrentHotspot() != 0) + // We already handle a hotspot + return false; + + setCurrentHotspot(ids, id); + + const Hotspot &spot = _hotspots[index]; + if (spot.funcLeave != 0) { + // It has a leave function + + uint32 startTime, callTime; + + // Call the leave and time it + startTime = _vm->_util->getTimeKey(); + call(spot.funcLeave); + callTime = _vm->_util->getTimeKey() - startTime; + + // Remove the time it took from the time we have available + duration = CLIP<int>(timeVal - callTime, 2, timeVal); + } + + if (getCurrentHotspot() == 0) { + id = 0; + index = 0; + } + + return getCurrentHotspot() != 0; +} + +void Hotspots::setCurrentHotspot(const uint16 *ids, uint16 id) const { + if (!ids) { + WRITE_VAR(16, 0); + return; + } + + if (Hotspot::getState(id) == kStateFilled) + WRITE_VAR(16, ids[id & 0xFFF]); + else + WRITE_VAR(16, id & 0xFFF); +} + +uint32 Hotspots::getCurrentHotspot() const { + return VAR(16); +} + +void Hotspots::cleanFloatString(const Hotspot &spot) const { + char *to, *from; + + to = from = GET_VARO_STR(spot.key); + for (int i = 0; (i < 257) && (*from != '\0'); i++, from++) { + char c = *from; + + // Skip spaces + if (c == ' ') + continue; + + // Convert decimal separator if necessary + if ((_vm->_global->_language == kLanguageBritish) && (c == '.')) + c = ','; + + *to++ = c; + } + + *to = '\0'; +} + +void Hotspots::checkStringMatch(const Hotspot &spot, const InputDesc &input, + uint16 inputPos) const { + + const char *str = input.str; + + char tempStr[256]; + char spotStr[256]; + + strncpy0(tempStr, GET_VARO_STR(spot.key), 255); + + if (spot.getType() < kTypeInput3NoLeave) + _vm->_util->cleanupStr(tempStr); + + uint16 pos = 0; + do { + strncpy0(spotStr, str, 255); + + pos += strlen(str) + 1; + str += strlen(str) + 1; + + if (spot.getType() < kTypeInput3NoLeave) + _vm->_util->cleanupStr(spotStr); + + // Compare the entered string with the string we wanted + if (strcmp(tempStr, spotStr) == 0) { + WRITE_VAR(17, VAR(17) + 1); + WRITE_VAR(17 + inputPos, 1); + break; + } + } while (input.length > pos); +} + +void Hotspots::matchInputStrings(const InputDesc *inputs) const { + uint16 strInputCount = 0; + uint16 inputIndex = 0; + uint16 inputPos = 1; + + for (int i = 0; i < kHotspotCount; i++) { + const Hotspot &spot = _hotspots[i]; + + // Looking for all enabled inputs + if (spot.isEnd()) + continue; + if (!spot.isFilledEnabled()) + continue; + if (!spot.isInput()) + continue; + + if (spot.getType() >= kTypeInputFloatNoLeave) + cleanFloatString(spot); + + if ((spot.getType() >= kTypeInput2NoLeave) && (spot.getType() <= kTypeInput3Leave)) { + + // Look if we find a match between the wanted and the typed string + checkStringMatch(spot, inputs[inputIndex], inputPos); + strInputCount++; + } else + WRITE_VAR(17 + inputPos, 2); + + inputIndex++; + inputPos++; + } + + // Notify the scripts if we reached the requested hotspot + WRITE_VAR(17, (uint32) (strInputCount == ((uint16) VAR(17)))); +} + +uint16 Hotspots::convertSpecialKey(uint16 key) const { + if (((key & 0xFF) >= ' ') && ((key & 0xFF) <= 0xFF) && + ((key >> 8) > 1) && ((key >> 8) < 12)) + key = '0' + (((key >> 8) - 1) % 10) + (key & 0xFF00); + + return key; +} + +void Hotspots::getTextCursorPos(const Font &font, const char *str, + uint32 pos, uint16 x, uint16 y, uint16 width, uint16 height, + uint16 &cursorX, uint16 &cursorY, uint16 &cursorWidth, uint16 &cursorHeight) const { + + if (!font.isMonospaced()) { + // Cursor to the right of the current character + + cursorX = x; + cursorY = y; + cursorWidth = 1; + cursorHeight = height; + + // Iterate through the string and add each character's width + for (uint32 i = 0; i < pos; i++) + cursorX += font.getCharWidth(str[i]); + + } else { + // Cursor underlining the current character + + cursorX = x + font.getCharWidth() * pos; + cursorY = y + height - 1; + cursorWidth = font.getCharWidth(); + cursorHeight = 1; + } +} + +void Hotspots::fillRect(uint16 x, uint16 y, uint16 width, uint16 height, uint16 color) const { + _vm->_draw->_destSurface = 21; + _vm->_draw->_destSpriteX = x; + _vm->_draw->_destSpriteY = y; + _vm->_draw->_spriteRight = width; + _vm->_draw->_spriteBottom = height; + _vm->_draw->_backColor = color; + + _vm->_draw->spriteOperation(DRAW_FILLRECT | 0x10 ); +} + +void Hotspots::printText(uint16 x, uint16 y, const char *str, uint16 fontIndex, uint16 color) const { + _vm->_draw->_destSpriteX = x; + _vm->_draw->_destSpriteY = y; + _vm->_draw->_frontColor = color; + _vm->_draw->_fontIndex = fontIndex; + _vm->_draw->_textToPrint = str; + _vm->_draw->_transparency = 1; + + _vm->_draw->spriteOperation(DRAW_PRINTTEXT | 0x10); +} + +void Hotspots::updateAllTexts(const InputDesc *inputs) const { + uint16 input = 0; + + for (int i = 0; i < kHotspotCount; i++) { + const Hotspot &spot = _hotspots[i]; + + if (spot.isEnd()) + // It's an end, we don't want it + continue; + + if (!spot.isFilledEnabled()) + // This one's either not used or disabled + continue; + + if (!spot.isInput()) + // Not an input + continue; + + // Get its text + char tempStr[256]; + strncpy0(tempStr, GET_VARO_STR(spot.key), 255); + + // Coordinates + uint16 x = spot.left; + uint16 y = spot.top; + uint16 width = spot.right - spot.left + 1; + uint16 height = spot.bottom - spot.top + 1; + // Clear the background + fillRect(x, y, width, height, inputs[input].backColor); + + // Center the text vertically + y += (height - _vm->_draw->_fonts[_vm->_draw->_fontIndex]->getCharHeight()) / 2; + + // Draw it + printText(x, y, tempStr, inputs[input].fontIndex, inputs[input].frontColor); + + input++; + } +} + +} // End of namespace Gob diff --git a/engines/gob/hotspots.h b/engines/gob/hotspots.h new file mode 100644 index 0000000000..a389987c27 --- /dev/null +++ b/engines/gob/hotspots.h @@ -0,0 +1,272 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GOB_HOTSPOTS_H +#define GOB_HOTSPOTS_H + +#include "common/stack.h" + +#include "gob/util.h" + +namespace Gob { + +class Font; +class Script; + +class Hotspots { +public: + static const int kHotspotCount = 250; + + enum Type { + kTypeNone = 0, + kTypeMove = 1, + kTypeClick = 2, + kTypeInput1NoLeave = 3, + kTypeInput1Leave = 4, + kTypeInput2NoLeave = 5, + kTypeInput2Leave = 6, + kTypeInput3NoLeave = 7, + kTypeInput3Leave = 8, + kTypeInputFloatNoLeave = 9, + kTypeInputFloatLeave = 10, + kTypeEnable2 = 11, + kTypeEnable1 = 12, + kTypeClickEnter = 21 + }; + + enum State { + kStateFilledDisabled = 0xC, + kStateFilled = 0x8, + kStateDisabled = 0x4, + kStateType2 = 0x2, + kStateType1 = 0x1 + }; + + Hotspots(GobEngine *vm); + ~Hotspots(); + + /** Remove all hotspots. */ + void clear(); + + /** Add a hotspot, returning the new index. */ + uint16 add(uint16 id, + uint16 left, uint16 top, uint16 right, uint16 bottom, + uint16 flags, uint16 key, + uint16 funcEnter, uint16 funcLeave, uint16 funcPos); + + /** Remove a specific hotspot. */ + void remove(uint16 id); + /** Remove all hotspots in this state. */ + void removeState(uint8 state); + + /** Push the current hotspots onto the stack. + * + * @param all 0: Don't push global ones; 1: Push all; 2: Push only the disabled ones + * @param force Force a push although _shouldPush is false + */ + void push(uint8 all, bool force = false); + /** Pop hotspots from the stack. */ + void pop(); + + /** Check the current hotspot. */ + uint16 check(uint8 handleMouse, int16 delay, uint16 &id, uint16 &index); + /** Check the current hotspot. */ + uint16 check(uint8 handleMouse, int16 delay); + + /** Evaluate hotspot changes. */ + void evaluate(); + + /** Return the cursor found in the hotspot to the coordinates. */ + int16 findCursor(uint16 x, uint16 y) const; + +private: + struct Hotspot { + uint16 id; + uint16 left; + uint16 top; + uint16 right; + uint16 bottom; + uint16 flags; + uint16 key; + uint16 funcEnter; + uint16 funcLeave; + uint16 funcPos; + Script *script; + + Hotspot(); + Hotspot(uint16 i, + uint16 l, uint16 t, uint16 r, uint16 b, uint16 f, uint16 k, + uint16 enter, uint16 leave, uint16 pos); + + void clear(); + + Type getType () const; + MouseButtons getButton() const; + uint8 getWindow() const; + uint8 getCursor() const; + uint8 getState () const; + + /** Is this hotspot the block end marker? */ + bool isEnd() const; + + bool isInput () const; + bool isActiveInput() const; + bool isInputLeave () const; + + bool isFilled () const; + bool isFilledEnabled() const; + bool isFilledNew () const; + bool isDisabled () const; + + /** Are the specified coordinates in the hotspot? */ + bool isIn(uint16 x, uint16 y) const; + /** Does the specified button trigger the hotspot? */ + bool buttonMatch(MouseButtons button) const; + + static uint8 getState(uint16 id); + + void disable(); + void enable (); + }; + + struct StackEntry { + bool shouldPush; + Hotspot *hotspots; + uint32 size; + uint32 key; + uint32 id; + uint32 index; + }; + + struct InputDesc { + uint16 fontIndex; + uint16 backColor; + uint16 frontColor; + uint16 length; + const char *str; + }; + + GobEngine *_vm; + + Hotspot *_hotspots; + Common::Stack<StackEntry> _stack; + + bool _shouldPush; + + uint16 _currentKey; + uint16 _currentIndex; + uint16 _currentId; + + /** Add a hotspot, returning the new index. */ + uint16 add(const Hotspot &hotspot); + + /** Recalculate all hotspot parameters + * + * @param force Force recalculation of all hotspots, including global ones. + */ + void recalculate(bool force); + + /** Is this a valid hotspot? */ + bool isValid(uint16 key, uint16 id, uint16 index) const; + + /** Call a hotspot subroutine. */ + void call(uint16 offset); + /** Handling hotspot enter events. */ + void enter(uint16 index); + /** Handling hotspot leave events. */ + void leave(uint16 index); + + /** Which hotspot is the mouse cursor currently at? */ + uint16 checkMouse(Type type, uint16 &id, uint16 &index) const; + + /** Did the current hotspot change in the meantime? */ + bool checkHotspotChanged(); + + /** Update events from a specific input. */ + uint16 updateInput(uint16 xPos, uint16 yPos, uint16 width, uint16 height, + uint16 backColor, uint16 frontColor, char *str, uint16 fontIndex, + Type type, int16 &duration, uint16 &id, uint16 &index); + + /** Handle all inputs we currently manage. */ + uint16 handleInputs(int16 time, uint16 inputCount, uint16 &curInput, + InputDesc *inputs, uint16 &id, uint16 &index); + + /** Evaluate adding new hotspots script commands. */ + void evaluateNew(uint16 i, uint16 *ids, InputDesc *inputs, + uint16 &inputId, bool &hasInput, uint16 &inputCount); + /** Find the hotspot requested by script commands. */ + bool evaluateFind(uint16 key, int16 timeVal, const uint16 *ids, + uint16 hotspotIndex1, uint16 hotspotIndex2, uint16 endIndex, + int16 &duration, uint16 &id, uint16 &index, bool &finished); + + // Finding specific hotspots + /** Find the hotspot index that corresponds to the input index. */ + uint16 inputToHotspot(uint16 input) const; + /** Find the input index that corresponds to the hotspot index. */ + uint16 hotspotToInput(uint16 hotspot) const; + /** Find the input that was clicked on. */ + uint16 findClickedInput(uint16 index) const; + /** Find the first input hotspot with a leave function. */ + bool findFirstInputLeave(uint16 &id, uint16 &inputId, uint16 &index) const; + /** Find the hotspot with the matching key, case sensitively. */ + bool findKey(uint16 key, uint16 &id, uint16 &index) const; + /** Find the hotspot with the matching key, case insensitively. */ + bool findKeyCaseInsensitive(uint16 key, uint16 &id, uint16 &index) const; + /** Find the nth plain (without Type1 or Type2 state) hotspot. */ + bool findNthPlain(uint16 n, uint16 startIndex, uint16 &id, uint16 &index) const; + + /** Leave the nth plain (without Type1 or Type2 state) hotspot. */ + bool leaveNthPlain(uint16 n, uint16 startIndex, int16 timeVal, const uint16 *ids, + uint16 &id, uint16 &index, int16 &duration); + + // Hotspot ID variable access + void setCurrentHotspot(const uint16 *ids, uint16 id) const; + uint32 getCurrentHotspot() const; + + // String input functions + void cleanFloatString(const Hotspot &spot) const; + void checkStringMatch(const Hotspot &spot, const InputDesc &input, + uint16 inputPos) const; + void matchInputStrings(const InputDesc *inputs) const; + + uint16 convertSpecialKey(uint16 key) const; + + /** Calculate the graphical cursor position. */ + void getTextCursorPos(const Font &font, const char *str, + uint32 pos, uint16 x, uint16 y, uint16 width, uint16 height, + uint16 &cursorX, uint16 &cursorY, uint16 &cursorWidth, uint16 &cursorHeight) const; + + /** Fill that rectangle with the color. */ + void fillRect(uint16 x, uint16 y, uint16 width, uint16 height, uint16 color) const; + /** Print the given text. */ + void printText(uint16 x, uint16 y, const char *str, uint16 fontIndex, uint16 color) const; + + /** Go through all inputs we manage and redraw their texts. */ + void updateAllTexts(const InputDesc *inputs) const; +}; + +} // End of namespace Gob + +#endif // GOB_HOTSPOTS_H diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp index f9a22f52fb..faf85a5b41 100644 --- a/engines/gob/init.cpp +++ b/engines/gob/init.cpp @@ -123,8 +123,7 @@ void Init::initGame() { if (!_vm->_dataIO->existData("intro.inf")) { for (int i = 0; i < 4; i++) - if (_vm->_dataIO->existData(_fontNames[i])) - _vm->_draw->_fonts[i] = _vm->_util->loadFont(_fontNames[i]); + _vm->_draw->loadFont(i, _fontNames[i]); } else { infBuf = _vm->_dataIO->getData("intro.inf"); @@ -140,8 +139,8 @@ void Init::initGame() { buffer[j] = 0; strcat(buffer, ".let"); - if (_vm->_dataIO->existData(buffer)) - _vm->_draw->_fonts[i] = _vm->_util->loadFont(buffer); + + _vm->_draw->loadFont(i, buffer); if ((infPtr + 1) >= infEnd) break; diff --git a/engines/gob/init.h b/engines/gob/init.h index a8d4b9833e..60642d0189 100644 --- a/engines/gob/init.h +++ b/engines/gob/init.h @@ -32,7 +32,7 @@ namespace Gob { class Init { public: - void initGame(); + virtual void initGame(); virtual void initVideo() = 0; @@ -72,6 +72,14 @@ public: virtual ~Init_v3() {} }; +class Init_v6 : public Init_v3 { +public: + virtual void initGame(); + + Init_v6(GobEngine *vm); + virtual ~Init_v6() {} +}; + } // End of namespace Gob #endif // GOB_INIT_H diff --git a/engines/gob/init_v6.cpp b/engines/gob/init_v6.cpp new file mode 100644 index 0000000000..4b14c8a29c --- /dev/null +++ b/engines/gob/init_v6.cpp @@ -0,0 +1,48 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/endian.h" + +#include "gob/gob.h" +#include "gob/init.h" +#include "gob/global.h" + +namespace Gob { + +Init_v6::Init_v6(GobEngine *vm) : Init_v3(vm) { +} + +void Init_v6::initGame() { + _vm->_global->_noCd = false; + + if (Common::File::exists("cd1.itk") && Common::File::exists("cd2.itk") && + Common::File::exists("cd3.itk") && Common::File::exists("cd4.itk")) { + _vm->_global->_noCd = true; + } + + Init::initGame(); +} + +} // End of namespace Gob diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp index 8be07034c6..afd215a00d 100644 --- a/engines/gob/inter.cpp +++ b/engines/gob/inter.cpp @@ -35,6 +35,7 @@ #include "gob/game.h" #include "gob/expression.h" #include "gob/script.h" +#include "gob/hotspots.h" #include "gob/scenery.h" #include "gob/sound/sound.h" @@ -180,7 +181,7 @@ void Inter::storeMouse() { WRITE_VAR(2, x); WRITE_VAR(3, y); - WRITE_VAR(4, _vm->_game->_mouseButtons); + WRITE_VAR(4, (uint32) _vm->_game->_mouseButtons); } void Inter::storeKey(int16 key) { @@ -189,20 +190,20 @@ void Inter::storeKey(int16 key) { storeMouse(); WRITE_VAR(1, _vm->_sound->blasterPlayingSound()); - if (key == 0x4800) - key = 0x0B; - else if (key == 0x5000) - key = 0x0A; - else if (key == 0x4D00) - key = 0x09; - else if (key == 0x4B00) - key = 0x08; - else if (key == 0x011B) - key = 0x1B; - else if (key == 0x0E08) - key = 0x19; - else if (key == 0x5300) - key = 0x1A; + if (key == kKeyUp) + key = kShortKeyUp; + else if (key == kKeyDown) + key = kShortKeyDown; + else if (key == kKeyRight) + key = kShortKeyRight; + else if (key == kKeyLeft) + key = kShortKeyLeft; + else if (key == kKeyEscape) + key = kShortKeyEscape; + else if (key == kKeyBackspace) + key = kShortKeyBackspace; + else if (key == kKeyDelete) + key = kShortKeyDelete; else if ((key & 0xFF) != 0) key &= 0xFF; @@ -334,7 +335,7 @@ void Inter::callSub(int16 retFlag) { if (block == 1) funcBlock(retFlag); else if (block == 2) - _vm->_game->collisionsBlock(); + _vm->_game->_hotspots->evaluate(); else error("Unknown block type %d in Inter::callSub()", block); } diff --git a/engines/gob/inter.h b/engines/gob/inter.h index d4ed2d3240..a31860885f 100644 --- a/engines/gob/inter.h +++ b/engines/gob/inter.h @@ -238,7 +238,7 @@ protected: bool o1_playComposition(OpFuncParams ¶ms); bool o1_getFreeMem(OpFuncParams ¶ms); bool o1_checkData(OpFuncParams ¶ms); - bool o1_prepareStr(OpFuncParams ¶ms); + bool o1_cleanupStr(OpFuncParams ¶ms); bool o1_insertStr(OpFuncParams ¶ms); bool o1_cutStr(OpFuncParams ¶ms); bool o1_strstr(OpFuncParams ¶ms); @@ -380,8 +380,8 @@ protected: bool o2_assign(OpFuncParams ¶ms); bool o2_printText(OpFuncParams ¶ms); bool o2_animPalInit(OpFuncParams ¶ms); - bool o2_addCollision(OpFuncParams ¶ms); - bool o2_freeCollision(OpFuncParams ¶ms); + bool o2_addHotspot(OpFuncParams ¶ms); + bool o2_removeHotspot(OpFuncParams ¶ms); bool o2_goblinFunc(OpFuncParams ¶ms); bool o2_stopSound(OpFuncParams ¶ms); bool o2_loadSound(OpFuncParams ¶ms); @@ -541,7 +541,7 @@ protected: bool o6_loadCursor(OpFuncParams ¶ms); bool o6_assign(OpFuncParams ¶ms); bool o6_palLoad(OpFuncParams ¶ms); - bool o6_freeCollision(OpFuncParams ¶ms); + bool o6_removeHotspot(OpFuncParams ¶ms); bool o6_fillRect(OpFuncParams ¶ms); void probe16bitMusic(char *fileName); diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp index 12079600c0..b955057bac 100644 --- a/engines/gob/inter_bargon.cpp +++ b/engines/gob/inter_bargon.cpp @@ -89,7 +89,7 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { int i; int16 mouseX; int16 mouseY; - int16 buttons; + MouseButtons buttons; SurfaceDescPtr surface; SoundDesc samples[4]; int16 comp[5] = { 0, 1, 2, 3, -1 }; @@ -107,13 +107,13 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { for (i = 320; i >= 0; i--) { _vm->_util->setScrollOffset(i, 0); _vm->_video->dirtyRectsAll(); - if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B) || + if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == kKeyEscape) || _vm->shouldQuit()) { _vm->_palAnim->fade(0, -2, 0); _vm->_video->clearSurf(*_vm->_draw->_frontSurface); memset((char *) _vm->_draw->_vgaPalette, 0, 768); WRITE_VAR(4, buttons); - WRITE_VAR(0, 0x11B); + WRITE_VAR(0, kKeyEscape); WRITE_VAR(57, (uint32) -1); break; } @@ -137,7 +137,7 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { int16 mouseX; int16 mouseY; - int16 buttons; + MouseButtons buttons; Video::Color *palBak; SoundDesc samples[2]; int16 comp[3] = { 0, 1, -1 }; @@ -158,14 +158,14 @@ void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); _vm->_util->longDelay(_vm->_util->getRandom(200)); } - if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B) || + if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == kKeyEscape) || _vm->shouldQuit()) { _vm->_sound->blasterStop(10); _vm->_palAnim->fade(0, -2, 0); _vm->_video->clearSurf(*_vm->_draw->_frontSurface); memset(_vm->_draw->_vgaPalette, 0, 768); WRITE_VAR(4, buttons); - WRITE_VAR(0, 0x11B); + WRITE_VAR(0, kKeyEscape); WRITE_VAR(57, (uint32) -1); break; } diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index d5d5fcad9a..69c392b198 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -37,6 +37,7 @@ #include "gob/expression.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/goblin.h" #include "gob/inter.h" #include "gob/map.h" @@ -147,7 +148,7 @@ void Inter_v1::setupOpcodesFunc() { OPCODEFUNC(0x3E, o1_getFreeMem); OPCODEFUNC(0x3F, o1_checkData); - OPCODEFUNC(0x41, o1_prepareStr); + OPCODEFUNC(0x41, o1_cleanupStr); OPCODEFUNC(0x42, o1_insertStr); OPCODEFUNC(0x43, o1_cutStr); @@ -867,7 +868,16 @@ bool Inter_v1::o1_loadSpriteToPos(OpFuncParams ¶ms) { _vm->_draw->_spriteLeft = _vm->_game->_script->readInt16(); _vm->_draw->_destSpriteX = _vm->_game->_script->readValExpr(); - _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); + + // WORKAROUND: The EGA version of Gobliiins 1 has an invalid expression there + if (_vm->isEGA() && (_vm->_game->_script->pos() == 1398) && + !scumm_stricmp(_vm->_game->_curTotFile, "intro.tot")) { + + _vm->_draw->_destSpriteY = 0; + _vm->_game->_script->skip(1); + + } else + _vm->_draw->_destSpriteY = _vm->_game->_script->readValExpr(); _vm->_draw->_transparency = _vm->_game->_script->peekByte() & 1; _vm->_draw->_destSurface = ((int16) (_vm->_game->_script->peekByte() >> 1)) - 1; @@ -1095,7 +1105,7 @@ bool Inter_v1::o1_palLoad(OpFuncParams ¶ms) { if (!resource) break; - memcpy((char *) _vm->_draw->_vgaPalette, resource->getData(), MIN(768, resource->getSize())); + memcpy((char *) _vm->_draw->_vgaPalette, resource->getData(), MIN<int>(768, resource->getSize())); delete resource; break; @@ -1173,7 +1183,7 @@ bool Inter_v1::o1_keyFunc(OpFuncParams ¶ms) { case 0: _vm->_draw->_showCursor &= ~2; _vm->_util->longDelay(1); - key = _vm->_game->checkCollisions(0, 0, 0, 0); + key = _vm->_game->_hotspots->check(0, 0); storeKey(key); _vm->_util->clearKeyBuf(); @@ -1601,11 +1611,11 @@ bool Inter_v1::o1_checkData(OpFuncParams ¶ms) { return false; } -bool Inter_v1::o1_prepareStr(OpFuncParams ¶ms) { +bool Inter_v1::o1_cleanupStr(OpFuncParams ¶ms) { int16 strVar; strVar = _vm->_game->_script->readVarIndex(); - _vm->_util->prepareStr(GET_VARO_FSTR(strVar)); + _vm->_util->cleanupStr(GET_VARO_FSTR(strVar)); return false; } @@ -1702,12 +1712,9 @@ bool Inter_v1::o1_loadFont(OpFuncParams ¶ms) { _vm->_game->_script->evalExpr(0); index = _vm->_game->_script->readInt16(); - delete _vm->_draw->_fonts[index]; - _vm->_draw->animateCursor(4); - _vm->_draw->_fonts[index] = - _vm->_util->loadFont(_vm->_game->_script->getResultStr()); + _vm->_draw->loadFont(index, _vm->_game->_script->getResultStr()); return false; } diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index 82822330b1..20f812bb88 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -39,6 +39,7 @@ #include "gob/expression.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/goblin.h" #include "gob/map.h" #include "gob/mult.h" @@ -121,8 +122,8 @@ void Inter_v2::setupOpcodesFunc() { OPCODEFUNC(0x17, o2_animPalInit); - OPCODEFUNC(0x18, o2_addCollision); - OPCODEFUNC(0x19, o2_freeCollision); + OPCODEFUNC(0x18, o2_addHotspot); + OPCODEFUNC(0x19, o2_removeHotspot); OPCODEFUNC(0x25, o2_goblinFunc); @@ -1176,67 +1177,51 @@ bool Inter_v2::o2_animPalInit(OpFuncParams ¶ms) { return false; } -bool Inter_v2::o2_addCollision(OpFuncParams ¶ms) { - int16 id; - int16 left, top, width, height; - int16 flags; - int16 key; - int16 funcSub; - - id = _vm->_game->_script->readValExpr(); - funcSub = _vm->_game->_script->pos(); - left = _vm->_game->_script->readValExpr(); - top = _vm->_game->_script->readValExpr(); - width = _vm->_game->_script->readValExpr(); - height = _vm->_game->_script->readValExpr(); - flags = _vm->_game->_script->readValExpr(); - key = _vm->_game->_script->readInt16(); +bool Inter_v2::o2_addHotspot(OpFuncParams ¶ms) { + int16 id = _vm->_game->_script->readValExpr(); + uint16 funcPos = _vm->_game->_script->pos(); + int16 left = _vm->_game->_script->readValExpr(); + int16 top = _vm->_game->_script->readValExpr(); + uint16 width = _vm->_game->_script->readValExpr(); + uint16 height = _vm->_game->_script->readValExpr(); + uint16 flags = _vm->_game->_script->readValExpr(); + uint16 key = _vm->_game->_script->readInt16(); if (key == 0) key = ABS(id) + 41960; - _vm->_draw->adjustCoords(0, &left, &top); - _vm->_draw->adjustCoords(2, &width, &height); - if (left < 0) { width += left; - left = 0; + left = 0; } if (top < 0) { height += top; - top = 0; + top = 0; } int16 index; if (id < 0) - index = _vm->_game->addNewCollision(0xD000 - id, left & 0xFFFC, top & 0xFFFC, - left + width + 3, top + height + 3, flags, key, 0, 0); + index = _vm->_game->_hotspots->add(0xD000 - id, left & 0xFFFC, top & 0xFFFC, + left + width + 3, top + height + 3, flags, key, 0, 0, funcPos); else - index = _vm->_game->addNewCollision(0xE000 + id, left, top, - left + width - 1, top + height - 1, flags, key, 0, 0); - - _vm->_game->_collisionAreas[index].funcSub = funcSub; + index = _vm->_game->_hotspots->add(0xE000 + id, left, top, + left + width - 1, top + height - 1, flags, key, 0, 0, funcPos); return false; } -bool Inter_v2::o2_freeCollision(OpFuncParams ¶ms) { - int16 id; +bool Inter_v2::o2_removeHotspot(OpFuncParams ¶ms) { + int16 id = _vm->_game->_script->readValExpr(); + uint8 stateType1 = Hotspots::kStateFilledDisabled | Hotspots::kStateType1; + uint8 stateType2 = Hotspots::kStateFilledDisabled | Hotspots::kStateType2; - id = _vm->_game->_script->readValExpr(); - if (id == -2) { - for (int i = 0; i < 150; i++) { - if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xD000) - _vm->_game->_collisionAreas[i].left = 0xFFFF; - } - } else if (id == -1) { - for (int i = 0; i < 150; i++) { - if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xE000) - _vm->_game->_collisionAreas[i].left = 0xFFFF; - } - } else - _vm->_game->freeCollision(0xE000 + id); + if (id == -2) + _vm->_game->_hotspots->removeState(stateType1); + else if (id == -1) + _vm->_game->_hotspots->removeState(stateType2); + else + _vm->_game->_hotspots->remove((stateType2 << 12) + id); return false; } diff --git a/engines/gob/inter_v5.cpp b/engines/gob/inter_v5.cpp index 1c20851c8d..986bad7cd3 100644 --- a/engines/gob/inter_v5.cpp +++ b/engines/gob/inter_v5.cpp @@ -266,9 +266,9 @@ void Inter_v5::o5_spaceShooter(OpGobParams ¶ms) { void Inter_v5::o5_getSystemCDSpeed(OpGobParams ¶ms) { WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% - Video::FontDesc *font; - if ((font = _vm->_util->loadFont("SPEED.LET"))) { - _vm->_draw->drawString("100 %", 402, 89, 112, 144, 0, *_vm->_draw->_backSurface, font); + Font *font; + if ((font = _vm->_draw->loadFont("SPEED.LET"))) { + _vm->_draw->drawString("100 %", 402, 89, 112, 144, 0, *_vm->_draw->_backSurface, *font); _vm->_draw->forceBlit(); delete font; @@ -278,9 +278,9 @@ void Inter_v5::o5_getSystemCDSpeed(OpGobParams ¶ms) { void Inter_v5::o5_getSystemRAM(OpGobParams ¶ms) { WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% - Video::FontDesc *font; - if ((font = _vm->_util->loadFont("SPEED.LET"))) { - _vm->_draw->drawString("100 %", 402, 168, 112, 144, 0, *_vm->_draw->_backSurface, font); + Font *font; + if ((font = _vm->_draw->loadFont("SPEED.LET"))) { + _vm->_draw->drawString("100 %", 402, 168, 112, 144, 0, *_vm->_draw->_backSurface, *font); _vm->_draw->forceBlit(); delete font; @@ -290,9 +290,9 @@ void Inter_v5::o5_getSystemRAM(OpGobParams ¶ms) { void Inter_v5::o5_getSystemCPUSpeed(OpGobParams ¶ms) { WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% - Video::FontDesc *font; - if ((font = _vm->_util->loadFont("SPEED.LET"))) { - _vm->_draw->drawString("100 %", 402, 248, 112, 144, 0, *_vm->_draw->_backSurface, font); + Font *font; + if ((font = _vm->_draw->loadFont("SPEED.LET"))) { + _vm->_draw->drawString("100 %", 402, 248, 112, 144, 0, *_vm->_draw->_backSurface, *font); _vm->_draw->forceBlit(); delete font; @@ -302,9 +302,9 @@ void Inter_v5::o5_getSystemCPUSpeed(OpGobParams ¶ms) { void Inter_v5::o5_getSystemDrawSpeed(OpGobParams ¶ms) { WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% - Video::FontDesc *font; - if ((font = _vm->_util->loadFont("SPEED.LET"))) { - _vm->_draw->drawString("100 %", 402, 326, 112, 144, 0, *_vm->_draw->_backSurface, font); + Font *font; + if ((font = _vm->_draw->loadFont("SPEED.LET"))) { + _vm->_draw->drawString("100 %", 402, 326, 112, 144, 0, *_vm->_draw->_backSurface, *font); _vm->_draw->forceBlit(); delete font; @@ -314,9 +314,9 @@ void Inter_v5::o5_getSystemDrawSpeed(OpGobParams ¶ms) { void Inter_v5::o5_totalSystemSpecs(OpGobParams ¶ms) { WRITE_VAR_UINT32(_vm->_game->_script->readInt16(), 100); // Fudging 100% - Video::FontDesc *font; - if ((font = _vm->_util->loadFont("SPEED.LET"))) { - _vm->_draw->drawString("100 %", 402, 405, 112, 144, 0, *_vm->_draw->_backSurface, font); + Font *font; + if ((font = _vm->_draw->loadFont("SPEED.LET"))) { + _vm->_draw->drawString("100 %", 402, 405, 112, 144, 0, *_vm->_draw->_backSurface, *font); _vm->_draw->forceBlit(); delete font; diff --git a/engines/gob/inter_v6.cpp b/engines/gob/inter_v6.cpp index 506de821d4..aa4721ff0a 100644 --- a/engines/gob/inter_v6.cpp +++ b/engines/gob/inter_v6.cpp @@ -31,10 +31,12 @@ #include "gob/inter.h" #include "gob/helper.h" #include "gob/global.h" +#include "gob/dataio.h" #include "gob/game.h" #include "gob/expression.h" #include "gob/script.h" #include "gob/resources.h" +#include "gob/hotspots.h" #include "gob/draw.h" #include "gob/sound/sound.h" #include "gob/videoplayer.h" @@ -64,7 +66,7 @@ void Inter_v6::setupOpcodesFunc() { OPCODEFUNC(0x03, o6_loadCursor); OPCODEFUNC(0x09, o6_assign); OPCODEFUNC(0x13, o6_palLoad); - OPCODEFUNC(0x19, o6_freeCollision); + OPCODEFUNC(0x19, o6_removeHotspot); OPCODEFUNC(0x33, o6_fillRect); } @@ -187,7 +189,7 @@ void Inter_v6::o6_openItk() { // (it checks CD1.ITK - CD4.ITK and the first that's found determines // the CD number), while its NO_CD modus wants everything in CD1.ITK. // So we just open the other ITKs, too. - if (_vm->_game->_noCd && !scumm_stricmp(fileName, "CD1.ITK")) { + if (_vm->_global->_noCd && !scumm_stricmp(fileName, "CD1.ITK")) { _vm->_dataIO->openDataFile("CD2.ITK", true); _vm->_dataIO->openDataFile("CD3.ITK", true); _vm->_dataIO->openDataFile("CD4.ITK", true); @@ -351,36 +353,33 @@ bool Inter_v6::o6_palLoad(OpFuncParams ¶ms) { return false; } -bool Inter_v6::o6_freeCollision(OpFuncParams ¶ms) { +bool Inter_v6::o6_removeHotspot(OpFuncParams ¶ms) { int16 id; + uint8 stateType1 = Hotspots::kStateFilledDisabled | Hotspots::kStateType1; + uint8 stateType2 = Hotspots::kStateFilledDisabled | Hotspots::kStateType2; + uint8 stateDisabled = Hotspots::kStateDisabled; id = _vm->_game->_script->readValExpr(); switch (id + 5) { case 0: - _vm->_game->pushCollisions(1); + _vm->_game->_hotspots->push(1); break; case 1: - _vm->_game->popCollisions(); + _vm->_game->_hotspots->pop(); break; case 2: - _vm->_game->pushCollisions(2); + _vm->_game->_hotspots->push(2); break; case 3: - for (int i = 0; i < 150; i++) { - if (((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xD000) || - ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0x4000)) - _vm->_game->_collisionAreas[i].left = 0xFFFF; - } + _vm->_game->_hotspots->removeState(stateType1); + _vm->_game->_hotspots->removeState(stateDisabled); break; case 4: - for (int i = 0; i < 150; i++) { - if ((_vm->_game->_collisionAreas[i].id & 0xF000) == 0xE000) - _vm->_game->_collisionAreas[i].left = 0xFFFF; - } + _vm->_game->_hotspots->removeState(stateType2); break; default: - _vm->_game->freeCollision(0xE000 + id); + _vm->_game->_hotspots->remove((stateType2 << 12) + id); break; } diff --git a/engines/gob/module.mk b/engines/gob/module.mk index 695976da61..611abb6038 100644 --- a/engines/gob/module.mk +++ b/engines/gob/module.mk @@ -11,10 +11,6 @@ MODULE_OBJS := \ driver_vga.o \ expression.o \ game.o \ - game_v1.o \ - game_v2.o \ - game_v6.o \ - game_fascin.o \ global.o \ gob.o \ goblin.o \ @@ -22,11 +18,12 @@ MODULE_OBJS := \ goblin_v2.o \ goblin_v3.o \ goblin_v4.o \ - videoplayer.o \ + hotspots.o \ init.o \ init_v1.o \ init_v2.o \ init_v3.o \ + init_v6.o \ inter.o \ inter_v1.o \ inter_v2.o \ @@ -56,6 +53,7 @@ MODULE_OBJS := \ video_v1.o \ video_v2.o \ video_v6.o \ + videoplayer.o \ demos/demoplayer.o \ demos/scnplayer.o \ demos/batplayer.o \ @@ -66,6 +64,7 @@ MODULE_OBJS := \ save/saveload_v3.o \ save/saveload_v4.o \ save/saveload_v6.o \ + save/saveload_playtoons.o \ save/saveconverter.o \ save/saveconverter_v2.o \ save/saveconverter_v3.o \ diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp index 5aec5ff76e..d383d955c7 100644 --- a/engines/gob/mult.cpp +++ b/engines/gob/mult.cpp @@ -204,7 +204,7 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape, stop = false; _vm->_util->processInput(); - if (checkEscape && (_vm->_util->checkKey() == 0x11B)) + if (checkEscape && (_vm->_util->checkKey() == kKeyEscape)) stop = true; _frame++; diff --git a/engines/gob/resources.cpp b/engines/gob/resources.cpp index 20427e547b..c52b65f0d7 100644 --- a/engines/gob/resources.cpp +++ b/engines/gob/resources.cpp @@ -158,29 +158,29 @@ bool Resources::load(const Common::String &fileName) { _extFile = fileBase + ".ext"; - if (!loadTOTResourceTable()) { - unload(); - return false; - } + bool hasTOTRes = loadTOTResourceTable(); + bool hasEXTRes = loadEXTResourceTable(); - if (!loadEXTResourceTable()) { - unload(); + if (!hasTOTRes && !hasEXTRes) return false; - } - if (!loadTOTTextTable(fileBase)) { - unload(); - return false; - } + if (hasTOTRes) { + if (!loadTOTTextTable(fileBase)) { + unload(); + return false; + } - if (!loadIMFile()) { - unload(); - return false; + if (!loadIMFile()) { + unload(); + return false; + } } - if (!loadEXFile()) { - unload(); - return false; + if (hasEXTRes) { + if (!loadEXFile()) { + unload(); + return false; + } } return true; @@ -255,7 +255,7 @@ bool Resources::loadTOTResourceTable() { TOTResourceItem &item = _totResourceTable->items[i]; item.offset = stream->readSint32LE(); - item.size = stream->readSint16LE(); + item.size = stream->readUint16LE(); item.width = stream->readSint16LE(); item.height = stream->readSint16LE(); @@ -286,7 +286,7 @@ bool Resources::loadEXTResourceTable() { DataStream *stream = _vm->_dataIO->getDataStream(_extFile.c_str()); if (!stream) - return true; + return false; _extResourceTable->itemsCount = stream->readSint16LE(); _extResourceTable->unknown = stream->readByte(); @@ -588,15 +588,22 @@ Resource *Resources::getTOTResource(uint16 id) const { if (totItem.type == kResourceTOT) data = getTOTData(totItem); - if (!data) + if (!data) { + warning("Failed to load TOT resource (%s, %d/%d, %d)", + _totFile.c_str(), id, _totResourceTable->itemsCount - 1, totItem.type); return 0; + } return new Resource(data, totItem.size, false, totItem.width, totItem.height); } Resource *Resources::getEXTResource(uint16 id) const { - if (!_extResourceTable || (id > _extResourceTable->itemsCount)) + if (!_extResourceTable || (id > _extResourceTable->itemsCount)) { + warning("Trying to load non-existent EXT resource (%s, %d/%d)", + _totFile.c_str(), id, + _extResourceTable ? (_extResourceTable->itemsCount - 1) : -1); return 0; + } EXTResourceItem &extItem = _extResourceTable->items[id]; @@ -617,8 +624,11 @@ Resource *Resources::getEXTResource(uint16 id) const { if (extItem.type == kResourceEX) data = getEXData(extItem, size); - if (!data) + if (!data) { + warning("Failed to load EXT resource (%s, %d/%d, %d)", + _totFile.c_str(), id, _extResourceTable->itemsCount - 1, extItem.type); return 0; + } if (extItem.packed) { byte *packedData = data; @@ -635,7 +645,7 @@ Resource *Resources::getEXTResource(uint16 id) const { } byte *Resources::getTOTData(TOTResourceItem &totItem) const { - if (totItem.size < 0) + if (totItem.size == 0) return 0; int32 offset = _totResourceTable->dataOffset + totItem.offset - _totResStart; @@ -647,7 +657,7 @@ byte *Resources::getTOTData(TOTResourceItem &totItem) const { } byte *Resources::getIMData(TOTResourceItem &totItem) const { - if (totItem.size < 0) + if (totItem.size == 0) return 0; int32 indexOffset = totItem.index * 4; diff --git a/engines/gob/resources.h b/engines/gob/resources.h index 80acef645c..d316be83e5 100644 --- a/engines/gob/resources.h +++ b/engines/gob/resources.h @@ -109,7 +109,7 @@ private: struct TOTResourceItem { ResourceType type; - int16 size; + uint16 size; int16 width; int16 height; union { diff --git a/engines/gob/save/saveload.h b/engines/gob/save/saveload.h index a74b64b883..8d785c7233 100644 --- a/engines/gob/save/saveload.h +++ b/engines/gob/save/saveload.h @@ -445,6 +445,32 @@ protected: SaveFile *getSaveFile(const char *fileName); }; +/** Save/Load class for Playtoons. */ +/** Only used for the moment to check file presence */ + +class SaveLoad_Playtoons : public SaveLoad { +public: + SaveLoad_Playtoons(GobEngine *vm); + virtual ~SaveLoad_Playtoons(); + +protected: + struct SaveFile { + const char *sourceName; + SaveMode mode; + SaveHandler *handler; + const char *description; + }; + + static SaveFile _saveFiles[]; + + SaveMode getSaveMode(const char *fileName) const; + + const SaveFile *getSaveFile(const char *fileName) const; + + SaveFile *getSaveFile(const char *fileName); + +}; + } // End of namespace Gob #endif // GOB_SAVE_SAVELOAD_H diff --git a/engines/gob/save/saveload_playtoons.cpp b/engines/gob/save/saveload_playtoons.cpp new file mode 100644 index 0000000000..97da909e7c --- /dev/null +++ b/engines/gob/save/saveload_playtoons.cpp @@ -0,0 +1,88 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "gob/save/saveload.h" +#include "gob/inter.h" +#include "gob/variables.h" + +namespace Gob { + +SaveLoad_Playtoons::SaveFile SaveLoad_Playtoons::_saveFiles[] = { + { "disk.001", kSaveModeExists, 0, 0}, // Playtoons 1 identification file + { "disk.002", kSaveModeExists, 0, 0}, // Playtoons 2 identification file + { "disk.003", kSaveModeExists, 0, 0}, // Playtoons 3 identification file + { "disk.004", kSaveModeExists, 0, 0}, // Playtoons 4 identification file + { "disk.005", kSaveModeExists, 0, 0}, // Playtoons 5 identification file + { "disk.006", kSaveModeExists, 0, 0}, // Playtoons CK 1 identification file + { "disk.007", kSaveModeExists, 0, 0}, // Playtoons CK 2 identification file + { "disk.008", kSaveModeExists, 0, 0}, // Playtoons CK 3 identification file + { "titre.001", kSaveModeExists, 0, 0}, // Playtoons 1 titles + { "titre.002", kSaveModeExists, 0, 0}, // Playtoons 2 titles + { "titre.003", kSaveModeExists, 0, 0}, // Playtoons 3 titles + { "titre.004", kSaveModeExists, 0, 0}, // Playtoons 4 titles + { "titre.005", kSaveModeExists, 0, 0}, // Playtoons 5 titles + { "titre.006", kSaveModeExists, 0, 0}, // Playtoons CK 1 empty title (???) + { "titre.007", kSaveModeExists, 0, 0}, // Playtoons CK 2 empty title (???) + { "titre.008", kSaveModeExists, 0, 0}, // Playtoons CK 3 empty title (???) + { "mdo.def", kSaveModeExists, 0, 0}, +}; + +SaveLoad::SaveMode SaveLoad_Playtoons::getSaveMode(const char *fileName) const { + const SaveFile *saveFile = getSaveFile(fileName); + + if (saveFile) + return saveFile->mode; + + return kSaveModeNone; +} + +SaveLoad_Playtoons::SaveLoad_Playtoons(GobEngine *vm) : + SaveLoad(vm) { +} + +SaveLoad_Playtoons::~SaveLoad_Playtoons() { +} + +const SaveLoad_Playtoons::SaveFile *SaveLoad_Playtoons::getSaveFile(const char *fileName) const { + fileName = stripPath(fileName); + + for (int i = 0; i < ARRAYSIZE(_saveFiles); i++) + if (!scumm_stricmp(fileName, _saveFiles[i].sourceName)) + return &_saveFiles[i]; + + return 0; +} + +SaveLoad_Playtoons::SaveFile *SaveLoad_Playtoons::getSaveFile(const char *fileName) { + fileName = stripPath(fileName); + + for (int i = 0; i < ARRAYSIZE(_saveFiles); i++) + if (!scumm_stricmp(fileName, _saveFiles[i].sourceName)) + return &_saveFiles[i]; + + return 0; +} + +} // End of namespace Gob diff --git a/engines/gob/script.cpp b/engines/gob/script.cpp index 6162e943bf..38b1f8fa40 100644 --- a/engines/gob/script.cpp +++ b/engines/gob/script.cpp @@ -127,6 +127,10 @@ bool Script::skip(int32 offset) { return seek(offset, SEEK_CUR); } +bool Script::skipBlock() { + return seek(peekUint16(2) + 2, SEEK_CUR); +} + int32 Script::getOffset(byte *ptr) const { if (!_totData) return -1; diff --git a/engines/gob/script.h b/engines/gob/script.h index 64a04503b1..84daeaf1af 100644 --- a/engines/gob/script.h +++ b/engines/gob/script.h @@ -53,6 +53,7 @@ public: // Stream seeking bool seek(int32 offset, int whence = SEEK_SET); bool skip(int32 offset); + bool skipBlock(); // Reading data byte readByte (); diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp index d3afc9baa3..2d7ba02385 100644 --- a/engines/gob/sound/sound.cpp +++ b/engines/gob/sound/sound.cpp @@ -506,7 +506,7 @@ void Sound::blasterWaitEndPlay(bool interruptible, bool stopComp) { _blaster->endComposition(); while (_blaster->isPlaying() && !_vm->shouldQuit()) { - if (interruptible && (_vm->_util->checkKey() == 0x11B)) { + if (interruptible && (_vm->_util->checkKey() == kKeyEscape)) { WRITE_VAR(57, (uint32) -1); return; } diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp index b0e7691c07..356eb3c643 100644 --- a/engines/gob/util.cpp +++ b/engines/gob/util.cpp @@ -38,14 +38,14 @@ namespace Gob { Util::Util(GobEngine *vm) : _vm(vm) { - _mouseButtons = 0; - _keyBufferHead = 0; - _keyBufferTail = 0; - _fastMode = 0; - _frameRate = 12; - _frameWaitTime = 0; + _mouseButtons = kMouseButtonsNone, + _keyBufferHead = 0; + _keyBufferTail = 0; + _fastMode = 0; + _frameRate = 12; + _frameWaitTime = 0; _startFrameTime = 0; - _frameWaitLag = 0; + _frameWaitLag = 0; } uint32 Util::getTimeKey(void) { @@ -85,7 +85,7 @@ void Util::longDelay(uint16 msecs) { } void Util::initInput(void) { - _mouseButtons = 0; + _mouseButtons = kMouseButtonsNone; _keyBufferHead = _keyBufferTail = 0; } @@ -103,16 +103,16 @@ void Util::processInput(bool scroll) { y = event.mouse.y; break; case Common::EVENT_LBUTTONDOWN: - _mouseButtons |= 1; + _mouseButtons = (MouseButtons) (((uint32) _mouseButtons) | ((uint32) kMouseButtonsLeft)); break; case Common::EVENT_RBUTTONDOWN: - _mouseButtons |= 2; + _mouseButtons = (MouseButtons) (((uint32) _mouseButtons) | ((uint32) kMouseButtonsRight)); break; case Common::EVENT_LBUTTONUP: - _mouseButtons &= ~1; + _mouseButtons = (MouseButtons) (((uint32) _mouseButtons) & ~((uint32) kMouseButtonsLeft)); break; case Common::EVENT_RBUTTONUP: - _mouseButtons &= ~2; + _mouseButtons = (MouseButtons) (((uint32) _mouseButtons) & ~((uint32) kMouseButtonsRight)); break; case Common::EVENT_KEYDOWN: if (event.kbd.flags == Common::KBD_CTRL) { @@ -179,26 +179,26 @@ int16 Util::translateKey(const Common::KeyState &key) { int16 from; int16 to; } keys[] = { - {Common::KEYCODE_INVALID, 0x0000}, - {Common::KEYCODE_BACKSPACE, 0x0E08}, - {Common::KEYCODE_SPACE, 0x3920}, - {Common::KEYCODE_RETURN, 0x1C0D}, - {Common::KEYCODE_ESCAPE, 0x011B}, - {Common::KEYCODE_DELETE, 0x5300}, - {Common::KEYCODE_UP, 0x4800}, - {Common::KEYCODE_DOWN, 0x5000}, - {Common::KEYCODE_RIGHT, 0x4D00}, - {Common::KEYCODE_LEFT, 0x4B00}, - {Common::KEYCODE_F1, 0x3B00}, - {Common::KEYCODE_F2, 0x3C00}, - {Common::KEYCODE_F3, 0x3D00}, - {Common::KEYCODE_F4, 0x3E00}, - {Common::KEYCODE_F5, 0x011B}, - {Common::KEYCODE_F6, 0x4000}, - {Common::KEYCODE_F7, 0x4100}, - {Common::KEYCODE_F8, 0x4200}, - {Common::KEYCODE_F9, 0x4300}, - {Common::KEYCODE_F10, 0x4400} + {Common::KEYCODE_INVALID, kKeyNone }, + {Common::KEYCODE_BACKSPACE, kKeyBackspace}, + {Common::KEYCODE_SPACE, kKeySpace }, + {Common::KEYCODE_RETURN, kKeyReturn }, + {Common::KEYCODE_ESCAPE, kKeyEscape }, + {Common::KEYCODE_DELETE, kKeyDelete }, + {Common::KEYCODE_UP, kKeyUp }, + {Common::KEYCODE_DOWN, kKeyDown }, + {Common::KEYCODE_RIGHT, kKeyRight }, + {Common::KEYCODE_LEFT, kKeyLeft }, + {Common::KEYCODE_F1, kKeyF1 }, + {Common::KEYCODE_F2, kKeyF2 }, + {Common::KEYCODE_F3, kKeyF3 }, + {Common::KEYCODE_F4, kKeyF4 }, + {Common::KEYCODE_F5, kKeyEscape }, + {Common::KEYCODE_F6, kKeyF6 }, + {Common::KEYCODE_F7, kKeyF7 }, + {Common::KEYCODE_F8, kKeyF8 }, + {Common::KEYCODE_F9, kKeyF9 }, + {Common::KEYCODE_F10, kKeyF10 } }; for (int i = 0; i < ARRAYSIZE(keys); i++) @@ -246,7 +246,7 @@ bool Util::checkKey(int16 &key) { return true; } -void Util::getMouseState(int16 *pX, int16 *pY, int16 *pButtons) { +void Util::getMouseState(int16 *pX, int16 *pY, MouseButtons *pButtons) { Common::Point mouse = g_system->getEventManager()->getMousePos(); *pX = mouse.x + _vm->_video->_scrollOffsetX - _vm->_video->_screenDeltaX; *pY = mouse.y + _vm->_video->_scrollOffsetY - _vm->_video->_screenDeltaY; @@ -264,15 +264,15 @@ void Util::setMousePos(int16 x, int16 y) { void Util::waitMouseUp(void) { do { processInput(); - if (_mouseButtons != 0) + if (_mouseButtons != kMouseButtonsNone) delay(10); - } while (_mouseButtons != 0); + } while (_mouseButtons != kMouseButtonsNone); } void Util::waitMouseDown(void) { int16 x; int16 y; - int16 buttons; + MouseButtons buttons; do { processInput(); @@ -283,7 +283,7 @@ void Util::waitMouseDown(void) { } void Util::waitMouseRelease(char drawMouse) { - int16 buttons; + MouseButtons buttons; int16 mouseX; int16 mouseY; @@ -300,8 +300,8 @@ void Util::forceMouseUp(bool onlyWhenSynced) { if (onlyWhenSynced && (_vm->_game->_mouseButtons != _mouseButtons)) return; - _vm->_game->_mouseButtons = 0; - _mouseButtons = 0; + _vm->_game->_mouseButtons = kMouseButtonsNone; + _mouseButtons = kMouseButtonsNone; } void Util::clearPalette(void) { @@ -379,38 +379,6 @@ void Util::setScrollOffset(int16 x, int16 y) { _vm->_video->waitRetrace(); } -Video::FontDesc *Util::loadFont(const char *path) { - Video::FontDesc *fontDesc = new Video::FontDesc; - byte *data; - - if (!fontDesc) - return 0; - - data = _vm->_dataIO->getData(path); - if (!data) { - delete fontDesc; - return 0; - } - - fontDesc->dataPtr = data + 4; - fontDesc->itemWidth = data[0] & 0x7F; - fontDesc->itemHeight = data[1]; - fontDesc->startItem = data[2]; - fontDesc->endItem = data[3]; - - fontDesc->itemSize = - ((fontDesc->itemWidth - 1) / 8 + 1) * fontDesc->itemHeight; - fontDesc->bitWidth = fontDesc->itemWidth; - - if (data[0] & 0x80) - fontDesc->extraData = data + 4 + fontDesc->itemSize * - (fontDesc->endItem - fontDesc->startItem + 1); - else - fontDesc->extraData = 0; - - return fontDesc; -} - void Util::insertStr(const char *str1, char *str2, int16 pos) { int len1 = strlen(str1); int len2 = strlen(str2); @@ -452,7 +420,7 @@ static const char trStr2[] = " "; static const char trStr3[] = " "; -void Util::prepareStr(char *str) { +void Util::cleanupStr(char *str) { char *start, *end; char buf[300]; @@ -460,17 +428,20 @@ void Util::prepareStr(char *str) { strcat(buf, trStr2); strcat(buf, trStr3); + // Translating "wrong" characters for (size_t i = 0; i < strlen(str); i++) - str[i] = buf[str[i] - 32]; + str[i] = buf[MIN<int>(str[i] - 32, 32)]; + // Trim spaces left while (str[0] == ' ') cutFromStr(str, 0, 1); + // Trim spaces right while ((strlen(str) > 0) && (str[strlen(str) - 1] == ' ')) cutFromStr(str, strlen(str) - 1, 1); + // Merge double spaces start = strchr(str, ' '); - while (start) { if (start[1] == ' ') { cutFromStr(str, start - str, 1); diff --git a/engines/gob/util.h b/engines/gob/util.h index 0a76ee40ab..82e2df94de 100644 --- a/engines/gob/util.h +++ b/engines/gob/util.h @@ -28,12 +28,53 @@ #include "common/keyboard.h" -#include "gob/video.h" - namespace Gob { +class GobEngine; + #define KEYBUFSIZE 16 +enum MouseButtons { + kMouseButtonsNone = 0, + kMouseButtonsLeft = 1, + kMouseButtonsRight = 2, + kMouseButtonsBoth = 3, + kMouseButtonsAny = 4 +}; + +enum Keys { + kKeyNone = 0x0000, + kKeyBackspace = 0x0E08, + kKeySpace = 0x3920, + kKeyReturn = 0x1C0D, + kKeyEscape = 0x011B, + kKeyDelete = 0x5300, + kKeyUp = 0x4800, + kKeyDown = 0x5000, + kKeyRight = 0x4D00, + kKeyLeft = 0x4B00, + kKeyF1 = 0x3B00, + kKeyF2 = 0x3C00, + kKeyF3 = 0x3D00, + kKeyF4 = 0x3E00, + kKeyF5 = 0x3F00, + kKeyF6 = 0x4000, + kKeyF7 = 0x4100, + kKeyF8 = 0x4200, + kKeyF9 = 0x4300, + kKeyF10 = 0x4400 +}; + +enum ShortKey { + kShortKeyUp = 0x0B, + kShortKeyDown = 0x0A, + kShortKeyRight = 0x09, + kShortKeyLeft = 0x08, + kShortKeyEscape = 0x1B, + kShortKeyBackspace = 0x19, + kShortKeyDelete = 0x1A +}; + class Util { public: struct ListNode; @@ -66,7 +107,7 @@ public: int16 checkKey(void); bool checkKey(int16 &key); - void getMouseState(int16 *pX, int16 *pY, int16 *pButtons); + void getMouseState(int16 *pX, int16 *pY, MouseButtons *pButtons); void setMousePos(int16 x, int16 y); void waitMouseUp(void); void waitMouseDown(void); @@ -80,11 +121,9 @@ public: void waitEndFrame(); void setScrollOffset(int16 x = -1, int16 y = -1); - Video::FontDesc *loadFont(const char *path); - static void insertStr(const char *str1, char *str2, int16 pos); static void cutFromStr(char *str, int16 from, int16 cutlen); - static void prepareStr(char *str); + static void cleanupStr(char *str); static void replaceChar(char *str, char c1, char c2); static void listInsertFront(List *list, void *data); @@ -95,7 +134,8 @@ public: Util(GobEngine *vm); protected: - int16 _mouseButtons; + MouseButtons _mouseButtons; + Common::KeyState _keyBuffer[KEYBUFSIZE]; int16 _keyBufferHead; int16 _keyBufferTail; diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp index 3b4822cc77..98350af738 100644 --- a/engines/gob/video.cpp +++ b/engines/gob/video.cpp @@ -40,6 +40,82 @@ namespace Gob { +Font::Font(const byte *data) : _dataPtr(data) { + assert(data); + + bool hasWidths = _dataPtr[0] & 0x80; + + _data = _dataPtr + 4; + _itemWidth = _dataPtr[0] & 0x7F; + _itemHeight = _dataPtr[1]; + _startItem = _dataPtr[2]; + _endItem = _dataPtr[3]; + _charWidths = 0; + + uint8 rowAlignedBits = (_itemWidth - 1) / 8 + 1; + + _itemSize = rowAlignedBits * _itemHeight; + _bitWidth = _itemWidth; + + if (hasWidths) + _charWidths = _dataPtr + 4 + _itemSize * getCharCount(); +} + +Font::~Font() { + delete[] _dataPtr; +} + +uint8 Font::getCharWidth(uint8 c) const { + if (!_charWidths || (_endItem == 0)) + return _itemWidth; + + if ((c < _startItem) || (c > _endItem)) + return _itemWidth; + + return _charWidths[c - _startItem]; +} + +uint8 Font::getCharWidth() const { + return _itemWidth; +} + +uint8 Font::getCharHeight() const { + return _itemHeight; +} + +uint16 Font::getCharCount() const { + return _endItem - _startItem + 1; +} + +uint8 Font::getFirstChar() const { + return _startItem; +} + +uint8 Font::getLastChar() const { + return _endItem; +} + +uint8 Font::getCharSize() const { + return _itemSize; +} + +bool Font::isMonospaced() const { + return _charWidths == 0; +} + +const byte *Font::getCharData(uint8 c) const { + if (_endItem == 0) { + warning("Font::getCharData(): _endItem == 0"); + return 0; + } + + if ((c < _startItem) || (c > _endItem)) + return 0; + + return _data + (c - _startItem) * _itemSize; +} + + SurfaceDesc::SurfaceDesc(int16 vidMode, int16 width, int16 height, byte *vidMem) : _width(width), _height(height) { @@ -381,41 +457,9 @@ void Video::drawSpriteDouble(SurfaceDesc &source, SurfaceDesc &dest, _videoDriver->drawSpriteDouble(source, dest, left, top, right, bottom, x, y, transp); } -void Video::drawLetter(int16 item, int16 x, int16 y, FontDesc *fontDesc, +void Video::drawLetter(int16 item, int16 x, int16 y, const Font &font, int16 color1, int16 color2, int16 transp, SurfaceDesc &dest) { - byte *dataPtr; - byte *itemData; - int16 itemSize; - int16 newItem; - int16 curItem; - int16 newItemPos; - int16 curItemPos; - - if (fontDesc->endItem == 0) { - itemSize = fontDesc->itemSize + 3; - dataPtr = fontDesc->dataPtr; - // startItem - curItem = READ_LE_UINT16(dataPtr - 2) - 1; - - curItemPos = 0; - do { - newItemPos = ((curItemPos + curItem) / 2) * itemSize; - itemData = fontDesc->dataPtr + newItemPos; - newItem = (READ_LE_UINT16(itemData) & 0x7FFF); - if (item > newItem) - curItem = newItemPos - 1; - else - curItemPos = newItemPos + 1; - } while ((newItem != item) && (curItemPos <= curItem)); - - if (newItem != item) - return; - - fontDesc->dataPtr = itemData + 3; - item = 0; - } - - _videoDriver->drawLetter((unsigned char)item, x, y, fontDesc, color1, color2, transp, dest); + _videoDriver->drawLetter((unsigned char)item, x, y, font, color1, color2, transp, dest); } void Video::drawPackedSprite(byte *sprBuf, int16 width, int16 height, diff --git a/engines/gob/video.h b/engines/gob/video.h index c71a18daa6..b8a46598b7 100644 --- a/engines/gob/video.h +++ b/engines/gob/video.h @@ -38,6 +38,36 @@ namespace Graphics { namespace Gob { +class Font { +public: + uint8 getCharWidth (uint8 c) const; + uint8 getCharWidth () const; + uint8 getCharHeight() const; + uint16 getCharCount () const; + uint8 getFirstChar () const; + uint8 getLastChar () const; + uint8 getCharSize () const; + + bool isMonospaced() const; + + const byte *getCharData(uint8 c) const; + + Font(const byte *data); + ~Font(); + +private: + const byte *_dataPtr; + const byte *_data; + const uint8 *_charWidths; + + int8 _itemWidth; + int8 _itemHeight; + uint8 _startItem; + uint8 _endItem; + int8 _itemSize; + int8 _bitWidth; +}; + // Some Surfaces are simultaneous in Draw::spritesArray and discrete // variables, so if in doubt you should use a SurfaceDescPtr shared // pointer object to refer to any SurfaceDesc. @@ -70,23 +100,6 @@ typedef Common::SharedPtr<SurfaceDesc> SurfaceDescPtr; class Video { public: - struct FontDesc { - byte *dataPtr; - int8 itemWidth; - int8 itemHeight; - uint8 startItem; - uint8 endItem; - int8 itemSize; - int8 bitWidth; - byte *extraData; - FontDesc() : dataPtr(0), itemWidth(0), itemHeight(0), startItem(0), - endItem(0), itemSize(0), bitWidth(0) {} - ~FontDesc() { - if (dataPtr) - delete[] (dataPtr - 4); - } - }; - #define GDR_VERSION 4 #define PRIMARY_SURFACE 0x80 @@ -154,7 +167,7 @@ public: int16 x, int16 y, int16 transp); void drawSpriteDouble(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp); - void drawLetter(int16 item, int16 x, int16 y, FontDesc *fontDesc, + void drawLetter(int16 item, int16 x, int16 y, const Font &font, int16 color1, int16 color2, int16 transp, SurfaceDesc &dest); void drawPackedSprite(byte *sprBuf, int16 width, int16 height, int16 x, int16 y, int16 transp, SurfaceDesc &dest); @@ -266,7 +279,7 @@ public: virtual void drawSpriteDouble(SurfaceDesc &source, SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, int16 x, int16 y, int16 transp) = 0; virtual void fillRect(SurfaceDesc &dest, int16 left, int16 top, int16 right, int16 bottom, byte color) = 0; virtual void putPixel(int16 x, int16 y, byte color, SurfaceDesc &dest) = 0; - virtual void drawLetter(unsigned char item, int16 x, int16 y, Video::FontDesc *fontDesc, byte color1, byte color2, byte transp, SurfaceDesc &dest) = 0; + virtual void drawLetter(unsigned char item, int16 x, int16 y, const Font &font, byte color1, byte color2, byte transp, SurfaceDesc &dest) = 0; virtual void drawLine(SurfaceDesc &dest, int16 x0, int16 y0, int16 x1, int16 y1, byte color) = 0; virtual void drawPackedSprite(byte *sprBuf, int16 width, int16 height, int16 x, int16 y, byte transp, SurfaceDesc &dest) = 0; }; diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp index 6c07d22333..da552d7202 100644 --- a/engines/gob/videoplayer.cpp +++ b/engines/gob/videoplayer.cpp @@ -27,7 +27,6 @@ #include "gob/videoplayer.h" #include "gob/helper.h" #include "gob/global.h" -#include "gob/util.h" #include "gob/dataio.h" #include "gob/video.h" #include "gob/draw.h" diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h index 842426f90a..ead752d446 100644 --- a/engines/gob/videoplayer.h +++ b/engines/gob/videoplayer.h @@ -31,11 +31,12 @@ #include "graphics/video/coktelvideo/coktelvideo.h" -#include "gob/dataio.h" +#include "gob/util.h" namespace Gob { class GobEngine; +class DataStream; class VideoPlayer { public: @@ -60,13 +61,14 @@ public: bool primaryOpen(const char *videoFile, int16 x = -1, int16 y = -1, int32 flags = kFlagFrontSurface, Type which = kVideoTypeTry); - bool primaryPlay(int16 startFrame = -1, int16 lastFrame = -1, int16 breakKey = 27, + bool primaryPlay(int16 startFrame = -1, int16 lastFrame = -1, + int16 breakKey = kShortKeyEscape, uint16 palCmd = 8, int16 palStart = 0, int16 palEnd = 255, int16 palFrame = -1, int16 endFrame = -1, bool fade = false, int16 reverseTo = -1, bool forceSeek = false); void primaryClose(); - void playFrame(int16 frame, int16 breakKey = 27, + void playFrame(int16 frame, int16 breakKey = kShortKeyEscape, uint16 palCmd = 8, int16 palStart = 0, int16 palEnd = 255, int16 palFrame = -1 , int16 endFrame = -1); diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index e2315459d4..9381b5b47c 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -94,7 +94,11 @@ Common::Error GroovieEngine::run() { } // Create the music player - _musicPlayer = new MusicPlayer(this, _gameDescription->version == kGroovieT7G ? "fat" : "sample"); + if (_gameDescription->desc.platform == Common::kPlatformMacintosh) { + _musicPlayer = new MusicPlayerMac(this); + } else { + _musicPlayer = new MusicPlayerXMI(this, _gameDescription->version == kGroovieT7G ? "fat" : "sample"); + } // Load volume levels syncSoundSettings(); diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index 30889deb44..1a1de92156 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -31,72 +31,20 @@ namespace Groovie { -MusicPlayer::MusicPlayer(GroovieEngine *vm, const Common::String >lName) : - _vm(vm), _midiParser(NULL), _data(NULL), _driver(NULL), - _backgroundFileRef(0), _gameVolume(100), _prevCDtrack(0), _isPlaying(0) { - // Create the parser - _midiParser = MidiParser::createParser_XMIDI(); - - // Create the driver - int driver = detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - _driver = createMidi(driver); - this->open(); - - // Initialize the channel volumes and banks - for (int i = 0; i < 0x10; i++) { - _chanVolumes[i] = 0x7F; - _chanBanks[i] = 0; - } - - // Load the Global Timbre Library - if (driver == MD_ADLIB) { - // MIDI through AdLib - _musicType = MD_ADLIB; - loadTimbres(gtlName + ".ad"); - - // Setup the percussion channel - for (unsigned int i = 0; i < _timbres.size(); i++) { - if (_timbres[i].bank == 0x7F) - setTimbreAD(9, _timbres[i]); - } - } else if ((driver == MD_MT32) || ConfMan.getBool("native_mt32")) { - // MT-32 - _musicType = MD_MT32; - loadTimbres(gtlName + ".mt"); - } else { - // GM - _musicType = 0; - } - - // Set the parser's driver - _midiParser->setMidiDriver(this); - - // Set the timer rate - _midiParser->setTimerRate(_driver->getBaseTempo()); -} - -MusicPlayer::~MusicPlayer() { - _driver->setTimerCallback(NULL, NULL); - - Common::StackLock lock(_mutex); - - // Unload the parser - unload(); - delete _midiParser; +// MusicPlayer - // Unload the MIDI Driver - _driver->close(); - delete _driver; - - // Unload the timbres - clearTimbres(); +MusicPlayer::MusicPlayer(GroovieEngine *vm) : + _vm(vm), _isPlaying(false), _backgroundFileRef(0), _gameVolume(100), + _prevCDtrack(0) { } void MusicPlayer::playSong(uint32 fileref) { Common::StackLock lock(_mutex); + // Set the volumes _fadingEndVolume = 100; _gameVolume = 100; + // Play the referenced file once play(fileref, false); } @@ -146,6 +94,14 @@ void MusicPlayer::playCD(uint8 track) { AudioCD.play(track - 1, 1, startms * 75 / 1000, 0); } +void MusicPlayer::startBackground() { + debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: startBackground()"); + if (!_isPlaying && _backgroundFileRef) { + debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the background song (0x%4X)", _backgroundFileRef); + play(_backgroundFileRef, true); + } +} + void MusicPlayer::setUserVolume(uint16 volume) { Common::StackLock lock(_mutex); @@ -154,10 +110,8 @@ void MusicPlayer::setUserVolume(uint16 volume) { if (_userVolume > 0x100) _userVolume = 0x100; - // Apply it to all the channels - for (int i = 0; i < 0x10; i++) { - updateChanVolume(i); - } + // Apply it + updateVolume(); } void MusicPlayer::setGameVolume(uint16 volume, uint16 time) { @@ -176,17 +130,15 @@ void MusicPlayer::setGameVolume(uint16 volume, uint16 time) { _fadingEndVolume = 100; } -void MusicPlayer::startBackground() { - debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: startBackground()"); - if (!_isPlaying && _backgroundFileRef) { - debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the background song (0x%4X)", _backgroundFileRef); - play(_backgroundFileRef, true); - } -} - -void MusicPlayer::endTrack() { - debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: endTrack()"); +bool MusicPlayer::play(uint32 fileref, bool loop) { + // Unload the previous song unload(); + + // Set the new state + _isPlaying = true; + + // Load the new file + return load(fileref, loop); } void MusicPlayer::applyFading() { @@ -212,13 +164,129 @@ void MusicPlayer::applyFading() { } } - // Apply the new volume to all the channels + // Apply it + updateVolume(); +} + +void MusicPlayer::onTimer(void *refCon) { + debugC(9, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: onTimer()"); + MusicPlayer *music = (MusicPlayer *)refCon; + Common::StackLock lock(music->_mutex); + + // Apply the game volume fading + if (music->_gameVolume != music->_fadingEndVolume) { + // Apply the next step of the fading + music->applyFading(); + } + + // Handle internal timed events + music->onTimerInternal(); +} + +void MusicPlayer::unload() { + debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Stopping the playback"); + + // Set the new state + _isPlaying = false; +} + + +// MusicPlayerMidi + +MusicPlayerMidi::MusicPlayerMidi(GroovieEngine *vm) : + MusicPlayer(vm), _midiParser(NULL), _data(NULL), _driver(NULL) { + // Initialize the channel volumes for (int i = 0; i < 0x10; i++) { - updateChanVolume(i); + _chanVolumes[i] = 0x7F; + } +} + +MusicPlayerMidi::~MusicPlayerMidi() { + // Stop the callback + if (_driver) + _driver->setTimerCallback(NULL, NULL); + + Common::StackLock lock(_mutex); + + // Unload the parser + unload(); + delete _midiParser; + + // Unload the MIDI Driver + if (_driver) + _driver->close(); + delete _driver; +} + +int MusicPlayerMidi::open() { + // Don't ever call open without first setting the output driver! + if (!_driver) + return 255; + + int ret = _driver->open(); + if (ret) + return ret; + + return 0; +} + +void MusicPlayerMidi::close() {} + +void MusicPlayerMidi::send(uint32 b) { + if ((b & 0xFFF0) == 0x07B0) { // Volume change + // Save the specific channel volume + byte chan = b & 0xF; + _chanVolumes[chan] = (b >> 16) & 0x7F; + + // Send the updated value + updateChanVolume(chan); + + return; + } + if (_driver) + _driver->send(b); +} + +void MusicPlayerMidi::metaEvent(byte type, byte *data, uint16 length) { + switch (type) { + case 0x2F: + // End of Track, play the background song + endTrack(); + break; + default: + if (_driver) + _driver->metaEvent(type, data, length); + break; } } -void MusicPlayer::updateChanVolume(byte channel) { +void MusicPlayerMidi::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) { + if (_driver) + _driver->setTimerCallback(timer_param, timer_proc); +} + +uint32 MusicPlayerMidi::getBaseTempo(void) { + if (_driver) + return _driver->getBaseTempo(); + else + return 0; +} + +MidiChannel *MusicPlayerMidi::allocateChannel() { + if (_driver) + return _driver->allocateChannel(); + else + return 0; +} + +MidiChannel *MusicPlayerMidi::getPercussionChannel() { + if (_driver) + return _driver->getPercussionChannel(); + else + return 0; +} + +void MusicPlayerMidi::updateChanVolume(byte channel) { // Generate a MIDI Control change message for the volume uint32 b = 0x7B0; @@ -230,76 +298,119 @@ void MusicPlayer::updateChanVolume(byte channel) { val &= 0x7F; // Send it to the driver - _driver->send(b | (val << 16)); + if (_driver) + _driver->send(b | (val << 16)); } -bool MusicPlayer::play(uint32 fileref, bool loop) { - // Unload the previous song +void MusicPlayerMidi::endTrack() { + debugC(3, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: endTrack()"); unload(); +} - // Set the looping option - _midiParser->property(MidiParser::mpAutoLoop, loop); +void MusicPlayerMidi::onTimerInternal() { + // TODO: We really only need to call this while music is playing. + if (_midiParser) + _midiParser->onTimer(); +} - _isPlaying = true; - // Load the new file - return load(fileref); +void MusicPlayerMidi::updateVolume() { + // Apply it to all the channels + for (int i = 0; i < 0x10; i++) { + updateChanVolume(i); + } } -bool MusicPlayer::load(uint32 fileref) { - debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref); +void MusicPlayerMidi::unload() { + MusicPlayer::unload(); - // Open the song resource - Common::SeekableReadStream *xmidiFile = _vm->_resMan->open(fileref); - if (!xmidiFile) { - error("Groovie::Music: Couldn't find resource 0x%04X", fileref); + // Unload the parser data + if (_midiParser) + _midiParser->unloadMusic(); + + // Unload the data + delete[] _data; + _data = NULL; +} + +bool MusicPlayerMidi::loadParser(Common::SeekableReadStream *stream, bool loop) { + if (!_midiParser) return false; - } // Read the whole file to memory - int length = xmidiFile->size(); + int length = stream->size(); _data = new byte[length]; - xmidiFile->read(_data, length); - delete xmidiFile; + stream->read(_data, length); + delete stream; + + // Set the looping option + _midiParser->property(MidiParser::mpAutoLoop, loop); // Start parsing the data if (!_midiParser->loadMusic(_data, length)) { - error("Groovie::Music: Invalid XMI file"); + error("Groovie::Music: Couldn't parse the data"); return false; } // Activate the timer source - _driver->setTimerCallback(this, &onTimer); + if (_driver) + _driver->setTimerCallback(this, &onTimer); return true; } -void MusicPlayer::unload() { - debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Stopping the playback"); - _isPlaying = false; - // Unload the parser - _midiParser->unloadMusic(); +// MusicPlayerXMI - // Unload the xmi file - delete[] _data; - _data = NULL; -} +MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName) : + MusicPlayerMidi(vm) { + // Create the parser + _midiParser = MidiParser::createParser_XMIDI(); -int MusicPlayer::open() { - // Don't ever call open without first setting the output driver! - if (!_driver) - return 255; + // Create the driver + int driver = detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + _driver = createMidi(driver); + this->open(); - int ret = _driver->open(); - if (ret) - return ret; + // Set the parser's driver + _midiParser->setMidiDriver(this); - return 0; + // Set the timer rate + _midiParser->setTimerRate(_driver->getBaseTempo()); + + // Initialize the channel banks + for (int i = 0; i < 0x10; i++) { + _chanBanks[i] = 0; + } + + // Load the Global Timbre Library + if (driver == MD_ADLIB) { + // MIDI through AdLib + _musicType = MD_ADLIB; + loadTimbres(gtlName + ".ad"); + + // Setup the percussion channel + for (unsigned int i = 0; i < _timbres.size(); i++) { + if (_timbres[i].bank == 0x7F) + setTimbreAD(9, _timbres[i]); + } + } else if ((driver == MD_MT32) || ConfMan.getBool("native_mt32")) { + // MT-32 + _musicType = MD_MT32; + loadTimbres(gtlName + ".mt"); + } else { + // GM + _musicType = 0; + } } -void MusicPlayer::close() {} +MusicPlayerXMI::~MusicPlayerXMI() { + //~MusicPlayer(); + + // Unload the timbres + clearTimbres(); +} -void MusicPlayer::send(uint32 b) { +void MusicPlayerXMI::send(uint32 b) { if ((b & 0xFFF0) == 0x72B0) { // XMIDI Patch Bank Select 114 // From AIL2's documentation: XMIDI Patch Bank Select controller (114) // selects a bank to be used when searching the next patches @@ -337,63 +448,24 @@ void MusicPlayer::send(uint32 b) { // If we got here we couldn't find the patch, and the // received message will be sent unchanged. } - } else if ((b & 0xFFF0) == 0x07B0) { // Volume change - // Save the specific channel volume - byte chan = b & 0xF; - _chanVolumes[chan] = (b >> 16) & 0x7F; - - // Send the updated value - updateChanVolume(chan); - - return; - } - _driver->send(b); -} - -void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) { - switch (type) { - case 0x2F: - // End of Track, play the background song - endTrack(); - break; - default: - _driver->metaEvent(type, data, length); - break; } + MusicPlayerMidi::send(b); } -void MusicPlayer::onTimer(void *refCon) { - debugC(9, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: onTimer()"); - MusicPlayer *music = (MusicPlayer *)refCon; - Common::StackLock lock(music->_mutex); +bool MusicPlayerXMI::load(uint32 fileref, bool loop) { + debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref); - // Apply the game volume fading - if (music->_gameVolume != music->_fadingEndVolume) { - // Apply the next step of the fading - music->applyFading(); + // Open the song resource + Common::SeekableReadStream *file = _vm->_resMan->open(fileref); + if (!file) { + error("Groovie::Music: Couldn't find resource 0x%04X", fileref); + return false; } - // TODO: We really only need to call this while music is playing. - music->_midiParser->onTimer(); -} - -void MusicPlayer::setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) { - _driver->setTimerCallback(timer_param, timer_proc); -} - -uint32 MusicPlayer::getBaseTempo(void) { - return _driver->getBaseTempo(); -} - -MidiChannel *MusicPlayer::allocateChannel() { - return _driver->allocateChannel(); -} - -MidiChannel *MusicPlayer::getPercussionChannel() { - return _driver->getPercussionChannel(); + return loadParser(file, loop); } -void MusicPlayer::loadTimbres(const Common::String &filename) { +void MusicPlayerXMI::loadTimbres(const Common::String &filename) { // Load the Global Timbre Library format as documented in AIL2 debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Loading the GTL file %s", filename.c_str()); @@ -451,7 +523,7 @@ void MusicPlayer::loadTimbres(const Common::String &filename) { delete gtl; } -void MusicPlayer::clearTimbres() { +void MusicPlayerXMI::clearTimbres() { // Delete the allocated data int num = _timbres.size(); for (int i = 0; i < num; i++) { @@ -462,7 +534,7 @@ void MusicPlayer::clearTimbres() { _timbres.clear(); } -void MusicPlayer::setTimbreAD(byte channel, const Timbre &timbre) { +void MusicPlayerXMI::setTimbreAD(byte channel, const Timbre &timbre) { // Verify the timbre size if (timbre.size != 12) { error("Groovie::Music: Invalid size for an AdLib timbre: %d", timbre.size); @@ -514,7 +586,7 @@ void MusicPlayer::setTimbreAD(byte channel, const Timbre &timbre) { } } -void MusicPlayer::setTimbreMT(byte channel, const Timbre &timbre) { +void MusicPlayerXMI::setTimbreMT(byte channel, const Timbre &timbre) { // Verify the timbre size if (timbre.size != 0xF6) { error("Groovie::Music: Invalid size for an MT-32 timbre: %d", timbre.size); @@ -528,4 +600,28 @@ void MusicPlayer::setTimbreMT(byte channel, const Timbre &timbre) { warning("Groovie::Music: Setting MT32 custom instruments isn't supported yet"); } + +// MusicPlayerMac + +MusicPlayerMac::MusicPlayerMac(GroovieEngine *vm) : + MusicPlayerMidi(vm) { +} + +bool MusicPlayerMac::load(uint32 fileref, bool loop) { + debugC(1, kGroovieDebugMIDI | kGroovieDebugAll, "Groovie::Music: Starting the playback of song: %04X", fileref); + debug("Groovie::Music: Starting the playback of song: %04X %d", fileref, fileref); + + // Open the song resource + /* + Common::SeekableReadStream *file = _vm->_resMan->open(fileref); + if (!file) { + error("Groovie::Music: Couldn't find resource 0x%04X", fileref); + return false; + } + */ + + //return loadParser(file, loop); + return false; +} + } // End of Groovie namespace diff --git a/engines/groovie/music.h b/engines/groovie/music.h index 92c7afde70..db50930c37 100644 --- a/engines/groovie/music.h +++ b/engines/groovie/music.h @@ -34,10 +34,11 @@ namespace Groovie { -class MusicPlayer : public MidiDriver { +class MusicPlayer { public: - MusicPlayer(GroovieEngine *vm, const Common::String >lName); - ~MusicPlayer(); + MusicPlayer(GroovieEngine *vm); + virtual ~MusicPlayer() {} + void playSong(uint32 fileref); void setBackgroundSong(uint32 fileref); void playCD(uint8 track); @@ -48,25 +49,89 @@ public: void setGameVolume(uint16 volume, uint16 time); private: - // User volume - uint16 _userVolume; + // Song playback + bool play(uint32 fileref, bool loop); + bool _isPlaying; + uint32 _backgroundFileRef; + uint8 _prevCDtrack; - // Game volume - uint16 _gameVolume; + // Volume fading uint32 _fadingStartTime; uint16 _fadingStartVolume; uint16 _fadingEndVolume; uint16 _fadingDuration; - void endTrack(); void applyFading(); - // Song volumes +protected: + GroovieEngine *_vm; + + // Callback + static void onTimer(void *data); + virtual void onTimerInternal() {} + Common::Mutex _mutex; + + // User volume + uint16 _userVolume; + // Game volume + uint16 _gameVolume; + + // These are specific for each type of music + virtual void updateVolume() = 0; + virtual bool load(uint32 fileref, bool loop) = 0; + virtual void unload(); +}; + +class MusicPlayerMidi : public MusicPlayer, public MidiDriver { +public: + MusicPlayerMidi(GroovieEngine *vm); + ~MusicPlayerMidi(); + + // MidiDriver interface + int open(); + void close(); + void send(uint32 b); + void metaEvent(byte type, byte *data, uint16 length); + void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc); + uint32 getBaseTempo(void); + MidiChannel *allocateChannel(); + MidiChannel *getPercussionChannel(); + +private: + // Channel volumes byte _chanVolumes[0x10]; void updateChanVolume(byte channel); + void endTrack(); + +protected: + byte *_data; + MidiParser *_midiParser; + MidiDriver *_driver; + + void onTimerInternal(); + void updateVolume(); + void unload(); + + bool loadParser(Common::SeekableReadStream *stream, bool loop); +}; + +class MusicPlayerXMI : public MusicPlayerMidi { +public: + MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName); + ~MusicPlayerXMI(); + + void send(uint32 b); + +protected: + bool load(uint32 fileref, bool loop); + +private: // Channel banks byte _chanBanks[0x10]; + // Output music type + uint8 _musicType; + // Timbres class Timbre { public: @@ -81,35 +146,14 @@ private: void clearTimbres(); void setTimbreAD(byte channel, const Timbre &timbre); void setTimbreMT(byte channel, const Timbre &timbre); +}; +class MusicPlayerMac : public MusicPlayerMidi { public: - // MidiDriver interface - int open(); - void close(); - void send(uint32 b); - void metaEvent(byte type, byte *data, uint16 length); - void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc); - uint32 getBaseTempo(void); - MidiChannel *allocateChannel(); - MidiChannel *getPercussionChannel(); + MusicPlayerMac(GroovieEngine *vm); -private: - GroovieEngine *_vm; - Common::Mutex _mutex; - byte *_data; - MidiParser *_midiParser; - MidiDriver *_driver; - uint8 _musicType; - bool _isPlaying; - - uint32 _backgroundFileRef; - uint8 _prevCDtrack; - - static void onTimer(void *data); - - bool play(uint32 fileref, bool loop); - bool load(uint32 fileref); - void unload(); +protected: + bool load(uint32 fileref, bool loop); }; } // End of Groovie namespace diff --git a/engines/groovie/resource.cpp b/engines/groovie/resource.cpp index eda3f0bec0..148fa9c451 100644 --- a/engines/groovie/resource.cpp +++ b/engines/groovie/resource.cpp @@ -98,7 +98,7 @@ uint16 ResMan_t7g::getRef(Common::String name, Common::String scriptname) { uint16 resNum; bool found = false; - for (resNum = 0; !found && !rlFile.ioFailed(); resNum++) { + for (resNum = 0; !found && !rlFile.err() && !rlFile.eos(); resNum++) { // Read the resource name char readname[12]; rlFile.read(readname, 12); diff --git a/engines/groovie/roq.cpp b/engines/groovie/roq.cpp index 28d0d23fc1..dcb8eafcb8 100644 --- a/engines/groovie/roq.cpp +++ b/engines/groovie/roq.cpp @@ -256,6 +256,7 @@ bool ROQPlayer::processBlock() { break; case 0x1013: // Hang assert(blockHeader.size == 0 && blockHeader.param == 0); + endframe = true; break; case 0x1020: // Mono sound samples ok = processBlockSoundMono(blockHeader); diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp index df627e841c..eb53842b91 100644 --- a/engines/groovie/script.cpp +++ b/engines/groovie/script.cpp @@ -38,7 +38,9 @@ namespace Groovie { -void debugScript(int level, bool nl, const char *s, ...) { +static void debugScript(int level, bool nl, const char *s, ...) GCC_PRINTF(3, 4); + +static void debugScript(int level, bool nl, const char *s, ...) { char buf[STRINGBUFLEN]; va_list va; @@ -511,7 +513,7 @@ void Script::o_videofromref() { // 0x09 } } if (fileref != _videoRef) { - debugScript(1, true, ""); + debugScript(1, false, "\n"); } // Play the video if (!playvideofromref(fileref)) { @@ -569,7 +571,7 @@ bool Script::playvideofromref(uint32 fileref) { _eventKbdChar = 0; // Newline - debugScript(1, true, ""); + debugScript(1, false, "\n"); } // Let the caller know if the video has ended @@ -759,7 +761,7 @@ void Script::o_loadstring() { setVariable(varnum++, readScriptChar(true, true, true)); debugScript(1, false, " 0x%02X", _variables[varnum - 1]); } while (!(getCodeByte(_currentInstruction - 1) & 0x80)); - debugScript(1, true, ""); + debugScript(1, false, "\n"); } void Script::o_ret() { @@ -840,7 +842,7 @@ void Script::o_xor_obfuscate() { varnum++; } while (!_firstbit); - debugScript(1, true, ""); + debugScript(1, false, "\n"); } void Script::o_vdxtransition() { // 0x1C @@ -1095,7 +1097,7 @@ void Script::o_loadstringvar() { setVariable(varnum++, readScriptChar(true, true, true)); debugScript(1, false, " 0x%02X", _variables[varnum - 1]); } while (!(getCodeByte(_currentInstruction - 1) & 0x80)); - debugScript(1, true, ""); + debugScript(1, false, "\n"); } void Script::o_chargreatjmp() { diff --git a/engines/igor/igor.cpp b/engines/igor/igor.cpp index 0581f6ddc3..6cf7bda33d 100644 --- a/engines/igor/igor.cpp +++ b/engines/igor/igor.cpp @@ -2095,7 +2095,7 @@ int IgorEngine::getHorizontalStepsCount(int minX, int minY, int maxX, int maxY) float r2 = _walkScaleSpeedTable[scale - 1]; debugC(9, kDebugWalk, "getHorizontalStepsCount() maxX - minX = %d r1 = %f r2 = %f", maxX - minX, r1, r2); - int16 steps = roundReal((maxX - minX) / ((r1 + r2) / 2.)); + int16 steps = roundReal((maxX - minX) / ((r1 + r2) / 2.0f)); int count = 0; if (steps != 0) { float r3 = (maxY - minY) / (float)steps; diff --git a/engines/igor/staticres.cpp b/engines/igor/staticres.cpp index e5df644c5e..ef19d7033f 100644 --- a/engines/igor/staticres.cpp +++ b/engines/igor/staticres.cpp @@ -230,11 +230,11 @@ const uint8 IgorEngine::_walkWidthScaleTable[] = { }; const float IgorEngine::_walkScaleSpeedTable[] = { - 0.6250, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.1250, 1.3750, 1.6250, 1.6250, - 1.6250, 1.6250, 2.0000, 2.1250, 2.3750, 2.3750, 2.6250, 2.6250, 2.7500, 2.7500, - 2.7500, 3.0000, 3.0000, 3.0000, 3.0000, 3.6250, 3.6250, 3.6250, 3.8750, 3.8750, - 3.8750, 4.0000, 4.0000, 4.3750, 4.3750, 4.6250, 4.6250, 5.0000, 5.0000, 5.0000, - 5.0000, 5.2500, 5.5000, 5.6250, 5.6250, 5.6250, 5.6250, 5.6250, 5.6250, 5.6250 + 0.6250f, 1.0000f, 1.0000f, 1.0000f, 1.0000f, 1.0000f, 1.1250f, 1.3750f, 1.6250f, 1.6250f, + 1.6250f, 1.6250f, 2.0000f, 2.1250f, 2.3750f, 2.3750f, 2.6250f, 2.6250f, 2.7500f, 2.7500f, + 2.7500f, 3.0000f, 3.0000f, 3.0000f, 3.0000f, 3.6250f, 3.6250f, 3.6250f, 3.8750f, 3.8750f, + 3.8750f, 4.0000f, 4.0000f, 4.3750f, 4.3750f, 4.6250f, 4.6250f, 5.0000f, 5.0000f, 5.0000f, + 5.0000f, 5.2500f, 5.5000f, 5.6250f, 5.6250f, 5.6250f, 5.6250f, 5.6250f, 5.6250f, 5.6250f }; const uint8 IgorEngine::_walkScaleTable[] = { diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 3491c54b36..3199a043e7 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -230,7 +230,7 @@ const KYRAGameDescription adGameDescs[] = { KYRA1_FLOPPY_FLAGS }, - { // FM-Towns version + { // FM-TOWNS version { "kyra1", 0, @@ -263,26 +263,12 @@ const KYRAGameDescription adGameDescs[] = { KYRA1_TOWNS_SJIS_FLAGS }, - { // PC-9821 (CD) version - { - "kyra1", - "CD", - { - { "EMC.PAK", 0, "a046bb0b422061aab8e4c4689400343a", -1 }, - { "MUSIC98.PAK", 0, "02fc212f799331b769b274e33d87b37f", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC98, - ADGF_CD, - Common::GUIO_NOSPEECH - }, - KYRA1_TOWNS_FLAGS - }, + // PC-9801 floppy + CD / PC-9821 floppy version are all using the same data files, + // thus we will mark it as non CD game. { { "kyra1", - "CD", + "", { { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 }, { "MUSIC98.PAK", 0, "02fc212f799331b769b274e33d87b37f", -1 }, @@ -290,7 +276,7 @@ const KYRAGameDescription adGameDescs[] = { }, Common::JA_JPN, Common::kPlatformPC98, - ADGF_CD, + ADGF_NO_FLAGS, Common::GUIO_NOSPEECH }, KYRA1_TOWNS_SJIS_FLAGS @@ -652,7 +638,7 @@ const KYRAGameDescription adGameDescs[] = { KYRA2_DEMO_FLAGS }, - { // FM-Towns + { // FM-TOWNS { "kyra2", 0, diff --git a/engines/kyra/gui.h b/engines/kyra/gui.h index 3989062506..95df656977 100644 --- a/engines/kyra/gui.h +++ b/engines/kyra/gui.h @@ -260,7 +260,7 @@ private: void drawBox(int x, int y, int w, int h, int fill); bool getInput(); - void printString(const char *string, int x, int y, int col1, int col2, int flags, ...); + void printString(const char *string, int x, int y, int col1, int col2, int flags, ...) GCC_PRINTF(2, 8); }; } // end of namesapce Kyra diff --git a/engines/kyra/kyra_lok.cpp b/engines/kyra/kyra_lok.cpp index e5ca52abcc..a3a249de18 100644 --- a/engines/kyra/kyra_lok.cpp +++ b/engines/kyra/kyra_lok.cpp @@ -434,7 +434,7 @@ void KyraEngine_LoK::mainLoop() { // FIXME: Why is this here? _screen->showMouse(); - int inputFlag = checkInput(_buttonList, true); + int inputFlag = checkInput(_buttonList, _currentCharacter->sceneId != 210); removeInputTop(); updateMousePointer(); diff --git a/engines/kyra/kyra_mr.cpp b/engines/kyra/kyra_mr.cpp index 871edd578d..a00b3a8956 100644 --- a/engines/kyra/kyra_mr.cpp +++ b/engines/kyra/kyra_mr.cpp @@ -310,16 +310,19 @@ Common::Error KyraEngine_MR::go() { break; case 3: - default: fadeOutMusic(60); _screen->fadeToBlack(60); uninitMainMenu(); quitGame(); running = false; + break; + + default: + break; } } - if (_showOutro) + if (_showOutro && !shouldQuit()) playVQA("CREDITS"); return Common::kNoError; diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index a8889768a7..186b270e58 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -117,7 +117,6 @@ Common::Error KyraEngine_v1::init() { _sound = new SoundAmiga(this, _mixer); } else if (midiDriver == MD_ADLIB) { _sound = new SoundAdlibPC(this, _mixer); - assert(_sound); } else { Sound::kType type; @@ -128,7 +127,6 @@ Common::Error KyraEngine_v1::init() { else type = Sound::kMidiGM; - MidiDriver *driver = 0; if (midiDriver == MD_PCSPK) { @@ -153,9 +151,10 @@ Common::Error KyraEngine_v1::init() { assert(adlib); _sound = new MixedSoundDriver(this, _mixer, soundMidiPc, adlib); - assert(_sound); } } + + assert(_sound); } if (_sound) diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 020e1ea3ea..d2c8be9556 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -214,8 +214,6 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _compassBroken = _drainMagic = 0; _dialogueField = false; - _rndSpecial = 0x12349876; - _buttonData = 0; _activeButtons = 0; gui_resetButtonList(); @@ -1082,7 +1080,7 @@ bool LoLEngine::addCharacter(int id) { loadCharFaceShapes(numChars, id); - _characters[numChars].nextAnimUpdateCountdown = (int16) _rnd.getRandomNumberRng(1, 12) + 6; + _characters[numChars].nextAnimUpdateCountdown = rollDice(1, 12) + 6; for (i = 0; i < 11; i++) { if (_characters[numChars].items[i]) { @@ -1176,7 +1174,7 @@ void LoLEngine::updatePortraitSpeechAnim() { } } - int f = _rnd.getRandomNumberRng(1, 6) - 1; + int f = rollDice(1, 6) - 1; if (f == _characters[_updateCharNum].curFaceFrame) f++; if (f > 5) @@ -1404,24 +1402,24 @@ void LoLEngine::increaseExperience(int charNum, int skill, uint32 points) { switch (skill) { case 0: _txt->printMessage(0x8003, getLangString(0x4023), _characters[charNum].name); - inc = _rnd.getRandomNumberRng(4, 6); + inc = rollDice(4, 6); _characters[charNum].hitPointsCur += inc; _characters[charNum].hitPointsMax += inc; break; case 1: _txt->printMessage(0x8003, getLangString(0x4025), _characters[charNum].name); - inc = _rnd.getRandomNumberRng(2, 6); + inc = rollDice(2, 6); _characters[charNum].hitPointsCur += inc; _characters[charNum].hitPointsMax += inc; break; case 2: _txt->printMessage(0x8003, getLangString(0x4024), _characters[charNum].name); - inc = (_characters[charNum].defaultModifiers[6] * (_rnd.getRandomNumberRng(1, 8) + 17)) >> 8; + inc = (_characters[charNum].defaultModifiers[6] * (rollDice(1, 8) + 17)) >> 8; _characters[charNum].magicPointsCur += inc; _characters[charNum].magicPointsMax += inc; - inc = _rnd.getRandomNumberRng(1, 6); + inc = rollDice(1, 6); _characters[charNum].hitPointsCur += inc; _characters[charNum].hitPointsMax += inc; break; @@ -1874,6 +1872,17 @@ void LoLEngine::delay(uint32 millis, bool doUpdate, bool) { } } +int LoLEngine::rollDice(int times, int pips) { + if (times <= 0 || pips <= 0) + return 0; + + int res = 0; + while (times--) + res += _rnd.getRandomNumberRng(1, pips); + + return res; +} + void LoLEngine::updateEnvironmentalSfx(int soundId) { snd_processEnvironmentalSoundEffect(soundId, _currentBlock); } @@ -1885,7 +1894,7 @@ int LoLEngine::castSpell(int charNum, int spellType, int spellLevel) { _activeSpell.spell = spellType; _activeSpell.p = &_spellProperties[spellType]; - _activeSpell.level = spellLevel < 0 ? -spellLevel : spellLevel; + _activeSpell.level = ABS(spellLevel); if ((_spellProperties[spellType].flags & 0x100) && testWallFlag(calcNewBlockPosition(_currentBlock, _currentDirection), _currentDirection, 1)) { _txt->printMessage(2, getLangString(0x4257)); @@ -2260,7 +2269,7 @@ int LoLEngine::processMagicIce(int charNum, int spellLevel) { } else { uint16 o = _levelBlockProperties[calcNewBlockPosition(_currentBlock, _currentDirection)].assignedObjects; while (o & 0x8000) { - int might = _rnd.getRandomNumberRng(iceDamageMin[spellLevel], iceDamageMax[spellLevel]) + iceDamageAdd[spellLevel]; + int might = rollDice(iceDamageMin[spellLevel], iceDamageMax[spellLevel]) + iceDamageAdd[spellLevel]; int dmg = calcInflictableDamagePerItem(charNum, 0, might, 3, 2); MonsterInPlay *m = &_monsters[o & 0x7fff]; @@ -2880,7 +2889,7 @@ void LoLEngine::drinkBezelCup(int numUses, int charNum) { uint16 step = 0; do { - step = (step & 0xff) + (hpDiff * 256) / (bezelAnimData[numUses * 3 + 2]); + step = (step & 0xff) + (hpDiff * 256) / (bezelAnimData[numUses * 3 + 1]); increaseCharacterHitpoints(charNum, step / 256, true); gui_drawCharPortraitWithStats(charNum); @@ -3192,7 +3201,7 @@ int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) { evadeChanceModifier = _characters[target].defaultModifiers[3]; } - int r = _rnd.getRandomNumberRng(1, 100); + int r = rollDice(1, 100); if (r >= sk) return 2; @@ -3230,9 +3239,9 @@ int LoLEngine::inflictDamage(uint16 target, int damage, uint16 attacker, int ski m->hitPoints -= damage; m->damageReceived = 0x8000 | damage; m->flags |= 0x10; - m->hitOffsX = _rnd.getRandomNumberRng(1, 24); + m->hitOffsX = rollDice(1, 24); m->hitOffsX -= 12; - m->hitOffsY = _rnd.getRandomNumberRng(1, 24); + m->hitOffsY = rollDice(1, 24); m->hitOffsY -= 12; m->hitPoints = CLIP<int16>(m->hitPoints, 0, m->properties->hitPoints); @@ -3436,7 +3445,7 @@ void LoLEngine::checkForPartyDeath() { } void LoLEngine::applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, int16 damage) { - if (_rnd.getRandomNumberRng(1, 100) > monster->properties->attackSkillChance) + if (rollDice(1, 100) > monster->properties->attackSkillChance) return; int t = 0; @@ -3506,7 +3515,7 @@ void LoLEngine::applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, in } void LoLEngine::applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, int flags, int skill, int damage) { - if (_rnd.getRandomNumberRng(1, 100) > monster->properties->defenseSkillChance) + if (rollDice(1, 100) > monster->properties->defenseSkillChance) return; int itm = 0; @@ -3593,7 +3602,7 @@ int LoLEngine::paralyzePoisonCharacter(int charNum, int typeFlag, int immunityFl if (!(_characters[charNum].flags & 1) || (_characters[charNum].flags & immunityFlags)) return 0; - if ((int)_rnd.getRandomNumberRng(1, 100) > hitChance) + if (rollDice(1, 100) > hitChance) return 0; int r = 0; @@ -3711,7 +3720,7 @@ void LoLEngine::launchMagicViper() { _screen->copyPage(12, 0); _screen->copyPage(12, 2); - int t = _rnd.getRandomNumberRng(1, 4); + int t = rollDice(1, 4); for (int i = 0; i < 4; i++) { if (!(_characters[i].flags & 1)) { diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index 12000c31fa..f4ac597b5c 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -642,6 +642,7 @@ private: int olol_setWallType(EMCState *script); int olol_getWallType(EMCState *script); int olol_drawScene(EMCState *script); + int olol_rollDice(EMCState *script); int olol_moveParty(EMCState *script); int olol_delay(EMCState *script); int olol_setGameFlag(EMCState *script); @@ -1313,6 +1314,7 @@ private: // misc void delay(uint32 millis, bool doUpdate = false, bool isMainLoop = false); + int rollDice(int times, int pips); uint8 _compassBroken; uint8 _drainMagic; @@ -1320,8 +1322,7 @@ private: uint8 *_pageBuffer1; uint8 *_pageBuffer2; - uint32 _rndSpecial; - + // spells typedef Common::Functor1Mem<ActiveSpell*, int, LoLEngine> SpellProc; Common::Array<const SpellProc*> _spellProcs; diff --git a/engines/kyra/saveload.cpp b/engines/kyra/saveload.cpp index ecd6bbe450..83230d6e3b 100644 --- a/engines/kyra/saveload.cpp +++ b/engines/kyra/saveload.cpp @@ -126,7 +126,7 @@ KyraEngine_v1::kReadSaveHeaderError KyraEngine_v1::readSaveHeader(Common::Seekab } } - return (in->ioFailed() ? kRSHEIoError : kRSHENoError); + return ((in->err() || in->eos()) ? kRSHEIoError : kRSHENoError); } Common::SeekableReadStream *KyraEngine_v1::openSaveForReading(const char *filename, SaveHeader &header) { @@ -168,7 +168,7 @@ Common::SeekableReadStream *KyraEngine_v1::openSaveForReading(const char *filena delete in; return 0; } else if ((header.flags & GF_FMTOWNS) && !(_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98)) { - warning("Can not load FM-Towns/PC98 savefile for this (non FM-Towns/PC98) gameversion"); + warning("Can not load FM-TOWNS/PC98 savefile for this (non FM-TOWNS/PC98) gameversion"); delete in; return 0; } diff --git a/engines/kyra/saveload_lok.cpp b/engines/kyra/saveload_lok.cpp index c481794e53..c59f2bebf6 100644 --- a/engines/kyra/saveload_lok.cpp +++ b/engines/kyra/saveload_lok.cpp @@ -167,7 +167,6 @@ Common::Error KyraEngine_LoK::loadGameState(int slot) { } } - _screen->_disableScreen = true; loadMainScreen(8); if (queryGameFlag(0x2D)) { @@ -185,19 +184,16 @@ Common::Error KyraEngine_LoK::loadGameState(int slot) { setHandItem(_itemInHand); _animator->setBrandonAnimSeqSize(3, 48); redrawInventory(0); - _animator->_noDrawShapesFlag = 1; + _brandonPosX = brandonX; + _brandonPosY = brandonY; enterNewScene(_currentCharacter->sceneId, _currentCharacter->facing, 0, 0, 1); - _animator->_noDrawShapesFlag = 0; - _currentCharacter->x1 = brandonX; - _currentCharacter->y1 = brandonY; _animator->animRefreshNPC(0); _animator->restoreAllObjectBackgrounds(); _animator->preserveAnyChangedBackgrounds(); _animator->prepDrawAllObjects(); _animator->copyChangedObjectsForward(0); _screen->copyRegion(8, 8, 8, 8, 304, 128, 2, 0); - _screen->_disableScreen = false; _screen->updateScreen(); setMousePos(brandonX, brandonY); diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index 945495517f..32ee7a4d77 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -552,14 +552,14 @@ void LoLEngine::updateLampStatus() { if (_lampEffect == -1) { if (_screen->_fadeFlag == 0) setPaletteBrightness(_screen->getPalette(0), _brightness, newLampEffect); - _lampStatusTimer = _system->getMillis() + (10 + _rnd.getRandomNumberRng(1, 30)) * _tickLength; + _lampStatusTimer = _system->getMillis() + (10 + rollDice(1, 30)) * _tickLength; } else { if ((_lampEffect & 0xfe) == (newLampEffect & 0xfe)) { if (_system->getMillis() <= _lampStatusTimer) { newLampEffect = _lampEffect; } else { newLampEffect = _lampEffect ^ 1; - _lampStatusTimer = _system->getMillis() + (10 + _rnd.getRandomNumberRng(1, 30)) * _tickLength; + _lampStatusTimer = _system->getMillis() + (10 + rollDice(1, 30)) * _tickLength; } } else { if (_screen->_fadeFlag == 0) diff --git a/engines/kyra/scene_v2.cpp b/engines/kyra/scene_v2.cpp index 9ffaf5515d..3def71a076 100644 --- a/engines/kyra/scene_v2.cpp +++ b/engines/kyra/scene_v2.cpp @@ -73,7 +73,7 @@ void KyraEngine_v2::runSceneScript6() { _sceneScriptState.regs[0] = _mainCharacter.sceneId; _sceneScriptState.regs[1] = _mouseX; _sceneScriptState.regs[2] = _mouseY; - _sceneScriptState.regs[3] = _itemInHand; + _sceneScriptState.regs[4] = _itemInHand; _emc->start(&_sceneScriptState, 6); while (_emc->isValid(&_sceneScriptState)) diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index fa54bffa98..6c2c48cb02 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -26,7 +26,10 @@ #include "common/endian.h" #include "common/system.h" + #include "graphics/cursorman.h" +#include "graphics/sjis.h" + #include "kyra/screen.h" #include "kyra/kyra_v1.h" #include "kyra/resource.h" @@ -43,6 +46,8 @@ Screen::Screen(KyraEngine_v1 *vm, OSystem *system) _drawShapeVar3 = 1; _drawShapeVar4 = 0; _drawShapeVar5 = 0; + + _sjisFont = 0; } Screen::~Screen() { @@ -56,8 +61,7 @@ Screen::~Screen() { _fonts[f].fontData = NULL; } - delete[] _sjisFontData; - delete[] _sjisTempPage; + delete _sjisFont; delete _screenPalette; delete _internFadePalette; delete[] _decodeShapeBuffer; @@ -70,7 +74,6 @@ Screen::~Screen() { } bool Screen::init() { - _disableScreen = false; _debugEnabled = false; memset(_sjisOverlayPtrs, 0, sizeof(_sjisOverlayPtrs)); @@ -78,8 +81,6 @@ bool Screen::init() { _useSJIS = false; _use16ColorMode = _vm->gameFlags().use16ColorMode; - _sjisTempPage = _sjisFontData = 0; - if (_vm->gameFlags().useHiResOverlay) { _useOverlays = true; _useSJIS = (_vm->gameFlags().lang == Common::JA_JPN); @@ -94,14 +95,17 @@ bool Screen::init() { } if (_useSJIS) { - if (!_sjisFontData) { - // we use the FM-Towns font rom for PC-98, too, until we feel + if (!_sjisFont) { + // we use the FM-TOWNS font rom for PC-98, too, until we feel // like adding support for the PC-98 font //if (_vm->gameFlags().platform == Common::kPlatformFMTowns) { - // FM-Towns - _sjisFontData = _vm->resource()->fileData("FMT_FNT.ROM", 0); - if (!_sjisFontData) - error("missing font rom ('FMT_FNT.ROM') required for this version"); + // FM-TOWNS + Common::SeekableReadStream *rom = _vm->resource()->createReadStream("FMT_FNT.ROM"); + Graphics::FontTowns *townsFont = new Graphics::FontTowns(); + if (!rom || !townsFont || !townsFont->loadFromStream(*rom)) + error("Could not load font rom ('FMT_FNT.ROM') required for this version"); + _sjisFont = townsFont; + delete rom; /*} else { // PC-98 _sjisFontData = _vm->resource()->fileData("FONT.ROM", 0); @@ -109,16 +113,12 @@ bool Screen::init() { error("missing font rom ('FONT.ROM') required for this version"); }*/ } - - if (!_sjisTempPage) { - _sjisTempPage = new uint8[420]; - assert(_sjisTempPage); - _sjisTempPage2 = _sjisTempPage + 60; - _sjisSourceChar = _sjisTempPage + 384; - } + + _sjisFont->enableOutline(!_use16ColorMode); } } + _curPage = 0; uint8 *pagePtr = new uint8[SCREEN_PAGE_SIZE * 8]; for (int pageNum = 0; pageNum < SCREEN_PAGE_NUM; pageNum += 2) @@ -218,9 +218,6 @@ void Screen::setResolution() { } void Screen::updateScreen() { - if (_disableScreen) - return; - if (_useOverlays) updateDirtyRectsOvl(); else @@ -657,7 +654,7 @@ void Screen::copyToPage0(int y, int h, uint8 page, uint8 *seqBuf) { } addDirtyRect(0, y, SCREEN_W, h); // This would remove the text in the end sequence of - // the (Kyrandia 1) FM-Towns version. + // the (Kyrandia 1) FM-TOWNS version. // Since this method is just used for the Seqplayer // this shouldn't be a problem anywhere else, so it's // safe to disable the call here. @@ -1027,8 +1024,8 @@ int Screen::getCharWidth(uint16 c) const { if (_vm->gameFlags().platform == Common::kPlatformAmiga) return 0; - if (c & 0xFF00) - return SJIS_CHARSIZE >> 1; + if ((c & 0xFF00) && _sjisFont) + return _sjisFont->getFontWidth() >> 1; if (_fonts[_currentFont].lastGlyph < c) return 0; @@ -1115,7 +1112,7 @@ void Screen::printText(const char *str, int x, int y, uint8 color1, uint8 color2 c = READ_LE_UINT16(str - 1); ++str; charWidth = getCharWidth(c); - charHeight = SJIS_CHARSIZE >> 1; + charHeight = _sjisFont->getFontHeight() >> 1; drawCharSJIS(c, x, y); } @@ -1529,6 +1526,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int _dsTmpWidth = shapeWidth; int cnt = _dsOffscreenLeft; int scaleState = (this->*_dsProcessMargin)(d, src, cnt); + if (_dsTmpWidth) { cnt += shpWidthScaled1; if (cnt > 0) { @@ -1584,7 +1582,6 @@ int Screen::drawShapeMarginScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt) while (cnt > 0) { --cnt; - if (*src++) continue; @@ -1611,7 +1608,6 @@ int Screen::drawShapeMarginScaleDownwind(uint8 *&dst, const uint8 *&src, int &cn while (cnt > 0) { --cnt; - if (*src++) continue; @@ -1640,10 +1636,11 @@ int Screen::drawShapeSkipScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt) { return 0; do { + --cnt; if (*src++) continue; cnt = cnt + 1 - (*src++); - } while (--cnt > 0); + } while (cnt > 0); return 0; } @@ -1656,16 +1653,17 @@ int Screen::drawShapeSkipScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt) return 0; do { + --cnt; if (*src++) continue; found = true; cnt = cnt + 1 - (*src++); - } while (--cnt > 0); + } while (cnt > 0); return found ? 0 : _dsOffscreenScaleVal1; } -void Screen::drawShapeProcessLineNoScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16) { +void Screen::drawShapeProcessLineNoScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, int16) { do { uint8 c = *src++; if (c) { @@ -1680,7 +1678,7 @@ void Screen::drawShapeProcessLineNoScaleUpwind(uint8 *&dst, const uint8 *&src, i } while (cnt > 0); } -void Screen::drawShapeProcessLineNoScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16) { +void Screen::drawShapeProcessLineNoScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, int16) { do { uint8 c = *src++; if (c) { @@ -1695,7 +1693,7 @@ void Screen::drawShapeProcessLineNoScaleDownwind(uint8 *&dst, const uint8 *&src, } while (cnt > 0); } -void Screen::drawShapeProcessLineScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState) { +void Screen::drawShapeProcessLineScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState) { int c = 0; do { @@ -1723,7 +1721,7 @@ void Screen::drawShapeProcessLineScaleUpwind(uint8 *&dst, const uint8 *&src, int cnt = -1; } -void Screen::drawShapeProcessLineScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState) { +void Screen::drawShapeProcessLineScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState) { int c = 0; do { @@ -3006,93 +3004,6 @@ void Screen::copyOverlayRegion(int x, int y, int x2, int y2, int w, int h, int s } } -// SJIS rendering - -namespace { -int SJIStoFMTChunk(int f, int s) { // copied from scumm\charset.cpp - enum { - KANA = 0, - KANJI = 1, - EKANJI = 2 - }; - int base = s - ((s + 1) % 32); - int c = 0, p = 0, chunk_f = 0, chunk = 0, cr = 0, kanjiType = KANA; - - if (f >= 0x81 && f <= 0x84) kanjiType = KANA; - if (f >= 0x88 && f <= 0x9f) kanjiType = KANJI; - if (f >= 0xe0 && f <= 0xea) kanjiType = EKANJI; - - if ((f > 0xe8 || (f == 0xe8 && base >= 0x9f)) || (f > 0x90 || (f == 0x90 && base >= 0x9f))) { - c = 48; //correction - p = -8; //correction - } - - if (kanjiType == KANA) {//Kana - chunk_f = (f - 0x81) * 2; - } else if (kanjiType == KANJI) {//Standard Kanji - p += f - 0x88; - chunk_f = c + 2 * p; - } else if (kanjiType == EKANJI) {//Enhanced Kanji - p += f - 0xe0; - chunk_f = c + 2 * p; - } - - // Base corrections - if (base == 0x7f && s == 0x7f) - base -= 0x20; - if (base == 0x9f && s == 0xbe) - base += 0x20; - if (base == 0xbf && s == 0xde) - base += 0x20; - //if (base == 0x7f && s == 0x9e) - // base += 0x20; - - switch (base) { - case 0x3f: - cr = 0; //3f - if (kanjiType == KANA) chunk = 1; - else if (kanjiType == KANJI) chunk = 31; - else if (kanjiType == EKANJI) chunk = 111; - break; - case 0x5f: - cr = 0; //5f - if (kanjiType == KANA) chunk = 17; - else if (kanjiType == KANJI) chunk = 47; - else if (kanjiType == EKANJI) chunk = 127; - break; - case 0x7f: - cr = -1; //80 - if (kanjiType == KANA) chunk = 9; - else if (kanjiType == KANJI) chunk = 63; - else if (kanjiType == EKANJI) chunk = 143; - break; - case 0x9f: - cr = 1; //9e - if (kanjiType == KANA) chunk = 2; - else if (kanjiType == KANJI) chunk = 32; - else if (kanjiType == EKANJI) chunk = 112; - break; - case 0xbf: - cr = 1; //be - if (kanjiType == KANA) chunk = 18; - else if (kanjiType == KANJI) chunk = 48; - else if (kanjiType == EKANJI) chunk = 128; - break; - case 0xdf: - cr = 1; //de - if (kanjiType == KANA) chunk = 10; - else if (kanjiType == KANJI) chunk = 64; - else if (kanjiType == EKANJI) chunk = 144; - break; - default: - debug(4, "Invalid Char! f %x s %x base %x c %d p %d", f, s, base, c, p); - } - - debug(6, "Kanji: %c%c f 0x%x s 0x%x base 0x%x c %d p %d chunk %d cr %d index %d", f, s, f, s, base, c, p, chunk, cr, ((chunk_f + chunk) * 32 + (s - base)) + cr); - return ((chunk_f + chunk) * 32 + (s - base)) + cr; -} -} // end of anonymous namespace - void Screen::drawCharSJIS(uint16 c, int x, int y) { int color1, color2; @@ -3104,14 +3015,13 @@ void Screen::drawCharSJIS(uint16 c, int x, int y) { } else { color1 = _textColorsMap[1]; color2 = _textColorsMap[0]; - } - memset(_sjisTempPage2, _sjisInvisibleColor, 324); - memset(_sjisSourceChar, 0, 36); - memcpy(_sjisSourceChar, _sjisFontData + 0x20 * SJIStoFMTChunk(c & 0xff, c >> 8), 0x20); + if (color2 == _sjisInvisibleColor) + _sjisFont->enableOutline(false); + } if (_curPage == 0 || _curPage == 1) - addDirtyRect(x, y, SJIS_CHARSIZE >> 1, SJIS_CHARSIZE >> 1); + addDirtyRect(x, y, _sjisFont->getFontWidth() >> 1, _sjisFont->getFontHeight() >> 1); x <<= 1; y <<= 1; @@ -3123,154 +3033,10 @@ void Screen::drawCharSJIS(uint16 c, int x, int y) { } destPage += y * 640 + x; - uint8 *src = 0, *dst = 0; - if (color2 != _sjisInvisibleColor) { - // draw color2 shadow - src = _sjisSourceChar; - dst = _sjisTempPage2; - - for (int i = 0; i < SJIS_CHARSIZE; i++) { - *((uint16*)dst) = READ_LE_UINT16(src); - dst += 2; src += 2; - *dst++ = 0; - } + _sjisFont->drawChar(destPage, c, 640, 1, color1, color2); - src = _sjisTempPage2; - dst = _sjisTempPage; - memset(dst, 0, 60); - for (int i = 0; i < 48; i++) - *dst++ |= *src++; - - src = _sjisTempPage2; - dst = _sjisTempPage + 3; - for (int i = 0; i < 48; i++) - *dst++ |= *src++; - - src = _sjisTempPage2; - dst = _sjisTempPage + 6; - for (int i = 0; i < 48; i++) - *dst++ |= *src++; - - for (int i = 0; i < 2; i++) { - src = _sjisTempPage; - for (int ii = 0; ii < SJIS_CHARSIZE; ii++) { - uint8 cy2 = 0; - uint8 cy1 = 0; - for (int iii = 0; iii < 3; iii++) { - cy1 = *src & 1; - *src |= ((*src >> 1) | (cy2 << 7)); - cy2 = cy1; - src++; - } - } - } - - src = _sjisTempPage2; - for (int i = 0; i < SJIS_CHARSIZE; i++) { - uint8 cy2 = 0; - uint8 cy1 = 0; - for (int ii = 0; ii < 3; ii++) { - cy1 = *src & 1; - *src = ((*src >> 1) | (cy2 << 7)); - cy2 = cy1; - src++; - } - } - - src = _sjisTempPage2; - dst = _sjisTempPage + 3; - for (int i = 0; i < 48; i++) - *dst++ ^= *src++; - - memset(_sjisTempPage2, _sjisInvisibleColor, 324); - src = _sjisTempPage; - dst = _sjisTempPage2; - - uint8 height = SJIS_CHARSIZE * 3; - uint8 width = SJIS_CHARSIZE; - if (color2 & 0xff00) { - height -= 3; - width--; - dst += 0x13; - } - - for (int i = 0; i < height; i++) { - uint8 rs = *src++; - for (int ii = 0; ii < 8; ii++) { - if (rs & 0x80) - *dst = (color2 & 0xff); - rs <<= 1; - dst++; - - if (!--width) { - width = SJIS_CHARSIZE; - if (color2 & 0xff00) { - width--; - dst++; - } - break; - } - } - } - } - - // draw color1 char - src = _sjisSourceChar; - dst = _sjisTempPage; - - for (int i = 0; i < SJIS_CHARSIZE; i++) { - *(uint16*)dst = READ_LE_UINT16(src); - dst += 2; src += 2; - *dst++ = 0; - } - - src = _sjisTempPage; - dst = _sjisTempPage2; - if (color2 != _sjisInvisibleColor) - color1 = (color1 & 0xff) | 0x100; - - uint8 height = SJIS_CHARSIZE * 3; - uint8 width = SJIS_CHARSIZE; - if (color1 & 0xff00) { - height -= 3; - width--; - dst += 0x13; - } - - for (int i = 0; i < height; i++) { - uint8 rs = *src++; - for (int ii = 0; ii < 8; ii++) { - if (rs & 0x80) - *dst = (color1 & 0xff); - rs <<= 1; - dst++; - - if (!--width) { - width = SJIS_CHARSIZE; - if (color1 & 0xff00) { - width--; - dst++; - } - break; - } - } - } - - // copy char to surface - src = _sjisTempPage2; - dst = destPage; - int pitch = 640 - SJIS_CHARSIZE; - - for (int i = 0; i < SJIS_CHARSIZE; i++) { - for (int ii = 0; ii < SJIS_CHARSIZE; ii++) { - if (*src != _sjisInvisibleColor) - *dst = *src; - src++; - dst++; - } - dst += pitch; - } + _sjisFont->enableOutline(!_use16ColorMode); } #pragma mark - diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index 390d058bb8..d8380d104d 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -35,6 +35,10 @@ class OSystem; +namespace Graphics { +class FontSJIS; +} // end of namespace Graphics + namespace Kyra { typedef Common::Functor0<void> UpdateFunctor; @@ -331,7 +335,6 @@ public: uint8 *_shapePages[2]; int _maskMinY, _maskMaxY; FontId _currentFont; - bool _disableScreen; // decoding functions static void decodeFrame3(const uint8 *src, uint8 *dst, uint32 size); @@ -360,11 +363,6 @@ protected: void drawCharANSI(uint8 c, int x, int y); void drawCharSJIS(uint16 c, int x, int y); - enum { - SJIS_CHARSIZE = 18, - SJIS_CHARS = 8192 - }; - int16 encodeShapeAndCalculateSize(uint8 *from, uint8 *to, int size); template<bool noXor> static void wrapped_decodeFrameDelta(uint8 *dst, const uint8 *src); @@ -377,10 +375,7 @@ protected: bool _useSJIS; bool _use16ColorMode; - uint8 *_sjisFontData; - uint8 *_sjisTempPage; - uint8 *_sjisTempPage2; - uint8 *_sjisSourceChar; + Graphics::FontSJIS *_sjisFont; uint8 _sjisInvisibleColor; Palette *_screenPalette; @@ -421,10 +416,10 @@ protected: int drawShapeMarginScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt); int drawShapeSkipScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt); int drawShapeSkipScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt); - void drawShapeProcessLineNoScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState); - void drawShapeProcessLineNoScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState); - void drawShapeProcessLineScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState); - void drawShapeProcessLineScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState); + void drawShapeProcessLineNoScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState); + void drawShapeProcessLineNoScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState); + void drawShapeProcessLineScaleUpwind(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState); + void drawShapeProcessLineScaleDownwind(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState); void drawShapePlotType0(uint8 *dst, uint8 cmd); void drawShapePlotType1(uint8 *dst, uint8 cmd); @@ -446,7 +441,7 @@ protected: void drawShapePlotType52(uint8 *dst, uint8 cmd); typedef int (Screen::*DsMarginSkipFunc)(uint8 *&dst, const uint8 *&src, int &cnt); - typedef void (Screen::*DsLineFunc)(uint8 *&dst, const uint8 *&src, int &cnt, uint16 scaleState); + typedef void (Screen::*DsLineFunc)(uint8 *&dst, const uint8 *&src, int &cnt, int16 scaleState); typedef void (Screen::*DsPlotFunc)(uint8 *dst, uint8 cmd); DsMarginSkipFunc _dsProcessMargin; diff --git a/engines/kyra/screen_lol.cpp b/engines/kyra/screen_lol.cpp index b9bf9961c5..ce8a1bdaa4 100644 --- a/engines/kyra/screen_lol.cpp +++ b/engines/kyra/screen_lol.cpp @@ -44,8 +44,6 @@ Screen_LoL::Screen_LoL(LoLEngine *vm, OSystem *system) : Screen_v2(vm, system), _fadeFlag = 2; _curDimIndex = 0; - - _internDimX = _internDimY = _internDimW = _internDimH = _internDimDstX = _internBlockWidth = _internDimDstY = _internBlockHeight = _internDimU5 = _internDimU6 = _internBlockWidth2 = _internDimU8 = 0; } Screen_LoL::~Screen_LoL() { @@ -588,44 +586,25 @@ void Screen_LoL::copyRegionSpecial(int page1, int w1, int h1, int x1, int y1, in va_end(args); } - // _internDimH: h0 -// _internDimW: w0 -// _internDimDstX: x1 -// _internDimDstY: y1 -// _internBlockWidth: w1 -// _internBlockHeight: h1 -// _internDimU5: x2 -// _internDimU6: y2 -// _internBlockWidth2: w2 - - _internDimX = _internDimY = 0; - _internDimW = w1; - _internDimH = h1; - calcBoundariesIntern(x1, y1, w3, h3); - if (_internBlockWidth == -1) + int na = 0, nb = 0, nc = w3; + if (!calcBounds(w1, h1, x1, y1, w3, h3, na, nb, nc)) return; - int iu5_1 = _internDimU5; - int iu6_1 = _internDimU6; - int ibw_1 = _internBlockWidth; - int ibh_1 = _internBlockHeight; - int dx_1 = _internDimDstX; - int dy_1 = _internDimDstY; - - _internDimX = _internDimY = 0; - _internDimW = w2; - _internDimH = h2; + int iu5_1 = na; + int iu6_1 = nb; + int ibw_1 = w3; + int dx_1 = x1; + int dy_1 = y1; - calcBoundariesIntern(x2, y2, ibw_1, ibh_1); - if (_internBlockWidth == -1) + if (!calcBounds(w2, h2, x2, y2, w3, h3, na, nb, nc)) return; - int iu5_2 = _internDimU5; - int iu6_2 = _internDimU6; - int ibw_2 = _internBlockWidth; - int ibh_2 = _internBlockHeight; - int dx_2 = _internDimDstX; - int dy_2 = _internDimDstY; + int iu5_2 = na; + int iu6_2 = nb; + int ibw_2 = w3; + int ibh_2 = h3; + int dx_2 = x2; + int dy_2 = y2; uint8 *src = getPagePtr(page1) + (dy_1 + iu6_2) * w1; uint8 *dst = getPagePtr(page2) + (dy_2 + iu6_1) * w2; @@ -670,7 +649,7 @@ void Screen_LoL::copyRegionSpecial(int page1, int w1, int h1, int x1, int y1, in } if (!page2) - addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight); + addDirtyRect(x2, y2, w2, h2); } void Screen_LoL::copyBlockAndApplyOverlay(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl) { @@ -678,23 +657,23 @@ void Screen_LoL::copyBlockAndApplyOverlay(int page1, int x1, int y1, int page2, return; const ScreenDim *cdim = getScreenDim(dim); - _internDimX = cdim->sx << 3; - _internDimY = cdim->sy; - _internDimW = cdim->w << 3; - _internDimH = cdim->h; + int ix = cdim->sx << 3; + int iy = cdim->sy; + int iw = cdim->w << 3; + int ih = cdim->h; - calcBoundariesIntern(x2, y2, w, h); - if (_internBlockWidth == -1) + int na = 0, nb = 0, nc = w; + if (!calcBounds(iw, ih, x2, y2, w, h, na, nb, nc)) return; uint8 *src = getPagePtr(page1) + y1 * 320 + x1; - uint8 *dst = getPagePtr(page2) + (_internDimDstY + _internDimY) * 320; + uint8 *dst = getPagePtr(page2) + (y2 + iy) * 320; - for (int i = 0; i < _internBlockHeight; i++) { - uint8 *s = src + _internDimU5; - uint8 *d = dst + (_internDimDstX + _internDimX); + for (int i = 0; i < h; i++) { + uint8 *s = src + na; + uint8 *d = dst + (x2 + ix); - for (int ii = 0; ii < _internBlockWidth; ii++) { + for (int ii = 0; ii < w; ii++) { uint8 p = ovl[*s++]; if (p) *d = p; @@ -706,7 +685,7 @@ void Screen_LoL::copyBlockAndApplyOverlay(int page1, int x1, int y1, int page2, } if (!page2) - addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight); + addDirtyRect(x2 + ix, y2 + iy, w, h); } void Screen_LoL::applyOverlaySpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, int flag, uint8 *ovl) { @@ -714,26 +693,26 @@ void Screen_LoL::applyOverlaySpecial(int page1, int x1, int y1, int page2, int x return; const ScreenDim *cdim = getScreenDim(dim); - _internDimX = cdim->sx << 3; - _internDimY = cdim->sy; - _internDimW = cdim->w << 3; - _internDimH = cdim->h; + int ix = cdim->sx << 3; + int iy = cdim->sy; + int iw = cdim->w << 3; + int ih = cdim->h; - calcBoundariesIntern(x2, y2, w, h); - if (_internBlockWidth == -1) + int na = 0, nb = 0, nc = w; + if (!calcBounds(iw, ih, x2, y2, w, h, na, nb, nc)) return; uint8 *src = getPagePtr(page1) + y1 * 320 + x1; - uint8 *dst = getPagePtr(page2) + (_internDimDstY + _internDimY) * 320; + uint8 *dst = getPagePtr(page2) + (y2 + iy) * 320; - for (int i = 0; i < _internBlockHeight; i++) { - uint8 *s = src + _internDimU5; - uint8 *d = dst + (_internDimDstX + _internDimX); + for (int i = 0; i < h; i++) { + uint8 *s = src + na; + uint8 *d = dst + (x2 + ix); if (flag) d += (i >> 1); - for (int ii = 0; ii < _internBlockWidth; ii++) { + for (int ii = 0; ii < w; ii++) { if (*s++) *d = ovl[*d]; d++; @@ -744,7 +723,7 @@ void Screen_LoL::applyOverlaySpecial(int page1, int x1, int y1, int page2, int x } if (!page2) - addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight); + addDirtyRect(x2 + ix, y2 + iy, w, h); } void Screen_LoL::copyBlockAndApplyOverlayOutro(int srcPage, int dstPage, const uint8 *ovl) { @@ -778,59 +757,6 @@ void Screen_LoL::copyBlockAndApplyOverlayOutro(int srcPage, int dstPage, const u } } -void Screen_LoL::calcBoundariesIntern(int dstX, int dstY, int width, int height) { - _internBlockWidth = _internBlockWidth2 = width; - _internBlockHeight = height; - _internDimDstX = dstX; - _internDimDstY = dstY; - - _internDimU5 = _internDimU6 = _internDimU8 = 0; - - int t = _internDimDstX + _internBlockWidth; - if (t <= 0) { - _internBlockWidth = _internBlockHeight = -1; - return; - } - - if (t <= _internDimDstX) { - _internDimU5 = _internBlockWidth - t; - _internBlockWidth = t; - _internDimDstX = 0; - } - - t = _internDimW - _internDimDstX; - if (t <= 0) { - _internBlockWidth = _internBlockHeight = -1; - return; - } - - if (t <= _internBlockWidth) - _internBlockWidth = t; - - _internBlockWidth2 -= _internBlockWidth; - - t = _internDimDstY + _internBlockHeight; - if (t <= 0) { - _internBlockWidth = _internBlockHeight = -1; - return; - } - - if (t <= _internDimDstY) { - _internDimU6 = _internBlockHeight - t; - _internBlockHeight = t; - _internDimDstY = 0; - } - - t = _internDimH - _internDimDstY; - if (t <= 0) { - _internBlockWidth = _internBlockHeight = -1; - return; - } - - if (t <= _internBlockHeight) - _internBlockHeight = t; -} - void Screen_LoL::fadeToBlack(int delay, const UpdateFunctor *upFunc) { Screen::fadeToBlack(delay, upFunc); _fadeFlag = 2; @@ -986,7 +912,7 @@ void Screen_LoL::mergeOverlay(int x, int y, int w, int h) { void Screen_LoL::convertPC98Gfx(uint8 *data, int w, int h, int pitch) { while (h--) { for (int i = 0; i < w; ++i) { - *data = _paletteConvTable[*data]; + *data = (*data >> 4) & (*data & 0x0F); ++data; } @@ -1001,7 +927,7 @@ void Screen_LoL::postProcessCursor(uint8 *data, int w, int h, int pitch) { while (h--) { for (int i = 0; i < w; ++i) { if (*data != _cursorColorKey) - *data = _paletteConvTable[*data]; + *data = (*data >> 4) & (*data & 0x0F); ++data; } diff --git a/engines/kyra/screen_lol.h b/engines/kyra/screen_lol.h index db355977f8..4980a89694 100644 --- a/engines/kyra/screen_lol.h +++ b/engines/kyra/screen_lol.h @@ -46,8 +46,8 @@ public: int curDimIndex() { return _curDimIndex; } void modifyScreenDim(int dim, int x, int y, int w, int h); - void fprintString(const char *format, int x, int y, uint8 col1, uint8 col2, uint16 flags, ...); - void fprintStringIntro(const char *format, int x, int y, uint8 c1, uint8 c2, uint8 c3, uint16 flags, ...); + void fprintString(const char *format, int x, int y, uint8 col1, uint8 col2, uint16 flags, ...) GCC_PRINTF(2, 8); + void fprintStringIntro(const char *format, int x, int y, uint8 c1, uint8 c2, uint8 c3, uint16 flags, ...) GCC_PRINTF(2, 9); void drawGridBox(int x, int y, int w, int h, int col); void fadeClearSceneWindow(int delay); @@ -109,25 +109,8 @@ private: uint8 *_levelOverlays[8]; - static const uint8 _paletteConvTable[256]; void mergeOverlay(int x, int y, int w, int h); void postProcessCursor(uint8 *data, int width, int height, int pitch); - - // magic atlas - void calcBoundariesIntern(int dstX, int dstY, int c, int d); - - int _internDimX; - int _internDimY; - int _internDimW; - int _internDimH; - int _internDimDstX; - int _internBlockWidth; - int _internDimDstY; - int _internBlockHeight; - int _internDimU5; - int _internDimU6; - int _internBlockWidth2; - int _internDimU8; }; } // end of namespace Kyra diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp index 0473f03591..726c013b5a 100644 --- a/engines/kyra/script.cpp +++ b/engines/kyra/script.cpp @@ -125,7 +125,7 @@ bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Commo error("No DATA chunk found in file: '%s'", filename); if (stream->err()) - error("Read error while parsing file '%s", filename); + error("Read error while parsing file '%s'", filename); delete stream; diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index a606419722..e4b77f6a07 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -135,6 +135,11 @@ int LoLEngine::olol_drawScene(EMCState *script) { return 1; } +int LoLEngine::olol_rollDice(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_rollDice(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + return rollDice(stackPos(0), stackPos(1)); +} + int LoLEngine::olol_moveParty(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_moveParty(%p) (%d)", (const void *)script, stackPos(0)); int mode = stackPos(0); @@ -831,10 +836,10 @@ int LoLEngine::olol_initMonster(EMCState *script) { l->hitPoints = (l->properties->hitPoints * _monsterModifiers[_monsterDifficulty]) >> 8; if (_currentLevel == 12 && l->type == 2) - l->hitPoints = (l->hitPoints * (_rnd.getRandomNumberRng(1, 128) + 192)) >> 8; + l->hitPoints = (l->hitPoints * (rollDice(1, 128) + 192)) >> 8; l->numDistAttacks = l->properties->numDistAttacks; - l->distAttackTick = _rnd.getRandomNumberRng(1, calcMonsterSkillLevel(l->id | 0x8000, 8)) - 1; + l->distAttackTick = rollDice(1, calcMonsterSkillLevel(l->id | 0x8000, 8)) - 1; l->flyingHeight = 2; l->flags = stackPos(5); l->assignedItems = 0; @@ -1366,18 +1371,18 @@ int LoLEngine::olol_characterSkillTest(EMCState *script){ debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_characterSkillTest(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); int skill = stackPos(0); int n = countActiveCharacters(); - uint m = 0; + int m = 0; int c = 0; for (int i = 0; i < n ; i++) { - uint v = _characters[i].skillModifiers[skill] + _characters[i].skillLevels[skill] + 25; + int v = _characters[i].skillModifiers[skill] + _characters[i].skillLevels[skill] + 25; if (v > m) { m = v; c = i; } } - return (_rnd.getRandomNumberRng(1, 100) > m) ? -1 : c; + return (rollDice(1, 100) > m) ? -1 : c; } int LoLEngine::olol_countAllMonsters(EMCState *script){ @@ -1440,7 +1445,7 @@ int LoLEngine::olol_calcInflictableDamage(EMCState *script) { int LoLEngine::olol_getInflictedDamage(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getInflictedDamage(%p) (%d)", (const void *)script, stackPos(0)); int mx = stackPos(0); - return mx ? _rnd.getRandomNumberRng(2, mx) : 0; + return rollDice(2, mx); } int LoLEngine::olol_checkForCertainPartyMember(EMCState *script) { @@ -2340,8 +2345,8 @@ int LoLEngine::tlol_processWsaFrame(const TIM *tim, const uint16 *param) { int h2 = (h1 * factor) / 100; anim->wsa->displayFrame(frame, 2, x1, y1, anim->wsaCopyParams & 0xF0FF, 0, 0); - _screen->wsaFrameAnimationStep(x1, y1, x2, y2, w1, h1, w2, h2, 2, _flags.isDemo ? 0 : 8, 0); - if (!_flags.isDemo) + _screen->wsaFrameAnimationStep(x1, y1, x2, y2, w1, h1, w2, h2, 2, _flags.isDemo && _flags.platform != Common::kPlatformPC98 ? 0 : 8, 0); + if (!_flags.isDemo && _flags.platform != Common::kPlatformPC98) _screen->checkedPageUpdate(8, 4); _screen->updateScreen(); @@ -2617,7 +2622,7 @@ void LoLEngine::setupOpcodeTable() { Opcode(olol_setWallType); Opcode(olol_getWallType); Opcode(olol_drawScene); - Opcode(o1_getRand); + Opcode(olol_rollDice); // 0x04 Opcode(olol_moveParty); diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index 424a62aaf8..731b8d206f 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -98,7 +98,10 @@ TIMInterpreter::TIMInterpreter(KyraEngine_v1 *engine, Screen_v2 *screen_v2, OSys _textDisplayed = false; _textAreaBuffer = new uint8[320*40]; assert(_textAreaBuffer); - _drawPage2 = (_vm->gameFlags().isDemo && _vm->gameFlags().gameID == GI_LOL) ? 0 : 8; + if ((_vm->gameFlags().platform == Common::kPlatformPC98 || _vm->gameFlags().isDemo) && _vm->gameFlags().gameID == GI_LOL) + _drawPage2 = 0; + else + _drawPage2 = 8; _palDelayInc = _palDiff = _palDelayAcc = 0; _abortFlag = 0; @@ -169,7 +172,7 @@ TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpc error("No AVTL chunk found in file: '%s'", filename); if (stream->err()) - error("Read error while parsing file '%s", filename); + error("Read error while parsing file '%s'", filename); delete stream; @@ -461,7 +464,10 @@ TIMInterpreter::Animation *TIMInterpreter::initAnimStruct(int index, const char anim->wsaCopyParams = wsaFlags; const bool isLoLDemo = _vm->gameFlags().isDemo && _vm->gameFlags().gameID == GI_LOL; - _drawPage2 = (isLoLDemo || _currentTim->isLoLOutro) ? 0 : 8; + if (isLoLDemo || _vm->gameFlags().platform == Common::kPlatformPC98 || _currentTim->isLoLOutro) + _drawPage2 = 0; + else + _drawPage2 = 8; uint16 wsaOpenFlags = 0; if (isLoLDemo) { diff --git a/engines/kyra/sequences_hof.cpp b/engines/kyra/sequences_hof.cpp index 90b2fdd580..81ab237e0f 100644 --- a/engines/kyra/sequences_hof.cpp +++ b/engines/kyra/sequences_hof.cpp @@ -770,12 +770,12 @@ int KyraEngine_HoF::seq_introDragon(WSAMovie_v2 *wsaObj, int x, int y, int frm) } int KyraEngine_HoF::seq_introDarm(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in fm-towns version) + //NULLSUB (at least in FM-TOWNS version) return frm; } int KyraEngine_HoF::seq_introLibrary2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in fm-towns version) + //NULLSUB (at least in FM-TOWNS version) return frm; } @@ -788,7 +788,7 @@ int KyraEngine_HoF::seq_introMarco(WSAMovie_v2 *wsaObj, int x, int y, int frm) { } int KyraEngine_HoF::seq_introHand1a(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in fm-towns version) + //NULLSUB (at least in FM-TOWNS version) return frm; } @@ -805,12 +805,12 @@ int KyraEngine_HoF::seq_introHand1c(WSAMovie_v2 *wsaObj, int x, int y, int frm) } int KyraEngine_HoF::seq_introHand2(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in fm-towns version) + //NULLSUB (at least in FM-TOWNS version) return frm; } int KyraEngine_HoF::seq_introHand3(WSAMovie_v2 *wsaObj, int x, int y, int frm) { - //NULLSUB (at least in fm-towns version) + //NULLSUB (at least in FM-TOWNS version) return frm; } diff --git a/engines/kyra/sequences_lok.cpp b/engines/kyra/sequences_lok.cpp index d483409090..0279831c9d 100644 --- a/engines/kyra/sequences_lok.cpp +++ b/engines/kyra/sequences_lok.cpp @@ -1049,7 +1049,7 @@ void KyraEngine_LoK::seq_playCredits() { _screen->setTextColorMap(colorMap); _screen->_charWidth = -1; - // we only need this for the fm-towns version + // we only need this for the FM-TOWNS version if (_flags.platform == Common::kPlatformFMTowns && _configMusic == 1) snd_playWanderScoreViaMap(53, 1); diff --git a/engines/kyra/sequences_lol.cpp b/engines/kyra/sequences_lol.cpp index beea129f66..5826b2b09e 100644 --- a/engines/kyra/sequences_lol.cpp +++ b/engines/kyra/sequences_lol.cpp @@ -224,7 +224,7 @@ void LoLEngine::showIntro() { while (!_tim->finished() && !shouldQuit() && !skipFlag()) { updateInput(); _tim->exec(intro, false); - if (!_flags.isDemo) + if (!_flags.isDemo && _flags.platform != Common::kPlatformPC98) _screen->checkedPageUpdate(8, 4); if (_tim->_palDiff) { diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index f393ae15ba..263cd586f7 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -8,32 +8,16 @@ * 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. * - * LGPL License - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - - * This library 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 - * Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * * $URL$ * $Id$ * diff --git a/engines/kyra/sound_adlib.h b/engines/kyra/sound_adlib.h new file mode 100644 index 0000000000..f384113af7 --- /dev/null +++ b/engines/kyra/sound_adlib.h @@ -0,0 +1,113 @@ +/* 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. + * + * LGPL License + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * $URL$ + * $Id$ + * + */ + +#ifndef KYRA_SOUND_ADLIB_H +#define KYRA_SOUND_ADLIB_H + +#include "kyra/sound.h" + +#include "common/mutex.h" + +namespace Kyra { +class AdlibDriver; + +/** + * AdLib implementation of the sound output device. + * + * It uses a special sound file format special to + * Dune II, Kyrandia 1 and 2. While Dune II and + * Kyrandia 1 are using exact the same format, the + * one of Kyrandia 2 slightly differs. + * + * See AdlibDriver for more information. + * @see AdlibDriver + */ +class SoundAdlibPC : public Sound { +public: + SoundAdlibPC(KyraEngine_v1 *vm, Audio::Mixer *mixer); + ~SoundAdlibPC(); + + kType getMusicType() const { return kAdlib; } + + bool init(); + void process(); + + void loadSoundFile(uint file); + void loadSoundFile(Common::String file); + + void playTrack(uint8 track); + void haltTrack(); + bool isPlaying(); + + void playSoundEffect(uint8 track); + + void beginFadeOut(); +private: + void internalLoadFile(Common::String file); + + void play(uint8 track); + + void unk1(); + void unk2(); + + AdlibDriver *_driver; + + bool _v2; + uint8 _trackEntries[500]; + uint8 *_soundDataPtr; + int _sfxPlayingSound; + + Common::String _soundFileLoaded; + + uint8 _sfxPriority; + uint8 _sfxFourthByteOfSong; + + int _numSoundTriggers; + const int *_soundTriggers; + + static const int _kyra1NumSoundTriggers; + static const int _kyra1SoundTriggers[]; +}; + +} // end of namespace Kyra + +#endif + diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h index a41ca2258c..792887ab35 100644 --- a/engines/kyra/sound_intern.h +++ b/engines/kyra/sound_intern.h @@ -8,12 +8,12 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. @@ -27,6 +27,7 @@ #define KYRA_SOUND_INTERN_H #include "kyra/sound.h" +#include "kyra/sound_adlib.h" #include "common/mutex.h" @@ -40,66 +41,6 @@ class MaxTrax; } // end of namespace Audio namespace Kyra { -class AdlibDriver; - -/** - * AdLib implementation of the sound output device. - * - * It uses a special sound file format special to - * Dune II, Kyrandia 1 and 2. While Dune II and - * Kyrandia 1 are using exact the same format, the - * one of Kyrandia 2 slightly differs. - * - * See AdlibDriver for more information. - * @see AdlibDriver - */ -class SoundAdlibPC : public Sound { -public: - SoundAdlibPC(KyraEngine_v1 *vm, Audio::Mixer *mixer); - ~SoundAdlibPC(); - - kType getMusicType() const { return kAdlib; } - - bool init(); - void process(); - - void loadSoundFile(uint file); - void loadSoundFile(Common::String file); - - void playTrack(uint8 track); - void haltTrack(); - bool isPlaying(); - - void playSoundEffect(uint8 track); - - void beginFadeOut(); -private: - void internalLoadFile(Common::String file); - - void play(uint8 track); - - void unk1(); - void unk2(); - - AdlibDriver *_driver; - - bool _v2; - uint8 _trackEntries[500]; - uint8 *_soundDataPtr; - int _sfxPlayingSound; - - Common::String _soundFileLoaded; - - uint8 _sfxPriority; - uint8 _sfxFourthByteOfSong; - - int _numSoundTriggers; - const int *_soundTriggers; - - static const int _kyra1NumSoundTriggers; - static const int _kyra1SoundTriggers[]; -}; - class MidiOutput; /** diff --git a/engines/kyra/sound_pcspk.cpp b/engines/kyra/sound_pcspk.cpp index 22c24bf56c..2afed22a80 100644 --- a/engines/kyra/sound_pcspk.cpp +++ b/engines/kyra/sound_pcspk.cpp @@ -1,25 +1,22 @@ -/* - * 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. +/* ScummVM - Graphic Adventure Engine * - * LGPL License + * 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 library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * 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 library is distributed in the hope that it will be useful, + * 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 - * Lesser General Public License for more details. + * 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 Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $URL$ * $Id$ diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp index 8cee1dc5fc..f644feeb65 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -1071,7 +1071,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) { monster->speedTick = 0; if (monster->properties->flags & 0x40) { - monster->hitPoints += _rnd.getRandomNumberRng(1, 8); + monster->hitPoints += rollDice(1, 8); if (monster->hitPoints > monster->properties->hitPoints) monster->hitPoints = monster->properties->hitPoints; } @@ -1264,7 +1264,7 @@ bool LoLEngine::chasePartyWithDistanceAttacks(MonsterInPlay *monster) { int s = 0; if (monster->flags & 0x10) { - s = monster->properties->numDistWeapons ? _rnd.getRandomNumberRng(1, monster->properties->numDistWeapons) : 0; + s = monster->properties->numDistWeapons ? rollDice(1, monster->properties->numDistWeapons) : 0; } else { s = monster->curDistWeapon++; if (monster->curDistWeapon >= monster->properties->numDistWeapons) @@ -1344,7 +1344,7 @@ void LoLEngine::chasePartyWithCloseAttacks(MonsterInPlay *monster) { if (hit) { int mx = calcInflictableDamage(m, dst, hit); - int dmg = mx ? _rnd.getRandomNumberRng(2, mx) : 0; + int dmg = rollDice(2, mx ); inflictDamage(dst, dmg, m, 0, 0); applyMonsterAttackSkill(monster, dst, dmg); } @@ -1364,7 +1364,7 @@ void LoLEngine::chasePartyWithCloseAttacks(MonsterInPlay *monster) { walkMonster(monster); } else { setMonsterDirection(monster, monster->destDirection); - setMonsterMode(monster, (_rnd.getRandomNumberRng(1, 100) <= 50) ? 4 : 3); + setMonsterMode(monster, (rollDice(1, 100) <= 50) ? 4 : 3); } } diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index e8597c8326..86680a7b76 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -3159,42 +3159,6 @@ const ScreenDim Screen_LoL::_screenDimTable16C[] = { const int Screen_LoL::_screenDimTableCount = ARRAYSIZE(Screen_LoL::_screenDimTable256C); -// 256 -> 16 color conversion table -const uint8 Screen_LoL::_paletteConvTable[256] = { - 0x0, 0x1, 0x0, 0x3, 0x0, 0x5, 0x0, 0x7, - 0x0, 0x9, 0x0, 0xB, 0x0, 0xD, 0x0, 0xF, - 0x1, 0x1, 0x1, 0x3, 0x1, 0x5, 0x1, 0x7, - 0x1, 0x9, 0x1, 0xB, 0x1, 0xD, 0x1, 0xF, - 0x2, 0x1, 0x2, 0x3, 0x2, 0x5, 0x2, 0x7, - 0x2, 0x9, 0x2, 0xB, 0x2, 0xD, 0x2, 0xF, - 0x3, 0x1, 0x3, 0x3, 0x3, 0x5, 0x3, 0x7, - 0x3, 0x9, 0x3, 0xB, 0x3, 0xD, 0x3, 0xF, - 0x4, 0x1, 0x4, 0x3, 0x4, 0x5, 0x4, 0x7, - 0x4, 0x9, 0x4, 0xB, 0x4, 0xD, 0x4, 0xF, - 0x5, 0x1, 0x5, 0x3, 0x5, 0x5, 0x5, 0x7, - 0x5, 0x9, 0x5, 0xB, 0x5, 0xD, 0x5, 0xF, - 0x6, 0x1, 0x6, 0x3, 0x6, 0x5, 0x6, 0x7, - 0x6, 0x9, 0x6, 0xB, 0x6, 0xD, 0x6, 0xF, - 0x7, 0x1, 0x7, 0x3, 0x7, 0x5, 0x7, 0x7, - 0x7, 0x9, 0x7, 0xB, 0x7, 0xD, 0x7, 0xF, - 0x8, 0x1, 0x8, 0x3, 0x8, 0x5, 0x8, 0x7, - 0x8, 0x9, 0x8, 0xB, 0x8, 0xD, 0x8, 0xF, - 0x9, 0x1, 0x9, 0x3, 0x9, 0x5, 0x9, 0x7, - 0x9, 0x9, 0x9, 0xB, 0x9, 0xD, 0x9, 0xF, - 0xA, 0x1, 0xA, 0x3, 0xA, 0x5, 0xA, 0x7, - 0xA, 0x9, 0xA, 0xB, 0xA, 0xD, 0xA, 0xF, - 0xB, 0x1, 0xB, 0x3, 0xB, 0x5, 0xB, 0x7, - 0xB, 0x9, 0xB, 0xB, 0xB, 0xD, 0xB, 0xF, - 0xC, 0x1, 0xC, 0x3, 0xC, 0x5, 0xC, 0x7, - 0xC, 0x9, 0xC, 0xB, 0xC, 0xD, 0xC, 0xF, - 0xD, 0x1, 0xD, 0x3, 0xD, 0x5, 0xD, 0x7, - 0xD, 0x9, 0xD, 0xB, 0xD, 0xD, 0xD, 0xF, - 0xE, 0x1, 0xE, 0x3, 0xE, 0x5, 0xE, 0x7, - 0xE, 0x9, 0xE, 0xB, 0xE, 0xD, 0xE, 0xF, - 0xF, 0x1, 0xF, 0x3, 0xF, 0x5, 0xF, 0x7, - 0xF, 0x9, 0xF, 0xB, 0xF, 0xD, 0xF, 0xF -}; - const char * const LoLEngine::_languageExt[] = { "ENG", "FRE", diff --git a/engines/kyra/text_lol.h b/engines/kyra/text_lol.h index 06c13e1fef..5586be730e 100644 --- a/engines/kyra/text_lol.h +++ b/engines/kyra/text_lol.h @@ -47,7 +47,7 @@ public: void resetDimTextPositions(int dim); void printDialogueText(int dim, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex); - void printMessage(uint16 type, const char *str, ...); + void printMessage(uint16 type, const char *str, ...) GCC_PRINTF(3, 4); int16 _scriptParameter; diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp index 84c4f8b19d..0e43487217 100644 --- a/engines/kyra/timer_lol.cpp +++ b/engines/kyra/timer_lol.cpp @@ -147,7 +147,7 @@ void LoLEngine::timerSpecialCharacterUpdate(int timerNum) { break; case 3: - v = _rnd.getRandomNumberRng(1, 2); + v = rollDice(1, 2); if (inflictDamage(i, v, 0x8000, 0, 0x80)) { _txt->printMessage(2, getLangString(0x4022), _characters[i].name); _characters[i].characterUpdateDelay[ii] = 10; @@ -241,7 +241,7 @@ void LoLEngine::timerUpdatePortraitAnimations(int skipUpdate) { } else { _characters[i].curFaceFrame = 0; gui_drawCharPortraitWithStats(i); - _characters[i].nextAnimUpdateCountdown = (int16) _rnd.getRandomNumberRng(1, 12) + 6; + _characters[i].nextAnimUpdateCountdown = rollDice(1, 12) + 6; } } } diff --git a/engines/lure/lure.h b/engines/lure/lure.h index 12494870ad..e8f1a7c1e1 100644 --- a/engines/lure/lure.h +++ b/engines/lure/lure.h @@ -91,7 +91,7 @@ public: bool saveGame(uint8 slotNumber, Common::String &caption); Common::String *detectSave(int slotNumber); uint8 saveVersion() { return _saveVersion; } - void GUIError(const char *msg, ...); + void GUIError(const char *msg, ...) GCC_PRINTF(2, 3); uint32 getFeatures() const; Common::Language getLanguage() const; diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h index 8fcfb94a9a..5a2c5e1c38 100644 --- a/engines/parallaction/sound.h +++ b/engines/parallaction/sound.h @@ -30,7 +30,7 @@ #include "common/mutex.h" #include "sound/audiostream.h" -#include "sound/iff.h" +#include "sound/iff_sound.h" #include "sound/mixer.h" #include "sound/mididrv.h" diff --git a/engines/queen/command.cpp b/engines/queen/command.cpp index 2ae222479d..81f0f3ff89 100644 --- a/engines/queen/command.cpp +++ b/engines/queen/command.cpp @@ -123,7 +123,7 @@ public: virtual void displayTemp(InkColor color, const char *name, bool outlined) { char temp[MAX_COMMAND_LEN]; // don't show a space after the goto and give commands in the Greek version - if (_command[1] != -34 && !(_command[1] == -2 && strlen(_command) > 5)) + if (_command[1] != (char)-34 && !(_command[1] == (char)-2 && strlen(_command) > 5)) sprintf(temp, "%s %s", _command, name); else sprintf(temp, "%s%s", _command, name); @@ -132,7 +132,7 @@ public: virtual void addObject(const char *objName) { // don't show a space after the goto and give commands in the Greek version - if (_command[1] != -34 && !(_command[1] == -2 && strlen(_command) > 5)) + if (_command[1] != (char)-34 && !(_command[1] == (char)-2 && strlen(_command) > 5)) strcat(_command, " "); strcat(_command, objName); } diff --git a/engines/saga/font.cpp b/engines/saga/font.cpp index 175ab01478..d58d1a8900 100644 --- a/engines/saga/font.cpp +++ b/engines/saga/font.cpp @@ -154,6 +154,7 @@ void Font::createOutline(FontData *font) { unsigned char *destPointer2; unsigned char *destPointer3; unsigned char charRep; + int nextIndex = 0; // Populate new font style character data @@ -165,6 +166,25 @@ void Font::createOutline(FontData *font) { index += indexOffset; } + bool skip = false; + + if (font->normal.fontCharEntry[i].width != 0 && font->normal.fontCharEntry[i].index < nextIndex) { + // Some characters are copies of earlier characters. + // Look up the original, and make sure not to grow the size of + // the outline font twice. + skip = true; + bool found = false; + for (int j = 0; j < i; j++) { + if (font->normal.fontCharEntry[i].index == font->normal.fontCharEntry[j].index) { + index = font->outline.fontCharEntry[j].index; + found = true; + break; + } + } + if (!found) + error("Invalid index backreference in font char %d", i); + } + font->outline.fontCharEntry[i].index = index; font->outline.fontCharEntry[i].tracking = font->normal.fontCharEntry[i].tracking; font->outline.fontCharEntry[i].flag = font->normal.fontCharEntry[i].flag; @@ -173,14 +193,18 @@ void Font::createOutline(FontData *font) { newByteWidth = getByteLen(font->normal.fontCharEntry[i].width + 2); oldByteWidth = getByteLen(font->normal.fontCharEntry[i].width); - if (newByteWidth > oldByteWidth) { + if (!skip && newByteWidth > oldByteWidth) { indexOffset++; } } font->outline.fontCharEntry[i].width = font->normal.fontCharEntry[i].width + 2; font->outline.fontCharEntry[i].byteWidth = newByteWidth; - newRowLength += newByteWidth; + + if (!skip) { + newRowLength += newByteWidth; + nextIndex = font->normal.fontCharEntry[i].index + oldByteWidth; + } } debug(2, "New row length: %d", newRowLength); @@ -196,6 +220,10 @@ void Font::createOutline(FontData *font) { // Generate outline font representation for (i = 0; i < FONT_CHARCOUNT; i++) { + if (i > 0 && font->normal.fontCharEntry[i].index < font->normal.fontCharEntry[i-1].index) { + // Skip copies + continue; + } for (row = 0; row < font->normal.header.charHeight; row++) { for (currentByte = 0; currentByte < font->outline.fontCharEntry[i].byteWidth; currentByte++) { basePointer = font->outline.font + font->outline.fontCharEntry[i].index + currentByte; diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 2f2fbc5243..7c1a165ec1 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -50,10 +50,6 @@ int g_debug_sleeptime_factor = 1; int g_debug_simulated_key = 0; bool g_debug_track_mouse_clicks = false; bool g_debug_weak_validations = true; -// Script related variables -int g_debug_seeking = 0; // Stepping forward until some special condition is met -int g_debug_seek_special = 0; // Used for special seeks -int g_debug_seek_level = 0; // Used for seekers that want to check their exec stack depth Console::Console(SciEngine *vm) : GUI::Debugger() { _vm = vm; @@ -71,6 +67,7 @@ Console::Console(SciEngine *vm) : GUI::Debugger() { // Kernel // DCmd_Register("classes", WRAP_METHOD(Console, cmdClasses)); // TODO DCmd_Register("opcodes", WRAP_METHOD(Console, cmdOpcodes)); + DCmd_Register("selector", WRAP_METHOD(Console, cmdSelector)); DCmd_Register("selectors", WRAP_METHOD(Console, cmdSelectors)); DCmd_Register("functions", WRAP_METHOD(Console, cmdKernelFunctions)); DCmd_Register("class_table", WRAP_METHOD(Console, cmdClassTable)); @@ -192,18 +189,25 @@ Console::Console(SciEngine *vm) : GUI::Debugger() { con_hook_int(&(gfx_options.dirty_frames), "dirty_frames", "Dirty frames management\n"); */ + + scriptState.seeking = kDebugSeekNothing; + scriptState.seekLevel = 0; + scriptState.runningStep = 0; + scriptState.stopOnEvent = false; } Console::~Console() { } void Console::preEnter() { - _vm->_gamestate->_sound.sfx_suspend(true); + if (_vm->_gamestate) + _vm->_gamestate->_sound.sfx_suspend(true); _vm->_mixer->pauseAll(true); } void Console::postEnter() { - _vm->_gamestate->_sound.sfx_suspend(false); + if (_vm->_gamestate) + _vm->_gamestate->_sound.sfx_suspend(false); _vm->_mixer->pauseAll(false); } @@ -237,6 +241,7 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf("Kernel:\n"); DebugPrintf(" opcodes - Lists the opcode names\n"); DebugPrintf(" selectors - Lists the selector names\n"); + DebugPrintf(" selector - Attempts to find the requested selector by name\n"); DebugPrintf(" functions - Lists the kernel functions\n"); DebugPrintf(" class_table - Shows the available classes\n"); DebugPrintf("\n"); @@ -361,25 +366,23 @@ ResourceType parseResourceType(const char *resid) { } const char *selector_name(EngineState *s, int selector) { - if (selector >= 0 && selector < (int)s->_kernel->getSelectorNamesSize()) - return s->_kernel->getSelectorName(selector).c_str(); + if (selector >= 0 && selector < (int)((SciEngine*)g_engine)->getKernel()->getSelectorNamesSize()) + return ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector).c_str(); else return "--INVALID--"; } bool Console::cmdGetVersion(int argc, const char **argv) { - int ver = _vm->getVersion(); - - DebugPrintf("Resource file version: %s\n", sci_version_types[_vm->getResMgr()->_sciVersion]); - DebugPrintf("Emulated interpreter version: %s\n", versionNames[ver]); + DebugPrintf("Resource file version: %s\n", versionNames[_vm->getResMgr()->_sciVersion]); + DebugPrintf("Emulated interpreter version: %s\n", versionNames[_vm->getVersion()]); return true; } bool Console::cmdOpcodes(int argc, const char **argv) { DebugPrintf("Opcode names in numeric order [index: type name]:\n"); - for (uint seeker = 0; seeker < _vm->_gamestate->_kernel->getOpcodesSize(); seeker++) { - opcode op = _vm->_gamestate->_kernel->getOpcode(seeker); + for (uint seeker = 0; seeker < _vm->getKernel()->getOpcodesSize(); seeker++) { + opcode op = _vm->getKernel()->getOpcode(seeker); DebugPrintf("%03x: %03x %20s | ", seeker, op.type, op.name.c_str()); if ((seeker % 3) == 2) DebugPrintf("\n"); @@ -390,10 +393,29 @@ bool Console::cmdOpcodes(int argc, const char **argv) { return true; } +bool Console::cmdSelector(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Attempts to find the requested selector by name.\n"); + DebugPrintf("Usage: %s <selector name>\n", argv[0]); + return true; + } + + for (uint seeker = 0; seeker < _vm->getKernel()->getSelectorNamesSize(); seeker++) { + if (!scumm_stricmp(_vm->getKernel()->getSelectorName(seeker).c_str(), argv[1])) { + DebugPrintf("Selector %s found at %03x\n", _vm->getKernel()->getSelectorName(seeker).c_str(), seeker); + return true; + } + } + + DebugPrintf("Selector %s wasn't found\n", argv[1]); + + return true; +} + bool Console::cmdSelectors(int argc, const char **argv) { DebugPrintf("Selector names in numeric order:\n"); - for (uint seeker = 0; seeker < _vm->_gamestate->_kernel->getSelectorNamesSize(); seeker++) { - DebugPrintf("%03x: %20s | ", seeker, _vm->_gamestate->_kernel->getSelectorName(seeker).c_str()); + for (uint seeker = 0; seeker < _vm->getKernel()->getSelectorNamesSize(); seeker++) { + DebugPrintf("%03x: %20s | ", seeker, _vm->getKernel()->getSelectorName(seeker).c_str()); if ((seeker % 3) == 2) DebugPrintf("\n"); } @@ -405,8 +427,8 @@ bool Console::cmdSelectors(int argc, const char **argv) { bool Console::cmdKernelFunctions(int argc, const char **argv) { DebugPrintf("Kernel function names in numeric order:\n"); - for (uint seeker = 0; seeker < _vm->_gamestate->_kernel->getKernelNamesSize(); seeker++) { - DebugPrintf("%03x: %20s | ", seeker, _vm->_gamestate->_kernel->getKernelName(seeker).c_str()); + for (uint seeker = 0; seeker < _vm->getKernel()->getKernelNamesSize(); seeker++) { + DebugPrintf("%03x: %20s | ", seeker, _vm->getKernel()->getKernelName(seeker).c_str()); if ((seeker % 3) == 2) DebugPrintf("\n"); } @@ -417,13 +439,13 @@ bool Console::cmdKernelFunctions(int argc, const char **argv) { } bool Console::cmdSuffixes(int argc, const char **argv) { - _vm->_gamestate->_vocabulary->printSuffixes(); + _vm->getVocabulary()->printSuffixes(); return true; } bool Console::cmdParserWords(int argc, const char **argv) { - _vm->_gamestate->_vocabulary->printParserWords(); + _vm->getVocabulary()->printParserWords(); return true; } @@ -438,6 +460,7 @@ enum { int parseNodes(EngineState *s, int *i, int *pos, int type, int nr, int argc, const char **argv) { int nextToken = 0, nextValue = 0, newPos = 0, oldPos = 0; + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); if (type == kParseNil) return 0; @@ -448,11 +471,11 @@ int parseNodes(EngineState *s, int *i, int *pos, int type, int nr, int argc, con return *pos; } if (type == kParseEndOfInput) { - sciprintf("Unbalanced parentheses\n"); + con->DebugPrintf("Unbalanced parentheses\n"); return -1; } if (type == kParseClosingParenthesis) { - sciprintf("Syntax error at token %d\n", *i); + con->DebugPrintf("Syntax error at token %d\n", *i); return -1; } @@ -482,7 +505,7 @@ int parseNodes(EngineState *s, int *i, int *pos, int type, int nr, int argc, con const char *token = argv[(*i)++]; if (strcmp(token, ")")) - sciprintf("Expected ')' at token %d\n", *i); + con->DebugPrintf("Expected ')' at token %d\n", *i); return oldPos; } @@ -522,16 +545,13 @@ bool Console::cmdSetParseNodes(int argc, const char **argv) { bool Console::cmdRegisters(int argc, const char **argv) { DebugPrintf("Current register values:\n"); -#if 0 - // TODO: p_restadjust - DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(_vm->_gamestate->r_acc), PRINT_REG(_vm->_gamestate->r_prev), *p_restadjust); -#endif + DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(_vm->_gamestate->r_acc), PRINT_REG(_vm->_gamestate->r_prev), scriptState.restAdjust); if (!_vm->_gamestate->_executionStack.empty()) { -#if 0 - // TODO: p_pc, p_objp, p_pp, p_sp - DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", PRINT_REG(*p_pc), PRINT_REG(*p_objp), PRINT_STK(*p_pp), PRINT_STK(*p_sp)); -#endif + EngineState *s = _vm->_gamestate; // for PRINT_STK + DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", + PRINT_REG(scriptState.xs->addr.pc), PRINT_REG(scriptState.xs->objp), + PRINT_STK(scriptState.xs->fp), PRINT_STK(scriptState.xs->sp)); } else DebugPrintf("<no execution stack: pc,obj,fp omitted>\n"); @@ -547,11 +567,6 @@ bool Console::cmdHexDump(int argc, const char **argv) { } int resNum = atoi(argv[2]); - if (resNum == 0) { - DebugPrintf("The resource number specified is not a number"); - return true; - } - ResourceType res = parseResourceType(argv[1]); if (res == kResourceTypeInvalid) @@ -589,7 +604,7 @@ bool Console::cmdDissectScript(int argc, const char **argv) { return true; } - _vm->_gamestate->_kernel->dissectScript(atoi(argv[1]), _vm->_gamestate->_vocabulary); + _vm->getKernel()->dissectScript(atoi(argv[1]), _vm->getVocabulary()); return true; } @@ -608,11 +623,6 @@ bool Console::cmdResourceSize(int argc, const char **argv) { } int resNum = atoi(argv[2]); - if (resNum == 0) { - DebugPrintf("The resource number specified is not a number"); - return true; - } - ResourceType res = parseResourceType(argv[1]); if (res == kResourceTypeInvalid) @@ -835,7 +845,6 @@ bool Console::cmdRestoreGame(int argc, const char **argv) { _vm->_gamestate->successor = newstate; // Set successor script_abort_flag = 2; // Abort current game with replay - g_debugstate_valid = 0; shrink_execution_stack(_vm->_gamestate, _vm->_gamestate->execution_stack_base + 1); return 0; @@ -866,7 +875,6 @@ bool Console::cmdRestartGame(int argc, const char **argv) { _vm->_gamestate->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW; script_abort_flag = 1; - g_debugstate_valid = 0; return false; } @@ -886,10 +894,10 @@ bool Console::cmdClassTable(int argc, const char **argv) { bool Console::cmdSentenceFragments(int argc, const char **argv) { DebugPrintf("Sentence fragments (used to build Parse trees)\n"); - for (uint i = 0; i < _vm->_gamestate->_vocabulary->getParserBranchesSize(); i++) { + for (uint i = 0; i < _vm->getVocabulary()->getParserBranchesSize(); i++) { int j = 0; - const parse_tree_branch_t &branch = _vm->_gamestate->_vocabulary->getParseTreeBranch(i); + const parse_tree_branch_t &branch = _vm->getVocabulary()->getParseTreeBranch(i); DebugPrintf("R%02d: [%x] ->", i, branch.id); while ((j < 10) && branch.data[j]) { int dat = branch.data[j++]; @@ -921,7 +929,7 @@ bool Console::cmdSentenceFragments(int argc, const char **argv) { DebugPrintf("\n"); } - DebugPrintf("%d rules.\n", _vm->_gamestate->_vocabulary->getParserBranchesSize()); + DebugPrintf("%d rules.\n", _vm->getVocabulary()->getParserBranchesSize()); return true; } @@ -944,7 +952,7 @@ bool Console::cmdParse(int argc, const char **argv) { } DebugPrintf("Parsing '%s'\n", string); - bool res = _vm->_gamestate->_vocabulary->tokenizeString(words, string, &error); + bool res = _vm->getVocabulary()->tokenizeString(words, string, &error); if (res && !words.empty()) { int syntax_fail = 0; @@ -955,7 +963,7 @@ bool Console::cmdParse(int argc, const char **argv) { for (ResultWordList::const_iterator i = words.begin(); i != words.end(); ++i) DebugPrintf(" Type[%04x] Group[%04x]\n", i->_class, i->_group); - if (_vm->_gamestate->_vocabulary->parseGNF(_vm->_gamestate->parser_nodes, words, true)) + if (_vm->getVocabulary()->parseGNF(_vm->_gamestate->parser_nodes, words, true)) syntax_fail = 1; // Building a tree failed if (syntax_fail) @@ -1206,7 +1214,7 @@ bool Console::cmdPrintPort(int argc, const char **argv) { bool Console::cmdParseGrammar(int argc, const char **argv) { DebugPrintf("Parse grammar, in strict GNF:\n"); - _vm->_gamestate->_vocabulary->buildGNF(true); + _vm->getVocabulary()->buildGNF(true); return true; } @@ -1598,7 +1606,7 @@ bool Console::cmdGCObjects(int argc, const char **argv) { void _print_address(void * _, reg_t addr) { if (addr.segment) - ((SciEngine *)g_engine)->getDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(addr)); + ((SciEngine *)g_engine)->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(addr)); } bool Console::cmdGCShowReachable(int argc, const char **argv) { @@ -1689,20 +1697,16 @@ bool Console::cmdGCNormalize(int argc, const char **argv) { } bool Console::cmdVMVarlist(int argc, const char **argv) { - //const char *varnames[] = {"global", "local", "temp", "param"}; + const char *varnames[] = {"global", "local", "temp", "param"}; DebugPrintf("Addresses of variables in the VM:\n"); -#if 0 - // TODO: p_var_segs, p_vars, p_var_base, p_var_max - for (int i = 0; i < 4; i++) { - DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(p_var_segs[i], p_vars[i] - p_var_base[i]))); - if (p_var_max) - DebugPrintf(" total %d", p_var_max[i]); + DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(scriptState.variables_seg[i], scriptState.variables[i] - scriptState.variables_base[i]))); + if (scriptState.variables_max) + DebugPrintf(" total %d", scriptState.variables_max[i]); DebugPrintf("\n"); } -#endif return true; } @@ -1718,7 +1722,7 @@ bool Console::cmdVMVars(int argc, const char **argv) { return true; } - //const char *varnames[] = {"global", "local", "temp", "param"}; + const char *varnames[] = {"global", "local", "temp", "param"}; const char *varabbrev = "gltp"; const char *vartype_pre = strchr(varabbrev, *argv[1]); int vartype; @@ -1736,31 +1740,21 @@ bool Console::cmdVMVars(int argc, const char **argv) { return true; } -#if 0 - // TODO: p_var_max - if ((p_var_max) && (p_var_max[vartype] <= idx)) { - DebugPrintf("Max. index is %d (0x%x)\n", p_var_max[vartype], p_var_max[vartype]); + if ((scriptState.variables_max) && (scriptState.variables_max[vartype] <= idx)) { + DebugPrintf("Max. index is %d (0x%x)\n", scriptState.variables_max[vartype], scriptState.variables_max[vartype]); return true; } -#endif switch (argc) { case 2: -#if 0 - // TODO: p_vars - DebugPrintf("%s var %d == %04x:%04x\n", varnames[vartype], idx, PRINT_REG(p_vars[vartype][idx])); -#endif + DebugPrintf("%s var %d == %04x:%04x\n", varnames[vartype], idx, PRINT_REG(scriptState.variables[vartype][idx])); break; case 3: -#if 0 - // TODO: p_vars - - if (parse_reg_t(_vm->_gamestate, argv[3], &p_vars[vartype][idx])) { + if (parse_reg_t(_vm->_gamestate, argv[3], &scriptState.variables[vartype][idx])) { DebugPrintf("Invalid address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } -#endif break; default: DebugPrintf("Too many arguments\n"); @@ -1933,7 +1927,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { break; case KSIG_OBJECT: DebugPrintf("object\n"); - printObject(_vm->_gamestate, reg); + printObject(reg); break; case KSIG_REF: { int size; @@ -1988,25 +1982,21 @@ bool Console::cmdViewObject(int argc, const char **argv) { } DebugPrintf("Information on the object at the given address:\n"); - printObject(_vm->_gamestate, addr); + printObject(addr); return true; } bool Console::cmdViewActiveObject(int argc, const char **argv) { DebugPrintf("Information on the currently active object or class:\n"); - -#if 0 - // TODO: p_objp - printObject(_vm->_gamestate, *p_objp); -#endif + printObject(scriptState.xs->objp); return true; } bool Console::cmdViewAccumulatorObject(int argc, const char **argv) { DebugPrintf("Information on the currently active object or class at the address indexed by the accumulator:\n"); - printObject(_vm->_gamestate, _vm->_gamestate->r_acc); + printObject(_vm->_gamestate->r_acc); return true; } @@ -2040,7 +2030,7 @@ bool Console::cmdSetAccumulator(int argc, const char **argv) { bool Console::cmdBacktrace(int argc, const char **argv) { DebugPrintf("Dumping the send/self/super/call/calle/callb stack:\n"); - DebugPrintf("Call stack (current base: 0x%x):\n", _vm->_gamestate->execution_stack_base); + printf("Call stack (current base: 0x%x):\n", _vm->_gamestate->execution_stack_base); Common::List<ExecStack>::iterator iter; uint i = 0; @@ -2053,18 +2043,18 @@ bool Console::cmdBacktrace(int argc, const char **argv) { switch (call.type) { case EXEC_STACK_TYPE_CALL: {// Normal function - sciprintf(" %x:[%x] %s::%s(", i, call.origin, objname, (call.selector == -1) ? "<call[be]?>" : + printf(" %x:[%x] %s::%s(", i, call.origin, objname, (call.selector == -1) ? "<call[be]?>" : selector_name(_vm->_gamestate, call.selector)); } break; case EXEC_STACK_TYPE_KERNEL: // Kernel function - sciprintf(" %x:[%x] k%s(", i, call.origin, _vm->_gamestate->_kernel->getKernelName(-(call.selector) - 42).c_str()); + printf(" %x:[%x] k%s(", i, call.origin, _vm->getKernel()->getKernelName(-(call.selector) - 42).c_str()); break; case EXEC_STACK_TYPE_VARSELECTOR: - sciprintf(" %x:[%x] vs%s %s::%s (", i, call.origin, (call.argc) ? "write" : "read", - objname, _vm->_gamestate->_kernel->getSelectorName(call.selector).c_str()); + printf(" %x:[%x] vs%s %s::%s (", i, call.origin, (call.argc) ? "write" : "read", + objname, _vm->getKernel()->getSelectorName(call.selector).c_str()); break; } @@ -2074,31 +2064,31 @@ bool Console::cmdBacktrace(int argc, const char **argv) { totalparamc = 16; for (paramc = 1; paramc <= totalparamc; paramc++) { - sciprintf("%04x:%04x", PRINT_REG(call.variables_argp[paramc])); + printf("%04x:%04x", PRINT_REG(call.variables_argp[paramc])); if (paramc < call.argc) - sciprintf(", "); + printf(", "); } if (call.argc > 16) - sciprintf("..."); + printf("..."); - sciprintf(")\n obj@%04x:%04x", PRINT_REG(call.objp)); + printf(")\n obj@%04x:%04x", PRINT_REG(call.objp)); if (call.type == EXEC_STACK_TYPE_CALL) { - sciprintf(" pc=%04x:%04x", PRINT_REG(call.addr.pc)); + printf(" pc=%04x:%04x", PRINT_REG(call.addr.pc)); if (call.sp == CALL_SP_CARRY) - sciprintf(" sp,fp:carry"); + printf(" sp,fp:carry"); else { - sciprintf(" sp=ST:%04x", (unsigned)(call.sp - _vm->_gamestate->stack_base)); - sciprintf(" fp=ST:%04x", (unsigned)(call.fp - _vm->_gamestate->stack_base)); + printf(" sp=ST:%04x", (unsigned)(call.sp - _vm->_gamestate->stack_base)); + printf(" fp=ST:%04x", (unsigned)(call.fp - _vm->_gamestate->stack_base)); } } else - sciprintf(" pc:none"); + printf(" pc:none"); - sciprintf(" argp:ST:%04x", (unsigned)(call.variables_argp - _vm->_gamestate->stack_base)); + printf(" argp:ST:%04x", (unsigned)(call.variables_argp - _vm->_gamestate->stack_base)); if (call.type == EXEC_STACK_TYPE_CALL) - sciprintf(" script: %d", (*(Script *)_vm->_gamestate->seg_manager->_heap[call.addr.pc.segment]).nr); - sciprintf("\n"); + printf(" script: %d", (*(Script *)_vm->_gamestate->seg_manager->_heap[call.addr.pc.segment]).nr); + printf("\n"); } return 0; @@ -2106,24 +2096,21 @@ bool Console::cmdBacktrace(int argc, const char **argv) { } bool Console::cmdStep(int argc, const char **argv) { - g_debugstate_valid = 0; if (argc == 2 && atoi(argv[1]) > 0) - g_debug_step_running = atoi(argv[1]) - 1; + scriptState.runningStep = atoi(argv[1]) - 1; return true; } bool Console::cmdStepEvent(int argc, const char **argv) { - g_stop_on_event = 1; - g_debugstate_valid = 0; + scriptState.stopOnEvent = true; return true; } bool Console::cmdStepRet(int argc, const char **argv) { - g_debug_seeking = kDebugSeekLevelRet; - g_debug_seek_level = _vm->_gamestate->_executionStack.size() - 1; - g_debugstate_valid = 0; + scriptState.seeking = kDebugSeekLevelRet; + scriptState.seekLevel = _vm->_gamestate->_executionStack.size() - 1; return true; } @@ -2135,9 +2122,8 @@ bool Console::cmdStepGlobal(int argc, const char **argv) { return true; } - g_debug_seeking = kDebugSeekGlobal; - g_debug_seek_special = atoi(argv[1]); - g_debugstate_valid = 0; + scriptState.seeking = kDebugSeekGlobal; + scriptState.seekSpecial = atoi(argv[1]); return true; } @@ -2153,8 +2139,8 @@ bool Console::cmdStepCallk(int argc, const char **argv) { callk_index = strtoul(argv[1], &endptr, 0); if (*endptr != '\0') { callk_index = -1; - for (uint i = 0; i < _vm->_gamestate->_kernel->getKernelNamesSize(); i++) - if (argv[1] == _vm->_gamestate->_kernel->getKernelName(i)) { + for (uint i = 0; i < _vm->getKernel()->getKernelNamesSize(); i++) + if (argv[1] == _vm->getKernel()->getKernelName(i)) { callk_index = i; break; } @@ -2165,12 +2151,10 @@ bool Console::cmdStepCallk(int argc, const char **argv) { } } - g_debug_seeking = kDebugSeekSpecialCallk; - g_debug_seek_special = callk_index; - g_debugstate_valid = 0; + scriptState.seeking = kDebugSeekSpecialCallk; + scriptState.seekSpecial = callk_index; } else { - g_debug_seeking = kDebugSeekCallk; - g_debugstate_valid = 0; + scriptState.seeking = kDebugSeekCallk; } return true; @@ -2192,7 +2176,7 @@ bool Console::cmdDissassemble(int argc, const char **argv) { } Object *obj = obj_get(_vm->_gamestate, objAddr); - int selector_id = _vm->_gamestate->_kernel->findSelector(argv[2]); + int selector_id = _vm->getKernel()->findSelector(argv[2]); reg_t addr; if (!obj) { @@ -2211,8 +2195,7 @@ bool Console::cmdDissassemble(int argc, const char **argv) { } do { - // TODO - //addr = disassemble(_vm->_gamestate, addr, 0, 0); + addr = disassemble(_vm->_gamestate, addr, 0, 0); } while (addr.offset > 0); return true; @@ -2263,9 +2246,7 @@ bool Console::cmdDissassembleAddress(int argc, const char **argv) { } do { - // TODO - //vpc = disassemble(_vm->_gamestate, vpc, do_bwc, do_bytes); - + vpc = disassemble(_vm->_gamestate, vpc, do_bwc, do_bytes); } while ((vpc.offset > 0) && (vpc.offset + 6 < size) && (--op_count)); return true; @@ -2295,24 +2276,24 @@ bool Console::cmdSend(int argc, const char **argv) { Object *o; reg_t fptr; - selector_id = _vm->_gamestate->_kernel->findSelector(selector_name); + selector_id = _vm->getKernel()->findSelector(selector_name); if (selector_id < 0) { - sciprintf("Unknown selector: \"%s\"\n", selector_name); - return 1; + DebugPrintf("Unknown selector: \"%s\"\n", selector_name); + return true; } o = obj_get(_vm->_gamestate, object); if (o == NULL) { - sciprintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object)); - return 1; + DebugPrintf("Address \"%04x:%04x\" is not an object\n", PRINT_REG(object)); + return true; } SelectorType selector_type = lookup_selector(_vm->_gamestate, object, selector_id, 0, &fptr); if (selector_type == kSelectorNone) { - sciprintf("Object does not support selector: \"%s\"\n", selector_name); - return 1; + DebugPrintf("Object does not support selector: \"%s\"\n", selector_name); + return true; } stackframe[0] = make_reg(0, selector_id); @@ -2346,8 +2327,7 @@ bool Console::cmdSend(int argc, const char **argv) { } bool Console::cmdGo(int argc, const char **argv) { - g_debug_seeking = 0; - g_debugstate_valid = 0; + scriptState.seeking = kDebugSeekNothing; return true; } @@ -2761,9 +2741,8 @@ bool Console::cmdExit(int argc, const char **argv) { if (!scumm_stricmp(argv[1], "game")) { // Quit gracefully script_abort_flag = 1; // Terminate VM - g_debugstate_valid = 0; - g_debug_seeking = 0; - g_debug_step_running = 0; + scriptState.seeking = kDebugSeekNothing; + scriptState.runningStep = 0; } else if (!scumm_stricmp(argv[1], "now")) { // Quit ungracefully @@ -3047,46 +3026,47 @@ int Console::printNode(reg_t addr) { return 0; } -int printObject(EngineState *s, reg_t pos) { +int Console::printObject(reg_t pos) { + EngineState *s = _vm->_gamestate; // for the several defines in this function Object *obj = obj_get(s, pos); Object *var_container = obj; int i; if (!obj) { - sciprintf("[%04x:%04x]: Not an object.", PRINT_REG(pos)); + DebugPrintf("[%04x:%04x]: Not an object.", PRINT_REG(pos)); return 1; } // Object header - sciprintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), obj_get_name(s, pos), + DebugPrintf("[%04x:%04x] %s : %3d vars, %3d methods\n", PRINT_REG(pos), obj_get_name(s, pos), obj->_variables.size(), obj->methods_nr); if (!(obj->_variables[SCRIPT_INFO_SELECTOR].offset & SCRIPT_INFO_CLASS)) var_container = obj_get(s, obj->_variables[SCRIPT_SUPERCLASS_SELECTOR]); - sciprintf(" -- member variables:\n"); + DebugPrintf(" -- member variables:\n"); for (i = 0; (uint)i < obj->_variables.size(); i++) { - sciprintf(" "); + printf(" "); if (i < var_container->variable_names_nr) { - sciprintf("[%03x] %s = ", VM_OBJECT_GET_VARSELECTOR(var_container, i), selector_name(s, VM_OBJECT_GET_VARSELECTOR(var_container, i))); + DebugPrintf("[%03x] %s = ", VM_OBJECT_GET_VARSELECTOR(var_container, i), selector_name(s, VM_OBJECT_GET_VARSELECTOR(var_container, i))); } else - sciprintf("p#%x = ", i); + DebugPrintf("p#%x = ", i); reg_t val = obj->_variables[i]; - sciprintf("%04x:%04x", PRINT_REG(val)); + DebugPrintf("%04x:%04x", PRINT_REG(val)); Object *ref = obj_get(s, val); if (ref) - sciprintf(" (%s)", obj_get_name(s, val)); + DebugPrintf(" (%s)", obj_get_name(s, val)); - sciprintf("\n"); + DebugPrintf("\n"); } - sciprintf(" -- methods:\n"); + DebugPrintf(" -- methods:\n"); for (i = 0; i < obj->methods_nr; i++) { reg_t fptr = VM_OBJECT_READ_FUNCTION(obj, i); - sciprintf(" [%03x] %s = %04x:%04x\n", VM_OBJECT_GET_FUNCSELECTOR(obj, i), selector_name(s, VM_OBJECT_GET_FUNCSELECTOR(obj, i)), PRINT_REG(fptr)); + DebugPrintf(" [%03x] %s = %04x:%04x\n", VM_OBJECT_GET_FUNCSELECTOR(obj, i), selector_name(s, VM_OBJECT_GET_FUNCSELECTOR(obj, i)), PRINT_REG(fptr)); } if (s->seg_manager->_heap[pos.segment]->getType() == MEM_OBJ_SCRIPT) - sciprintf("\nOwner script:\t%d\n", s->seg_manager->getScript(pos.segment)->nr); + DebugPrintf("\nOwner script:\t%d\n", s->seg_manager->getScript(pos.segment)->nr); return 0; } @@ -3128,7 +3108,7 @@ static void viewobjinfo(EngineState *s, HeapPtr pos) { int have_rects = 0; Common::Rect nsrect, nsrect_clipped, brrect; - if (lookup_selector(s, pos, s->_kernel->_selectorMap.nsBottom, NULL) == kSelectorVariable) { + if (lookup_selector(s, pos, ((SciEngine*)g_engine)->getKernel()->_selectorMap.nsBottom, NULL) == kSelectorVariable) { GETRECT(nsLeft, nsRight, nsBottom, nsTop); GETRECT(lsLeft, lsRight, lsBottom, lsTop); GETRECT(brLeft, brRight, brBottom, brTop); @@ -3137,39 +3117,39 @@ static void viewobjinfo(EngineState *s, HeapPtr pos) { GETRECT(view, loop, signal, cel); - sciprintf("\n-- View information:\ncel %d/%d/%d at ", view, loop, cel); + printf("\n-- View information:\ncel %d/%d/%d at ", view, loop, cel); x = GET_SELECTOR(pos, x); y = GET_SELECTOR(pos, y); priority = GET_SELECTOR(pos, priority); - if (s->_kernel->_selectorMap.z > 0) { + if (((SciEngine*)g_engine)->getKernel()->_selectorMap.z > 0) { z = GET_SELECTOR(pos, z); - sciprintf("(%d,%d,%d)\n", x, y, z); + printf("(%d,%d,%d)\n", x, y, z); } else - sciprintf("(%d,%d)\n", x, y); + printf("(%d,%d)\n", x, y); if (priority == -1) - sciprintf("No priority.\n\n"); + printf("No priority.\n\n"); else - sciprintf("Priority = %d (band starts at %d)\n\n", priority, PRIORITY_BAND_FIRST(priority)); + printf("Priority = %d (band starts at %d)\n\n", priority, PRIORITY_BAND_FIRST(priority)); if (have_rects) { - sciprintf("nsRect: [%d..%d]x[%d..%d]\n", nsLeft, nsRight, nsTop, nsBottom); - sciprintf("lsRect: [%d..%d]x[%d..%d]\n", lsLeft, lsRight, lsTop, lsBottom); - sciprintf("brRect: [%d..%d]x[%d..%d]\n", brLeft, brRight, brTop, brBottom); + printf("nsRect: [%d..%d]x[%d..%d]\n", nsLeft, nsRight, nsTop, nsBottom); + printf("lsRect: [%d..%d]x[%d..%d]\n", lsLeft, lsRight, lsTop, lsBottom); + printf("brRect: [%d..%d]x[%d..%d]\n", brLeft, brRight, brTop, brBottom); } nsrect = get_nsrect(s, pos, 0); nsrect_clipped = get_nsrect(s, pos, 1); brrect = set_base(s, pos); - sciprintf("new nsRect: [%d..%d]x[%d..%d]\n", nsrect.x, nsrect.xend, nsrect.y, nsrect.yend); - sciprintf("new clipped nsRect: [%d..%d]x[%d..%d]\n", nsrect_clipped.x, nsrect_clipped.xend, nsrect_clipped.y, nsrect_clipped.yend); - sciprintf("new brRect: [%d..%d]x[%d..%d]\n", brrect.x, brrect.xend, brrect.y, brrect.yend); - sciprintf("\n signals = %04x:\n", signal); + printf("new nsRect: [%d..%d]x[%d..%d]\n", nsrect.x, nsrect.xend, nsrect.y, nsrect.yend); + printf("new clipped nsRect: [%d..%d]x[%d..%d]\n", nsrect_clipped.x, nsrect_clipped.xend, nsrect_clipped.y, nsrect_clipped.yend); + printf("new brRect: [%d..%d]x[%d..%d]\n", brrect.x, brrect.xend, brrect.y, brrect.yend); + printf("\n signals = %04x:\n", signal); for (i = 0; i < 16; i++) if (signal & (1 << i)) - sciprintf(" %04x: %s\n", 1 << i, signals[i]); + printf(" %04x: %s\n", 1 << i, signals[i]); } #endif #undef GETRECT @@ -3191,28 +3171,28 @@ static int c_gfx_draw_viewobj(EngineState *s, const Common::Array<cmd_param_t> & int brLeft, brRight, brBottom, brTop; if (!s) { - sciprintf("Not in debug state!\n"); + printf("Not in debug state!\n"); return 1; } if ((pos < 4) || (pos > 0xfff0)) { - sciprintf("Invalid address.\n"); + printf("Invalid address.\n"); return 1; } if (((int16)READ_LE_UINT16(s->heap + pos + SCRIPT_OBJECT_MAGIC_OFFSET)) != SCRIPT_OBJECT_MAGIC_NUMBER) { - sciprintf("Not an object.\n"); + printf("Not an object.\n"); return 0; } - is_view = (lookup_selector(s, pos, s->_kernel->_selectorMap.x, NULL) == kSelectorVariable) && - (lookup_selector(s, pos, s->_kernel->_selectorMap.brLeft, NULL) == kSelectorVariable) && - (lookup_selector(s, pos, s->_kernel->_selectorMap.signal, NULL) == kSelectorVariable) && - (lookup_selector(s, pos, s->_kernel->_selectorMap.nsTop, NULL) == kSelectorVariable); + is_view = (lookup_selector(s, pos, ((SciEngine*)g_engine)->getKernel()->_selectorMap.x, NULL) == kSelectorVariable) && + (lookup_selector(s, pos, ((SciEngine*)g_engine)->getKernel()->_selectorMap.brLeft, NULL) == kSelectorVariable) && + (lookup_selector(s, pos, ((SciEngine*)g_engine)->getKernel()->_selectorMap.signal, NULL) == kSelectorVariable) && + (lookup_selector(s, pos, ((SciEngine*)g_engine)->getKernel()->_selectorMap.nsTop, NULL) == kSelectorVariable); if (!is_view) { - sciprintf("Not a dynamic View object.\n"); + printf("Not a dynamic View object.\n"); return 0; } @@ -3246,39 +3226,33 @@ static int c_gfx_draw_viewobj(EngineState *s, const Common::Array<cmd_param_t> & int c_stepover(EngineState *s, const Common::Array<cmd_param_t> &cmdParams) { int opcode, opnumber; - if (!g_debugstate_valid) { - sciprintf("Not in debug state\n"); - return 1; - } - - g_debugstate_valid = 0; opcode = s->_heap[*p_pc]; opnumber = opcode >> 1; if (opnumber == 0x22 /* callb */ || opnumber == 0x23 /* calle */ || opnumber == 0x25 /* send */ || opnumber == 0x2a /* self */ || opnumber == 0x2b /* super */) { - g_debug_seeking = kDebugSeekSO; - g_debug_seek_level = s->_executionStack.size()-1; - // Store in g_debug_seek_special the offset of the next command after send + scriptState.seeking = kDebugSeekSO; + scriptState.seekLevel = s->_executionStack.size()-1; + // Store in scriptState.seekSpecial the offset of the next command after send switch (opcode) { case 0x46: // calle W - g_debug_seek_special = *p_pc + 5; + scriptState.seekSpecial = *p_pc + 5; break; case 0x44: // callb W case 0x47: // calle B case 0x56: // super W - g_debug_seek_special = *p_pc + 4; + scriptState.seekSpecial = *p_pc + 4; break; case 0x45: // callb B case 0x57: // super B case 0x4A: // send W case 0x54: // self W - g_debug_seek_special = *p_pc + 3; + scriptState.seekSpecial = *p_pc + 3; break; default: - g_debug_seek_special = *p_pc + 2; + scriptState.seekSpecial = *p_pc + 2; } } diff --git a/engines/sci/console.h b/engines/sci/console.h index 22b5505bf2..8d1299dd1e 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -35,18 +35,9 @@ namespace Sci { class SciEngine; struct List; -enum DebugSeeking { - kDebugSeekNothing = 0, - kDebugSeekCallk = 1, // Step forward until callk is found - kDebugSeekLevelRet = 2, // Step forward until returned from this level - kDebugSeekSpecialCallk = 3, // Step forward until a /special/ callk is found - kDebugSeekSO = 4, // Step forward until specified PC (after the send command) and stack depth - kDebugSeekGlobal = 5 // Step forward until one specified global variable is modified -}; - // Refer to the "addresses" command on how to pass address parameters int parse_reg_t(EngineState *s, const char *str, reg_t *dest); -int printObject(EngineState *s, reg_t pos); +reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecode); class Console : public GUI::Debugger { public: @@ -55,12 +46,15 @@ public: void preEnter(); void postEnter(); + int printObject(reg_t pos); + private: // General bool cmdHelp(int argc, const char **argv); // Kernel // bool cmdClasses(int argc, const char **argv); // TODO bool cmdOpcodes(int argc, const char **argv); + bool cmdSelector(int argc, const char **argv); bool cmdSelectors(int argc, const char **argv); bool cmdKernelFunctions(int argc, const char **argv); bool cmdClassTable(int argc, const char **argv); @@ -163,6 +157,7 @@ private: private: SciEngine *_vm; + bool _mouseVisible; }; } // End of namespace Sci diff --git a/engines/sci/debug.h b/engines/sci/debug.h index e12d7fbe2d..cd2de2b3a9 100644 --- a/engines/sci/debug.h +++ b/engines/sci/debug.h @@ -28,22 +28,37 @@ namespace Sci { -// Various global variables used for debugging are declared here - -extern int g_stop_on_event; +enum DebugSeeking { + kDebugSeekNothing = 0, + kDebugSeekCallk = 1, // Step forward until callk is found + kDebugSeekLevelRet = 2, // Step forward until returned from this level + kDebugSeekSpecialCallk = 3, // Step forward until a /special/ callk is found + kDebugSeekSO = 4, // Step forward until specified PC (after the send command) and stack depth + kDebugSeekGlobal = 5 // Step forward until one specified global variable is modified +}; -extern int g_debugstate_valid; -extern int g_debug_seeking; -extern int g_debug_step_running; +struct ScriptState { + bool stopOnEvent; + DebugSeeking seeking; // Stepping forward until some special condition is met + int runningStep; // Set to > 0 to allow multiple stepping + int seekLevel; // Used for seekers that want to check their exec stack depth + int seekSpecial; // Used for special seeks + int old_pc_offset; + StackPtr old_sp; + ExecStack *xs; + int16 restAdjust; + reg_t *variables[4]; // global, local, temp, param, as immediate pointers + reg_t *variables_base[4]; // Used for referencing VM ops + SegmentId variables_seg[4]; // Same as above, contains segment IDs + int variables_max[4]; // Max. values for all variables +}; +// Various global variables used for debugging are declared here extern int g_debug_sleeptime_factor; extern int g_debug_simulated_key; extern bool g_debug_track_mouse_clicks; extern bool g_debug_weak_validations; -// Script related variables -extern int g_debug_seeking; -extern int g_debug_seek_special; -extern int g_debug_seek_level; +extern ScriptState scriptState; } // End of namespace Sci diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index bdf2c7c72a..7118eb682d 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -31,15 +31,8 @@ namespace Sci { -// The 4 SCI0 engine generations (pre-395, pre-502, pre-629 and post-629) -#define GF_FOR_SCI0_BEFORE_395 (GF_SCI0_OLD | GF_SCI0_OLDGFXFUNCS | GF_SCI0_OLDGETTIME) -#define GF_FOR_SCI0_BEFORE_502 (GF_SCI0_OLDGFXFUNCS | GF_SCI0_OLDGETTIME) #define GF_FOR_SCI0_BEFORE_629 GF_SCI0_OLDGETTIME -// SCI1 -#define GF_FOR_SCI1_200_OR_LATER GF_SCI1_LOFSABSOLUTE -#define GF_FOR_SCI1_510_OR_LATER (GF_SCI1_LOFSABSOLUTE | GF_SCI1_NEWDOSOUND) - // Titles of the games static const PlainGameDescriptor SciGameTitles[] = { {"sci", "Sierra SCI Game"}, @@ -134,7 +127,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "f3d1be7752d30ba60614533d531e2e98", 474}, {"resource.001", 0, "6fd05926c2199af0af6f72f90d0d7260", 126895}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_502, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -149,7 +142,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "d226d7d3b4f77c4a566913fc310487fc", 792380}, {"resource.003", 0, "d226d7d3b4f77c4a566913fc310487fc", 464348}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -164,7 +157,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "85e51acb5f9c539d66e3c8fe40e17da5", 826309}, {"resource.003", 0, "85e51acb5f9c539d66e3c8fe40e17da5", 493638}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -190,7 +183,19 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "d2f5a1be74ed963fa849a76892be5290", 794832}, {"resource.002", 0, "c0c29c51af66d65cb53f49e785a2d978", 1280907}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, + SCI_VERSION_AUTODETECT, + SCI_VERSION_1 + }, + + // Castle of Dr. Brain - English DOS Floppy 1.1 + {{"castlebrain", "", { + {"resource.map", 0, "f77728304c70017c54793eb6ca648174", 2745}, + {"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 347071}, + {"resource.001", 0, "13e81e1839cd7b216d2bb5615c1ca160", 796776}, + {"resource.002", 0, "930e416bec196b9703a331d81b3d66f2", 1283812}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -202,7 +207,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "27ec5fa09cd12a7fd16e86d96a2ed245", 1197694}, {"resource.001", 0, "735be4e58957180cfc807d5e18fdffcd", 1433302}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -213,7 +218,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "39485580d34a72997f3d5b3aba4d24f1", 426}, {"resource.001", 0, "11391434f41c834090d7a1e9488ce936", 129739}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_395, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -384,7 +389,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "1c3804e56b114028c5873a35c2f06d13", 653002}, {"resource.006", 0, "f9487732289a4f4966b4e34eea413325", 842817}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -401,7 +406,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "d036df0872f2db19bca34601276be2d7", 1154950}, {"resource.006", 0, "b367a6a59f29ee30dde1d88a5a41152d", 1042966}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -418,7 +423,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1261462}, {"resource.005", 0, "21ebe6b39b57a73fc449f67f013765aa", 1284720}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -434,7 +439,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "9cfce07e204a329e94fda8b5657621da", 1260237}, {"resource.005", 0, "21ebe6b39b57a73fc449f67f013765aa", 1284609}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -451,7 +456,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "58942b1aa6d6ffeb66e9f8897fd4435f", 469243}, {"resource.006", 0, "8c767b3939add63d11274065e46aad04", 713158}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER | GF_SCI1_EGA, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -479,7 +484,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "d036df0872f2db19bca34601276be2d7", 1176914}, {"resource.006", 0, "b367a6a59f29ee30dde1d88a5a41152d", 1123585}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -516,7 +521,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "28fe9b4f0567e71feb198bc9f3a2c605", 1241816}, {"resource.003", 0, "f3146df0ad4297f5ce35aa8c4753bf6c", 586832}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -530,7 +535,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "323b3b12f43d53f27d259beb225f0aa7", 1129316}, {"resource.003", 0, "83ac03e4bddb2c1ac2d36d2a587d0536", 1145616}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -544,7 +549,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "02d7d0411f7903aacb3bc8b0f8ca8a9a", 1202581}, {"resource.003", 0, "84dd11b6825255671c703aee5ceff620", 1175835}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -559,7 +564,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "2d21a1d2dcbffa551552e3e0725d2284", 1186033}, {"resource.003", 0, "84dd11b6825255671c703aee5ceff620", 1174993}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -795,16 +800,6 @@ static const struct SciGameDescription SciGameDescriptions[] = { }, #endif // ENABLE_SCI32 - // Hoyle 1 - English DOS Non-Interactive Demo - {{"hoyle1", "Demo", { - {"resource.map", 0, "60f764020a6b788bbbe415dbc2ccb9f3", 931}, - {"resource.000", 0, "5fe3670e3ddcd4f85c10013b5453141a", 615522}, - {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_629, - SCI_VERSION_AUTODETECT, - SCI_VERSION_0 - }, - // Hoyle 1 - English DOS (supplied by wibble92 in bug report #2644547) // SCI interpreter version 0.000.530 {{"hoyle1", "", { @@ -876,7 +871,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "595b6039ea1356e7f96a52c58eedcf22", 355791}, {"resource.001", 0, "143df8aef214a2db34c2d48190742012", 632273}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -889,7 +884,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "0d06cacc87dc21a08cd017e73036f905", 735}, {"resource.001", 0, "24db2bccda0a3c43ac4a7b5edb116c7e", 797678}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -902,7 +897,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "6ef28cac094dcd97fdb461662ead6f92", 541845}, {"resource.001", 0, "0a98a268ee99b92c233a0d7187c1f0fa", 845795}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -953,7 +948,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "59b13619078bd47011421468959ee5d4", 954}, {"resource.001", 0, "4cfb9040db152868f7cb6a1e8151c910", 296555}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, - GF_SCI0_SCI1VOCAB, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -1026,7 +1021,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.006", 0, "851a62d00972dc4002f472cc0d84e71d", 333777}, {"resource.007", 0, "851a62d00972dc4002f472cc0d84e71d", 341038}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_395, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -1043,7 +1038,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.006", 0, "0c8566848a76eea19a6d6220914030a7", 337288}, {"resource.007", 0, "0c8566848a76eea19a6d6220914030a7", 343882}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_395, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -1113,7 +1108,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "449471bfd77be52f18a3773c7f7d843d", 571368}, {"resource.001", 0, "b45a581ff8751e052c7e364f58d3617f", 16800210}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1154,6 +1149,25 @@ static const struct SciGameDescription SciGameDescriptions[] = { SCI_VERSION_1 }, + // King's Quest 5 - French DOS Floppy (from the King's Quest Collector's Edition 1994) + // Supplied by aroenai in bug report #2812611 + // VERSION file reports "1.000", SCI interpreter version 1.000.784 + {{"kq5", "", { + {"resource.map", 0, "eb7853832f3bb10900b13b421a0bbe7f", 8283}, + {"resource.000", 0, "f063775b279208c14a83eda47073be90", 332806}, + {"resource.001", 0, "3e6add38564250fd1a5bb10593007530", 1136827}, + {"resource.002", 0, "d9a97a9cf6c79bbe8f19378f6dea45d5", 1343738}, + {"resource.003", 0, "bef90d755076c110e67ee3e635503f82", 1324811}, + {"resource.004", 0, "c14dbafcfbe00855ac6b2f2701058047", 1332216}, + {"resource.005", 0, "f4b31cafc5defac75125c5f7b7f9a31a", 1268334}, + {"resource.006", 0, "f7dc85307632ef657ceb1651204f6f51", 1210081}, + {"resource.007", 0, "7db4d0a1d8d547c0019cb7d2a6acbdd4", 1338473}, + {NULL, 0, NULL, 0}}, Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH}, + 0, + SCI_VERSION_AUTODETECT, + SCI_VERSION_1 + }, + // King's Quest 5 - Italian DOS Floppy (from glorifindel) // SCI interpreter version 1.000.060 {{"kq5", "", { @@ -1235,7 +1249,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "233394a5f33b475ae5975e7e9a420865", 8376352}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, - 7, + SCI_VERSION_1_1, SCI_VERSION_1_1 }, @@ -1484,7 +1498,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "5790ac0505f7ca98d4567132b875eb1e", 681041}, {"resource.003", 0, "4a34c3367c2fe7eb380d741374da1989", 572251}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1497,7 +1511,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "ec20246209d7b19f38989261e5c8f5b8", 1111226}, {"resource.002", 0, "85d6935ef77e6b0e16bc307640a0d913", 1088312}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1510,7 +1524,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "d34cadb11e1aefbb497cf91bc1d3baa7", 1114688}, {"resource.002", 0, "85b030bb66d5342b0a068f1208c431a8", 1078443}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1537,7 +1551,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "3fe2a3aec0ed53c7d6db1845a67e3aa2", 1095908}, {"resource.003", 0, "ac175df0ea9a2cba57f0248651856d27", 376556}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1551,7 +1565,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "bc8ca10c807515d959cbd91f9ba47735", 1123759}, {"resource.002", 0, "b7409ab32bc3bee2d6cce887cd33f2b6", 1092160}, {NULL, 0, NULL, 0}}, Common::RU_RUS, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1578,7 +1592,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "03dba704bb77da55a91ad27b5a3cac09", 528}, {"resource.001", 0, "9f5520f0297206928df0b0b36493cd33", 127532}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_502, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -1594,7 +1608,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "4a24443a25e2b1492462a52809605dc2", 277732}, {"resource.006", 0, "4a24443a25e2b1492462a52809605dc2", 345683}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_502, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -1610,7 +1624,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "96033f57accfca903750413fd09193c8", 274953}, {"resource.006", 0, "96033f57accfca903750413fd09193c8", 345818}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_395, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -1718,7 +1732,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "f8b2d1137bb767e5d232056b99dd69eb", 623621}, {"resource.006", 0, "bafc64e3144f115dc58c6aee02de98fb", 715598}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1737,7 +1751,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.006", 0, "bafc64e3144f115dc58c6aee02de98fb", 754966}, {"resource.007", 0, "59eba83ad465b08d763b44f86afa86f6", 683135}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1766,7 +1780,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1024810}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 1030656}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1784,7 +1798,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1021774}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 993408}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1803,7 +1817,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 946540}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 958842}, {NULL, 0, NULL, 0}}, Common::FR_FRA, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1822,7 +1836,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.006", 0, "dda27ce00682aa76198dac124bbbe334", 1015136}, {"resource.007", 0, "ac443fae1285fb359bf2b2bc6a7301ae", 987222}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1833,7 +1847,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a99776df795127f387cb35dae872d4e4", 5919}, {"resource.000", 0, "a8989a5a89e7d4f702b26b378c7a357a", 7001981}, {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -1845,7 +1859,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "4462fe48c7452d98fddcec327a3e738d", 5789138}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, 0, - SCI_VERSION_1_1, + SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 }, @@ -1856,7 +1870,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "57d5fe8bb9e044158514476ea7678eb0", 5754790}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NONE}, 0, - SCI_VERSION_1_1, + SCI_VERSION_AUTODETECT, SCI_VERSION_1_1 }, @@ -2159,7 +2173,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "5b457cbe5042f557e5b610148171f6c0", 1158}, {"resource.001", 0, "453ea81ef66a50cbe33ce06302afe47f", 229737}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2208,6 +2222,17 @@ static const struct SciGameDescription SciGameDescriptions[] = { }, #endif // ENABLE_SCI32 + // Pepper's Adventure In Time 1.000 English + // Executable scanning reports "1.001.072", VERSION file reports "1.000" + {{"pepper", "", { + {"resource.map", 0, "72726dc81c1b4c1110c486be77369bc8", 5179}, + {"resource.000", 0, "670d0c53622429f4b11275caf7f8d292", 5459574}, + {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, + 0, + SCI_VERSION_AUTODETECT, + SCI_VERSION_1_1 + }, + // Pepper - English DOS Non-Interactive Demo // Executable scanning reports "1.001.060", VERSION file reports "1.000" {{"pepper", "Demo", { @@ -2272,7 +2297,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "8b77d0d4650c2052b356cece28294b58", 576}, {"resource.001", 0, "376ef6d6eaaeed66e1424bd219c4b9ab", 215398}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_502, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -2288,7 +2313,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "77f02def3094af804fd2371db25b7100", 349899}, {"resource.006", 0, "77f02def3094af804fd2371db25b7100", 354991}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_502, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -2301,7 +2326,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 546000}, {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 591851}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_502, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -2314,7 +2339,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "77f02def3094af804fd2371db25b7100", 542897}, {"resource.003", 0, "77f02def3094af804fd2371db25b7100", 586857}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_502, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -2330,7 +2355,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "630bfa65beb05f743552704ac2899dae", 759891}, {"resource.004", 0, "7b229fbdf30d670d0728cede3e984a7e", 838663}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2347,7 +2372,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "6258d5dd85898d8e218eb8113ebc9059", 722738}, {"resource.005", 0, "6258d5dd85898d8e218eb8113ebc9059", 704485}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2363,7 +2388,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "8791b9eef53edf77c2dac950142221d3", 1159791}, {"resource.004", 0, "1b91e891a3c60a941dac0eecdf83375b", 1143606}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2376,7 +2401,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.000", 0, "277f97771f7a6d89677141f02da313d6", 65150}, {"resource.001", 0, "5c5a551b6c86cce2ee75becb90e0b586", 624411}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2392,7 +2417,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "4836f460f4cfc8de61e2df4c45775504", 1180956}, {"resource.004", 0, "0c3eb84b9755852d9e795e0d5c9373c7", 1171760}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2856,7 +2881,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "b25a1539c71701f7715f738c5037e9a6", 775515}, {"resource.005", 0, "640ffe1a9acde392cc33cc1b1a528328", 806324}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2872,7 +2897,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "c47600e50c6fc591957ae0c5020ee7b8", 1213262}, {"resource.004", 0, "e19ea4ad131472f9238590f2e1d40289", 1203051}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2900,7 +2925,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "9b78228ad4f9f335fedf74f1812dcfca", 513325}, {"resource.005", 0, "7d4ebcb745c0bf8fc42e4013f52ecd49", 1101812}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -2914,7 +2939,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 746496}, {"resource.004", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 761984}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_502, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_0, SCI_VERSION_0 }, @@ -2930,7 +2955,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 545053}, {"resource.005", 0, "6d8f34090503ce937e7dbef6cb6cdb6a", 687507}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER, + 0, SCI_VERSION_0, SCI_VERSION_0 }, @@ -2941,7 +2966,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "ec66ac2b1ce58b2575ba00b65058de1a", 612}, {"resource.001", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 180245}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_502, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -2954,7 +2979,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 720244}, {"resource.003", 0, "ceeda7202b96e5c85ecaa88a40a540fc", 688367}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_502, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -2984,7 +3009,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.006", 0, "9107c2aa5398e28b5c5406df13491f85", 320643}, {"resource.007", 0, "9107c2aa5398e28b5c5406df13491f85", 344287}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI0_BEFORE_502, + GF_FOR_SCI0_BEFORE_629, SCI_VERSION_AUTODETECT, SCI_VERSION_0 }, @@ -3015,7 +3040,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "3540d1cc84d674cf4b2c898b88a3b563", 790296}, {"resource.006", 0, "ade814bc4d56244c156d9e9bcfebbc11", 664085}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3032,7 +3057,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "10ee1709e6559c724676d058199b75b5", 818745}, {"resource.006", 0, "67fb188b191d88efe8414af6ea297b93", 672675}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformAmiga, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3044,7 +3069,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "a18088c8aceb06025dbc945f29e02935", 5124}, {"resource.000", 0, "e1f46832cd2458796028e054a0466031", 5502009}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3056,7 +3081,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.map", 0, "71ccf4f82ac4efb588731acfb7bf2603", 5646}, {"resource.000", 0, "e1f46832cd2458796028e054a0466031", 933928}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3073,7 +3098,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "ff9c87da3bc53473fdee8b9d3edbc93c", 1200631}, {"resource.005", 0, "e33019ac19f755ae33fbf49b4fc9066c", 1053294}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3090,7 +3115,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.005", 0, "47ee647b5b12232d27e63cc627c25899", 1156765}, {"resource.006", 0, "dfb023e4e2a1e7a00fa18f9ede72a91b", 924059}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3106,7 +3131,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "4277c61bed40a50dadc4b5a344520af2", 1251000}, {"resource.005", 0, "5f885abd335978e2fd4e5f886d7676c8", 1102880}, {NULL, 0, NULL, 0}}, Common::IT_ITA, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3119,7 +3144,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088}, {"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249}, {NULL, 0, NULL, 0}}, Common::JA_JPN, Common::kPlatformPC98, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER | GF_SCI1_EGA, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3132,7 +3157,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.001", 0, "454684e3a7a68cbca073945e50778447", 1187088}, {"resource.002", 0, "6dc668326cc22cb9e8bd8ca9e68d2a66", 1181249}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC98, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_510_OR_LATER | GF_SCI1_EGA, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3160,7 +3185,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "776fba81c110d1908776232cbe190e20", 1253752}, {"resource.005", 0, "55fae26c2a92f16ef72c1e216e827c0f", 1098328}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NONE}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3175,7 +3200,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.002", 0, "74c62fa2146ff3b3b2ea2b3fb95b9af9", 1140801}, {"resource.003", 0, "42a307941edeb1a3be31daeb2e4be90b", 1088408}, {NULL, 0, NULL, 0}}, Common::ES_ESP, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3192,7 +3217,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { {"resource.004", 0, "c06350184a490c10eb4585fff0aa3192", 1254368}, {"resource.005", 0, "b8d6efbd3235329bfe844c794097b2c9", 1098717}, {NULL, 0, NULL, 0}}, Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH}, - GF_FOR_SCI1_200_OR_LATER, + 0, SCI_VERSION_AUTODETECT, SCI_VERSION_1 }, @@ -3415,7 +3440,7 @@ static const struct SciGameDescription SciGameDescriptions[] = { FANMADE("The Legend of the Lost Jewel", "ba1bca315e3818c5626eda51bcfbcccf", 636, "9b0736d69924af0cff32a0f78db96855", 300398), // FIXME: The vga demo does not have a resource.000/001 file. - //FANMADE_V("SCI VGA Demo", "00b1abd87bad356b90fcdfcb6132c26f", 8, "", 0, GF_FOR_SCI1_510_OR_LATER), + //FANMADE_V("SCI VGA Demo", "00b1abd87bad356b90fcdfcb6132c26f", 8, "", 0, 0), {AD_TABLE_END_MARKER, 0, SCI_VERSION_AUTODETECT, SCI_VERSION_0} }; diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index bbb29ada3b..0a74ac32e4 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -43,10 +43,8 @@ int _reset_graphics_input(EngineState *s) { gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0 }; debug(2, "Initializing graphics"); - if (s->resmgr->_sciVersion <= SCI_VERSION_01 || (s->_flags & GF_SCI1_EGA)) { - int i; - - for (i = 0; i < 16; i++) { + if (!s->resmgr->isVGA()) { + for (int i = 0; i < 16; i++) { if (gfxop_set_color(s->gfx_state, &(s->ega_colors[i]), gfx_sci0_image_colors[sci0_palette][i].r, gfx_sci0_image_colors[sci0_palette][i].g, gfx_sci0_image_colors[sci0_palette][i].b, 0, -1, -1)) { return 1; @@ -89,7 +87,7 @@ int _reset_graphics_input(EngineState *s) { s->priority_first = 42; // Priority zone 0 ends here - if (s->_flags & GF_SCI0_OLDGFXFUNCS) + if (((SciEngine*)g_engine)->getKernel()->usesOldGfxFunctions()) s->priority_last = 200; else s->priority_last = 190; @@ -97,7 +95,7 @@ int _reset_graphics_input(EngineState *s) { font_nr = -1; do { resource = s->resmgr->testResource(ResourceId(kResourceTypeFont, ++font_nr)); - } while ((!resource) && (font_nr < sci_max_resource_nr[s->resmgr->_sciVersion])); + } while ((!resource) && (font_nr < 65536)); if (!resource) { debug(2, "No text font was found."); @@ -111,7 +109,7 @@ int _reset_graphics_input(EngineState *s) { s->iconbar_port = new GfxPort(s->visual, gfx_rect(0, 0, 320, 200), s->ega_colors[0], transparent); s->iconbar_port->_flags |= GFXW_FLAG_NO_IMPLICIT_SWITCH; - if (s->resmgr->_sciVersion >= SCI_VERSION_01_VGA) { + if (s->resmgr->isVGA()) { // This bit sets the foreground and background colors in VGA SCI games gfx_color_t fgcolor; gfx_color_t bgcolor; @@ -259,7 +257,7 @@ static int create_class_table_sci0(EngineState *s) { Resource *script = s->resmgr->findResource(ResourceId(kResourceTypeScript, scriptnr), 0); if (script) { - if (s->_flags & GF_SCI0_OLD) + if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) magic_offset = seeker = 2; else magic_offset = seeker = 0; @@ -364,20 +362,17 @@ int script_init_engine(EngineState *s) { s->r_acc = s->r_prev = NULL_REG; - s->r_amp_rest = 0; + s->restAdjust = 0; s->_executionStack.clear(); // Start without any execution stack s->execution_stack_base = -1; // No vm is running yet - s->_kernel = new Kernel(s->resmgr, (s->_flags & GF_SCI0_OLD)); - s->_vocabulary = new Vocabulary(s->resmgr); - s->restarting_flags = SCI_GAME_IS_NOT_RESTARTING; s->bp_list = NULL; // No breakpoints defined s->have_bp = 0; - if ((s->_flags & GF_SCI1_LOFSABSOLUTE) && s->_version < SCI_VERSION_1_1) + if (((SciEngine*)g_engine)->getKernel()->hasLofsAbsolute()) s->seg_manager->setExportWidth(1); else s->seg_manager->setExportWidth(0); @@ -414,11 +409,6 @@ void script_free_engine(EngineState *s) { script_free_vm_memory(s); debug(2, "Freeing state-dependant data"); - - delete s->_vocabulary; - s->_vocabulary = 0; - delete s->_kernel; - s->_kernel = 0; } void script_free_breakpoints(EngineState *s) { @@ -466,7 +456,7 @@ int game_init(EngineState *s) { s->successor = NULL; // No successor s->_statusBarText.clear(); // Status bar is blank s->status_bar_foreground = 0; - s->status_bar_background = (s->resmgr->_sciVersion >= SCI_VERSION_01_VGA) ? 255 : 15; + s->status_bar_background = !s->resmgr->isVGA() ? 15 : 255; SystemString *str = &s->sys_strings->strings[SYS_STRING_PARSER_BASE]; str->name = strdup("parser-base"); diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index 1bfb66987e..63a20ddf25 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -29,7 +29,6 @@ namespace Sci { //#define DEBUG_GC -//#define DEBUG_GC_VERBOSE struct WorklistManager { Common::Array<reg_t> _worklist; @@ -39,9 +38,7 @@ struct WorklistManager { if (!reg.segment) // No numbers return; - #ifdef DEBUG_GC_VERBOSE - sciprintf("[GC] Adding %04x:%04x\n", PRINT_REG(reg)); - #endif + debugC(2, kDebugLevelGC, "[GC] Adding %04x:%04x\n", PRINT_REG(reg)); if (_map.contains(reg)) return; // already dealt with it @@ -92,9 +89,8 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { for (pos = s->stack_base; pos < xs.sp; pos++) wm.push(*pos); } -#ifdef DEBUG_GC_VERBOSE - sciprintf("[GC] -- Finished adding value stack"); -#endif + + debugC(2, kDebugLevelGC, "[GC] -- Finished adding value stack"); // Init: Execution Stack Common::List<ExecStack>::iterator iter; @@ -109,9 +105,8 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { wm.push(*(es.getVarPointer(s))); } } -#ifdef DEBUG_GC_VERBOSE - sciprintf("[GC] -- Finished adding execution stack"); -#endif + + debugC(2, kDebugLevelGC, "[GC] -- Finished adding execution stack"); // Init: Explicitly loaded scripts for (i = 1; i < sm->_heap.size(); i++) @@ -129,18 +124,15 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { } } } -#ifdef DEBUG_GC_VERBOSE - sciprintf("[GC] -- Finished explicitly loaded scripts, done with root set"); -#endif + + debugC(2, kDebugLevelGC, "[GC] -- Finished explicitly loaded scripts, done with root set\n"); // Run Worklist Algorithm while (!wm._worklist.empty()) { reg_t reg = wm._worklist.back(); wm._worklist.pop_back(); if (reg.segment != s->stack_segment) { // No need to repeat this one -#ifdef DEBUG_GC_VERBOSE - sciprintf("[GC] Checking %04x:%04x\n", PRINT_REG(reg)); -#endif + debugC(2, kDebugLevelGC, "[GC] Checking %04x:%04x\n", PRINT_REG(reg)); if (reg.segment < sm->_heap.size() && sm->_heap[reg.segment]) sm->_heap[reg.segment]->listAllOutgoingReferences(s, reg, &wm, add_outgoing_refs); } @@ -170,7 +162,7 @@ void free_unless_used(void *refcon, reg_t addr) { // Not found -> we can free it deallocator->mobj->freeAtAddress(deallocator->segmgr, addr); #ifdef DEBUG_GC - sciprintf("[GC] Deallocating %04x:%04x\n", PRINT_REG(addr)); + debugC(2, kDebugLevelGC, "[GC] Deallocating %04x:%04x\n", PRINT_REG(addr)); deallocator->segcount[deallocator->mobj->getType()]++; #endif } @@ -183,7 +175,7 @@ void run_gc(EngineState *s) { SegManager *sm = s->seg_manager; #ifdef DEBUG_GC - sciprintf("[GC] Running...\n"); + debugC(2, kDebugLevelGC, "[GC] Running...\n"); memset(&(deallocator.segcount), 0, sizeof(int) * (MEM_OBJ_MAX + 1)); #endif @@ -205,10 +197,10 @@ void run_gc(EngineState *s) { #ifdef DEBUG_GC { int i; - sciprintf("[GC] Summary:\n"); + debugC(2, kDebugLevelGC, "[GC] Summary:\n"); for (i = 0; i <= MEM_OBJ_MAX; i++) if (deallocator.segcount[i]) - sciprintf("\t%d\t* %s\n", deallocator.segcount[i], deallocator.segnames[i]); + debugC(2, kDebugLevelGC, "\t%d\t* %s\n", deallocator.segcount[i], deallocator.segnames[i]); } #endif } diff --git a/engines/sci/engine/grammar.cpp b/engines/sci/engine/grammar.cpp index 275a31a0d4..26f540a373 100644 --- a/engines/sci/engine/grammar.cpp +++ b/engines/sci/engine/grammar.cpp @@ -51,51 +51,51 @@ static void vocab_print_rule(parse_rule_t *rule) { int wspace = 0; if (!rule) { - sciprintf("NULL rule"); + warning("NULL rule"); return; } - sciprintf("[%03x] -> ", rule->id); + printf("[%03x] -> ", rule->id); if (!rule->length) - sciprintf("e"); + printf("e"); for (i = 0; i < rule->length; i++) { uint token = rule->data[i]; if (token == TOKEN_OPAREN) { if (i == rule->first_special) - sciprintf("_"); + printf("_"); - sciprintf("("); + printf("("); wspace = 0; } else if (token == TOKEN_CPAREN) { if (i == rule->first_special) - sciprintf("_"); + printf("_"); - sciprintf(")"); + printf(")"); wspace = 0; } else { if (wspace) - sciprintf(" "); + printf(" "); if (i == rule->first_special) - sciprintf("_"); + printf("_"); if (token & TOKEN_TERMINAL_CLASS) - sciprintf("C(%04x)", token & 0xffff); + printf("C(%04x)", token & 0xffff); else if (token & TOKEN_TERMINAL_GROUP) - sciprintf("G(%04x)", token & 0xffff); + printf("G(%04x)", token & 0xffff); else if (token & TOKEN_STUFFING_WORD) - sciprintf("%03x", token & 0xffff); + printf("%03x", token & 0xffff); else - sciprintf("[%03x]", token); /* non-terminal */ + printf("[%03x]", token); /* non-terminal */ wspace = 1; } if (i == rule->first_special) - sciprintf("_"); + printf("_"); } - sciprintf(" [%d specials]", rule->specials_nr); + printf(" [%d specials]", rule->specials_nr); } static void _vfree(parse_rule_t *rule) { @@ -287,12 +287,12 @@ static parse_rule_list_t *_vocab_add_rule(parse_rule_list_t *list, parse_rule_t static void _vprl(parse_rule_list_t *list, int pos) { if (list) { - sciprintf("R%03d: ", pos); + printf("R%03d: ", pos); vocab_print_rule(list->rule); - sciprintf("\n"); + printf("\n"); _vprl(list->next, pos + 1); } else { - sciprintf("%d rules total.\n", pos); + printf("%d rules total.\n", pos); } } @@ -351,7 +351,7 @@ parse_rule_list_t *Vocabulary::buildGNF(bool verbose) { int ntrules_nr; parse_rule_list_t *ntlist = NULL; parse_rule_list_t *tlist, *new_tlist; - GUI::Debugger *con = ((SciEngine *)g_engine)->getDebugger(); + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); for (uint i = 1; i < _parserBranches.size(); i++) { // branch rule 0 is treated specially parse_rule_t *rule = _vbuild_rule(&_parserBranches[i]); @@ -466,9 +466,9 @@ static int _vbpt_write_subexpression(parse_tree_node_t *nodes, int *pos, parse_r else writepos = _vbpt_append(nodes, pos, writepos, token & 0xffff); } else { - sciprintf("\nError in parser (grammar.cpp, _vbpt_write_subexpression()): Rule data broken in rule "); + printf("\nError in parser (grammar.cpp, _vbpt_write_subexpression()): Rule data broken in rule "); vocab_print_rule(rule); - sciprintf(", at token position %d\n", *pos); + printf(", at token position %d\n", *pos); return rulepos; } } @@ -477,7 +477,7 @@ static int _vbpt_write_subexpression(parse_tree_node_t *nodes, int *pos, parse_r } int Vocabulary::parseGNF(parse_tree_node_t *nodes, const ResultWordList &words, bool verbose) { - GUI::Debugger *con = ((SciEngine *)g_engine)->getDebugger(); + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); // Get the start rules: parse_rule_list_t *work = _vocab_clone_rule_list_by_id(_parserRules, _parserBranches[0].data[1]); parse_rule_list_t *results = NULL; diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index eafc6dbd4d..4133f4cb3b 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -38,127 +38,9 @@ namespace Sci { // Default kernel name table #define SCI0_KNAMES_WELL_DEFINED 0x6e -#define SCI0_KNAMES_DEFAULT_ENTRIES_NR 0x72 -#define SCI1_KNAMES_DEFAULT_ENTRIES_NR 0x89 +#define SCI_KNAMES_DEFAULT_ENTRIES_NR 0x89 -static const char *sci0_default_knames[SCI0_KNAMES_DEFAULT_ENTRIES_NR] = { - /*0x00*/ "Load", - /*0x01*/ "UnLoad", - /*0x02*/ "ScriptID", - /*0x03*/ "DisposeScript", - /*0x04*/ "Clone", - /*0x05*/ "DisposeClone", - /*0x06*/ "IsObject", - /*0x07*/ "RespondsTo", - /*0x08*/ "DrawPic", - /*0x09*/ "Show", - /*0x0a*/ "PicNotValid", - /*0x0b*/ "Animate", - /*0x0c*/ "SetNowSeen", - /*0x0d*/ "NumLoops", - /*0x0e*/ "NumCels", - /*0x0f*/ "CelWide", - /*0x10*/ "CelHigh", - /*0x11*/ "DrawCel", - /*0x12*/ "AddToPic", - /*0x13*/ "NewWindow", - /*0x14*/ "GetPort", - /*0x15*/ "SetPort", - /*0x16*/ "DisposeWindow", - /*0x17*/ "DrawControl", - /*0x18*/ "HiliteControl", - /*0x19*/ "EditControl", - /*0x1a*/ "TextSize", - /*0x1b*/ "Display", - /*0x1c*/ "GetEvent", - /*0x1d*/ "GlobalToLocal", - /*0x1e*/ "LocalToGlobal", - /*0x1f*/ "MapKeyToDir", - /*0x20*/ "DrawMenuBar", - /*0x21*/ "MenuSelect", - /*0x22*/ "AddMenu", - /*0x23*/ "DrawStatus", - /*0x24*/ "Parse", - /*0x25*/ "Said", - /*0x26*/ "SetSynonyms", - /*0x27*/ "HaveMouse", - /*0x28*/ "SetCursor", - /*0x29*/ "FOpen", - /*0x2a*/ "FPuts", - /*0x2b*/ "FGets", - /*0x2c*/ "FClose", - /*0x2d*/ "SaveGame", - /*0x2e*/ "RestoreGame", - /*0x2f*/ "RestartGame", - /*0x30*/ "GameIsRestarting", - /*0x31*/ "DoSound", - /*0x32*/ "NewList", - /*0x33*/ "DisposeList", - /*0x34*/ "NewNode", - /*0x35*/ "FirstNode", - /*0x36*/ "LastNode", - /*0x37*/ "EmptyList", - /*0x38*/ "NextNode", - /*0x39*/ "PrevNode", - /*0x3a*/ "NodeValue", - /*0x3b*/ "AddAfter", - /*0x3c*/ "AddToFront", - /*0x3d*/ "AddToEnd", - /*0x3e*/ "FindKey", - /*0x3f*/ "DeleteKey", - /*0x40*/ "Random", - /*0x41*/ "Abs", - /*0x42*/ "Sqrt", - /*0x43*/ "GetAngle", - /*0x44*/ "GetDistance", - /*0x45*/ "Wait", - /*0x46*/ "GetTime", - /*0x47*/ "StrEnd", - /*0x48*/ "StrCat", - /*0x49*/ "StrCmp", - /*0x4a*/ "StrLen", - /*0x4b*/ "StrCpy", - /*0x4c*/ "Format", - /*0x4d*/ "GetFarText", - /*0x4e*/ "ReadNumber", - /*0x4f*/ "BaseSetter", - /*0x50*/ "DirLoop", - /*0x51*/ "CanBeHere", - /*0x52*/ "OnControl", - /*0x53*/ "InitBresen", - /*0x54*/ "DoBresen", - /*0x55*/ "DoAvoider", - /*0x56*/ "SetJump", - /*0x57*/ "SetDebug", - /*0x58*/ "InspectObj", - /*0x59*/ "ShowSends", - /*0x5a*/ "ShowObjs", - /*0x5b*/ "ShowFree", - /*0x5c*/ "MemoryInfo", - /*0x5d*/ "StackUsage", - /*0x5e*/ "Profiler", - /*0x5f*/ "GetMenu", - /*0x60*/ "SetMenu", - /*0x61*/ "GetSaveFiles", - /*0x62*/ "GetCWD", - /*0x63*/ "CheckFreeSpace", - /*0x64*/ "ValidPath", - /*0x65*/ "CoordPri", - /*0x66*/ "StrAt", - /*0x67*/ "DeviceInfo", - /*0x68*/ "GetSaveDir", - /*0x69*/ "CheckSaveGame", - /*0x6a*/ "ShakeScreen", - /*0x6b*/ "FlushResources", - /*0x6c*/ "SinMult", - /*0x6d*/ "CosMult", - /*0x6e*/ "SinDiv", - /*0x6f*/ "CosDiv", - /*0x70*/ "Graph", - /*0x71*/ SCRIPT_UNKNOWN_FUNCTION_STRING -}; - -static const char *sci1_default_knames[SCI1_KNAMES_DEFAULT_ENTRIES_NR] = { +static const char *sci_default_knames[SCI_KNAMES_DEFAULT_ENTRIES_NR] = { /*0x00*/ "Load", /*0x01*/ "UnLoad", /*0x02*/ "ScriptID", @@ -427,7 +309,7 @@ SciKernelFunction kfunct_mappers[] = { /*6f*/ DEFUN("6f", kTimesCos, "ii"), /*70*/ DEFUN("Graph", kGraph, ".*"), /*71*/ DEFUN("Joystick", kJoystick, ".*"), - /*72*/ NOFUN("unknown72"), + /*72*/ NOFUN("unknown72"), // ShiftScreen, perhaps? /*73*/ NOFUN("unknown73"), // Experimental functions @@ -440,7 +322,6 @@ SciKernelFunction kfunct_mappers[] = { /*(?)*/ DEFUN("IsItSkip", kIsItSkip, "iiiii"), // Non-experimental Functions without a fixed ID - DEFUN("CosMult", kTimesCos, "ii"), DEFUN("SinMult", kTimesSin, "ii"), /*(?)*/ DEFUN("CosDiv", kCosDiv, "ii"), @@ -459,6 +340,21 @@ SciKernelFunction kfunct_mappers[] = { // Special and NOP stuff {NULL, k_Unknown, NULL}, + // Stub functions + DEFUN("ShiftScreen", kStub, ".*"), + DEFUN("MemorySegment", kStub, ".*"), + DEFUN("ListOps", kStub, ".*"), + DEFUN("ATan", kStub, ".*"), + DEFUN("StrSplit", kStub, ".*"), + DEFUN("MergePoly", kStub, ".*"), + DEFUN("AssertPalette", kStub, ".*"), + DEFUN("TextColors", kStub, ".*"), + DEFUN("TextFonts", kStub, ".*"), + DEFUN("Record", kStub, ".*"), + DEFUN("PlayBack", kStub, ".*"), + DEFUN("DbugStr", kStub, ".*"), + DEFUN("Platform", kStub, ".*"), // SCI1 + {NULL, NULL, NULL} // Terminator }; @@ -471,36 +367,127 @@ static const char *argtype_description[] = { "Arithmetic" }; -Kernel::Kernel(ResourceManager *resmgr, bool isOldSci0) : _resmgr(resmgr) { +Kernel::Kernel(ResourceManager *resmgr) : _resmgr(resmgr) { memset(&_selectorMap, 0, sizeof(_selectorMap)); // FIXME: Remove this once/if we C++ify selector_map_t + detectSciFeatures(); // must be called before loadSelectorNames() + loadSelectorNames(); + mapSelectors(); // Map a few special selectors for later use + loadOpcodes(); loadKernelNames(); + mapFunctions(); // Map the kernel functions +} - loadOpcodes(); +Kernel::~Kernel() { +} + +void Kernel::detectSciFeatures() { + Resource *r = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES), 0); - if (!loadSelectorNames(isOldSci0)) { - error("Kernel: Could not retrieve selector names"); + Common::StringList staticSelectorTable; + + if (!r) { // No such resource? + staticSelectorTable = checkStaticSelectorNames(); + if (staticSelectorTable.empty()) + error("Kernel: Could not retrieve selector names"); } - // Map the kernel functions - mapFunctions(); + int count = staticSelectorTable.empty() ? READ_LE_UINT16(r->data) + 1 : staticSelectorTable.size(); // Counter is slightly off + features = 0; - // Map a few special selectors for later use - mapSelectors(); -} + // Initialize features based on SCI version + if (_resmgr->_sciVersion == SCI_VERSION_0) { + features |= kFeatureOldScriptHeader; + features |= kFeatureOldGfxFunctions; + } -Kernel::~Kernel() { -} + for (int i = 0; i < count; i++) { + Common::String tmp; + + if (staticSelectorTable.empty()) { + int offset = READ_LE_UINT16(r->data + 2 + i * 2); + int len = READ_LE_UINT16(r->data + offset); + + tmp = Common::String((const char *)r->data + offset + 2, len); + } else { + tmp = staticSelectorTable[i]; + } + + if (tmp == "setTarget") // "motionInited" can also be used + features &= ~kFeatureOldScriptHeader; + + if (tmp == "motionCue") + features &= ~kFeatureOldGfxFunctions; + + if (tmp == "egoMoveSpeed" && _resmgr->_sciVersion < SCI_VERSION_1_1) + features |= kFeatureLofsAbsolute; -bool Kernel::loadSelectorNames(bool isOldSci0) { - int count; + if (tmp == "sightAngle" && _resmgr->_sciVersion == SCI_VERSION_0) + features |= kFeatureSci0Sci1Table; + + if (tmp == "setVol") + features |= kFeatureSci1Sound; + + if (tmp == "nodePtr") + features |= kFeatureSci01Sound; + } + + if (features & kFeatureSci1Sound) + features &= ~kFeatureSci01Sound; + + printf("Kernel auto-detected features:\n"); + + printf("Script block headers: "); + if (features & kFeatureOldScriptHeader) + printf("old\n"); + else + printf("new\n"); + printf("Graphics functions: "); + if (features & kFeatureOldGfxFunctions) + printf("old\n"); + else + printf("new\n"); + + printf("lofs parameters: "); + if (features & kFeatureLofsAbsolute) + printf("absolute\n"); + else + printf("relative\n"); + + printf("Sound functions: "); + if (features & kFeatureSci1Sound) + printf("SCI1\n"); + else if (features & kFeatureSci01Sound) + printf("SCI01\n"); + else + printf("SCI0\n"); + + if (features & kFeatureSci0Sci1Table) + printf("Found SCI0 game using a SCI1 kernel table\n"); +} + +void Kernel::loadSelectorNames() { Resource *r = _resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SNAMES), 0); - if (!r) // No such resource? - return false; + if (!r) { // No such resource? + // Check if we have a table for this game + // Some demos do not have a selector table + Common::StringList staticSelectorTable = checkStaticSelectorNames(); + + if (staticSelectorTable.empty()) + error("Kernel: Could not retrieve selector names"); + + for (uint32 i = 0; i < staticSelectorTable.size(); i++) { + _selectorNames.push_back(staticSelectorTable[i]); + if (features & kFeatureOldScriptHeader) + _selectorNames.push_back(staticSelectorTable[i]); + } + + return; + } - count = READ_LE_UINT16(r->data) + 1; // Counter is slightly off + int count = READ_LE_UINT16(r->data) + 1; // Counter is slightly off for (int i = 0; i < count; i++) { int offset = READ_LE_UINT16(r->data + 2 + i * 2); @@ -508,14 +495,13 @@ bool Kernel::loadSelectorNames(bool isOldSci0) { Common::String tmp((const char *)r->data + offset + 2, len); _selectorNames.push_back(tmp); + //printf("%s\n", tmp.c_str()); // debug // Early SCI versions used the LSB in the selector ID as a read/write // toggle. To compensate for that, we add every selector name twice. - if (isOldSci0) + if (features & kFeatureOldScriptHeader) _selectorNames.push_back(tmp); } - - return true; } bool Kernel::loadOpcodes() { @@ -706,15 +692,15 @@ void Kernel::mapFunctions() { _kernelFuncs[functnr].signature = kfunct_mappers[found].signature; kernel_compile_signature(&(_kernelFuncs[functnr].signature)); ++mapped; - } else + } else { + //warning("Ignoring function %s\n", kfunct_mappers[found].name); ++ignored; + } } } // for all functions requesting to be mapped - sciprintf("Handled %d/%d kernel functions, mapping %d", mapped + ignored, getKernelNamesSize(), mapped); - if (ignored) - sciprintf(" and ignoring %d", ignored); - sciprintf(".\n"); + debugC(2, kDebugLevelVM, "Handled %d/%d kernel functions, mapping %d and ignoring %d.\n", + mapped + ignored, getKernelNamesSize(), mapped, ignored); return; } @@ -792,12 +778,12 @@ bool kernel_matches_signature(EngineState *s, const char *sig, int argc, const r int type = determine_reg_type(s, *argv, *sig & KSIG_ALLOW_INV); if (!type) { - sciprintf("[KERN] Could not determine type of ref %04x:%04x; failing signature check\n", PRINT_REG(*argv)); + warning("[KERN] Could not determine type of ref %04x:%04x; failing signature check", PRINT_REG(*argv)); return false; } if (type & KSIG_INVALID) { - sciprintf("[KERN] ref %04x:%04x was determined to be a %s, but the reference itself is invalid\n", + warning("[KERN] ref %04x:%04x was determined to be a %s, but the reference itself is invalid", PRINT_REG(*argv), kernel_argtype_description(type)); return false; } @@ -846,72 +832,42 @@ reg_t *kernel_dereference_reg_pointer(EngineState *s, reg_t pointer, int entries return (reg_t*)_kernel_dereference_pointer(s, pointer, entries, sizeof(reg_t)); } -// Alternative kernel func names retriever. Required for KQ1/SCI (at least). -static void _vocab_get_knames0alt(const Resource *r, Common::StringList &names) { - uint idx = 0; - - while (idx < r->size) { - Common::String tmp((const char *)r->data + idx); - names.push_back(tmp); - idx += tmp.size() + 1; - } - - // The mystery kernel function- one in each SCI0 package - names.push_back(SCRIPT_UNKNOWN_FUNCTION_STRING); -} - -static void vocab_get_knames0(ResourceManager *resmgr, Common::StringList &names) { - int count, i, index = 2, empty_to_add = 1; - Resource *r = resmgr->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES), 0); - - if (!r) { // No kernel name table found? Fall back to default table - names.resize(SCI0_KNAMES_DEFAULT_ENTRIES_NR); - for (i = 0; i < SCI0_KNAMES_DEFAULT_ENTRIES_NR; i++) - names[i] = sci0_default_knames[i]; - return; - } - - count = READ_LE_UINT16(r->data); - - if (count > 1023) { - _vocab_get_knames0alt(r, names); - return; - } - - if (count < SCI0_KNAMES_WELL_DEFINED) { - empty_to_add = SCI0_KNAMES_WELL_DEFINED - count; - sciprintf("Less than %d kernel functions; adding %d\n", SCI0_KNAMES_WELL_DEFINED, empty_to_add); - } +void Kernel::setDefaultKernelNames() { + bool isSci0 = (_resmgr->_sciVersion == SCI_VERSION_0); + int offset = 0; + + // Check if we have a SCI01 game which uses a SCI1 kernel table (e.g. the KQ1 demo + // and full version). We do this by checking if the sightAngle selector exists, as no + // SCI0 game seems to have it + if (features & kFeatureSci0Sci1Table) + isSci0 = false; + + _kernelNames.resize(SCI_KNAMES_DEFAULT_ENTRIES_NR + (isSci0 ? 4 : 0)); + for (int i = 0; i < SCI_KNAMES_DEFAULT_ENTRIES_NR; i++) { + // In SCI0, Platform was DoAvoider + if (!strcmp(sci_default_knames[i], "Platform") && isSci0) { + _kernelNames[i + offset] = "DoAvoider"; + continue; + } - names.resize(count + 1 + empty_to_add); + _kernelNames[i + offset] = sci_default_knames[i]; - for (i = 0; i < count; i++) { - int offset = READ_LE_UINT16(r->data + index); - int len = READ_LE_UINT16(r->data + offset); - //fprintf(stderr,"Getting name %d of %d...\n", i, count); - index += 2; - names[i] = Common::String((const char *)r->data + offset + 2, len); + // SCI0 has 4 extra functions between SetCursor (0x28) and Savegame + if (!strcmp(sci_default_knames[i], "SetCursor") && isSci0) { + _kernelNames[i + 1] = "FOpen"; + _kernelNames[i + 2] = "FPuts"; + _kernelNames[i + 3] = "FGets"; + _kernelNames[i + 4] = "FClose"; + offset = 4; + } } - for (i = 0; i < empty_to_add; i++) { - names[count + i] = SCRIPT_UNKNOWN_FUNCTION_STRING; + if (_resmgr->_sciVersion == SCI_VERSION_1_1) { + // HACK: KQ6CD calls unimplemented function 0x26 + _kernelNames[0x26] = "Dummy"; } } -static void vocab_get_knames1(ResourceManager *resmgr, Common::StringList &names) { - // vocab.999/999.voc is notoriously unreliable in SCI1 games, and should not be used - // We hardcode the default SCI1 kernel names here (i.e. the ones inside the "special" - // 999.voc file from FreeSCI). All SCI1 games seem to be working with this change, but - // if any SCI1 game has different kernel vocabulary names, it might not work. It seems - // that all SCI1 games use the same kernel vocabulary names though, so this seems to be - // a safe change. If there's any SCI1 game with different kernel vocabulary names, we can - // add special flags to it to our detector - - names.resize(SCI1_KNAMES_DEFAULT_ENTRIES_NR); - for (int i = 0; i < SCI1_KNAMES_DEFAULT_ENTRIES_NR; i++) - names[i] = sci1_default_knames[i]; -} - #ifdef ENABLE_SCI32 static void vocab_get_knames11(ResourceManager *resmgr, Common::StringList &names) { /* @@ -945,27 +901,10 @@ bool Kernel::loadKernelNames() { switch (_resmgr->_sciVersion) { case SCI_VERSION_0: case SCI_VERSION_01: - // HACK: The KQ1 demo requires the SCI1 vocabulary. - if (((SciEngine*)g_engine)->getFlags() & GF_SCI0_SCI1VOCAB) - vocab_get_knames1(_resmgr, _kernelNames); - else - vocab_get_knames0(_resmgr, _kernelNames); - break; - case SCI_VERSION_01_VGA: case SCI_VERSION_01_VGA_ODD: - // HACK: KQ5 needs the SCI1 default vocabulary names to work correctly. - // Having more vocabulary names (like in SCI1) doesn't seem to have any - // ill effects, other than resulting in unmapped functions towards the - // end, which are never used by the game interpreter anyway - // return vocab_get_knames0(resmgr, count); - case SCI_VERSION_1_EARLY: - case SCI_VERSION_1_LATE: - vocab_get_knames1(_resmgr, _kernelNames); - break; + case SCI_VERSION_1: case SCI_VERSION_1_1: - vocab_get_knames1(_resmgr, _kernelNames); - // KQ6CD calls unimplemented function 0x26 - _kernelNames[0x26] = "Dummy"; + setDefaultKernelNames(); break; #ifdef ENABLE_SCI32 case SCI_VERSION_32: diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 46913a5b39..15f7c9fcf3 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -55,9 +55,18 @@ struct KernelFuncWithSignature { Common::String orig_name; /**< Original name, in case we couldn't map it */ }; +enum AutoDetectedFeatures { + kFeatureOldScriptHeader = 1 << 0, + kFeatureOldGfxFunctions = 1 << 1, + kFeatureLofsAbsolute = 1 << 2, + kFeatureSci01Sound = 1 << 3, + kFeatureSci1Sound = 1 << 4, + kFeatureSci0Sci1Table = 1 << 5 +}; + class Kernel { public: - Kernel(ResourceManager *resmgr, bool isOldSci0); + Kernel(ResourceManager *resmgr); ~Kernel(); uint getOpcodesSize() const { return _opcodes.size(); } @@ -83,6 +92,42 @@ public: */ bool hasKernelFunction(const char *functionName) const; + /** + * Applies to all versions before 0.000.395 (i.e. KQ4 old, XMAS 1988 and LSL2). + * Old SCI versions used two word header for script blocks (first word equal + * to 0x82, meaning of the second one unknown). New SCI versions used one + * word header. + * Also, old SCI versions assign 120 degrees to left & right, and 60 to up + * and down. Later versions use an even 90 degree distribution. + */ + bool hasOldScriptHeader() const { return (features & kFeatureOldScriptHeader); } + + /** + * Applies to all versions before 0.000.502 + * Old SCI versions used to interpret the third DrawPic() parameter inversely, + * with the opposite default value (obviously). + * Also, they used 15 priority zones from 42 to 200 instead of 14 priority + * zones from 42 to 190. + */ + bool usesOldGfxFunctions() const { return (features & kFeatureOldGfxFunctions); } + + /** + * Applies to all SCI1 versions after 1.000.200 + * In late SCI1 versions, the argument of lofs[as] instructions + * is absolute rather than relative. + */ + bool hasLofsAbsolute() const { return (features & kFeatureLofsAbsolute); } + + /** + * Determines if the game is using SCI01 sound functions + */ + bool usesSci01SoundFunctions() const { return (features & kFeatureSci01Sound); } + + /** + * Determines if the game is using SCI1 sound functions + */ + bool usesSci1SoundFunctions() const { return (features & kFeatureSci1Sound); } + // Script dissection/dumping functions void dissectScript(int scriptNumber, Vocabulary *vocab); void dumpScriptObject(char *data, int seeker, int objsize); @@ -104,10 +149,20 @@ private: bool loadKernelNames(); /** - * Loads the kernel selector names. - * @return True upon success, false otherwise. - */ - bool loadSelectorNames(bool isOldSci0); + * Sets the default kernel function names, based on the SCI version used + */ + void setDefaultKernelNames(); + + /** + * Loads the kernel selector names. + */ + void loadSelectorNames(); + + /** + * Check for any hardcoded selector table we might have that can be used + * if a game is missing the selector names. + */ + Common::StringList checkStaticSelectorNames(); /** * Maps special selectors @@ -115,6 +170,11 @@ private: void mapSelectors(); /** + * Detects SCI features based on the existence of certain selectors + */ + void detectSciFeatures(); + + /** * Maps kernel functions */ void mapFunctions(); @@ -126,6 +186,7 @@ private: bool loadOpcodes(); ResourceManager *_resmgr; + uint32 features; // Kernel-related lists /** @@ -144,7 +205,7 @@ enum SelectorInvocation { kContinueOnInvalidSelector = 1 }; -#define GET_SEL32(_o_, _slc_) read_selector(s, _o_, s->_kernel->_selectorMap._slc_, __FILE__, __LINE__) +#define GET_SEL32(_o_, _slc_) read_selector(s, _o_, ((SciEngine*)g_engine)->getKernel()->_selectorMap._slc_, __FILE__, __LINE__) #define GET_SEL32V(_o_, _slc_) (GET_SEL32(_o_, _slc_).offset) #define GET_SEL32SV(_o_, _slc_) ((int16)(GET_SEL32(_o_, _slc_).offset)) /* Retrieves a selector from an object @@ -155,8 +216,8 @@ enum SelectorInvocation { ** selector_map_t and mapped in script.c. */ -#define PUT_SEL32(_o_, _slc_, _val_) write_selector(s, _o_, s->_kernel->_selectorMap._slc_, _val_, __FILE__, __LINE__) -#define PUT_SEL32V(_o_, _slc_, _val_) write_selector(s, _o_, s->_kernel->_selectorMap._slc_, make_reg(0, _val_), __FILE__, __LINE__) +#define PUT_SEL32(_o_, _slc_, _val_) write_selector(s, _o_, ((SciEngine*)g_engine)->getKernel()->_selectorMap._slc_, _val_, __FILE__, __LINE__) +#define PUT_SEL32V(_o_, _slc_, _val_) write_selector(s, _o_, ((SciEngine*)g_engine)->getKernel()->_selectorMap._slc_, make_reg(0, _val_), __FILE__, __LINE__) /* Writes a selector value to an object ** Parameters: (reg_t) object: The address of the object which the selector should be written to ** (selector_name) selector: The selector to read @@ -168,7 +229,7 @@ enum SelectorInvocation { #define INV_SEL(_object_, _selector_, _noinvalid_) \ - s, _object_, s->_kernel->_selectorMap._selector_, _noinvalid_, funct_nr, argv, argc, __FILE__, __LINE__ + s, _object_, ((SciEngine*)g_engine)->getKernel()->_selectorMap._selector_, _noinvalid_, funct_nr, argv, argc, __FILE__, __LINE__ /* Kludge for use with invoke_selector(). Used for compatibility with compilers that can't ** handle vararg macros. */ @@ -482,12 +543,10 @@ reg_t kSetVideoMode(EngineState *s, int funct_nr, int argc, reg_t *argv); reg_t k_Unknown(EngineState *s, int funct_nr, int argc, reg_t *argv); // The Unknown/Unnamed kernel function -reg_t kstub(EngineState *s, int funct_nr, int argc, reg_t *argv); +reg_t kStub(EngineState *s, int funct_nr, int argc, reg_t *argv); // for unimplemented kernel functions reg_t kNOP(EngineState *s, int funct_nr, int argc, reg_t *argv); // for kernel functions that don't do anything -reg_t kFsciEmu(EngineState *s, int funct_nr, int argc, reg_t *argv); -// Emulating "old" kernel functions on the heap } // End of namespace Sci diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index d5a725a230..c4b3f5d71a 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -33,8 +33,6 @@ namespace Sci { -int g_stop_on_event = 0; - #define SCI_VARIABLE_GAME_SPEED 3 reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { @@ -89,11 +87,13 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { case SCI_EVT_KEYBOARD: if ((e.buckybits & SCI_EVM_LSHIFT) && (e.buckybits & SCI_EVM_RSHIFT) && (e.data == '-')) { - sciprintf("Debug mode activated\n"); - g_debug_seeking = g_debug_step_running = 0; + printf("Debug mode activated\n"); + scriptState.seeking = kDebugSeekNothing; + scriptState.runningStep = 0; } else if ((e.buckybits & SCI_EVM_CTRL) && (e.data == '`')) { - sciprintf("Debug mode activated\n"); - g_debug_seeking = g_debug_step_running = 0; + printf("Debug mode activated\n"); + scriptState.seeking = kDebugSeekNothing; + scriptState.runningStep = 0; } else { PUT_SEL32V(obj, type, SCI_EVT_KEYBOARD); // Keyboard event s->r_acc = make_reg(0, 1); @@ -110,7 +110,7 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { // track left buttton clicks, if requested if (e.type == SCI_EVT_MOUSE_PRESS && e.data == 1 && g_debug_track_mouse_clicks) { - ((SciEngine *)g_engine)->getDebugger()->DebugPrintf("Mouse clicked at %d, %d\n", + ((SciEngine *)g_engine)->getSciDebugger()->DebugPrintf("Mouse clicked at %d, %d\n", s->gfx_state->pointer_pos.x, s->gfx_state->pointer_pos.y); } @@ -137,11 +137,11 @@ reg_t kGetEvent(EngineState *s, int funct_nr, int argc, reg_t *argv) { s->r_acc = NULL_REG; // Unknown or no event } - if ((s->r_acc.offset) && (g_stop_on_event)) { - g_stop_on_event = 0; + if ((s->r_acc.offset) && (scriptState.stopOnEvent)) { + scriptState.stopOnEvent = false; // A SCI event occured, and we have been asked to stop, so open the debug console - GUI::Debugger *con = ((Sci::SciEngine*)g_engine)->getDebugger(); + Console *con = ((Sci::SciEngine*)g_engine)->getSciDebugger(); con->DebugPrintf("SCI event occured: "); switch (e.type) { case SCI_EVT_QUIT: diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 29c9c5e336..c03e69c6d0 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -267,6 +267,12 @@ static void fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) { return; } f->_in->readLine_NEW(dest, maxsize); + // The returned string must not have an ending LF + int strSize = strlen(dest); + if (strSize > 0) { + if (dest[strSize - 1] == 0x0A) + dest[strSize - 1] = 0; + } debugC(2, kDebugLevelFile, "FGets'ed \"%s\"\n", dest); } @@ -328,7 +334,7 @@ reg_t kGetCWD(EngineState *s, int funct_nr, int argc, reg_t *argv) { void delete_savegame(EngineState *s, int savedir_nr) { Common::String filename = ((Sci::SciEngine*)g_engine)->getSavegameName(savedir_nr); - sciprintf("Deleting savegame '%s'\n", filename.c_str()); + //printf("Deleting savegame '%s'\n", filename.c_str()); Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); saveFileMan->removeSavefile(filename); @@ -658,14 +664,14 @@ reg_t kRestoreGame(EngineState *s, int funct_nr, int argc, reg_t *argv) { shrink_execution_stack(s, s->execution_stack_base + 1); } else { s->r_acc = make_reg(0, 1); - sciprintf("Restoring failed (game_id = '%s').\n", game_id); + warning("Restoring failed (game_id = '%s')", game_id); } return s->r_acc; } } s->r_acc = make_reg(0, 1); - sciprintf("Savegame #%d not found!\n", savedir_nr); + warning("Savegame #%d not found", savedir_nr); return s->r_acc; } diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 2856c76aa3..c7086ddef7 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -25,6 +25,7 @@ #include "common/system.h" #include "common/events.h" +#include "graphics/cursorman.h" #include "sci/sci.h" #include "sci/debug.h" // for g_debug_sleeptime_factor @@ -163,7 +164,7 @@ int _find_view_priority(EngineState *s, int y) { return j; return 14; // Maximum } else { - if (!(s->_flags & GF_SCI0_OLDGFXFUNCS)) + if (!((SciEngine*)g_engine)->getKernel()->usesOldGfxFunctions()) return SCI0_VIEW_PRIORITY_14_ZONES(y); else return SCI0_VIEW_PRIORITY(y) == 15 ? 14 : SCI0_VIEW_PRIORITY(y); @@ -171,7 +172,7 @@ int _find_view_priority(EngineState *s, int y) { } int _find_priority_band(EngineState *s, int nr) { - if (!(s->_flags & GF_SCI0_OLDGFXFUNCS) && (nr < 0 || nr > 14)) { + if (!((SciEngine*)g_engine)->getKernel()->usesOldGfxFunctions() && (nr < 0 || nr > 14)) { if (nr == 15) return 0xffff; else { @@ -180,7 +181,7 @@ int _find_priority_band(EngineState *s, int nr) { return 0; } - if ((s->_flags & GF_SCI0_OLDGFXFUNCS) && (nr < 0 || nr > 15)) { + if (((SciEngine*)g_engine)->getKernel()->usesOldGfxFunctions() && (nr < 0 || nr > 15)) { warning("Attempt to get priority band %d", nr); return 0; } @@ -190,7 +191,7 @@ int _find_priority_band(EngineState *s, int nr) { else { int retval; - if (!(s->_flags & GF_SCI0_OLDGFXFUNCS)) + if (!((SciEngine*)g_engine)->getKernel()->usesOldGfxFunctions()) retval = SCI0_PRIORITY_BAND_FIRST_14_ZONES(nr); else retval = SCI0_PRIORITY_BAND_FIRST(nr); @@ -268,7 +269,7 @@ void graph_restore_box(EngineState *s, reg_t handle) { } PaletteEntry get_pic_color(EngineState *s, int color) { - if (s->resmgr->_sciVersion < SCI_VERSION_01_VGA) + if (!s->resmgr->isVGA()) return s->ega_colors[color].visual; if (color == -1 || color == 255) // -1 occurs in Eco Quest 1. Not sure if this is the best approach, but it seems to work @@ -285,7 +286,7 @@ PaletteEntry get_pic_color(EngineState *s, int color) { static gfx_color_t graph_map_color(EngineState *s, int color, int priority, int control) { gfx_color_t retval; - if (s->resmgr->_sciVersion < SCI_VERSION_01_VGA) { + if (!s->resmgr->isVGA()) { retval = s->ega_colors[(color >=0 && color < 16)? color : 0]; gfxop_set_color(s->gfx_state, &retval, (color < 0) ? -1 : retval.visual.r, retval.visual.g, retval.visual.b, (color == -1) ? 255 : 0, priority, control); @@ -303,21 +304,26 @@ static gfx_color_t graph_map_color(EngineState *s, int color, int priority, int reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { switch (argc) { case 1 : - if (s->_version < SCI_VERSION_1_1) { + if (s->_version < SCI_VERSION_1) { + GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, argv[0].toSint16())); + } else if (s->_version == SCI_VERSION_1) { if (argv[0].toSint16() <= 1) { // Newer (SCI1.1) semantics: show/hide cursor - g_system->showMouse(argv[0].toSint16() != 0); + CursorMan.showMouse(argv[0].toSint16() != 0); } else { // Pre-SCI1.1: set cursor according to the first parameter GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, argv[0].toSint16())); } - } else { + } else if (s->_version >= SCI_VERSION_1_1) { // SCI1.1: Show/hide cursor - g_system->showMouse(argv[0].toSint16() != 0); + CursorMan.showMouse(argv[0].toSint16() != 0); } break; case 2 : - if (s->_version < SCI_VERSION_1_1) { + if (s->_version < SCI_VERSION_1) { + GFX_ASSERT(gfxop_set_pointer_cursor(s->gfx_state, + argv[1].toSint16() == 0 ? GFXOP_NO_POINTER : argv[0].toSint16())); + } else if (s->_version == SCI_VERSION_1) { // Pre-SCI1.1: set cursor according to the first parameter, and toggle its // visibility based on the second parameter // Some late SCI1 games actually use the SCI1.1 version of this call (EcoQuest 1 @@ -336,7 +342,7 @@ reg_t kSetCursor(EngineState *s, int funct_nr, int argc, reg_t *argv) { GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, Common::Point(argv[0].toUint16(), argv[1].toUint16()))); } - } else { + } else if (s->_version >= SCI_VERSION_1_1) { // SCI1.1 and newer: set pointer position GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, Common::Point(argv[0].toUint16(), argv[1].toUint16()))); @@ -411,7 +417,7 @@ reg_t kShow(EngineState *s, int funct_nr, int argc, reg_t *argv) { s->visual->draw(Common::Point(0, 0)); gfxop_update(s->gfx_state); - sciprintf("Switching visible map to %x\n", s->pic_visible_map); + debugC(2, kDebugLevelGraphics, "Switching visible map to %x\n", s->pic_visible_map); } break; @@ -433,13 +439,12 @@ reg_t kPicNotValid(EngineState *s, int funct_nr, int argc, reg_t *argv) { } void _k_redraw_box(EngineState *s, int x1, int y1, int x2, int y2) { - sciprintf("_k_redraw_box(): Unimplemented!\n"); + warning("_k_redraw_box(): Unimplemented"); #if 0 int i; ViewObject *list = s->dyn_views; - sciprintf("Reanimating views\n", s->dyn_views_nr); - + printf("Reanimating views\n", s->dyn_views_nr); for (i = 0;i < s->dyn_views_nr;i++) { *(list[i].underBitsp) = graph_save_box(s, list[i].nsLeft, list[i].nsTop, list[i].nsRight - list[i].nsLeft, @@ -497,7 +502,7 @@ reg_t kGraph(EngineState *s, int funct_nr, int argc, reg_t *argv) { case K_GRAPH_GET_COLORS_NR: - return make_reg(0, s->resmgr->_sciVersion < SCI_VERSION_01_VGA ? 0x10 : 0x100); + return make_reg(0, !s->resmgr->isVGA() ? 0x10 : 0x100); break; case K_GRAPH_DRAW_LINE: { @@ -691,7 +696,7 @@ void _k_dirloop(reg_t obj, uint16 angle, EngineState *s, int funct_nr, int argc, angle %= 360; - if (!(s->_flags & GF_SCI0_OLD)) { + if (!((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) { if (angle < 45) loop = 3; else if (angle < 136) @@ -997,7 +1002,7 @@ reg_t kDrawPic(EngineState *s, int funct_nr, int argc, reg_t *argv) { gfx_color_t transparent = s->wm_port->_bgcolor; int picFlags = DRAWPIC01_FLAG_FILL_NORMALLY; - if (s->_flags & GF_SCI0_OLDGFXFUNCS) + if (((SciEngine*)g_engine)->getKernel()->usesOldGfxFunctions()) add_to_pic = (argc > 2) ? argv[2].toSint16() : false; dp.nr = argv[0].toSint16(); @@ -1051,7 +1056,7 @@ reg_t kDrawPic(EngineState *s, int funct_nr, int argc, reg_t *argv) { s->priority_first = 42; - if (s->_flags & GF_SCI0_OLDGFXFUNCS) + if (((SciEngine*)g_engine)->getKernel()->usesOldGfxFunctions()) s->priority_last = 200; else s->priority_last = 190; @@ -1074,7 +1079,7 @@ Common::Rect set_base(EngineState *s, reg_t object) { x = GET_SEL32SV(object, x); original_y = y = GET_SEL32SV(object, y); - if (s->_kernel->_selectorMap.z > -1) + if (((SciEngine*)g_engine)->getKernel()->_selectorMap.z > -1) z = GET_SEL32SV(object, z); else z = 0; @@ -1128,7 +1133,7 @@ Common::Rect set_base(EngineState *s, reg_t object) { void _k_base_setter(EngineState *s, reg_t object) { Common::Rect absrect = set_base(s, object); - if (lookup_selector(s, object, s->_kernel->_selectorMap.brLeft, NULL, NULL) != kSelectorVariable) + if (lookup_selector(s, object, ((SciEngine*)g_engine)->getKernel()->_selectorMap.brLeft, NULL, NULL) != kSelectorVariable) return; // non-fatal // Note: there was a check here for a very old version of SCI, which supposedly needed @@ -1209,7 +1214,7 @@ Common::Rect get_nsrect(EngineState *s, reg_t object, byte clip) { x = GET_SEL32SV(object, x); y = GET_SEL32SV(object, y); - if (s->_kernel->_selectorMap.z > -1) + if (((SciEngine*)g_engine)->getKernel()->_selectorMap.z > -1) z = GET_SEL32SV(object, z); else z = 0; @@ -1233,7 +1238,7 @@ Common::Rect get_nsrect(EngineState *s, reg_t object, byte clip) { static void _k_set_now_seen(EngineState *s, reg_t object) { Common::Rect absrect = get_nsrect(s, object, 0); - if (lookup_selector(s, object, s->_kernel->_selectorMap.nsTop, NULL, NULL) != kSelectorVariable) { + if (lookup_selector(s, object, ((SciEngine*)g_engine)->getKernel()->_selectorMap.nsTop, NULL, NULL) != kSelectorVariable) { return; } // This isn't fatal @@ -1719,7 +1724,7 @@ static void _k_view_list_do_postdraw(EngineState *s, GfxList *list) { * if ((widget->signal & (_K_VIEW_SIG_FLAG_PRIVATE | _K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_NO_UPDATE)) == _K_VIEW_SIG_FLAG_PRIVATE) { */ if ((widget->signal & (_K_VIEW_SIG_FLAG_REMOVE | _K_VIEW_SIG_FLAG_NO_UPDATE)) == 0) { - int has_nsrect = lookup_selector(s, obj, s->_kernel->_selectorMap.nsBottom, NULL, NULL) == kSelectorVariable; + int has_nsrect = lookup_selector(s, obj, ((SciEngine*)g_engine)->getKernel()->_selectorMap.nsBottom, NULL, NULL) == kSelectorVariable; if (has_nsrect) { int temp; @@ -1741,7 +1746,7 @@ static void _k_view_list_do_postdraw(EngineState *s, GfxList *list) { } #ifdef DEBUG_LSRECT else - fprintf(stderr, "Not lsRecting %04x:%04x because %d\n", PRINT_REG(obj), lookup_selector(s, obj, s->_kernel->_selectorMap.nsBottom, NULL, NULL)); + fprintf(stderr, "Not lsRecting %04x:%04x because %d\n", PRINT_REG(obj), lookup_selector(s, obj, ((SciEngine*)g_engine)->getKernel()->_selectorMap.nsBottom, NULL, NULL)); #endif if (widget->signal & _K_VIEW_SIG_FLAG_HIDDEN) @@ -1895,7 +1900,7 @@ static GfxDynView *_k_make_dynview_obj(EngineState *s, reg_t obj, int options, i loop = oldloop = sign_extend_byte(GET_SEL32V(obj, loop)); cel = oldcel = sign_extend_byte(GET_SEL32V(obj, cel)); - if (s->_kernel->_selectorMap.palette) + if (((SciEngine*)g_engine)->getKernel()->_selectorMap.palette) palette = GET_SEL32V(obj, palette); else palette = 0; @@ -1918,7 +1923,7 @@ static GfxDynView *_k_make_dynview_obj(EngineState *s, reg_t obj, int options, i } ObjVarRef under_bitsp; - if (lookup_selector(s, obj, s->_kernel->_selectorMap.underBits, &(under_bitsp), NULL) != kSelectorVariable) { + if (lookup_selector(s, obj, ((SciEngine*)g_engine)->getKernel()->_selectorMap.underBits, &(under_bitsp), NULL) != kSelectorVariable) { under_bitsp.obj = NULL_REG; under_bits = NULL_REG; debugC(2, kDebugLevelGraphics, "Object at %04x:%04x has no underBits\n", PRINT_REG(obj)); @@ -1926,7 +1931,7 @@ static GfxDynView *_k_make_dynview_obj(EngineState *s, reg_t obj, int options, i under_bits = *under_bitsp.getPointer(s); ObjVarRef signalp; - if (lookup_selector(s, obj, s->_kernel->_selectorMap.signal, &(signalp), NULL) != kSelectorVariable) { + if (lookup_selector(s, obj, ((SciEngine*)g_engine)->getKernel()->_selectorMap.signal, &(signalp), NULL) != kSelectorVariable) { signalp.obj = NULL_REG; signal = 0; debugC(2, kDebugLevelGraphics, "Object at %04x:%04x has no signal selector\n", PRINT_REG(obj)); @@ -2019,7 +2024,7 @@ static void _k_prepare_view_list(EngineState *s, GfxList *list, int options) { while (view) { reg_t obj = make_reg(view->_ID, view->_subID); int priority, _priority; - int has_nsrect = (view->_ID <= 0) ? 0 : lookup_selector(s, obj, s->_kernel->_selectorMap.nsBottom, NULL, NULL) == kSelectorVariable; + int has_nsrect = (view->_ID <= 0) ? 0 : lookup_selector(s, obj, ((SciEngine*)g_engine)->getKernel()->_selectorMap.nsBottom, NULL, NULL) == kSelectorVariable; int oldsignal = view->signal; _k_set_now_seen(s, obj); @@ -2458,7 +2463,7 @@ reg_t kDisposeWindow(EngineState *s, int funct_nr, int argc, reg_t *argv) { while (id > 0 && (!s->visual->_portRefs[id] || (s->visual->_portRefs[id]->_flags & GFXW_FLAG_NO_IMPLICIT_SWITCH))) id--; - sciprintf("Activating port %d after disposing window %d\n", id, goner_nr); + debugC(2, kDebugLevelGraphics, "Activating port %d after disposing window %d\n", id, goner_nr); s->port = (id >= 0) ? s->visual->_portRefs[id] : 0; if (!s->port) @@ -2497,7 +2502,7 @@ reg_t kNewWindow(EngineState *s, int funct_nr, int argc, reg_t *argv) { int16 bgColor = (argc > 8 + argextra) ? argv[8 + argextra].toSint16() : 255; if (bgColor >= 0) { - if (s->resmgr->_sciVersion < SCI_VERSION_01_VGA) + if (!s->resmgr->isVGA()) bgcolor.visual = get_pic_color(s, MIN<int>(bgColor, 15)); else bgcolor.visual = get_pic_color(s, bgColor); @@ -2523,7 +2528,7 @@ reg_t kNewWindow(EngineState *s, int funct_nr, int argc, reg_t *argv) { black.alpha = 0; black.control = -1; black.priority = -1; - lWhite.visual = get_pic_color(s, s->resmgr->_sciVersion < SCI_VERSION_01_VGA ? 15 : 255); + lWhite.visual = get_pic_color(s, !s->resmgr->isVGA() ? 15 : 255); lWhite.mask = GFX_MASK_VISUAL; lWhite.alpha = 0; lWhite.priority = -1; @@ -3144,7 +3149,7 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) { bg_color = port->_bgcolor; // TODO: in SCI1VGA the default colors for text and background are #0 (black) // SCI0 case should be checked - if (s->resmgr->_sciVersion >= SCI_VERSION_01_VGA) { + if (s->resmgr->isVGA()) { // This priority check fixes the colors in the menus in KQ5 // TODO/FIXME: Is this correct? if (color0.priority >= 0) @@ -3186,10 +3191,10 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) { temp = argv[argpt++].toSint16(); debugC(2, kDebugLevelGraphics, "Display: set_color(%d)\n", temp); - if ((s->resmgr->_sciVersion < SCI_VERSION_01_VGA) && temp >= 0 && temp <= 15) + if (!s->resmgr->isVGA() && temp >= 0 && temp <= 15) color0 = (s->ega_colors[temp]); else - if (s->resmgr->_sciVersion >= SCI_VERSION_01_VGA && temp >= 0 && temp < 256) { + if (s->resmgr->isVGA() && temp >= 0 && temp < 256) { color0.visual = get_pic_color(s, temp); color0.mask = GFX_MASK_VISUAL; } else @@ -3203,10 +3208,10 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) { temp = argv[argpt++].toSint16(); debugC(2, kDebugLevelGraphics, "Display: set_bg_color(%d)\n", temp); - if (s->resmgr->_sciVersion < SCI_VERSION_01_VGA && temp >= 0 && temp <= 15) + if (!s->resmgr->isVGA() && temp >= 0 && temp <= 15) bg_color = s->ega_colors[temp]; else - if ((s->resmgr->_sciVersion >= SCI_VERSION_01_VGA) && temp >= 0 && temp <= 256) { + if (s->resmgr->isVGA() && temp >= 0 && temp <= 256) { bg_color.visual = get_pic_color(s, temp); bg_color.mask = GFX_MASK_VISUAL; } else diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 7954dc5783..c693009b35 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -94,9 +94,10 @@ reg_t kFlushResources(EngineState *s, int funct_nr, int argc, reg_t *argv) { } reg_t kSetDebug(EngineState *s, int funct_nr, int argc, reg_t *argv) { - sciprintf("Debug mode activated\n"); + printf("Debug mode activated\n"); - g_debug_seeking = g_debug_step_running = 0; + scriptState.seeking = kDebugSeekNothing; + scriptState.runningStep = 0; return s->r_acc; } @@ -236,20 +237,27 @@ reg_t kMemory(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } -reg_t kstub(EngineState *s, int funct_nr, int argc, reg_t *argv) { - sciprintf("Unimplemented syscall: %s[%x](", s->_kernel->getKernelName(funct_nr).c_str(), funct_nr); +reg_t kStub(EngineState *s, int funct_nr, int argc, reg_t *argv) { + char tmpbuf[200]; + sprintf(tmpbuf, "Unimplemented syscall: %s[%x] (", + ((SciEngine*)g_engine)->getKernel()->getKernelName(funct_nr).c_str(), funct_nr); for (int i = 0; i < argc; i++) { - sciprintf("%04x:%04x", PRINT_REG(argv[i])); - if (i + 1 < argc) sciprintf(", "); + char tmpbuf2[20]; + sprintf(tmpbuf2, "%04x:%04x", PRINT_REG(argv[i])); + if (i + 1 < argc) + strcat(tmpbuf2, ", "); + strcat(tmpbuf, tmpbuf2); } - sciprintf(")\n"); + strcat(tmpbuf, ")"); + + warning(tmpbuf); return NULL_REG; } reg_t kNOP(EngineState *s, int funct_nr, int argc, reg_t *argv) { - warning("Kernel function 0x%02x (%s) invoked: unmapped", funct_nr, s->_kernel->_kernelFuncs[funct_nr].orig_name.c_str()); + warning("Kernel function 0x%02x (%s) invoked: unmapped", funct_nr, ((SciEngine*)g_engine)->getKernel()->_kernelFuncs[funct_nr].orig_name.c_str()); return NULL_REG; } diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index 20a7be3aea..8774224f60 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -267,7 +267,7 @@ static void bresenham_autodetect(EngineState *s) { return; } - if (lookup_selector(s, motion_class, s->_kernel->_selectorMap.doit, NULL, &fptr) != kSelectorMethod) { + if (lookup_selector(s, motion_class, ((SciEngine*)g_engine)->getKernel()->_selectorMap.doit, NULL, &fptr) != kSelectorMethod) { warning("bresenham_autodetect failed"); handle_movecnt = INCREMENT_MOVECNT; // Most games do this, so best guess return; @@ -275,7 +275,7 @@ static void bresenham_autodetect(EngineState *s) { buf = s->seg_manager->getScript(fptr.segment)->buf + fptr.offset; handle_movecnt = (s->_version <= SCI_VERSION_0 || checksum_bytes(buf, 8) == 0x216) ? INCREMENT_MOVECNT : IGNORE_MOVECNT; - sciprintf("b-moveCnt action based on checksum: %s\n", handle_movecnt == IGNORE_MOVECNT ? "ignore" : "increment"); + printf("b-moveCnt action based on checksum: %s\n", handle_movecnt == IGNORE_MOVECNT ? "ignore" : "increment"); } else { warning("bresenham_autodetect failed"); handle_movecnt = INCREMENT_MOVECNT; // Most games do this, so best guess @@ -313,7 +313,7 @@ reg_t kDoBresen(EngineState *s, int funct_nr, int argc, reg_t *argv) { bdelta = GET_SEL32SV(mover, b_incr); axis = GET_SEL32SV(mover, b_xAxis); - //sciprintf("movecnt %d, move speed %d\n", movcnt, max_movcnt); + //printf("movecnt %d, move speed %d\n", movcnt, max_movcnt); if (handle_movecnt) { if (max_movcnt > movcnt) { @@ -362,7 +362,7 @@ reg_t kDoBresen(EngineState *s, int funct_nr, int argc, reg_t *argv) { debugC(2, kDebugLevelBresen, "New data: (x,y)=(%d,%d), di=%d\n", x, y, bdi); - if (s->_kernel->_selectorMap.cantBeHere != -1) + if (((SciEngine*)g_engine)->getKernel()->_selectorMap.cantBeHere != -1) invoke_selector(INV_SEL(client, cantBeHere, kStopOnInvalidSelector), 0); else invoke_selector(INV_SEL(client, canBeHere, kStopOnInvalidSelector), 0); diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index c254875230..da24a388fa 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -410,24 +410,24 @@ static void print_polygon(EngineState *s, reg_t polygon) { int is_reg_t = polygon_is_reg_t(point_array, size); Common::Point point; - sciprintf("%i:", type); + printf("%i:", type); for (i = 0; i < size; i++) { point = read_point(point_array, is_reg_t, i); - sciprintf(" (%i, %i)", point.x, point.y); + printf(" (%i, %i)", point.x, point.y); } point = read_point(point_array, is_reg_t, 0); - sciprintf(" (%i, %i);\n", point.x, point.y); + printf(" (%i, %i);\n", point.x, point.y); } static void print_input(EngineState *s, reg_t poly_list, Common::Point start, Common::Point end, int opt) { List *list; Node *node; - sciprintf("Start point: (%i, %i)\n", start.x, start.y); - sciprintf("End point: (%i, %i)\n", end.x, end.y); - sciprintf("Optimization level: %i\n", opt); + printf("Start point: (%i, %i)\n", start.x, start.y); + printf("End point: (%i, %i)\n", end.x, end.y); + printf("Optimization level: %i\n", opt); if (!poly_list.segment) return; @@ -439,7 +439,7 @@ static void print_input(EngineState *s, reg_t poly_list, Common::Point start, Co return; } - sciprintf("Polygons:\n"); + printf("Polygons:\n"); node = lookup_node(s, list->first); while (node) { @@ -1539,7 +1539,7 @@ static void dijkstra(PathfindingState *s) { } if (min == HUGE_DISTANCE) { - sciprintf("[avoidpath] Warning: end point (%i, %i) is unreachable\n", s->vertex_end->v.x, s->vertex_end->v.y); + warning("[avoidpath] End point (%i, %i) is unreachable", s->vertex_end->v.x, s->vertex_end->v.y); return; } @@ -1629,13 +1629,13 @@ static reg_t output_path(PathfindingState *p, EngineState *s) { POLY_SET_POINT(oref, offset, Common::Point(POLY_LAST_POINT, POLY_LAST_POINT)); #ifdef DEBUG_AVOIDPATH - sciprintf("[avoidpath] Returning path:"); + printf("[avoidpath] Returning path:"); for (int i = 0; i < offset; i++) { Common::Point pt; POLY_GET_POINT(oref, i, pt); - sciprintf(" (%i, %i)", pt.x, pt.y); + printf(" (%i, %i)", pt.x, pt.y); } - sciprintf("\n"); + printf("\n"); #endif return output; @@ -1677,7 +1677,7 @@ reg_t kAvoidPath(EngineState *s, int funct_nr, int argc, reg_t *argv) { PathfindingState *p; #ifdef DEBUG_AVOIDPATH - sciprintf("[avoidpath] Pathfinding input:\n"); + printf("[avoidpath] Pathfinding input:\n"); draw_point(s, start, 1); draw_point(s, end, 0); @@ -1690,16 +1690,16 @@ reg_t kAvoidPath(EngineState *s, int funct_nr, int argc, reg_t *argv) { p = convert_polygon_set(s, poly_list, start, end, opt); if (p && intersecting_polygons(p)) { - sciprintf("[avoidpath] Error: input set contains (self-)intersecting polygons\n"); + warning("[avoidpath] input set contains (self-)intersecting polygons"); delete p; p = NULL; } if (!p) { byte *oref; - sciprintf("[avoidpath] Error: pathfinding failed for following input:\n"); + printf("[avoidpath] Error: pathfinding failed for following input:\n"); print_input(s, poly_list, start, end, opt); - sciprintf("[avoidpath] Returning direct path from start point to end point\n"); + printf("[avoidpath] Returning direct path from start point to end point\n"); oref = s->seg_manager->allocDynmem(POLY_POINT_SIZE * 3, AVOIDPATH_DYNMEM_STRING, &output); @@ -1720,8 +1720,7 @@ reg_t kAvoidPath(EngineState *s, int funct_nr, int argc, reg_t *argv) { } default: - warning("Unknown AvoidPath subfunction %d", - argc); + warning("Unknown AvoidPath subfunction %d", argc); return NULL_REG; break; } diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index d82f8ff132..df25e11729 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -43,7 +43,7 @@ reg_t read_selector(EngineState *s, reg_t object, Selector selector_id, const ch void write_selector(EngineState *s, reg_t object, Selector selector_id, reg_t value, const char *fname, int line) { ObjVarRef address; - if ((selector_id < 0) || (selector_id > (int)s->_kernel->getSelectorNamesSize())) { + if ((selector_id < 0) || (selector_id > (int)((SciEngine*)g_engine)->getKernel()->getSelectorNamesSize())) { warning("Attempt to write to invalid selector %d of" " object at %04x:%04x (%s L%d).", selector_id, PRINT_REG(object), fname, line); return; @@ -51,7 +51,7 @@ void write_selector(EngineState *s, reg_t object, Selector selector_id, reg_t va if (lookup_selector(s, object, selector_id, &address, NULL) != kSelectorVariable) warning("Selector '%s' of object at %04x:%04x could not be" - " written to (%s L%d)", s->_kernel->getSelectorName(selector_id).c_str(), PRINT_REG(object), fname, line); + " written to (%s L%d)", ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector_id).c_str(), PRINT_REG(object), fname, line); else *address.getPointer(s) = value; } @@ -72,7 +72,7 @@ int invoke_selector(EngineState *s, reg_t object, int selector_id, SelectorInvoc if (slc_type == kSelectorNone) { warning("Selector '%s' of object at %04x:%04x could not be invoked (%s L%d)", - s->_kernel->getSelectorName(selector_id).c_str(), PRINT_REG(object), fname, line); + ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector_id).c_str(), PRINT_REG(object), fname, line); if (noinvalid == kStopOnInvalidSelector) error("[Kernel] Not recoverable: VM was halted\n"); return 1; diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index bb27589d84..8c113d35a3 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -148,6 +148,9 @@ SongIterator *build_iterator(EngineState *s, int song_nr, SongIteratorType type, return songit_new(song->data, song->size, type, id); } +SongIterator *build_timeriterator(EngineState *s, int delta) { + return new_timer_iterator(delta); +} void process_sound_events(EngineState *s) { /* Get all sound events, apply their changes to the heap */ int result; @@ -194,7 +197,7 @@ void process_sound_events(EngineState *s) { /* Get all sound events, apply their break; default: - sciprintf("Unexpected result from sfx_poll: %d\n", result); + warning("Unexpected result from sfx_poll: %d", result); break; } } @@ -215,63 +218,63 @@ reg_t kDoSound_SCI0(EngineState *s, int funct_nr, int argc, reg_t *argv) { debugC(2, kDebugLevelSound, "Command 0x%x", command); switch (command) { case 0: - sciprintf("[InitObj]"); + debugC(2, kDebugLevelSound, "[InitObj]"); break; case 1: - sciprintf("[Play]"); + debugC(2, kDebugLevelSound, "[Play]"); break; case 2: - sciprintf("[NOP]"); + debugC(2, kDebugLevelSound, "[NOP]"); break; case 3: - sciprintf("[DisposeHandle]"); + debugC(2, kDebugLevelSound, "[DisposeHandle]"); break; case 4: - sciprintf("[SetSoundOn(?)]"); + debugC(2, kDebugLevelSound, "[SetSoundOn(?)]"); break; case 5: - sciprintf("[Stop]"); + debugC(2, kDebugLevelSound, "[Stop]"); break; case 6: - sciprintf("[Suspend]"); + debugC(2, kDebugLevelSound, "[Suspend]"); break; case 7: - sciprintf("[Resume]"); + debugC(2, kDebugLevelSound, "[Resume]"); break; case 8: - sciprintf("[Get(Set?)Volume]"); + debugC(2, kDebugLevelSound, "[Get(Set?)Volume]"); break; case 9: - sciprintf("[Signal: Obj changed]"); + debugC(2, kDebugLevelSound, "[Signal: Obj changed]"); break; case 10: - sciprintf("[Fade(?)]"); + debugC(2, kDebugLevelSound, "[Fade(?)]"); break; case 11: - sciprintf("[ChkDriver]"); + debugC(2, kDebugLevelSound, "[ChkDriver]"); break; case 12: - sciprintf("[PlayNextSong (formerly StopAll)]"); + debugC(2, kDebugLevelSound, "[PlayNextSong (formerly StopAll)]"); break; default: - sciprintf("[unknown]"); + debugC(2, kDebugLevelSound, "[unknown]"); break; } - sciprintf("("); + debugC(2, kDebugLevelSound, "("); for (i = 1; i < argc; i++) { - sciprintf("%04x:%04x", PRINT_REG(argv[i])); + debugC(2, kDebugLevelSound, "%04x:%04x", PRINT_REG(argv[i])); if (i + 1 < argc) - sciprintf(", "); + debugC(2, kDebugLevelSound, ", "); } - sciprintf(")\n"); + debugC(2, kDebugLevelSound, ")\n"); #endif // DEBUG_SOUND switch (command) { case _K_SCI0_SOUND_INIT_HANDLE: if (obj.segment) { - sciprintf("Initializing song number %d\n", GET_SEL32V(obj, number)); + debugC(2, kDebugLevelSound, "Initializing song number %d\n", GET_SEL32V(obj, number)); s->_sound.sfx_add_song(build_iterator(s, number, SCI_SONG_ITERATOR_TYPE_SCI0, handle), 0, handle, number); @@ -395,62 +398,62 @@ reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) { debugC(2, kDebugLevelSound, "Command 0x%x", command); switch (command) { case 0: - sciprintf("[MasterVolume]"); + debugC(2, kDebugLevelSound, "[MasterVolume]"); break; case 1: - sciprintf("[Mute]"); + debugC(2, kDebugLevelSound, "[Mute]"); break; case 2: - sciprintf("[NOP(2)]"); + debugC(2, kDebugLevelSound, "[NOP(2)]"); break; case 3: - sciprintf("[GetPolyphony]"); + debugC(2, kDebugLevelSound, "[GetPolyphony]"); break; case 4: - sciprintf("[Update]"); + debugC(2, kDebugLevelSound, "[Update]"); break; case 5: - sciprintf("[Init]"); + debugC(2, kDebugLevelSound, "[Init]"); break; case 6: - sciprintf("[Dispose]"); + debugC(2, kDebugLevelSound, "[Dispose]"); break; case 7: - sciprintf("[Play]"); + debugC(2, kDebugLevelSound, "[Play]"); break; case 8: - sciprintf("[Stop]"); + debugC(2, kDebugLevelSound, "[Stop]"); break; case 9: - sciprintf("[Suspend]"); + debugC(2, kDebugLevelSound, "[Suspend]"); break; case 10: - sciprintf("[Fade]"); + debugC(2, kDebugLevelSound, "[Fade]"); break; case 11: - sciprintf("[UpdateCues]"); + debugC(2, kDebugLevelSound, "[UpdateCues]"); break; case 12: - sciprintf("[MidiSend]"); + debugC(2, kDebugLevelSound, "[MidiSend]"); break; case 13: - sciprintf("[Reverb]"); + debugC(2, kDebugLevelSound, "[Reverb]"); break; case 14: - sciprintf("[Hold]"); + debugC(2, kDebugLevelSound, "[Hold]"); break; default: - sciprintf("[unknown]"); + debugC(2, kDebugLevelSound, "[unknown]"); break; } - sciprintf("("); + debugC(2, kDebugLevelSound, "("); for (i = 1; i < argc; i++) { - sciprintf("%04x:%04x", PRINT_REG(argv[i])); + debugC(2, kDebugLevelSound, "%04x:%04x", PRINT_REG(argv[i])); if (i + 1 < argc) - sciprintf(", "); + debugC(2, kDebugLevelSound, ", "); } - sciprintf(")\n"); + debugC(2, kDebugLevelSound, ")\n"); } #endif @@ -504,7 +507,7 @@ reg_t kDoSound_SCI01(EngineState *s, int funct_nr, int argc, reg_t *argv) { //int pri = GET_SEL32V(obj, pri); if (obj.segment && (s->resmgr->testResource(ResourceId(kResourceTypeSound, number)))) { - sciprintf("Initializing song number %d\n", number); + debugC(2, kDebugLevelSound, "Initializing song number %d\n", number); s->_sound.sfx_add_song(build_iterator(s, number, SCI_SONG_ITERATOR_TYPE_SCI1, handle), 0, handle, number); PUT_SEL32(obj, nodePtr, obj); @@ -685,80 +688,80 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { debugC(2, kDebugLevelSound, "Command 0x%x", command); switch (command) { case 0: - sciprintf("[MasterVolume]"); + debugC(2, kDebugLevelSound, "[MasterVolume]"); break; case 1: - sciprintf("[Mute]"); + debugC(2, kDebugLevelSound, "[Mute]"); break; case 2: - sciprintf("[NOP(2)]"); + debugC(2, kDebugLevelSound, "[NOP(2)]"); break; case 3: - sciprintf("[GetPolyphony]"); + debugC(2, kDebugLevelSound, "[GetPolyphony]"); break; case 4: - sciprintf("[GetAudioCapability]"); + debugC(2, kDebugLevelSound, "[GetAudioCapability]"); break; case 5: - sciprintf("[GlobalSuspend]"); + debugC(2, kDebugLevelSound, "[GlobalSuspend]"); break; case 6: - sciprintf("[Init]"); + debugC(2, kDebugLevelSound, "[Init]"); break; case 7: - sciprintf("[Dispose]"); + debugC(2, kDebugLevelSound, "[Dispose]"); break; case 8: - sciprintf("[Play]"); + debugC(2, kDebugLevelSound, "[Play]"); break; case 9: - sciprintf("[Stop]"); + debugC(2, kDebugLevelSound, "[Stop]"); break; case 10: - sciprintf("[SuspendHandle]"); + debugC(2, kDebugLevelSound, "[SuspendHandle]"); break; case 11: - sciprintf("[Fade]"); + debugC(2, kDebugLevelSound, "[Fade]"); break; case 12: - sciprintf("[Hold]"); + debugC(2, kDebugLevelSound, "[Hold]"); break; case 13: - sciprintf("[Unused(13)]"); + debugC(2, kDebugLevelSound, "[Unused(13)]"); break; case 14: - sciprintf("[SetVolume]"); + debugC(2, kDebugLevelSound, "[SetVolume]"); break; case 15: - sciprintf("[SetPriority]"); + debugC(2, kDebugLevelSound, "[SetPriority]"); break; case 16: - sciprintf("[SetLoop]"); + debugC(2, kDebugLevelSound, "[SetLoop]"); break; case 17: - sciprintf("[UpdateCues]"); + debugC(2, kDebugLevelSound, "[UpdateCues]"); break; case 18: - sciprintf("[MidiSend]"); + debugC(2, kDebugLevelSound, "[MidiSend]"); break; case 19: - sciprintf("[Reverb]"); + debugC(2, kDebugLevelSound, "[Reverb]"); break; case 20: - sciprintf("[UpdateVolPri]"); + debugC(2, kDebugLevelSound, "[UpdateVolPri]"); break; default: - sciprintf("[unknown]"); + debugC(2, kDebugLevelSound, "[unknown]"); break; } - sciprintf("("); + debugC(2, kDebugLevelSound, "("); for (i = 1; i < argc; i++) { - sciprintf("%04x:%04x", PRINT_REG(argv[i])); + debugC(2, kDebugLevelSound, "%04x:%04x", PRINT_REG(argv[i])); if (i + 1 < argc) - sciprintf(", "); + debugC(2, kDebugLevelSound, ", "); } - sciprintf(")\n"); + debugC(2, kDebugLevelSound, ")\n"); } #endif // DEBUG_SOUND @@ -798,6 +801,7 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { int looping = GET_SEL32V(obj, loop); //int vol = GET_SEL32V(obj, vol); int pri = GET_SEL32V(obj, pri); + int sampleLen = 0; Song *song = s->_sound._songlib.findSong(handle); if (GET_SEL32V(obj, nodePtr) && (song && number != song->_resourceNum)) { @@ -807,14 +811,31 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { } if (!GET_SEL32V(obj, nodePtr) && obj.segment) { - if (!s->resmgr->testResource(ResourceId(kResourceTypeSound, number))) { - sciprintf("Could not open song number %d\n", number); - return NULL_REG; + // In SCI1.1 games, sound effects are started from here. If we can find + // a relevant audio resource, play it, otherwise switch to synthesized + // effects. If the resource exists, play it using map 65535 (sound + // effects map) + if (s->resmgr->testResource(ResourceId(kResourceTypeAudio, number)) && + s->_version >= SCI_VERSION_1_1) { + // Found a relevant audio resource, play it + s->_sound.stopAudio(); + warning("Initializing audio resource instead of requested sound resource %d\n", number); + sampleLen = s->_sound.startAudio(65535, number); + // Also create iterator, that will fire SI_FINISHED event, when the sound is done playing + s->_sound.sfx_add_song(build_timeriterator(s, sampleLen), 0, handle, number); + } else { + if (!s->resmgr->testResource(ResourceId(kResourceTypeSound, number))) { + warning("Could not open song number %d", number); + // Send a "stop handle" event so that the engine won't wait forever here + s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED); + PUT_SEL32V(obj, signal, -1); + return s->r_acc; + } + debugC(2, kDebugLevelSound, "Initializing song number %d\n", number); + s->_sound.sfx_add_song(build_iterator(s, number, SCI_SONG_ITERATOR_TYPE_SCI1, + handle), 0, handle, number); } - sciprintf("Initializing song number %d\n", number); - s->_sound.sfx_add_song(build_iterator(s, number, SCI_SONG_ITERATOR_TYPE_SCI1, - handle), 0, handle, number); PUT_SEL32(obj, nodePtr, obj); PUT_SEL32(obj, handle, obj); } @@ -838,7 +859,7 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { } if (obj.segment && (s->resmgr->testResource(ResourceId(kResourceTypeSound, number)))) { - sciprintf("Initializing song number %d\n", number); + debugC(2, kDebugLevelSound, "Initializing song number %d\n", number); s->_sound.sfx_add_song(build_iterator(s, number, SCI_SONG_ITERATOR_TYPE_SCI1, handle), 0, handle, number); PUT_SEL32(obj, nodePtr, obj); @@ -925,14 +946,14 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { case SI_ABSOLUTE_CUE: signal = cue; - fprintf(stderr, "[CUE] %04x:%04x Absolute Cue: %d\n", + debugC(2, kDebugLevelSound, "[CUE] %04x:%04x Absolute Cue: %d\n", PRINT_REG(obj), signal); PUT_SEL32V(obj, signal, signal); break; case SI_RELATIVE_CUE: - fprintf(stderr, "[CUE] %04x:%04x Relative Cue: %d\n", + debugC(2, kDebugLevelSound, "[CUE] %04x:%04x Relative Cue: %d\n", PRINT_REG(obj), cue); PUT_SEL32V(obj, dataInc, cue); @@ -963,16 +984,21 @@ reg_t kDoSound_SCI1(EngineState *s, int funct_nr, int argc, reg_t *argv) { return s->r_acc; } +/** + * Used for synthesized music playback + */ reg_t kDoSound(EngineState *s, int funct_nr, int argc, reg_t *argv) { - if (s->_version >= SCI_VERSION_1_1 || s->_flags & GF_SCI1_NEWDOSOUND) + if (((SciEngine*)g_engine)->getKernel()->usesSci1SoundFunctions()) return kDoSound_SCI1(s, funct_nr, argc, argv); - else if (s->_version >= SCI_VERSION_01) + else if (((SciEngine*)g_engine)->getKernel()->usesSci01SoundFunctions()) return kDoSound_SCI01(s, funct_nr, argc, argv); else return kDoSound_SCI0(s, funct_nr, argc, argv); } -// Used for speech playback in CD games +/** + * Used for speech playback and digital soundtracks in CD games + */ reg_t kDoAudio(EngineState *s, int funct_nr, int argc, reg_t *argv) { Audio::Mixer *mixer = g_system->getMixer(); diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 2a30a103b6..b6bb404d5b 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -95,7 +95,7 @@ reg_t kSaid(EngineState *s, int funct_nr, int argc, reg_t *argv) { #ifdef DEBUG_PARSER debugC(2, kDebugLevelParser, "Said block:", 0); - s->_vocabulary->decipherSaidBlock(said_block); + ((SciEngine*)g_engine)->getVocabulary()->decipherSaidBlock(said_block); #endif if (s->parser_event.isNull() || (GET_SEL32V(s->parser_event, claimed))) { @@ -112,7 +112,7 @@ reg_t kSaid(EngineState *s, int funct_nr, int argc, reg_t *argv) { if (new_lastmatch != SAID_NO_MATCH) { /* Build and possibly display a parse tree */ #ifdef DEBUG_PARSER - sciprintf("Match.\n"); + printf("kSaid: Match.\n"); #endif s->r_acc = make_reg(0, 1); @@ -190,15 +190,11 @@ reg_t kParse(EngineState *s, int funct_nr, int argc, reg_t *argv) { char *error; ResultWordList words; reg_t event = argv[1]; + Vocabulary *voc = ((SciEngine*)g_engine)->getVocabulary(); s->parser_event = event; - if (s->parser_valid == 2) { - sciprintf("Parsing skipped: Parser in simparse mode\n"); - return s->r_acc; - } - - bool res = s->_vocabulary->tokenizeString(words, string, &error); + bool res = voc->tokenizeString(words, string, &error); s->parser_valid = 0; /* not valid */ if (res && !words.empty()) { @@ -216,7 +212,7 @@ reg_t kParse(EngineState *s, int funct_nr, int argc, reg_t *argv) { debugC(2, kDebugLevelParser, " Type[%04x] Group[%04x]\n", i->_class, i->_group); #endif - if (s->_vocabulary->parseGNF(s->parser_nodes, words)) + if (voc->parseGNF(s->parser_nodes, words)) syntax_fail = 1; /* Building a tree failed */ if (syntax_fail) { diff --git a/engines/sci/engine/memobj.cpp b/engines/sci/engine/memobj.cpp index 4d37d2aece..ab8e14efc7 100644 --- a/engines/sci/engine/memobj.cpp +++ b/engines/sci/engine/memobj.cpp @@ -159,7 +159,7 @@ bool Script::isValidOffset(uint16 offset) const { byte *Script::dereference(reg_t pointer, int *size) { if (pointer.offset > buf_size) { - sciprintf("Error: Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)\n", + warning("Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)\n", PRINT_REG(pointer), (uint)buf_size); return NULL; } @@ -231,9 +231,9 @@ reg_t Script::findCanonicAddress(SegManager *segmgr, reg_t addr) { void Script::freeAtAddress(SegManager *segmgr, reg_t addr) { /* - sciprintf("[GC] Freeing script %04x:%04x\n", PRINT_REG(addr)); + debugC(2, kDebugLevelGC, "[GC] Freeing script %04x:%04x\n", PRINT_REG(addr)); if (locals_segment) - sciprintf("[GC] Freeing locals %04x:0000\n", locals_segment); + debugC(2, kDebugLevelGC, "[GC] Freeing locals %04x:0000\n", locals_segment); */ if (_markedAsDeleted) @@ -289,7 +289,7 @@ void CloneTable::listAllOutgoingReferences(EngineState *s, reg_t addr, void *par // Note that this also includes the 'base' object, which is part of the script and therefore also emits the locals. (*note)(param, clone->pos); - //sciprintf("[GC] Reporting clone-pos %04x:%04x\n", PRINT_REG(clone->pos)); + //debugC(2, kDebugLevelGC, "[GC] Reporting clone-pos %04x:%04x\n", PRINT_REG(clone->pos)); } void CloneTable::freeAtAddress(SegManager *segmgr, reg_t addr) { @@ -302,15 +302,15 @@ void CloneTable::freeAtAddress(SegManager *segmgr, reg_t addr) { #ifdef GC_DEBUG if (!(victim_obj->flags & OBJECT_FLAG_FREED)) - sciprintf("[GC] Warning: Clone %04x:%04x not reachable and not freed (freeing now)\n", PRINT_REG(addr)); + warning("[GC] Clone %04x:%04x not reachable and not freed (freeing now)", PRINT_REG(addr)); #ifdef GC_DEBUG_VERBOSE else - sciprintf("[GC-DEBUG] Clone %04x:%04x: Freeing\n", PRINT_REG(addr)); + warning("[GC-DEBUG] Clone %04x:%04x: Freeing", PRINT_REG(addr)); #endif #endif /* - sciprintf("[GC] Clone %04x:%04x: Freeing\n", PRINT_REG(addr)); - sciprintf("[GC] Clone had pos %04x:%04x\n", PRINT_REG(victim_obj->pos)); + warning("[GC] Clone %04x:%04x: Freeing", PRINT_REG(addr)); + warning("[GC] Clone had pos %04x:%04x", PRINT_REG(victim_obj->pos)); */ clone_table->freeEntry(addr.offset); } diff --git a/engines/sci/engine/said.cpp b/engines/sci/engine/said.cpp index 327231857e..b1d174b30f 100644 --- a/engines/sci/engine/said.cpp +++ b/engines/sci/engine/said.cpp @@ -172,9 +172,10 @@ namespace Sci { #ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION -#define scidprintf sciprintf +#define scidprintf printf #else -#define scidprintf if (0) sciprintf +void print_nothing(...) { } +#define scidprintf print_nothing #endif @@ -2027,23 +2028,23 @@ static int said_parse_spec(EngineState *s, byte *spec) { if (nextitem == SAID_TERM) yyparse(); else { - sciprintf("Error: SAID spec is too long\n"); + warning("SAID spec is too long"); return 1; } if (said_parse_error) { - sciprintf("Error while parsing SAID spec: %s\n", said_parse_error); + warning("Error while parsing SAID spec: %s", said_parse_error); free(said_parse_error); return 1; } if (said_tree_pos == 0) { - sciprintf("Error: Out of tree space while parsing SAID spec\n"); + warning("Out of tree space while parsing SAID spec"); return 1; } if (said_blessed != 1) { - sciprintf("Error: Found multiple top branches\n"); + warning("Found multiple top branches"); return 1; } @@ -2146,7 +2147,7 @@ static void aug_find_words_recursively(parse_tree_node_t *tree, int startpos, in if ((word = aug_get_wgroup(tree, pos))) { // found a word if (!refbranch && major == WORD_TYPE_BASE) { if ((*base_words_nr) == maxwords) { - sciprintf("Out of regular words\n"); + warning("Out of regular words"); return; // return gracefully } @@ -2156,7 +2157,7 @@ static void aug_find_words_recursively(parse_tree_node_t *tree, int startpos, in } if (major == WORD_TYPE_REF || refbranch) { if ((*ref_words_nr) == maxwords) { - sciprintf("Out of reference words\n"); + warning("Out of reference words"); return; // return gracefully } @@ -2165,7 +2166,7 @@ static void aug_find_words_recursively(parse_tree_node_t *tree, int startpos, in } if (major != WORD_TYPE_SYNTACTIC_SUGAR && major != WORD_TYPE_BASE && major != WORD_TYPE_REF) - sciprintf("aug_find_words_recursively(): Unknown word type %03x\n", major); + warning("aug_find_words_recursively(): Unknown word type %03x", major); } else // Did NOT find a word group: Attempt to recurse aug_find_words_recursively(tree, pos, base_words, base_words_nr, @@ -2210,7 +2211,7 @@ static int augment_match_expression_p(parse_tree_node_t *saidt, int augment_pos, int cmajor, cminor, cpos; cpos = aug_get_first_child(saidt, augment_pos, &cmajor, &cminor); if (!cpos) { - sciprintf("augment_match_expression_p(): Empty condition\n"); + warning("augment_match_expression_p(): Empty condition"); return 1; } @@ -2246,7 +2247,7 @@ static int augment_match_expression_p(parse_tree_node_t *saidt, int augment_pos, gchild = aug_get_next_sibling(saidt, gchild, &gc_major, &gc_minor); } } else - sciprintf("augment_match_expression_p(): Unknown type 141 minor number %3x\n", cminor); + warning("augment_match_expression_p(): Unknown type 141 minor number %3x", cminor); cpos = aug_get_next_sibling(saidt, cpos, &cmajor, &cminor); @@ -2277,7 +2278,7 @@ static int augment_match_expression_p(parse_tree_node_t *saidt, int augment_pos, gchild = aug_get_next_sibling(saidt, gchild, &gc_major, &gc_minor); } } else - sciprintf("augment_match_expression_p(): Unknown type 144 minor number %3x\n", cminor); + warning("augment_match_expression_p(): Unknown type 144 minor number %3x", cminor); cpos = aug_get_next_sibling(saidt, cpos, &cmajor, &cminor); @@ -2303,17 +2304,17 @@ static int augment_match_expression_p(parse_tree_node_t *saidt, int augment_pos, break; default: - sciprintf("augment_match_expression_p(): (subp1) Unkonwn sub-bracket predicate %03x\n", cmajor); + warning("augment_match_expression_p(): (subp1) Unkonwn sub-bracket predicate %03x", cmajor); } break; default: - sciprintf("augment_match_expression_p(): Unknown predicate %03x\n", major); + warning("augment_match_expression_p(): Unknown predicate %03x", major); } - scidprintf("Generic failure\n"); + scidprintf("augment_match_expression_p(): Generic failure\n"); return 0; } @@ -2371,13 +2372,13 @@ static int augment_sentence_part(parse_tree_node_t *saidt, int augment_pos, pars aug_find_words(parset, parse_branch, base_words, &base_words_nr, ref_words, &ref_words_nr, AUGMENT_MAX_WORDS); foundwords |= (ref_words_nr | base_words_nr); #ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION - sciprintf("%d base words:", base_words_nr); + printf("%d base words:", base_words_nr); for (i = 0; i < base_words_nr; i++) - sciprintf(" %03x", base_words[i]); - sciprintf("\n%d reference words:", ref_words_nr); + printf(" %03x", base_words[i]); + printf("\n%d reference words:", ref_words_nr); for (i = 0; i < ref_words_nr; i++) - sciprintf(" %03x", ref_words[i]); - sciprintf("\n"); + printf(" %03x", ref_words[i]); + printf("\n"); #endif success = augment_sentence_expression(saidt, augment_pos, parset, parse_basepos, major, minor, @@ -2407,13 +2408,13 @@ static int augment_parse_nodes(parse_tree_node_t *parset, parse_tree_node_t *sai parse_basepos = aug_get_base_node(parset); if (!parse_basepos) { - sciprintf("augment_parse_nodes(): Parse tree is corrupt\n"); + warning("augment_parse_nodes(): Parse tree is corrupt"); return 0; } augment_basepos = aug_get_base_node(saidt); if (!augment_basepos) { - sciprintf("augment_parse_nodes(): Said tree is corrupt\n"); + warning("augment_parse_nodes(): Said tree is corrupt"); return 0; } @@ -2447,8 +2448,8 @@ int said(EngineState *s, byte *spec, int verbose) { if (s->parser_valid) { if (said_parse_spec(s, spec)) { - sciprintf("Offending spec was: "); - s->_vocabulary->decipherSaidBlock(spec); + printf("Offending spec was: "); + ((SciEngine*)g_engine)->getVocabulary()->decipherSaidBlock(spec); return SAID_NO_MATCH; } diff --git a/engines/sci/engine/said.y b/engines/sci/engine/said.y index 10906d94ef..e7c225b3e6 100644 --- a/engines/sci/engine/said.y +++ b/engines/sci/engine/said.y @@ -65,9 +65,10 @@ namespace Sci { #ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION -#define scidprintf sciprintf +#define scidprintf printf #else -#define scidprintf if (0) sciprintf +void print_nothing(...) { } +#define scidprintf print_nothing #endif @@ -383,23 +384,23 @@ static int said_parse_spec(EngineState *s, byte *spec) { if (nextitem == SAID_TERM) yyparse(); else { - sciprintf("Error: SAID spec is too long\n"); + warning("SAID spec is too long"); return 1; } if (said_parse_error) { - sciprintf("Error while parsing SAID spec: %s\n", said_parse_error); + warning("Error while parsing SAID spec: %s", said_parse_error); free(said_parse_error); return 1; } if (said_tree_pos == 0) { - sciprintf("Error: Out of tree space while parsing SAID spec\n"); + warning("Out of tree space while parsing SAID spec"); return 1; } if (said_blessed != 1) { - sciprintf("Error: Found multiple top branches\n"); + warning("Found multiple top branches"); return 1; } @@ -502,7 +503,7 @@ static void aug_find_words_recursively(parse_tree_node_t *tree, int startpos, in if ((word = aug_get_wgroup(tree, pos))) { // found a word if (!refbranch && major == WORD_TYPE_BASE) { if ((*base_words_nr) == maxwords) { - sciprintf("Out of regular words\n"); + warning("Out of regular words"); return; // return gracefully } @@ -512,7 +513,7 @@ static void aug_find_words_recursively(parse_tree_node_t *tree, int startpos, in } if (major == WORD_TYPE_REF || refbranch) { if ((*ref_words_nr) == maxwords) { - sciprintf("Out of reference words\n"); + warning("Out of reference words"); return; // return gracefully } @@ -521,7 +522,7 @@ static void aug_find_words_recursively(parse_tree_node_t *tree, int startpos, in } if (major != WORD_TYPE_SYNTACTIC_SUGAR && major != WORD_TYPE_BASE && major != WORD_TYPE_REF) - sciprintf("aug_find_words_recursively(): Unknown word type %03x\n", major); + warning("aug_find_words_recursively(): Unknown word type %03x", major); } else // Did NOT find a word group: Attempt to recurse aug_find_words_recursively(tree, pos, base_words, base_words_nr, @@ -566,7 +567,7 @@ static int augment_match_expression_p(parse_tree_node_t *saidt, int augment_pos, int cmajor, cminor, cpos; cpos = aug_get_first_child(saidt, augment_pos, &cmajor, &cminor); if (!cpos) { - sciprintf("augment_match_expression_p(): Empty condition\n"); + warning("augment_match_expression_p(): Empty condition"); return 1; } @@ -602,7 +603,7 @@ static int augment_match_expression_p(parse_tree_node_t *saidt, int augment_pos, gchild = aug_get_next_sibling(saidt, gchild, &gc_major, &gc_minor); } } else - sciprintf("augment_match_expression_p(): Unknown type 141 minor number %3x\n", cminor); + warning("augment_match_expression_p(): Unknown type 141 minor number %3x", cminor); cpos = aug_get_next_sibling(saidt, cpos, &cmajor, &cminor); @@ -633,7 +634,7 @@ static int augment_match_expression_p(parse_tree_node_t *saidt, int augment_pos, gchild = aug_get_next_sibling(saidt, gchild, &gc_major, &gc_minor); } } else - sciprintf("augment_match_expression_p(): Unknown type 144 minor number %3x\n", cminor); + warning("augment_match_expression_p(): Unknown type 144 minor number %3x", cminor); cpos = aug_get_next_sibling(saidt, cpos, &cmajor, &cminor); @@ -659,17 +660,17 @@ static int augment_match_expression_p(parse_tree_node_t *saidt, int augment_pos, break; default: - sciprintf("augment_match_expression_p(): (subp1) Unkonwn sub-bracket predicate %03x\n", cmajor); + warning("augment_match_expression_p(): (subp1) Unkonwn sub-bracket predicate %03x", cmajor); } break; default: - sciprintf("augment_match_expression_p(): Unknown predicate %03x\n", major); + warning("augment_match_expression_p(): Unknown predicate %03x", major); } - scidprintf("Generic failure\n"); + scidprintf("augment_match_expression_p(): Generic failure\n"); return 0; } @@ -727,13 +728,13 @@ static int augment_sentence_part(parse_tree_node_t *saidt, int augment_pos, pars aug_find_words(parset, parse_branch, base_words, &base_words_nr, ref_words, &ref_words_nr, AUGMENT_MAX_WORDS); foundwords |= (ref_words_nr | base_words_nr); #ifdef SCI_DEBUG_PARSE_TREE_AUGMENTATION - sciprintf("%d base words:", base_words_nr); + printf("%d base words:", base_words_nr); for (i = 0; i < base_words_nr; i++) - sciprintf(" %03x", base_words[i]); - sciprintf("\n%d reference words:", ref_words_nr); + printf(" %03x", base_words[i]); + printf("\n%d reference words:", ref_words_nr); for (i = 0; i < ref_words_nr; i++) - sciprintf(" %03x", ref_words[i]); - sciprintf("\n"); + printf(" %03x", ref_words[i]); + printf("\n"); #endif success = augment_sentence_expression(saidt, augment_pos, parset, parse_basepos, major, minor, @@ -763,13 +764,13 @@ static int augment_parse_nodes(parse_tree_node_t *parset, parse_tree_node_t *sai parse_basepos = aug_get_base_node(parset); if (!parse_basepos) { - sciprintf("augment_parse_nodes(): Parse tree is corrupt\n"); + warning("augment_parse_nodes(): Parse tree is corrupt"); return 0; } augment_basepos = aug_get_base_node(saidt); if (!augment_basepos) { - sciprintf("augment_parse_nodes(): Said tree is corrupt\n"); + warning("augment_parse_nodes(): Said tree is corrupt"); return 0; } @@ -803,8 +804,8 @@ int said(EngineState *s, byte *spec, int verbose) { if (s->parser_valid) { if (said_parse_spec(s, spec)) { - sciprintf("Offending spec was: "); - s->_vocabulary->decypherSaidBlock(spec); + warning("Offending spec was: "); + ((SciEngine*)g_engine)->getVocabulary()->decypherSaidBlock(spec); return SAID_NO_MATCH; } diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 146d65b56d..d5f094b540 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -464,15 +464,15 @@ int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename meta.savegame_time = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF); if (s->execution_stack_base) { - sciprintf("Cannot save from below kernel function\n"); + warning("Cannot save from below kernel function"); return 1; } /* if (s->sound_server) { if ((s->sound_server->save)(s, dirname)) { - sciprintf("Saving failed for the sound subsystem\n"); - chdir(".."); + warning("Saving failed for the sound subsystem"); + //chdir(".."); return 1; } } @@ -497,7 +497,7 @@ static SegmentId find_unique_seg_by_type(SegManager *self, int type) { } static byte *find_unique_script_block(EngineState *s, byte *buf, int type) { - if (s->_flags & GF_SCI0_OLD) + if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) buf += 2; do { @@ -616,7 +616,7 @@ static void reconstruct_scripts(EngineState *s, SegManager *self) { base_obj = obj_get(s, scr->_objects[j]._variables[SCRIPT_SPECIES_SELECTOR]); if (!base_obj) { - sciprintf("Object without a base class: Script %d, index %d (reg address %04x:%04x\n", + warning("Object without a base class: Script %d, index %d (reg address %04x:%04x", scr->nr, j, PRINT_REG(scr->_objects[j]._variables[SCRIPT_SPECIES_SELECTOR])); continue; } @@ -646,18 +646,18 @@ static void reconstruct_clones(EngineState *s, SegManager *self) { CloneTable *ct = (CloneTable *)mobj; /* - sciprintf("Free list: "); + printf("Free list: "); for (uint j = ct->first_free; j != HEAPENTRY_INVALID; j = ct->_table[j].next_free) { - sciprintf("%d ", j); + printf("%d ", j); } - sciprintf("\n"); + printf("\n"); - sciprintf("Entries w/zero vars: "); + printf("Entries w/zero vars: "); for (uint j = 0; j < ct->_table.size(); j++) { if (ct->_table[j].variables == NULL) - sciprintf("%d ", j); + printf("%d ", j); } - sciprintf("\n"); + printf("\n"); */ for (uint j = 0; j < ct->_table.size(); j++) { @@ -669,7 +669,7 @@ static void reconstruct_clones(EngineState *s, SegManager *self) { CloneTable::Entry &seeker = ct->_table[j]; base_obj = obj_get(s, seeker._variables[SCRIPT_SPECIES_SELECTOR]); if (!base_obj) { - sciprintf("Clone entry without a base class: %d\n", j); + printf("Clone entry without a base class: %d\n", j); seeker.base = seeker.base_obj = NULL; seeker.base_vars = seeker.base_method = NULL; } else { @@ -729,7 +729,7 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { /* if (s->sound_server) { if ((s->sound_server->restore)(s, dirname)) { - sciprintf("Restoring failed for the sound subsystem\n"); + warning("Restoring failed for the sound subsystem"); return NULL; } } @@ -746,9 +746,9 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { if ((meta.savegame_version < MINIMUM_SAVEGAME_VERSION) || (meta.savegame_version > CURRENT_SAVEGAME_VERSION)) { if (meta.savegame_version < MINIMUM_SAVEGAME_VERSION) - sciprintf("Old savegame version detected- can't load\n"); + warning("Old savegame version detected- can't load"); else - sciprintf("Savegame version is %d- maximum supported is %0d\n", meta.savegame_version, CURRENT_SAVEGAME_VERSION); + warning("Savegame version is %d- maximum supported is %0d", meta.savegame_version, CURRENT_SAVEGAME_VERSION); return NULL; } @@ -814,21 +814,9 @@ EngineState *gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { retval->game_start_time = g_system->getMillis() - retval->game_time * 1000; // static parser information: - assert(0 == retval->_vocabulary); - retval->_vocabulary = s->_vocabulary; -// s->_vocabulary = 0; // FIXME: We should set s->_vocabulary to 0 here, -// else it could be freed when the old EngineState is freed. Luckily, this freeing currently -// never happens, so we don't need to. retval->parser_base = make_reg(s->sys_strings_segment, SYS_STRING_PARSER_BASE); - // static VM/Kernel information: - assert(0 == retval->_kernel); - retval->_kernel = s->_kernel; -// s->_kernel = 0; // FIXME: We should set s->_kernel to 0 here, -// else it could be freed when the old EngineState is freed. Luckily, this freeing currently -// never happens, so we don't need to. - // Copy breakpoint information from current game instance retval->have_bp = s->have_bp; retval->bp_list = s->bp_list; @@ -864,9 +852,9 @@ bool get_savegame_metadata(Common::SeekableReadStream *stream, SavegameMetadata if ((meta->savegame_version < MINIMUM_SAVEGAME_VERSION) || (meta->savegame_version > CURRENT_SAVEGAME_VERSION)) { if (meta->savegame_version < MINIMUM_SAVEGAME_VERSION) - sciprintf("Old savegame version detected- can't load\n"); + warning("Old savegame version detected- can't load"); else - sciprintf("Savegame version is %d- maximum supported is %0d\n", meta->savegame_version, CURRENT_SAVEGAME_VERSION); + warning("Savegame version is %d- maximum supported is %0d", meta->savegame_version, CURRENT_SAVEGAME_VERSION); return false; } diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index fb094e00f6..b7529c33bd 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -30,8 +30,6 @@ namespace Sci { -// #define SCRIPT_DEBUG - #define END Script_None opcode_format g_opcode_formats[128][4] = { @@ -93,18 +91,16 @@ opcode_format g_opcode_formats[128][4] = { void script_adjust_opcode_formats(int res_version) { switch (res_version) { case SCI_VERSION_0: - case SCI_VERSION_01: break; - case SCI_VERSION_01_VGA: + case SCI_VERSION_01: case SCI_VERSION_01_VGA_ODD: - case SCI_VERSION_1_EARLY: - case SCI_VERSION_1_LATE: + case SCI_VERSION_1: case SCI_VERSION_1_1: g_opcode_formats[op_lofsa][0] = Script_Offset; g_opcode_formats[op_lofss][0] = Script_Offset; break; default: - sciprintf("script_adjust_opcode_formats(): Unknown script version %d\n", res_version); + error("script_adjust_opcode_formats(): Unknown script version %d\n", res_version); } } @@ -212,28 +208,27 @@ void Kernel::dumpScriptObject(char *data, int seeker, int objsize) { int namepos = (int16)READ_LE_UINT16((unsigned char *) data + 14 + seeker); int i = 0; - sciprintf("Object\n"); + printf("Object\n"); Common::hexdump((unsigned char *) data + seeker, objsize - 4, 16, seeker); //-4 because the size includes the two-word header - sciprintf("Name: %s\n", namepos ? ((char *)(data + namepos)) : "<unknown>"); - sciprintf("Superclass: %x\n", superclass); - sciprintf("Species: %x\n", species); - sciprintf("-info-:%x\n", (int16)READ_LE_UINT16((unsigned char *) data + 12 + seeker) & 0xffff); + printf("Name: %s\n", namepos ? ((char *)(data + namepos)) : "<unknown>"); + printf("Superclass: %x\n", superclass); + printf("Species: %x\n", species); + printf("-info-:%x\n", (int16)READ_LE_UINT16((unsigned char *) data + 12 + seeker) & 0xffff); - sciprintf("Function area offset: %x\n", (int16)READ_LE_UINT16((unsigned char *) data + seeker + 4)); - sciprintf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_LE_UINT16((unsigned char *) data + seeker + 6))); + printf("Function area offset: %x\n", (int16)READ_LE_UINT16((unsigned char *) data + seeker + 4)); + printf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_LE_UINT16((unsigned char *) data + seeker + 6))); seeker += 8; while (selectors--) { - sciprintf(" [#%03x] = 0x%x\n", i++, (int16)READ_LE_UINT16((unsigned char *)data + seeker) & 0xffff); - + printf(" [#%03x] = 0x%x\n", i++, (int16)READ_LE_UINT16((unsigned char *)data + seeker) & 0xffff); seeker += 2; } - sciprintf("Overridden functions: %x\n", selectors = overloads = (int16)READ_LE_UINT16((unsigned char *)data + seeker)); + printf("Overridden functions: %x\n", selectors = overloads = (int16)READ_LE_UINT16((unsigned char *)data + seeker)); seeker += 2; @@ -241,8 +236,8 @@ void Kernel::dumpScriptObject(char *data, int seeker, int objsize) { while (overloads--) { int selector = (int16)READ_LE_UINT16((unsigned char *) data + (seeker)); - sciprintf(" [%03x] %s: @", selector & 0xffff, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>"); - sciprintf("%04x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + selectors*2 + 2) & 0xffff); + printf(" [%03x] %s: @", selector & 0xffff, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>"); + printf("%04x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + selectors*2 + 2) & 0xffff); seeker += 2; } @@ -254,17 +249,17 @@ void Kernel::dumpScriptClass(char *data, int seeker, int objsize) { int superclass = (int16)READ_LE_UINT16((unsigned char *) data + 10 + seeker); int namepos = (int16)READ_LE_UINT16((unsigned char *) data + 14 + seeker); - sciprintf("Class\n"); + printf("Class\n"); Common::hexdump((unsigned char *) data + seeker, objsize - 4, 16, seeker); - sciprintf("Name: %s\n", namepos ? ((char *)data + namepos) : "<unknown>"); - sciprintf("Superclass: %x\n", superclass); - sciprintf("Species: %x\n", species); - sciprintf("-info-:%x\n", (int16)READ_LE_UINT16((unsigned char *)data + 12 + seeker) & 0xffff); + printf("Name: %s\n", namepos ? ((char *)data + namepos) : "<unknown>"); + printf("Superclass: %x\n", superclass); + printf("Species: %x\n", species); + printf("-info-:%x\n", (int16)READ_LE_UINT16((unsigned char *)data + 12 + seeker) & 0xffff); - sciprintf("Function area offset: %x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + 4)); - sciprintf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_LE_UINT16((unsigned char *)data + seeker + 6))); + printf("Function area offset: %x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + 4)); + printf("Selectors [%x]:\n", selectors = (selectorsize = (int16)READ_LE_UINT16((unsigned char *)data + seeker + 6))); seeker += 8; selectorsize <<= 1; @@ -272,7 +267,7 @@ void Kernel::dumpScriptClass(char *data, int seeker, int objsize) { while (selectors--) { int selector = (int16)READ_LE_UINT16((unsigned char *) data + (seeker) + selectorsize); - sciprintf(" [%03x] %s = 0x%x\n", 0xffff & selector, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>", + printf(" [%03x] %s = 0x%x\n", 0xffff & selector, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>", (int16)READ_LE_UINT16((unsigned char *)data + seeker) & 0xffff); seeker += 2; @@ -280,16 +275,16 @@ void Kernel::dumpScriptClass(char *data, int seeker, int objsize) { seeker += selectorsize; - sciprintf("Overloaded functions: %x\n", selectors = overloads = (int16)READ_LE_UINT16((unsigned char *)data + seeker)); + printf("Overloaded functions: %x\n", selectors = overloads = (int16)READ_LE_UINT16((unsigned char *)data + seeker)); seeker += 2; while (overloads--) { int selector = (int16)READ_LE_UINT16((unsigned char *)data + (seeker)); fprintf(stderr, "selector=%d; selectorNames.size() =%d\n", selector, _selectorNames.size()); - sciprintf(" [%03x] %s: @", selector & 0xffff, (selector >= 0 && selector < (int)_selectorNames.size()) ? + printf(" [%03x] %s: @", selector & 0xffff, (selector >= 0 && selector < (int)_selectorNames.size()) ? _selectorNames[selector].c_str() : "<?>"); - sciprintf("%04x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + selectors * 2 + 2) & 0xffff); + printf("%04x\n", (int16)READ_LE_UINT16((unsigned char *)data + seeker + selectors * 2 + 2) & 0xffff); seeker += 2; } @@ -301,7 +296,7 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { Resource *script = _resmgr->findResource(ResourceId(kResourceTypeScript, scriptNumber), 0); if (!script) { - sciprintf("Script not found!\n"); + warning("dissectScript(): Script not found!\n"); return; } @@ -311,17 +306,17 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { unsigned int seeker = _seeker + 4; if (!objtype) { - sciprintf("End of script object (#0) encountered.\n"); - sciprintf("Classes: %i, Objects: %i, Export: %i,\n Var: %i (all base 10)", + printf("End of script object (#0) encountered.\n"); + printf("Classes: %i, Objects: %i, Export: %i,\n Var: %i (all base 10)", objectctr[6], objectctr[1], objectctr[7], objectctr[10]); return; } - sciprintf("\n"); + printf("\n"); objsize = (int16)READ_LE_UINT16(script->data + _seeker + 2); - sciprintf("Obj type #%x, size 0x%x: ", objtype, objsize); + printf("Obj type #%x, size 0x%x: ", objtype, objsize); _seeker += objsize; @@ -333,72 +328,72 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { break; case SCI_OBJ_CODE: { - sciprintf("Code\n"); + printf("Code\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); }; break; case 3: { - sciprintf("<unknown>\n"); + printf("<unknown>\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); }; break; case SCI_OBJ_SAID: { - sciprintf("Said\n"); + printf("Said\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); - sciprintf("%04x: ", seeker); + printf("%04x: ", seeker); while (seeker < _seeker) { unsigned char nextitem = script->data [seeker++]; if (nextitem == 0xFF) - sciprintf("\n%04x: ", seeker); + printf("\n%04x: ", seeker); else if (nextitem >= 0xF0) { switch (nextitem) { case 0xf0: - sciprintf(", "); + printf(", "); break; case 0xf1: - sciprintf("& "); + printf("& "); break; case 0xf2: - sciprintf("/ "); + printf("/ "); break; case 0xf3: - sciprintf("( "); + printf("( "); break; case 0xf4: - sciprintf(") "); + printf(") "); break; case 0xf5: - sciprintf("[ "); + printf("[ "); break; case 0xf6: - sciprintf("] "); + printf("] "); break; case 0xf7: - sciprintf("# "); + printf("# "); break; case 0xf8: - sciprintf("< "); + printf("< "); break; case 0xf9: - sciprintf("> "); + printf("> "); break; } } else { nextitem = nextitem << 8 | script->data [seeker++]; - sciprintf("%s[%03x] ", vocab->getAnyWordFromGroup(nextitem), nextitem); + printf("%s[%03x] ", vocab->getAnyWordFromGroup(nextitem), nextitem); } } - sciprintf("\n"); + printf("\n"); } break; case SCI_OBJ_STRINGS: { - sciprintf("Strings\n"); + printf("Strings\n"); while (script->data [seeker]) { - sciprintf("%04x: %s\n", seeker, script->data + seeker); + printf("%04x: %s\n", seeker, script->data + seeker); seeker += strlen((char *)script->data + seeker) + 1; } seeker++; // the ending zero byte @@ -410,37 +405,37 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { break; case SCI_OBJ_EXPORTS: { - sciprintf("Exports\n"); + printf("Exports\n"); Common::hexdump((unsigned char *)script->data + seeker, objsize - 4, 16, seeker); }; break; case SCI_OBJ_POINTERS: { - sciprintf("Pointers\n"); + printf("Pointers\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); }; break; case 9: { - sciprintf("<unknown>\n"); + printf("<unknown>\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); }; break; case SCI_OBJ_LOCALVARS: { - sciprintf("Local vars\n"); + printf("Local vars\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); }; break; default: - sciprintf("Unsupported!\n"); + printf("Unsupported!\n"); return; } } - sciprintf("Script ends without terminator\n"); + printf("Script ends without terminator\n"); } } // End of namespace Sci diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 5b8dbe1869..98e5b08bb9 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -33,8 +33,6 @@ namespace Sci { struct EngineState; class ResourceManager; -/*#define SCRIPT_DEBUG */ - #define SCI_SCRIPTS_NR 1000 enum ScriptObjectTypes { diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 11c38052db..92cfe9daf3 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -32,29 +32,17 @@ namespace Sci { -int g_debugstate_valid = 0; // Set to 1 while script_debug is running -int g_debug_step_running = 0; // Set to >0 to allow multiple stepping -extern int g_debug_seek_special; - -static reg_t *p_pc; -static StackPtr *p_sp; -static StackPtr *p_pp; -static reg_t *p_objp; -static int *p_restadjust; -static SegmentId *p_var_segs; -static reg_t **p_vars; -static reg_t **p_var_base; -static int *p_var_max; // May be NULL even in valid state! - extern const char *selector_name(EngineState *s, int selector); +ScriptState scriptState; + int propertyOffsetToId(EngineState *s, int prop_ofs, reg_t objp) { Object *obj = obj_get(s, objp); byte *selectoroffset; int selectors; if (!obj) { - sciprintf("Applied propertyOffsetToId on non-object at %04x:%04x\n", PRINT_REG(objp)); + warning("Applied propertyOffsetToId on non-object at %04x:%04x", PRINT_REG(objp)); return -1; } @@ -71,7 +59,7 @@ int propertyOffsetToId(EngineState *s, int prop_ofs, reg_t objp) { } if (prop_ofs < 0 || (prop_ofs >> 1) >= selectors) { - sciprintf("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d]) on object at %04x:%04x\n", + warning("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d]) on object at %04x:%04x", prop_ofs, prop_ofs >> 1, selectors - 1, PRINT_REG(objp)); return -1; } @@ -93,7 +81,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod int i = 0; if (!mobj) { - sciprintf("Disassembly failed: Segment %04x non-existant or not a script\n", pos.segment); + warning("Disassembly failed: Segment %04x non-existant or not a script", pos.segment); return retval; } else script_entity = (Script *)mobj; @@ -102,21 +90,16 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod scr_size = script_entity->buf_size; if (pos.offset >= scr_size) { - sciprintf("Trying to disassemble beyond end of script\n"); + warning("Trying to disassemble beyond end of script"); return pos; } opsize = scr[pos.offset]; opcode = opsize >> 1; - if (!g_debugstate_valid) { - sciprintf("Not in debug state\n"); - return retval; - } - opsize &= 1; // byte if true, word if false - sciprintf("%04x:%04x: ", PRINT_REG(pos)); + printf("%04x:%04x: ", PRINT_REG(pos)); if (print_bytecode) { while (g_opcode_formats[opcode][i]) { @@ -152,36 +135,36 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } if (pos.offset + bytecount > scr_size) { - sciprintf("Operation arguments extend beyond end of script\n"); + warning("Operation arguments extend beyond end of script"); return retval; } for (i = 0; i < bytecount; i++) - sciprintf("%02x ", scr[pos.offset + i]); + printf("%02x ", scr[pos.offset + i]); for (i = bytecount; i < 5; i++) - sciprintf(" "); + printf(" "); } if (print_bw_tag) - sciprintf("[%c] ", opsize ? 'B' : 'W'); - sciprintf("%s", s->_kernel->getOpcode(opcode).name.c_str()); + printf("[%c] ", opsize ? 'B' : 'W'); + printf("%s", ((SciEngine*)g_engine)->getKernel()->getOpcode(opcode).name.c_str()); i = 0; while (g_opcode_formats[opcode][i]) { switch (g_opcode_formats[opcode][i++]) { case Script_Invalid: - sciprintf("-Invalid operation-"); + warning("-Invalid operation-"); break; case Script_SByte: case Script_Byte: - sciprintf(" %02x", scr[retval.offset++]); + printf(" %02x", scr[retval.offset++]); break; case Script_Word: case Script_SWord: - sciprintf(" %04x", 0xffff & (scr[retval.offset] | (scr[retval.offset+1] << 8))); + printf(" %04x", 0xffff & (scr[retval.offset] | (scr[retval.offset+1] << 8))); retval.offset += 2; break; @@ -200,11 +183,11 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } if (opcode == op_callk) - sciprintf(" %s[%x]", (param_value < s->_kernel->_kernelFuncs.size()) ? - ((param_value < s->_kernel->getKernelNamesSize()) ? s->_kernel->getKernelName(param_value).c_str() : "[Unknown(postulated)]") + printf(" %s[%x]", (param_value < ((SciEngine*)g_engine)->getKernel()->_kernelFuncs.size()) ? + ((param_value < ((SciEngine*)g_engine)->getKernel()->getKernelNamesSize()) ? ((SciEngine*)g_engine)->getKernel()->getKernelName(param_value).c_str() : "[Unknown(postulated)]") : "<invalid>", param_value); else - sciprintf(opsize ? " %02x" : " %04x", param_value); + printf(opsize ? " %02x" : " %04x", param_value); break; @@ -215,7 +198,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod param_value = 0xffff & (scr[retval.offset] | (scr[retval.offset+1] << 8)); retval.offset += 2; } - sciprintf(opsize ? " %02x" : " %04x", param_value); + printf(opsize ? " %02x" : " %04x", param_value); break; case Script_SRelative: @@ -225,7 +208,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod param_value = 0xffff & (scr[retval.offset] | (scr[retval.offset+1] << 8)); retval.offset += 2; } - sciprintf(opsize ? " %02x [%04x]" : " %04x [%04x]", param_value, (0xffff) & (retval.offset + param_value)); + printf(opsize ? " %02x [%04x]" : " %04x [%04x]", param_value, (0xffff) & (retval.offset + param_value)); break; case Script_End: @@ -233,55 +216,55 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod break; default: - sciprintf("Internal assertion failed in 'disassemble', %s, L%d\n", __FILE__, __LINE__); + error("Internal assertion failed in disassemble()"); } } - if (pos == *p_pc) { // Extra information if debugging the current opcode + if (pos == scriptState.xs->addr.pc) { // Extra information if debugging the current opcode if ((opcode == op_pTos) || (opcode == op_sTop) || (opcode == op_pToa) || (opcode == op_aTop) || (opcode == op_dpToa) || (opcode == op_ipToa) || (opcode == op_dpTos) || (opcode == op_ipTos)) { int prop_ofs = scr[pos.offset + 1]; - int prop_id = propertyOffsetToId(s, prop_ofs, *p_objp); + int prop_id = propertyOffsetToId(s, prop_ofs, scriptState.xs->objp); - sciprintf(" (%s)", selector_name(s, prop_id)); + printf(" (%s)", selector_name(s, prop_id)); } } - sciprintf("\n"); + printf("\n"); - if (pos == *p_pc) { // Extra information if debugging the current opcode + if (pos == scriptState.xs->addr.pc) { // Extra information if debugging the current opcode if (opcode == op_callk) { - int stackframe = (scr[pos.offset + 2] >> 1) + (*p_restadjust); - int argc = ((*p_sp)[- stackframe - 1]).offset; + int stackframe = (scr[pos.offset + 2] >> 1) + (scriptState.restAdjust); + int argc = ((scriptState.xs->sp)[- stackframe - 1]).offset; - if (!(s->_flags & GF_SCI0_OLD)) - argc += (*p_restadjust); + if (!((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) + argc += (scriptState.restAdjust); - sciprintf(" Kernel params: ("); + printf(" Kernel params: ("); for (int j = 0; j < argc; j++) { - sciprintf("%04x:%04x", PRINT_REG((*p_sp)[j - stackframe])); + printf("%04x:%04x", PRINT_REG((scriptState.xs->sp)[j - stackframe])); if (j + 1 < argc) - sciprintf(", "); + printf(", "); } - sciprintf(")\n"); + printf(")\n"); } else if ((opcode == op_send) || (opcode == op_self)) { - int restmod = *p_restadjust; + int restmod = scriptState.restAdjust; int stackframe = (scr[pos.offset + 1] >> 1) + restmod; - reg_t *sb = *p_sp; + reg_t *sb = scriptState.xs->sp; uint16 selector; reg_t fun_ref; while (stackframe > 0) { int argc = sb[- stackframe + 1].offset; const char *name = NULL; - reg_t called_obj_addr = *p_objp; + reg_t called_obj_addr = scriptState.xs->objp; if (opcode == op_send) called_obj_addr = s->r_acc; else if (opcode == op_self) - called_obj_addr = *p_objp; + called_obj_addr = scriptState.xs->objp; selector = sb[- stackframe].offset; @@ -290,32 +273,32 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (!name) name = "<invalid>"; - sciprintf(" %s::%s[", name, (selector > s->_kernel->getSelectorNamesSize()) ? "<invalid>" : selector_name(s, selector)); + printf(" %s::%s[", name, (selector > ((SciEngine*)g_engine)->getKernel()->getSelectorNamesSize()) ? "<invalid>" : selector_name(s, selector)); switch (lookup_selector(s, called_obj_addr, selector, 0, &fun_ref)) { case kSelectorMethod: - sciprintf("FUNCT"); + printf("FUNCT"); argc += restmod; restmod = 0; break; case kSelectorVariable: - sciprintf("VAR"); + printf("VAR"); break; case kSelectorNone: - sciprintf("INVALID"); + printf("INVALID"); break; } - sciprintf("]("); + printf("]("); while (argc--) { - sciprintf("%04x:%04x", PRINT_REG(sb[- stackframe + 2])); + printf("%04x:%04x", PRINT_REG(sb[- stackframe + 2])); if (argc) - sciprintf(", "); + printf(", "); stackframe--; } - sciprintf(")\n"); + printf(")\n"); stackframe -= 2; } // while (stackframe > 0) } // Send-like opcodes @@ -325,45 +308,30 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } -void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t *objp, int *restadjust, - SegmentId *segids, reg_t **variables, reg_t **variables_base, int *variables_nr, int bp) { +void script_debug(EngineState *s, bool bp) { // Do we support a separate console? - int old_debugstate = g_debugstate_valid; - - p_var_segs = segids; - p_vars = variables; - p_var_max = variables_nr; - p_var_base = variables_base; - p_pc = pc; - p_sp = sp; - p_pp = pp; - p_objp = objp; - p_restadjust = restadjust; - sciprintf("%d: acc=%04x:%04x ", script_step_counter, PRINT_REG(s->r_acc)); - g_debugstate_valid = 1; - disassemble(s, *pc, 0, 1); - if (g_debug_seeking == kDebugSeekGlobal) - sciprintf("Global %d (0x%x) = %04x:%04x\n", g_debug_seek_special, - g_debug_seek_special, PRINT_REG(s->script_000->locals_block->_locals[g_debug_seek_special])); - - g_debugstate_valid = old_debugstate; - - if (g_debug_seeking && !bp) { // Are we looking for something special? - MemObject *mobj = GET_SEGMENT(*s->seg_manager, pc->segment, MEM_OBJ_SCRIPT); + printf("%d: acc=%04x:%04x ", script_step_counter, PRINT_REG(s->r_acc)); + disassemble(s, scriptState.xs->addr.pc, 0, 1); + if (scriptState.seeking == kDebugSeekGlobal) + printf("Global %d (0x%x) = %04x:%04x\n", scriptState.seekSpecial, + scriptState.seekSpecial, PRINT_REG(s->script_000->locals_block->_locals[scriptState.seekSpecial])); + + if (scriptState.seeking && !bp) { // Are we looking for something special? + MemObject *mobj = GET_SEGMENT(*s->seg_manager, scriptState.xs->addr.pc.segment, MEM_OBJ_SCRIPT); if (mobj) { Script *scr = (Script *)mobj; byte *code_buf = scr->buf; int code_buf_size = scr->buf_size; - int opcode = pc->offset >= code_buf_size ? 0 : code_buf[pc->offset]; + int opcode = scriptState.xs->addr.pc.offset >= code_buf_size ? 0 : code_buf[scriptState.xs->addr.pc.offset]; int op = opcode >> 1; - int paramb1 = pc->offset + 1 >= code_buf_size ? 0 : code_buf[pc->offset + 1]; - int paramf1 = (opcode & 1) ? paramb1 : (pc->offset + 2 >= code_buf_size ? 0 : (int16)READ_LE_UINT16(code_buf + pc->offset + 1)); + int paramb1 = scriptState.xs->addr.pc.offset + 1 >= code_buf_size ? 0 : code_buf[scriptState.xs->addr.pc.offset + 1]; + int paramf1 = (opcode & 1) ? paramb1 : (scriptState.xs->addr.pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_LE_UINT16(code_buf + scriptState.xs->addr.pc.offset + 1)); - switch (g_debug_seeking) { + switch (scriptState.seeking) { case kDebugSeekSpecialCallk: - if (paramb1 != g_debug_seek_special) + if (paramb1 != scriptState.seekSpecial) return; case kDebugSeekCallk: { @@ -373,7 +341,7 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * } case kDebugSeekLevelRet: { - if ((op != op_ret) || (g_debug_seek_level < (int)s->_executionStack.size()-1)) + if ((op != op_ret) || (scriptState.seekLevel < (int)s->_executionStack.size()-1)) return; break; } @@ -385,34 +353,26 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, reg_t * return; // param or temp if ((op & 0x3) && s->_executionStack.back().local_segment > 0) return; // locals and not running in script.000 - if (paramf1 != g_debug_seek_special) + if (paramf1 != scriptState.seekSpecial) return; // CORRECT global? break; + case kDebugSeekSO: + // FIXME: Unhandled? + break; + + case kDebugSeekNothing: + // We seek nothing, so just continue + break; } - g_debug_seeking = kDebugSeekNothing; + scriptState.seeking = kDebugSeekNothing; // OK, found whatever we were looking for } } - - g_debugstate_valid = (g_debug_step_running == 0); - - if (g_debugstate_valid) { - p_pc = pc; - p_sp = sp; - p_pp = pp; - p_objp = objp; - p_restadjust = restadjust; - p_var_segs = segids; - p_vars = variables; - p_var_max = variables_nr; - p_var_base = variables_base; - - sciprintf("Step #%d\n", script_step_counter); - disassemble(s, *pc, 0, 1); - } - + + printf("Step #%d\n", script_step_counter); + disassemble(s, scriptState.xs->addr.pc, 0, 1); } } // End of namespace Sci diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 2227167673..6752ba3e56 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -121,7 +121,7 @@ Script *SegManager::allocateScript(EngineState *s, int script_nr, SegmentId *seg // allocate the MemObject mem = memObjAllocate(*seg_id, script_nr, MEM_OBJ_SCRIPT); if (!mem) { - sciprintf("%s, %d, Not enough memory, ", __FILE__, __LINE__); + error("allocateScript: Not enough memory"); return NULL; } @@ -138,7 +138,7 @@ void SegManager::setScriptSize(Script &scr, EngineState *s, int script_nr) { if (!script || (s->_version >= SCI_VERSION_1_1 && !heap)) { error("SegManager::setScriptSize: failed to load %s", !script ? "script" : "heap"); } - if (s->_flags & GF_SCI0_OLD) { + if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) { scr.buf_size = script->size + READ_LE_UINT16(script->data) * 2; //locals_size = READ_LE_UINT16(script->data) * 2; } else if (s->_version < SCI_VERSION_1_1) { @@ -154,10 +154,10 @@ void SegManager::setScriptSize(Script &scr, EngineState *s, int script_nr) { } if (scr.buf_size > 65535) { - sciprintf("Script and heap sizes combined exceed 64K.\n" + error("Script and heap sizes combined exceed 64K.\n" "This means a fundamental design bug was made in SCI\n" "regarding SCI1.1 games.\nPlease report this so it can be" - "fixed in the next major version!\n"); + "fixed in the next major version"); return; } } @@ -172,7 +172,7 @@ int SegManager::initialiseScript(Script &scr, EngineState *s, int script_nr) { dbgPrint("scr.buf ", scr.buf); if (!scr.buf) { scr.freeScript(); - sciprintf("SegManager: Not enough memory space for script size"); + warning("SegManager: Not enough memory space for script size"); scr.buf_size = 0; return 0; } @@ -235,7 +235,7 @@ int SegManager::deallocateScript(int script_nr) { MemObject *SegManager::memObjAllocate(SegmentId segid, int hash_id, MemObjectType type) { MemObject *mem = MemObject::createMemObject(type); if (!mem) { - sciprintf("SegManager: invalid mobj "); + warning("SegManager: invalid mobj"); return NULL; } @@ -313,7 +313,7 @@ int SegManager::relocateBlock(Common::Array<reg_t> &block, int block_location, S return 0; if (rel & 1) { - sciprintf("Error: Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location); + warning("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location); return 0; } block[idx].segment = segment; // Perform relocation @@ -372,18 +372,17 @@ void SegManager::scriptRelocate(reg_t block) { } if (!done) { - sciprintf("While processing relocation block %04x:%04x:\n", PRINT_REG(block)); - sciprintf("Relocation failed for index %04x (%d/%d)\n", pos, i + 1, count); + printf("While processing relocation block %04x:%04x:\n", PRINT_REG(block)); + printf("Relocation failed for index %04x (%d/%d)\n", pos, i + 1, count); if (scr->locals_block) - sciprintf("- locals: %d at %04x\n", scr->locals_block->_locals.size(), scr->locals_offset); + printf("- locals: %d at %04x\n", scr->locals_block->_locals.size(), scr->locals_offset); else - sciprintf("- No locals\n"); + printf("- No locals\n"); for (k = 0; k < scr->_objects.size(); k++) - sciprintf("- obj#%d at %04x w/ %d vars\n", k, scr->_objects[k].pos.offset, scr->_objects[k]._variables.size()); -// SQ3 script 71 has broken relocation entries. -// Since this is mainstream, we can't break out as we used to do. - sciprintf("Trying to continue anyway...\n"); -// BREAKPOINT(); + printf("- obj#%d at %04x w/ %d vars\n", k, scr->_objects[k].pos.offset, scr->_objects[k]._variables.size()); + // SQ3 script 71 has broken relocation entries. + // Since this is mainstream, we can't break out as we used to do. + printf("Trying to continue anyway...\n"); } } } @@ -413,15 +412,15 @@ void SegManager::heapRelocate(reg_t block) { } if (!done) { - sciprintf("While processing relocation block %04x:%04x:\n", PRINT_REG(block)); - sciprintf("Relocation failed for index %04x (%d/%d)\n", pos, i + 1, count); + printf("While processing relocation block %04x:%04x:\n", PRINT_REG(block)); + printf("Relocation failed for index %04x (%d/%d)\n", pos, i + 1, count); if (scr->locals_block) - sciprintf("- locals: %d at %04x\n", scr->locals_block->_locals.size(), scr->locals_offset); + printf("- locals: %d at %04x\n", scr->locals_block->_locals.size(), scr->locals_offset); else - sciprintf("- No locals\n"); + printf("- No locals\n"); for (k = 0; k < scr->_objects.size(); k++) - sciprintf("- obj#%d at %04x w/ %d vars\n", k, scr->_objects[k].pos.offset, scr->_objects[k]._variables.size()); - sciprintf("Triggering breakpoint...\n"); + printf("- obj#%d at %04x w/ %d vars\n", k, scr->_objects[k].pos.offset, scr->_objects[k]._variables.size()); + printf("Triggering breakpoint...\n"); error("Breakpoint in %s, line %d", __FILE__, __LINE__); } } @@ -596,7 +595,7 @@ void SegManager::scriptInitialiseLocals(reg_t location) { scr->locals_offset = location.offset; if (!(location.offset + count * 2 + 1 < scr->buf_size)) { - sciprintf("Locals extend beyond end of script: offset %04x, count %x vs size %x\n", location.offset, count, (uint)scr->buf_size); + warning("Locals extend beyond end of script: offset %04x, count %x vs size %x", location.offset, count, (uint)scr->buf_size); count = (scr->buf_size - location.offset) >> 1; } @@ -719,7 +718,7 @@ SegmentId SegManager::allocateStringFrags() { uint16 SegManager::validateExportFunc(int pubfunct, SegmentId seg) { Script *scr = getScript(seg); if (scr->exports_nr <= pubfunct) { - sciprintf("pubfunct is invalid"); + warning("validateExportFunc(): pubfunct is invalid"); return 0; } @@ -735,7 +734,7 @@ void SegManager::free_hunk_entry(reg_t addr) { HunkTable *ht = (HunkTable *)GET_SEGMENT(*this, addr.segment, MEM_OBJ_HUNK); if (!ht) { - sciprintf("Attempt to free Hunk from address %04x:%04x: Invalid segment type\n", PRINT_REG(addr)); + warning("Attempt to free Hunk from address %04x:%04x: Invalid segment type", PRINT_REG(addr)); return; } diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index e618077d54..38320c29cc 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -87,7 +87,7 @@ EngineState::EngineState(ResourceManager *res, sci_version_t version, uint32 fla _executionStackPosChanged = false; r_acc = NULL_REG; - r_amp_rest = 0; + restAdjust = 0; r_prev = NULL_REG; stack_segment = 0; @@ -113,9 +113,6 @@ EngineState::EngineState(ResourceManager *res, sci_version_t version, uint32 fla seg_manager = 0; gc_countdown = 0; - _vocabulary = 0; - _kernel = 0; - successor = 0; } diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index ecfb9fe6f7..b41e9e383a 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -208,7 +208,7 @@ public: bool _executionStackPosChanged; /**< Set to true if the execution stack position should be re-evaluated by the vm */ reg_t r_acc; /**< Accumulator */ - unsigned int r_amp_rest; /**< &rest register (only used for save games) */ + int16 restAdjust; /**< &rest register (only used for save games) */ reg_t r_prev; /**< previous comparison result */ SegmentId stack_segment; /**< Heap area for the stack to use */ @@ -257,9 +257,6 @@ public: MessageState _msgState; - Vocabulary *_vocabulary; - Kernel *_kernel; - EngineState *successor; /**< Successor of this state: Used for restoring */ private: @@ -283,7 +280,7 @@ PaletteEntry get_pic_color(EngineState *s, int color); // misleading. A different name (and a different place for declaring this) // would be highly welcome. static inline reg_t not_register(EngineState *s, reg_t r) { - if (s->_kernel->_selectorMap.cantBeHere != -1) + if (((SciEngine*)g_engine)->getKernel()->_selectorMap.cantBeHere != -1) return make_reg(0, !r.offset); else return r; diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp new file mode 100644 index 0000000000..c1d0ad9bac --- /dev/null +++ b/engines/sci/engine/static_selectors.cpp @@ -0,0 +1,429 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// We place selector vocab name tables here for any game that doesn't have +// them. This includes the King's Quest IV Demo and LSL3 Demo. + +#ifndef SCI_STATIC_SELECTORS_H +#define SCI_STATIC_SELECTORS_H + +#include "sci/engine/kernel.h" + +namespace Sci { + +struct SelectorRemap { + const char *name; + uint32 slot; +}; + +// Taken from King's Quest IV (Full Game) +static const SelectorRemap kq4_demo_selectors[] = { + { "init", 87 }, + { "play", 42 }, + { "replay", 65 }, + { "x", 4 }, + { "y", 3 }, + { "z", 85 }, + { "priority", 63 }, + { "view", 5 }, + { "loop", 6 }, + { "cel", 7 }, + { "brLeft", 20 }, + { "brRight", 22 }, + { "brTop", 19 }, + { "brBottom", 21 }, + { "xStep", 54 }, + { "yStep", 55 }, + { "nsBottom", 11 }, + { "nsTop", 9 }, + { "nsLeft", 10 }, + { "nsRight", 12 }, + { "font", 33 }, + { "text", 26 }, + { "type", 34 }, + { "state", 32 }, + { "doit", 60 }, + { "delete", 84 }, + { "signal", 17 }, + { "underBits", 8 }, + { "canBeHere", 57 }, + { "client", 45 }, + { "dx", 46 }, + { "dy", 47 }, + { "xStep", 54 }, + { "yStep", 55 }, + { "b-moveCnt", 48 }, + { "b-i1", 49 }, + { "b-i2", 50 }, + { "b-di", 51 }, + { "b-xAxis", 52 }, + { "b-incr", 53 }, + { "completed", 158 }, + { "illegalBits", 18 }, + { "dispose", 88 }, + { "prevSignal", 129 }, + { "message", 40 }, + { "modifiers", 64 }, + { "cue", 121 }, + { "owner", 130 }, + { "handle", 44 }, + { "number", 43 }, + { "max", 37 }, + { "cursor", 36 }, + { "claimed", 76 }, + { "edgeHit", 225 }, + { "wordFail", 71 }, + { "syntaxFail", 72 }, + { "semanticFail", 73 }, + { "cycler", 165 }, + { "elements", 27 }, + { "lsTop", 13 }, + { "lsBottom", 15 }, + { "lsLeft", 14 }, + { "lsRight", 16 }, + { "baseSetter", 208 }, + { "who", 39 }, + { "distance", 173 }, + { "mover", 59 }, + { "looper", 62 }, + { "isBlocked", 61 }, + { "heading", 58 }, + { "mode", 30 }, + { "caller", 119 }, + { "moveDone", 169 }, + { "size", 96 }, + { "moveSpeed", 56 }, + { "motionCue", 161 }, + { "setTarget", 171 } +}; + +// Taken from EcoQuest 2 (Demo) +static const SelectorRemap christmas1992_selectors[] = { + { "init", 110 }, + { "play", 39 }, + { "replay", 62 }, + { "x", 1 }, + { "y", 0 }, + { "z", 82 }, + { "priority", 60 }, + { "view", 2 }, + { "loop", 3 }, + { "cel", 4 }, + { "brLeft", 17 }, + { "brRight", 19 }, + { "brTop", 16 }, + { "brBottom", 18 }, + { "xStep", 51 }, + { "yStep", 52 }, + { "nsBottom", 8 }, + { "nsTop", 6 }, + { "nsLeft", 7 }, + { "nsRight", 9 }, + { "font", 30 }, + { "text", 23 }, + { "type", 31 }, + { "state", 29 }, + { "doit", 57 }, + { "delete", 81 }, + { "signal", 14 }, + { "underBits", 5 }, + { "canBeHere", 450 }, + { "client", 42 }, + { "dx", 43 }, + { "dy", 44 }, + { "xStep", 51 }, + { "yStep", 52 }, + { "b-moveCnt", 45 }, + { "b-i1", 46 }, + { "b-i2", 47 }, + { "b-di", 48 }, + { "b-xAxis", 49 }, + { "b-incr", 50 }, + { "completed", 250 }, + { "illegalBits", 15 }, + { "dispose", 111 }, + { "prevSignal", 171 }, + { "message", 37 }, + { "modifiers", 61 }, + { "cue", 145 }, + { "owner", 172 }, + { "handle", 90 }, + { "number", 40 }, + { "max", 34 }, + { "cursor", 33 }, + { "claimed", 73 }, + { "edgeHit", 333 }, + { "wordFail", 68 }, + { "syntaxFail", 69 }, + { "semanticFail", 70 }, + { "cycler", 255 }, + { "elements", 24 }, + { "lsTop", 10 }, + { "lsBottom", 12 }, + { "lsLeft", 11 }, + { "lsRight", 13 }, + { "baseSetter", 310 }, + { "who", 36 }, + { "distance", 264 }, + { "mover", 56 }, + { "looper", 59 }, + { "isBlocked", 58 }, + { "heading", 55 }, + { "mode", 27 }, + { "caller", 143 }, + { "moveDone", 97 }, + { "vol", 94 }, + { "pri", 95 }, + { "min", 91 }, + { "sec", 92 }, + { "frame", 93 }, + { "dataInc", 89 }, + { "size", 86 }, + { "palette", 88 }, + { "moveSpeed", 53 }, + { "cantBeHere", 54 }, + { "nodePtr", 41 }, + { "flags", 99 }, + { "points", 87 }, + { "syncCue", 271 }, + { "syncTime", 270 }, + { "printLang", 84 }, + { "subtitleLang", 85 }, + { "parseLang", 83 }, + { "setVol", 178 } +}; + +// Taken from Leisure Suit Larry 1 VGA (Full Game) +static const SelectorRemap lsl1_demo_selectors[] = { + { "init", 104 }, + { "play", 42 }, + { "replay", 65 }, + { "x", 4 }, + { "y", 3 }, + { "z", 85 }, + { "priority", 63 }, + { "view", 5 }, + { "loop", 6 }, + { "cel", 7 }, + { "brLeft", 20 }, + { "brRight", 22 }, + { "brTop", 19 }, + { "brBottom", 21 }, + { "xStep", 54 }, + { "yStep", 55 }, + { "nsBottom", 11 }, + { "nsTop", 9 }, + { "nsLeft", 10 }, + { "nsRight", 12 }, + { "font", 33 }, + { "text", 26 }, + { "type", 34 }, + { "state", 32 }, + { "doit", 60 }, + { "delete", 84 }, + { "signal", 17 }, + { "underBits", 8 }, + { "canBeHere", 232 }, + { "client", 45 }, + { "dx", 46 }, + { "dy", 47 }, + { "xStep", 54 }, + { "yStep", 55 }, + { "b-moveCnt", 48 }, + { "b-i1", 49 }, + { "b-i2", 50 }, + { "b-di", 51 }, + { "b-xAxis", 52 }, + { "b-incr", 53 }, + { "completed", 210 }, + { "illegalBits", 18 }, + { "dispose", 105 }, + { "prevSignal", 149 }, + { "message", 40 }, + { "modifiers", 64 }, + { "cue", 136 }, + { "owner", 150 }, + { "handle", 93 }, + { "number", 43 }, + { "max", 37 }, + { "cursor", 36 }, + { "claimed", 76 }, + { "edgeHit", 321 }, + { "wordFail", 71 }, + { "syntaxFail", 72 }, + { "semanticFail", 73 }, + { "cycler", 215 }, + { "elements", 27 }, + { "lsTop", 13 }, + { "lsBottom", 15 }, + { "lsLeft", 14 }, + { "lsRight", 16 }, + { "baseSetter", 290 }, + { "who", 39 }, + { "distance", 224 }, + { "mover", 59 }, + { "looper", 62 }, + { "isBlocked", 61 }, + { "heading", 58 }, + { "mode", 30 }, + { "caller", 134 }, + { "moveDone", 100 }, + { "vol", 97 }, + { "pri", 98 }, + { "min", 94 }, + { "sec", 95 }, + { "frame", 96 }, + { "dataInc", 92 }, + { "size", 89 }, + { "palette", 91 }, + { "moveSpeed", 56 }, + { "cantBeHere", 57 }, + { "nodePtr", 44 }, + { "flags", 102 }, + { "points", 90 }, + { "syncCue", 248 }, + { "syncTime", 247 }, + { "printLang", 87 }, + { "subtitleLang", 88 }, + { "parseLang", 86 }, + { "setVol", 156 }, + { "motionCue", 213 }, + { "setTarget", 221 }, + { "egoMoveSpeed", 370 } +}; + +// Taken from Codename: Iceman (Full Game) +static const SelectorRemap iceman_demo_selectors[] = { + { "init", 87 }, + { "play", 42 }, + { "replay", 65 }, + { "x", 4 }, + { "y", 3 }, + { "z", 85 }, + { "priority", 63 }, + { "view", 5 }, + { "loop", 6 }, + { "cel", 7 }, + { "brLeft", 20 }, + { "brRight", 22 }, + { "brTop", 19 }, + { "brBottom", 21 }, + { "xStep", 54 }, + { "yStep", 55 }, + { "nsBottom", 11 }, + { "nsTop", 9 }, + { "nsLeft", 10 }, + { "nsRight", 12 }, + { "font", 33 }, + { "text", 26 }, + { "type", 34 }, + { "state", 32 }, + { "doit", 60 }, + { "delete", 84 }, + { "signal", 17 }, + { "underBits", 8 }, + { "canBeHere", 57 }, + { "client", 45 }, + { "dx", 46 }, + { "dy", 47 }, + { "xStep", 54 }, + { "yStep", 55 }, + { "b-moveCnt", 48 }, + { "b-i1", 49 }, + { "b-i2", 50 }, + { "b-di", 51 }, + { "b-xAxis", 52 }, + { "b-incr", 53 }, + { "completed", 159 }, + { "illegalBits", 18 }, + { "dispose", 88 }, + { "prevSignal", 129 }, + { "message", 40 }, + { "modifiers", 64 }, + { "cue", 121 }, + { "owner", 130 }, + { "handle", 44 }, + { "number", 43 }, + { "max", 37 }, + { "cursor", 36 }, + { "claimed", 76 }, + { "edgeHit", 236 }, + { "wordFail", 71 }, + { "syntaxFail", 72 }, + { "semanticFail", 73 }, + { "cycler", 164 }, + { "elements", 27 }, + { "lsTop", 13 }, + { "lsBottom", 15 }, + { "lsLeft", 14 }, + { "lsRight", 16 }, + { "baseSetter", 207 }, + { "who", 39 }, + { "distance", 173 }, + { "mover", 59 }, + { "looper", 62 }, + { "isBlocked", 61 }, + { "heading", 58 }, + { "mode", 30 }, + { "caller", 119 }, + { "moveDone", 170 }, + { "size", 96 }, + { "moveSpeed", 56 }, + { "flags", 368 }, + { "points", 316 }, + { "motionCue", 162 }, + { "setTarget", 171 } +}; + +// A macro for loading one of the above tables in the function below +#define USE_SELECTOR_TABLE(x) \ + do { \ + for (uint32 i = 0; i < ARRAYSIZE(x); i++) { \ + if (x[i].slot >= names.size()) \ + names.resize(x[i].slot + 1); \ + names[x[i].slot] = x[i].name; \ + } \ + } while (0) + +Common::StringList Kernel::checkStaticSelectorNames() { + Common::String gameID = ((SciEngine*)g_engine)->getGameID(); + + Common::StringList names; + + if (gameID == "kq4sci") + USE_SELECTOR_TABLE(kq4_demo_selectors); + else if (gameID == "lsl3" || gameID == "iceman") // identical, except iceman has "flags" + USE_SELECTOR_TABLE(iceman_demo_selectors); + else if (gameID == "christmas1992") + USE_SELECTOR_TABLE(christmas1992_selectors); + else if (gameID == "lsl1sci") + USE_SELECTOR_TABLE(lsl1_demo_selectors); + + return names; +} + +} // End of namespace Sci + +#endif // SCI_STATIC_SELECTORS_H diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index cbd0b0cfbb..99b5a86e53 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -27,6 +27,7 @@ #include "common/stack.h" #include "sci/sci.h" +#include "sci/console.h" #include "sci/debug.h" // for g_debug_weak_validations #include "sci/resource.h" #include "sci/engine/state.h" @@ -50,7 +51,6 @@ int script_abort_flag = 0; // Set to 1 to abort execution. Set to 2 to force a r int script_step_counter = 0; // Counts the number of steps executed // FIXME: Avoid non-const global vars int script_gc_interval = GC_INTERVAL; // Number of steps in between gcs // FIXME: Avoid non-const global vars - static bool breakpointFlag = false; // FIXME: Avoid non-const global vars static reg_t _dummy_register; // FIXME: Avoid non-const global vars @@ -136,10 +136,10 @@ static int validate_variable(reg_t *r, reg_t *stack_base, int type, int max, int if (type == VAR_PARAM || type == VAR_TEMP) { int total_offset = r - stack_base; if (total_offset < 0 || total_offset >= VM_STACK_SIZE) { - sciprintf("[VM] Access would be outside even of the stack (%d); access denied\n", total_offset); + warning("[VM] Access would be outside even of the stack (%d); access denied", total_offset); return 1; } else { - sciprintf("[VM] Access within stack boundaries; access granted.\n"); + debugC(2, kDebugLevelVM, "[VM] Access within stack boundaries; access granted.\n"); return 0; } } @@ -177,8 +177,8 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i #endif -#define READ_VAR(type, index, def) validate_read_var(variables[type], s->stack_base, type, variables_max[type], index, __LINE__, def) -#define WRITE_VAR(type, index, value) validate_write_var(variables[type], s->stack_base, type, variables_max[type], index, __LINE__, value) +#define READ_VAR(type, index, def) validate_read_var(scriptState.variables[type], s->stack_base, type, scriptState.variables_max[type], index, __LINE__, def) +#define WRITE_VAR(type, index, value) validate_write_var(scriptState.variables[type], s->stack_base, type, scriptState.variables_max[type], index, __LINE__, value) #define WRITE_VAR16(type, index, value) WRITE_VAR(type, index, make_reg(0, value)); #define ACC_ARITHMETIC_L(op) make_reg(0, (op validate_arithmetic(s->r_acc))) @@ -187,12 +187,6 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i #define OBJ_PROPERTY(o, p) (validate_property(o, p)) -int script_error(EngineState *s, const char *file, int line, const char *reason) { - error("Script error in file %s, line %d: %s\n", file, line, reason); - return 0; -} -#define CORE_ERROR(area, msg) script_error(s, "[" area "] " __FILE__, __LINE__, msg) - reg_t get_class_address(EngineState *s, int classnr, SCRIPT_GET lock, reg_t caller) { if (NULL == s) { @@ -226,15 +220,15 @@ reg_t get_class_address(EngineState *s, int classnr, SCRIPT_GET lock, reg_t call #define PUSH(v) PUSH32(make_reg(0, v)) #define POP() (validate_arithmetic(POP32())) // 32 bit: -#define PUSH32(a) (*(validate_stack_addr(s, (xs->sp)++)) = (a)) -#define POP32() (*(validate_stack_addr(s, --(xs->sp)))) +#define PUSH32(a) (*(validate_stack_addr(s, (scriptState.xs->sp)++)) = (a)) +#define POP32() (*(validate_stack_addr(s, --(scriptState.xs->sp)))) // Getting instruction parameters -#define GET_OP_BYTE() ((uint8)code_buf[(xs->addr.pc.offset)++]) -#define GET_OP_WORD() (READ_LE_UINT16(code_buf + ((xs->addr.pc.offset) += 2) - 2)) +#define GET_OP_BYTE() ((uint8)code_buf[(scriptState.xs->addr.pc.offset)++]) +#define GET_OP_WORD() (READ_LE_UINT16(code_buf + ((scriptState.xs->addr.pc.offset) += 2) - 2)) #define GET_OP_FLEX() ((opcode & 1)? GET_OP_BYTE() : GET_OP_WORD()) -#define GET_OP_SIGNED_BYTE() ((int8)(code_buf[(xs->addr.pc.offset)++])) -#define GET_OP_SIGNED_WORD() (((int16)READ_LE_UINT16(code_buf + ((xs->addr.pc.offset) += 2) - 2))) +#define GET_OP_SIGNED_BYTE() ((int8)(code_buf[(scriptState.xs->addr.pc.offset)++])) +#define GET_OP_SIGNED_WORD() (((int16)READ_LE_UINT16(code_buf + ((scriptState.xs->addr.pc.offset) += 2) - 2))) #define GET_OP_SIGNED_FLEX() ((opcode & 1)? GET_OP_SIGNED_BYTE() : GET_OP_SIGNED_WORD()) ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp) { @@ -262,7 +256,8 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP bp = s->bp_list; while (bp) { if (bp->type == BREAK_EXPORT && bp->data.address == bpaddress) { - sciprintf("Break on script %d, export %d\n", script, pubfunct); + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); + con->DebugPrintf("Break on script %d, export %d\n", script, pubfunct); breakpointFlag = true; break; } @@ -309,8 +304,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt argc = validate_arithmetic(*argp); if (argc > 0x800) { // More arguments than the stack could possibly accomodate for - CORE_ERROR("SEND", "More than 0x800 arguments to function call\n"); - return NULL; + error("send_selector(): More than 0x800 arguments to function call"); } // Check if a breakpoint is set on this method @@ -318,7 +312,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt Breakpoint *bp; char method_name [256]; - sprintf(method_name, "%s::%s", obj_get_name(s, send_obj), s->_kernel->getSelectorName(selector).c_str()); + sprintf(method_name, "%s::%s", obj_get_name(s, send_obj), ((SciEngine*)g_engine)->getKernel()->getSelectorName(selector).c_str()); bp = s->bp_list; while (bp) { @@ -327,7 +321,8 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt cmplen = 256; if (bp->type == BREAK_SELECTOR && !strncmp(bp->data.name, method_name, cmplen)) { - sciprintf("Break on %s (in [%04x:%04x])\n", method_name, PRINT_REG(send_obj)); + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); + con->DebugPrintf("Break on %s (in [%04x:%04x])\n", method_name, PRINT_REG(send_obj)); print_send_action = 1; breakpointFlag = true; break; @@ -337,7 +332,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt } #ifdef VM_DEBUG_SEND - sciprintf("Send to %04x:%04x, selector %04x (%s):", PRINT_REG(send_obj), selector, s->_selectorNames[selector].c_str()); + printf("Send to %04x:%04x, selector %04x (%s):", PRINT_REG(send_obj), selector, s->_selectorNames[selector].c_str()); #endif // VM_DEBUG_SEND ObjVarRef varp; @@ -357,17 +352,16 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt case kSelectorVariable: #ifdef VM_DEBUG_SEND - sciprintf("Varselector: "); if (argc) - sciprintf("Write %04x:%04x\n", PRINT_REG(argp[1])); + printf("Varselector: Write %04x:%04x\n", PRINT_REG(argp[1])); else - sciprintf("Read\n"); + printf("Varselector: Read\n"); #endif // VM_DEBUG_SEND switch (argc) { case 0: // Read selector if (print_send_action) { - sciprintf("[read selector]\n"); + printf("[read selector]\n"); print_send_action = 0; } // fallthrough @@ -380,7 +374,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt reg_t oldReg = *varp.getPointer(s); reg_t newReg = argp[1]; - sciprintf("[write to selector: change %04x:%04x to %04x:%04x]\n", PRINT_REG(oldReg), PRINT_REG(newReg)); + printf("[write to selector: change %04x:%04x to %04x:%04x]\n", PRINT_REG(oldReg), PRINT_REG(newReg)); print_send_action = 0; } CallsStruct call; @@ -394,9 +388,8 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt break; #ifdef STRICT_SEND default: - sciprintf("Send error: Variable selector %04x in %04x:%04x called with %04x params\n", selector, PRINT_REG(send_obj), argc); - script_debug_flag = 1; // Enter debug mode - g_debug_seeking = g_debug_step_running = 0; + scriptState.seeking = scriptState.runningStep = 0; + error("Send error: Variable selector %04x in %04x:%04x called with %04x params", selector, PRINT_REG(send_obj), argc); #endif } break; @@ -404,16 +397,16 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt case kSelectorMethod: #ifdef VM_DEBUG_SEND - sciprintf("Funcselector("); + printf("Funcselector("); for (int i = 0; i < argc; i++) { - sciprintf(PREG, PRINT_REG(argp[i+1])); + printf(PREG, PRINT_REG(argp[i+1])); if (i + 1 < argc) - sciprintf(", "); + printf(", "); } - sciprintf(") at %04x:%04x\n", PRINT_REG(funcp)); + printf(") at %04x:%04x\n", PRINT_REG(funcp)); #endif // VM_DEBUG_SEND if (print_send_action) { - sciprintf("[invoke selector]\n"); + printf("[invoke selector]\n"); print_send_action = 0; } @@ -469,7 +462,7 @@ ExecStack *add_exec_stack_entry(EngineState *s, reg_t pc, StackPtr sp, reg_t obj // Returns new TOS element for the execution stack // locals_segment may be -1 if derived from the called object - //sciprintf("Exec stack: [%d/%d], origin %d, at %p\n", s->execution_stack_pos, s->_executionStack.size(), origin, s->execution_stack); + //printf("Exec stack: [%d/%d], origin %d, at %p\n", s->execution_stack_pos, s->_executionStack.size(), origin, s->execution_stack); ExecStack xstack; @@ -514,7 +507,7 @@ static reg_t pointer_add(EngineState *s, reg_t base, int offset) { MemObject *mobj = GET_SEGMENT_ANY(*s->seg_manager, base.segment); if (!mobj) { - error("[VM] Error: Attempt to add %d to invalid pointer %04x:%04x!", offset, PRINT_REG(base)); + error("[VM] Error: Attempt to add %d to invalid pointer %04x:%04x", offset, PRINT_REG(base)); return NULL_REG; } @@ -532,7 +525,7 @@ static reg_t pointer_add(EngineState *s, reg_t base, int offset) { break; default: - sciprintf("[VM] Error: Attempt to add %d to pointer %04x:%04x: Pointer arithmetics of this type unsupported!", offset, PRINT_REG(base)); + error("[VM] Error: Attempt to add %d to pointer %04x:%04x: Pointer arithmetics of this type unsupported", offset, PRINT_REG(base)); return NULL_REG; } @@ -550,11 +543,7 @@ static const byte _fake_return_buffer[2] = {op_ret << 1, op_ret << 1}; void run_vm(EngineState *s, int restoring) { assert(s); - reg_t *variables[4]; // global, local, temp, param, as immediate pointers - reg_t *variables_base[4]; // Used for referencing VM ops - SegmentId variables_seg[4]; // Same as above, contains segment IDs #ifndef DISABLE_VALIDATIONS - int variables_max[4]; // Max. values for all variables unsigned int code_buf_size = 0 ; // (Avoid spurious warning) #endif int temp; @@ -563,20 +552,19 @@ void run_vm(EngineState *s, int restoring) { StackPtr s_temp; // Temporary stack pointer int16 opparams[4]; // opcode parameters - int restadjust = s->r_amp_rest; + scriptState.restAdjust = s->restAdjust; // &rest adjusts the parameter count by this value // Current execution data: - ExecStack *xs = &(s->_executionStack.back()); + scriptState.xs = &(s->_executionStack.back()); ExecStack *xs_new = NULL; - Object *obj = obj_get(s, xs->objp); - Script *local_script = script_locate_by_segment(s, xs->local_segment); + Object *obj = obj_get(s, scriptState.xs->objp); + Script *local_script = script_locate_by_segment(s, scriptState.xs->local_segment); int old_execution_stack_base = s->execution_stack_base; // Used to detect the stack bottom, for "physical" returns const byte *code_buf = NULL; // (Avoid spurious warning) if (!local_script) { - script_error(s, __FILE__, __LINE__, "Program Counter gone astray"); - return; + error("run_vm(): program counter gone astray (local_script pointer is null)"); } if (!restoring) @@ -585,85 +573,81 @@ void run_vm(EngineState *s, int restoring) { #ifndef DISABLE_VALIDATIONS // Initialize maximum variable count if (s->script_000->locals_block) - variables_max[VAR_GLOBAL] = s->script_000->locals_block->_locals.size(); + scriptState.variables_max[VAR_GLOBAL] = s->script_000->locals_block->_locals.size(); else - variables_max[VAR_GLOBAL] = 0; + scriptState.variables_max[VAR_GLOBAL] = 0; #endif - variables_seg[VAR_GLOBAL] = s->script_000->locals_segment; - variables_seg[VAR_TEMP] = variables_seg[VAR_PARAM] = s->stack_segment; - variables_base[VAR_TEMP] = variables_base[VAR_PARAM] = s->stack_base; + scriptState.variables_seg[VAR_GLOBAL] = s->script_000->locals_segment; + scriptState.variables_seg[VAR_TEMP] = scriptState.variables_seg[VAR_PARAM] = s->stack_segment; + scriptState.variables_base[VAR_TEMP] = scriptState.variables_base[VAR_PARAM] = s->stack_base; // SCI code reads the zeroeth argument to determine argc if (s->script_000->locals_block) - variables_base[VAR_GLOBAL] = variables[VAR_GLOBAL] = s->script_000->locals_block->_locals.begin(); + scriptState.variables_base[VAR_GLOBAL] = scriptState.variables[VAR_GLOBAL] = s->script_000->locals_block->_locals.begin(); else - variables_base[VAR_GLOBAL] = variables[VAR_GLOBAL] = NULL; - - + scriptState.variables_base[VAR_GLOBAL] = scriptState.variables[VAR_GLOBAL] = NULL; s->_executionStackPosChanged = true; // Force initialization while (1) { byte opcode; - int old_pc_offset; - StackPtr old_sp; byte opnumber; int var_type; // See description below int var_number; - old_pc_offset = xs->addr.pc.offset; - old_sp = xs->sp; + scriptState.old_pc_offset = scriptState.xs->addr.pc.offset; + scriptState.old_sp = scriptState.xs->sp; if (s->_executionStackPosChanged) { Script *scr; - xs = &(s->_executionStack.back()); + scriptState.xs = &(s->_executionStack.back()); s->_executionStackPosChanged = false; - scr = script_locate_by_segment(s, xs->addr.pc.segment); + scr = script_locate_by_segment(s, scriptState.xs->addr.pc.segment); if (!scr) { // No script? Implicit return via fake instruction buffer - warning("Running on non-existant script in segment %x", xs->addr.pc.segment); + warning("Running on non-existant script in segment %x", scriptState.xs->addr.pc.segment); code_buf = _fake_return_buffer; #ifndef DISABLE_VALIDATIONS code_buf_size = 2; #endif - xs->addr.pc.offset = 1; + scriptState.xs->addr.pc.offset = 1; scr = NULL; obj = NULL; } else { - obj = obj_get(s, xs->objp); + obj = obj_get(s, scriptState.xs->objp); code_buf = scr->buf; #ifndef DISABLE_VALIDATIONS code_buf_size = scr->buf_size; #endif - local_script = script_locate_by_segment(s, xs->local_segment); + local_script = script_locate_by_segment(s, scriptState.xs->local_segment); if (!local_script) { - warning("Could not find local script from segment %x", xs->local_segment); + warning("Could not find local script from segment %x", scriptState.xs->local_segment); local_script = NULL; - variables_base[VAR_LOCAL] = variables[VAR_LOCAL] = NULL; + scriptState.variables_base[VAR_LOCAL] = scriptState.variables[VAR_LOCAL] = NULL; #ifndef DISABLE_VALIDATIONS - variables_max[VAR_LOCAL] = 0; + scriptState.variables_max[VAR_LOCAL] = 0; #endif } else { - variables_seg[VAR_LOCAL] = local_script->locals_segment; + scriptState.variables_seg[VAR_LOCAL] = local_script->locals_segment; if (local_script->locals_block) - variables_base[VAR_LOCAL] = variables[VAR_LOCAL] = local_script->locals_block->_locals.begin(); + scriptState.variables_base[VAR_LOCAL] = scriptState.variables[VAR_LOCAL] = local_script->locals_block->_locals.begin(); else - variables_base[VAR_LOCAL] = variables[VAR_LOCAL] = NULL; + scriptState.variables_base[VAR_LOCAL] = scriptState.variables[VAR_LOCAL] = NULL; #ifndef DISABLE_VALIDATIONS if (local_script->locals_block) - variables_max[VAR_LOCAL] = local_script->locals_block->_locals.size(); + scriptState.variables_max[VAR_LOCAL] = local_script->locals_block->_locals.size(); else - variables_max[VAR_LOCAL] = 0; - variables_max[VAR_TEMP] = xs->sp - xs->fp; - variables_max[VAR_PARAM] = xs->argc + 1; + scriptState.variables_max[VAR_LOCAL] = 0; + scriptState.variables_max[VAR_TEMP] = scriptState.xs->sp - scriptState.xs->fp; + scriptState.variables_max[VAR_PARAM] = scriptState.xs->argc + 1; #endif } - variables[VAR_TEMP] = xs->fp; - variables[VAR_PARAM] = xs->variables_argp; + scriptState.variables[VAR_TEMP] = scriptState.xs->fp; + scriptState.variables[VAR_PARAM] = scriptState.xs->variables_argp; } } @@ -675,25 +659,19 @@ void run_vm(EngineState *s, int restoring) { #if 0 // Debug if this has been requested: if (script_debug_flag || sci_debug_flags) { - script_debug(s, &(xs->addr.pc), &(xs->sp), &(xs->fp), &(xs->objp), &restadjust, variables_seg, variables, variables_base, -#ifdef DISABLE_VALIDATIONS - NULL, -#else - variables_max, -#endif - breakpointFlag); + script_debug(s, breakpointFlag); breakpointFlag = false; } #endif #ifndef DISABLE_VALIDATIONS - if (xs->sp < xs->fp) - script_error(s, "[VM] "__FILE__, __LINE__, "Stack underflow"); + if (scriptState.xs->sp < scriptState.xs->fp) + error("run_vm(): stack underflow"); - variables_max[VAR_TEMP] = xs->sp - xs->fp; + scriptState.variables_max[VAR_TEMP] = scriptState.xs->sp - scriptState.xs->fp; - if (xs->addr.pc.offset >= code_buf_size) - script_error(s, "[VM] "__FILE__, __LINE__, "Program Counter gone astray"); + if (scriptState.xs->addr.pc.offset >= code_buf_size) + error("run_vm(): program counter gone astray"); #endif opcode = GET_OP_BYTE(); // Get opcode @@ -910,16 +888,16 @@ void run_vm(EngineState *s, int restoring) { case 0x17: // bt if (s->r_acc.offset || s->r_acc.segment) - xs->addr.pc.offset += opparams[0]; + scriptState.xs->addr.pc.offset += opparams[0]; break; case 0x18: // bnt if (!(s->r_acc.offset || s->r_acc.segment)) - xs->addr.pc.offset += opparams[0]; + scriptState.xs->addr.pc.offset += opparams[0]; break; case 0x19: // jmp - xs->addr.pc.offset += opparams[0]; + scriptState.xs->addr.pc.offset += opparams[0]; break; case 0x1a: // ldi @@ -935,33 +913,36 @@ void run_vm(EngineState *s, int restoring) { break; case 0x1d: // toss - xs->sp--; + scriptState.xs->sp--; break; case 0x1e: // dup - r_temp = xs->sp[-1]; + r_temp = scriptState.xs->sp[-1]; PUSH32(r_temp); break; case 0x1f: { // link int i; for (i = 0; i < opparams[0]; i++) - xs->sp[i] = NULL_REG; - xs->sp += opparams[0]; + scriptState.xs->sp[i] = NULL_REG; + scriptState.xs->sp += opparams[0]; break; } case 0x20: { // call int argc = (opparams[1] >> 1) // Given as offset, but we need count - + 1 + restadjust; - StackPtr call_base = xs->sp - argc; - xs->sp[1].offset += restadjust; - - xs_new = add_exec_stack_entry(s, make_reg(xs->addr.pc.segment, xs->addr.pc.offset + opparams[0]), - xs->sp, xs->objp, (validate_arithmetic(*call_base)) + restadjust, - call_base, NULL_SELECTOR, xs->objp, s->_executionStack.size()-1, xs->local_segment); - restadjust = 0; // Used up the &rest adjustment - xs->sp = call_base; + + 1 + scriptState.restAdjust; + StackPtr call_base = scriptState.xs->sp - argc; + scriptState.xs->sp[1].offset += scriptState.restAdjust; + + xs_new = add_exec_stack_entry(s, make_reg(scriptState.xs->addr.pc.segment, + scriptState.xs->addr.pc.offset + opparams[0]), + scriptState.xs->sp, scriptState.xs->objp, + (validate_arithmetic(*call_base)) + scriptState.restAdjust, + call_base, NULL_SELECTOR, scriptState.xs->objp, + s->_executionStack.size()-1, scriptState.xs->local_segment); + scriptState.restAdjust = 0; // Used up the &rest adjustment + scriptState.xs->sp = call_base; s->_executionStackPosChanged = true; break; @@ -970,25 +951,28 @@ void run_vm(EngineState *s, int restoring) { case 0x21: // callk gc_countdown(s); - xs->sp -= (opparams[1] >> 1) + 1; - if (!(s->_flags & GF_SCI0_OLD)) { - xs->sp -= restadjust; - s->r_amp_rest = 0; // We just used up the restadjust, remember? + scriptState.xs->sp -= (opparams[1] >> 1) + 1; + if (!((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) { + scriptState.xs->sp -= scriptState.restAdjust; + s->restAdjust = 0; // We just used up the scriptState.restAdjust, remember? } - if (opparams[0] >= (int)s->_kernel->_kernelFuncs.size()) { + if (opparams[0] >= (int)((SciEngine*)g_engine)->getKernel()->_kernelFuncs.size()) { error("Invalid kernel function 0x%x requested\n", opparams[0]); } else { - int argc = ASSERT_ARITHMETIC(xs->sp[0]); + int argc = ASSERT_ARITHMETIC(scriptState.xs->sp[0]); - if (!(s->_flags & GF_SCI0_OLD)) - argc += restadjust; + if (!((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) + argc += scriptState.restAdjust; - if (s->_kernel->_kernelFuncs[opparams[0]].signature - && !kernel_matches_signature(s, s->_kernel->_kernelFuncs[opparams[0]].signature, argc, xs->sp + 1)) { + if (((SciEngine*)g_engine)->getKernel()->_kernelFuncs[opparams[0]].signature + && !kernel_matches_signature(s, + ((SciEngine*)g_engine)->getKernel()->_kernelFuncs[opparams[0]].signature, argc, + scriptState.xs->sp + 1)) { error("[VM] Invalid arguments to kernel call %x\n", opparams[0]); } else { - s->r_acc = s->_kernel->_kernelFuncs[opparams[0]].fun(s, opparams[0], argc, xs->sp + 1); + s->r_acc = ((SciEngine*)g_engine)->getKernel()->_kernelFuncs[opparams[0]].fun(s, opparams[0], + argc, scriptState.xs->sp + 1); } // Call kernel function @@ -998,32 +982,34 @@ void run_vm(EngineState *s, int restoring) { xs_new = &(s->_executionStack.back()); s->_executionStackPosChanged = true; - if (!(s->_flags & GF_SCI0_OLD)) - restadjust = s->r_amp_rest; + if (!((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) + scriptState.restAdjust = s->restAdjust; } break; case 0x22: // callb - temp = ((opparams[1] >> 1) + restadjust + 1); - s_temp = xs->sp; - xs->sp -= temp; - - xs->sp[0].offset += restadjust; - xs_new = execute_method(s, 0, opparams[0], s_temp, xs->objp, xs->sp[0].offset, xs->sp); - restadjust = 0; // Used up the &rest adjustment + temp = ((opparams[1] >> 1) + scriptState.restAdjust + 1); + s_temp = scriptState.xs->sp; + scriptState.xs->sp -= temp; + + scriptState.xs->sp[0].offset += scriptState.restAdjust; + xs_new = execute_method(s, 0, opparams[0], s_temp, scriptState.xs->objp, + scriptState.xs->sp[0].offset, scriptState.xs->sp); + scriptState.restAdjust = 0; // Used up the &rest adjustment if (xs_new) // in case of error, keep old stack s->_executionStackPosChanged = true; break; case 0x23: // calle - temp = ((opparams[2] >> 1) + restadjust + 1); - s_temp = xs->sp; - xs->sp -= temp; + temp = ((opparams[2] >> 1) + scriptState.restAdjust + 1); + s_temp = scriptState.xs->sp; + scriptState.xs->sp -= temp; - xs->sp[0].offset += restadjust; - xs_new = execute_method(s, opparams[0], opparams[1], s_temp, xs->objp, xs->sp[0].offset, xs->sp); - restadjust = 0; // Used up the &rest adjustment + scriptState.xs->sp[0].offset += scriptState.restAdjust; + xs_new = execute_method(s, opparams[0], opparams[1], s_temp, scriptState.xs->objp, + scriptState.xs->sp[0].offset, scriptState.xs->sp); + scriptState.restAdjust = 0; // Used up the &rest adjustment if (xs_new) // in case of error, keep old stack s->_executionStackPosChanged = true; @@ -1031,8 +1017,8 @@ void run_vm(EngineState *s, int restoring) { case 0x24: // ret do { - StackPtr old_sp2 = xs->sp; - StackPtr old_fp = xs->fp; + StackPtr old_sp2 = scriptState.xs->sp; + StackPtr old_fp = scriptState.xs->fp; ExecStack *old_xs = &(s->_executionStack.back()); if ((int)s->_executionStack.size()-1 == s->execution_stack_base) { // Have we reached the base? @@ -1041,7 +1027,7 @@ void run_vm(EngineState *s, int restoring) { s->_executionStack.pop_back(); s->_executionStackPosChanged = true; - s->r_amp_rest = restadjust; // Update &rest + s->restAdjust = scriptState.restAdjust; // Update &rest return; // "Hard" return } @@ -1056,80 +1042,84 @@ void run_vm(EngineState *s, int restoring) { // Not reached the base, so let's do a soft return s->_executionStack.pop_back(); s->_executionStackPosChanged = true; - xs = &(s->_executionStack.back()); + scriptState.xs = &(s->_executionStack.back()); - if (xs->sp == CALL_SP_CARRY // Used in sends to 'carry' the stack pointer - || xs->type != EXEC_STACK_TYPE_CALL) { - xs->sp = old_sp2; - xs->fp = old_fp; + if (scriptState.xs->sp == CALL_SP_CARRY // Used in sends to 'carry' the stack pointer + || scriptState.xs->type != EXEC_STACK_TYPE_CALL) { + scriptState.xs->sp = old_sp2; + scriptState.xs->fp = old_fp; } - } while (xs->type == EXEC_STACK_TYPE_VARSELECTOR); + } while (scriptState.xs->type == EXEC_STACK_TYPE_VARSELECTOR); // Iterate over all varselector accesses s->_executionStackPosChanged = true; - xs_new = xs; + xs_new = scriptState.xs; break; case 0x25: // send - s_temp = xs->sp; - xs->sp -= ((opparams[0] >> 1) + restadjust); // Adjust stack + s_temp = scriptState.xs->sp; + scriptState.xs->sp -= ((opparams[0] >> 1) + scriptState.restAdjust); // Adjust stack - xs->sp[1].offset += restadjust; - xs_new = send_selector(s, s->r_acc, s->r_acc, s_temp, (int)(opparams[0] >> 1) + (uint16)restadjust, xs->sp); + scriptState.xs->sp[1].offset += scriptState.restAdjust; + xs_new = send_selector(s, s->r_acc, s->r_acc, s_temp, + (int)(opparams[0] >> 1) + (uint16)scriptState.restAdjust, scriptState.xs->sp); - if (xs_new && xs_new != xs) + if (xs_new && xs_new != scriptState.xs) s->_executionStackPosChanged = true; - restadjust = 0; + scriptState.restAdjust = 0; break; case 0x28: // class - s->r_acc = get_class_address(s, (unsigned)opparams[0], SCRIPT_GET_LOCK, xs->addr.pc); + s->r_acc = get_class_address(s, (unsigned)opparams[0], SCRIPT_GET_LOCK, + scriptState.xs->addr.pc); break; case 0x2a: // self - s_temp = xs->sp; - xs->sp -= ((opparams[0] >> 1) + restadjust); // Adjust stack + s_temp = scriptState.xs->sp; + scriptState.xs->sp -= ((opparams[0] >> 1) + scriptState.restAdjust); // Adjust stack - xs->sp[1].offset += restadjust; - xs_new = send_selector(s, xs->objp, xs->objp, s_temp, (int)(opparams[0] >> 1) + (uint16)restadjust, xs->sp); + scriptState.xs->sp[1].offset += scriptState.restAdjust; + xs_new = send_selector(s, scriptState.xs->objp, scriptState.xs->objp, + s_temp, (int)(opparams[0] >> 1) + (uint16)scriptState.restAdjust, + scriptState.xs->sp); - if (xs_new && xs_new != xs) + if (xs_new && xs_new != scriptState.xs) s->_executionStackPosChanged = true; - restadjust = 0; + scriptState.restAdjust = 0; break; case 0x2b: // super - r_temp = get_class_address(s, opparams[0], SCRIPT_GET_LOAD, xs->addr.pc); + r_temp = get_class_address(s, opparams[0], SCRIPT_GET_LOAD, scriptState.xs->addr.pc); if (!r_temp.segment) - CORE_ERROR("VM", "Invalid superclass in object"); + error("[VM]: Invalid superclass in object"); else { - s_temp = xs->sp; - xs->sp -= ((opparams[1] >> 1) + restadjust); // Adjust stack + s_temp = scriptState.xs->sp; + scriptState.xs->sp -= ((opparams[1] >> 1) + scriptState.restAdjust); // Adjust stack - xs->sp[1].offset += restadjust; - xs_new = send_selector(s, r_temp, xs->objp, s_temp, (int)(opparams[1] >> 1) + (uint16)restadjust, xs->sp); + scriptState.xs->sp[1].offset += scriptState.restAdjust; + xs_new = send_selector(s, r_temp, scriptState.xs->objp, s_temp, + (int)(opparams[1] >> 1) + (uint16)scriptState.restAdjust, + scriptState.xs->sp); - if (xs_new && xs_new != xs) + if (xs_new && xs_new != scriptState.xs) s->_executionStackPosChanged = true; - restadjust = 0; + scriptState.restAdjust = 0; } break; case 0x2c: // &rest temp = (uint16) opparams[0]; // First argument - restadjust = xs->argc - temp + 1; // +1 because temp counts the paramcount while argc doesn't - if (restadjust < 0) - restadjust = 0; + scriptState.restAdjust = MAX<int16>(scriptState.xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't - for (; temp <= xs->argc; temp++) - PUSH32(xs->variables_argp[temp]); + for (; temp <= scriptState.xs->argc; temp++) + PUSH32(scriptState.xs->variables_argp[temp]); break; @@ -1138,8 +1128,8 @@ void run_vm(EngineState *s, int restoring) { var_number = temp & 0x03; // Get variable type // Get variable block offset - r_temp.segment = variables_seg[var_number]; - r_temp.offset = variables[var_number] - variables_base[var_number]; + r_temp.segment = scriptState.variables_seg[var_number]; + r_temp.offset = scriptState.variables[var_number] - scriptState.variables_base[var_number]; if (temp & 0x08) // Add accumulator offset if requested r_temp.offset += signed_validate_arithmetic(s->r_acc); @@ -1152,7 +1142,7 @@ void run_vm(EngineState *s, int restoring) { case 0x2e: // selfID - s->r_acc = xs->objp; + s->r_acc = scriptState.xs->objp; break; case 0x30: // pprev @@ -1199,15 +1189,15 @@ void run_vm(EngineState *s, int restoring) { case 0x39: // lofsa - s->r_acc.segment = xs->addr.pc.segment; + s->r_acc.segment = scriptState.xs->addr.pc.segment; if (s->_version >= SCI_VERSION_1_1) { s->r_acc.offset = opparams[0] + local_script->script_size; } else { - if (s->_flags & GF_SCI1_LOFSABSOLUTE) + if (((SciEngine*)g_engine)->getKernel()->hasLofsAbsolute()) s->r_acc.offset = opparams[0]; else - s->r_acc.offset = xs->addr.pc.offset + opparams[0]; + s->r_acc.offset = scriptState.xs->addr.pc.offset + opparams[0]; } #ifndef DISABLE_VALIDATIONS @@ -1219,12 +1209,17 @@ void run_vm(EngineState *s, int restoring) { break; case 0x3a: // lofss - r_temp.segment = xs->addr.pc.segment; + r_temp.segment = scriptState.xs->addr.pc.segment; + + if (s->_version >= SCI_VERSION_1_1) { + r_temp.offset = opparams[0] + local_script->script_size; + } else { + if (((SciEngine*)g_engine)->getKernel()->hasLofsAbsolute()) + r_temp.offset = opparams[0]; + else + r_temp.offset = scriptState.xs->addr.pc.offset + opparams[0]; + } - if (s->_flags & GF_SCI1_LOFSABSOLUTE) - r_temp.offset = opparams[0]; - else - r_temp.offset = xs->addr.pc.offset + opparams[0]; #ifndef DISABLE_VALIDATIONS if (r_temp.offset >= code_buf_size) { error("VM: lofss operation overflowed: %04x:%04x beyond end" @@ -1247,7 +1242,7 @@ void run_vm(EngineState *s, int restoring) { break; case 0x3e: // pushSelf - PUSH32(xs->objp); + PUSH32(scriptState.xs->objp); break; case 0x40: // lag @@ -1410,30 +1405,21 @@ void run_vm(EngineState *s, int restoring) { break; default: - script_error(s, __FILE__, __LINE__, "Illegal opcode"); + error("run_vm(): illegal opcode %x", opnumber); } // switch(opcode >> 1) if (s->_executionStackPosChanged) // Force initialization - xs = xs_new; + scriptState.xs = xs_new; //#ifndef DISABLE_VALIDATIONS - if (xs != &(s->_executionStack.back())) { + if (scriptState.xs != &(s->_executionStack.back())) { warning("xs is stale (%p vs %p); last command was %02x", - (void *)xs, (void *)&(s->_executionStack.back()), + (void *)scriptState.xs, (void *)&(s->_executionStack.back()), opnumber); } //#endif - -#if 0 - if (script_error_flag) { - g_debug_step_running = 0; // Stop multiple execution - g_debug_seeking = 0; // Stop special seeks - xs->addr.pc.offset = old_pc_offset; - xs->sp = old_sp; - } else -#endif - ++script_step_counter; + ++script_step_counter; } } @@ -1514,13 +1500,12 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select // Early SCI versions used the LSB in the selector ID as a read/write // toggle, meaning that we must remove it for selector lookup. - if (s->_flags & GF_SCI0_OLD) + if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) selector_id &= ~1; if (!obj) { - CORE_ERROR("SLC-LU", "Attempt to send to non-object or invalid script"); - sciprintf("Address was %04x:%04x\n", PRINT_REG(obj_location)); - return kSelectorNone; + error("lookup_selector(): Attempt to send to non-object or invalid script. Address was %04x:%04x", + PRINT_REG(obj_location)); } if (IS_CLASS(obj)) @@ -1530,9 +1515,8 @@ SelectorType lookup_selector(EngineState *s, reg_t obj_location, Selector select if (!obj) { - CORE_ERROR("SLC-LU", "Error while looking up Species class"); - sciprintf("Original address was %04x:%04x\n", PRINT_REG(obj_location)); - sciprintf("Species address was %04x:%04x\n", PRINT_REG(obj->_variables[SCRIPT_SPECIES_SELECTOR])); + error("lookup_selector(): Error while looking up Species class.\nOriginal address was %04x:%04x. Species address was %04x:%04x\n", + PRINT_REG(obj_location), PRINT_REG(obj->_variables[SCRIPT_SPECIES_SELECTOR])); return kSelectorNone; } @@ -1572,31 +1556,24 @@ reg_t script_lookup_export(EngineState *s, int script_nr, int export_index) { Script *script = NULL; #ifndef DISABLE_VALIDATIONS - if (!seg) { - CORE_ERROR("EXPORTS", "Script invalid or not loaded"); - sciprintf("Script was script.%03d (0x%x)\n", - script_nr, script_nr); - return NULL_REG; - } + if (!seg) + error("script_lookup_export(): script.%03d (0x%x) is invalid or not loaded", + script_nr, script_nr); #endif script = script_locate_by_segment(s, seg); #ifndef DISABLE_VALIDATIONS - if (script - && export_index < script->exports_nr - && export_index >= 0) + if (script && export_index < script->exports_nr && export_index >= 0) #endif return make_reg(seg, READ_LE_UINT16((byte *)(script->export_table + export_index))); #ifndef DISABLE_VALIDATIONS else { - CORE_ERROR("EXPORTS", "Export invalid or script missing "); if (!script) - sciprintf("(script.%03d missing)\n", script_nr); + error("script_lookup_export(): script.%03d missing", script_nr); else - sciprintf("(script.%03d: Sought export %d/%d)\n", - script_nr, export_index, script->exports_nr); - return NULL_REG; + error("script_lookup_export(): script.%03d: Sought invalid export %d/%d", + script_nr, export_index, script->exports_nr); } #endif } @@ -1614,18 +1591,18 @@ int script_instantiate_common(EngineState *s, int script_nr, Resource **script, *heap = s->resmgr->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); if (!*script || (s->_version >= SCI_VERSION_1_1 && !heap)) { - sciprintf("Script 0x%x requested but not found\n", script_nr); + warning("Script 0x%x requested but not found", script_nr); if (s->_version >= SCI_VERSION_1_1) { if (*heap) - sciprintf("Inconsistency: heap resource WAS found\n"); + warning("Inconsistency: heap resource WAS found"); else if (*script) - sciprintf("Inconsistency: script resource WAS found\n"); + warning("Inconsistency: script resource WAS found"); } return 0; } if (NULL == s) { - sciprintf("vm.c: script_instantiate(): NULL passed for \"s\"\n"); + warning("script_instantiate_common(): script_instantiate(): NULL passed for \"s\""); return 0; } @@ -1682,7 +1659,7 @@ int script_instantiate_sci0(EngineState *s, int script_nr) { Script *scr = s->seg_manager->getScript(seg_id); - if (s->_flags & GF_SCI0_OLD) { + if (((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader()) { // int locals_nr = READ_LE_UINT16(script->data); @@ -1858,7 +1835,7 @@ int script_instantiate(EngineState *s, int script_nr) { } void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) { - reg_t reg = make_reg(seg, (s->_flags & GF_SCI0_OLD) ? 2 : 0); + reg_t reg = make_reg(seg, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader() ? 2 : 0); int objtype, objlength; Script *scr = s->seg_manager->getScript(seg); @@ -1902,7 +1879,7 @@ void script_uninstantiate_sci0(EngineState *s, int script_nr, SegmentId seg) { } void script_uninstantiate(EngineState *s, int script_nr) { - reg_t reg = make_reg(0, (s->_flags & GF_SCI0_OLD) ? 2 : 0); + reg_t reg = make_reg(0, ((SciEngine*)g_engine)->getKernel()->hasOldScriptHeader() ? 2 : 0); reg.segment = s->seg_manager->segGet(script_nr); Script *scr = script_locate_by_segment(s, reg.segment); @@ -1926,7 +1903,7 @@ void script_uninstantiate(EngineState *s, int script_nr) { if (s->_version < SCI_VERSION_1_1) script_uninstantiate_sci0(s, script_nr, reg.segment); else - sciprintf("FIXME: Add proper script uninstantiation for SCI 1.1\n"); + warning("FIXME: Add proper script uninstantiation for SCI 1.1"); if (scr->getLockers()) return; // if xxx.lockers > 0 @@ -1961,7 +1938,7 @@ static EngineState *_game_run(EngineState *&s, int restoring) { script_init_engine(s); game_init(s); sfx_reset_player(); - _init_stack_base_with_selector(s, s->_kernel->_selectorMap.play); + _init_stack_base_with_selector(s, ((SciEngine*)g_engine)->getKernel()->_selectorMap.play); send_selector(s, s->game_obj, s->game_obj, s->stack_base, 2, s->stack_base); @@ -1977,10 +1954,10 @@ static EngineState *_game_run(EngineState *&s, int restoring) { s = successor; if (script_abort_flag == 2) { - sciprintf("Restarting with replay()\n"); + debugC(2, kDebugLevelVM, "Restarting with replay()\n"); s->_executionStack.clear(); // Restart with replay - _init_stack_base_with_selector(s, s->_kernel->_selectorMap.replay); + _init_stack_base_with_selector(s, ((SciEngine*)g_engine)->getKernel()->_selectorMap.replay); send_selector(s, s->game_obj, s->game_obj, s->stack_base, 2, s->stack_base); } @@ -1995,24 +1972,23 @@ static EngineState *_game_run(EngineState *&s, int restoring) { return s; } -int printObject(EngineState *s, reg_t pos); - int game_run(EngineState **_s) { EngineState *s = *_s; - sciprintf(" Calling %s::play()\n", s->_gameName.c_str()); - _init_stack_base_with_selector(s, s->_kernel->_selectorMap.play); // Call the play selector + debugC(2, kDebugLevelVM, "Calling %s::play()\n", s->_gameName.c_str()); + _init_stack_base_with_selector(s, ((SciEngine*)g_engine)->getKernel()->_selectorMap.play); // Call the play selector // Now: Register the first element on the execution stack- if (!send_selector(s, s->game_obj, s->game_obj, s->stack_base, 2, s->stack_base)) { - printObject(s, s->game_obj); - sciprintf("Failed to run the game! Aborting...\n"); + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); + con->printObject(s->game_obj); + warning("Failed to run the game! Aborting..."); return 1; } // and ENGAGE! _game_run(*_s, 0); - sciprintf(" Game::play() finished.\n"); + debugC(2, kDebugLevelVM, "Game::play() finished.\n"); return 0; } @@ -2057,11 +2033,11 @@ const char *obj_get_name(EngineState *s, reg_t pos) { return name; } + void quit_vm() { script_abort_flag = 1; // Terminate VM - g_debugstate_valid = 0; - g_debug_seeking = 0; - g_debug_step_running = 0; + scriptState.seeking = kDebugSeekNothing; + scriptState.runningStep = 0; } void shrink_execution_stack(EngineState *s, uint size) { diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index a3fabbe44b..f711570d11 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -243,24 +243,23 @@ enum ExecStackType { }; struct ExecStack { - reg_t objp; - reg_t sendp; /**< Pointer to the object containing the invoked method */ + reg_t objp; // Pointer to the beginning of the current object + reg_t sendp; // Pointer to the object containing the invoked method union { - ObjVarRef varp; /**< Variable pointer for r/w access */ - reg_t pc; /**< Not accurate for the TOS element */ + ObjVarRef varp; // Variable pointer for r/w access + reg_t pc; // Pointer to the initial program counter. Not accurate for the TOS element } addr; - StackPtr fp; /**< Frame pointer */ - StackPtr sp; /**< Stack pointer */ + StackPtr fp; // Frame pointer + StackPtr sp; // Stack pointer int argc; - /* former variables[4]: [all other values are derived] */ - StackPtr variables_argp; /**< Argument pointer */ - SegmentId local_segment; /**< local variables etc. */ + StackPtr variables_argp; // Argument pointer + SegmentId local_segment; // local variables etc - Selector selector; /**< The selector which was used to call or -1 if not applicable */ - int origin; /**< The stack frame position the call was made from, or -1 if it was the initial call. */ + Selector selector; // The selector which was used to call or -1 if not applicable + int origin; // The stack frame position the call was made from, or -1 if it was the initial call ExecStackType type; reg_t* getVarPointer(EngineState *s) const; @@ -409,27 +408,10 @@ void vm_handle_fatal_error(EngineState *s, int line, const char *file); /** * Debugger functionality - * @param[in] s The state at which debugging should take - * place - * @param[in] pc Pointer to the program counter - * @param[in] sp Pointer to the stack pointer - * @param[in] pp Pointer to the frame pointer - * @param[in] objp Pointer to the object base pointer - * @param[in] restadjust Pointer to the &rest adjustment value - * @param[in] segids four-element array containing segment IDs - * for locals etc. - * @param[in] variables four-element array referencing registers - * for globals etc. - * @param[in] variables_base four-element array referencing register - * bases for temps etc. - * @param[in] variables_nr four-element array giving sizes for params - * etc. (may be NULL) - * @param[in] bp Flag, set to 1 when a breakpoint is - * triggered - */ -void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, - reg_t *objp, int *restadjust, SegmentId *segids, reg_t **variables, - reg_t **variables_base, int *variables_nr, int bp); + * @param[in] s The state at which debugging should take place + * @param[in] bp Flag, set to true when a breakpoint is triggered + */ +void script_debug(EngineState *s, bool bp); /** * Initializes a EngineState block @@ -437,7 +419,7 @@ void script_debug(EngineState *s, reg_t *pc, StackPtr *sp, StackPtr *pp, * @return 0 on success, 1 if vocab.996 (the class table) is missing * or corrupted */ -int script_init_engine(EngineState *s); +int script_init_engine(EngineState *); /** * Sets the gamestate's save_dir to the parameter path diff --git a/engines/sci/gfx/font.cpp b/engines/sci/gfx/font.cpp index 0f1a19f1c0..9265cba040 100644 --- a/engines/sci/gfx/font.cpp +++ b/engines/sci/gfx/font.cpp @@ -186,7 +186,7 @@ gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *stext, int cha int ch = (int) text[i]; if (ch >= font->chars_nr) { - GFXERROR("Invalid character 0x%02x encountered!\n", text[i]); + error("Invalid character 0x%02x encountered", text[i]); return NULL; } diff --git a/engines/sci/gfx/gfx_driver.cpp b/engines/sci/gfx/gfx_driver.cpp index 961eecc6fd..0b1387074c 100644 --- a/engines/sci/gfx/gfx_driver.cpp +++ b/engines/sci/gfx/gfx_driver.cpp @@ -25,6 +25,7 @@ #include "common/scummsys.h" #include "common/system.h" +#include "graphics/cursorman.h" #include "graphics/primitives.h" #include "sci/sci.h" @@ -204,7 +205,7 @@ int GfxDriver::update(rect_t src, Common::Point dest, gfx_buffer_t buffer) { g_system->updateScreen(); break; default: - GFXERROR("Invalid buffer %d in update!\n", buffer); + error("Invalid buffer %d in update", buffer); return GFX_ERROR; } @@ -252,22 +253,21 @@ byte *GfxDriver::createCursor(gfx_pixmap_t *pointer) { int GfxDriver::setPointer(gfx_pixmap_t *pointer, Common::Point *hotspot) { if ((pointer == NULL) || (hotspot == NULL)) { - g_system->showMouse(false); + CursorMan.showMouse(false); } else { byte *cursorData = createCursor(pointer); - // FIXME: The palette size check is a workaround for cursors using non-palette colour GFX_CURSOR_TRANSPARENT - // Note that some cursors don't have a palette in SQ5 + // FIXME: The palette size check is a workaround for cursors using non-palette color GFX_CURSOR_TRANSPARENT + // Note that some cursors don't have a palette (e.g. in SQ5 and QFG3) byte color_key = GFX_CURSOR_TRANSPARENT; if ((pointer->color_key != GFX_PIXMAP_COLOR_KEY_NONE) && (pointer->palette && (unsigned int)pointer->color_key < pointer->palette->size())) color_key = pointer->palette->getColor(pointer->color_key).parent_index; - // Some cursors in SQ5 don't have a palette. The cursor palette seems to use 64 colors, so setting the color key to 63 works - // TODO: Is this correct? + // Some cursors don't have a palette, so we set the color key directly if (!pointer->palette) - color_key = 63; + color_key = pointer->color_key; - g_system->setMouseCursor(cursorData, pointer->width, pointer->height, hotspot->x, hotspot->y, color_key); - g_system->showMouse(true); + CursorMan.replaceCursor(cursorData, pointer->width, pointer->height, hotspot->x, hotspot->y, color_key); + CursorMan.showMouse(true); delete[] cursorData; cursorData = 0; diff --git a/engines/sci/gfx/gfx_gui.cpp b/engines/sci/gfx/gfx_gui.cpp index fb05c0fe29..218bf1523e 100644 --- a/engines/sci/gfx/gfx_gui.cpp +++ b/engines/sci/gfx/gfx_gui.cpp @@ -81,14 +81,14 @@ void sciw_set_status_bar(EngineState *s, GfxPort *status_bar, const Common::Stri gfx_color_t black = s->ega_colors[0]; if (!status_bar->_visual) { - GFXERROR("Attempt to change title bar without visual!\n"); + error("Attempt to change title bar without visual"); return; } state = status_bar->_visual->_gfxState; if (!state) { - GFXERROR("Attempt to change title bar with stateless visual!\n"); + error("Attempt to change title bar with stateless visual"); return; } @@ -121,7 +121,8 @@ void sciw_set_status_bar(EngineState *s, GfxPort *status_bar, const Common::Stri static void sciw_make_window_fit(rect_t *rect, GfxPort *parent) { // This window is meant to cover the whole screen, so we allow it to go through. - if (rect->width == 319 && rect->height == 189) return; + if (rect->width == 319 && rect->height == 189) + return; if (rect->x + rect->width > parent->_bounds.x + parent->_bounds.width) rect->x -= (rect->x + rect->width) - (parent->_bounds.x + parent->_bounds.width) + 2; @@ -220,7 +221,7 @@ GfxPort *sciw_new_window(EngineState *s, if (!(flags & kWindowNoDropShadow)) { if (gfxop_set_color(state, &black, 0, 0, 0, 0x80, bgcolor.priority, -1)) { - GFXERROR("Could not get black/semitrans color entry!\n"); + error("Could not get black/semitrans color entry"); return NULL; } @@ -236,7 +237,7 @@ GfxPort *sciw_new_window(EngineState *s, // Draw frame if (gfxop_set_color(state, &black, 0, 0, 0, 0, bgcolor.priority, -1)) { - GFXERROR("Could not get black color entry!\n"); + error("Could not get black color entry"); return NULL; } @@ -418,7 +419,7 @@ GfxList *sciw_new_icon_control(GfxPort *port, reg_t ID, rect_t zone, int view, i gfxw_set_id(list, ID.segment, ID.offset); if (!port->_visual) { - GFXERROR("Attempting to create icon control for virtual port!\n"); + error("Attempting to create icon control for virtual port"); return NULL; } @@ -429,7 +430,7 @@ GfxList *sciw_new_icon_control(GfxPort *port, reg_t ID, rect_t zone, int view, i ALIGN_LEFT, ALIGN_TOP, GFXW_VIEW_FLAG_DONT_MODIFY_OFFSET); if (!icon) { - GFXERROR("Attempt to create icon control with cel %d/%d/%d (invalid)\n", view, loop, cel); + error("Attempt to create icon control with cel %d/%d/%d (invalid)", view, loop, cel); return NULL; } @@ -461,7 +462,7 @@ GfxList *sciw_new_list_control(GfxPort *port, reg_t ID, rect_t zone, int font_nr columns = (zone.height - 20); if (font_height <= 0) { - GFXERROR("Attempt to create list control with invalid font %d\n", font_nr); + error("Attempt to create list control with invalid font %d", font_nr); delete list; return NULL; } @@ -565,7 +566,7 @@ GfxPort *sciw_new_menu(EngineState *s, GfxPort *status_bar, Menubar *menubar, in return NULL; if (selection >= (int)menubar->_menus.size()) { - GFXERROR("Attempt to make menu #%d of %d\n", selection, menubar->_menus.size()); + error("Attempt to make menu #%d of %d", selection, menubar->_menus.size()); return NULL; } diff --git a/engines/sci/gfx/gfx_pixmap_scale.cpp b/engines/sci/gfx/gfx_pixmap_scale.cpp index 52c7b12396..034efafe8d 100644 --- a/engines/sci/gfx/gfx_pixmap_scale.cpp +++ b/engines/sci/gfx/gfx_pixmap_scale.cpp @@ -517,8 +517,7 @@ static void _gfx_xlate_pixmap_unfiltered(gfx_mode_t *mode, gfx_pixmap_t *pxm, in break; default: - GFXERROR("Invalid mode->bytespp=%d\n", mode->bytespp); - + error("Invalid mode->bytespp=%d", mode->bytespp); } if (pxm->flags & GFX_PIXMAP_FLAG_SCALED_INDEX) { @@ -562,8 +561,7 @@ static void _gfx_xlate_pixmap_linear(gfx_mode_t *mode, gfx_pixmap_t *pxm, int sc break; default: - GFXERROR("Invalid mode->bytespp=%d\n", mode->bytespp); - + error("Invalid mode->bytespp=%d", mode->bytespp); } } @@ -599,7 +597,7 @@ static void _gfx_xlate_pixmap_trilinear(gfx_mode_t *mode, gfx_pixmap_t *pxm, int break; default: - GFXERROR("Invalid mode->bytespp=%d\n", mode->bytespp); + error("Invalid mode->bytespp=%d", mode->bytespp); } } @@ -638,7 +636,7 @@ void gfx_xlate_pixmap(gfx_pixmap_t *pxm, gfx_mode_t *mode, gfx_xlate_filter_t fi break; default: - GFXERROR("Attempt to filter pixmap %04x in invalid mode #%d\n", pxm->ID, filter); + error("Attempt to filter pixmap %04x in invalid mode #%d", pxm->ID, filter); if (!was_allocated) { if (!mode->alpha_mask && pxm->colors_nr() < GFX_PIC_COLORS) diff --git a/engines/sci/gfx/gfx_resmgr.cpp b/engines/sci/gfx/gfx_resmgr.cpp index 0ec27ae41a..bf1c88b4d6 100644 --- a/engines/sci/gfx/gfx_resmgr.cpp +++ b/engines/sci/gfx/gfx_resmgr.cpp @@ -49,14 +49,20 @@ struct param_struct { GfxDriver *driver; }; -GfxResManager::GfxResManager(int version, bool isVGA, gfx_options_t *options, GfxDriver *driver, ResourceManager *resManager) : - _version(version), _isVGA(isVGA), _options(options), _driver(driver), _resManager(resManager), +GfxResManager::GfxResManager(gfx_options_t *options, GfxDriver *driver, ResourceManager *resManager) : + _options(options), _driver(driver), _resManager(resManager), _lockCounter(0), _tagLockCounter(0), _staticPalette(0) { gfxr_init_static_palette(); _portBounds = Common::Rect(0, 10, 320, 200); // default value, with a titlebar of 10px + _version = resManager->_volVersion; - if (_version < SCI_VERSION_01_VGA || !_isVGA) { + // Workaround for QFG1 VGA (has SCI 1.1 view data with SCI 1 compression) + if (_version == SCI_VERSION_1 && !strcmp(((SciEngine*)g_engine)->getGameID(), "qfg1")) { + _version = SCI_VERSION_1_1; + } + + if (!_resManager->isVGA()) { _staticPalette = gfx_sci0_pic_colors->getref(); } else if (_version == SCI_VERSION_1_1) { debugC(2, kDebugLevelGraphics, "Palettes are not yet supported in this SCI version\n"); @@ -99,7 +105,7 @@ int GfxResManager::calculatePic(gfxr_pic_t *scaled_pic, gfxr_pic_t *unscaled_pic if (_version == SCI_VERSION_1_1) gfxr_draw_pic11(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id.number, _staticPalette, _portBounds); else - gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id.number, _isVGA, _staticPalette, _portBounds); + gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id.number, _resManager->isVGA(), _staticPalette, _portBounds); } if (scaled_pic && scaled_pic->undithered_buffer) @@ -108,9 +114,9 @@ int GfxResManager::calculatePic(gfxr_pic_t *scaled_pic, gfxr_pic_t *unscaled_pic if (_version == SCI_VERSION_1_1) gfxr_draw_pic11(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id.number, _staticPalette, _portBounds); else - gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id.number, _isVGA, _staticPalette, _portBounds); + gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id.number, _resManager->isVGA(), _staticPalette, _portBounds); - if (!_isVGA) { + if (!_resManager->isVGA()) { if (need_unscaled) gfxr_remove_artifacts_pic0(scaled_pic, unscaled_pic); @@ -144,7 +150,7 @@ int GfxResManager::getOptionsHash(gfx_resource_type_t type) { case GFX_RESOURCE_TYPE_PIC: #ifdef CUSTOM_GRAPHICS_OPTIONS - if (_version >= SCI_VERSION_01_VGA) + if (_resManager->isVGA()) // NOTE: here, it is assumed that the upper port bound is always 10, but this doesn't seem to matter for the // generated options hash anyway return 10; @@ -153,7 +159,7 @@ int GfxResManager::getOptionsHash(gfx_resource_type_t type) { | (_options->pic0_dither_pattern << 8) | (_options->pic0_brush_mode << 4) | (_options->pic0_line_mode); #else - if (_version >= SCI_VERSION_01_VGA) + if (_resManager->isVGA()) return 10; else return 0x10000 | (GFXR_DITHER_PATTERN_SCALED << 8) | (GFX_BRUSH_MODE_RANDOM_ELLIPSES << 4) | GFX_LINE_MODE_CORRECT; @@ -165,7 +171,7 @@ int GfxResManager::getOptionsHash(gfx_resource_type_t type) { case GFX_RESOURCE_TYPES_NR: default: - GFXERROR("Invalid resource type: %d\n", type); + error("Invalid resource type: %d", type); return -1; } } @@ -334,31 +340,31 @@ gfxr_pic_t *GfxResManager::getPic(int num, int maps, int flags, int default_pale res = resMap.contains(num) ? resMap[num] : NULL; if (!res || res->mode != hash) { - gfxr_pic_t *pic; + gfxr_pic_t *pic = NULL; gfxr_pic_t *unscaled_pic = NULL; #ifdef CUSTOM_GRAPHICS_OPTIONS if (_options->pic0_unscaled) { need_unscaled = 0; - pic = gfxr_init_pic(&mode_1x1_color_index, GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _version >= SCI_VERSION_01_VGA); + pic = gfxr_init_pic(&mode_1x1_color_index, GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _resManager->isVGA()); } else - pic = gfxr_init_pic(_driver->getMode(), GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _version >= SCI_VERSION_01_VGA); + pic = gfxr_init_pic(_driver->getMode(), GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _resManager->isVGA()); #else need_unscaled = 0; - pic = gfxr_init_pic(_driver->getMode(), GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _version >= SCI_VERSION_01_VGA); + pic = gfxr_init_pic(_driver->getMode(), GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _resManager->isVGA()); #endif if (!pic) { - GFXERROR("Failed to allocate scaled pic!\n"); + error("Failed to allocate scaled pic"); return NULL; } gfxr_clear_pic0(pic, SCI_TITLEBAR_SIZE); if (need_unscaled) { - unscaled_pic = gfxr_init_pic(&mode_1x1_color_index, GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _version >= SCI_VERSION_01_VGA); + unscaled_pic = gfxr_init_pic(&mode_1x1_color_index, GFXR_RES_ID(GFX_RESOURCE_TYPE_PIC, num), _resManager->isVGA()); if (!unscaled_pic) { - GFXERROR("Failed to allocate unscaled pic!\n"); + error("Failed to allocate unscaled pic"); return NULL; } gfxr_clear_pic0(pic, SCI_TITLEBAR_SIZE); @@ -529,17 +535,16 @@ gfxr_view_t *GfxResManager::getView(int nr, int *loop, int *cel, int palette) { return NULL; int resid = GFXR_RES_ID(GFX_RESOURCE_TYPE_VIEW, nr); + + if (!_resManager->isVGA()) { + int pal = (_version == SCI_VERSION_0) ? -1 : palette; + view = getEGAView(resid, viewRes->data, viewRes->size, pal); + } else { + if (_version < SCI_VERSION_1_1) + view = getVGAView(resid, viewRes->data, viewRes->size, _staticPalette, false); + else + view = getVGAView(resid, viewRes->data, viewRes->size, 0, true); - if (_version < SCI_VERSION_01) - view = gfxr_draw_view0(resid, viewRes->data, viewRes->size, -1); - else if (_version == SCI_VERSION_01 || !_isVGA) - view = gfxr_draw_view0(resid, viewRes->data, viewRes->size, palette); - else if (_version >= SCI_VERSION_01_VGA && _version <= SCI_VERSION_1_LATE) - view = gfxr_draw_view1(resid, viewRes->data, viewRes->size, _staticPalette, false); - else if (_version >= SCI_VERSION_1_1) - view = gfxr_draw_view1(resid, viewRes->data, viewRes->size, 0, true); - - if (_isVGA) { if (!view->palette) { view->palette = new Palette(_staticPalette->size()); view->palette->name = "interpreter_get_view"; @@ -553,7 +558,6 @@ gfxr_view_t *GfxResManager::getView(int nr, int *loop, int *cel, int palette) { view->palette->setColor(i, sc.r, sc.g, sc.b); } } - } if (!res) { @@ -602,6 +606,8 @@ gfxr_view_t *GfxResManager::getView(int nr, int *loop, int *cel, int palette) { } if (!cel_data->data) { + if (!cel_data->palette) + cel_data->palette = view->palette->getref(); #ifdef CUSTOM_GRAPHICS_OPTIONS gfx_get_res_config(_options, cel_data); gfx_xlate_pixmap(cel_data, _driver->getMode(), _options->view_xlate_filter); @@ -618,6 +624,11 @@ gfx_bitmap_font_t *GfxResManager::getFont(int num, bool scaled) { gfx_resource_t *res = NULL; int hash = getOptionsHash(GFX_RESOURCE_TYPE_FONT); + // Workaround: LSL1VGA mixes its own internal fonts with the global + // SCI ones, so we translate them here, by removing their extra bits + if (!resMap.contains(num) && !_resManager->testResource(ResourceId(kResourceTypeFont, num))) + num = num & 0x7ff; + res = resMap.contains(num) ? resMap[num] : NULL; if (!res || res->mode != hash) { diff --git a/engines/sci/gfx/gfx_resmgr.h b/engines/sci/gfx/gfx_resmgr.h index 1f0f58dce9..5cd5d018cc 100644 --- a/engines/sci/gfx/gfx_resmgr.h +++ b/engines/sci/gfx/gfx_resmgr.h @@ -90,9 +90,7 @@ typedef Common::HashMap<int, gfx_resource_t *> IntResMap; /** Graphics resource manager */ class GfxResManager { public: - GfxResManager(int version, bool isVGA, gfx_options_t *options, - GfxDriver *driver, ResourceManager *resManager); - + GfxResManager(gfx_options_t *options, GfxDriver *driver, ResourceManager *resManager); ~GfxResManager(); /** @@ -272,8 +270,7 @@ public: /** * Retrieves a color from the static palette */ - const PaletteEntry &getColor(int color) - { + const PaletteEntry &getColor(int color) { return _staticPalette->getColor(color); } @@ -311,14 +308,17 @@ public: * * @return Number of pallete entries */ - int getColorCount() - { + int getColorCount() { return _staticPalette ? _staticPalette->size() : 0; } + /** + * Returns the resource version that the resource manager is using + */ + int getVersion() { return _version; } + private: int _version; - bool _isVGA; gfx_options_t *_options; GfxDriver *_driver; Palette *_staticPalette; diff --git a/engines/sci/gfx/gfx_resource.h b/engines/sci/gfx/gfx_resource.h index 780060bc4f..9c83cf07cd 100644 --- a/engines/sci/gfx/gfx_resource.h +++ b/engines/sci/gfx/gfx_resource.h @@ -245,7 +245,7 @@ void gfxr_remove_artifacts_pic0(gfxr_pic_t *dest, gfxr_pic_t *src); void gfxr_dither_pic0(gfxr_pic_t *pic, int mode, int pattern); /** - * Calculates a SCI0 view. + * Calculates an EGA view. * * @param[in] id Resource ID of the view * @param[in] resource Pointer to the resource to read @@ -253,7 +253,7 @@ void gfxr_dither_pic0(gfxr_pic_t *pic, int mode, int pattern); * @param[in] palette The palette to use * @return The resulting view */ -gfxr_view_t *gfxr_draw_view0(int id, byte *resource, int size, int palette); +gfxr_view_t *getEGAView(int id, byte *resource, int size, int palette); /** * Calculates a SCI cursor. @@ -265,8 +265,7 @@ gfxr_view_t *gfxr_draw_view0(int id, byte *resource, int size, int palette); * @return A newly allocated pixmap containing an index color * representation of the cursor */ -gfx_pixmap_t *gfxr_draw_cursor(int id, byte *resource, int size, - bool isSci01); +gfx_pixmap_t *gfxr_draw_cursor(int id, byte *resource, int size, bool isSci01); /** @} */ @@ -304,7 +303,7 @@ Palette *gfxr_read_pal1_amiga(Common::File &file); Palette *gfxr_read_pal11(int id, byte *resource, int size); /** - * Calculates an SCI1 view. + * Calculates a VGA view. * * @param[in] id Resource ID of the view * @param[in] resource Pointer to the resource to read @@ -313,7 +312,7 @@ Palette *gfxr_read_pal11(int id, byte *resource, int size); * @param[in] isSci11 true if SCI1.1, false otherwise * @return The resulting view */ -gfxr_view_t *gfxr_draw_view1(int id, byte *resource, int size, Palette *static_pal, bool isSci11); +gfxr_view_t *getVGAView(int id, byte *resource, int size, Palette *static_pal, bool isSci11); gfx_pixmap_t *gfxr_draw_cel1(int id, int loop, int cel, int mirrored, byte *resource, byte *cel_base, int size, gfxr_view_t *view, bool isAmiga, bool isSci11); /** @} */ diff --git a/engines/sci/gfx/gfx_state_internal.h b/engines/sci/gfx/gfx_state_internal.h index 3f00b5213c..3beb0ea067 100644 --- a/engines/sci/gfx/gfx_state_internal.h +++ b/engines/sci/gfx/gfx_state_internal.h @@ -132,7 +132,7 @@ public: } /** - * Prints a string representation of the widget with sciprintf. + * Prints a string representation of the widget with printf. * * Will recursively print all of the widget's contents if the widget * contains further sub-widgets diff --git a/engines/sci/gfx/gfx_support.cpp b/engines/sci/gfx/gfx_support.cpp index 3a32752b9a..314e955367 100644 --- a/engines/sci/gfx/gfx_support.cpp +++ b/engines/sci/gfx/gfx_support.cpp @@ -94,7 +94,7 @@ static void gfx_draw_line_buffer(byte *buffer, int linewidth, int pixelwidth, return; default: - GFXERROR("pixelwidth=%d not supported!\n", pixelwidth); + error("pixelwidth=%d not supported", pixelwidth); return; } @@ -292,7 +292,7 @@ int gfx_crossblit_pixmap(gfx_mode_t *mode, gfx_pixmap_t *pxm, int priority, rect alpha_mask = mode->alpha_mask; if (!alpha_mask && pxm->alpha_map) { - GFXERROR("Invalid alpha mode: both pxm->alpha_map and alpha_mask are white!\n"); + error("Invalid alpha mode: both pxm->alpha_map and alpha_mask are white"); return GFX_ERROR; } @@ -335,7 +335,7 @@ int gfx_crossblit_pixmap(gfx_mode_t *mode, gfx_pixmap_t *pxm, int priority, rect xl, yl, alpha, bytes_per_alpha_line, bytes_per_alpha_pixel, alpha_mask, alpha_min, 0, 0, 0, 0); else { - GFXERROR("Invalid mode->bytespp: %d\n", mode->bytespp); + error("Invalid mode->bytespp: %d", mode->bytespp); return GFX_ERROR; } } else { // priority @@ -344,7 +344,7 @@ int gfx_crossblit_pixmap(gfx_mode_t *mode, gfx_pixmap_t *pxm, int priority, rect xl, yl, alpha, bytes_per_alpha_line, bytes_per_alpha_pixel, alpha_mask, alpha_min, priority_pos, priority_line_width, priority_skip, priority); else { - GFXERROR("Invalid mode->bytespp: %d\n", mode->bytespp); + error("Invalid mode->bytespp: %d", mode->bytespp); return GFX_ERROR; } } diff --git a/engines/sci/gfx/gfx_system.h b/engines/sci/gfx/gfx_system.h index 6b7724a6bd..20c92efa2d 100644 --- a/engines/sci/gfx/gfx_system.h +++ b/engines/sci/gfx/gfx_system.h @@ -35,9 +35,6 @@ namespace Sci { #define GFX_DEBUG -/* General output macros */ -#define GFXERROR sciprintf("GFX Error: %s, L%d:", __FILE__, __LINE__); error - /***********************/ /*** Data structures ***/ /***********************/ @@ -192,7 +189,7 @@ struct gfx_pixmap_t { * As a special exception, 256 colors are allowed for background pictures * (which do not use transparency) */ - int colors_nr() const { return palette ? palette->size() : 0; } + int colors_nr() const { return palette ? MIN<int>(palette->size(), 256) : 0; } uint32 flags; /* @} */ diff --git a/engines/sci/gfx/gfx_tools.cpp b/engines/sci/gfx/gfx_tools.cpp index e89fb1572a..e3d35ecb14 100644 --- a/engines/sci/gfx/gfx_tools.cpp +++ b/engines/sci/gfx/gfx_tools.cpp @@ -245,7 +245,7 @@ gfx_pixmap_t *gfx_pixmap_scale_index_data(gfx_pixmap_t *pixmap, gfx_mode_t *mode old_data = pixmap->index_data; if (!old_data) { - GFXERROR("Attempt to scale index data without index data!\n"); + error("Attempt to scale index data without index data!\n"); return pixmap; } diff --git a/engines/sci/gfx/gfx_widgets.cpp b/engines/sci/gfx/gfx_widgets.cpp index 2207309f48..12cec0ada6 100644 --- a/engines/sci/gfx/gfx_widgets.cpp +++ b/engines/sci/gfx/gfx_widgets.cpp @@ -81,7 +81,7 @@ static void _gfxw_debug_remove_widget(GfxWidget *widget) { static void indent(int indentation) { for (int i = 0; i < indentation; i++) - sciprintf(" "); + printf(" "); } void GfxWidget::printIntern(int indentation) const { @@ -92,35 +92,35 @@ void GfxWidget::printIntern(int indentation) const { if (_magic == GFXW_MAGIC_VALID) { if (_visual) - sciprintf("v "); + printf("v "); else - sciprintf("NoVis "); + printf("NoVis "); } else if (_magic == GFXW_MAGIC_INVALID) - sciprintf("INVALID "); + printf("INVALID "); - sciprintf("S%08x", _serial); + printf("S%08x", _serial); if (_ID != GFXW_NO_ID) { - sciprintf("#%x", _ID); + printf("#%x", _ID); if (_subID != GFXW_NO_ID) - sciprintf(":%x ", _subID); + printf(":%x ", _subID); else - sciprintf(" "); + printf(" "); } - sciprintf("[(%d,%d)(%dx%d)]", _bounds.x, _bounds.y, _bounds.width, _bounds.height); + printf("[(%d,%d)(%dx%d)]", _bounds.x, _bounds.y, _bounds.width, _bounds.height); for (i = 0; i < strlen(flags_list); i++) if (_flags & (1 << i)) - sciprintf("%c", flags_list[i]); + printf("%c", flags_list[i]); - sciprintf(" "); + printf(" "); } void GfxWidget::print(int indentation) const { printIntern(indentation); - sciprintf("<untyped #%d>", _type); + printf("<untyped #%d>", _type); } GfxWidget::GfxWidget(gfxw_widget_type_t type_) { @@ -149,13 +149,13 @@ GfxWidget::GfxWidget(gfxw_widget_type_t type_) { static int verify_widget(GfxWidget *widget) { if (!widget) { - GFXERROR("Attempt to use NULL widget\n"); + warning("Attempt to use NULL widget"); return 1; } else if (widget->_magic != GFXW_MAGIC_VALID) { if (widget->_magic == GFXW_MAGIC_INVALID) { - GFXERROR("Attempt to use invalidated widget\n"); + warning("Attempt to use invalidated widget"); } else { - GFXERROR("Attempt to use non-widget\n"); + warning("Attempt to use non-widget"); } return 1; } @@ -163,13 +163,13 @@ static int verify_widget(GfxWidget *widget) { } #define VERIFY_WIDGET(w) \ - if (verify_widget((GfxWidget *)(w))) { GFXERROR("Error occured while validating widget\n"); } + if (verify_widget((GfxWidget *)(w))) { error("Error occured while validating widget"); } #define GFX_ASSERT(_x) \ { \ int retval = (_x); \ if (retval == GFX_ERROR) { \ - GFXERROR("Error occured while drawing widget!\n"); \ + warning("Error occured while drawing widget"); \ return 1; \ } else if (retval == GFX_FATAL) { \ error("Fatal error occured while drawing widget!\nGraphics state invalid; aborting program..."); \ @@ -183,23 +183,23 @@ static int verify_widget(GfxWidget *widget) { // Assertion for drawing #define DRAW_ASSERT(widget, exp_type) \ if (!(widget)) { \ - sciprintf("L%d: NULL widget", __LINE__); \ + printf("L%d: NULL widget", __LINE__); \ return 1; \ } \ if ((widget)->_type != (exp_type)) { \ - sciprintf("L%d: Error in widget: Expected type " # exp_type "(%d) but got %d\n", __LINE__, exp_type, (widget)->_type); \ - sciprintf("Erroneous widget: "); \ + printf("L%d: Error in widget: Expected type " # exp_type "(%d) but got %d\n", __LINE__, exp_type, (widget)->_type); \ + printf("Erroneous widget: "); \ widget->print(4); \ - sciprintf("\n"); \ + printf("\n"); \ return 1; \ } \ if (!(widget->_flags & GFXW_FLAG_VISIBLE)) \ return 0; \ if (!(widget->_type == GFXW_VISUAL || widget->_visual)) { \ - sciprintf("L%d: Error while drawing widget: Widget has no visual\n", __LINE__); \ - sciprintf("Erroneous widget: "); \ + printf("L%d: Error while drawing widget: Widget has no visual\n", __LINE__); \ + printf("Erroneous widget: "); \ widget->print(1); \ - sciprintf("\n"); \ + printf("\n"); \ return 1; \ } @@ -253,8 +253,7 @@ void gfxw_remove_widget_from_container(GfxContainer *container, GfxWidget *widge GfxWidget **seekerp; if (!container) { - GFXERROR("Attempt to remove widget from NULL container!\n"); - error("gfxw_remove_widget_from_container() failed. Breakpoint in %s, line %d", __FILE__, __LINE__); + error("Attempt to remove widget from NULL container!\n"); } seekerp = &(container->_contents); @@ -271,10 +270,10 @@ void gfxw_remove_widget_from_container(GfxContainer *container, GfxWidget *widge seekerp = &((*seekerp)->_next); if (!*seekerp) { - GFXERROR("Internal error: Attempt to remove widget from container it was not contained in!\n"); - sciprintf("Widget:"); + printf("Internal error: Attempt to remove widget from container it was not contained in!\n"); + printf("Widget:"); widget->print(1); - sciprintf("Container:"); + printf("Container:"); widget->print(1); error("gfxw_remove_widget_from_container() failed. Breakpoint in %s, line %d", __FILE__, __LINE__); return; @@ -341,7 +340,7 @@ int GfxBox::draw(const Common::Point &pos) { void GfxBox::print(int indentation) const { printIntern(indentation); - sciprintf("BOX"); + printf("BOX"); } static int _gfxwop_box_superarea_of(GfxWidget *widget, GfxWidget *other) { @@ -472,7 +471,7 @@ int GfxRect::draw(const Common::Point &pos) { void GfxRect::print(int indentation) const { printIntern(indentation); - sciprintf("RECT"); + printf("RECT"); } void _gfxw_set_ops_RECT(GfxWidget *prim) { @@ -518,7 +517,7 @@ int GfxLine::draw(const Common::Point &pos) { void GfxLine::print(int indentation) const { printIntern(indentation); -// sciprintf("LINE"); +// printf("LINE"); } void _gfxw_set_ops_LINE(GfxWidget *prim) { @@ -598,13 +597,13 @@ void GfxView::print(int indentation) const { printIntern(indentation); if (_type == GFXW_STATIC_VIEW) - sciprintf("STATICVIEW"); + printf("STATICVIEW"); else if (_type == GFXW_VIEW) - sciprintf("VIEW"); + printf("VIEW"); else error("GfxView::print: Invalid type %d", _type); - sciprintf("(%d/%d/%d)@(%d,%d)[p:%d,c:%d]", _view, _loop, _cel, _pos.x, _pos.y, + printf("(%d/%d/%d)@(%d,%d)[p:%d,c:%d]", _view, _loop, _cel, _pos.x, _pos.y, (_color.mask & GFX_MASK_PRIORITY) ? _color.priority : -1, (_color.mask & GFX_MASK_CONTROL) ? _color.control : -1); } @@ -675,13 +674,13 @@ int GfxDynView::draw(const Common::Point &pos) { printIntern(indentation); if (_type == GFXW_DYN_VIEW) - sciprintf("DYNVIEW"); + printf("DYNVIEW"); else if (_type == GFXW_PIC_VIEW) - sciprintf("PICVIEW"); + printf("PICVIEW"); else error("GfxDynView::print: Invalid type %d", _type); - sciprintf(" SORT=%d z=%d seq=%d (%d/%d/%d)@(%d,%d)[p:%d,c:%d]; sig[%04x@%04X:%04X[%d]]", force_precedence, _z, + printf(" SORT=%d z=%d seq=%d (%d/%d/%d)@(%d,%d)[p:%d,c:%d]; sig[%04x@%04X:%04X[%d]]", force_precedence, _z, sequence, _view, _loop, _cel, _pos.x, _pos.y, (_color.mask & GFX_MASK_PRIORITY) ? _color.priority : -1, (_color.mask & GFX_MASK_CONTROL) ? _color.control : -1, signal, signalp.obj.segment, signalp.obj.offset, signalp.varindex); @@ -815,8 +814,7 @@ GfxText::~GfxText() { if (_textHandle) { GfxState *state = _visual ? _visual->_gfxState : NULL; if (!state) { - GFXERROR("Attempt to free text without supplying mode to free it from!\n"); - error("GfxText destructor failed. Breakpoint in %s, line %d", __FILE__, __LINE__); + error("Attempt to free text without supplying mode to free it from!\n"); } else { gfxop_free_text(state, _textHandle); _textHandle = NULL; @@ -838,7 +836,7 @@ int GfxText::draw(const Common::Point &pos) { void GfxText::print(int indentation) const { printIntern(indentation); - sciprintf("TEXT:'%s'", _text.c_str()); + printf("TEXT:'%s'", _text.c_str()); } static int _gfxwop_text_equals(GfxWidget *widget, GfxWidget *other) { @@ -964,11 +962,11 @@ static int _w_gfxwop_container_print_contents(const char *name, GfxWidget *widge indent(indentation); - sciprintf("--%s:\n", name); + printf("--%s:\n", name); while (seeker) { seeker->print(indentation + 1); - sciprintf("\n"); + printf("\n"); seeker = seeker->_next; } @@ -976,14 +974,14 @@ static int _w_gfxwop_container_print_contents(const char *name, GfxWidget *widge } void GfxContainer::print(int indentation) const { - sciprintf(" viszone=((%d,%d),(%dx%d))\n", zone.x, zone.y, zone.width, zone.height); + printf(" viszone=((%d,%d),(%dx%d))\n", zone.x, zone.y, zone.width, zone.height); indent(indentation); - sciprintf("--dirty:\n"); + printf("--dirty:\n"); for (DirtyRectList::const_iterator dirty = _dirtyRects.begin(); dirty != _dirtyRects.end(); ++dirty) { indent(indentation + 1); - sciprintf("dirty(%d,%d, (%dx%d))\n", dirty->x, dirty->y, dirty->width, dirty->height); + printf("dirty(%d,%d, (%dx%d))\n", dirty->x, dirty->y, dirty->width, dirty->height); } _w_gfxwop_container_print_contents("contents", _contents, indentation); @@ -1155,11 +1153,11 @@ static void _gfxw_dirtify_container(GfxContainer *container, GfxWidget *widget) static int _parentize_widget(GfxContainer *container, GfxWidget *widget) { if (widget->_parent) { - GFXERROR("_gfxwop_container_add(): Attempt to give second parent node to widget!\nWidget:"); + printf("_parentize_widget(): Attempt to give second parent node to widget!\nWidget:"); widget->print(3); - sciprintf("\nContainer:"); + printf("\nContainer:"); container->print(3); - + error("Error in _parentize_widget()"); return 1; } @@ -1253,9 +1251,9 @@ void GfxList::print(int indentation) const { printIntern(indentation); if (_type == GFXW_LIST) - sciprintf("LIST"); + printf("LIST"); else if (_type == GFXW_SORTED_LIST) - sciprintf("SORTED_LIST"); + printf("SORTED_LIST"); else error("GfxList::print: Invalid type %d", _type); @@ -1272,7 +1270,7 @@ static int _gfxwop_list_equals(GfxWidget *widget, GfxWidget *other) { if (!GFXW_IS_LIST(widget)) { warning("[GFX] _gfxwop_list_equals(): Method called on non-list"); widget->print(0); - sciprintf("\n"); + printf("\n"); return 0; } @@ -1316,11 +1314,11 @@ int _gfxwop_ordered_add(GfxContainer *container, GfxWidget *widget, int compare_ GfxWidget **seekerp = &(container->_contents); if (widget->_next) { - GFXERROR("_gfxwop_sorted_list_add(): Attempt to add widget to two lists!\nWidget:"); + printf("_gfxwop_ordered_add(): Attempt to add widget to two lists!\nWidget:"); widget->print(3); - sciprintf("\nList:"); + printf("\nList:"); container->print(3); - error("Breakpoint in %s, line %d", __FILE__, __LINE__); + error("Error in _gfxwop_ordered_add()"); } if (_gfxw_container_id_equals(container, widget)) @@ -1388,7 +1386,7 @@ int GfxVisual::draw(const Common::Point &pos) { int err = gfxop_clear_box(_gfxState, *dirty); if (err) { - GFXERROR("Error while clearing dirty rect (%d,%d,(%dx%d))\n", dirty->x, + error("Error while clearing dirty rect (%d,%d,(%dx%d))", dirty->x, dirty->y, dirty->width, dirty->height); if (err == GFX_FATAL) return err; @@ -1405,15 +1403,15 @@ int GfxVisual::draw(const Common::Point &pos) { void GfxVisual::print(int indentation) const { printIntern(indentation); - sciprintf("VISUAL; ports={"); + printf("VISUAL; ports={"); for (uint i = 0; i < _portRefs.size(); i++) { if (_portRefs[i]) { if (i != 0) - sciprintf(","); - sciprintf("%d", i); + printf(","); + printf("%d", i); } } - sciprintf("}\n"); + printf("}\n"); GfxContainer::print(indentation); } @@ -1519,10 +1517,10 @@ GfxPort::~GfxPort() { void GfxPort::print(int indentation) const { printIntern(indentation); - sciprintf("PORT"); - sciprintf(" font=%d drawpos=(%d,%d)", _font, draw_pos.x, draw_pos.y); + printf("PORT"); + printf(" font=%d drawpos=(%d,%d)", _font, draw_pos.x, draw_pos.y); if (gray_text) - sciprintf(" (gray)"); + printf(" (gray)"); GfxContainer::print(indentation); _w_gfxwop_container_print_contents("decorations", _decorations, indentation); diff --git a/engines/sci/gfx/menubar.cpp b/engines/sci/gfx/menubar.cpp index 9d3ed6a4a5..a5a43a7f00 100644 --- a/engines/sci/gfx/menubar.cpp +++ b/engines/sci/gfx/menubar.cpp @@ -334,7 +334,7 @@ int Menubar::setAttribute(EngineState *s, int menu_nr, int item_nr, int attribut break; default: - sciprintf("Attempt to set invalid attribute of menu %d, item %d: 0x%04x\n", menu_nr, item_nr, attribute); + error("Attempt to set invalid attribute of menu %d, item %d: 0x%04x", menu_nr, item_nr, attribute); return 1; } @@ -367,7 +367,7 @@ reg_t Menubar::getAttribute(int menu_nr, int item_nr, int attribute) const { return make_reg(0, item._tag); default: - sciprintf("Attempt to read invalid attribute from menu %d, item %d: 0x%04x\n", menu_nr, item_nr, attribute); + warning("Attempt to read invalid attribute from menu %d, item %d: 0x%04x", menu_nr, item_nr, attribute); return make_reg(0, -1); } } diff --git a/engines/sci/gfx/operations.cpp b/engines/sci/gfx/operations.cpp index 613e5de1b1..6b15cdc516 100644 --- a/engines/sci/gfx/operations.cpp +++ b/engines/sci/gfx/operations.cpp @@ -61,13 +61,6 @@ gfx_pixmap_color_t default_colors[DEFAULT_COLORS_NR] = {{GFX_COLOR_SYSTEM, 0x00, #define POINTER_VISIBLE_BUT_CLIPPED 2 -// Performs basic checks that apply to most functions -#define BASIC_CHECKS(error_retval) \ -if (!state) { \ - GFXERROR("Null state!\n"); \ - return error_retval; \ -} - // How to determine whether colors have to be allocated #define PALETTE_MODE state->driver->getMode()->palette @@ -157,7 +150,7 @@ static int _gfxop_grab_pixmap(GfxState *state, gfx_pixmap_t **pxmp, int x, int y int x,y; \ \ if (!pxm->index_data) { \ - GFXERROR("Attempt to draw control color %d on pixmap %d/%d/%d without index data", color, pxm->ID, pxm->loop, pxm->cel); \ + error("Attempt to draw control color %d on pixmap %d/%d/%d without index data", color, pxm->ID, pxm->loop, pxm->cel); \ return; \ } \ \ @@ -257,7 +250,7 @@ static int _gfxop_draw_pixmap(GfxDriver *driver, gfx_pixmap_t *pxm, int priority err = driver->drawPixmap(pxm, priority, src, clipped_dest, static_buf ? GFX_BUFFER_STATIC : GFX_BUFFER_BACK); if (err) { - GFXERROR("driver->draw_pixmap() returned err!\n"); + error("driver->draw_pixmap() returned error code"); return err; } @@ -301,7 +294,7 @@ static int _gfxop_update_box(GfxState *state, rect_t box) { _gfxop_scale_rect(&box, state->driver->getMode()); if ((retval = _gfxop_buffer_propagate_box(state, box, GFX_BUFFER_FRONT))) { - GFXERROR("Error occured while propagating box (%d,%d,%d,%d) to front buffer\n", box.x, box.y, box.width, box.height); + error("Error occured while propagating box (%d,%d,%d,%d) to front buffer", box.x, box.y, box.width, box.height); return retval; } return GFX_OK; @@ -354,7 +347,7 @@ void gfxdr_add_dirty(DirtyRectList &list, rect_t box, int strategy) { break; default: - GFXERROR("Attempt to use invalid dirty frame mode %d!\nPlease refer to gfx_options.h.", strategy); + error("Attempt to use invalid dirty frame mode %d!\nPlease refer to gfx_options.h", strategy); } } @@ -411,13 +404,11 @@ static void init_aux_pixmap(gfx_pixmap_t **pixmap) { (*pixmap)->palette = new Palette(default_colors, DEFAULT_COLORS_NR); } -int gfxop_init(int version, bool isVGA, GfxState *state, gfx_options_t *options, ResourceManager *resManager, +int gfxop_init(int version, GfxState *state, gfx_options_t *options, ResourceManager *resManager, int xfact, int yfact, gfx_color_mode_t bpp) { //int color_depth = bpp ? bpp : 1; //int initialized = 0; - BASIC_CHECKS(GFX_FATAL); - state->options = options; state->visible_map = GFX_MASK_VISUAL; state->fullscreen_override = NULL; // No magical override @@ -432,8 +423,8 @@ int gfxop_init(int version, bool isVGA, GfxState *state, gfx_options_t *options, state->driver = new GfxDriver(xfact, yfact, bpp); - state->gfxResMan = new GfxResManager(version, isVGA, state->options, state->driver, resManager); - + state->gfxResMan = new GfxResManager(state->options, state->driver, resManager); + gfxop_set_clip_zone(state, gfx_rect(0, 0, 320, 200)); init_aux_pixmap(&(state->control_map)); @@ -444,8 +435,6 @@ int gfxop_init(int version, bool isVGA, GfxState *state, gfx_options_t *options, } int gfxop_exit(GfxState *state) { - BASIC_CHECKS(GFX_ERROR); - state->gfxResMan->freeResManager(); if (state->control_map) { @@ -520,7 +509,6 @@ int gfxop_scan_bitmask(GfxState *state, rect_t area, gfx_map_mask_t map) { int gfxop_set_clip_zone(GfxState *state, rect_t zone) { int xfact, yfact; - BASIC_CHECKS(GFX_ERROR); DDIRTY(stderr, "-- Setting clip zone %d %d %d %d\n", GFX_PRINT_RECT(zone)); @@ -557,8 +545,6 @@ int gfxop_set_color(GfxState *state, gfx_color_t *color, int r, int g, int b, in int mask = ((r >= 0 && g >= 0 && b >= 0) ? GFX_MASK_VISUAL : 0) | ((priority >= 0) ? GFX_MASK_PRIORITY : 0) | ((control >= 0) ? GFX_MASK_CONTROL : 0); - BASIC_CHECKS(GFX_FATAL); - if (PALETTE_MODE && a >= GFXOP_ALPHA_THRESHOLD) mask &= ~GFX_MASK_VISUAL; @@ -593,13 +579,11 @@ int gfxop_set_color(GfxState *state, gfx_color_t *colorOut, gfx_color_t &colorIn } int gfxop_set_system_color(GfxState *state, unsigned int index, gfx_color_t *color) { - BASIC_CHECKS(GFX_FATAL); - if (!PALETTE_MODE) return GFX_OK; if (index >= state->driver->getMode()->palette->size()) { - GFXERROR("Attempt to set invalid color index %02x as system color\n", color->visual.parent_index); + error("Attempt to set invalid color index %02x as system color", color->visual.parent_index); return GFX_ERROR; } @@ -662,7 +646,7 @@ static int line_clip(rect_t *line, rect_t clip, int xfact, int yfact) { return line_check_bar(&(line->x), &(line->width), clip.x, clip.width); } else { // "normal" line - float start = 0.0, end = 1.0; + float start = 0.0f, end = 1.0f; float xv = (float)line->width; float yv = (float)line->height; @@ -682,7 +666,7 @@ static int line_clip(rect_t *line, rect_t clip, int xfact, int yfact) { line->width = (int)(xv * (end - start)); line->height = (int)(yv * (end - start)); - return (start > 1.0 || end < 0.0); + return (start > 1.0f || end < 0.0f); } } @@ -752,7 +736,7 @@ static int simulate_stippled_line_draw(GfxDriver *driver, int skipone, Common::P Common::Point nextpos = Common::Point(start.x + xl, start.y + yl); if ((retval = driver->drawLine(start, nextpos, color, line_mode, GFX_LINE_STYLE_NORMAL))) { - GFXERROR("Failed to draw partial stippled line (%d,%d) -- (%d,%d)\n", start.x, start.y, nextpos.x, nextpos.y); + error("Failed to draw partial stippled line (%d,%d) -- (%d,%d)", start.x, start.y, nextpos.x, nextpos.y); return retval; } *posvar += delta; @@ -774,7 +758,7 @@ static int simulate_stippled_line_draw(GfxDriver *driver, int skipone, Common::P nextpos = Common::Point(start.x + xl, start.y + yl); if ((retval = driver->drawLine(start, nextpos, color, line_mode, GFX_LINE_STYLE_NORMAL))) { - GFXERROR("Failed to draw partial stippled line (%d,%d) -- (%d,%d)\n", start.x, start.y, nextpos.x, nextpos.y); + error("Failed to draw partial stippled line (%d,%d) -- (%d,%d)", start.x, start.y, nextpos.x, nextpos.y); return retval; } } @@ -787,7 +771,6 @@ static int _gfxop_draw_line_clipped(GfxState *state, Common::Point start, Common int retval; int skipone = (start.x ^ end.y) & 1; // Used for simulated line stippling - BASIC_CHECKS(GFX_FATAL); _gfxop_full_pointer_refresh(state); // First, make sure that the line is normalized @@ -813,7 +796,7 @@ static int _gfxop_draw_line_clipped(GfxState *state, Common::Point start, Common } if ((retval = state->driver->drawLine(start, end, color, line_mode, line_style))) { - GFXERROR("Failed to draw line (%d,%d) -- (%d,%d)\n", start.x, start.y, end.x, end.y); + error("Failed to draw line (%d,%d) -- (%d,%d)", start.x, start.y, end.x, end.y); return retval; } @@ -824,7 +807,6 @@ int gfxop_draw_line(GfxState *state, Common::Point start, Common::Point end, gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style) { int xfact, yfact; - BASIC_CHECKS(GFX_FATAL); _gfxop_add_dirty_x(state, gfx_rect(start.x, start.y, end.x - start.x, end.y - start.y)); xfact = state->driver->getMode()->xfact; @@ -855,7 +837,6 @@ int gfxop_draw_rectangle(GfxState *state, rect_t rect, gfx_color_t color, gfx_li Common::Point upper_left_u, upper_right_u, lower_left_u, lower_right_u; Common::Point upper_left, upper_right, lower_left, lower_right; - BASIC_CHECKS(GFX_FATAL); _gfxop_full_pointer_refresh(state); xfact = state->driver->getMode()->xfact; @@ -889,7 +870,7 @@ int gfxop_draw_rectangle(GfxState *state, rect_t rect, gfx_color_t color, gfx_li #undef PARTIAL_LINE if (retval) { - GFXERROR("Failed to draw rectangle (%d,%d)+(%d,%d)\n", rect.x, rect.y, rect.width, rect.height); + error("Failed to draw rectangle (%d,%d)+(%d,%d)", rect.x, rect.y, rect.width, rect.height); return retval; } @@ -902,11 +883,10 @@ int gfxop_draw_rectangle(GfxState *state, rect_t rect, gfx_color_t color, gfx_li int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t color2, gfx_box_shade_t shade_type) { GfxDriver *drv = state->driver; int reverse = 0; // switch color1 and color2 - float mod_offset = 0.0, mod_breadth = 1.0; // 0.0 to 1.0: Color adjustment + float mod_offset = 0.0f, mod_breadth = 1.0f; // 0.0 to 1.0: Color adjustment gfx_rectangle_fill_t driver_shade_type; rect_t new_box; - BASIC_CHECKS(GFX_FATAL); _gfxop_full_pointer_refresh(state); shade_type = GFX_BOX_SHADE_FLAT; @@ -959,7 +939,7 @@ int gfxop_draw_box(GfxState *state, rect_t box, gfx_color_t color1, gfx_color_t break; default: - GFXERROR("Invalid shade type: %d\n", shade_type); + error("Invalid shade type: %d", shade_type); return GFX_ERROR; } @@ -1020,7 +1000,7 @@ static int _gfxop_buffer_propagate_box(GfxState *state, rect_t box, gfx_buffer_t return GFX_OK; if ((err = state->driver->update(box, Common::Point(box.x, box.y), buffer))) { - GFXERROR("Error occured while updating region (%d,%d,%d,%d) in buffer %d\n", box.x, box.y, box.width, box.height, buffer); + error("Error occured while updating region (%d,%d,%d,%d) in buffer %d", box.x, box.y, box.width, box.height, buffer); return err; } @@ -1030,7 +1010,6 @@ static int _gfxop_buffer_propagate_box(GfxState *state, rect_t box, gfx_buffer_t extern int sci0_palette; int gfxop_clear_box(GfxState *state, rect_t box) { - BASIC_CHECKS(GFX_FATAL); _gfxop_full_pointer_refresh(state); _gfxop_add_dirty(state, box); DDIRTY(stderr, "[] clearing box %d %d %d %d\n", GFX_PRINT_RECT(box)); @@ -1077,11 +1056,7 @@ int gfxop_set_visible_map(GfxState *state, gfx_map_mask_t visible_map) { } int gfxop_update(GfxState *state) { - int retval; - - BASIC_CHECKS(GFX_FATAL); - - retval = _gfxop_clear_dirty_rec(state, state->_dirtyRects); + int retval = _gfxop_clear_dirty_rec(state, state->_dirtyRects); if (state->fullscreen_override) { // We've been asked to re-draw the active full-screen image, essentially. @@ -1092,7 +1067,7 @@ int gfxop_update(GfxState *state) { } if (retval) { - GFXERROR("Clearing the dirty rectangles failed!\n"); + error("Clearing the dirty rectangles failed"); } if (state->tag_mode) { @@ -1107,8 +1082,6 @@ int gfxop_update(GfxState *state) { } int gfxop_update_box(GfxState *state, rect_t box) { - BASIC_CHECKS(GFX_FATAL); - if (state->disable_dirty) _gfxop_update_box(state, box); else @@ -1118,15 +1091,12 @@ int gfxop_update_box(GfxState *state, rect_t box) { } int gfxop_enable_dirty_frames(GfxState *state) { - BASIC_CHECKS(GFX_ERROR); state->disable_dirty = 0; return GFX_OK; } int gfxop_disable_dirty_frames(GfxState *state) { - BASIC_CHECKS(GFX_ERROR); - state->disable_dirty = 1; return GFX_OK; @@ -1135,8 +1105,6 @@ int gfxop_disable_dirty_frames(GfxState *state) { // Pointer and IO ops int gfxop_sleep(GfxState *state, uint32 msecs) { - BASIC_CHECKS(GFX_FATAL); - uint32 time; const uint32 wakeup_time = g_system->getMillis() + msecs; @@ -1159,8 +1127,6 @@ int gfxop_sleep(GfxState *state, uint32 msecs) { } static int _gfxop_set_pointer(GfxState *state, gfx_pixmap_t *pxm, Common::Point *hotspot) { - BASIC_CHECKS(GFX_FATAL); - // FIXME: We may have to store this pxm somewhere, as the global palette // may change when a new PIC is loaded. The cursor has to be regenerated // from this pxm at that point. (An alternative might be to ensure the @@ -1173,8 +1139,6 @@ static int _gfxop_set_pointer(GfxState *state, gfx_pixmap_t *pxm, Common::Point } int gfxop_set_pointer_cursor(GfxState *state, int nr) { - BASIC_CHECKS(GFX_FATAL); - if (nr == GFXOP_NO_POINTER) return _gfxop_set_pointer(state, NULL, NULL); @@ -1190,8 +1154,6 @@ int gfxop_set_pointer_cursor(GfxState *state, int nr) { } int gfxop_set_pointer_view(GfxState *state, int nr, int loop, int cel, Common::Point *hotspot) { - BASIC_CHECKS(GFX_FATAL); - int real_loop = loop; int real_cel = cel; // FIXME: For now, don't palettize pointers @@ -1220,8 +1182,6 @@ int gfxop_set_pointer_view(GfxState *state, int nr, int loop, int cel, Common::P } int gfxop_set_pointer_position(GfxState *state, Common::Point pos) { - BASIC_CHECKS(GFX_ERROR); - state->pointer_pos = pos; if (pos.x > 320 || pos.y > 200) { @@ -1418,8 +1378,9 @@ static sci_event_t scummvm_get_event(GfxDriver *drv) { // Debug console if (ev.kbd.flags == Common::KBD_CTRL && ev.kbd.keycode == Common::KEYCODE_d) { // Open debug console - ((Sci::SciEngine*)g_engine)->getDebugger()->attach(); - ((Sci::SciEngine*)g_engine)->getDebugger()->onFrame(); + Console *con = ((Sci::SciEngine*)g_engine)->getSciDebugger(); + con->attach(); + con->onFrame(); // Clear keyboard event input.type = SCI_EVT_NONE; @@ -1547,10 +1508,9 @@ static sci_event_t scummvm_get_event(GfxDriver *drv) { } sci_event_t gfxop_get_event(GfxState *state, unsigned int mask) { - sci_event_t error_event = { SCI_EVT_ERROR, 0, 0, 0 }; + //sci_event_t error_event = { SCI_EVT_ERROR, 0, 0, 0 }; sci_event_t event = { 0, 0, 0, 0 }; - BASIC_CHECKS(error_event); _gfxop_full_pointer_refresh(state); // Update the screen here, since it's called very often @@ -1613,8 +1573,6 @@ int gfxop_lookup_view_get_loops(GfxState *state, int nr) { int loop = 0, cel = 0; gfxr_view_t *view = NULL; - BASIC_CHECKS(GFX_ERROR); - view = state->gfxResMan->getView(nr, &loop, &cel, 0); if (!view) { @@ -1629,8 +1587,6 @@ int gfxop_lookup_view_get_cels(GfxState *state, int nr, int loop) { int real_loop = loop, cel = 0; gfxr_view_t *view = NULL; - BASIC_CHECKS(GFX_ERROR); - view = state->gfxResMan->getView(nr, &real_loop, &cel, 0); if (!view) { @@ -1644,8 +1600,6 @@ int gfxop_lookup_view_get_cels(GfxState *state, int nr, int loop) { } int gfxop_check_cel(GfxState *state, int nr, int *loop, int *cel) { - BASIC_CHECKS(GFX_ERROR); - gfxr_view_t *testView = state->gfxResMan->getView(nr, loop, cel, 0); if (!testView) { @@ -1659,7 +1613,6 @@ int gfxop_check_cel(GfxState *state, int nr, int *loop, int *cel) { int gfxop_overflow_cel(GfxState *state, int nr, int *loop, int *cel) { int loop_v = *loop; int cel_v = *cel; - BASIC_CHECKS(GFX_ERROR); gfxr_view_t *testView = state->gfxResMan->getView(nr, &loop_v, &cel_v, 0); @@ -1681,7 +1634,6 @@ int gfxop_overflow_cel(GfxState *state, int nr, int *loop, int *cel) { int gfxop_get_cel_parameters(GfxState *state, int nr, int loop, int cel, int *width, int *height, Common::Point *offset) { gfxr_view_t *view = NULL; gfx_pixmap_t *pxm = NULL; - BASIC_CHECKS(GFX_ERROR); view = state->gfxResMan->getView(nr, &loop, &cel, 0); @@ -1705,7 +1657,6 @@ static int _gfxop_draw_cel_buffer(GfxState *state, int nr, int loop, int cel, Co gfxr_view_t *view = NULL; gfx_pixmap_t *pxm = NULL; int old_x, old_y; - BASIC_CHECKS(GFX_FATAL); view = state->gfxResMan->getView(nr, &loop, &cel, palette); @@ -1761,8 +1712,10 @@ static int _gfxop_set_pic(GfxState *state) { // FIXME: The _gfxop_install_pixmap call below updates the OSystem palette. // This is too soon, since it causes brief palette corruption until the // screen is updated too. (Possibly related: EngineState::pic_not_valid .) - state->pic->visual_map->palette->forceInto(state->driver->getMode()->palette); - _gfxop_install_pixmap(state->driver, state->pic->visual_map); + if (state->pic->visual_map->palette && state->driver->getMode()->palette) { + state->pic->visual_map->palette->forceInto(state->driver->getMode()->palette); + _gfxop_install_pixmap(state->driver, state->pic->visual_map); + } #ifdef CUSTOM_GRAPHICS_OPTIONS if (state->options->pic0_unscaled) @@ -1776,8 +1729,6 @@ int *gfxop_get_pic_metainfo(GfxState *state) { } int gfxop_new_pic(GfxState *state, int nr, int flags, int default_palette) { - BASIC_CHECKS(GFX_FATAL); - state->gfxResMan->tagResources(); state->tag_mode = 1; state->palette_nr = default_palette; @@ -1790,15 +1741,16 @@ int gfxop_new_pic(GfxState *state, int nr, int flags, int default_palette) { } if (!state->pic || !state->pic_unscaled) { - GFXERROR("Could not retrieve background pic %d!\n", nr); + warning("Could not retrieve background pic %d", nr); if (state->pic) { - GFXERROR(" -- Inconsistency: scaled pic _was_ retrieved!\n"); + warning(" -- Inconsistency: scaled pic _was_ retrieved!"); } if (state->pic_unscaled) { - GFXERROR(" -- Inconsistency: unscaled pic _was_ retrieved!\n"); + warning(" -- Inconsistency: unscaled pic _was_ retrieved!"); } + error("Error occured in gfxop_new_pic()"); state->pic = state->pic_unscaled = NULL; return GFX_ERROR; } @@ -1809,17 +1761,15 @@ int gfxop_new_pic(GfxState *state, int nr, int flags, int default_palette) { } int gfxop_add_to_pic(GfxState *state, int nr, int flags, int default_palette) { - BASIC_CHECKS(GFX_FATAL); - if (!state->pic) { - GFXERROR("Attempt to add to pic with no pic active!\n"); + error("Attempt to add to pic with no pic active"); return GFX_ERROR; } state->pic = state->gfxResMan->addToPic(state->pic_nr, nr, flags, state->palette_nr, default_palette); if (!state->pic) { - GFXERROR("Could not add pic #%d to pic #%d!\n", state->pic_nr, nr); + error("Could not add pic #%d to pic #%d", state->pic_nr, nr); return GFX_ERROR; } @@ -1834,7 +1784,6 @@ int gfxop_add_to_pic(GfxState *state, int nr, int flags, int default_palette) { // replacing GfxState* state parameter with gfx_resstate_t* gfxResourceState and adjust callers accordingly int gfxop_get_font_height(GfxState *state, int font_nr) { gfx_bitmap_font_t *font; - BASIC_CHECKS(GFX_FATAL); font = state->gfxResMan->getFont(font_nr); @@ -1850,12 +1799,10 @@ int gfxop_get_text_params(GfxState *state, int font_nr, const char *text, int ma bool textsplits; gfx_bitmap_font_t *font; - BASIC_CHECKS(GFX_FATAL); - font = state->gfxResMan->getFont(font_nr); if (!font) { - GFXERROR("Attempt to calculate text size with invalid font #%d\n", font_nr); + error("Attempt to calculate text size with invalid font #%d", font_nr); *width = *height = 0; return GFX_ERROR; } @@ -1868,7 +1815,7 @@ int gfxop_get_text_params(GfxState *state, int font_nr, const char *text, int ma #endif if (!textsplits) { - GFXERROR("Could not calculate text size!"); + error("Could not calculate text size"); *width = *height = 0; return GFX_ERROR; } @@ -1884,21 +1831,20 @@ TextHandle *gfxop_new_text(GfxState *state, int font_nr, const Common::String &t TextHandle *handle; gfx_bitmap_font_t *font; int err = 0; - BASIC_CHECKS(NULL); // mapping text colors to palette err |= gfxop_set_color(state, &color1, color1); err |= gfxop_set_color(state, &color2, color2); err |= gfxop_set_color(state, &bg_color, bg_color); if (err) { - GFXERROR("Unable to set up colors"); + error("Unable to set up colors"); return NULL; } font = state->gfxResMan->getFont(font_nr); if (!font) { - GFXERROR("Attempt to draw text with invalid font #%d\n", font_nr); + error("Attempt to draw text with invalid font #%d", font_nr); return NULL; } @@ -1920,7 +1866,7 @@ TextHandle *gfxop_new_text(GfxState *state, int font_nr, const Common::String &t #endif if (!result) { - GFXERROR("Could not calculate text parameters in font #%d\n", font_nr); + error("Could not calculate text parameters in font #%d", font_nr); delete handle; return NULL; } @@ -1941,7 +1887,7 @@ TextHandle *gfxop_new_text(GfxState *state, int font_nr, const Common::String &t (bg_color.mask & GFX_MASK_VISUAL) ? &bg_color.visual : NULL); if (!handle->text_pixmaps[i]) { - GFXERROR("Failed to draw text pixmap for line %d/%d\n", i, handle->lines.size()); + error("Failed to draw text pixmap for line %d/%d", i, handle->lines.size()); delete handle; return NULL; } @@ -1956,8 +1902,6 @@ TextHandle *gfxop_new_text(GfxState *state, int font_nr, const Common::String &t } int gfxop_free_text(GfxState *state, TextHandle *handle) { - BASIC_CHECKS(GFX_ERROR); - delete handle; return GFX_OK; @@ -1982,11 +1926,10 @@ TextHandle::~TextHandle() { int gfxop_draw_text(GfxState *state, TextHandle *handle, rect_t zone) { int line_height; rect_t pos; - BASIC_CHECKS(GFX_FATAL); _gfxop_full_pointer_refresh(state); if (!handle) { - GFXERROR("Attempt to draw text with NULL handle!\n"); + error("Attempt to draw text with NULL handle"); return GFX_ERROR; } @@ -2015,7 +1958,7 @@ int gfxop_draw_text(GfxState *state, TextHandle *handle, rect_t zone) { break; default: - GFXERROR("Invalid vertical alignment %d!\n", handle->valign); + error("Invalid vertical alignment %d", handle->valign); return GFX_FATAL; // Internal error... } @@ -2031,7 +1974,7 @@ int gfxop_draw_text(GfxState *state, TextHandle *handle, rect_t zone) { #endif } if (!pxm) { - GFXERROR("Could not find text pixmap %d/%d\n", i, handle->lines.size()); + error("Could not find text pixmap %d/%d", i, handle->lines.size()); return GFX_ERROR; } @@ -2051,7 +1994,7 @@ int gfxop_draw_text(GfxState *state, TextHandle *handle, rect_t zone) { break; default: - GFXERROR("Invalid vertical alignment %d!\n", handle->valign); + error("Invalid vertical alignment %d", handle->valign); return GFX_FATAL; // Internal error... } @@ -2071,7 +2014,6 @@ int gfxop_draw_text(GfxState *state, TextHandle *handle, rect_t zone) { gfx_pixmap_t *gfxop_grab_pixmap(GfxState *state, rect_t area) { gfx_pixmap_t *pixmap = NULL; rect_t resultzone; // Ignored for this application - BASIC_CHECKS(NULL); _gfxop_full_pointer_refresh(state); _gfxop_scale_rect(&area, state->driver->getMode()); @@ -2083,10 +2025,9 @@ gfx_pixmap_t *gfxop_grab_pixmap(GfxState *state, rect_t area) { int gfxop_draw_pixmap(GfxState *state, gfx_pixmap_t *pxm, rect_t zone, Common::Point pos) { rect_t target; - BASIC_CHECKS(GFX_ERROR); if (!pxm) { - GFXERROR("Attempt to draw NULL pixmap!\n"); + error("Attempt to draw NULL pixmap"); return GFX_ERROR; } @@ -2097,7 +2038,7 @@ int gfxop_draw_pixmap(GfxState *state, gfx_pixmap_t *pxm, rect_t zone, Common::P _gfxop_add_dirty(state, target); if (!pxm) { - GFXERROR("Attempt to draw_pixmap with pxm=NULL\n"); + error("Attempt to draw_pixmap with pxm=NULL"); return GFX_ERROR; } @@ -2109,7 +2050,6 @@ int gfxop_draw_pixmap(GfxState *state, gfx_pixmap_t *pxm, rect_t zone, Common::P } int gfxop_free_pixmap(GfxState *state, gfx_pixmap_t *pxm) { - BASIC_CHECKS(GFX_ERROR); gfx_free_pixmap(pxm); return GFX_OK; } diff --git a/engines/sci/gfx/operations.h b/engines/sci/gfx/operations.h index 491b485da0..b9a16d4a27 100644 --- a/engines/sci/gfx/operations.h +++ b/engines/sci/gfx/operations.h @@ -135,7 +135,6 @@ struct GfxState { * Initializes a graphics mode. * * @param[in] version The interpreter version - * @param[in] isVGA true if using VGA resolution * @param[in] state The state to initialize * @param[in] xfact Horizontal scale factor * @param[in] yfact Vertical scale factors @@ -147,7 +146,7 @@ struct GfxState { * is unavailable, or GFX_FATAL if the graphics driver * is unable to provide any useful graphics support */ -int gfxop_init(int version, bool isVGA, GfxState *state, gfx_options_t *options, +int gfxop_init(int version, GfxState *state, gfx_options_t *options, ResourceManager *resManager, int xfact = 1, int yfact = 1, gfx_color_mode_t bpp = GFX_COLOR_MODE_INDEX); diff --git a/engines/sci/gfx/res_cursor.cpp b/engines/sci/gfx/res_cursor.cpp index f78134536c..9b3e64b8d5 100644 --- a/engines/sci/gfx/res_cursor.cpp +++ b/engines/sci/gfx/res_cursor.cpp @@ -53,7 +53,7 @@ gfx_pixmap_t *gfxr_draw_cursor(int id, byte *resource, int size, bool isSci01) { colors[3] = 2; if (size != CURSOR_RESOURCE_SIZE) { - GFXERROR("Expected resource size of %d, but found %d\n", CURSOR_RESOURCE_SIZE, size); + error("Expected resource size of %d, but found %d", CURSOR_RESOURCE_SIZE, size); return NULL; } diff --git a/engines/sci/gfx/res_font.cpp b/engines/sci/gfx/res_font.cpp index 7330df7441..cddbade845 100644 --- a/engines/sci/gfx/res_font.cpp +++ b/engines/sci/gfx/res_font.cpp @@ -44,12 +44,12 @@ static int calc_char(byte *dest, int total_width, int total_height, byte *src, i src += 2; if ((width >> 3) > total_width || height > total_height) { - GFXERROR("Weird character: width=%d/%d, height=%d/%d\n", width, total_width, height, total_height); + error("Weird character: width=%d/%d, height=%d/%d", width, total_width, height, total_height); return GFX_ERROR; } if (byte_width * height + 2 > size) { - GFXERROR("Character extends to %d of %d allowed bytes\n", byte_width * height + 2, size); + error("Character extends to %d of %d allowed bytes", byte_width * height + 2, size); return GFX_ERROR; } @@ -71,7 +71,7 @@ gfx_bitmap_font_t *gfxr_read_font(int id, byte *resource, int size) { ++font_counter; if (size < 6) { - GFXERROR("Font %04x size is %d- this is a joke, right?\n", id, size); + error("Font %04x size is %d", id, size); gfxr_free_font(font); return NULL; } @@ -81,15 +81,15 @@ gfx_bitmap_font_t *gfxr_read_font(int id, byte *resource, int size) { if (chars_nr < 0 || chars_nr > 256 || max_height < 0) { if (chars_nr < 0 || chars_nr > 256) - GFXERROR("Font %04x: Invalid number of characters: %d\n", id, chars_nr); + error("Font %04x: Invalid number of characters: %d", id, chars_nr); if (max_height < 0) - GFXERROR("Font %04x: Invalid font height: %d\n", id, max_height); + error("Font %04x: Invalid font height: %d", id, max_height); gfxr_free_font(font); return NULL; } if (size < 6 + chars_nr * 2) { - GFXERROR("Font %04x: Insufficient space for %d characters in font\n", id, chars_nr); + error("Font %04x: Insufficient space for %d characters in font", id, chars_nr); gfxr_free_font(font); return NULL; } @@ -101,7 +101,7 @@ gfx_bitmap_font_t *gfxr_read_font(int id, byte *resource, int size) { int offset = READ_LE_UINT16(resource + (i << 1) + 6); if (offset >= size) { - GFXERROR("Font %04x: Error: Character 0x%02x is at offset 0x%04x (beyond 0x%04x)\n", id, i, offset, size); + error("Font %04x: Error: Character 0x%02x is at offset 0x%04x (beyond 0x%04x)", id, i, offset, size); gfxr_free_font(font); return NULL; } @@ -130,7 +130,7 @@ gfx_bitmap_font_t *gfxr_read_font(int id, byte *resource, int size) { int offset = READ_LE_UINT16(resource + (i << 1) + 6); if (calc_char(font->data + (font->char_size * i), font->row_size, max_height, resource + offset, size - offset)) { - GFXERROR("Problem occured in font %04x, char %d/%d\n", id, i, chars_nr); + error("Problem occured in font %04x, char %d/%d", id, i, chars_nr); gfxr_free_font(font); return NULL; } diff --git a/engines/sci/gfx/res_pal.cpp b/engines/sci/gfx/res_pal.cpp index 0acc27a9b1..d686220453 100644 --- a/engines/sci/gfx/res_pal.cpp +++ b/engines/sci/gfx/res_pal.cpp @@ -44,6 +44,11 @@ Palette *gfxr_read_pal11(int id, byte *resource, int size) { int entry_size = (format == SCI_PAL_FORMAT_VARIABLE_FLAGS) ? 4 : 3; byte *pal_data = resource + 37; int _colors_nr = READ_LE_UINT16(resource + 29); + + // Happens at the beginning of Pepper + if (_colors_nr > 256) + return NULL; + Palette *retval = new Palette(_colors_nr + start_color); int i; @@ -76,7 +81,7 @@ Palette *gfxr_read_pal1(int id, byte *resource, int size) { unsigned int colors[MAX_COLORS] = {0}; if (size < PALETTE_START + 4) { - GFXERROR("Palette resource too small in %04x\n", id); + error("Palette resource too small in %04x", id); return NULL; } @@ -88,7 +93,7 @@ Palette *gfxr_read_pal1(int id, byte *resource, int size) { } if (counter < MAX_COLORS) { - GFXERROR("Palette %04x ends prematurely\n", id); + error("SCI1 palette %04x ends prematurely", id); return NULL; } @@ -117,7 +122,7 @@ Palette *gfxr_read_pal1_amiga(Common::File &file) { b2 = file.readByte(); if (b1 == EOF || b2 == EOF) { - GFXERROR("Palette file ends prematurely\n"); + error("Amiga palette file ends prematurely"); return NULL; } diff --git a/engines/sci/gfx/res_pic.cpp b/engines/sci/gfx/res_pic.cpp index 5ee2665b50..e7b34976b0 100644 --- a/engines/sci/gfx/res_pic.cpp +++ b/engines/sci/gfx/res_pic.cpp @@ -400,7 +400,7 @@ enum { #ifdef GFXR_DEBUG_PIC0 -#define p0printf sciprintf +#define p0printf printf #else void do_nothing(...) { } #define p0printf do_nothing @@ -1197,7 +1197,7 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, pal += default_palette; if (pal >= GFXR_PIC0_NUM_PALETTES) { - GFXERROR("Attempt to access invalid palette %d\n", pal); + error("Attempt to access invalid palette %d", pal); return; } @@ -1442,7 +1442,7 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, index %= GFXR_PIC0_PALETTE_SIZE; if (pal >= GFXR_PIC0_NUM_PALETTES) { - GFXERROR("Attempt to write to invalid palette %d\n", pal); + error("Attempt to write to invalid palette %d", pal); return; } palette[pal][index] = *(resource + pos++); @@ -1453,7 +1453,7 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, p0printf("Set palette @%d\n", pos); pal = *(resource + pos++); if (pal >= GFXR_PIC0_NUM_PALETTES) { - GFXERROR("Attempt to write to invalid palette %d\n", pal); + error("Attempt to write to invalid palette %d", pal); return; } @@ -1527,7 +1527,7 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, // *if it's not for some reason, we should die if (view->palette && view->palette->isShared() && !sci1) { - sciprintf("gfx_draw_pic0(): can't set a non-static palette for an embedded view!\n"); + warning("gfx_draw_pic0(): can't set a non-static palette for an embedded view"); } // For SCI0, use special color mapping to copy the low @@ -1602,7 +1602,7 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, if (!pic->priorityTable) { pic->priorityTable = (int*)malloc(16 * sizeof(int)); } else { - GFXERROR("pic->priorityTable is not NULL (%p); possible memory corruption", (void *)pic->priorityTable); + error("pic->priorityTable is not NULL (%p); possible memory corruption", (void *)pic->priorityTable); } pri_table = pic->priorityTable; @@ -1614,7 +1614,7 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, } default: - sciprintf("%s L%d: Warning: Unknown opx %02x\n", __FILE__, __LINE__, opx); + warning("gfxr_draw_pic01(): Unknown opx %02x", opx); return; } goto end_op_loop; @@ -1714,7 +1714,7 @@ void gfxr_dither_pic0(gfxr_pic_t *pic, int dmode, int pattern) { break; default: - GFXERROR("Invalid dither mode %d!\n", dmode); + error("Invalid dither mode %d", dmode); return; } diff --git a/engines/sci/gfx/res_view.cpp b/engines/sci/gfx/res_view.cpp index b30c57f38d..d484136f8e 100644 --- a/engines/sci/gfx/res_view.cpp +++ b/engines/sci/gfx/res_view.cpp @@ -76,7 +76,7 @@ gfx_pixmap_t *gfxr_draw_cel0(int id, int loop, int cel, byte *resource, int size if (xl <= 0 || yl <= 0) { gfx_free_pixmap(retval); - GFXERROR("View %02x:(%d/%d) has invalid xl=%d or yl=%d\n", id, loop, cel, xl, yl); + error("View %02x:(%d/%d) has invalid xl=%d or yl=%d", id, loop, cel, xl, yl); return NULL; } @@ -123,7 +123,7 @@ gfx_pixmap_t *gfxr_draw_cel0(int id, int loop, int cel, byte *resource, int size color = retval->color_key; if (writepos + count > pixmap_size) { - GFXERROR("View %02x:(%d/%d) writes RLE data over its designated end at rel. offset 0x%04x\n", id, loop, cel, pos); + error("View %02x:(%d/%d) writes RLE data over its designated end at rel. offset 0x%04x", id, loop, cel, pos); return NULL; } @@ -135,7 +135,7 @@ gfx_pixmap_t *gfxr_draw_cel0(int id, int loop, int cel, byte *resource, int size return retval; } -gfxr_view_t *gfxr_draw_view0(int id, byte *resource, int size, int palette) { +gfxr_view_t *getEGAView(int id, byte *resource, int size, int palette) { int i; gfxr_view_t *view; int mirror_bitpos = 1; @@ -143,7 +143,7 @@ gfxr_view_t *gfxr_draw_view0(int id, byte *resource, int size, int palette) { int palette_ofs = READ_LE_UINT16(resource + 6); if (size < V0_FIRST_LOOP_OFFSET + 8) { - GFXERROR("Attempt to draw empty view %04x\n", id); + error("Attempt to draw empty view %04x", id); return NULL; } @@ -166,7 +166,7 @@ gfxr_view_t *gfxr_draw_view0(int id, byte *resource, int size, int palette) { } if (view->loops_nr * 2 + V0_FIRST_LOOP_OFFSET > size) { - GFXERROR("View %04x: Not enough space in resource to accomodate for the claimed %d loops\n", id, view->loops_nr); + error("View %04x: Not enough space in resource to accomodate for the claimed %d loops", id, view->loops_nr); free(view); return NULL; } @@ -346,7 +346,7 @@ gfx_pixmap_t *gfxr_draw_cel1(int id, int loop, int cel, int mirrored, byte *reso if (xl <= 0 || yl <= 0) { gfx_free_pixmap(retval); - GFXERROR("View %02x:(%d/%d) has invalid xl=%d or yl=%d\n", id, loop, cel, xl, yl); + error("View %02x:(%d/%d) has invalid xl=%d or yl=%d", id, loop, cel, xl, yl); return NULL; } @@ -365,7 +365,7 @@ gfx_pixmap_t *gfxr_draw_cel1(int id, int loop, int cel, int mirrored, byte *reso return retval; } -gfxr_view_t *gfxr_draw_view1(int id, byte *resource, int size, Palette *static_pal, bool isSci11) { +gfxr_view_t *getVGAView(int id, byte *resource, int size, Palette *static_pal, bool isSci11) { uint16 palOffset = READ_LE_UINT16(resource + V1_PALETTE_OFFSET + (isSci11 ? 2 : 0)); uint16 headerSize = isSci11 ? READ_LE_UINT16(resource + V2_HEADER_SIZE) : 0; byte* seeker = resource + headerSize; diff --git a/engines/sci/module.mk b/engines/sci/module.mk index f2c58bcd8d..bada214b61 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -33,6 +33,7 @@ MODULE_OBJS = \ engine/script.o \ engine/scriptdebug.o \ engine/seg_manager.o \ + engine/static_selectors.o \ engine/stringfrag.o \ engine/state.o \ engine/vm.o \ diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 3c377e8ef2..d99f9f0771 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -42,20 +42,6 @@ namespace Sci { //#define SCI_VERBOSE_RESMGR 1 -const char *sci_version_types[] = { - "SCI version undetermined (Autodetect failed / not run)", - "SCI version 0.xxx", - "SCI version 0.xxx w/ 1.000 compression", - "SCI version 1.000 w/ 0.xxx resource.map", - "SCI version 1.000 w/ special resource.map", - "SCI version 1.000 (early)", - "SCI version 1.000 (late)", - "SCI version 1.001", - "SCI WIN/32" -}; - -const int sci_max_resource_nr[] = {65536, 1000, 2048, 2048, 2048, 65536, 65536, 65536}; - static const char *sci_error_types[] = { "No error", "I/O error", @@ -359,7 +345,7 @@ int ResourceManager::guessSciVersion() { file.close(); if (compression == 3) { - return SCI_VERSION_01_VGA; + return SCI_VERSION_01; } } @@ -383,7 +369,7 @@ int ResourceManager::guessSciVersion() { file.close(); if (compression == 3) { - return SCI_VERSION_01_VGA; + return SCI_VERSION_01; } } @@ -484,9 +470,18 @@ ResourceManager::ResourceManager(int version, int maxMemory) { } else { _mapVersion = detectMapVersion(); _volVersion = detectVolVersion(); + if (_volVersion == 0 && _mapVersion > 0) { + warning("Volume version not detected, but map version has been detected. Setting volume version to map version"); + _volVersion = _mapVersion; + } + + if (_mapVersion == 0 && _volVersion > 0) { + warning("Map version not detected, but volume version has been detected. Setting map version to volume version"); + _mapVersion = _volVersion; + } } - debug("Using resource map version %d %s", _mapVersion, sci_version_types[_mapVersion]); - debug("Using volume version %d %s", _volVersion, sci_version_types[_volVersion]); + debug("Using resource map version %d %s", _mapVersion, versionNames[_mapVersion]); + debug("Using volume version %d %s", _volVersion, versionNames[_volVersion]); scanNewSources(); addInternalSources(); @@ -496,29 +491,22 @@ ResourceManager::ResourceManager(int version, int maxMemory) { switch (_mapVersion) { case SCI_VERSION_0: if (testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB))) { - version = guessSciVersion() ? SCI_VERSION_01_VGA : SCI_VERSION_0; + version = guessSciVersion() ? SCI_VERSION_01 : SCI_VERSION_0; } else if (testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB))) { version = guessSciVersion(); - if (version != SCI_VERSION_01_VGA) { + if (version != SCI_VERSION_01) { version = testResource(ResourceId(kResourceTypeVocab, 912)) ? SCI_VERSION_0 : SCI_VERSION_01; } } else { - version = guessSciVersion() ? SCI_VERSION_01_VGA : SCI_VERSION_0; + version = guessSciVersion() ? SCI_VERSION_01 : SCI_VERSION_0; } break; case SCI_VERSION_01_VGA_ODD: version = _mapVersion; break; - case SCI_VERSION_1: { - Resource *res = testResource(ResourceId(kResourceTypeScript, 0)); - - _sciVersion = version = SCI_VERSION_1_EARLY; - loadResource(res); - - if (res->status == kResStatusNoMalloc) - version = SCI_VERSION_1_LATE; + case SCI_VERSION_1: + _sciVersion = version = SCI_VERSION_1; break; - } case SCI_VERSION_1_1: // No need to handle SCI 1.1 here - it was done in resource_map.cpp version = SCI_VERSION_1_1; @@ -527,6 +515,34 @@ ResourceManager::ResourceManager(int version, int maxMemory) { version = SCI_VERSION_AUTODETECT; } + _isVGA = false; + + // Determine if the game is using EGA graphics or not + if (version == SCI_VERSION_0) { + _isVGA = false; // There is no SCI0 VGA game + } else if (version >= SCI_VERSION_1_1) { + _isVGA = true; // There is no SCI11 EGA game + } else { + // SCI01 or SCI1: EGA games have the second byte of their views set + // to 0, VGA ones to non-zero + int i = 0; + + while (true) { + Resource *res = findResource(ResourceId(kResourceTypeView, i), 0); + if (res) { + _isVGA = (res->data[1] != 0); + break; + } + i++; + } + } + + // Workaround for QFG1 VGA (has SCI 1.1 view data with SCI 1 compression) + if (version == SCI_VERSION_1 && !strcmp(((SciEngine*)g_engine)->getGameID(), "qfg1")) { + debug("Resmgr: Detected QFG1 VGA"); + _isVGA = true; + } + _sciVersion = version; // temporary version printout - should be reworked later switch (_sciVersion) { @@ -536,17 +552,11 @@ ResourceManager::ResourceManager(int version, int maxMemory) { case SCI_VERSION_01: debug("Resmgr: Detected SCI01"); break; - case SCI_VERSION_01_VGA: - debug("Resmgr: Detected SCI01VGA - KQ5 or similar"); - break; case SCI_VERSION_01_VGA_ODD: debug("Resmgr: Detected SCI01VGA - Jones/CD or similar"); break; - case SCI_VERSION_1_EARLY: - debug("Resmgr: Detected SCI1 Early"); - break; - case SCI_VERSION_1_LATE: - debug("Resmgr: Detected SCI1 Late"); + case SCI_VERSION_1: + debug("Resmgr: Detected SCI1"); break; case SCI_VERSION_1_1: debug("Resmgr: Detected SCI1.1"); @@ -560,6 +570,11 @@ ResourceManager::ResourceManager(int version, int maxMemory) { debug("Resmgr: Couldn't determine SCI version"); break; } + + if (_isVGA) + debug("Resmgr: Detected VGA graphic resources"); + else + debug("Resmgr: Detected non-VGA/EGA graphic resources"); } ResourceManager::~ResourceManager() { @@ -581,7 +596,7 @@ ResourceManager::~ResourceManager() { void ResourceManager::removeFromLRU(Resource *res) { if (res->status != kResStatusEnqueued) { - sciprintf("Resmgr: Oops: trying to remove resource that isn't enqueued\n"); + warning("Resmgr: trying to remove resource that isn't enqueued"); return; } _LRU.remove(res); @@ -591,16 +606,15 @@ void ResourceManager::removeFromLRU(Resource *res) { void ResourceManager::addToLRU(Resource *res) { if (res->status != kResStatusAllocated) { - warning("Resmgr: Oops: trying to enqueue resource with state %d", res->status); + warning("Resmgr: trying to enqueue resource with state %d", res->status); return; } _LRU.push_front(res); _memoryLRU += res->size; -#if (SCI_VERBOSE_RESMGR > 1) +#if SCI_VERBOSE_RESMGR debug("Adding %s.%03d (%d bytes) to lru control: %d bytes total", getResourceTypeName(res->type), res->number, res->size, mgr->_memoryLRU); - #endif res->status = kResStatusEnqueued; } @@ -629,7 +643,7 @@ void ResourceManager::freeOldResources() { removeFromLRU(goner); goner->unalloc(); #ifdef SCI_VERBOSE_RESMGR - sciprintf("Resmgr-debug: LRU: Freeing %s.%03d (%d bytes)\n", getResourceTypeName(goner->type), goner->number, goner->size); + printf("Resmgr-debug: LRU: Freeing %s.%03d (%d bytes)\n", getResourceTypeName(goner->type), goner->number, goner->size); #endif } } @@ -648,16 +662,7 @@ Common::List<ResourceId> *ResourceManager::listResources(ResourceType type, int } Resource *ResourceManager::findResource(ResourceId id, bool lock) { - Resource *retval; - - if (id.number >= sci_max_resource_nr[_sciVersion]) { - ResourceId moddedId = ResourceId(id.type, id.number % sci_max_resource_nr[_sciVersion], id.tuple); - sciprintf("[resmgr] Requested invalid resource %s, mapped to %s\n", - id.toString().c_str(), moddedId.toString().c_str()); - id = moddedId; - } - - retval = testResource(id); + Resource *retval = testResource(id); if (!retval) return NULL; @@ -686,7 +691,7 @@ Resource *ResourceManager::findResource(ResourceId id, bool lock) { if (retval->data) return retval; else { - sciprintf("Resmgr: Failed to read %s\n", retval->id.toString().c_str()); + warning("Resmgr: Failed to read %s", retval->id.toString().c_str()); return NULL; } } @@ -711,7 +716,7 @@ void ResourceManager::unlockResource(Resource *res) { int ResourceManager::detectMapVersion() { Common::File file; byte buff[6]; - ResourceSource *rsrc; + ResourceSource *rsrc= 0; for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) { rsrc = *it; @@ -722,7 +727,7 @@ int ResourceManager::detectMapVersion() { } } if (file.isOpen() == false) { - warning("Failed to open resource map file"); + error("Failed to open resource map file"); return SCI_VERSION_AUTODETECT; } // detection @@ -738,32 +743,51 @@ int ResourceManager::detectMapVersion() { } return SCI_VERSION_0; } - // SCI1E/L and some SCI1.1 maps have last directory entry set to 0xFF - // and offset set to filesize - // SCI1 have 6-bytes entries, while SCI1.1 have 5-byte entries - file.seek(1, SEEK_SET); - uint16 off1, off = file.readUint16LE(); - uint16 nEntries = off / 3; - file.seek(1, SEEK_CUR); - file.seek(off - 3, SEEK_SET); - if (file.readByte() == 0xFF && file.readUint16LE() == file.size()) { - file.seek(3, SEEK_SET); - for (int i = 0; i < nEntries; i++) { - file.seek(1, SEEK_CUR); - off1 = file.readUint16LE(); - if ((off1 - off) % 5 && (off1 - off) % 6 == 0) - return SCI_VERSION_1; - if ((off1 - off) % 5 == 0 && (off1 - off) % 6) - return SCI_VERSION_1_1; - off = off1; + + // SCI1 and SCI1.1 maps consist of a fixed 3-byte header, a directory list (3-bytes each) that has one entry + // of id FFh and points to EOF. The actual entries have 6-bytes on SCI1 and 5-bytes on SCI1.1 + byte directoryType = 0; + uint16 directoryOffset = 0; + uint16 lastDirectoryOffset = 0; + uint16 directorySize = 0; + int mapDetected = 0; + file.seek(0, SEEK_SET); + while (!file.eos()) { + directoryType = file.readByte(); + directoryOffset = file.readUint16LE(); + if ((directoryType < 0x80) || ((directoryType > 0xA0) && (directoryType != 0xFF))) + break; + // Offset is above file size? -> definitely not SCI1/SCI1.1 + if (directoryOffset > file.size()) + break; + if (lastDirectoryOffset) { + directorySize = directoryOffset - lastDirectoryOffset; + if ((directorySize % 5) && (directorySize % 6 == 0)) + mapDetected = SCI_VERSION_1; + if ((directorySize % 5 == 0) && (directorySize % 6)) + mapDetected = SCI_VERSION_1_1; } - return SCI_VERSION_1; + if (directoryType==0xFF) { + // FFh entry needs to point to EOF + if (directoryOffset != file.size()) + break; + if (mapDetected) + return mapDetected; + return SCI_VERSION_1; + } + lastDirectoryOffset = directoryOffset; } #ifdef ENABLE_SCI32 // late SCI1.1 and SCI32 maps have last directory entry set to 0xFF // offset set to filesize and 4 more bytes - file.seek(off - 7, SEEK_SET); + + // TODO/FIXME: This code was not updated in r42300, which changed the behavior of this + // function a lot. To make it compile again "off" was changed to the newly introduced + // "lastDirectoryOffset". This is probably not the correct fix, since before r43000 + // the loop above could not prematurely terminate and thus this would always check the + // last directory entry instead of the last checked directory entry. + file.seek(lastDirectoryOffset - 7, SEEK_SET); if (file.readByte() == 0xFF && file.readUint16LE() == file.size()) return SCI_VERSION_32; // TODO : check if there is a difference between these maps #endif @@ -783,7 +807,7 @@ int ResourceManager::detectVolVersion() { } } if (file.isOpen() == false) { - warning("Failed to open volume file"); + error("Failed to open volume file"); return SCI_VERSION_AUTODETECT; } // SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes @@ -874,6 +898,21 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, debug("Patching %s failed - resource type mismatch", source->location_name.c_str()); return; } + + // Fixes SQ5/German, patch file special case logic taken from SCI View disassembly + if (patch_data_offset & 0x80) { + switch (patch_data_offset & 0x7F) { + case 0: + patch_data_offset = 24; + break; + case 1: + patch_data_offset = 2; + break; + default: + warning("Resource patch unsupported special case %X\n", patch_data_offset); + } + } + if (patch_data_offset + 2 >= fsize) { debug("Patching %s failed - patch starting at offset %d can't be in file of size %d", source->location_name.c_str(), patch_data_offset + 2, fsize); @@ -984,6 +1023,9 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { res->file_offset = offset & (((~bMask) << 24) | 0xFFFFFF); res->id = resId; res->source = getVolume(map, offset >> bShift); + if (!res->source) { + warning("Could not get volume for resource %d, VolumeID %d\n", id, offset >> bShift); + } _resMap.setVal(resId, res); } } while (!file.eos()); diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 77c92840ee..b212a36710 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -66,8 +66,6 @@ enum { /* the first critical error number */ }; -#define SCI_VERSION_1 SCI_VERSION_1_EARLY - #define MAX_OPENED_VOLUMES 5 // Max number of simultaneously opened volumes enum ResSourceType { @@ -84,10 +82,6 @@ enum ResSourceType { #define SCI1_RESMAP_ENTRIES_SIZE 6 #define SCI11_RESMAP_ENTRIES_SIZE 5 -extern const char *sci_version_types[]; -extern const int sci_max_resource_nr[]; /**< Highest possible resource numbers */ - - enum ResourceType { kResourceTypeView = 0, kResourceTypePic, @@ -216,6 +210,8 @@ public: int _mapVersion; //!< RESOURCE.MAP version int _volVersion; //!< RESOURCE.0xx version + bool isVGA() const { return _isVGA; } + /** * Creates a new SCI resource manager. * @param version The SCI version to look for; use SCI_VERSION_AUTODETECT @@ -267,6 +263,7 @@ public: void setAudioLanguage(int language); protected: + bool _isVGA; // Used to determine if the game has EGA or VGA graphics int _maxMemory; //!< Config option: Maximum total byte number allocated Common::List<ResourceSource *> _sources; int _memoryLocked; //!< Amount of resource bytes in locked memory diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 9b277b058f..504e38c7c1 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -29,6 +29,7 @@ #include "engines/advancedDetector.h" #include "sci/sci.h" +#include "sci/debug.h" #include "sci/console.h" #include "sci/engine/state.h" @@ -42,14 +43,12 @@ namespace Sci { class GfxDriver; -const char *versionNames[9] = { +const char *versionNames[7] = { "Autodetected", "SCI0", - "SCI01 EGA", - "SCI01 VGA", + "SCI01", "SCI01 VGA ODD", - "SCI1 early", - "SCI1 late", + "SCI1", "SCI1.1", "SCI32" }; @@ -87,6 +86,9 @@ SciEngine::SciEngine(OSystem *syst, const SciGameDescription *desc) Common::addDebugChannel(kDebugLevelDclInflate, "DCL", "DCL inflate debugging"); Common::addDebugChannel(kDebugLevelVM, "VM", "VM debugging"); Common::addDebugChannel(kDebugLevelScripts, "Scripts", "Notifies when scripts are unloaded"); + Common::addDebugChannel(kDebugLevelGC, "GC", "Garbage Collector debugging"); + + _gamestate = 0; printf("SciEngine::SciEngine\n"); } @@ -98,7 +100,10 @@ SciEngine::~SciEngine() { // Remove all of our debug levels here Common::clearAllDebugChannels(); + delete _kernel; + delete _vocabulary; delete _console; + delete _resmgr; } Common::Error SciEngine::run() { @@ -135,6 +140,8 @@ Common::Error SciEngine::run() { return Common::kNoGameDataFoundError; } + _kernel = new Kernel(_resmgr); + _vocabulary = new Vocabulary(_resmgr); script_adjust_opcode_formats(_resmgr->_sciVersion); #if 0 @@ -146,37 +153,16 @@ Common::Error SciEngine::run() { _gamestate = new EngineState(_resmgr, version, flags); // Verify that we haven't got an invalid game detection entry - if (version < SCI_VERSION_1_EARLY) { + if (version < SCI_VERSION_1) { // SCI0/SCI01 - if (flags & GF_SCI1_EGA || - flags & GF_SCI1_LOFSABSOLUTE || - flags & GF_SCI1_NEWDOSOUND) { - error("This game entry is erroneous. It's marked as SCI0/SCI01, but it has SCI1 flags set"); - } - } else if (version >= SCI_VERSION_1_EARLY && version <= SCI_VERSION_1_LATE) { - // SCI1 - - if (flags & GF_SCI0_OLD || - flags & GF_SCI0_OLDGFXFUNCS || - flags & GF_SCI0_OLDGETTIME || - flags & GF_SCI0_SCI1VOCAB) { + } else if (version == SCI_VERSION_1) { + if (flags & GF_SCI0_OLDGETTIME) { error("This game entry is erroneous. It's marked as SCI1, but it has SCI0 flags set"); } } else if (version == SCI_VERSION_1_1 || version == SCI_VERSION_32) { - if (flags & GF_SCI1_EGA || - flags & GF_SCI1_LOFSABSOLUTE || - flags & GF_SCI1_NEWDOSOUND) { - error("This game entry is erroneous. It's marked as SCI1.1/SCI32, but it has SCI1 flags set"); - } - - if (flags & GF_SCI0_OLD || - flags & GF_SCI0_OLDGFXFUNCS || - flags & GF_SCI0_OLDGETTIME || - flags & GF_SCI0_SCI1VOCAB) { + if (flags & GF_SCI0_OLDGETTIME) { error("This game entry is erroneous. It's marked as SCI1.1/SCI32, but it has SCI0 flags set"); } - - // SCI1.1 / SCI32 } else { error ("Unknown SCI version in game entry"); } @@ -223,8 +209,7 @@ Common::Error SciEngine::run() { // Default config ends #endif - bool isVGA = _resmgr->_sciVersion >= SCI_VERSION_01_VGA && !(getFlags() & GF_SCI1_EGA); - if (gfxop_init(_resmgr->_sciVersion, isVGA, &gfx_state, &gfx_options, _resmgr)) { + if (gfxop_init(_resmgr->_sciVersion, &gfx_state, &gfx_options, _resmgr)) { warning("Graphics initialization failed. Aborting..."); return Common::kUnknownError; } @@ -249,14 +234,27 @@ Common::Error SciEngine::run() { delete _gamestate; - delete _resmgr; - gfxop_exit(&gfx_state); return Common::kNoError; } +// Invoked by error() when a severe error occurs GUI::Debugger *SciEngine::getDebugger() { + if (_gamestate) { + ExecStack *xs = &(_gamestate->_executionStack.back()); + xs->addr.pc.offset = scriptState.old_pc_offset; + xs->sp = scriptState.old_sp; + } + + scriptState.runningStep = 0; // Stop multiple execution + scriptState.seeking = kDebugSeekNothing; // Stop special seeks + + return _console; +} + +// Used to obtain the engine's console in order to print messages to it +Console *SciEngine::getSciDebugger() { return _console; } diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 18b1b93a92..886a579799 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -35,6 +35,8 @@ namespace Sci { class Console; struct EngineState; +class Kernel; +class Vocabulary; // our engine debug levels enum kDebugLevels { @@ -49,16 +51,16 @@ enum kDebugLevels { kDebugLevelGfxDriver = 1 << 8, kDebugLevelBaseSetter = 1 << 9, kDebugLevelParser = 1 << 10, - // FIXME: seems that debug level 11 is special (check debugC in common/debug.cpp) - kDebugLevelMenu = 1 << 12, - kDebugLevelSaid = 1 << 13, - kDebugLevelFile = 1 << 14, - kDebugLevelTime = 1 << 15, - kDebugLevelRoom = 1 << 16, - kDebugLevelAvoidPath = 1 << 17, - kDebugLevelDclInflate = 1 << 18, - kDebugLevelVM = 1 << 19, - kDebugLevelScripts = 1 << 20 + kDebugLevelMenu = 1 << 11, + kDebugLevelSaid = 1 << 12, + kDebugLevelFile = 1 << 13, + kDebugLevelTime = 1 << 14, + kDebugLevelRoom = 1 << 15, + kDebugLevelAvoidPath = 1 << 16, + kDebugLevelDclInflate = 1 << 17, + kDebugLevelVM = 1 << 18, + kDebugLevelScripts = 1 << 19, + kDebugLevelGC = 1 << 20 }; struct SciGameDescription { @@ -72,69 +74,21 @@ enum SciGameVersions { SCI_VERSION_AUTODETECT = 0, SCI_VERSION_0 = 1, SCI_VERSION_01 = 2, - SCI_VERSION_01_VGA = 3, - SCI_VERSION_01_VGA_ODD = 4, - SCI_VERSION_1_EARLY = 5, - SCI_VERSION_1_LATE = 6, - SCI_VERSION_1_1 = 7, - SCI_VERSION_32 = 8 + SCI_VERSION_01_VGA_ODD = 3, + SCI_VERSION_1 = 4, + SCI_VERSION_1_1 = 5, + SCI_VERSION_32 = 6 }; -extern const char *versionNames[9]; +extern const char *versionNames[7]; enum SciGameFlags { - /* - ** SCI0 flags - */ - - /* Applies to all versions before 0.000.395 (i.e. KQ4 old, XMAS 1988 and LSL2) - ** Old SCI versions used two word header for script blocks (first word equal - ** to 0x82, meaning of the second one unknown). New SCI versions used one - ** word header. - ** Also, old SCI versions assign 120 degrees to left & right, and 60 to up - ** and down. Later versions use an even 90 degree distribution. - */ - GF_SCI0_OLD = (1 << 0), - - /* Applies to all versions before 0.000.502 - ** Old SCI versions used to interpret the third DrawPic() parameter inversely, - ** with the opposite default value (obviously). - ** Also, they used 15 priority zones from 42 to 200 instead of 14 priority - ** zones from 42 to 190. - */ - GF_SCI0_OLDGFXFUNCS = (1 << 1), + // SCI0 flags /* Applies to all versions before 0.000.629 - ** Older SCI versions had simpler code for GetTime() - */ - GF_SCI0_OLDGETTIME = (1 << 2), - - /* Applies to any game that requires the SCI1 kernel vocab - ** Some games (such as the King's Quest I demo) require the default kernel vocab table. - */ - GF_SCI0_SCI1VOCAB = (1 << 3), - - // ---------------------------------------------------------------------------- - - /* - ** SCI1 flags - */ - - /* - ** Used to distinguish SCI1 EGA games - */ - GF_SCI1_EGA = (1 << 4), - - /* Applies to all SCI1 versions after 1.000.200 - ** In late SCI1 versions, the argument of lofs[as] instructions - ** is absolute rather than relative. - */ - GF_SCI1_LOFSABSOLUTE = (1 << 5), - - /* Applies to all versions from 1.000.510 onwards - ** kDoSound() is different than in earlier SCI1 versions. - */ - GF_SCI1_NEWDOSOUND = (1 << 6) + * Older SCI versions had simpler code for GetTime() + */ + GF_SCI0_OLDGETTIME = (1 << 0) }; class SciEngine : public Engine { @@ -147,6 +101,7 @@ public: virtual Common::Error run(); void pauseEngineIntern(bool pause); virtual GUI::Debugger *getDebugger(); + Console *getSciDebugger(); const char* getGameID() const; int getResourceVersion() const; @@ -154,7 +109,9 @@ public: Common::Language getLanguage() const; Common::Platform getPlatform() const; uint32 getFlags() const; - ResourceManager *getResMgr() { return _resmgr; } + ResourceManager *getResMgr() const { return _resmgr; } + Kernel *getKernel() const { return _kernel; } + Vocabulary *getVocabulary() const { return _vocabulary; } Common::String getSavegameName(int nr) const; Common::String getSavegamePattern() const; @@ -169,6 +126,8 @@ private: const SciGameDescription *_gameDescription; ResourceManager *_resmgr; EngineState *_gamestate; + Kernel *_kernel; + Vocabulary *_vocabulary; Console *_console; }; diff --git a/engines/sci/sfx/core.cpp b/engines/sci/sfx/core.cpp index 9bf7730fc9..95d79b3666 100644 --- a/engines/sci/sfx/core.cpp +++ b/engines/sci/sfx/core.cpp @@ -1130,7 +1130,7 @@ static byte* readSOLAudio(Common::SeekableReadStream *audioStream, uint32 &size, Audio::AudioStream* SfxState::getAudioStream(uint32 number, uint32 volume, int *sampleLen) { Audio::AudioStream *audioStream = 0; - uint32 size; + uint32 size = 0; byte *data = 0; byte flags = 0; Sci::Resource* audioRes; diff --git a/engines/sci/sfx/iterator.cpp b/engines/sci/sfx/iterator.cpp index ad33bc8dfb..dc2979abda 100644 --- a/engines/sci/sfx/iterator.cpp +++ b/engines/sci/sfx/iterator.cpp @@ -27,6 +27,7 @@ #include "common/util.h" +#include "sci/sci.h" #include "sci/sfx/iterator_internal.h" #include "sci/sfx/misc.h" // for sfx_player_tell_synth #include "sci/tools.h" @@ -233,7 +234,7 @@ int BaseSongIterator::parseMidiCommand(byte *buf, int *result, SongIteratorChann channel->state = SI_STATE_DELTA_TIME; channel->total_timepos = channel->loop_timepos; channel->last_cmd = 0xfe; - fprintf(stderr, "Looping song iterator %08lx.\n", ID); + debugC(2, kDebugLevelSound, "Looping song iterator %08lx.\n", ID); return SI_LOOP; } else { channel->state = SI_STATE_FINISHED; @@ -287,15 +288,15 @@ int BaseSongIterator::parseMidiCommand(byte *buf, int *result, SongIteratorChann voices += _polyphony[i]; } - sciprintf("SET_POLYPHONY(%d, %d) for a total of %d voices\n", midi_channel, buf[2], voices); - sciprintf("[iterator-1] DEBUG: Polyphony = [ "); + printf("SET_POLYPHONY(%d, %d) for a total of %d voices\n", midi_channel, buf[2], voices); + printf("[iterator] DEBUG: Polyphony = [ "); for (i = 0; i < self1->_numChannels; i++) - sciprintf("%d ", _polyphony[i]); - sciprintf("]\n"); - sciprintf("[iterator-1] DEBUG: Importance = [ "); + printf("%d ", _polyphony[i]); + printf("]\n"); + printf("[iterator] DEBUG: Importance = [ "); for (i = 0; i < self1->_numChannels; i++) - sciprintf("%d ", _importance[i]); - sciprintf("]\n"); + printf("%d ", _importance[i]); + printf("]\n"); } #endif break; @@ -304,7 +305,7 @@ int BaseSongIterator::parseMidiCommand(byte *buf, int *result, SongIteratorChann break; case SCI_MIDI_CHANNEL_MUTE: - sciprintf("CHANNEL_MUTE(%d, %d)\n", midi_channel, buf[2]); + warning("CHANNEL_MUTE(%d, %d)", midi_channel, buf[2]); break; case SCI_MIDI_HOLD: { @@ -379,7 +380,7 @@ int BaseSongIterator::processMidi(byte *buf, int *result, channel->state = SI_STATE_FINISHED; delay = (size * 50 + format.rate - 1) / format.rate; /* number of ticks to completion*/ - fprintf(stderr, "delaying %d ticks\n", delay); + debugC(2, kDebugLevelSound, "delaying %d ticks\n", delay); return delay; } @@ -523,7 +524,7 @@ static int _sci0_get_pcm_data(Sci0SongIterator *self, } static Audio::AudioStream *makeStream(byte *data, int size, sfx_pcm_config_t conf) { - printf("Playing PCM data of size %d, rate %d\n", size, conf.rate); + debugC(2, kDebugLevelSound, "Playing PCM data of size %d, rate %d\n", size, conf.rate); // Duplicate the data byte *sound = (byte *)malloc(size); @@ -563,7 +564,7 @@ SongIterator *Sci0SongIterator::handleMessage(Message msg) { case _SIMSG_BASEMSG_PRINT: print_tabs_id(msg._arg.i, ID); - fprintf(stderr, "SCI0: dev=%d, active-chan=%d, size=%d, loops=%d\n", + debugC(2, kDebugLevelSound, "SCI0: dev=%d, active-chan=%d, size=%d, loops=%d\n", _deviceId, _numActiveChannels, _data.size(), _loops); break; @@ -680,7 +681,7 @@ int Sci1SongIterator::initSample(const int offset) { CHECK_FOR_END_ABSOLUTE((uint)offset + 10); if (_data[offset + 1] != 0) - sciprintf("[iterator-1] In sample at offset 0x04x: Byte #1 is %02x instead of zero\n", + warning("[iterator-1] In sample at offset 0x04x: Byte #1 is %02x instead of zero", _data[offset + 1]); rate = (int16)READ_LE_UINT16(_data.begin() + offset + 2); @@ -739,9 +740,7 @@ int Sci1SongIterator::initSong() { } if (_data[offset] == 0xff) { - sciprintf("[iterator-1] Song does not support" - " hardware 0x%02x\n", - _deviceId); + warning("[iterator] Song does not support hardware 0x%02x", _deviceId); return 1; } @@ -765,16 +764,18 @@ int Sci1SongIterator::initSong() { } else { /* Regular MIDI channel */ if (_numChannels >= MIDI_CHANNELS) { - sciprintf("[iterator-1] Warning: Song has more than %d channels, cutting them off\n", + warning("[iterator] Song has more than %d channels, cutting them off", MIDI_CHANNELS); break; /* Scan for remaining samples */ } else { int channel_nr = _data[track_offset] & 0xf; SongIteratorChannel &channel = _channels[_numChannels++]; + /* if (_data[track_offset] & 0xf0) printf("Channel %d has mapping bits %02x\n", channel_nr, _data[track_offset] & 0xf0); + */ // Add 2 to skip over header bytes */ channel.init(channel_nr, track_offset + 2, track_offset + end); @@ -801,8 +802,8 @@ int Sci1SongIterator::initSong() { for (Common::List<Sci1Sample>::iterator seeker = _samples.begin(); seeker != _samples.end(); ++seeker) { int prev_last_time = last_time; - sciprintf("[iterator-1] Detected sample: %d Hz, %d bytes at time %d\n", - seeker->format.rate, seeker->size, seeker->delta); + //printf("[iterator] Detected sample: %d Hz, %d bytes at time %d\n", + // seeker->format.rate, seeker->size, seeker->delta); last_time = seeker->delta; seeker->delta -= prev_last_time; } @@ -884,8 +885,7 @@ Audio::AudioStream *Sci1SongIterator::getAudioStream() { int Sci1SongIterator::nextCommand(byte *buf, int *result) { if (!_initialised) { - sciprintf("[iterator-1] DEBUG: Initialising for %d\n", - _deviceId); + //printf("[iterator] DEBUG: Initialising for %d\n", _deviceId); _initialised = true; if (initSong()) return SI_FINISHED; @@ -981,7 +981,7 @@ SongIterator *Sci1SongIterator::handleMessage(Message msg) { playmask |= _channels[i].playmask; print_tabs_id(msg._arg.i, ID); - fprintf(stderr, "SCI1: chan-nr=%d, playmask=%04x\n", + debugC(2, kDebugLevelSound, "SCI1: chan-nr=%d, playmask=%04x\n", _numChannels, playmask); } break; @@ -1010,7 +1010,7 @@ SongIterator *Sci1SongIterator::handleMessage(Message msg) { ; if (_deviceId == 0xff) { - sciprintf("[iterator-1] Warning: Device %d(%d) not supported", + warning("[iterator] Device %d(%d) not supported", msg._arg.i & 0xff, sfx_pcm_available()); } if (_initialised) { @@ -1143,7 +1143,7 @@ public: SongIterator *CleanupSongIterator::handleMessage(Message msg) { if (msg._class == _SIMSG_BASEMSG_PRINT && msg._type == _SIMSG_BASEMSG_PRINT) { print_tabs_id(msg._arg.i, ID); - fprintf(stderr, "CLEANUP\n"); + debugC(2, kDebugLevelSound, "CLEANUP\n"); } return NULL; @@ -1164,6 +1164,43 @@ int CleanupSongIterator::nextCommand(byte *buf, int *result) { return SI_FINISHED; } +/**********************/ +/*-- Timer iterator --*/ +/**********************/ +TimerSongIterator::TimerSongIterator(int delta) + : _delta(delta) { +} + +int TimerSongIterator::nextCommand(byte *buf, int *result) { + if (_delta) { + int d = _delta; + _delta = 0; + return d; + } + return SI_FINISHED; +} + +SongIterator *TimerSongIterator::handleMessage(Message msg) { + return NULL; +} + +int TimerSongIterator::getTimepos() { + return 0; +} + +Audio::AudioStream *TimerSongIterator::getAudioStream() { + return NULL; +} + +SongIterator *TimerSongIterator::clone(int delta) { + TimerSongIterator *newit = new TimerSongIterator(*this); + return newit; +} + +SongIterator *new_timer_iterator(int delta) { + return new TimerSongIterator(delta); +} + /**********************************/ /*-- Fast-forward song iterator --*/ /**********************************/ @@ -1209,7 +1246,7 @@ SongIterator *FastForwardSongIterator::handleMessage(Message msg) { if (msg._class == _SIMSG_BASE && msg._type == _SIMSG_BASEMSG_PRINT) { print_tabs_id(msg._arg.i, ID); - fprintf(stderr, "FASTFORWARD:\n"); + debugC(2, kDebugLevelSound, "FASTFORWARD:\n"); msg._arg.i++; } @@ -1269,6 +1306,14 @@ static void song_iterator_remove_death_listener(SongIterator *it, TeeSongIterato } } +static void song_iterator_transfer_death_listeners(SongIterator *it, SongIterator *it_from) { + for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i) { + if (it_from->_deathListeners[i]) + song_iterator_add_death_listener(it, it_from->_deathListeners[i]); + it_from->_deathListeners[i] = 0; + } +} + static void songit_tee_death_notification(TeeSongIterator *self, SongIterator *corpse) { if (corpse == self->_children[TEE_LEFT].it) { self->_status &= ~TEE_LEFT_ACTIVE; @@ -1505,12 +1550,16 @@ SongIterator *TeeSongIterator::handleMessage(Message msg) { delete _children[TEE_LEFT].it; _children[TEE_LEFT].it = 0; old_it = _children[TEE_RIGHT].it; + song_iterator_remove_death_listener(old_it, this); + song_iterator_transfer_death_listeners(old_it, this); delete this; return old_it; } else if (!(_status & TEE_RIGHT_ACTIVE)) { delete _children[TEE_RIGHT].it; _children[TEE_RIGHT].it = 0; old_it = _children[TEE_LEFT].it; + song_iterator_remove_death_listener(old_it, this); + song_iterator_transfer_death_listeners(old_it, this); delete this; return old_it; } @@ -1521,7 +1570,7 @@ SongIterator *TeeSongIterator::handleMessage(Message msg) { if (msg._class == _SIMSG_BASE && msg._type == _SIMSG_BASEMSG_PRINT) { print_tabs_id(msg._arg.i, ID); - fprintf(stderr, "TEE:\n"); + debugC(2, kDebugLevelSound, "TEE:\n"); msg._arg.i++; } @@ -1565,15 +1614,15 @@ int songit_next(SongIterator **it, byte *buf, int *result, int mask) { do { retval = (*it)->nextCommand(buf, result); if (retval == SI_MORPH) { - fprintf(stderr, " Morphing %p (stored at %p)\n", (void *)*it, (void *)it); + debugC(2, kDebugLevelSound, " Morphing %p (stored at %p)\n", (void *)*it, (void *)it); if (!SIMSG_SEND((*it), SIMSG_ACK_MORPH)) { error("SI_MORPH failed. Breakpoint in %s, line %d", __FILE__, __LINE__); } else - fprintf(stderr, "SI_MORPH successful\n"); + debugC(2, kDebugLevelSound, "SI_MORPH successful\n"); } if (retval == SI_FINISHED) - fprintf(stderr, "[song-iterator] Song finished. mask = %04x, cm=%04x\n", + debugC(2, kDebugLevelSound, "[song-iterator] Song finished. mask = %04x, cm=%04x\n", mask, (*it)->channel_mask); if (retval == SI_FINISHED && (mask & IT_READER_MAY_CLEAN) @@ -1582,9 +1631,11 @@ int songit_next(SongIterator **it, byte *buf, int *result, int mask) { ** cleanup iterator */ int channel_mask = (*it)->channel_mask; - if (mask & IT_READER_MAY_FREE) - delete *it; + SongIterator *old_it = *it; *it = new CleanupSongIterator(channel_mask); + song_iterator_transfer_death_listeners(*it, old_it); + if (mask & IT_READER_MAY_FREE) + delete old_it; retval = -9999; /* Continue */ } } while (!( /* Until one of the following holds */ diff --git a/engines/sci/sfx/iterator.h b/engines/sci/sfx/iterator.h index 547c479bbf..4e6df367c9 100644 --- a/engines/sci/sfx/iterator.h +++ b/engines/sci/sfx/iterator.h @@ -281,6 +281,12 @@ int songit_next(SongIterator **it, byte *buf, int *result, int mask); */ SongIterator *songit_new(byte *data, uint size, SongIteratorType type, songit_id_t id); +/* Constructs a new song timer iterator object +** Parameters: (int) delta: The delta after which to fire SI_FINISHED +** Returns : (SongIterator *) A newly allocated but uninitialized song +** iterator +*/ +SongIterator *new_timer_iterator(int delta); /* Handles a message to the song iterator ** Parameters: (SongIterator **): A reference to the variable storing the song iterator diff --git a/engines/sci/sfx/iterator_internal.h b/engines/sci/sfx/iterator_internal.h index 7d5a17fd25..00044b8ab7 100644 --- a/engines/sci/sfx/iterator_internal.h +++ b/engines/sci/sfx/iterator_internal.h @@ -181,6 +181,28 @@ private: #define PLAYMASK_NONE 0x0 +/***************************/ +/*--------- Timer ---------*/ +/***************************/ + +/** + * A song iterator which waits a specified time and then fires + * SI_FINISHED. Used by DoSound, where audio resources are played (SCI1) + */ +class TimerSongIterator : public SongIterator { +protected: + int _delta; /**!< Remaining time */ + +public: + TimerSongIterator(int delta); + + int nextCommand(byte *buf, int *result); + Audio::AudioStream *getAudioStream(); + SongIterator *handleMessage(Message msg); + int getTimepos(); + SongIterator *clone(int delta); +}; + /**********************************/ /*--------- Fast Forward ---------*/ /**********************************/ diff --git a/engines/sci/sfx/seq/map-mt32-to-gm.cpp b/engines/sci/sfx/seq/map-mt32-to-gm.cpp index 8b93f62043..269f6cb24f 100644 --- a/engines/sci/sfx/seq/map-mt32-to-gm.cpp +++ b/engines/sci/sfx/seq/map-mt32-to-gm.cpp @@ -582,19 +582,19 @@ static int8 lookup_rhythm_key(const char *iname) { static void print_map(int sci, int ins, int rhythm, int mt32) { #ifdef DEBUG_MT32_TO_GM if (ins == SFX_UNMAPPED || (ins == SFX_MAPPED_TO_RHYTHM && rhythm == SFX_UNMAPPED)) { - sciprintf("[MT32-to-GM] No mapping available for [%i] `%s' (%i)\n", + printf("[MT32-to-GM] No mapping available for [%i] `%s' (%i)\n", sci, MT32_PresetTimbreMaps[mt32].name, mt32); return; } if (ins == SFX_MAPPED_TO_RHYTHM) { - sciprintf("[MT32-to-GM] Mapping [%i] `%s' (%i) to `%s' [R] (%i)\n", + printf("[MT32-to-GM] Mapping [%i] `%s' (%i) to `%s' [R] (%i)\n", sci, MT32_PresetTimbreMaps[mt32].name, mt32, GM_Percussion_Names[rhythm], rhythm); return; } - sciprintf("[MT32-to-GM] Mapping [%i] `%s' (%i) to `%s' (%i)\n", + printf("[MT32-to-GM] Mapping [%i] `%s' (%i) to `%s' (%i)\n", sci, MT32_PresetTimbreMaps[mt32].name, mt32, GM_Instrument_Names[ins], ins); #endif @@ -608,18 +608,18 @@ static void print_map_mem(int sci, int ins, int rhythm, char *mt32) { name[10] = 0; if (ins == SFX_UNMAPPED || (ins == SFX_MAPPED_TO_RHYTHM && rhythm == SFX_UNMAPPED)) { - sciprintf("[MT32-to-GM] No mapping available for [%i] `%s'\n", + printf("[MT32-to-GM] No mapping available for [%i] `%s'\n", sci, name); return; } if (ins == SFX_MAPPED_TO_RHYTHM) { - sciprintf("[MT32-to-GM] Mapping [%i] `%s' to `%s' [R] (%i)\n", + printf("[MT32-to-GM] Mapping [%i] `%s' to `%s' [R] (%i)\n", sci, name, GM_Percussion_Names[rhythm], rhythm); return; } - sciprintf("[MT32-to-GM] Mapping [%i] `%s' to `%s' (%i)\n", + printf("[MT32-to-GM] Mapping [%i] `%s' to `%s' (%i)\n", sci, name, GM_Instrument_Names[ins], ins); #endif } @@ -627,19 +627,19 @@ static void print_map_mem(int sci, int ins, int rhythm, char *mt32) { static void print_map_rhythm(int sci, int ins, int rhythm, int mt32) { #ifdef DEBUG_MT32_TO_GM if (ins == SFX_UNMAPPED || (ins == SFX_MAPPED_TO_RHYTHM && rhythm == SFX_UNMAPPED)) { - sciprintf("[MT32-to-GM] No mapping available for [%i] `%s' [R] (%i)\n", + printf("[MT32-to-GM] No mapping available for [%i] `%s' [R] (%i)\n", sci, MT32_RhythmTimbreMaps[mt32].name, mt32); return; } if (ins == SFX_MAPPED_TO_RHYTHM) { - sciprintf("[MT32-to-GM] Mapping [%i] `%s' [R] (%i) to `%s' [R] (%i)\n", + printf("[MT32-to-GM] Mapping [%i] `%s' [R] (%i) to `%s' [R] (%i)\n", sci, MT32_RhythmTimbreMaps[mt32].name, mt32, GM_Percussion_Names[rhythm], rhythm); return; } - sciprintf("[MT32-to-GM] Mapping [%i] `%s' [R] (%i) to `%s' (%i)\n", + printf("[MT32-to-GM] Mapping [%i] `%s' [R] (%i) to `%s' (%i)\n", sci, MT32_RhythmTimbreMaps[mt32].name, mt32, GM_Instrument_Names[ins], ins); #endif @@ -653,12 +653,12 @@ static void print_map_rhythm_mem(int sci, int rhythm, char *mt32) { name[10] = 0; if (rhythm == SFX_UNMAPPED) { - sciprintf("[MT32-to-GM] No mapping available for [%i] `%s'\n", + printf("[MT32-to-GM] No mapping available for [%i] `%s'\n", sci, name); return; } - sciprintf("[MT32-to-GM] Mapping [%i] `%s' to `%s' (%i)\n", + printf("[MT32-to-GM] Mapping [%i] `%s' to `%s' (%i)\n", sci, name, GM_Percussion_Names[rhythm], rhythm); #endif } @@ -691,18 +691,18 @@ sfx_instrument_map_t *sfx_instrument_map_mt32_to_gm(byte *data, size_t size) { } if (!data) { - sciprintf("[MT32-to-GM] No MT-32 patch data supplied, using default mapping\n"); + printf("[MT32-to-GM] No MT-32 patch data supplied, using default mapping\n"); return map; } type = sfx_instrument_map_detect(data, size); if (type == SFX_MAP_UNKNOWN) { - sciprintf("[MT32-to-GM] Patch data format unknown, using default mapping\n"); + printf("[MT32-to-GM] Patch data format unknown, using default mapping\n"); return map; } if (type == SFX_MAP_MT32_GM) { - sciprintf("[MT32-to-GM] Patch data format not supported, using default mapping\n"); + printf("[MT32-to-GM] Patch data format not supported, using default mapping\n"); return map; } @@ -715,10 +715,10 @@ sfx_instrument_map_t *sfx_instrument_map_mt32_to_gm(byte *data, size_t size) { } else patches = 48; - sciprintf("[MT32-to-GM] %d MT-32 Patches detected\n", patches); - sciprintf("[MT32-to-GM] %d MT-32 Memory Timbres\n", memtimbres); + printf("[MT32-to-GM] %d MT-32 Patches detected\n", patches); + printf("[MT32-to-GM] %d MT-32 Memory Timbres\n", memtimbres); - sciprintf("[MT32-to-GM] Mapping patches..\n"); + printf("[MT32-to-GM] Mapping patches..\n"); for (i = 0; i < patches; i++) { char *name; @@ -765,7 +765,7 @@ sfx_instrument_map_t *sfx_instrument_map_mt32_to_gm(byte *data, size_t size) { } if (size > pos && ((0x100 * *(data + pos) + *(data + pos + 1)) == 0xDCBA)) { - sciprintf("[MT32-to-GM] Mapping percussion..\n"); + printf("[MT32-to-GM] Mapping percussion..\n"); for (i = 0; i < 64 ; i++) { number = *(data + pos + 4 * i + 2); diff --git a/engines/sci/sfx/softseq/adlib.cpp b/engines/sci/sfx/softseq/adlib.cpp index 0bb13e120c..41c7c63fc9 100644 --- a/engines/sci/sfx/softseq/adlib.cpp +++ b/engines/sci/sfx/softseq/adlib.cpp @@ -482,7 +482,7 @@ void MidiDriver_Adlib::setNote(int voice, int note, bool key) { if (bend < 8192) bend = 8192 - bend; - delta = pow(2.0, (float)(bend % 8192) / 8192.0); + delta = (float)pow(2.0, (bend % 8192) / 8192.0); if (bend > 8192) fre = (int)(ym3812_note[n] * delta); diff --git a/engines/sci/sfx/softseq/amiga.cpp b/engines/sci/sfx/softseq/amiga.cpp index d097ec47f5..7eebadbf59 100644 --- a/engines/sci/sfx/softseq/amiga.cpp +++ b/engines/sci/sfx/softseq/amiga.cpp @@ -28,6 +28,7 @@ #include "common/file.h" #include "common/frac.h" +#include "common/util.h" namespace Sci { @@ -253,9 +254,9 @@ static void play_instrument(int16 *dest, channel_t *channel, int count) { static void change_instrument(int channel, int instrument) { #ifdef DEBUG if (bank.instruments[instrument]) - sciprintf("[sfx:seq:amiga] Setting channel %i to \"%s\" (%i)\n", channel, bank.instruments[instrument]->name, instrument); + printf("[sfx:seq:amiga] Setting channel %i to \"%s\" (%i)\n", channel, bank.instruments[instrument]->name, instrument); else - sciprintf("[sfx:seq:amiga] Warning: instrument %i does not exist (channel %i)\n", instrument, channel); + warning("[sfx:seq:amiga] instrument %i does not exist (channel %i)", instrument, channel); #endif hw_channels[channel].instrument = instrument; } @@ -283,7 +284,7 @@ static void stop_note(int ch, int note) { if (channel == CHANNELS_NR) { #ifdef DEBUG - sciprintf("[sfx:seq:amiga] Warning: cannot stop note %i on channel %i\n", note, ch); + warning("[sfx:seq:amiga] cannot stop note %i on channel %i", note, ch); #endif return; } @@ -300,14 +301,14 @@ static void start_note(int ch, int note, int velocity) { int channel; if (hw_channels[ch].instrument < 0 || hw_channels[ch].instrument > 255) { - sciprintf("[sfx:seq:amiga] Error: invalid instrument %i on channel %i\n", hw_channels[ch].instrument, ch); + warning("[sfx:seq:amiga] invalid instrument %i on channel %i", hw_channels[ch].instrument, ch); return; } instrument = bank.instruments[hw_channels[ch].instrument]; if (!instrument) { - sciprintf("[sfx:seq:amiga] Error: instrument %i does not exist\n", hw_channels[ch].instrument); + warning("[sfx:seq:amiga] instrument %i does not exist", hw_channels[ch].instrument); return; } @@ -316,7 +317,7 @@ static void start_note(int ch, int note, int velocity) { break; if (channel == CHANNELS_NR) { - sciprintf("[sfx:seq:amiga] Warning: could not find a free channel\n"); + warning("[sfx:seq:amiga] could not find a free channel"); return; } @@ -326,7 +327,7 @@ static void start_note(int ch, int note, int velocity) { int fnote = note + instrument->transpose; if (fnote < 0 || fnote > 127) { - sciprintf("[sfx:seq:amiga] Error: illegal note %i\n", fnote); + warning("[sfx:seq:amiga] illegal note %i\n", fnote); return; } @@ -369,7 +370,7 @@ static instrument_t *read_instrument(Common::File &file, int *id) { int i; if (file.read(header, 61) < 61) { - sciprintf("[sfx:seq:amiga] Error: failed to read instrument header\n"); + warning("[sfx:seq:amiga] failed to read instrument header"); return NULL; } @@ -402,31 +403,31 @@ static instrument_t *read_instrument(Common::File &file, int *id) { strncpy(instrument->name, (char *) header + 2, 29); instrument->name[29] = 0; #ifdef DEBUG - sciprintf("[sfx:seq:amiga] Reading instrument %i: \"%s\" (%i bytes)\n", + printf("[sfx:seq:amiga] Reading instrument %i: \"%s\" (%i bytes)\n", *id, instrument->name, size); - sciprintf(" Mode: %02x\n", instrument->mode); - sciprintf(" Looping: %s\n", instrument->mode & MODE_LOOP ? "on" : "off"); - sciprintf(" Pitch changes: %s\n", instrument->mode & MODE_PITCH ? "on" : "off"); - sciprintf(" Segment sizes: %i %i %i\n", seg_size[0], seg_size[1], seg_size[2]); - sciprintf(" Segment offsets: 0 %i %i\n", loop_offset, read_int32(header + 43)); + printf(" Mode: %02x\n", instrument->mode); + printf(" Looping: %s\n", instrument->mode & MODE_LOOP ? "on" : "off"); + printf(" Pitch changes: %s\n", instrument->mode & MODE_PITCH ? "on" : "off"); + printf(" Segment sizes: %i %i %i\n", seg_size[0], seg_size[1], seg_size[2]); + printf(" Segment offsets: 0 %i %i\n", loop_offset, read_int32(header + 43)); #endif instrument->samples = (int8 *) malloc(size + 1); if (file.read(instrument->samples, size) < (unsigned int)size) { - sciprintf("[sfx:seq:amiga] Error: failed to read instrument samples\n"); + warning("[sfx:seq:amiga] failed to read instrument samples"); return NULL; } if (instrument->mode & MODE_LOOP) { if (loop_offset + seg_size[1] > size) { #ifdef DEBUG - sciprintf("[sfx:seq:amiga] Warning: looping samples extend %i bytes past end of sample block\n", + warning("[sfx:seq:amiga] looping samples extend %i bytes past end of sample block", loop_offset + seg_size[1] - size); #endif seg_size[1] = size - loop_offset; } if (seg_size[1] < 0) { - sciprintf("[sfx:seq:amiga] Error: invalid looping point\n"); + warning("[sfx:seq:amiga] invalid looping point"); return NULL; } @@ -456,12 +457,12 @@ static Common::Error ami_init(sfx_softseq_t *self, byte *patch, int patch_len, b int i; if (!file.open("bank.001")) { - sciprintf("[sfx:seq:amiga] Error: file bank.001 not found\n"); + warning("[sfx:seq:amiga] file bank.001 not found"); return Common::kUnknownError; } if (file.read(header, 40) < 40) { - sciprintf("[sfx:seq:amiga] Error: failed to read header of file bank.001\n"); + warning("[sfx:seq:amiga] failed to read header of file bank.001"); return Common::kUnknownError; } @@ -482,7 +483,7 @@ static Common::Error ami_init(sfx_softseq_t *self, byte *patch, int patch_len, b strncpy(bank.name, (char *) header + 8, 29); bank.name[29] = 0; #ifdef DEBUG - sciprintf("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", bank.size, bank.name); + printf("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", bank.size, bank.name); #endif for (i = 0; i < bank.size; i++) { @@ -490,12 +491,12 @@ static Common::Error ami_init(sfx_softseq_t *self, byte *patch, int patch_len, b instrument_t *instrument = read_instrument(file, &id); if (!instrument) { - sciprintf("[sfx:seq:amiga] Error: failed to read bank.001\n"); + warning("[sfx:seq:amiga] failed to read bank.001"); return Common::kUnknownError; } if (id < 0 || id > 255) { - sciprintf("[sfx:seq:amiga] Error: instrument ID out of bounds\n"); + warning("[sfx:seq:amiga] Error: instrument ID out of bounds"); return Common::kUnknownError; } @@ -524,7 +525,7 @@ static void ami_event(sfx_softseq_t *self, byte command, int argc, byte *argv) { if (channel >= HW_CHANNELS_NR) { #ifdef DEBUG - sciprintf("[sfx:seq:amiga] Warning: received event for non-existing channel %i\n", channel); + warning("[sfx:seq:amiga] received event for non-existing channel %i", channel); #endif return; } @@ -543,21 +544,21 @@ static void ami_event(sfx_softseq_t *self, byte command, int argc, byte *argv) { break; case 0x0a: #ifdef DEBUG - sciprintf("[sfx:seq:amiga] Warning: ignoring pan 0x%02x event for channel %i\n", argv[1], channel); + warning("[sfx:seq:amiga] ignoring pan 0x%02x event for channel %i", argv[1], channel); #endif break; case 0x7b: stop_channel(channel); break; default: - sciprintf("[sfx:seq:amiga] Warning: unknown control event 0x%02x\n", argv[0]); + warning("[sfx:seq:amiga] unknown control event 0x%02x", argv[0]); } break; case 0xc0: change_instrument(channel, argv[0]); break; default: - sciprintf("[sfx:seq:amiga] Warning: unknown event %02x\n", command); + warning("[sfx:seq:amiga] unknown event %02x", command); } } diff --git a/engines/sci/sfx/songlib.cpp b/engines/sci/sfx/songlib.cpp index 3a6549a0d4..0fe6440e7a 100644 --- a/engines/sci/sfx/songlib.cpp +++ b/engines/sci/sfx/songlib.cpp @@ -74,7 +74,7 @@ void SongLibrary::addSong(Song *song) { int pri = song->_priority; if (NULL == song) { - sciprintf("addSong(): NULL passed for song\n"); + warning("addSong(): NULL passed for song"); return; } diff --git a/engines/sci/tools.cpp b/engines/sci/tools.cpp index 589ce298d7..b35c6ce7b6 100644 --- a/engines/sci/tools.cpp +++ b/engines/sci/tools.cpp @@ -45,35 +45,4 @@ int sci_ffs(int bits) { return retval; } -bool g_redirect_sciprintf_to_gui = false; - -void sciprintf(const char *fmt, ...) { - va_list argp; - - assert(fmt); - - // First determine how big a buffer we need - va_start(argp, fmt); - int bufsize = vsnprintf(0, 0, fmt, argp); - assert(bufsize >= 0); - va_end(argp); - - // Allocate buffer for the full printed string - char *buf = (char *)malloc(bufsize + 1); - assert(buf); - - // Print everything according to fmt into buf - va_start(argp, fmt); // reset argp - int bufsize2 = vsnprintf(buf, bufsize + 1, fmt, argp); - assert(bufsize == bufsize2); - va_end(argp); - - // Display the result suitably - if (g_redirect_sciprintf_to_gui) - ((SciEngine *)g_engine)->getDebugger()->DebugPrintf("%s", buf); - printf("%s", buf); - - free(buf); -} - } // End of namespace Sci diff --git a/engines/sci/tools.h b/engines/sci/tools.h index a4352837e8..b0d30aadb7 100644 --- a/engines/sci/tools.h +++ b/engines/sci/tools.h @@ -31,13 +31,6 @@ namespace Sci { -/** - * Prints a string to the console stack. - * @param fmt a printf-style format string - * @param Additional parameters as defined in fmt - */ -void sciprintf(const char *fmt, ...) GCC_PRINTF(1, 2); - /** Find first set bit in bits and return its index. Returns 0 if bits is 0. */ int sci_ffs(int bits); diff --git a/engines/sci/vocabulary.cpp b/engines/sci/vocabulary.cpp index c877053060..5253e7885b 100644 --- a/engines/sci/vocabulary.cpp +++ b/engines/sci/vocabulary.cpp @@ -91,7 +91,7 @@ Vocabulary::Vocabulary(ResourceManager *resmgr) : _resmgr(resmgr) { debug(2, "Initializing vocabulary"); - if (_resmgr->_sciVersion < SCI_VERSION_01_VGA && loadParserWords()) { + if (_resmgr->_sciVersion <= SCI_VERSION_01 && loadParserWords()) { loadSuffixes(); if (loadBranches()) // Now build a GNF grammar out of this @@ -351,46 +351,46 @@ void Vocabulary::decipherSaidBlock(byte *addr) { if (nextitem < 0xf0) { nextitem = nextitem << 8 | *addr++; - sciprintf(" %s[%03x]", getAnyWordFromGroup(nextitem), nextitem); + printf(" %s[%03x]", getAnyWordFromGroup(nextitem), nextitem); nextitem = 42; // Make sure that group 0xff doesn't abort } else switch (nextitem) { case 0xf0: - sciprintf(" ,"); + printf(" ,"); break; case 0xf1: - sciprintf(" &"); + printf(" &"); break; case 0xf2: - sciprintf(" /"); + printf(" /"); break; case 0xf3: - sciprintf(" ("); + printf(" ("); break; case 0xf4: - sciprintf(" )"); + printf(" )"); break; case 0xf5: - sciprintf(" ["); + printf(" ["); break; case 0xf6: - sciprintf(" ]"); + printf(" ]"); break; case 0xf7: - sciprintf(" #"); + printf(" #"); break; case 0xf8: - sciprintf(" <"); + printf(" <"); break; case 0xf9: - sciprintf(" >"); + printf(" >"); break; case 0xff: break; } } while (nextitem != 0xff); - sciprintf("\n"); + printf("\n"); } bool Vocabulary::tokenizeString(ResultWordList &retval, const char *sentence, char **error) { @@ -438,7 +438,7 @@ bool Vocabulary::tokenizeString(ResultWordList &retval, const char *sentence, ch void Vocabulary::printSuffixes() const { char word_buf[256], alt_buf[256]; - GUI::Debugger *con = ((SciEngine *)g_engine)->getDebugger(); + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); int i = 0; for (SuffixList::const_iterator suf = _parserSuffixes.begin(); suf != _parserSuffixes.end(); ++suf) { @@ -453,7 +453,7 @@ void Vocabulary::printSuffixes() const { } void Vocabulary::printParserWords() const { - GUI::Debugger *con = ((SciEngine *)g_engine)->getDebugger(); + Console *con = ((SciEngine *)g_engine)->getSciDebugger(); int j = 0; for (WordMap::iterator i = _parserWords.begin(); i != _parserWords.end(); ++i) { @@ -472,7 +472,7 @@ int Kernel::findSelector(const char *selectorName) const { return pos; } - warning("Could not map '%s' to any selector", selectorName); + debugC(2, kDebugLevelVM, "Could not map '%s' to any selector\n", selectorName); return -1; } @@ -484,32 +484,32 @@ bool Kernel::hasKernelFunction(const char *functionName) const { void _vocab_recursive_ptree_dump_treelike(parse_tree_node_t *nodes, int nr, int prevnr) { if ((nr > VOCAB_TREE_NODES)/* || (nr < prevnr)*/) { - sciprintf("Error(%04x)", nr); + printf("Error(%04x)", nr); return; } if (nodes[nr].type == kParseTreeLeafNode) - //sciprintf("[%03x]%04x", nr, nodes[nr].content.value); - sciprintf("%x", nodes[nr].content.value); + //printf("[%03x]%04x", nr, nodes[nr].content.value); + printf("%x", nodes[nr].content.value); else { int lbranch = nodes[nr].content.branches[0]; int rbranch = nodes[nr].content.branches[1]; - //sciprintf("<[%03x]", nr); - sciprintf("<"); + //printf("<[%03x]", nr); + printf("<"); if (lbranch) _vocab_recursive_ptree_dump_treelike(nodes, lbranch, nr); else - sciprintf("NULL"); + printf("NULL"); - sciprintf(","); + printf(","); if (rbranch) _vocab_recursive_ptree_dump_treelike(nodes, rbranch, nr); else - sciprintf("NULL"); + printf("NULL"); - sciprintf(">"); + printf(">"); } } @@ -519,43 +519,43 @@ void _vocab_recursive_ptree_dump(parse_tree_node_t *nodes, int nr, int prevnr, i int i; if (nodes[nr].type == kParseTreeLeafNode) { - sciprintf("vocab_dump_parse_tree: Error: consp is nil for element %03x\n", nr); + printf("vocab_dump_parse_tree: Error: consp is nil for element %03x\n", nr); return; } if ((nr > VOCAB_TREE_NODES)/* || (nr < prevnr)*/) { - sciprintf("Error(%04x))", nr); + printf("Error(%04x))", nr); return; } if (lbranch) { if (nodes[lbranch].type == kParseTreeBranchNode) { - sciprintf("\n"); + printf("\n"); for (i = 0; i < blanks; i++) - sciprintf(" "); - sciprintf("("); + printf(" "); + printf("("); _vocab_recursive_ptree_dump(nodes, lbranch, nr, blanks + 1); - sciprintf(")\n"); + printf(")\n"); for (i = 0; i < blanks; i++) - sciprintf(" "); + printf(" "); } else - sciprintf("%x", nodes[lbranch].content.value); - sciprintf(" "); - }/* else sciprintf ("nil");*/ + printf("%x", nodes[lbranch].content.value); + printf(" "); + }/* else printf ("nil");*/ if (rbranch) { if (nodes[rbranch].type == kParseTreeBranchNode) _vocab_recursive_ptree_dump(nodes, rbranch, nr, blanks); else - sciprintf("%x", nodes[rbranch].content.value); - }/* else sciprintf("nil");*/ + printf("%x", nodes[rbranch].content.value); + }/* else printf("nil");*/ } void vocab_dump_parse_tree(const char *tree_name, parse_tree_node_t *nodes) { //_vocab_recursive_ptree_dump_treelike(nodes, 0, 0); - sciprintf("(setq %s \n'(", tree_name); + printf("(setq %s \n'(", tree_name); _vocab_recursive_ptree_dump(nodes, 0, 0, 1); - sciprintf("))\n"); + printf("))\n"); } void vocab_synonymize_tokens(ResultWordList &words, const SynonymList &synonyms) { diff --git a/engines/sci/vocabulary.h b/engines/sci/vocabulary.h index ce6d48c570..14e3ad6013 100644 --- a/engines/sci/vocabulary.h +++ b/engines/sci/vocabulary.h @@ -236,7 +236,7 @@ public: parse_rule_list_t *buildGNF(bool verbose = false); /** - * Deciphers a said block and dumps its content via sciprintf. + * Deciphers a said block and dumps its content via printf. * For debugging only. * @param pos pointer to the data to dump */ diff --git a/engines/scumm/boxes.cpp b/engines/scumm/boxes.cpp index f1429d4261..472e04b5f3 100644 --- a/engines/scumm/boxes.cpp +++ b/engines/scumm/boxes.cpp @@ -369,7 +369,7 @@ void ScummEngine::convertScaleTableToScaleSlot(int slot) { */ // Search for the bend on the left side - m = (resptr[199] - resptr[0]) / 199.0; + m = (resptr[199] - resptr[0]) / 199.0f; for (lowerIdx = 0; lowerIdx < 199 && (resptr[lowerIdx] == 1 || resptr[lowerIdx] == 255); lowerIdx++) { oldM = m; m = (resptr[199] - resptr[lowerIdx+1]) / (float)(199 - (lowerIdx+1)); @@ -383,7 +383,7 @@ void ScummEngine::convertScaleTableToScaleSlot(int slot) { } // Search for the bend on the right side - m = (resptr[199] - resptr[0]) / 199.0; + m = (resptr[199] - resptr[0]) / 199.0f; for (upperIdx = 199; upperIdx > 1 && (resptr[upperIdx] == 1 || resptr[upperIdx] == 255); upperIdx--) { oldM = m; m = (resptr[upperIdx-1] - resptr[0]) / (float)(upperIdx-1); diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index cf88ded3b8..5fa74d22c3 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -882,6 +882,10 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co if (res.game.platform == Common::kPlatformFMTowns && res.game.version == 3) res.game.midi = MDT_TOWNS; + // If the GUI options were updated, we catch this here and update them in the users config + // file transparently. + Common::updateGameGUIOptions(res.game.guioptions); + // Finally, we have massaged the GameDescriptor to our satisfaction, and can // instantiate the appropriate game engine. Hooray! switch (res.game.version) { diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index 2ea593c571..92024a21cc 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -230,13 +230,13 @@ static const GameSettings gameVariantsTable[] = { {"monkey2", 0, 0, GID_MONKEY2, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, - {"atlantis", 0, 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, + {"atlantis", "", 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, {"atlantis", "CD" , 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NONE}, - {"tentacle", 0, 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NOSPEECH}, + {"tentacle", "", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NOSPEECH}, {"tentacle", "CD", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, - {"samnmax", 0, 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NOSPEECH}, + {"samnmax", "", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NOSPEECH}, {"samnmax", "CD", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, #ifdef ENABLE_SCUMM_7_8 diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index 9fb107f9fc..880fab04a5 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -641,6 +641,8 @@ HelpDialog::HelpDialog(const GameSettings &game) new GUI::ButtonWidget(this, "ScummHelp.Close", "Close", kCloseCmd, 'C'); _prevButton->clearFlags(WIDGET_ENABLED); + _numLines = HELP_NUM_LINES; + // Dummy entries for (int i = 0; i < HELP_NUM_LINES; i++) { _key[i] = new StaticTextWidget(this, 0, 0, 10, 10, "", Graphics::kTextAlignRight); @@ -658,22 +660,25 @@ void HelpDialog::reflowLayout() { g_gui.xmlEval()->getWidgetData("ScummHelp.HelpText", x, y, w, h); + // Make sure than we don't have more lines than what we can fit + // on the space that the layout reserves for text + _numLines = MIN(HELP_NUM_LINES, (int)(h / lineHeight)); + int keyW = w * 20 / 100; int dscX = x + keyW + 32; int dscW = w * 80 / 100; int xoff = (_w >> 1) - (w >> 1); - for (int i = 0; i < HELP_NUM_LINES; i++) { - _key[i]->resize(xoff + x, y + lineHeight * i, keyW, lineHeight + 2); - _dsc[i]->resize(xoff + dscX, y + lineHeight * i, dscW, lineHeight + 2); + for (int i = 0; i < _numLines; i++) { + _key[i]->resize(xoff + x, y + lineHeight * i, keyW, lineHeight); + _dsc[i]->resize(xoff + dscX, y + lineHeight * i, dscW, lineHeight); } displayKeyBindings(); } void HelpDialog::displayKeyBindings() { - String titleStr, *keyStr, *dscStr; #ifndef __DS__ @@ -684,7 +689,7 @@ void HelpDialog::displayKeyBindings() { #endif _title->setLabel(titleStr); - for (int i = 0; i < HELP_NUM_LINES; i++) { + for (int i = 0; i < _numLines; i++) { _key[i]->setLabel(keyStr[i]); _dsc[i]->setLabel(dscStr[i]); } diff --git a/engines/scumm/dialogs.h b/engines/scumm/dialogs.h index 290b3450dc..af844272fa 100644 --- a/engines/scumm/dialogs.h +++ b/engines/scumm/dialogs.h @@ -124,6 +124,7 @@ protected: int _page; int _numPages; + int _numLines; const GameSettings _game; diff --git a/engines/scumm/gfx.cpp b/engines/scumm/gfx.cpp index 62e18561d3..5961ec4013 100644 --- a/engines/scumm/gfx.cpp +++ b/engines/scumm/gfx.cpp @@ -36,7 +36,7 @@ #include "scumm/util.h" #ifdef USE_ARM_GFX_ASM -extern "C" void asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst, +extern "C" void asmDrawStripToScreen(int height, int width, void const* text, void const* src, byte* dst, int vsPitch, int vmScreenWidth, int textSurfacePitch); extern "C" void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height); #endif /* USE_ARM_GFX_ASM */ @@ -574,13 +574,13 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i if (width <= 0 || height <= 0) return; - const byte *src = vs->getPixels(x, top); + const void *src = vs->getPixels(x, top); int m = _textSurfaceMultiplier; int vsPitch; int pitch = vs->pitch; if (_useCJKMode && _textSurfaceMultiplier == 2) { - scale2x(_fmtownsBuf, _screenWidth * m, src, vs->pitch, width, height); + scale2x(_fmtownsBuf, _screenWidth * m, (const byte *)src, vs->pitch, width, height); src = _fmtownsBuf; vsPitch = _screenWidth * m - width * m; @@ -599,7 +599,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i // Compute pointer to the text surface assert(_compositeBuf); - const byte *text = (byte *)_textSurface.getBasePtr(x * m, y * m); + const void *text = _textSurface.getBasePtr(x * m, y * m); // The values x, width, etc. are all multiples of 8 at this point, // so loop unrolloing might be a good idea... @@ -677,7 +677,7 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i } // Finally blit the whole thing to the screen - _system->copyRectToScreen(src, pitch, x, y, width, height); + _system->copyRectToScreen((const byte *)src, pitch, x, y, width, height); } // CGA diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h index c2079fa5fe..4c2da19cc5 100644 --- a/engines/scumm/he/intern_he.h +++ b/engines/scumm/he/intern_he.h @@ -359,6 +359,8 @@ protected: virtual void setupScummVars(); virtual void resetScummVars(); + virtual void parseEvent(Common::Event event); + virtual void initCharset(int charset); virtual void clearDrawQueues(); @@ -386,6 +388,7 @@ protected: byte VAR_PLATFORM; byte VAR_PLATFORM_VERSION; byte VAR_CURRENT_CHARSET; + byte VAR_KEY_STATE; byte VAR_COLOR_DEPTH; }; diff --git a/engines/scumm/he/logic_he.cpp b/engines/scumm/he/logic_he.cpp index a095622173..a24f4d4665 100644 --- a/engines/scumm/he/logic_he.cpp +++ b/engines/scumm/he/logic_he.cpp @@ -357,8 +357,8 @@ int32 LogicHErace::op_1140(int32 *args) { const double scalarProduct = x * args[0] + y * args[1]; // Finally compute the projection of (arg2,arg3) onto (arg0,arg1) - double projX = args[0] - 2 * scalarProduct * args[2]; - double projY = args[1] - 2 * scalarProduct * args[3]; + double projX = args[0] - 2 * scalarProduct * x; + double projY = args[1] - 2 * scalarProduct * y; projX = projX * 20.0 / 23.0; // FIXME: Why is this here? diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp index 1b5b467512..ce29bf0319 100644 --- a/engines/scumm/he/resource_he.cpp +++ b/engines/scumm/he/resource_he.cpp @@ -474,7 +474,7 @@ bool Win32ResExtractor::check_offset(byte *memory, int total_size, const char *n int need_size = (int)((byte *)offset - memory + size); debugC(DEBUG_RESOURCE, "check_offset: size=%x vs %x offset=%x size=%x", - need_size, total_size, (byte *)offset - memory, size); + need_size, total_size, (uint)((byte *)offset - memory), size); if (need_size < 0 || need_size > total_size) { error("%s: premature end", name); @@ -913,7 +913,7 @@ int Win32ResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int if (entries[c].dib_size != bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad)) debugC(DEBUG_RESOURCE, "incorrect total size of bitmap (%d specified; %d real)", entries[c].dib_size, - bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad) + (int)(bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad)) ); image_data = (byte *)malloc(image_size); diff --git a/engines/scumm/he/script_v71he.cpp b/engines/scumm/he/script_v71he.cpp index 316d51b12d..c832d64316 100644 --- a/engines/scumm/he/script_v71he.cpp +++ b/engines/scumm/he/script_v71he.cpp @@ -59,7 +59,7 @@ byte *ScummEngine_v71he::heFindResourceData(uint32 tag, byte *ptr) { byte *ScummEngine_v71he::heFindResource(uint32 tag, byte *searchin) { uint32 curpos, totalsize, size; - debugC(DEBUG_RESOURCE, "heFindResource(%s, %lx)", tag2str(tag), searchin); + debugC(DEBUG_RESOURCE, "heFindResource(%s, %p)", tag2str(tag), (const void *)searchin); assert(searchin); searchin += 4; diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp index b23b7ac869..4c20ed7835 100644 --- a/engines/scumm/he/wiz_he.cpp +++ b/engines/scumm/he/wiz_he.cpp @@ -831,6 +831,11 @@ void Wiz::decompressWizImage(uint8 *dst, int dstPitch, const uint8 *src, const C } } +// NOTE: These templates are used outside this file. We don't want the compiler to optimize them away, so we need to explicitely instantiate them. +template void Wiz::decompressWizImage<kWizXMap>(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr); +template void Wiz::decompressWizImage<kWizRMap>(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr); +template void Wiz::decompressWizImage<kWizCopy>(uint8 *dst, int dstPitch, const uint8 *src, const Common::Rect &srcRect, int flags, const uint8 *palPtr, const uint8 *xmapPtr); + template <int type> void Wiz::decompressRawWizImage(uint8 *dst, int dstPitch, const uint8 *src, int srcPitch, int w, int h, int transColor, const uint8 *palPtr) { if (type == kWizRMap) { diff --git a/engines/scumm/imuse_digi/dimuse_track.cpp b/engines/scumm/imuse_digi/dimuse_track.cpp index 6ded6d23b2..a389c0e7e7 100644 --- a/engines/scumm/imuse_digi/dimuse_track.cpp +++ b/engines/scumm/imuse_digi/dimuse_track.cpp @@ -22,6 +22,7 @@ * $Id$ */ +#include "common/config-manager.h" #include "common/timer.h" #include "scumm/actor.h" @@ -136,6 +137,11 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType, track->pan = a->_talkPan; track->vol = a->_talkVolume * 1000; } + + // The volume is set to zero, when using subtitles only setting in COMI + if (ConfMan.getBool("speech_mute") || _vm->VAR(_vm->VAR_VOICE_MODE) == 2) { + track->vol = 0; + } } assert(bits == 8 || bits == 12 || bits == 16); diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp index f378f2225e..61b714a3e2 100644 --- a/engines/scumm/input.cpp +++ b/engines/scumm/input.cpp @@ -55,145 +55,173 @@ enum MouseButtonStatus { msClicked = 2 }; -void ScummEngine::parseEvents() { - Common::Event event; - - while (_eventMan->pollEvent(event)) { - - switch (event.type) { - case Common::EVENT_KEYDOWN: - if (event.kbd.keycode >= '0' && event.kbd.keycode <= '9' - && (event.kbd.flags == Common::KBD_ALT || - event.kbd.flags == Common::KBD_CTRL)) { - _saveLoadSlot = event.kbd.keycode - '0'; - - // don't overwrite autosave (slot 0) - if (_saveLoadSlot == 0) - _saveLoadSlot = 10; - - sprintf(_saveLoadName, "Quicksave %d", _saveLoadSlot); - _saveLoadFlag = (event.kbd.flags == Common::KBD_ALT) ? 1 : 2; - _saveTemporaryState = false; - } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'f') { - _fastMode ^= 1; - } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'g') { - _fastMode ^= 2; - } else if ((event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'd') || - event.kbd.ascii == '~' || event.kbd.ascii == '#') { - _debugger->attach(); - } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 's') { - _res->resourceStats(); - } else { - // Normal key press, pass on to the game. - _keyPressed = event.kbd; - } +#ifdef ENABLE_HE +void ScummEngine_v80he::parseEvent(Common::Event event) { + ScummEngine::parseEvent(event); - if (_game.heversion >= 80) { - // FIXME: Move this code & VAR_KEY_STATE to class ScummEngine_v80he + // Keyboard is controlled via variable + switch (event.type) { + case Common::EVENT_KEYDOWN: + if (event.kbd.keycode == Common::KEYCODE_LEFT) + VAR(VAR_KEY_STATE) |= 1; - // Keyboard is controlled via variable - int keyState = 0; + if (event.kbd.keycode == Common::KEYCODE_RIGHT) + VAR(VAR_KEY_STATE) |= 2; - if (event.kbd.keycode == Common::KEYCODE_LEFT) // Left - keyState = 1; + if (event.kbd.keycode == Common::KEYCODE_UP) + VAR(VAR_KEY_STATE) |= 4; - if (event.kbd.keycode == Common::KEYCODE_RIGHT) // Right - keyState |= 2; + if (event.kbd.keycode == Common::KEYCODE_DOWN) + VAR(VAR_KEY_STATE) |= 8; - if (event.kbd.keycode == Common::KEYCODE_UP) // Up - keyState |= 4; + if (event.kbd.keycode == Common::KEYCODE_LSHIFT || event.kbd.keycode == Common::KEYCODE_RSHIFT) + VAR(VAR_KEY_STATE) |= 16; - if (event.kbd.keycode == Common::KEYCODE_DOWN) // Down - keyState |= 8; + if (event.kbd.keycode == Common::KEYCODE_LCTRL || event.kbd.keycode == Common::KEYCODE_RCTRL) + VAR(VAR_KEY_STATE) |= 32; + break; - if (event.kbd.flags == Common::KBD_SHIFT) - keyState |= 16; + case Common::EVENT_KEYUP: + if (event.kbd.keycode == Common::KEYCODE_LEFT) + VAR(VAR_KEY_STATE) &= ~1; - if (event.kbd.flags == Common::KBD_CTRL) - keyState |= 32; + if (event.kbd.keycode == Common::KEYCODE_RIGHT) + VAR(VAR_KEY_STATE) &= ~2; - VAR(VAR_KEY_STATE) = keyState; - } + if (event.kbd.keycode == Common::KEYCODE_UP) + VAR(VAR_KEY_STATE) &= ~4; - // FIXME: We are using ASCII values to index the _keyDownMap here, - // yet later one code which checks _keyDownMap will use KEYCODEs - // to do so. That is, we are mixing ascii and keycode values here, - // which is bad. We probably should be only using keycodes, but at - // least INSANE checks for "Shift-V" by looking for the 'V' key - // being pressed. It would be easy to solve that by also storing - // the modifier flags. However, since getKeyState() is also called - // by scripts, we have to be careful with semantic changes. - if (_keyPressed.ascii >= 512) - debugC(DEBUG_GENERAL, "_keyPressed > 512 (%d)", _keyPressed.ascii); - else - _keyDownMap[_keyPressed.ascii] = true; - break; + if (event.kbd.keycode == Common::KEYCODE_DOWN) + VAR(VAR_KEY_STATE) &= ~8; - case Common::EVENT_KEYUP: - if (event.kbd.ascii >= 512) { - debugC(DEBUG_GENERAL, "keyPressed > 512 (%d)", event.kbd.ascii); - } else { - _keyDownMap[event.kbd.ascii] = false; - - // Due to some weird bug with capslock key pressed - // generated keydown event is for lower letter but - // keyup is for upper letter - // On most (all?) keyboards it is safe to assume that - // both upper and lower letters are unpressed on keyup event - // - // Fixes bug #1709430: "FT: CAPSLOCK + V enables cheating for all fights" - // - // Fingolfin remarks: This wouldn't be a problem if we used keycodes. - _keyDownMap[toupper(event.kbd.ascii)] = false; - } - break; + if (event.kbd.keycode == Common::KEYCODE_LSHIFT || event.kbd.keycode == Common::KEYCODE_RSHIFT) + VAR(VAR_KEY_STATE) &= ~16; + if (event.kbd.keycode == Common::KEYCODE_LCTRL || event.kbd.keycode == Common::KEYCODE_RCTRL) + VAR(VAR_KEY_STATE) &= ~32; + break; - // We update the mouse position whenever the mouse moves or a click occurs. - // The latter is done to accomodate systems with a touchpad / pen controller. - case Common::EVENT_LBUTTONDOWN: - case Common::EVENT_RBUTTONDOWN: - case Common::EVENT_MOUSEMOVE: - if (event.type == Common::EVENT_LBUTTONDOWN) - _leftBtnPressed |= msClicked|msDown; - else if (event.type == Common::EVENT_RBUTTONDOWN) - _rightBtnPressed |= msClicked|msDown; - _mouse.x = event.mouse.x; - _mouse.y = event.mouse.y; - - if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) { - _mouse.x -= (Common::kHercW - _screenWidth * 2) / 2; - _mouse.x >>= 1; - _mouse.y = _mouse.y * 4 / 7; - } else if (_useCJKMode && _textSurfaceMultiplier == 2) { - _mouse.x >>= 1; - _mouse.y >>= 1; - } - break; - case Common::EVENT_LBUTTONUP: - _leftBtnPressed &= ~msDown; - break; + default: + break; + } +} +#endif - case Common::EVENT_RBUTTONUP: - _rightBtnPressed &= ~msDown; - break; +void ScummEngine::parseEvent(Common::Event event) { + switch (event.type) { + case Common::EVENT_KEYDOWN: + if (event.kbd.keycode >= '0' && event.kbd.keycode <= '9' + && (event.kbd.flags == Common::KBD_ALT || + event.kbd.flags == Common::KBD_CTRL)) { + _saveLoadSlot = event.kbd.keycode - '0'; + + // don't overwrite autosave (slot 0) + if (_saveLoadSlot == 0) + _saveLoadSlot = 10; + + sprintf(_saveLoadName, "Quicksave %d", _saveLoadSlot); + _saveLoadFlag = (event.kbd.flags == Common::KBD_ALT) ? 1 : 2; + _saveTemporaryState = false; + } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'f') { + _fastMode ^= 1; + } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'g') { + _fastMode ^= 2; + } else if ((event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'd') || + event.kbd.ascii == '~' || event.kbd.ascii == '#') { + _debugger->attach(); + } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 's') { + _res->resourceStats(); + } else { + // Normal key press, pass on to the game. + _keyPressed = event.kbd; + } - // The following two cases enable dialog choices to be scrolled - // through in the SegaCD version of MI. Values are taken from script-14. - // See bug report #1193185 for details. - case Common::EVENT_WHEELDOWN: - if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD) - _keyPressed = Common::KeyState(Common::KEYCODE_7, 55); // '7' - break; + // FIXME: We are using ASCII values to index the _keyDownMap here, + // yet later one code which checks _keyDownMap will use KEYCODEs + // to do so. That is, we are mixing ascii and keycode values here, + // which is bad. We probably should be only using keycodes, but at + // least INSANE checks for "Shift-V" by looking for the 'V' key + // being pressed. It would be easy to solve that by also storing + // the modifier flags. However, since getKeyState() is also called + // by scripts, we have to be careful with semantic changes. + if (_keyPressed.ascii >= 512) + debugC(DEBUG_GENERAL, "_keyPressed > 512 (%d)", _keyPressed.ascii); + else + _keyDownMap[_keyPressed.ascii] = true; + break; + + case Common::EVENT_KEYUP: + if (event.kbd.ascii >= 512) { + debugC(DEBUG_GENERAL, "keyPressed > 512 (%d)", event.kbd.ascii); + } else { + _keyDownMap[event.kbd.ascii] = false; + + // Due to some weird bug with capslock key pressed + // generated keydown event is for lower letter but + // keyup is for upper letter + // On most (all?) keyboards it is safe to assume that + // both upper and lower letters are unpressed on keyup event + // + // Fixes bug #1709430: "FT: CAPSLOCK + V enables cheating for all fights" + // + // Fingolfin remarks: This wouldn't be a problem if we used keycodes. + _keyDownMap[toupper(event.kbd.ascii)] = false; + } + break; + + + // We update the mouse position whenever the mouse moves or a click occurs. + // The latter is done to accomodate systems with a touchpad / pen controller. + case Common::EVENT_LBUTTONDOWN: + case Common::EVENT_RBUTTONDOWN: + case Common::EVENT_MOUSEMOVE: + if (event.type == Common::EVENT_LBUTTONDOWN) + _leftBtnPressed |= msClicked|msDown; + else if (event.type == Common::EVENT_RBUTTONDOWN) + _rightBtnPressed |= msClicked|msDown; + _mouse.x = event.mouse.x; + _mouse.y = event.mouse.y; + + if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) { + _mouse.x -= (Common::kHercW - _screenWidth * 2) / 2; + _mouse.x >>= 1; + _mouse.y = _mouse.y * 4 / 7; + } else if (_useCJKMode && _textSurfaceMultiplier == 2) { + _mouse.x >>= 1; + _mouse.y >>= 1; + } + break; + case Common::EVENT_LBUTTONUP: + _leftBtnPressed &= ~msDown; + break; + + case Common::EVENT_RBUTTONUP: + _rightBtnPressed &= ~msDown; + break; + + // The following two cases enable dialog choices to be scrolled + // through in the SegaCD version of MI. Values are taken from script-14. + // See bug report #1193185 for details. + case Common::EVENT_WHEELDOWN: + if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD) + _keyPressed = Common::KeyState(Common::KEYCODE_7, 55); // '7' + break; + + case Common::EVENT_WHEELUP: + if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD) + _keyPressed = Common::KeyState(Common::KEYCODE_6, 54); // '6' + break; + + default: + break; + } +} - case Common::EVENT_WHEELUP: - if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD) - _keyPressed = Common::KeyState(Common::KEYCODE_6, 54); // '6' - break; +void ScummEngine::parseEvents() { + Common::Event event; - default: - break; - } + while (_eventMan->pollEvent(event)) { + parseEvent(event); } } @@ -230,6 +258,18 @@ void ScummEngine_v0::processInput() { ScummEngine::processInput(); } +#ifdef ENABLE_SCUMM_7_8 +void ScummEngine_v7::processInput() { + ScummEngine::processInput(); + + if (_skipVideo && !_smushActive) { + abortCutscene(); + _mouseAndKeyboardStat = Common::ASCII_ESCAPE; + _skipVideo = false; + } +} +#endif + void ScummEngine::processInput() { Common::KeyState lastKeyHit = _keyPressed; _keyPressed.reset(); @@ -364,9 +404,10 @@ void ScummEngine_v7::processKeyboard(Common::KeyState lastKeyHit) { _insane->escapeKeyHandler(); else _smushVideoShouldFinish = true; - } - if (!_smushActive || _smushVideoShouldFinish) + _skipVideo = true; + } else { abortCutscene(); + } _mouseAndKeyboardStat = Common::ASCII_ESCAPE; diff --git a/engines/scumm/object.cpp b/engines/scumm/object.cpp index 372fcd9e45..f29be071e0 100644 --- a/engines/scumm/object.cpp +++ b/engines/scumm/object.cpp @@ -1816,9 +1816,8 @@ void ScummEngine::loadFlObject(uint object, uint room) { assert(flob); // Copy object code + object image to floating object - ((uint32 *)flob)[0] = MKID_BE('FLOB'); - ((uint32 *)flob)[1] = TO_BE_32(flob_size); - + WRITE_UINT32(flob, MKID_BE('FLOB')); + WRITE_BE_UINT32(flob + 4, flob_size); memcpy(flob + 8, foir.obcd, obcd_size); memcpy(flob + 8 + obcd_size, foir.obim, obim_size); diff --git a/engines/scumm/palette.cpp b/engines/scumm/palette.cpp index 44249a8715..6adf5c524e 100644 --- a/engines/scumm/palette.cpp +++ b/engines/scumm/palette.cpp @@ -417,13 +417,9 @@ void ScummEngine::moveMemInPalRes(int start, int end, byte direction) { } void ScummEngine::palManipulateInit(int resID, int start, int end, int time) { - byte *pal, *target, *between; - byte *string1, *string2, *string3; - int i; - - string1 = getStringAddress(resID); - string2 = getStringAddress(resID + 1); - string3 = getStringAddress(resID + 2); + byte *string1 = getStringAddress(resID); + byte *string2 = getStringAddress(resID + 1); + byte *string3 = getStringAddress(resID + 2); if (!string1 || !string2 || !string3) { error("palManipulateInit(%d,%d,%d,%d): Cannot obtain string resources %d, %d and %d", resID, start, end, time, resID, resID + 1, resID + 2); @@ -443,29 +439,24 @@ void ScummEngine::palManipulateInit(int resID, int start, int end, int time) { if (!_palManipIntermediatePal) _palManipIntermediatePal = (byte *)calloc(0x600, 1); - pal = _currentPalette + start * 3; - target = _palManipPalette + start * 3; - between = _palManipIntermediatePal + start * 6; + byte *pal = _currentPalette + start * 3; + byte *target = _palManipPalette + start * 3; + uint16 *between = (uint16 *)(_palManipIntermediatePal + start * 6); - for (i = start; i < end; ++i) { + for (int i = start; i < end; ++i) { *target++ = *string1++; *target++ = *string2++; *target++ = *string3++; - *(uint16 *)between = ((uint16) *pal++) << 8; - between += 2; - *(uint16 *)between = ((uint16) *pal++) << 8; - between += 2; - *(uint16 *)between = ((uint16) *pal++) << 8; - between += 2; + *between++ = ((uint16) *pal++) << 8; + *between++ = ((uint16) *pal++) << 8; + *between++ = ((uint16) *pal++) << 8; } _palManipCounter = time; } void ScummEngine_v6::palManipulateInit(int resID, int start, int end, int time) { - byte *pal, *target, *between; const byte *new_pal; - int i; new_pal = getPalettePtr(resID, _roomResource); @@ -480,20 +471,17 @@ void ScummEngine_v6::palManipulateInit(int resID, int start, int end, int time) if (!_palManipIntermediatePal) _palManipIntermediatePal = (byte *)calloc(0x600, 1); - pal = _currentPalette + start * 3; - target = _palManipPalette + start * 3; - between = _palManipIntermediatePal + start * 6; + byte *pal = _currentPalette + start * 3; + byte *target = _palManipPalette + start * 3; + uint16 *between = (uint16 *)(_palManipIntermediatePal + start * 6); - for (i = start; i < end; ++i) { + for (int i = start; i < end; ++i) { *target++ = *new_pal++; *target++ = *new_pal++; *target++ = *new_pal++; - *(uint16 *)between = ((uint16) *pal++) << 8; - between += 2; - *(uint16 *)between = ((uint16) *pal++) << 8; - between += 2; - *(uint16 *)between = ((uint16) *pal++) << 8; - between += 2; + *between++ = ((uint16) *pal++) << 8; + *between++ = ((uint16) *pal++) << 8; + *between++ = ((uint16) *pal++) << 8; } _palManipCounter = time; @@ -501,26 +489,24 @@ void ScummEngine_v6::palManipulateInit(int resID, int start, int end, int time) void ScummEngine::palManipulate() { - byte *target, *pal, *between; - int i, j; - if (!_palManipCounter || !_palManipPalette || !_palManipIntermediatePal) return; - target = _palManipPalette + _palManipStart * 3; - pal = _currentPalette + _palManipStart * 3; - between = _palManipIntermediatePal + _palManipStart * 6; + byte *target = _palManipPalette + _palManipStart * 3; + byte *pal = _currentPalette + _palManipStart * 3; + uint16 *between = (uint16 *)(_palManipIntermediatePal + _palManipStart * 6); - for (i = _palManipStart; i < _palManipEnd; ++i) { - j = (*((uint16 *)between) += ((*target++ << 8) - *((uint16 *)between)) / _palManipCounter); + for (int i = _palManipStart; i < _palManipEnd; ++i) { + int j; + j = (*between += ((*target++ << 8) - *between) / _palManipCounter); *pal++ = j >> 8; - between += 2; - j = (*((uint16 *)between) += ((*target++ << 8) - *((uint16 *)between)) / _palManipCounter); + between++; + j = (*between += ((*target++ << 8) - *between) / _palManipCounter); *pal++ = j >> 8; - between += 2; - j = (*((uint16 *)between) += ((*target++ << 8) - *((uint16 *)between)) / _palManipCounter); + between++; + j = (*between += ((*target++ << 8) - *between) / _palManipCounter); *pal++ = j >> 8; - between += 2; + between++; } setDirtyColors(_palManipStart, _palManipEnd); _palManipCounter--; diff --git a/engines/scumm/player_v2.h b/engines/scumm/player_v2.h index f0e14cdde3..5b375fb1e5 100644 --- a/engines/scumm/player_v2.h +++ b/engines/scumm/player_v2.h @@ -242,8 +242,8 @@ protected: Voice2 _cmsVoices[8]; MusicChip _cmsChips[2]; - char _tempo; - char _tempoSum; + int8 _tempo; + int8 _tempoSum; byte _looping; byte _octaveMask; int16 _midiDelay; diff --git a/engines/scumm/player_v2cms.cpp b/engines/scumm/player_v2cms.cpp index 97efb4dc63..d628293d7d 100644 --- a/engines/scumm/player_v2cms.cpp +++ b/engines/scumm/player_v2cms.cpp @@ -1428,6 +1428,10 @@ int Player_V2CMS::readBuffer(int16 *buffer, const int numSamples) { } _tempoSum += _tempo; + // FIXME: _tempoSum is declared as char; on some systems char is unsigned. + // E.g. on OS X. Hence the following check is always false. + // Moral of the story: Use uint8, int8 or any of the other types provided by + // ScummVM if you want to ensure signedness and number of available bits. if (_tempoSum < 0) { // this have to be called in the same rate as in the original (I think) processMidiData(1); diff --git a/engines/scumm/resource.cpp b/engines/scumm/resource.cpp index 874b787615..88802a205f 100644 --- a/engines/scumm/resource.cpp +++ b/engines/scumm/resource.cpp @@ -787,8 +787,6 @@ void ResourceManager::setResourceCounter(int type, int idx, byte flag) { #define SAFETY_AREA 2 byte *ResourceManager::createResource(int type, int idx, uint32 size) { - byte *ptr; - debugC(DEBUG_RESOURCE, "_res->createResource(%s,%d,%d)", resTypeFromId(type), idx, size); if (!validateResource("allocating", type, idx)) @@ -807,17 +805,17 @@ byte *ResourceManager::createResource(int type, int idx, uint32 size) { expireResources(size); - ptr = (byte *)calloc(size + sizeof(MemBlkHeader) + SAFETY_AREA, 1); + void *ptr = calloc(size + sizeof(MemBlkHeader) + SAFETY_AREA, 1); if (ptr == NULL) { error("createResource(%s,%d): Out of memory while allocating %d", resTypeFromId(type), idx, size); } _allocatedSize += size; - address[type][idx] = ptr; + address[type][idx] = (byte *)ptr; ((MemBlkHeader *)ptr)->size = size; setResourceCounter(type, idx, 1); - return ptr + sizeof(MemBlkHeader); /* skip header */ + return (byte *)ptr + sizeof(MemBlkHeader); /* skip header */ } ResourceManager::ResourceManager(ScummEngine *vm) { @@ -1374,7 +1372,7 @@ const byte *ResourceIterator::findNext(uint32 tag) { const byte *ScummEngine::findResource(uint32 tag, const byte *searchin) { uint32 curpos, totalsize, size; - debugC(DEBUG_RESOURCE, "findResource(%s, %lx)", tag2str(tag), searchin); + debugC(DEBUG_RESOURCE, "findResource(%s, %p)", tag2str(tag), (const void *)searchin); if (!searchin) { if (_game.heversion >= 70) { diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index cef13341b5..d474a43b05 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -137,7 +137,7 @@ bool ScummEngine::saveState(Common::OutSaveFile *out, bool writeHeader) { memcpy(hdr.name, _saveLoadName, sizeof(hdr.name)); saveSaveGameHeader(out, hdr); } -#if !defined(__DS__) +#if !defined(__DS__) /* && !defined(__PLAYSTATION2__) */ Graphics::saveThumbnail(*out); #endif saveInfos(out); diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp index c70c819b69..4d9447bee5 100644 --- a/engines/scumm/script.cpp +++ b/engines/scumm/script.cpp @@ -462,7 +462,7 @@ void ScummEngine::executeScript() { vm.slot[_currentScript].didexec = true; debugC(DEBUG_OPCODES, "Script %d, offset 0x%x: [%X] %s()", vm.slot[_currentScript].number, - _scriptPointer - _scriptOrgPointer, + (uint)(_scriptPointer - _scriptOrgPointer), _opcode, getOpcodeDesc(_opcode)); if (_hexdumpScripts == true) { @@ -1367,17 +1367,6 @@ void ScummEngine::abortCutscene() { VAR(VAR_OVERRIDE) = 1; vm.cutScenePtr[idx] = 0; - - // HACK to fix issues with SMUSH and the way it does keyboard handling. - // In particular, normally abortCutscene() is being called while no - // scripts are active. But SMUSH runs from *inside* the script engine. - // And it calls abortCutscene() if ESC is pressed... not good. - // Proper fix might be to let SMUSH/INSANE run from outside the script - // engine but that would require lots of changes and may actually have - // negative effects, too. So we cheat here, to fix bug #751670. - if (_game.version == 7) - getScriptEntryPoint(); - } } diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp index 00d01143d6..1ce38fd800 100644 --- a/engines/scumm/script_v5.cpp +++ b/engines/scumm/script_v5.cpp @@ -1750,7 +1750,7 @@ void ScummEngine_v5::o5_roomOps() { while ((chr = fetchScriptByte())) filename += chr; - if (filename.hasPrefix("iq-") || filename.hasPrefix("IQ-") || filename.hasSuffix("-iq")) { + if (filename.hasPrefix("iq-") || filename.hasPrefix("IQ-") || filename.hasSuffix("-iq") || filename.hasSuffix("-IQ")) { filename = _targetName + ".iq"; } else { error("SO_SAVE_STRING: Unsupported filename %s", filename.c_str()); diff --git a/engines/scumm/script_v6.cpp b/engines/scumm/script_v6.cpp index c23a64be5b..dcd60352c7 100644 --- a/engines/scumm/script_v6.cpp +++ b/engines/scumm/script_v6.cpp @@ -1396,6 +1396,7 @@ void ScummEngine_v6::o6_getVerbFromXY() { void ScummEngine_v6::o6_beginOverride() { beginOverride(); + _skipVideo = 0; } void ScummEngine_v6::o6_endOverride() { @@ -2457,7 +2458,7 @@ void ScummEngine_v7::o6_kernelSetFunctions() { break; case 6: { // SMUSH movie playback - if (args[1] == 0) { + if (args[1] == 0 && !_skipVideo) { const char *videoname = (const char *)getStringAddressVar(VAR_VIDEONAME); assert(videoname); @@ -2474,7 +2475,7 @@ void ScummEngine_v7::o6_kernelSetFunctions() { if (_game.id == GID_DIG) { _disableFadeInEffect = true; } - } else if (_game.id == GID_FT) { + } else if (_game.id == GID_FT && !_skipVideo) { const int insaneVarNum = ((_game.features & GF_DEMO) && (_game.platform == Common::kPlatformPC)) ? 232 : 233; diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index 8ab4e00caa..5bb0e097dc 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Fri May 15 10:19:51 2009 + This file was generated by the md5table tool on Sat Jul 11 01:37:44 2009 DO NOT EDIT MANUALLY! */ @@ -20,7 +20,7 @@ static const MD5Table md5table[] = { { "035deab53b47bc43abc763560d0f8d4b", "atlantis", "", "Demo", -1, Common::EN_ANY, Common::kPlatformPC }, { "037385a953789190298494d92b89b3d0", "catalog", "HE 72", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, { "03d3b18ee3fd68114e2a687c871e38d5", "freddi4", "HE 99", "Mini Game", -1, Common::EN_USA, Common::kPlatformWindows }, - { "0425954a9db5c340861672892c3e678d", "samnmax", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, + { "0425954a9db5c340861672892c3e678d", "samnmax", "CD", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "04401d747f1a2c1c4b388daff71ed378", "ft", "", "", 535405461, Common::DE_DEU, Common::kPlatformMacintosh }, { "04687cdf7f975a89d2474929f7b80946", "indy3", "FM-TOWNS", "", 7552, Common::EN_ANY, Common::kPlatformFMTowns }, { "0557df19f046a84c2fdc63507c6616cb", "farm", "HE 72", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows }, @@ -53,10 +53,10 @@ static const MD5Table md5table[] = { { "0e96ab45a4eb72acc1b46813976589fd", "activity", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "0e9b01430e31d9fcd94071d433bbc6bf", "loom", "No Adlib", "EGA", -1, Common::FR_FRA, Common::kPlatformAtariST }, { "0f5935bd5e88ba6f09e558d64459746d", "thinker1", "", "Demo", 30919, Common::EN_USA, Common::kPlatformWindows }, - { "0f6f2e716ba896a44e5059bba1de7ca9", "samnmax", "", "CD", -1, Common::IT_ITA, Common::kPlatformUnknown }, + { "0f6f2e716ba896a44e5059bba1de7ca9", "samnmax", "CD", "CD", -1, Common::IT_ITA, Common::kPlatformUnknown }, { "0f9c7a76657f0840b8f7ccb5bffeb9f4", "indy3", "No Adlib", "EGA", -1, Common::FR_FRA, Common::kPlatformAtariST }, { "0f9d3317910ac7a9f449243118884ada", "puttzoo", "", "", 42070, Common::DE_DEU, Common::kPlatformWindows }, - { "0fb73eddfcf584c02ba097984df131ba", "samnmax", "", "CD", 9080, Common::DE_DEU, Common::kPlatformUnknown }, + { "0fb73eddfcf584c02ba097984df131ba", "samnmax", "CD", "CD", 9080, Common::DE_DEU, Common::kPlatformUnknown }, { "1005456bfe351c1b679e1ff2dc2849e9", "puttzoo", "", "", -1, Common::UNK_LANG, Common::kPlatformWindows }, { "100b4c8403ad6a83d4bf7dbf83e44dc4", "spyfox", "", "", -1, Common::FR_FRA, Common::kPlatformWindows }, { "10d8e66cd11049ce64815ebb9fd76eb3", "spyozon", "", "", -1, Common::FR_FRA, Common::kPlatformUnknown }, @@ -74,20 +74,20 @@ static const MD5Table md5table[] = { { "15e03ffbfeddb9c2aebc13dcb2a4a8f4", "monkey", "VGA", "VGA", 8357, Common::EN_ANY, Common::kPlatformPC }, { "15f588e887e857e8c56fe6ade4956168", "atlantis", "", "Floppy", -1, Common::ES_ESP, Common::kPlatformAmiga }, { "16542a7342a918bfe4ba512007d36c47", "FreddisFunShop", "HE 99L", "", -1, Common::EN_USA, Common::kPlatformUnknown }, - { "166553538ff320c69edafeee29525419", "samnmax", "", "CD", -1, Common::EN_ANY, Common::kPlatformMacintosh }, + { "166553538ff320c69edafeee29525419", "samnmax", "CD", "CD", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "16effd200aa6b8abe9c569c3e578814d", "freddi4", "HE 99", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows }, { "179879b6e35c1ead0d93aab26db0951b", "fbear", "HE 70", "", 13381, Common::EN_ANY, Common::kPlatformWindows }, { "17b5d5e6af4ae89d62631641d66d5a05", "indy3", "VGA", "VGA", -1, Common::IT_ITA, Common::kPlatformPC }, { "17f7296f63c78642724f057fd8e736a7", "maniac", "NES", "extracted", -1, Common::EN_GRB, Common::kPlatformNES }, - { "17fa250eb72dae2dad511ba79c0b6b0a", "tentacle", "", "Demo", -1, Common::FR_FRA, Common::kPlatformPC }, - { "182344899c2e2998fca0bebcd82aa81a", "atlantis", "", "CD", 12035, Common::EN_ANY, Common::kPlatformPC }, + { "17fa250eb72dae2dad511ba79c0b6b0a", "tentacle", "CD", "Demo", -1, Common::FR_FRA, Common::kPlatformPC }, + { "182344899c2e2998fca0bebcd82aa81a", "atlantis", "CD", "CD", 12035, Common::EN_ANY, Common::kPlatformPC }, { "183d7464902d40d00800e8ee1f04117c", "maniac", "V2", "V2", 1988, Common::DE_DEU, Common::kPlatformPC }, { "1875b90fade138c9253a8e967007031a", "indy3", "VGA", "VGA", 6295, Common::EN_ANY, Common::kPlatformPC }, { "187d315f6b5168f68680dfe8c3d76a3e", "loom", "EGA", "EGA", -1, Common::HB_ISR, Common::kPlatformPC }, { "1900e501a52fbf55bde6e4196f6d2aa6", "zak", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformPC }, { "19263586f749a560c1adf8b3393a9593", "socks", "HE 85", "", -1, Common::RU_RUS, Common::kPlatformWindows }, { "19bf6938a94698296bcb0c99c31c91a7", "spyfox2", "", "Demo", -1, Common::EN_GRB, Common::kPlatformWindows }, - { "1a6e5ae2777a6a33f06ffc0226210934", "atlantis", "", "CD", -1, Common::EN_ANY, Common::kPlatformMacintosh }, + { "1a6e5ae2777a6a33f06ffc0226210934", "atlantis", "CD", "CD", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "1c792d28376d45e145cb916bca0400a2", "spyfox2", "", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "1c7e7db2cfab1ad62746ab680a634204", "maniac", "NES", "extracted", -1, Common::FR_FRA, Common::kPlatformNES }, { "1ca86e2cf9aaa2068738a1e5ba477e60", "zak", "FM-TOWNS", "", -1, Common::JA_JPN, Common::kPlatformFMTowns }, @@ -117,11 +117,11 @@ static const MD5Table md5table[] = { { "2723fea3dae0cb47768c424b145ae0e7", "tentacle", "", "Floppy", 7932, Common::EN_ANY, Common::kPlatformPC }, { "27b2ef1653089fe5b897d9cc89ce784f", "balloon", "HE 80", "", -1, Common::RU_RUS, Common::kPlatformWindows }, { "27b3a4224ad63d5b04627595c1c1a025", "zak", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformAmiga }, - { "28d24a33448fab6795850bc9f159a4a2", "atlantis", "", "Demo", 11170, Common::JA_JPN, Common::kPlatformFMTowns }, + { "28d24a33448fab6795850bc9f159a4a2", "atlantis", "CD", "Demo", 11170, Common::JA_JPN, Common::kPlatformFMTowns }, { "28ef68ee3ed76d7e2ee8ee13c15fbd5b", "loom", "EGA", "EGA", 5748, Common::EN_ANY, Common::kPlatformPC }, { "28f07458f1b6c24e118a1ea056827701", "lost", "HE 99", "", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "2a208ffbcd0e83e86f4356e6f64aa6e1", "loom", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformPC }, - { "2a41b53cf1a90b6e6f26c10cc6041084", "tentacle", "", "Demo", 2439158, Common::EN_ANY, Common::kPlatformMacintosh }, + { "2a41b53cf1a90b6e6f26c10cc6041084", "tentacle", "CD", "Demo", 2439158, Common::EN_ANY, Common::kPlatformMacintosh }, { "2a446817ffcabfef8716e0c456ecaf81", "puttzoo", "", "Demo", -1, Common::DE_DEU, Common::kPlatformWindows }, { "2a8658dbd13d84d1bce64a71a35995eb", "pajama2", "HE 99", "Demo", -1, Common::HB_ISR, Common::kPlatformWindows }, { "2c04aacffb8428f30ccf4f734fbe3adc", "activity", "", "", -1, Common::EN_ANY, Common::kPlatformPC }, @@ -130,7 +130,7 @@ static const MD5Table md5table[] = { { "2d388339d6050d8ccaa757b64633954e", "zak", "FM-TOWNS", "Demo", 7520, Common::EN_ANY, Common::kPlatformFMTowns }, { "2d4536a56e01da4b02eb021e7770afa2", "zak", "FM-TOWNS", "", 7520, Common::EN_ANY, Common::kPlatformFMTowns }, { "2d4acbdcfd8e374c9da8c2e7303a5cd0", "BluesBirthday", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, - { "2d9d46f23cb07bbc90b8ad464d3e4ff8", "atlantis", "", "CD", -1, Common::EN_ANY, Common::kPlatformMacintosh }, + { "2d9d46f23cb07bbc90b8ad464d3e4ff8", "atlantis", "CD", "CD", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "2e85f7aa054930c692a5b1bed1dfc295", "football2002", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "2e8a1f76ea33bc5e04347646feee173d", "pajama3", "", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, { "2fe369ad70f52a8cf7ad6077ee64f81a", "loom", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformAmiga }, @@ -165,7 +165,7 @@ static const MD5Table md5table[] = { { "3a03dab514e4038df192d8a8de469788", "atlantis", "", "Floppy", -1, Common::EN_ANY, Common::kPlatformAmiga }, { "3a0c35f3c147b98a2bdf8d400cfc4ab5", "indy3", "FM-TOWNS", "", -1, Common::JA_JPN, Common::kPlatformFMTowns }, { "3a3e592b074f595489f7f11e150c398d", "puttzoo", "HE 99", "Updated", -1, Common::EN_USA, Common::kPlatformWindows }, - { "3a5d13675e9a23aedac0bac7730f0ac1", "samnmax", "", "CD", -1, Common::FR_FRA, Common::kPlatformMacintosh }, + { "3a5d13675e9a23aedac0bac7730f0ac1", "samnmax", "CD", "CD", -1, Common::FR_FRA, Common::kPlatformMacintosh }, { "3a5ec90d556d4920976c5578bfbfaf79", "maniac", "NES", "extracted", -1, Common::DE_DEU, Common::kPlatformNES }, { "3af61c5edf8e15b43dbafd285b2e9777", "puttcircus", "", "Demo", -1, Common::HB_ISR, Common::kPlatformWindows }, { "3b301b7892f883ce42ab4be6a274fea6", "samnmax", "", "Floppy", -1, Common::EN_ANY, Common::kPlatformPC }, @@ -176,7 +176,7 @@ static const MD5Table md5table[] = { { "3df6ead57930488bc61e6e41901d0e97", "fbear", "HE 61", "", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "3e48298920fab9b7aec5a971e1bd1fab", "pajama3", "", "Demo", -1, Common::EN_GRB, Common::kPlatformWindows }, { "40564ec47da48a67787d1f9bd043902a", "maniac", "V2 Demo", "V2 Demo", 1988, Common::EN_ANY, Common::kPlatformPC }, - { "4167a92a1d46baa4f4127d918d561f88", "tentacle", "", "CD", 7932, Common::EN_ANY, Common::kPlatformUnknown }, + { "4167a92a1d46baa4f4127d918d561f88", "tentacle", "CD", "CD", 7932, Common::EN_ANY, Common::kPlatformUnknown }, { "41958e24d03181ff9a381a66d048a581", "ft", "", "", -1, Common::PT_BRA, Common::kPlatformUnknown }, { "425205754fa749f4f0b0dd9d09fa45fd", "football", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "430bc518017b6fac046f58bab6baad5d", "monkey2", "", "", -1, Common::JA_JPN, Common::kPlatformFMTowns }, @@ -195,13 +195,13 @@ static const MD5Table md5table[] = { { "4aa93cb30e485b728504ba3a693f12bf", "pajama", "HE 100", "", -1, Common::RU_RUS, Common::kPlatformWindows }, { "4af4a6b248103c1fe9edef619677f540", "puttmoon", "", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "4ba37f835be11a59d969f90f272f575b", "water", "HE 80", "", -1, Common::EN_USA, Common::kPlatformUnknown }, - { "4ba7fb331296c283e73d8f5b2096e551", "samnmax", "", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown }, + { "4ba7fb331296c283e73d8f5b2096e551", "samnmax", "CD", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown }, { "4bedb49943df95a9c900a5a82ccbe9de", "ft", "", "", -1, Common::FR_FRA, Common::kPlatformUnknown }, { "4bfa4a43684bcb437f7fb47f457a0aa5", "socks", "HE 99", "", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "4c4820518e16e1a0e3616a3b021a04f3", "catalog", "HE CUP", "Preview", 10927456, Common::DE_DEU, Common::kPlatformUnknown }, { "4cb9c3618f71668f8e4346c8f323fa82", "monkey2", "", "", 10700, Common::EN_ANY, Common::kPlatformMacintosh }, { "4ce2d5b355964bbcb5e5ce73236ef868", "freddicove", "HE 100", "", -1, Common::RU_RUS, Common::kPlatformWindows }, - { "4d34042713958b971cb139fba4658586", "atlantis", "", "", -1, Common::JA_JPN, Common::kPlatformFMTowns }, + { "4d34042713958b971cb139fba4658586", "atlantis", "CD", "", -1, Common::JA_JPN, Common::kPlatformFMTowns }, { "4dbff3787aedcd96b0b325f2d92d7ad9", "maze", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown }, { "4dc780f1bc587a193ce8a97652791438", "loom", "EGA", "EGA", -1, Common::EN_ANY, Common::kPlatformAmiga }, { "4e5867848ee61bc30d157e2c94eee9b4", "PuttTime", "HE 90", "Demo", 18394, Common::EN_USA, Common::kPlatformUnknown }, @@ -212,7 +212,7 @@ static const MD5Table md5table[] = { { "4f267a901719623de7dde83e47d5b474", "atlantis", "", "Floppy", -1, Common::DE_DEU, Common::kPlatformAmiga }, { "4f580a021eee026f3b4589e17d130d78", "freddi4", "", "", -1, Common::UNK_LANG, Common::kPlatformUnknown }, { "4fa6870d9bc8c313b65d54b1da5a1891", "pajama", "", "", -1, Common::NL_NLD, Common::kPlatformWindows }, - { "4fbbe9f64b8bc547503a379a301183ce", "tentacle", "", "CD", -1, Common::IT_ITA, Common::kPlatformUnknown }, + { "4fbbe9f64b8bc547503a379a301183ce", "tentacle", "CD", "CD", -1, Common::IT_ITA, Common::kPlatformUnknown }, { "4fe6a2e8df3c4536b278fdd2fbcb181e", "pajama3", "", "Mini Game", -1, Common::EN_ANY, Common::kPlatformWindows }, { "5057fb0e99e5aa29df1836329232f101", "freddi2", "HE 80", "", -1, Common::UNK_LANG, Common::kPlatformWindows }, { "507bb360688dc4180fdf0d7597352a69", "freddi", "HE 73", "", 26402, Common::SE_SWE, Common::kPlatformWindows }, @@ -289,9 +289,9 @@ static const MD5Table md5table[] = { { "6bf70eee5de3d24d2403e0dd3d267e8a", "spyfox", "", "", 49221, Common::UNK_LANG, Common::kPlatformWindows }, { "6c2bff0e327f2962e809c2e1a82d7309", "monkey", "VGA", "VGA", -1, Common::EN_ANY, Common::kPlatformAmiga }, { "6d1baa1065ac5f7b210be8ebe4235e49", "freddi", "HE 73", "", -1, Common::NL_NLD, Common::kPlatformMacintosh }, - { "6dead580b0ff14d5f7b33b4219f04159", "samnmax", "", "Demo", 16556335, Common::EN_ANY, Common::kPlatformMacintosh }, + { "6dead580b0ff14d5f7b33b4219f04159", "samnmax", "CD", "Demo", 16556335, Common::EN_ANY, Common::kPlatformMacintosh }, { "6df20c50c1ab19799de9be7ae7716881", "fbear", "HE 61", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, - { "6e959d65358eedf9b68b81e304b97fa4", "tentacle", "", "CD", 7932, Common::DE_DEU, Common::kPlatformUnknown }, + { "6e959d65358eedf9b68b81e304b97fa4", "tentacle", "CD", "CD", 7932, Common::DE_DEU, Common::kPlatformUnknown }, { "6ea966b4d660c870b9ee790d1fbfc535", "monkey2", "", "", -1, Common::ES_ESP, Common::kPlatformAmiga }, { "6f0be328c64d689bb606d22a389e1b0f", "loom", "No Adlib", "EGA", 5748, Common::EN_ANY, Common::kPlatformMacintosh }, { "6f6ef668c608c7f534fea6e6d3878dde", "indy3", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformPC }, @@ -332,7 +332,7 @@ static const MD5Table md5table[] = { { "7ddeaf52c8b9a50551ce0aa2ac811d07", "BluesABCTime", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "7e151c17adf624f1966c8fc5827c95e9", "puttputt", "HE 61", "", -1, Common::EN_ANY, Common::kPlatform3DO }, { "7ea2da67ebabea4ac20cee9f4f9d2934", "airport", "", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, - { "7edd665bbede7ea8b7233f8e650be6f8", "samnmax", "", "CD", -1, Common::FR_FRA, Common::kPlatformUnknown }, + { "7edd665bbede7ea8b7233f8e650be6f8", "samnmax", "CD", "CD", -1, Common::FR_FRA, Common::kPlatformUnknown }, { "7f45ddd6dbfbf8f80c0c0efea4c295bc", "maniac", "V1", "V1", 1972, Common::EN_ANY, Common::kPlatformPC }, { "7f945525abcd48015adf1632637a44a1", "pajama", "", "Demo", -1, Common::FR_FRA, Common::kPlatformUnknown }, { "7fc6cdb46b4c9d384c52327f4bca6416", "football", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, @@ -354,12 +354,12 @@ static const MD5Table md5table[] = { { "87df3e0074624040407764b7c5e710b9", "pajama", "", "Demo", 18354, Common::NL_NLD, Common::kPlatformWindows }, { "87f6e8037b7cc996e13474b491a7a98e", "maniac", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformPC }, { "8801fb4a1200b347f7a38523339526dd", "jungle", "", "", -1, Common::EN_ANY, Common::kPlatformWindows }, - { "883af4b0af4f77a92f1dcf1d0a283140", "tentacle", "", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown }, + { "883af4b0af4f77a92f1dcf1d0a283140", "tentacle", "CD", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown }, { "898ce8eb1234a955ef75e87141902bb3", "freddi3", "", "", -1, Common::RU_RUS, Common::kPlatformWindows }, { "898eaa21f79cf8d4f08db856244689ff", "pajama", "HE 99", "Updated", 66505, Common::EN_ANY, Common::kPlatformWindows }, { "89cfc425566003ff74b7dc7b3e6fd469", "indy3", "EGA", "EGA", -1, Common::FR_FRA, Common::kPlatformPC }, { "8a484262363a8e18be87112454f1456b", "pjgames", "", "", -1, Common::EN_USA, Common::kPlatformUnknown }, - { "8aa05d3cdb0e795436043f0546af2da2", "tentacle", "", "CD?", -1, Common::FR_FRA, Common::kPlatformUnknown }, + { "8aa05d3cdb0e795436043f0546af2da2", "tentacle", "CD", "CD?", -1, Common::FR_FRA, Common::kPlatformUnknown }, { "8aed489aba45d2b9fb8a04079c9c6e6a", "baseball", "HE CUP", "Preview", 12876596, Common::UNK_LANG, Common::kPlatformUnknown }, { "8afb3cf9f95abf208358e984f0c9e738", "funpack", "", "", -1, Common::EN_ANY, Common::kPlatform3DO }, { "8bdb0bf87b5e303dd35693afb9351215", "ft", "", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, @@ -367,7 +367,7 @@ static const MD5Table md5table[] = { { "8de13897f0121c79d29a2377159f9ad0", "socks", "HE 99", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows }, { "8e3241ddd6c8dadf64305e8740d45e13", "balloon", "HE 100", "Updated", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "8e4ee4db46954bfe2912e259a16fad82", "monkey2", "", "", -1, Common::FR_FRA, Common::kPlatformPC }, - { "8e9417564f33790815445b2136efa667", "atlantis", "", "CD", 11915, Common::JA_JPN, Common::kPlatformMacintosh }, + { "8e9417564f33790815445b2136efa667", "atlantis", "CD", "CD", 11915, Common::JA_JPN, Common::kPlatformMacintosh }, { "8e9830a6f2702be5b22c8fa0a6aaf977", "freddi2", "HE 80", "", -1, Common::NL_NLD, Common::kPlatformMacintosh }, { "8eb84cee9b429314c7f0bdcf560723eb", "monkey", "FM-TOWNS", "", -1, Common::EN_ANY, Common::kPlatformFMTowns }, { "8ee63cafb1fe9d62aa0d5a23117e70e7", "freddi2", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown }, @@ -395,7 +395,7 @@ static const MD5Table md5table[] = { { "98744fe66ff730e8c2b3b1f58803ab0b", "atlantis", "", "Demo", -1, Common::EN_ANY, Common::kPlatformPC }, { "99128b6a5bdd9831d9682fb8b5cbf8d4", "BluesBirthday", "", "Yellow", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "99a3699f80b8f776efae592b44b9b991", "maniac", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformPC }, - { "99b6f822b0b2612415407865438697d6", "atlantis", "", "Demo", -1, Common::EN_ANY, Common::kPlatformPC }, + { "99b6f822b0b2612415407865438697d6", "atlantis", "CD", "Demo", -1, Common::EN_ANY, Common::kPlatformPC }, { "9b7452b5cd6d3ffb2b2f5118010af84f", "ft", "Demo", "Demo", 116463537, Common::EN_ANY, Common::kPlatformMacintosh }, { "9bc548e179cdb0767009401c094d0895", "maniac", "V2", "V2", -1, Common::DE_DEU, Common::kPlatformAmiga }, { "9bd2a8f72613e715c199246dd511e10f", "atlantis", "", "Floppy", -1, Common::ES_ESP, Common::kPlatformPC }, @@ -441,7 +441,7 @@ static const MD5Table md5table[] = { { "aaa587701cde7e74692c68c1024b85eb", "puttrace", "HE 99", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "aaa7f36a253f277dd29dd1c051b0e4b9", "indy3", "No Adlib", "EGA", -1, Common::DE_DEU, Common::kPlatformAtariST }, { "ab0693e9324cfcf498fdcbb12acf8bb4", "puttcircus", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, - { "ac1642b6edfb8521ca03760126f1c250", "tentacle", "", "Demo", -1, Common::DE_DEU, Common::kPlatformPC }, + { "ac1642b6edfb8521ca03760126f1c250", "tentacle", "CD", "Demo", -1, Common::DE_DEU, Common::kPlatformPC }, { "ac62d50e39492ee3738b4e83a5ac780f", "freddi2", "HE 80", "", -1, Common::NL_NLD, Common::kPlatformWindows }, { "acad97ab1c6fc2a5b2d98abf6db4a190", "tentacle", "", "Floppy", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "ae94f110a14ce71fc515d5b648827a8f", "tentacle", "", "Floppy", -1, Common::ES_ESP, Common::kPlatformPC }, @@ -492,15 +492,15 @@ static const MD5Table md5table[] = { { "c6907d44f1166941d982864cd42cdc89", "pajama2", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, { "c782fbbe74a987c3df8ac73cd3e289ed", "freddi", "HE 73", "", -1, Common::SE_SWE, Common::kPlatformMacintosh }, { "c7890e038806df2bb5c0c8c6f1986ea2", "monkey", "VGA", "VGA", -1, Common::EN_ANY, Common::kPlatformPC }, - { "c7be10f775404fd9785a8b92a06d240c", "atlantis", "", "", -1, Common::EN_ANY, Common::kPlatformFMTowns }, + { "c7be10f775404fd9785a8b92a06d240c", "atlantis", "CD", "", -1, Common::EN_ANY, Common::kPlatformFMTowns }, { "c7c492a107ec520d7a7943037d0ca54a", "freddi", "HE 71", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows }, - { "c83079157ec765a28de445aec9768d60", "tentacle", "", "Demo", 7477, Common::EN_ANY, Common::kPlatformUnknown }, + { "c83079157ec765a28de445aec9768d60", "tentacle", "CD", "Demo", 7477, Common::EN_ANY, Common::kPlatformUnknown }, { "c8575e0b973ff1723aba6cd92c642db2", "puttrace", "HE 99", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, { "c8aac5e3e701874e2fa4117896f9e1b1", "freddi", "HE 73", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "c8c5baadcbfc8d0372ed4335abace8a7", "pajama3", "", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, { "c9717ee6059f1e43b768b464493d2fba", "fbpack", "", "", -1, Common::JA_JPN, Common::kPlatform3DO }, { "cb1559e8405d17a5a278a6b5ad9338d1", "freddi3", "", "Demo", 22718, Common::EN_ANY, Common::kPlatformUnknown }, - { "cc04a076779379524ed4d9c5ee3c6fb1", "tentacle", "", "CD", 282467632, Common::EN_ANY, Common::kPlatformMacintosh }, + { "cc04a076779379524ed4d9c5ee3c6fb1", "tentacle", "CD", "CD", 282467632, Common::EN_ANY, Common::kPlatformMacintosh }, { "cc0c4111449054f1692bb3c0c5e04629", "BluesBirthday", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "cc8ba2b0df2f9c450bcf055fe2711979", "samnmax", "", "Demo", 7485, Common::DE_DEU, Common::kPlatformPC }, { "cd424f143a141bc59226ad83a6e40f51", "maze", "HE 98.5", "", -1, Common::NL_NLD, Common::kPlatformUnknown }, @@ -525,7 +525,7 @@ static const MD5Table md5table[] = { { "d220d154aafbfa12bd6f3ab1b2dae420", "puttzoo", "", "Demo", -1, Common::DE_DEU, Common::kPlatformMacintosh }, { "d2cc8e31bce61e6cf2951249e10638fe", "basketball", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "d37c55388294b66e53e7ced3af88fa68", "freddi2", "HE 100", "Updated Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, - { "d43352a805d78b5f4936c6d7779bf575", "samnmax", "", "CD", -1, Common::RU_RUS, Common::kPlatformPC }, + { "d43352a805d78b5f4936c6d7779bf575", "samnmax", "CD", "CD", -1, Common::RU_RUS, Common::kPlatformPC }, { "d4aac997e2f4e15341f0bfbf905419bd", "PuttTime", "HE 99", "", 62698, Common::EN_GRB, Common::kPlatformWindows }, { "d4b8ee426b1afd3e53bc0cf020418cf6", "dog", "HE 99", "", -1, Common::EN_ANY, Common::kPlatformWindows }, { "d4cccb5af88f3e77f370896e9ba8c5f9", "freddi", "HE 71", "", -1, Common::UNK_LANG, Common::kPlatformWindows }, @@ -543,8 +543,8 @@ static const MD5Table md5table[] = { { "d831f7c048574dd9d5d85db2a1468099", "maniac", "C64", "", -1, Common::EN_ANY, Common::kPlatformC64 }, { "d8323015ecb8b10bf53474f6e6b0ae33", "dig", "", "", 16304, Common::UNK_LANG, Common::kPlatformUnknown }, { "d8d07efcb88f396bee0b402b10c3b1c9", "maniac", "NES", "", 262144, Common::EN_GRB, Common::kPlatformNES }, - { "d917f311a448e3cc7239c31bddb00dd2", "samnmax", "", "CD", 9080, Common::EN_ANY, Common::kPlatformUnknown }, - { "d9d0dd93d16ab4dec55cabc2b86bbd17", "samnmax", "", "Demo", 6478, Common::EN_ANY, Common::kPlatformPC }, + { "d917f311a448e3cc7239c31bddb00dd2", "samnmax", "CD", "CD", 9080, Common::EN_ANY, Common::kPlatformUnknown }, + { "d9d0dd93d16ab4dec55cabc2b86bbd17", "samnmax", "CD", "Demo", 6478, Common::EN_ANY, Common::kPlatformPC }, { "da09e666fc8f5b78d7b0ac65d1a3b56e", "monkey2", "", "", 11135, Common::EN_ANY, Common::kPlatformFMTowns }, { "da6269b18fcb08189c0aa9c95533cce2", "monkey", "CD", "CD", 8955, Common::IT_ITA, Common::kPlatformPC }, { "da669b20271b85182e9c17a2a37ea02e", "monkey2", "", "", -1, Common::DE_DEU, Common::kPlatformAmiga }, @@ -584,7 +584,7 @@ static const MD5Table md5table[] = { { "ecc4340c2b801f5af8da4e00c0e432d9", "puttcircus", "", "", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "ed2b074bc3166087a747acb2a3c6abb0", "freddi3", "HE 98.5", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown }, { "ed361270102e355afe5236954216aba2", "lost", "", "", -1, Common::EN_USA, Common::kPlatformUnknown }, - { "ede149fda3edfc1dbd7347e0737cb583", "tentacle", "", "CD", -1, Common::FR_FRA, Common::kPlatformMacintosh }, + { "ede149fda3edfc1dbd7347e0737cb583", "tentacle", "CD", "CD", -1, Common::FR_FRA, Common::kPlatformMacintosh }, { "edfdb24a499d92c59f824c52987c0eec", "atlantis", "", "Floppy", -1, Common::FR_FRA, Common::kPlatformPC }, { "ee41f6afbc5b26fa475754b56fe92048", "puttputt", "HE 61", "", 8032, Common::JA_JPN, Common::kPlatform3DO }, { "ee785fe2569bc9965526e774f7ab86f1", "spyfox", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformMacintosh }, @@ -602,7 +602,7 @@ static const MD5Table md5table[] = { { "f3d55aea441e260e9e9c7d2a187097e0", "puttzoo", "", "Demo", 14337, Common::EN_ANY, Common::kPlatformWindows }, { "f40a7f495f59188ca57a9d1d50301bb6", "puttputt", "Demo", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "f5228b0cc1c19e6ea8268ba2eeb61f60", "freddi", "HE 73", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, - { "f73883f13b5a302749a5bad31d909780", "tentacle", "", "CD", -1, Common::DE_DEU, Common::kPlatformMacintosh }, + { "f73883f13b5a302749a5bad31d909780", "tentacle", "CD", "CD", -1, Common::DE_DEU, Common::kPlatformMacintosh }, { "f7711f9264d4d43c2a1518ec7c10a607", "pajama3", "", "", 79382, Common::EN_USA, Common::kPlatformUnknown }, { "f79e60c17cca601e411f1f75e8ee9b5a", "spyfox2", "", "", 51286, Common::UNK_LANG, Common::kPlatformUnknown }, { "f8be685007a8b425ba2a455da732f59f", "pajama2", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformMacintosh }, diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 6716fda3fd..b02c3b3346 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -443,7 +443,6 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr) VAR_SCRIPT_CYCLE = 0xFF; VAR_NUM_GLOBAL_OBJS = 0xFF; - VAR_KEY_STATE = 0xFF; // Use g_scumm from error() ONLY g_scumm = this; @@ -685,6 +684,7 @@ ScummEngine_v6::ScummEngine_v6(OSystem *syst, const DetectorResult &dr) _curVerbSlot = 0; _forcedWaitForMessage = false; + _skipVideo = false; VAR_VIDEONAME = 0xFF; VAR_RANDOM_NR = 0xFF; @@ -786,6 +786,7 @@ ScummEngine_v80he::ScummEngine_v80he(OSystem *syst, const DetectorResult &dr) VAR_PLATFORM = 0xFF; VAR_PLATFORM_VERSION = 0xFF; VAR_CURRENT_CHARSET = 0xFF; + VAR_KEY_STATE = 0xFF; VAR_COLOR_DEPTH = 0xFF; } diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index b74104ea3c..143051c162 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -28,6 +28,7 @@ #include "engines/engine.h" #include "common/endian.h" +#include "common/events.h" #include "common/file.h" #include "common/savefile.h" #include "common/keyboard.h" @@ -128,7 +129,7 @@ enum GameFeatures { }; /* SCUMM Debug Channels */ -void debugC(int level, const char *s, ...); +void debugC(int level, const char *s, ...) GCC_PRINTF(2, 3); enum { DEBUG_GENERAL = 1 << 0, // General debug @@ -498,6 +499,8 @@ protected: public: void parseEvents(); // Used by IMuseDigital::startSound protected: + virtual void parseEvent(Common::Event event); + void waitForTimer(int msec_delay); virtual void processInput(); virtual void processKeyboard(Common::KeyState lastKeyHit); @@ -528,7 +531,7 @@ protected: void versionDialog(); void scummMenuDialog(); - char displayMessage(const char *altButton, const char *message, ...); + char displayMessage(const char *altButton, const char *message, ...) GCC_PRINTF(3, 4); byte _fastMode; @@ -543,15 +546,13 @@ public: // VAR is a wrapper around scummVar, which attempts to include additional // useful information should an illegal var access be detected. #define VAR(x) scummVar(x, #x, __FILE__, __LINE__) - int32& scummVar(byte var, const char *varName, const char *file, int line) - { + int32& scummVar(byte var, const char *varName, const char *file, int line) { if (var == 0xFF) { error("Illegal access to variable %s in file %s, line %d", varName, file, line); } return _scummVars[var]; } - int32 scummVar(byte var, const char *varName, const char *file, int line) const - { + int32 scummVar(byte var, const char *varName, const char *file, int line) const { if (var == 0xFF) { error("Illegal access to variable %s in file %s, line %d", varName, file, line); } @@ -1378,8 +1379,6 @@ public: byte VAR_SCRIPT_CYCLE; // Used in runScript()/runObjectScript() byte VAR_NUM_SCRIPT_CYCLES; // Used in runAllScripts() - byte VAR_KEY_STATE; // Used in parseEvents() - // Exists both in V7 and in V72HE: byte VAR_NUM_GLOBAL_OBJS; }; diff --git a/engines/scumm/scumm_v6.h b/engines/scumm/scumm_v6.h index d4768a7e92..eb55b83596 100644 --- a/engines/scumm/scumm_v6.h +++ b/engines/scumm/scumm_v6.h @@ -93,6 +93,7 @@ protected: int _curVerbSlot; bool _forcedWaitForMessage; + bool _skipVideo; public: ScummEngine_v6(OSystem *syst, const DetectorResult &dr); diff --git a/engines/scumm/scumm_v7.h b/engines/scumm/scumm_v7.h index fdc1d6de9c..fcadadb04d 100644 --- a/engines/scumm/scumm_v7.h +++ b/engines/scumm/scumm_v7.h @@ -103,6 +103,7 @@ protected: virtual void scummLoop_handleSound(); virtual void scummLoop_handleDrawing(); + virtual void processInput(); virtual void processKeyboard(Common::KeyState lastKeyHit); virtual void setupScumm(); diff --git a/engines/scumm/smush/imuse_channel.cpp b/engines/scumm/smush/imuse_channel.cpp index e39397eded..c1167a57c1 100644 --- a/engines/scumm/smush/imuse_channel.cpp +++ b/engines/scumm/smush/imuse_channel.cpp @@ -158,7 +158,7 @@ void ImuseChannel::decode() { _sbufferSize -= remaining_size; } else { debugC(DEBUG_SMUSH, "impossible ! : %p, %d, %d, %p(%d), %p(%d, %d)", - this, _dataSize, _inData, _tbuffer, _tbufferSize, _sbuffer, _sbufferSize, _srbufferSize); + (const void *)this, _dataSize, _inData, _tbuffer, _tbufferSize, _sbuffer, _sbufferSize, _srbufferSize); byte *old = _tbuffer; int new_size = remaining_size + _tbufferSize; _tbuffer = new byte[new_size]; diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp index 970b3970b6..2a681ffd62 100644 --- a/engines/scumm/sound.cpp +++ b/engines/scumm/sound.cpp @@ -1690,7 +1690,7 @@ static void convertADResource(ResourceManager *res, const GameSettings& game, in } else { dw = 500000 * 256 / ticks; } - debugC(DEBUG_SOUND, " ticks = %d, speed = %ld", ticks, dw); + debugC(DEBUG_SOUND, " ticks = %d, speed = %d", ticks, dw); // Write a tempo change Meta event memcpy(ptr, "\x00\xFF\x51\x03", 4); ptr += 4; diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp index d40bbb9aaa..f00f4ff33b 100644 --- a/engines/scumm/string.cpp +++ b/engines/scumm/string.cpp @@ -1415,6 +1415,9 @@ void ScummEngine_v7::loadLanguageBundle() { } void ScummEngine_v7::playSpeech(const byte *ptr) { + if (_game.id == GID_DIG && (ConfMan.getBool("speech_mute") || VAR(VAR_VOICE_MODE) == 2)) + return; + if ((_game.id == GID_DIG || _game.id == GID_CMI) && ptr[0]) { char pointer[20]; strcpy(pointer, (const char *)ptr); diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp index e62d9406d3..81b28ce563 100644 --- a/engines/scumm/verbs.cpp +++ b/engines/scumm/verbs.cpp @@ -567,7 +567,7 @@ void ScummEngine::checkExecVerbs() { } if (_game.platform == Common::kPlatformFMTowns && _game.version == 3) { - // HACK: In the FM-Towns games Indy3, Loom and Zak the most significant bit is set for special keys + // HACK: In the FM-TOWNS games Indy3, Loom and Zak the most significant bit is set for special keys // like F5 (=0x8005) or joystick buttons (mask 0xFE00, e.g. SELECT=0xFE40 for the save/load menu). // Hence the distinction with (_mouseAndKeyboardStat < MBS_MAX_KEY) between mouse- and key-events is not applicable // to this games, so we have to remap the special keys here. diff --git a/engines/sky/control.cpp b/engines/sky/control.cpp index 764f3de9dd..4b5887da69 100644 --- a/engines/sky/control.cpp +++ b/engines/sky/control.cpp @@ -1115,7 +1115,7 @@ void Control::doAutoSave(void) { outf->finalize(); if (outf->err()) - displayMessage(0, "Unable to write autosave file '%s'. Disk full?", fName, _saveFileMan->popErrorDesc().c_str()); + displayMessage(0, "Unable to write autosave file '%s'. Disk full? (%s)", fName, _saveFileMan->popErrorDesc().c_str()); delete outf; free(saveData); diff --git a/engines/sky/control.h b/engines/sky/control.h index 2a3a229cb3..04ed26fefe 100644 --- a/engines/sky/control.h +++ b/engines/sky/control.h @@ -198,7 +198,7 @@ public: void saveDescriptions(const Common::StringList &list); private: - int displayMessage(const char *altButton, const char *message, ...); + int displayMessage(const char *altButton, const char *message, ...) GCC_PRINTF(3, 4); void initPanel(void); void removePanel(void); diff --git a/engines/sky/grid.cpp b/engines/sky/grid.cpp index d9b7a17351..7b473c7934 100644 --- a/engines/sky/grid.cpp +++ b/engines/sky/grid.cpp @@ -255,8 +255,10 @@ void Grid::removeGrid(uint32 x, uint32 y, uint32 width, Compact *cpt) { } uint8 *Grid::giveGrid(uint32 pScreen) { - assert((_gridConvertTable[pScreen] >= 0) && (_gridConvertTable[pScreen] < TOT_NO_GRIDS)); - return _gameGrids[_gridConvertTable[pScreen]]; + if ((_gridConvertTable[pScreen] >= 0) && (_gridConvertTable[pScreen] < TOT_NO_GRIDS)) { + return _gameGrids[_gridConvertTable[pScreen]]; + } + return 0; } } // End of namespace Sky diff --git a/engines/sky/logic.cpp b/engines/sky/logic.cpp index ccfbfbbd62..991fbe19d0 100644 --- a/engines/sky/logic.cpp +++ b/engines/sky/logic.cpp @@ -1702,6 +1702,15 @@ bool Logic::fnQuit(uint32 a, uint32 b, uint32 c) { } bool Logic::fnSpeakMe(uint32 targetId, uint32 mesgNum, uint32 animNum) { + /* WORKAROUND for #2687172: When Mrs. Piermont is talking + on the phone in her apartment, ignore her fnSpeakMe calls + on other screens, as the lack of speech files for these lines + will cause Foster's speech to be aborted if the timing is bad. + */ + if (targetId == 0x4039 && animNum == 0x9B && Logic::_scriptVariables[SCREEN] != 38) { + return false; + } + stdSpeak(_skyCompact->fetchCpt(targetId), mesgNum, animNum, 0); return false; //drop out of script } diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp index 47cc65e96d..e85da6297a 100644 --- a/engines/sky/sky.cpp +++ b/engines/sky/sky.cpp @@ -208,8 +208,11 @@ Common::Error SkyEngine::go() { _skyScreen->recreate(); _skyScreen->spriteEngine(); if (_debugger->showGrid()) { - _skyScreen->showGrid(_skyLogic->_skyGrid->giveGrid(Logic::_scriptVariables[SCREEN])); - _skyScreen->forceRefresh(); + uint8 *grid = _skyLogic->_skyGrid->giveGrid(Logic::_scriptVariables[SCREEN]); + if (grid) { + _skyScreen->showGrid(grid); + _skyScreen->forceRefresh(); + } } _skyScreen->flip(); diff --git a/engines/sword1/control.h b/engines/sword1/control.h index d6adc61c3a..0193afc7f1 100644 --- a/engines/sword1/control.h +++ b/engines/sword1/control.h @@ -101,7 +101,7 @@ public: } private: - int displayMessage(const char *altButton, const char *message, ...); + int displayMessage(const char *altButton, const char *message, ...) GCC_PRINTF(3, 4); bool convertSaveGame(uint8 slot, char* desc); void showSavegameNames(void); diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp index 5577c66fc6..b23bf71445 100644 --- a/engines/sword1/sound.cpp +++ b/engines/sword1/sound.cpp @@ -51,6 +51,7 @@ Sound::Sound(const char *searchPath, Audio::Mixer *mixer, ResMan *pResMan) { strcpy(_filePath, searchPath); _mixer = mixer; _resMan = pResMan; + _bigEndianSpeech = false; _cowHeader = NULL; _endOfQueue = 0; _currentCowFile = 0; @@ -67,6 +68,83 @@ Sound::~Sound(void) { closeCowSystem(); } +void Sound::checkSpeechFileEndianness() { + // Some mac versions (not all of them) use big endian wav, although + // the wav header doesn't indicate it. + // Use heuristic to determine endianness of speech. + // The heuristic consist in computing the sum of the absolute difference for + // every two consecutive samples. This is done both with a big endian and a + // little endian assumption. The one with the smallest sum should be the + // correct one (the sound wave is supposed to be relatively smooth). + // It needs at least 1000 samples to get stable result (the code below is + // using the first 2000 samples of the wav sound). + + // Init speech file if not already done. + if (!_currentCowFile) { + // Open one of the speech files. It uses SwordEngine::_systemVars.currentCD + // to decide which file to open, therefore if it is currently set to zero + // we have to set it to either 1 or 2 (I decided to set it to 1 as this is + // more likely to be the first file that will be needed). + bool no_current_cd = false; + if (SwordEngine::_systemVars.currentCD == 0) { + SwordEngine::_systemVars.currentCD = 1; + no_current_cd = true; + } + initCowSystem(); + if (no_current_cd) { + // In case it fails with CD1 retry with CD2 + if (!_currentCowFile) { + SwordEngine::_systemVars.currentCD = 2; + initCowSystem(); + } + // Reset currentCD flag + SwordEngine::_systemVars.currentCD = 0; + } + } + + // Testing for endianness makes sense only if using the uncompressed files. + if (_cowHeader == NULL || (_cowMode != CowWave && _cowMode != CowDemo)) + return; + + // I picked the sample to use randomly (I just made sure it is long enough so that there is + // a fair change of the heuristic to have a stable result and work for every language). + int roomNo = _currentCowFile == 1 ? 1 : 129; + int localNo = _currentCowFile == 1 ? 2 : 933; + // Get the speech data and apply the heuristic + uint32 locIndex = _cowHeader[roomNo] >> 2; + uint32 sampleSize = _cowHeader[locIndex + (localNo * 2)]; + uint32 index = _cowHeader[locIndex + (localNo * 2) - 1]; + if (sampleSize) { + uint32 size; + double be_diff_sum = 0., le_diff_sum = 0.; + _bigEndianSpeech = false; + int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size); + // Compute average of difference between two consecutive samples for both BE and LE + if (data) { + if (size > 4000) + size = 2000; + else + size /= 2; + int16 prev_be_value = (int16)SWAP_BYTES_16(*((uint16*)(data))); + for (uint32 i = 1 ; i < size ; ++i) { + le_diff_sum += fabs((double)(data[i] - data[i-1])); + int16 be_value = (int16)SWAP_BYTES_16(*((uint16*)(data + i))); + be_diff_sum += fabs((double)(be_value - prev_be_value)); + prev_be_value = be_value; + } + delete [] data; + } + // Set the big endian flag + _bigEndianSpeech = (be_diff_sum < le_diff_sum); + if (_bigEndianSpeech) + debug(6, "Mac version: using big endian speech file"); + else + debug(6, "Mac version: using little endian speech file"); + debug(8, "Speech endianness heuristic: average = %f for BE and %f for LE, computed on %d samples)", be_diff_sum / (size - 1), le_diff_sum / (size - 1), size); + } +} + + int Sound::addToQueue(int32 fxNo) { bool alreadyInQueue = false; for (uint8 cnt = 0; (cnt < _endOfQueue) && (!alreadyInQueue); cnt++) @@ -386,21 +464,32 @@ int16 *Sound::uncompressSpeech(uint32 index, uint32 cSize, uint32 *size) { int16 *dstData = (int16*)malloc(resSize * 2); int32 samplesLeft = resSize; while (srcPos < cSize && samplesLeft > 0) { - length = (int16)READ_LE_UINT16(srcData + srcPos); + length = (int16)(_bigEndianSpeech ? READ_BE_UINT16(srcData + srcPos) : READ_LE_UINT16(srcData + srcPos)); srcPos++; if (length < 0) { length = -length; if (length > samplesLeft) length = samplesLeft; + int16 value; + if (_bigEndianSpeech) { + value = (int16)SWAP_BYTES_16(*((uint16*)(srcData + srcPos))); + } else { + value = srcData[srcPos]; + } for (uint16 cnt = 0; cnt < (uint16)length; cnt++) - dstData[dstPos++] = srcData[srcPos]; + dstData[dstPos++] = value; srcPos++; } else { if (length > samplesLeft) length = samplesLeft; - memcpy(dstData + dstPos, srcData + srcPos, length * 2); - dstPos += length; - srcPos += length; + if (_bigEndianSpeech) { + for (uint16 cnt = 0; cnt < (uint16)length; cnt++) + dstData[dstPos++] = (int16)SWAP_BYTES_16(*((uint16*)(srcData + (srcPos++)))); + } else { + memcpy(dstData + dstPos, srcData + srcPos, length * 2); + dstPos += length; + srcPos += length; + } } samplesLeft -= length; } diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h index cdbdcdf6bb..c105d06b50 100644 --- a/engines/sword1/sound.h +++ b/engines/sword1/sound.h @@ -95,6 +95,8 @@ public: void engine(void); + void checkSpeechFileEndianness(); + private: uint8 _sfxVolL, _sfxVolR, _speechVolL, _speechVolR; void playSample(QueueElement *elem); @@ -116,6 +118,7 @@ private: uint8 _endOfQueue; Audio::Mixer *_mixer; ResMan *_resMan; + bool _bigEndianSpeech; char _filePath[100]; static const char _musicList[270]; static const uint16 _roomsFixedFx[TOTAL_ROOMS][TOTAL_FX_PER_ROOM]; diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp index 3796ceefd6..61ab835da6 100644 --- a/engines/sword1/sword1.cpp +++ b/engines/sword1/sword1.cpp @@ -145,6 +145,10 @@ Common::Error SwordEngine::init() { _systemVars.playSpeech = 1; _mouseState = 0; + + // Some Mac versions use big endian for the speech files but not all of them. + if (_systemVars.platform == Common::kPlatformMacintosh) + _sound->checkSpeechFileEndianness(); _logic->initialize(); _objectMan->initialize(); diff --git a/engines/sword2/screen.h b/engines/sword2/screen.h index 2f72b75980..166245c6ef 100644 --- a/engines/sword2/screen.h +++ b/engines/sword2/screen.h @@ -423,8 +423,8 @@ public: void setPalette(int16 startEntry, int16 noEntries, byte *palette, uint8 setNow); void setSystemPalette(const byte *colors, uint start, uint num); uint8 quickMatch(uint8 r, uint8 g, uint8 b); - int32 fadeUp(float time = 0.75); - int32 fadeDown(float time = 0.75); + int32 fadeUp(float time = 0.75f); + int32 fadeDown(float time = 0.75f); uint8 getFadeStatus(); void dimPalette(bool dim); void waitForFade(); diff --git a/engines/tinsel/actors.h b/engines/tinsel/actors.h index 74a5ba4185..bda0e8bbb3 100644 --- a/engines/tinsel/actors.h +++ b/engines/tinsel/actors.h @@ -137,8 +137,6 @@ int GetActorFilmNumber(int ano); void StoreActorReel(int actor, int column, OBJECT *pObj); void NotPlayingReel(int actor, int filmNumber, int column); bool ActorReelPlaying(int actor, int column); -void SetActorPlayFilm(int ano, SCNHANDLE hFilm); -SCNHANDLE GetActorPlayFilm(int ano); /*----------------------------------------------------------------------*/ @@ -161,8 +159,6 @@ struct Z_POSITIONS { int z; }; -int SaveActors(SAVED_ACTOR *sActorInfo); - void RestoreActorProcess(int id, INT_CONTEXT *pic); int SaveActors(PSAVED_ACTOR sActorInfo); diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp index a3cd0bc7b7..a3f921505a 100644 --- a/engines/tinsel/detection.cpp +++ b/engines/tinsel/detection.cpp @@ -163,6 +163,28 @@ static const TinselGameDescription gameDescriptions[] = { TINSEL_V1, }, + { // Italian CD with english speech and *.gra files. + // Note: It contains only italian subtitles, but inside english.txt + { + "dw", + "CD", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"english.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 237774}, + {"english.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::IT_ITA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + { // Multilingual CD with english speech and *.gra files. // Note: It contains no english subtitles. { @@ -187,6 +209,7 @@ static const TinselGameDescription gameDescriptions[] = { GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, TINSEL_V1, }, + { { "dw", @@ -505,7 +528,7 @@ static const TinselGameDescription gameDescriptions[] = { "CD", { {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"english1.smp", 0, "aa8d05f6fade11e6f066d42c302c8e89", 250926923}, + {"english1.smp", 0, NULL, -1}, {"english1.txt", 0, "b522e19d7b2cd7b85e50e36fe48e36a9", 274444}, {NULL, 0, NULL, 0} }, diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp index 9a0e1f37f8..5ef5bea702 100644 --- a/engines/tinsel/handle.cpp +++ b/engines/tinsel/handle.cpp @@ -207,9 +207,7 @@ void OpenCDGraphFile(void) { // As the theory goes, the right CD will be in there! - cdGraphStream.clearIOFailed(); - cdGraphStream.open(szCdPlayFile); - if (cdGraphStream.ioFailed()) + if (!cdGraphStream.open(szCdPlayFile)) error(CANNOT_FIND_FILE, szCdPlayFile); } diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp index f80217b4f4..12d9f0393a 100644 --- a/engines/tinsel/music.cpp +++ b/engines/tinsel/music.cpp @@ -207,6 +207,10 @@ bool PlayMidiSequence(uint32 dwFileOffset, bool bLoop) { if (track > 0) { StopMidi(); + // StopMidi resets these fields, so set them again + currentMidi = dwFileOffset; + currentLoop = bLoop; + // try to play track, but don't fall back to a true CD AudioCD.play(track, bLoop ? -1 : 1, 0, 0, true); diff --git a/engines/tinsel/pcode.cpp b/engines/tinsel/pcode.cpp index a9c6f43d85..1d73411e13 100644 --- a/engines/tinsel/pcode.cpp +++ b/engines/tinsel/pcode.cpp @@ -112,6 +112,43 @@ static INT_CONTEXT *icList = 0; static uint32 hMasterScript; +//----------------- SCRIPT BUGS WORKAROUNDS -------------- + +const byte fragment1[] = {OP_ZERO, OP_GSTORE | OPSIZE16, 206, 0}; +const int fragment1_size = 4; +const byte fragment2[] = {OP_LIBCALL | OPSIZE8, 110}; +const int fragment2_size = 2; +const byte fragment3[] = {OP_ZERO, OP_GSTORE | OPSIZE16, 490 % 256, 490 / 256}; +const int fragment3_size = 4; + +const WorkaroundEntry workaroundList[] = { + // DW1-SCN: Global 206 is whether Rincewind is trying to take the book back to the present. + // In the GRA version, it was global 373, and was reset when he is returned to the past, but + // was forgotten in the SCN version, so this ensures the flag is properly reset + {TINSEL_V1, true, 427942095, 1, fragment1_size, fragment1}, + + // DW1-GRA: Rincewind exiting the Inn is blocked by the luggage. Whilst you can then move + // into walkable areas, saving and restoring the game, it will error if you try to move. + // This fragment turns off NPC blocking for the Outside Inn rooms so that the luggage won't block + // Past Outside Inn + {TINSEL_V1, false, 444622076, 0, fragment2_size, fragment2}, + // Present Outside Inn + {TINSEL_V1, false, 352600876, 0, fragment2_size, fragment2}, + + // DW2: In the garden, global #490 is set when the bees begin their 'out of hive' animation, and reset when done. + // But if the game is saved/restored during it, the animation sequence is reset without the global being cleared. + // This causes bugs in several actions which try to disable the bees animation, since they wait indefinitely for + // the global to be cleared, incorrectly believing the animation is currently playing. This includes + // * Giving the brochure to the beekeeper + // * Stealing the mallets from the wizards + // This fix ensures that the global is reset when the Garden scene is loaded (both entering and restoring a game) + {TINSEL_V2, true, 2888147476U, 0, fragment3_size, fragment3}, + + {TINSEL_V0, false, 0, 0, 0, NULL} +}; + +//----------------- LOCAL GLOBAL DATA -------------------- + /** * Keeps the code array pointer up to date. */ @@ -398,38 +435,93 @@ void SaveInterpretContexts(INT_CONTEXT *sICInfo) { } /** - * Fetch (and sign extend, if necessary) a 8/16/32 bit value from the code - * stream and advance the instruction pointer accordingly. + * Fetches up to 4 bytes from the code script */ -static int32 Fetch(byte opcode, byte *code, int &ip) { - int32 tmp; - if (TinselV0) { - // Fetch a 32 bit value. - tmp = (int32)READ_LE_UINT32(code + ip++ * 4); - } else if (opcode & OPSIZE8) { +static int32 GetBytes(const byte *scriptCode, const WorkaroundEntry* &wkEntry, int &ip, uint numBytes) { + assert(numBytes <= 4 && numBytes != 3); + const byte *code = scriptCode; + + if (wkEntry != NULL) { + if (ip >= wkEntry->numBytes) { + // Finished the workaround + ip = wkEntry->ip; + wkEntry = NULL; + } else { + code = wkEntry->script; + } + } + + uint32 tmp; + switch (numBytes) { + case 0: + // Instruction byte + tmp = code[ip++ * (TinselV0 ? 4 : 1)]; + break; + case 1: // Fetch and sign extend a 8 bit value to 32 bits. - tmp = *(int8 *)(code + ip); - ip += 1; - } else if (opcode & OPSIZE16) { + tmp = (int8)code[ip++]; + break; + case 2: // Fetch and sign extend a 16 bit value to 32 bits. tmp = (int16)READ_LE_UINT16(code + ip); ip += 2; - } else { - // Fetch a 32 bit value. - tmp = (int32)READ_LE_UINT32(code + ip); - ip += 4; + break; + default: + if (TinselV0) + tmp = (int32)READ_LE_UINT32(code + ip++ * 4); + else { + tmp = (int32)READ_LE_UINT32(code + ip); + ip += 4; + } + break; } + return tmp; } /** + * Fetch (and sign extend, if necessary) a 8/16/32 bit value from the code + * stream and advance the instruction pointer accordingly. + */ +static int32 Fetch(byte opcode, const byte *code, const WorkaroundEntry* &wkEntry, int &ip) { + if (TinselV0) + // Fetch a 32 bit value. + return GetBytes(code, wkEntry, ip, 4); + else if (opcode & OPSIZE8) + // Fetch and sign extend a 8 bit value to 32 bits. + return GetBytes(code, wkEntry, ip, 1); + else if (opcode & OPSIZE16) + return GetBytes(code, wkEntry, ip, 2); + + return GetBytes(code, wkEntry, ip, 4); +} + +/** * Interprets the PCODE instructions in the code array. */ void Interpret(CORO_PARAM, INT_CONTEXT *ic) { do { int tmp, tmp2; int ip = ic->ip; - byte opcode = ic->code[ip++ * (TinselV0 ? 4 : 1)]; + const WorkaroundEntry *wkEntry = ic->fragmentPtr; + + if (wkEntry == NULL) { + // Check to see if a workaround fragment needs to be executed + for (wkEntry = workaroundList; wkEntry->script != NULL; ++wkEntry) { + if ((wkEntry->version == TinselVersion) && + (wkEntry->hCode == ic->hCode) && + (wkEntry->ip == ip) && + (!TinselV1 || (wkEntry->scnFlag == ((_vm->getFeatures() & GF_SCNFILES) != 0)))) { + // Point to start of workaround fragment + ip = 0; + break; + } + } + if (wkEntry->script == NULL) + wkEntry = NULL; + } + + byte opcode = (byte)GetBytes(ic->code, wkEntry, ip, 0); if (TinselV0 && ((opcode & OPMASK) > OP_IMM)) opcode += 3; @@ -447,7 +539,7 @@ void Interpret(CORO_PARAM, INT_CONTEXT *ic) { case OP_FONT: // loads font handle onto stack case OP_PAL: // loads palette handle onto stack - ic->stack[++ic->sp] = Fetch(opcode, ic->code, ip); + ic->stack[++ic->sp] = Fetch(opcode, ic->code, wkEntry, ip); break; case OP_ZERO: // loads zero onto stack @@ -464,31 +556,31 @@ void Interpret(CORO_PARAM, INT_CONTEXT *ic) { case OP_LOAD: // loads local variable onto stack - ic->stack[++ic->sp] = ic->stack[ic->bp + Fetch(opcode, ic->code, ip)]; + ic->stack[++ic->sp] = ic->stack[ic->bp + Fetch(opcode, ic->code, wkEntry, ip)]; break; case OP_GLOAD: // loads global variable onto stack - tmp = Fetch(opcode, ic->code, ip); + tmp = Fetch(opcode, ic->code, wkEntry, ip); assert(0 <= tmp && tmp < numGlobals); ic->stack[++ic->sp] = pGlobals[tmp]; break; case OP_STORE: // pops stack and stores in local variable - ic->stack[ic->bp + Fetch(opcode, ic->code, ip)] = ic->stack[ic->sp--]; + ic->stack[ic->bp + Fetch(opcode, ic->code, wkEntry, ip)] = ic->stack[ic->sp--]; break; case OP_GSTORE: // pops stack and stores in global variable - tmp = Fetch(opcode, ic->code, ip); + tmp = Fetch(opcode, ic->code, wkEntry, ip); assert(0 <= tmp && tmp < numGlobals); pGlobals[tmp] = ic->stack[ic->sp--]; break; case OP_CALL: // procedure call - tmp = Fetch(opcode, ic->code, ip); + tmp = Fetch(opcode, ic->code, wkEntry, ip); //assert(0 <= tmp && tmp < codeSize); // TODO: Verify jumps are not out of bounds ic->stack[ic->sp + 1] = 0; // static link ic->stack[ic->sp + 2] = ic->bp; // dynamic link @@ -499,7 +591,7 @@ void Interpret(CORO_PARAM, INT_CONTEXT *ic) { case OP_LIBCALL: // library procedure or function call - tmp = Fetch(opcode, ic->code, ip); + tmp = Fetch(opcode, ic->code, wkEntry, ip); // NOTE: Interpret() itself is not using the coroutine facilities, // but still accepts a CORO_PARAM, so from the outside it looks // like a coroutine. In fact it may still acts as a kind of "proxy" @@ -538,17 +630,17 @@ void Interpret(CORO_PARAM, INT_CONTEXT *ic) { case OP_ALLOC: // allocate storage on stack - ic->sp += (int32)Fetch(opcode, ic->code, ip); + ic->sp += (int32)Fetch(opcode, ic->code, wkEntry, ip); break; case OP_JUMP: // unconditional jump - ip = Fetch(opcode, ic->code, ip); + ip = Fetch(opcode, ic->code, wkEntry, ip); break; case OP_JMPFALSE: // conditional jump - tmp = Fetch(opcode, ic->code, ip); + tmp = Fetch(opcode, ic->code, wkEntry, ip); if (ic->stack[ic->sp--] == 0) { // condition satisfied - do the jump ip = tmp; @@ -557,7 +649,7 @@ void Interpret(CORO_PARAM, INT_CONTEXT *ic) { case OP_JMPTRUE: // conditional jump - tmp = Fetch(opcode, ic->code, ip); + tmp = Fetch(opcode, ic->code, wkEntry, ip); if (ic->stack[ic->sp--] != 0) { // condition satisfied - do the jump ip = tmp; @@ -660,6 +752,7 @@ void Interpret(CORO_PARAM, INT_CONTEXT *ic) { // check for stack under-overflow assert(ic->sp >= 0 && ic->sp < PCODE_STACK_SIZE); ic->ip = ip; + ic->fragmentPtr = wkEntry; } while (!ic->bHalt); // make sure stack is unwound diff --git a/engines/tinsel/pcode.h b/engines/tinsel/pcode.h index 4bdfcf5626..fad50cdb9d 100644 --- a/engines/tinsel/pcode.h +++ b/engines/tinsel/pcode.h @@ -54,6 +54,17 @@ enum GSORT { enum RESCODE {RES_WAITING, RES_FINISHED, RES_CUTSHORT}; +// The following structure is used to introduce bug fixes into the scripts used by the games + +struct WorkaroundEntry { + TinselEngineVersion version; + bool scnFlag; // Only applicable for Tinsel 1 (DW 1) + SCNHANDLE hCode; // Script to apply fragment to + int ip; // Script offset to run this fragment before + int numBytes; // Number of bytes in the script + const byte *script; // Instruction(s) to execute +}; + struct INT_CONTEXT { // Elements for interpret context management @@ -82,6 +93,9 @@ struct INT_CONTEXT { RESCODE resumeCode; RESUME_STATE resumeState; + // Used to store execution state within a script workaround fragment + const WorkaroundEntry *fragmentPtr; + void syncWithSerializer(Common::Serializer &s); }; typedef INT_CONTEXT *PINT_CONTEXT; diff --git a/engines/tinsel/pdisplay.cpp b/engines/tinsel/pdisplay.cpp index e0262839a2..17e9a3a517 100644 --- a/engines/tinsel/pdisplay.cpp +++ b/engines/tinsel/pdisplay.cpp @@ -55,14 +55,6 @@ extern int newestString; // The overrun counter, in STRRES.C #endif -//----------------- EXTERNAL FUNCTIONS --------------------- - -// in BG.C -extern int BgWidth(void); -extern int BgHeight(void); - - - //----------------- LOCAL DEFINES -------------------- #define LPOSX 295 // X-co-ord of lead actor's position display diff --git a/engines/tinsel/polygons.h b/engines/tinsel/polygons.h index 62ec0422c6..7cb22a1b8a 100644 --- a/engines/tinsel/polygons.h +++ b/engines/tinsel/polygons.h @@ -92,7 +92,6 @@ bool IsPolyCorner(HPOLYGON hPath, int x, int y); int GetScale(HPOLYGON path, int y); int GetBrightness(HPOLYGON hPath, int y); void getNpathNode(HPOLYGON npath, int node, int *px, int *py); -void GetTagTag(HPOLYGON p, SCNHANDLE *hTagText, int *tagx, int *tagy); SCNHANDLE GetPolyFilm(HPOLYGON p); void GetPolyNode(HPOLYGON hp, int *pNodeX, int *pNodeY); SCNHANDLE GetPolyScript(HPOLYGON p); @@ -108,8 +107,6 @@ void DisablePath(int path); void EnablePath(int path); void DisableRefer(int refer); void EnableRefer(int refer); -void DisableBlock(int blockno); -void EnableBlock(int blockno); HPOLYGON GetTagHandle(int tagno); void DisableTag(CORO_PARAM, int tag); void EnableTag(CORO_PARAM, int tag); @@ -152,8 +149,7 @@ bool PolyTagIsWanted(HPOLYGON hp); bool PolyTagFollowsCursor(HPOLYGON hp); SCNHANDLE GetPolyTagHandle(HPOLYGON hp); bool IsTagPolygon(int tagno); -int GetTagPolyId(HPOLYGON hp); -void GetPolyMidBottom( HPOLYGON hp, int *pX, int *pY); +void GetPolyMidBottom(HPOLYGON hp, int *pX, int *pY); int PathCount(void); void MovePolygon(PTYPE ptype, int id, int x, int y); void MovePolygonTo(PTYPE ptype, int id, int x, int y); diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp index a07a417723..c6d30fa222 100644 --- a/engines/tinsel/sound.cpp +++ b/engines/tinsel/sound.cpp @@ -41,6 +41,9 @@ #include "sound/mixer.h" #include "sound/adpcm.h" #include "sound/vag.h" +#include "sound/flac.h" +#include "sound/mp3.h" +#include "sound/vorbis.h" #include "gui/message.h" @@ -52,7 +55,9 @@ extern LANGUAGE sampleLanguage; SoundManager::SoundManager(TinselEngine *vm) : //_vm(vm), // TODO: Enable this once global _vm var is gone - _sampleIndex(0), _sampleIndexLen(0) { + _sampleIndex(0), _sampleIndexLen(0), + _soundMode(kVOCMode) + { for (int i = 0; i < kNumChannels; i++) _channels[i].sampleNum = _channels[i].subSample = -1; @@ -68,6 +73,7 @@ SoundManager::~SoundManager() { * @param type type of sound (voice or sfx) * @param handle sound handle */ +// playSample for DiscWorld 1 bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::SoundHandle *handle) { // Floppy version has no sample file if (_vm->getFeatures() & GF_FLOPPY) @@ -114,7 +120,7 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound _vm->_mixer->playInputStream(type, &curChan.handle, vagStream); } else { // allocate a buffer - void *sampleBuf = malloc(sampleLen); + byte *sampleBuf = (byte *)malloc(sampleLen); assert(sampleBuf); // read all of the sample @@ -126,10 +132,35 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound //_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic); _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volVoice); + Common::MemoryReadStream *compressedStream = + new Common::MemoryReadStream(sampleBuf, sampleLen, true); + Audio::AudioStream *sampleStream = 0; // play it - _vm->_mixer->playRaw(type, &curChan.handle, sampleBuf, sampleLen, 22050, - Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED); + switch (_soundMode) { + case kMP3Mode: + #ifdef USE_MAD + sampleStream = Audio::makeMP3Stream(compressedStream, true); + #endif + break; + case kVorbisMode: + #ifdef USE_VORBIS + sampleStream = Audio::makeVorbisStream(compressedStream, true); + #endif + break; + case kFlacMode: + #ifdef USE_FLAC + sampleStream = Audio::makeFlacStream(compressedStream, true); + #endif + break; + default: + _vm->_mixer->playRaw(type, &curChan.handle, sampleBuf, sampleLen, 22050, + Audio::Mixer::FLAG_AUTOFREE | Audio::Mixer::FLAG_UNSIGNED); + break; + } + if (sampleStream) { + _vm->_mixer->playInputStream(type, &curChan.handle, sampleStream); + } } if (handle) @@ -138,6 +169,7 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound return true; } +// playSample for DiscWorld 2 bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int priority, Audio::Mixer::SoundType type, Audio::SoundHandle *handle) { @@ -251,10 +283,30 @@ bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int p if (_sampleStream.read(sampleBuf, sampleLen) != sampleLen) error(FILE_IS_CORRUPT, _vm->getSampleFile(sampleLanguage)); - Common::MemoryReadStream *sampleStream = + Common::MemoryReadStream *compressedStream = new Common::MemoryReadStream(sampleBuf, sampleLen, true); - Audio::AudioStream *_stream = - makeADPCMStream(sampleStream, true, sampleLen, Audio::kADPCMTinsel6, 22050, 1, 24); + Audio::AudioStream *sampleStream = 0; + + switch (_soundMode) { + case kMP3Mode: + #ifdef USE_MAD + sampleStream = Audio::makeMP3Stream(compressedStream, true); + #endif + break; + case kVorbisMode: + #ifdef USE_VORBIS + sampleStream = Audio::makeVorbisStream(compressedStream, true); + #endif + break; + case kFlacMode: + #ifdef USE_FLAC + sampleStream = Audio::makeFlacStream(compressedStream, true); + #endif + break; + default: + sampleStream = Audio::makeADPCMStream(compressedStream, true, sampleLen, Audio::kADPCMTinsel6, 22050, 1, 24); + break; + } // FIXME: Should set this in a different place ;) _vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volSound); @@ -269,10 +321,12 @@ bool SoundManager::playSample(int id, int sub, bool bLooped, int x, int y, int p curChan->priority = priority; curChan->lastStart = g_system->getMillis(); // /---Compression----\ Milis BytesPerSecond - curChan->timeDuration = (((sampleLen * 64) / 25) * 1000) / (22050 * 2); + // not needed and won't work when using MP3/OGG/FLAC anyway + //curChan->timeDuration = (((sampleLen * 64) / 25) * 1000) / (22050 * 2); // Play it - _vm->_mixer->playInputStream(type, &curChan->handle, _stream); + _vm->_mixer->playInputStream(type, &curChan->handle, sampleStream); + _vm->_mixer->setChannelVolume(curChan->handle, sndVol); _vm->_mixer->setChannelBalance(curChan->handle, getPan(x)); @@ -455,6 +509,30 @@ void SoundManager::openSampleFiles(void) { // convert file size to size in DWORDs _sampleIndexLen /= sizeof(uint32); + + // Detect format of soundfile by looking at 1st sample-index + switch (_sampleIndex[0]) { + case MKID_BE(' 3PM'): + debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected MP3 sound-data"); + _soundMode = kMP3Mode; + break; + + case MKID_BE(' GGO'): + debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected OGG sound-data"); + _soundMode = kVorbisMode; + break; + + case MKID_BE('CLAF'): + debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected FLAC sound-data"); + _soundMode = kFlacMode; + break; + + default: + debugC(DEBUG_DETAILED, kTinselDebugSound, "Detected original sound-data"); + break; + } + // Normally the 1st sample-index points to nothing at all + _sampleIndex[0] = 0; } else { char buf[50]; sprintf(buf, CANNOT_FIND_FILE, _vm->getSampleIndex(sampleLanguage)); diff --git a/engines/tinsel/sound.h b/engines/tinsel/sound.h index 15919f8ec5..9bdd037ff0 100644 --- a/engines/tinsel/sound.h +++ b/engines/tinsel/sound.h @@ -58,6 +58,13 @@ protected: }; static const int kNumChannels = kChannelSFX + kNumSFX; + enum SoundMode { + kVOCMode, + kMP3Mode, + kVorbisMode, + kFlacMode + }; + struct Channel { // Sample handle Audio::SoundHandle handle; @@ -87,6 +94,9 @@ protected: /** Number of entries in the sample index */ long _sampleIndexLen; + /** Specifies if the sample-data is compressed and if yes, how */ + SoundMode _soundMode; + /** file stream for sample file */ TinselFile _sampleStream; diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp index b73a66b6d3..4b5e0ce450 100644 --- a/engines/tinsel/tinlib.cpp +++ b/engines/tinsel/tinlib.cpp @@ -89,8 +89,6 @@ int clRunMode = 0; // in BG.CPP extern void ChangePalette(SCNHANDLE hPal); -extern int BgWidth(void); -extern int BgHeight(void); // in BMV.CPP void PlayBMV(CORO_PARAM, SCNHANDLE hFileStem, int myEscape); @@ -278,7 +276,6 @@ static COLORREF s_talkfontColor = 0; //----------------- FORWARD REFERENCES -------------------- static int HeldObject(void); -void Offset(EXTREME extreme, int x, int y); static void PostTag(CORO_PARAM, int tagno, TINSEL_EVENT event, HPOLYGON hp, int myEscape); void ResetIdleTime(void); static void SendTag(CORO_PARAM, int tagno, TINSEL_EVENT event, HPOLYGON hp, int myEscape, bool *result); diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index 1a08fd2420..95541e3287 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -93,10 +93,6 @@ extern void InventoryProcess(CORO_PARAM, const void *); extern void PrimeBackground(); extern SCNHANDLE GetSceneHandle(void); -// In TIMER.CPP -extern void FettleTimers(void); -extern void RebootTimers(void); - //----------------- FORWARD DECLARATIONS --------------------- void SetNewScene(SCNHANDLE scene, int entrance, int transition); diff --git a/engines/touche/saveload.cpp b/engines/touche/saveload.cpp index 69b8f9ba43..73817a5a1a 100644 --- a/engines/touche/saveload.cpp +++ b/engines/touche/saveload.cpp @@ -355,10 +355,10 @@ Common::Error ToucheEngine::loadGameState(int num) { } else { f->skip(2 + kGameStateDescriptionLen); loadGameStateData(f); - if (!f->ioFailed()) { - loadOk = true; - } else { + if (f->err() || f->eos()) { warning("Can't read file '%s'", gameStateFileName.c_str()); + } else { + loadOk = true; } } delete f; diff --git a/engines/tucker/locations.cpp b/engines/tucker/locations.cpp index 9faa2024a6..4117391cdf 100644 --- a/engines/tucker/locations.cpp +++ b/engines/tucker/locations.cpp @@ -195,8 +195,8 @@ void TuckerEngine::execData3PreUpdate_locationNum2() { for (int j = 0; j < 2; ++j) { const int offset = (_updateLocationYPosTable2[i] + j) * 640 + _updateLocationXPosTable2[i]; _locationBackgroundGfxBuf[offset] = 142 + j * 2; - addDirtyRect(offset % 640, offset / 640, 1, 1); } + addDirtyRect(_updateLocationXPosTable2[i], _updateLocationYPosTable2[i], 1, 2); _updateLocationYPosTable2[i] += 2; if (_updateLocationYPosTable2[i] > _updateLocationYMaxTable[i]) { _updateLocationYPosTable2[i] = 0; @@ -540,13 +540,14 @@ void TuckerEngine::execData3PreUpdate_locationNum6Helper1() { x2 = 15 - _flagsTable[27]; } for (int i = 0; i < x1; ++i) { - execData3PreUpdate_locationNum6Helper2(13125 + i * 8, _data3GfxBuf + _dataTable[238].sourceOffset); - execData3PreUpdate_locationNum6Helper2(13245 - i * 8, _data3GfxBuf + _dataTable[238].sourceOffset); + execData3PreUpdate_locationNum6Helper2(20 * 640 + 325 + i * 8, _data3GfxBuf + _dataTable[238].sourceOffset); + execData3PreUpdate_locationNum6Helper2(20 * 640 + 445 - i * 8, _data3GfxBuf + _dataTable[238].sourceOffset); } for (int i = 0; i < x2; ++i) { - execData3PreUpdate_locationNum6Helper3(13125 + x1 * 8 + i * 4, _data3GfxBuf + _dataTable[238].sourceOffset); - execData3PreUpdate_locationNum6Helper3(13249 - x1 * 8 - i * 4, _data3GfxBuf + _dataTable[238].sourceOffset); + execData3PreUpdate_locationNum6Helper3(20 * 640 + 325 + x1 * 8 + i * 4, _data3GfxBuf + _dataTable[238].sourceOffset); + execData3PreUpdate_locationNum6Helper3(20 * 640 + 449 - x1 * 8 - i * 4, _data3GfxBuf + _dataTable[238].sourceOffset); } + addDirtyRect(0, 20, 640, 51); } void TuckerEngine::execData3PreUpdate_locationNum6Helper2(int dstOffset, const uint8 *src) { @@ -562,7 +563,6 @@ void TuckerEngine::execData3PreUpdate_locationNum6Helper2(int dstOffset, const u } } } - addDirtyRect(dstOffset % 640, dstOffset / 640, 8, 51); } void TuckerEngine::execData3PreUpdate_locationNum6Helper3(int dstOffset, const uint8 *src) { @@ -575,7 +575,6 @@ void TuckerEngine::execData3PreUpdate_locationNum6Helper3(int dstOffset, const u } } } - addDirtyRect(dstOffset % 640, dstOffset / 640, 4, 51); } void TuckerEngine::execData3PostUpdate_locationNum6() { @@ -661,7 +660,7 @@ void TuckerEngine::execData3PostUpdate_locationNum8() { _locationBackgroundGfxBuf[offset + 640 * j + i] = colorsTable[(j - 1) * 3 + i + 1]; } } - addDirtyRect(_updateLocationXPosTable2[0] - 1, _updateLocationYPosTable2[0], 3, 4); + addDirtyRect(_updateLocationXPosTable2[0] - 1, _updateLocationYPosTable2[0] + 1, 3, 4); _updateLocationYPosTable2[0] += 2; if (_updateLocationYPosTable2[0] > 120) { _updateLocationYPosTable2[0] = 0; @@ -1013,9 +1012,10 @@ void TuckerEngine::execData3PreUpdate_locationNum14() { if (num > 0) { const int w = _dataTable[num].xSize; const int h = _dataTable[num].ySize; - const int dstOffset = (_updateLocationYPosTable2[i] / 16 - h / 2) * 640 + (_updateLocationXPosTable2[i] - w / 2); - Graphics::decodeRLE_248(_locationBackgroundGfxBuf + dstOffset, _data3GfxBuf + _dataTable[num].sourceOffset, w, h, 0, 0, false); - addDirtyRect(dstOffset % 640, dstOffset / 640, w, h); + const int x = _updateLocationXPosTable2[i] - w / 2; + const int y = _updateLocationYPosTable2[i] / 16 - h / 2; + Graphics::decodeRLE_248(_locationBackgroundGfxBuf + y * 640 + x, _data3GfxBuf + _dataTable[num].sourceOffset, w, h, 0, 0, false); + addDirtyRect(x, y, w, h); } } } @@ -3033,17 +3033,17 @@ void TuckerEngine::execData3PreUpdate_locationNum70() { _panelState = 1; setCursorType(2); int pos = getPositionForLine(22, _infoBarBuf); - int offset = (_flagsTable[143] == 0) ? 57688 : 46168; + int offset = (_flagsTable[143] == 0) ? 90 * 640 + 88 : 72 * 640 + 88; drawStringAlt(offset, color, &_infoBarBuf[pos]); - Graphics::drawStringChar(_locationBackgroundGfxBuf + offset + 5760, 62, 640, color, _charsetGfxBuf); + Graphics::drawStringChar(_locationBackgroundGfxBuf + offset + 9 * 640, 62, 640, color, _charsetGfxBuf); if (_flagsTable[143] != 0) { pos = getPositionForLine(_flagsTable[143] * 2 + 23, _infoBarBuf); - drawStringAlt(offset + 11520, color, &_infoBarBuf[pos]); + drawStringAlt(offset + 18 * 640, color, &_infoBarBuf[pos]); pos = getPositionForLine(_flagsTable[143] * 2 + 24, _infoBarBuf); - drawStringAlt(offset + 17280, color, &_infoBarBuf[pos]); + drawStringAlt(offset + 27 * 640, color, &_infoBarBuf[pos]); } execData3PreUpdate_locationNum70Helper(); - drawStringAlt(offset + 5768, color, _updateLocation70String, _updateLocation70StringLen); + drawStringAlt(offset + 9 * 640 + 8, color, _updateLocation70String, _updateLocation70StringLen); } void TuckerEngine::execData3PreUpdate_locationNum70Helper() { diff --git a/engines/tucker/resource.cpp b/engines/tucker/resource.cpp index 11c1c78133..9b8304e9fd 100644 --- a/engines/tucker/resource.cpp +++ b/engines/tucker/resource.cpp @@ -467,7 +467,7 @@ void TuckerEngine::loadLoc() { copyLocBitmap(filename, 0, false); Graphics::copyRect(_quadBackgroundGfxBuf + 134400, 320, _locationBackgroundGfxBuf + 320, 640, 320, 140); } - _fullRedrawCounter = 2; + _fullRedraw = true; } void TuckerEngine::loadObj() { diff --git a/engines/tucker/saveload.cpp b/engines/tucker/saveload.cpp index cf7f985416..83533a90c3 100644 --- a/engines/tucker/saveload.cpp +++ b/engines/tucker/saveload.cpp @@ -88,7 +88,7 @@ Common::Error TuckerEngine::loadGameState(int num) { } else { f->skip(2); saveOrLoadGameStateData(*f); - if (f->ioFailed()) { + if (f->err() || f->eos()) { warning("Can't read file '%s'", gameStateFileName.c_str()); ret = Common::kReadingFailed; } else { diff --git a/engines/tucker/sequences.cpp b/engines/tucker/sequences.cpp index 11a535e54a..8041b95414 100644 --- a/engines/tucker/sequences.cpp +++ b/engines/tucker/sequences.cpp @@ -102,7 +102,7 @@ void TuckerEngine::handleCreditsSequence() { counter2 = 0; } } - _fullRedrawCounter = 2; + _fullRedraw = true; ++counter3; if (counter3 == 2) { counter3 = 0; @@ -172,7 +172,7 @@ void TuckerEngine::handleCongratulationsSequence() { stopSounds(); loadImage("congrat.pcx", _loadTempBuf, 1); Graphics::copyRect(_locationBackgroundGfxBuf, 640, _loadTempBuf, 320, 320, 200); - _fullRedrawCounter = 2; + _fullRedraw = true; redrawScreen(0); while (!_quitGame && _timerCounter2 < 450) { while (_fadePaletteCounter < 14) { @@ -242,7 +242,7 @@ void TuckerEngine::handleNewPartSequence() { ++_fadePaletteCounter; } Graphics::copyRect(_locationBackgroundGfxBuf, 640, _quadBackgroundGfxBuf, 320, 320, 200); - _fullRedrawCounter = 2; + _fullRedraw = true; updateSprites(); drawSprite(0); redrawScreen(0); @@ -259,7 +259,7 @@ void TuckerEngine::handleNewPartSequence() { --_fadePaletteCounter; } Graphics::copyRect(_locationBackgroundGfxBuf, 640, _quadBackgroundGfxBuf, 320, 320, 200); - _fullRedrawCounter = 2; + _fullRedraw = true; updateSprites(); drawSprite(0); redrawScreen(0); @@ -294,7 +294,7 @@ void TuckerEngine::handleMeanwhileSequence() { ++_fadePaletteCounter; } Graphics::copyRect(_locationBackgroundGfxBuf, 640, _quadBackgroundGfxBuf + 89600, 320, 320, 200); - _fullRedrawCounter = 2; + _fullRedraw = true; redrawScreen(0); waitForTimer(3); ++i; @@ -305,11 +305,12 @@ void TuckerEngine::handleMeanwhileSequence() { --_fadePaletteCounter; } Graphics::copyRect(_locationBackgroundGfxBuf, 640, _quadBackgroundGfxBuf + 89600, 320, 320, 200); - _fullRedrawCounter = 2; + _fullRedraw = true; redrawScreen(0); waitForTimer(3); } while (_fadePaletteCounter > 0); memcpy(_currentPalette, backupPalette, 256 * 3); + _fullRedraw = true; } void TuckerEngine::handleMapSequence() { @@ -337,7 +338,7 @@ void TuckerEngine::handleMapSequence() { waitForTimer(2); updateMouseState(); Graphics::copyRect(_locationBackgroundGfxBuf + _scrollOffset, 640, _quadBackgroundGfxBuf + 89600, 320, 320, 200); - _fullRedrawCounter = 2; + _fullRedraw = true; if (_flagsTable[7] > 0 && _mousePosX > 30 && _mousePosX < 86 && _mousePosY > 36 && _mousePosY < 86) { textNum = 13; _nextLocationNum = (_partNum == 1) ? 3 : 65; @@ -459,7 +460,7 @@ int TuckerEngine::handleSpecialObjectSelectionSequence() { waitForTimer(2); updateMouseState(); Graphics::copyRect(_locationBackgroundGfxBuf + _scrollOffset, 640, _quadBackgroundGfxBuf, 320, 320, 200); - _fullRedrawCounter = 2; + _fullRedraw = true; if (_fadePaletteCounter < 14) { fadeOutPalette(); ++_fadePaletteCounter; diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp index 692335d5ef..09e9a0d38a 100644 --- a/engines/tucker/tucker.cpp +++ b/engines/tucker/tucker.cpp @@ -305,7 +305,7 @@ void TuckerEngine::restart() { _currentGfxBackground = 0; _fadePaletteCounter = 0; memset(_currentPalette, 0, sizeof(_currentPalette)); - _fullRedrawCounter = 0; + _fullRedraw = false; _dirtyRectsPrevCount = _dirtyRectsCount = 0; _updateLocationFadePaletteCounter = 0; @@ -469,7 +469,7 @@ void TuckerEngine::mainLoop() { _mainSpritesBaseOffset = 1; } } - _fullRedrawCounter = 2; + _fullRedraw = true; } else { _currentGfxBackground = _quadBackgroundGfxBuf; } @@ -1460,7 +1460,7 @@ void TuckerEngine::updateScreenScrolling() { } } if (scrollPrevOffset != _scrollOffset) { - _fullRedrawCounter = 2; + _fullRedraw = true; } } @@ -1733,34 +1733,40 @@ void TuckerEngine::drawBackgroundSprites() { } else if (_xPosCurrent > 320 && _xPosCurrent < 640) { srcX += 320; } - int offset = _backgroundSprOffset + srcY * 640 + srcX; - Graphics::decodeRLE_248(_locationBackgroundGfxBuf + offset, _backgroundSpriteDataPtr + frameOffset + 12, srcW, srcH, 0, _locationHeightTable[_locationNum], false); - addDirtyRect(offset % 640, offset / 640, srcW, srcH); + srcX += _backgroundSprOffset; + Graphics::decodeRLE_248(_locationBackgroundGfxBuf + srcY * 640 + srcX, _backgroundSpriteDataPtr + frameOffset + 12, srcW, srcH, 0, _locationHeightTable[_locationNum], false); + addDirtyRect(srcX, srcY, srcW, srcH); } } void TuckerEngine::drawCurrentSprite() { + // Workaround original game glitch: skip first bud frame drawing when entering location (tracker item #2597763) + if ((_locationNum == 17 || _locationNum == 18) && _currentSpriteAnimationFrame == 16) { + return; + } SpriteFrame *chr = &_spriteFramesTable[_currentSpriteAnimationFrame]; - int offset = (_yPosCurrent + _mainSpritesBaseOffset - 54 + chr->yOffset) * 640 + _xPosCurrent; + int yPos = _yPosCurrent + _mainSpritesBaseOffset - 54 + chr->yOffset; + int xPos = _xPosCurrent; if (_mirroredDrawing == 0) { - offset += chr->xOffset - 14; + xPos += chr->xOffset - 14; } else { - offset -= chr->xSize + chr->xOffset - 14; + xPos -= chr->xSize + chr->xOffset - 14; } - Graphics::decodeRLE_248(_locationBackgroundGfxBuf + offset, _spritesGfxBuf + chr->sourceOffset, chr->xSize, chr->ySize, + Graphics::decodeRLE_248(_locationBackgroundGfxBuf + yPos * 640 + xPos, _spritesGfxBuf + chr->sourceOffset, chr->xSize, chr->ySize, chr->yOffset, _locationHeightTable[_locationNum], _mirroredDrawing != 0); - addDirtyRect(offset % 640, offset / 640, chr->xSize, chr->ySize); + addDirtyRect(xPos, yPos, chr->xSize, chr->ySize); if (_currentSpriteAnimationLength > 1) { SpriteFrame *chr2 = &_spriteFramesTable[_currentSpriteAnimationFrame2]; - offset = (_yPosCurrent + _mainSpritesBaseOffset - 54 + chr2->yOffset) * 640 + _xPosCurrent; + yPos = _yPosCurrent + _mainSpritesBaseOffset - 54 + chr2->yOffset; + xPos = _xPosCurrent; if (_mirroredDrawing == 0) { - offset += chr2->xOffset - 14; + xPos += chr2->xOffset - 14; } else { - offset -= chr2->xSize + chr2->xOffset - 14; + xPos -= chr2->xSize + chr2->xOffset - 14; } - Graphics::decodeRLE_248(_locationBackgroundGfxBuf + offset, _spritesGfxBuf + chr2->sourceOffset, chr2->xSize, chr2->ySize, + Graphics::decodeRLE_248(_locationBackgroundGfxBuf + yPos * 640 + xPos, _spritesGfxBuf + chr2->sourceOffset, chr2->xSize, chr2->ySize, chr2->yOffset, _locationHeightTable[_locationNum], _mirroredDrawing != 0); - addDirtyRect(offset % 640, offset / 640, chr2->xSize, chr2->ySize); + addDirtyRect(xPos, yPos, chr2->xSize, chr2->ySize); } } @@ -1891,13 +1897,13 @@ void TuckerEngine::drawSprite(int num) { int srcH = READ_LE_UINT16(p + frameOffset + 2); int srcX = READ_LE_UINT16(p + frameOffset + 8); int srcY = READ_LE_UINT16(p + frameOffset + 10); - int dstOffset = s->gfxBackgroundOffset + srcX; - if (dstOffset < 600 && (_scrollOffset + 320 < dstOffset || _scrollOffset - srcW > dstOffset)) { + int xPos = s->gfxBackgroundOffset + srcX; + if (xPos < 600 && (_scrollOffset + 320 < xPos || _scrollOffset - srcW > xPos)) { return; } s->xSource = srcX; s->gfxBackgroundOffset += s->backgroundOffset; - uint8 *dstPtr = _locationBackgroundGfxBuf + srcY * 640 + dstOffset; + uint8 *dstPtr = _locationBackgroundGfxBuf + srcY * 640 + xPos; const uint8 *srcPtr = p + frameOffset + 12; switch (s->colorType) { case 0: @@ -1910,7 +1916,7 @@ void TuckerEngine::drawSprite(int num) { Graphics::decodeRLE_248(dstPtr, srcPtr, srcW, srcH, 0, s->yMaxBackground, s->flipX != 0); break; } - addDirtyRect(dstOffset % 640, dstOffset / 640 + srcY, srcW, srcH); + addDirtyRect(xPos, srcY, srcW, srcH); } } @@ -2826,7 +2832,7 @@ void TuckerEngine::drawStringInteger(int num, int x, int y, int digits) { Graphics::drawStringChar(_locationBackgroundGfxBuf + offset, numStr[i], 640, 102, _charsetGfxBuf); offset += 8; } - addDirtyRect(x, y, Graphics::_charset.charW * 3, Graphics::_charset.charH); + addDirtyRect(_scrollOffset + x, y, Graphics::_charset.charW * 3, Graphics::_charset.charH); } void TuckerEngine::drawStringAlt(int offset, int color, const uint8 *str, int strLen) { @@ -3740,20 +3746,20 @@ void TuckerEngine::drawSpeechText(int xStart, int y, const uint8 *dataPtr, int n y = count * 10; } for (int i = 0; i < count; ++i) { - int dstOffset = xStart - lines[i].w / 2; - if (dstOffset < _scrollOffset) { - dstOffset = _scrollOffset; - } else if (dstOffset > _scrollOffset + 320 - lines[i].w) { - dstOffset = _scrollOffset + 320 - lines[i].w; + int yPos, xPos = xStart - lines[i].w / 2; + if (xPos < _scrollOffset) { + xPos = _scrollOffset; + } else if (xPos > _scrollOffset + 320 - lines[i].w) { + xPos = _scrollOffset + 320 - lines[i].w; } if (_conversationOptionsCount != 0) { - dstOffset = xStart + _scrollOffset; - dstOffset += (i * 10 + y) * 640; + xPos = xStart + _scrollOffset; + yPos = i * 10 + y; _panelItemWidth = count; } else { - dstOffset += (y - (count - i) * 10) * 640; + yPos = y - (count - i) * 10; } - drawSpeechTextLine(dataPtr, lines[i].offset, lines[i].count, dstOffset, color); + drawSpeechTextLine(dataPtr, lines[i].offset, lines[i].count, xPos, yPos, color); } } @@ -3780,23 +3786,24 @@ int TuckerEngine::splitSpeechTextLines(const uint8 *dataPtr, int pos, int x, int return ret; } -void TuckerEngine::drawSpeechTextLine(const uint8 *dataPtr, int pos, int count, int dstOffset, uint8 color) { - int startOffset = dstOffset; +void TuckerEngine::drawSpeechTextLine(const uint8 *dataPtr, int pos, int count, int x, int y, uint8 color) { + int xStart = x; int i = 0; for (; i < count && dataPtr[pos] != '\n'; ++i) { - Graphics::drawStringChar(_locationBackgroundGfxBuf + dstOffset, dataPtr[pos], 640, color, _charsetGfxBuf); - dstOffset += _charWidthTable[dataPtr[pos]]; + Graphics::drawStringChar(_locationBackgroundGfxBuf + y * 640 + x, dataPtr[pos], 640, color, _charsetGfxBuf); + x += _charWidthTable[dataPtr[pos]]; ++pos; } - addDirtyRect(startOffset % 640, startOffset / 640, Graphics::_charset.charW * i, Graphics::_charset.charH); + addDirtyRect(xStart, y, Graphics::_charset.charW * i, Graphics::_charset.charH); } void TuckerEngine::redrawScreen(int offset) { - debug(9, "redrawScreen() _fullRedrawCounter %d offset %d _dirtyRectsCount %d", _fullRedrawCounter, offset, _dirtyRectsCount); + debug(9, "redrawScreen() _fullRedraw %d offset %d _dirtyRectsCount %d", _fullRedraw, offset, _dirtyRectsCount); assert(offset <= kScreenWidth); - if (_fullRedrawCounter > 0) { - --_fullRedrawCounter; + if (_fullRedraw) { + _fullRedraw = false; _system->copyRectToScreen(_locationBackgroundGfxBuf + offset, kScreenPitch, 0, 0, kScreenWidth, kScreenHeight); + _dirtyRectsPrevCount = _dirtyRectsCount = 0; } else { const int xClip = offset % kScreenPitch; const int yClip = offset / kScreenPitch; @@ -3806,13 +3813,11 @@ void TuckerEngine::redrawScreen(int offset) { } for (int i = 0; i < _dirtyRectsCount; ++i) { redrawScreenRect(clipRect, _dirtyRectsTable[0][i]); - } - _dirtyRectsPrevCount = _dirtyRectsCount; - for (int i = 0; i < _dirtyRectsCount; ++i) { _dirtyRectsTable[1][i] = _dirtyRectsTable[0][i]; } + _dirtyRectsPrevCount = _dirtyRectsCount; + _dirtyRectsCount = 0; } - _dirtyRectsCount = 0; _system->updateScreen(); } @@ -3827,17 +3832,33 @@ void TuckerEngine::redrawScreenRect(const Common::Rect &clip, const Common::Rect if (w <= 0 || h <= 0) { return; } +#if 0 + static const uint8 outlineColor = 0; + memset(_locationBackgroundGfxBuf + r.top * 640 + r.left, outlineColor, w); + memset(_locationBackgroundGfxBuf + (r.top + h - 1) * 640 + r.left, outlineColor, w); + for (int y = r.top; y < r.top + h; ++y) { + _locationBackgroundGfxBuf[y * 640 + r.left] = outlineColor; + _locationBackgroundGfxBuf[y * 640 + r.left + w - 1] = outlineColor; + } +#endif _system->copyRectToScreen(src, 640, r.left, r.top, w, h); } } void TuckerEngine::addDirtyRect(int x, int y, int w, int h) { - if (_dirtyRectsCount >= kMaxDirtyRects) { - _fullRedrawCounter = 2; - _dirtyRectsCount = 0; - } else { - _dirtyRectsTable[0][_dirtyRectsCount] = Common::Rect(x, y, x + w, y + h); - ++_dirtyRectsCount; + if (!_fullRedraw) { + Common::Rect r(x, y, x + w, y + h); + for (int i = 0; i < _dirtyRectsCount; ++i) { + if (_dirtyRectsTable[0][i].contains(r)) { + return; + } + } + if (_dirtyRectsCount < kMaxDirtyRects) { + _dirtyRectsTable[0][_dirtyRectsCount] = r; + ++_dirtyRectsCount; + } else { + _fullRedraw = true; + } } } diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h index 6afccdc4da..21d2e2d49c 100644 --- a/engines/tucker/tucker.h +++ b/engines/tucker/tucker.h @@ -342,7 +342,7 @@ protected: void playSpeechForAction(int i); void drawSpeechText(int xStart, int y, const uint8 *dataPtr, int num, int color); int splitSpeechTextLines(const uint8 *dataPtr, int pos, int x, int &lineCharsCount, int &lineWidth); - void drawSpeechTextLine(const uint8 *dataPtr, int pos, int count, int dstOffset, uint8 color); + void drawSpeechTextLine(const uint8 *dataPtr, int pos, int count, int x, int y, uint8 color); void redrawScreen(int offset); void redrawScreenRect(const Common::Rect &clip, const Common::Rect &dirty); void addDirtyRect(int x, int y, int w, int h); @@ -801,7 +801,7 @@ protected: uint8 *_currentGfxBackground; int _fadePaletteCounter; uint8 _currentPalette[768]; - int _fullRedrawCounter; + bool _fullRedraw; int _dirtyRectsPrevCount, _dirtyRectsCount; Common::Rect _dirtyRectsTable[2][kMaxDirtyRects]; |