[Scummvm-git-logs] scummvm master -> 2392177a7c070e2ade826dadf70b09f34b7e524f

AndywinXp noreply at scummvm.org
Mon Oct 16 11:00:06 UTC 2023


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

Summary:
e19ac44440 SWORD1: PSX: Fix text position margin to match original
5daae32032 SWORD1: PSX: Implement credits
2392177a7c SWORD1: PSX: Fix y coordinate for sprite drawing


Commit: e19ac44440f0b707a9d391c6f15f1d3127b3516b
    https://github.com/scummvm/scummvm/commit/e19ac44440f0b707a9d391c6f15f1d3127b3516b
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-16T12:59:17+02:00

Commit Message:
SWORD1: PSX: Fix text position margin to match original

This still doesn't render correctly because the PSX version has
a blitting routing which moves coordinates around, but 34 is
the correct value to have here.

Changed paths:
    engines/sword1/logic.cpp


diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index 19dd6e7da31..e488adcc6ab 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -1219,7 +1219,7 @@ int Logic::fnISpeak(Object *cpt, int32 id, int32 cdt, int32 textNo, int32 spr, i
 		int textMargin = SwordEngine::_systemVars.isDemo ? 5 : 3; // distance kept from edges of screen
 
 		if (SwordEngine::isPsx())
-			textMargin = 33;
+			textMargin = 34;
 
 		int aboveHead = (SwordEngine::_systemVars.isDemo || SwordEngine::isPsx()) ? 10 : 20; // distance kept above talking sprite
 		uint16 textX, textY;


Commit: 5daae320328fe65becb5fe92e779392f7e622529
    https://github.com/scummvm/scummvm/commit/5daae320328fe65becb5fe92e779392f7e622529
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-16T12:59:17+02:00

Commit Message:
SWORD1: PSX: Implement credits

The PSX version doesn't have a credits Smacker video
but has a CREDITS.DAT file containing credits strings which
have to be displayed as a scrolling list of names and roles.

Changed paths:
    engines/sword1/control.cpp
    engines/sword1/control.h
    engines/sword1/logic.cpp
    engines/sword1/logic.h
    engines/sword1/sword1.cpp


diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 2eb11ebd106..7bbf08c1b2e 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -3312,4 +3312,374 @@ const uint8 Control::_mediaHouseLanguageStrings[20][43] = {
 	"DRIVE FULL!",
 };
 
+/* ---------- PSX CREDITS CODE ---------- */
+
+int32 Control::getCreditsStringLength(uint8 *str, uint8 *font) {
+	int32 width = 0;
+	FrameHeader *f;
+
+	while (*str) {
+		f = (FrameHeader *)_resMan->fetchFrame(font, *str - 32);
+		width += f->width;
+		str++;
+
+		if (*str)
+			width += PSX_CREDITS_SPACING;
+	}
+
+	return width;
+}
+
+int32 Control::getCreditsFontHeight(uint8 *font) {
+	FrameHeader *f;
+
+	f = (FrameHeader *)_resMan->fetchFrame(font, 'A' - 32);
+	return (f->height / 2);
+}
+
+void Control::createCreditsTextSprite(uint8 *data, int32 pitch, uint8 *str, uint8 *font) {
+	uint16 x = 0;
+	FrameHeader *f;
+	uint8 *src, *dst;
+
+	while (*str) {
+		f = (FrameHeader *)_resMan->fetchFrame(font, *str - 32);
+
+		src = (uint8 *)f + sizeof(FrameHeader);
+		dst = data + x;
+
+		for (int i = 0; i < f->height / 2; i++) {
+			memcpy(dst, src, f->width);
+			src += f->width;
+			dst += pitch;
+		}
+
+		x += (f->width + PSX_CREDITS_SPACING);
+		str++;
+	}
+}
+
+void Control::renderCreditsTextSprite(uint8 *data, uint8 *screenBuf, int16 x, int16 y, int16 width, int16 height) {
+	// Coordinates corrections from disasm
+	// (remember that the PSX framebuffer is bigger than our target 640x480 screen)
+	x -= 129;
+	y -= 72;
+
+	// Boundary checks
+	if (x >= SCREEN_WIDTH || y >= SCREEN_FULL_DEPTH)
+		return;
+
+	if (x + width <= 0 || y + height <= 0)
+		return;
+
+	// Are there rows outside the screen?
+	// Calculate how many doubled rows of the sprite are outside the screen on the top
+	int16 skippedDoubledRows = (y < 0) ? -y : 0;
+	int16 skippedRowsInData = skippedDoubledRows / 2;
+
+	data += width * skippedRowsInData; // Adjust data pointer based on the number of skipped rows in the sprite
+	height -= skippedDoubledRows;      // Adjust height based on the number of skipped doubled rows
+
+	if (y < 0) {
+		y = 0;
+	}
+
+	uint8 *dst = screenBuf + x + SCREEN_WIDTH * y;
+
+	for (int i = 0; i < height; i += 2) { // Increment by 2 for the doubled height
+		// Boundary check for y
+		if (y + i >= SCREEN_FULL_DEPTH)
+			break;
+
+		// First horizontal line
+		for (int j = 0; j < width; j++) {
+			// Boundary checks for x
+			if (x + j < 0)
+				continue;
+
+			if (x + j >= SCREEN_WIDTH)
+				break;
+
+			if (data[j])
+				dst[j] = data[j];
+		}
+
+		dst += SCREEN_WIDTH;
+
+		// Second horizontal line (duplicated)
+		for (int j = 0; j < width; j++) {
+			// Boundary checks for x
+			if (x + j < 0)
+				continue;
+
+			if (x + j >= SCREEN_WIDTH)
+				break;
+
+			if (data[j])
+				dst[j] = data[j];
+		}
+
+		dst += SCREEN_WIDTH; // Move to the next line
+		data += width;       // Move to the next row of source sprite
+	}
+}
+
+void Control::psxEndCredits() {
+	int16 h;
+	int16 nextCredit = PSX_NUM_CREDITS + 1;
+	uint8 *creditLine = nullptr;
+	uint8 *titleLine = nullptr;
+	int32 *creditData = nullptr;
+	Common::File creditsFile;
+
+	int32 creditsFileSize = 0;
+	int32 totalCreditsNum = 0;
+
+	uint8 *creditSprite[PSX_NUM_CREDITS];
+	uint8 *titleSprite[PSX_NUM_CREDITS];
+	int16 creditWidth[PSX_NUM_CREDITS];
+	int16 titleWidth[PSX_NUM_CREDITS];
+	int16 creditsHeight[PSX_NUM_CREDITS] = {
+		400, 440, 480, 520, 560, 600, 640,
+		680, 720, 760, 800, 840, 880, 920
+	};
+
+	for (int i = 0; i < PSX_NUM_CREDITS; i++) {
+		creditSprite[i] = nullptr;
+		titleSprite[i] = nullptr;
+		creditWidth[i] = 0;
+		titleWidth[i] = 0;
+	}
+
+	// If we're here, the resource is already there, no need to open it
+	uint8 *font = (uint8 *)_resMan->fetchRes(GAME_FONT);
+
+	switch (SwordEngine::_systemVars.language) {
+	case BS1_ENGLISH:
+		totalCreditsNum = 101;
+		creditsFileSize = 2798;
+		break;
+	case BS1_GERMAN:
+		totalCreditsNum = 83;
+		creditsFileSize = 2382;
+		break;
+	case BS1_FRENCH:
+		totalCreditsNum = 83;
+		creditsFileSize = 2382;
+		break;
+	case BS1_SPANISH:
+		totalCreditsNum = 83;
+		creditsFileSize = 2412;
+		break;
+	case BS1_ITALIAN:
+		totalCreditsNum = 101;
+		creditsFileSize = 2823;
+		break;
+	default:
+		totalCreditsNum = 101;
+		creditsFileSize = 2798;
+	}
+
+	_sound->clearAllFx();
+	_screen->startFadePaletteUp(1);
+
+	for (int i = 0; i < PSX_NUM_CREDITS; i++)
+		creditsHeight[i] = 400 + i * 40;
+
+	h = getCreditsFontHeight(font);
+	_screen->fnSetFadeTargetPalette(193, 1, 0, TEXT_WHITE);
+
+	_sound->streamMusicFile(101, 1);
+	_sound->updateMusicStreaming();
+
+	uint8 *creditsScreenBuf = (uint8 *)malloc(SCREEN_WIDTH * SCREEN_FULL_DEPTH);
+	if (!creditsScreenBuf) {
+		warning("Control::psxEndCredits(): Couldn't allocate memory for credits screen buffer");
+		return;
+	}
+
+	memset(creditsScreenBuf, 0, SCREEN_WIDTH * SCREEN_FULL_DEPTH);
+
+	creditData = (int32 *)malloc(creditsFileSize);
+	if (!creditData) {
+		warning("Control::psxEndCredits(): Couldn't allocate memory for text data");
+		free(creditsScreenBuf);
+		return;
+	}
+
+	if (!creditsFile.exists("CREDITS.DAT")) {
+		debug(2, "Control::psxEndCredits(): Couldn't find CREDITS.DAT");
+		free(creditsScreenBuf);
+		free(creditData);
+		return;
+	}
+
+	creditsFile.open("CREDITS.DAT");
+	if (!creditsFile.isOpen()) {
+		debug(2, "Control::psxEndCredits(): Couldn't open CREDITS.DAT");
+		free(creditsScreenBuf);
+		free(creditData);
+		return;
+	}
+
+	creditsFile.read(creditData, creditsFileSize);
+	creditsFile.close();
+
+	bool allSet = true;
+
+	for (int i = 0; i < PSX_NUM_CREDITS; i++) {
+		_sound->updateMusicStreaming();
+		_sound->setCrossFadeIncrement();
+
+		creditLine = ((uint8 *)creditData + creditData[i + totalCreditsNum]);
+		titleLine = ((uint8 *)creditData + creditData[i]);
+
+		creditWidth[i] = (getCreditsStringLength(creditLine, font) + 1) & 0xFFFE;
+		titleWidth[i] = (getCreditsStringLength(titleLine, font) + 1) & 0xFFFE;
+
+		if (creditWidth[i]) {
+			creditSprite[i] = (uint8 *)malloc(h * creditWidth[i]);
+			if (!creditSprite[i]) {
+				warning("Control::psxEndCredits(): Couldn't allocate memory for text sprites");
+				allSet = false;
+				break; // Break so the clean-up code is executed
+			}
+
+			memset(creditSprite[i], 0, h * creditWidth[i]);
+		} else {
+			creditSprite[i] = nullptr;
+		}
+
+		if (titleWidth[i]) {
+			titleSprite[i] = (uint8 *)malloc(h * titleWidth[i]);
+			if (!titleSprite[i]) {
+				warning("Control::psxEndCredits(): Couldn't allocate memory for text sprites");
+				allSet = false;
+				break; // Break so the clean-up code is executed
+			}
+
+			memset(titleSprite[i], 0, h * titleWidth[i]);
+		} else {
+			titleSprite[i] = nullptr;
+		}
+
+		createCreditsTextSprite(creditSprite[i], creditWidth[i], creditLine, font);
+		createCreditsTextSprite(titleSprite[i], titleWidth[i], titleLine, font);
+	}
+
+	_keyPressed.reset();
+
+	while (allSet && creditsHeight[PSX_NUM_CREDITS - 1] > -120 &&
+		!Engine::shouldQuit() &&
+		_keyPressed.keycode != Common::KEYCODE_ESCAPE) {
+		memset(creditsScreenBuf, 0, SCREEN_WIDTH * SCREEN_FULL_DEPTH);
+
+		for (int i = 0; i < PSX_NUM_CREDITS; i++) {
+			// Name
+			renderCreditsTextSprite(
+				creditSprite[i],
+				creditsScreenBuf,
+				PSX_CREDITS_MIDDLE + Logic::_scriptVars[SCROLL_OFFSET_X],
+				PSX_CREDITS_OFFSET + creditsHeight[i],
+				creditWidth[i],
+				h * 2);
+
+			// Role
+			renderCreditsTextSprite(
+				titleSprite[i],
+				creditsScreenBuf,
+				PSX_CREDITS_MIDDLE + Logic::_scriptVars[SCROLL_OFFSET_X] - 30 - titleWidth[i],
+				PSX_CREDITS_OFFSET + creditsHeight[i],
+				titleWidth[i],
+				h * 2);
+
+			creditsHeight[i] -= 2;
+		}
+
+		_system->copyRectToScreen(creditsScreenBuf, SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_FULL_DEPTH);
+
+		delay(33); // Run credits at about 30 FPS
+
+		// Always remember to update sound :-)
+		_sound->updateMusicStreaming();
+		_sound->setCrossFadeIncrement();
+
+		// Scroll the credits!
+		if (creditsHeight[0] < -120) {
+			if (nextCredit <= totalCreditsNum) {
+				for (int i = 0; i < PSX_NUM_CREDITS; i++) {
+					creditsHeight[i] += 40;
+				}
+
+				if (creditSprite[0] != nullptr)
+					free(creditSprite[0]);
+
+				if (titleSprite[0] != nullptr)
+					free(titleSprite[0]);
+
+				for (int i = 0; i < PSX_NUM_CREDITS - 1; i++) {
+					creditSprite[i] = creditSprite[i + 1];
+					titleSprite[i] = titleSprite[i + 1];
+					creditWidth[i] = creditWidth[i + 1];
+					titleWidth[i] = titleWidth[i + 1];
+				}
+
+				creditLine = ((uint8 *)creditData + creditData[nextCredit - 1 + totalCreditsNum]);
+				titleLine = ((uint8 *)creditData + creditData[nextCredit - 1]);
+
+				creditWidth[PSX_NUM_CREDITS - 1] = (getCreditsStringLength(creditLine, font) + 1) & 0xFFFE;
+				titleWidth[PSX_NUM_CREDITS - 1] = (getCreditsStringLength(titleLine, font) + 1) & 0xFFFE;
+
+				if (creditWidth[PSX_NUM_CREDITS - 1]) {
+					creditSprite[PSX_NUM_CREDITS - 1] = (uint8 *)malloc(h * creditWidth[PSX_NUM_CREDITS - 1]);
+					if (!creditSprite[PSX_NUM_CREDITS - 1]) {
+						warning("Control::psxEndCredits(): Couldn't allocate memory for text sprites");
+						break;
+					}
+
+					memset(creditSprite[PSX_NUM_CREDITS - 1], 0, h * creditWidth[PSX_NUM_CREDITS - 1]);
+				} else {
+					creditSprite[PSX_NUM_CREDITS - 1] = nullptr;
+				}
+
+				if (titleWidth[PSX_NUM_CREDITS - 1]) {
+					titleSprite[PSX_NUM_CREDITS - 1] = (uint8 *)malloc(h * titleWidth[PSX_NUM_CREDITS - 1]);
+					if (!titleSprite[PSX_NUM_CREDITS - 1]) {
+						warning("Control::psxEndCredits(): Couldn't allocate memory for text sprites");
+						break;
+					}
+
+					memset(titleSprite[PSX_NUM_CREDITS - 1], 0, h * titleWidth[PSX_NUM_CREDITS - 1]);
+				} else {
+					titleSprite[PSX_NUM_CREDITS - 1] = nullptr;
+				}
+
+				createCreditsTextSprite(creditSprite[PSX_NUM_CREDITS - 1], creditWidth[PSX_NUM_CREDITS - 1], creditLine, font);
+				createCreditsTextSprite(titleSprite[PSX_NUM_CREDITS - 1], titleWidth[PSX_NUM_CREDITS - 1], titleLine, font);
+
+				nextCredit += 1;
+			}
+		}
+	}
+
+	for (int i = 0; i < PSX_NUM_CREDITS; i++) {
+		if (creditSprite[i] != nullptr)
+			free(creditSprite[i]);
+
+		if (titleSprite[i] != nullptr)
+			free(titleSprite[i]);
+	}
+
+	free(creditData);
+
+	_screen->startFadePaletteDown(1);
+	_vm->waitForFade();
+
+	memset(creditsScreenBuf, 0, SCREEN_WIDTH * SCREEN_FULL_DEPTH);
+	_system->copyRectToScreen(creditsScreenBuf, SCREEN_WIDTH, 0, 0, SCREEN_WIDTH, SCREEN_FULL_DEPTH);
+	free(creditsScreenBuf);
+
+	_keyPressed.reset();
+}
+
 } // End of namespace Sword1
