aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine
diff options
context:
space:
mode:
authorMatthew Hoops2009-12-30 16:00:56 +0000
committerMatthew Hoops2009-12-30 16:00:56 +0000
commit5382aa1ab0ac0b42a33a4b73664e3a8064b4211b (patch)
tree17ad3256bc97d181433414aac36b8cf224e22e71 /engines/sci/engine
parentfd2d0fc7182e97fedf901b276bc7e48dcdcb4c13 (diff)
downloadscummvm-rg350-5382aa1ab0ac0b42a33a4b73664e3a8064b4211b.tar.gz
scummvm-rg350-5382aa1ab0ac0b42a33a4b73664e3a8064b4211b.tar.bz2
scummvm-rg350-5382aa1ab0ac0b42a33a4b73664e3a8064b4211b.zip
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
Diffstat (limited to 'engines/sci/engine')
-rw-r--r--engines/sci/engine/kernel.cpp6
-rw-r--r--engines/sci/engine/kernel.h2
-rw-r--r--engines/sci/engine/kernel32.cpp87
-rw-r--r--engines/sci/engine/kfile.cpp4
-rw-r--r--engines/sci/engine/kstring.cpp10
-rw-r--r--engines/sci/engine/message.cpp28
-rw-r--r--engines/sci/engine/seg_manager.cpp7
-rw-r--r--engines/sci/engine/segment.cpp8
-rw-r--r--engines/sci/engine/segment.h1
9 files changed, 119 insertions, 34 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<SciArray<reg_t> > {
ArrayTable() : Table<SciArray<reg_t> >(SEG_TYPE_ARRAY) {}
virtual void saveLoadWithSerializer(Common::Serializer &ser) {}
+ SegmentRef dereference(reg_t pointer);
};
struct StringTable : public Table<SciString> {