/* ScummVM - Scumm Interpreter * Copyright (C) 2001 Ludvig Strigeus * Copyright (C) 2001-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * $URL$ * $Id$ * */ // Conversion routines for planar graphics in Amiga verisions #include "common/stdafx.h" #include "agos/agos.h" #include "agos/intern.h" namespace AGOS { byte *buffer; byte *bufptr; byte *bufferout; byte *bufptrout; uint32 bufoutend; byte *clipptr; byte *clipoutptr; int clipnumber; static void uncompressplane(byte *plane, byte *outptr, uint16 length) { debug(10, "uncompressplane: length %d", length); char x; byte y, z; while (length) { x = *plane++; if (x >= 0) { x += 1; y = *plane++; z = *plane++; while (x) { *outptr++ = y; *outptr++ = z; length--; if (length == 0) break; x--; } } else { while (x) { *outptr++ = *plane++; *outptr++ = *plane++; length--; if (length == 0) break; x++; } } } } static void convertcompressedclip(uint16 height, uint16 width) { debug(10, "convertcompressedclip: height %d width %d", height, width); byte *plane0; byte *plane1; byte *plane2; byte *plane3; byte *uncbuffer; byte *uncptr0; byte *uncptr1; byte *uncptr2; byte *uncptr3; byte *uncbfrout; byte *uncbfroutptr; uint16 length, i, j, k, word1, word2, word3, word4, cliplength; byte outbyte, outbyte1, x, y; char n; uncbuffer = (byte *)malloc(height * width * 4); uncbfrout = (byte *)malloc(height * width * 4); length = width / 16; length *= height; plane0 = READ_BE_UINT16(clipptr) + READ_BE_UINT16(clipptr + 2) + clipptr; clipptr += 4; plane0 += 4; plane1 = READ_BE_UINT16(clipptr) + READ_BE_UINT16(clipptr + 2) + clipptr; clipptr += 4; plane1 += 4; plane2 = READ_BE_UINT16(clipptr) + READ_BE_UINT16(clipptr + 2) + clipptr; clipptr += 4; plane2 += 4; plane3 = READ_BE_UINT16(clipptr) + READ_BE_UINT16(clipptr + 2) + clipptr; clipptr += 4; plane3 += 4; plane0 -= 4; plane1 -= 8; plane2 -= 12; plane3 -= 16; uncptr0 = uncbuffer; uncptr1 = uncptr0+(length*2); uncptr2 = uncptr1+(length*2); uncptr3 = uncptr2+(length*2); uncompressplane(plane0, uncptr0, length); uncompressplane(plane1, uncptr1, length); uncompressplane(plane2, uncptr2, length); uncompressplane(plane3, uncptr3, length); uncbfroutptr = uncbfrout; for (i = 0; i < length; i++) { word1=READ_BE_UINT16(uncptr0); uncptr0 += 2; word2=READ_BE_UINT16(uncptr1); uncptr1 += 2; word3=READ_BE_UINT16(uncptr2); uncptr2 += 2; word4=READ_BE_UINT16(uncptr3); uncptr3 += 2; for (j = 0; j < 8; j++) { outbyte = ((word1 / 32768) + ((word2 / 32768) * 2) + ((word3 / 32768) * 4) + ((word4 / 32768) * 8)); word1 <<= 1; word2 <<= 1; word3 <<= 1; word4 <<= 1; outbyte1 = ((word1 / 32768) + ((word2 / 32768) * 2) + ((word3 / 32768) * 4) + ((word4 / 32768) * 8)); word1 <<= 1; word2 <<= 1; word3 <<= 1; word4 <<= 1; *uncbfroutptr++ = (outbyte * 16 + outbyte1); } } uncptr0 = uncbuffer; uncptr1 = uncbfrout; uncptr2 = uncbfrout; uncptr3 = uncbfrout; for (i = 0; i < (width / 16); i++) { for (k = 0; k < 8; k++) { for (j = 0; j < height; j++) { *uncptr0++ = *uncptr1; uncptr1 += 8; } uncptr2++; uncptr1 = uncptr2; } uncptr3 += (height * 8); uncptr2 = uncptr3; uncptr1 = uncptr2; } length *= 8; cliplength = 0; while(1) { if (length == 1) { *clipoutptr++ = 0xFF; bufoutend++; *clipoutptr++ = *uncbuffer; bufoutend++; cliplength += 2; break; } x = *uncbuffer++; y = *uncbuffer++; length -= 2; if (x == y) { n = 1; y = *uncbuffer++; if (length == 0) { *clipoutptr++ = n; bufoutend++; *clipoutptr++ = x; bufoutend++; cliplength += 2; break; } length--; while (x == y) { n++; y = *uncbuffer++; if (length == 0) break; length--; if(n == 127) break; } *clipoutptr++ = n; bufoutend++; *clipoutptr++ = x; bufoutend++; cliplength += 2; uncbuffer--; if (length == 0) break; length++; } else { n =- 1; uncptr0 = clipoutptr; clipoutptr++; bufoutend++; *clipoutptr++ = x; bufoutend++; cliplength += 2; x = y; y = *uncbuffer++; if (length == 0) { *uncptr0 = n; break; } length--; while (x != y) { if (n == -127) break; n--; *clipoutptr++ = x; bufoutend++; cliplength++; x = y; y = *uncbuffer++; if (length == 0) break; length--; } *uncptr0 = n; if (length == 0) break; uncbuffer -= 2; length += 2; } } if (cliplength > (height * width / 2)) warning("Negative compression. Clip %d. %d bytes bigger.",clipnumber,(cliplength-(height*width/2))); //free(uncbuffer); //free(uncbfrout); } static void convertclip(uint32 offset, uint16 height, uint16 width) { debug(10, "convertclip: height %d width %d", height, width); uint32 length, i, j; uint16 word1, word2, word3, word4; byte outbyte, outbyte1; clipptr = offset + buffer; clipoutptr = bufoutend + bufferout; WRITE_BE_UINT32(bufptrout, bufoutend); bufptrout += 4; WRITE_BE_UINT16(bufptrout, height); bufptrout += 2; WRITE_BE_UINT16(bufptrout, width); bufptrout += 2; if (height > 32000) { convertcompressedclip((uint16)(height - 32768), width); } else { width /= 16; length = height * width; for (i = 0; i < length; i++) { word1 = READ_BE_UINT16(clipptr); clipptr += 2; word2 = READ_BE_UINT16(clipptr); clipptr += 2; word3 = READ_BE_UINT16(clipptr); clipptr += 2; word4 = READ_BE_UINT16(clipptr); clipptr += 2; for (j = 0; j < 8; j++) { outbyte = ((word1 / 32768) + ((word2 / 32768) * 2) + ((word3 / 32768) * 4) + ((word4 / 32768) * 8)); word1 <<= 1; word2 <<= 1; word3 <<= 1; word4 <<= 1; outbyte1 = ((word1 / 32768) + ((word2 / 32768) * 2) + ((word3 / 32768) * 4) + ((word4 / 32768) * 8)); word1 <<= 1; word2 <<= 1; word3 <<= 1; word4 <<= 1; *clipoutptr++ = (outbyte * 16 + outbyte1); bufoutend++; } } } } void AGOSEngine::convertAmiga(byte *srcBuf, int32 fileSize) { // TODO Better detection of full screen images if ((getGameType() == GType_WW && fileSize == 178624) || fileSize == 64800) { byte *dstBuf = allocBlock (fileSize); memcpy(dstBuf, srcBuf, fileSize); return; } uint32 clipoffset, outlength; uint16 clipwidth, clipheight; byte *clipsend; debug(10, "convertAmiga: fizeSize %d", fileSize); buffer = (byte *)malloc((int32)fileSize); memcpy(buffer, srcBuf, fileSize); bufptr = buffer; bufferout = (byte *)malloc((int32)(fileSize * 2)); bufptr = buffer; bufptrout = bufferout; clipnumber = 0; while(1) { clipoffset = READ_BE_UINT32(bufptr); bufptr += 4; clipheight = READ_BE_UINT16(bufptr); bufptr += 2; clipwidth = READ_BE_UINT16(bufptr); bufptr += 2; if (clipoffset != 0) break; WRITE_BE_UINT32(bufptrout, 0); bufptrout += 4; WRITE_BE_UINT32(bufptrout, 0); bufptrout += 4; clipnumber++; } clipsend = buffer + clipoffset; bufoutend = clipoffset; while (bufptr <= clipsend) { if (clipoffset != 0) { convertclip(clipoffset, clipheight, clipwidth); } else { WRITE_BE_UINT32(bufptrout, 0); bufptrout += 4; WRITE_BE_UINT32(bufptrout, 0); bufptrout += 4; } clipoffset = READ_BE_UINT32(bufptr); bufptr += 4; clipheight = READ_BE_UINT16(bufptr); bufptr += 2; clipwidth = READ_BE_UINT16(bufptr); bufptr += 2; clipnumber++; } outlength = bufoutend; debug(10, "convertAmiga: outlength %d",outlength); byte *dstBuf = allocBlock (outlength); memcpy(dstBuf, bufferout, outlength); free(buffer); free(bufferout); } } // End of namespace AGOS