mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-13 21:31:53 +00:00
9c0f422d0b
svn-id: r16504
261 lines
6.1 KiB
C++
261 lines
6.1 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2004-2005 The ScummVM project
|
|
*
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* $Header$
|
|
*
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "codecs.h"
|
|
|
|
/*****************************************************************************
|
|
* decode.c - Decoding routines for format80, format40, format20
|
|
* and format3 type graphics
|
|
* Author: Olaf van der spek
|
|
* Modified for FreeCNC by Kareem Dana
|
|
* Modified for Kyra by Jack Burton
|
|
* Format3 decoding added by Jack Burton
|
|
* Modified for ScummVM by Johannes Schickel
|
|
****************************************************************************/
|
|
|
|
namespace Kyra {
|
|
|
|
/** decompress format 80 compressed data.
|
|
* @param image_in compressed data.
|
|
* @param image_out pointer to output uncompressed data.
|
|
* @returns size of uncompressed data.
|
|
*/
|
|
int Compression::decode80(const uint8* image_in, uint8* image_out) {
|
|
/*
|
|
0 copy 0cccpppp p
|
|
1 copy 10cccccc
|
|
2 copy 11cccccc p p
|
|
3 fill 11111110 c c v
|
|
4 copy 11111111 c c p p
|
|
*/
|
|
|
|
const uint8* copyp;
|
|
const uint8* readp = image_in;
|
|
uint8* writep = image_out;
|
|
uint16 code;
|
|
uint16 count;
|
|
|
|
while (1) {
|
|
code = *readp++;
|
|
if (~code & 0x80) {
|
|
//bit 7 = 0
|
|
//command 0 (0cccpppp p): copy
|
|
count = (code >> 4) + 3;
|
|
copyp = writep - (((code & 0xf) << 8) + *readp++);
|
|
while (count--)
|
|
*writep++ = *copyp++;
|
|
} else {
|
|
//bit 7 = 1
|
|
count = code & 0x3f;
|
|
if (~code & 0x40) {
|
|
//bit 6 = 0
|
|
if (!count)
|
|
//end of image
|
|
break;
|
|
//command 1 (10cccccc): copy
|
|
while (count--)
|
|
*writep++ = *readp++;
|
|
} else {
|
|
//bit 6 = 1
|
|
if (count < 0x3e) {
|
|
//command 2 (11cccccc p p): copy
|
|
count += 3;
|
|
|
|
copyp = (const uint8*)&image_out[READ_LE_UINT16(readp)];
|
|
readp += 2;
|
|
|
|
// FIXME: Using memmove sometimes segfaults
|
|
// (reproducably for Ender), which suggests something Bad here
|
|
//memmove(writep, copyp, count);
|
|
//writep += count;
|
|
//copyp += count;
|
|
while (count--)
|
|
*writep++ = *copyp++;
|
|
} else if (count == 0x3e) {
|
|
//command 3 (11111110 c c v): fill
|
|
|
|
count = READ_LE_UINT16(readp);
|
|
readp += 2;
|
|
code = *readp++;
|
|
memset(writep, code, count);
|
|
writep += count;
|
|
} else {
|
|
//command 4 (copy 11111111 c c p p): copy
|
|
|
|
count = READ_LE_UINT16(readp);
|
|
readp += 2;
|
|
|
|
copyp = (const uint8*)&image_out[READ_LE_UINT16(readp)];
|
|
readp += 2;
|
|
while (count--)
|
|
*writep++ = *copyp++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (writep - image_out);
|
|
}
|
|
|
|
/** decompress format 40 compressed data.
|
|
* @param image_in compressed data.
|
|
* @param image_out pointer to put uncompressed data in.
|
|
* @returns size of uncompressed data.
|
|
*/
|
|
int Compression::decode40(const uint8* image_in, uint8* image_out) {
|
|
/*
|
|
0 fill 00000000 c v
|
|
1 copy 0ccccccc
|
|
2 skip 10000000 c 0ccccccc
|
|
3 copy 10000000 c 10cccccc
|
|
4 fill 10000000 c 11cccccc v
|
|
5 skip 1ccccccc
|
|
*/
|
|
|
|
const uint8* readp = image_in;
|
|
uint8* writep = image_out;
|
|
uint16 code;
|
|
uint16 count;
|
|
|
|
while (1) {
|
|
code = *readp++;
|
|
if (~code & 0x80) {
|
|
//bit 7 = 0
|
|
if (!code) {
|
|
//command 0 (00000000 c v): fill
|
|
count = *readp++;
|
|
code = *readp++;
|
|
while (count--)
|
|
*writep++ ^= code;
|
|
} else {
|
|
//command 1 (0ccccccc): copy
|
|
count = code;
|
|
while (count--)
|
|
*writep++ ^= *readp++;
|
|
}
|
|
|
|
} else {
|
|
//bit 7 = 1
|
|
if (!(count = code & 0x7f)) {
|
|
|
|
count = READ_LE_UINT16(readp);
|
|
readp += 2;
|
|
code = count >> 8;
|
|
if (~code & 0x80) {
|
|
//bit 7 = 0
|
|
//command 2 (10000000 c 0ccccccc): skip
|
|
if (!count)
|
|
// end of image
|
|
break;
|
|
writep += count;
|
|
} else {
|
|
//bit 7 = 1
|
|
count &= 0x3fff;
|
|
if (~code & 0x40) {
|
|
//bit 6 = 0
|
|
//command 3 (10000000 c 10cccccc): copy
|
|
while (count--)
|
|
*writep++ ^= *readp++;
|
|
} else {
|
|
//bit 6 = 1
|
|
//command 4 (10000000 c 11cccccc v): fill
|
|
code = *readp++;
|
|
while (count--)
|
|
*writep++ ^= code;
|
|
}
|
|
}
|
|
} else //command 5 (1ccccccc): skip
|
|
writep += count;
|
|
}
|
|
}
|
|
return (writep - image_out);
|
|
}
|
|
|
|
/** decompress format 3 compressed data.
|
|
* @param image_in compressed data.
|
|
* @param image_out pointer to put uncompressed data in.
|
|
* @param size of uncompressed image.
|
|
*/
|
|
int Compression::decode3(const uint8* image_in, uint8* image_out, int size) {
|
|
/* Untested on BIG-Endian machines */
|
|
|
|
/*
|
|
0 copy
|
|
1 fill
|
|
2 fill
|
|
*/
|
|
const uint8* readp = image_in;
|
|
uint8* writep = image_out;
|
|
int16 code;
|
|
int16 count;
|
|
|
|
do {
|
|
code = *const_cast<int8*>((const int8*)readp++);
|
|
if (code > 0) { // Copy
|
|
count = code ;
|
|
while (count--)
|
|
*writep++ = *readp++;
|
|
} else if (code == 0) { // Fill(1)
|
|
count = READ_BE_UINT16(readp);
|
|
|
|
readp += 2;
|
|
code = *readp++;
|
|
while (count--)
|
|
*writep++ = (uint8)code;
|
|
} else if (code < 0) { // Fill (2)
|
|
count = -code;
|
|
code = *readp++;
|
|
while (count--)
|
|
*writep++ = (uint8)code;
|
|
}
|
|
} while ((writep - image_out) < size);
|
|
|
|
//and, to be uniform to other decomp. functions...
|
|
return (writep - image_out);
|
|
}
|
|
|
|
/** decompress format 20 compressed data.
|
|
* @param s compressed data.
|
|
* @param d pointer to pu uncompressed data in.
|
|
* @param cb_s size of compressed data?
|
|
* @returns size of uncompressed data?
|
|
*/
|
|
int Compression::decode2(const uint8* s, uint8* d, int cb_s) {
|
|
const uint8* r = s;
|
|
const uint8* r_end = s + cb_s;
|
|
uint8* w = d;
|
|
while (r < r_end) {
|
|
int v = *r++;
|
|
if (v)
|
|
*w++ = v;
|
|
else {
|
|
v = *r++;
|
|
memset(w, 0, v);
|
|
w += v;
|
|
}
|
|
}
|
|
return w - d;
|
|
|
|
}
|
|
} // end of namespace Kyra
|
|
|