Ejemplo n.º 1
0
ZorkCursor::ZorkCursor(const Common::String &fileName)
    : _width(0),
      _height(0),
      _hotspotX(0),
      _hotspotY(0) {
    Common::File file;
    if (!file.open(fileName))
        return;

    uint32 magic = file.readUint32BE();
    if (magic != MKTAG('Z', 'C', 'R', '1')) {
        warning("%s is not a Zork Cursor file", fileName.c_str());
        return;
    }

    _hotspotX = file.readUint16LE();
    _hotspotY = file.readUint16LE();
    _width = file.readUint16LE();
    _height = file.readUint16LE();

    uint dataSize = _width * _height * sizeof(uint16);
    _surface.create(_width, _height, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0));
    uint32 bytesRead = file.read(_surface.getPixels(), dataSize);
    assert(bytesRead == dataSize);

    // Convert to RGB 565
    _surface.convertToInPlace(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
}
Ejemplo n.º 2
0
InventoryData *Resource::readInventory(const Common::String fileName) {
	Common::File *dataFile = openDataFile(fileName, MKTAG('I', 'N', 'V', '1'));

	_vm->_numInv = dataFile->readUint16LE();
	InventoryData *inventory = new InventoryData[_vm->_numInv + 1];

	for (int i = 1; i <= _vm->_numInv; i++) {
		inventory[i]._quantity = dataFile->readUint16LE();
		inventory[i]._name = readString(dataFile);
		inventory[i]._bitmapName = readString(dataFile);
	}

	delete dataFile;
	return inventory;
}
Ejemplo n.º 3
0
int AgiEngine::loadWords_v1(Common::File &f) {
	char str[64];
	int k;

	debug(0, "Loading dictionary");

	// Loop through alphabet, as words in the dictionary file are sorted by
	// first character
	f.seek(f.pos() + 26 * 2, SEEK_SET);
	do {
		// Read next word
		for (k = 0; k < (int)sizeof(str) - 1; k++) {
			str[k] = f.readByte();
			if (str[k] == 0 || (uint8)str[k] == 0xFF)
				break;
		}

		// And store it in our internal dictionary
		if (k > 0) {
			AgiWord *w = new AgiWord;
			w->word = myStrndup(str, k + 1);
			w->id = f.readUint16LE();
			_game.words[str[0] - 'a'].push_back(w);
			debug(3, "'%s' (%d)", w->word, w->id);
		}
	} while((uint8)str[0] != 0xFF);

	return errOK;
}
Ejemplo n.º 4
0
/**
 * Loads the contents of the mort.dat data file
 */
Common::ErrorCode MortevielleEngine::loadMortDat() {
	Common::File f;

	// Open the mort.dat file
	if (!f.open(MORT_DAT)) {
		Common::String msg = Common::String::format(_("Unable to locate the '%s' engine data file."), MORT_DAT);
		GUIErrorMessage(msg);
		return Common::kReadingFailed;
	}

	// Validate the data file header
	char fileId[4];
	f.read(fileId, 4);
	if (strncmp(fileId, "MORT", 4) != 0) {
		Common::String msg = Common::String::format(_("The '%s' engine data file is corrupt."), MORT_DAT);
		GUIErrorMessage(msg);
		return Common::kReadingFailed;
	}

	// Check the version
	int majVer = f.readByte();
	int minVer = f.readByte();

	if (majVer < MORT_DAT_REQUIRED_VERSION) {
		Common::String msg = Common::String::format(
			_("Incorrect version of the '%s' engine data file found. Expected %d.%d but got %d.%d."),
			MORT_DAT, MORT_DAT_REQUIRED_VERSION, 0, majVer, minVer);
		GUIErrorMessage(msg);
		return Common::kReadingFailed;
	}

	// Loop to load resources from the data file
	while (f.pos() < f.size()) {
		// Get the Id and size of the next resource
		char dataType[4];
		int dataSize;
		f.read(dataType, 4);
		dataSize = f.readUint16LE();

		if (!strncmp(dataType, "FONT", 4)) {
			// Font resource
			_screenSurface->readFontData(f, dataSize);
		} else if (!strncmp(dataType, "SSTR", 4)) {
			readStaticStrings(f, dataSize, kStaticStrings);
		} else if ((!strncmp(dataType, "GSTR", 4)) && (!_txxFileFl)) {
			readStaticStrings(f, dataSize, kGameStrings);
		} else if (!strncmp(dataType, "VERB", 4)) {
			_menu->readVerbNums(f, dataSize);
		} else {
			// Unknown section
			f.skip(dataSize);
		}
	}

	// Close the file
	f.close();

	assert(_engineStrings.size() > 0);
	return Common::kNoError;
}
Ejemplo n.º 5
0
Archivo: hqr.cpp Proyecto: somaen/twin
Common::SeekableReadStream *Hqr::createReadStreamForIndex(int index) const {
	if (index >= _numIndices)
		return 0;

	uint32 realSize;
	uint32 compressedSize;
	uint16 mode;

	Common::File *file = new Common::File();
	file->open(_hqrFileName);
	file->seek(_indices[index]);
	realSize = file->readUint32LE();
	compressedSize = file->readUint32LE();
	mode = file->readUint16LE();
	
	uint32 begin = _indices[index] + 10;
	uint32 end = 0;
	if (mode == 0) {
		end = begin + realSize;
	} else {
		end = begin + compressedSize;
	}
	Common::SeekableReadStream *stream = new Common::SeekableSubReadStream(file, begin, end, DisposeAfterUse::YES);

	if (mode != 0) {
		stream = new LzssReadStream(stream, mode, realSize);
	}

	return stream;
}
Ejemplo n.º 6
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.º 7
0
Common::SeekableReadStream *MADSResourceManager::loadResource(const char *resourceName, bool loadFlag) {
	Common::File hagFile;
	uint32 offset = 0, size = 0;

	// If the first character is a '@' then look for an external file

	if (*resourceName == '@') {
		++resourceName;

		hagFile.open(resourceName);
		if (loadFlag)
			return hagFile.readStream(hagFile.size());
		else
			return new Common::SeekableSubReadStream(&hagFile, 0, hagFile.size());
	}

	// If the first character is the wildcard (resource indicator), skip over it
	if (*resourceName == '*')
		++resourceName;

	char resName[20];
	strcpy(resName, resourceName);
	str_upper(resName);

	hagFile.open(getResourceFilename(resName));

	// Validate hag file header
	char headerBuffer[16];
	if ((hagFile.read(headerBuffer, 16) != 16) || (strncmp(headerBuffer, madsConcatString, 10) != 0))
		error("Invalid HAG file opened");

	int numEntries = hagFile.readUint16LE();

	int resIndex = -1;
	while (++resIndex < numEntries) {
		// Read in the details of the next resource
		char resourceBuffer[14];
		offset = hagFile.readUint32LE();
		size = hagFile.readUint32LE();
		hagFile.read(resourceBuffer, 14);

		if (!strcmp(resName, resourceBuffer))
			break;
	}

	if (resIndex == numEntries)
		error("Invalid resource '%s' specified", resourceName);

	// Get the resource, either loading it in it's entirely or getting a stream reference

	if (loadFlag) {
		hagFile.seek(offset);
		return hagFile.readStream(size);
	} else {
		return new Common::SeekableSubReadStream(&hagFile, offset, offset + size);
	}
}
Ejemplo n.º 8
0
void Resource::readRoomData(const Common::String fileName) {
	Common::File *dataFile = openDataFile(fileName, MKTAG('D', 'O', 'R', '1'));

	_vm->_manyRooms = dataFile->readUint16LE();
	_vm->_highestCondition = dataFile->readUint16LE();
	_vm->_rooms = new RoomData[_vm->_manyRooms + 1];

	for (int i = 1; i <= _vm->_manyRooms; i++) {
		RoomData *curRoom = &_vm->_rooms[i];
		curRoom->_doors[kDirectionNorth] = dataFile->readUint16LE();
		curRoom->_doors[kDirectionSouth] = dataFile->readUint16LE();
		curRoom->_doors[kDirectionEast] = dataFile->readUint16LE();
		curRoom->_doors[kDirectionWest] = dataFile->readUint16LE();
		curRoom->_transitionType = dataFile->readByte();
	}

	delete dataFile;
}
Ejemplo n.º 9
0
Font::Font(Common::String filename) {
	const uint32 headerFont = MKTAG('T', 'F', 'F', '\0');
	Common::File stream;

	stream.open(filename);

	uint32 header = stream.readUint32BE();

	if (header != headerFont)
		error("Invalid resource - %s", filename.c_str());

	stream.skip(4);	// total memory
	_count = stream.readUint16LE();
	_first = stream.readUint16LE();
	_last = stream.readUint16LE();
	_width = stream.readUint16LE();
	_height = stream.readUint16LE();

	_fontSurface.create(_width * _count, _height, ::Graphics::PixelFormat::createFormatCLUT8());

	byte cur;
	int bitIndex = 7;
	byte *p;

	cur = stream.readByte();

	for (uint n = 0; n < _count; n++) {
		for (uint y = 0; y < _height; y++) {
			p = (byte *)_fontSurface.getBasePtr(n * _width, y);

			for (uint x = n * _width; x < n * _width + _width; x++) {
				*p++ = (cur & (1 << bitIndex)) ? 0 : 0xFF;

				bitIndex--;
				if (bitIndex < 0) {
					bitIndex = 7;
					cur = stream.readByte();
				}
			}
		}
	}
}
Ejemplo n.º 10
0
/**
 * Loads the contents of the mort.dat data file
 */
