reg_t reg_t::operator-(const reg_t right) const { if (getSegment() == right.getSegment()) { // We can subtract numbers, or pointers with the same segment, // an operation which will yield a number like in C return make_reg(0, toSint16() - right.toSint16()); } else { return *this + make_reg(right.getSegment(), -right.toSint16()); } }
uint16 Kernel::findRegType(reg_t reg) { // No segment? Must be integer if (!reg.getSegment()) return SIG_TYPE_INTEGER | (reg.getOffset() ? 0 : SIG_TYPE_NULL); if (reg.getSegment() == 0xFFFF) return SIG_TYPE_UNINITIALIZED; // Otherwise it's an object SegmentObj *mobj = _segMan->getSegmentObj(reg.getSegment()); if (!mobj) return SIG_TYPE_ERROR; uint16 result = 0; if (!mobj->isValidOffset(reg.getOffset())) result |= SIG_IS_INVALID; switch (mobj->getType()) { case SEG_TYPE_SCRIPT: if (reg.getOffset() <= (*(Script *)mobj).getBufSize() && reg.getOffset() >= (uint)-SCRIPT_OBJECT_MAGIC_OFFSET && (*(Script *)mobj).offsetIsObject(reg.getOffset())) { result |= ((Script *)mobj)->getObject(reg.getOffset()) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE; } else result |= SIG_TYPE_REFERENCE; break; case SEG_TYPE_CLONES: result |= SIG_TYPE_OBJECT; break; case SEG_TYPE_LOCALS: case SEG_TYPE_STACK: case SEG_TYPE_DYNMEM: case SEG_TYPE_HUNK: #ifdef ENABLE_SCI32 case SEG_TYPE_ARRAY: case SEG_TYPE_STRING: #endif result |= SIG_TYPE_REFERENCE; break; case SEG_TYPE_LISTS: result |= SIG_TYPE_LIST; break; case SEG_TYPE_NODES: result |= SIG_TYPE_NODE; break; default: return SIG_TYPE_ERROR; } return result; }
static void patchGameSaveRestoreCodeSci2(SegManager *segMan, reg_t methodAddress, byte id, bool doRestore) { Script *script = segMan->getScript(methodAddress.getSegment()); byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.getOffset())); int kcallOffset; if (getSciVersion() < SCI_VERSION_2_1_MIDDLE) { if (doRestore) { memcpy(patchPtr, patchGameRestoreSci2, sizeof(patchGameRestoreSci2)); kcallOffset = 9; } else { memcpy(patchPtr, patchGameSaveSci2, sizeof(patchGameSaveSci2)); kcallOffset = 10; } } else { if (doRestore) { memcpy(patchPtr, patchGameRestoreSci21, sizeof(patchGameRestoreSci21)); kcallOffset = 10; } else { memcpy(patchPtr, patchGameSaveSci21, sizeof(patchGameSaveSci21)); kcallOffset = 11; } } patchPtr[kcallOffset] = id; if (g_sci->isBE()) { SWAP(patchPtr[kcallOffset + 1], patchPtr[kcallOffset + 2]); } }
static void patchGameSaveRestoreCode(SegManager *segMan, reg_t methodAddress, byte id) { Script *script = segMan->getScript(methodAddress.getSegment()); byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.getOffset())); memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave)); patchPtr[8] = id; }
Common::String Kernel::lookupText(reg_t address, int index) { char *seeker; Resource *textres; if (address.getSegment()) return _segMan->getString(address); int textlen; int _index = index; textres = _resMan->findResource(ResourceId(kResourceTypeText, address.getOffset()), 0); if (!textres) { error("text.%03d not found", address.getOffset()); return NULL; /* Will probably segfault */ } textlen = textres->size; seeker = (char *) textres->data; while (index--) while ((textlen--) && (*seeker++)) ; if (textlen) return seeker; error("Index %d out of bounds in text.%03d", _index, address.getOffset()); return NULL; }
void Object::initSuperClass(SegManager *segMan, reg_t addr) { uint16 superClassOffset = getSuperClassSelector().getOffset(); if (superClassOffset == 0xffff) // -1 setSuperClassSelector(NULL_REG); // no superclass else setSuperClassSelector(segMan->getClassAddress(superClassOffset, SCRIPT_GET_LOCK, addr.getSegment())); }
static void patchGameSaveRestoreCodeSci21(SegManager *segMan, reg_t methodAddress, byte id, bool doRestore) { Script *script = segMan->getScript(methodAddress.getSegment()); byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.getOffset())); memcpy(patchPtr, patchGameRestoreSaveSci21, sizeof(patchGameRestoreSaveSci21)); if (doRestore) patchPtr[2] = 0x78; // push1 patchPtr[9] = id; }
static void patchGameSaveRestoreCode(SegManager *segMan, reg_t methodAddress, byte id) { Script *script = segMan->getScript(methodAddress.getSegment()); byte *patchPtr = const_cast<byte *>(script->getBuf(methodAddress.getOffset())); if (getSciVersion() <= SCI_VERSION_1_1) memcpy(patchPtr, patchGameRestoreSave, sizeof(patchGameRestoreSave)); else // SCI2+ memcpy(patchPtr, patchGameRestoreSaveSci2, sizeof(patchGameRestoreSaveSci2)); patchPtr[8] = id; }
void MessageState::outputString(reg_t buf, const Common::String &str) { #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { if (_segMan->getSegmentType(buf.getSegment()) == SEG_TYPE_STRING) { 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 if (_segMan->getSegmentType(buf.getSegment()) == SEG_TYPE_ARRAY) { // Happens in the intro of LSL6, we are asked to write the string // into an array SciArray<reg_t> *sciString = _segMan->lookupArray(buf); sciString->setSize(str.size() + 1); for (uint32 i = 0; i < str.size(); i++) sciString->setValue(i, make_reg(0, str.c_str()[i])); sciString->setValue(str.size(), NULL_REG); } } else { #endif SegmentRef buffer_r = _segMan->dereference(buf); if ((unsigned)buffer_r.maxSize >= str.size() + 1) { _segMan->strcpy(buf, str.c_str()); } else { // LSL6 sets an exit text here, but the buffer size allocated // is too small. Don't display a warning in this case, as we // don't use the exit text anyway - bug report #3035533 if (g_sci->getGameId() == GID_LSL6 && str.hasPrefix("\r\n(c) 1993 Sierra On-Line, Inc")) { // LSL6 buggy exit text, don't show warning } 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, ""); } #ifdef ENABLE_SCI32 } #endif }
void WorklistManager::push(reg_t reg) { if (!reg.getSegment()) // No numbers return; debugC(kDebugLevelGC, "[GC] Adding %04x:%04x", PRINT_REG(reg)); if (_map.contains(reg)) return; // already dealt with it _map.setVal(reg, true); _worklist.push_back(reg); }
int SoundCommandParser::getSoundResourceId(reg_t obj) { int resourceId = obj.getSegment() ? (int)readSelectorValue(_segMan, obj, SELECTOR(number)) : -1; // Modify the resourceId for the Windows versions that have an alternate MIDI soundtrack, like SSCI did. if (g_sci && g_sci->_features->useAltWinGMSound()) { // Check if the alternate MIDI song actually exists... // There are cases where it just doesn't exist (e.g. SQ4, room 530 - // bug #3392767). In these cases, use the DOS tracks instead. if (resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, resourceId + 1000))) resourceId += 1000; } return resourceId; }
void GfxMenu::kernelSetAttribute(uint16 menuId, uint16 itemId, uint16 attributeId, reg_t value) { GuiMenuItemEntry *itemEntry = findItem(menuId, itemId); if (!itemEntry) { // PQ2 demo calls this, for example, but has no menus (bug report #3034507). Some SCI // fan games (Al Pond 2, Aquarius) call this too on non-existent menu items. The // original interpreter ignored these as well. debugC(kDebugLevelGraphics, "Tried to setAttribute() on non-existent menu-item %d:%d", menuId, itemId); return; } switch (attributeId) { case SCI_MENU_ATTRIBUTE_ENABLED: itemEntry->enabled = !value.isNull(); break; case SCI_MENU_ATTRIBUTE_SAID: itemEntry->saidVmPtr = value; break; case SCI_MENU_ATTRIBUTE_TEXT: itemEntry->text = _segMan->getString(value); itemEntry->textVmPtr = value; // We assume here that no script ever creates a separatorLine dynamically break; case SCI_MENU_ATTRIBUTE_KEYPRESS: itemEntry->keyPress = tolower(value.getOffset()); itemEntry->keyModifier = 0; // TODO: Find out how modifier is handled debug("setAttr keypress %X %X", value.getSegment(), value.getOffset()); break; case SCI_MENU_ATTRIBUTE_TAG: itemEntry->tag = value.getOffset(); break; default: // Happens when loading a game in LSL3 - attribute 1A warning("setAttribute() called with unsupported attributeId %X", attributeId); } }