diff --git a/engines/sword1/control.h b/engines/sword1/control.h
index 8784b9c47b6..870d0f91679 100644
--- a/engines/sword1/control.h
+++ b/engines/sword1/control.h
@@ -105,6 +105,11 @@ class Logic;
 #define SP_OVERLAP   2
 #define TEXTBUTTONID 7
 
+#define PSX_CREDITS_SPACING (-3)
+#define PSX_CREDITS_MIDDLE  450
+#define PSX_CREDITS_OFFSET  150
+#define PSX_NUM_CREDITS     14
+
 struct Button {
 	int32 x1;
 	int32 y1;
@@ -126,6 +131,7 @@ public:
 	void checkForOldSaveGames();
 	bool isPanelShown();
 	const uint8 *getPauseString();
+	void psxEndCredits();
 
 	void setSaveDescription(int slot, const char *desc) {
 		Common::strcpy_s((char *)_fileDescriptions[slot], sizeof(_fileDescriptions[slot]), desc);
@@ -198,6 +204,12 @@ private:
 
 	int displayMessage(const char *altButton, MSVC_PRINTF const char *message, ...) GCC_PRINTF(3, 4);
 
+	// PSX Credits functions
+	int32 getCreditsFontHeight(uint8 *font);
+	int32 getCreditsStringLength(uint8 *str, uint8 *font);
+	void renderCreditsTextSprite(uint8 *data, uint8 *dst, int16 x, int16 y, int16 width, int16 height);
+	void createCreditsTextSprite(uint8 *data, int32 pitch, uint8 *str, uint8 *font);
+
 	Common::MemoryWriteStreamDynamic *_tempThumbnail;
 	static const uint8 _languageStrings[8 * 20][43];
 	static const uint8 _akellaLanguageStrings[20][43];
diff --git a/engines/sword1/logic.cpp b/engines/sword1/logic.cpp
index e488adcc6ab..d509cea2373 100644
--- a/engines/sword1/logic.cpp
+++ b/engines/sword1/logic.cpp
@@ -95,6 +95,10 @@ void Logic::initialize() {
 	SwordEngine::_systemVars.speechFinished = true;
 }
 
+void Logic::setControlPanelObject(Control *control) {
+	_control = control;
+}
+
 void Logic::newScreen(uint32 screen) {
 	Object *compact = (Object *)_objMan->fetchObject(PLAYER);
 
@@ -984,21 +988,26 @@ int Logic::fnPlaySequence(Object *cpt, int32 id, int32 sequenceId, int32 d, int3
 	// meantime, we don't want any looping sound effects still playing.
 	_sound->clearAllFx();
 
-	MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _resMan, _sound, _system);
-	if (player) {
-		_screen->clearScreen();
-		if (player->load(sequenceId))
-			player->play();
-		delete player;
-
-		// In some instances, when you start a video when the palette is still fading
-		// and the video is finished earlier, another palette fade(-out) is performed with the
-		// wrong palette. This happens when traveling to Spain or Ireland. It couldn't happen
-		// in the original, as it asked for the CD before loading the scene.
-		// Let's fix this by forcing a black fade palette on the next fade out. If a fade-in
-		// is then scheduled, we will clear the flag without doing anything different from the usual.
-		_screen->setNextFadeOutToBlack();
+	if (SwordEngine::isPsx() && sequenceId == 19) {
+		_control->psxEndCredits();
+	} else {
+		MoviePlayer *player = makeMoviePlayer(sequenceId, _vm, _textMan, _resMan, _sound, _system);
+		if (player) {
+			_screen->clearScreen();
+			if (player->load(sequenceId))
+				player->play();
+			delete player;
+
+			// In some instances, when you start a video when the palette is still fading
+			// and the video is finished earlier, another palette fade(-out) is performed with the
+			// wrong palette. This happens when traveling to Spain or Ireland. It couldn't happen
+			// in the original, as it asked for the CD before loading the scene.
+			// Let's fix this by forcing a black fade palette on the next fade out. If a fade-in
+			// is then scheduled, we will clear the flag without doing anything different from the usual.
+			_screen->setNextFadeOutToBlack();
+		}
 	}
+
 	return SCRIPT_CONT;
 }
 
diff --git a/engines/sword1/logic.h b/engines/sword1/logic.h
index 96089534263..20b298b6b0c 100644
--- a/engines/sword1/logic.h
+++ b/engines/sword1/logic.h
@@ -47,6 +47,7 @@ class Menu;
 class Router;
 class Screen;
 class Mouse;
+class Control;
 
 class Logic;
 typedef int (Logic::*BSMcodeTable)(Object *, int32, int32, int32, int32, int32, int32, int32);
@@ -57,6 +58,7 @@ public:
 	Logic(SwordEngine *vm, ObjectMan *pObjMan, ResMan *resMan, Screen *pScreen, Mouse *pMouse, Sound *pSound, Menu *pMenu, OSystem *system, Audio::Mixer *mixer);
 	~Logic();
 	void initialize();
+	void setControlPanelObject(Control *control);
 	void newScreen(uint32 screen);
 	void engine();
 	void updateScreenParams();
@@ -81,6 +83,7 @@ private:
 	Text *_textMan;
 	EventManager *_eventMan;
 	Menu *_menu;
+	Control *_control;
 	uint32 _newScript; // <= ugly, but I can't avoid it.
 	uint8 _speechClickDelay = 0;
 	Common::RandomSource _rnd;
diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp
index 53ecbb75524..4e890cb83d1 100644
--- a/engines/sword1/sword1.cpp
+++ b/engines/sword1/sword1.cpp
@@ -172,6 +172,7 @@ Common::Error SwordEngine::init() {
 	_objectMan->initialize();
 	_mouse->initialize();
 	_control = new Control(this, _saveFileMan, _resMan, _objectMan, _system, _mouse, _sound, _screen, _logic);
+	_logic->setControlPanelObject(_control);
 
 	return Common::kNoError;
 }


Commit: 2392177a7c070e2ade826dadf70b09f34b7e524f
    https://github.com/scummvm/scummvm/commit/2392177a7c070e2ade826dadf70b09f34b7e524f
Author: AndywinXp (andywinxp at gmail.com)
Date: 2023-10-16T12:59:17+02:00

Commit Message:
SWORD1: PSX: Fix y coordinate for sprite drawing

Now sprites don't randomly go up and down when being
animated :-) This was taken from disasm.

Changed paths:
    engines/sword1/control.cpp
    engines/sword1/screen.cpp


diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp
index 7bbf08c1b2e..74c10ab2370 100644
--- a/engines/sword1/control.cpp
+++ b/engines/sword1/control.cpp
@@ -3362,6 +3362,7 @@ void Control::createCreditsTextSprite(uint8 *data, int32 pitch, uint8 *str, uint
 void Control::renderCreditsTextSprite(uint8 *data, uint8 *screenBuf, int16 x, int16 y, int16 width, int16 height) {
 	// Coordinates corrections from disasm
 	// (remember that the PSX framebuffer is bigger than our target 640x480 screen)
+	y = (y + 1) & 0xFFFE;
 	x -= 129;
 	y -= 72;
 
diff --git a/engines/sword1/screen.cpp b/engines/sword1/screen.cpp
index 02d06189554..7616acb743a 100644
--- a/engines/sword1/screen.cpp
+++ b/engines/sword1/screen.cpp
@@ -1396,6 +1396,9 @@ void Screen::spriteClipAndSet(uint16 *pSprX, uint16 *pSprY, uint16 *pSprWidth, u
 			gridBuf += _gridSizeX;
 		}
 	}
+
+	if (SwordEngine::isPsx())
+		*pSprY = (*pSprY + 1) & 0xFFFE;
 }
 
 void Screen::fnFlash(uint8 color) {




More information about the Scummvm-git-logs mailing list