Common::ErrorCode MortevielleEngine::loadMortDat() {
	Common::File f;

	// Open the mort.dat file
	if (!f.open(MORT_DAT)) {
		GUIErrorMessage("Could not locate 'mort.dat'.");
		return Common::kReadingFailed;
	}

	// Validate the data file header
	char fileId[4];
	f.read(fileId, 4);
	if (strncmp(fileId, "MORT", 4) != 0) {
		GUIErrorMessage("The located mort.dat data file is invalid");
		return Common::kReadingFailed;
	}

	// Check the version
	if (f.readByte() < MORT_DAT_REQUIRED_VERSION) {
		GUIErrorMessage("The located mort.dat data file is too old, please download an updated version on scummvm.org");
		return Common::kReadingFailed;
	}
	f.readByte();		// Minor version

	// Loop to load resources from the data file
	while (f.pos() < f.size()) {
		// Get the Id and size of the next resource
		char dataType[4];
		int dataSize;
		f.read(dataType, 4);
		dataSize = f.readUint16LE();

		if (!strncmp(dataType, "FONT", 4)) {
			// Font resource
			_screenSurface.readFontData(f, dataSize);
		} else if (!strncmp(dataType, "SSTR", 4)) {
			readStaticStrings(f, dataSize, kStaticStrings);
		} else if ((!strncmp(dataType, "GSTR", 4)) && (!_txxFileFl)) {
			readStaticStrings(f, dataSize, kGameStrings);
		} else if (!strncmp(dataType, "VERB", 4)) {
			_menu.readVerbNums(f, dataSize);
		} else {
			// Unknown section
			f.skip(dataSize);
		}
	}

	// Close the file
	f.close();

	assert(_engineStrings.size() > 0);
	return Common::kNoError;
}
Ejemplo n.º 11
0
TextFont *Resource::getFont(const Common::String fileName) {
	// TODO: Add support for the font format of the Amiga version
	Common::File *dataFile = openDataFile(fileName, MKTAG('V', 'G', 'A', 'F'));

	uint32 headerSize = 4 + 2 + 256 * 3 + 4;
	uint32 fileSize = dataFile->size();
	if (fileSize <= headerSize)
		return nullptr;

	TextFont *textfont = new TextFont();
	textfont->_dataLength = fileSize - headerSize;
	textfont->_height = dataFile->readUint16LE();
	dataFile->read(textfont->_widths, 256);
	for (int i = 0; i < 256; i++)
		textfont->_offsets[i] = dataFile->readUint16LE();
	dataFile->skip(4);
	textfont->_data = new byte[textfont->_dataLength + 4];
	dataFile->read(textfont->_data, textfont->_dataLength);
	delete dataFile;
	return textfont;
}
Ejemplo n.º 12
0
void LabEngine::loadMapData() {
	Common::File *mapImages = _resource->openDataFile("P:MapImage");

	_imgMap = new Image(mapImages, this);
	_imgRoom = new Image(mapImages, this);
	_imgUpArrowRoom = new Image(mapImages, this);
	_imgDownArrowRoom = new Image(mapImages, this);
	_imgHRoom = new Image(mapImages, this);
	_imgVRoom = new Image(mapImages, this);
	_imgMaze = new Image(mapImages, this);
	_imgHugeMaze = new Image(mapImages, this);

	_imgMapX[kDirectionNorth] = new Image(mapImages, this);
	_imgMapX[kDirectionEast] = new Image(mapImages, this);
	_imgMapX[kDirectionSouth] = new Image(mapImages, this);
	_imgMapX[kDirectionWest] = new Image(mapImages, this);
	_imgPath = new Image(mapImages, this);
	_imgBridge = new Image(mapImages, this);

	_mapButtonList.push_back(_interface->createButton( 8,  _utils->vgaScaleY(105), 0, Common::KEYCODE_ESCAPE, new Image(mapImages, this), new Image(mapImages, this)));	// back
	_mapButtonList.push_back(_interface->createButton( 55, _utils->vgaScaleY(105), 1, Common::KEYCODE_UP,     new Image(mapImages, this), new Image(mapImages, this)));	// up
	_mapButtonList.push_back(_interface->createButton(101, _utils->vgaScaleY(105), 2, Common::KEYCODE_DOWN,   new Image(mapImages, this), new Image(mapImages, this)));	// down

	delete mapImages;

	Common::File *mapFile = _resource->openDataFile("Lab:Maps", MKTAG('M', 'A', 'P', '0'));
	updateEvents();

	_maxRooms = mapFile->readUint16LE();
	_maps = new MapData[_maxRooms + 1];	// will be freed when the user exits the map
	for (int i = 0; i <= _maxRooms; i++) {
		_maps[i]._x = mapFile->readUint16LE();
		_maps[i]._y = mapFile->readUint16LE();
		_maps[i]._pageNumber = mapFile->readUint16LE();
		_maps[i]._specialID = (SpecialRoom) mapFile->readUint16LE();
		_maps[i]._mapFlags = mapFile->readUint32LE();
	}

	delete mapFile;
}
Ejemplo n.º 13
0
bool ScummDebugger::Cmd_ImportRes(int argc, const char** argv) {
	Common::File file;
	uint32 size;
	int resnum;

	if (argc != 4) {
		DebugPrintf("Syntax: importres <restype> <filename> <resnum>\n");
		return true;
	}

	resnum = atoi(argv[3]);
	// FIXME add bounds check

	if (!strncmp(argv[1], "scr", 3)) {
		file.open(argv[2], Common::File::kFileReadMode);
		if (file.isOpen() == false) {
			DebugPrintf("Could not open file %s\n", argv[2]);
			return true;
		}
		if (_vm->_game.features & GF_SMALL_HEADER) {
			size = file.readUint16LE();
			file.seek(-2, SEEK_CUR);
		} else if (_vm->_game.features & GF_SMALL_HEADER) {
			if (_vm->_game.version == 4)
				file.seek(8, SEEK_CUR);
			size = file.readUint32LE();
			file.readUint16LE();
			file.seek(-6, SEEK_CUR);
		} else {
			file.readUint32BE();
			size = file.readUint32BE();
			file.seek(-8, SEEK_CUR);
		}

		file.read(_vm->res.createResource(rtScript, resnum, size), size);

	} else
		DebugPrintf("Unknown importres type '%s'\n", argv[1]);
	return true;
}
Ejemplo n.º 14
0
void Music::loadSoundEffect(const Common::String filename, bool loop, bool waitTillFinished) {
	stopSoundEffect();

	Common::File *file = _vm->_resource->openDataFile(filename, MKTAG('D', 'I', 'F', 'F'));
	if (!file)
		return;

	_vm->_anim->_doBlack = false;

	uint32 magicBytes = file->readUint32LE();
	if (magicBytes != 1219009121) {
		warning("readSound: Bad signature, skipping");
		return;
	}
	uint32 soundTag = file->readUint32LE();
	uint32 soundSize = file->readUint32LE();

	if (soundTag != 0)
		return;

	file->skip(soundSize);	// skip the header

	while (soundTag != 65535) {
		_vm->updateEvents();
		soundTag = file->readUint32LE();
		soundSize = file->readUint32LE() - 8;

		if ((soundTag == 30) || (soundTag == 31)) {
			if (waitTillFinished) {
				while (isSoundEffectActive()) {
					_vm->updateEvents();
					_vm->waitTOF();
				}
			}

			file->skip(4);

			uint16 sampleRate = file->readUint16LE();
			file->skip(2);
			playSoundEffect(sampleRate, soundSize, loop, file);
		} else if (soundTag == 65535) {
			if (waitTillFinished) {
				while (isSoundEffectActive()) {
					_vm->updateEvents();
					_vm->waitTOF();
				}
			}
		} else
			file->skip(soundSize);
	}
}
Ejemplo n.º 15
0
/**
 * Reads boot file for program environment.  Fatal error if not there or
 * file checksum is bad.  De-crypts structure while checking checksum
 */
