[Scummvm-git-logs] scummvm master -> 4f1676e38b5e5677ba7f647128a51002bbe40821

bluegr bluegr at gmail.com
Sat Sep 4 09:14:28 UTC 2021


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
4f1676e38b TINSEL: Initial work on the Saturn version of DW1


Commit: 4f1676e38b5e5677ba7f647128a51002bbe40821
    https://github.com/scummvm/scummvm/commit/4f1676e38b5e5677ba7f647128a51002bbe40821
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2021-09-04T12:13:18+03:00

Commit Message:
TINSEL: Initial work on the Saturn version of DW1

This version is using the same graphics format as the PSX version, with
differences in resource endianess, but features digital music with a
different track structure and has a different sound sample format

Pending issues:
- Font rendering is wrong - this is evident in the text and menus in
  the game title screen
- Cursor sprite and trails are wrong - can be seen in the menu of the
  game title screen
- Digital music is not supported yet - seems that a different track
  structure is used
- The sound sample format is different than the PC version - looks to
   be raw, but isn't
- The game crashes at the first room after watching Rincewind's waking
  up cutscene

Changed paths:
    engines/tinsel/drives.cpp
    engines/tinsel/drives.h
    engines/tinsel/graphics.cpp
    engines/tinsel/handle.cpp
    engines/tinsel/music.cpp
    engines/tinsel/scene.cpp
    engines/tinsel/sound.cpp
    engines/tinsel/strres.cpp
    engines/tinsel/tinsel.h


