static void syncCT(Common::Serializer &s) { int v = (_vm->_polyStruct) ? 1 : 0; s.syncAsSint32LE(v); if (s.isLoading()) _vm->_polyStruct = (v != 0) ? &_vm->_polyStructNorm : NULL; if (v == 0) // There is no further data to load or save return; s.syncAsSint16LE(numberOfWalkboxes); if (numberOfWalkboxes) { for (int i = 0; i < numberOfWalkboxes; ++i) s.syncAsSint16LE(walkboxColor[i]); for (int i = 0; i < numberOfWalkboxes; ++i) s.syncAsSint16LE(walkboxState[i]); } for (int i = 0; i < 10; i++) { v = 0; if (s.isSaving()) v = (persoTable[i]) ? 1 : 0; s.syncAsSint32LE(v); if (s.isLoading()) // Set up the pointer for the next structure persoTable[i] = (v == 0) ? NULL : (persoStruct *)mallocAndZero(sizeof(persoStruct)); if (v != 0) syncPerso(s, *persoTable[i]); } }
static bool DoSync(Common::Serializer &s, int numInterp) { int sg = 0; if (TinselV2) { if (s.isSaving()) g_restoreCD = GetCurrentCD(); s.syncAsSint16LE(g_restoreCD); } if (TinselV2 && s.isLoading()) HoldItem(INV_NOICON); syncSavedData(s, *g_srsd, numInterp); syncGlobInfo(s); // Glitter globals syncInvInfo(s); // Inventory data // Held object if (s.isSaving()) sg = WhichItemHeld(); s.syncAsSint32LE(sg); if (s.isLoading()) { if (sg != -1 && !GetIsInvObject(sg)) // Not a valid inventory object, so return false return false; if (TinselV2) g_thingHeld = sg; else HoldItem(sg); } syncTimerInfo(s); // Timer data if (!TinselV2) syncPolyInfo(s); // Dead polygon data syncSCdata(s); // Hook Scene and delayed scene s.syncAsSint32LE(*g_SaveSceneSsCount); if (*g_SaveSceneSsCount != 0) { SAVED_DATA *sdPtr = g_SaveSceneSsData; for (int i = 0; i < *g_SaveSceneSsCount; ++i, ++sdPtr) syncSavedData(s, *sdPtr, numInterp); // Flag that there is a saved scene to return to. Note that in this context 'saved scene' // is a stored scene to return to from another scene, such as from the Summoning Book close-up // in Discworld 1 to whatever scene Rincewind was in prior to that g_ASceneIsSaved = true; } if (!TinselV2) syncAllActorsAlive(s); return true; }
void syncScript(Common::Serializer &s, scriptInstanceStruct *entry) { int numScripts = 0; uint32 dummyLong = 0; uint16 dummyWord = 0; if (s.isSaving()) { // Figure out the number of scripts to save scriptInstanceStruct* pCurrent = entry->nextScriptPtr; while (pCurrent) { ++numScripts; pCurrent = pCurrent->nextScriptPtr; } } s.syncAsSint16LE(numScripts); scriptInstanceStruct *ptr = entry->nextScriptPtr; for (int i = 0; i < numScripts; ++i) { if (s.isLoading()) ptr = (scriptInstanceStruct *)mallocAndZero(sizeof(scriptInstanceStruct)); s.syncAsUint16LE(dummyWord); s.syncAsSint16LE(ptr->ccr); s.syncAsSint16LE(ptr->scriptOffset); s.syncAsUint32LE(dummyLong); s.syncAsSint16LE(ptr->dataSize); s.syncAsSint16LE(ptr->scriptNumber); s.syncAsSint16LE(ptr->overlayNumber); s.syncAsSint16LE(ptr->sysKey); s.syncAsSint16LE(ptr->freeze); s.syncAsSint16LE(ptr->type); s.syncAsSint16LE(ptr->var16); s.syncAsSint16LE(ptr->var18); s.syncAsSint16LE(ptr->var1A); s.syncAsSint16LE(ptr->dataSize); if (ptr->dataSize) { if (s.isLoading()) ptr->data = (byte *)mallocAndZero(ptr->dataSize); s.syncBytes(ptr->data, ptr->dataSize); } if (s.isLoading()) { ptr->nextScriptPtr = NULL; entry->nextScriptPtr = ptr; entry = ptr; } else { ptr = ptr->nextScriptPtr; } } }
void Player_AD::saveLoadWithSerializer(Common::Serializer &s) { Common::StackLock lock(_mutex); if (s.getVersion() < VER(95)) { IMuse *dummyImuse = IMuse::create(_vm->_system, NULL, NULL); dummyImuse->saveLoadIMuse(s, _vm, false); delete dummyImuse; return; } if (s.getVersion() >= VER(96)) { int32 res[4] = { _musicResource, _sfx[0].resource, _sfx[1].resource, _sfx[2].resource }; // The first thing we save is a list of sound resources being played // at the moment. s.syncArray(res, 4, Common::Serializer::Sint32LE); // If we are loading start the music again at this point. if (s.isLoading()) { if (res[0] != -1) { startSound(res[0]); } } uint32 musicOffset = _curOffset; s.syncAsSint32LE(_engineMusicTimer, VER(96)); s.syncAsUint32LE(_musicTimer, VER(96)); s.syncAsUint32LE(_internalMusicTimer, VER(96)); s.syncAsUint32LE(_curOffset, VER(96)); s.syncAsUint32LE(_nextEventTimer, VER(96)); // We seek back to the old music position. if (s.isLoading()) { SWAP(musicOffset, _curOffset); musicSeekTo(musicOffset); } // Finally start up the SFX. This makes sure that they are not // accidently stopped while seeking to the old music position. if (s.isLoading()) { for (int i = 1; i < ARRAYSIZE(res); ++i) { if (res[i] != -1) { startSound(res[i]); } } } } }
void Rails::synchronize(Common::Serializer &s) { s.syncAsSint16LE(_routeLength); s.syncAsSint16LE(_next); if (s.isLoading()) { _routeIndexes.clear(); } }
////////////////////////////////////////////////////////////////////////// // Serializable ////////////////////////////////////////////////////////////////////////// void SavePoints::saveLoadWithSerializer(Common::Serializer &s) { // Serialize savepoint data uint32 dataSize = (s.isLoading() ? _savePointsMaxSize : _data.size()); for (uint i = 0; i < dataSize; i++) { if (s.isLoading()) { SavePointData data; _data.push_back(data); } s.syncAsUint32LE(_data[i].entity1); s.syncAsUint32LE(_data[i].action); s.syncAsUint32LE(_data[i].entity2); s.syncAsUint32LE(_data[i].param); } // Skip uninitialized data if any s.skip((_savePointsMaxSize - dataSize) * 16); // Number of savepoints uint32 numSavepoints = _savepoints.size(); s.syncAsUint32LE(numSavepoints); // Savepoints if (s.isLoading()) { for (uint i = 0; i < numSavepoints; i++) { SavePoint point; s.syncAsUint32LE(point.entity1); s.syncAsUint32LE(point.action); s.syncAsUint32LE(point.entity2); s.syncAsUint32LE(point.param.intValue); _savepoints.push_back(point); if (_savepoints.size() >= _savePointsMaxSize) break; } } else { for (Common::List<SavePoint>::iterator it = _savepoints.begin(); it != _savepoints.end(); ++it) { s.syncAsUint32LE((*it).entity1); s.syncAsUint32LE((*it).action); s.syncAsUint32LE((*it).entity2); s.syncAsUint32LE((*it).param.intValue); } } }
void UserInterface::synchronize(Common::Serializer &s) { InventoryObjects &invObjects = _vm->_game->_objects; if (s.isLoading()) { _selectedInvIndex = invObjects._inventoryList.empty() ? -1 : 0; } for (int i = 0; i < 8; ++i) s.syncAsSint16LE(_categoryIndexes[i]); }
void SaveLoad::sync<ScriptRegister::Script>(Common::Serializer &serializer, ScriptRegister::Script &var) { if (serializer.isSaving()) if (var.chunk) var.line = var.chunk->getCurLine(); serializer.syncAsUint32LE(var.line); if (serializer.isLoading()) var.chunk = 0; }
static void DoSync(Common::Serializer &s) { int sg = 0; if (TinselV2) { if (s.isSaving()) restoreCD = GetCurrentCD(); s.syncAsSint16LE(restoreCD); } if (TinselV2 && s.isLoading()) HoldItem(INV_NOICON); syncSavedData(s, *srsd); syncGlobInfo(s); // Glitter globals syncInvInfo(s); // Inventory data // Held object if (s.isSaving()) sg = WhichItemHeld(); s.syncAsSint32LE(sg); if (s.isLoading()) { if (TinselV2) thingHeld = sg; else HoldItem(sg); } syncTimerInfo(s); // Timer data if (!TinselV2) syncPolyInfo(s); // Dead polygon data syncSCdata(s); // Hook Scene and delayed scene s.syncAsSint32LE(*SaveSceneSsCount); if (*SaveSceneSsCount != 0) { SAVED_DATA *sdPtr = SaveSceneSsData; for (int i = 0; i < *SaveSceneSsCount; ++i, ++sdPtr) syncSavedData(s, *sdPtr); } if (!TinselV2) syncAllActorsAlive(s); }
static void syncFilesDatabase(Common::Serializer &s) { uint8 dummyVal = 0; uint32 tmp; for (int i = 0; i < NUM_FILE_ENTRIES; i++) { dataFileEntry &fe = filesDatabase[i]; s.syncAsUint16LE(fe.widthInColumn); s.syncAsUint16LE(fe.width); s.syncAsUint16LE(fe.resType); s.syncAsUint16LE(fe.height); // Remember whether this file database was open or not. // Upon loading, loadSavegameData uses this information // in order to re-open the file databases accordingly. tmp = (fe.subData.ptr) ? 1 : 0; s.syncAsUint32LE(tmp); if (s.isLoading()) { fe.subData.ptr = tmp ? (uint8 *)1 : 0; } s.syncAsSint16LE(fe.subData.index); s.syncBytes((byte *)fe.subData.name, 13); s.syncAsByte(dummyVal); s.syncAsSint16LE(fe.subData.transparency); // Treat fe.subData.ptrMask the same as fe.subData.ptr. tmp = (fe.subData.ptrMask) ? 1 : 0; s.syncAsUint32LE(tmp); if (s.isLoading()) { fe.subData.ptrMask = tmp ? (uint8 *)1 : 0; } s.syncAsUint16LE(fe.subData.resourceType); s.syncAsSint16LE(fe.subData.compression); } }
static bool syncSaveGameHeader(Common::Serializer &s, SaveGameHeader &hdr) { s.syncAsUint32LE(hdr.id); s.syncAsUint32LE(hdr.size); s.syncAsUint32LE(hdr.ver); s.syncBytes((byte *)hdr.desc, SG_DESC_LEN); hdr.desc[SG_DESC_LEN - 1] = 0; syncTime(s, hdr.dateTime); int tmp = hdr.size - s.bytesSynced(); // NOTE: We can't use SAVEGAME_ID here when attempting to remove a saved game from the launcher, // as there is no TinselEngine initialized then. This means that we can't check if this is a DW1 // or DW2 savegame in this case, but it doesn't really matter, as the saved game is about to be // deleted anyway. Refer to bug #3387551. bool correctID = _vm ? (hdr.id == SAVEGAME_ID) : (hdr.id == DW1_SAVEGAME_ID || hdr.id == DW2_SAVEGAME_ID); // Perform sanity check if (tmp < 0 || !correctID || hdr.ver > CURRENT_VER || hdr.size > 1024) return false; if (tmp > 0) { // If there's header space left, handling syncing the Scn flag and game language s.syncAsByte(hdr.scnFlag); s.syncAsByte(hdr.language); tmp -= 2; if (_vm && s.isLoading()) { // If the engine is loaded, ensure the Scn/Gra usage is correct, and it's the correct language if ((hdr.scnFlag != ((_vm->getFeatures() & GF_SCNFILES) != 0)) || (hdr.language != _vm->_config->_language)) return false; } } // Handle the number of interpreter contexts that will be saved in the savegame if (tmp >= 2) { tmp -= 2; hdr.numInterpreters = NUM_INTERPRET; s.syncAsUint16LE(hdr.numInterpreters); } else { hdr.numInterpreters = (TinselV2 ? 70 : 64) - 20; } // Skip over any extra bytes s.skip(tmp); return true; }
static void syncSongs(Common::Serializer &s) { int size = 0; if (songLoaded) { // TODO: implement s.syncAsByte(size); if (s.isLoading()) { saveVar1 = size; if (saveVar1) s.syncBytes(saveVar2, saveVar1); } } else { s.syncAsByte(size); } }
static void syncFilesDatabase(Common::Serializer &s) { uint8 dummyVal = 0; uint32 tmp; for (int i = 0; i < NUM_FILE_ENTRIES; i++) { dataFileEntry &fe = filesDatabase[i]; s.syncAsUint16LE(fe.widthInColumn); s.syncAsUint16LE(fe.width); s.syncAsUint16LE(fe.resType); s.syncAsUint16LE(fe.height); // TODO: Have a look at the saving/loading of this pointer tmp = (fe.subData.ptr) ? 1 : 0; s.syncAsUint32LE(tmp); if (s.isLoading()) { fe.subData.ptr = (uint8 *)tmp; } s.syncAsSint16LE(fe.subData.index); s.syncBytes((byte *)fe.subData.name, 13); s.syncAsByte(dummyVal); s.syncAsSint16LE(fe.subData.transparency); // TODO: Have a look at the saving/loading of this pointer tmp = (fe.subData.ptrMask) ? 1 : 0; s.syncAsUint32LE(tmp); if (s.isLoading()) { fe.subData.ptrMask = (uint8 *)tmp; } s.syncAsUint16LE(fe.subData.resourceType); s.syncAsSint16LE(fe.subData.compression); } }
void StopWalkers::synchronize(Common::Serializer &s) { StopWalkerEntry rec; int count = size(); s.syncAsUint16LE(count); if (s.isLoading()) { clear(); for (int idx = 0; idx < count; ++idx) { rec.synchronize(s); push(rec); } } else { for (int idx = 0; idx < count; ++idx) (*this)[idx].synchronize(s); } }
void CGEEngine::syncHeader(Common::Serializer &s) { debugC(1, kCGEDebugEngine, "CGEEngine::syncHeader(s)"); int i = kDemo; s.syncAsUint16LE(_now); s.syncAsUint16LE(_oldLev); s.syncAsUint16LE(i); // unused Demo string id for (i = 0; i < 5; i++) s.syncAsUint16LE(_game); s.syncAsSint16LE(i); // unused VGA::Mono variable s.syncAsUint16LE(_music); s.syncBytes(_volume, 2); for (i = 0; i < 4; i++) s.syncAsUint16LE(_flag[i]); if (s.isLoading()) { // Reset scene values initSceneValues(); } for (i = 0; i < kSceneMax; i++) { s.syncAsSint16LE(_heroXY[i].x); s.syncAsUint16LE(_heroXY[i].y); } for (i = 0; i < 1 + kSceneMax; i++) { s.syncAsByte(_barriers[i]._horz); s.syncAsByte(_barriers[i]._vert); } for (i = 0; i < kPocketNX; i++) s.syncAsUint16LE(_pocref[i]); if (s.isSaving()) { // Write checksum int checksum = kSavegameCheckSum; s.syncAsUint16LE(checksum); } else { // Read checksum and validate it uint16 checksum = 0; s.syncAsUint16LE(checksum); if (checksum != kSavegameCheckSum) error("%s", _text->getText(kBadSVG)); } }
void SavesManager::syncBitFlags(Common::Serializer &s, bool *startP, bool *endP) { byte data = 0; int bitCounter = 0; for (bool *p = startP; p <= endP; ++p, bitCounter = (bitCounter + 1) % 8) { if (p == endP || bitCounter == 0) { if (p != endP || s.isSaving()) s.syncAsByte(data); if (p == endP) break; if (s.isSaving()) data = 0; } if (s.isLoading()) *p = (data >> bitCounter) != 0; else if (*p) data |= 1 << bitCounter; }
void SaveLoadManager::syncSavegameData(Common::Serializer &s, int version) { // The brief version 3 had the highscores embedded. They're in a separate file now, so skip if (version == 3 && s.isLoading()) s.skip(100); s.syncBytes(&_vm->_globals->_saveData->_data[0], 2050); syncCharacterLocation(s, _vm->_globals->_saveData->_cloneHopkins); syncCharacterLocation(s, _vm->_globals->_saveData->_realHopkins); syncCharacterLocation(s, _vm->_globals->_saveData->_samantha); for (int i = 0; i < 35; ++i) s.syncAsSint16LE(_vm->_globals->_saveData->_inventory[i]); if (version > 1) { s.syncAsSint16LE(_vm->_globals->_saveData->_mapCarPosX); s.syncAsSint16LE(_vm->_globals->_saveData->_mapCarPosY); } else { _vm->_globals->_saveData->_mapCarPosX = _vm->_globals->_saveData->_mapCarPosY = 0; } }
bool SaveHeader::sync(Common::Serializer &sz) { const uint32 SAVE_MAGIC_NUMBER = MKTAG('M', 'O', 'J', 'B'); const uint32 SAVE_FILE_VERSION = 1; if (sz.isLoading()) { uint32 magic = 0; sz.syncAsUint32BE(magic); if (magic != SAVE_MAGIC_NUMBER) { warning("Invalid save"); return false; } } else { uint32 magic = SAVE_MAGIC_NUMBER; sz.syncAsUint32BE(magic); } sz.syncVersion(SAVE_FILE_VERSION); sz.syncString(_description); return true; }
/** * (Un)serialize an interpreter context for save/restore game. */ void INT_CONTEXT::syncWithSerializer(Common::Serializer &s) { if (s.isLoading()) { // Null out the pointer fields pProc = NULL; code = NULL; pinvo = NULL; } // Write out used fields s.syncAsUint32LE(GSort); s.syncAsUint32LE(hCode); s.syncAsUint32LE(event); s.syncAsSint32LE(hPoly); s.syncAsSint32LE(idActor); for (int i = 0; i < PCODE_STACK_SIZE; ++i) s.syncAsSint32LE(stack[i]); s.syncAsSint32LE(sp); s.syncAsSint32LE(bp); s.syncAsSint32LE(ip); s.syncAsUint32LE(bHalt); s.syncAsUint32LE(escOn); s.syncAsSint32LE(myEscape); }
void Sprite::sync(Common::Serializer &s) { uint16 unused = 0; s.syncAsUint16LE(unused); s.syncAsUint16LE(unused); // _ext s.syncAsUint16LE(_ref); s.syncAsByte(_scene); // bitfield in-memory storage is unpredictable, so to avoid // any issues, pack/unpack everything manually uint16 flags = 0; if (s.isLoading()) { s.syncAsUint16LE(flags); _flags._hide = flags & 0x0001 ? true : false; _flags._near = flags & 0x0002 ? true : false; _flags._drag = flags & 0x0004 ? true : false; _flags._hold = flags & 0x0008 ? true : false; _flags._____ = flags & 0x0010 ? true : false; _flags._slav = flags & 0x0020 ? true : false; _flags._syst = flags & 0x0040 ? true : false; _flags._kill = flags & 0x0080 ? true : false; _flags._xlat = flags & 0x0100 ? true : false; _flags._port = flags & 0x0200 ? true : false; _flags._kept = flags & 0x0400 ? true : false; _flags._east = flags & 0x0800 ? true : false; _flags._shad = flags & 0x1000 ? true : false; _flags._back = flags & 0x2000 ? true : false; _flags._bDel = flags & 0x4000 ? true : false; _flags._tran = flags & 0x8000 ? true : false; } else { flags = (flags << 1) | _flags._tran; flags = (flags << 1) | _flags._bDel; flags = (flags << 1) | _flags._back; flags = (flags << 1) | _flags._shad; flags = (flags << 1) | _flags._east; flags = (flags << 1) | _flags._kept; flags = (flags << 1) | _flags._port; flags = (flags << 1) | _flags._xlat; flags = (flags << 1) | _flags._kill; flags = (flags << 1) | _flags._syst; flags = (flags << 1) | _flags._slav; flags = (flags << 1) | _flags._____; flags = (flags << 1) | _flags._hold; flags = (flags << 1) | _flags._drag; flags = (flags << 1) | _flags._near; flags = (flags << 1) | _flags._hide; s.syncAsUint16LE(flags); } s.syncAsUint16LE(_x); s.syncAsUint16LE(_y); s.syncAsByte(_z); s.syncAsUint16LE(_w); s.syncAsUint16LE(_h); s.syncAsUint16LE(_time); s.syncAsByte(_nearPtr); s.syncAsByte(_takePtr); s.syncAsSint16LE(_seqPtr); s.syncAsUint16LE(_shpCnt); s.syncBytes((byte *)&_file[0], 9); _file[8] = '\0'; s.syncAsUint16LE(unused); // _prev s.syncAsUint16LE(unused); // _next }
static void syncIncrust(Common::Serializer &s) { int numEntries = 0; backgroundIncrustStruct *pl, *pl1; uint8 dummyByte = 0; uint16 dummyWord = 0; uint32 dummyLong = 0; if (s.isSaving()) { // Figure out the number of entries to save pl = backgroundIncrustHead.next; while (pl) { ++numEntries; pl = pl->next; } } s.syncAsSint16LE(numEntries); pl = s.isSaving() ? backgroundIncrustHead.next : &backgroundIncrustHead; pl1 = &backgroundIncrustHead; for (int i = 0; i < numEntries; ++i) { backgroundIncrustStruct *t = s.isSaving() ? pl : (backgroundIncrustStruct *)mallocAndZero(sizeof(backgroundIncrustStruct)); s.syncAsUint32LE(dummyLong); s.syncAsSint16LE(t->objectIdx); s.syncAsSint16LE(t->type); s.syncAsSint16LE(t->overlayIdx); s.syncAsSint16LE(t->X); s.syncAsSint16LE(t->Y); s.syncAsSint16LE(t->frame); s.syncAsSint16LE(t->scale); s.syncAsSint16LE(t->backgroundIdx); s.syncAsSint16LE(t->scriptNumber); s.syncAsSint16LE(t->scriptOverlayIdx); s.syncAsUint32LE(dummyLong); s.syncAsSint16LE(t->saveWidth); s.syncAsSint16LE(t->saveHeight); s.syncAsSint16LE(t->saveSize); s.syncAsSint16LE(t->savedX); s.syncAsSint16LE(t->savedY); s.syncBytes((byte *)t->name, 13); s.syncAsByte(dummyByte); s.syncAsSint16LE(t->spriteId); s.syncAsUint16LE(dummyWord); if (t->saveSize) { if (s.isLoading()) t->ptr = (byte *)MemAlloc(t->saveSize); s.syncBytes(t->ptr, t->saveSize); } if (s.isSaving()) pl = pl->next; else { t->next = NULL; pl->next = t; t->prev = pl1->prev; pl1->prev = t; pl = t; } } }
void Nim::synchronize(Common::Serializer &sz) { if (sz.isLoading() && sz.getVersion() < 2) return; sz.syncAsByte(_playedNim); }
void IMuseDigital::saveLoadEarly(Common::Serializer &s) { Common::StackLock lock(_mutex, "IMuseDigital::saveLoadEarly()"); s.skip(4, VER(31), VER(42)); // _volVoice s.skip(4, VER(31), VER(42)); // _volSfx s.skip(4, VER(31), VER(42)); // _volMusic s.syncAsSint32LE(_curMusicState, VER(31)); s.syncAsSint32LE(_curMusicSeq, VER(31)); s.syncAsSint32LE(_curMusicCue, VER(31)); s.syncAsSint32LE(_nextSeqToPlay, VER(31)); s.syncAsByte(_radioChatterSFX, VER(76)); s.syncArray(_attributes, 188, Common::Serializer::Sint32LE, VER(31)); for (int l = 0; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) { Track *track = _track[l]; if (s.isLoading()) { memset(track, 0, sizeof(Track)); } syncWithSerializer(s, *track); if (s.isLoading()) { _track[l]->trackId = l; if (!track->used) continue; if ((track->toBeRemoved) || (track->souStreamUsed) || (track->curRegion == -1)) { track->used = false; continue; } // TODO: The code below has a lot in common with that in IMuseDigital::startSound. // Try to refactor them to reduce the code duplication. track->soundDesc = _sound->openSound(track->soundId, track->soundName, track->soundType, track->volGroupId, -1); if (!track->soundDesc) track->soundDesc = _sound->openSound(track->soundId, track->soundName, track->soundType, track->volGroupId, 1); if (!track->soundDesc) track->soundDesc = _sound->openSound(track->soundId, track->soundName, track->soundType, track->volGroupId, 2); if (!track->soundDesc) { warning("IMuseDigital::saveOrLoad: Can't open sound so will not be resumed"); track->used = false; continue; } track->sndDataExtComp = _sound->isSndDataExtComp(track->soundDesc); track->dataOffset = _sound->getRegionOffset(track->soundDesc, track->curRegion); int bits = _sound->getBits(track->soundDesc); int channels = _sound->getChannels(track->soundDesc); int freq = _sound->getFreq(track->soundDesc); track->feedSize = freq * channels; track->mixerFlags = 0; if (channels == 2) track->mixerFlags = kFlagStereo; if ((bits == 12) || (bits == 16)) { track->mixerFlags |= kFlag16Bits; track->feedSize *= 2; } else if (bits == 8) { track->mixerFlags |= kFlagUnsigned; } else error("IMuseDigital::saveOrLoad(): Can't handle %d bit samples", bits); track->stream = Audio::makeQueuingAudioStream(freq, (track->mixerFlags & kFlagStereo) != 0); _mixer->playStream(track->getType(), &track->mixChanHandle, track->stream, -1, track->getVol(), track->getPan()); _mixer->pauseHandle(track->mixChanHandle, true); } } }