void FileManager::readBootFile() {
	debugC(1, kDebugFile, "readBootFile()");

	Common::File ofp;
	if (!ofp.open(getBootFilename())) {
		if (_vm->_gameVariant == kGameVariantH1Dos) {
			//TODO initialize properly _boot structure
			warning("readBootFile - Skipping as H1 Dos may be a freeware");
			memset(_vm->_boot._distrib, '\0', sizeof(_vm->_boot._distrib));
			_vm->_boot._registered = kRegFreeware;
			return;
		} else if (_vm->getPlatform() == Common::kPlatformPC) {
			warning("readBootFile - Skipping as H2 and H3 Dos may be shareware");
			memset(_vm->_boot._distrib, '\0', sizeof(_vm->_boot._distrib));
			_vm->_boot._registered = kRegShareware;
			return;
		} else {
			Utils::notifyBox(Common::String::format("Missing startup file '%s'", getBootFilename()));
			_vm->getGameStatus()._doQuitFl = true;
			return;
		}
	}

	if (ofp.size() < (int32)sizeof(_vm->_boot)) {
		Utils::notifyBox(Common::String::format("Corrupted startup file '%s'", getBootFilename()));
		_vm->getGameStatus()._doQuitFl = true;
		return;
	}

	_vm->_boot._checksum = ofp.readByte();
	_vm->_boot._registered = ofp.readByte();
	ofp.read(_vm->_boot._pbswitch, sizeof(_vm->_boot._pbswitch));
	ofp.read(_vm->_boot._distrib, sizeof(_vm->_boot._distrib));
	_vm->_boot._exitLen = ofp.readUint16LE();

	byte *p = (byte *)&_vm->_boot;

	byte checksum = 0;
	for (uint32 i = 0; i < sizeof(_vm->_boot); i++) {
		checksum ^= p[i];
		p[i] ^= s_bootCypher[i % s_bootCypherLen];
	}
	ofp.close();

	if (checksum) {
		Utils::notifyBox(Common::String::format("Corrupted startup file '%s'", getBootFilename()));
		_vm->getGameStatus()._doQuitFl = true;
	}
}
Ejemplo n.º 16
0
/**
 * Read sound (or music) file data.  Call with SILENCE to free-up
 * any allocated memory.  Also returns size of data
 */