diff --git a/engines/tinsel/drives.cpp b/engines/tinsel/drives.cpp
index a497fda200..6bfa086496 100644
--- a/engines/tinsel/drives.cpp
+++ b/engines/tinsel/drives.cpp
@@ -157,7 +157,11 @@ bool GotoCD() {
 
 bool TinselFile::_warningShown = false;
 
-TinselFile::TinselFile() : ReadStreamEndian(TinselV1Mac) {
+TinselFile::TinselFile() : ReadStreamEndian(TinselV1Saturn) {
+	_stream = nullptr;
+}
+
+TinselFile::TinselFile(bool bigEndian) : ReadStreamEndian(bigEndian) {
 	_stream = nullptr;
 }
 
diff --git a/engines/tinsel/drives.h b/engines/tinsel/drives.h
index afedd0d529..e2ded64b54 100644
--- a/engines/tinsel/drives.h
+++ b/engines/tinsel/drives.h
@@ -62,7 +62,9 @@ private:
 	Common::SeekableReadStream *_stream;
 	bool openInternal(const Common::String &filename);
 public:
+	// This constructor is only used for _sampleStream inside sound.h
 	TinselFile();
+	TinselFile(bool bigEndian);
 	~TinselFile() override;
 	bool open(const Common::String &filename);
 	void close();
diff --git a/engines/tinsel/graphics.cpp b/engines/tinsel/graphics.cpp
index 8d69003285..95b39a40c6 100644
--- a/engines/tinsel/graphics.cpp
+++ b/engines/tinsel/graphics.cpp
@@ -56,11 +56,11 @@ static inline uint16 t3getColor(uint8 r, uint8 g, uint8 b) {
 }
 
 /**
- * PSX Block list unwinder.
+ * PSX/Saturn Block list unwinder.
  * 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* psxPJCRLEUnwinder(uint16 imageWidth, uint16 imageHeight, uint8 *srcIdx) {
+uint8* psxSaturnPJCRLEUnwinder(uint16 imageWidth, uint16 imageHeight, uint8 *srcIdx) {
 	uint32 remainingBlocks = 0;
 
 	uint16 compressionType = 0; // Kind of decompression to apply
@@ -84,7 +84,7 @@ uint8* psxPJCRLEUnwinder(uint16 imageWidth, uint16 imageHeight, uint8 *srcIdx) {
 
 	while (remainingBlocks) { // Repeat until all blocks are decompressed
 		if (!controlBits) {
-			controlData = READ_16(srcIdx);
+			controlData = READ_LE_UINT16(srcIdx);
 			srcIdx += 2;
 
 			// If bit 15 of controlData is enabled, compression data is type 1.
@@ -103,7 +103,7 @@ uint8* psxPJCRLEUnwinder(uint16 imageWidth, uint16 imageHeight, uint8 *srcIdx) {
 			// If there is compression, we need to fetch an index
 			// to be treated as "base" for compression.
 			if (compressionType != 0) {
-				controlData = READ_16(srcIdx);
+				controlData = READ_LE_UINT16(srcIdx);
 				srcIdx += 2;
 				baseIndex = controlData;
 			}
@@ -125,7 +125,7 @@ uint8* psxPJCRLEUnwinder(uint16 imageWidth, uint16 imageHeight, uint8 *srcIdx) {
 		switch (compressionType) {
 			case 0: // No compression, plain copy of indexes
 				while (decremTiles) {
-					WRITE_LE_UINT16(dstIdx, READ_16(srcIdx));
+					WRITE_LE_UINT16(dstIdx, READ_LE_UINT16(srcIdx));
 					srcIdx += 2;
 					dstIdx += 2;
 					decremTiles--;
@@ -301,9 +301,9 @@ static void MacDrawTiles(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool apply
 
 
 /**
- * Straight rendering with transparency support, PSX variant supporting also 4-BIT clut data
+ * Straight rendering with transparency support, PSX/Saturn variant supporting also 4-BIT clut data for PSX
  */
-static void PsxDrawTiles(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool applyClipping, bool fourBitClut, uint32 psxSkipBytes, byte *psxMapperTable, bool transparency) {
+static void psxSaturnDrawTiles(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool applyClipping, bool fourBitClut, uint32 psxSkipBytes, byte *psxMapperTable, bool transparency) {
 	// Set up the offset between destination blocks
 	int rightClip = applyClipping ? pObj->rightClip : 0;
 	Common::Rect boxBounds;
@@ -1066,7 +1066,7 @@ void DrawObject(DRAWOBJECT *pObj) {
 	byte psxMapperTable[16];
 
 	bool psxFourBitClut = false; // Used by Tinsel PSX, true if an image using a 4bit CLUT is rendered
-	bool psxRLEindex = false; // Used by Tinsel PSX, true if an image is using PJCRLE compressed indexes
+	bool psxSaturnRLEindex = false; // Used by Tinsel PSX/Saturn, true if an image is using PJCRLE compressed indexes
 	uint32 psxSkipBytes = 0; // Used by Tinsel PSX, number of bytes to skip before counting indexes for image tiles
 
 	if ((pObj->width <= 0) || (pObj->height <= 0))
@@ -1083,29 +1083,30 @@ void DrawObject(DRAWOBJECT *pObj) {
 			byte *p = (byte *)_vm->_handle->LockMem(pObj->hBits & HANDLEMASK);
 
 			srcPtr = p + (pObj->hBits & OFFSETMASK);
-			pObj->charBase = (char *)p + READ_LE_UINT32(p + 0x10);
-			pObj->transOffset = READ_LE_UINT32(p + 0x14);
+			pObj->charBase = (char *)p + READ_32(p + 0x10);
+			pObj->transOffset = READ_32(p + 0x14);
 
-			// Decompress block indexes for Discworld PSX
-			if (TinselV1PSX) {
-				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
+			// Decompress block indexes for Discworld PSX/Saturn
+			if (TinselV1PSX || TinselV1Saturn) {
+				uint8 paletteType = TinselV1PSX ? *(srcPtr) : *(srcPtr + 1); // if 0x88 we are using an 8bit palette type, if 0x44 we are using a 4 bit PSX CLUT
+				uint8 indexType = TinselV1PSX ? *(srcPtr + 1) : *(srcPtr); // if 0xCC indexes for this image are compressed with PCJRLE, if 0xDD indexes are not compressed
 
 				switch (paletteType) {
-					case 0x88: // Normal 8-bit palette
+					case 0x00: // Normal 8-bit palette (Saturn)
+					case 0x88: // Normal 8-bit palette (PSX)
 						psxFourBitClut = false;
 						psxSkipBytes = 0;
 						switch (indexType) {
 							case 0xDD: // Normal uncompressed indexes
-								psxRLEindex = false;
+								psxSaturnRLEindex = 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));
+								psxSaturnRLEindex = true;
+								srcPtr = psxSaturnPJCRLEUnwinder(pObj->width, pObj->height, srcPtr + sizeof(uint16));
 								break;
 							default:
-								error("Unknown PSX index type 0x%.2X", indexType);
+								error("Unknown PSX/Saturn index type 0x%.2X", indexType);
 								break;
 						}
 						break;
@@ -1113,15 +1114,15 @@ void DrawObject(DRAWOBJECT *pObj) {
 						psxPaletteMapper(pObj->pPal, srcPtr + sizeof(uint16), psxMapperTable);
 
 						psxFourBitClut = true;
-						psxSkipBytes = READ_LE_UINT32(p + sizeof(uint32) * 5) << 4; // Fetch number of bytes we have to skip
+						psxSkipBytes = READ_32(p + sizeof(uint32) * 5) << 4; // Fetch number of bytes we have to skip
 						switch (indexType) {
 							case 0xDD: // Normal uncompressed indexes
-								psxRLEindex = false;
+								psxSaturnRLEindex = 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);
+								psxSaturnRLEindex = true;
+								srcPtr = psxSaturnPJCRLEUnwinder(pObj->width, pObj->height, srcPtr + sizeof(uint16) * 17);
 								break;
 							default:
 								error("Unknown PSX index type 0x%.2X", indexType);
@@ -1129,7 +1130,7 @@ void DrawObject(DRAWOBJECT *pObj) {
 						}
 						break;
 					default:
-						error("Unknown PSX palette type 0x%.2X", paletteType);
+						error("Unknown PSX/Saturn palette type 0x%.2X", paletteType);
 						break;
 				}
 			}
@@ -1169,8 +1170,8 @@ void DrawObject(DRAWOBJECT *pObj) {
 				t3WrtNonZero(pObj, srcPtr, destPtr);
 			else if (TinselV2)
 				t2WrtNonZero(pObj, srcPtr, destPtr, (typeId & DMA_CLIP) != 0, (typeId & DMA_FLIPH) != 0);
-			else if (TinselV1PSX)
-				PsxDrawTiles(pObj, srcPtr, destPtr, typeId == 0x41, psxFourBitClut, psxSkipBytes, psxMapperTable, true);
+			else if (TinselV1PSX || TinselV1Saturn)
+				psxSaturnDrawTiles(pObj, srcPtr, destPtr, typeId == 0x41, psxFourBitClut, psxSkipBytes, psxMapperTable, true);
 			else if (TinselV1Mac)
 				MacDrawTiles(pObj, srcPtr, destPtr, typeId == 0x41);
 			else if (TinselV1)
@@ -1184,8 +1185,8 @@ void DrawObject(DRAWOBJECT *pObj) {
 				t3WrtAll(pObj, srcPtr, destPtr);
 			else if (TinselV2 || TinselV1Mac || TinselV0)
 				WrtAll(pObj, srcPtr, destPtr, typeId == 0x48);
-			else if (TinselV1PSX)
-				PsxDrawTiles(pObj, srcPtr, destPtr, typeId == 0x48, psxFourBitClut, psxSkipBytes, psxMapperTable, false);
+			else if (TinselV1PSX || TinselV1Saturn)
+				psxSaturnDrawTiles(pObj, srcPtr, destPtr, typeId == 0x48, psxFourBitClut, psxSkipBytes, psxMapperTable, false);
 			else if (TinselV1)
 				WrtNonZero(pObj, srcPtr, destPtr, typeId == 0x48);
 			break;
@@ -1214,9 +1215,9 @@ void DrawObject(DRAWOBJECT *pObj) {
 		}
 	}
 
-	// If we were using Discworld PSX, free the memory allocated
+	// If we were using Discworld PSX/Saturn, free the memory allocated
 	// for decompressed block indexes.
-	if (TinselV1PSX && psxRLEindex)
+	if ((TinselV1PSX || TinselV1Saturn) && psxSaturnRLEindex)
 		free(srcPtr);
 }
 
diff --git a/engines/tinsel/handle.cpp b/engines/tinsel/handle.cpp
index 24e3875f3c..b5c3a1b6a0 100644
--- a/engines/tinsel/handle.cpp
+++ b/engines/tinsel/handle.cpp
@@ -83,7 +83,7 @@ void Handle::SetupHandleTable() {
 	int len;
 	uint i;
 	MEMHANDLE *pH;
-	TinselFile f;
+	TinselFile f(TinselV1Mac || TinselV1Saturn);
 
 	const char *indexFileName = TinselV1PSX ? PSX_INDEX_FILENAME : INDEX_FILENAME;
 
diff --git a/engines/tinsel/music.cpp b/engines/tinsel/music.cpp
index 498a5fb62f..bd0ed7fbf0 100644
--- a/engines/tinsel/music.cpp
+++ b/engines/tinsel/music.cpp
@@ -176,6 +176,8 @@ bool Music::PlayMidiSequence(uint32 dwFileOffset, bool bLoop) {
 		// The Macintosh version of DW1 uses raw PCM for music
 		dwSeqLen = midiStream.readUint32BE();
 		_vm->_sound->playDW1MacMusic(midiStream, dwSeqLen);
+	} else if (TinselV1Saturn) {
+		// TODO: Music format for the Saturn version
 	} else {
 		dwSeqLen = midiStream.readUint32LE();
 
@@ -298,6 +300,10 @@ void Music::OpenMidiFiles() {
 		}
 
 		midiStream.close();
+	} else if (TinselV1Saturn) {
+		// The Saturn version has digital music with a different track structure
+		// TODO
+		warning("Music support for Discworld 1 Saturn");
 	} else {
 		if (_midiBuffer.pDat)
 			// already allocated
diff --git a/engines/tinsel/scene.cpp b/engines/tinsel/scene.cpp
index 293824f2b2..c6fa04205d 100644
--- a/engines/tinsel/scene.cpp
+++ b/engines/tinsel/scene.cpp
@@ -192,9 +192,8 @@ static void SceneTinselProcess(CORO_PARAM, const void *param) {
 
 	// The following myEscape value setting is used for enabling title screen skipping in DW1
 	if (TinselV1 && (g_sceneCtr == 1)) g_initialMyEscape = GetEscEvents();
-	// DW1 PSX has its own scene skipping script code for scenes 2 and 3 (bug #6094).
-	// Same goes for DW1 Mac.
-	_ctx->myEscape = (TinselV1 && (g_sceneCtr < ((TinselV1PSX || TinselV1Mac) ? 2 : 4))) ? g_initialMyEscape : 0;
+	// DW1 PSX, Saturn and Mac has its own scene skipping script code for scenes 2 and 3 (bug #6094).
+	_ctx->myEscape = (TinselV1 && (g_sceneCtr < ((TinselV1PSX || TinselV1Saturn || TinselV1Mac) ? 2 : 4))) ? g_initialMyEscape : 0;
 
 	// get the stuff copied to process when it was created
 	_ctx->pInit = (const TP_INIT *)param;
diff --git a/engines/tinsel/sound.cpp b/engines/tinsel/sound.cpp
index fc0df73887..3c46462789 100644
--- a/engines/tinsel/sound.cpp
+++ b/engines/tinsel/sound.cpp
@@ -100,7 +100,7 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound
 		error(FILE_IS_CORRUPT, _vm->getSampleFile(g_sampleLanguage));
 
 	// read the length of the sample
-	uint32 sampleLen = _sampleStream.readUint32LE();
+	uint32 sampleLen = _sampleStream.readUint32();
 	if (_sampleStream.eos() || _sampleStream.err())
 		error(FILE_IS_CORRUPT, _vm->getSampleFile(g_sampleLanguage));
 
@@ -115,6 +115,8 @@ bool SoundManager::playSample(int id, Audio::Mixer::SoundType type, Audio::Sound
 
 		// Play the audio stream
 		_vm->_mixer->playStream(type, &curChan.handle, xaStream);
+	} else if (TinselV1Saturn) {
+		// TODO: Sound format for the Saturn version - looks to be raw, but isn't
 	} else {
 		// allocate a buffer
 		byte *sampleBuf = (byte *)malloc(sampleLen);
@@ -499,7 +501,7 @@ void SoundManager::openSampleFiles() {
 	if (TinselV0 || (TinselV1 && !_vm->isV1CD()))
 		return;
 
-	TinselFile f;
+	TinselFile f(TinselV1Saturn);
 
 	if (_sampleIndex)
 		// already allocated
@@ -518,7 +520,7 @@ void SoundManager::openSampleFiles() {
 
 		// Load data
 		for (int i = 0; i < _sampleIndexLen; ++i) {
-			_sampleIndex[i] = f.readUint32LE();
+			_sampleIndex[i] = f.readUint32();
 			if (f.err()) {
 				showSoundError(FILE_READ_ERROR, _vm->getSampleIndex(g_sampleLanguage));
 			}
diff --git a/engines/tinsel/strres.cpp b/engines/tinsel/strres.cpp
index 45b0b47e5c..ce7fae0622 100644
--- a/engines/tinsel/strres.cpp
+++ b/engines/tinsel/strres.cpp
@@ -88,7 +88,7 @@ void ResetVarsStrRes() {
  * @param newLang			The new language
  */
 void ChangeLanguage(LANGUAGE newLang) {
-	TinselFile f;
+	TinselFile f(TinselV1Mac || TinselV1Saturn);
 	uint32 textLen = 0;	// length of buffer
 
 	g_textLanguage = newLang;
diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h
index 18c9f992d8..d0ef3421ce 100644
--- a/engines/tinsel/tinsel.h
+++ b/engines/tinsel/tinsel.h
@@ -107,12 +107,13 @@ typedef bool (*KEYFPTR)(const Common::KeyState &);
 #define TinselV2Demo (TinselVersion == TINSEL_V2 && _vm->getIsADGFDemo())
 #define TinselV1PSX (TinselVersion == TINSEL_V1 && _vm->getPlatform() == Common::kPlatformPSX)
 #define TinselV1Mac (TinselVersion == TINSEL_V1 && _vm->getPlatform() == Common::kPlatformMacintosh)
+#define TinselV1Saturn (TinselVersion == TINSEL_V1 && _vm->getPlatform() == Common::kPlatformSaturn)
 
-#define READ_16(v) (TinselV1Mac ? READ_BE_UINT16(v) : READ_LE_UINT16(v))
-#define READ_32(v) (TinselV1Mac ? READ_BE_UINT32(v) : READ_LE_UINT32(v))
-#define FROM_16(v) (TinselV1Mac ? FROM_BE_16(v) : FROM_LE_16(v))
-#define FROM_32(v) (TinselV1Mac ? FROM_BE_32(v) : FROM_LE_32(v))
-#define TO_32(v)   (TinselV1Mac ? TO_BE_32(v) : TO_LE_32(v))
+#define READ_16(v) (TinselV1Mac || TinselV1Saturn ? READ_BE_UINT16(v) : READ_LE_UINT16(v))
+#define READ_32(v) (TinselV1Mac || TinselV1Saturn ? READ_BE_UINT32(v) : READ_LE_UINT32(v))
+#define FROM_16(v) (TinselV1Mac || TinselV1Saturn ? FROM_BE_16(v) : FROM_LE_16(v))
+#define FROM_32(v) (TinselV1Mac || TinselV1Saturn ? FROM_BE_32(v) : FROM_LE_32(v))
+#define TO_32(v)   (TinselV1Mac || TinselV1Saturn ? TO_BE_32(v) : TO_LE_32(v))
 
 // Global reference to the TinselEngine object
 extern TinselEngine *_vm;




More information about the Scummvm-git-logs mailing list