Ejemplo n.º 1
0
// Will try to set amiga palette by using "spal" file. If not found, we return false
bool GfxPalette::setAmiga() {
	Common::File file;

	if (file.open("spal")) {
		for (int curColor = 0; curColor < 32; curColor++) {
			byte byte1 = file.readByte();
			byte byte2 = file.readByte();

			if (file.eos())
				error("Amiga palette file ends prematurely");

			_sysPalette.colors[curColor].used = 1;
			_sysPalette.colors[curColor].r = (byte1 & 0x0F) * 0x11;
			_sysPalette.colors[curColor].g = ((byte2 & 0xF0) >> 4) * 0x11;
			_sysPalette.colors[curColor].b = (byte2 & 0x0F) * 0x11;

			if (_totalScreenColors == 64) {
				// Set the associated color from the Amiga halfbrite colors
				_sysPalette.colors[curColor + 32].used = 1;
				_sysPalette.colors[curColor + 32].r = _sysPalette.colors[curColor].r >> 1;
				_sysPalette.colors[curColor + 32].g = _sysPalette.colors[curColor].g >> 1;
				_sysPalette.colors[curColor + 32].b = _sysPalette.colors[curColor].b >> 1;
			}
		}

		// Directly set the palette, because setOnScreen() wont do a thing for amiga
		copySysPaletteToScreen();
		return true;
	}
Ejemplo n.º 2
0
void ScriptManager::parseScrFile(const Common::String &fileName, bool isGlobal) {
	Common::File file;
	if (!file.open(fileName)) {
		warning("Script file not found: %s", fileName.c_str());
		return;
	}

	while(!file.eos()) {
		Common::String line = file.readLine();
		if (file.err()) {
			warning("Error parsing scr file: %s", fileName.c_str());
			return;
		}

		trimCommentsAndWhiteSpace(&line);
		if (line.empty())
			continue;

		if (line.matchString("puzzle:*", true)) {
			Puzzle *puzzle = new Puzzle();
			sscanf(line.c_str(),"puzzle:%u",&(puzzle->key));

			parsePuzzle(puzzle, file);
			if (isGlobal) {
				_globalPuzzles.push_back(puzzle);
			} else {
				_activePuzzles.push_back(puzzle);
			}
		} else if (line.matchString("control:*", true)) {
			parseControl(line, file);
		}
	}
}
Ejemplo n.º 3
0
	bool readBit8u(MT32Emu::Bit8u *in) {
		byte b = _in.readByte();
		if (_in.eos())
			return false;
		*in = b;
		return true;
	}
Ejemplo n.º 4
0
//Gets AGIPAL Data
void GfxMgr::setAGIPal(int p0) {
	//If 0 from savefile, do not use
	if (p0 == 0)
		return;

	char filename[15];
	sprintf(filename, "pal.%d", p0);

	Common::File agipal;
	if (!agipal.open(filename)) {
		warning("Couldn't open AGIPAL palette file '%s'. Not changing palette", filename);
		return; // Needed at least by Naturette 3 which uses AGIPAL but provides no palette files
	}

	//Chunk0 holds colors 0-7
	agipal.read(&_agipalPalette[0], 24);

	//Chunk1 is the same as the chunk0

	//Chunk2 chunk holds colors 8-15
	agipal.seek(24, SEEK_CUR);
	agipal.read(&_agipalPalette[24], 24);

	//Chunk3 is the same as the chunk2

	//Chunks4-7 are duplicates of chunks0-3

	if (agipal.eos() || agipal.err()) {
		warning("Couldn't read AGIPAL palette from '%s'. Not changing palette", filename);
		return;
	}

	// Use only the lowest 6 bits of each color component (Red, Green and Blue)
	// because VGA used only 6 bits per color component (i.e. VGA had 18-bit colors).
	// This should now be identical to the original AGIPAL-hack's behavior.
	bool validVgaPalette = true;
	for (int i = 0; i < 16 * 3; i++) {
		if (_agipalPalette[i] >= (1 << 6)) {
			_agipalPalette[i] &= 0x3F; // Leave only the lowest 6 bits of each color component
			validVgaPalette = false;
		}
	}

	if (!validVgaPalette)
		warning("Invalid AGIPAL palette (Over 6 bits per color component) in '%s'. Using only the lowest 6 bits per color component", filename);

	_agipalFileNum = p0;

	initPalette(_agipalPalette);
	gfxSetPalette();

	debug(1, "Using AGIPAL palette from '%s'", filename);
}
Ejemplo n.º 5
0
int AgiEngine::loadWords(const char *fname) {
	Common::File fp;

	if (!fp.open(fname)) {
		warning("loadWords: can't open %s", fname);
		return errOK; // err_BadFileOpen
	}
	debug(0, "Loading dictionary: %s", fname);

	// Loop through alphabet, as words in the dictionary file are sorted by
	// first character
	for (int i = 0; i < 26; i++) {
		fp.seek(i * 2, SEEK_SET);
		int offset = fp.readUint16BE();
		if (offset == 0)
			continue;
		fp.seek(offset, SEEK_SET);
		int k = fp.readByte();
		while (!fp.eos() && !fp.err()) {
			// Read next word
			char c, str[64];
			do {
				c = fp.readByte();
				str[k++] = (c ^ 0x7F) & 0x7F;
			} while (!(c & 0x80) && k < (int)sizeof(str) - 1);
			str[k] = 0;

			// WORKAROUND:
			// The SQ0 fan game stores words starting with numbers (like '7up')
			// in its dictionary under the 'a' entry. We skip these.
			// See bug #3615061
			if (str[0] == 'a' + i) {
				// And store it in our internal dictionary
				AgiWord *w = new AgiWord;
				w->word = myStrndup(str, k);
				w->id = fp.readUint16BE();
				_game.words[i].push_back(w);
			}

			k = fp.readByte();

			// Are there more words with an already known prefix?
			// WORKAROUND: We only break after already seeing words with the
			// right prefix, for the SQ0 words starting with digits filed under
			// 'a'. See above comment and bug #3615061.
			if (k == 0 && str[0] >= 'a' + i)
				break;
		}
	}

	return errOK;
}
Ejemplo n.º 6
0
void ResMan::resOpen(uint32 id) {  // load resource ID into memory
	MemHandle *memHandle = resHandle(id);
	if (!memHandle)
		return;
	if (memHandle->cond == MEM_FREED) { // memory has been freed
		uint32 size = resLength(id);
		_memMan->alloc(memHandle, size);
		Common::File *clusFile = resFile(id);
		assert(clusFile);
		clusFile->seek(resOffset(id));
		clusFile->read(memHandle->data, size);
		if (clusFile->err() || clusFile->eos()) {
			error("Can't read %d bytes from offset %d from cluster file %s\nResource ID: %d (%08X)", size, resOffset(id), _prj.clu[(id >> 24) - 1].label, id, id);
		}
Ejemplo n.º 7
0
void StringManager::loadStrFile(const Common::String &fileName) {
	Common::File file;
	if (!_engine->getSearchManager()->openFile(file, fileName)) {
		error("%s does not exist. String parsing failed", fileName.c_str());
	}

	uint lineNumber = 0;
	while (!file.eos()) {
		_lines[lineNumber] = readWideLine(file);

		lineNumber++;
		assert(lineNumber <= NUM_TEXT_LINES);
	}
}
Ejemplo n.º 8
0
/**
 * Allocates enough RAM to hold the global Glitter variables.
 */
void RegisterGlobals(int num) {
	if (pGlobals == NULL) {
		numGlobals = num;

		hMasterScript = !TinselV2 ? 0 :
			READ_LE_UINT32(FindChunk(MASTER_SCNHANDLE, CHUNK_MASTER_SCRIPT));

		// Allocate RAM for pGlobals and make sure it's allocated
		pGlobals = (int32 *)calloc(numGlobals, sizeof(int32));
		if (pGlobals == NULL) {
			error("Cannot allocate memory for global data");
		}

		// Allocate RAM for interpret contexts and make sure it's allocated
		icList = (INT_CONTEXT *)calloc(NUM_INTERPRET, sizeof(INT_CONTEXT));
		if (icList == NULL) {
			error("Cannot allocate memory for interpret contexts");
		}
		g_scheduler->setResourceCallback(FreeInterpretContextPr);
	} else {
		// Check size is still the same
		assert(numGlobals == num);

		memset(pGlobals, 0, numGlobals * sizeof(int32));
		memset(icList, 0, NUM_INTERPRET * sizeof(INT_CONTEXT));
	}

	if (TinselV2) {
		// read initial values
		CdCD(nullContext);

		Common::File f;
		if (!f.open(GLOBALS_FILENAME))
			error(CANNOT_FIND_FILE, GLOBALS_FILENAME);

		int32 length = f.readSint32LE();
		if (length != num)
			error(FILE_IS_CORRUPT, GLOBALS_FILENAME);

		for (int i = 0; i < length; ++i)
			pGlobals[i] = f.readSint32LE();

		if (f.eos() || f.err())
			error(FILE_IS_CORRUPT, GLOBALS_FILENAME);

		f.close();
	}
}
Ejemplo n.º 9
0
void TitlerControl::readStringsFile(const Common::String &fileName) {
	Common::File file;
	if (!_engine->getSearchManager()->openFile(file, fileName)) {
		warning("String_resource_file %s could could be opened", fileName.c_str());
		return;
	}

	_strings.clear();

	while (!file.eos()) {

		Common::String line = readWideLine(file);
		_strings.push_back(line);
	}
	file.close();
}
Ejemplo n.º 10
0
// AUDIOnnn.MAP contains 10-byte entries:
// Early format:
// w 5 bits resource type and 11 bits resource number
// dw 7 bits volume number and 25 bits offset
// dw size
// Later format:
// w nEntry
// dw offset+volume (as in resource.map)
// dw size
// ending with 10 0xFFs
int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) {
	Common::File file;

	if (!file.open(map->getLocationName()))
		return SCI_ERROR_RESMAP_NOT_FOUND;

	bool oldFormat = (file.readUint16LE() >> 11) == kResourceTypeAudio;
	file.seek(0);

	for (;;) {
		uint16 n = file.readUint16LE();
		uint32 offset = file.readUint32LE();
		uint32 size = file.readUint32LE();

		if (file.eos() || file.err()) {
			warning("Error while reading %s", map->getLocationName().c_str());
			return SCI_ERROR_RESMAP_NOT_FOUND;
		}

		if (n == 0xffff)
			break;

		byte volume_nr;

		if (oldFormat) {
			n &= 0x07ff; // Mask out resource type
			volume_nr = offset >> 25; // most significant 7 bits
			offset &= 0x01ffffff; // least significant 25 bits
		} else {
			volume_nr = offset >> 28; // most significant 4 bits
			offset &= 0x0fffffff; // least significant 28 bits
		}

		ResourceSource *src = findVolume(map, volume_nr);

		if (src) {
			const ResourceId resId(kResourceTypeAudio, n);

			if (unload)
				removeAudioResource(resId);
			else
				addResource(resId, src, offset, size, map->getLocationName());
		} else {
			warning("Failed to find audio volume %i", volume_nr);
			return SCI_ERROR_NO_RESOURCE_FILES_FOUND;
		}
	}
Ejemplo n.º 11
0
TLib::TLib(MemoryManager &memManager, const Common::String &filename) :
		_memoryManager(memManager) {

	// If the resource strings list isn't yet loaded, load them
	if (_resStrings.size() == 0) {
		Common::File f;
		if (f.open("tsage.cfg")) {
			while (!f.eos()) {
				_resStrings.push_back(f.readLine());
			}
			f.close();
		}
	}

	if (!_file.open(filename))
		error("Missing file %s", filename.c_str());

	loadIndex();
}
Ejemplo n.º 12
0
// Will try to set amiga palette by using "spal" file. If not found, we return false
bool GfxPalette::setAmiga() {
	Common::File file;

	if (file.open("spal")) {
		for (int curColor = 0; curColor < 32; curColor++) {
			byte byte1 = file.readByte();
			byte byte2 = file.readByte();

			if (file.eos())
				error("Amiga palette file ends prematurely");

			_sysPalette.colors[curColor].used = 1;
			_sysPalette.colors[curColor].r = (byte1 & 0x0F) * 0x11;
			_sysPalette.colors[curColor].g = ((byte2 & 0xF0) >> 4) * 0x11;
			_sysPalette.colors[curColor].b = (byte2 & 0x0F) * 0x11;
		}

		// Directly set the palette, because setOnScreen() wont do a thing for amiga
		copySysPaletteToScreen();
		return true;
	}

	return false;
}
Ejemplo n.º 13
0
bool PCMMusicPlayer::getNextChunk() {
	MusicSegment *musicSegments;
	int32 *script, *scriptBuffer;
	int id;
	int snum;
	uint32 sampleOffset, sampleLength, sampleCLength;
	Common::File file;
	byte *buffer;
	Common::SeekableReadStream *sampleStream;

	switch (_state) {
	case S_NEW:
	case S_NEXT:
		_forcePlay = false;

		script = scriptBuffer = (int32 *)LockMem(_hScript);

		// Set parameters for this chunk of music
		id = _scriptNum;
		while (id--)
			script = scriptBuffer + READ_32(script);
		snum = FROM_32(script[_scriptIndex++]);

		if (snum == MUSIC_JUMP || snum == MUSIC_END) {
			// Let usual code sort it out!
			_scriptIndex--;    // Undo increment
			_forcePlay = true; // Force a Play
			_state = S_END1;   // 'Goto' S_END1
			break;
		}

		musicSegments = (MusicSegment *) LockMem(_hSegment);

		assert(FROM_32(musicSegments[snum].numChannels) == 1);
		assert(FROM_32(musicSegments[snum].bitsPerSample) == 16);

		sampleOffset = FROM_32(musicSegments[snum].sampleOffset);
		sampleLength = FROM_32(musicSegments[snum].sampleLength);
		sampleCLength = (((sampleLength + 63) & ~63)*33)/64;

		if (!file.open(_filename))
			error(CANNOT_FIND_FILE, _filename.c_str());

		file.seek(sampleOffset);
		if (file.eos() || file.err() || (uint32)file.pos() != sampleOffset)
			error(FILE_IS_CORRUPT, _filename.c_str());

		buffer = (byte *) malloc(sampleCLength);
		assert(buffer);

		// read all of the sample
		if (file.read(buffer, sampleCLength) != sampleCLength)
			error(FILE_IS_CORRUPT, _filename.c_str());

		debugC(DEBUG_DETAILED, kTinselDebugMusic, "Creating ADPCM music chunk with size %d, "
				"offset %d (script %d.%d)", sampleCLength, sampleOffset,
				_scriptNum, _scriptIndex - 1);

		sampleStream = new Common::MemoryReadStream(buffer, sampleCLength, DisposeAfterUse::YES);

		delete _curChunk;
		_curChunk = new Tinsel8_ADPCMStream(sampleStream, DisposeAfterUse::YES, sampleCLength,
				22050, 1, 32);

		_state = S_MID;
		return true;

	case S_END1:
		debugC(DEBUG_DETAILED, kTinselDebugMusic, "Music reached state S_END1 (script %d.%d)",
				_scriptNum, _scriptIndex);

		script = scriptBuffer = (int32 *) LockMem(_hScript);

		id = _scriptNum;
		while (id--)
			script = scriptBuffer + READ_32(script);
		snum = FROM_32(script[_scriptIndex]);

		if (snum == MUSIC_END) {
			_state = S_END2;
		} else {
			if (snum == MUSIC_JUMP)
				_scriptIndex = FROM_32(script[_scriptIndex+1]);

			_state = _forcePlay ? S_NEW : S_NEXT;
			_forcePlay = false;
		}

		return true;

	case S_END2:
		debugC(DEBUG_DETAILED, kTinselDebugMusic, "Music reached state S_END2 (script %d.%d)",
				_scriptNum, _scriptIndex);

		_silenceSamples = 11025; // Half a second of silence
		return true;

	case S_END3:
		debugC(DEBUG_DETAILED, kTinselDebugMusic, "Music reached state S_END3 (script %d.%d)",
				_scriptNum, _scriptIndex);

		stop();
		_state = S_IDLE;
		return false;

	case S_IDLE:
		return false;

	default:
		break;
	}

	return true;
}
Ejemplo n.º 14
0
	bool isEOF() {
		return _in.isOpen() && _in.eos();
	}
Ejemplo n.º 15
0
bool fileToStack(const Common::String &filename, StackHandler *sH) {

	Variable stringVar;
	stringVar.varType = SVT_NULL;
	Common::String checker = saveEncoding ? "[Custom data (encoded)]\r\n" : "[Custom data (ASCII)]\n";

	Common::File fd;

	if (!fd.open(filename)) {
#if 0
		char currentDir[1000];
		if (!getcwd(currentDir, 998)) {
			debugOut("Can't get current directory.\n");
		}

		if (chdir(gamePath)) {
			debugOut("Error: Failed changing to directory %s\n", gamePath);
		}

		if (chdir(currentDir)) {
			debugOut("Error: Failed changing to directory %s\n", currentDir);
		}

		if (!fd.open(filename)) {
			return fatal("No such file", filename);
		}
#endif
		return fatal("No such file", filename); //TODO: false value
	}

	encode1 = (byte)saveEncoding & 255;
	encode2 = (byte)(saveEncoding >> 8);

	for (uint i = 0; i < checker.size(); ++i) {
		if (fd.readByte() != checker[i]) {
			fd.close();
			return fatal(LOAD_ERROR "This isn't a SLUDGE custom data file:", filename);
		}
	}

	if (saveEncoding) {
		checker = readStringEncoded(&fd);
		if (checker == UTF8_CHECKER) {
			fd.close();
			return fatal(
			LOAD_ERROR "The current file encoding setting does not match the encoding setting used when this file was created:", filename);
		}
	}

	for (;;) {
		if (saveEncoding) {
			char i = fd.readByte() ^ encode1;

			if (fd.eos())
				break;
			switch (i) {
				case 0: {
					Common::String g = readStringEncoded(&fd);
					makeTextVar(stringVar, g);
				}
					break;

				case 1:
					setVariable(stringVar, SVT_INT, fd.readUint32LE());
					break;

				case 2:
					setVariable(stringVar, SVT_INT, fd.readByte());
					break;

				default:
					fatal(LOAD_ERROR "Corrupt custom data file:", filename);
					fd.close();
					return false;
			}
		} else {
			char *line = readTextPlain(&fd);
			if (!line)
				break;
			makeTextVar(stringVar, line);
		}

		if (sH->first == NULL) {
			// Adds to the TOP of the array... oops!
			if (!addVarToStackQuick(stringVar, sH->first))
				return false;
			sH->last = sH->first;
		} else {
			// Adds to the END of the array... much better
			if (!addVarToStackQuick(stringVar, sH->last->next))
				return false;
			sH->last = sH->last->next;
		}
	}
	fd.close();

	return true;
}
Ejemplo n.º 16
0
bool Sound::startSpeech(uint16 roomNo, uint16 localNo) {
	if (_cowHeader == NULL) {
		warning("Sound::startSpeech: COW file isn't open");
		return false;
	}

	uint32 locIndex = 0xFFFFFFFF;
	uint32 sampleSize = 0;
	uint32 index = 0;

	if (_cowMode == CowPSX) {
		Common::File file;
		uint16 i;

		if (!file.open("speech.lis")) {
			warning ("Could not open speech.lis");
			return false;
		}

		for (i = 0; !file.eos() && !file.err(); i++)
			if (file.readUint16LE() == roomNo) {
				locIndex = i;
				break;
			}
		file.close();

		if (locIndex == 0xFFFFFFFF) {
			warning ("Could not find room %d in speech.lis", roomNo);
			return false;
		}

		if (!file.open("speech.inf")) {
			warning ("Could not open speech.inf");
			return false;
		}

		uint16 numRooms = file.readUint16LE(); // Read number of rooms referenced in this file

		file.seek(locIndex * 4 + 2); // 4 bytes per room, skip first 2 bytes

		uint16 numLines = file.readUint16LE();
		uint16 roomOffset = file.readUint16LE();

		file.seek(2 + numRooms * 4 + roomOffset * 2); // The offset is in terms of uint16's, so multiply by 2. Skip the room indexes too.

		locIndex = 0xFFFFFFFF;

		for (i = 0; i < numLines; i++)
			if (file.readUint16LE() == localNo) {
				locIndex = i;
				break;
			}

		if (locIndex == 0xFFFFFFFF) {
			warning ("Could not find local number %d in room %d in speech.inf", roomNo, localNo);
			return false;
		}

		file.close();

		index = _cowHeader[(roomOffset + locIndex) * 2];
		sampleSize = _cowHeader[(roomOffset + locIndex) * 2 + 1];
	} else {
		locIndex = _cowHeader[roomNo] >> 2;
		sampleSize = _cowHeader[locIndex + (localNo * 2)];
		index = _cowHeader[locIndex + (localNo * 2) - 1];
	}

	debug(6, "startSpeech(%d, %d): locIndex %d, sampleSize %d, index %d", roomNo, localNo, locIndex, sampleSize, index);

	Audio::AudioStream *stream = 0;

	if (sampleSize) {
		uint8 speechVol = (_speechVolR + _speechVolL) / 2;
		int8 speechPan = (_speechVolR - _speechVolL) / 2;
		if ((_cowMode == CowWave) || (_cowMode == CowDemo)) {
			uint32 size;
			int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size);
			if (data) {
				stream = Audio::makeRawStream((byte *)data, size, 11025, SPEECH_FLAGS);
				_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream, SOUND_SPEECH_ID, speechVol, speechPan);
			}
		} else if (_cowMode == CowPSX && sampleSize != 0xffffffff) {
			_cowFile.seek(index * 2048);
			Common::SeekableReadStream *tmp = _cowFile.readStream(sampleSize);
			assert(tmp);
			stream = Audio::makeVagStream(tmp);
			_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream, SOUND_SPEECH_ID, speechVol, speechPan);
			// with compressed audio, we can't calculate the wave volume.
			// so default to talking.
			for (int cnt = 0; cnt < 480; cnt++)
				_waveVolume[cnt] = true;
			_waveVolPos = 0;
		}
#ifdef USE_FLAC
		else if (_cowMode == CowFLAC) {
			_cowFile.seek(index);
			Common::SeekableReadStream *tmp = _cowFile.readStream(sampleSize);
			assert(tmp);
			stream = Audio::makeFLACStream(tmp, DisposeAfterUse::YES);
			_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream, SOUND_SPEECH_ID, speechVol, speechPan);
			// with compressed audio, we can't calculate the wave volume.
			// so default to talking.
			for (int cnt = 0; cnt < 480; cnt++)
				_waveVolume[cnt] = true;
			_waveVolPos = 0;
		}
#endif
#ifdef USE_VORBIS
		else if (_cowMode == CowVorbis) {
			_cowFile.seek(index);
			Common::SeekableReadStream *tmp = _cowFile.readStream(sampleSize);
			assert(tmp);
			stream = Audio::makeVorbisStream(tmp, DisposeAfterUse::YES);
			_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream, SOUND_SPEECH_ID, speechVol, speechPan);
			// with compressed audio, we can't calculate the wave volume.
			// so default to talking.
			for (int cnt = 0; cnt < 480; cnt++)
				_waveVolume[cnt] = true;
			_waveVolPos = 0;
		}
