uint32_t File::readUint32BE(uint8_t *ptr) { read(ptr, 4); return READ_BE_UINT32(ptr); }
int ResourceManager::readAudioMapSCI11(ResourceSource *map) { #ifndef ENABLE_SCI32 // SCI32 support is not built in. Check if this is a SCI32 game // and if it is abort here. if (_volVersion >= kResVersionSci2) return SCI_ERROR_RESMAP_NOT_FOUND; #endif uint32 offset = 0; Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->_volumeNumber), false); if (!mapRes) { warning("Failed to open %i.MAP", map->_volumeNumber); return SCI_ERROR_RESMAP_NOT_FOUND; } ResourceSource *src = findVolume(map, 0); if (!src) return SCI_ERROR_NO_RESOURCE_FILES_FOUND; byte *ptr = mapRes->data; // Heuristic to detect entry size uint32 entrySize = 0; for (int i = mapRes->size - 1; i >= 0; --i) { if (ptr[i] == 0xff) entrySize++; else break; } if (map->_volumeNumber == 65535) { while (ptr < mapRes->data + mapRes->size) { uint16 n = READ_LE_UINT16(ptr); ptr += 2; if (n == 0xffff) break; if (entrySize == 6) { offset = READ_LE_UINT32(ptr); ptr += 4; } else { offset += READ_LE_UINT24(ptr); ptr += 3; } addResource(ResourceId(kResourceTypeAudio, n), src, offset); } } else if (map->_volumeNumber == 0 && entrySize == 10 && ptr[3] == 0) { // QFG3 demo format // ptr[3] would be 'seq' in the normal format and cannot possibly be 0 while (ptr < mapRes->data + mapRes->size) { uint16 n = READ_BE_UINT16(ptr); ptr += 2; if (n == 0xffff) break; offset = READ_LE_UINT32(ptr); ptr += 4; uint32 size = READ_LE_UINT32(ptr); ptr += 4; addResource(ResourceId(kResourceTypeAudio, n), src, offset, size); } } else if (map->_volumeNumber == 0 && entrySize == 8 && READ_LE_UINT16(ptr + 2) == 0xffff) { // LB2 Floppy/Mother Goose SCI1.1 format Common::SeekableReadStream *stream = getVolumeFile(src); while (ptr < mapRes->data + mapRes->size) { uint16 n = READ_LE_UINT16(ptr); ptr += 4; if (n == 0xffff) break; offset = READ_LE_UINT32(ptr); ptr += 4; // The size is not stored in the map and the entries have no order. // We need to dig into the audio resource in the volume to get the size. stream->seek(offset + 1); byte headerSize = stream->readByte(); assert(headerSize == 11 || headerSize == 12); stream->skip(5); uint32 size = stream->readUint32LE() + headerSize + 2; addResource(ResourceId(kResourceTypeAudio, n), src, offset, size); } } else { bool isEarly = (entrySize != 11); if (!isEarly) { offset = READ_LE_UINT32(ptr); ptr += 4; } while (ptr < mapRes->data + mapRes->size) { uint32 n = READ_BE_UINT32(ptr); int syncSize = 0; ptr += 4; if (n == 0xffffffff) break; if (isEarly) { offset = READ_LE_UINT32(ptr); ptr += 4; } else { offset += READ_LE_UINT24(ptr); ptr += 3; } if (isEarly || (n & 0x80)) { syncSize = READ_LE_UINT16(ptr); ptr += 2; if (syncSize > 0) addResource(ResourceId(kResourceTypeSync36, map->_volumeNumber, n & 0xffffff3f), src, offset, syncSize); } if (n & 0x40) { // This seems to define the size of raw lipsync data (at least // in kq6), may also just be general appended data. syncSize += READ_LE_UINT16(ptr); ptr += 2; } addResource(ResourceId(kResourceTypeAudio36, map->_volumeNumber, n & 0xffffff3f), src, offset + syncSize); } } return 0; }
void AGOSEngine::loadGamePcFile() { Common::SeekableReadStream *in; int fileSize; if (getFileName(GAME_BASEFILE) != NULL) { /* Read main gamexx file */ in = _archives.open(getFileName(GAME_BASEFILE)); if (!in) { error("loadGamePcFile: Can't load gamexx file '%s'", getFileName(GAME_BASEFILE)); } if (getFeatures() & GF_CRUNCHED_GAMEPC) { uint srcSize = in->size(); byte *srcBuf = (byte *)malloc(srcSize); in->read(srcBuf, srcSize); uint dstSize = READ_BE_UINT32(srcBuf + srcSize - 4); byte *dstBuf = (byte *)malloc(dstSize); decrunchFile(srcBuf, dstBuf, srcSize); free(srcBuf); Common::MemoryReadStream stream(dstBuf, dstSize); readGamePcFile(&stream); free(dstBuf); } else { readGamePcFile(in); } delete in; } if (getFileName(GAME_TBLFILE) != NULL) { /* Read list of TABLE resources */ in = _archives.open(getFileName(GAME_TBLFILE)); if (!in) { error("loadGamePcFile: Can't load table resources file '%s'", getFileName(GAME_TBLFILE)); } fileSize = in->size(); _tblList = (byte *)malloc(fileSize); if (_tblList == NULL) error("loadGamePcFile: Out of memory for strip table list"); in->read(_tblList, fileSize); delete in; /* Remember the current state */ _subroutineListOrg = _subroutineList; _tablesHeapPtrOrg = _tablesHeapPtr; _tablesHeapCurPosOrg = _tablesHeapCurPos; } if (getFileName(GAME_STRFILE) != NULL) { /* Read list of TEXT resources */ in = _archives.open(getFileName(GAME_STRFILE)); if (!in) error("loadGamePcFile: Can't load text resources file '%s'", getFileName(GAME_STRFILE)); fileSize = in->size(); _strippedTxtMem = (byte *)malloc(fileSize); if (_strippedTxtMem == NULL) error("loadGamePcFile: Out of memory for strip text list"); in->read(_strippedTxtMem, fileSize); delete in; } if (getFileName(GAME_STATFILE) != NULL) { /* Read list of ROOM STATE resources */ in = _archives.open(getFileName(GAME_STATFILE)); if (!in) { error("loadGamePcFile: Can't load state resources file '%s'", getFileName(GAME_STATFILE)); } _numRoomStates = in->size() / 8; _roomStates = (RoomState *)calloc(_numRoomStates, sizeof(RoomState)); if (_roomStates == NULL) error("loadGamePcFile: Out of memory for room state list"); for (uint s = 0; s < _numRoomStates; s++) { uint16 num = in->readUint16BE() - (_itemArrayInited - 2); _roomStates[num].state = in->readUint16BE(); _roomStates[num].classFlags = in->readUint16BE(); _roomStates[num].roomExitStates = in->readUint16BE(); } delete in; } if (getFileName(GAME_RMSLFILE) != NULL) { /* Read list of ROOM ITEMS resources */ in = _archives.open(getFileName(GAME_RMSLFILE)); if (!in) { error("loadGamePcFile: Can't load room resources file '%s'", getFileName(GAME_RMSLFILE)); } fileSize = in->size(); _roomsList = (byte *)malloc(fileSize); if (_roomsList == NULL) error("loadGamePcFile: Out of memory for room items list"); in->read(_roomsList, fileSize); delete in; } if (getFileName(GAME_XTBLFILE) != NULL) { /* Read list of XTABLE resources */ in = _archives.open(getFileName(GAME_XTBLFILE)); if (!in) { error("loadGamePcFile: Can't load xtable resources file '%s'", getFileName(GAME_XTBLFILE)); } fileSize = in->size(); _xtblList = (byte *)malloc(fileSize); if (_xtblList == NULL) error("loadGamePcFile: Out of memory for strip xtable list"); in->read(_xtblList, fileSize); delete in; /* Remember the current state */ _xsubroutineListOrg = _subroutineList; _xtablesHeapPtrOrg = _tablesHeapPtr; _xtablesHeapCurPosOrg = _tablesHeapCurPos; } }
uint32 AGOSEngine::readUint32Wrapper(const void *src) { return READ_BE_UINT32(src); }
void DXADecoder::DXAVideoTrack::decode13(int size) { #ifdef USE_ZLIB uint8 *codeBuf, *dataBuf, *motBuf, *maskBuf; if (!_decompBuffer) { _decompBuffer = new byte[_decompBufferSize]; memset(_decompBuffer, 0, _decompBufferSize); } /* decompress the input data */ decodeZlib(_decompBuffer, size, _decompBufferSize); memcpy(_frameBuffer2, _frameBuffer1, _frameSize); int codeSize = _width * _curHeight / 16; int dataSize, motSize; dataSize = READ_BE_UINT32(&_decompBuffer[0]); motSize = READ_BE_UINT32(&_decompBuffer[4]); //maskSize = READ_BE_UINT32(&_decompBuffer[8]); codeBuf = &_decompBuffer[12]; dataBuf = &codeBuf[codeSize]; motBuf = &dataBuf[dataSize]; maskBuf = &motBuf[motSize]; for (uint32 by = 0; by < _curHeight; by += BLOCKH) { for (uint32 bx = 0; bx < _width; bx += BLOCKW) { uint8 type = *codeBuf++; uint8 *b2 = (uint8 *)_frameBuffer1 + bx + by * _width; switch (type) { case 0: break; case 1: { uint16 diffMap = READ_BE_UINT16(maskBuf); maskBuf += 2; for (int yc = 0; yc < BLOCKH; yc++) { for (int xc = 0; xc < BLOCKW; xc++) { if (diffMap & 0x8000) { b2[xc] = *dataBuf++; } diffMap <<= 1; } b2 += _width; } break; } case 2: { uint8 color = *dataBuf++; for (int yc = 0; yc < BLOCKH; yc++) { for (int xc = 0; xc < BLOCKW; xc++) { b2[xc] = color; } b2 += _width; } break; } case 3: { for (int yc = 0; yc < BLOCKH; yc++) { for (int xc = 0; xc < BLOCKW; xc++) { b2[xc] = *dataBuf++; } b2 += _width; } break; } case 4: { uint8 mbyte = *motBuf++; int mx = (mbyte >> 4) & 0x07; if (mbyte & 0x80) mx = -mx; int my = mbyte & 0x07; if (mbyte & 0x08) my = -my; uint8 *b1 = (uint8 *)_frameBuffer2 + (bx+mx) + (by+my) * _width; for (int yc = 0; yc < BLOCKH; yc++) { memcpy(b2, b1, BLOCKW); b1 += _width; b2 += _width; } break; } case 8: { static const int subX[4] = {0, 2, 0, 2}; static const int subY[4] = {0, 0, 2, 2}; uint8 subMask = *maskBuf++; for (int subBlock = 0; subBlock < 4; subBlock++) { int sx = bx + subX[subBlock], sy = by + subY[subBlock]; b2 = (uint8 *)_frameBuffer1 + sx + sy * _width; switch (subMask & 0xC0) { // 00: skip case 0x00: break; // 01: solid color case 0x40: { uint8 subColor = *dataBuf++; for (int yc = 0; yc < BLOCKH / 2; yc++) { for (int xc = 0; xc < BLOCKW / 2; xc++) { b2[xc] = subColor; } b2 += _width; } break; } // 02: motion vector case 0x80: { uint8 mbyte = *motBuf++; int mx = (mbyte >> 4) & 0x07; if (mbyte & 0x80) mx = -mx; int my = mbyte & 0x07; if (mbyte & 0x08) my = -my; uint8 *b1 = (uint8 *)_frameBuffer2 + (sx+mx) + (sy+my) * _width; for (int yc = 0; yc < BLOCKH / 2; yc++) { memcpy(b2, b1, BLOCKW / 2); b1 += _width; b2 += _width; } break; } // 03: raw case 0xC0: for (int yc = 0; yc < BLOCKH / 2; yc++) { for (int xc = 0; xc < BLOCKW / 2; xc++) { b2[xc] = *dataBuf++; } b2 += _width; } break; } subMask <<= 2; } break; } case 32: case 33: case 34: { int count = type - 30; uint8 pixels[4]; memcpy(pixels, dataBuf, count); dataBuf += count; if (count == 2) { uint16 code = READ_BE_UINT16(maskBuf); maskBuf += 2; for (int yc = 0; yc < BLOCKH; yc++) { for (int xc = 0; xc < BLOCKW; xc++) { b2[xc] = pixels[code & 1]; code >>= 1; } b2 += _width; } } else { uint32 code = READ_BE_UINT32(maskBuf); maskBuf += 4; for (int yc = 0; yc < BLOCKH; yc++) { for (int xc = 0; xc < BLOCKW; xc++) { b2[xc] = pixels[code & 3]; code >>= 2; } b2 += _width; } } break; } default: error("decode13: Unknown type %d", type); } }