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 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; }
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 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; }
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; } }