aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/tinsel/graphics.cpp75
1 files changed, 55 insertions, 20 deletions
diff --git a/engines/tinsel/graphics.cpp b/engines/tinsel/graphics.cpp
index 3682a2dcb3..71de8c0239 100644
--- a/engines/tinsel/graphics.cpp
+++ b/engines/tinsel/graphics.cpp
@@ -30,6 +30,7 @@
#include "tinsel/palette.h"
#include "tinsel/scene.h"
#include "tinsel/tinsel.h"
+#include "tinsel/scn.h"
namespace Tinsel {
@@ -46,10 +47,10 @@ extern uint8 transPalette[MAX_COLOURS];
/**
* PSX Block list unwinder.
- * Chunk type 0x3 in PSX version of Discworld 1 is compressed, thus we need to decompress
- * it before passing data to drawing functions
+ * Chunk type 0x0003 (CHUNK_CHARPTR) in PSX version of DW 1 & 2 is compressed (original code
+ * calls the compression PJCRLE), thus we need to decompress it before passing data to drawing functions
*/
-uint8* psxBlockListUnwinder(uint16 imageWidth, uint16 imageHeight, uint8 *srcIdx) {
+uint8* psxPJCRLEUnwinder(uint16 imageWidth, uint16 imageHeight, uint8 *srcIdx) {
uint32 remainingBlocks = 0;
uint16 compressionType = 0; // Kind of decompression to apply
@@ -71,14 +72,6 @@ uint8* psxBlockListUnwinder(uint16 imageWidth, uint16 imageHeight, uint8 *srcIdx
dstIdx = destinationBuffer;
remainingBlocks = (imageWidth * imageHeight) / 16;
- controlData = READ_LE_UINT16(srcIdx);
-
- // Get to index data
- if ( (controlData & 0xff) == 0x88) // These images go straight to compressed index data
- srcIdx += 2;
- else // In this case we have to skip psx CLUT before getting to data
- srcIdx += 32;
-
while (remainingBlocks) { // Repeat until all blocks are decompressed
if (!controlBits) {
controlData = READ_LE_UINT16(srcIdx);
@@ -223,7 +216,7 @@ static void t0WrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool apply
* Straight rendering with transparency support, PSX variant supporting also 4-BIT clut data
* TODO: finish supporting 4-bit data
*/
-static void PsxWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool applyClipping, bool fourBitClut, uint32 palStart) {
+static void PsxWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool applyClipping, bool fourBitClut, uint32 psxSkipBytes, uint32 palStart) {
// Set up the offset between destination blocks
int rightClip = applyClipping ? pObj->rightClip : 0;
Common::Rect boxBounds;
@@ -289,9 +282,9 @@ static void PsxWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool appl
// In case we have a 4-bit CLUT image, blocks are 2x4, then expanded into 4x4
const uint8 *p;
if (fourBitClut)
- p = (uint8 *)pObj->charBase + (indexVal << 3);
+ p = (uint8 *)pObj->charBase + psxSkipBytes + (indexVal << 3);
else
- p = (uint8 *)pObj->charBase + (indexVal << 4);
+ p = (uint8 *)pObj->charBase + psxSkipBytes + (indexVal << 4);
p += boxBounds.top * (fourBitClut ? sizeof(uint16) : sizeof(uint32));
for (int yp = boxBounds.top; yp <= boxBounds.bottom; ++yp, p += (fourBitClut ? sizeof(uint16) : sizeof(uint32))) {
@@ -752,7 +745,9 @@ void DrawObject(DRAWOBJECT *pObj) {
uint8 *srcPtr = NULL;
uint8 *destPtr;
- bool psxFourBitClut = false; // Used for PSX version, to check if image is in 4-bit CLUT mode
+ bool psxFourBitClut; // Used by Tinsel PSX, true if an image using a 4bit CLUT is rendered
+ bool psxRLEindex; // Used by Tinsel PSX, true if an image is using PJCRLE compressed indexes
+ uint32 psxSkipBytes; // Used by Tinsel PSX, number of bytes to skip before counting indexes for image tiles
if ((pObj->width <= 0) || (pObj->height <= 0))
// Empty image, so return immediately
@@ -770,11 +765,51 @@ void DrawObject(DRAWOBJECT *pObj) {
srcPtr = p + (pObj->hBits & OFFSETMASK);
pObj->charBase = (char *)p + READ_LE_UINT32(p + 0x10);
pObj->transOffset = READ_LE_UINT32(p + 0x14);
-
+
// Decompress block indexes for Discworld PSX
if (TinselV1PSX) {
- psxFourBitClut = (READ_LE_UINT16(srcPtr) != 0xCC88) ? true : false;
- srcPtr = psxBlockListUnwinder(pObj->width, pObj->height, srcPtr);
+ uint8 paletteType = *(srcPtr); // if 0x88 we are using an 8bit palette type, if 0x44 we are using a 4 bit PSX CLUT
+ uint8 indexType = *(srcPtr + 1); // if 0xCC indexes for this image are compressed with PCJRLE, if 0xDD indexes are not compressed
+
+ switch (paletteType) {
+ case 0x88: // Normal 8-bit palette
+ psxFourBitClut = false;
+ psxSkipBytes = 0;
+ switch (indexType) {
+ case 0xDD: // Normal uncompressed indexes
+ psxRLEindex = false;
+ srcPtr += sizeof(uint16); // Get to the beginning of index data
+ break;
+ case 0xCC: // PJCRLE compressed indexes
+ psxRLEindex = true;
+ srcPtr = psxPJCRLEUnwinder(pObj->width, pObj->height, srcPtr + sizeof(uint16));
+ break;
+ default:
+ error("Unknown PSX index type 0x%.2X", indexType);
+ break;
+ }
+ break;
+ case 0x44: // PSX 4-bit CLUT
+ psxFourBitClut = true;
+ psxSkipBytes = READ_LE_UINT32(p + sizeof(uint32) * 5) << 4; // Fetch number of bytes we have to skip
+ switch (indexType) {
+ case 0xDD: // Normal uncompressed indexes
+ psxRLEindex = false;
+ srcPtr += sizeof(uint16) * 17; // Skip image type and clut, and get to beginning of index data
+ break;
+ case 0xCC: // PJCRLE compressed indexes
+ psxRLEindex = true;
+ srcPtr = psxPJCRLEUnwinder(pObj->width, pObj->height, srcPtr + sizeof(uint16) * 17);
+ break;
+ default:
+ error("Unknown PSX index type 0x%.2X", indexType);
+ break;
+ }
+ break;
+ default:
+ error("Unknown PSX palette type 0x%.2X", paletteType);
+ break;
+ }
}
}
@@ -842,7 +877,7 @@ void DrawObject(DRAWOBJECT *pObj) {
case 0x08:
case 0x41:
case 0x48:
- PsxWrtNonZero(pObj, srcPtr, destPtr, typeId >= 0x40, psxFourBitClut, pObj->pPal->posInDAC);
+ PsxWrtNonZero(pObj, srcPtr, destPtr, typeId >= 0x40, psxFourBitClut, psxSkipBytes, pObj->pPal->posInDAC);
break;
case 0x04:
@@ -907,7 +942,7 @@ void DrawObject(DRAWOBJECT *pObj) {
// If we were using Discworld PSX, free the memory allocated
// for decompressed block indexes.
- if (TinselV1PSX)
+ if (TinselV1PSX && psxRLEindex)
free(srcPtr);
}