SoundPtr FileManager::getSound(const int16 sound, uint16 *size) {
	debugC(1, kDebugFile, "getSound(%d)", sound);

	// No more to do if SILENCE (called for cleanup purposes)
	if (sound == _vm->_soundSilence)
		return 0;

	// Open sounds file
	Common::File fp;                                // Handle to SOUND_FILE
	if (!fp.open(getSoundFilename())) {
		warning("Hugo Error: File not found %s", getSoundFilename());
		return 0;
	}

	if (!_hasReadHeader) {
		for (int i = 0; i < kMaxSounds; i++) {
			_soundHdr[i]._size = fp.readUint16LE();
			_soundHdr[i]._offset = fp.readUint32LE();
		}
		if (fp.err())
			error("Wrong sound file format");
		_hasReadHeader = true;
	}

	*size = _soundHdr[sound]._size;
	if (*size == 0)
		error("Wrong sound file format or missing sound %d", sound);

	// Allocate memory for sound or music, if possible
	SoundPtr soundPtr = (byte *)malloc(_soundHdr[sound]._size); // Ptr to sound data
	assert(soundPtr);

	// Seek to data and read it
	fp.seek(_soundHdr[sound]._offset, SEEK_SET);
	if (fp.read(soundPtr, _soundHdr[sound]._size) != _soundHdr[sound]._size)
		error("Wrong sound file format");

	fp.close();

	return soundPtr;
}
Ejemplo n.º 17
0
bool MADSResourceManager::resourceExists(const char *resourceName) {
	Common::File hagFile;
	uint32 offset, size;

	// If the first character is the wildcard (resource indicator), skip over it
	if (*resourceName == '*')
		++resourceName;

	char resName[20];
	strcpy(resName, resourceName);
	str_upper(resName);

	hagFile.open(getResourceFilename(resName));

	// Validate hag file header
	char headerBuffer[16];
	if ((hagFile.read(headerBuffer, 16) != 16) || (strncmp(headerBuffer, madsConcatString, 10) != 0))
		error("Invalid HAG file opened");

	int numEntries = hagFile.readUint16LE();

	int resIndex = -1;
	while (++resIndex < numEntries) {
		// Read in the details of the next resource
		char resourceBuffer[14];
		offset = hagFile.readUint32LE();
		size = hagFile.readUint32LE();
		hagFile.read(resourceBuffer, 14);

		if (!strcmp(resName, resourceBuffer))
			break;
	}

	if (resIndex == numEntries)
		return false;
	else
		return true;
}
Ejemplo n.º 18
0
/**
 * Returns address of uif_hdr[id], reading it in if first call
 * This file contains, between others, the bitmaps of the fonts used in the application
 * UIF means User interface database (Windows Only)
 */
UifHdr *FileManager::getUIFHeader(const Uif id) {
	debugC(1, kDebugFile, "getUIFHeader(%d)", id);

	// Initialize offset lookup if not read yet
	if (_firstUIFFl) {
		_firstUIFFl = false;
		// Open unbuffered to do far read
		Common::File ip;                            // Image data file
		if (!ip.open(getUifFilename()))
			error("File not found: %s", getUifFilename());

		if (ip.size() < (int32)sizeof(_UIFHeader))
			error("Wrong UIF file format");

		for (int i = 0; i < kMaxUifs; ++i) {
			_UIFHeader[i]._size = ip.readUint16LE();
			_UIFHeader[i]._offset = ip.readUint32LE();
		}

		ip.close();
	}
	return &_UIFHeader[id];
}
Ejemplo n.º 19
0
/**
 * Reads boot file for program environment.  Fatal error if not there or
 * file checksum is bad.  De-crypts structure while checking checksum
 */
