Initial commit
This commit is contained in:
550
engines/cryo/resource.cpp
Normal file
550
engines/cryo/resource.cpp
Normal file
@@ -0,0 +1,550 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cryo/defs.h"
|
||||
#include "cryo/cryo.h"
|
||||
#include "cryo/cryolib.h"
|
||||
#include "cryo/eden.h"
|
||||
|
||||
#include "common/substream.h"
|
||||
|
||||
namespace Cryo {
|
||||
|
||||
#define CRYO_DAT_VER 1 // 32-bit integer
|
||||
|
||||
// Original name: prechargephrases
|
||||
void EdenGame::preloadDialogs(int16 vid) {
|
||||
perso_t *perso = &_persons[PER_MORKUS];
|
||||
if (vid == 170)
|
||||
perso = &_persons[PER_UNKN_156];
|
||||
_globals->_characterPtr = perso;
|
||||
_globals->_dialogType = DialogType::dtInspect;
|
||||
int num = (perso->_id << 3) | _globals->_dialogType;
|
||||
Dialog *dial = (Dialog *)getElem(_gameDialogs, num);
|
||||
dialoscansvmas(dial);
|
||||
}
|
||||
|
||||
////// datfile.c
|
||||
void EdenGame::verifh(byte *ptr) {
|
||||
byte sum = 0;
|
||||
byte *head = ptr;
|
||||
|
||||
for (int8 i = 0; i < 6; i++)
|
||||
sum += *head++;
|
||||
|
||||
if (sum != 0xAB)
|
||||
return;
|
||||
|
||||
debug("* Begin unpacking resource");
|
||||
head -= 6;
|
||||
uint16 h0 = READ_LE_UINT16(head);
|
||||
// 3 = 2 bytes for the uint16 and 1 byte for an unused char
|
||||
head += 3;
|
||||
uint16 h3 = READ_LE_UINT16(head);
|
||||
head += 2;
|
||||
byte *data = h0 + head + 26;
|
||||
h3 -= 6;
|
||||
head += h3;
|
||||
for (; h3; h3--)
|
||||
*data-- = *head--;
|
||||
head = data + 1;
|
||||
data = ptr;
|
||||
expandHSQ(head, data);
|
||||
}
|
||||
|
||||
void EdenGame::openbigfile() {
|
||||
_bigfile.open("EDEN.DAT");
|
||||
|
||||
char buf[16];
|
||||
int count = _bigfile.readUint16LE();
|
||||
_bigfileHeader = new PakHeaderNode(count);
|
||||
for (int j = 0; j < count; j++) {
|
||||
for (int k = 0; k < 16; k++)
|
||||
buf[k] = _bigfile.readByte();
|
||||
_bigfileHeader->_files[j]._name = Common::String(buf);
|
||||
_bigfileHeader->_files[j]._size = _bigfile.readUint32LE();
|
||||
_bigfileHeader->_files[j]._offs = _bigfile.readUint32LE();
|
||||
_bigfileHeader->_files[j]._flag = _bigfile.readByte();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void EdenGame::closebigfile() {
|
||||
_bigfile.close();
|
||||
}
|
||||
|
||||
int EdenGame::loadmusicfile(int16 num) {
|
||||
PakHeaderItem *file = &_bigfileHeader->_files[num + 435];
|
||||
int32 size = file->_size;
|
||||
int32 offs = file->_offs;
|
||||
_bigfile.seek(offs, SEEK_SET);
|
||||
uint32 numread = size;
|
||||
if (numread > kMaxMusicSize)
|
||||
error("Music file %s is too big", file->_name.c_str());
|
||||
_bigfile.read(_musicBuf, numread);
|
||||
return size;
|
||||
}
|
||||
|
||||
void EdenGame::loadRawFile(uint16 num, byte *buffer) {
|
||||
if (_vm->getPlatform() == Common::kPlatformDOS) {
|
||||
if ((_vm->isDemo() && num > 2204) || num > 2472)
|
||||
error("Trying to read invalid game resource");
|
||||
}
|
||||
|
||||
assert(num < _bigfileHeader->_count);
|
||||
PakHeaderItem *file = &_bigfileHeader->_files[num];
|
||||
int32 size = file->_size;
|
||||
int32 offs = file->_offs;
|
||||
|
||||
_bigfile.seek(offs, SEEK_SET);
|
||||
_bigfile.read(buffer, size);
|
||||
}
|
||||
|
||||
void EdenGame::loadIconFile(uint16 num, Icon *buffer) {
|
||||
if (_vm->getPlatform() == Common::kPlatformDOS) {
|
||||
if ((_vm->isDemo() && num > 2204) || num > 2472)
|
||||
error("Trying to read invalid game resource");
|
||||
}
|
||||
|
||||
assert(num < _bigfileHeader->_count);
|
||||
PakHeaderItem *file = &_bigfileHeader->_files[num];
|
||||
int32 size = file->_size;
|
||||
int32 offs = file->_offs;
|
||||
debug("* Loading icon - Resource %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), offs, size);
|
||||
_bigfile.seek(offs, SEEK_SET);
|
||||
|
||||
int count = size / 18; // sizeof(Icon)
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (_vm->getPlatform() == Common::kPlatformMacintosh) {
|
||||
buffer[i].sx = _bigfile.readSint16BE();
|
||||
buffer[i].sy = _bigfile.readSint16BE();
|
||||
buffer[i].ex = _bigfile.readSint16BE();
|
||||
buffer[i].ey = _bigfile.readSint16BE();
|
||||
buffer[i]._cursorId = _bigfile.readUint16BE();
|
||||
buffer[i]._actionId = _bigfile.readUint32BE();
|
||||
buffer[i]._objectId = _bigfile.readUint32BE();
|
||||
}
|
||||
else {
|
||||
buffer[i].sx = _bigfile.readSint16LE();
|
||||
buffer[i].sy = _bigfile.readSint16LE();
|
||||
buffer[i].ex = _bigfile.readSint16LE();
|
||||
buffer[i].ey = _bigfile.readSint16LE();
|
||||
buffer[i]._cursorId = _bigfile.readUint16LE();
|
||||
buffer[i]._actionId = _bigfile.readUint32LE();
|
||||
buffer[i]._objectId = _bigfile.readUint32LE();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EdenGame::loadRoomFile(uint16 num, Room *buffer) {
|
||||
if (_vm->getPlatform() == Common::kPlatformDOS) {
|
||||
if ((_vm->isDemo() && num > 2204) || num > 2472)
|
||||
error("Trying to read invalid game resource");
|
||||
}
|
||||
|
||||
assert(num < _bigfileHeader->_count);
|
||||
PakHeaderItem *file = &_bigfileHeader->_files[num];
|
||||
int32 size = file->_size;
|
||||
int32 offs = file->_offs;
|
||||
debug("* Loading room - Resource %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), offs, size);
|
||||
_bigfile.seek(offs, SEEK_SET);
|
||||
|
||||
int count = size / 14; // sizeof(Room)
|
||||
for (int i = 0; i < count; i++) {
|
||||
buffer[i]._id = _bigfile.readByte();
|
||||
for (int j = 0; j < 4; j++)
|
||||
buffer[i]._exits[j] = _bigfile.readByte();
|
||||
buffer[i]._flags = _bigfile.readByte();
|
||||
if (_vm->getPlatform() == Common::kPlatformMacintosh) {
|
||||
buffer[i]._bank = _bigfile.readUint16BE();
|
||||
buffer[i]._party = _bigfile.readUint16BE();
|
||||
}
|
||||
else {
|
||||
buffer[i]._bank = _bigfile.readUint16LE();
|
||||
buffer[i]._party = _bigfile.readUint16LE();
|
||||
}
|
||||
buffer[i]._level = _bigfile.readByte();
|
||||
buffer[i]._video = _bigfile.readByte();
|
||||
buffer[i]._location = _bigfile.readByte();
|
||||
buffer[i]._backgroundBankNum = _bigfile.readByte();
|
||||
}
|
||||
}
|
||||
|
||||
Common::SeekableReadStream *EdenGame::loadSubStream(uint16 resNum) {
|
||||
assert(resNum < _bigfileHeader->_count);
|
||||
PakHeaderItem *file = &_bigfileHeader->_files[resNum];
|
||||
int size = file->_size;
|
||||
int offs = file->_offs;
|
||||
debug("* Loading file %s at 0x%X, %d bytes", file->_name.c_str(), (uint)offs, size);
|
||||
return new Common::SafeSeekableSubReadStream(&_bigfile, offs, offs + size, DisposeAfterUse::NO);
|
||||
}
|
||||
|
||||
// Original name: ssndfl
|
||||
int EdenGame::loadSound(uint16 num) {
|
||||
unsigned int resNum = num - 1 + ((_vm->getPlatform() == Common::kPlatformDOS && _vm->isDemo()) ? 656 : 661);
|
||||
assert(resNum < _bigfileHeader->_count);
|
||||
PakHeaderItem *file = &_bigfileHeader->_files[resNum];
|
||||
int32 size = file->_size;
|
||||
int32 offs = file->_offs;
|
||||
debug("* Loading sound %d (%s) at 0x%X, %d bytes", num, file->_name.c_str(), (uint)offs, size);
|
||||
if (_soundAllocated) {
|
||||
free(_voiceSamplesBuffer);
|
||||
_voiceSamplesBuffer = nullptr;
|
||||
_soundAllocated = false; //TODO: bug??? no alloc
|
||||
}
|
||||
else {
|
||||
_voiceSamplesBuffer = (byte *)malloc(size);
|
||||
_soundAllocated = true;
|
||||
}
|
||||
|
||||
_bigfile.seek(offs, SEEK_SET);
|
||||
//For PC loaded data is a VOC file, on Mac version this is a raw samples
|
||||
if (_vm->getPlatform() == Common::kPlatformMacintosh)
|
||||
_bigfile.read(_voiceSamplesBuffer, size);
|
||||
else {
|
||||
// VOC files also include extra information for lipsync
|
||||
// 1. Standard VOC header
|
||||
_bigfile.read(_voiceSamplesBuffer, 0x1A);
|
||||
|
||||
// 2. Lipsync?
|
||||
unsigned char chunkType = _bigfile.readByte();
|
||||
|
||||
uint32 val = 0;
|
||||
_bigfile.read(&val, 3);
|
||||
unsigned int chunkLen = FROM_LE_32(val);
|
||||
|
||||
if (chunkType == 5) {
|
||||
_bigfile.read(_gameLipsync + 7260, chunkLen);
|
||||
chunkType = _bigfile.readByte();
|
||||
_bigfile.read(&val, 3);
|
||||
chunkLen = FROM_LE_32(val);
|
||||
}
|
||||
|
||||
// 3. Normal sound data
|
||||
if (chunkType == 1) {
|
||||
_bigfile.readUint16LE();
|
||||
size = chunkLen - 2;
|
||||
_bigfile.read(_voiceSamplesBuffer, size);
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void EdenGame::convertMacToPC() {
|
||||
// Convert all mac (big-endian) resources to native format
|
||||
// Array of longs
|
||||
int *p = (int *)_gameLipsync;
|
||||
for (int i = 0; i < 7240 / 4; i++)
|
||||
p[i] = FROM_BE_32(p[i]);
|
||||
}
|
||||
|
||||
void EdenGame::loadpermfiles() {
|
||||
Common::File f;
|
||||
const int kNumIcons = 136;
|
||||
const int kNumRooms = 424;
|
||||
const int kNumFollowers = 15;
|
||||
const int kNumLabyrinthPath = 70;
|
||||
const int kNumDinoSpeedForCitaLevel = 16;
|
||||
const int kNumTabletView = 12;
|
||||
const int kNumPersoRoomBankTable = 84;
|
||||
const int kNumGotos = 130;
|
||||
const int kNumObjects = 42;
|
||||
const int kNumObjectLocations = 45;
|
||||
const int kNumPersons = 58;
|
||||
const int kNumCitadel = 7;
|
||||
const int kNumCharacterRects = 19;
|
||||
const int kNumCharacters = 20;
|
||||
const int kNumAreas = 12;
|
||||
// tab_2CEF0
|
||||
// tab_2CF70
|
||||
const int kNumActionCursors = 299;
|
||||
|
||||
const int expectedDataSize =
|
||||
kNumIcons * 18 + // sizeof(Icon)
|
||||
kNumRooms * 14 + // sizeof(Room)
|
||||
kNumFollowers * 16 + // sizeof(Follower)
|
||||
kNumLabyrinthPath +
|
||||
kNumDinoSpeedForCitaLevel +
|
||||
kNumTabletView +
|
||||
kNumPersoRoomBankTable +
|
||||
kNumGotos * 5 + // sizeof(Goto)
|
||||
kNumObjects * 12 + // sizeof(object_t)
|
||||
kNumObjectLocations * 2 +
|
||||
kNumPersons * 18 + // sizeof(perso_t)
|
||||
kNumCitadel * 34 + // sizeof(Citadel)
|
||||
kNumCharacterRects * 8 +
|
||||
kNumCharacters * 5 +
|
||||
kNumAreas * 10 + // (sizeof(Area) - 4)
|
||||
64 * 2 +
|
||||
64 * 2 +
|
||||
kNumActionCursors +
|
||||
12 +
|
||||
3 * 6 * 2 * 3 * 2;
|
||||
|
||||
if (f.open("cryo.dat")) {
|
||||
const int dataSize = f.size() - 8 - 4; // CRYODATA + version
|
||||
char headerId[9];
|
||||
|
||||
f.read(headerId, 8);
|
||||
headerId[8] = '\0';
|
||||
if (strcmp(headerId, "CRYODATA"))
|
||||
error("Invalid cryo.dat aux data file");
|
||||
|
||||
if (f.readUint32LE() != CRYO_DAT_VER)
|
||||
error("Incorrect data version for cryo.dat");
|
||||
|
||||
if (dataSize != expectedDataSize)
|
||||
error("Mismatching data in cryo.dat aux data file (got %d, expected %d)", dataSize, expectedDataSize);
|
||||
}
|
||||
else
|
||||
error("Can not load cryo.dat");
|
||||
|
||||
switch (_vm->getPlatform()) {
|
||||
case Common::kPlatformDOS:
|
||||
// Since PC version stores hotspots and rooms info in the executable, load them from premade resource file
|
||||
for (int i = 0; i < kNumIcons; i++) {
|
||||
_gameIcons[i].sx = f.readSint16LE();
|
||||
_gameIcons[i].sy = f.readSint16LE();
|
||||
_gameIcons[i].ex = f.readSint16LE();
|
||||
_gameIcons[i].ey = f.readSint16LE();
|
||||
_gameIcons[i]._cursorId = f.readUint16LE();
|
||||
_gameIcons[i]._actionId = f.readUint32LE();
|
||||
_gameIcons[i]._objectId = f.readUint32LE();
|
||||
}
|
||||
|
||||
for (int i = 0; i < kNumRooms; i++) {
|
||||
_gameRooms[i]._id = f.readByte();
|
||||
for (int j = 0; j < 4; j++)
|
||||
_gameRooms[i]._exits[j] = f.readByte();
|
||||
_gameRooms[i]._flags = f.readByte();
|
||||
_gameRooms[i]._bank = f.readUint16LE();
|
||||
_gameRooms[i]._party = f.readUint16LE();
|
||||
_gameRooms[i]._level = f.readByte();
|
||||
_gameRooms[i]._video = f.readByte();
|
||||
_gameRooms[i]._location = f.readByte();
|
||||
_gameRooms[i]._backgroundBankNum = f.readByte();
|
||||
}
|
||||
break;
|
||||
case Common::kPlatformMacintosh:
|
||||
loadIconFile(2498, _gameIcons);
|
||||
loadRoomFile(2497, _gameRooms);
|
||||
loadRawFile(2486, _gameLipsync);
|
||||
convertMacToPC();
|
||||
|
||||
// Skip the icons and rooms of the DOS version
|
||||
f.skip(kNumIcons * 14 + kNumRooms * 11);
|
||||
break;
|
||||
default:
|
||||
error("Unsupported platform");
|
||||
}
|
||||
|
||||
// Read the common static data
|
||||
|
||||
for (int i = 0; i < kNumFollowers; i++) {
|
||||
_followerList[i]._id = f.readSByte();
|
||||
_followerList[i]._spriteNum = f.readSByte();
|
||||
_followerList[i].sx = f.readSint16LE();
|
||||
_followerList[i].sy = f.readSint16LE();
|
||||
_followerList[i].ex = f.readSint16LE();
|
||||
_followerList[i].ey = f.readSint16LE();
|
||||
_followerList[i]._spriteBank = f.readSint16LE();
|
||||
_followerList[i].ff_C = f.readSint16LE();
|
||||
_followerList[i].ff_E = f.readSint16LE();
|
||||
}
|
||||
|
||||
f.read(_labyrinthPath, kNumLabyrinthPath);
|
||||
f.read(_dinoSpeedForCitadelLevel, kNumDinoSpeedForCitaLevel);
|
||||
f.read(_tabletView, kNumTabletView);
|
||||
f.read(_personRoomBankTable, kNumPersoRoomBankTable);
|
||||
f.read(_gotos, kNumGotos * 5); // sizeof(Goto)
|
||||
|
||||
for (int i = 0; i < kNumObjects; i++) {
|
||||
_objects[i]._id = f.readByte();
|
||||
_objects[i]._flags = f.readByte();
|
||||
_objects[i]._locations = f.readUint32LE();
|
||||
_objects[i]._itemMask = f.readUint16LE();
|
||||
_objects[i]._powerMask = f.readUint16LE();
|
||||
_objects[i]._count = f.readSint16LE();
|
||||
}
|
||||
|
||||
for (int i = 0; i < kNumObjectLocations; i++) {
|
||||
_objectLocations[i] = f.readUint16LE();
|
||||
}
|
||||
|
||||
for (int i = 0; i < kNumPersons; i++) {
|
||||
_persons[i]._roomNum = f.readUint16LE();
|
||||
_persons[i]._actionId = f.readUint16LE();
|
||||
_persons[i]._partyMask = f.readUint16LE();
|
||||
_persons[i]._id = f.readByte();
|
||||
_persons[i]._flags = f.readByte();
|
||||
_persons[i]._roomBankId = f.readByte();
|
||||
_persons[i]._spriteBank = f.readByte();
|
||||
_persons[i]._items = f.readUint16LE();
|
||||
_persons[i]._powers = f.readUint16LE();
|
||||
_persons[i]._targetLoc = f.readByte();
|
||||
_persons[i]._lastLoc = f.readByte();
|
||||
_persons[i]._speed = f.readByte();
|
||||
_persons[i]._steps = f.readByte();
|
||||
}
|
||||
|
||||
for (int i = 0; i < kNumCitadel; i++) {
|
||||
_citadelList[i]._id = f.readSint16LE();
|
||||
for (int j = 0; j < 8; j++)
|
||||
_citadelList[i]._bank[j] = f.readSint16LE();
|
||||
for (int j = 0; j < 8; j++)
|
||||
_citadelList[i]._video[j] = f.readSint16LE();
|
||||
}
|
||||
|
||||
for (int i = 0; i < kNumCharacterRects; i++) {
|
||||
_characterRects[i].left = f.readSint16LE();
|
||||
_characterRects[i].top = f.readSint16LE();
|
||||
_characterRects[i].right = f.readSint16LE();
|
||||
_characterRects[i].bottom = f.readSint16LE();
|
||||
}
|
||||
|
||||
f.read(_characterArray, kNumCharacters * 5);
|
||||
|
||||
for (int i = 0; i < kNumAreas; i++) {
|
||||
_areasTable[i]._num = f.readByte();
|
||||
_areasTable[i]._type = f.readByte();
|
||||
_areasTable[i]._flags = f.readUint16LE();
|
||||
_areasTable[i]._firstRoomIdx = f.readUint16LE();
|
||||
_areasTable[i]._citadelLevel = f.readByte();
|
||||
_areasTable[i]._placeNum = f.readByte();
|
||||
_areasTable[i]._citadelRoomPtr = nullptr;
|
||||
_areasTable[i]._visitCount = f.readSint16LE();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 64; i++) {
|
||||
tab_2CEF0[i] = f.readSint16LE();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 64; i++) {
|
||||
tab_2CF70[i] = f.readSint16LE();
|
||||
}
|
||||
|
||||
f.read(_actionCursors, kNumActionCursors);
|
||||
f.read(_mapMode, 12);
|
||||
f.read(_cubeTextureCoords, 3 * 6 * 2 * 3 * 2);
|
||||
|
||||
f.close();
|
||||
|
||||
loadRawFile(0, _mainBankBuf);
|
||||
loadRawFile(402, _gameFont);
|
||||
loadRawFile(404, _gameDialogs);
|
||||
loadRawFile(403, _gameConditions);
|
||||
}
|
||||
|
||||
bool EdenGame::ReadDataSyncVOC(unsigned int num) {
|
||||
unsigned int resNum = num - 1 + ((_vm->getPlatform() == Common::kPlatformDOS && _vm->isDemo()) ? 656 : 661);
|
||||
unsigned char vocHeader[0x1A];
|
||||
int filePos = 0;
|
||||
loadpartoffile(resNum, vocHeader, filePos, sizeof(vocHeader));
|
||||
filePos += sizeof(vocHeader);
|
||||
unsigned char chunkType = 0;
|
||||
loadpartoffile(resNum, &chunkType, sizeof(vocHeader), 1);
|
||||
filePos++;
|
||||
if (chunkType == 5) {
|
||||
uint32 chunkLen = 0;
|
||||
loadpartoffile(resNum, &chunkLen, filePos, 3);
|
||||
filePos += 3;
|
||||
chunkLen = FROM_LE_32(chunkLen);
|
||||
loadpartoffile(resNum, _gameLipsync + 7260, filePos, chunkLen);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EdenGame::ReadDataSync(uint16 num) {
|
||||
if (_vm->getPlatform() == Common::kPlatformMacintosh) {
|
||||
long pos = READ_LE_UINT32(_gameLipsync + num * 4);
|
||||
if (pos != -1) {
|
||||
long len = 1024;
|
||||
loadpartoffile(1936, _gameLipsync + 7260, pos, len);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
return ReadDataSyncVOC(num + 1); //TODO: remove -1 in caller
|
||||
return false;
|
||||
}
|
||||
|
||||
void EdenGame::loadpartoffile(uint16 num, void *buffer, int32 pos, int32 len) {
|
||||
assert(num < _bigfileHeader->_count);
|
||||
PakHeaderItem *file = &_bigfileHeader->_files[num];
|
||||
int32 offs = READ_LE_UINT32(&file->_offs);
|
||||
debug("* Loading partial resource %d (%s) at 0x%X(+0x%X), %d bytes", num, file->_name.c_str(), offs, pos, len);
|
||||
_bigfile.seek(offs + pos, SEEK_SET);
|
||||
_bigfile.read(buffer, len);
|
||||
}
|
||||
|
||||
void EdenGame::expandHSQ(byte *input, byte *output) {
|
||||
byte *src = input;
|
||||
byte *dst = output;
|
||||
byte *ptr;
|
||||
uint16 bit; // bit
|
||||
uint16 queue = 0; // queue
|
||||
uint16 len = 0;
|
||||
int16 ofs;
|
||||
#define GetBit \
|
||||
bit = queue & 1; \
|
||||
queue >>= 1; \
|
||||
if (!queue) { \
|
||||
queue = (src[1] << 8) | src[0]; src += 2; \
|
||||
bit = queue & 1; \
|
||||
queue = (queue >> 1) | 0x8000; \
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
GetBit;
|
||||
if (bit)
|
||||
*dst++ = *src++;
|
||||
else {
|
||||
len = 0;
|
||||
GetBit;
|
||||
if (!bit) {
|
||||
GetBit;
|
||||
len = (len << 1) | bit;
|
||||
GetBit;
|
||||
len = (len << 1) | bit;
|
||||
ofs = 0xFF00 | *src++; //TODO: -256
|
||||
}
|
||||
else {
|
||||
ofs = (src[1] << 8) | src[0];
|
||||
src += 2;
|
||||
len = ofs & 7;
|
||||
ofs = (ofs >> 3) | 0xE000;
|
||||
if (!len) {
|
||||
len = *src++;
|
||||
if (!len)
|
||||
break;
|
||||
}
|
||||
}
|
||||
ptr = dst + ofs;
|
||||
len += 2;
|
||||
while (len--)
|
||||
*dst++ = *ptr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Cryo
|
||||
Reference in New Issue
Block a user