bool createIDMap(PAKFile &out, const ExtractInformation *eI, const int *needList) { int dataEntries = 0; // Count entries in the need list for (const int *n = needList; *n != -1; ++n) ++dataEntries; const int mapSize = 2 + dataEntries * (2 + 1 + 4); uint8 *map = new uint8[mapSize]; uint8 *dst = map; WRITE_BE_UINT16(dst, dataEntries); dst += 2; for (const int *id = needList; *id != -1; ++id) { WRITE_BE_UINT16(dst, *id); dst += 2; const ExtractFilename *fDesc = getFilenameDesc(*id); if (!fDesc) return false; *dst++ = getTypeID(fDesc->type); WRITE_BE_UINT32(dst, getFilename(eI, *id)); dst += 4; } char filename[12]; if (!getFilename(filename, eI, 0)) { fprintf(stderr, "ERROR: Could not create ID map for game\n"); return false; } out.removeFile(filename); if (!out.addFile(filename, map, mapSize)) { fprintf(stderr, "ERROR: Could not add ID map \"%s\" to kyra.dat\n", filename); return false; } return true; }
static void writeFakeChar(std::vector<byte> &output, uint32 c, Encoding encoding) { byte data[2]; switch (encoding) { case kEncodingASCII: case kEncodingLatin9: case kEncodingUTF8: case kEncodingCP1250: case kEncodingCP1251: case kEncodingCP1252: case kEncodingCP932: case kEncodingCP936: case kEncodingCP949: case kEncodingCP950: output.push_back(c); break; case kEncodingUTF16LE: WRITE_LE_UINT16(data, c); output.push_back(data[0]); output.push_back(data[1]); break; case kEncodingUTF16BE: WRITE_BE_UINT16(data, c); output.push_back(data[0]); output.push_back(data[1]); break; default: break; } }
void Glyph::convertChar16x16(uint8 *dst) const { const uint8 *src = plainData; dst += yOffset * 2; for (int y = 0; y < height; ++y) { uint16 mask = 1 << (15 - xOffset); const uint8 *curSrc = src; uint16 line = 0; uint8 d = 0; for (int x = 0; x < width; ++x) { if (x == 0 || x == 8) d = *curSrc++; if (d & 0x80) line |= mask; d <<= 1; mask >>= 1; } WRITE_BE_UINT16(dst, line); dst += 2; src += pitch; } }
/** * Handle a phoneme * @remarks Originally called 'trait_ph' */ void SpeechManager::handlePhoneme() { const uint16 deca[3] = {300, 30, 40}; uint16 startPos = _cfiphBuffer[_phonemeNumb - 1] + deca[_typlec]; uint16 endPos = _cfiphBuffer[_phonemeNumb] + deca[_typlec]; int wordCount = endPos - startPos; startPos /= 2; endPos /= 2; for (int i = startPos, currWord = 0; i < endPos; i++, currWord += 2) WRITE_BE_UINT16(&_vm->_mem[(kAdrWord * 16) + currWord], _cfiphBuffer[i]); _ptr_oct = 0; int currWord = 0; initQueue(); do { moveQueue(); charg_car(currWord); trait_car(); } while (currWord < wordCount); moveQueue(); trait_car(); entroct((int)'#'); }
bool createIDMap(PAKFile &out, const Game *g, const int *needList) { int dataEntries = 0; // Count entries in the need list and check whether the resources are // present for (const int *n = needList; *n != -1; ++n) { char filename[12]; if (!getFilename(filename, g, *n) || !out.getFileList()->findEntry(filename)) { fprintf(stderr, "ERROR: Could not find need %d for game %04X", *n, createGameDef(g)); return false; } ++dataEntries; } const int mapSize = 2 + dataEntries * (2 + 1 + 4); uint8 *map = new uint8[mapSize]; uint8 *dst = map; WRITE_BE_UINT16(dst, dataEntries); dst += 2; for (const int *id = needList; *id != -1; ++id) { WRITE_BE_UINT16(dst, *id); dst += 2; const ExtractFilename *fDesc = getFilenameDesc(*id); if (!fDesc) { delete[] map; return false; } *dst++ = fDesc->type; WRITE_BE_UINT32(dst, getFilename(g, *id)); dst += 4; } char filename[12]; if (!getFilename(filename, g, 0)) { fprintf(stderr, "ERROR: Could not create ID map for game\n"); delete[] map; return false; } if (!out.addFile(filename, map, mapSize)) { fprintf(stderr, "ERROR: Could not add ID map \"%s\" to kyra.dat\n", filename); delete[] map; return false; } return true; }
int main(int argc, char *argv[]) { if (argc != 2) { printHelp(argv[0]); return -1; } PAKFile out; // First step: Write out all resources. outputAllResources(out); // Second step: Write all game version information std::vector<GameDef> games; outputAllGames(out, games); // Third step: Write index file byte *const indexBuffer = new byte[8 + 2 * games.size()]; byte *dst = indexBuffer; WRITE_BE_UINT32(dst, kKyraDatVersion); dst += 4; WRITE_BE_UINT32(dst, games.size()); dst += 4; for (std::vector<GameDef>::const_iterator i = games.begin(), end = games.end(); i != end; ++i) { WRITE_BE_UINT16(dst, *i); dst += 2; } if (!out.addFile("INDEX", indexBuffer, 8 + 2 * games.size())) { error("couldn't write INDEX file"); } if (!out.saveFile(argv[1])) { error("couldn't save changes to '%s'", argv[1]); } uint8 digest[16]; if (!md5_file(argv[1], digest, 0)) error("couldn't calc. md5 for file '%s'", argv[1]); FILE *f = fopen(argv[1], "ab"); if (!f) error("couldn't open file '%s'", argv[1]); if (fwrite(digest, 1, 16, f) != 16) error("couldn't write md5sum to file '%s'", argv[1]); fclose(f); return 0; }
bool updateIndex(PAKFile &out, const ExtractInformation *eI) { uint32 size = 0; const uint8 *data = out.getFileData("INDEX", &size); Index index; if (data) index = parseIndex(data, size); GameDef gameDef = createGameDef(eI); if (index.version == kKyraDatVersion) { if (std::find(index.gameList.begin(), index.gameList.end(), gameDef) == index.gameList.end()) { ++index.includedGames; index.gameList.push_back(gameDef); } else { // Already included in the game list, thus we do not need any further processing here. return true; } } else { index.version = kKyraDatVersion; index.includedGames = 1; index.gameList.push_back(gameDef); } const uint32 indexBufferSize = 8 + index.includedGames * 2; uint8 *indexBuffer = new uint8[indexBufferSize]; assert(indexBuffer); uint8 *dst = indexBuffer; WRITE_BE_UINT32(dst, index.version); dst += 4; WRITE_BE_UINT32(dst, index.includedGames); dst += 4; for (Index::GameList::const_iterator i = index.gameList.begin(); i != index.gameList.end(); ++i) { WRITE_BE_UINT16(dst, *i); dst += 2; } out.removeFile("INDEX"); if (!out.addFile("INDEX", indexBuffer, indexBufferSize)) { fprintf(stderr, "ERROR: couldn't update kyra.dat INDEX\n"); delete[] indexBuffer; return false; } return true; }
int16 Op_Exec() { int scriptIdx; int ovlIdx; uint8 *ptr; uint8 *ptr2; int16 popTable[200]; int numOfArgToPop = popVar(); int i = 0; for (i = 0; i < numOfArgToPop; i++) { popTable[numOfArgToPop - i - 1] = popVar(); } scriptIdx = popVar(); ovlIdx = popVar(); if (!ovlIdx) { ovlIdx = currentScriptPtr->overlayNumber; } ptr = attacheNewScriptToTail(&procHead, ovlIdx, scriptIdx, currentScriptPtr->type, currentScriptPtr->scriptNumber, currentScriptPtr->overlayNumber, scriptType_MinusPROC); if (!ptr) return (0); if (numOfArgToPop <= 0) { return (0); } ptr2 = ptr; for (i = 0; i < numOfArgToPop; i++) { WRITE_BE_UINT16(ptr2, popTable[i]); ptr2 += 2; } return (0); }
void Sound::saveState(byte *&ptr) { WRITE_BE_UINT16(ptr, _lastOverride); ptr += 2; }
void WRITE_SCI11ENDIAN_UINT16(void *ptr, uint16 val) { if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) WRITE_BE_UINT16(ptr, val); else WRITE_LE_UINT16(ptr, val); }
void WRITE_SCIENDIAN_UINT16(void *ptr, uint16 val) { if (g_sci->isBE()) WRITE_BE_UINT16(ptr, val); else WRITE_LE_UINT16(ptr, val); }
void MidiMusicPlayer::playSEQ(uint32 size, bool loop) { // MIDI.DAT holds the file names in DW1 PSX Common::String baseName((char *)g_midiBuffer.pDat, size); Common::String seqName = baseName + ".SEQ"; // TODO: Load the instrument bank (<baseName>.VB and <baseName>.VH) Common::File seqFile; if (!seqFile.open(seqName)) error("Failed to open SEQ file '%s'", seqName.c_str()); if (seqFile.readUint32LE() != MKTAG('S', 'E', 'Q', 'p')) error("Failed to find SEQp tag"); // Make sure we don't have a SEP file (with multiple SEQ's inside) if (seqFile.readUint32BE() != 1) error("Can only play SEQ files, not SEP"); uint16 ppqn = seqFile.readUint16BE(); uint32 tempo = seqFile.readUint16BE() << 8; tempo |= seqFile.readByte(); /* uint16 beat = */ seqFile.readUint16BE(); // SEQ is directly based on SMF and we'll use that to our advantage here // and convert to SMF and then use the SMF MidiParser. // Calculate the SMF size we'll need uint32 dataSize = seqFile.size() - 15; uint32 actualSize = dataSize + 7 + 22; // Resize the buffer if necessary if (g_midiBuffer.size < actualSize) { g_midiBuffer.pDat = (byte *)realloc(g_midiBuffer.pDat, actualSize); assert(g_midiBuffer.pDat); } // Now construct the header WRITE_BE_UINT32(g_midiBuffer.pDat, MKTAG('M', 'T', 'h', 'd')); WRITE_BE_UINT32(g_midiBuffer.pDat + 4, 6); // header size WRITE_BE_UINT16(g_midiBuffer.pDat + 8, 0); // type 0 WRITE_BE_UINT16(g_midiBuffer.pDat + 10, 1); // one track WRITE_BE_UINT16(g_midiBuffer.pDat + 12, ppqn); WRITE_BE_UINT32(g_midiBuffer.pDat + 14, MKTAG('M', 'T', 'r', 'k')); WRITE_BE_UINT32(g_midiBuffer.pDat + 18, dataSize + 7); // SEQ data size + tempo change event size // Add in a fake tempo change event WRITE_BE_UINT32(g_midiBuffer.pDat + 22, 0x00FF5103); // no delta, meta event, tempo change, param size = 3 WRITE_BE_UINT16(g_midiBuffer.pDat + 26, tempo >> 8); g_midiBuffer.pDat[28] = tempo & 0xFF; // Now copy in the rest of the events seqFile.read(g_midiBuffer.pDat + 29, dataSize); seqFile.close(); MidiParser *parser = MidiParser::createParser_SMF(); if (parser->loadMusic(g_midiBuffer.pDat, actualSize)) { parser->setTrack(0); parser->setMidiDriver(this); parser->setTimerRate(getBaseTempo()); parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); parser->property(MidiParser::mpSendSustainOffOnNotesOff, 1); _parser = parser; _isLooping = loop; _isPlaying = true; } else { delete parser; } }
void SmackerDecoder::SmackerAudioTrack::queueCompressedBuffer(byte *buffer, uint32 bufferSize, uint32 unpackedSize) { Common::BitStream8LSB audioBS(new Common::MemoryReadStream(buffer, bufferSize), true); bool dataPresent = audioBS.getBit(); if (!dataPresent) return; bool isStereo = audioBS.getBit(); assert(isStereo == _audioInfo.isStereo); bool is16Bits = audioBS.getBit(); assert(is16Bits == _audioInfo.is16Bits); int numBytes = 1 * (isStereo ? 2 : 1) * (is16Bits ? 2 : 1); byte *unpackedBuffer = (byte *)malloc(unpackedSize); byte *curPointer = unpackedBuffer; uint32 curPos = 0; SmallHuffmanTree *audioTrees[4]; for (int k = 0; k < numBytes; k++) audioTrees[k] = new SmallHuffmanTree(audioBS); // Base values, stored as big endian int32 bases[2]; if (isStereo) { if (is16Bits) { bases[1] = SWAP_BYTES_16(audioBS.getBits(16)); } else { bases[1] = audioBS.getBits(8); } } if (is16Bits) { bases[0] = SWAP_BYTES_16(audioBS.getBits(16)); } else { bases[0] = audioBS.getBits(8); } // The bases are the first samples, too for (int i = 0; i < (isStereo ? 2 : 1); i++, curPointer += (is16Bits ? 2 : 1), curPos += (is16Bits ? 2 : 1)) { if (is16Bits) WRITE_BE_UINT16(curPointer, bases[i]); else *curPointer = (bases[i] & 0xFF) ^ 0x80; } // Next follow the deltas, which are added to the corresponding base values and // are stored as little endian // We store the unpacked bytes in big endian format while (curPos < unpackedSize) { // If the sample is stereo, the data is stored for the left and right channel, respectively // (the exact opposite to the base values) if (!is16Bits) { for (int k = 0; k < (isStereo ? 2 : 1); k++) { bases[k] += (int8) ((int16) audioTrees[k]->getCode(audioBS)); *curPointer++ = CLIP<int>(bases[k], 0, 255) ^ 0x80; curPos++; } } else { for (int k = 0; k < (isStereo ? 2 : 1); k++) { byte lo = audioTrees[k * 2]->getCode(audioBS); byte hi = audioTrees[k * 2 + 1]->getCode(audioBS); bases[k] += (int16) (lo | (hi << 8)); WRITE_BE_UINT16(curPointer, bases[k]); curPointer += 2; curPos += 2; } } } for (int k = 0; k < numBytes; k++) delete audioTrees[k]; queuePCM(unpackedBuffer, unpackedSize); }
void decompressVima(const byte *src, int16 *dest, int destLen, uint16 *destTable) { int numChannels = 1; byte sBytes[2]; int16 sWords[2]; sBytes[0] = *src++; if (sBytes[0] & 0x80) { sBytes[0] = ~sBytes[0]; numChannels = 2; } sWords[0] = READ_BE_UINT16(src); src += 2; if (numChannels > 1) { sBytes[1] = *src++; sWords[1] = READ_BE_UINT16(src); src += 2; } int numSamples = destLen / (numChannels * 2); int bits = READ_BE_UINT16(src); int bitPtr = 0; src += 2; for (int channel = 0; channel < numChannels; channel++) { int16 *destPos = dest + channel; int currTablePos = sBytes[channel]; int outputWord = sWords[channel]; for (int sample = 0; sample < numSamples; sample++) { int numBits = imcTable2[currTablePos]; bitPtr += numBits; int highBit = 1 << (numBits - 1); int lowBits = highBit - 1; int val = (bits >> (16 - bitPtr)) & (highBit | lowBits); if (bitPtr > 7) { bits = ((bits & 0xff) << 8) | *src++; bitPtr -= 8; } if (val & highBit) val ^= highBit; else highBit = 0; if (val == lowBits) { outputWord = ((int16)(bits << bitPtr) & 0xffffff00); bits = ((bits & 0xff) << 8) | *src++; outputWord |= ((bits >> (8 - bitPtr)) & 0xff); bits = ((bits & 0xff) << 8) | *src++; } else { int index = (val << (7 - numBits)) | (currTablePos << 6); int delta = destTable[index]; if (val) delta += (imcTable1[currTablePos] >> (numBits - 1)); if (highBit) delta = -delta; outputWord += delta; if (outputWord < -0x8000) outputWord = -0x8000; else if (outputWord > 0x7fff) outputWord = 0x7fff; } WRITE_BE_UINT16(destPos, outputWord); destPos += numChannels; currTablePos += offsets[numBits - 2][val]; if (currTablePos < 0) currTablePos = 0; else if (currTablePos > 88) currTablePos = 88; }
static void DumpWord(int i, FILE* D) { byte out[2]; WRITE_BE_UINT16(out, i); DumpBlock(out,2,D); }
void SmackerDecoder::queueCompressedBuffer(byte *buffer, uint32 bufferSize, uint32 unpackedSize, int streamNum) { BitStream audioBS(buffer, bufferSize); bool dataPresent = audioBS.getBit(); if (!dataPresent) return; bool isStereo = audioBS.getBit(); assert(isStereo == _header.audioInfo[streamNum].isStereo); bool is16Bits = audioBS.getBit(); assert(is16Bits == _header.audioInfo[streamNum].is16Bits); int numBytes = 1 * (isStereo ? 2 : 1) * (is16Bits ? 2 : 1); byte *unpackedBuffer = (byte *)malloc(unpackedSize); byte *curPointer = unpackedBuffer; uint32 curPos = 0; SmallHuffmanTree *audioTrees[4]; for (int k = 0; k < numBytes; k++) audioTrees[k] = new SmallHuffmanTree(audioBS); // Base values, stored as big endian int32 bases[2]; if (isStereo) { if (is16Bits) { byte hi = audioBS.getBits8(); byte lo = audioBS.getBits8(); bases[1] = (int16) ((hi << 8) | lo); } else { bases[1] = audioBS.getBits8(); } } if (is16Bits) { byte hi = audioBS.getBits8(); byte lo = audioBS.getBits8(); bases[0] = (int16) ((hi << 8) | lo); } else { bases[0] = audioBS.getBits8(); } // The bases are the first samples, too for (int i = 0; i < (isStereo ? 2 : 1); i++, curPointer += (is16Bits ? 2 : 1), curPos += (is16Bits ? 2 : 1)) { if (is16Bits) WRITE_BE_UINT16(curPointer, bases[i]); else *curPointer = (bases[i] & 0xFF) ^ 0x80; } // Next follow the deltas, which are added to the corresponding base values and // are stored as little endian // We store the unpacked bytes in big endian format while (curPos < unpackedSize) { // If the sample is stereo, the data is stored for the left and right channel, respectively // (the exact opposite to the base values) if (!is16Bits) { for (int k = 0; k < (isStereo ? 2 : 1); k++) { bases[k] += (int8) ((int16) audioTrees[k]->getCode(audioBS)); *curPointer++ = CLIP<int>(bases[k], 0, 255) ^ 0x80; curPos++; } } else { for (int k = 0; k < (isStereo ? 2 : 1); k++) { byte lo = audioTrees[k * 2]->getCode(audioBS); byte hi = audioTrees[k * 2 + 1]->getCode(audioBS); bases[k] += (int16) (lo | (hi << 8)); WRITE_BE_UINT16(curPointer, bases[k]); curPointer += 2; curPos += 2; } } } for (int k = 0; k < numBytes; k++) delete audioTrees[k]; byte flags = 0; if (_header.audioInfo[0].is16Bits) flags = flags | Audio::FLAG_16BITS; if (_header.audioInfo[0].isStereo) flags = flags | Audio::FLAG_STEREO; _audioStream->queueBuffer(unpackedBuffer, unpackedSize, DisposeAfterUse::YES, flags); // unpackedBuffer will be deleted by QueuingAudioStream }
int updateScriptImport(int ovlIdx) { char buffer[256]; ovlDataStruct *ovlData; int numData3; int size5; int numRelocGlob; int param; int var_32; ovlData3Struct *pScript; // char* arrayRelocGlob; // char* namePtr; // char* arrayMsgRelHeader; if (!overlayTable[ovlIdx].ovlData) return (-4); ovlData = overlayTable[ovlIdx].ovlData; numData3 = ovlData->numProc; size5 = ovlData->numRel; numRelocGlob = ovlData->numRelocGlob; param = 0; // do it for the 2 first string types do { int i = 0; if (param == 0) { var_32 = numData3; } else { var_32 = size5; } if (var_32) { do { importScriptStruct *ptrImportData; const char *ptrImportName; uint8 *ptrData; int var_22 = 0; if (param == 0) { pScript = getOvlData3Entry(ovlIdx, i); } else { pScript = scriptFunc1Sub2(ovlIdx, i); } ptrImportData = (importScriptStruct *)(pScript->dataPtr + pScript->offsetToImportData); // import data ptrImportName = (const char*)(pScript->dataPtr + pScript->offsetToImportName); // import name ptrData = pScript->dataPtr; var_22 = 0; if (pScript->numRelocGlob > 0) { int counter = pScript->numRelocGlob; do { int param2 = ptrImportData->type; if (param2 != 70) { exportEntryStruct * ptrDest2; int out1; int out2; strcpy(buffer, ptrImportName + ptrImportData->offsetToName); ptrDest2 = parseExport(&out1, &out2, buffer); if (ptrDest2 && out2) { int temp = ptrImportData-> offset; if (out1) { //is sub function... (ie 'invent.livre:s') uint8 *ptr = ptrData + temp; *(ptr + 1) = out2; WRITE_BE_UINT16(ptr + 2, ptrDest2->idx); } else { if (param2 == 20 || param2 == 30 || param2 == 40 || param2 == 50) { // this patch a double push uint8 *ptr = ptrData + temp; *(ptr + 1) = 0; *(ptr + 2) = out2; // update the overlay number WRITE_BE_UINT16(ptr + 4, ptrDest2->idx); } else { int var_4 = ptrDest2->var4; if (var_4 & 1) { param2 = 8; } else { param2 = 16; } if (var_4 >= 0 && var_4 <= 3) { param2 |= 5; } else { param2 |= 6; } *(ptrData + temp) = param2; *(ptrData + temp + 1) = out2; WRITE_BE_UINT16(ptrData + temp + 2, ptrDest2->idx); } } } } ptrImportData++; } while (--counter); } } while (++i < var_32); } } while (++param < 2); if (ovlData->arrayRelocGlob && ovlData->arrayNameRelocGlob && numRelocGlob) { int numImport2 = numRelocGlob; int i; for (i = 0; i < numImport2; i++) { int out1; int foundExportIdx; exportEntryStruct *pFoundExport; int linkType; int linkEntryIdx; strcpy(buffer, ovlData->arrayNameRelocGlob + ovlData->arrayRelocGlob[i].nameOffset); pFoundExport = parseExport(&out1, &foundExportIdx, buffer); linkType = ovlData->arrayRelocGlob[i].linkType; linkEntryIdx = ovlData->arrayRelocGlob[i].linkIdx; if (pFoundExport && foundExportIdx) { switch (linkType) { case 0: { // verb ovlData->arrayMsgRelHeader[linkEntryIdx].verbOverlay = foundExportIdx; ovlData->arrayMsgRelHeader[linkEntryIdx].verbNumber = pFoundExport->idx; break; } case 1: { // obj1 ovlData->arrayMsgRelHeader[linkEntryIdx].obj1Overlay = foundExportIdx; ovlData->arrayMsgRelHeader[linkEntryIdx].obj1Number = pFoundExport->idx; break; } case 2: { // obj2 ovlData->arrayMsgRelHeader[linkEntryIdx].obj2Overlay = foundExportIdx; ovlData->arrayMsgRelHeader[linkEntryIdx].obj2Number = pFoundExport->idx; break; } } } } } return (0); }