#endif
#ifdef USE_MAD
		else if (_cowMode == CowMP3) {
			_cowFile.seek(index);
			Common::SeekableReadStream *tmp = _cowFile.readStream(sampleSize);
			assert(tmp);
			stream = Audio::makeMP3Stream(tmp, DisposeAfterUse::YES);
			_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream, SOUND_SPEECH_ID, speechVol, speechPan);
			// with compressed audio, we can't calculate the wave volume.
			// so default to talking.
			for (int cnt = 0; cnt < 480; cnt++)
				_waveVolume[cnt] = true;
			_waveVolPos = 0;
		}
#endif
		return true;
	} else
		return false;
}
Ejemplo n.º 17
0
void LeverControl::parseLevFile(const Common::String &fileName) {
	Common::File file;
	if (!file.open(fileName)) {
		warning("LEV file %s could could be opened", fileName.c_str());
		return;
	}

	Common::String line = file.readLine();

	while (!file.eos()) {
		if (line.matchString("*animation_id*", true)) {
			// Not used
		} else if (line.matchString("*filename*", true)) {
			char fileNameBuffer[25];
			sscanf(line.c_str(), "%*[^:]:%25[^~]~", fileNameBuffer);

			Common::String animationFileName(fileNameBuffer);

			if (animationFileName.hasSuffix(".avi")) {
				_animation.avi = new ZorkAVIDecoder();
				_animation.avi->loadFile(animationFileName);
				_fileType = AVI;
			} else if (animationFileName.hasSuffix(".rlf")) {
				_animation.rlf = new RlfAnimation(animationFileName, false);
				_fileType = RLF;
			}
		} else if (line.matchString("*skipcolor*", true)) {
			// Not used
		} else if (line.matchString("*anim_coords*", true)) {
			int left, top, right, bottom;
			sscanf(line.c_str(), "%*[^:]:%d %d %d %d~", &left, &top, &right, &bottom);

			_animationCoords.left = left;
			_animationCoords.top = top;
			_animationCoords.right = right;
			_animationCoords.bottom = bottom;
		} else if (line.matchString("*mirrored*", true)) {
			uint mirrored;
			sscanf(line.c_str(), "%*[^:]:%u~", &mirrored);

			_mirrored = mirrored == 0 ? false : true;
		} else if (line.matchString("*frames*", true)) {
			sscanf(line.c_str(), "%*[^:]:%u~", &_frameCount);

			_frameInfo = new FrameInfo[_frameCount];
		} else if (line.matchString("*elsewhere*", true)) {
			// Not used
		} else if (line.matchString("*out_of_control*", true)) {
			// Not used
		} else if (line.matchString("*start_pos*", true)) {
			sscanf(line.c_str(), "%*[^:]:%u~", &_startFrame);
			_currentFrame = _startFrame;
		} else if (line.matchString("*hotspot_deltas*", true)) {
			uint x;
			uint y;
			sscanf(line.c_str(), "%*[^:]:%u %u~", &x, &y);

			_hotspotDelta.x = x;
			_hotspotDelta.y = y;
		} else {
			uint frameNumber;
			uint x, y;

			if (sscanf(line.c_str(), "%u:%u %u", &frameNumber, &x, &y) == 3) {
				_frameInfo[frameNumber].hotspot.left = x;
				_frameInfo[frameNumber].hotspot.top = y;
				_frameInfo[frameNumber].hotspot.right = x + _hotspotDelta.x;
				_frameInfo[frameNumber].hotspot.bottom = y + _hotspotDelta.y;
			}

			Common::StringTokenizer tokenizer(line, " ^=()");
			tokenizer.nextToken();
			tokenizer.nextToken();

			Common::String token = tokenizer.nextToken();
			while (!tokenizer.empty()) {
				if (token == "D") {
					token = tokenizer.nextToken();

					uint angle;
					uint toFrame;
					sscanf(token.c_str(), "%u,%u", &toFrame, &angle);

					_frameInfo[frameNumber].directions.push_back(Direction(angle, toFrame));
				} else if (token.hasPrefix("P")) {
					// Format: P(<from> to <to>)
					tokenizer.nextToken();
					tokenizer.nextToken();
					token = tokenizer.nextToken();
					uint to = atoi(token.c_str());

					_frameInfo[frameNumber].returnRoute.push_back(to);
				}

				token = tokenizer.nextToken();
			}
		}

		line = file.readLine();
	}
}
Ejemplo n.º 18
0
void LeverControl::parseLevFile(const Common::String &fileName) {
	Common::File file;
	if (!_engine->getSearchManager()->openFile(file, fileName)) {
		warning("LEV file %s could could be opened", fileName.c_str());
		return;
	}

	Common::String line;
	Common::String param;
	Common::String values;

	while (!file.eos()) {
		line = file.readLine();
		getLevParams(line, param, values);

		if (param.matchString("animation_id", true)) {
			// Not used
		} else if (param.matchString("filename", true)) {
			_animation = _engine->loadAnimation(values);
		} else if (param.matchString("skipcolor", true)) {
			// Not used
		} else if (param.matchString("anim_coords", true)) {
			int left, top, right, bottom;
			sscanf(values.c_str(), "%d %d %d %d", &left, &top, &right, &bottom);

			_animationCoords.left = left;
			_animationCoords.top = top;
			_animationCoords.right = right;
			_animationCoords.bottom = bottom;
		} else if (param.matchString("mirrored", true)) {
			uint mirrored;
			sscanf(values.c_str(), "%u", &mirrored);

			_mirrored = mirrored == 0 ? false : true;
		} else if (param.matchString("frames", true)) {
			sscanf(values.c_str(), "%u", &_frameCount);

			_frameInfo = new FrameInfo[_frameCount];
		} else if (param.matchString("elsewhere", true)) {
			// Not used
		} else if (param.matchString("out_of_control", true)) {
			// Not used
		} else if (param.matchString("start_pos", true)) {
			sscanf(values.c_str(), "%u", &_startFrame);
			_currentFrame = _startFrame;
		} else if (param.matchString("hotspot_deltas", true)) {
			uint x;
			uint y;
			sscanf(values.c_str(), "%u %u", &x, &y);

			_hotspotDelta.x = x;
			_hotspotDelta.y = y;
		} else if (param.matchString("venus_id", true)) {
			_venusId = atoi(values.c_str());
		} else {
			uint frameNumber;
			uint x, y;

			line.toLowercase();

			if (sscanf(line.c_str(), "%u:%u %u", &frameNumber, &x, &y) == 3) {
				_frameInfo[frameNumber].hotspot.left = x;
				_frameInfo[frameNumber].hotspot.top = y;
				_frameInfo[frameNumber].hotspot.right = x + _hotspotDelta.x;
				_frameInfo[frameNumber].hotspot.bottom = y + _hotspotDelta.y;
			}

			Common::StringTokenizer tokenizer(line, " ^=()~");
			tokenizer.nextToken();
			tokenizer.nextToken();

			Common::String token = tokenizer.nextToken();
			while (!tokenizer.empty()) {
				if (token == "d") {
					token = tokenizer.nextToken();

					uint angle;
					uint toFrame;
					sscanf(token.c_str(), "%u,%u", &toFrame, &angle);

					_frameInfo[frameNumber].directions.push_back(Direction(angle, toFrame));
				} else if (token.hasPrefix("p")) {
					// Format: P(<from> to <to>)
					tokenizer.nextToken();
					tokenizer.nextToken();
					token = tokenizer.nextToken();
					uint to = atoi(token.c_str());

					_frameInfo[frameNumber].returnRoute.push_back(to);
				}

				token = tokenizer.nextToken();
			}
		}

		// Don't read lines in this place because last will not be parsed.
	}
}
Ejemplo n.º 19
0
Common::Error GagEngine::StateScript()
{
	Common::Error status(Common::kNoError);

	Common::File file;
	if(file.open(_script, *_archive))
	{
		// simple script parsing: skim through, find section and execute commands
		ParserState parse_state(PS_SECTION_SEARCH);
		Common::String buffer;
		Common::String command_name;

		bool done(false);
		while(!file.eos())
		{
			// add space for multiline command support
			Common::String line = file.readLine() + ' ';
			if(file.err())
			{
				status = Common::Error(Common::kReadingFailed, _script + ", readLine()");
				break;
			}

			bool skip_line(false);
			for(Common::String::const_iterator it = line.begin(); it != line.end(); ++it)
			{
				switch(parse_state)
				{
				case PS_SECTION_SEARCH:
					// section
					if(*it == '[')
					{
						buffer.clear();

						parse_state = PS_SECTION_NAME;
					}
					break;

				case PS_SECTION_NAME:
					// section end
					if(*it == ']')
					{
#ifdef DEBUG_SKIM_SCRIPT
						parse_state = PS_SECTION_BODY;
#else
						if(buffer == _section)
							parse_state = PS_SECTION_BODY;
						else if(buffer == _END_SECTION)
						{
							status = Common::Error(Common::kUnknownError, "[" + _section + "] script section not found");
							skip_line = true;
							done = true;
						}
						else
							parse_state = PS_SECTION_SEARCH;
#endif
					}
					else
						buffer += *it;
					break;

				case PS_SECTION_BODY:
					// section
					if(*it == '[')
					{
#ifdef DEBUG_SKIM_SCRIPT
						buffer.clear();
						parse_state = PS_SECTION_NAME;
#else
						skip_line = true;
						done = true;
#endif
					}
					// comment
					else if(*it == '*')
					{
						skip_line = true;
					}
					//NOTE: invalid syntax
					else if(*it == '-' || *it == '/' || (*it >= 'A' && *it <= 'Z'))
					{
#ifndef DEBUG_SKIM_SCRIPT
						warning("invalid script syntax [file: %s, section: %s, line: \"%s\"], skipped", _script.c_str(), _section.c_str(), line.c_str());
#endif
						skip_line = true;
					}
					// command name
					else if((*it >= 'a' && *it <= 'z'))
					{
						buffer.clear();
						buffer += *it;

						parse_state = PS_COMMAND_NAME;
					}
					break;

				case PS_COMMAND_NAME:
					// command value
					if(*it == '=')
					{
						command_name = buffer;
						buffer.clear();

						parse_state = PS_COMMAND_VALUE;
					}
					else
						buffer += *it;
					break;

				case PS_COMMAND_VALUE:
					// command value end
					if(*it == ';')
					{
						command_name.trim();
						buffer.trim();

#ifndef DEBUG_SKIM_SCRIPT
						debug("%s=%s;", command_name.c_str(), buffer.c_str());
#endif

						Common::HashMap<Common::String, Common::Error (GagEngine::*)(const Common::String &)>::const_iterator f = _commandCallbacks.find(command_name);
						if(f != _commandCallbacks.end())
						{
							status = (this->*f->_value)(buffer);
							if(status.getCode() != Common::kNoError)
							{
								skip_line = true;
								done = true;
							}
						}

						parse_state = PS_SECTION_BODY;
					}
					else
						buffer += *it;
					break;
				}

				if(skip_line)
					break;
			}

			if(done)
				break;
		}
	}
	else
	{
		status = Common::Error(Common::kReadingFailed, _script + ", open()");
	}

	return status;
}
Ejemplo n.º 20
0
/**
 * Plays an animated cutscene.
 * @param id the id of the file
 */
