mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-05 17:20:30 +00:00
570 lines
16 KiB
C++
570 lines
16 KiB
C++
// Residual - Virtual machine to run LucasArts' 3D adventure games
|
|
// Copyright (C) 2003 The ScummVM-Residual Team (www.scummvm.org)
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2.1 of the License, or (at your option) any later version.
|
|
//
|
|
// This library 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
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
#include <stdint.h>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
|
|
uint32_t get_be_uint32(char *p) {
|
|
unsigned char *pos = reinterpret_cast<unsigned char *>(p);
|
|
return (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) | pos[3];
|
|
}
|
|
|
|
uint16_t imcTable1[] = {
|
|
0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e,
|
|
0x0010, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001c, 0x001f,
|
|
0x0022, 0x0025, 0x0029, 0x002d, 0x0032, 0x0037, 0x003c, 0x0042,
|
|
0x0049, 0x0050, 0x0058, 0x0061, 0x006b, 0x0076, 0x0082, 0x008f,
|
|
0x009d, 0x00ad, 0x00be, 0x00d1, 0x00e6, 0x00fd, 0x0117, 0x0133,
|
|
0x0151, 0x0173, 0x0198, 0x01c1, 0x01ee, 0x0220, 0x0256, 0x0292,
|
|
0x02d4, 0x031c, 0x036c, 0x03c3, 0x0424, 0x048e, 0x0502, 0x0583,
|
|
0x0610, 0x06ab, 0x0756, 0x0812, 0x08e0, 0x09c3, 0x0abd, 0x0bd0,
|
|
0x0cff, 0x0e4c, 0x0fba, 0x114c, 0x1307, 0x14ee, 0x1706, 0x1954,
|
|
0x1bdc, 0x1ea5, 0x21b6, 0x2515, 0x28ca, 0x2cdf, 0x315b, 0x364b,
|
|
0x3bb9, 0x41b2, 0x4844, 0x4f7e, 0x5771, 0x602f, 0x69ce, 0x7462,
|
|
0x7fff
|
|
};
|
|
|
|
uint8_t imcTable2[] = {
|
|
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
|
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
|
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
|
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
|
0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05,
|
|
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06,
|
|
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
|
|
0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
|
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07
|
|
};
|
|
|
|
uint8_t imcOtherTable1[] = {
|
|
0xff, 0x04, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00
|
|
};
|
|
uint8_t imcOtherTable2[] = {
|
|
0xff, 0xff, 0x02, 0x06, 0xff, 0xff, 0x02, 0x06
|
|
};
|
|
uint8_t imcOtherTable3[] = {
|
|
0xff, 0xff, 0xff, 0xff, 0x01, 0x02, 0x04, 0x06,
|
|
0xff, 0xff, 0xff, 0xff, 0x01, 0x02, 0x04, 0x06
|
|
};
|
|
uint8_t imcOtherTable4[] = {
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0x01, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0x01, 0x01, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06
|
|
};
|
|
uint8_t imcOtherTable5[] = {
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02,
|
|
0x02, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02,
|
|
0x02, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06
|
|
};
|
|
uint8_t imcOtherTable6[] = {
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
|
0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
|
0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
|
0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
|
0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
|
|
0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06
|
|
};
|
|
uint8_t *offsets[] = {
|
|
NULL, NULL, imcOtherTable1, imcOtherTable2, imcOtherTable3,
|
|
imcOtherTable4, imcOtherTable5, imcOtherTable6
|
|
};
|
|
|
|
uint16_t destTable[5786];
|
|
uint8_t sBytes[4];
|
|
uint16_t sWords[4];
|
|
int decLength, currTablePos, entrySize, decsToDo, tableEntry,
|
|
sBytesPos, destPos_sWordsPos, destPos, outputWord,
|
|
decsLeft, bytesToDec, var40, currTableVal, destOffs;
|
|
char *sourceBuffer;
|
|
unsigned char *sourcePos;
|
|
uint16_t *sWordsPos;
|
|
|
|
void initVima() {
|
|
int destTableStartPos, incer;
|
|
for (destTableStartPos = 0, incer = 0; destTableStartPos < 64;
|
|
destTableStartPos++, incer++) {
|
|
unsigned int destTablePos, imcTable1Pos;
|
|
for (imcTable1Pos = 0, destTablePos = destTableStartPos;
|
|
imcTable1Pos < sizeof(imcTable1) / sizeof(imcTable1[0]);
|
|
imcTable1Pos++, destTablePos += 64) {
|
|
int put = 0, count, tableValue;
|
|
for (count = 32, tableValue = imcTable1[imcTable1Pos]; count != 0;
|
|
count >>= 1, tableValue >>= 1) {
|
|
if ((incer & count) != 0)
|
|
put += tableValue;
|
|
}
|
|
destTable[destTablePos] = put;
|
|
}
|
|
}
|
|
}
|
|
|
|
void decompressVima_asm() {
|
|
asm("\tpush %esp\n"
|
|
"\tpush %ebp\n"
|
|
"\tpush %ebx\n"
|
|
"\tpush %esi\n"
|
|
"\tpush %edi\n"
|
|
"\n"
|
|
"\tmov sourceBuffer,%ecx\n"
|
|
"\tmov $1,%esi\n"
|
|
"\tmov (%ecx),%al\n"
|
|
"\tinc %ecx\n"
|
|
"\ttest %al,%al\n"
|
|
"\tmov %al,sBytes\n"
|
|
"\tjge .readWords\n"
|
|
"\tnot %al\n"
|
|
"\tmov %al,sBytes\n"
|
|
"\tmov $2,%esi\n"
|
|
"\n"
|
|
".readWords:\n"
|
|
"\tmov (%ecx),%ax\n"
|
|
"\txor %edx,%edx\n"
|
|
"\tmov %al,%dh\n"
|
|
"\tadd $2,%ecx\n"
|
|
"\tmov %ah,%dl\n"
|
|
"\tcmp $1,%esi\n"
|
|
"\tmov %dx,sWords\n"
|
|
"\tjbe .oneWord\n"
|
|
"\tmov (%ecx),%al\n"
|
|
"\tinc %ecx\n"
|
|
"\tmov %al,sBytes+1\n"
|
|
"\txor %edx,%edx\n"
|
|
"\tmov (%ecx),%ax\n"
|
|
"\tadd $2,%ecx\n"
|
|
"\tmov %al,%dh\n"
|
|
"\tmov %ah,%dl\n"
|
|
"\tmov %dx,sWords+2\n"
|
|
"\n"
|
|
".oneWord:\n"
|
|
"\tmov decLength,%eax\n"
|
|
"\tmovl $1,currTablePos\n"
|
|
"\tmov %esi,entrySize\n"
|
|
"\tadd %esi,%esi\n"
|
|
"\txor %edx,%edx\n"
|
|
"\tdiv %esi\n"
|
|
"\tmov %eax,decsToDo\n"
|
|
"\tmov %ecx,sourcePos\n"
|
|
"\n"
|
|
"\txor %ebx,%ebx\n"
|
|
"\n"
|
|
"\tmov %eax,currTablePos\n"
|
|
"\txor %edi,%edi\n"
|
|
"\tcmp %edi,%eax\n"
|
|
"\tjnz .label1\n"
|
|
"\tmovb $0,sBytes+1\n"
|
|
"\tmovb $0,sBytes\n"
|
|
"\tmov %di,sWords+2\n"
|
|
"\tmov %di,sWords\n"
|
|
"\n"
|
|
".label1:\n"
|
|
"\tmov sourcePos,%esi\n"
|
|
"\tmov entrySize,%edx\n"
|
|
"\txor %ecx,%ecx\n"
|
|
"\tmov (%esi),%ch\n"
|
|
"\tlea 1(%esi),%eax\n"
|
|
"\txor %esi,%esi\n"
|
|
"\tmov (%eax),%cl\n"
|
|
"\tinc %eax\n"
|
|
"\tcmp %edi,%edx\n"
|
|
"\tmov %ecx,tableEntry\n"
|
|
"\tmov %eax,sourcePos\n"
|
|
"\tmov %esi,sBytesPos\n"
|
|
"\tjbe .exitMainDec\n"
|
|
"\tmov destOffs,%edi\n"
|
|
"\tlea sWords,%eax\n"
|
|
"\tsub %eax,%edi\n"
|
|
"\tmov %eax,sWordsPos\n"
|
|
"\tmov %edi,destPos_sWordsPos\n"
|
|
"\n"
|
|
".nextByte:\n"
|
|
"\tlea (%edi,%eax,1),%ecx\n"
|
|
"\tmov %ecx,destPos\n"
|
|
"\tmovsbl sBytes(%esi),%ecx\n"
|
|
"\tmov %ecx,currTablePos\n"
|
|
"\tmovswl (%eax),%ecx\n"
|
|
"\tmov %ecx,outputWord\n"
|
|
"\tmov decsToDo,%ecx\n"
|
|
"\ttest %ecx,%ecx\n"
|
|
"\tjz .done\n"
|
|
"\tadd %edx,%edx\n"
|
|
"\tmov %ecx,decsLeft\n"
|
|
"\tmov %edx,bytesToDec\n"
|
|
"\n"
|
|
".nextDec:\n"
|
|
"\tmov currTablePos,%eax\n"
|
|
"\tmov $1,%edx\n"
|
|
"\tmov imcTable2(%eax),%cl\n"
|
|
"\tmov %cl,currTableVal\n"
|
|
"\tmov currTableVal,%esi\n"
|
|
"\tand $0xff,%esi\n"
|
|
"\tadd %esi,%ebx\n"
|
|
"\tlea -1(%esi),%ecx\n"
|
|
"\tmov %ebx,destOffs\n"
|
|
"\tshl %cl,%edx\n"
|
|
"\tmov $0x10,%cl\n"
|
|
"\tsub %bl,%cl\n"
|
|
"\tmov %dl,%al\n"
|
|
"\tdec %al\n"
|
|
"\tmov %al,var40\n"
|
|
"\tmov tableEntry,%eax\n"
|
|
"\tmov var40,%edi\n"
|
|
"\tand $0xffff,%eax\n"
|
|
"\tshr %cl,%eax\n"
|
|
"\tand $0xff,%edi\n"
|
|
"\tmov %edx,%ecx\n"
|
|
"\tor %edi,%ecx\n"
|
|
"\tand %ecx,%eax\n"
|
|
"\tcmp $7,%ebx\n"
|
|
"\tjle .label2\n"
|
|
"\tmov sourcePos,%ebx\n"
|
|
"\txor %ecx,%ecx\n"
|
|
"\tmov tableEntry,%ch\n"
|
|
"\tmovzbw (%ebx),%bx\n"
|
|
"\tor %ebx,%ecx\n"
|
|
"\tmov sourcePos,%ebx\n"
|
|
"\tinc %ebx\n"
|
|
"\tmov %ecx,tableEntry\n"
|
|
"\tmov %ebx,sourcePos\n"
|
|
"\tmov destOffs,%ebx\n"
|
|
"\tsub $8,%ebx\n"
|
|
"\tmov %ebx,destOffs\n"
|
|
"\tjmp .label3\n"
|
|
"\n"
|
|
".label2:\n"
|
|
"\tmov tableEntry,%ecx\n"
|
|
"\n"
|
|
".label3:\n"
|
|
"\ttest %edx,%eax\n"
|
|
"\tjz .clearEDX\n"
|
|
"\txor %edx,%eax\n"
|
|
"\tjmp .noClear\n"
|
|
"\n"
|
|
".clearEDX:\n"
|
|
"\txor %edx,%edx\n"
|
|
"\n"
|
|
".noClear:\n"
|
|
"\tcmp %edi,%eax\n"
|
|
"\tjnz .label4\n"
|
|
"\tmov %ecx,%edx\n"
|
|
"\tmov %ebx,%ecx\n"
|
|
"\tshl %cl,%edx\n"
|
|
"\tmov sourcePos,%ecx\n"
|
|
"\tmovzbw (%ecx),%di\n"
|
|
"\tpush %ecx\n"
|
|
"\tmovswl %dx,%ecx\n"
|
|
"\txor %edx,%edx\n"
|
|
"\tand $0xffffff00,%ecx\n"
|
|
"\tmov %ecx,outputWord\n"
|
|
"\tpop %ecx\n"
|
|
"\tmov tableEntry,%dh\n"
|
|
"\tor %edi,%edx\n"
|
|
"\tinc %ecx\n"
|
|
"\tmov %ecx,sourcePos\n"
|
|
"\tmov $8,%cx\n"
|
|
"\tsub %bx,%cx\n"
|
|
"\tmov %edx,%edi\n"
|
|
"\tshr %cl,%di\n"
|
|
"\txor %ecx,%ecx\n"
|
|
"\tmov destOffs,%ebx\n"
|
|
"\tmov %dl,%ch\n"
|
|
"\tmov %ecx,%edx\n"
|
|
"\tmov sourcePos,%ecx\n"
|
|
"\tand $0xff,%edi\n"
|
|
"\tpush %ecx\n"
|
|
"\tmov outputWord,%ecx\n"
|
|
"\tor %edi,%ecx\n"
|
|
"\tmov %ecx,outputWord\n"
|
|
"\tpop %ecx\n"
|
|
"\tmovzbw (%ecx),%di\n"
|
|
"\n"
|
|
"\tor %edi,%edx\n"
|
|
"\tinc %ecx\n"
|
|
"\tmov %edx,tableEntry\n"
|
|
"\tmov %ecx,sourcePos\n"
|
|
"\tjmp .writeDec\n"
|
|
"\n"
|
|
".label4:\n"
|
|
"\tmov $7,%ecx\n"
|
|
"\tmov %eax,%edi\n"
|
|
"\tsub %esi,%ecx\n"
|
|
"\tshl %cl,%edi\n"
|
|
"\tmov currTablePos,%ecx\n"
|
|
"\tshl $6,%ecx\n"
|
|
"\tor %ecx,%edi\n"
|
|
"\txor %ecx,%ecx\n"
|
|
"\ttest %eax,%eax\n"
|
|
"\tmov destTable(,%edi,2),%cx\n"
|
|
"\tmov %ecx,destOffs\n"
|
|
"\tjz .label5\n"
|
|
"\tmov currTablePos,%edi\n"
|
|
"\txor %ecx,%ecx\n"
|
|
"\tmov imcTable1(,%edi,2),%cx\n"
|
|
"\tmov %ecx,%edi\n"
|
|
"\tlea -1(%esi),%ecx\n"
|
|
"\tshr %cl,%edi\n"
|
|
"\tmov destOffs,%ecx\n"
|
|
"\tadd %edi,%ecx\n"
|
|
"\n"
|
|
".label5:\n"
|
|
"\ttest %edx,%edx\n"
|
|
"\tjz .label6\n"
|
|
"\tneg %ecx\n"
|
|
"\n"
|
|
".label6:\n"
|
|
"\tmov outputWord,%edx\n"
|
|
"\tadd %ecx,%edx\n"
|
|
"\tcmp $-0x8000,%edx\n"
|
|
"\tjge .label7\n"
|
|
"\tmov $-0x8000,%edx\n"
|
|
"\tmov %edx,outputWord\n"
|
|
"\tjmp .writeDec\n"
|
|
"\n"
|
|
".label7:\n"
|
|
"\tcmp $0x7fff,%edx\n"
|
|
"\tmov %edx,outputWord\n"
|
|
"\tjle .writeDec\n"
|
|
"\tmov $0x7fff,%edx\n"
|
|
"\tmov %edx,outputWord\n"
|
|
"\n"
|
|
".writeDec:\n"
|
|
"\tmov destPos,%ecx\n"
|
|
"\tmov bytesToDec,%edx\n"
|
|
"\tpush %eax\n"
|
|
"\tmov outputWord,%eax\n"
|
|
"\tmov %ax,(%ecx)\n"
|
|
"\tadd %edx,%ecx\n"
|
|
"\tmov offsets(,%esi,4),%edx\n"
|
|
"\tmov %ecx,destPos\n"
|
|
"\tmov currTablePos,%ecx\n"
|
|
"\tpop %eax\n"
|
|
"\tmovsbl (%edx,%eax,1),%eax\n"
|
|
"\tadd %eax,%ecx\n"
|
|
"\tmov %ecx,currTablePos\n"
|
|
"\tjns .label8\n"
|
|
"\tmovl $0,currTablePos\n"
|
|
"\tjmp .done\n"
|
|
"\n"
|
|
".label8:\n"
|
|
"\tmov currTablePos,%ecx\n"
|
|
"\tmov $0x58,%eax\n"
|
|
"\tcmp %eax,%ecx\n"
|
|
"\tjle .done\n"
|
|
"\tmov %eax,currTablePos\n"
|
|
"\n"
|
|
".done:\n"
|
|
"\tmov decsLeft,%eax\n"
|
|
"\tdec %eax\n"
|
|
"\tmov %eax,decsLeft\n"
|
|
"\tjnz .nextDec\n"
|
|
"\tmov entrySize,%edx\n"
|
|
"\tmov sBytesPos,%esi\n"
|
|
"\tmov sWordsPos,%eax\n"
|
|
"\tmov destPos_sWordsPos,%edi\n"
|
|
"\tmov currTablePos,%cl\n"
|
|
"\tadd $2,%eax\n"
|
|
"\tmov %cl,sBytes(%esi)\n"
|
|
"\tpush %ebx\n"
|
|
"\tmov outputWord,%ebx\n"
|
|
"\tmov %bx,-2(%eax)\n"
|
|
"\tpop %ebx\n"
|
|
"\tinc %esi\n"
|
|
"\tmov %eax,sWordsPos\n"
|
|
"\tcmp %edx,%esi\n"
|
|
"\tmov %esi,sBytesPos\n"
|
|
"\tjb .nextByte\n"
|
|
"\n"
|
|
".exitMainDec:\n"
|
|
"\tpop %edi\n"
|
|
"\tpop %esi\n"
|
|
"\tpop %ebx\n"
|
|
"\tpop %ebp\n"
|
|
"\tpop %esp\n");
|
|
}
|
|
|
|
int eax, bit;
|
|
|
|
void decompressVima() {
|
|
sourcePos = (unsigned char *) sourceBuffer; // sourcePos in ecx
|
|
entrySize = 1; // entrySize in esi
|
|
sBytes[0] = *sourcePos;
|
|
sourcePos++;
|
|
if (sBytes[0] & 0x80) {
|
|
sBytes[0] = ~sBytes[0];
|
|
entrySize = 2;
|
|
}
|
|
sWords[0] = (sourcePos[0] << 8) | sourcePos[1];
|
|
sourcePos += 2;
|
|
if (entrySize > 1) {
|
|
sBytes[1] = *sourcePos;
|
|
sourcePos++;
|
|
sWords[1] = (sourcePos[0] << 8) | sourcePos[1];
|
|
sourcePos += 2;
|
|
}
|
|
currTablePos = 1;
|
|
decsToDo = decLength / (2 * entrySize);
|
|
if (currTablePos == 0) {
|
|
sBytes[1] = 0;
|
|
sBytes[0] = 0;
|
|
sWords[1] = 0;
|
|
sWords[0] = 0;
|
|
}
|
|
tableEntry = (sourcePos[0] << 8) | sourcePos[1];
|
|
sourcePos += 2;
|
|
sBytesPos = 0;
|
|
if (entrySize <= 0)
|
|
goto exitMainDec;
|
|
sWordsPos = sWords;
|
|
destPos_sWordsPos = destOffs - (int) sWords;
|
|
destOffs = 0; // destOffs in ebx
|
|
nextByte:
|
|
// edi = destPos_sWordsPos, eax = sWordsPos, esi = sBytesPos
|
|
destPos = destPos_sWordsPos + (int) sWordsPos;
|
|
currTablePos = (signed char) sBytes[sBytesPos];
|
|
outputWord = (signed short) *sWordsPos;
|
|
if (decsToDo == 0)
|
|
goto done;
|
|
decsLeft = decsToDo;
|
|
bytesToDec = entrySize * 2;
|
|
nextDec:
|
|
currTableVal = imcTable2[currTablePos];
|
|
destOffs += currTableVal & 0xff;
|
|
bit = 1 << (currTableVal - 1);
|
|
var40 = bit - 1;
|
|
eax = (tableEntry & 0xffff) >> (16 - destOffs);
|
|
eax &= (bit | var40);
|
|
if (destOffs > 7) {
|
|
tableEntry = ((tableEntry & 0xff) << 8) | *sourcePos;
|
|
sourcePos++;
|
|
destOffs -= 8;
|
|
}
|
|
if (eax & bit)
|
|
eax ^= bit;
|
|
else
|
|
bit = 0;
|
|
if (eax == var40) {
|
|
outputWord = ((signed short) (tableEntry << destOffs) & 0xffffff00);
|
|
tableEntry = ((tableEntry & 0xff) << 8) | *sourcePos;
|
|
sourcePos++;
|
|
outputWord |= ((tableEntry >> (8 - destOffs)) & 0xff);
|
|
tableEntry = ((tableEntry & 0xff) << 8) | *sourcePos;
|
|
sourcePos++;
|
|
}
|
|
else {
|
|
int index = (eax << (7 - currTableVal)) | (currTablePos << 6);
|
|
int delta;
|
|
delta = destTable[index];
|
|
if (eax != 0)
|
|
delta += (imcTable1[currTablePos] >> (currTableVal - 1));
|
|
if (bit != 0)
|
|
delta = -delta;
|
|
outputWord += delta;
|
|
if (outputWord < -0x8000)
|
|
outputWord = -0x8000;
|
|
else if (outputWord > 0x7fff)
|
|
outputWord = 0x7fff;
|
|
}
|
|
*((uint16_t *) destPos) = outputWord;
|
|
destPos += bytesToDec;
|
|
currTablePos += (signed char) offsets[currTableVal][eax];
|
|
if (currTablePos < 0)
|
|
currTablePos = 0;
|
|
else if (currTablePos > 88)
|
|
currTablePos = 88;
|
|
done:
|
|
decsLeft--;
|
|
if (decsLeft != 0)
|
|
goto nextDec;
|
|
sBytes[sBytesPos] = currTablePos;
|
|
*sWordsPos = outputWord;
|
|
sWordsPos++;
|
|
sBytesPos++;
|
|
if (sBytesPos < entrySize)
|
|
goto nextByte;
|
|
exitMainDec:
|
|
return;
|
|
}
|
|
|
|
int main(int /* argc */, char *argv[]) {
|
|
initVima();
|
|
|
|
FILE *f = fopen(argv[1], "rb");
|
|
if (f == NULL) {
|
|
perror(argv[1]);
|
|
return 1;
|
|
}
|
|
|
|
char magic[4];
|
|
fread(magic, 4, 1, f);
|
|
if (memcmp(magic, "MCMP", 4) != 0) {
|
|
fprintf(stderr, "Not a valid file\n");
|
|
return 1;
|
|
}
|
|
uint16_t numBlocks = getc(f) << 8;
|
|
numBlocks |= getc(f);
|
|
char *blocks = new char[9 * numBlocks];
|
|
fread(blocks, 9, numBlocks, f);
|
|
|
|
uint16_t numCodecs = getc(f) << 8;
|
|
numCodecs |= getc(f);
|
|
numCodecs /= 5;
|
|
char *codecs = new char[5 * numCodecs];
|
|
fread(codecs, 5, numCodecs, f);
|
|
|
|
for (int i = 0; i < numBlocks; i++) {
|
|
int codec = blocks[9 * i];
|
|
int uncompSize = get_be_uint32(blocks + 9 * i + 1);
|
|
int compSize = get_be_uint32(blocks + 9 * i + 5);
|
|
|
|
sourceBuffer = new char[compSize];
|
|
fread(sourceBuffer, 1, compSize, f);
|
|
|
|
if (strcmp(codecs + 5 * codec, "NULL") == 0)
|
|
fwrite(sourceBuffer, 1, uncompSize, stdout);
|
|
else if (strcmp(codecs + 5 * codec, "VIMA") == 0) {
|
|
decLength = uncompSize;
|
|
char *buffer = new char[uncompSize];
|
|
destOffs = (int) buffer;
|
|
decompressVima();
|
|
fwrite(buffer, 1, uncompSize, stdout);
|
|
delete[] buffer;
|
|
}
|
|
else {
|
|
fprintf(stderr, "Unrecognized codec %s\n", codecs + 5 * codec);
|
|
return 1;
|
|
}
|
|
delete[] sourceBuffer;
|
|
}
|
|
return 0;
|
|
}
|