/** * Read 16 bit values from a little endian binary file. * * This function will read 16 bit values from a little endian binary file * and convert them to the native byte order. * * Error messages from this function are sent to the message handler * (see msngr_init_log() and msngr_init_mail()). * * @param fd - file descriptor * @param data - pointer to the output data array * @param nvals - number of data values to read * * @return * - number of data values successfully read * - -1 if an error occurred */ int lton_read_16(int fd, void *data, size_t nvals) { ssize_t bytes_read; int vals_read; bytes_read = read(fd, data, 2*nvals); if (bytes_read < 0) { ERROR( ARMUTILS_LIB_NAME, "Could not read data from file: %s\n", strerror(errno)); return(-1); } vals_read = bytes_read/2; #ifdef _BIG_ENDIAN { uint16_t *dp = (uint16_t *)data; int i; for (i = 0; i < vals_read; ++i) { dp[i] = SWAP_BYTES_16(dp[i]); } } #endif return(vals_read); }
Bitmap::Bitmap(const char *fname, const char *data, int len) : Object() { _fname = fname; if (len < 8 || memcmp(data, "BM F\0\0\0", 8) != 0) { if (gDebugLevel == DEBUG_BITMAPS || gDebugLevel == DEBUG_ERROR || gDebugLevel == DEBUG_ALL) error("Invalid magic loading bitmap"); } strcpy(_filename, fname); int codec = READ_LE_UINT32(data + 8); // _paletteIncluded = READ_LE_UINT32(data + 12); _numImages = READ_LE_UINT32(data + 16); _x = READ_LE_UINT32(data + 20); _y = READ_LE_UINT32(data + 24); // _transparentColor = READ_LE_UINT32(data + 28); _format = READ_LE_UINT32(data + 32); // _numBits = READ_LE_UINT32(data + 36); // _blueBits = READ_LE_UINT32(data + 40); // _greenBits = READ_LE_UINT32(data + 44); // _redBits = READ_LE_UINT32(data + 48); // _blueShift = READ_LE_UINT32(data + 52); // _greenShift = READ_LE_UINT32(data + 56); // _redShift = READ_LE_UINT32(data + 60); _width = READ_LE_UINT32(data + 128); _height = READ_LE_UINT32(data + 132); _currImage = 1; _data = new char *[_numImages]; int pos = 0x88; for (int i = 0; i < _numImages; i++) { _data[i] = new char[2 * _width * _height]; if (codec == 0) { memcpy(_data[i], data + pos, 2 * _width * _height); pos += 2 * _width * _height + 8; } else if (codec == 3) { int compressed_len = READ_LE_UINT32(data + pos); decompress_codec3(data + pos + 4, _data[i]); pos += compressed_len + 12; } #ifdef SYSTEM_BIG_ENDIAN if (_format == 1) for (int j = 0; j < _width * _height; ++j) { ((uint16 *)_data[i])[j] = SWAP_BYTES_16(((uint16 *)_data[i])[j]); } #endif } g_driver->createBitmap(this); }
/** * Convert array of 16 bit big endian values to native byte order. * * @param data - pointer to the array of data values * @param nvals - number of values in the data array * * @return pointer to the array of data values */ void *bton_16(void *data, size_t nvals) { #ifndef _BIG_ENDIAN uint16_t *dp = (uint16_t *)data; size_t i; for (i = 0; i < nvals; ++i) { dp[i] = SWAP_BYTES_16(dp[i]); } #endif return(data); }
void OpenGLTexture::byteswapSurface(Graphics::Surface *surface) { for (int y = 0; y < surface->h; y++) { for (int x = 0; x < surface->w; x++) { if (surface->format.bytesPerPixel == 4) { uint32 *pixel = (uint32 *) (surface->getBasePtr(x, y)); *pixel = SWAP_BYTES_32(*pixel); } else if (surface->format.bytesPerPixel == 2) { uint16 *pixel = (uint16 *) (surface->getBasePtr(x, y)); *pixel = SWAP_BYTES_16(*pixel); } else { error("Unexpected bytes per pixedl %d", surface->format.bytesPerPixel); } } } }
bool SaveConverter::swapDataEndian(byte *data, const byte *sizes, uint32 count) { if (!data || !sizes || (count == 0)) return false; while (count-- > 0) { if (*sizes == 3) // 32bit value (3 additional bytes) WRITE_UINT32(data, SWAP_BYTES_32(READ_UINT32(data))); else if (*sizes == 1) // 16bit value (1 additional byte) WRITE_UINT16(data, SWAP_BYTES_16(READ_UINT16(data))); else if (*sizes != 0) // else, it has to be an 8bit value return false; count -= *sizes; data += *sizes + 1; sizes += *sizes + 1; } return true; }
bool BitmapData::loadGrimBm(Common::SeekableReadStream *data) { uint32 tag2 = data->readUint32BE(); if (tag2 != (MKTAG('F','\0','\0','\0'))) return false; int codec = data->readUint32LE(); data->readUint32LE(); //_paletteIncluded _numImages = data->readUint32LE(); _x = data->readUint32LE(); _y = data->readUint32LE(); data->readUint32LE(); //_transparentColor _format = data->readUint32LE(); _bpp = data->readUint32LE(); // uint32 redBits = data->readUint32LE(); // uint32 greenBits = data->readUint32LE(); // uint32 blueBits = data->readUint32LE(); // uint32 redShift = data->readUint32LE(); // uint32 greenShift = data->readUint32LE(); // uint32 blueShift = data->readUint32LE(); // Hardcode the format, since the values saved in the files are garbage for some, like "ha_0_elvos.zbm". Graphics::PixelFormat pixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0); data->seek(128, SEEK_SET); _width = data->readUint32LE(); _height = data->readUint32LE(); _colorFormat = BM_RGB565; _hasTransparency = false; _data = new Graphics::PixelBuffer[_numImages]; data->seek(0x80, SEEK_SET); for (int i = 0; i < _numImages; i++) { data->seek(8, SEEK_CUR); _data[i].create(pixelFormat, _width * _height, DisposeAfterUse::YES); if (codec == 0) { uint32 dsize = _bpp / 8 * _width * _height; data->read(_data[i].getRawBuffer(), dsize); } else if (codec == 3) { int compressed_len = data->readUint32LE(); char *compressed = new char[compressed_len]; data->read(compressed, compressed_len); bool success = decompress_codec3(compressed, (char *)_data[i].getRawBuffer(), _bpp / 8 * _width * _height); delete[] compressed; if (!success) warning(".. when loading image %s.\n", _fname.c_str()); } else Debug::error(Debug::Bitmaps, "Unknown image codec in BitmapData ctor!"); #ifdef SCUMM_BIG_ENDIAN if (_format == 1) { uint16 *d = (uint16 *)_data[i].getRawBuffer(); for (int j = 0; j < _width * _height; ++j) { d[j] = SWAP_BYTES_16(d[j]); } } #endif } // Initially, no GPU-side textures created. the createBitmap // function will allocate some if necessary (and successful) _numTex = 0; _texIds = nullptr; g_driver->createBitmap(this); return true; }
void Sound::checkSpeechFileEndianness() { // Some mac versions (not all of them) use big endian wav, although // the wav header doesn't indicate it. // Use heuristic to determine endianness of speech. // The heuristic consist in computing the sum of the absolute difference for // every two consecutive samples. This is done both with a big endian and a // little endian assumption. The one with the smallest sum should be the // correct one (the sound wave is supposed to be relatively smooth). // It needs at least 1000 samples to get stable result (the code below is // using the first 2000 samples of the wav sound). // Init speech file if not already done. if (!_currentCowFile) { // Open one of the speech files. It uses SwordEngine::_systemVars.currentCD // to decide which file to open, therefore if it is currently set to zero // we have to set it to either 1 or 2 (I decided to set it to 1 as this is // more likely to be the first file that will be needed). bool no_current_cd = false; if (SwordEngine::_systemVars.currentCD == 0) { SwordEngine::_systemVars.currentCD = 1; no_current_cd = true; } initCowSystem(); if (no_current_cd) { // In case it fails with CD1 retry with CD2 if (!_currentCowFile) { SwordEngine::_systemVars.currentCD = 2; initCowSystem(); } // Reset currentCD flag SwordEngine::_systemVars.currentCD = 0; } } // Testing for endianness makes sense only if using the uncompressed files. if (_cowHeader == NULL || (_cowMode != CowWave && _cowMode != CowDemo)) return; // I picked the sample to use randomly (I just made sure it is long enough so that there is // a fair change of the heuristic to have a stable result and work for every language). int roomNo = _currentCowFile == 1 ? 1 : 129; int localNo = _currentCowFile == 1 ? 2 : 933; // Get the speech data and apply the heuristic uint32 locIndex = _cowHeader[roomNo] >> 2; uint32 sampleSize = _cowHeader[locIndex + (localNo * 2)]; uint32 index = _cowHeader[locIndex + (localNo * 2) - 1]; if (sampleSize) { uint32 size; double be_diff_sum = 0., le_diff_sum = 0.; _bigEndianSpeech = false; int16 *data = uncompressSpeech(index + _cowHeaderSize, sampleSize, &size); // Compute average of difference between two consecutive samples for both BE and LE if (data) { if (size > 4000) size = 2000; else size /= 2; int16 prev_be_value = (int16)SWAP_BYTES_16(*((uint16*)(data))); for (uint32 i = 1; i < size; ++i) { le_diff_sum += fabs((double)(data[i] - data[i-1])); int16 be_value = (int16)SWAP_BYTES_16(*((uint16*)(data + i))); be_diff_sum += fabs((double)(be_value - prev_be_value)); prev_be_value = be_value; } delete [] data; } // Set the big endian flag _bigEndianSpeech = (be_diff_sum < le_diff_sum); if (_bigEndianSpeech) debug(6, "Mac version: using big endian speech file"); else debug(6, "Mac version: using little endian speech file"); debug(8, "Speech endianness heuristic: average = %f for BE and %f for LE, computed on %d samples)", be_diff_sum / (size - 1), le_diff_sum / (size - 1), size); } }
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); }