bool MoviePlayer::load(uint32 id) {
	Common::File f;
	Common::String filename;

	if (_decoderType == kVideoDecoderDXA)
		_bgSoundStream = Audio::SeekableAudioStream::openStreamFile(sequenceList[id]);
	else
		_bgSoundStream = NULL;

	if (SwordEngine::_systemVars.showText) {
		filename = Common::String::format("%s.txt", sequenceList[id]);
		if (f.open(filename)) {
			Common::String line;
			int lineNo = 0;
			int lastEnd = -1;

			_movieTexts.clear();
			while (!f.eos() && !f.err()) {
				line = f.readLine();
				lineNo++;
				if (line.empty() || line[0] == '#') {
					continue;
				}

				const char *ptr = line.c_str();

				// TODO: Better error handling
				int startFrame = strtoul(ptr, const_cast<char **>(&ptr), 10);
				int endFrame = strtoul(ptr, const_cast<char **>(&ptr), 10);

				while (*ptr && Common::isSpace(*ptr))
					ptr++;

				if (startFrame > endFrame) {
					warning("%s:%d: startFrame (%d) > endFrame (%d)", filename.c_str(), lineNo, startFrame, endFrame);
					continue;
				}

				if (startFrame <= lastEnd) {
					warning("%s:%d startFrame (%d) <= lastEnd (%d)", filename.c_str(), lineNo, startFrame, lastEnd);
					continue;
				}
				
				int color = 0;
				if (*ptr == '@') {
					++ptr;
					color = strtoul(ptr, const_cast<char **>(&ptr), 10);
					while (*ptr && Common::isSpace(*ptr))
						ptr++;
				} 

				_movieTexts.push_back(MovieText(startFrame, endFrame, ptr, color));
				lastEnd = endFrame;
			}
			f.close();
		}
	}

	switch (_decoderType) {
	case kVideoDecoderDXA:
		filename = Common::String::format("%s.dxa", sequenceList[id]);
		break;
	case kVideoDecoderSMK:
		filename = Common::String::format("%s.smk", sequenceList[id]);
		break;
	case kVideoDecoderPSX:
		filename = Common::String::format("%s.str", (_vm->_systemVars.isDemo) ? sequenceList[id] : sequenceListPSX[id]);

		// Need to switch to true color
		initGraphics(g_system->getWidth(), g_system->getHeight(), true, 0);

		// Need to load here in case it fails in which case we'd need
		// to go back to paletted mode
		if (_decoder->loadFile(filename)) {
			return true;
		} else {
			initGraphics(g_system->getWidth(), g_system->getHeight(), true);
			return false;
		}
		break;
	}

	return _decoder->loadFile(filename.c_str());
}
Ejemplo n.º 21
0
/**
 * Opens and inits all MIDI sequence files.
 */
