reg_t SoundCommandParser::kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc) { reg_t obj = argv[0]; int16 value = argv[1].toSint16(); debugC(kDebugLevelSound, "kDoSound(setPriority): %04x:%04x, %d", PRINT_REG(obj), value); MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { debugC(kDebugLevelSound, "kDoSound(setPriority): Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } if (value == -1) { uint16 resourceId = musicSlot->resourceId; // Set priority from the song data Resource *song = _resMan->findResource(ResourceId(kResourceTypeSound, resourceId), 0); if (song->data[0] == 0xf0) _music->soundSetPriority(musicSlot, song->data[1]); else warning("kDoSound(setPriority): Attempt to unset song priority when there is no built-in value"); //pSnd->prio=0;field_15B=0 writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) & 0xFD); } else { // Scripted priority //pSnd->field_15B=1; writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) | 2); //DoSOund(0xF,hobj,w) } return acc; }
static bool isSaneNodePointer(SegManager *segMan, reg_t addr) { bool havePrev = false; reg_t prev = addr; do { Node *node = segMan->lookupNode(addr, false); if (!node) { if ((g_sci->getGameId() == GID_ICEMAN) && (g_sci->getEngineState()->currentRoomNumber() == 40)) { // ICEMAN: when plotting course, unDrawLast is called by startPlot::changeState // there is no previous entry so we get 0 in here } else if ((g_sci->getGameId() == GID_HOYLE1) && (g_sci->getEngineState()->currentRoomNumber() == 3)) { // HOYLE1: after sorting cards in hearts, in the next round // we get an invalid node - bug #3038433 } else { error("isSaneNodePointer: Node at %04x:%04x wasn't found", PRINT_REG(addr)); } return false; } if (havePrev && node->pred != prev) { error("isSaneNodePointer: Node at %04x:%04x points to invalid predecessor %04x:%04x (should be %04x:%04x)", PRINT_REG(addr), PRINT_REG(node->pred), PRINT_REG(prev)); //node->pred = prev; // fix the problem in the node return false; } prev = addr; addr = node->succ; havePrev = true; } while (!addr.isNull()); return true; }
static void addToEnd(EngineState *s, reg_t listRef, reg_t nodeRef) { List *list = s->_segMan->lookupList(listRef); Node *newNode = s->_segMan->lookupNode(nodeRef); debugC(kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef)); if (!newNode) error("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef)); #ifdef CHECK_LISTS checkListPointer(s->_segMan, listRef); #endif newNode->pred = list->last; newNode->succ = NULL_REG; // Set node to be the first and last node if it's the only node of the list if (list->last.isNull()) list->first = nodeRef; else { Node *old_n = s->_segMan->lookupNode(list->last); old_n->succ = nodeRef; } list->last = nodeRef; }
reg_t kFindKey(EngineState *s, int argc, reg_t *argv) { reg_t node_pos; reg_t key = argv[1]; reg_t list_pos = argv[0]; debugC(kDebugLevelNodes, "Looking for key %04x:%04x in list %04x:%04x", PRINT_REG(key), PRINT_REG(list_pos)); #ifdef CHECK_LISTS checkListPointer(s->_segMan, argv[0]); #endif node_pos = s->_segMan->lookupList(list_pos)->first; debugC(kDebugLevelNodes, "First node at %04x:%04x", PRINT_REG(node_pos)); while (!node_pos.isNull()) { Node *n = s->_segMan->lookupNode(node_pos); if (n->key == key) { debugC(kDebugLevelNodes, " Found key at %04x:%04x", PRINT_REG(node_pos)); return node_pos; } node_pos = n->succ; debugC(kDebugLevelNodes, "NextNode at %04x:%04x", PRINT_REG(node_pos)); } debugC(kDebugLevelNodes, "Looking for key without success"); return NULL_REG; }
reg_t SoundCommandParser::kDoSoundSendMidi(int argc, reg_t *argv, reg_t acc) { reg_t obj = argv[0]; byte channel = argv[1].toUint16() & 0xf; byte midiCmd = argv[2].toUint16() & 0xff; // TODO: first there is a 4-parameter variant of this call which needs to get reversed // second the current code isn't 100% accurate, sierra sci does checks on the 4th parameter if (argc == 4) return acc; uint16 controller = argv[3].toUint16(); uint16 param = argv[4].toUint16(); debugC(kDebugLevelSound, "kDoSound(sendMidi): %04x:%04x, %d, %d, %d, %d", PRINT_REG(obj), channel, midiCmd, controller, param); if (channel) channel--; // channel is given 1-based, we are using 0-based uint32 midiCommand = (channel | midiCmd) | ((uint32)controller << 8) | ((uint32)param << 16); MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // TODO: maybe it's possible to call this with obj == 0:0 and send directly?! // if so, allow it //_music->sendMidiCommand(_midiCommand); warning("kDoSound(sendMidi): Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } _music->sendMidiCommand(musicSlot, midiCommand); return acc; }
void invokeSelector(EngineState *s, reg_t object, int selectorId, int k_argc, StackPtr k_argp, int argc, const reg_t *argv) { int i; int framesize = 2 + 1 * argc; int slc_type; StackPtr stackframe = k_argp + k_argc; stackframe[0] = make_reg(0, selectorId); // The selector we want to call stackframe[1] = make_reg(0, argc); // Argument count slc_type = lookupSelector(s->_segMan, object, selectorId, NULL, NULL); if (slc_type == kSelectorNone) { error("Selector '%s' of object at %04x:%04x could not be invoked", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object)); } if (slc_type == kSelectorVariable) { error("Attempting to invoke variable selector %s of object %04x:%04x", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object)); } for (i = 0; i < argc; i++) stackframe[2 + i] = argv[i]; // Write each argument ExecStack *xstack; // Now commit the actual function: xstack = send_selector(s, object, object, stackframe, framesize, stackframe); xstack->sp += argc + 2; xstack->fp += argc + 2; run_vm(s); // Start a new vm }
void process_sound_events(EngineState *s) { /* Get all sound events, apply their changes to the heap */ int result; SongHandle handle; int cue; if (s->_version >= SCI_VERSION_01) return; /* SCI01 and later explicitly poll for everything */ while ((result = s->_sound.sfx_poll(&handle, &cue))) { reg_t obj = DEFROBNICATE_HANDLE(handle); if (!is_object(s, obj)) { warning("Non-object %04x:%04x received sound signal (%d/%d)", PRINT_REG(obj), result, cue); return; } switch (result) { case SI_LOOP: debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x looped (to %d)\n", PRINT_REG(obj), cue); /* PUT_SEL32V(obj, loops, GET_SEL32V(obj, loop) - 1);*/ PUT_SEL32V(obj, signal, -1); break; case SI_RELATIVE_CUE: debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x received relative cue %d\n", PRINT_REG(obj), cue); PUT_SEL32V(obj, signal, cue + 0x7f); break; case SI_ABSOLUTE_CUE: debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x received absolute cue %d\n", PRINT_REG(obj), cue); PUT_SEL32V(obj, signal, cue); break; case SI_FINISHED: debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x finished\n", PRINT_REG(obj)); PUT_SEL32V(obj, signal, -1); PUT_SEL32V(obj, state, _K_SOUND_STATUS_STOPPED); break; default: warning("Unexpected result from sfx_poll: %d", result); break; } } }
reg_t SoundCommandParser::kDoSoundSetHold(int argc, reg_t *argv, reg_t acc) { reg_t obj = argv[0]; debugC(kDebugLevelSound, "doSoundSetHold: %04x:%04x, %d", PRINT_REG(argv[0]), argv[1].toUint16()); MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(setHold): Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } // Set the special hold marker ID where the song should be looped at. musicSlot->hold = argv[1].toSint16(); return acc; }
void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t value) { ObjVarRef address; if ((selectorId < 0) || (selectorId > (int)g_sci->getKernel()->getSelectorNamesSize())) { error("Attempt to write to invalid selector %d of" " object at %04x:%04x.", selectorId, PRINT_REG(object)); return; } if (lookupSelector(segMan, object, selectorId, &address, NULL) != kSelectorVariable) error("Selector '%s' of object at %04x:%04x could not be" " written to", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object)); else *address.getPointer(segMan) = value; }
reg_t GfxPaint32::kernelAddLine(const reg_t planeObject, const Common::Point &startPoint, const Common::Point &endPoint, const int16 priority, const uint8 color, const LineStyle style, const uint16 pattern, const uint8 thickness) { Plane *plane = g_sci->_gfxFrameout->getPlanes().findByObject(planeObject); if (plane == nullptr) { error("kAddLine: Plane %04x:%04x not found", PRINT_REG(planeObject)); } Common::Rect gameRect; reg_t bitmapId = makeLineBitmap(startPoint, endPoint, priority, color, style, pattern, thickness, gameRect); CelInfo32 celInfo; celInfo.type = kCelTypeMem; celInfo.bitmap = bitmapId; // SSCI stores the line color on `celInfo`, even though // this is not a `kCelTypeColor`, as a hack so that // `kUpdateLine` can get the originally used color celInfo.color = color; ScreenItem *screenItem = new ScreenItem(planeObject, celInfo, gameRect); screenItem->_priority = priority; screenItem->_fixedPriority = true; plane->_screenItemList.add(screenItem); return screenItem->_object; }
void SoundCommandParser::processStopSound(reg_t obj, bool sampleFinishedPlaying) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(stop): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } if (_soundVersion <= SCI_VERSION_0_LATE) { writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundStopped); } else { writeSelectorValue(_segMan, obj, SELECTOR(handle), 0); } // Set signal selector in sound SCI0 games only, when the sample has // finished playing. If we don't set it at all, we get a problem when using // vaporizer on the 2 guys. If we set it all the time, we get no music in // sq3new and kq1. // FIXME: This *may* be wrong, it's impossible to find out in Sierra DOS // SCI, because SCI0 under DOS didn't have sfx drivers included. // We need to set signal in sound SCI1+ games all the time. if ((_soundVersion > SCI_VERSION_0_LATE) || sampleFinishedPlaying) writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); musicSlot->dataInc = 0; musicSlot->signal = SIGNAL_OFFSET; _music->soundStop(musicSlot); }
reg_t reg_t::operator+(const reg_t right) const { if (isPointer() && right.isNumber()) { // Pointer arithmetics. Only some pointer types make sense here SegmentObj *mobj = g_sci->getEngineState()->_segMan->getSegmentObj(getSegment()); if (!mobj) error("[VM]: Attempt to add %d to invalid pointer %04x:%04x", right.getOffset(), PRINT_REG(*this)); switch (mobj->getType()) { case SEG_TYPE_LOCALS: case SEG_TYPE_SCRIPT: case SEG_TYPE_STACK: case SEG_TYPE_DYNMEM: return make_reg(getSegment(), getOffset() + right.toSint16()); default: return lookForWorkaround(right, "addition"); } } else if (isNumber() && right.isPointer()) { // Adding a pointer to a number, flip the order return right + *this; } else if (isNumber() && right.isNumber()) { // Normal arithmetics return make_reg(0, toSint16() + right.toSint16()); } else { return lookForWorkaround(right, "addition"); } }
void GfxFrameout::printPlaneList(Console *con) { for (PlaneList::const_iterator it = _planes.begin(); it != _planes.end(); ++it) { PlaneEntry p = *it; Common::String curPlaneName = _segMan->getObjectName(p.object); Common::Rect r = p.upscaledPlaneRect; Common::Rect cr = p.upscaledPlaneClipRect; con->DebugPrintf("%04x:%04x (%s): prio %d, lastprio %d, offsetX %d, offsetY %d, pic %d, mirror %d, back %d\n", PRINT_REG(p.object), curPlaneName.c_str(), (int16)p.priority, (int16)p.lastPriority, p.planeOffsetX, p.planeOffsetY, p.pictureId, p.planePictureMirrored, p.planeBack); con->DebugPrintf(" rect: (%d, %d, %d, %d), clip rect: (%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom, cr.left, cr.top, cr.right, cr.bottom); if (p.pictureId != 0xffff && p.pictureId != 0xfffe) { con->DebugPrintf("Pictures:\n"); for (PlanePictureList::iterator pictureIt = _planePictures.begin(); pictureIt != _planePictures.end(); pictureIt++) { if (pictureIt->object == p.object) { con->DebugPrintf(" Picture %d: x %d, y %d\n", pictureIt->pictureId, pictureIt->startX, pictureIt->startY); } } } } }
void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) { #ifdef GC_DEBUG Object *victim_obj = &(_table[addr.offset]); if (!(victim_obj->_flags & OBJECT_FLAG_FREED)) warning("[GC] Clone %04x:%04x not reachable and not freed (freeing now)", PRINT_REG(addr)); #ifdef GC_DEBUG_VERBOSE else warning("[GC-DEBUG] Clone %04x:%04x: Freeing", PRINT_REG(addr)); warning("[GC] Clone had pos %04x:%04x", PRINT_REG(victim_obj->pos)); #endif #endif freeEntry(addr.offset); }
reg_t kListAt(EngineState *s, int argc, reg_t *argv) { if (argc != 2) { error("kListAt called with %d parameters", argc); return NULL_REG; } List *list = s->_segMan->lookupList(argv[0]); reg_t curAddress = list->first; if (list->first.isNull()) { error("kListAt tried to reference empty list (%04x:%04x)", PRINT_REG(argv[0])); return NULL_REG; } Node *curNode = s->_segMan->lookupNode(curAddress); reg_t curObject = curNode->value; int16 listIndex = argv[1].toUint16(); int curIndex = 0; while (curIndex != listIndex) { if (curNode->succ.isNull()) { // end of the list? return NULL_REG; } curAddress = curNode->succ; curNode = s->_segMan->lookupNode(curAddress); curObject = curNode->value; curIndex++; } return curObject; }
SegmentRef LocalVariables::dereference(reg_t pointer) { SegmentRef ret; ret.isRaw = false; // reg_t based data! ret.maxSize = (_locals.size() - pointer.offset / 2) * 2; if (pointer.offset & 1) { ret.maxSize -= 1; ret.skipByte = true; } if (ret.maxSize > 0) { ret.reg = &_locals[pointer.offset / 2]; } else { if ((g_sci->getEngineState()->currentRoomNumber() == 160 || g_sci->getEngineState()->currentRoomNumber() == 220) && g_sci->getGameId() == GID_LAURABOW2) { // WORKAROUND: Happens in two places during the intro of LB2CD, both // from kMemory(peek): // - room 160: Heap 160 has 83 local variables (0-82), and the game // asks for variables at indices 83 - 90 too. // - room 220: Heap 220 has 114 local variables (0-113), and the // game asks for variables at indices 114-120 too. } else { error("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer)); } ret.reg = 0; } return ret; }
reg_t SoundCommandParser::kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc) { reg_t obj = argv[0]; int16 value = argv[1].toSint16(); debugC(kDebugLevelSound, "kDoSound(setLoop): %04x:%04x, %d", PRINT_REG(obj), value); MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // Apparently, it's perfectly normal for a game to call cmdSetSoundLoop // before actually initializing the sound and adding it to the playlist // with cmdInitSound. Usually, it doesn't matter if the game doesn't // request to loop the sound, so in this case, don't throw any warning, // otherwise do, because the sound won't be looped. if (value == -1) { warning("kDoSound(setLoop): Slot not found (%04x:%04x) and the song was requested to be looped", PRINT_REG(obj)); } else { // Doesn't really matter } return acc; } if (value == -1) { musicSlot->loop = 0xFFFF; } else { musicSlot->loop = 1; // actually plays the music once } writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop); return acc; }
reg_t kClone(EngineState *s, int argc, reg_t *argv) { reg_t parentAddr = argv[0]; const Object *parentObj = s->_segMan->getObject(parentAddr); reg_t cloneAddr; Clone *cloneObj; // same as Object* if (!parentObj) { error("Attempt to clone non-object/class at %04x:%04x failed", PRINT_REG(parentAddr)); return NULL_REG; } debugC(kDebugLevelMemory, "Attempting to clone from %04x:%04x", PRINT_REG(parentAddr)); uint16 infoSelector = parentObj->getInfoSelector().toUint16(); cloneObj = s->_segMan->allocateClone(&cloneAddr); if (!cloneObj) { error("Cloning %04x:%04x failed-- internal error", PRINT_REG(parentAddr)); return NULL_REG; } // In case the parent object is a clone itself we need to refresh our // pointer to it here. This is because calling allocateClone might // invalidate all pointers, references and iterators to data in the clones // segment. // // The reason why it might invalidate those is, that the segment code // (Table) uses Common::Array for internal storage. Common::Array now // might invalidate references to its contained data, when it has to // extend the internal storage size. if (infoSelector & kInfoFlagClone) parentObj = s->_segMan->getObject(parentAddr); *cloneObj = *parentObj; // Mark as clone infoSelector &= ~kInfoFlagClass; // remove class bit cloneObj->setInfoSelector(make_reg(0, infoSelector | kInfoFlagClone)); cloneObj->setSpeciesSelector(cloneObj->getPos()); if (parentObj->isClass()) cloneObj->setSuperClassSelector(parentObj->getPos()); s->_segMan->getScript(parentObj->getPos().getSegment())->incrementLockers(); s->_segMan->getScript(cloneObj->getPos().getSegment())->incrementLockers(); return cloneAddr; }
reg_t SoundCommandParser::kDoSoundPlay(EngineState *s, int argc, reg_t *argv) { debugC(kDebugLevelSound, "kDoSound(play): %04x:%04x", PRINT_REG(argv[0])); bool playBed = false; if (argc >= 2 && !argv[1].isNull()) playBed = true; processPlaySound(argv[0], playBed); return s->r_acc; }
reg_t kNewList(EngineState *s, int argc, reg_t *argv) { reg_t listRef; List *list = s->_segMan->allocateList(&listRef); list->first = list->last = NULL_REG; debugC(kDebugLevelNodes, "New listRef at %04x:%04x", PRINT_REG(listRef)); return listRef; // Return list base address }
reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { if (argc == 1) debugC(kDebugLevelSound, "kDoSound(pause): %04x:%04x", PRINT_REG(argv[0])); else debugC(kDebugLevelSound, "kDoSound(pause): %04x:%04x, %04x:%04x", PRINT_REG(argv[0]), PRINT_REG(argv[1])); if (_soundVersion <= SCI_VERSION_0_LATE) { // SCI0 games give us 0/1 for either resuming or pausing the current music // this one doesn't count, so pausing 2 times and resuming once means here that we are supposed to resume uint16 value = argv[0].toUint16(); MusicEntry *musicSlot = _music->getActiveSci0MusicSlot(); switch (value) { case 1: if ((musicSlot) && (musicSlot->status == kSoundPlaying)) { _music->soundPause(musicSlot); writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPaused); } return make_reg(0, 0); case 0: if ((musicSlot) && (musicSlot->status == kSoundPaused)) { _music->soundResume(musicSlot); writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying); return make_reg(0, 1); } return make_reg(0, 0); default: error("kDoSound(pause): parameter 0 is invalid for sound-sci0"); } } reg_t obj = argv[0]; uint16 value = argc > 1 ? argv[1].toUint16() : 0; if (!obj.segment) { // pause the whole playlist _music->pauseAll(value); } else { // pause a playlist slot MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // This happens quite frequently debugC(kDebugLevelSound, "kDoSound(pause): Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } _music->soundToggle(musicSlot, value); } return acc; }
void ScreenItem::update() { Plane *plane = g_sci->_gfxFrameout->getPlanes().findByObject(_plane); if (plane == nullptr) { error("ScreenItem::update: Invalid plane %04x:%04x", PRINT_REG(_plane)); } if (plane->_screenItemList.findByObject(_object) == nullptr) { error("ScreenItem::update: %04x:%04x not in plane %04x:%04x", PRINT_REG(_object), PRINT_REG(_plane)); } if (!_created) { _updated = g_sci->_gfxFrameout->getScreenCount(); } _deleted = 0; delete _celObj; _celObj = nullptr; }
void nrf24_print_status() { uint8_t status = nrf24_read_reg(STATUS); PRINT_REG(STATUS); PRINT_REG_BIT("TX_FULL", status, TX_FULL_STATUS); PRINT_REG_BIT("MAX_RT", status, MAX_RT); PRINT_REG_BIT("TX_DS", status, TX_DS); PRINT_REG_BIT("RX_DR", status, RX_DR); }
void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) { Common::StackLock lock(_mutex); if (!pSnd->pMidiParser) error("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj)); pSnd->pMidiParser->mainThreadBegin(); pSnd->pMidiParser->sendFromScriptToDriver(cmd); pSnd->pMidiParser->mainThreadEnd(); }
void nrf24_print_fifo_status() { uint8_t fifo_status = nrf24_read_reg(FIFO_STATUS); PRINT_REG(FIFO_STATUS); PRINT_REG_BIT("RX_EMPTY", fifo_status, RX_EMPTY); PRINT_REG_BIT("RX_FULL", fifo_status, RX_FULL); PRINT_REG_BIT("TX_EMPTY", fifo_status, TX_EMPTY); PRINT_REG_BIT("TX_FULL", fifo_status, TX_FULL_FIFO); }
void run_gc(EngineState *s) { SegManager *segMan = s->_segMan; // Some debug stuff debugC(kDebugLevelGC, "[GC] Running..."); #ifdef GC_DEBUG_CODE const char *segnames[SEG_TYPE_MAX + 1]; int segcount[SEG_TYPE_MAX + 1]; memset(segnames, 0, sizeof(segnames)); memset(segcount, 0, sizeof(segcount)); #endif // Compute the set of all segments references currently in use. AddrSet *activeRefs = findAllActiveReferences(s); // Iterate over all segments, and check for each whether it // contains stuff that can be collected. const Common::Array<SegmentObj *> &heap = segMan->getSegments(); for (uint seg = 1; seg < heap.size(); seg++) { SegmentObj *mobj = heap[seg]; if (mobj != NULL) { #ifdef GC_DEBUG_CODE const SegmentType type = mobj->getType(); segnames[type] = segmentTypeNames[type]; #endif // Get a list of all deallocatable objects in this segment, // then free any which are not referenced from somewhere. const Common::Array<reg_t> tmp = mobj->listAllDeallocatable(seg); for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) { const reg_t addr = *it; if (!activeRefs->contains(addr)) { // Not found -> we can free it mobj->freeAtAddress(segMan, addr); debugC(kDebugLevelGC, "[GC] Deallocating %04x:%04x", PRINT_REG(addr)); #ifdef GC_DEBUG_CODE segcount[type]++; #endif } } } } delete activeRefs; #ifdef GC_DEBUG_CODE // Output debug summary of garbage collection debugC(kDebugLevelGC, "[GC] Summary:"); for (int i = 0; i <= SEG_TYPE_MAX; i++) if (segcount[i]) debugC(kDebugLevelGC, "\t%d\t* %s", segcount[i], segnames[i]); #endif }
reg_t SoundCommandParser::kDoSoundUpdate(EngineState *s, int argc, reg_t *argv) { reg_t obj = argv[0]; debugC(kDebugLevelSound, "kDoSound(update): %04x:%04x", PRINT_REG(argv[0])); MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("kDoSound(update): Slot not found (%04x:%04x)", PRINT_REG(obj)); return s->r_acc; } musicSlot->loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); int16 objVol = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, 255); if (objVol != musicSlot->volume) _music->soundSetVolume(musicSlot, objVol); int16 objPrio = readSelectorValue(_segMan, obj, SELECTOR(priority)); if (objPrio != musicSlot->priority) _music->soundSetPriority(musicSlot, objPrio); return s->r_acc; }
reg_t kNewNode(EngineState *s, int argc, reg_t *argv) { reg_t nodeValue = argv[0]; // Some SCI32 games call this with 1 parameter (e.g. the demo of Phantasmagoria). // Set the key to be the same as the value in this case reg_t nodeKey = (argc == 2) ? argv[1] : argv[0]; s->r_acc = s->_segMan->newNode(nodeValue, nodeKey); debugC(kDebugLevelNodes, "New nodeRef at %04x:%04x", PRINT_REG(s->r_acc)); return s->r_acc; }
void SciMusic::printPlayList(Console *con) { Common::StackLock lock(_mutex); const char *musicStatus[] = { "Stopped", "Initialized", "Paused", "Playing" }; for (uint32 i = 0; i < _playList.size(); i++) { MusicEntry *song = _playList[i]; con->DebugPrintf("%d: %04x:%04x, resource id: %d, status: %s, %s type\n", i, PRINT_REG(song->soundObj), song->resourceId, musicStatus[song->status], song->pMidiParser ? "MIDI" : "digital audio"); } }
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); }