void AGOSEngine::dumpVgaFile(const byte *vga) { const byte *pp; const byte *p; int16 count; pp = vga; p = pp + READ_BE_UINT16(pp + 10) + 20; count = READ_BE_UINT16(&((const VgaFile1Header_Common *) p)->animationCount); p = pp + READ_BE_UINT16(&((const VgaFile1Header_Common *) p)->animationTable); while (--count >= 0) { uint16 id = READ_BE_UINT16(&((const AnimationHeader_WW *) p)->id); dumpVgaScriptAlways(vga + READ_BE_UINT16(&((const AnimationHeader_WW *) p)->scriptOffs), id / 100, id); p += sizeof(AnimationHeader_WW); } pp = vga; p = pp + READ_BE_UINT16(pp + 10) + 20; count = READ_BE_UINT16(&((const VgaFile1Header_Common *) p)->imageCount); p = pp + READ_BE_UINT16(&((const VgaFile1Header_Common *) p)->imageTable); while (--count >= 0) { uint16 id = READ_BE_UINT16(&((const ImageHeader_WW *) p)->id); dumpVgaScriptAlways(vga + READ_BE_UINT16(&((const ImageHeader_WW *) p)->scriptOffs), id / 100, id); p += sizeof(ImageHeader_WW); } }
void IMuseDigital::getLipSync(int soundId, int syncId, int32 msPos, int32 &width, int32 &height) { int32 sync_size; byte *sync_ptr; msPos /= 16; if (msPos < 65536) { Common::StackLock lock(_mutex, "IMuseDigital::getLipSync()"); for (int l = 0; l < MAX_DIGITAL_TRACKS; l++) { Track *track = _track[l]; if (track->used && !track->toBeRemoved && (track->soundId == soundId)) { _sound->getSyncSizeAndPtrById(track->soundDesc, syncId, sync_size, &sync_ptr); if ((sync_size != 0) && (sync_ptr != NULL)) { sync_size /= 4; while (sync_size--) { if (READ_BE_UINT16(sync_ptr) >= msPos) break; sync_ptr += 4; } if (sync_size < 0) sync_ptr -= 4; else if (READ_BE_UINT16(sync_ptr) > msPos) sync_ptr -= 4; width = sync_ptr[2]; height = sync_ptr[3]; return; } } } } }
void SfxPlayer::loadSfxModule(uint16_t resNum, uint16_t delay, uint8_t pos) { debug(DBG_SND, "SfxPlayer::loadSfxModule(0x%X, %d, %d)", resNum, delay, pos); MutexStack(sys, _mutex); MemEntry *me = &res->_memList[resNum]; if (me->state == 1 && me->type == Resource::RT_MUSIC) { _resNum = resNum; memset(&_sfxMod, 0, sizeof(SfxModule)); _sfxMod.curOrder = pos; _sfxMod.numOrder = READ_BE_UINT16(me->bufPtr + 0x3E); debug(DBG_SND, "SfxPlayer::loadSfxModule() curOrder = 0x%X numOrder = 0x%X", _sfxMod.curOrder, _sfxMod.numOrder); for (int i = 0; i < 0x80; ++i) { _sfxMod.orderTable[i] = *(me->bufPtr + 0x40 + i); } if (delay == 0) { _delay = READ_BE_UINT16(me->bufPtr); } else { _delay = delay; } _delay = _delay * 60 / 7050; _sfxMod.data = me->bufPtr + 0xC0; debug(DBG_SND, "SfxPlayer::loadSfxModule() eventDelay = %d ms", _delay); prepareInstruments(me->bufPtr + 2); } else { warning("SfxPlayer::loadSfxModule() ec=0x%X", 0xF8); } }
void loadRel(char *pRelName) { uint16 numEntry; uint16 i; byte *ptr; checkDataDisk(-1); for (i = 0; i < NUM_MAX_REL; i++) { if (relTable[i].data) { free(relTable[i].data); relTable[i].data = NULL; relTable[i].size = 0; } } ptr = readBundleFile(findFileInBundle(pRelName)); setMouseCursor(MOUSE_CURSOR_DISK); numEntry = READ_BE_UINT16(ptr); ptr += 2; assert(numEntry <= NUM_MAX_REL); for (i = 0; i < numEntry; i++) { relTable[i].size = READ_BE_UINT16(ptr); ptr += 2; relTable[i].obj1Param1 = READ_BE_UINT16(ptr); ptr += 2; relTable[i].obj1Param2 = READ_BE_UINT16(ptr); ptr += 2; relTable[i].obj2Param = READ_BE_UINT16(ptr); ptr += 2; } for (i = 0; i < numEntry; i++) { if (relTable[i].size) { relTable[i].data = (byte *)malloc(relTable[i].size); assert(relTable[i].data); memcpy(relTable[i].data, ptr, relTable[i].size); ptr += relTable[i].size; } } #ifdef DUMP_SCRIPTS { uint16 s; char buffer[256]; for (s = 0; s < numEntry; s++) { if (relTable[s].size) { sprintf(buffer, "%s_%03d.txt", pRelName, s); decompileScript(relTable[s].data, NULL, relTable[s].size, s); dumpScript(buffer); } } } #endif }
/*! \todo Is script size of 0 valid? * \todo Fix script dump code */ void loadRel(char *pRelName) { uint16 numEntry; uint16 i; uint16 size, p1, p2, p3; byte *ptr, *dataPtr; checkDataDisk(-1); objectScripts.clear(); relTable.clear(); ptr = dataPtr = readBundleFile(findFileInBundle(pRelName)); setMouseCursor(MOUSE_CURSOR_DISK); numEntry = READ_BE_UINT16(ptr); ptr += 2; for (i = 0; i < numEntry; i++) { size = READ_BE_UINT16(ptr); ptr += 2; p1 = READ_BE_UINT16(ptr); ptr += 2; p2 = READ_BE_UINT16(ptr); ptr += 2; p3 = READ_BE_UINT16(ptr); ptr += 2; RawObjectScriptPtr tmp(new RawObjectScript(size, p1, p2, p3)); assert(tmp); relTable.push_back(tmp); } for (i = 0; i < numEntry; i++) { size = relTable[i]->_size; // TODO: delete the test? if (size) { relTable[i]->setData(*scriptInfo, ptr); ptr += size; } } free(dataPtr); #ifdef DUMP_SCRIPTS { uint16 s; char buffer[256]; for (s = 0; s < numEntry; s++) { if (relTable[s]->_size) { sprintf(buffer, "%s_%03d.txt", pRelName, s); decompileScript((const byte *)relTable[s]->getString(0), relTable[s]->_size, s); dumpScript(buffer); } } } #endif }
bool Player_V3M::loadMusic(const byte *ptr) { Common::MacResManager resource; bool found = false; for (int i = 0; i < ARRAYSIZE(loomFileNames); i++) { if (resource.open(loomFileNames[i])) { found = true; break; } } if (!found) { return false; } if (ptr[4] != 's' || ptr[5] != 'o') { // Like the original we ignore all sound resources which do not have // a 'so' tag in them. // See bug #3602239 ("Mac Loom crashes using opening spell on // gravestone") for a case where this is required. Loom Mac tries to // play resource 11 here. This resource is no Mac sound resource // though, it is a PC Speaker resource. A test with the original // interpreter also has shown that no sound is played while the // screen is shaking. debug(5, "Player_V3M::loadMusic: Skipping unknown music type %02X%02X", ptr[4], ptr[5]); resource.close(); return false; } uint i; for (i = 0; i < 5; i++) { int instrument = READ_BE_UINT16(ptr + 20 + 2 * i); int offset = READ_BE_UINT16(ptr + 30 + 2 * i); _channel[i]._looped = false; _channel[i]._length = READ_BE_UINT16(ptr + offset + 4) * 3; _channel[i]._data = ptr + offset + 6; _channel[i]._pos = 0; _channel[i]._pitchModifier = 0; _channel[i]._velocity = 0; _channel[i]._remaining = 0; _channel[i]._notesLeft = true; Common::SeekableReadStream *stream = resource.getResource(RES_SND, instrument); if (_channel[i].loadInstrument(stream)) { debug(6, "Player_V3M::loadMusic: Channel %d - Loaded Instrument %d (%s)", i, instrument, resource.getResName(RES_SND, instrument).c_str()); } else { resource.close(); return false; } } resource.close(); return true; }
void playSoundRaw(uint8_t channel, const uint8_t *data, uint16_t freq, uint8_t volume) { int len = READ_BE_UINT16(data) * 2; const int loopLen = READ_BE_UINT16(data + 2) * 2; if (loopLen != 0) { len = loopLen; } uint8_t *sample = convertToWav(data + 8, freq, len); if (sample) { playSoundWav(channel, sample, volume, (loopLen != 0) ? -1 : 0); free(sample); } }
/** * Find a word in the dictionary * Uses an algorithm hopefully like the one Sierra used. Returns the ID * of the word and the length in flen. Returns -1 if not found. * * Thomas Akesson, November 2001 */ int AgiEngine::findWord(char *word, int *flen) { int mchr = 0; // matched chars int len, fchr, id = -1; uint8 *p = words; uint8 *q = words + wordsFlen; *flen = 0; debugC(2, kDebugLevelScripts, "find_word(%s)", word); if (word[0] >= 'a' && word[0] <= 'z') fchr = word[0] - 'a'; else return -1; len = strlen(word); // Get the offset to the first word beginning with the // right character p += READ_BE_UINT16(p + 2 * fchr); while (p[0] >= mchr) { if (p[0] == mchr) { p++; // Loop through all matching characters while ((p[0] ^ word[mchr]) == 0x7F && mchr < len) { mchr++; p++; } // Check if this is the last character of the word // and if it matches if ((p[0] ^ word[mchr]) == 0xFF && mchr < len) { mchr++; if (word[mchr] == 0 || word[mchr] == 0x20) { id = READ_BE_UINT16(p + 1); *flen = mchr; } } } if (p >= q) return -1; // Step to the next word while (p[0] < 0x80) p++; p += 3; } return id; }
void Sound::playSound(uint16 sound, uint16 volume, uint8 channel) { if (channel == 0) _mixer->stopID(SOUND_CH0); else _mixer->stopID(SOUND_CH1); if (!_soundData) { warning("Sound::playSound(%04X, %04X) called with a section having been loaded", sound, volume); return; } if (sound > _soundsTotal) { debug(5, "Sound::playSound %d ignored, only %d sfx in file", sound, _soundsTotal); return; } volume = (volume & 0x7F) << 1; sound &= 0xFF; // Note: All those tables are big endian. Don't ask me why. *sigh* // Use the sample rate from game data, see bug #1507757. uint16 sampleRate = READ_BE_UINT16(_sampleRates + (sound << 2)); if (sampleRate > 11025) sampleRate = 11025; uint32 dataOfs = READ_BE_UINT16(_sfxInfo + (sound << 3) + 0) << 4; uint32 dataSize = READ_BE_UINT16(_sfxInfo + (sound << 3) + 2); uint32 dataLoop = READ_BE_UINT16(_sfxInfo + (sound << 3) + 6); dataOfs += _sfxBaseOfs; Audio::SeekableAudioStream *stream = Audio::makeRawStream(_soundData + dataOfs, dataSize, sampleRate, Audio::FLAG_UNSIGNED, DisposeAfterUse::NO); Audio::AudioStream *output = 0; if (dataLoop) { uint32 loopSta = dataSize - dataLoop; uint32 loopEnd = dataSize; output = Audio::makeLoopingAudioStream(stream, Audio::Timestamp(0, loopSta, sampleRate), Audio::Timestamp(0, loopEnd, sampleRate), 0); } else { output = stream; } if (channel == 0) _mixer->playStream(Audio::Mixer::kSFXSoundType, &_ingameSound0, output, SOUND_CH0, volume, 0); else _mixer->playStream(Audio::Mixer::kSFXSoundType, &_ingameSound1, output, SOUND_CH1, volume, 0); }
static void convertCompressedImage(const byte *src, byte *dst, uint8 colorDepth, int height, int width, bool horizontal = true) { const byte *plane[kMaxColorDepth]; byte *uncptr[kMaxColorDepth]; int length, i, j; byte *uncbfrout = (byte *)malloc(width * height); length = (width + 15) / 16 * height; for (i = 0; i < colorDepth; ++i) { plane[i] = src + READ_BE_UINT16(src + i * 4) + READ_BE_UINT16(src + i * 4 + 2); uncptr[i] = (uint8 *)malloc(length * 2); uncompressPlane(plane[i], uncptr[i], length); plane[i] = uncptr[i]; } byte *uncbfroutptr = uncbfrout; for (i = 0; i < length; ++i) { uint16 w[kMaxColorDepth]; for (j = 0; j < colorDepth; ++j) { w[j] = READ_BE_UINT16(plane[j]); plane[j] += 2; } bitplaneToChunky(w, colorDepth, uncbfroutptr); } uncbfroutptr = uncbfrout; const int chunkSize = colorDepth > 4 ? 16 : 8; if (horizontal) { for (j = 0; j < height; ++j) { for (i = 0; i < width / 16; ++i) { memcpy(dst + width * chunkSize / 16 * j + chunkSize * i, uncbfroutptr, chunkSize); uncbfroutptr += chunkSize; } } } else { for (i = 0; i < width / 16; ++i) { for (j = 0; j < height; ++j) { memcpy(dst + width * chunkSize / 16 * j + chunkSize * i, uncbfroutptr, chunkSize); uncbfroutptr += chunkSize; } } } free(uncbfrout); for (i = 0; i < colorDepth; ++i) { free(uncptr[i]); } }
byte loadCtOS(const char *ctName) { debugC(1, kCineDebugCollision, "loadCtOS(\"%s\")", ctName); byte *ptr, *dataPtr; int16 foundFileIdx = findFileInBundle(ctName); if (foundFileIdx == -1) { warning("loadCtOS: Unable to find collision data file '%s'", ctName); // FIXME: Rework this function's return value policy and return an appropriate value here. // The return value isn't yet used for anything so currently it doesn't really matter. return 0; } if (currentCtName != ctName) strcpy(currentCtName, ctName); ptr = dataPtr = readBundleFile(foundFileIdx); uint16 bpp = READ_BE_UINT16(ptr); ptr += 2; if (bpp == 8) { renderer->loadCt256(ptr, ctName); } else { gfxConvertSpriteToRaw(collisionPage, ptr + 32, 160, 200); renderer->loadCt16(ptr, ctName); } free(dataPtr); return 0; }
byte loadCt(const char *ctName) { uint16 header[32]; strcpy(currentCtName, ctName); byte *ptr = readBundleFile(findFileInBundle(ctName)); if (gameType == Cine::GID_OS) { uint16 bpp = READ_BE_UINT16(ptr); ptr += 2; if (bpp == 8) { ptr += 3 * 256; loadCtHigh(ptr); } else { ptr += 32; gfxResetRawPage(page3Raw); gfxConvertSpriteToRaw(page3Raw, ptr, 160, 200); } } else { loadRelatedPalette(ctName); assert(strstr(ctName, ".NEO")); Common::MemoryReadStream readS(ptr, 32); for (int i = 0; i < 16; i++) { header[i] = readS.readUint16BE(); } gfxConvertSpriteToRaw(page3Raw, ptr + 0x80, 160, 200); } return 0; }
void SoundManager::regenbruit() { int i = 69876; for (int j = 0; j < 100; j++) { _cfiphBuffer[j] = READ_BE_UINT16(&_noiseBuf[i]); i += 2; } }
/** * This function does noting but load a raw resource into memory, * if further decoding is required, it must be done by another * routine. NULL is returned if unsucsessfull. */ uint8 *AgiLoader_v2::loadVolRes(struct AgiDir *agid) { uint8 *data = NULL; char x[MAXPATHLEN], *path; Common::File fp; unsigned int sig; sprintf(x, "vol.%i", agid->volume); path = x; debugC(3, kDebugLevelResources, "Vol res: path = %s", path); if (agid->offset != _EMPTY && fp.open(path)) { debugC(3, kDebugLevelResources, "loading resource at offset %d", agid->offset); fp.seek(agid->offset, SEEK_SET); fp.read(&x, 5); if ((sig = READ_BE_UINT16((uint8 *) x)) == 0x1234) { agid->len = READ_LE_UINT16((uint8 *) x + 3); data = (uint8 *) calloc(1, agid->len + 32); if (data != NULL) { fp.read(data, agid->len); } else { exit(1); } } else { warning("AgiLoader_v2::loadVolRes: bad signature %04x", sig); return 0; } fp.close(); } else { // we have a bad volume resource // set that resource to NA agid->offset = _EMPTY; } return data; }
int Graphics::drawChar16(uint8 *dst, int dstPitch, uint8 chr, int x, int y, uint16 color) { dst += y * dstPitch + x; uint8 color1 = color & 0xFF; uint8 color2 = color >> 8; assert(chr >= 32 && chr < 32 + _fontSize); const uint8 *chrData = _fontData + _fontOffs[chr - 32]; int chrHeight = chrData[1]; int chrWidth = chrData[2]; chrData += 3; while (chrHeight--) { int shiftCount = 0; int mask = 0; for (int i = 0; i < chrWidth; ++i) { if (shiftCount == 0) { mask = READ_BE_UINT16(chrData); chrData += 2; shiftCount = 8; } int b = (mask & 0xC000) >> 14; mask <<= 2; --shiftCount; if (b) { if (b & 2) { dst[i] = color2; } else { dst[i] = color1; } } } dst += dstPitch; } return chrWidth; }
byte *AGOSEngine::convertImage(VC10_state *state, bool compressed) { int length, i, j; uint8 colorDepth = 4; if (getGameType() == GType_SIMON1) { if (((_videoLockOut & 0x20) && !state->palette) || ((getFeatures() & GF_32COLOR) && state->palette != 0xC0)) { colorDepth = 5; } } const byte *src = state->srcPtr; int width = state->width * 16; int height = state->height; free(_planarBuf); _planarBuf = (byte *)malloc(width * height); byte *dst = _planarBuf; if (compressed) { convertCompressedImage(src, dst, colorDepth, height, width, (getGameType() == GType_PN)); } else { length = (width + 15) / 16 * height; for (i = 0; i < length; i++) { uint16 w[kMaxColorDepth]; if (getGameType() == GType_SIMON1 && colorDepth == 4) { for (j = 0; j < colorDepth; ++j) { w[j] = READ_BE_UINT16(src + j * length * 2); } if (state->palette == 0xC0) { bitplaneToChunkyText(w, colorDepth, dst); } else { bitplaneToChunky(w, colorDepth, dst); } src += 2; } else { for (j = 0; j < colorDepth; ++j) { w[j] = READ_BE_UINT16(src); src += 2; } bitplaneToChunky(w, colorDepth, dst); } } } return _planarBuf; }
void Player::handlePattern(uint8_t channel, uint8_t *&data, Pattern *pat) { pat->note_1 = READ_BE_UINT16(data + 0); pat->note_2 = READ_BE_UINT16(data + 2); data += 4; if (pat->note_1 != 0xFFFD) { uint16_t sample = (pat->note_2 & 0xF000) >> 12; if (sample != 0) { uint8_t *ptr = _sfxMod.samples[sample - 1].buf.buf; fprintf(stdout, "Preparing sample %d ptr = %p\n", sample, ptr); if (ptr != 0) { pat->sample_volume = _sfxMod.samples[sample - 1].volume; pat->sample_start = 8; pat->sample_buffer = ptr; pat->period_value = READ_BE_UINT16(ptr) * 2; uint16_t loopLen = READ_BE_UINT16(ptr + 2) * 2; if (loopLen != 0) { pat->loopPos = pat->period_value; pat->loopData = ptr; pat->loopLen = loopLen; } else { pat->loopPos = 0; pat->loopData = 0; pat->loopLen = 0; } int16_t m = pat->sample_volume; uint8_t effect = pat->note_2 & 0x0F00; fprintf(stdout, "effect = %d\n", effect); if (effect == 5) { // volume up uint8_t volume = (pat->note_2 & 0xFF); m += volume; if (m > 0x3F) { m = 0x3F; } } else if (effect == 6) { // volume down uint8_t volume = (pat->note_2 & 0xFF); m -= volume; if (m < 0) { m = 0; } } Mix_setChannelVolume(channel, m); pat->sample_volume = m; } } }
void SfxPlayer::prepareInstruments(const uint8_t *p) { memset(_sfxMod.samples, 0, sizeof(_sfxMod.samples)); for (int i = 0; i < 15; ++i) { SfxInstrument *ins = &_sfxMod.samples[i]; uint16_t resNum = READ_BE_UINT16(p); p += 2; if (resNum != 0) { ins->volume = READ_BE_UINT16(p); MemEntry *me = &_res->_memList[resNum]; if (me->status == Resource::STATUS_LOADED && me->type == 0) { ins->data = me->bufPtr; debug(DBG_SND, "Loaded instrument 0x%X n=%d volume=%d", resNum, i, ins->volume); } else { error("Error loading instrument 0x%X", resNum); } } p += 2; // skip volume } }
void SpeechManager::regenbruit() { int i = kOffsetB3 + 8590; int j = 0; do { _cfiphBuffer[j] = READ_BE_UINT16(&_vm->_mem[(kAdrNoise3 * 16) + i]); i += 2; ++j; } while (i < kOffsetB3 + 8790); }
void Kernel::loadSelectorNames() { Resource *r = _resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SELECTORS), 0); bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); // Starting with KQ7, Mac versions have a BE name table. GK1 Mac and earlier (and all // other platforms) always use LE. bool isBE = (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_2_1 && g_sci->getGameId() != GID_GK1); if (!r) { // No such resource? // Check if we have a table for this game // Some demos do not have a selector table Common::StringArray staticSelectorTable = checkStaticSelectorNames(); if (staticSelectorTable.empty()) error("Kernel: Could not retrieve selector names"); else warning("No selector vocabulary found, using a static one"); for (uint32 i = 0; i < staticSelectorTable.size(); i++) { _selectorNames.push_back(staticSelectorTable[i]); if (oldScriptHeader) _selectorNames.push_back(staticSelectorTable[i]); } return; } int count = (isBE ? READ_BE_UINT16(r->data) : READ_LE_UINT16(r->data)) + 1; // Counter is slightly off for (int i = 0; i < count; i++) { int offset = isBE ? READ_BE_UINT16(r->data + 2 + i * 2) : READ_LE_UINT16(r->data + 2 + i * 2); int len = isBE ? READ_BE_UINT16(r->data + offset) : READ_LE_UINT16(r->data + offset); Common::String tmp((const char *)r->data + offset + 2, len); _selectorNames.push_back(tmp); //debug("%s", tmp.c_str()); // Early SCI versions used the LSB in the selector ID as a read/write // toggle. To compensate for that, we add every selector name twice. if (oldScriptHeader) _selectorNames.push_back(tmp); } }
void SmushDecoder::handleIACT(const byte *src, int32 size) { int32 bsize = size - 18; const byte *d_src = src + 18; while (bsize > 0) { if (_IACTpos >= 2) { int32 len = READ_BE_UINT16(_IACToutput) + 2; len -= _IACTpos; if (len > bsize) { memcpy(_IACToutput + _IACTpos, d_src, bsize); _IACTpos += bsize; bsize = 0; } else { byte *output_data = new byte[4096]; memcpy(_IACToutput + _IACTpos, d_src, len); byte *dst = output_data; byte *d_src2 = _IACToutput; d_src2 += 2; int32 count = 1024; byte variable1 = *d_src2++; byte variable2 = variable1 / 16; variable1 &= 0x0f; do { byte value; value = *(d_src2++); if (value == 0x80) { *dst++ = *d_src2++; *dst++ = *d_src2++; } else { int16 val = (int8)value << variable2; *dst++ = val >> 8; *dst++ = (byte)(val); } value = *(d_src2++); if (value == 0x80) { *dst++ = *d_src2++; *dst++ = *d_src2++; } else { int16 val = (int8)value << variable1; *dst++ = val >> 8; *dst++ = (byte)(val); } } while (--count); if (!_stream) { _stream = Audio::makeQueuingAudioStream(22050, true); g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, _stream); } _stream->queueBuffer(output_data, 0x1000, DisposeAfterUse::YES, Audio::FLAG_STEREO | Audio::FLAG_16BITS); bsize -= len; d_src += len; _IACTpos = 0; } } else { if (bsize > 1 && _IACTpos == 0) {
void SfxPlayer::handlePattern(uint8_t channel, const uint8_t *data) { SfxPattern pat; memset(&pat, 0, sizeof(SfxPattern)); pat.note_1 = READ_BE_UINT16(data + 0); pat.note_2 = READ_BE_UINT16(data + 2); if (pat.note_1 != 0xFFFD) { uint16_t sample = (pat.note_2 & 0xF000) >> 12; if (sample != 0) { uint8_t *ptr = _sfxMod.samples[sample - 1].data; if (ptr != 0) { debug(DBG_SND, "SfxPlayer::handlePattern() preparing sample %d", sample); pat.sampleVolume = _sfxMod.samples[sample - 1].volume; pat.sampleStart = 8; pat.sampleBuffer = ptr; pat.sampleLen = READ_BE_UINT16(ptr) * 2; uint16_t loopLen = READ_BE_UINT16(ptr + 2) * 2; if (loopLen != 0) { pat.loopPos = pat.sampleLen; pat.loopData = ptr; pat.loopLen = loopLen; } else { pat.loopPos = 0; pat.loopData = 0; pat.loopLen = 0; } int16_t m = pat.sampleVolume; uint8_t effect = (pat.note_2 & 0x0F00) >> 8; if (effect == 5) { // volume up uint8_t volume = (pat.note_2 & 0xFF); m += volume; if (m > 0x3F) { m = 0x3F; } } else if (effect == 6) { // volume down uint8_t volume = (pat.note_2 & 0xFF); m -= volume; if (m < 0) { m = 0; } } mixer->setChannelVolume(channel, m); pat.sampleVolume = m; }
void ExtractCine::unpackAllResourceFiles(const Common::Filename &filename) { Common::File f(filename, "rb"); uint32 unpackedSize, packedSize; { char header[8]; f.read_throwsOnError(header, 8); if (memcmp(header, "ABASECP", 7) == 0) { unpackedSize = f.readUint32BE(); packedSize = f.readUint32BE(); } else { unpackedSize = packedSize = f.pos(); /* Get file size */ f.seek(0, SEEK_SET); } } assert(unpackedSize >= packedSize); uint8 *buf = (uint8 *)calloc(unpackedSize, 1); assert(buf); f.read_throwsOnError(buf, packedSize); if (packedSize != unpackedSize) { CineUnpacker cineUnpacker; if (!cineUnpacker.unpack(buf, packedSize, buf, unpackedSize)) { error("Failed to unpack 'vol.cnf' data"); } } unsigned int resourceFilesCount = READ_BE_UINT16(&buf[0]); unsigned int entrySize = READ_BE_UINT16(&buf[2]); print("--- Unpacking all %d resource files from 'vol.cnf' (entrySize = %d):", resourceFilesCount, entrySize); char resourceFileName[9]; for (unsigned int i = 0; i < resourceFilesCount; ++i) { memcpy(resourceFileName, &buf[4 + i * entrySize], 8); resourceFileName[8] = 0; Common::File fpResFile(resourceFileName, "rb"); print("--- Unpacking resource file %s:", resourceFileName); unpackFile(fpResFile); } free(buf); }
void loadObject(char *pObjectName) { debug(5, "loadObject(\"%s\")", pObjectName); uint16 numEntry; uint16 entrySize; uint16 i; byte *ptr, *dataPtr; checkDataDisk(-1); ptr = dataPtr = readBundleFile(findFileInBundle(pObjectName)); setMouseCursor(MOUSE_CURSOR_DISK); numEntry = READ_BE_UINT16(ptr); ptr += 2; entrySize = READ_BE_UINT16(ptr); ptr += 2; assert(numEntry <= NUM_MAX_OBJECT); for (i = 0; i < numEntry; i++) { if (g_cine->_objectTable[i].costume != -2 && g_cine->_objectTable[i].costume != -3) { // flag is keep? Common::MemoryReadStream readS(ptr, entrySize); g_cine->_objectTable[i].x = readS.readSint16BE(); g_cine->_objectTable[i].y = readS.readSint16BE(); g_cine->_objectTable[i].mask = readS.readUint16BE(); g_cine->_objectTable[i].frame = readS.readSint16BE(); g_cine->_objectTable[i].costume = readS.readSint16BE(); readS.read(g_cine->_objectTable[i].name, 20); g_cine->_objectTable[i].part = readS.readUint16BE(); } ptr += entrySize; } if (!strcmp(pObjectName, "INTRO.OBJ")) { for (i = 0; i < 10; i++) { g_cine->_objectTable[i].costume = 0; } } free(dataPtr); }
// Elvira 2 and Waxworks specific void AGOSEngine::doMenuStrip(uint menuNum) { uint i; const uint var = (getGameType() == GType_WW) ? 11 : 1; for (i = 111; i != 115; i++) disableBox(i); for (i = var; i != (var + 5); i++) _variableArray[i] = 0; byte *srcPtr = _menuBase; while (menuNum--) { while (READ_BE_UINT16(srcPtr) != 0) srcPtr += 2; srcPtr += 2; } uint id = 111; uint v = var; while (READ_BE_UINT16(srcPtr) != 0) { uint verb = READ_BE_UINT16(srcPtr); _variableArray[v] = verb; HitArea *ha = findBox(id); if (ha != NULL) { ha->flags &= ~kBFBoxDead; ha->verb = verb; } id++; srcPtr += 2; v++; } _variableArray[var + 4] = id - 111; if (getGameType() == GType_WW) { setWindowImageEx(2, 102); } else { setWindowImageEx(2, 103); } }
void Player::loadInstruments(const uint8_t *p) { memset(_sfxMod.samples, 0, sizeof(_sfxMod.samples)); for (int i = 0; i < 0xF; ++i) { SfxInstrument *ins = &_sfxMod.samples[i]; ins->resId = READ_BE_UINT16(p); p += 2; if (ins->resId != 0) { ins->volume = READ_BE_UINT16(p); char path[MAXPATHLEN]; snprintf(path, sizeof(path), kSndFilePath, ins->resId); ins->buf = readFile(path); if (ins->buf.buf) { memset(ins->buf.buf + 8, 0, 4); fprintf(stdout, "Loaded instrument '%s' n=%d volume=%d\n", path, i, ins->volume); } else { fprintf(stderr, "Error loading instrument '%s'\n", path); } } p += 2; // volume } }
bool Player_V5M::getNextNote(int ch, uint32 &samples, int &pitchModifier, byte &velocity) { if (_channel[ch]._pos >= _channel[ch]._length) { if (!_channel[ch]._looped) { _channel[ch]._notesLeft = false; return false; } // FIXME: Jamieson630: The jump seems to be happening // too quickly! There should maybe be a pause after // the last Note Off? But I couldn't find one in the // MI1 Lookout music, where I was hearing problems. _channel[ch]._pos = 0; } uint16 duration = READ_BE_UINT16(&_channel[ch]._data[_channel[ch]._pos]); byte note = _channel[ch]._data[_channel[ch]._pos + 2]; samples = durationToSamples(duration); if (note != 1) { _channel[ch]._instrument.newNote(); } if (note > 1) { pitchModifier = noteToPitchModifier(note, &_channel[ch]._instrument); velocity = _channel[ch]._data[_channel[ch]._pos + 3]; } else if (note == 1) { // This is guesswork, but Monkey Island uses two different // "special" note values: 0, which is clearly a rest, and 1 // which is... I thought at first it was a "soft" key off, to // fade out the note, but listening to the music in a Mac // emulator (which unfortunately doesn't work all that well), // I hear no trace of fading out. // // It could mean "change the volume on the current note", but // I can't hear that either, and it always seems to use the // exact same velocity on this note. // // So it appears it really just is a "hold the current note", // but why? Couldn't they just have made the original note // longer? pitchModifier = _channel[ch]._pitchModifier; velocity = _channel[ch]._velocity; } else { pitchModifier = 0; velocity = 0; } _channel[ch]._pos += 4; if (_channel[ch]._pos >= _channel[ch]._length) { samples = _lastNoteSamples[ch]; } return true; }
bool SoundDesc::loadSND(byte *data, uint32 dSize) { assert(dSize > 6); _type = SOUND_SND; _data = data; _dataPtr = data + 6; _frequency = MAX((int16) READ_BE_UINT16(data + 4), (int16) 4700); _flag = data[0] ? (data[0] & 0x7F) : 8; data[0] = 0; _size = MIN(READ_BE_UINT32(data), dSize - 6); return true; }
void Player::loadSfxModule(int num) { char path[MAXPATHLEN]; snprintf(path, sizeof(path), kSfxFilePath, num); _sfxMod.buf = readFile(path); if (_sfxMod.buf.buf) { uint8_t *p = _sfxMod.buf.buf; _sfxMod.curOrder = 0; _sfxMod.numOrder = READ_BE_UINT16(p + 0x3E); fprintf(stdout, "curOrder = 0x%X numOrder = 0x%X\n", _sfxMod.curOrder, _sfxMod.numOrder); for (int i = 0; i < 0x80; ++i) { _sfxMod.orderTable[i] = *(p + 0x40 + i); } _delay = READ_BE_UINT16(p); // _delay = 15700; _delay = _delay * 60 / 7050; _bufData = p + 0xC0; fprintf(stdout, "eventDelay = %d\n", _delay); loadInstruments(p + 2); stop(); start(); } }
void loadMsg(char *pMsgName) { uint32 sourceSize; checkDataDisk(-1); g_cine->_messageTable.clear(); byte *dataPtr = readBundleFile(findFileInBundle(pMsgName), &sourceSize); setMouseCursor(MOUSE_CURSOR_DISK); uint count = READ_BE_UINT16(dataPtr); uint messageLenPos = 2; uint messageDataPos = messageLenPos + 2 * count; // Read in the messages for (uint i = 0; i < count; i++) { // Read message's length uint messageLen = READ_BE_UINT16(dataPtr + messageLenPos); messageLenPos += 2; // Store the read message. // This code works around input data that has empty strings residing outside the input // buffer (e.g. message indexes 58-254 in BATEAU.MSG in PROCS08 in Operation Stealth). if (messageDataPos < sourceSize) { g_cine->_messageTable.push_back((const char *)(dataPtr + messageDataPos)); } else { if (messageLen > 0) { // Only warn about overflowing non-empty strings warning("loadMsg(%s): message (%d. / %d) is overflowing the input buffer. Replacing it with an empty string", pMsgName, i + 1, count); } else { debugC(5, kCineDebugPart, "loadMsg(%s): empty message (%d. / %d) resides outside input buffer", pMsgName, i + 1, count); } // Message resides outside the input buffer so we replace it with an empty string g_cine->_messageTable.push_back(""); } // Jump to the next message messageDataPos += messageLen; } free(dataPtr); }