void OpenMidiFiles() {
	Common::File midiStream;

	// Demo version has no midi file
	// Also, Discworld PSX uses still unsupported psx SEQ format for music...
	if ((_vm->getFeatures() & GF_DEMO) || (TinselVersion == TINSEL_V2) || TinselV1PSX)
		return;

	if (midiBuffer.pDat)
		// already allocated
		return;

	// open MIDI sequence file in binary mode
	if (!midiStream.open(MIDI_FILE))
		error(CANNOT_FIND_FILE, MIDI_FILE);

	// gen length of the largest sequence
	midiBuffer.size = midiStream.readUint32LE();
	if (midiStream.eos() || midiStream.err())
		error(FILE_IS_CORRUPT, MIDI_FILE);

	if (midiBuffer.size) {
		// allocate a buffer big enough for the largest MIDI sequence
		if ((midiBuffer.pDat = (uint8 *)malloc(midiBuffer.size)) != NULL) {
			// clear out the buffer
			memset(midiBuffer.pDat, 0, midiBuffer.size);
//			VMM_lock(midiBuffer.pDat, midiBuffer.size);
		} else {
			//mSeqHandle = NULL;
		}
	}

	// Now scan through the contents of the MIDI file to find the offset
	// of each individual track, in order to create a mapping from MIDI
	// offset to track number, for the enhanced MIDI soundtrack.
	// The first song is always at position 4. The subsequent ones are
	// calculated dynamically.
	uint32 curOffset = 4;
	uint32 curTrack = 0;
	uint32 songLength = 0;

	// Init
	for (int i = 0; i < ARRAYSIZE(midiOffsets); i++)
		midiOffsets[i] = 0;

	while (!midiStream.eos() && !midiStream.err()) {
		if (curOffset + (4 * curTrack) >= (uint32)midiStream.size())
			break;

		assert(curTrack < ARRAYSIZE(midiOffsets));
		midiOffsets[curTrack] = curOffset + (4 * curTrack);
		//debug("%d: %d", curTrack, midiOffsets[curTrack]);

		songLength = midiStream.readUint32LE();
		curOffset += songLength;
		midiStream.skip(songLength);

		curTrack++;
	}

	midiStream.close();
}
Ejemplo n.º 22
0
    void loadKoreanStrings()
    {
        Common::File fp;
        char fname[128];
        
        strcpy(fname, "sub/");
        strcat(fname, _gameID);
        strcat(fname, ".dat");
        
        if(!fp.open(fname)) {
            warning("WARNING: Cannot load Korean V2 subtitle!, %s\n", fname);
            return;
//            strcpy(fname, "");
//            strcat(fname, _gameID);
//            strcat(fname, ".dat");
//                
//            if(!fp.open(fname)) {
//                warning("WARNING: Cannot load Korean V2 subtitle!, %s\n", fname);
//                return;
//            }
        }
        
        int k;
        char *buf = new char[1024];
        int len = 0;
        
        for(k = 0; !fp.eos(); k++) {
            FGETS(buf, 1023, fp);
            //printf("%d: <%s>\n", k+1, buf);
        }
        // 파일의 라인 수를 계산
        _numKLines = k;
        
        // memory size = file size
        k = fp.size();
        fp.seek(0, SEEK_SET);
        
        _KBuffer = new char *[_numKLines];
        //printf("_KBuffer size = %d\n", (int)k);
        _KBuffer[0] = new char[k];
        //printf("_KBuffer[0] = 0x%x\n", (int)_KBuffer[0]);
        
        for(int i = 0; i < _numKLines; i++) {
            FGETS(buf, 1023, fp);
            buf[1023] = 0;
            len = strlen(buf);
            //_KBuffer[i] = new char[strlen(buf) + 1]; //\0
            if (i > 0)
                _KBuffer[i] = _KBuffer[i-1] + strlen(_KBuffer[i-1])+1;
            if (len > 1000)
                warning("_KBuffer[%d]:%lx, len=%d\n", i, (long)_KBuffer[i], len);
            if(strlen(buf)) {
                strcpy(_KBuffer[i], buf);
                char *b = _KBuffer[i];
                if(b[strlen(b) - 1] == '\n' || b[strlen(b) - 1] == 0x0a || b[strlen(b) - 1] == 0x0d)
                    b[strlen(b) - 1] = 0;
                if(b[strlen(b) - 1] == '\n' || b[strlen(b) - 1] == 0x0a || b[strlen(b) - 1] == 0x0d)
                    b[strlen(b) - 1] = 0;
            } else
                _KBuffer[i][0] = 0;
        }
        fp.close();
        
        warning("Korean subtitle file loaded -- total %d lines, %ld bytes\n", _numKLines, _KBuffer[_numKLines-1]-_KBuffer[0]+len);
        
        delete[] buf;
        
        return;
    }