void FileManager::readBootFile() {
	debugC(1, kDebugFile, "readBootFile()");

	Common::File ofp;
	if (!ofp.open(getBootFilename())) {
		if (_vm->_gameVariant == kGameVariantH1Dos) {
			//TODO initialize properly _boot structure
			warning("readBootFile - Skipping as H1 Dos may be a freeware");
			memset(_vm->_boot.distrib, '\0', sizeof(_vm->_boot.distrib));
			_vm->_boot.registered = kRegFreeware;
			return;
		} else {
			error("Missing startup file '%s'", getBootFilename());
		}
	}

	if (ofp.size() < (int32)sizeof(_vm->_boot))
		error("Corrupted startup file");

	_vm->_boot.checksum = ofp.readByte();
	_vm->_boot.registered = ofp.readByte();
	ofp.read(_vm->_boot.pbswitch, sizeof(_vm->_boot.pbswitch));
	ofp.read(_vm->_boot.distrib, sizeof(_vm->_boot.distrib));
	_vm->_boot.exit_len = ofp.readUint16LE();

	byte *p = (byte *)&_vm->_boot;

	byte checksum = 0;
	for (uint32 i = 0; i < sizeof(_vm->_boot); i++) {
		checksum ^= p[i];
		p[i] ^= s_bootCyper[i % s_bootCyperLen];
	}
	ofp.close();

	if (checksum)
		error("Corrupted startup file");
}
Ejemplo n.º 20
0
bool loadWAVFromStream(Common::File &stream, int &size, int &rate, byte &flags, uint16 *wavType, int *blockAlign_) {
    const uint32 initialPos = stream.pos();
    byte buf[4+1];

    buf[4] = 0;

    stream.read_noThrow(buf, 4);
    if (memcmp(buf, "RIFF", 4) != 0) {
        warning("getWavInfo: No 'RIFF' header");
        return false;
    }

    uint32 wavLength = stream.readUint32LE();

    stream.read_noThrow(buf, 4);
    if (memcmp(buf, "WAVE", 4) != 0) {
        warning("getWavInfo: No 'WAVE' header");
        return false;
    }

    stream.read_noThrow(buf, 4);
    if (memcmp(buf, "fmt ", 4) != 0) {
        warning("getWavInfo: No 'fmt' header");
        return false;
    }

    uint32 fmtLength = stream.readUint32LE();
    if (fmtLength < 16) {
        // A valid fmt chunk always contains at least 16 bytes
        warning("getWavInfo: 'fmt' header is too short");
        return false;
    }

    // Next comes the "type" field of the fmt header. Some typical
    // values for it:
    // 1  -> uncompressed PCM
    // 17 -> IMA ADPCM compressed WAVE
    // See <http://www.saettler.com/RIFFNEW/RIFFNEW.htm> for a more complete
    // list of common WAVE compression formats...
    uint16 type = stream.readUint16LE();	// == 1 for PCM data
    uint16 numChannels = stream.readUint16LE();	// 1 for mono, 2 for stereo
    uint32 samplesPerSec = stream.readUint32LE();	// in Hz
    uint32 avgBytesPerSec = stream.readUint32LE();	// == SampleRate * NumChannels * BitsPerSample/8

    uint16 blockAlign = stream.readUint16LE();	// == NumChannels * BitsPerSample/8
    uint16 bitsPerSample = stream.readUint16LE();	// 8, 16 ...
    // 8 bit data is unsigned, 16 bit data signed


    if (wavType != 0)
        *wavType = type;

    if (blockAlign_ != 0)
        *blockAlign_ = blockAlign;
#if 0
    printf("WAVE information:\n");
    printf("  total size: %d\n", wavLength);
    printf("  fmt size: %d\n", fmtLength);
    printf("  type: %d\n", type);
    printf("  numChannels: %d\n", numChannels);
    printf("  samplesPerSec: %d\n", samplesPerSec);
    printf("  avgBytesPerSec: %d\n", avgBytesPerSec);
    printf("  blockAlign: %d\n", blockAlign);
    printf("  bitsPerSample: %d\n", bitsPerSample);
#endif

    if (type != 1 && type != 2 && type != 17) {
        warning("getWavInfo: only PCM, MS ADPCM or IMA ADPCM data is supported (type %d)", type);
        return false;
    }

    if (blockAlign != numChannels * bitsPerSample / 8 && type != 2) {
        debug(0, "getWavInfo: blockAlign is invalid");
    }

    if (avgBytesPerSec != samplesPerSec * blockAlign && type != 2) {
        debug(0, "getWavInfo: avgBytesPerSec is invalid");
    }

    // Prepare the return values.
    rate = samplesPerSec;

    flags = 0;
    if (bitsPerSample == 8)		// 8 bit data is unsigned
        flags |= Audio::Mixer::FLAG_UNSIGNED;
    else if (bitsPerSample == 16)	// 16 bit data is signed little endian
        flags |= (Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN);
    else if (bitsPerSample == 4 && type == 17)	// MS IMA ADPCM compressed. We decompress it
        flags |= (Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN);
    else if (bitsPerSample == 4 && type == 2)	// MS ADPCM compressed. We decompress it
        flags |= (Audio::Mixer::FLAG_16BITS | Audio::Mixer::FLAG_LITTLE_ENDIAN);
    else {
        warning("getWavInfo: unsupported bitsPerSample %d", bitsPerSample);
        return false;
    }

    if (numChannels == 2)
        flags |= Audio::Mixer::FLAG_STEREO;
    else if (numChannels != 1) {
        warning("getWavInfo: unsupported number of channels %d", numChannels);
        return false;
    }

    // It's almost certainly a WAV file, but we still need to find its
    // 'data' chunk.

    // Skip over the rest of the fmt chunk.
    int offset = fmtLength - 16;

    do {
        stream.seek(offset, SEEK_CUR);
        if (stream.pos() >= int(initialPos + wavLength + 8)) {
            warning("getWavInfo: Cannot find 'data' chunk");
            return false;
        }
        stream.read_noThrow(buf, 4);
        offset = stream.readUint32LE();

#if 0
        printf("  found a '%s' tag of size %d\n", buf, offset);
#endif
    } while (memcmp(buf, "data", 4) != 0);

    // Stream now points at 'offset' bytes of sample data...
    size = offset;

    return true;
}
Ejemplo n.º 21
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.º 22
0
void Screen::rollCredits() {
	uint32 loopingMusicId = _vm->_sound->getLoopingMusicId();

	// Prepare for the credits by fading down, stoping the music, etc.

	_vm->_mouse->setMouse(0);

	_vm->_sound->muteFx(true);
	_vm->_sound->muteSpeech(true);

	waitForFade();
	fadeDown();
	waitForFade();

	_vm->_mouse->closeMenuImmediately();

	// There are three files which I believe are involved in showing the
	// credits:
	//
	// credits.bmp  - The "Smacker" logo, stored as follows:
	//
	//     width     2 bytes, little endian
	//     height    2 bytes, little endian
	//     palette   3 * 256 bytes
	//     data      width * height bytes
	//
	//     Note that the maximum colour component in the palette is 0x3F.
	//     This is the same resolution as the _paletteMatch table. I doubt
	//     that this is a coincidence, but let's use the image palette
	//     directly anyway, just to be safe.
	//
	// credits.clu  - The credits text (credits.txt in PSX version)
	//
	//     This is simply a text file with CRLF line endings.
	//     '^' is not shown, but used to mark the center of the line.
	//     '@' is used as a placeholder for the "Smacker" logo. At least
	//     when it appears alone.
	//     Remaining lines are centered.
	//     The German version also contains character code 9 for no
	//     apparent reason. We ignore them.
	//
	// fonts.clu    - The credits font?
	//
	//     FIXME: At this time I don't know how to interpret fonts.clu. For
	//     now, let's just the standard speech font instead.

	SpriteInfo spriteInfo;
	Common::File f;
	int i;

	spriteInfo.isText = false;

	// Read the "Smacker" logo

	uint16 logoWidth = 0;
	uint16 logoHeight = 0;
	byte *logoData = NULL;
	byte palette[256 * 3];

	if (f.open("credits.bmp")) {
		logoWidth = f.readUint16LE();
		logoHeight = f.readUint16LE();

		for (i = 0; i < 256; i++) {
			palette[i * 3 + 0] = f.readByte() << 2;
			palette[i * 3 + 1] = f.readByte() << 2;
			palette[i * 3 + 2] = f.readByte() << 2;
		}

		logoData = (byte *)malloc(logoWidth * logoHeight);

		f.read(logoData, logoWidth * logoHeight);
		f.close();
	} else {
		warning("Can't find credits.bmp");
		memset(palette, 0, sizeof(palette));
		palette[14 * 3 + 0] = 252;
		palette[14 * 3 + 1] = 252;
		palette[14 * 3 + 2] = 252;
	}

	setPalette(0, 256, palette, RDPAL_INSTANT);

	// Read the credits text

	Common::Array<CreditsLine *> creditsLines;

	int lineCount = 0;
	int lineTop = 400;
	int paragraphStart = 0;
	bool hasCenterMark = false;

	if (Sword2Engine::isPsx()) {
		if (!f.open("credits.txt")) {
			warning("Can't find credits.txt");

			free(logoData);
			return;
		}
	} else {
		if (!f.open("credits.clu")) {
			warning("Can't find credits.clu");

			free(logoData);
			return;
		}
	}

	while (1) {
		char buffer[80];
		char *line = f.readLine(buffer, sizeof(buffer));

		if (line) {
			// Replace invalid character codes prevent the 'dud'
			// symbol from showing up in the credits.

			for (byte *ptr = (byte *)line; *ptr; ptr++) {
				switch (*ptr) {
				case 9:
					// The German credits contain these.
					// Convert them to spaces.
					*ptr = 32;
					break;
				case 10:
					// LF is treated as end of line.
					*ptr = 0;
					break;
				case 170:
					// The Spanish credits contain these.
					// Convert them to periods.
					*ptr = '.';
				default:
					break;
				}
			}
		}

		if (!line || *line == 0) {
			if (!hasCenterMark) {
				for (i = paragraphStart; i < lineCount; i++)
					creditsLines[i]->type = LINE_CENTER;
			}
			paragraphStart = lineCount;
			hasCenterMark = false;
			if (paragraphStart == lineCount)
				lineTop += CREDITS_LINE_SPACING;

			if (!line)
				break;

			continue;
		}

		char *center_mark = strchr(line, '^');

		if (center_mark) {
			// The current paragraph has at least one center mark.
			hasCenterMark = true;

			if (center_mark != line) {
				creditsLines.push_back(new CreditsLine);

				// The center mark is somewhere inside the
				// line. Split it into left and right side.
				*center_mark = 0;

				creditsLines[lineCount]->top = lineTop;
				creditsLines[lineCount]->height = CREDITS_FONT_HEIGHT;
				creditsLines[lineCount]->type = LINE_LEFT;
				creditsLines[lineCount]->str = strdup(line);

				lineCount++;
				*center_mark = '^';
			}

			line = center_mark;
		}

		creditsLines.push_back(new CreditsLine);

		creditsLines[lineCount]->top = lineTop;

		if (*line == '^') {
			creditsLines[lineCount]->type = LINE_RIGHT;
			line++;
		} else
			creditsLines[lineCount]->type = LINE_LEFT;

		if (strcmp(line, "@") == 0) {
			creditsLines[lineCount]->height = logoHeight;
			lineTop += logoHeight;
		} else {
			creditsLines[lineCount]->height = CREDITS_FONT_HEIGHT;
			lineTop += CREDITS_LINE_SPACING;
		}

		creditsLines[lineCount]->str = strdup(line);
		lineCount++;
	}

	f.close();

	// We could easily add some ScummVM stuff to the credits, if we wanted
	// to. On the other hand, anyone with the attention span to actually
	// read all the credits probably already knows. :-)

	// Start the music and roll the credits

	// The credits music (which can also be heard briefly in the "carib"
	// cutscene) is played once.

	_vm->_sound->streamCompMusic(309, false);

	clearScene();
	fadeUp(0);

	spriteInfo.scale = 0;
	spriteInfo.scaledWidth = 0;
	spriteInfo.scaledHeight = 0;
	spriteInfo.type = RDSPR_DISPLAYALIGN | RDSPR_NOCOMPRESSION | RDSPR_TRANS;
	spriteInfo.blend = 0;

	int startLine = 0;
	int scrollPos = 0;

	bool abortCredits = false;

	int scrollSteps = lineTop + CREDITS_FONT_HEIGHT;
	uint32 musicStart = getTick();

	// Ideally the music should last just a tiny bit longer than the
	// credits. Note that musicTimeRemaining() will return 0 if the music
	// is muted, so we need a sensible fallback for that case.

	uint32 musicLength = MAX((int32)(1000 * (_vm->_sound->musicTimeRemaining() - 3)), 25 * (int32)scrollSteps);

	while (scrollPos < scrollSteps && !_vm->shouldQuit()) {
		clearScene();

		for (i = startLine; i < lineCount; i++) {
			if (!creditsLines[i])
				continue;

			// Free any sprites that have scrolled off the screen

			if (creditsLines[i]->top + creditsLines[i]->height < scrollPos) {
				debug(2, "Freeing line %d: '%s'", i, creditsLines[i]->str);

				delete creditsLines[i];
				creditsLines[i] = NULL;

				startLine = i + 1;
			} else if (creditsLines[i]->top < scrollPos + 400) {
				if (!creditsLines[i]->sprite) {
					debug(2, "Creating line %d: '%s'", i, creditsLines[i]->str);
					creditsLines[i]->sprite = _vm->_fontRenderer->makeTextSprite((byte *)creditsLines[i]->str, 600, 14, _vm->_speechFontId, 0);
				}

				FrameHeader frame;

				frame.read(creditsLines[i]->sprite);

				spriteInfo.y = creditsLines[i]->top - scrollPos;
				spriteInfo.w = frame.width;
				spriteInfo.h = frame.height;
				spriteInfo.data = creditsLines[i]->sprite + FrameHeader::size();
				spriteInfo.isText = true;

				switch (creditsLines[i]->type) {
				case LINE_LEFT:
					spriteInfo.x = RENDERWIDE / 2 - 5 - frame.width;
					break;
				case LINE_RIGHT:
					spriteInfo.x = RENDERWIDE / 2 + 5;
					break;
				case LINE_CENTER:
					if (strcmp(creditsLines[i]->str, "@") == 0) {
						spriteInfo.data = logoData;
						spriteInfo.x = (RENDERWIDE - logoWidth) / 2;
						spriteInfo.w = logoWidth;
						spriteInfo.h = logoHeight;
					} else
						spriteInfo.x = (RENDERWIDE - frame.width) / 2;
					break;
				}

				if (spriteInfo.data)
					drawSprite(&spriteInfo);
			} else
				break;
		}

		updateDisplay();

		KeyboardEvent *ke = _vm->keyboardEvent();

		if (ke && ke->kbd.keycode == Common::KEYCODE_ESCAPE) {
			if (!abortCredits) {
				abortCredits = true;
				fadeDown();
			}
		}

		if (abortCredits && getFadeStatus() == RDFADE_BLACK)
			break;

		_vm->sleepUntil(musicStart + (musicLength * scrollPos) / scrollSteps + _pauseTicks);
		scrollPos++;
	}

	// We're done. Clean up and try to put everything back where it was
	// before the credits.

	for (i = 0; i < lineCount; i++) {
		delete creditsLines[i];
	}

	free(logoData);

	if (!abortCredits) {
		fadeDown();

		// The music should either have stopped or be about to stop, so
		// wait for it to really happen.

		while (_vm->_sound->musicTimeRemaining() && !_vm->shouldQuit()) {
			updateDisplay(false);
			_vm->_system->delayMillis(100);
		}
	}

	if (_vm->shouldQuit())
		return;

	waitForFade();

	_vm->_sound->muteFx(false);
	_vm->_sound->muteSpeech(false);

	if (loopingMusicId)
		_vm->_sound->streamCompMusic(loopingMusicId, true);
	else
		_vm->_sound->stopMusic(false);

	if (!_vm->_mouse->getMouseStatus() || _vm->_mouse->isChoosing())
		_vm->_mouse->setMouse(NORMAL_MOUSE_ID);

	if (_vm->_logic->readVar(DEAD))
		_vm->_mouse->buildSystemMenu();
}
Ejemplo n.º 23
0
/**
 * Loads an object file that is in the common VOL resource format. Expects
 * the file pointer to point to the last field in header, ie. file length.
 * This is used at least by the V1 booter games.
 */
