MusicEntry *initMusicTableDemo(const Common::String &filename) { Common::SeekableReadStream *data = g_resourceloader->openNewStreamFile(filename); if (!data) error("Couldn't open %s", filename.c_str()); // FIXME, for now we use a fixed-size table, as I haven't looked at the retail-data yet. MusicEntry *musicTable = new MusicEntry[15]; for (unsigned int i = 0; i < 15; i++) musicTable[i]._id = -1; TextSplitter *ts = new TextSplitter(filename, data); int id, x, y, sync; char musicfilename[64]; char name[64]; while (!ts->isEof()) { while (!ts->checkString("*/")) { while (!ts->checkString(".cuebutton")) ts->nextLine(); ts->scanString(".cuebutton id %d x %d y %d sync %d \"%[^\"]64s", 5, &id, &x, &y, &sync, name); ts->scanString(".playfile \"%[^\"]64s", 1, musicfilename); musicTable[id]._id = id; musicTable[id]._x = x; musicTable[id]._y = y; musicTable[id]._sync = sync; musicTable[id]._name = name; musicTable[id]._filename = musicfilename; } ts->nextLine(); } delete ts; delete data; return musicTable; }
void KeyframeAnim::loadText(TextSplitter &ts) { ts.expectString("section: header"); ts.scanString("flags %x", 1, &_flags); ts.scanString("type %x", 1, &_type); ts.scanString("frames %d", 1, &_numFrames); ts.scanString("fps %f", 1, &_fps); ts.scanString("joints %d", 1, &_numJoints); if (strcasecmp(ts.currentLine(), "section: markers") == 0) { ts.nextLine(); ts.scanString("markers %d", 1, &_numMarkers); _markers = new Marker[_numMarkers]; for (int i = 0; i < _numMarkers; i++) ts.scanString("%f %d", 2, &_markers[i].frame, &_markers[i].val); } else { _numMarkers = 0; _markers = NULL; } ts.expectString("section: keyframe nodes"); int numNodes; ts.scanString("nodes %d", 1, &numNodes); _nodes = new KeyframeNode *[_numJoints]; for (int i = 0; i < _numJoints; i++) _nodes[i] = NULL; for (int i = 0; i < numNodes; i++) { int which; ts.scanString("node %d", 1, &which); _nodes[which] = new KeyframeNode; _nodes[which]->loadText(ts); } }
void Chore::load(TextSplitter &ts) { _hasPlayed = _playing = false; for (int i = 0; i < _numTracks; i++) { int compID, numKeys; ts.scanString(" %d %d", 2, &compID, &numKeys); _tracks[i].compID = compID; _tracks[i].numKeys = numKeys; _tracks[i].keys = new TrackKey[numKeys]; for (int j = 0; j < numKeys; j++) { ts.scanString(" %d %d", 2, &_tracks[i].keys[j].time, &_tracks[i].keys[j].value); } } }
void Light::load(TextSplitter &ts) { char buf[256]; // Light names can be null, but ts doesn't seem flexible enough to allow this if (strlen(ts.getCurrentLine()) > strlen(" light")) ts.scanString(" light %256s", 1, buf); else { ts.nextLine(); strcpy(buf, ""); } _name = buf; ts.scanString(" type %256s", 1, buf); _type = buf; ts.scanString(" position %f %f %f", 3, &_pos.x(), &_pos.y(), &_pos.z()); ts.scanString(" direction %f %f %f", 3, &_dir.x(), &_dir.y(), &_dir.z()); ts.scanString(" intensity %f", 1, &_intensity); ts.scanString(" umbraangle %f", 1, &_umbraangle); ts.scanString(" penumbraangle %f", 1, &_penumbraangle); int r, g, b; ts.scanString(" color %d %d %d", 3, &r, &g, &b); _color.getRed() = r; _color.getGreen() = g; _color.getBlue() = b; _enabled = true; }
void Set::Setup::load(Set *set, int id, TextSplitter &ts) { char buf[256]; ts.scanString(" setup %256s", 1, buf); _name = buf; ts.scanString(" background %256s", 1, buf); _bkgndBm = Bitmap::create(buf); if (!_bkgndBm) { Debug::warning(Debug::Bitmaps | Debug::Sets, "Unable to load scene bitmap: %s\n", buf); } else { Debug::debug(Debug::Bitmaps | Debug::Sets, "Loaded scene bitmap: %s\n", buf); } // ZBuffer is optional _bkgndZBm = NULL; if (ts.checkString("zbuffer")) { ts.scanString(" zbuffer %256s", 1, buf); // Don't even try to load if it's the "none" bitmap if (strcmp(buf, "<none>.lbm") != 0) { _bkgndZBm = Bitmap::create(buf); Debug::debug(Debug::Bitmaps | Debug::Sets, "Loading scene z-buffer bitmap: %s\n", buf); } } ts.scanString(" position %f %f %f", 3, &_pos.x(), &_pos.y(), &_pos.z()); ts.scanString(" interest %f %f %f", 3, &_interest.x(), &_interest.y(), &_interest.z()); ts.scanString(" roll %f", 1, &_roll); ts.scanString(" fov %f", 1, &_fov); ts.scanString(" nclip %f", 1, &_nclip); ts.scanString(" fclip %f", 1, &_fclip); for (;;) { char name[256], zname[256]; char bitmap[256], zbitmap[256]; zbitmap[0] = '\0'; if (ts.checkString("object_art")) ts.scanString(" object_art %256s %256s", 2, name, bitmap); else break; if (ts.checkString("object_z")) ts.scanString(" object_z %256s %256s", 2, zname, zbitmap); if (zbitmap[0] == '\0' || strcmp(name, zname) == 0) { set->addObjectState(id, ObjectState::OBJSTATE_BACKGROUND, bitmap, zbitmap, true); } } }
void Chore::load(int id, Costume *owner, TextSplitter &ts) { _owner = owner; _tracks = new ChoreTrack[_numTracks]; _hasPlayed = _playing = false; _choreId = id; for (int i = 0; i < _numTracks; i++) { int compID, numKeys; ts.scanString(" %d %d", 2, &compID, &numKeys); _tracks[i].compID = compID; _tracks[i].numKeys = numKeys; _tracks[i].keys = new TrackKey[numKeys]; for (int j = 0; j < numKeys; j++) { ts.scanString(" %d %d", 2, &_tracks[i].keys[j].time, &_tracks[i].keys[j].value); } } }
void Sector::load(TextSplitter &ts) { char buf[256]; int ident = 0, i = 0; Math::Vector3d tempVert; // Sector NAMES can be null, but ts isn't flexible enough if (strlen(ts.getCurrentLine()) > strlen(" sector")) ts.scanString(" sector %256s", 1, buf); else { ts.nextLine(); strcpy(buf, ""); } ts.scanString(" id %d", 1, &ident); _name = buf; _id = ident; ts.scanString(" type %256s", 1, buf); if (strstr(buf, "walk")) _type = WalkType; else if (strstr(buf, "funnel")) _type = FunnelType; else if (strstr(buf, "camera")) _type = CameraType; else if (strstr(buf, "special")) _type = SpecialType; else if (strstr(buf, "chernobyl")) _type = HotType; else Debug::error(Debug::Sets, "Unknown sector type '%s' in room setup", buf); ts.scanString(" default visibility %256s", 1, buf); if (strcmp(buf, "visible") == 0) _visible = true; else if (strcmp(buf, "invisible") == 0) _visible = false; else error("Invalid visibility spec: %s", buf); ts.scanString(" height %f", 1, &_height); ts.scanString(" numvertices %d", 1, &_numVertices); _vertices = new Math::Vector3d[_numVertices + 1]; ts.scanString(" vertices: %f %f %f", 3, &_vertices[0].x(), &_vertices[0].y(), &_vertices[0].z()); for (i = 1; i < _numVertices; i++) ts.scanString(" %f %f %f", 3, &_vertices[i].x(), &_vertices[i].y(), &_vertices[i].z()); // Repeat the last vertex for convenience _vertices[_numVertices] = _vertices[0]; _normal = Math::Vector3d::crossProduct(_vertices[1] - _vertices[0], _vertices[_numVertices - 1] - _vertices[0]); float length = _normal.getMagnitude(); if (length > 0) _normal /= length; }
MusicEntry *initMusicTableRetail(MusicEntry *table, const Common::String &filename) { Common::SeekableReadStream *data = g_resourceloader->openNewStreamFile(filename); // Remember to check, in case we forgot to copy over those files from the CDs. if (!data) { warning("Couldn't open %s", filename.c_str()); delete[] table; return nullptr; } MusicEntry *musicTable = table; if (!table) { musicTable = new MusicEntry[126]; for (unsigned int i = 0; i < 126; i++) { musicTable[i]._id = -1; } } TextSplitter *ts = new TextSplitter(filename, data); int id, x, y, sync, trim; char musicfilename[64]; char type[16]; // Every block is followed by 3 lines of commenting/uncommenting, except the last. while (!ts->isEof()) { while (!ts->checkString("*/")) { while (!ts->checkString(".cuebutton")) ts->nextLine(); ts->scanString(".cuebutton id %d x %d y %d sync %d type %16s", 5, &id, &x, &y, &sync, type); ts->scanString(".playfile trim %d \"%[^\"]64s", 2, &trim, musicfilename); if (musicfilename[1] == '\\') musicfilename[1] = '/'; musicTable[id]._id = id; musicTable[id]._x = x; musicTable[id]._y = y; musicTable[id]._sync = sync; musicTable[id]._type = type; musicTable[id]._name = ""; musicTable[id]._trim = trim; musicTable[id]._filename = musicfilename; } ts->nextLine(); } delete ts; delete data; return musicTable; }
void MaterialData::initEMI(Common::SeekableReadStream *data) { Common::Array<Common::String> texFileNames; char readFileName[64]; if (_fname.hasSuffix(".sur")) { // This expects that we want all the materials in the sur-file TextSplitter *ts = new TextSplitter(data); ts->setLineNumber(2); // Skip copyright-line ts->expectString("version\t1.0"); if (ts->checkString("name:")) ts->scanString("name:%s", 1, readFileName); while(!ts->checkString("END_OF_SECTION")) { ts->scanString("tex:%s", 1, readFileName); Common::String mFileName(readFileName); texFileNames.push_back(mFileName); } Common::SeekableReadStream *texData; _textures = new Texture[texFileNames.size()]; for (uint i = 0; i < texFileNames.size(); i++) { warning("SUR-file texture: %s", texFileNames[i].c_str()); texData = g_resourceloader->openNewStreamFile(texFileNames[i].c_str(), true); if (!texData) { warning("Couldn't find tex-file: %s", texFileNames[i].c_str()); _textures[i]._width = 0; _textures[i]._height = 0; _textures[i]._texture = new int(1); // HACK to avoid initializing. continue; } loadTGA(texData, _textures + i); delete texData; } _numImages = texFileNames.size(); delete ts; return; } else if(_fname.hasSuffix(".tga")) { _numImages = 1; _textures = new Texture(); loadTGA(data, _textures); // texFileNames.push_back(filename); return; } else { warning("Unknown material-format: %s", _fname.c_str()); } }
void Set::Setup::load(TextSplitter &ts) { char buf[256]; ts.scanString(" setup %256s", 1, buf); _name = buf; ts.scanString(" background %256s", 1, buf); _bkgndBm = Bitmap::create(buf); if (!_bkgndBm) { Debug::warning(Debug::Bitmaps | Debug::Sets, "Unable to load scene bitmap: %s\n", buf); } else { Debug::debug(Debug::Bitmaps | Debug::Sets, "Loaded scene bitmap: %s\n", buf); } // ZBuffer is optional _bkgndZBm = NULL; if (ts.checkString("zbuffer")) { ts.scanString(" zbuffer %256s", 1, buf); // Don't even try to load if it's the "none" bitmap if (strcmp(buf, "<none>.lbm") != 0) { _bkgndZBm = Bitmap::create(buf); Debug::debug(Debug::Bitmaps | Debug::Sets, "Loading scene z-buffer bitmap: %s\n", buf); } } ts.scanString(" position %f %f %f", 3, &_pos.x(), &_pos.y(), &_pos.z()); ts.scanString(" interest %f %f %f", 3, &_interest.x(), &_interest.y(), &_interest.z()); ts.scanString(" roll %f", 1, &_roll); ts.scanString(" fov %f", 1, &_fov); ts.scanString(" nclip %f", 1, &_nclip); ts.scanString(" fclip %f", 1, &_fclip); for (;;) { if (ts.checkString("object_art")) ts.scanString(" object_art %256s", 1, buf); else break; if (ts.checkString("object_z")) ts.scanString(" object_z %256s", 1, buf); } }
void Set::Setup::load(TextSplitter &ts) { char buf[256]; ts.scanString(" setup %256s", 1, buf); _name = buf; ts.scanString(" background %256s", 1, buf); _bkgndBm = g_resourceloader->loadBitmap(buf); if (!_bkgndBm) { if (gDebugLevel == DEBUG_BITMAPS || gDebugLevel == DEBUG_ERROR || gDebugLevel == DEBUG_ALL) warning("Unable to load scene bitmap: %s\n", buf); } else { if (gDebugLevel == DEBUG_BITMAPS || gDebugLevel == DEBUG_NORMAL || gDebugLevel == DEBUG_ALL) warning("Loaded scene bitmap: %s\n", buf); } // ZBuffer is optional _bkgndZBm = NULL; if (ts.checkString("zbuffer")) { ts.scanString(" zbuffer %256s", 1, buf); // Don't even try to load if it's the "none" bitmap if (strcmp(buf, "<none>.lbm") != 0) { _bkgndZBm = g_resourceloader->loadBitmap(buf); if (gDebugLevel == DEBUG_BITMAPS || gDebugLevel == DEBUG_NORMAL || gDebugLevel == DEBUG_ALL) printf("Loading scene z-buffer bitmap: %s\n", buf); } } ts.scanString(" position %f %f %f", 3, &_pos.x(), &_pos.y(), &_pos.z()); ts.scanString(" interest %f %f %f", 3, &_interest.x(), &_interest.y(), &_interest.z()); ts.scanString(" roll %f", 1, &_roll); ts.scanString(" fov %f", 1, &_fov); ts.scanString(" nclip %f", 1, &_nclip); ts.scanString(" fclip %f", 1, &_fclip); for (;;) { if (ts.checkString("object_art")) ts.scanString(" object_art %256s", 1, buf); else break; if (ts.checkString("object_z")) ts.scanString(" object_z %256s", 1, buf); } }
void KeyframeAnim::KeyframeNode::loadText(TextSplitter &ts) { ts.scanString("mesh name %s", 1, _meshName); ts.scanString("entries %d", 1, &_numEntries); _entries = new KeyframeEntry[_numEntries]; for (int i = 0; i < _numEntries; i++) { int which; unsigned flags; float frame, x, y, z, p, yaw, r, dx, dy, dz, dp, dyaw, dr; ts.scanString(" %d: %f %x %f %f %f %f %f %f", 9, &which, &frame, &flags, &x, &y, &z, &p, &yaw, &r); ts.scanString(" %f %f %f %f %f %f", 6, &dx, &dy, &dz, &dp, &dyaw, &dr); _entries[which]._frame = frame; _entries[which]._flags = (int)flags; _entries[which]._pos = Graphics::Vector3d(x, y, z); _entries[which]._dpos = Graphics::Vector3d(dx, dy, dz); _entries[which]._pitch = p; _entries[which]._yaw = yaw; _entries[which]._roll = r; _entries[which]._dpitch = dp; _entries[which]._dyaw = dyaw; _entries[which]._droll = dr; } }
void Costume::loadGRIM(TextSplitter &ts, Costume *prevCost) { ts.expectString("costume v0.1"); ts.expectString("section tags"); int numTags; ts.scanString(" numtags %d", 1, &numTags); tag32 *tags = new tag32[numTags]; for (int i = 0; i < numTags; i++) { unsigned char t[4]; int which; // Obtain a tag ID from the file ts.scanString(" %d '%c%c%c%c'", 5, &which, &t[0], &t[1], &t[2], &t[3]); // Force characters to upper case for (int j = 0; j < 4; j++) t[j] = toupper(t[j]); memcpy(&tags[which], t, sizeof(tag32)); } ts.expectString("section components"); ts.scanString(" numcomponents %d", 1, &_numComponents); _components = new Component *[_numComponents]; for (int i = 0; i < _numComponents; i++) { int id, tagID, hash, parentID, namePos; const char *line = ts.getCurrentLine(); Component *prevComponent = NULL; if (sscanf(line, " %d %d %d %d %n", &id, &tagID, &hash, &parentID, &namePos) < 4) error("Bad component specification line: `%s'", line); ts.nextLine(); // A Parent ID of "-1" indicates that the component should // use the properties of the previous costume as a base if (parentID == -1) { if (prevCost) { MainModelComponent *mmc; // However, only the first item can actually share the // node hierarchy with the previous costume, so flag // that component so it knows what to do if (i == 0) parentID = -2; prevComponent = prevCost->_components[0]; mmc = dynamic_cast<MainModelComponent *>(prevComponent); // Make sure that the component is valid if (!mmc) prevComponent = NULL; } else if (id > 0) { // Use the MainModelComponent of this costume as prevComponent, // so that the component can use its colormap. prevComponent = _components[0]; } } // Actually load the appropriate component _components[id] = loadComponent(tags[tagID], parentID < 0 ? NULL : _components[parentID], parentID, line + namePos, prevComponent); _components[id]->setCostume(this); } delete[] tags; for (int i = 0; i < _numComponents; i++) if (_components[i]) { _components[i]->init(); } ts.expectString("section chores"); ts.scanString(" numchores %d", 1, &_numChores); _chores = new Chore[_numChores]; for (int i = 0; i < _numChores; i++) { int id, length, tracks; char name[32]; ts.scanString(" %d %d %d %32s", 4, &id, &length, &tracks, name); _chores[id]._length = length; _chores[id]._numTracks = tracks; memcpy(_chores[id]._name, name, 32); Debug::debug(Debug::Chores, "Loaded chore: %s\n", name); } ts.expectString("section keys"); for (int i = 0; i < _numChores; i++) { int which; ts.scanString("chore %d", 1, &which); _chores[which].load(i, this, ts); } }
void Set::loadText(TextSplitter &ts){ char tempBuf[256]; ts.expectString("section: colormaps"); ts.scanString(" numcolormaps %d", 1, &_numCmaps); _cmaps = new ObjectPtr<CMap>[_numCmaps]; char cmap_name[256]; for (int i = 0; i < _numCmaps; i++) { ts.scanString(" colormap %256s", 1, cmap_name); _cmaps[i] = g_resourceloader->getColormap(cmap_name); } if (ts.checkString("section: objectstates") || ts.checkString("sections: object_states")) { ts.nextLine(); ts.scanString(" tot_objects %d", 1, &_numObjectStates); char object_name[256]; for (int l = 0; l < _numObjectStates; l++) { ts.scanString(" object %256s", 1, object_name); } } else { _numObjectStates = 0; } ts.expectString("section: setups"); ts.scanString(" numsetups %d", 1, &_numSetups); _setups = new Setup[_numSetups]; for (int i = 0; i < _numSetups; i++) _setups[i].load(ts); _currSetup = _setups; _lightsConfigured = false; _numSectors = -1; _numLights = -1; _lights = NULL; _sectors = NULL; _minVolume = 0; _maxVolume = 0; // Lights are optional if (ts.isEof()) return; ts.expectString("section: lights"); ts.scanString(" numlights %d", 1, &_numLights); _lights = new Light[_numLights]; for (int i = 0; i < _numLights; i++) _lights[i].load(ts); // Calculate the number of sectors ts.expectString("section: sectors"); if (ts.isEof()) // Sectors are optional, but section: doesn't seem to be return; int sectorStart = ts.getLineNumber(); _numSectors = 0; // Find the number of sectors (while the sectors usually // count down from the highest number there are a few // cases where they count up, see hh.set for example) while (!ts.isEof()) { ts.scanString(" %s", 1, tempBuf); if (!scumm_stricmp(tempBuf, "sector")) _numSectors++; } // Allocate and fill an array of sector info _sectors = new Sector*[_numSectors]; ts.setLineNumber(sectorStart); for (int i = 0; i < _numSectors; i++) { // Use the ids as index for the sector in the array. // This way when looping they are checked from the id 0 sto the last, // which seems important for sets with overlapping camera sectors, like ga.set. Sector *s = new Sector(); s->load(ts); _sectors[s->getSectorId()] = s; } }