Ejemplo n.º 23
0
/**
 * Plays an animated cutscene.
 * @param id the id of the file
 */
bool MoviePlayer::load(uint32 id) {
	Common::String filename;

	if (SwordEngine::_systemVars.showText) {
		Common::File f;
		filename = Common::String::format("%s.txt", sequenceList[id]);

		if (f.open(filename)) {
			Common::String line;
			int lineNo = 0;
			int lastEnd = -1;

			_movieTexts.clear();
			while (!f.eos() && !f.err()) {
				line = f.readLine();
				lineNo++;
				if (line.empty() || line[0] == '#') {
					continue;
				}

				const char *ptr = line.c_str();

				// TODO: Better error handling
				int startFrame = strtoul(ptr, const_cast<char **>(&ptr), 10);
				int endFrame = strtoul(ptr, const_cast<char **>(&ptr), 10);

				while (*ptr && Common::isSpace(*ptr))
					ptr++;

				if (startFrame > endFrame) {
					warning("%s:%d: startFrame (%d) > endFrame (%d)", filename.c_str(), lineNo, startFrame, endFrame);
					continue;
				}

				if (startFrame <= lastEnd) {
					warning("%s:%d startFrame (%d) <= lastEnd (%d)", filename.c_str(), lineNo, startFrame, lastEnd);
					continue;
				}

				int color = 0;
				if (*ptr == '@') {
					++ptr;
					color = strtoul(ptr, const_cast<char **>(&ptr), 10);
					while (*ptr && Common::isSpace(*ptr))
						ptr++;
				}

				_movieTexts.push_back(MovieText(startFrame, endFrame, ptr, color));
				lastEnd = endFrame;
			}
		}
	}

	switch (_decoderType) {
	case kVideoDecoderDXA:
		filename = Common::String::format("%s.dxa", sequenceList[id]);
		break;
	case kVideoDecoderSMK:
		filename = Common::String::format("%s.smk", sequenceList[id]);
		break;
	case kVideoDecoderPSX:
		filename = Common::String::format("%s.str", (_vm->_systemVars.isDemo) ? sequenceList[id] : sequenceListPSX[id]);
		break;
	case kVideoDecoderMP2:
		filename = Common::String::format("%s.mp2", sequenceList[id]);
		break;
	}

	// Need to switch to true color for PSX/MP2 videos
	if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
		initGraphics(g_system->getWidth(), g_system->getHeight(), true, 0);

	if (!_decoder->loadFile(filename)) {
		// Go back to 8bpp color
		if (_decoderType == kVideoDecoderPSX || _decoderType == kVideoDecoderMP2)
			initGraphics(g_system->getWidth(), g_system->getHeight(), true);

		return false;
	}

	// For DXA/MP2, also add the external sound file
	if (_decoderType == kVideoDecoderDXA || _decoderType == kVideoDecoderMP2)
		_decoder->addStreamFileTrack(sequenceList[id]);

	_decoder->start();
	return true;
}
Ejemplo n.º 24
0
bool BaseAnimationState::init(const char *name) {
#ifdef USE_MPEG2
	char tempFile[512];

	_mpegDecoder = NULL;
	_mpegFile = NULL;

#ifdef BACKEND_8BIT

	uint i, p;

	// Load lookup palettes
	sprintf(tempFile, "%s.pal", name);

	Common::File f;

	if (!f.open(tempFile)) {
		warning("Cutscene: %s palette missing", tempFile);
		return false;
	}

	p = 0;
	while (!f.eos()) {
		_palettes[p].end = f.readUint16LE();
		_palettes[p].cnt = f.readUint16LE();

		for (i = 0; i < _palettes[p].cnt; i++) {
			_palettes[p].pal[4 * i] = f.readByte();
			_palettes[p].pal[4 * i + 1] = f.readByte();
			_palettes[p].pal[4 * i + 2] = f.readByte();
			_palettes[p].pal[4 * i + 3] = 0;
		}
		for (; i < 256; i++) {
			_palettes[p].pal[4 * i] = 0;
			_palettes[p].pal[4 * i + 1] = 0;
			_palettes[p].pal[4 * i + 2] = 0;
			_palettes[p].pal[4 * i + 3] = 0;
		}

		p++;
	}

	f.close();

	_palNum = 0;
	_maxPalNum = p;
	setPalette(_palettes[_palNum].pal);
	_lut = _lut2 = _yuvLookup[0];
	_curPal = -1;
	_cr = 0;
	buildLookup(_palNum, 256);
	_lut2 = _yuvLookup[1];
	_lutCalcNum = (BITDEPTH + _palettes[_palNum].end + 2) / (_palettes[_palNum].end + 2);
#else
	buildLookup();
	_overlay = (OverlayColor *)calloc(_movieScale * _movieWidth * _movieScale * _movieHeight, sizeof(OverlayColor));
	_sys->showOverlay();
#endif

	// Open MPEG2 stream
	_mpegFile = new Common::File();
	sprintf(tempFile, "%s.mp2", name);
	if (!_mpegFile->open(tempFile)) {
		warning("Cutscene: Could not open %s", tempFile);
		return false;
	}

	// Load and configure decoder
	_mpegDecoder = mpeg2_init();
	if (_mpegDecoder == NULL) {
		warning("Cutscene: Could not allocate an MPEG2 decoder");
		return false;
	}

	_mpegInfo = mpeg2_info(_mpegDecoder);
	_frameNum = 0;

	return true;
#else /* USE_MPEG2 */
	return false;
#endif
}
Ejemplo n.º 25
0
/**
 * Loads and draws the chosen page of the help.
 * @remarks Originally called 'getme'
 */
