From 5382aa1ab0ac0b42a33a4b73664e3a8064b4211b Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Wed, 30 Dec 2009 16:00:56 +0000 Subject: SCI32: - Set signature for Array/String - Add the kernel table differences for the GK2 demo - Implement kMessage changes in SCI32 - Use an empty string as the default path for all games now (and modify kValidPath to accept that only as valid) - Add dereferencing for Arrays svn-id: r46756 --- engines/sci/engine/kernel.cpp | 6 ++- engines/sci/engine/kernel.h | 2 +- engines/sci/engine/kernel32.cpp | 87 ++++++++++++++++++++++++++++---------- engines/sci/engine/kfile.cpp | 4 +- engines/sci/engine/kstring.cpp | 10 +++++ engines/sci/engine/message.cpp | 28 ++++++++---- engines/sci/engine/seg_manager.cpp | 7 +++ engines/sci/engine/segment.cpp | 8 ++++ engines/sci/engine/segment.h | 1 + engines/sci/sci.cpp | 12 +++--- engines/sci/sci.h | 1 + 11 files changed, 125 insertions(+), 41 deletions(-) diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 0351ef0ae4..702113b23a 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -657,6 +657,10 @@ int determine_reg_type(SegManager *segMan, reg_t reg) { case SEG_TYPE_STACK: case SEG_TYPE_SYS_STRINGS: case SEG_TYPE_DYNMEM: +#ifdef ENABLE_SCI32 + case SEG_TYPE_ARRAY: + case SEG_TYPE_STRING: +#endif return KSIG_REF; case SEG_TYPE_LISTS: return KSIG_LIST; @@ -771,7 +775,7 @@ bool Kernel::loadKernelNames(Common::String gameId) { #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2_1) - setKernelNamesSci21(); + setKernelNamesSci21(gameId); else if (getSciVersion() == SCI_VERSION_2) setKernelNamesSci2(); else diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 9cf39e7e7a..2cc7ae8e57 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -111,7 +111,7 @@ private: /** * Sets the default kernel function names to the SCI2.1 kernel functions */ - void setKernelNamesSci21(); + void setKernelNamesSci21(Common::String gameId); #endif /** diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index fbe5b200a8..d6fe995467 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -32,6 +32,8 @@ namespace Sci { +// NOTE: 0x72-0x79, 0x85-0x86, 0x88 are from the GK2 demo (which has debug support) and are +// just Dummy in other SCI2 games. static const char *sci2_default_knames[] = { /*0x00*/ "Load", /*0x01*/ "UnLoad", @@ -147,14 +149,14 @@ static const char *sci2_default_knames[] = { /*0x6f*/ "AvoidPath", /*0x70*/ "InPolygon", /*0x71*/ "MergePoly", - /*0x72*/ "Dummy", - /*0x73*/ "Dummy", - /*0x74*/ "Dummy", - /*0x75*/ "Dummy", - /*0x76*/ "Dummy", - /*0x77*/ "Dummy", - /*0x78*/ "Dummy", - /*0x79*/ "Dummy", + /*0x72*/ "SetDebug", + /*0x73*/ "InspectObject", + /*0x74*/ "MemoryInfo", + /*0x75*/ "Profiler", + /*0x76*/ "Record", + /*0x77*/ "PlayBack", + /*0x78*/ "MonoOut", + /*0x79*/ "SetFatalStr", /*0x7a*/ "GetCWD", /*0x7b*/ "ValidPath", /*0x7c*/ "FileIO", @@ -166,12 +168,35 @@ static const char *sci2_default_knames[] = { /*0x82*/ "Array", /*0x83*/ "String", /*0x84*/ "RemapColors", - /*0x85*/ "Dummy", - /*0x86*/ "Dummy", + /*0x85*/ "IntegrityChecking", + /*0x86*/ "CheckIntegrity", /*0x87*/ "ObjectIntersect", - /*0x88*/ "Dummy", + /*0x88*/ "MarkMemory", /*0x89*/ "TextWidth", - /*0x8a*/ "PointSize" + /*0x8a*/ "PointSize", + + // GK2 Demo only kernel functions + /*0x8b*/ "AddLine", + /*0x8c*/ "DeleteLine", + /*0x8d*/ "UpdateLine", + /*0x8e*/ "AddPolygon", + /*0x8f*/ "DeletePolygon", + /*0x90*/ "UpdatePolygon", + /*0x91*/ "Bitmap", + /*0x92*/ "ScrollWindow", + /*0x93*/ "SetFontRes", + /*0x94*/ "MovePlaneItems", + /*0x95*/ "PreloadResource", + /*0x96*/ "Dummy", + /*0x97*/ "ResourceTrack", + /*0x98*/ "CheckCDisc", + /*0x99*/ "GetSaveCDisc", + /*0x9a*/ "TestPoly", + /*0x9b*/ "WinHelp", + /*0x9c*/ "LoadChunk", + /*0x9d*/ "SetPalStyleRange", + /*0x9e*/ "AddPicAt", + /*0x9f*/ "MessageBox" }; static const char *sci21_default_knames[] = { @@ -302,7 +327,7 @@ static const char *sci21_default_knames[] = { /*0x7c*/ "SetQuitStr", /*0x7d*/ "GetConfig", /*0x7e*/ "Table", - /*0x7f*/ "Dummy", + /*0x7f*/ "WinHelp", // Windows only /*0x80*/ "Dummy", /*0x81*/ "Dummy", /*0x82*/ "Dummy", @@ -314,7 +339,7 @@ static const char *sci21_default_knames[] = { /*0x88*/ "Dummy", /*0x89*/ "Dummy", /*0x8a*/ "LoadChunk", - /*0x8b*/ "SetPalStyleRange" + /*0x8b*/ "SetPalStyleRange", /*0x8c*/ "AddPicAt", /*0x8d*/ "Dummy", /*0x8e*/ "NewRoom", @@ -324,11 +349,11 @@ static const char *sci21_default_knames[] = { /*0x92*/ "PlayVMD", /*0x93*/ "SetHotRectangles", /*0x94*/ "MulDiv", - /*0x95*/ "Dummy", - /*0x96*/ "Dummy", - /*0x97*/ "Dummy", - /*0x98*/ "Dummy", - /*0x99*/ "Dummy", + /*0x95*/ "GetSierraProfileInt", // Windows only + /*0x96*/ "GetSierraProfileString", // Windows only + /*0x97*/ "SetWindowsOption", // Windows only + /*0x98*/ "GetWindowsOption", // Windows only + /*0x99*/ "WinDLL", // Windows only // SCI3 /*0x9a*/ "Dummy", @@ -336,12 +361,30 @@ static const char *sci21_default_knames[] = { /*0x9c*/ "DeletePic" }; +enum { + kKernelEntriesSci2 = 0x8b, + kKernelEntriesGk2Demo = 0xa0, + kKernelEntriesSci21 = 0x9a, + kKernelEntriesSci3 = 0x9d +}; + void Kernel::setKernelNamesSci2() { - _kernelNames = Common::StringList(sci2_default_knames, ARRAYSIZE(sci2_default_knames)); + _kernelNames = Common::StringList(sci2_default_knames, kKernelEntriesSci2); } -void Kernel::setKernelNamesSci21() { - _kernelNames = Common::StringList(sci21_default_knames, ARRAYSIZE(sci21_default_knames)); +void Kernel::setKernelNamesSci21(Common::String gameId) { + // The Gabriel Knight 2 demo uses a different kernel function set. It's pretty much a cross between + // the SCI2 and SCI2.1 set. Strangely, the GK2 executable still has the 2.100.002 version string, + // even though it wouldn't be compatible with the other 2.100.002 games... + if (gameId == "gk2" && ((SciEngine *)g_engine)->isDemo()) { + _kernelNames = Common::StringList(sci2_default_knames, kKernelEntriesGk2Demo); + // OnMe is IsOnMe here, but they should be compatible + _kernelNames[0x23] = "Robot"; // Graph in SCI2 + _kernelNames[0x2e] = "Priority"; // DisposeTextBitmap in SCI2 + } else { + // TODO: Differentiate between SCI2.1/3 + _kernelNames = Common::StringList(sci21_default_knames, kKernelEntriesSci3); + } } // SCI2 Kernel Functions diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 550b6740b6..665142c90c 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -592,8 +592,8 @@ reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { reg_t kValidPath(EngineState *s, int argc, reg_t *argv) { Common::String path = s->_segMan->getString(argv[0]); - // FIXME: For now, we only accept the (fake) root dir "/" as a valid path. - s->r_acc = make_reg(0, path == "/"); + // FIXME: For now, we only accept the (fake) dir "" as a valid path. + s->r_acc = make_reg(0, path == ""); debug(3, "kValidPath(%s) -> %d", path.c_str(), s->r_acc.offset); diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index b32edf7a68..19c3f1540f 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -639,6 +639,16 @@ reg_t kGetMessage(EngineState *s, int argc, reg_t *argv) { reg_t kMessage(EngineState *s, int argc, reg_t *argv) { uint func = argv[0].toUint16(); + +#ifdef ENABLE_SCI32 + if (getSciVersion() >= SCI_VERSION_2) { + // In complete weirdness, SCI32 bumps up subops 3-8 to 4-9 and stubs off subop 3. + if (func == 3) + warning("SCI32 kMessage(3)"); + else if (func > 3) + func--; + } +#endif if ((func != K_MESSAGE_NEXT) && (argc < 2)) { warning("Message: not enough arguments passed to subfunction %d", func); diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp index 39c2eb326b..c55ac0b84f 100644 --- a/engines/sci/engine/message.cpp +++ b/engines/sci/engine/message.cpp @@ -363,17 +363,29 @@ Common::String MessageState::processString(const char *s) { } void MessageState::outputString(reg_t buf, const Common::String &str) { - SegmentRef buffer_r = _segMan->dereference(buf); - - if ((unsigned)buffer_r.maxSize >= str.size() + 1) { - _segMan->strcpy(buf, str.c_str()); +#ifdef ENABLE_SCI32 + if (getSciVersion() >= SCI_VERSION_2) { + SciString *sciString = _segMan->lookupString(buf); + sciString->setSize(str.size() + 1); + for (uint32 i = 0; i < str.size(); i++) + sciString->setValue(i, str.c_str()[i]); + sciString->setValue(str.size(), 0); } else { - warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(buf), str.size() + 1, str.c_str()); +#endif + SegmentRef buffer_r = _segMan->dereference(buf); + + if ((unsigned)buffer_r.maxSize >= str.size() + 1) { + _segMan->strcpy(buf, str.c_str()); + } else { + warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(buf), str.size() + 1, str.c_str()); - // Set buffer to empty string if possible - if (buffer_r.maxSize > 0) - _segMan->strcpy(buf, ""); + // Set buffer to empty string if possible + if (buffer_r.maxSize > 0) + _segMan->strcpy(buf, ""); + } +#ifdef ENABLE_SCI32 } +#endif } void MessageState::lastQuery(int &module, MessageTuple &tuple) { diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 5db6b88136..755e44c543 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -929,7 +929,14 @@ byte *SegManager::derefBulkPtr(reg_t pointer, int entries) { } reg_t *SegManager::derefRegPtr(reg_t pointer, int entries) { +#ifdef ENABLE_SCI32 + // HACK: Due to a limitation in the SegManager, we don't know if the pointer needs to be + // word aligned. If it's a new style array, then it is just accessing the arrays from a + // table and this doesn't need to be true. + if (pointer.offset & 1 && pointer.segment != Arrays_seg_id) { +#else if (pointer.offset & 1) { +#endif warning("Unaligned pointer read: %04x:%04x expected with word alignment", PRINT_REG(pointer)); return NULL; } diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 4b4ce491e5..20d27b9ba2 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -493,6 +493,14 @@ void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback not #ifdef ENABLE_SCI32 +SegmentRef ArrayTable::dereference(reg_t pointer) { + SegmentRef ret; + ret.isRaw = false; + ret.maxSize = _table[pointer.offset].getSize() * 2; + ret.reg = _table[pointer.offset].getRawData(); + return ret; +} + Common::String SciString::toString() { if (_type != 3) error("SciString::toString(): Array is not a string"); diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index eb34043c01..a57c9766ae 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -757,6 +757,7 @@ struct ArrayTable : public Table > { ArrayTable() : Table >(SEG_TYPE_ARRAY) {} virtual void saveLoadWithSerializer(Common::Serializer &ser) {} + SegmentRef dereference(reg_t pointer); }; struct StringTable : public Table { diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index dd085fe9aa..eda02d6999 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -179,13 +179,7 @@ Common::Error SciEngine::run() { // Set the savegame dir (actually, we set it to a fake value, // since we cannot let the game control where saves are stored) - // Some SCI1.1 games (e.g. SQ4CD) complain if this is empty -#ifdef ENABLE_SCI32 - if (getSciVersion() >= SCI_VERSION_2) - strcpy(_gamestate->sys_strings->_strings[SYS_STRING_SAVEDIR]._value, ""); - else -#endif - strcpy(_gamestate->sys_strings->_strings[SYS_STRING_SAVEDIR]._value, "/"); + strcpy(_gamestate->sys_strings->_strings[SYS_STRING_SAVEDIR]._value, ""); SciVersion soundVersion = _gamestate->detectDoSoundType(); @@ -274,6 +268,10 @@ uint32 SciEngine::getFlags() const { return _gameDescription->flags; } +bool SciEngine::isDemo() const { + return getFlags() & ADGF_DEMO; +} + Common::String SciEngine::getSavegameName(int nr) const { return _targetName + Common::String::printf(".%03d", nr); } diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 78f444f6f6..f6df9ce1fc 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -134,6 +134,7 @@ public: Kernel *getKernel() const { return _kernel; } EngineState *getEngineState() const { return _gamestate; } Vocabulary *getVocabulary() const { return _vocabulary; } + bool isDemo() const; Common::String getSavegameName(int nr) const; Common::String getSavegamePattern() const; -- cgit v1.2.3