int AgiEngine::loadObjects(Common::File &fp) {
	int flen = fp.readUint16LE();
	return readObjects(fp, flen);
}
Ejemplo n.º 24
0
void Menu::readVerbNums(Common::File &f, int dataSize) {
	// Figure out what language Id is needed
	byte desiredLanguageId;
	switch(_vm->getLanguage()) {
	case Common::EN_ANY:
		desiredLanguageId = MORTDAT_LANG_ENGLISH;
		break;
	case Common::FR_FRA:
		desiredLanguageId = MORTDAT_LANG_FRENCH;
		break;
	case Common::DE_DEU:
		desiredLanguageId = MORTDAT_LANG_GERMAN;
		break;
	default:
		warning("Language not supported, switching to English");
		desiredLanguageId = MORTDAT_LANG_ENGLISH;
		break;
	}
	// Read in the language
	byte languageId = f.readByte();
	--dataSize;

	// If the language isn't correct, then skip the entire block
	if (languageId != desiredLanguageId) {
		f.skip(dataSize);
		return;
	}

	assert(dataSize == 52);
	_opcodeAttach  = f.readUint16LE();
	_opcodeWait    = f.readUint16LE();
	_opcodeForce   = f.readUint16LE();
	_opcodeSleep   = f.readUint16LE();
	_opcodeListen  = f.readUint16LE();
	_opcodeEnter   = f.readUint16LE();
	_opcodeClose   = f.readUint16LE();
	_opcodeSearch  = f.readUint16LE();
	_opcodeKnock   = f.readUint16LE();
	_opcodeScratch = f.readUint16LE();
	_opcodeRead    = f.readUint16LE();
	_opcodeEat     = f.readUint16LE();
	_opcodePlace   = f.readUint16LE();
	_opcodeOpen    = f.readUint16LE();
	_opcodeTake    = f.readUint16LE();
	_opcodeLook    = f.readUint16LE();
	_opcodeSmell   = f.readUint16LE();
	_opcodeSound   = f.readUint16LE();
	_opcodeLeave   = f.readUint16LE();
	_opcodeLift    = f.readUint16LE();
	_opcodeTurn    = f.readUint16LE();
	_opcodeSHide   = f.readUint16LE();
	_opcodeSSearch = f.readUint16LE();
	_opcodeSRead   = f.readUint16LE();
	_opcodeSPut    = f.readUint16LE();
	_opcodeSLook   = f.readUint16LE();

	_actionMenu[0]._menuId    = OPCODE_NONE   >> 8;
	_actionMenu[0]._actionId  = OPCODE_NONE   & 0xFF;

	_actionMenu[1]._menuId    = _opcodeSHide  >> 8;
	_actionMenu[1]._actionId  = _opcodeSHide  & 0xFF;

	_actionMenu[2]._menuId    = _opcodeAttach >> 8;
	_actionMenu[2]._actionId  = _opcodeAttach & 0xFF;

	_actionMenu[3]._menuId    = _opcodeForce  >> 8;
	_actionMenu[3]._actionId  = _opcodeForce  & 0xFF;

	_actionMenu[4]._menuId    = _opcodeSleep  >> 8;
	_actionMenu[4]._actionId  = _opcodeSleep  & 0xFF;

	_actionMenu[5]._menuId    = _opcodeEnter  >> 8;
	_actionMenu[5]._actionId  = _opcodeEnter  & 0xFF;

	_actionMenu[6]._menuId    = _opcodeClose  >> 8;
	_actionMenu[6]._actionId  = _opcodeClose  & 0xFF;

	_actionMenu[7]._menuId    = _opcodeKnock  >> 8;
	_actionMenu[7]._actionId  = _opcodeKnock  & 0xFF;

	_actionMenu[8]._menuId    = _opcodeEat    >> 8;
	_actionMenu[8]._actionId  = _opcodeEat    & 0xFF;

	_actionMenu[9]._menuId    = _opcodePlace  >> 8;
	_actionMenu[9]._actionId  = _opcodePlace  & 0xFF;

	_actionMenu[10]._menuId   = _opcodeOpen   >> 8;
	_actionMenu[10]._actionId = _opcodeOpen   & 0xFF;

	_actionMenu[11]._menuId   = _opcodeLeave  >> 8;
	_actionMenu[11]._actionId = _opcodeLeave  & 0xFF;
}
Ejemplo n.º 25
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.º 26
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.º 27
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.º 28
0
void ExtractMMApple::execute() {
	int i, j;
	unsigned short signature;
	char fname[256];

	Common::Filename inpath1(_inputPaths[0].path);
	Common::Filename inpath2(_inputPaths[1].path);
	Common::Filename &outpath = _outputPath;

	if (outpath.empty())
		// Standard output path
		outpath.setFullPath("out/");

	Common::File input1(inpath1, "rb");
	Common::File input2(inpath2, "rb");

	input1.seek(142080, SEEK_SET);
	input2.seek(143104, SEEK_SET);

	/* check signature */
	signature = input1.readUint16LE();
	if (signature != 0x0A31)
		error("Signature not found in disk 1!");

	signature = input2.readUint16LE();
	if (signature != 0x0032)
		error("Signature not found in disk 2!");

	outpath.setFullName("00.LFL");
	Common::File output(outpath, "wb");
	// All output should be xored
	output.setXorMode(0xFF);
	print("Creating 00.LFL...\n");

	/* write signature */
	output.writeUint16LE(signature);

	/* copy object flags */
	for (i = 0; i < 256; i++)
		output.writeByte(input1.readByte());

	/* copy room offsets */
	for (i = 0; i < NUM_ROOMS; i++) {
		room_disks_apple[i] = input1.readByte();
		output.writeByte(room_disks_apple[i]);
	}
	for (i = 0; i < NUM_ROOMS; i++) {
		room_sectors_apple[i] = input1.readByte();
		output.writeByte(room_sectors_apple[i]);
		room_tracks_apple[i] = input1.readByte();
		output.writeByte(room_tracks_apple[i]);
	}

	/* copy costume offsets */
	for (i = 0; i < 25; i++)
		output.writeByte(input1.readByte());
	for (i = 0; i < 25; i++)
		output.writeUint16LE(input1.readUint16LE());

	/* copy script offsets */
	for (i = 0; i < 160; i++)
		output.writeByte(input1.readByte());
	for (i = 0; i < 160; i++)
		output.writeUint16LE(input1.readUint16LE());

	/* copy sound offsets */
	for (i = 0; i < 70; i++)
		output.writeByte(input1.readByte());
	for (i = 0; i < 70; i++)
		output.writeUint16LE(input1.readUint16LE());

	/* NOTE: Extra 92 bytes of unknown data */

	for (i = 0; i < NUM_ROOMS; i++) {
		Common::File *input;

		if (room_disks_apple[i] == '1')
			input = &input1;
		else if (room_disks_apple[i] == '2')
			input = &input2;
		else
			continue;

		sprintf(fname, "%02i.LFL", i);
		outpath.setFullName(fname);
		output.open(outpath, "wb");

		print("Creating %s...\n", fname);
		input->seek((SectorOffset[room_tracks_apple[i]] + room_sectors_apple[i]) * 256, SEEK_SET);

		for (j = 0; j < ResourcesPerFile[i]; j++) {
			unsigned short len = input->readUint16LE();
			output.writeUint16LE(len);

			for (len -= 2; len > 0; len--)
				output.writeByte(input->readByte());
		}
		input->rewind();
	}
	print("All done!");
}
Ejemplo n.º 29
0
bool PatchedFile::load(Common::SeekableReadStream *file, const Common::String &patchName) {
	uint8 md5_p[16], md5_f[16];
	uint32 zctrllen, zdatalen, zextralen;
	Common::File patch;

	_patchName = patchName;

	// Open the patch
	if (!patch.open(_patchName)) {
		error("Unable to open patchfile %s", _patchName.c_str());
		return false;
	}

	// Check for appropriate signature
	if (patch.readUint32BE() != MKTAG('P','A','T','R')) {
		error("%s patchfile is corrupted", _patchName.c_str());
		return false;
	}

	// Check the version number
	if (patch.readUint16LE() != _kVersionMajor || patch.readUint16LE() > _kVersionMinor) {
		error("%s has a wrong version number (must be major = %d, minor <= %d)", _patchName.c_str(), _kVersionMajor, _kVersionMinor);
		return false;
	}

	_flags = patch.readUint32LE();

	// Check if the file to patch match
	Common::computeStreamMD5(*file, md5_f, _kMd5size);
	file->seek(0, SEEK_SET);
	patch.read(md5_p, 16);
	if (memcmp(md5_p, md5_f, 16) != 0 || (uint32)file->size() != patch.readUint32LE()) {
		Debug::debug(Debug::Patchr,"%s targets a different file", _patchName.c_str());
		return false;
	}

	// Read lengths from header
	_newSize = patch.readUint32LE();
	zctrllen = patch.readUint32LE();
	zdatalen = patch.readUint32LE();
	zextralen = patch.readUint32LE();

	patch.close();

	// Opens ctrl, diff and extra substreams
	Common::File *tmp;
	tmp = new Common::File;
	tmp->open(_patchName);
	_ctrl = new Common::SeekableSubReadStream(tmp, _kHeaderSize, _kHeaderSize + zctrllen, DisposeAfterUse::YES);
	if (_flags & FLAG_COMPRESS_CTRL)
		_ctrl = Common::wrapCompressedReadStream(_ctrl);

	//ctrl stream sanity checks
	if (_ctrl->size() % (3 * sizeof(uint32)) != 0) {
		error("%s patchfile is corrupted", _patchName.c_str());
		return false;
	}

	instrLeft = _ctrl->size() / (3 * sizeof(uint32));

	tmp = new Common::File;
	tmp->open(_patchName);
	_diff = new Common::SeekableSubReadStream(tmp, _kHeaderSize + zctrllen, _kHeaderSize + zctrllen + zdatalen, DisposeAfterUse::YES);
	_diff = Common::wrapCompressedReadStream(_diff);

	if (_flags & FLAG_MIX_DIFF_EXTRA)
		_extra = _diff;
	else {
		tmp = new Common::File;
		tmp->open(_patchName);
		_extra = new Common::SeekableSubReadStream(tmp, _kHeaderSize + zctrllen + zdatalen, _kHeaderSize + zctrllen + zdatalen + zextralen, DisposeAfterUse::YES);
		_extra = Common::wrapCompressedReadStream(_extra);
	}

	_file = file;

	readNextInst();

	return true;
}
Ejemplo n.º 30
0
void ExtractZakC64::execute() {
    int i, j;
    unsigned short signature;
    char fname[256];

    // Two disks...
    Common::Filename inpath1(_inputPaths[0].path);
    Common::Filename inpath2(_inputPaths[1].path);
    Common::Filename &outpath = _outputPath;

    if (outpath.empty())
        // Standard output path
        outpath.setFullPath("out/");

    Common::File input1(inpath1, "rb");
    Common::File input2(inpath2, "rb");

    /* check signature */
    signature = input1.readUint16LE();
    if (signature != 0x0A31)
        error("Signature not found in disk 1!");
    signature = input2.readUint16LE();
    if (signature != 0x0132)
        error("Signature not found in disk 2!");

    outpath.setFullName("00.LFL");
    Common::File output(outpath, "wb");
    output.setXorMode(0xFF);
    print("Creating 00.LFL...");

    /* write signature */
    output.writeUint16LE(signature);

    /* copy object flags */
    for (i = 0; i < 775; i++)
        output.writeByte(input1.readByte());

    /* copy room offsets */
    for (i = 0; i < NUM_ROOMS; i++) {
        room_disks_c64[i] = input1.readByte();
        output.writeByte(room_disks_c64[i]);
    }
    for (i = 0; i < NUM_ROOMS; i++) {
        room_sectors_c64[i] = input1.readByte();
        output.writeByte(room_sectors_c64[i]);
        room_tracks_c64[i] = input1.readByte();
        output.writeByte(room_tracks_c64[i]);
    }

    /* copy costume offsets */
    for (i = 0; i < 38; i++)
        output.writeByte(input1.readByte());
    for (i = 0; i < 38; i++)
        output.writeUint16LE(input1.readUint16LE());

    /* copy script offsets */
    for (i = 0; i < 155; i++)
        output.writeByte(input1.readByte());
    for (i = 0; i < 155; i++)
        output.writeUint16LE(input1.readUint16LE());

    /* copy sound offsets */
    for (i = 0; i < 127; i++)
        output.writeByte(input1.readByte());
    for (i = 0; i < 127; i++)
        output.writeUint16LE(input1.readUint16LE());

    output.close();

    for (i = 0; i < NUM_ROOMS; i++) {
        Common::File *input;

        if (room_disks_c64[i] == '1')
            input = &input1;
        else if (room_disks_c64[i] == '2')
            input = &input2;
        else
            continue;

        sprintf(fname, "%02i.LFL", i);
        outpath.setFullName(fname);
        output.open(outpath, "wb");

        print("Creating %s...", fname);
        input->seek((SectorOffset[room_tracks_c64[i]] + room_sectors_c64[i]) * 256, SEEK_SET);

        for (j = 0; j < ResourcesPerFile[i]; j++) {
            unsigned short len;

            do {
                len = input->readUint16LE();
                output.writeUint16LE(len);
            } while (len == 0xffff);

            for (len -= 2; len > 0; len--) {
                output.writeByte(input->readByte());
            }
        }

        input->rewind();
    }

    print("All done!");
}