void Help::switchPage(byte which) {
	// Help icons are 80x20.

	_highlightWas = 177; // Forget where the highlight was.

	Common::File file;

	if (!file.open("help.avd"))
		error("AVALANCHE: Help: File not found: help.avd");

	file.seek(which * 2);
	uint16 offset = file.readUint16LE();
	file.seek(offset);

	Common::String title = getLine(file);

	_vm->_graphics->drawFilledRectangle(Common::Rect(0, 0, 640, 200), kColorBlue);
	_vm->_graphics->drawFilledRectangle(Common::Rect(8, 40, 450, 200), kColorWhite);

	byte index = file.readByte();
	_vm->_graphics->helpDrawButton(-177, index);

	// Plot the title:
	_vm->_graphics->drawNormalText(title, _vm->_font, 8, 629 - 8 * title.size(), 26, kColorBlack);
	_vm->_graphics->drawNormalText(title, _vm->_font, 8, 630 - 8 * title.size(), 25, kColorCyan);

	_vm->_graphics->helpDrawBigText("help!", 549, 1, kColorBlack);
	_vm->_graphics->helpDrawBigText("help!", 550, 0, kColorCyan);

	byte y = 0;
	do {
		Common::String line = getLine(file);
		if (!line.empty()) {
			if (line.compareTo(Common::String('!')) == 0)  // End of the help text is signalled with a '!'.
				break;
			if (line[0] == '\\') {
				line.deleteChar(0);
				_vm->_graphics->drawNormalText(line, _vm->_font, 8, 16, 41 + y * 10, kColorRed);
			}
			else
				_vm->_graphics->drawNormalText(line, _vm->_font, 8, 16, 41 + y * 10, kColorBlack);
		}
		y++;
	} while (true);

	// We are now at the end of the text. Next we must read the icons:
	y = 0;
	_buttonNum = 0;
	while (!file.eos()) {
		int trigger = file.readByte();

		if (trigger == 177)
			break;
		switch (trigger) {
		case 254: // Escape
			trigger = 27;
			break;
		case 214: // PageUp
			trigger = 280;
			break;
		case 216: // PageDown
			trigger = 281;
			break;
		default: // A - Z
			// The characters are stored in the file in uppercase, but we need the lowercase versions for KeyCode:
			trigger = tolower(trigger);
			break;
		}

		_buttons[y]._trigger = Common::KeyCode(trigger);
		index = file.readByte();
		if (_buttons[y]._trigger != Common::KEYCODE_INVALID)
			_vm->_graphics->helpDrawButton(13 + (y + 1) * 27, index);
		_buttons[y]._whither = file.readByte(); // This is the position to jump to.

		Common::String text = "";
		switch (_buttons[y]._trigger) {
		case Common::KEYCODE_ESCAPE:
			text = Common::String("Esc");
			break;
		case Common::KEYCODE_PAGEUP:
			text = Common::String(24);
			break;
		case Common::KEYCODE_PAGEDOWN:
			text = Common::String(25);
			break;
		default:
			text = Common::String(toupper(_buttons[y]._trigger));
			break;
		}

		_vm->_graphics->helpDrawBigText(text, 589 - (text.size() * 8), 18 + (y + 1) * 27, kColorBlack);
		_vm->_graphics->helpDrawBigText(text, 590 - (text.size() * 8), 17 + (y + 1) * 27, kColorCyan);

		y++;
		_buttonNum++;
	}

	_vm->_graphics->refreshScreen();

	file.close();
}
Ejemplo n.º 26
0
bool ResourceManager::init() {
    uint32 i, j;

    // Until proven differently, assume we're on CD 1. This is so the start
    // dialog will be able to play any music at all.

    setCD(1);

    // We read in the resource info which tells us the names of the
    // resource cluster files ultimately, although there might be groups
    // within the clusters at this point it makes no difference. We only
    // wish to know what resource files there are and what is in each

    Common::File file;

    if (!file.open("resource.inf")) {
        GUIErrorMessage("Broken Sword II: Cannot open resource.inf");
        return false;
    }

    // The resource.inf file is a simple text file containing the names of
    // all the resource files.

    while (1) {
        char *buf = _resFiles[_totalClusters].fileName;
        uint len = sizeof(_resFiles[_totalClusters].fileName);

        if (!file.readLine(buf, len))
            break;

        int pos = strlen(buf);
        if (buf[pos - 1] == 0x0A)
            buf[pos - 1] = 0;

        _resFiles[_totalClusters].numEntries = -1;
        _resFiles[_totalClusters].entryTab = NULL;
        if (++_totalClusters >= MAX_res_files) {
            GUIErrorMessage("Broken Sword II: Too many entries in resource.inf");
            return false;
        }
    }

    file.close();

    // Now load in the binary id to res conversion table
    if (!file.open("resource.tab")) {
        GUIErrorMessage("Broken Sword II: Cannot open resource.tab");
        return false;
    }

    // Find how many resources
    uint32 size = file.size();

    _totalResFiles = size / 4;

    // Table seems ok so malloc some space
    _resConvTable = (uint16 *)malloc(size);

    for (i = 0; i < size / 2; i++)
        _resConvTable[i] = file.readUint16LE();

    if (file.eos() || file.err()) {
        file.close();
        GUIErrorMessage("Broken Sword II: Cannot read resource.tab");
        return false;
    }

    file.close();

    // Check that we have cd.inf file, unless we are running PSX
    // version, which has all files on one disc.

    if (!file.open("cd.inf") && !Sword2Engine::isPsx()) {
        GUIErrorMessage("Broken Sword II: Cannot open cd.inf");
        return false;
    }

    CdInf *cdInf = new CdInf[_totalClusters];

    for (i = 0; i < _totalClusters; i++) {

        if (Sword2Engine::isPsx()) { // We are running PSX version, artificially fill CdInf structure
            cdInf[i].cd = CD1;
        } else { // We are running PC version, read cd.inf file
            file.read(cdInf[i].clusterName, sizeof(cdInf[i].clusterName));

            cdInf[i].cd = file.readByte();

            if (file.eos() || file.err()) {
                delete[] cdInf;
                file.close();
                GUIErrorMessage("Broken Sword II: Cannot read cd.inf");
                return false;
            }

        }

        // It has been reported that there are two different versions
        // of the cd.inf file: One where all clusters on CD also have
        // the LOCAL_CACHE bit set. This bit is no longer used. To
        // avoid future problems, let's normalize the flag once and for
        // all here.

        if (cdInf[i].cd & LOCAL_PERM)
            cdInf[i].cd = 0;
        else if (cdInf[i].cd & CD1)
            cdInf[i].cd = 1;
        else if (cdInf[i].cd & CD2)
            cdInf[i].cd = 2;
        else
            cdInf[i].cd = 0;

        // Any file on "CD 0" may be needed at all times. Verify that
        // it exists. Any other missing cluster will be requested with
        // an "insert CD" message. Of course, the file may still vanish
        // during game-play (oh, that wascally wabbit!) in which case
        // the resource manager will print a fatal error.

        if (cdInf[i].cd == 0 && !Common::File::exists((char *)cdInf[i].clusterName)) {
            GUIErrorMessage("Broken Sword II: Cannot find " + Common::String((char *)cdInf[i].clusterName));
            delete[] cdInf;
            return false;
        }
    }

    file.close();

    // We check the presence of resource files in cd.inf
    // This is ok in PC version, but in PSX version we don't
    // have cd.inf so we'll have to skip this.
    if (!Sword2Engine::isPsx()) {
        for (i = 0; i < _totalClusters; i++) {
            for (j = 0; j < _totalClusters; j++) {
                if (scumm_stricmp((char *)cdInf[j].clusterName, _resFiles[i].fileName) == 0)
                    break;
            }

            if (j == _totalClusters) {
                delete[] cdInf;
                GUIErrorMessage(Common::String(_resFiles[i].fileName) + " is not in cd.inf");
                return false;
            }

            _resFiles[i].cd = cdInf[j].cd;
        }
    }

    delete[] cdInf;

    debug(1, "%d resources in %d cluster files", _totalResFiles, _totalClusters);
    for (i = 0; i < _totalClusters; i++)
        debug(2, "filename of cluster %d: -%s (%d)", i, _resFiles[i].fileName, _resFiles[i].cd);

    _resList = (Resource *)malloc(_totalResFiles * sizeof(Resource));

    for (i = 0; i < _totalResFiles; i++) {
        _resList[i].ptr = NULL;
        _resList[i].size = 0;
        _resList[i].refCount = 0;
        _resList[i].prev = _resList[i].next = NULL;
    }

    return true;
}
Ejemplo n.º 27
0
Common::Error GroovieEngine::run() {
	_script = new Script(this, _gameDescription->version);

	// Initialize the graphics
	switch (_gameDescription->version) {
	case kGroovieV2:
		// Request the mode with the highest precision available
		initGraphics(640, 480, true, NULL);

		// Save the enabled mode as it can be both an RGB mode or CLUT8
		_pixelFormat = _system->getScreenFormat();
		_mode8bit = (_pixelFormat == Graphics::PixelFormat::createFormatCLUT8());
		break;
	case kGroovieT7G:
		initGraphics(640, 480, true);
		_pixelFormat = Graphics::PixelFormat::createFormatCLUT8();
		break;
	}

	// Create debugger. It requires GFX to be initialized
	_debugger = new Debugger(this);
	_script->setDebugger(_debugger);

	// Create the graphics manager
	_graphicsMan = new GraphicsMan(this);

	// Create the resource and cursor managers and the video player
	// Prepare the font too
	switch (_gameDescription->version) {
	case kGroovieT7G:
		if (getPlatform() == Common::kPlatformMacintosh) {
			_macResFork = new Common::MacResManager();
			if (!_macResFork->open(_gameDescription->desc.filesDescriptions[0].fileName))
				error("Could not open %s as a resource fork", _gameDescription->desc.filesDescriptions[0].fileName);
			// The Macintosh release used system fonts. We use GUI fonts.
			_font = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
		} else {
			Common::File fontfile;
			if (!fontfile.open("sphinx.fnt")) {
				error("Couldn't open sphinx.fnt");
				return Common::kNoGameDataFoundError;
			} else if (!_sphinxFont.load(fontfile)) {
				error("Error loading sphinx.fnt");
				return Common::kUnknownError;
			}
			fontfile.close();
			_font = &_sphinxFont;
		}

		_resMan = new ResMan_t7g(_macResFork);
		_grvCursorMan = new GrvCursorMan_t7g(_system, _macResFork);
		_videoPlayer = new VDXPlayer(this);
		break;
	case kGroovieV2:
		_resMan = new ResMan_v2();
		_grvCursorMan = new GrvCursorMan_v2(_system);
		_videoPlayer = new ROQPlayer(this);
		break;
	}

	// Create the music player
	if (getPlatform() == Common::kPlatformMacintosh)
		_musicPlayer = new MusicPlayerMac(this);
	else
		_musicPlayer = new MusicPlayerXMI(this, _gameDescription->version == kGroovieT7G ? "fat" : "sample");

	// Load volume levels
	syncSoundSettings();

	// Get the name of the main script
	Common::String filename = _gameDescription->desc.filesDescriptions[0].fileName;
	if (_gameDescription->version == kGroovieT7G) {
		// Run The 7th Guest's demo if requested
		if (ConfMan.hasKey("demo_mode") && ConfMan.getBool("demo_mode"))
			filename = "demo.grv";
		else if (getPlatform() == Common::kPlatformMacintosh)
			filename = "script.grv"; // Stored inside the executable's resource fork
	} else if (_gameDescription->version == kGroovieV2) {
		// Open the disk index
		Common::File disk;
		if (!disk.open(filename)) {
			error("Couldn't open %s", filename.c_str());
			return Common::kNoGameDataFoundError;
		}

		// Search the entry
		bool found = false;
		int index = 0;
		while (!found && !disk.eos()) {
			Common::String line = disk.readLine();
			if (line.hasPrefix("title: ")) {
				// A new entry
				index++;
			} else if (line.hasPrefix("boot: ") && index == _gameDescription->indexEntry) {
				// It's the boot of the entry we're looking for,
				// get the script filename
				filename = line.c_str() + 6;
				found = true;
			}
		}

		// Couldn't find the entry
		if (!found) {
			error("Couldn't find entry %d in %s", _gameDescription->indexEntry, filename.c_str());
			return Common::kUnknownError;
		}
	}

	// Check the script file extension
	if (!filename.hasSuffix(".grv")) {
		error("%s isn't a valid script filename", filename.c_str());
		return Common::kUnknownError;
	}

	// Load the script
	if (!_script->loadScript(filename)) {
		error("Couldn't load the script file %s", filename.c_str());
		return Common::kUnknownError;
	}

	// Should I load a saved game?
	if (ConfMan.hasKey("save_slot")) {
		// Get the requested slot
		int slot = ConfMan.getInt("save_slot");
		_script->directGameLoad(slot);
	}

	// Check that the game files and the audio tracks aren't together run from
	// the same cd
	checkCD();

	// Game timer counter
	uint16 tmr = 0;

	// Initialize the CD
	int cd_num = ConfMan.getInt("cdrom");
	if (cd_num >= 0)
		_system->getAudioCDManager()->openCD(cd_num);

	while (!shouldQuit()) {
		// Give the debugger a chance to act
		_debugger->onFrame();

		// Handle input
		Common::Event ev;
		while (_eventMan->pollEvent(ev)) {
			switch (ev.type) {
			case Common::EVENT_KEYDOWN:
				// CTRL-D: Attach the debugger
				if ((ev.kbd.flags & Common::KBD_CTRL) && ev.kbd.keycode == Common::KEYCODE_d)
					_debugger->attach();

				// Send the event to the scripts
				_script->setKbdChar(ev.kbd.ascii);

				// Continue the script execution to handle the key
				_waitingForInput = false;
				break;

			case Common::EVENT_MAINMENU:
				// Closing the GMM
			case Common::EVENT_MOUSEMOVE:
				// Continue the script execution, the mouse pointer
				// may fall inside a different hotspot now
				_waitingForInput = false;
				break;

			case Common::EVENT_LBUTTONDOWN:
				// Send the event to the scripts
				_script->setMouseClick(1);

				// Continue the script execution to handle
				// the click
				_waitingForInput = false;
				break;

			case Common::EVENT_RBUTTONDOWN:
				// Send the event to the scripts (to skip the video)
				_script->setMouseClick(2);
				break;

			case Common::EVENT_QUIT:
				quitGame();
				break;

			default:
				break;
			}
		}

		// The event loop may have triggered the quit status. In this case,
		// stop the execution.
		if (shouldQuit()) {
			continue;
		}

		if (_waitingForInput) {
			// Still waiting for input, just update the mouse, game timer and then wait a bit more
			_grvCursorMan->animate();
			_system->updateScreen();
			tmr++;
			// Wait a little bit between increments.  While mouse is moving, this triggers
			// only negligably slower.
			if (tmr > 4) {
				_script->timerTick();
				tmr = 0;
			}

			_system->delayMillis(50);
		} else if (_graphicsMan->isFading()) {
			// We're waiting for a fading to end, let the CPU rest
			// for a while and continue
			_system->delayMillis(30);
		} else {
			// Everything's fine, execute another script step
			_script->step();
		}

		// Update the screen if required
		_graphicsMan->update();
	}

	return Common::kNoError;
}
Ejemplo n.º 28
0
FileSystem::FileSystem(const char *hashFilename) {

	for (int i = 0; i < 10; i++) {
		_hagEntries[i].filename[0] = '\0';
		_hagEntries[i].fileIndex = 0; // Was -1
		_hagEntries[i].hagFile = 0;
	}

	Common::File hashFile;
	uint32 hashSize;

	hashFile.open(hashFilename);

	if (!hashFile.isOpen()) {
		debugCN(kDebugCore, "FileSystem::FileSystem: error opening hash %s\n", hashFilename);
	}

	hashSize = hashFile.readUint32LE();

	//debugCN(kDebugCore, "FileSystem::FileSystem: hashSize = %d\n", hashSize);

	/* load file records and add them to the hash list */
	for (uint i = 0; i < hashSize; i++) {
		HashFileEntry entry;
		hashFile.read(entry.filename, kM4MaxFilenameSize);
		str_lower(entry.filename);
		entry.hagfile = hashFile.readByte();
		hashFile.readByte();
		entry.offset = hashFile.readUint32LE();
		entry.size = hashFile.readUint32LE();
		hashFile.readUint32LE();

		if (entry.filename[0]) {
			/*
			debugCN(kDebugCore, "  filename: %s\n", entry.filename);
			debugCN(kDebugCore, "  hagfile: %d\n", entry.hagfile);
			debugCN(kDebugCore, "  disks: %d\n", entry.disks);
			debugCN(kDebugCore, "  offset: %08X\n", entry.offset);
			debugCN(kDebugCore, "  size: %d\n", entry.size);
			debugCN(kDebugCore, "  next: %08X\n", entry.next);
			*/
			_fileEntries[entry.filename] = entry;
		}

	}

	/* load hagfile records and update the list */
	while (!hashFile.eos()) {
		HashHagEntry entry;
		hashFile.read(entry.filename, kM4MaxFilenameSize);
		entry.fileIndex = hashFile.readByte();
		if (hashFile.eos())
			break;

		changeExtension(_hagEntries[entry.fileIndex].filename, entry.filename, "HAG");
		_hagEntries[entry.fileIndex].fileIndex = entry.fileIndex;

		_hagEntries[entry.fileIndex].hagFile = new Common::File();
		_hagEntries[entry.fileIndex].hagFile->open(_hagEntries[entry.fileIndex].filename);

		if (!_hagEntries[entry.fileIndex].hagFile->isOpen()) {
			debugCN(kDebugCore, "FileSystem::FileSystem: error opening hag %s\n", _hagEntries[entry.fileIndex].filename);
		}

	}

	hashFile.close();

}
Ejemplo n.º 29
0
bool Sword2Engine::initStartMenu() {
	// Print out a list of all the start points available.
	// There should be a linc produced file called startup.txt.
	// This file should contain ascii numbers of all the resource game
	// objects that are screen managers.
	// We query each in turn and setup an array of start structures.
	// If the file doesn't exist then we say so and return a 0.

	Common::File fp;

	// ok, load in the master screen manager file

	_totalStartups = 0;
	_totalScreenManagers = 0;

	if (!fp.open("startup.inf")) {
		warning("Cannot open startup.inf - the debugger won't have a start menu");
		return false;
	}

	// The startup.inf file which contains a list of all the files. Now
	// extract the filenames

	int start_ids[MAX_starts];
	int lineno = 0;

	while (!fp.eos() && !fp.err()) {
		Common::String line = fp.readLine();

		// Skip empty lines or, more likely, the end of the stream.
		if (line.size() == 0)
			continue;

		char *errptr;
		int id;

		lineno++;
		id = strtol(line.c_str(), &errptr, 10);

		if (*errptr) {
			warning("startup.inf:%d: Invalid string '%s'", lineno, line.c_str());
			continue;
		}

		if (!_resman->checkValid(id)) {
			warning("startup.inf:%d: Invalid resource %d", lineno, id);
			continue;
		}

		if (_resman->fetchType(id) != SCREEN_MANAGER) {
			warning("startup.inf:%d: '%s' (%d) is not a screen manager", lineno, _resman->fetchName(id), id);
			continue;
		}

		start_ids[_totalScreenManagers] = id;

		if (++_totalScreenManagers >= MAX_starts) {
			warning("Too many entries in startup.inf");
			break;
		}
	}

	// An I/O error before EOS? That's bad, but this is not a vital file.
	if (fp.err() && !fp.eos())
		warning("I/O error while reading startup.inf");

	fp.close();

	// Using this method the Gode generated resource.inf must have #0d0a
	// on the last entry

	debug(1, "%d screen manager objects", _totalScreenManagers);

	// Open each object and make a query call. The object must fill in a
	// startup structure. It may fill in several if it wishes - for
	// instance a startup could be set for later in the game where
	// specific vars are set

	for (uint i = 0; i < _totalScreenManagers; i++) {
		_startRes = start_ids[i];

		debug(2, "Querying screen manager %d", _startRes);

		// Open each one and run through the interpreter. Script 0 is
		// the query request script. We have already made reasonably
		// sure the resource is ok.

		_logic->runResScript(_startRes, 0);
	}

	return 1;
}
Ejemplo n.º 30
0
/**
 * Opens and inits all MIDI sequence files.
 */
