bool ComposerEngine::initSprite(Sprite &sprite) { Common::SeekableReadStream *stream = getStreamForSprite(sprite._id); if (!stream) return false; uint16 type = stream->readUint16LE(); int16 height = stream->readSint16LE(); int16 width = stream->readSint16LE(); uint32 size = stream->readUint32LE(); debug(1, "loading BMAP: type %d, width %d, height %d, size %d", type, width, height, size); if (width > 0 && height > 0) { sprite._surface.create(width, height, Graphics::PixelFormat::createFormatCLUT8()); decompressBitmap(type, stream, (byte *)sprite._surface.getPixels(), size, width, height); } else { // there are some sprites (e.g. a -998x-998 one in Gregory's title screen) // which have an invalid size, but the original engine doesn't notice for // RLE sprites since the width/height is ignored until the actual draw if (type != kBitmapRLESLWM) error("sprite (type %d) had invalid size %dx%d", type, width, height); delete stream; return false; } delete stream; return true; }
void KyraEngine_MR::loadSceneMsc() { char filename[16]; strcpy(filename, _sceneList[_mainCharacter.sceneId].filename1); strcat(filename, ".MSC"); _res->exists(filename, true); Common::SeekableReadStream *stream = _res->createReadStream(filename); assert(stream); int16 minY = 0, height = 0; minY = stream->readSint16LE(); height = stream->readSint16LE(); delete stream; stream = 0; musicUpdate(0); _maskPageMinY = minY; _maskPageMaxY = minY + height - 1; _screen->setShapePages(5, 3, _maskPageMinY, _maskPageMaxY); musicUpdate(0); _screen->loadBitmap(filename, 5, 5, 0, true); // HACK uint8 *data = new uint8[320*200]; _screen->copyRegionToBuffer(5, 0, 0, 320, 200, data); _screen->clearPage(5); _screen->copyBlockToPage(5, 0, _maskPageMinY, 320, height, data); delete[] data; musicUpdate(0); }
void WidthHeight::load(Common::SeekableReadStream &stream) { _width = stream.readSint16LE(); _height = stream.readSint16LE(); debug(5, "WidthHeight::load() _width: %d; _height: %d", _width, _height); }
void AmazonResources::load(Common::SeekableReadStream &s) { Resources::load(s); uint count; // Load the version specific data NO_HELP_MESSAGE = readString(s); NO_HINTS_MESSAGE = readString(s); RIVER_HIT1 = readString(s); RIVER_HIT2 = readString(s); BAR_MESSAGE = readString(s); for (int idx = 0; idx < 3; ++idx) HELPLVLTXT[idx] = readString(s); for (int idx = 0; idx < 9; ++idx) IQLABELS[idx] = readString(s); CANT_GET_THERE = readString(s); // Get the offset of the general shared data for the game uint entryOffset = findEntry(_vm->getGameID(), 2, 0, (Common::Language)0); s.seek(entryOffset); // Read in the cursor list count = s.readUint16LE(); CURSORS.resize(count); for (uint idx = 0; idx < count; ++idx) { uint count2 = s.readUint16LE(); CURSORS[idx].resize(count2); s.read(&CURSORS[idx][0], count2); } // Load font data count = s.readUint16LE(); Common::Array<int> index; Common::Array<byte> data; index.resize(count); for (uint idx = 0; idx < count; ++idx) index[idx] = s.readSint16LE(); count = s.readUint16LE(); data.resize(count); for (uint idx = 0; idx < count; ++idx) data[idx] = s.readByte(); _font3x5 = new AmazonFont(&index[0], &data[0]); count = s.readUint16LE(); index.resize(count); for (uint idx = 0; idx < count; ++idx) index[idx] = s.readSint16LE(); count = s.readUint16LE(); data.resize(count); for (uint idx = 0; idx < count; ++idx) data[idx] = s.readByte(); _font6x6 = new AmazonFont(&index[0], &data[0]); }
void Map_v2::loadGoblinStates(Common::SeekableReadStream &data, int index) { Mult::Mult_GobState *statesPtr; Mult::Mult_GobState *gobState; int8 indices[102]; uint8 statesCount; uint8 dataCount; int16 state; uint32 tmpPos; memset(indices, -1, 101); _vm->_mult->_objects[index].goblinStates = new Mult::Mult_GobState*[101]; memset(_vm->_mult->_objects[index].goblinStates, 0, 101 * sizeof(Mult::Mult_GobState *)); data.read(indices, 100); tmpPos = data.pos(); statesCount = 0; for (int i = 0; i < 100; i++) { if (indices[i] != -1) { statesCount++; data.skip(4); dataCount = data.readByte(); statesCount += dataCount; data.skip(dataCount * 9); } } data.seek(tmpPos); statesPtr = new Mult::Mult_GobState[statesCount]; _vm->_mult->_objects[index].goblinStates[0] = statesPtr; for (int i = 0; i < 100; i++) { state = indices[i]; if (state != -1) { _vm->_mult->_objects[index].goblinStates[state] = statesPtr++; gobState = _vm->_mult->_objects[index].goblinStates[state]; gobState[0].animation = data.readSint16LE(); gobState[0].layer = data.readSint16LE(); dataCount = data.readByte(); gobState[0].dataCount = dataCount; for (uint8 j = 1; j <= dataCount; j++) { data.skip(1); gobState[j].sndItem = data.readSByte(); data.skip(1); gobState[j].sndFrame = data.readByte(); data.skip(1); gobState[j].freq = data.readSint16LE(); gobState[j].repCount = data.readSByte(); gobState[j].speaker = data.readByte(); statesPtr++; } } } }
bool StaticResource::loadCharData(Common::SeekableReadStream &stream, void *&ptr, int &size) { size = stream.size() / 130; LoLCharacter *charData = new LoLCharacter[size]; for (int i = 0; i < size; i++) { LoLCharacter *t = &charData[i]; t->flags = stream.readUint16LE(); stream.read(t->name, 11); t->raceClassSex = stream.readByte(); t->id = stream.readSint16LE(); t->curFaceFrame = stream.readByte(); t->tempFaceFrame = stream.readByte(); t->screamSfx = stream.readByte(); stream.readUint32LE(); for (int ii = 0; ii < 8; ii++) t->itemsMight[ii] = stream.readUint16LE(); for (int ii = 0; ii < 8; ii++) t->protectionAgainstItems[ii] = stream.readUint16LE(); t->itemProtection = stream.readUint16LE(); t->hitPointsCur = stream.readSint16LE(); t->hitPointsMax = stream.readUint16LE(); t->magicPointsCur = stream.readSint16LE(); t->magicPointsMax = stream.readUint16LE(); t->field_41 = stream.readByte(); t->damageSuffered = stream.readUint16LE(); t->weaponHit = stream.readUint16LE(); t->totalMightModifier = stream.readUint16LE(); t->totalProtectionModifier = stream.readUint16LE(); t->might = stream.readUint16LE(); t->protection = stream.readUint16LE(); t->nextAnimUpdateCountdown = stream.readSint16LE(); for (int ii = 0; ii < 11; ii++) t->items[ii] = stream.readUint16LE(); for (int ii = 0; ii < 3; ii++) t->skillLevels[ii] = stream.readByte(); for (int ii = 0; ii < 3; ii++) t->skillModifiers[ii] = stream.readByte(); for (int ii = 0; ii < 3; ii++) t->experiencePts[ii] = stream.readUint32LE(); for (int ii = 0; ii < 5; ii++) t->characterUpdateEvents[ii] = stream.readByte(); for (int ii = 0; ii < 5; ii++) t->characterUpdateDelay[ii] = stream.readByte(); }; ptr = charData; return true; }
int64 GFF4Struct::getSint(Common::SeekableReadStream &data, IFieldType type) const { switch (type) { case kIFieldTypeUint8: return (int64) ((uint64) data.readByte()); case kIFieldTypeSint8: return (int64) data.readSByte(); case kIFieldTypeUint16: return (int64) ((uint64) data.readUint16LE()); case kIFieldTypeSint16: return (int64) data.readSint16LE(); case kIFieldTypeUint32: return (int64) ((uint64) data.readUint32LE()); case kIFieldTypeSint32: return (int64) data.readSint32LE(); case kIFieldTypeUint64: return (int64) ((uint64) data.readUint64LE()); case kIFieldTypeSint64: return (int64) data.readSint64LE(); default: break; } throw Common::Exception("GFF4: Field is not an int type"); }
bool Animation::loadStream(Common::SeekableReadStream &stream) { stream.skip(2); // skip not used x and y coord diff _loopCount = stream.readUint16LE(); _phaseCount = stream.readUint16LE(); stream.skip(2); // skip _frameCount here _baseX = stream.readUint16LE(); _baseY = stream.readUint16LE(); uint32 phaseTableOffset = stream.readUint32LE(); uint32 tableOfFrameOffsets = stream.pos(); stream.seek(phaseTableOffset); Phase tempPhase; _frameCount = 0; for (int phase = 0; phase < _phaseCount; phase++) { tempPhase._phaseOffsetX = stream.readSint16LE(); tempPhase._phaseOffsetY = stream.readSint16LE(); tempPhase._phaseToFrameIndex = stream.readUint16LE(); if (tempPhase._phaseToFrameIndex > _frameCount) { _frameCount = tempPhase._phaseToFrameIndex; } _phaseList.push_back(tempPhase); stream.skip(2); } if (_phaseCount) { _frameCount++; } Frame tempFrame; for (int frame = 0; frame < _frameCount; frame++) { stream.seek(tableOfFrameOffsets + frame * 4); uint32 frameInfoOffset = stream.readUint32LE(); stream.seek(frameInfoOffset); uint16 frameWidth = stream.readUint16LE(); uint16 frameHeight = stream.readUint16LE(); uint32 frameDataPos = stream.pos(); uint32 frameDataOffset = stream.readUint32BE(); tempFrame._surface = new Graphics::Surface(); tempFrame._surface->create(frameWidth, frameHeight, Graphics::PixelFormat::createFormatCLUT8()); if (frameDataOffset == MKTAG('m', 'a', 's', 'm')) { tempFrame._isCompressed = true; tempFrame._dataSize = stream.readUint32LE(); tempFrame._compressedData = (byte *)malloc(tempFrame._dataSize); stream.read(tempFrame._compressedData, tempFrame._dataSize); } else { tempFrame._isCompressed = false; tempFrame._dataSize = 0; tempFrame._compressedData = nullptr; stream.seek(frameDataPos); for (uint16 i = 0; i < frameHeight; i++) { stream.read(tempFrame._surface->getBasePtr(0, i), frameWidth); } } _frameList.push_back(tempFrame); } return true; }
Hotspot::Hotspot(Common::SeekableReadStream &f, bool isV2) { _bounds.left = f.readSint16LE(); _bounds.top = f.readSint16LE(); _bounds.right = f.readSint16LE(); _bounds.bottom = f.readSint16LE(); _feetPos.x = f.readSint16LE(); _feetPos.y = f.readSint16LE(); _facing = (Facing)f.readByte(); _articleNumber = f.readByte(); _active = f.readByte() != 0; _cursor = (CursorType)f.readByte(); if (isV2) { f.skip(1); // cursor f.skip(1); // syntax } _vocabId = f.readUint16LE(); _verbId = f.readUint16LE(); }
void ScriptEntry::Conditional::load(Common::SeekableReadStream &s) { _operation = (ConditionalOperation)s.readUint16LE(); if (_operation == CONDOP_ABORT) { _param1._isVariable = false; _param1._val = 0; } else { _param1._isVariable = s.readByte() != 0; _param1._val = s.readSint16LE(); } if (_operation == CONDOP_ABORT || _operation == CONDOP_VALUE) { _param2._isVariable = false; _param2._val = 0; } else { _param2._isVariable = s.readByte() != 0; _param2._val = s.readSint16LE(); } }
void SoundTowns_Darkmoon::loadSoundFile(Common::String name) { Common::SeekableReadStream *s = _vm->resource()->createReadStream(Common::String::format("%s.SDT", name.c_str())); if (!s) error("Failed to load sound file '%s.SDT'", name.c_str()); for (int i = 0; i < 120; i++) { _soundTable[i].type = s->readSByte(); _soundTable[i].para1 = s->readSint32LE(); _soundTable[i].para2 = s->readSint16LE(); } delete s; uint32 bytesLeft; uint8 *pmb = _vm->resource()->fileData(Common::String::format("%s.PMB", name.c_str()).c_str(), &bytesLeft); _vm->delay(300); if (pmb) { uint8 *src = pmb + 8; for (int i = 0; i < 32; i++) _intf->callback(5, 0x40, i, &src[i << 7]); _intf->callback(35, -1); src += 0x1000; bytesLeft -= 0x1008; while (bytesLeft) { _intf->callback(34, src); uint32 len = READ_LE_UINT16(&src[12]) + 32; src = src + len; bytesLeft -= len; } delete[] pmb; } else { warning("Sound file '%s.PMB' not found.", name.c_str()); // TODO } }
void loadPoint(Common::SeekableReadStream &stream, Common::Point &pt) { pt.x = stream.readSint16LE(); pt.y = stream.readSint16LE(); debug(0, "loadPoint() x: %d; y: %d", pt.x, pt.y); }
void SEQFile::load(Common::SeekableReadStream &seq) { const uint16 decCount = (uint16)seq.readByte() + 1; const uint16 aniCount = (uint16)seq.readByte() + 1; // Load backgrounds _backgrounds.reserve(decCount); for (uint i = 0; i < decCount; i++) { const Common::String dec = Util::readString(seq, 13); if (!_vm->_dataIO->hasFile(dec)) { warning("SEQFile::load(): No such background \"%s\"", dec.c_str()); return; } _backgrounds.push_back(new DECFile(_vm, dec, 320, 200)); } // Load animations _animations.reserve(aniCount); for (uint i = 0; i < aniCount; i++) { const Common::String ani = Util::readString(seq, 13); if (!_vm->_dataIO->hasFile(ani)) { warning("SEQFile::load(): No such animation \"%s\"", ani.c_str()); return; } _animations.push_back(new ANIFile(_vm, ani)); } _frameRate = seq.readUint16LE(); // Load background change keys const uint16 bgKeyCount = seq.readUint16LE(); _bgKeys.resize(bgKeyCount); for (uint16 i = 0; i < bgKeyCount; i++) { const uint16 frame = seq.readUint16LE(); const uint16 index = seq.readUint16LE(); _bgKeys[i].frame = frame; _bgKeys[i].background = index < _backgrounds.size() ? _backgrounds[index] : 0; } // Load animation keys for all 4 objects for (uint i = 0; i < kObjectCount; i++) { const uint16 animKeyCount = seq.readUint16LE(); _animKeys.reserve(_animKeys.size() + animKeyCount); for (uint16 j = 0; j < animKeyCount; j++) { _animKeys.push_back(AnimationKey()); const uint16 frame = seq.readUint16LE(); const uint16 index = seq.readUint16LE(); uint16 animation; const ANIFile *ani = findANI(index, animation); _animKeys.back().object = i; _animKeys.back().frame = frame; _animKeys.back().ani = ani; _animKeys.back().animation = animation; _animKeys.back().x = seq.readSint16LE(); _animKeys.back().y = seq.readSint16LE(); _animKeys.back().order = seq.readSint16LE(); } } }
void SmushPlayer::handleIACT(int32 subSize, Common::SeekableReadStream &b) { debugC(DEBUG_SMUSH, "SmushPlayer::IACT()"); assert(subSize >= 8); int code = b.readUint16LE(); int flags = b.readUint16LE(); int unknown = b.readSint16LE(); int track_flags = b.readUint16LE(); if ((code != 8) && (flags != 46)) { _vm->_insane->procIACT(_dst, 0, 0, 0, b, 0, 0, code, flags, unknown, track_flags); return; } if (_compressedFileMode) { return; } assert(flags == 46 && unknown == 0); int track_id = b.readUint16LE(); int index = b.readUint16LE(); int nbframes = b.readUint16LE(); int32 size = b.readUint32LE(); int32 bsize = subSize - 18; if (_vm->_game.id != GID_CMI) { int32 track = track_id; if (track_flags == 1) { track = track_id + 100; } else if (track_flags == 2) { track = track_id + 200; } else if (track_flags == 3) { track = track_id + 300; } else if ((track_flags >= 100) && (track_flags <= 163)) { track = track_id + 400; } else if ((track_flags >= 200) && (track_flags <= 263)) { track = track_id + 500; } else if ((track_flags >= 300) && (track_flags <= 363)) { track = track_id + 600; } else { error("SmushPlayer::handleIACT(): bad track_flags: %d", track_flags); } debugC(DEBUG_SMUSH, "SmushPlayer::handleIACT(): %d, %d, %d", track, index, track_flags); SmushChannel *c = _smixer->findChannel(track); if (c == 0) { c = new ImuseChannel(track); _smixer->addChannel(c); } if (index == 0) c->setParameters(nbframes, size, track_flags, unknown, 0); else c->checkParameters(index, nbframes, size, track_flags, unknown); c->appendData(b, bsize); } else { // TODO: Move this code into another SmushChannel subclass? byte *src = (byte *)malloc(bsize); b.read(src, bsize); byte *d_src = src; byte value; while (bsize > 0) { if (_IACTpos >= 2) { int32 len = READ_BE_UINT16(_IACToutput) + 2; len -= _IACTpos; if (len > bsize) { memcpy(_IACToutput + _IACTpos, d_src, bsize); _IACTpos += bsize; bsize = 0; } else { byte *output_data = (byte *)malloc(4096); memcpy(_IACToutput + _IACTpos, d_src, len); byte *dst = output_data; byte *d_src2 = _IACToutput; d_src2 += 2; int32 count = 1024; byte variable1 = *d_src2++; byte variable2 = variable1 / 16; variable1 &= 0x0f; do { value = *(d_src2++); if (value == 0x80) { *dst++ = *d_src2++; *dst++ = *d_src2++; } else { int16 val = (int8)value << variable2; *dst++ = val >> 8; *dst++ = (byte)(val); } value = *(d_src2++); if (value == 0x80) { *dst++ = *d_src2++; *dst++ = *d_src2++; } else { int16 val = (int8)value << variable1; *dst++ = val >> 8; *dst++ = (byte)(val); } } while (--count); if (!_IACTstream) { _IACTstream = Audio::makeQueuingAudioStream(22050, true); _vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_IACTchannel, _IACTstream); } _IACTstream->queueBuffer(output_data, 0x1000, DisposeAfterUse::YES, Audio::FLAG_STEREO | Audio::FLAG_16BITS); bsize -= len; d_src += len; _IACTpos = 0; } } else { if (bsize > 1 && _IACTpos == 0) { *(_IACToutput + 0) = *d_src++; _IACTpos = 1; bsize--; } *(_IACToutput + _IACTpos) = *d_src++; _IACTpos++; bsize--; } }
void KyraEngine_MR::initSceneScript(int unk1) { const SceneDesc &scene = _sceneList[_mainCharacter.sceneId]; musicUpdate(0); char filename[16]; strcpy(filename, scene.filename1); strcat(filename, ".DAT"); _res->exists(filename, true); Common::SeekableReadStream *stream = _res->createReadStream(filename); assert(stream); stream->seek(2, SEEK_CUR); byte scaleTable[15]; stream->read(scaleTable, 15); stream->read(_sceneDatPalette, 45); stream->read(_sceneDatLayerTable, 15); int16 shapesCount = stream->readSint16LE(); for (int i = 0; i < 15; ++i) _scaleTable[i] = (uint16(scaleTable[i]) << 8) / 100; if (shapesCount > 0) { strcpy(filename, scene.filename1); strcat(filename, "9.CPS"); musicUpdate(0); _screen->loadBitmap(filename, 3, 3, 0); int pageBackUp = _screen->_curPage; _screen->_curPage = 2; for (int i = 0; i < shapesCount; ++i) { int16 x = stream->readSint16LE(); int16 y = stream->readSint16LE(); int16 w = stream->readSint16LE(); int16 h = stream->readSint16LE(); _sceneShapeDescs[i].drawX = stream->readSint16LE(); _sceneShapeDescs[i].drawY = stream->readSint16LE(); _sceneShapes[i] = _screen->encodeShape(x, y, w, h, 0); assert(_sceneShapes[i]); musicUpdate(0); } _screen->_curPage = pageBackUp; musicUpdate(0); } delete stream; stream = 0; musicUpdate(0); strcpy(filename, scene.filename1); strcat(filename, ".CPS"); _screen->loadBitmap(filename, 3, 3, 0); musicUpdate(0); Common::set_to(_specialSceneScriptState, _specialSceneScriptState+ARRAYSIZE(_specialSceneScriptState), false); _sceneEnterX1 = 160; _sceneEnterY1 = 0; _sceneEnterX2 = 296; _sceneEnterY2 = 93; _sceneEnterX3 = 160; _sceneEnterY3 = 171; _sceneEnterX4 = 24; _sceneEnterY4 = 93; _sceneMinX = 0; _sceneMaxX = 319; _emc->init(&_sceneScriptState, &_sceneScriptData); strcpy(filename, scene.filename2); strcat(filename, ".EMC"); musicUpdate(0); _res->exists(filename, true); _emc->load(filename, &_sceneScriptData, &_opcodes); strcpy(filename, scene.filename2); strcat(filename, "."); loadLanguageFile(filename, _sceneStrings); musicUpdate(0); runSceneScript8(); _emc->start(&_sceneScriptState, 0); _sceneScriptState.regs[0] = _mainCharacter.sceneId; _sceneScriptState.regs[5] = unk1; while (_emc->isValid(&_sceneScriptState)) _emc->run(&_sceneScriptState); _screen->copyRegionToBuffer(3, 0, 0, 320, 200, _gamePlayBuffer); musicUpdate(0); for (int i = 0; i < 10; ++i) { _emc->init(&_sceneSpecialScripts[i], &_sceneScriptData); _emc->start(&_sceneSpecialScripts[i], i+9); musicUpdate(0); _sceneSpecialScriptsTimer[i] = 0; } _sceneEnterX1 &= ~3; _sceneEnterY1 &= ~1; _sceneEnterX2 &= ~3; _sceneEnterY2 &= ~1; _sceneEnterX3 &= ~3; _sceneEnterY3 &= ~1; _sceneEnterX4 &= ~3; _sceneEnterY4 &= ~1; musicUpdate(0); }
void ConversationConditionals::load(const Common::String &filename) { Common::File inFile; Common::SeekableReadStream *convFile; // Open up the file for access inFile.open(filename); MadsPack convFileUnpacked(&inFile); // **** Section 0: Header ************************************************* convFile = convFileUnpacked.getItemStream(0); _currentNode = convFile->readUint16LE(); int entryFlagsCount = convFile->readUint16LE(); int varsCount = convFile->readUint16LE(); int importsCount = convFile->readUint16LE(); convFile->skip(4); _messageList1.resize(convFile->readUint16LE()); _messageList2.resize(convFile->readUint16LE()); _messageList3.resize(convFile->readUint16LE()); _messageList4.resize(convFile->readUint16LE()); convFile->skip(20); for (uint idx = 0; idx < 10; ++idx) { int v = convFile->readUint16LE(); if (idx < _messageList1.size()) _messageList1[idx] = v; } for (uint idx = 0; idx < 10; ++idx) { int v = convFile->readUint16LE(); if (idx < _messageList2.size()) _messageList2[idx] = v; } for (uint idx = 0; idx < 10; ++idx) { int v = convFile->readUint16LE(); if (idx < _messageList3.size()) _messageList3[idx] = v; } for (uint idx = 0; idx < 10; ++idx) { int v = convFile->readUint16LE(); if (idx < _messageList4.size()) _messageList4[idx] = v; } delete convFile; // **** Section: Imports ************************************************* int streamNum = 1; _importVariables.resize(importsCount); if (importsCount > 0) { convFile = convFileUnpacked.getItemStream(streamNum++); // Read in the variable indexes that each import value will be stored in for (int idx = 0; idx < importsCount; ++idx) _importVariables[idx] = convFile->readUint16LE(); delete convFile; } // **** Section: Entry Flags ********************************************* convFile = convFileUnpacked.getItemStream(streamNum++); assert(convFile->size() == (entryFlagsCount * 2)); _entryFlags.resize(entryFlagsCount); for (int idx = 0; idx < entryFlagsCount; ++idx) _entryFlags[idx] = convFile->readUint16LE(); delete convFile; // **** Section: Variables *********************************************** convFile = convFileUnpacked.getItemStream(streamNum); assert(convFile->size() == (varsCount * 6)); _vars.resize(varsCount); for (int idx = 0; idx < varsCount; ++idx) { convFile->skip(2); // Loaded values are never pointers, so don't need this _vars[idx]._isPtr = false; _vars[idx]._val = convFile->readSint16LE(); convFile->skip(2); // Unused segment selector for pointer values } delete convFile; }
void ScriptEntry::load(Common::SeekableReadStream &s) { // Get the command byte _command = (DialogCommand)s.readByte(); if (!(_command == CMD_DIALOG_END || (_command >= CMD_END && _command <= CMD_ASSIGN))) { warning("unknown opcode - %d", _command); s.seek(0, SEEK_END); return; } // Get in the conditional values int numConditionals = 1; if (_command == CMD_NODE) numConditionals = 3; else if (_command == CMD_ASSIGN) numConditionals = 2; else if (_command == CMD_ERROR) numConditionals = 0; for (int idx = 0; idx < numConditionals; ++idx) _conditionals[idx].load(s); // Get further parameters switch (_command) { case CMD_1: case CMD_HIDE: case CMD_UNHIDE: { // Read in the list of entries whose flags are to be updated int count = s.readByte(); for (int idx = 0; idx < count; ++idx) _entries.push_back(s.readSint16LE()); break; } case CMD_MESSAGE1: case CMD_MESSAGE2: { int count2 = s.readByte(); int count1 = s.readByte(); _entries2.resize(count2); _entries.resize(count1); for (uint idx = 0; idx < _entries2.size(); ++idx) { int v = s.readByte(); if (idx < 10) _entries2[idx]._size = v; } for (uint idx = 0; idx < _entries2.size(); ++idx) { int v = s.readUint16LE(); if (idx < 10) _entries2[idx]._v2 = v; } for (uint idx = 0; idx < _entries.size(); ++idx) { int v = s.readUint16LE(); if (idx < 10) _entries[idx] = v; } break; } case CMD_ERROR: case CMD_NODE: // These opcodes have no extra parameters break; case CMD_GOTO: case CMD_ASSIGN: // Goto has a single extra parameter for the destination // Assign has a single extra parameter for the variable index // that the value resulting from the condition will be set to _index = s.readUint16LE(); break; default: break; } }
void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Surface *depthSurface, M4Surface *surface) { char buffer1[80]; const char *sceneName; // TODO: Initialise spriteSet / xp_list if (sceneNumber > 0) { sceneName = MADSResourceManager::getResourceName(RESPREFIX_RM, sceneNumber, ".DAT"); } else { strcpy(buffer1, "*"); strcat(buffer1, resName); sceneName = buffer1; // TODO: Check whether this needs to be converted to 'HAG form' } Common::SeekableReadStream *rawStream = _vm->_resourceManager->get(sceneName); MadsPack sceneInfo(rawStream); // Chunk 0: // Basic scene info Common::SeekableReadStream *stream = sceneInfo.getItemStream(0); if (_vm->getGameType() == GType_RexNebular) { int resSceneId = stream->readUint16LE(); assert(resSceneId == sceneNumber); } else { char roomFilename[10]; char roomFilenameExpected[10]; sprintf(roomFilenameExpected, "*RM%d", sceneNumber); stream->read(roomFilename, 6); roomFilename[6] = 0; assert(!strcmp(roomFilename, roomFilenameExpected)); } // TODO: The following is wrong for Phantom/Dragon _artFileNum = stream->readUint16LE(); _depthStyle = stream->readUint16LE(); _width = stream->readUint16LE(); _height = stream->readUint16LE(); stream->skip(24); int nodeCount = stream->readUint16LE(); _yBandsEnd = stream->readUint16LE(); _yBandsStart = stream->readUint16LE(); _maxScale = stream->readSint16LE(); _minScale = stream->readSint16LE(); for (int i = 0; i < DEPTH_BANDS_SIZE; ++i) _depthBands[i] = stream->readUint16LE(); stream->skip(2); // Load in any scene objects for (int i = 0; i < nodeCount; ++i) { SceneNode rec; rec.load(stream); _nodes.push_back(rec); } for (int i = 0; i < 20 - nodeCount; ++i) stream->skip(48); // Add two extra nodes in that will be used for player movement for (int i = 0; i < 2; ++i) { SceneNode rec; _nodes.push_back(rec); } int setCount = stream->readUint16LE(); stream->readUint16LE(); for (int i = 0; i < setCount; ++i) { char buffer2[64]; Common::String s(buffer2, 64); _setNames.push_back(s); } delete stream; // Initialise a copy of the surfaces if they weren't provided bool dsFlag = false, ssFlag = false; if (!surface) { surface = new M4Surface(_width, _height); ssFlag = true; } else if ((_width != surface->width()) || (_height != surface->height())) surface->setSize(_width, _height); if (!depthSurface) { depthSurface = new M4Surface(_width, _height); dsFlag = true; } else if ((_width != depthSurface->width()) || (_height != depthSurface->height())) depthSurface->setSize(_width, _height); // For Rex Nebular, read in the scene's compressed walk surface information if (_vm->getGameType() == GType_RexNebular) { assert(depthSurface); stream = sceneInfo.getItemStream(1); byte *walkData = (byte *)malloc(stream->size()); stream->read(walkData, stream->size()); // For Rex Nebular, the walk areas are part of the scene info byte *destP = depthSurface->getBasePtr(0, 0); const byte *srcP = walkData; byte runLength; // Run length encoded depth data while ((runLength = *srcP++) != 0) { if (_depthStyle == 2) { // 2-bit depth pixels byte byteVal = *srcP++; for (int byteCtr = 0; byteCtr < runLength; ++byteCtr) { byte v = byteVal; for (int bitCtr = 0; bitCtr < 4; ++bitCtr, v >>= 2) *destP++ = (((v & 1) + 1) << 3) - 1; } } else {
void ConversationData::load(const Common::String &filename) { Common::File inFile; char buffer[16]; inFile.open(filename); MadsPack convFileUnpacked(&inFile); // **** Section 0: Header ************************************************* Common::SeekableReadStream *convFile = convFileUnpacked.getItemStream(0); _nodeCount = convFile->readUint16LE(); _dialogCount = convFile->readUint16LE(); _messageCount = convFile->readUint16LE(); _textLineCount = convFile->readUint16LE(); _unk2 = convFile->readUint16LE(); _maxImports = convFile->readUint16LE(); _speakerCount = convFile->readUint16LE(); for (uint idx = 0; idx < MAX_SPEAKERS; ++idx) { convFile->read(buffer, 16); _portraits[idx] = buffer; } for (uint idx = 0; idx < MAX_SPEAKERS; ++idx) { _speakerFrame[idx] = convFile->readUint16LE(); } convFile->read(buffer, 14); _speechFile = Common::String(buffer); // Total text length in section 5 _textSize = convFile->readUint32LE(); _commandsSize = convFile->readUint32LE(); // The rest of the section 0 is padding to allow room for a set of pointers // to the contents of the remaining sections loaded into memory as a // continuous data block containing both the header and the sections delete convFile; // **** Section 1: Nodes ************************************************** convFile = convFileUnpacked.getItemStream(1); _nodes.clear(); for (uint i = 0; i < _nodeCount; i++) { ConvNode node; node._index = convFile->readUint16LE(); node._dialogCount = convFile->readUint16LE(); node._unk1 = convFile->readSint16LE(); // TODO node._active = convFile->readSint16LE() != 0; node._unk3 = convFile->readSint16LE(); // TODO _nodes.push_back(node); } delete convFile; // **** Section 2: Dialogs ************************************************ convFile = convFileUnpacked.getItemStream(2); assert(convFile->size() == _dialogCount * 8); _dialogs.resize(_dialogCount); for (uint idx = 0; idx < _dialogCount; ++idx) { _dialogs[idx]._textLineIndex = convFile->readSint16LE(); _dialogs[idx]._speechIndex = convFile->readSint16LE(); _dialogs[idx]._scriptOffset = convFile->readUint16LE(); _dialogs[idx]._scriptSize = convFile->readUint16LE(); } delete convFile; // **** Section 3: Messages *********************************************** convFile = convFileUnpacked.getItemStream(3); assert(convFile->size() == _messageCount * 4); _messages.resize(_messageCount); for (uint idx = 0; idx < _messageCount; ++idx) { _messages[idx]._stringIndex = convFile->readUint16LE(); _messages[idx]._count = convFile->readUint16LE(); } delete convFile; // **** Section 4: Text line offsets ************************************** convFile = convFileUnpacked.getItemStream(4); assert(convFile->size() == _textLineCount * 2); uint16 *textLineOffsets = new uint16[_textLineCount]; // deleted below in section 5 for (uint16 i = 0; i < _textLineCount; i++) textLineOffsets[i] = convFile->readUint16LE(); delete convFile; // **** Section 5: Text lines ********************************************* convFile = convFileUnpacked.getItemStream(5); assert(convFile->size() == _textSize); Common::String textLine; _textLines.resize(_textLineCount); char textLineBuffer[256]; uint16 nextOffset; for (uint16 i = 0; i < _textLineCount; i++) { nextOffset = (i != _textLineCount - 1) ? textLineOffsets[i + 1] : convFile->size(); convFile->read(textLineBuffer, nextOffset - textLineOffsets[i]); _textLines[i] = Common::String(textLineBuffer); } delete[] textLineOffsets; delete convFile; // **** Section 6: Scripts ************************************************ convFile = convFileUnpacked.getItemStream(6); assert(convFile->size() == _commandsSize); for (uint idx = 0; idx < _dialogs.size(); ++idx) { // Move to the correct position for the dialog's script, and create // a memory stream to represent the data for just that script convFile->seek(_dialogs[idx]._scriptOffset); Common::SeekableReadStream *scriptStream = convFile->readStream(_dialogs[idx]._scriptSize); // Pass it to the dialog's script set class to parse into commands _dialogs[idx]._script.load(*scriptStream, _dialogs[idx]._scriptOffset); delete scriptStream; } delete convFile; inFile.close(); }
void ConversationData::load(const Common::String &filename) { Common::File inFile; char buffer[16]; inFile.open(filename); MadsPack convFileUnpacked(&inFile); Common::SeekableReadStream *convFile = convFileUnpacked.getItemStream(0); // **** Section 0: Header ************************************************* _nodeCount = convFile->readUint16LE(); _dialogCount = convFile->readUint16LE(); _messageCount = convFile->readUint16LE(); _textLineCount = convFile->readUint16LE(); _unk2 = convFile->readUint16LE(); _importCount = convFile->readUint16LE(); _speakerCount = convFile->readUint16LE(); for (uint idx = 0; idx < MAX_SPEAKERS; ++idx) { convFile->read(buffer, 16); _portraits[idx] = buffer; } for (uint idx = 0; idx < MAX_SPEAKERS; ++idx) { _speakerExists[idx] = convFile->readUint16LE(); } convFile->read(buffer, 14); _speechFile = Common::String(buffer); // Total text length in section 5 _textSize = convFile->readUint32LE(); _commandsSize = convFile->readUint32LE(); // The rest of the section 0 is padding to allow room for a set of pointers // to the contents of the remaining sections loaded into memory as a // continuous data block containing both the header and the sections delete convFile; // **** Section 1: Nodes ************************************************** convFile = convFileUnpacked.getItemStream(1); _convNodes.clear(); for (uint i = 0; i < _nodeCount; i++) { ConvNode node; node._index = convFile->readUint16LE(); node._dialogCount = convFile->readUint16LE(); node._unk1 = convFile->readSint16LE(); // TODO node._unk2 = convFile->readSint16LE(); // TODO node._unk3 = convFile->readSint16LE(); // TODO _convNodes.push_back(node); //debug("Node %d, index %d, entries %d - %d, %d, %d", i, node.index, node.dialogCount, node.unk1, node.unk2, node.unk3); } delete convFile; // **** Section 2: Dialogs ************************************************ convFile = convFileUnpacked.getItemStream(2); assert(convFile->size() == _dialogCount * 8); for (uint idx = 0; idx < _nodeCount; ++idx) { uint dialogCount = _convNodes[idx]._dialogCount; for (uint j = 0; j < dialogCount; ++j) { ConvDialog dialog; dialog._textLineIndex = convFile->readSint16LE(); dialog._speechIndex = convFile->readSint16LE(); dialog._nodeOffset = convFile->readUint16LE(); dialog._nodeSize = convFile->readUint16LE(); _convNodes[idx]._dialogs.push_back(dialog); } } delete convFile; // **** Section 3: Messages *********************************************** convFile = convFileUnpacked.getItemStream(3); assert(convFile->size() == _messageCount * 8); _messages.resize(_messageCount); for (uint idx = 0; idx < _messageCount; ++idx) _messages[idx] = convFile->readUint32LE(); delete convFile; // **** Section 4: Text line offsets ************************************** convFile = convFileUnpacked.getItemStream(4); assert(convFile->size() == _textLineCount * 2); uint16 *textLineOffsets = new uint16[_textLineCount]; // deleted below in section 5 for (uint16 i = 0; i < _textLineCount; i++) textLineOffsets[i] = convFile->readUint16LE(); delete convFile; // **** Section 5: Text lines ********************************************* convFile = convFileUnpacked.getItemStream(5); assert(convFile->size() == _textSize); Common::String textLine; _textLines.resize(_textLineCount); char textLineBuffer[256]; uint16 nextOffset; for (uint16 i = 0; i < _textLineCount; i++) { nextOffset = (i != _textLineCount - 1) ? textLineOffsets[i + 1] : convFile->size(); convFile->read(textLineBuffer, nextOffset - textLineOffsets[i]); _textLines[i] = Common::String(textLineBuffer); } delete[] textLineOffsets; delete convFile; // **** Section 6: Node entry commands ************************************ convFile = convFileUnpacked.getItemStream(6); assert(convFile->size() == _commandsSize); for (uint16 i = 0; i < _nodeCount; i++) { uint16 dialogCount = _convNodes[i]._dialogCount; for (uint16 j = 0; j < dialogCount; j++) { //ConvDialog dialog = _convNodes[i].dialogs[j]; byte command; uint16 chk; do { command = convFile->readByte(); chk = convFile->readUint16BE(); if (chk != 0xFF00 && chk != 0x0000) { warning("Error while reading conversation node entries - bailing out"); break; } switch (command) { case cmdNodeEnd: //debug("Node end"); break; case cmdDialogEnd: //debug("Dialog end"); break; case cmdHide: { byte count = convFile->readByte(); for (byte k = 0; k < count; k++) { /*uint16 nodeRef = */convFile->readUint16LE(); //debug("Hide node %d", nodeRef); } } break; case cmdUnhide: { byte count = convFile->readByte(); for (byte k = 0; k < count; k++) { /*uint16 nodeRef = */convFile->readUint16LE(); //debug("Unhide node %d", nodeRef); } } break; case cmdMessage: //debug("Message"); convFile->skip(7); // TODO break; case cmdGoto: { convFile->skip(3); // unused? /*byte nodeRef = */convFile->readByte(); //debug("Goto %d", nodeRef); } break; case cmdAssign: { convFile->skip(3); // unused? /*uint16 value = */convFile->readUint16LE(); /*uint16 variable = */convFile->readUint16LE(); //debug("Variable %d = %d", variable, value); } break; default: error("Unknown conversation command %d", command); break; } } while (command != cmdNodeEnd && command != cmdDialogEnd); } } delete convFile; inFile.close(); // TODO: Still stuff to do warning("TODO GameConversations::get"); }
void FileIdent::load(Common::SeekableReadStream &s) { _fileNum = s.readSint16LE(); _subfile = s.readUint16LE(); }
/** * Initialises and loads the data of an animation */ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4Surface *surface, M4Surface *depthSurface) { MadsPack anim(filename.c_str(), _vm); bool madsRes = filename[0] == '*'; char buffer[20]; int streamIndex = 1; // Chunk 1: header // header Common::SeekableReadStream *animStream = anim.getItemStream(0); int spriteListCount = animStream->readUint16LE(); int miscEntriesCount = animStream->readUint16LE(); int frameEntryCount = animStream->readUint16LE(); int messagesCount = animStream->readUint16LE(); animStream->skip(1); _flags = animStream->readByte(); animStream->skip(2); _animMode = animStream->readUint16LE(); _roomNumber = animStream->readUint16LE(); animStream->skip(2); _field12 = animStream->readUint16LE() != 0; _spriteListIndex = animStream->readUint16LE(); _scrollX = animStream->readSint16LE(); _scrollY = animStream->readSint16LE(); _scrollTicks = animStream->readUint16LE(); animStream->skip(8); animStream->read(buffer, FILENAME_SIZE); buffer[FILENAME_SIZE] = '\0'; _interfaceFile = Common::String(buffer); for (int i = 0; i < 10; ++i) { animStream->read(buffer, FILENAME_SIZE); buffer[FILENAME_SIZE] = '\0'; _spriteSetNames[i] = Common::String(buffer); } animStream->skip(81); animStream->read(buffer, FILENAME_SIZE); buffer[FILENAME_SIZE] = '\0'; _lbmFilename = Common::String(buffer); animStream->skip(365); animStream->read(buffer, FILENAME_SIZE); buffer[FILENAME_SIZE] = '\0'; _spritesFilename = Common::String(buffer); animStream->skip(48); animStream->read(buffer, FILENAME_SIZE); buffer[FILENAME_SIZE] = '\0'; _soundName = Common::String(buffer); animStream->skip(13); animStream->read(buffer, FILENAME_SIZE); buffer[FILENAME_SIZE] = '\0'; _dsrName = Common::String(buffer); animStream->read(buffer, FILENAME_SIZE); buffer[FILENAME_SIZE] = '\0'; Common::String fontResource(buffer); if (_animMode == 4) flags |= 0x4000; if (flags & 0x100) loadInterface(surface, depthSurface); // Initialise the reference list for (int i = 0; i < spriteListCount; ++i) _spriteListIndexes.push_back(-1); delete animStream; if (messagesCount > 0) { // Chunk 2 // Following is a list of any messages for the animation animStream = anim.getItemStream(streamIndex++); for (int i = 0; i < messagesCount; ++i) { AnimMessage rec; rec.soundId = animStream->readSint16LE(); animStream->read(rec.msg, 64); animStream->skip(4); rec.pos.x = animStream->readSint16LE(); rec.pos.y = animStream->readSint16LE(); rec.flags = animStream->readUint16LE(); rec.rgb1.r = animStream->readByte() << 2; rec.rgb1.g = animStream->readByte() << 2; rec.rgb1.b = animStream->readByte() << 2; rec.rgb2.r = animStream->readByte() << 2; rec.rgb2.g = animStream->readByte() << 2; rec.rgb2.b = animStream->readByte() << 2; animStream->skip(2); // Space for kernelMsgIndex rec.kernelMsgIndex = -1; animStream->skip(6); rec.startFrame = animStream->readUint16LE(); rec.endFrame = animStream->readUint16LE(); animStream->skip(2); _messages.push_back(rec); } delete animStream; } if (frameEntryCount > 0) { // Chunk 3: animation frame info animStream = anim.getItemStream(streamIndex++); for (int i = 0; i < frameEntryCount; i++) { AnimFrameEntry rec; rec.frameNumber = animStream->readUint16LE(); rec.seqIndex = animStream->readByte(); rec.spriteSlot.spriteListIndex = animStream->readByte(); rec.spriteSlot.frameNumber = animStream->readUint16LE(); rec.spriteSlot.xp = animStream->readSint16LE(); rec.spriteSlot.yp = animStream->readSint16LE(); rec.spriteSlot.depth = animStream->readSByte(); rec.spriteSlot.scale = (int8)animStream->readByte(); _frameEntries.push_back(rec); } delete animStream; } if (miscEntriesCount > 0) { // Chunk 4: Misc Data animStream = anim.getItemStream(streamIndex); for (int i = 0; i < miscEntriesCount; ++i) { AnimMiscEntry rec; rec.soundNum = animStream->readByte(); rec.msgIndex = animStream->readSByte(); rec.numTicks = animStream->readUint16LE(); rec.posAdjust.x = animStream->readUint16LE(); rec.posAdjust.y = animStream->readUint16LE(); animStream->readUint16LE(); _miscEntries.push_back(rec); } delete animStream; } // If the animation specifies a font, then load it for access if (_flags & ANIM_CUSTOM_FONT) { Common::String fontName; if (madsRes) fontName += "*"; fontName += fontResource; if (fontName != "") _font = _vm->_font->getFont(fontName.c_str()); else warning("Attempted to set a font with an empty name"); } // If a speech file is specified, then load it if (!_dsrName.empty()) _vm->_sound->loadDSRFile(_dsrName.c_str()); // Load all the sprite sets for the animation for (int i = 0; i < spriteListCount; ++i) { if (_field12 && (i == _spriteListIndex)) // Skip over field, since it's manually loaded continue; _spriteListIndexes[i] = _view->_spriteSlots.addSprites(_spriteSetNames[i].c_str()); } if (_field12) { Common::String resName; if (madsRes) resName += "*"; resName += _spriteSetNames[_spriteListIndex]; _spriteListIndexes[_spriteListIndex] = _view->_spriteSlots.addSprites(resName.c_str()); } // TODO: Unknown section about handling sprite set list combined with messages size // TODO: The original has two separate loops for the loop below based on _animMode == 4. Is it // perhaps that in that mode the sprite frames has a different format..? // Remap the sprite list index fields from the initial value to the indexes of the loaded // sprite sets for the animation for (uint i = 0; i < _frameEntries.size(); ++i) { int idx = _frameEntries[i].spriteSlot.spriteListIndex; _frameEntries[i].spriteSlot.spriteListIndex = _spriteListIndexes[idx]; } if (hasScroll()) _nextScrollTimer = _madsVm->_currentTimer + _scrollTicks; }