diff options
Diffstat (limited to 'engines/glk/alan2/decode.cpp')
-rw-r--r-- | engines/glk/alan2/decode.cpp | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/engines/glk/alan2/decode.cpp b/engines/glk/alan2/decode.cpp new file mode 100644 index 0000000000..4ffdc2f3b9 --- /dev/null +++ b/engines/glk/alan2/decode.cpp @@ -0,0 +1,193 @@ +/* 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. + * + */ + +#include <stdlib.h> +#include "glk/alan2/main.h" +#include "glk/alan2/decode.h" + +namespace Glk { +namespace Alan2 { + +/* Bit output */ +static int decodeBuffer; /* Bits to be input */ +static int bitsToGo; /* Bits still in buffer */ +static int garbageBits; /* Bits past EOF */ + + +#ifdef _PROTOTYPES_ +static int inputBit(void) +#else +static int inputBit() +#endif +{ + int bit; + + if (!bitsToGo) { /* More bits available ? */ + decodeBuffer = txtfil->readByte(); /* No, so get more */ + if (decodeBuffer == EOF) { + garbageBits++; + if (garbageBits > VALUEBITS-2) + syserr("Error in encoded data file."); + } else + bitsToGo = 8; /* Another Char, 8 new bits */ + } + bit = decodeBuffer&1; /* Get next bit */ + decodeBuffer = decodeBuffer>>1; /* and remove it */ + bitsToGo--; + return bit; +} + + +/* Current state of decoding */ + +static CodeValue value; /* Currently seen code value */ +static CodeValue low, high; /* Current code region */ + + +#ifdef _PROTOTYPES_ +void startDecoding(void) +#else +void startDecoding() +#endif +{ + int i; + + bitsToGo = 0; + garbageBits = 0; + + value = 0; + for (i = 0; i < VALUEBITS; i++) + value = 2*value + inputBit(); + low = 0; + high = TOPVALUE; +} + + +#ifdef _PROTOTYPES_ +int decodeChar(void) +#else +int decodeChar() +#endif +{ + long range; + int f; + int symbol; + + range = (long)(high-low) + 1; + f = (((long)(value-low)+1)*freq[0]-1)/range; + + /* Find the symbol */ + for (symbol = 1; (int)freq[symbol] > f; symbol++); + + high = low + range*freq[symbol-1]/freq[0]-1; + low = low + range*freq[symbol]/freq[0]; + + for (;;) { + if (high < HALF) + ; + else if (low >= HALF) { + value = value - HALF; + low = low - HALF; + high = high - HALF; + } else if (low >= ONEQUARTER && high < THREEQUARTER) { + value = value - ONEQUARTER; + low = low - ONEQUARTER; + high = high - ONEQUARTER; + } else + break; + + /* Scale up the range */ + low = 2*low; + high = 2*high+1; + value = 2*value + inputBit(); + } + return symbol-1; +} + + + +/* Structure for saved decode info */ +typedef struct DecodeInfo { + long fpos; + int buffer; + int bits; + CodeValue value; + CodeValue high; + CodeValue low; +} DecodeInfo; + + +/*====================================================================== + + pushDecode() + + Save so much info about the decoding process so it is possible to + restore and continue later. + + */ +#ifdef _PROTOTYPES_ +void *pushDecode(void) +#else +void *pushDecode() +#endif +{ + DecodeInfo *info; + + info = (DecodeInfo *) allocate(sizeof(DecodeInfo)); + info->fpos = txtfil->pos(); + info->buffer = decodeBuffer; + info->bits = bitsToGo; + info->value = value; + info->high = high; + info->low = low; + return(info); +} + + +/*====================================================================== + + popDecode() + + Restore enough info about the decoding process so it is possible to + continue after having decoded something else. + + */ +#ifdef _PROTOTYPES_ +void popDecode(void *i) +#else +void popDecode(i) + void *i; +#endif +{ + DecodeInfo *info = (DecodeInfo *) i; + fseek(txtfil, info->fpos, 0); + decodeBuffer = info->buffer; + bitsToGo = info->bits; + value = info->value; + high = info->high; + low = info->low; + + free(info); +} + +} // End of namespace Alan2 +} // End of namespace Glk |