void OpenMidiFiles() {
	Common::File midiStream;

	if (TinselV0) {
		// The early demo version of DW1 doesn't have MIDI
	} else if (TinselV2) {
		// DW2 uses a different music mechanism
	} else if (TinselV1Mac) {
		// open MIDI sequence file in binary mode
		if (!midiStream.open(MIDI_FILE))
			error(CANNOT_FIND_FILE, MIDI_FILE);

		uint32 curTrack = 1;
		uint32 songLength = 0;
		int32 fileSize = midiStream.size();

		// Init
		for (int i = 0; i < ARRAYSIZE(g_midiOffsets); i++)
			g_midiOffsets[i] = 0;

		midiStream.skip(4);	// skip file header

		while (!midiStream.eos() && !midiStream.err() && midiStream.pos() != fileSize) {
			assert(curTrack < ARRAYSIZE(g_midiOffsets));
			g_midiOffsets[curTrack] = midiStream.pos();
			//debug("%d: %d", curTrack, g_midiOffsets[curTrack]);

			songLength = midiStream.readUint32BE();
			midiStream.skip(songLength);

			curTrack++;
		}

		midiStream.close();
	} else {
		if (g_midiBuffer.pDat)
			// already allocated
			return;

		// open MIDI sequence file in binary mode
		if (!midiStream.open(MIDI_FILE))
			error(CANNOT_FIND_FILE, MIDI_FILE);

		// get length of the largest sequence
		g_midiBuffer.size = midiStream.readUint32LE();
		if (midiStream.eos() || midiStream.err())
			error(FILE_IS_CORRUPT, MIDI_FILE);

		if (g_midiBuffer.size) {
			// allocate a buffer big enough for the largest MIDI sequence
			if ((g_midiBuffer.pDat = (uint8 *)malloc(g_midiBuffer.size)) != NULL) {
				// clear out the buffer
				memset(g_midiBuffer.pDat, 0, g_midiBuffer.size);
			}
		}

		// Now scan through the contents of the MIDI file to find the offset
		// of each individual track, in order to create a mapping from MIDI
		// offset to track number, for the enhanced MIDI soundtrack.
		// The first song is always at position 4. The subsequent ones are
		// calculated dynamically.
		uint32 curOffset = 4;
		uint32 curTrack = 0;
		uint32 songLength = 0;

		// Init
		for (int i = 0; i < ARRAYSIZE(g_midiOffsets); i++)
			g_midiOffsets[i] = 0;

		while (!midiStream.eos() && !midiStream.err()) {
			if (curOffset + (4 * curTrack) >= (uint32)midiStream.size())
				break;

			assert(curTrack < ARRAYSIZE(g_midiOffsets));
			g_midiOffsets[curTrack] = curOffset + (4 * curTrack);
			//debug("%d: %d", curTrack, midiOffsets[curTrack]);

			songLength = midiStream.readUint32LE();
			curOffset += songLength;
			midiStream.skip(songLength);

			curTrack++;
		}

		midiStream.close();
	}
}