diff options
author | Filippos Karapetis | 2009-05-15 14:07:45 +0000 |
---|---|---|
committer | Filippos Karapetis | 2009-05-15 14:07:45 +0000 |
commit | 87e8f94fde8330e1d5e600cc7b3e5c24225d6158 (patch) | |
tree | 2774c88f62f0491b480e0add2dd7e009546e7a74 /engines/sci/scicore | |
parent | ce29fec17a9316b5fee0349d013a4d7863af9c03 (diff) | |
download | scummvm-rg350-87e8f94fde8330e1d5e600cc7b3e5c24225d6158.tar.gz scummvm-rg350-87e8f94fde8330e1d5e600cc7b3e5c24225d6158.tar.bz2 scummvm-rg350-87e8f94fde8330e1d5e600cc7b3e5c24225d6158.zip |
- Moved all the files out of /sci/scicore and into /sci
- Moved /scicore/sciconsole.h into /engine, and renamed /engine/scriptconsole.cpp to /engine/sciconsole.cpp
svn-id: r40608
Diffstat (limited to 'engines/sci/scicore')
-rw-r--r-- | engines/sci/scicore/decompressor.cpp | 969 | ||||
-rw-r--r-- | engines/sci/scicore/decompressor.h | 201 | ||||
-rw-r--r-- | engines/sci/scicore/resource.cpp | 1161 | ||||
-rw-r--r-- | engines/sci/scicore/resource.h | 302 | ||||
-rw-r--r-- | engines/sci/scicore/sciconsole.h | 130 | ||||
-rw-r--r-- | engines/sci/scicore/vocab_debug.cpp | 518 | ||||
-rw-r--r-- | engines/sci/scicore/vocabulary.cpp | 566 | ||||
-rw-r--r-- | engines/sci/scicore/vocabulary.h | 359 |
8 files changed, 0 insertions, 4206 deletions
diff --git a/engines/sci/scicore/decompressor.cpp b/engines/sci/scicore/decompressor.cpp deleted file mode 100644 index 91738aa1d8..0000000000 --- a/engines/sci/scicore/decompressor.cpp +++ /dev/null @@ -1,969 +0,0 @@ -/* 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -// Resource library - -#include "common/util.h" -#include "common/endian.h" -#include "common/debug.h" - -#include "sci/scicore/decompressor.h" -#include "sci/sci.h" - -namespace Sci { -int Decompressor::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) { - uint32 chunk; - while (nPacked && !src->ioFailed()) { - chunk = MIN<uint32>(1024, nPacked); - src->read(dest, chunk); - nPacked -= chunk; - dest += chunk; - } - return src->ioFailed() ? 1 : 0; -} - -void Decompressor::init(Common::ReadStream *src, byte *dest, uint32 nPacked, - uint32 nUnpacked) { - _src = src; - _dest = dest; - _szPacked = nPacked; - _szUnpacked = nUnpacked; - _nBits = 0; - _dwRead = _dwWrote = 0; - _dwBits = 0; -} - -void Decompressor::fetchBitsMSB() { - while (_nBits <= 24) { - _dwBits |= ((uint32)_src->readByte()) << (24 - _nBits); - _nBits += 8; - _dwRead++; - } -} - -uint32 Decompressor::getBitsMSB(int n) { - // fetching more data to buffer if needed - if (_nBits < n) - fetchBitsMSB(); - uint32 ret = _dwBits >> (32 - n); - _dwBits <<= n; - _nBits -= n; - return ret; -} - -byte Decompressor::getByteMSB() { - return getBitsMSB(8); -} - -void Decompressor::fetchBitsLSB() { - while (_nBits <= 24) { - _dwBits |= ((uint32)_src->readByte()) << _nBits; - _nBits += 8; - _dwRead++; - } -} - -uint32 Decompressor::getBitsLSB(int n) { - // fetching more data to buffer if needed - if (_nBits < n) - fetchBitsLSB(); - uint32 ret = (_dwBits & ~((~0) << n)); - _dwBits >>= n; - _nBits -= n; - return ret; -} - -byte Decompressor::getByteLSB() { - return getBitsLSB(8); -} - -void Decompressor::putByte(byte b) { - _dest[_dwWrote++] = b; -} -//------------------------------- -// Huffman decompressor -//------------------------------- -int DecompressorHuffman::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, - uint32 nUnpacked) { - init(src, dest, nPacked, nUnpacked); - byte numnodes; - int16 c; - uint16 terminator; - - numnodes = _src->readByte(); - terminator = _src->readByte() | 0x100; - _nodes = new byte [numnodes << 1]; - _src->read(_nodes, numnodes << 1); - - while ((c = getc2()) != terminator && (c >= 0) && !isFinished()) - putByte(c); - - delete[] _nodes; - return _dwWrote == _szUnpacked ? 0 : 1; -} - -int16 DecompressorHuffman::getc2() { - byte *node = _nodes; - int16 next; - while (node[1]) { - if (getBitsMSB(1)) { - next = node[1] & 0x0F; // use lower 4 bits - if (next == 0) - return getByteMSB() | 0x100; - } else - next = node[1] >> 4; // use higher 4 bits - node += next << 1; - } - return (int16)(*node | (node[1] << 8)); -} - -//------------------------------- -// LZW Decompressor for SCI0/01/1 -//------------------------------- -void DecompressorLZW::init(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) { - Decompressor::init(src, dest, nPacked, nUnpacked); - - _numbits = 9; - _curtoken = 0x102; - _endtoken = 0x1ff; -} - -int DecompressorLZW::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, - uint32 nUnpacked) { - byte *buffer = NULL; - - switch (_compression) { - case kCompLZW: // SCI0 LZW compression - return unpackLZW(src, dest, nPacked, nUnpacked); - break; - case kCompLZW1: // SCI01/1 LZW compression - return unpackLZW1(src, dest, nPacked, nUnpacked); - break; - case kCompLZW1View: - buffer = new byte[nUnpacked]; - unpackLZW1(src, buffer, nPacked, nUnpacked); - reorderView(buffer, dest); - break; - case kCompLZW1Pic: - buffer = new byte[nUnpacked]; - unpackLZW1(src, buffer, nPacked, nUnpacked); - reorderPic(buffer, dest, nUnpacked); - break; - } - delete[] buffer; - return 0; -} - -int DecompressorLZW::unpackLZW(Common::ReadStream *src, byte *dest, uint32 nPacked, - uint32 nUnpacked) { - init(src, dest, nPacked, nUnpacked); - - uint16 token; // The last received value - - uint16 tokenlist[4096]; // pointers to dest[] - uint16 tokenlengthlist[4096]; // char length of each token - uint16 tokenlastlength = 0; - - while (!isFinished()) { - token = getBitsLSB(_numbits); - - if (token == 0x101) - return 0; // terminator - if (token == 0x100) { // reset command - _numbits = 9; - _endtoken = 0x1FF; - _curtoken = 0x0102; - } else { - if (token > 0xff) { - if (token >= _curtoken) { - warning("unpackLZW: Bad token %x", token); - return SCI_ERROR_DECOMPRESSION_ERROR; - } - tokenlastlength = tokenlengthlist[token] + 1; - if (_dwWrote + tokenlastlength > _szUnpacked) { - // For me this seems a normal situation, It's necessary to handle it - warning("unpackLZW: Trying to write beyond the end of array(len=%d, destctr=%d, tok_len=%d)", - _szUnpacked, _dwWrote, tokenlastlength); - for (int i = 0; _dwWrote < _szUnpacked; i++) - putByte(dest[tokenlist[token] + i]); - } else - for (int i = 0; i < tokenlastlength; i++) - putByte(dest[tokenlist[token] + i]); - } else { - tokenlastlength = 1; - if (_dwWrote >= _szUnpacked) - warning("unpackLZW: Try to write single byte beyond end of array"); - else - putByte(token); - } - if (_curtoken > _endtoken && _numbits < 12) { - _numbits++; - _endtoken = (_endtoken << 1) + 1; - } - if (_curtoken <= _endtoken) { - tokenlist[_curtoken] = _dwWrote - tokenlastlength; - tokenlengthlist[_curtoken] = tokenlastlength; - _curtoken++; - } - - } - } - - return _dwWrote == _szUnpacked ? 0 : SCI_ERROR_DECOMPRESSION_ERROR; -} - -int DecompressorLZW::unpackLZW1(Common::ReadStream *src, byte *dest, uint32 nPacked, - uint32 nUnpacked) { - init(src, dest, nPacked, nUnpacked); - - byte stak[0x1014]; - byte lastchar = 0; - uint16 stakptr = 0, lastbits = 0; - Tokenlist tokens[0x1004]; - memset(tokens, 0, sizeof(tokens)); - - - byte decryptstart = 0; - uint16 bitstring; - uint16 token; - bool bExit = false; - - while (!isFinished() && !bExit) { - switch (decryptstart) { - case 0: - bitstring = getBitsMSB(_numbits); - if (bitstring == 0x101) {// found end-of-data signal - bExit = true; - continue; - } - putByte(bitstring); - lastbits = bitstring; - lastchar = (bitstring & 0xff); - decryptstart = 1; - break; - - case 1: - bitstring = getBitsMSB(_numbits); - if (bitstring == 0x101) { // found end-of-data signal - bExit = true; - continue; - } - if (bitstring == 0x100) { // start-over signal - _numbits = 9; - _curtoken = 0x102; - _endtoken = 0x1ff; - decryptstart = 0; - continue; - } - - token = bitstring; - if (token >= _curtoken) { // index past current point - token = lastbits; - stak[stakptr++] = lastchar; - } - while ((token > 0xff) && (token < 0x1004)) { // follow links back in data - stak[stakptr++] = tokens[token].data; - token = tokens[token].next; - } - lastchar = stak[stakptr++] = token & 0xff; - // put stack in buffer - while (stakptr > 0) { - putByte(stak[--stakptr]); - if (_dwWrote == _szUnpacked) { - bExit = true; - continue; - } - } - // put token into record - if (_curtoken <= _endtoken) { - tokens[_curtoken].data = lastchar; - tokens[_curtoken].next = lastbits; - _curtoken++; - if (_curtoken == _endtoken && _numbits < 12) { - _numbits++; - _endtoken = (_endtoken << 1) + 1; - } - } - lastbits = bitstring; - break; - } - } - return _dwWrote == _szUnpacked ? 0 : SCI_ERROR_DECOMPRESSION_ERROR; -} - -#define PAL_SIZE 1284 -#define EXTRA_MAGIC_SIZE 15 -#define VIEW_HEADER_COLORS_8BIT 0x80 - -void DecompressorLZW::decodeRLE(byte **rledata, byte **pixeldata, byte *outbuffer, int size) { - int pos = 0; - byte nextbyte; - byte *rd = *rledata; - byte *ob = outbuffer; - byte *pd = *pixeldata; - - while (pos < size) { - nextbyte = *rd++; - *ob++ = nextbyte; - pos++; - switch (nextbyte & 0xC0) { - case 0x40: - case 0x00: - memcpy(ob, pd, nextbyte); - pd += nextbyte; - ob += nextbyte; - pos += nextbyte; - break; - case 0xC0: - break; - case 0x80: - nextbyte = *pd++; - *ob++ = nextbyte; - pos++; - break; - } - } - - *rledata = rd; - *pixeldata = pd; -} - -/** - * Does the same this as decodeRLE, only to determine the length of the - * compressed source data. - */ -int DecompressorLZW::getRLEsize(byte *rledata, int dsize) { - int pos = 0; - byte nextbyte; - int size = 0; - - while (pos < dsize) { - nextbyte = *(rledata++); - pos++; - size++; - - switch (nextbyte & 0xC0) { - case 0x40: - case 0x00: - pos += nextbyte; - break; - case 0xC0: - break; - case 0x80: - pos++; - break; - } - } - - return size; -} - -void DecompressorLZW::reorderPic(byte *src, byte *dest, int dsize) { - uint16 view_size, view_start, cdata_size; - int i; - byte *seeker = src; - byte *writer = dest; - char viewdata[7]; - byte *cdata, *cdata_start; - - *writer++ = PIC_OP_OPX; - *writer++ = PIC_OPX_SET_PALETTE; - - for (i = 0; i < 256; i++) /* Palette translation map */ - *writer++ = i; - - WRITE_LE_UINT32(writer, 0); /* Palette stamp */ - writer += 4; - - view_size = READ_LE_UINT16(seeker); - seeker += 2; - view_start = READ_LE_UINT16(seeker); - seeker += 2; - cdata_size = READ_LE_UINT16(seeker); - seeker += 2; - - memcpy(viewdata, seeker, sizeof(viewdata)); - seeker += sizeof(viewdata); - - memcpy(writer, seeker, 4*256); /* Palette */ - seeker += 4*256; - writer += 4*256; - - if (view_start != PAL_SIZE + 2) { /* +2 for the opcode */ - memcpy(writer, seeker, view_start-PAL_SIZE-2); - seeker += view_start - PAL_SIZE - 2; - writer += view_start - PAL_SIZE - 2; - } - - if (dsize != view_start + EXTRA_MAGIC_SIZE + view_size) { - memcpy(dest + view_size + view_start + EXTRA_MAGIC_SIZE, seeker, - dsize - view_size - view_start - EXTRA_MAGIC_SIZE); - seeker += dsize - view_size - view_start - EXTRA_MAGIC_SIZE; - } - - cdata_start = cdata = (byte *)malloc(cdata_size); - memcpy(cdata, seeker, cdata_size); - seeker += cdata_size; - - writer = dest + view_start; - *writer++ = PIC_OP_OPX; - *writer++ = PIC_OPX_EMBEDDED_VIEW; - *writer++ = 0; - *writer++ = 0; - *writer++ = 0; - WRITE_LE_UINT16(writer, view_size + 8); - writer += 2; - - memcpy(writer, viewdata, sizeof(viewdata)); - writer += sizeof(viewdata); - - *writer++ = 0; - - decodeRLE(&seeker, &cdata, writer, view_size); - - free(cdata_start); -} - -void DecompressorLZW::buildCelHeaders(byte **seeker, byte **writer, int celindex, int *cc_lengths, int max) { - for (int c = 0; c < max; c++) { - memcpy(*writer, *seeker, 6); - *seeker += 6; - *writer += 6; - int w = *((*seeker)++); - WRITE_LE_UINT16(*writer, w); /* Zero extension */ - *writer += 2; - - *writer += cc_lengths[celindex]; - celindex++; - } -} - -void DecompressorLZW::reorderView(byte *src, byte *dest) { - byte *cellengths; - int loopheaders; - int lh_present; - int lh_mask; - int pal_offset; - int cel_total; - int unknown; - byte *seeker = src; - char celcounts[100]; - byte *writer = dest; - byte *lh_ptr; - byte *rle_ptr, *pix_ptr; - int l, lb, c, celindex, lh_last = -1; - int chptr; - int w; - int *cc_lengths; - byte **cc_pos; - - /* Parse the main header */ - cellengths = src + READ_LE_UINT16(seeker) + 2; - seeker += 2; - loopheaders = *seeker++; - lh_present = *seeker++; - lh_mask = READ_LE_UINT16(seeker); - seeker += 2; - unknown = READ_LE_UINT16(seeker); - seeker += 2; - pal_offset = READ_LE_UINT16(seeker); - seeker += 2; - cel_total = READ_LE_UINT16(seeker); - seeker += 2; - - cc_pos = (byte **) malloc(sizeof(byte *) * cel_total); - cc_lengths = (int *) malloc(sizeof(int) * cel_total); - - for (c = 0; c < cel_total; c++) - cc_lengths[c] = READ_LE_UINT16(cellengths + 2 * c); - - *writer++ = loopheaders; - *writer++ = VIEW_HEADER_COLORS_8BIT; - WRITE_LE_UINT16(writer, lh_mask); - writer += 2; - WRITE_LE_UINT16(writer, unknown); - writer += 2; - WRITE_LE_UINT16(writer, pal_offset); - writer += 2; - - lh_ptr = writer; - writer += 2 * loopheaders; /* Make room for the loop offset table */ - - pix_ptr = writer; - - memcpy(celcounts, seeker, lh_present); - seeker += lh_present; - - lb = 1; - celindex = 0; - - rle_ptr = pix_ptr = cellengths + (2 * cel_total); - w = 0; - - for (l = 0; l < loopheaders; l++) { - if (lh_mask & lb) { /* The loop is _not_ present */ - if (lh_last == -1) { - warning("Error: While reordering view: Loop not present, but can't re-use last loop"); - lh_last = 0; - } - WRITE_LE_UINT16(lh_ptr, lh_last); - lh_ptr += 2; - } else { - lh_last = writer - dest; - WRITE_LE_UINT16(lh_ptr, lh_last); - lh_ptr += 2; - WRITE_LE_UINT16(writer, celcounts[w]); - writer += 2; - WRITE_LE_UINT16(writer, 0); - writer += 2; - - /* Now, build the cel offset table */ - chptr = (writer - dest) + (2 * celcounts[w]); - - for (c = 0; c < celcounts[w]; c++) { - WRITE_LE_UINT16(writer, chptr); - writer += 2; - cc_pos[celindex+c] = dest + chptr; - chptr += 8 + READ_LE_UINT16(cellengths + 2 * (celindex + c)); - } - - buildCelHeaders(&seeker, &writer, celindex, cc_lengths, celcounts[w]); - - celindex += celcounts[w]; - w++; - } - - lb = lb << 1; - } - - if (celindex < cel_total) { - warning("View decompression generated too few (%d / %d) headers", celindex, cel_total); - return; - } - - /* Figure out where the pixel data begins. */ - for (c = 0; c < cel_total; c++) - pix_ptr += getRLEsize(pix_ptr, cc_lengths[c]); - - rle_ptr = cellengths + (2 * cel_total); - for (c = 0; c < cel_total; c++) - decodeRLE(&rle_ptr, &pix_ptr, cc_pos[c] + 8, cc_lengths[c]); - - *writer++ = 'P'; - *writer++ = 'A'; - *writer++ = 'L'; - - for (c = 0; c < 256; c++) - *writer++ = c; - - seeker -= 4; /* The missing four. Don't ask why. */ - memcpy(writer, seeker, 4*256 + 4); - - free(cc_pos); - free(cc_lengths); -} - -//---------------------------------------------- -// DCL decompressor for SCI1.1 -//---------------------------------------------- -#define HUFFMAN_LEAF 0x40000000 -// Branch node -#define BN(pos, left, right) ((left << 12) | (right)), -// Leaf node -#define LN(pos, value) ((value) | HUFFMAN_LEAF), - -static int length_tree[] = { - BN(0, 1, 2) - BN(1, 3, 4) BN(2, 5, 6) - BN(3, 7, 8) BN(4, 9, 10) BN(5, 11, 12) LN(6, 1) - BN(7, 13, 14) BN(8, 15, 16) BN(9, 17, 18) LN(10, 3) LN(11, 2) LN(12, 0) - BN(13, 19, 20) BN(14, 21, 22) BN(15, 23, 24) LN(16, 6) LN(17, 5) LN(18, 4) - BN(19, 25, 26) BN(20, 27, 28) LN(21, 10) LN(22, 9) LN(23, 8) LN(24, 7) - BN(25, 29, 30) LN(26, 13) LN(27, 12) LN(28, 11) - LN(29, 15) LN(30, 14) - 0 // We need something witout a comma at the end -}; - -static int distance_tree[] = { - BN(0, 1, 2) - BN(1, 3, 4) BN(2, 5, 6) - // - BN(3, 7, 8) BN(4, 9, 10) BN(5, 11, 12) LN(6, 0) - BN(7, 13, 14) BN(8, 15, 16) BN(9, 17, 18) BN(10, 19, 20) - BN(11, 21, 22) BN(12, 23, 24) - // - BN(13, 25, 26) BN(14, 27, 28) BN(15, 29, 30) BN(16, 31, 32) - BN(17, 33, 34) BN(18, 35, 36) BN(19, 37, 38) BN(20, 39, 40) - BN(21, 41, 42) BN(22, 43, 44) LN(23, 2) LN(24, 1) - // - BN(25, 45, 46) BN(26, 47, 48) BN(27, 49, 50) BN(28, 51, 52) - BN(29, 53, 54) BN(30, 55, 56) BN(31, 57, 58) BN(32, 59, 60) - BN(33, 61, 62) BN(34, 63, 64) BN(35, 65, 66) BN(36, 67, 68) - BN(37, 69, 70) BN(38, 71, 72) BN(39, 73, 74) BN(40, 75, 76) - LN(41, 6) LN(42, 5) LN(43, 4) LN(44, 3) - // - BN(45, 77, 78) BN(46, 79, 80) BN(47, 81, 82) BN(48, 83, 84) - BN(49, 85, 86) BN(50, 87, 88) BN(51, 89, 90) BN(52, 91, 92) - BN(53, 93, 94) BN(54, 95, 96) BN(55, 97, 98) BN(56, 99, 100) - BN(57, 101, 102) BN(58, 103, 104) BN(59, 105, 106) BN(60, 107, 108) - BN(61, 109, 110) LN(62, 21) LN(63, 20) LN(64, 19) - LN(65, 18) LN(66, 17) LN(67, 16) LN(68, 15) - LN(69, 14) LN(70, 13) LN(71, 12) LN(72, 11) - LN(73, 10) LN(74, 9) LN(75, 8) LN(76, 7) - // - BN(77, 111, 112) BN(78, 113, 114) BN(79, 115, 116) BN(80, 117, 118) - BN(81, 119, 120) BN(82, 121, 122) BN(83, 123, 124) BN(84, 125, 126) - LN(85, 47) LN(86, 46) LN(87, 45) LN(88, 44) - LN(89, 43) LN(90, 42) LN(91, 41) LN(92, 40) - LN(93, 39) LN(94, 38) LN(95, 37) LN(96, 36) - LN(97, 35) LN(98, 34) LN(99, 33) LN(100, 32) - LN(101, 31) LN(102, 30) LN(103, 29) LN(104, 28) - LN(105, 27) LN(106, 26) LN(107, 25) LN(108, 24) - LN(109, 23) LN(110, 22) LN(111, 63) LN(112, 62) - LN(113, 61) LN(114, 60) LN(115, 59) LN(116, 58) - LN(117, 57) LN(118, 56) LN(119, 55) LN(120, 54) - LN(121, 53) LN(122, 52) LN(123, 51) LN(124, 50) - LN(125, 49) LN(126, 48) - 0 // We need something witout a comma at the end -}; - -static int ascii_tree[] = { - BN(0, 1, 2) BN(1, 3, 4) BN(2, 5, 6) BN(3, 7, 8) - BN(4, 9, 10) BN(5, 11, 12) BN(6, 13, 14) BN(7, 15, 16) - BN(8, 17, 18) BN(9, 19, 20) BN(10, 21, 22) BN(11, 23, 24) - BN(12, 25, 26) BN(13, 27, 28) BN(14, 29, 30) BN(15, 31, 32) - BN(16, 33, 34) BN(17, 35, 36) BN(18, 37, 38) BN(19, 39, 40) - BN(20, 41, 42) BN(21, 43, 44) BN(22, 45, 46) BN(23, 47, 48) - BN(24, 49, 50) BN(25, 51, 52) BN(26, 53, 54) BN(27, 55, 56) - BN(28, 57, 58) BN(29, 59, 60) LN(30, 32) - // - BN(31, 61, 62) BN(32, 63, 64) BN(33, 65, 66) BN(34, 67, 68) - BN(35, 69, 70) BN(36, 71, 72) BN(37, 73, 74) BN(38, 75, 76) - BN(39, 77, 78) BN(40, 79, 80) BN(41, 81, 82) BN(42, 83, 84) - BN(43, 85, 86) BN(44, 87, 88) BN(45, 89, 90) BN(46, 91, 92) - BN(47, 93, 94) BN(48, 95, 96) BN(49, 97, 98) LN(50, 117) - LN(51, 116) LN(52, 115) LN(53, 114) LN(54, 111) - LN(55, 110) LN(56, 108) LN(57, 105) LN(58, 101) - LN(59, 97) LN(60, 69) - // - BN(61, 99, 100) BN(62, 101, 102) BN(63, 103, 104) BN(64, 105, 106) - BN(65, 107, 108) BN(66, 109, 110) BN(67, 111, 112) BN(68, 113, 114) - BN(69, 115, 116) BN(70, 117, 118) BN(71, 119, 120) BN(72, 121, 122) - BN(73, 123, 124) BN(74, 125, 126) BN(75, 127, 128) BN(76, 129, 130) - BN(77, 131, 132) BN(78, 133, 134) LN(79, 112) LN(80, 109) - LN(81, 104) LN(82, 103) LN(83, 102) LN(84, 100) - LN(85, 99) LN(86, 98) LN(87, 84) LN(88, 83) - LN(89, 82) LN(90, 79) LN(91, 78) LN(92, 76) - LN(93, 73) LN(94, 68) LN(95, 67) LN(96, 65) - LN(97, 49) LN(98, 45) - // - BN(99, 135, 136) BN(100, 137, 138) BN(101, 139, 140) BN(102, 141, 142) - BN(103, 143, 144) BN(104, 145, 146) BN(105, 147, 148) BN(106, 149, 150) - BN(107, 151, 152) BN(108, 153, 154) BN(109, 155, 156) BN(110, 157, 158) - BN(111, 159, 160) BN(112, 161, 162) BN(113, 163, 164) LN(114, 119) - LN(115, 107) LN(116, 85) LN(117, 80) LN(118, 77) - LN(119, 70) LN(120, 66) LN(121, 61) LN(122, 56) - LN(123, 55) LN(124, 53) LN(125, 52) LN(126, 51) - LN(127, 50) LN(128, 48) LN(129, 46) LN(130, 44) - LN(131, 41) LN(132, 40) LN(133, 13) LN(134, 10) - // - BN(135, 165, 166) BN(136, 167, 168) BN(137, 169, 170) BN(138, 171, 172) - BN(139, 173, 174) BN(140, 175, 176) BN(141, 177, 178) BN(142, 179, 180) - BN(143, 181, 182) BN(144, 183, 184) BN(145, 185, 186) BN(146, 187, 188) - BN(147, 189, 190) BN(148, 191, 192) LN(149, 121) LN(150, 120) - LN(151, 118) LN(152, 95) LN(153, 91) LN(154, 87) - LN(155, 72) LN(156, 71) LN(157, 58) LN(158, 57) - LN(159, 54) LN(160, 47) LN(161, 42) LN(162, 39) - LN(163, 34) LN(164, 9) - // - BN(165, 193, 194) BN(166, 195, 196) BN(167, 197, 198) BN(168, 199, 200) - BN(169, 201, 202) BN(170, 203, 204) BN(171, 205, 206) BN(172, 207, 208) - BN(173, 209, 210) BN(174, 211, 212) BN(175, 213, 214) BN(176, 215, 216) - BN(177, 217, 218) BN(178, 219, 220) BN(179, 221, 222) BN(180, 223, 224) - BN(181, 225, 226) BN(182, 227, 228) BN(183, 229, 230) BN(184, 231, 232) - BN(185, 233, 234) LN(186, 93) LN(187, 89) LN(188, 88) - LN(189, 86) LN(190, 75) LN(191, 62) LN(192, 43) - // - BN(193, 235, 236) BN(194, 237, 238) BN(195, 239, 240) BN(196, 241, 242) - BN(197, 243, 244) BN(198, 245, 246) BN(199, 247, 248) BN(200, 249, 250) - BN(201, 251, 252) BN(202, 253, 254) BN(203, 255, 256) BN(204, 257, 258) - BN(205, 259, 260) BN(206, 261, 262) BN(207, 263, 264) BN(208, 265, 266) - BN(209, 267, 268) BN(210, 269, 270) BN(211, 271, 272) BN(212, 273, 274) - BN(213, 275, 276) BN(214, 277, 278) BN(215, 279, 280) BN(216, 281, 282) - BN(217, 283, 284) BN(218, 285, 286) BN(219, 287, 288) BN(220, 289, 290) - BN(221, 291, 292) BN(222, 293, 294) BN(223, 295, 296) BN(224, 297, 298) - BN(225, 299, 300) BN(226, 301, 302) BN(227, 303, 304) BN(228, 305, 306) - BN(229, 307, 308) LN(230, 122) LN(231, 113) LN(232, 38) - LN(233, 36) LN(234, 33) - // - BN(235, 309, 310) BN(236, 311, 312) BN(237, 313, 314) BN(238, 315, 316) - BN(239, 317, 318) BN(240, 319, 320) BN(241, 321, 322) BN(242, 323, 324) - BN(243, 325, 326) BN(244, 327, 328) BN(245, 329, 330) BN(246, 331, 332) - BN(247, 333, 334) BN(248, 335, 336) BN(249, 337, 338) BN(250, 339, 340) - BN(251, 341, 342) BN(252, 343, 344) BN(253, 345, 346) BN(254, 347, 348) - BN(255, 349, 350) BN(256, 351, 352) BN(257, 353, 354) BN(258, 355, 356) - BN(259, 357, 358) BN(260, 359, 360) BN(261, 361, 362) BN(262, 363, 364) - BN(263, 365, 366) BN(264, 367, 368) BN(265, 369, 370) BN(266, 371, 372) - BN(267, 373, 374) BN(268, 375, 376) BN(269, 377, 378) BN(270, 379, 380) - BN(271, 381, 382) BN(272, 383, 384) BN(273, 385, 386) BN(274, 387, 388) - BN(275, 389, 390) BN(276, 391, 392) BN(277, 393, 394) BN(278, 395, 396) - BN(279, 397, 398) BN(280, 399, 400) BN(281, 401, 402) BN(282, 403, 404) - BN(283, 405, 406) BN(284, 407, 408) BN(285, 409, 410) BN(286, 411, 412) - BN(287, 413, 414) BN(288, 415, 416) BN(289, 417, 418) BN(290, 419, 420) - BN(291, 421, 422) BN(292, 423, 424) BN(293, 425, 426) BN(294, 427, 428) - BN(295, 429, 430) BN(296, 431, 432) BN(297, 433, 434) BN(298, 435, 436) - LN(299, 124) LN(300, 123) LN(301, 106) LN(302, 92) - LN(303, 90) LN(304, 81) LN(305, 74) LN(306, 63) - LN(307, 60) LN(308, 0) - // - BN(309, 437, 438) BN(310, 439, 440) BN(311, 441, 442) BN(312, 443, 444) - BN(313, 445, 446) BN(314, 447, 448) BN(315, 449, 450) BN(316, 451, 452) - BN(317, 453, 454) BN(318, 455, 456) BN(319, 457, 458) BN(320, 459, 460) - BN(321, 461, 462) BN(322, 463, 464) BN(323, 465, 466) BN(324, 467, 468) - BN(325, 469, 470) BN(326, 471, 472) BN(327, 473, 474) BN(328, 475, 476) - BN(329, 477, 478) BN(330, 479, 480) BN(331, 481, 482) BN(332, 483, 484) - BN(333, 485, 486) BN(334, 487, 488) BN(335, 489, 490) BN(336, 491, 492) - BN(337, 493, 494) BN(338, 495, 496) BN(339, 497, 498) BN(340, 499, 500) - BN(341, 501, 502) BN(342, 503, 504) BN(343, 505, 506) BN(344, 507, 508) - BN(345, 509, 510) LN(346, 244) LN(347, 243) LN(348, 242) - LN(349, 238) LN(350, 233) LN(351, 229) LN(352, 225) - LN(353, 223) LN(354, 222) LN(355, 221) LN(356, 220) - LN(357, 219) LN(358, 218) LN(359, 217) LN(360, 216) - LN(361, 215) LN(362, 214) LN(363, 213) LN(364, 212) - LN(365, 211) LN(366, 210) LN(367, 209) LN(368, 208) - LN(369, 207) LN(370, 206) LN(371, 205) LN(372, 204) - LN(373, 203) LN(374, 202) LN(375, 201) LN(376, 200) - LN(377, 199) LN(378, 198) LN(379, 197) LN(380, 196) - LN(381, 195) LN(382, 194) LN(383, 193) LN(384, 192) - LN(385, 191) LN(386, 190) LN(387, 189) LN(388, 188) - LN(389, 187) LN(390, 186) LN(391, 185) LN(392, 184) - LN(393, 183) LN(394, 182) LN(395, 181) LN(396, 180) - LN(397, 179) LN(398, 178) LN(399, 177) LN(400, 176) - LN(401, 127) LN(402, 126) LN(403, 125) LN(404, 96) - LN(405, 94) LN(406, 64) LN(407, 59) LN(408, 37) - LN(409, 35) LN(410, 31) LN(411, 30) LN(412, 29) - LN(413, 28) LN(414, 27) LN(415, 25) LN(416, 24) - LN(417, 23) LN(418, 22) LN(419, 21) LN(420, 20) - LN(421, 19) LN(422, 18) LN(423, 17) LN(424, 16) - LN(425, 15) LN(426, 14) LN(427, 12) LN(428, 11) - LN(429, 8) LN(430, 7) LN(431, 6) LN(432, 5) - LN(433, 4) LN(434, 3) LN(435, 2) LN(436, 1) - LN(437, 255) LN(438, 254) LN(439, 253) LN(440, 252) - LN(441, 251) LN(442, 250) LN(443, 249) LN(444, 248) - LN(445, 247) LN(446, 246) LN(447, 245) LN(448, 241) - LN(449, 240) LN(450, 239) LN(451, 237) LN(452, 236) - LN(453, 235) LN(454, 234) LN(455, 232) LN(456, 231) - LN(457, 230) LN(458, 228) LN(459, 227) LN(460, 226) - LN(461, 224) LN(462, 175) LN(463, 174) LN(464, 173) - LN(465, 172) LN(466, 171) LN(467, 170) LN(468, 169) - LN(469, 168) LN(470, 167) LN(471, 166) LN(472, 165) - LN(473, 164) LN(474, 163) LN(475, 162) LN(476, 161) - LN(477, 160) LN(478, 159) LN(479, 158) LN(480, 157) - LN(481, 156) LN(482, 155) LN(483, 154) LN(484, 153) - LN(485, 152) LN(486, 151) LN(487, 150) LN(488, 149) - LN(489, 148) LN(490, 147) LN(491, 146) LN(492, 145) - LN(493, 144) LN(494, 143) LN(495, 142) LN(496, 141) - LN(497, 140) LN(498, 139) LN(499, 138) LN(500, 137) - LN(501, 136) LN(502, 135) LN(503, 134) LN(504, 133) - LN(505, 132) LN(506, 131) LN(507, 130) LN(508, 129) - LN(509, 128) LN(510, 26) -}; - -int DecompressorDCL::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, - uint32 nUnpacked) { - init(src, dest, nPacked, nUnpacked); - return unpackDCL(dest); -} - - -int DecompressorDCL::huffman_lookup(int *tree) { - int pos = 0; - int bit; - - while (!(tree[pos] & HUFFMAN_LEAF)) { - bit = getBitsLSB(1); - debugC(kDebugLevelDclInflate, "[%d]:%d->", pos, bit); - pos = bit ? tree[pos] & 0xFFF : tree[pos] >> 12; - } - debugC(kDebugLevelDclInflate, "=%02x\n", tree[pos] & 0xffff); - return tree[pos] & 0xFFFF; -} - -#define DCL_ASCII_MODE 1 - -int DecompressorDCL::unpackDCL(byte* dest) { - int mode, length_param, value; - uint32 val_distance, val_length; - - mode = getByteLSB(); - length_param = getByteLSB(); - - if (mode == DCL_ASCII_MODE) { - //warning("DCL-INFLATE: Decompressing ASCII mode (untested)"); - } else if (mode) { - warning("DCL-INFLATE: Error: Encountered mode %02x, expected 00 or 01\n", mode); - return -1; - } - - if (length_param < 3 || length_param > 6) - warning("Unexpected length_param value %d (expected in [3,6])\n", length_param); - - while (_dwWrote < _szUnpacked) { - if (getBitsLSB(1)) { // (length,distance) pair - value = huffman_lookup(length_tree); - - if (value < 8) - val_length = value + 2; - else - val_length = 8 + (1 << (value - 7)) + getBitsLSB(value - 7); - - debugC(kDebugLevelDclInflate, " | "); - - value = huffman_lookup(distance_tree); - - if (val_length == 2) - val_distance = (value << 2) | getBitsLSB(2); - else - val_distance = (value << length_param) | getBitsLSB(length_param); - val_distance ++; - - debugC(kDebugLevelDclInflate, "\nCOPY(%d from %d)\n", val_length, val_distance); - - if (val_length + _dwWrote > _szUnpacked) { - warning("DCL-INFLATE Error: Write out of bounds while copying %d bytes", val_length); - return SCI_ERROR_DECOMPRESSION_ERROR; - } - - if (_dwWrote < val_distance) { - warning("DCL-INFLATE Error: Attempt to copy from before beginning of input stream"); - return SCI_ERROR_DECOMPRESSION_ERROR; - } - - while (val_length) { - uint32 copy_length = (val_length > val_distance) ? val_distance : val_length; - assert(val_distance >= copy_length); - uint32 pos = _dwWrote - val_distance; - for (uint32 i = 0; i < copy_length; i++) - putByte(dest[pos + i]); - - if (Common::isDebugChannelEnabled(kDebugLevelDclInflate)) { - for (uint32 i = 0; i < copy_length; i++) - debugC(kDebugLevelDclInflate, "\33[32;31m%02x\33[37;37m ", dest[pos + i]); - debugC(kDebugLevelDclInflate, "\n"); - } - - val_length -= copy_length; - val_distance += copy_length; - } - - } else { // Copy byte verbatim - value = (mode == DCL_ASCII_MODE) ? huffman_lookup(ascii_tree) : getByteLSB(); - putByte(value); - debugC(kDebugLevelDclInflate, "\33[32;31m%02x \33[37;37m", value); - } - } - - return _dwWrote == _szUnpacked ? 0 : SCI_ERROR_DECOMPRESSION_ERROR; -} - -#ifdef ENABLE_SCI32 - -//---------------------------------------------- -// STACpack/LZS decompressor for SCI32 -// Based on Andre Beck's code from http://micky.ibh.de/~beck/stuff/lzs4i4l/ -//---------------------------------------------- -int DecompressorLZS::unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) { - init(src, dest, nPacked, nUnpacked); - return unpackLZS(); -} - -int DecompressorLZS::unpackLZS() { - uint16 offs = 0, clen; - - while (!isFinished()) { - if (getBitsMSB(1)) { // Compressed bytes follow - if (getBitsMSB(1)) { // Seven bit offset follows - offs = getBitsMSB(7); - if (!offs) // This is the end marker - a 7 bit offset of zero - break; - if (!(clen = getCompLen())) { - warning("lzsDecomp: length mismatch"); - return SCI_ERROR_DECOMPRESSION_ERROR; - } - copyComp(offs, clen); - } else { // Eleven bit offset follows - offs = getBitsMSB(11); - if (!(clen = getCompLen())) { - warning("lzsDecomp: length mismatch"); - return SCI_ERROR_DECOMPRESSION_ERROR; - } - copyComp(offs, clen); - } - } else // Literal byte follows - putByte(getByteMSB()); - } // end of while () - return _dwWrote == _szUnpacked ? 0 : SCI_ERROR_DECOMPRESSION_ERROR; -} - -uint16 DecompressorLZS::getCompLen() { - int clen, nibble; - // The most probable cases are hardcoded - switch (getBitsMSB(2)) { - case 0: - return 2; - case 1: - return 3; - case 2: - return 4; - default: - switch (getBitsMSB(2)) { - case 0: - return 5; - case 1: - return 6; - case 2: - return 7; - default: - // Ok, no shortcuts anymore - just get nibbles and add up - clen = 8; - do { - nibble = getBitsMSB(4); - clen += nibble; - } while (nibble == 0xf); - return clen; - } - } -} - -void DecompressorLZS::copyComp(int offs, int clen) { - int hpos = _dwWrote - offs; - - while (clen--) - putByte(_dest[hpos++]); -} - -#endif // #ifdef ENABLE_SCI32 - -} // End of namespace Sci diff --git a/engines/sci/scicore/decompressor.h b/engines/sci/scicore/decompressor.h deleted file mode 100644 index 5f24b0f41d..0000000000 --- a/engines/sci/scicore/decompressor.h +++ /dev/null @@ -1,201 +0,0 @@ -/* 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#ifndef SCI_SCICORE_DECOMPRESSOR_H -#define SCI_SCICORE_DECOMPRESSOR_H - -#include "common/file.h" - -namespace Sci { -enum ResourceCompression { - kCompUnknown = -1, - kCompNone = 0, - kCompLZW, - kCompHuffman, - kCompLZW1, // LZW-like compression used in SCI01 and SCI1 - kCompLZW1View, // Comp3 + view Post-processing - kCompLZW1Pic, // Comp3 + pic Post-processing -#ifdef ENABLE_SCI32 - kCompSTACpack, // ? Used in SCI32 -#endif - kCompDCL -}; -//---------------------------------------------- -// Base class for decompressors -// Simply copies nPacked bytes from src to dest -//---------------------------------------------- -class Decompressor { -public: - Decompressor() {} - virtual ~Decompressor() {} - - - virtual int unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked); - -protected: - /** - * Initialize decompressor. - * @param src source stream to read from - * @param dest destination stream to write to - * @param nPacked size of packed data - * @param nUnpacket size of unpacked data - * @return 0 on success, non-zero on error - */ - virtual void init(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked); - - /** - * Get a number of bits from _src stream, starting with the most - * significant unread bit of the current four byte block. - * @param n number of bits to get - * @return n-bits number - */ - uint32 getBitsMSB(int n); - - /** - * Get a number of bits from _src stream, starting with the least - * significant unread bit of the current four byte block. - * @param n number of bits to get - * @return n-bits number - */ - uint32 getBitsLSB(int n); - - /** - * Get one byte from _src stream. - * @return byte - */ - byte getByteMSB(); - byte getByteLSB(); - - void fetchBitsMSB(); - void fetchBitsLSB(); - - /** - * Write one byte into _dest stream - * @param b byte to put - */ - - virtual void putByte(byte b); - - /** - * Returns true if all expected data has been unpacked to _dest - * and there is no more data in _src. - */ - bool isFinished() { - return (_dwWrote == _szUnpacked) && (_dwRead >= _szPacked); - } - - uint32 _dwBits; //!< bits buffer - byte _nBits; //!< number of unread bits in _dwBits - uint32 _szPacked; //!< size of the compressed data - uint32 _szUnpacked; //!< size of the decompressed data - uint32 _dwRead; //!< number of bytes read from _src - uint32 _dwWrote; //!< number of bytes written to _dest - Common::ReadStream *_src; - byte *_dest; -}; - -//---------------------------------------------- -// Huffman decompressor -//---------------------------------------------- -class DecompressorHuffman : public Decompressor { -public: - int unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked); - -protected: - int16 getc2(); - - byte *_nodes; -}; - -//---------------------------------------------- -// LZW-like decompressor for SCI01/SCI1 -// TODO: Needs clean-up of post-processing fncs -//---------------------------------------------- -class DecompressorLZW : public Decompressor { -public: - DecompressorLZW(int nCompression) { - _compression = nCompression; - } - void init(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked); - int unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked); - -protected: - enum { - PIC_OPX_EMBEDDED_VIEW = 1, - PIC_OPX_SET_PALETTE = 2, - PIC_OP_OPX = 0xfe - }; - // unpacking procedures - // TODO: unpackLZW and unpackLZW1 are similar and should be merged - int unpackLZW1(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked); - int unpackLZW(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked); - - // functions to post-process view and pic resources - void reorderPic(byte *src, byte *dest, int dsize); - void reorderView(byte *src, byte *dest); - void decodeRLE(byte **rledata, byte **pixeldata, byte *outbuffer, int size); - int getRLEsize(byte *rledata, int dsize); - void buildCelHeaders(byte **seeker, byte **writer, int celindex, int *cc_lengths, int max); - - // decompressor data - struct Tokenlist { - byte data; - uint16 next; - }; - uint16 _numbits; - uint16 _curtoken, _endtoken; - int _compression; -}; - -//---------------------------------------------- -// DCL decompressor for SCI1.1 -//---------------------------------------------- -class DecompressorDCL : public Decompressor { -public: - int unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked); - -protected: - int unpackDCL(byte *dest); - int huffman_lookup(int *tree); -}; - -#ifdef ENABLE_SCI32 -//---------------------------------------------- -// STACpack decompressor for SCI32 -//---------------------------------------------- -class DecompressorLZS : public Decompressor { -public: - int unpack(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked); -protected: - int unpackLZS(); - uint16 getCompLen(); - void copyComp(int offs, int clen); -}; -#endif - -} // End of namespace Sci - -#endif // SCI_SCICORE_DECOMPRESSOR_H - diff --git a/engines/sci/scicore/resource.cpp b/engines/sci/scicore/resource.cpp deleted file mode 100644 index 9b7d7dca98..0000000000 --- a/engines/sci/scicore/resource.cpp +++ /dev/null @@ -1,1161 +0,0 @@ -/* 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -// Resource library - -#include "common/util.h" -#include "common/debug.h" - -#include "sci/sci.h" -#include "sci/engine/state.h" -#include "sci/engine/kernel.h" -#include "sci/tools.h" -#include "sci/scicore/resource.h" -#include "sci/scicore/vocabulary.h" -#include "sci/scicore/decompressor.h" - -namespace Sci { - -#undef SCI_REQUIRE_RESOURCE_FILES - -//#define SCI_VERBOSE_RESMGR 1 - -const char *sci_version_types[] = { - "SCI version undetermined (Autodetect failed / not run)", - "SCI version 0.xxx", - "SCI version 0.xxx w/ 1.000 compression", - "SCI version 1.000 w/ 0.xxx resource.map", - "SCI version 1.000 w/ special resource.map", - "SCI version 1.000 (early)", - "SCI version 1.000 (late)", - "SCI version 1.001", - "SCI WIN/32" -}; - -const int sci_max_resource_nr[] = {65536, 1000, 2048, 2048, 2048, 8192, 8192, 65536}; - -const char *sci_error_types[] = { - "No error", - "I/O error", - "Resource is empty (size 0)", - "resource.map entry is invalid", - "resource.map file not found", - "No resource files found", - "Unknown compression method", - "Decompression failed: Decompression buffer overflow", - "Decompression failed: Sanity check failed", - "Decompression failed: Resource too big", - "SCI version is unsupported" -}; - -// These are the 18 resource types supported by SCI1 -const char *resourceTypeNames[] = { - "view", "pic", "script", "text", "sound", - "memory", "vocab", "font", "cursor", - "patch", "bitmap", "palette", "cdaudio", - "audio", "sync", "message", "map", "heap" -}; - -const char *resourceTypeSuffixes[] = { - "v56", "p56", "scr", "tex", "snd", - " ", "voc", "fon", "cur", "pat", - "bit", "pal", "cda", "aud", "syn", - "msg", "map", "hep" -}; - -const char *getResourceTypeName(ResourceType restype) { - return resourceTypeNames[restype]; -} - -const char *getResourceTypeSuffix(ResourceType restype) { - return resourceTypeSuffixes[restype]; -} - -typedef int decomp_funct(Resource *result, Common::ReadStream &stream, int sci_version); -typedef void patch_sprintf_funct(char *string, Resource *res); - -//-- Resource main functions -- -Resource::Resource() { - data = NULL; - number = 0; - type = kResourceTypeInvalid; - id = 0; - size = 0; - file_offset = 0; - status = kResStatusNoMalloc; - lockers = 0; - source = NULL; -} - -Resource::~Resource() { - delete[] data; - if (source && source->source_type == kSourcePatch) - delete source; -} - -void Resource::unalloc() { - delete[] data; - data = NULL; - status = kResStatusNoMalloc; -} - -//-- Resmgr helper functions -- - -// Resource source list management - -ResourceSource *ResourceManager::addExternalMap(const char *file_name) { - ResourceSource *newsrc = new ResourceSource(); - - // Add the new source to the SLL of sources - newsrc->next = _sources; - _sources = newsrc; - - newsrc->source_type = kSourceExtMap; - newsrc->location_name = file_name; - newsrc->scanned = false; - newsrc->associated_map = NULL; - - return newsrc; -} - -ResourceSource *ResourceManager::addVolume(ResourceSource *map, const char *filename, int number, int extended_addressing) { - ResourceSource *newsrc = new ResourceSource(); - - // Add the new source to the SLL of sources - newsrc->next = _sources; - _sources = newsrc; - - newsrc->source_type = kSourceVolume; - newsrc->scanned = false; - newsrc->location_name = filename; - newsrc->volume_number = number; - newsrc->associated_map = map; - - return 0; -} - -ResourceSource *ResourceManager::addPatchDir(const char *dirname) { - ResourceSource *newsrc = new ResourceSource(); - - // Add the new source to the SLL of sources - newsrc->next = _sources; - _sources = newsrc; - - newsrc->source_type = kSourceDirectory; - newsrc->scanned = false; - newsrc->location_name = dirname; - - return 0; -} - -ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) { - ResourceSource *seeker = _sources; - - while (seeker) { - if (seeker->source_type == kSourceVolume && seeker->associated_map == map && - seeker->volume_number == volume_nr) - return seeker; - seeker = seeker->next; - } - - return NULL; -} - -// Resource manager constructors and operations - -bool ResourceManager::loadFromPatchFile(Resource *res) { - Common::File file; - const char *filename = res->source->location_name.c_str(); - if (file.open(filename) == false) { - warning("Failed to open patch file %s", filename); - res->unalloc(); - return false; - } - res->data = new byte[res->size]; - - if (res->data == NULL) { - error("Can't allocate %d bytes needed for loading %s!", res->size, filename); - } - - file.seek(res->file_offset, SEEK_SET); - unsigned int really_read = file.read(res->data, res->size); - if (really_read != res->size) { - error("Read %d bytes from %s but expected %d!", really_read, filename, res->size); - } - res->status = kResStatusAllocated; - return true; -} - -Common::File *ResourceManager::getVolumeFile(const char *filename) { - Common::List<Common::File *>::iterator it = _volumeFiles.begin(); - Common::File *file; - - // check if file is already opened - while (it != _volumeFiles.end()) { - file = *it; - if (scumm_stricmp(file->getName(), filename) == 0) { - // move file to top - if (it != _volumeFiles.begin()) { - _volumeFiles.erase(it); - _volumeFiles.push_front(file); - } - return file; - } - it ++; - } - // adding a new file - file = new Common::File; - if (file->open(filename)) { - if (_volumeFiles.size() == MAX_OPENED_VOLUMES) { - it = --_volumeFiles.end(); - delete *it; - _volumeFiles.erase(it); - } - _volumeFiles.push_front(file); - return file; - } - // failed - delete file; - return NULL; -} - -void ResourceManager::loadResource(Resource *res) { - Common::File *file; - - if (res->source->source_type == kSourcePatch && loadFromPatchFile(res)) - return; - // Either loading from volume or patch loading failed - file = getVolumeFile(res->source->location_name.c_str()); - if (!file) { - warning("Failed to open %s", res->source->location_name.c_str()); - res->unalloc(); - return; - } - file->seek(res->file_offset, SEEK_SET); - int error = decompress(res, file); - if (error) { - warning("Error %d occured while reading %s.%03d from resource file: %s\n", - error, getResourceTypeName(res->type), res->number, sci_error_types[error]); - res->unalloc(); - } - -} - -Resource *ResourceManager::testResource(ResourceType type, int number) { - if (_resMap.contains(RESOURCE_HASH(type, number))) - return _resMap.getVal(RESOURCE_HASH(type, number)); - return NULL; -} - -int sci0_get_compression_method(Common::ReadStream &stream) { - uint16 compressionMethod; - - stream.readUint16LE(); - stream.readUint16LE(); - stream.readUint16LE(); - compressionMethod = stream.readUint16LE(); - if (stream.err()) - return SCI_ERROR_IO_ERROR; - - return compressionMethod; -} - -int sci_test_view_type(ResourceManager *mgr) { - Common::File file; - char filename[MAXPATHLEN]; - int compression; - Resource *res; - int i; - - for (i = 0; i < 1000; i++) { - res = mgr->testResource(kResourceTypeView, i); - - if (!res) - continue; - - if (res->source->source_type == kSourceDirectory) - continue; - - strcpy(filename, res->source->location_name.c_str()); - - if (!file.open(filename)) - continue; - file.seek(res->file_offset, SEEK_SET); - - compression = sci0_get_compression_method(file); - file.close(); - - if (compression == 3) { - return SCI_VERSION_01_VGA; - } - } - - // Try the same thing with pics - for (i = 0; i < 1000; i++) { - res = mgr->testResource(kResourceTypePic, i); - - if (!res) - continue; - - if (res->source->source_type == kSourceDirectory) - continue; - - strcpy(filename, res->source->location_name.c_str()); - - if (!file.open(filename)) - continue; - file.seek(res->file_offset, SEEK_SET); - - compression = sci0_get_compression_method(file); - file.close(); - - if (compression == 3) { - return SCI_VERSION_01_VGA; - } - } - - return SCI_VERSION_AUTODETECT; -} - -int ResourceManager::addAppropriateSources() { - ResourceSource *map; - - if (!Common::File::exists("RESOURCE.MAP")) - return 0; - map = addExternalMap("RESOURCE.MAP"); - - Common::ArchiveMemberList files; - SearchMan.listMatchingMembers(files, "RESOURCE.0??"); - - for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { - const Common::String name = (*x)->getName(); - const char *dot = strrchr(name.c_str(), '.'); - int number = atoi(dot + 1); - - addVolume(map, name.c_str(), number, 0); - } - addPatchDir(""); - // TODO: add RESOURCE.AUD and RESOURCE.SFX for SCI1.1 games - if (Common::File::exists("MESSAGE.MAP")) - addVolume(addExternalMap("MESSAGE.MAP"), "RESOURCE.MSG",0 ,0); - return 1; -} - -int ResourceManager::scanNewSources(ResourceSource *source) { - if (!source) - return SCI_ERROR_NO_RESOURCE_FILES_FOUND; - - int resource_error = 0; - if (source->next) - scanNewSources(source->next); - - if (!source->scanned) { - source->scanned = true; - switch (source->source_type) { - case kSourceDirectory: - readResourcePatches(source); - break; - case kSourceExtMap: - if (_mapVersion < SCI_VERSION_1) - resource_error = readResourceMapSCI0(source); - else - resource_error = readResourceMapSCI1(source); - - if (resource_error == SCI_ERROR_RESMAP_NOT_FOUND) { - // FIXME: Try reading w/o resource.map - resource_error = SCI_ERROR_NO_RESOURCE_FILES_FOUND; - } - - if (resource_error == SCI_ERROR_NO_RESOURCE_FILES_FOUND) { - // Initialize empty resource manager - _resMap.clear(); - resource_error = 0; - } - break; - default: - break; - } - } - return resource_error; -} - -void ResourceManager::freeResourceSources(ResourceSource *rss) { - if (rss) { - freeResourceSources(rss->next); - delete rss; - } -} - -ResourceManager::ResourceManager(int version, int maxMemory) { - _maxMemory = maxMemory; - _memoryLocked = 0; - _memoryLRU = 0; - _LRU.clear(); - _resMap.clear(); - _sources = NULL; - _sciVersion = version; - - addAppropriateSources(); - - if (version != SCI_VERSION_AUTODETECT) { - _mapVersion = version; - _volVersion = version; - } else { - _mapVersion = detectMapVersion(); - _volVersion = detectVolVersion(); - } - debug("Using resource map version %d %s", _mapVersion, sci_version_types[_mapVersion]); - debug("Using volume version %d %s", _volVersion, sci_version_types[_volVersion]); - - scanNewSources(_sources); - if (version == SCI_VERSION_AUTODETECT) - switch (_mapVersion) { - case SCI_VERSION_0: - if (testResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB)) { - version = sci_test_view_type(this) ? SCI_VERSION_01_VGA : SCI_VERSION_0; - } else if (testResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB)) { - version = sci_test_view_type(this); - if (version != SCI_VERSION_01_VGA) { - version = testResource(kResourceTypeVocab, 912) ? SCI_VERSION_0 : SCI_VERSION_01; - } - } else { - version = sci_test_view_type(this) ? SCI_VERSION_01_VGA : SCI_VERSION_0; - } - break; - case SCI_VERSION_01_VGA_ODD: - version = _mapVersion; - break; - case SCI_VERSION_1: { - Resource *res = testResource(kResourceTypeScript, 0); - - _sciVersion = version = SCI_VERSION_1_EARLY; - loadResource(res); - - if (res->status == kResStatusNoMalloc) - version = SCI_VERSION_1_LATE; - break; - } - case SCI_VERSION_1_1: - // No need to handle SCI 1.1 here - it was done in resource_map.cpp - version = SCI_VERSION_1_1; - break; - default: - version = SCI_VERSION_AUTODETECT; - } - - _sciVersion = version; - // temporary version printout - should be reworked later - switch (_sciVersion) { - case SCI_VERSION_0: - debug("Resmgr: Detected SCI0"); - break; - case SCI_VERSION_01: - debug("Resmgr: Detected SCI01"); - break; - case SCI_VERSION_01_VGA: - debug("Resmgr: Detected SCI01VGA - KQ5 or similar"); - break; - case SCI_VERSION_01_VGA_ODD: - debug("Resmgr: Detected SCI01VGA - Jones/CD or similar"); - break; - case SCI_VERSION_1_EARLY: - debug("Resmgr: Detected SCI1 Early"); - break; - case SCI_VERSION_1_LATE: - debug("Resmgr: Detected SCI1 Late"); - break; - case SCI_VERSION_1_1: - debug("Resmgr: Detected SCI1.1"); - break; -#ifdef ENABLE_SCI32 - case SCI_VERSION_32: - debug("Resmgr: Couldn't determine SCI version"); - break; -#endif - default: - debug("Resmgr: Couldn't determine SCI version"); - break; - } -} - -ResourceManager::~ResourceManager() { - // freeing resources - Common::HashMap<uint32, Resource *>::iterator itr = _resMap.begin(); - while (itr != _resMap.end()) { - delete itr->_value; - itr ++; - } - freeResourceSources(_sources); - _resMap.empty(); - - Common::List<Common::File *>::iterator it = _volumeFiles.begin(); - while (it != _volumeFiles.end()) { - delete *it; - it ++; - } -} - -void ResourceManager::removeFromLRU(Resource *res) { - if (res->status != kResStatusEnqueued) { - sciprintf("Resmgr: Oops: trying to remove resource that isn't enqueued\n"); - return; - } - _LRU.remove(res); - _memoryLRU -= res->size; - res->status = kResStatusAllocated; -} - -void ResourceManager::addToLRU(Resource *res) { - if (res->status != kResStatusAllocated) { - warning("Resmgr: Oops: trying to enqueue resource with state %d", res->status); - return; - } - _LRU.push_front(res); - _memoryLRU += res->size; -#if (SCI_VERBOSE_RESMGR > 1) - debug("Adding %s.%03d (%d bytes) to lru control: %d bytes total", - getResourceTypeName(res->type), res->number, res->size, - mgr->_memoryLRU); - -#endif - res->status = kResStatusEnqueued; -} - -void ResourceManager::printLRU() { - int mem = 0; - int entries = 0; - Common::List<Resource *>::iterator it = _LRU.begin(); - Resource *res; - - while (it != _LRU.end()) { - res = *it; - debug("\t%s.%03d: %d bytes", getResourceTypeName(res->type), - res->number, res->size); - mem += res->size; - entries ++; - it ++; - } - - debug("Total: %d entries, %d bytes (mgr says %d)", entries, mem, _memoryLRU); -} - -void ResourceManager::freeOldResources(int last_invulnerable) { - while (_maxMemory < _memoryLRU && (!last_invulnerable || !_LRU.empty())) { - Resource *goner = *_LRU.reverse_begin(); - if (!goner) { - debug("Internal error: mgr->lru_last is NULL!"); - debug("LRU-mem= %d", _memoryLRU); - debug("lru_first = %p", (void *)*_LRU.begin()); - printLRU(); - } - removeFromLRU(goner); - goner->unalloc(); -#ifdef SCI_VERBOSE_RESMGR - sciprintf("Resmgr-debug: LRU: Freeing %s.%03d (%d bytes)\n", getResourceTypeName(goner->type), goner->number, goner->size); -#endif - } -} - -Resource *ResourceManager::findResource(ResourceType type, int number, int lock) { - Resource *retval; - - if (number >= sci_max_resource_nr[_sciVersion]) { - int modded_number = number % sci_max_resource_nr[_sciVersion]; - sciprintf("[resmgr] Requested invalid resource %s.%d, mapped to %s.%d\n", - getResourceTypeName(type), number, getResourceTypeName(type), modded_number); - number = modded_number; - } - - retval = testResource(type, number); - - if (!retval) - return NULL; - - if (retval->status == kResStatusNoMalloc) - loadResource(retval); - else if (retval->status == kResStatusEnqueued) - removeFromLRU(retval); - // Unless an error occured, the resource is now either - // locked or allocated, but never queued or freed. - - if (lock) { - if (retval->status == kResStatusAllocated) { - retval->status = kResStatusLocked; - retval->lockers = 0; - _memoryLocked += retval->size; - } - retval->lockers++; - } else if (retval->status != kResStatusLocked) { // Don't lock it - if (retval->status == kResStatusAllocated) - addToLRU(retval); - } - - freeOldResources(retval->status == kResStatusAllocated); - - if (retval->data) - return retval; - else { - sciprintf("Resmgr: Failed to read %s.%03d\n", getResourceTypeName(retval->type), retval->number); - return NULL; - } -} - -void ResourceManager::unlockResource(Resource *res, int resnum, ResourceType restype) { - if (!res) { - if (restype == kResourceTypeInvalid) - sciprintf("Resmgr: Warning: Attempt to unlock non-existant resource %03d.%03d!\n", restype, resnum); - else - sciprintf("Resmgr: Warning: Attempt to unlock non-existant resource %s.%03d!\n", getResourceTypeName(restype), resnum); - return; - } - - if (res->status != kResStatusLocked) { - sciprintf("Resmgr: Warning: Attempt to unlock unlocked resource %s.%03d\n", - getResourceTypeName(res->type), res->number); - return; - } - - if (!--res->lockers) { // No more lockers? - res->status = kResStatusAllocated; - _memoryLocked -= res->size; - addToLRU(res); - } - - freeOldResources(0); -} - -int ResourceManager::detectMapVersion() { - Common::File file; - byte buff[6]; - ResourceSource *rsrc = _sources; - // looking for extarnal map among sources - while (rsrc) { - if (rsrc->source_type == kSourceExtMap) { - file.open(rsrc->location_name); - break; - } - rsrc = rsrc->next; - } - if (file.isOpen() == false) { - warning("Failed to open resource map file"); - return SCI_VERSION_AUTODETECT; - } - // detection - // SCI0 and SCI01 maps have last 6 bytes set to FF - file.seek(-4, SEEK_END); - uint32 uEnd = file.readUint32LE(); - if (uEnd == 0xFFFFFFFF) { - // check if 0 or 01 - try to read resources in SCI0 format and see if exists - file.seek(0, SEEK_SET); - while (file.read(buff, 6) == 6 && !(buff[0] == 0xFF && buff[1] == 0xFF && buff[2] == 0xFF)) { - if (getVolume(rsrc, (buff[5] & 0xFC) >> 2) == NULL) - return SCI_VERSION_01_VGA_ODD; - } - return SCI_VERSION_0; - } - // SCI1E/L and some SCI1.1 maps have last directory entry set to 0xFF - // and offset set to filesize - // SCI1 have 6-bytes entries, while SCI1.1 have 5-byte entries - file.seek(1, SEEK_SET); - uint16 off1, off = file.readUint16LE(); - uint16 nEntries = off / 3; - file.seek(1, SEEK_CUR); - file.seek(off - 3, SEEK_SET); - if (file.readByte() == 0xFF && file.readUint16LE() == file.size()) { - file.seek(3, SEEK_SET); - for (int i = 0; i < nEntries; i++) { - file.seek(1, SEEK_CUR); - off1 = file.readUint16LE(); - if ((off1 - off) % 5 && (off1 - off) % 6 == 0) - return SCI_VERSION_1; - if ((off1 - off) % 5 == 0 && (off1 - off) % 6) - return SCI_VERSION_1_1; - off = off1; - } - return SCI_VERSION_1; - } - -#ifdef ENABLE_SCI32 - // late SCI1.1 and SCI32 maps have last directory entry set to 0xFF - // offset set to filesize and 4 more bytes - file.seek(off - 7, SEEK_SET); - if (file.readByte() == 0xFF && file.readUint16LE() == file.size()) - return SCI_VERSION_32; // TODO : check if there is a difference between these maps -#endif - - return SCI_VERSION_AUTODETECT; -} - -int ResourceManager::detectVolVersion() { - Common::File file; - ResourceSource *rsrc = _sources; - // looking for a volume among sources - while (rsrc) { - if (rsrc->source_type == kSourceVolume) { - file.open(rsrc->location_name); - break; - } - rsrc = rsrc->next; - } - if (file.isOpen() == false) { - warning("Failed to open volume file"); - return SCI_VERSION_AUTODETECT; - } - // SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes - // SCI1 volume format: {bResType wResNumber wPacked+4 wUnpacked wCompression} = 9 bytes - // SCI1.1 volume format: {bResType wResNumber wPacked wUnpacked wCompression} = 9 bytes - // SCI32 volume format : {bResType wResNumber dwPacked dwUnpacked wCompression} = 13 bytes - // Try to parse volume with SCI0 scheme to see if it make sense - // Checking 1MB of data should be enough to determine the version - uint16 resId, wCompression; - uint32 dwPacked, dwUnpacked; - int curVersion = SCI_VERSION_0; - bool failed = false; - - // Check for SCI0, SCI1, SCI1.1 and SCI32 v2 (Gabriel Knight 1 CD) formats - while (!file.eos() && file.pos() < 0x100000) { - if (curVersion > SCI_VERSION_0) - file.readByte(); - resId = file.readUint16LE(); - dwPacked = (curVersion < SCI_VERSION_32) ? file.readUint16LE() : file.readUint32LE(); - dwUnpacked = (curVersion < SCI_VERSION_32) ? file.readUint16LE() : file.readUint32LE(); - wCompression = (curVersion < SCI_VERSION_32) ? file.readUint16LE() : file.readUint32LE(); - if (file.eos()) - return curVersion; - - int chk = (curVersion == SCI_VERSION_0) ? 4 : 20; - int offs = curVersion < SCI_VERSION_1_1 ? 4 : 0; - if ((curVersion < SCI_VERSION_32 && wCompression > chk) - || (curVersion == SCI_VERSION_32 && wCompression != 0 && wCompression != 32) - || (wCompression == 0 && dwPacked != dwUnpacked + offs) - || (dwUnpacked < dwPacked - offs)) { - - // Retry with a newer SCI version - if (curVersion == SCI_VERSION_0) { - curVersion = SCI_VERSION_1; - } else if (curVersion == SCI_VERSION_1) { - curVersion = SCI_VERSION_1_1; - } else if (curVersion == SCI_VERSION_1_1) { - curVersion = SCI_VERSION_32; - } else { - // All version checks failed, exit loop - failed = true; - break; - } - - file.seek(0, SEEK_SET); - continue; - } - - if (curVersion < SCI_VERSION_1_1) - file.seek(dwPacked - 4, SEEK_CUR); - else if (curVersion == SCI_VERSION_1_1) - file.seek((9 + dwPacked) % 2 ? dwPacked + 1 : dwPacked, SEEK_CUR); - else if (curVersion == SCI_VERSION_32) - file.seek(dwPacked, SEEK_CUR);//(9 + wPacked) % 2 ? wPacked + 1 : wPacked, SEEK_CUR); - } - - if (!failed) - return curVersion; - - // Failed to detect volume version - return SCI_VERSION_AUTODETECT; -} - -// version-agnostic patch application -void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, int resnumber) { - Common::File file; - Resource *newrsc; - uint32 resId = RESOURCE_HASH(restype, resnumber); - byte patchtype, patch_data_offset; - int fsize; - - if (resnumber == -1) - return; - if (!file.open(source->location_name)) { - perror("""__FILE__"": (""__LINE__""): failed to open"); - return; - } - fsize = file.size(); - if (fsize < 3) { - debug("Patching %s failed - file too small", source->location_name.c_str()); - return; - } - - patchtype = file.readByte() & 0x7F; - patch_data_offset = file.readByte(); - - if (patchtype != restype) { - debug("Patching %s failed - resource type mismatch", source->location_name.c_str()); - return; - } - if (patch_data_offset + 2 >= fsize) { - debug("Patching %s failed - patch starting at offset %d can't be in file of size %d", - source->location_name.c_str(), patch_data_offset + 2, fsize); - return; - } - // Prepare destination, if neccessary - if (_resMap.contains(resId) == false) { - newrsc = new Resource; - _resMap.setVal(resId, newrsc); - } else - newrsc = _resMap.getVal(resId); - // Overwrite everything, because we're patching - newrsc->id = resId; - newrsc->number = resnumber; - newrsc->status = kResStatusNoMalloc; - newrsc->type = restype; - newrsc->source = source; - newrsc->size = fsize - patch_data_offset - 2; - newrsc->file_offset = 2 + patch_data_offset; - debug("Patching %s - OK", source->location_name.c_str()); -} - - -void ResourceManager::readResourcePatches(ResourceSource *source) { -// Note: since some SCI1 games(KQ5 floppy, SQ4) might use SCI0 naming scheme for patch files -// this function tries to read patch file with any supported naming scheme, -// regardless of _sciVersion value - - Common::String mask, name; - Common::ArchiveMemberList files; - int number; - const char *szResType; - ResourceSource *psrcPatch; - bool bAdd; - - for (int i = kResourceTypeView; i < kResourceTypeInvalid; i ++) { - files.clear(); - szResType = getResourceTypeName((ResourceType)i); - // SCI0 naming - type.nnn - mask = szResType; - mask += ".???"; - SearchMan.listMatchingMembers(files, mask); - // SCI1 and later naming - nnn.typ - mask = "*."; - mask += getResourceTypeSuffix((ResourceType)i); - SearchMan.listMatchingMembers(files, mask); - for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); x++) { - bAdd = false; - name = (*x)->getName(); - // SCI1 scheme - if (isdigit(name[0])) { - number = atoi(name.c_str()); - bAdd = true; - } else { - // SCI0 scheme - int resname_len = strlen(szResType); - if (scumm_strnicmp(name.c_str(), szResType, resname_len) == 0 - && !isalpha(name[resname_len + 1])) { - number = atoi(name.c_str() + resname_len + 1); - bAdd = true; - } - } - - if (bAdd) { - psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourcePatch; - psrcPatch->location_name = name; - processPatch(psrcPatch, (ResourceType)i, number); - } - } - } -} - -int ResourceManager::readResourceMapSCI0(ResourceSource *map) { - Common::File file; - Resource *res; - ResourceType type; - uint16 number, id; - uint32 offset; - - if (!file.open(map->location_name)) - return SCI_ERROR_RESMAP_NOT_FOUND; - - file.seek(0, SEEK_SET); - - byte bMask = 0xFC; - // FIXME: The code above seems to give correct results for Jones - //byte bMask = _mapVersion == SCI_VERSION_01_VGA_ODD ? 0xF0 : 0xFC; - byte bShift = _mapVersion == SCI_VERSION_01_VGA_ODD ? 28 : 26; - - do { - id = file.readUint16LE(); - offset = file.readUint32LE(); - - if (file.ioFailed()) { - warning("Error while reading %s: ", map->location_name.c_str()); - perror(""); - return SCI_ERROR_RESMAP_NOT_FOUND; - } - if (offset == 0xFFFFFFFF) - break; - - type = (ResourceType)(id >> 11); - number = id & 0x7FF; - uint32 resId = RESOURCE_HASH(type, number); - // adding a new resource - if (_resMap.contains(resId) == false) { - res = new Resource; - res->id = resId;//id; - res->file_offset = offset & (((~bMask) << 24) | 0xFFFFFF); - res->number = number; - res->type = type; - res->source = getVolume(map, offset >> bShift); - _resMap.setVal(resId, res); - } - } while (!file.eos()); - return 0; -} - -int ResourceManager::readResourceMapSCI1(ResourceSource *map) { - Common::File file; - Resource *res; - if (!file.open(map->location_name)) - return SCI_ERROR_RESMAP_NOT_FOUND; - - resource_index_t resMap[32]; - memset(resMap, 0, sizeof(resource_index_t) * 32); - byte type = 0, prevtype = 0; - byte nEntrySize = _mapVersion == SCI_VERSION_1_1 ? SCI11_RESMAP_ENTRIES_SIZE : SCI1_RESMAP_ENTRIES_SIZE; - uint32 resId; - - // Read resource type and offsets to resource offsets block from .MAP file - // The last entry has type=0xFF (0x1F) and offset equals to map file length - do { - type = file.readByte() & 0x1F; - resMap[type].wOffset = file.readUint16LE(); - resMap[prevtype].wSize = (resMap[type].wOffset - - resMap[prevtype].wOffset) / nEntrySize; - prevtype = type; - } while (type != 0x1F); // the last entry is FF - - // reading each type's offsets - uint32 off = 0; - for (type = 0; type < 32; type++) { - if (resMap[type].wOffset == 0) // this resource does not exist in map - continue; - file.seek(resMap[type].wOffset); - for (int i = 0; i < resMap[type].wSize; i++) { - uint16 number = file.readUint16LE(); - int volume_nr = 0; - if (_mapVersion == SCI_VERSION_1_1) { - // offset stored in 3 bytes - off = file.readUint16LE(); - off |= file.readByte() << 16; - off <<= 1; - } else { - // offset/volume stored in 4 bytes - off = file.readUint32LE(); - if (_mapVersion < SCI_VERSION_1_1) { - volume_nr = off >> 28; // most significant 4 bits - off &= 0x0FFFFFFF; // least significant 28 bits - } else { - // in SCI32 it's a plain offset - } - } - if (file.ioFailed()) { - warning("Error while reading %s: ", map->location_name.c_str()); - perror(""); - return SCI_ERROR_RESMAP_NOT_FOUND; - } - resId = RESOURCE_HASH(type, number); - // adding new resource only if it does not exist - if (_resMap.contains(resId) == false) { - res = new Resource; - _resMap.setVal(resId, res); - res->type = (ResourceType)type; - res->number = number; - res->id = resId;//res->number | (res->type << 16); - res->source = getVolume(map, volume_nr); - res->file_offset = off; - } - } - } - return 0; -} - -int ResourceManager::readResourceInfo(Resource *res, Common::File *file, - uint32&szPacked, ResourceCompression &compression) { - // SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes - // SCI1 volume format: {bResType wResNumber wPacked+4 wUnpacked wCompression} = 9 bytes - // SCI1.1 volume format: {bResType wResNumber wPacked wUnpacked wCompression} = 9 bytes - // SCI32 volume format : {bResType wResNumber dwPacked dwUnpacked wCompression} = 13 bytes - uint16 w, number, szUnpacked; - uint32 wCompression; - ResourceType type; - - switch (_volVersion) { - case SCI_VERSION_0: - w = file->readUint16LE(); - type = (ResourceType)(w >> 11); - number = w & 0x7FF; - szPacked = file->readUint16LE() - 4; - szUnpacked = file->readUint16LE(); - wCompression = file->readUint16LE(); - break; - case SCI_VERSION_1: - type = (ResourceType)(file->readByte() & 0x7F); - number = file->readUint16LE(); - szPacked = file->readUint16LE() - 4; - szUnpacked = file->readUint16LE(); - wCompression = file->readUint16LE(); - break; - case SCI_VERSION_1_1: - type = (ResourceType)(file->readByte() & 0x7F); - number = file->readUint16LE(); - szPacked = file->readUint16LE(); - szUnpacked = file->readUint16LE(); - wCompression = file->readUint16LE(); - break; -#ifdef ENABLE_SCI32 - case SCI_VERSION_32: - type = (ResourceType)(file->readByte() &0x7F); - number = file->readUint16LE(); - szPacked = file->readUint32LE(); - szUnpacked = file->readUint32LE(); - wCompression = file->readUint16LE(); - break; -#endif - default: - return SCI_ERROR_INVALID_RESMAP_ENTRY; - } - // check if there were errors while reading - if (file->ioFailed()) - return SCI_ERROR_IO_ERROR; - res->id = RESOURCE_HASH(type, number); - res->type = type; - res->number = number; - res->size = szUnpacked; - // checking compression method - switch (wCompression) { - case 0: - compression = kCompNone; - break; - case 1: - compression = (_sciVersion == SCI_VERSION_0) ? kCompLZW : kCompHuffman; - break; - case 2: - compression = (_sciVersion == SCI_VERSION_0) ? kCompHuffman : kCompLZW1; - break; - case 3: - compression = kCompLZW1View; - break; - case 4: - compression = kCompLZW1Pic; - break; - case 18: - case 19: - case 20: - compression = kCompDCL; - break; -#ifdef ENABLE_SCI32 - case 32: - compression = kCompSTACpack; - break; -#endif - default: - compression = kCompUnknown; - } - - return compression == kCompUnknown ? SCI_ERROR_UNKNOWN_COMPRESSION : 0; -} - -int ResourceManager::decompress(Resource *res, Common::File *file) { - int error; - uint32 szPacked = 0; - ResourceCompression compression = kCompUnknown; - - // fill resource info - error = readResourceInfo(res, file, szPacked, compression); - if (error) - return error; - // getting a decompressor - Decompressor *dec = NULL; - switch (compression) { - case kCompNone: - dec = new Decompressor; - break; - case kCompHuffman: - dec = new DecompressorHuffman; - break; - case kCompLZW: - case kCompLZW1: - case kCompLZW1View: - case kCompLZW1Pic: - dec = new DecompressorLZW(compression); - break; - case kCompDCL: - dec = new DecompressorDCL; - break; -#ifdef ENABLE_SCI32 - case kCompSTACpack: - dec = new DecompressorLZS; - break; -#endif - default: - warning("Resource %s #%d: Compression method %d not supported", - getResourceTypeName(res->type), res->number, compression); - return SCI_ERROR_UNKNOWN_COMPRESSION; - } - - res->data = new byte[res->size]; - res->status = kResStatusAllocated; - error = res->data ? dec->unpack(file, res->data, szPacked, res->size) : SCI_ERROR_RESOURCE_TOO_BIG; - if (error) - res->unalloc(); - - delete dec; - return error; -} - -void ResourceSync::startSync(EngineState *s, reg_t obj) { - _syncTime = _syncCue = -1; - PUT_SEL32V(obj, syncCue, 0); - _ptr = (uint16 *)data; - //syncStarted = true; // not used -} - -void ResourceSync::nextSync(EngineState *s, reg_t obj) { - if (_ptr) { - _syncTime = (int16)READ_LE_UINT16(_ptr); - if (_syncTime == -1) { - stopSync(); - } else { - _syncCue = (int16)READ_LE_UINT16(_ptr + 1); - _ptr += 2; - } - PUT_SEL32V(obj, syncTime, _syncTime); - PUT_SEL32V(obj, syncCue, _syncCue); - } -} -//-------------------------------- -void ResourceSync::stopSync() { - _ptr = 0; - _syncCue = -1; - //syncStarted = false; // not used -} - -} // End of namespace Sci diff --git a/engines/sci/scicore/resource.h b/engines/sci/scicore/resource.h deleted file mode 100644 index e827152c57..0000000000 --- a/engines/sci/scicore/resource.h +++ /dev/null @@ -1,302 +0,0 @@ -/* 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#ifndef SCI_SCICORE_RESOURCE_H -#define SCI_SCICORE_RESOURCE_H - -#include "common/str.h" -#include "common/file.h" -#include "common/archive.h" - -#include "sci/engine/vm.h" // for Object -#include "sci/scicore/decompressor.h" - -namespace Common { -class ReadStream; -} - -namespace Sci { - -/** The maximum allowed size for a compressed or decompressed resource */ -#define SCI_MAX_RESOURCE_SIZE 0x0400000 - -/*** RESOURCE STATUS TYPES ***/ -enum ResourceStatus { - kResStatusNoMalloc = 0, - kResStatusAllocated, - kResStatusEnqueued, /* In the LRU queue */ - kResStatusLocked /* Allocated and in use */ -}; - -/*** INITIALIZATION RESULT TYPES ***/ -#define SCI_ERROR_IO_ERROR 1 -#define SCI_ERROR_INVALID_RESMAP_ENTRY 2 -/* Invalid resource.map entry */ -#define SCI_ERROR_RESMAP_NOT_FOUND 3 -#define SCI_ERROR_NO_RESOURCE_FILES_FOUND 4 -/* No resource at all was found */ -#define SCI_ERROR_UNKNOWN_COMPRESSION 5 -#define SCI_ERROR_DECOMPRESSION_ERROR 6 -/* sanity checks failed during decompression */ -#define SCI_ERROR_RESOURCE_TOO_BIG 8 -/* Resource size exceeds SCI_MAX_RESOURCE_SIZE */ - -/* the first critical error number */ - -#define SCI_VERSION_1 SCI_VERSION_1_EARLY - -#define MAX_OPENED_VOLUMES 5 // Max number of simultaneously opened volumes - -enum ResSourceType { - kSourceDirectory = 0, - kSourcePatch = 1, - kSourceVolume = 2, - kSourceExtMap = 3, - kSourceIntMap = 4, - kSourceMask = 127 -}; - -#define RESSOURCE_ADDRESSING_BASIC 0 -#define RESSOURCE_ADDRESSING_EXTENDED 128 -#define RESSOURCE_ADDRESSING_MASK 128 - -#define RESOURCE_HASH(type, number) (uint32)((type<<16) | number) -#define SCI0_RESMAP_ENTRIES_SIZE 6 -#define SCI1_RESMAP_ENTRIES_SIZE 6 -#define SCI11_RESMAP_ENTRIES_SIZE 5 - -extern const char *sci_error_types[]; -extern const char *sci_version_types[]; -extern const int sci_max_resource_nr[]; /* Highest possible resource numbers */ - - -enum ResourceType { - kResourceTypeView = 0, - kResourceTypePic, - kResourceTypeScript, - kResourceTypeText, - kResourceTypeSound, - kResourceTypeMemory, - kResourceTypeVocab, - kResourceTypeFont, - kResourceTypeCursor, - kResourceTypePatch, - kResourceTypeBitmap, - kResourceTypePalette, - kResourceTypeCdAudio, - kResourceTypeAudio, - kResourceTypeSync, - kResourceTypeMessage, - kResourceTypeMap, - kResourceTypeHeap, - kResourceTypeInvalid -}; - -const char *getResourceTypeName(ResourceType restype); -// Suffixes for SCI1 patch files -const char *getResourceTypeSuffix(ResourceType restype); - -#define sci0_last_resource kResourceTypePatch -#define sci1_last_resource kResourceTypeHeap -/* Used for autodetection */ - - -// resource type for SCI1 resource.map file -struct resource_index_t { - uint16 wOffset; - uint16 wSize; -}; - -struct ResourceSource { - ResSourceType source_type; - bool scanned; - Common::String location_name; // FIXME: Replace by FSNode ? - int volume_number; - ResourceSource *associated_map; - ResourceSource *next; -}; - -/** Class for storing resources in memory */ -class Resource { -public: - Resource(); - ~Resource(); - void unalloc(); - -// NOTE : Currently all member data has the same name and public visibility -// to let the rest of the engine compile without changes -public: - byte *data; - uint16 number; - ResourceType type; - uint32 id; // contains number and type. - unsigned int size; - unsigned int file_offset; /* Offset in file */ - ResourceStatus status; - unsigned short lockers; /* Number of places where this resource was locked */ - ResourceSource *source; -}; - - -class ResourceManager { -public: - int _sciVersion; /* SCI resource version to use */ - int _mapVersion; // RESOURCE.MAP version - int _volVersion; // RESOURCE.0xx version - - /** - * Creates a new SCI resource manager. - * @param version The SCI version to look for; use SCI_VERSION_AUTODETECT - * in the default case. - * @param maxMemory Maximum number of bytes to allow allocated for resources - * - * @note maxMemory will not be interpreted as a hard limit, only as a restriction - * for resources which are not explicitly locked. However, a warning will be - * issued whenever this limit is exceeded. - */ - ResourceManager(int version, int maxMemory); - ~ResourceManager(); - - //! Looks up a resource's data - /** @param type: The resource type to look for - * @param number: The resource number to search - * @param lock: non-zero iff the resource should be locked - * @return (Resource *): The resource, or NULL if it doesn't exist - * @note Locked resources are guaranteed not to have their contents freed until - * they are unlocked explicitly (by unlockResource). - */ - Resource *findResource(ResourceType type, int number, int lock); - - /* Unlocks a previously locked resource - ** (Resource *) res: The resource to free - ** (int) number: Number of the resource to check (ditto) - ** (ResourceType) type: Type of the resource to check (for error checking) - ** Returns : (void) - */ - void unlockResource(Resource *res, int restype, ResourceType resnum); - - /* Tests whether a resource exists - ** (ResourceType) type: Type of the resource to check - ** (int) number: Number of the resource to check - ** Returns : (Resource *) non-NULL if the resource exists, NULL otherwise - ** This function may often be much faster than finding the resource - ** and should be preferred for simple tests. - ** The resource object returned is, indeed, the resource in question, but - ** it should be used with care, as it may be unallocated. - ** Use scir_find_resource() if you want to use the data contained in the resource. - */ - Resource *testResource(ResourceType type, int number); - -protected: - int _maxMemory; // Config option: Maximum total byte number allocated - ResourceSource *_sources; - int _memoryLocked; // Amount of resource bytes in locked memory - int _memoryLRU; // Amount of resource bytes under LRU control - Common::List<Resource *> _LRU; // Last Resource Used list - Common::HashMap<uint32, Resource *> _resMap; - Common::List<Common::File *> _volumeFiles; // list of opened volume files - - /* Add a path to the resource manager's list of sources. - ** Returns: A pointer to the added source structure, or NULL if an error occurred. - */ - ResourceSource *addPatchDir(const char *path); - - ResourceSource *getVolume(ResourceSource *map, int volume_nr); - - //! Add a volume to the resource manager's list of sources. - /** @param map The map associated with this volume - * @param filename The name of the volume to add - * @param extended_addressing 1 if this volume uses extended addressing, - * 0 otherwise. - * @return A pointer to the added source structure, or NULL if an error occurred. - */ - ResourceSource *addVolume(ResourceSource *map, const char *filename, - int number, int extended_addressing); - //! Add an external (i.e. separate file) map resource to the resource manager's list of sources. - /** @param file_name The name of the volume to add - * @return A pointer to the added source structure, or NULL if an error occurred. - */ - ResourceSource *addExternalMap(const char *file_name); - //! Scans newly registered resource sources for resources, earliest addition first. - /** @param detected_version: Pointer to the detected version number, - * used during startup. May be NULL. - * @return One of SCI_ERROR_*. - */ - int scanNewSources(ResourceSource *source); - int addAppropriateSources(); - void freeResourceSources(ResourceSource *rss); - - Common::File *getVolumeFile(const char *filename); - void loadResource(Resource *res); - bool loadFromPatchFile(Resource *res); - void freeOldResources(int last_invulnerable); - int decompress(Resource *res, Common::File *file); - int readResourceInfo(Resource *res, Common::File *file, uint32&szPacked, ResourceCompression &compression); - - /**--- Resource map decoding functions ---*/ - int detectMapVersion(); - int detectVolVersion(); - - /* Reads the SCI0 resource.map file from a local directory - ** Returns : (int) 0 on success, an SCI_ERROR_* code otherwise - */ - int readResourceMapSCI0(ResourceSource *map); - - /* Reads the SCI1 resource.map file from a local directory - ** Returns : (int) 0 on success, an SCI_ERROR_* code otherwise - */ - int readResourceMapSCI1(ResourceSource *map); - - /**--- Patch management functions ---*/ - - //! Reads patch files from a local directory - /** @paramParameters: ResourceSource *source - */ - void readResourcePatches(ResourceSource *source); - void processPatch(ResourceSource *source, ResourceType restype, int resnumber); - - void printLRU(); - void addToLRU(Resource *res); - void removeFromLRU(Resource *res); -}; - -class ResourceSync : public Resource { -public: - ResourceSync() {} - ~ResourceSync() {} - - void startSync(EngineState *s, reg_t obj); - void nextSync(EngineState *s, reg_t obj); - void stopSync(); - -protected: - uint16 *_ptr; - int16 _syncTime, _syncCue; - //bool _syncStarted; // not used -}; - -} // End of namespace Sci - -#endif // SCI_SCICORE_RESOURCE_H diff --git a/engines/sci/scicore/sciconsole.h b/engines/sci/scicore/sciconsole.h deleted file mode 100644 index b2060143aa..0000000000 --- a/engines/sci/scicore/sciconsole.h +++ /dev/null @@ -1,130 +0,0 @@ -/* 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* Header file for the SCI console. -** Please note that the console does not use the priority field; the console -** should therefore be drawn after everything else has been drawn (with the -** possible exception of the mouse pointer). -*/ - -#ifndef SCI_SCICORE_SCICONSOLE_H -#define SCI_SCICORE_SCICONSOLE_H - -#include "common/scummsys.h" - -#include "sci/tools.h" -#include "sci/engine/state.h" -#include "sci/engine/vm_types.h" - -#define SCI_CONSOLE - -namespace Sci { - -struct gfx_pixmap_t; - -union cmd_param_t { - int32 val; - const char *str; - reg_t reg; -}; - - -typedef int (*ConCommand)(EngineState *s, const Common::Array<cmd_param_t> &cmdParams); - -/*** FUNCTION DEFINITIONS ***/ - -void con_init(); -/* Initializes the command parser -** Parameters: (void) -** Returns : (void) -** This function will initialize hook up a few commands to the parser. -** It must be called before cmdParse() is used. -*/ - - -void con_parse(EngineState *s, const char *command); -/* Parses a command and summons appropriate facilities to handle it -** Parameters: (EngineState *) s: The EngineState to use -** command: The command to execute -** Returns : (void) -*/ - - -int con_hook_command(ConCommand command, const char *name, const char *param, const char *description); -/* Adds a command to the parser's command list -** Parameters: command: The command to add -** name: The command's name -** param: A description of the parameters it takes -** description: A short description of what it does -** Returns : 0 if successful, 1 if appending failed because -** of an incorrect *param string, 'command'==0, or -** 'name' already being in use. -** A valid param string is either empty (no parameters allowed) -** or contains one of the following tokens: -** ! Special token: EngineState* must be set for this function to be called -** i (an int) -** s (a 'string' (char *)) -** h (a byte, described in hexadecimal digits) -** a (a heap address, register or object name) -** r (any register value) -** x* (an arbitrary (possibly 0) number of 'x' tokens) -** The '*' token may only be used as the last token of the list. -** Another way to specify optional parameters is by means of the -** '-opt:t' notation, which allows an optional parameter of type 't' -** to be specified as 'opt:<value>' when calling. See also the -** con_hasopt() and con_getopt() calls. -** -** Please note that the 'h' type does accept hexadecimal numbers greater -** than 0xff and less than 0x00, but clips them to this range. -** -** Example: "isi*" would define the function to take an int, a -** string, and an arbitrary number of ints as parameters (in that sequence). -** -** When the function is called, it can retrieve its parameters from cmd_params; -** the actual number of parameters is stored in cmd_paramlength. -** It is allowed to modify the char*s from a cmd_params[] element, as long -** as no element beyond strlen(cmd_params[x].str)+1 is accessed. -*/ - -int con_hook_page(const char *topic, const char *body); -/* Hooks a general information page to the manual page system -** Parameters: (const char *) topic: The topic name -** (const char *) body: The text body to assign to the topic -** Returns : (int) 0 on success -*/ - -int con_hook_int(int *pointer, const char *name, const char *description); -/* Adds an int to the list of modifyable ints. -** Parameters: pointer: Pointer to the int to add to the list -** name: Name for this value -** description: A short description for the value -** Returns : 0 on success, 1 if either value has already been added -** or if name is already being used for a different value. -** The internal list of int references is used by some of the basic commands. -*/ - -} // End of namespace Sci - -#endif // SCI_SCICORE_SCICONSOLE_H diff --git a/engines/sci/scicore/vocab_debug.cpp b/engines/sci/scicore/vocab_debug.cpp deleted file mode 100644 index caafa32ca7..0000000000 --- a/engines/sci/scicore/vocab_debug.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/* 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "sci/sci.h" -#include "sci/engine/state.h" -#include "sci/scicore/resource.h" - -namespace Sci { - -// Default kernel name table -#define SCI0_KNAMES_WELL_DEFINED 0x6e -#define SCI0_KNAMES_DEFAULT_ENTRIES_NR 0x72 -#define SCI1_KNAMES_DEFAULT_ENTRIES_NR 0x7E - -static const char *sci0_default_knames[SCI0_KNAMES_DEFAULT_ENTRIES_NR] = { - /*0x00*/ "Load", - /*0x01*/ "UnLoad", - /*0x02*/ "ScriptID", - /*0x03*/ "DisposeScript", - /*0x04*/ "Clone", - /*0x05*/ "DisposeClone", - /*0x06*/ "IsObject", - /*0x07*/ "RespondsTo", - /*0x08*/ "DrawPic", - /*0x09*/ "Show", - /*0x0a*/ "PicNotValid", - /*0x0b*/ "Animate", - /*0x0c*/ "SetNowSeen", - /*0x0d*/ "NumLoops", - /*0x0e*/ "NumCels", - /*0x0f*/ "CelWide", - /*0x10*/ "CelHigh", - /*0x11*/ "DrawCel", - /*0x12*/ "AddToPic", - /*0x13*/ "NewWindow", - /*0x14*/ "GetPort", - /*0x15*/ "SetPort", - /*0x16*/ "DisposeWindow", - /*0x17*/ "DrawControl", - /*0x18*/ "HiliteControl", - /*0x19*/ "EditControl", - /*0x1a*/ "TextSize", - /*0x1b*/ "Display", - /*0x1c*/ "GetEvent", - /*0x1d*/ "GlobalToLocal", - /*0x1e*/ "LocalToGlobal", - /*0x1f*/ "MapKeyToDir", - /*0x20*/ "DrawMenuBar", - /*0x21*/ "MenuSelect", - /*0x22*/ "AddMenu", - /*0x23*/ "DrawStatus", - /*0x24*/ "Parse", - /*0x25*/ "Said", - /*0x26*/ "SetSynonyms", - /*0x27*/ "HaveMouse", - /*0x28*/ "SetCursor", - /*0x29*/ "FOpen", - /*0x2a*/ "FPuts", - /*0x2b*/ "FGets", - /*0x2c*/ "FClose", - /*0x2d*/ "SaveGame", - /*0x2e*/ "RestoreGame", - /*0x2f*/ "RestartGame", - /*0x30*/ "GameIsRestarting", - /*0x31*/ "DoSound", - /*0x32*/ "NewList", - /*0x33*/ "DisposeList", - /*0x34*/ "NewNode", - /*0x35*/ "FirstNode", - /*0x36*/ "LastNode", - /*0x37*/ "EmptyList", - /*0x38*/ "NextNode", - /*0x39*/ "PrevNode", - /*0x3a*/ "NodeValue", - /*0x3b*/ "AddAfter", - /*0x3c*/ "AddToFront", - /*0x3d*/ "AddToEnd", - /*0x3e*/ "FindKey", - /*0x3f*/ "DeleteKey", - /*0x40*/ "Random", - /*0x41*/ "Abs", - /*0x42*/ "Sqrt", - /*0x43*/ "GetAngle", - /*0x44*/ "GetDistance", - /*0x45*/ "Wait", - /*0x46*/ "GetTime", - /*0x47*/ "StrEnd", - /*0x48*/ "StrCat", - /*0x49*/ "StrCmp", - /*0x4a*/ "StrLen", - /*0x4b*/ "StrCpy", - /*0x4c*/ "Format", - /*0x4d*/ "GetFarText", - /*0x4e*/ "ReadNumber", - /*0x4f*/ "BaseSetter", - /*0x50*/ "DirLoop", - /*0x51*/ "CanBeHere", - /*0x52*/ "OnControl", - /*0x53*/ "InitBresen", - /*0x54*/ "DoBresen", - /*0x55*/ "DoAvoider", - /*0x56*/ "SetJump", - /*0x57*/ "SetDebug", - /*0x58*/ "InspectObj", - /*0x59*/ "ShowSends", - /*0x5a*/ "ShowObjs", - /*0x5b*/ "ShowFree", - /*0x5c*/ "MemoryInfo", - /*0x5d*/ "StackUsage", - /*0x5e*/ "Profiler", - /*0x5f*/ "GetMenu", - /*0x60*/ "SetMenu", - /*0x61*/ "GetSaveFiles", - /*0x62*/ "GetCWD", - /*0x63*/ "CheckFreeSpace", - /*0x64*/ "ValidPath", - /*0x65*/ "CoordPri", - /*0x66*/ "StrAt", - /*0x67*/ "DeviceInfo", - /*0x68*/ "GetSaveDir", - /*0x69*/ "CheckSaveGame", - /*0x6a*/ "ShakeScreen", - /*0x6b*/ "FlushResources", - /*0x6c*/ "SinMult", - /*0x6d*/ "CosMult", - /*0x6e*/ "SinDiv", - /*0x6f*/ "CosDiv", - /*0x70*/ "Graph", - /*0x71*/ SCRIPT_UNKNOWN_FUNCTION_STRING -}; - -static const char *sci1_default_knames[SCI1_KNAMES_DEFAULT_ENTRIES_NR] = { - /*0x00*/ "Load", - /*0x01*/ "UnLoad", - /*0x02*/ "ScriptID", - /*0x03*/ "DisposeScript", - /*0x04*/ "Clone", - /*0x05*/ "DisposeClone", - /*0x06*/ "IsObject", - /*0x07*/ "RespondsTo", - /*0x08*/ "DrawPic", - /*0x09*/ "Show", - /*0x0a*/ "PicNotValid", - /*0x0b*/ "Animate", - /*0x0c*/ "SetNowSeen", - /*0x0d*/ "NumLoops", - /*0x0e*/ "NumCels", - /*0x0f*/ "CelWide", - /*0x10*/ "CelHigh", - /*0x11*/ "DrawCel", - /*0x12*/ "AddToPic", - /*0x13*/ "NewWindow", - /*0x14*/ "GetPort", - /*0x15*/ "SetPort", - /*0x16*/ "DisposeWindow", - /*0x17*/ "DrawControl", - /*0x18*/ "HiliteControl", - /*0x19*/ "EditControl", - /*0x1a*/ "TextSize", - /*0x1b*/ "Display", - /*0x1c*/ "GetEvent", - /*0x1d*/ "GlobalToLocal", - /*0x1e*/ "LocalToGlobal", - /*0x1f*/ "MapKeyToDir", - /*0x20*/ "DrawMenuBar", - /*0x21*/ "MenuSelect", - /*0x22*/ "AddMenu", - /*0x23*/ "DrawStatus", - /*0x24*/ "Parse", - /*0x25*/ "Said", - /*0x26*/ "SetSynonyms", - /*0x27*/ "HaveMouse", - /*0x28*/ "SetCursor", - /*0x29*/ "SaveGame", - /*0x2a*/ "RestoreGame", - /*0x2b*/ "RestartGame", - /*0x2c*/ "GameIsRestarting", - /*0x2d*/ "DoSound", - /*0x2e*/ "NewList", - /*0x2f*/ "DisposeList", - /*0x30*/ "NewNode", - /*0x31*/ "FirstNode", - /*0x32*/ "LastNode", - /*0x33*/ "EmptyList", - /*0x34*/ "NextNode", - /*0x35*/ "PrevNode", - /*0x36*/ "NodeValue", - /*0x37*/ "AddAfter", - /*0x38*/ "AddToFront", - /*0x39*/ "AddToEnd", - /*0x3a*/ "FindKey", - /*0x3b*/ "DeleteKey", - /*0x3c*/ "Random", - /*0x3d*/ "Abs", - /*0x3e*/ "Sqrt", - /*0x3f*/ "GetAngle", - /*0x40*/ "GetDistance", - /*0x41*/ "Wait", - /*0x42*/ "GetTime", - /*0x43*/ "StrEnd", - /*0x44*/ "StrCat", - /*0x45*/ "StrCmp", - /*0x46*/ "StrLen", - /*0x47*/ "StrCpy", - /*0x48*/ "Format", - /*0x49*/ "GetFarText", - /*0x4a*/ "ReadNumber", - /*0x4b*/ "BaseSetter", - /*0x4c*/ "DirLoop", - /*0x4d*/ "CanBeHere", - /*0x4e*/ "OnControl", - /*0x4f*/ "InitBresen", - /*0x50*/ "DoBresen", - /*0x51*/ SCRIPT_UNKNOWN_FUNCTION_STRING, // DoAvoider is not implemented in SCI1 - /*0x52*/ "SetJump", - /*0x53*/ "SetDebug", - /*0x54*/ "InspectObj", - /*0x55*/ "ShowSends", - /*0x56*/ "ShowObjs", - /*0x57*/ "ShowFree", - /*0x58*/ "MemoryInfo", - /*0x59*/ "StackUsage", - /*0x5a*/ "Profiler", - /*0x5b*/ "GetMenu", - /*0x5c*/ "SetMenu", - /*0x5d*/ "GetSaveFiles", - /*0x5e*/ "GetCWD", - /*0x5f*/ "CheckFreeSpace", - /*0x60*/ "ValidPath", - /*0x61*/ "CoordPri", - /*0x62*/ "StrAt", - /*0x63*/ "DeviceInfo", - /*0x64*/ "GetSaveDir", - /*0x65*/ "CheckSaveGame", - /*0x66*/ "ShakeScreen", - /*0x67*/ "FlushResources", - /*0x68*/ "SinMult", - /*0x69*/ "CosMult", - /*0x6a*/ "SinDiv", - /*0x6b*/ "CosDiv", - /*0x6c*/ "Graph", - /*0x6d*/ "Joystick", - /*0x6e*/ "ShiftScreen", - /*0x6f*/ "Palette", - /*0x70*/ "MemorySegment", - /*0x71*/ "MoveCursor", - /*0x72*/ "Memory", - /*0x73*/ "ListOps", - /*0x74*/ "FileIO", - /*0x75*/ "DoAudio", - /*0x76*/ "DoSync", - /*0x77*/ "AvoidPath", - /*0x78*/ "Sort", - /*0x79*/ "ATan", - /*0x7a*/ "Lock", - /*0x7b*/ "StrSplit", - /*0x7c*/ "Message", - /*0x7d*/ "IsItSkip" -}; - -#if 0 -int *vocabulary_get_classes(ResourceManager *resmgr, int* count) { - Resource* r; - int *c; - unsigned int i; - - if ((r = resmgr->findResource(kResourceTypeVocab, 996, 0)) == NULL) - return 0; - - c = (int *)malloc(sizeof(int) * r->size / 2); - for (i = 2; i < r->size; i += 4) { - c[i/4] = READ_LE_UINT16(r->data + i); - } - *count = r->size / 4; - - return c; -} - -int vocabulary_get_class_count(ResourceManager *resmgr) { - Resource* r; - - if ((r = resmgr->findResource(kResourceTypeVocab, 996, 0)) == 0) - return 0; - - return r->size / 4; -} -#endif - -bool vocabulary_get_snames(ResourceManager *resmgr, bool isOldSci0, Common::StringList &selectorNames) { - int count; - - Resource *r = resmgr->findResource(kResourceTypeVocab, 997, 0); - - if (!r) // No such resource? - return false; - - count = READ_LE_UINT16(r->data) + 1; // Counter is slightly off - - for (int i = 0; i < count; i++) { - int offset = READ_LE_UINT16(r->data + 2 + i * 2); - int len = READ_LE_UINT16(r->data + offset); - - Common::String tmp((const char *)r->data + offset + 2, len); - selectorNames.push_back(tmp); - - // 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 (isOldSci0) - selectorNames.push_back(tmp); - } - - return true; -} - -int vocabulary_lookup_sname(const Common::StringList &selectorNames, const char *sname) { - for (uint pos = 0; pos < selectorNames.size(); ++pos) { - if (selectorNames[pos] == sname) - return pos; - } - - return -1; -} - -opcode* vocabulary_get_opcodes(ResourceManager *resmgr) { - opcode* o; - int count, i = 0; - Resource* r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_OPCODES, 0); - - // if the resource couldn't be loaded, leave - if (r == NULL) { - fprintf(stderr, "unable to load vocab.%03d\n", VOCAB_RESOURCE_OPCODES); - return NULL; - } - - count = READ_LE_UINT16(r->data); - - o = (opcode*)malloc(sizeof(opcode) * 256); - for (i = 0; i < count; i++) { - int offset = READ_LE_UINT16(r->data + 2 + i * 2); - int len = READ_LE_UINT16(r->data + offset) - 2; - o[i].type = READ_LE_UINT16(r->data + offset + 2); - o[i].number = i; - o[i].name = (char *)malloc(len + 1); - memcpy(o[i].name, r->data + offset + 4, len); - o[i].name[len] = '\0'; -#ifdef VOCABULARY_DEBUG - printf("Opcode %02X: %s, %d\n", i, o[i].name, o[i].type); -#endif - } - for (i = count; i < 256; i++) { - o[i].type = 0; - o[i].number = i; - o[i].name = (char *)malloc(strlen("undefined") + 1); - strcpy(o[i].name, "undefined"); - } - return o; -} - -void vocabulary_free_opcodes(opcode *opcodes) { - int i; - if (!opcodes) - return; - - for (i = 0; i < 256; i++) { - if (opcodes[i].name) - free(opcodes[i].name); - } - free(opcodes); -} - -// Alternative kernel func names retriever. Required for KQ1/SCI (at least). -static void _vocabulary_get_knames0alt(const Resource *r, Common::StringList &names) { - uint idx = 0; - - while (idx < r->size) { - Common::String tmp((const char *)r->data + idx); - names.push_back(tmp); - idx += tmp.size() + 1; - } - - // The mystery kernel function- one in each SCI0 package - names.push_back(SCRIPT_UNKNOWN_FUNCTION_STRING); -} - -static void vocabulary_get_knames0(ResourceManager *resmgr, Common::StringList &names) { - int count, i, index = 2, empty_to_add = 1; - Resource *r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES, 0); - - if (!r) { // No kernel name table found? Fall back to default table - names.resize(SCI0_KNAMES_DEFAULT_ENTRIES_NR); - for (i = 0; i < SCI0_KNAMES_DEFAULT_ENTRIES_NR; i++) - names[i] = sci0_default_knames[i]; - return; - } - - count = READ_LE_UINT16(r->data); - - if (count > 1023) { - _vocabulary_get_knames0alt(r, names); - return; - } - - if (count < SCI0_KNAMES_WELL_DEFINED) { - empty_to_add = SCI0_KNAMES_WELL_DEFINED - count; - sciprintf("Less than %d kernel functions; adding %d\n", SCI0_KNAMES_WELL_DEFINED, empty_to_add); - } - - names.resize(count + 1 + empty_to_add); - - for (i = 0; i < count; i++) { - int offset = READ_LE_UINT16(r->data + index); - int len = READ_LE_UINT16(r->data + offset); - //fprintf(stderr,"Getting name %d of %d...\n", i, count); - index += 2; - names[i] = Common::String((const char *)r->data + offset + 2, len); - } - - for (i = 0; i < empty_to_add; i++) { - names[count + i] = SCRIPT_UNKNOWN_FUNCTION_STRING; - } -} - -static void vocabulary_get_knames1(ResourceManager *resmgr, Common::StringList &names) { - // vocab.999/999.voc is notoriously unreliable in SCI1 games, and should not be used - // We hardcode the default SCI1 kernel names here (i.e. the ones inside the "special" - // 999.voc file from FreeSCI). All SCI1 games seem to be working with this change, but - // if any SCI1 game has different kernel vocabulary names, it might not work. It seems - // that all SCI1 games use the same kernel vocabulary names though, so this seems to be - // a safe change. If there's any SCI1 game with different kernel vocabulary names, we can - // add special flags to it to our detector - - names.resize(SCI1_KNAMES_DEFAULT_ENTRIES_NR); - for (int i = 0; i < SCI1_KNAMES_DEFAULT_ENTRIES_NR; i++) - names[i] = sci1_default_knames[i]; -} - -#ifdef ENABLE_SCI32 -static void vocabulary_get_knames11(ResourceManager *resmgr, Common::StringList &names) { -/* - 999.voc format for SCI1.1 games: - [b] # of kernel functions - [w] unknown - [offset to function name info] - ... - {[w name-len][function name]} - ... -*/ - //unsigned int size = 64, pos = 3; - int len; - Resource *r = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_KNAMES, 0); - if(r == NULL) // failed to open vocab.999 (happens with SCI1 demos) - return; // FIXME: should return a default table for this engine - const byte nCnt = *r->data; - - names.resize(nCnt); - for (int i = 0; i < nCnt; i++) { - int off = READ_LE_UINT16(r->data + 2 * i + 2); - len = READ_LE_UINT16(r->data + off); - names[i] = Common::String((char *)r->data + off + 2, len); - } -} -#endif - -void vocabulary_get_knames(ResourceManager *resmgr, Common::StringList &names) { - names.clear(); - - switch (resmgr->_sciVersion) { - case SCI_VERSION_0: - case SCI_VERSION_01: - vocabulary_get_knames0(resmgr, names); - break; - case SCI_VERSION_01_VGA: - case SCI_VERSION_01_VGA_ODD: - // HACK: KQ5 needs the SCI1 default vocabulary names to work correctly. - // Having more vocabulary names (like in SCI1) doesn't seem to have any - // ill effects, other than resulting in unmapped functions towards the - // end, which are never used by the game interpreter anyway - // return vocabulary_get_knames0(resmgr, count); - case SCI_VERSION_1_EARLY: - case SCI_VERSION_1_LATE: - vocabulary_get_knames1(resmgr, names); - break; - case SCI_VERSION_1_1: - vocabulary_get_knames1(resmgr, names); - break; -#ifdef ENABLE_SCI32 - case SCI_VERSION_32: - vocabulary_get_knames11(resmgr, names); -#endif - break; - default: - break; - } -} - -} // End of namespace Sci diff --git a/engines/sci/scicore/vocabulary.cpp b/engines/sci/scicore/vocabulary.cpp deleted file mode 100644 index af63a9803a..0000000000 --- a/engines/sci/scicore/vocabulary.cpp +++ /dev/null @@ -1,566 +0,0 @@ -/* 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -// Main vocabulary support functions and word lookup - -#include "sci/scicore/vocabulary.h" -#include "sci/scicore/resource.h" -#include "sci/engine/state.h" -#include "sci/engine/kernel.h" - -namespace Sci { - -int vocab_version; - -#define VOCAB_RESOURCE_PARSE_TREE_BRANCHES vocab_version == 1 ? \ - VOCAB_RESOURCE_SCI1_PARSE_TREE_BRANCHES : \ - VOCAB_RESOURCE_SCI0_PARSE_TREE_BRANCHES - -#define VOCAB_RESOURCE_SUFFIX_VOCAB vocab_version==1 ? \ - VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB : \ - VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB - - -/* -// These strange names were taken from an SCI01 interpreter -const char *class_names[] = {"", - "", - "conj", // conjunction - "ass", // ? - "pos", // preposition ? - "art", // article - "adj", // adjective - "pron", // pronoun - "noun", // noun - "auxv", // auxillary verb - "adv", // adverb - "verb", // verb - "", - "", - "", - "" - }; -*/ - -bool vocab_get_words(ResourceManager *resmgr, WordMap &words) { - - char currentword[256] = ""; // They're not going to use words longer than 255 ;-) - int currentwordpos = 0; - - Resource *resource; - - // First try to load the SCI0 vocab resource. - resource = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI0_MAIN_VOCAB, 0); - vocab_version = 0; - - if (!resource) { - warning("SCI0: Could not find a main vocabulary, trying SCI01"); - resource = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SCI1_MAIN_VOCAB, 0); - vocab_version = 1; - } - - if (!resource) { - warning("SCI1: Could not find a main vocabulary"); - return false; // NOT critical: SCI1 games and some demos don't have one! - } - - unsigned int seeker; - if (vocab_version == 1) - seeker = 255 * 2; // vocab.900 starts with 255 16-bit pointers which we don't use - else - seeker = 26 * 2; // vocab.000 starts with 26 16-bit pointers which we don't use - - if (resource->size < seeker) { - fprintf(stderr, "Invalid main vocabulary encountered: Too small\n"); - return false; - // Now this ought to be critical, but it'll just cause parse() and said() not to work - } - - words.clear(); - - while (seeker < resource->size) { - byte c; - - currentwordpos = resource->data[seeker++]; // Parts of previous words may be re-used - - if (vocab_version == 1) { - c = 1; - while (seeker < resource->size && currentwordpos < 255 && c) { - c = resource->data[seeker++]; - currentword[currentwordpos++] = c; - } - if (seeker == resource->size) { - warning("SCI1: Vocabulary not usable, disabling"); - words.clear(); - return false; - } - } else { - do { - c = resource->data[seeker++]; - currentword[currentwordpos++] = c & 0x7f; // 0x80 is used to terminate the string - } while (c < 0x80); - } - - currentword[currentwordpos] = 0; - - // Now decode class and group: - c = resource->data[seeker + 1]; - ResultWord newWord; - newWord._class = ((resource->data[seeker]) << 4) | ((c & 0xf0) >> 4); - newWord._group = (resource->data[seeker + 2]) | ((c & 0x0f) << 8); - - // Add the word to the list - words[currentword] = newWord; - - seeker += 3; - } - - return true; -} - -const char *vocab_get_any_group_word(int group, const WordMap &words) { - if (group == VOCAB_MAGIC_NUMBER_GROUP) - return "{number}"; - - for (WordMap::const_iterator i = words.begin(); i != words.end(); ++i) - if (i->_value._group == group) - return i->_key.c_str(); - - return "{invalid}"; -} - -bool vocab_get_suffixes(ResourceManager *resmgr, SuffixList &suffixes) { - Resource *resource = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SUFFIX_VOCAB, 1); - unsigned int seeker = 1; - - if (!resource) { - warning("Could not find suffix vocabulary"); - return false; // Not critical - } - - while ((seeker < resource->size - 1) && (resource->data[seeker + 1] != 0xff)) { - suffix_t suffix; - - suffix.alt_suffix = (const char *)resource->data + seeker; - suffix.alt_suffix_length = strlen(suffix.alt_suffix); - seeker += suffix.alt_suffix_length + 1; // Hit end of string - - suffix.class_mask = (int16)READ_BE_UINT16(resource->data + seeker); - seeker += 2; - - // Beginning of next string - skip leading '*' - seeker++; - - suffix.word_suffix = (const char *)resource->data + seeker; - suffix.word_suffix_length = strlen(suffix.word_suffix); - seeker += suffix.word_suffix_length + 1; - - suffix.result_class = (int16)READ_BE_UINT16(resource->data + seeker); - seeker += 3; // Next entry - - suffixes.push_back(suffix); - } - - return true; -} - -void vocab_free_suffixes(ResourceManager *resmgr, SuffixList &suffixes) { - resmgr->unlockResource(resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_SUFFIX_VOCAB, 0), - VOCAB_RESOURCE_SUFFIX_VOCAB, kResourceTypeVocab); - - suffixes.clear(); -} - -bool vocab_get_branches(ResourceManager * resmgr, Common::Array<parse_tree_branch_t> &branches) { - Resource *resource = resmgr->findResource(kResourceTypeVocab, VOCAB_RESOURCE_PARSE_TREE_BRANCHES, 0); - - branches.clear(); - - if (!resource) { - fprintf(stderr, "No parser tree data found!\n"); - return false; - } - - int branches_nr = resource->size / 20; - - if (branches_nr == 0) { - fprintf(stderr, "Parser tree data is empty!\n"); - return false; - } - - branches.resize(branches_nr); - - for (int i = 0; i < branches_nr; i++) { - byte *base = resource->data + i * 20; - - branches[i].id = (int16)READ_LE_UINT16(base); - - for (int k = 0; k < 9; k++) - branches[i].data[k] = READ_LE_UINT16(base + 2 + 2 * k); - - branches[i].data[9] = 0; // Always terminate - } - - if (!branches[branches_nr - 1].id) // branch lists may be terminated by empty rules - branches.remove_at(branches_nr - 1); - - return true; -} - - -ResultWord vocab_lookup_word(const char *word, int word_len, const WordMap &words, const SuffixList &suffixes) { - Common::String tempword(word, word_len); - - // Remove all dashes from tempword - for (uint i = 0; i < tempword.size(); ) { - if (tempword[i] == '-') - tempword.deleteChar(i); - else - ++i; - } - - // Look it up: - WordMap::iterator dict_word = words.find(tempword); - - // Match found? Return it! - if (dict_word != words.end()) { - return dict_word->_value; - } - - // Now try all suffixes - for (SuffixList::const_iterator suffix = suffixes.begin(); suffix != suffixes.end(); ++suffix) - if (suffix->alt_suffix_length <= word_len) { - - int suff_index = word_len - suffix->alt_suffix_length; - // Offset of the start of the suffix - - if (scumm_strnicmp(suffix->alt_suffix, word + suff_index, suffix->alt_suffix_length) == 0) { // Suffix matched! - // Terminate word at suffix start position...: - Common::String tempword2(word, MIN(word_len, suff_index)); - - // ...and append "correct" suffix - tempword2 += Common::String(suffix->word_suffix, suffix->word_suffix_length); - - dict_word = words.find(tempword2); - - if ((dict_word != words.end()) && (dict_word->_value._class & suffix->class_mask)) { // Found it? - // Use suffix class - ResultWord tmp = dict_word->_value; - tmp._class = suffix->result_class; - return tmp; - } - } - } - - // No match so far? Check if it's a number. - - ResultWord retval = { -1, -1 }; - char *tester; - if ((strtol(tempword.c_str(), &tester, 10) >= 0) && (*tester == '\0')) { // Do we have a complete number here? - ResultWord tmp = { VOCAB_CLASS_NUMBER, VOCAB_MAGIC_NUMBER_GROUP }; - retval = tmp; - } - - return retval; -} - -void vocab_decypher_said_block(EngineState *s, byte *addr) { - int nextitem; - - do { - nextitem = *addr++; - - if (nextitem < 0xf0) { - nextitem = nextitem << 8 | *addr++; - sciprintf(" %s[%03x]", vocab_get_any_group_word(nextitem, s->_parserWords), nextitem); - - nextitem = 42; // Make sure that group 0xff doesn't abort - } else switch (nextitem) { - case 0xf0: - sciprintf(" ,"); - break; - case 0xf1: - sciprintf(" &"); - break; - case 0xf2: - sciprintf(" /"); - break; - case 0xf3: - sciprintf(" ("); - break; - case 0xf4: - sciprintf(" )"); - break; - case 0xf5: - sciprintf(" ["); - break; - case 0xf6: - sciprintf(" ]"); - break; - case 0xf7: - sciprintf(" #"); - break; - case 0xf8: - sciprintf(" <"); - break; - case 0xf9: - sciprintf(" >"); - break; - case 0xff: - break; - } - } while (nextitem != 0xff); - - sciprintf("\n"); -} - - -#ifdef SCI_SIMPLE_SAID_CODE - -static const short _related_words[][2] = { // 0 is backwards, 1 is forward - {0x800, 0x180}, // preposition - {0x000, 0x180}, // article - {0x000, 0x180}, // adjective - {0x800, 0x000}, // pronoun - {0x800, 0x180}, // noun - {0x000, 0x800}, // auxiliary verb - {0x800, 0x800}, // adverb - {0x000, 0x180}, // verb - {0x000, 0x180} // number -}; - -int vocab_build_simple_parse_tree(parse_tree_node_t *nodes, WordMap &words) { - int i, length, pos = 0; - - for (i = 0; i < words.size(); ++i) { - if (words[i]._class != VOCAB_CLASS_ANYWORD) { - nodes[pos].type = words[i]._class; - nodes[pos].content.value = words[i]._group; - pos += 2; // Link information is filled in below - } - } - nodes[pos].type = -1; // terminate - length = pos >> 1; - - // now find all referenced words -#ifdef SCI_SIMPLE_SAID_DEBUG - sciprintf("Semantic references:\n"); -#endif - - for (i = 0; i < length; i++) { - int j; - int searchmask; - int type; - - pos = (i << 1); - type = sci_ffs(nodes[pos].type); - - if (type) { - int found = -1; - - type -= 5; // 1 because ffs starts counting at 1, 4 because nodes[pos].type is a nibble off - if (type < 0) - type = 0; -#ifdef SCI_SIMPLE_SAID_DEBUG - sciprintf("#%d: Word %04x: type %04x\n", i, nodes[pos].content.value, type); -#endif - - // search backwards - searchmask = _related_words[type][0]; - if (searchmask) { - for (j = i - 1; j >= 0; j--) - if (nodes[j << 1].type & searchmask) { - found = j << 1; - break; - } - } - nodes[pos+1].content.branches[0] = found; -#ifdef SCI_SIMPLE_SAID_DEBUG - if (found > -1) - sciprintf(" %d <\n", found >> 1); -#endif - - // search forward - found = -1; - searchmask = _related_words[type][1]; - if (searchmask) { - for (j = i + 1; j < length; j++) - if (nodes[j << 1].type & searchmask) { - found = j << 1; - break; - } - } -#ifdef SCI_SIMPLE_SAID_DEBUG - if (found > -1) - sciprintf(" > %d\n", found >> 1); -#endif - } else { -#ifdef SCI_SIMPLE_SAID_DEBUG - sciprintf("#%d: Untypified word\n", i); /* Weird, but not fatal */ -#endif - nodes[pos + 1].content.branches[0] = -1; - nodes[pos + 1].content.branches[1] = -1; - } - } -#ifdef SCI_SIMPLE_SAID_DEBUG - sciprintf("/Semantic references.\n"); -#endif - - return 0; -} -#endif - -bool vocab_tokenize_string(ResultWordList &retval, const char *sentence, const WordMap &words, - const SuffixList &suffixes, char **error) { - const char *lastword = sentence; - int pos_in_sentence = 0; - char c; - int wordlen = 0; - - *error = NULL; - - do { - - c = sentence[pos_in_sentence++]; - - if (isalnum(c) || (c == '-' && wordlen)) - ++wordlen; - // Continue on this word */ - // Words may contain a '-', but may not - // start with one. - else { - if (wordlen) { // Finished a word? - - ResultWord lookup_result = - vocab_lookup_word(lastword, wordlen, words, suffixes); - // Look it up - - if (lookup_result._class == -1) { // Not found? - *error = (char *)calloc(wordlen + 1, 1); - strncpy(*error, lastword, wordlen); // Set the offending word - retval.clear(); - return false; // And return with error - } - - // Copy into list - retval.push_back(lookup_result); - } - - lastword = sentence + pos_in_sentence; - wordlen = 0; - } - - } while (c); // Until terminator is hit - - return true; -} - -void _vocab_recursive_ptree_dump_treelike(parse_tree_node_t *nodes, int nr, int prevnr) { - if ((nr > VOCAB_TREE_NODES)/* || (nr < prevnr)*/) { - sciprintf("Error(%04x)", nr); - return; - } - - if (nodes[nr].type == PARSE_TREE_NODE_LEAF) - //sciprintf("[%03x]%04x", nr, nodes[nr].content.value); - sciprintf("%x", nodes[nr].content.value); - else { - int lbranch = nodes[nr].content.branches[0]; - int rbranch = nodes[nr].content.branches[1]; - //sciprintf("<[%03x]", nr); - sciprintf("<"); - - if (lbranch) - _vocab_recursive_ptree_dump_treelike(nodes, lbranch, nr); - else - sciprintf("NULL"); - - sciprintf(","); - - if (rbranch) - _vocab_recursive_ptree_dump_treelike(nodes, rbranch, nr); - else - sciprintf("NULL"); - - sciprintf(">"); - } -} - -void _vocab_recursive_ptree_dump(parse_tree_node_t *nodes, int nr, int prevnr, int blanks) { - int lbranch = nodes[nr].content.branches[0]; - int rbranch = nodes[nr].content.branches[1]; - int i; - - if (nodes[nr].type == PARSE_TREE_NODE_LEAF) { - sciprintf("vocab_dump_parse_tree: Error: consp is nil for element %03x\n", nr); - return; - } - - if ((nr > VOCAB_TREE_NODES)/* || (nr < prevnr)*/) { - sciprintf("Error(%04x))", nr); - return; - } - - if (lbranch) { - if (nodes[lbranch].type == PARSE_TREE_NODE_BRANCH) { - sciprintf("\n"); - for (i = 0; i < blanks; i++) - sciprintf(" "); - sciprintf("("); - _vocab_recursive_ptree_dump(nodes, lbranch, nr, blanks + 1); - sciprintf(")\n"); - for (i = 0; i < blanks; i++) - sciprintf(" "); - } else - sciprintf("%x", nodes[lbranch].content.value); - sciprintf(" "); - }/* else sciprintf ("nil");*/ - - if (rbranch) { - if (nodes[rbranch].type == PARSE_TREE_NODE_BRANCH) - _vocab_recursive_ptree_dump(nodes, rbranch, nr, blanks); - else - sciprintf("%x", nodes[rbranch].content.value); - }/* else sciprintf("nil");*/ -} - -void vocab_dump_parse_tree(const char *tree_name, parse_tree_node_t *nodes) { - //_vocab_recursive_ptree_dump_treelike(nodes, 0, 0); - sciprintf("(setq %s \n'(", tree_name); - _vocab_recursive_ptree_dump(nodes, 0, 0, 1); - sciprintf("))\n"); -} - -void vocab_synonymize_tokens(ResultWordList &words, const SynonymList &synonyms) { - if (synonyms.empty()) - return; // No synonyms: Nothing to check - - for (ResultWordList::iterator i = words.begin(); i != words.end(); ++i) - for (SynonymList::const_iterator sync = synonyms.begin(); sync != synonyms.end(); ++sync) - if (i->_group == sync->replaceant) - i->_group = sync->replacement; -} - -} // End of namespace Sci diff --git a/engines/sci/scicore/vocabulary.h b/engines/sci/scicore/vocabulary.h deleted file mode 100644 index d0c807aebf..0000000000 --- a/engines/sci/scicore/vocabulary.h +++ /dev/null @@ -1,359 +0,0 @@ -/* 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 2 - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#ifndef SCI_SCICORE_VOCABULARY_H -#define SCI_SCICORE_VOCABULARY_H - -#include "common/str.h" -#include "common/hashmap.h" -#include "common/hash-str.h" -#include "common/list.h" - -#include "sci/sci.h" - -namespace Sci { - -class ResourceManager; - -/*#define VOCABULARY_DEBUG */ -/*#define SCI_SIMPLE_SAID_CODE */ /* Whether the simplified Said() matching should be used */ -/*#define SCI_SIMPLE_SAID_DEBUG */ /* uncomment to enable simple said debugging */ - - -#define SCRIPT_UNKNOWN_FUNCTION_STRING "[Unknown]" -/* The string used to identify the "unknown" SCI0 function for each game */ - -#define PARSE_HEAP_SIZE 64 -/* Number of bytes allocated on the heap to store bad words if parsing fails */ - - -struct opcode { - int type; - int number; - char* name; -}; - -#define VOCAB_RESOURCE_OPCODES 998 -#define VOCAB_RESOURCE_KNAMES 999 - -#define VOCAB_RESOURCE_SCI0_MAIN_VOCAB 0 -#define VOCAB_RESOURCE_SCI0_PARSE_TREE_BRANCHES 900 -#define VOCAB_RESOURCE_SCI0_SUFFIX_VOCAB 901 - -#define VOCAB_RESOURCE_SCI1_MAIN_VOCAB 900 -#define VOCAB_RESOURCE_SCI1_PARSE_TREE_BRANCHES 901 -#define VOCAB_RESOURCE_SCI1_SUFFIX_VOCAB 902 -#define VOCAB_RESOURCE_SCI1_CHAR_TRANSFORMS 913 - -enum { - VOCAB_CLASS_PREPOSITION = 0x01, - VOCAB_CLASS_ARTICLE = 0x02, - VOCAB_CLASS_ADJECTIVE = 0x04, - VOCAB_CLASS_PRONOUN = 0x08, - VOCAB_CLASS_NOUN = 0x10, - VOCAB_CLASS_INDICATIVE_VERB = 0x20, - VOCAB_CLASS_ADVERB = 0x40, - VOCAB_CLASS_IMPERATIVE_VERB = 0x80, - VOCAB_CLASS_NUMBER = 0x001 -}; - -extern const char *class_names[]; /* Vocabulary class names */ - -#define VOCAB_CLASS_ANYWORD 0xff -/* Anywords are ignored by the parser */ - -#define VOCAB_MAGIC_NUMBER_GROUP 0xffd /* 0xffe ? */ -/* This word class is used for numbers */ - -#define VOCAB_TREE_NODES 500 -/* Number of nodes for each parse_tree_node structure */ - -#define VOCAB_TREE_NODE_LAST_WORD_STORAGE 0x140 -#define VOCAB_TREE_NODE_COMPARE_TYPE 0x146 -#define VOCAB_TREE_NODE_COMPARE_GROUP 0x14d -#define VOCAB_TREE_NODE_FORCE_STORAGE 0x154 - -#define SAID_COMMA 0xf0 -#define SAID_AMP 0xf1 -#define SAID_SLASH 0xf2 -#define SAID_PARENO 0xf3 -#define SAID_PARENC 0xf4 -#define SAID_BRACKO 0xf5 -#define SAID_BRACKC 0xf6 -#define SAID_HASH 0xf7 -#define SAID_LT 0xf8 -#define SAID_GT 0xf9 -#define SAID_TERM 0xff - -#define SAID_FIRST SAID_COMMA - -/* There was no 'last matching word': */ -#define SAID_FULL_MATCH 0xffff -#define SAID_NO_MATCH 0xfffe -#define SAID_PARTIAL_MATCH 0xfffd - -#define SAID_LONG(x) ((x) << 8) - -struct ResultWord { - int _class; /* Word class */ - int _group; /* Word group */ -}; - -typedef Common::List<ResultWord> ResultWordList; - -typedef Common::HashMap<Common::String, ResultWord, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> WordMap; - - -struct parse_rule_t { - int id; /* non-terminal ID */ - int first_special; /* first terminal or non-terminal */ - int specials_nr; /* number of terminals and non-terminals */ - int length; - int data[1]; /* actual data (size 1 to avoid compiler warnings) */ -}; - - -struct parse_rule_list_t { - int terminal; /* Terminal character this rule matches against or 0 for a non-terminal rule */ - parse_rule_t *rule; - parse_rule_list_t *next; -}; - - -struct suffix_t { - - int class_mask; /* the word class this suffix applies to */ - int result_class; /* the word class a word is morphed to if it doesn't fail this check */ - - int alt_suffix_length; /* String length of the suffix */ - int word_suffix_length; /* String length of the other suffix */ - - const char *alt_suffix; /* The alternative suffix */ - const char *word_suffix; /* The suffix as used in the word vocabulary */ - -}; - -typedef Common::List<suffix_t> SuffixList; - - -struct synonym_t { - int replaceant; /* The word group to replace */ - int replacement; /* The replacement word group for this one */ -}; - -typedef Common::List<synonym_t> SynonymList; - -struct parse_tree_branch_t { - int id; - int data[10]; -}; - -#define PARSE_TREE_NODE_LEAF 0 -#define PARSE_TREE_NODE_BRANCH 1 - - -struct parse_tree_node_t { - short type; /* leaf or branch */ - union { - int value; /* For leaves */ - short branches[2]; /* For branches */ - } content; -}; - - - -/*FIXME: These need freeing functions...*/ - -#if 0 -int *vocabulary_get_classes(ResourceManager *resmgr, int *count); -int vocabulary_get_class_count(ResourceManager *resmgr); -#endif - -/** - * Fills the given StringList with selector names. - * Returns true upon success, false oterwise. - */ -bool vocabulary_get_snames(ResourceManager *resmgr, bool isOldSci0, Common::StringList &selectorNames); - -/* Look up a selector name in an array, return the index */ -int vocabulary_lookup_sname(const Common::StringList &selectorNames, const char *sname); - - -/** - * Returns a null terminated array of opcodes. - */ -opcode *vocabulary_get_opcodes(ResourceManager *resmgr); - -void vocabulary_free_opcodes(opcode *opcodes); -/* Frees a previously allocated list of opcodes -** Parameters: (opcode *) opcodes: Opcodes to free -*/ - -/** - * Fills a StringList with kernel function names. - * - * This function reads the kernel function name table from resource_map, - * and fills the given StringList with them. - * The resulting list has the same format regardless of the format of the - * name table of the resource (the format changed between version 0 and 1). - */ -void vocabulary_get_knames(ResourceManager *resmgr, Common::StringList &names); - - -/** - * Gets all words from the main vocabulary. - * @param resmr The resource manager to read from - * @param words A list of all words - * @return true on success, false on failure - */ -bool vocab_get_words(ResourceManager *resmgr, WordMap &words); - - -bool vocab_get_suffixes(ResourceManager *resmgr, SuffixList &suffixes); -/* Loads all suffixes from the suffix vocabulary. -** Parameters: (ResourceManager*) resmgr: Resource manager the resources are -** read from -** Returns : true on success, false on failure -*/ - -void vocab_free_suffixes(ResourceManager *resmgr, SuffixList &suffixes); -/* Frees all suffixes in the given list. -** Parameters: (ResourceManager *) resmgr: The resource manager to free from -** (SuffixList) suffixes: The suffixes to free -*/ - -/** - * Retrieves all grammar rules from the resource data. - * @param resmgr Resource manager the rules are read from - * @param branches The rules are stored into this Array - * @return true on success, false on error - */ -bool vocab_get_branches(ResourceManager *resmgr, Common::Array<parse_tree_branch_t> &branches); - -ResultWord vocab_lookup_word(const char *word, int word_len, - const WordMap &words, const SuffixList &suffixes); -/* Looks up a single word in the words and suffixes list -** Parameters: (char *) word: Pointer to the word to look up -** (int) word_len: Length of the word to look up -** (const WordMap &) words: List of words -** (SuffixList) suffixes: List of suffixes -** Returns : (const ResultWordList &) A list containing 1 or 0 words -*/ - - -bool vocab_tokenize_string(ResultWordList &retval, const char *sentence, - const WordMap &words, const SuffixList &suffixes, char **error); -/* Tokenizes a string and compiles it into word_ts. -** Parameters: (char *) sentence: The sentence to examine -** (const WordMap &) words: The words to scan for -** (SuffixList) suffixes: suffixes to scan for -** (char **) error: Points to a malloc'd copy of the offending text or to NULL on error -** (ResultWordList) retval: A list of word_ts containing the result, or NULL. -** Returns : true on success, false on failure -** On error, NULL is returned. If *error is NULL, the sentence did not contain any useful words; -** if not, *error points to a malloc'd copy of the offending word. -** The returned list may contain anywords. -*/ - - -parse_rule_list_t *vocab_build_gnf(const Common::Array<parse_tree_branch_t> &branches); -/* Constructs the Greibach Normal Form of the grammar supplied in 'branches' -** Parameters: (parse_tree_branch_t *) branches: The parser's branches -** Returns : (parse_rule_list_t *): Pointer to a list of singly linked -** GNF rules describing the same language -** that was described by 'branches' -** The original SCI rules are in almost-CNF (Chomsky Normal Form). Note that -** branch[0] is used only for a few magical incantations, as it is treated -** specially by the SCI parser. -*/ - - -void vocab_free_rule_list(parse_rule_list_t *rule_list); -/* Frees a parser rule list as returned by vocab_build_gnf() -** Parameters: (parse_rule_list_t *) rule_list: The rule list to free -*/ - - -int vocab_build_parse_tree(parse_tree_node_t *nodes, const ResultWordList &words, - const parse_tree_branch_t &branch0, parse_rule_list_t *rules); -/* Builds a parse tree from a list of words -** Parameters: (parse_tree_node_t *) nodes: A node list to store the tree in (must have -** at least VOCAB_TREE_NODES entries) -** (const ResultWordList &) words: The words to build the tree from -** (parse_tree_branch_t *) branche0: The zeroeth original branch of the -** original CNF parser grammar -** (parse_rule_list *) rules: The GNF ruleset to parse with -** Returns : 0 on success, 1 if the tree couldn't be built in VOCAB_TREE_NODES nodes -** or if the sentence structure in 'words' is not part of the language -** described by the grammar passed in 'rules'. -*/ - -void vocab_dump_parse_tree(const char *tree_name, parse_tree_node_t *nodes); -/* Prints a parse tree -** Parameters: (const char *) tree_name: Name of the tree to dump (free-form) -** (parse_tree_node_t *) nodes: The nodes containing the parse tree -*/ - - - - -int said(EngineState *s, byte *spec, int verbose); -/* Builds a parse tree from a spec and compares it to a parse tree -** Parameters: (EngineState *) s: The affected state -** (byte *) spec: Pointer to the spec to build -** (int) verbose: Whether to display the parse tree after building it -** Returns : (int) 1 on a match, 0 otherwise -*/ - -/** - * Gets any word from the specified group. For debugging only. - * @param group Group number - * @param words List of words - */ -const char *vocab_get_any_group_word(int group, const WordMap &words); - - -void vocab_decypher_said_block(EngineState *s, byte *pos); -/* Decyphers a said block and dumps its content via sciprintf. -** Parameters: (EngineState *) s: The state to use -** (byte *) pos: Pointer to the data to dump -** For debugging only. -*/ - - -void vocab_synonymize_tokens(ResultWordList &words, const SynonymList &synonyms); -/* Synonymizes a token list -** Parameters: (ResultWordList &) words: The word list to synonymize -** (const SynonymList &) synonyms: Synonym list -*/ - -int vocab_gnf_parse(parse_tree_node_t *nodes, const ResultWordList &words, - const parse_tree_branch_t &branch0, parse_rule_list_t *tlist, int verbose); - -void vocab_gnf_dump(const Common::Array<parse_tree_branch_t> &branches); - -} // End of namespace Sci - -#endif // SCI_SCICORE_VOCABULARY_H |