[Scummvm-git-logs] scummvm master -> bf5ac4770325c2ee402a69734ca03643b8b5e8c7
moralrecordings
noreply at scummvm.org
Sat Jul 25 04:01:28 UTC 2026
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
bf5ac47703 FOOL: Add support for Fool's Errand demo version
Commit: bf5ac4770325c2ee402a69734ca03643b8b5e8c7
https://github.com/scummvm/scummvm/commit/bf5ac4770325c2ee402a69734ca03643b8b5e8c7
Author: Scott Percival (code at moral.net.au)
Date: 2026-07-25T11:36:56+08:00
Commit Message:
FOOL: Add support for Fool's Errand demo version
Changed paths:
engines/fool/detection_tables.h
engines/fool/fool.cpp
engines/fool/fool.h
engines/fool/fool_cards.cpp
engines/fool/fool_game.cpp
engines/fool/fool_game.h
engines/fool/fool_justice.cpp
engines/fool/fool_maze.cpp
engines/fool/fool_polyomino.cpp
engines/fool/fool_thoth.cpp
diff --git a/engines/fool/detection_tables.h b/engines/fool/detection_tables.h
index 6e41f3db76f..6d990b8d645 100644
--- a/engines/fool/detection_tables.h
+++ b/engines/fool/detection_tables.h
@@ -64,6 +64,16 @@ const ADGameDescription gameDescriptions[] = {
GUIO1(GUIO_NONE)
},
+ // The Fool's Errand Demo - Version 1.0 (1987-06-25)
+ {
+ "foolserrand",
+ "Demo v1.0",
+ AD_ENTRY1s("Fool's DEMO", "rt:3890f5ed98166cf213e6d04fa2ce21b7", 142388),
+ Common::EN_ANY,
+ Common::kPlatformMacintosh,
+ ADGF_UNSTABLE | ADGF_DEMO,
+ GUIO1(GUIO_NONE)
+ },
AD_TABLE_END_MARKER
};
diff --git a/engines/fool/fool.cpp b/engines/fool/fool.cpp
index ce104f7b143..f1756f30a63 100644
--- a/engines/fool/fool.cpp
+++ b/engines/fool/fool.cpp
@@ -63,7 +63,9 @@ Common::Error FoolEngine::run() {
Common::String versionStr(_gameDescription->desc.extra);
FoolVersion version = kFool20;
- if (versionStr == "v1.1") {
+ if (versionStr == "Demo v1.0") {
+ version = kFoolDemo10;
+ } else if (versionStr == "v1.1") {
version = kFool11;
} else if (versionStr == "v2.0") {
version = kFool20;
diff --git a/engines/fool/fool.h b/engines/fool/fool.h
index 92316013e62..5a2b5039004 100644
--- a/engines/fool/fool.h
+++ b/engines/fool/fool.h
@@ -46,7 +46,8 @@ struct FoolGameDescription;
enum FoolVersion {
kFool11 = 1,
kFool20 = 2,
- kFool30 = 3,
+ kFool30 = 4,
+ kFoolDemo10 = 8,
};
class FoolEngine : public Engine {
diff --git a/engines/fool/fool_cards.cpp b/engines/fool/fool_cards.cpp
index b8876896343..16a3c8b182e 100644
--- a/engines/fool/fool_cards.cpp
+++ b/engines/fool/fool_cards.cpp
@@ -31,9 +31,6 @@ namespace Fool {
-// v1.1 and v2.0 have the winning score set to 700.
-// v3.0 revises this to be 666, which I can't dispute is a much cooler score.
-#define CARDS_MAX_SCORE 666
#define CARDS_MIN_SCORE (-999)
#define CARDS_YIELD_PENALTY 27
@@ -67,7 +64,7 @@ void FoolGame::cardsRun() {
arr_i32_192c0[i] = _toolbox->GetPicture(var_i16_484);
}
// 139:0184
- sub_128_bde(1, 1, 0, 1, 1, 1);
+ screenZap(1, 1, 0, 1, 1, 1);
fillRect(0xb4, 0xb5, 0x156, 0x14b, 2);
// illustration of the card game
_zbasic->picture(0xc3, 0xf3, arr_i32_192c0[0x17]);
@@ -95,7 +92,7 @@ void FoolGame::cardsRun() {
arr_i16_1eb8[6] = _zbasic->decodeInt(_zbasic->midStr(_activePuzzleBuffer, 3, 2));
// 139:0320
var_i16_2010 = _zbasic->decodeInt(_zbasic->midStr(_activePuzzleBuffer, 5, 2));
- if ((arr_i16_1eb8[5] > CARDS_MAX_SCORE) || (arr_i16_1eb8[6] > CARDS_MAX_SCORE)) {
+ if ((arr_i16_1eb8[5] > _cardsMaxScore) || (arr_i16_1eb8[6] > _cardsMaxScore)) {
arr_i16_1eb8[5] = 0;
arr_i16_1eb8[6] = 0;
var_i16_2010 = 0;
@@ -271,7 +268,7 @@ void FoolGame::cardsOnClick() {
}
// 139:0938
var_i16_2010 = 0;
- if (arr_i16_1eb8[5] > CARDS_MAX_SCORE) {
+ if (arr_i16_1eb8[5] > _cardsMaxScore) {
sub_139_1d3e();
return;
}
@@ -294,7 +291,7 @@ void FoolGame::cardsOnClick() {
}
}
// 139:09d8
- if (((_stateFlags & kStateReturn) == 0) && (arr_i16_1eb8[6] > CARDS_MAX_SCORE)) {
+ if (((_stateFlags & kStateReturn) == 0) && (arr_i16_1eb8[6] > _cardsMaxScore)) {
_stateFlags = kStateUndo;
var_i16_2014 = 0;
}
@@ -483,7 +480,7 @@ void FoolGame::cardsRevealHands() {
var_str_384 = _zbasic->str(OFF(12)); // The Old Man
}
// 139:11e2
- if ((arr_i16_1eb8[5] > CARDS_MAX_SCORE) || (arr_i16_1eb8[6] > CARDS_MAX_SCORE)) {
+ if ((arr_i16_1eb8[5] > _cardsMaxScore) || (arr_i16_1eb8[6] > _cardsMaxScore)) {
var_str_9f4 = _zbasic->str(OFF(13)); // the game!
} else {
// 139:123e
diff --git a/engines/fool/fool_game.cpp b/engines/fool/fool_game.cpp
index 5ec829f362e..2757217eb35 100644
--- a/engines/fool/fool_game.cpp
+++ b/engines/fool/fool_game.cpp
@@ -24,6 +24,7 @@
#include "common/translation.h"
#include "common/ustr.h"
#include "common/util.h"
+#include "fool.h"
#include "graphics/mactoolbox/toolbox.h"
#include "gui/saveload.h"
@@ -46,15 +47,19 @@ namespace Fool {
// Offset adjustments for the ZBasic string table to align
// across game versions
static const int fool11ZStrOffset[] = {
- 128, 59, 81, 170, 186, 188, 192, 194, 202, 239, 258, 280, 315, 341, 324, 13, 21, 6, 3
+ 128, 59, 81, 170, 186, 188, 192, 194, 202, 239, 258, 280, 315, 341, 324, 13, 21, 6, 3, 0, 0
};
static const int fool20ZStrOffset[] = {
- 102, 78, 103, 191, 207, 209, 213, 215, 223, 260, 279, 301, 336, 362, 345, 18, 22, 6, 3
+ 102, 78, 103, 191, 207, 209, 213, 215, 223, 260, 279, 301, 336, 362, 345, 18, 22, 6, 3, 0, 0
};
static const int fool30ZStrOffset[] = {
- 97, 73, 98, 161, 177, 179, 183, 185, 193, 230, 251, 273, 308, 334, 317, 8, 12, 76, 3
+ 97, 73, 98, 161, 177, 179, 183, 185, 193, 230, 251, 273, 308, 334, 317, 8, 12, 76, 3, 0, 0
+};
+
+static const int foolDemo10ZStrOffset[] = {
+ 0, 0, 0, 128, 0, 146, 150, 152, 160, 0, 198, 213, 0, 246, 231, 0, 0, 0, 0, 28, 18
};
// Fool's Errand v1.1 is missing FOND data, below is taken from 2.0
@@ -130,20 +135,38 @@ void FoolGame::run() {
// v1.0 filename ends with "tm"
} else if (_toolbox->GetFInfo(Common::U32String("xn--The Fool's Errand-306j"), 0, finfo) == Graphics::MacToolbox::kNoErr) {
_zbasic->loadProgram(Common::Path("xn--The Fool's Errand-306j", ':'));
+ } else if (_toolbox->GetFInfo(Common::U32String("Fool's DEMO"), 0, finfo) == Graphics::MacToolbox::kNoErr) {
+ _zbasic->loadProgram(Common::Path("Fool's DEMO", ':'));
} else {
error("FoolGame::run: Fool's Errand program not found");
return;
}
+ // index of the Chicago FONT data
int16 fontChicago = 0;
+ // name of the puzzle data file
+ _puzzlesPath = Common::U32String("Fool's Puzzles");
+ // Number of points required to win card game.
+ // v1.1 and v2.0 have the winning score set to 700.
+ // v3.0 revises this to be 666, which I can't dispute is a much cooler score.
+ _cardsMaxScore = 700;
+ // are we playing the demo version
+ _isDemo = false;
switch (_version) {
case kFool11:
_zstrOffset = fool11ZStrOffset;
break;
+ case kFoolDemo10:
+ _zstrOffset = foolDemo10ZStrOffset;
+ _puzzlesPath = Common::U32String("Demo Puzzles");
+ _cardsMaxScore = 333;
+ _isDemo = true;
+ break;
case kFool30:
_zstrOffset = fool30ZStrOffset;
// v3.0 calls the font "Foolish Chicago" and changes the index
fontChicago = 255;
+ _cardsMaxScore = 666;
break;
case kFool20:
default:
@@ -151,7 +174,7 @@ void FoolGame::run() {
break;
}
- if (_version == kFool11) {
+ if (_version & (kFool11 | kFoolDemo10)) {
// v1.1 doesn't include any FOND chunks, so we have to provide them here.
_zbasic->injectFOND(fondFool, sizeof(fondFool), Common::String("Fool"));
_zbasic->injectFOND(fondChicago, sizeof(fondChicago), Common::String("Foolish Chicago"));
@@ -675,7 +698,7 @@ void FoolGame::zoomRect(int16 startTop, int16 startLeft, int16 startBottom, int1
_toolbox->PenNormal();
}
-void FoolGame::sub_128_bde(int16 unk6, int16 unk5, int16 unk4, int16 unk3, int16 unk2, int16 unk1) {
+void FoolGame::screenZap(int16 unk6, int16 unk5, int16 unk4, int16 unk3, int16 unk2, int16 unk1) {
// 128:0bde
arr_i16_4758[0] = unk6;
arr_i16_4758[1] = unk5;
@@ -754,7 +777,7 @@ void FoolGame::flashRect(int16 top, int16 left, int16 bottom, int16 right, int16
}
}
-void FoolGame::showChoiceModal(uint16 font, int16 lineCount, int16 buttonCount, bool beep) {
+void FoolGame::showChoiceModal(uint16 font, int16 lineCount, int16 buttonCount, bool beep, bool dark) {
// 128:0dfe
_toolbox->SetPort(var_i32_4);
var_i16_7b2 = 0xa;
@@ -764,8 +787,9 @@ void FoolGame::showChoiceModal(uint16 font, int16 lineCount, int16 buttonCount,
playTone(0x19, 0x64, false);
}
// 128:0e46
+ bool hasButtons = buttonCount != 0;
copyScreen(0, arr_bmp_138bc);
- _zbasic->text(font, 0xc, Graphics::kMacFontRegular, Graphics::MacToolbox::kSrcBic);
+ _zbasic->text(font, 0xc, Graphics::kMacFontRegular, dark ? Graphics::MacToolbox::kSrcBic : Graphics::MacToolbox::kSrcCopy);
var_i16_7b4 = buttonCount*0x46;
var_i16_7b6 = 0;
for (int i = 0; i <= lineCount; i++) {
@@ -777,7 +801,7 @@ void FoolGame::showChoiceModal(uint16 font, int16 lineCount, int16 buttonCount,
var_i16_7b6 += 0x11;
}
// 128:0ed6
- if (buttonCount >= 0) {
+ if (buttonCount > 0) {
var_i16_7bc = 0xa4 + (var_i16_7b6 / 2);
var_i16_7b6 += 0x28;
} else {
@@ -801,7 +825,7 @@ void FoolGame::showChoiceModal(uint16 font, int16 lineCount, int16 buttonCount,
_toolbox->PenPat(_patterns[1]);
_toolbox->FrameRect(bounds);
_toolbox->InsetRect(bounds, 5, 5);
- _toolbox->FillRect(bounds, _patterns[2]);
+ _toolbox->FillRect(bounds, _patterns[dark ? 2 : 0]);
_toolbox->PenNormal();
int16 strY = 0xbe - var_i16_7b6;
// 128:1056
@@ -812,7 +836,7 @@ void FoolGame::showChoiceModal(uint16 font, int16 lineCount, int16 buttonCount,
strY += 0x11;
}
// 128:10a0
- if (buttonCount != 0) {
+ if (hasButtons) {
_toolbox->PenNormal();
_zbasic->text(kFontChicago, 0xc, Graphics::kMacFontRegular, Graphics::MacToolbox::kSrcOr);
@@ -948,6 +972,12 @@ void FoolGame::showChoiceModal(uint16 font, int16 lineCount, int16 buttonCount,
sub_128_61ec();
copyScreen(1, arr_bmp_138bc);
_toolbox->SetPort(var_i32_0);
+ } else {
+ menuClickMessage();
+ waitForClick();
+ _toolbox->DrawMenuBar();
+ copyScreen(1, arr_bmp_138bc);
+ _toolbox->SetPort(var_i32_0);
}
// 128:1784
@@ -1062,7 +1092,7 @@ void FoolGame::sub_128_1f1e() {
// 128:1f1e
_toolbox->InitCursor();
toggleMouseCursor(false);
- sub_128_bde(1, 1, Graphics::MacToolbox::kSrcCopy, 1, 1, 1);
+ screenZap(1, 1, Graphics::MacToolbox::kSrcCopy, 1, 1, 1);
}
void FoolGame::sub_128_1f44() {
@@ -1187,8 +1217,8 @@ void FoolGame::storyRenderPage() {
// if we've solved a puzzle, fill the scroll with crazy patterns
if ((var_i16_7ce & 0x8) != 0) {
var_i16_7ce ^= 0x8;
- sub_128_bde(1, 0, Graphics::MacToolbox::kSrcCopy, 0, 1, 0);
- sub_128_bde(1, 0, Graphics::MacToolbox::kSrcCopy, 0, 0, 0);
+ screenZap(1, 0, Graphics::MacToolbox::kSrcCopy, 0, 1, 0);
+ screenZap(1, 0, Graphics::MacToolbox::kSrcCopy, 0, 0, 0);
}
// 128:235e
if (_puzzleType[_storyCurrentChapter] > 0) {
@@ -1349,7 +1379,7 @@ void FoolGame::writeSaveFile() {
if (var_i16_7e6 != 0) {
_modalText[0] = Common::U32String::format("The file '%s' cannot be opened.", var_str_588.encode().c_str()); // was: str(17), str(18)
_modalText[1] = Common::U32String("Okay"); // was: str(19)
- showChoiceModal(kFontChicago, 0, 1, 1);
+ showChoiceModal(kFontChicago, 0, 1, true, true);
var_str_588.clear(); // was: str(20)
var_i16_7e6 = 0;
}
@@ -1454,24 +1484,29 @@ void FoolGame::newGame() {
var_i16_9ec = 0;
// set up the initially visible story chapters
- arr_i16_4758[0] = 0x103;
- arr_i16_4758[1] = 0;
- arr_i16_4758[2] = 0x1e;
- arr_i16_4758[3] = 0x1fc;
- arr_i16_4758[4] = (int16)0xa050;
- arr_i16_4758[5] = 0x3f7;
- var_i16_484 = 0;
- for (int j = 0; j <= 0x5; j++) {
- // 128:2c5e
- for (int i = 0; i <= 0xf; i++) {
- var_i16_484++;
- if (arr_i16_4758[j] & _bitLUT[i]) {
- _pageVisible[var_i16_484] = 1;
- } else {
- // 128:2ca6
- _pageVisible[var_i16_484] = 0;
+ if (_isDemo) {
+ // the demo has a bunch of cut-down logic
+ // for starting a new game, but it does
+ // the rough equivalent of the below:
+ for (int16 j = 1; j <= _storyPageCount; j++) {
+ int16 chapter = _pageToChapter[j];
+ _pageVisible[j] = _demoChapters[chapter] ? 1 : 0;
+ }
+ } else {
+ arr_i16_4758[0] = 0x103;
+ arr_i16_4758[1] = 0;
+ arr_i16_4758[2] = 0x1e;
+ arr_i16_4758[3] = 0x1fc;
+ arr_i16_4758[4] = (int16)0xa050;
+ arr_i16_4758[5] = 0x3f7;
+ var_i16_484 = 0;
+ for (int j = 0; j <= 0x5; j++) {
+ // 128:2c5e
+ for (int i = 0; i <= 0xf; i++) {
+ var_i16_484++;
+ _pageVisible[var_i16_484] = (arr_i16_4758[j] & _bitLUT[i]) ? 1 : 0;
+ // 128:2cb6
}
- // 128:2cb6
}
}
// 128:2cce
@@ -1580,6 +1615,7 @@ void FoolGame::openGame() {
}
void FoolGame::menuSetup() {
+ // 128:3032
_storyCurrentChapter = 0;
_stateFlags = kStateNull;
var_i16_484 = 0;
@@ -1653,6 +1689,9 @@ void FoolGame::menuToggleSound() {
}
void FoolGame::savePrompt() {
+ if (_isDemo)
+ return;
+
// 128:32fa
if (var_i16_7ce == 666) {
return;
@@ -1670,7 +1709,7 @@ void FoolGame::savePrompt() {
_modalText[1] = Common::U32String("Yes");
_modalText[2] = Common::U32String("No");
_modalText[3] = Common::U32String("Cancel");
- showChoiceModal(kFontChicago, 0, 3, 0);
+ showChoiceModal(kFontChicago, 0, 3, false, true);
if (_savePromptChoice > 1) {
_saveFileName = previous;
return;
@@ -1694,6 +1733,8 @@ void FoolGame::autoSaveGame() {
// In general, ScummVM treats user-initated save games as a snapshot,
// and writes any automatic progress to a dedicated "Autosave" slot.
// This wrapper changes the autosave behaviour to match the rest of ScummVM.
+ if (_isDemo)
+ return;
_isAutoSaving = true;
Common::U32String previous = _saveFileName;
_saveFileName = Common::U32String::format("%s-Autosave.000", g_engine->getTarget().c_str());
@@ -1847,6 +1888,12 @@ void FoolGame::puzzleRun() {
puzzleLoadContext();
// 128:3a22
// 128:3a38: JSR - "ZBASIC_115"
+
+ if (_isDemo) {
+ // disable instructions
+ _zbasic->menu(2, 1, 0, Common::U32String());
+ }
+
debugC(5, kDebugLoading, "puzzleRun: chapter 0x%x, puzzle module %d", _storyCurrentChapter, _puzzleType[_storyCurrentChapter]-1);
switch (_puzzleType[_storyCurrentChapter]-1) {
case 0:
@@ -1910,6 +1957,28 @@ void FoolGame::puzzleRun() {
setStateBits(0x100);
return;
}
+ bool showDemoScreen = false;
+ if (_isDemo) {
+ // enable instructions
+ _zbasic->menu(2, 1, 1, Common::U32String());
+ // if the puzzle is solved, reset it and jump to the next chapter
+ if (_activePuzzleStatus >= 0x63) {
+ _activePuzzleStatus = 0;
+ _activePuzzleBuffer = Common::String();
+ var_i16_7ce |= 8;
+ showDemoScreen = true;
+ for (int16 i = _storyCurrentPage; i <= _storyPageCount; i++) {
+ if (_pageVisible[i] && (_pageToChapter[i] != _storyCurrentChapter)) {
+ _storyNextPage = i;
+ break;
+ }
+ }
+ if (_storyNextPage == _storyCurrentPage) {
+ _storyNextPage = 1;
+ }
+ }
+ }
+
// 128:3aa4
puzzleSaveContext();
if ((_stateFlags & kStateQuit) == 0) {
@@ -1989,6 +2058,8 @@ void FoolGame::puzzleRun() {
// 128:3de0
sub_128_61ec();
// 128:3de4
+ if (showDemoScreen)
+ demoPuzzleComplete();
}
void FoolGame::storyUnlockChapter() {
@@ -2058,8 +2129,8 @@ void FoolGame::puzzleSetupMenu() {
// New: Override instructions for card game.
// v3 changed the score from 700 points to 666 points, but didn't change the puzzle data
// file (where the menu entries come from). V3 applies a bodge with a program string.
- if ((_activePuzzle == 7) &&(i == _puzzleMenuInstructions[_puzzleType[_activePuzzle]*2]+7)) {
- instructMsg = Common::U32String("⢠The first player to earn over 666 points wins the game. ");
+ if ((_activePuzzle == 7) && (i == _puzzleMenuInstructions[_puzzleType[_activePuzzle]*2]+7)) {
+ instructMsg = Common::U32String::format("⢠The first player to earn over %d points wins the game. ", _cardsMaxScore);
}
_zbasic->menu(8, itemNo, 1, instructMsg);
@@ -2485,7 +2556,11 @@ void FoolGame::onMenuSelect() {
_stateFlags = kStateNull;
if (_selectedMenuID == 1) { // Eye menu
if (_selectedMenuItem == 2) {
- menuAbout();
+ if (_isDemo) {
+ menuDemoAbout();
+ } else {
+ menuAbout();
+ }
} else if (_selectedMenuItem == 3) {
menuPrologue();
} else if (_selectedMenuItem == 4) {
@@ -2494,13 +2569,21 @@ void FoolGame::onMenuSelect() {
}
if (_selectedMenuID == 2) { // File menu
if (_selectedMenuItem == 1) {
- menuNewGame();
+ if (_isDemo) {
+ menuDemoInstructions();
+ } else {
+ menuNewGame();
+ }
} else if (_selectedMenuItem == 2) {
// 128:5c5c
menuOpenGame();
} else if (_selectedMenuItem == 3) {
// 128:5c6c
- menuSaveGame();
+ if (_isDemo) {
+ menuQuit();
+ } else {
+ menuSaveGame();
+ }
} else if (_selectedMenuItem == 4) {
menuSaveGameAs();
} else if (_selectedMenuItem == 6) {
@@ -2703,9 +2786,9 @@ void FoolGame::sub_129_004() {
// 129:000a: LEA - 0x3ea(A5),A0
// 129:000e: MOVE.L - A0,-0x8ee(A5)
// 129:0012: SF - 0x8,D0
- _zbasic->openR(1, Common::U32String("Fool's Puzzles"), 0x3e8, var_i16_e20); // was: str(110)
+ _zbasic->openR(1, _puzzlesPath, 0x3e8, var_i16_e20); // was: str(110)
if (var_i16_7e6 == 0) {
- var_str_e22 = Common::U32String("Fool's Puzzles"); // was: str(111)
+ var_str_e22 = _puzzlesPath; // was: str(111)
var_i16_f22 = var_i16_e20;
_zbasic->close(1);
var_i16_7e6 = 0;
@@ -2818,7 +2901,7 @@ void FoolGame::sub_129_068() {
_modalText[1] = Common::U32String("2 color black and white");
_modalText[2] = Common::U32String("and start the game again.");
_modalText[3] = Common::U32String("Okay");
- showChoiceModal(kFontChicago, 2, 1, 0);
+ showChoiceModal(kFontChicago, 2, 1, false, true);
_zbasic->unk_4();
}
// 129:0390
@@ -2834,7 +2917,7 @@ void FoolGame::sub_129_068() {
_modalText[4] = Common::U32String("for possible solutions.");
_modalText[5] = Common::U32String();
_modalText[6] = Common::U32String("Quit");
- showChoiceModal(kFontChicago, 5, 1, 1);
+ showChoiceModal(kFontChicago, 5, 1, true, true);
_zbasic->unk_4();
}
// 129:0496
@@ -2850,8 +2933,8 @@ void FoolGame::sub_129_068() {
//var_i16_484 = _zbasic->finderInfo(var_i16_7e4, var_str_588, var_i32_f28, var_i16_688);
var_str_588 = _startSaveFileName;
if (!var_str_588.empty()) { // was: str(126)
- if (var_str_588 == Common::U32String("Fool's Puzzles")) { // was: str(127)
- var_str_e22 = Common::U32String("Fool's Puzzles"); // was: str(128)
+ if (var_str_588 == _puzzlesPath) { // was: str(127)
+ var_str_e22 = _puzzlesPath; // was: str(128)
var_i16_f22 = var_i16_688;
} else {
// 129:052e
@@ -2901,7 +2984,7 @@ void FoolGame::sub_129_068() {
}
var_str_e22 = var_str_588;
var_i16_f22 = var_i16_688;
- } while (var_str_e22 != Common::U32String("Fool's Puzzles")); // was: str(139)
+ } while (var_str_e22 != _puzzlesPath); // was: str(139)
}
// 129:0718
setVolRefNum(var_i16_f22);
@@ -2963,7 +3046,7 @@ void FoolGame::sub_129_068() {
var_i32_c = _toolbox->GetIcon(0x101);
_toolbox->DetachResource(var_i32_c);
// 129:09c2: SF - 0x8,D0
- _zbasic->openR(1, Common::U32String("Fool's Puzzles"), 1000, var_i16_f22); // was: str(140)
+ _zbasic->openR(1, _puzzlesPath, 1000, var_i16_f22); // was: str(140)
var_i32_1036 = _zbasic->readFileDblInt(1);
_puzzleDataPtr = 0;
@@ -2976,6 +3059,17 @@ void FoolGame::sub_129_068() {
for (int i = 1; i <= 0x64; i++) {
_puzzleDataOffsets[i] = puzzlesReadLong();
}
+
+ // difference to the demo puzzle format??
+ if (_isDemo) {
+ // 129:069a in demo
+ for (int i = 1; i <= 0x50; i++) {
+ // saves to arr_i16_18f04
+ // corresponds to enabled puzzle IDs
+ _demoChapters[i] = puzzlesReadByte();
+ }
+ }
+
// 129:0a4e
// quickdraw patterns
// reworked slightly to fill the pattern buffer directly
@@ -3144,22 +3238,33 @@ void FoolGame::sub_129_068() {
_zbasic->menu(1, 0, 1, Common::U32String("~")); // wadjet eye, was: str(143)
_zbasic->menu(1, 1, 0, Common::U32String("-"));
_zbasic->menu(1, 2, 1, Common::U32String("/FAbout Fool's Errand"));
- // this is brand new
- _zbasic->menu(1, 3, 1, Common::U32String("Show Prologue"));
- _zbasic->menu(1, 4, 0, Common::U32String("Show Finale"));
- _zbasic->menu(1, 5, 0, Common::U32String("-"));
+ if (_isDemo) {
+ _zbasic->menu(1, 3, 0, Common::U32String("-"));
+ } else {
+ // this is brand new
+ _zbasic->menu(1, 3, 1, Common::U32String("Show Prologue"));
+ _zbasic->menu(1, 4, 0, Common::U32String("Show Finale"));
+ _zbasic->menu(1, 5, 0, Common::U32String("-"));
+ }
// File menu
- _zbasic->menu(2, 0, 1, Common::U32String("File"));
- _zbasic->menu(2, 1, 1, Common::U32String("/NNew"));
- _zbasic->menu(2, 2, 1, Common::U32String("/OOpen"));
- _zbasic->menu(2, 3, 1, Common::U32String("/SSave"));
- _zbasic->menu(2, 4, 1, Common::U32String("/ASave As"));
- _zbasic->menu(2, 5, 0, Common::U32String("-"));
- _zbasic->menu(2, 6, 1, Common::U32String("Sound"));
- _zbasic->menu(2, 7, 1, Common::U32String("Print Story"));
- _zbasic->menu(2, 8, 0, Common::U32String("-"));
- _zbasic->menu(2, 9, 1, Common::U32String("/QQuit"));
+ if (_isDemo) {
+ _zbasic->menu(2, 0, 1, Common::U32String("Demonstration"));
+ _zbasic->menu(2, 1, 1, Common::U32String("/IInstructions"));
+ _zbasic->menu(2, 2, 0, Common::U32String("-"));
+ _zbasic->menu(2, 3, 1, Common::U32String("/QQuit"));
+ } else {
+ _zbasic->menu(2, 0, 1, Common::U32String("File"));
+ _zbasic->menu(2, 1, 1, Common::U32String("/NNew"));
+ _zbasic->menu(2, 2, 1, Common::U32String("/OOpen"));
+ _zbasic->menu(2, 3, 1, Common::U32String("/SSave"));
+ _zbasic->menu(2, 4, 1, Common::U32String("/ASave As"));
+ _zbasic->menu(2, 5, 0, Common::U32String("-"));
+ _zbasic->menu(2, 6, 1, Common::U32String("Sound"));
+ _zbasic->menu(2, 7, 1, Common::U32String("Print Story"));
+ _zbasic->menu(2, 8, 0, Common::U32String("-"));
+ _zbasic->menu(2, 9, 1, Common::U32String("/QQuit"));
+ }
sub_128_6244();
// 129:11f6
@@ -3184,7 +3289,7 @@ void FoolGame::menuLoadingMessage(int16 percent) {
fillRect(0, 7, 0x13, _windowWidth - 7, 0);
_zbasic->text(kFontChicago, 0xc, Graphics::kMacFontRegular, Graphics::MacToolbox::kSrcOr);
// Loading Game text during initial puzzle load
- Common::U32String message = Common::U32String::format("Loading Game - %d%%", percent); // was: str(158)
+ Common::U32String message = Common::U32String::format("Loading %s - %d%%", _isDemo ? "Demonstration" : "Game", percent); // was: str(158)
int16 width = _toolbox->StringWidth(message);
_toolbox->MoveTo((_windowWidth / 2) - (width / 2), 0xe);
_toolbox->DrawString(message);
@@ -3272,7 +3377,7 @@ void FoolGame::metapuzzleComplete() {
_modalText[4] = Common::U32String("Congratulations!");
_modalText[5] = Common::U32String("You may now view the finale.");
_modalText[6] = Common::U32String("Okay");
- showChoiceModal(kFontFool, 5, 1, 0);
+ showChoiceModal(kFontFool, 5, 1, false, true);
//if (!_screenOversized) {
// _toolbox->ClearMenuBar();
@@ -3305,4 +3410,76 @@ void FoolGame::metapuzzleComplete() {
copyScreen(1, _scrollPage);
}
+void FoolGame::demoPuzzleComplete() {
+ int instrOff = _zstrOffset[kOffsetDemoPuzzleComplete];
+
+ _modalText[0] = _zbasic->str(instrOff+0);
+ _modalText[1] = _zbasic->str(instrOff+1);
+ _modalText[2] = _zbasic->str(instrOff+2);
+ _modalText[3] = _zbasic->str(instrOff+3);
+ _modalText[4] = _zbasic->str(instrOff+4);
+ showChoiceModal(kFontFool, 4, 0, false, true);
+
+}
+
+void FoolGame::menuDemoAbout() {
+ int instrOff = _zstrOffset[kOffsetDemoInstructions];
+ // 128:2dbc in the demo code
+ // "the fool's errand is something new..."
+ _modalText[0] = _zbasic->str(instrOff+0);
+ _modalText[1] = _zbasic->str(instrOff+1);
+ _modalText[2] = _zbasic->str(instrOff+2);
+ _modalText[3] = _zbasic->str(instrOff+3);
+ _modalText[4] = _zbasic->str(instrOff+4);
+ _modalText[5] = _zbasic->str(instrOff+5);
+ _modalText[6] = _zbasic->str(instrOff+6);
+ _modalText[7] = _zbasic->str(instrOff+7);
+ _modalText[8] = _zbasic->str(instrOff+8);
+ _modalText[9] = _zbasic->str(instrOff+9);
+ showChoiceModal(kFontFool, 9, 0, false, false);
+ _modalText[0] = _zbasic->str(instrOff+10);
+ _modalText[1] = _zbasic->str(instrOff+11);
+ _modalText[2] = _zbasic->str(instrOff+12);
+ _modalText[3] = _zbasic->str(instrOff+13);
+ _modalText[4] = _zbasic->str(instrOff+14);
+ _modalText[5] = _zbasic->str(instrOff+15);
+ _modalText[6] = _zbasic->str(instrOff+16);
+ showChoiceModal(kFontFool, 6, 0, false, false);
+ _modalText[0] = _zbasic->str(instrOff+17);
+ _modalText[1] = _zbasic->str(instrOff+18);
+ _modalText[2] = _zbasic->str(instrOff+19);
+ _modalText[3] = _zbasic->str(instrOff+20);
+ _modalText[4] = _zbasic->str(instrOff+21);
+ showChoiceModal(kFontFool, 4, 0, false, false);
+}
+
+void FoolGame::menuDemoInstructions() {
+ // 128:309a in demo code
+ int instrOff = _zstrOffset[kOffsetDemoInstructions];
+ // "this demonstration contains a few samples..."
+ _modalText[0] = _zbasic->str(instrOff+22);
+ _modalText[1] = _zbasic->str(instrOff+23);
+ _modalText[2] = _zbasic->str(instrOff+24);
+ showChoiceModal(kFontChicago, 2, 0, false, false);
+ _modalText[0] = _zbasic->str(instrOff+25);
+ _modalText[1] = _zbasic->str(instrOff+26);
+ _modalText[2] = _zbasic->str(instrOff+27);
+ _modalText[3] = _zbasic->str(instrOff+28);
+ _modalText[4] = _zbasic->str(instrOff+29);
+ _modalText[5] = _zbasic->str(instrOff+30);
+ _modalText[6] = _zbasic->str(instrOff+31);
+ _modalText[7] = _zbasic->str(instrOff+32);
+ _modalText[8] = _zbasic->str(instrOff+33);
+ showChoiceModal(kFontChicago, 8, 0, false, false);
+ _modalText[0] = _zbasic->str(instrOff+34);
+ _modalText[1] = _zbasic->str(instrOff+35);
+ _modalText[2] = _zbasic->str(instrOff+36);
+ _modalText[3] = _zbasic->str(instrOff+37);
+ _modalText[4] = _zbasic->str(instrOff+38);
+ _modalText[5] = _zbasic->str(instrOff+39);
+ _modalText[6] = _zbasic->str(instrOff+40);
+ _modalText[7] = _zbasic->str(instrOff+41);
+ showChoiceModal(kFontChicago, 7, 0, false, false);
+}
+
} // End of namespace Fool
diff --git a/engines/fool/fool_game.h b/engines/fool/fool_game.h
index 118c095d226..8c9468f1398 100644
--- a/engines/fool/fool_game.h
+++ b/engines/fool/fool_game.h
@@ -94,6 +94,8 @@ enum FoolZStrOffset : uint16 {
kOffsetFinale,
kOffsetPrologueMemory,
kOffsetPrologueClick,
+ kOffsetDemoInstructions,
+ kOffsetDemoPuzzleComplete,
};
enum FoolFontID : uint16 {
@@ -133,10 +135,10 @@ public:
void fillRect(int16 top, int16 left, int16 bottom, int16 right, int16 patternID); // sub_128_8b4
void drawTextCenter(const Common::U32String &str, int16 yPos); // sub_128_918
void zoomRect(int16 startTop, int16 startLeft, int16 startBottom, int16 startRight, int16 endTop, int16 endLeft, int16 endBottom, int16 endRight, int16 patternID, PatternMode mode, int16 steps); // sub_128_962
- void sub_128_bde(int16 unk6, int16 unk5, int16 unk4, int16 unk3, int16 unk2, int16 unk1);
+ void screenZap(int16 unk6, int16 unk5, int16 unk4, int16 unk3, int16 unk2, int16 unk1); // sub_128_bde
void getNextEvent(int32 mask); // sub_128_c6a
void flashRect(int16 top, int16 left, int16 bottom, int16 right, int16 millis); // sub_128_d34
- void showChoiceModal(uint16 font, int16 lineCount, int16 buttonCount, bool beep); // sub_128_dfe
+ void showChoiceModal(uint16 font, int16 lineCount, int16 buttonCount, bool beep, bool dark); // sub_128_dfe
void showBehold(int16 unk2, int16 unk1, const Common::U32String &message); // sub_128_178a
void setStateBits(uint16 bits); // sub_128_1c2c
@@ -211,6 +213,10 @@ public:
void sub_129_068();
void menuLoadingMessage(int16 percent); // sub_129_123a
+ void menuDemoAbout();
+ void menuDemoInstructions();
+ void demoPuzzleComplete();
+
// fool_jumble.cpp:
void jumbleRun();
void jumbleSave(); // sub_130_c56
@@ -469,6 +475,9 @@ public:
private:
FoolVersion _version;
+ Common::U32String _puzzlesPath;
+ bool _isDemo;
+ int _cardsMaxScore;
const int *_zstrOffset;
Toolbox *_toolbox;
ZBasic *_zbasic;
@@ -816,6 +825,9 @@ private:
Common::U32String _modalText[13]; // arr_str_1a8d8, 0x66 each
Common::Rect _screenClipRect; // arr_rect_1ae06
+
+ // demo only
+ int16 _demoChapters[101]; // arr_i16_18f04
};
}
diff --git a/engines/fool/fool_justice.cpp b/engines/fool/fool_justice.cpp
index 9ad398126cd..876aff1853e 100644
--- a/engines/fool/fool_justice.cpp
+++ b/engines/fool/fool_justice.cpp
@@ -41,6 +41,10 @@ void FoolGame::justiceRun() {
}
// 142:0874
justiceResetGrid();
+ if (_isDemo) {
+ _activePuzzleStatus = 0x63;
+ return;
+ }
if (_puzzleCompletionStatus[0x34] > 3) {
_activePuzzleStatus = 0x64;
return;
@@ -83,7 +87,7 @@ void FoolGame::justiceSetup() {
_zbasic->indexRawSet(puzzlesReadString(), 1, i);
}
// 142:09ea
- if (_puzzleCompletionStatus[0x34] < 4) {
+ if (_isDemo || (_puzzleCompletionStatus[0x34] < 4)) {
_zbasic->menu(8, 3, 1, _zbasic->str(OFF(3))); // a secret hides here
_zbasic->menu(8, 4, 1, _zbasic->str(OFF(4))); // if twenty-five appear
} else {
@@ -110,7 +114,7 @@ void FoolGame::justiceSetup() {
justiceZoom();
fillRect(0x1a, 0x82, 0x128, 0x190, 2);
if (_activePuzzleBuffer.empty()) { // was: str(OFF(7))
- _activePuzzleBuffer = (_zbasic->space(0xc) + _zbasic->str(OFF(8)) + _zbasic->space(0xc)).encode(Common::kMacRoman); // 1
+ _activePuzzleBuffer = (_zbasic->space(0xc) + Common::U32String("1") + _zbasic->space(0xc)).encode(Common::kMacRoman); // was: str(OFF(8))
_justiceFirstMove = 1;
} else {
// 142:0b4c
@@ -121,10 +125,10 @@ void FoolGame::justiceSetup() {
for (int16 i = 1; i <= 0x19; i++) {
int16 drawData = _zbasic->castInt(_zbasic->midStr(_activePuzzleBuffer, i, 1));
if ((drawData & 2) == 0) {
- _zbasic->indexRawSet(_zbasic->strRaw(OFF(9)), 1, (i + 0x19)); // bullet
+ _zbasic->indexRawSet(Common::String("\xa5"), 1, (i + 0x19)); // bullet, was OFF(9)
} else {
// 142:0be0
- _zbasic->indexRawSet(_zbasic->strRaw(OFF(10)), 1, (i + 0x19)); // wadjet
+ _zbasic->indexRawSet(Common::String("~"), 1, (i + 0x19)); // wadjet, was OFF(10)
}
// 142:0c06
if ((drawData & 1) != 0) {
@@ -167,14 +171,14 @@ void FoolGame::justiceOnClick() {
}
// 142:0d56
_toolbox->InvertRoundRect(_screenGrid[gridIndex], 0x1e, 0x1e);
- if (_zbasic->index(1, gridIndex + 0x19) == _zbasic->str(OFF(11))) { // bullet
- _zbasic->indexSet(_zbasic->str(OFF(12)), 1, gridIndex + 0x19); // wadjet
+ if (_zbasic->indexRaw(1, gridIndex + 0x19) == Common::String("\xa5")) { // bullet, was OFF(11)
+ _zbasic->indexRawSet(Common::String("~"), 1, gridIndex + 0x19); // wadjet, was OFF(12)
}
// 142:0dc6
if (gridIndex == 0xd) { // center button
if (_justiceFirstMove == 0) {
for (int16 i = 1; i <= 0x19; i++) {
- _zbasic->indexSet(_zbasic->str(OFF(13)), 1, i + 0x19); // bullet
+ _zbasic->indexRawSet(Common::String("\xa5"), 1, i + 0x19); // bullet, was OFF(13)
arr_i16_3738[i] = 0;
justiceRemoveBlock(i);
}
@@ -189,7 +193,7 @@ void FoolGame::justiceOnClick() {
// 142:0e44
Common::String buffer = _zbasic->indexRaw(1, gridIndex);
int16 offset = 2;
- if (_zbasic->leftStr(buffer, 1) == _zbasic->str(OFF(14)).encode(Common::kMacRoman)) { // M
+ if (_zbasic->leftStr(buffer, 1) == Common::String("M")) { // was OFF(14)
gridIndex = _zbasic->decodeInt(_zbasic->midStr(buffer, 2, 2));
justiceDrawBlock(gridIndex);
offset = 5;
@@ -251,7 +255,7 @@ void FoolGame::justiceStoreState() {
_activePuzzleBuffer = Common::String::format("%d", _justiceFirstMove);
for (int16 i = 1; i <= 0x19; i++) {
int16 data = arr_i16_3738[i];
- if (_zbasic->index(1, i + 0x19) == _zbasic->str(OFF(15))) { // wadjet
+ if (_zbasic->indexRaw(1, i + 0x19) == Common::String("~")) { // wadjet, was OFF(15)
data |= 2;
}
_activePuzzleBuffer += Common::String::format("%d", data);
diff --git a/engines/fool/fool_maze.cpp b/engines/fool/fool_maze.cpp
index 93bcc94e1c3..dc59cf2cf49 100644
--- a/engines/fool/fool_maze.cpp
+++ b/engines/fool/fool_maze.cpp
@@ -79,7 +79,7 @@ void FoolGame::mazeRun() {
}
}
// 136:02ce
- sub_128_bde(1, arr_i16_1eb8[17], 0, 1, 0, 1);
+ screenZap(1, arr_i16_1eb8[17], 0, 1, 0, 1);
Common::Rect playArea;
playArea.top = _screenGrid[1].top + 3;
@@ -397,9 +397,10 @@ void FoolGame::mazeHotspot() {
var_i16_1cde = _zbasic->instr(var_i16_1cde, var_str_1ac8, _zbasic->strRaw(OFF(4))); // \xa5\xa5
if (var_i16_1cde > 0) {
// get command ID
+ int16 commandId = 0;
for (int16 i = 1; i <= (int16)var_str_1bde.size(); i++) {
if (_zbasic->midStr(var_str_1ac8, var_i16_1cde + 2, 1) == _zbasic->midStr(var_str_1bde, i, 1)) {
- var_i16_1a9a = i;
+ commandId = i;
}
// 136:0c4c
}
@@ -414,7 +415,7 @@ void FoolGame::mazeHotspot() {
var_i16_1cde = var_i16_1ce0;
}
// 136:0cec
- switch (var_i16_1a9a - 1) {
+ switch (commandId - 1) {
case 0: // C
mazePrintMessage();
break;
diff --git a/engines/fool/fool_polyomino.cpp b/engines/fool/fool_polyomino.cpp
index b129deaa989..95cc1eeb99d 100644
--- a/engines/fool/fool_polyomino.cpp
+++ b/engines/fool/fool_polyomino.cpp
@@ -220,7 +220,7 @@ void FoolGame::polyominoRun() {
}
}
// 133:073c
- sub_128_bde(1, arr_i16_1eb8[0xf], 0, 1, 1, 1);
+ screenZap(1, arr_i16_1eb8[0xf], 0, 1, 1, 1);
var_i16_1ab0 = 0;
for (var_i16_7cc = 1; var_i16_7cc <= arr_i16_1eb8[0x10]; var_i16_7cc++) {
polyominoMove(
diff --git a/engines/fool/fool_thoth.cpp b/engines/fool/fool_thoth.cpp
index 5247297492d..3bf052a8906 100644
--- a/engines/fool/fool_thoth.cpp
+++ b/engines/fool/fool_thoth.cpp
@@ -51,6 +51,11 @@ void FoolGame::highPriestessRun() {
// 140:0056
_activePuzzleStatus = 1;
}
+ if (_isDemo && _activePuzzleStatus) {
+ // demo, stop after solving the enchantments
+ _activePuzzleStatus = 0x64;
+ return;
+ }
// 140:005c
if (_activePuzzleStatus == 1) {
thothKey1st();
@@ -177,7 +182,8 @@ void FoolGame::thoth99Enchantments() {
// 140:0458
toggleMouseCursor(false);
if (_activePuzzleBuffer.empty()) { // was: str(OFF(6))
- arr_i16_1eb8[0] = 0x63;
+ // number of enchantments to start with
+ arr_i16_1eb8[0] = _isDemo ? 33 : 99;
} else {
arr_i16_1eb8[0] = _zbasic->decodeInt(_activePuzzleBuffer);
}
@@ -185,7 +191,7 @@ void FoolGame::thoth99Enchantments() {
if (arr_i16_1eb8[0] < 1) {
arr_i16_1eb8[0] = 1;
}
- if (arr_i16_1eb8[0] == 0x63) {
+ if (!_isDemo && (arr_i16_1eb8[0] == 99)) {
_zbasic->text(kFontLarge, 0x18, 0x10, Graphics::MacToolbox::kSrcBic);
drawTextCenter(_zbasic->str(OFF(7)), 0xaf); // you dare to challenge
drawTextCenter(_zbasic->str(OFF(8)), 0xd2); // the high priestess
@@ -258,7 +264,7 @@ void FoolGame::thoth99Enchantments() {
}
// 140:07c4
// Phase 1: enchantments 99 to 34 are inverting and don't move
- if (arr_i16_1eb8[0] >= 0x21) {
+ if (arr_i16_1eb8[0] > (_isDemo ? 13 : 33)) {
if ((arr_i16_1eb8[1] % 0xa) == 0) {
arr_i16_1eb8[2] = arr_i16_1eb8[0];
} else {
@@ -1011,6 +1017,10 @@ void FoolGame::hermitNextStage() {
if (_hermitPathStage == 4) {
hermitScreenZoom();
}
+ if (_isDemo && (_hermitPathStage >= 5)) {
+ _activePuzzleSolved = true;
+ return;
+ }
if (_hermitPathStage == 5) {
hermitScreenBehold();
}
More information about the Scummvm-git-logs
mailing list