- 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
This commit is contained in:
Matthew Hoops 2009-12-30 16:00:56 +00:00
parent fd2d0fc718
commit 5382aa1ab0
11 changed files with 125 additions and 41 deletions

View file

@ -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

View file

@ -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
/**

View file

@ -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

View file

@ -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);

View file

@ -640,6 +640,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);
return NULL_REG;

View file

@ -363,6 +363,15 @@ Common::String MessageState::processString(const char *s) {
}
void MessageState::outputString(reg_t buf, const Common::String &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 {
#endif
SegmentRef buffer_r = _segMan->dereference(buf);
if ((unsigned)buffer_r.maxSize >= str.size() + 1) {
@ -374,6 +383,9 @@ void MessageState::outputString(reg_t buf, const Common::String &str) {
if (buffer_r.maxSize > 0)
_segMan->strcpy(buf, "");
}
#ifdef ENABLE_SCI32
}
#endif
}
void MessageState::lastQuery(int &module, MessageTuple &tuple) {

View file

@ -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;
}

View file

@ -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");

View file

@ -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> {

View file

@ -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, "/");
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);
}

View file

@ -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;