[Scummvm-git-logs] scummvm branch-2-7 -> 33e6c4a45685983b616ed32d5b491710da1f5183
neuromancer
noreply at scummvm.org
Mon Jul 3 20:17:20 UTC 2023
This automated email contains information about 80 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
06a0bb0298 FREESCAPE: refactored on screen controller code to acept clicks outside the view area
7fbbe29aeb FREESCAPE: fix for correct implementation of demo mode in driller/dark
e3c10896a5 FREESCAPE: implemented timed condition executions from dark (and other games)
9ca691aec6 FREESCAPE: fixed potentially unitialized variable
62a2dd0125 FREESCAPE: parsed and added ECD for driller dos demo
5e74f0e025 FREESCAPE: better rendering of lines in OpenGL
8793df7b16 FREESCAPE: added ECDs for driller for dos
9967b61eaa FREESCAPE: added walls and simplified area change code for driller for dos
ef9b556cfa FREESCAPE: re-use loadGlobalObjects for different games
578330a20f FREESCAPE: initial implementation of the opengl shader renderer
1c763a01f9 FREESCAPE: renamed shaders filenames and added them into shader.dat
7049d28f3b FREESCAPE: implemented lines in shader renderer
8ceaf7831e FREESCAPE: implemented player shoot in shader renderer
119405cfb8 FREESCAPE: correctly deallocate shaders memory
e6d6946871 FREESCAPE: loading of title and border images in castle for dos
8ac1af2c57 FREESCAPE: show basic UI in castle for dos
ee1d083a4d FREESCAPE: properly initialize _verts in shader renderer
03e42d15d4 GRAPHICS: OPENGL: added another setUniform function to set an uniform value in shaders from an array of ints
f57126e2fc FREESCAPE: initial implementation of stipple patterns in shader renderer
f937d769b0 FREESCAPE: avoid crashing parsing driller conditions for zx
cb3c3e5002 FREESCAPE: improved rendering of stipple in shader renderer
fdce543286 FREESCAPE: fixed incorrect parsing of 8-bit conditions
8260ca8828 FREESCAPE: make triangle shader more compatible with gles2
1e28728f14 FREESCAPE: make triangle shader more compatible with gles2 (again)
7fe579351e FREESCAPE: added detection of some unsupported demos
e5d0ebefd7 FREESCAPE: initial support for Dark Side ZX demo
81ef1ec054 FREESCAPE: started to implemented Dark Side UI in ZX spectrum
0eae3fbde3 FREESCAPE: attempt to fix effect execution when stepping up
d18b4fd29d FREESCAPE: some fixes in the parsing of fcl opcodes
ea41d363b1 FREESCAPE: correctly print the SETVAR opcode
ee159b6a0e FREESCAPE: refactored clear code as drawBackground
c57029b8e8 FREESCAPE: improved image reading for castle in DOS/EGA
73391bffd7 FREESCAPE: improved border palette for castle in DOS/EGA
c8afca45ec FREESCAPE: make sure the floor is available in area 2 of castle
bccfe4eb0b FREESCAPE: better rendering of EGA colors in castle
99f9bb7eba FREESCAPE: allow to reset color pairs, useful in castle EGA
a42d72ad6e FREESCAPE: improved rendering of rectangles and fixes
ef88a9886f FREESCAPE: disallow zero length conditions
6963aad584 FREESCAPE: allow to parse conditions using the ACTIVATED trigger for castle
d342614658 FREESCAPE: basic support for control flow opcodes of castle
3a6fbca79c FREESCAPE: refactored conditional handling to make it work with castle
55d4acc6e7 FREESCAPE: added support for using different languages in castle (DOS)
746f694b63 FREESCAPE: added support for parsing (hardcoded) font for castle (DOS)
764eb59b8e FREESCAPE: refactored castle (DOS) to use drawDOSUI
9e2f4b760e FREESCAPE: initial support for castle demo (EGA)
9dbe3433aa FREESCAPE: expanded floor size
700c62949c FREESCAPE: initial detection of castle demo for amiga
626f6721d1 FREESCAPE: basic implementation of activation (only used in castle/crypt)
acf7e1e940 FREESCAPE: Fix -Wformat warnings
f4555942b0 FREESCAPE: new collision code
a68b228f59 FREESCAPE: remove spaces from area name when displaying info menu in driller
12e0332415 FREESCAPE: make sure end game area is properly renderer in driller
a7a4415acb FREESCAPE: palette fixes for driller cpc
e5747d3916 FREESCAPE: color remap fixes for driller cpc/amiga/atari
54d4dfc2a4 FREESCAPE: info menu fixes for driller zx/amiga/atari
0f7f13813b FREESCAPE: added missing items for driller cga palettes
0d01a9efdc FREESCAPE: improved handling of entrance usage
e96d2199c3 FREESCAPE: improved handling of rise/fall
d0f9025cb9 FREESCAPE: initial parsing and rendering of group objects
cbe4d4fd45 FREESCAPE: improved rendering and scaling of group objects
2ed383c0d2 FREESCAPE: adjust aabb tolerance for castle
c0995c3fa2 FREESCAPE: improved rendering of group animations
2bdef2ef42 FREESCAPE: added start animation opcode
1145730b6e FREESCAPE: improved parsing of castle demo for amiga
c9bd9c62de FREESCAPE: improved parsing of castle demo for amiga
ababd0da8e FREESCAPE: added code to decrypt dark for amiga/atari
8e675393dd FREESCAPE: added code to decrypt some driller releases for atari
82fd2ee5d4 FREESCAPE: added better detection of driller releases for atari
40b73a35a7 FREESCAPE: better detection of driller releases for atari
7593592c45 FREESCAPE: more precise timing of some fcl instructions
7d3fc01cd1 FREESCAPE: better code to transition between areas
4486477a93 FREESCAPE: correctly scale mouse position in opengl renderers
c36b35b28f FREESCAPE: fixes for driller demo
2d154c3b70 FREESCAPE: Fix typo
fd50a5586b FREESCAPE: enable on screen controls in driller for all the scummvm platforms
60945611b9 DRILLER: Remove newline from detection "extra" field
8ef39c1a0c FREESCAPE: Fix typos in detection "extra" field
60818c0e41 FREESCAPE: invert colors when rendering player shots in driller
4c71526352 FREESCAPE: added offsetOrigin function to avoid breaking setOrigin
33e6c4a456 FREESCAPE: initialize r, g and b variables in renderPlayerShoot
Commit: 06a0bb0298bc88abc12840910a4c6e7afd5316c3
https://github.com/scummvm/scummvm/commit/06a0bb0298bc88abc12840910a4c6e7afd5316c3
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: refactored on screen controller code to acept clicks outside the view area
Changed paths:
engines/freescape/freescape.cpp
engines/freescape/freescape.h
engines/freescape/games/driller/driller.cpp
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 4911e723dd5..49381e47078 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -501,10 +501,17 @@ void FreescapeEngine::processInput() {
case Common::EVENT_LBUTTONDOWN:
if (_hasFallen)
break;
- if (_viewArea.contains(_crossairPosition))
- shoot();
- else
- onScreenControls(_crossairPosition);
+ mousePos = event.mouse;
+ {
+ bool touchedScreenControls = false;
+
+ #if defined(__ANDROID__) || defined(IPHONE)
+ touchedScreenControls = onScreenControls(mousePos);
+ #endif
+
+ if (!touchedScreenControls && _viewArea.contains(_crossairPosition))
+ shoot();
+ }
break;
default:
@@ -513,7 +520,8 @@ void FreescapeEngine::processInput() {
}
}
-void FreescapeEngine::onScreenControls(Common::Point mouse) {
+bool FreescapeEngine::onScreenControls(Common::Point mouse) {
+ return false;
}
void FreescapeEngine::executeMovementConditions() {
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index daf46137bbc..2219aaba3ec 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -221,7 +221,7 @@ public:
void resetInput();
void generateDemoInput();
virtual void pressedKey(const int keycode);
- virtual void onScreenControls(Common::Point mouse);
+ virtual bool onScreenControls(Common::Point mouse);
void move(CameraMovement direction, uint8 scale, float deltaTime);
virtual void checkIfStillInArea();
void changePlayerHeight(int index);
@@ -485,7 +485,7 @@ private:
void drawCPCUI(Graphics::Surface *surface) override;
void drawC64UI(Graphics::Surface *surface) override;
void drawAmigaAtariSTUI(Graphics::Surface *surface) override;
- void onScreenControls(Common::Point mouse) override;
+ bool onScreenControls(Common::Point mouse) override;
void initAmigaAtari();
void initDOS();
void initZX();
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 90a0a65a030..4c6da3eefd0 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -819,32 +819,43 @@ bool DrillerEngine::checkIfGameEnded() {
return false;
}
-void DrillerEngine::onScreenControls(Common::Point mouse) {
- if (_moveFowardArea.contains(mouse))
+bool DrillerEngine::onScreenControls(Common::Point mouse) {
+ if (_moveFowardArea.contains(mouse)) {
move(kForwardMovement, _scaleVector.x(), 20.0);
- else if (_moveLeftArea.contains(mouse))
+ return true;
+ } else if (_moveLeftArea.contains(mouse)) {
move(kLeftMovement, _scaleVector.y(), 20.0);
- else if (_moveRightArea.contains(mouse))
+ return true;
+ } else if (_moveRightArea.contains(mouse)) {
move(kRightMovement, _scaleVector.y(), 20.0);
- else if (_moveBackArea.contains(mouse))
+ return true;
+ } else if (_moveBackArea.contains(mouse)) {
move(kBackwardMovement, _scaleVector.x(), 20.0);
- else if (_moveUpArea.contains(mouse))
+ return true;
+ } else if (_moveUpArea.contains(mouse)) {
rise();
- else if (_moveDownArea.contains(mouse))
+ return true;
+ } else if (_moveDownArea.contains(mouse)) {
lower();
- else if (_deployDrillArea.contains(mouse))
+ return true;
+ } else if (_deployDrillArea.contains(mouse)) {
pressedKey(Common::KEYCODE_d);
- else if (_infoScreenArea.contains(mouse))
+ return true;
+ } else if (_infoScreenArea.contains(mouse)) {
drawInfoMenu();
- else if (_saveGameArea.contains(mouse)) {
+ return true;
+ } else if (_saveGameArea.contains(mouse)) {
_gfx->setViewport(_fullscreenViewArea);
saveGameDialog();
_gfx->setViewport(_viewArea);
+ return true;
} else if (_loadGameArea.contains(mouse)) {
_gfx->setViewport(_fullscreenViewArea);
loadGameDialog();
_gfx->setViewport(_viewArea);
+ return true;
}
+ return false;
}
Commit: 7fbbe29aeb33836d69f1dcf1624bd6be365207d4
https://github.com/scummvm/scummvm/commit/7fbbe29aeb33836d69f1dcf1624bd6be365207d4
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: fix for correct implementation of demo mode in driller/dark
Changed paths:
engines/freescape/assets.cpp
engines/freescape/games/driller/driller.cpp
diff --git a/engines/freescape/assets.cpp b/engines/freescape/assets.cpp
index 309c30a424a..d9e6e16931e 100644
--- a/engines/freescape/assets.cpp
+++ b/engines/freescape/assets.cpp
@@ -63,9 +63,6 @@ void FreescapeEngine::loadAssetsDemo() {
loadAssetsDOSDemo();
} else
error("Unsupported demo for Driller");
-
- _demoMode = !_disableDemoMode;
- _angleRotationIndex = 0;
}
void FreescapeEngine::loadAssetsAtariDemo() {
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 4c6da3eefd0..490912727d5 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -78,6 +78,11 @@ DrillerEngine::DrillerEngine(OSystem *syst, const ADGameDescription *gd) : Frees
Math::Vector3d drillBaseSize = Math::Vector3d(3, 2, 3);
_drillBase = new GeometricObject(kCubeType, 0, 0, drillBaseOrigin, drillBaseSize, nullptr, nullptr, FCLInstructionVector(), "");
assert(!_drillBase->isDestroyed() && !_drillBase->isInvisible());
+
+ if (isDemo()) {
+ _demoMode = !_disableDemoMode; // All the driller demos are non-interactive
+ _angleRotationIndex = 0;
+ }
}
DrillerEngine::~DrillerEngine() {
Commit: e3c10896a5b4b45344778aecfe27aaf2f82d18cf
https://github.com/scummvm/scummvm/commit/e3c10896a5b4b45344778aecfe27aaf2f82d18cf
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: implemented timed condition executions from dark (and other games)
Changed paths:
engines/freescape/freescape.cpp
engines/freescape/freescape.h
engines/freescape/games/dark/dark.cpp
engines/freescape/language/8bitDetokeniser.cpp
engines/freescape/language/instruction.cpp
engines/freescape/movement.cpp
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 49381e47078..661a2db9dff 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -526,7 +526,7 @@ bool FreescapeEngine::onScreenControls(Common::Point mouse) {
void FreescapeEngine::executeMovementConditions() {
// Only execute "on collision" room/global conditions
- executeLocalGlobalConditions(false, true);
+ executeLocalGlobalConditions(false, true, false);
}
void FreescapeEngine::updateTimeVariables() {
@@ -537,7 +537,7 @@ void FreescapeEngine::updateTimeVariables() {
_lastMinute = minutes;
_gameStateVars[0x1e] += 1;
_gameStateVars[0x1f] += 1;
- executeLocalGlobalConditions(false, true); // Only execute "on collision" room/global conditions
+ executeLocalGlobalConditions(false, true, false); // Only execute "on collision" room/global conditions
}
}
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 2219aaba3ec..ae3a2f8dc0b 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -276,8 +276,8 @@ public:
Math::Vector3d _objExecutingCodeSize;
virtual void executeMovementConditions();
void executeObjectConditions(GeometricObject *obj, bool shot, bool collided);
- void executeLocalGlobalConditions(bool shot, bool collided);
- void executeCode(FCLInstructionVector &code, bool shot, bool collided);
+ void executeLocalGlobalConditions(bool shot, bool collided, bool timer);
+ void executeCode(FCLInstructionVector &code, bool shot, bool collided, bool timer);
// Instructions
void executeIncrementVariable(FCLInstruction &instruction);
@@ -531,7 +531,6 @@ public:
int _lastTenSeconds;
void updateTimeVariables() override;
- void executeMovementConditions() override;
void drawDOSUI(Graphics::Surface *surface) override;
void drawFullscreenMessage(Common::String message);
diff --git a/engines/freescape/games/dark/dark.cpp b/engines/freescape/games/dark/dark.cpp
index d628c4d4ef5..1165f60243b 100644
--- a/engines/freescape/games/dark/dark.cpp
+++ b/engines/freescape/games/dark/dark.cpp
@@ -201,27 +201,20 @@ void DarkEngine::checkIfStillInArea() {
FreescapeEngine::checkIfStillInArea();
}
-void DarkEngine::executeMovementConditions() {
- // Only execute "on collision" room/global conditions
- if (_currentArea->getAreaFlags() == 1)
- executeLocalGlobalConditions(false, true);
-}
-
void DarkEngine::updateTimeVariables() {
// This function only executes "on collision" room/global conditions
int seconds, minutes, hours;
getTimeFromCountdown(seconds, minutes, hours);
if (_lastTenSeconds != seconds / 10) {
_lastTenSeconds = seconds / 10;
- if (_currentArea->getAreaFlags() == 0)
- executeLocalGlobalConditions(false, true);
+ executeLocalGlobalConditions(false, false, true);
}
if (_lastMinute != minutes) {
_lastMinute = minutes;
_gameStateVars[0x1e] += 1;
_gameStateVars[0x1f] += 1;
- executeLocalGlobalConditions(false, true);
+ executeLocalGlobalConditions(false, true, false);
}
}
diff --git a/engines/freescape/language/8bitDetokeniser.cpp b/engines/freescape/language/8bitDetokeniser.cpp
index 06fe20c56ab..187c46f1b48 100644
--- a/engines/freescape/language/8bitDetokeniser.cpp
+++ b/engines/freescape/language/8bitDetokeniser.cpp
@@ -39,9 +39,8 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
Common::Array<uint8>::size_type sizeOfTokenisedContent = tokenisedCondition.size();
// on the 8bit platforms, all instructions have a conditional flag;
- // we'll want to convert them into runs of "if shot? then" and "if collided? then",
+ // we'll want to convert them into runs of "if shot? then", "if collided? then" or "if timer? then",
// and we'll want to start that from the top
- uint8 conditionalIsShot = 0x1;
FCLInstructionVector *conditionalInstructions = new FCLInstructionVector();
FCLInstruction currentInstruction;
@@ -55,30 +54,42 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
0, 0, 0, 0, 0, 0, 2, 2,
1};
+ detokenisedStream += Common::String::format("CONDITION FLAG: %x\n", tokenisedCondition[0]);
+ Token::Type newConditional;
+ Token::Type oldConditional;
+
while (bytePointer < sizeOfTokenisedContent) {
// get the conditional type of the next operation
- uint8 newConditionalIsShot = tokenisedCondition[bytePointer] & 0x80;
+ uint8 conditionalByte = tokenisedCondition[bytePointer];
+
+ if (conditionalByte & 0x80)
+ newConditional = Token::SHOTQ;
+ else if (conditionalByte & 0x40)
+ newConditional = Token::TIMERQ;
+ else
+ newConditional = Token::COLLIDEDQ;
// if the conditional type has changed then end the old conditional,
// if we were in one, and begin a new one
- if (newConditionalIsShot != conditionalIsShot) {
+ if (bytePointer == 0 || newConditional != oldConditional) {
+ oldConditional = newConditional;
FCLInstruction branch;
- if (conditionalIsShot)
- branch = FCLInstruction(Token::SHOTQ);
- else
- branch = FCLInstruction(Token::COLLIDEDQ);
+ branch = FCLInstruction(oldConditional);
branch.setBranches(conditionalInstructions, nullptr);
instructions.push_back(branch);
- conditionalIsShot = newConditionalIsShot;
- if (bytePointer)
+ if (bytePointer > 0)
detokenisedStream += "ENDIF\n";
- if (conditionalIsShot)
+ if (oldConditional == Token::SHOTQ)
detokenisedStream += "IF SHOT? THEN\n";
- else
+ else if (oldConditional == Token::TIMERQ)
+ detokenisedStream += "IF TIMER? THEN\n";
+ else if (oldConditional == Token::COLLIDEDQ)
detokenisedStream += "IF COLLIDED? THEN\n";
+ else
+ error("Invalid conditional: %x", oldConditional);
// Allocate the next vector of instructions
conditionalInstructions = new FCLInstructionVector();
@@ -415,10 +426,7 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
// conditionalInstructions->push_back(currentInstruction);
FCLInstruction branch;
- if (conditionalIsShot)
- branch = FCLInstruction(Token::SHOTQ);
- else
- branch = FCLInstruction(Token::COLLIDEDQ);
+ branch = FCLInstruction(oldConditional);
branch.setBranches(conditionalInstructions, nullptr);
instructions.push_back(branch);
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index 2f68554d9cb..a528ec48275 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -72,11 +72,11 @@ void FreescapeEngine::executeObjectConditions(GeometricObject *obj, bool shot, b
_firstSound = true;
_objExecutingCodeSize = obj->getSize();
debugC(1, kFreescapeDebugCode, "Executing with collision flag: %s", obj->_conditionSource.c_str());
- executeCode(obj->_condition, shot, collided);
+ executeCode(obj->_condition, shot, collided, false); // TODO: check this last parameter
}
}
-void FreescapeEngine::executeLocalGlobalConditions(bool shot, bool collided) {
+void FreescapeEngine::executeLocalGlobalConditions(bool shot, bool collided, bool timer) {
if (isCastle())
return;
debugC(1, kFreescapeDebugCode, "Executing room conditions");
@@ -85,17 +85,17 @@ void FreescapeEngine::executeLocalGlobalConditions(bool shot, bool collided) {
for (uint i = 0; i < conditions.size(); i++) {
debugC(1, kFreescapeDebugCode, "%s", conditionSources[i].c_str());
- executeCode(conditions[i], shot, collided);
+ executeCode(conditions[i], shot, collided, timer);
}
debugC(1, kFreescapeDebugCode, "Executing global conditions (%d)", _conditions.size());
for (uint i = 0; i < _conditions.size(); i++) {
debugC(1, kFreescapeDebugCode, "%s", _conditionSources[i].c_str());
- executeCode(_conditions[i], shot, collided);
+ executeCode(_conditions[i], shot, collided, timer);
}
}
-void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool collided) {
+void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool collided, bool timer) {
assert(!(shot && collided));
int ip = 0;
int codeSize = code.size();
@@ -109,13 +109,19 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
break;
case Token::COLLIDEDQ:
if (collided)
- executeCode(*instruction._thenInstructions, shot, collided);
+ executeCode(*instruction._thenInstructions, shot, collided, timer);
// else branch is always empty
assert(instruction._elseInstructions == nullptr);
break;
case Token::SHOTQ:
if (shot)
- executeCode(*instruction._thenInstructions, shot, collided);
+ executeCode(*instruction._thenInstructions, shot, collided, timer);
+ // else branch is always empty
+ assert(instruction._elseInstructions == nullptr);
+ break;
+ case Token::TIMERQ:
+ if (timer)
+ executeCode(*instruction._thenInstructions, shot, collided, timer);
// else branch is always empty
assert(instruction._elseInstructions == nullptr);
break;
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index c9055e80248..f914780359e 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -92,7 +92,7 @@ void FreescapeEngine::shoot() {
executeObjectConditions(gobj, true, false);
}
- executeLocalGlobalConditions(true, false); // Only execute "on shot" room/global conditions
+ executeLocalGlobalConditions(true, false, false); // Only execute "on shot" room/global conditions
}
void FreescapeEngine::changePlayerHeight(int index) {
Commit: 9ca691aec601784f5ab0e4781b16b850358bef70
https://github.com/scummvm/scummvm/commit/9ca691aec601784f5ab0e4781b16b850358bef70
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: fixed potentially unitialized variable
Changed paths:
engines/freescape/language/8bitDetokeniser.cpp
diff --git a/engines/freescape/language/8bitDetokeniser.cpp b/engines/freescape/language/8bitDetokeniser.cpp
index 187c46f1b48..6b00ecc926e 100644
--- a/engines/freescape/language/8bitDetokeniser.cpp
+++ b/engines/freescape/language/8bitDetokeniser.cpp
@@ -55,8 +55,8 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
1};
detokenisedStream += Common::String::format("CONDITION FLAG: %x\n", tokenisedCondition[0]);
- Token::Type newConditional;
- Token::Type oldConditional;
+ Token::Type newConditional = Token::UNKNOWN;
+ Token::Type oldConditional = Token::UNKNOWN;
while (bytePointer < sizeOfTokenisedContent) {
// get the conditional type of the next operation
Commit: 62a2dd012598aab028e89f9cfaa6a5ca263a8b09
https://github.com/scummvm/scummvm/commit/62a2dd012598aab028e89f9cfaa6a5ca263a8b09
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: parsed and added ECD for driller dos demo
Changed paths:
engines/freescape/freescape.h
engines/freescape/games/dark/dark.cpp
engines/freescape/games/dark/dos.cpp
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index ae3a2f8dc0b..d1c96cf705c 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -539,6 +539,8 @@ public:
private:
void loadGlobalObjects(Common::SeekableReadStream *file, int offset);
+ void addECDs(Area *area);
+ void addECD(Area *area, const Math::Vector3d position, int index);
};
class EclipseEngine : public FreescapeEngine {
diff --git a/engines/freescape/games/dark/dark.cpp b/engines/freescape/games/dark/dark.cpp
index 1165f60243b..48bee2a33ba 100644
--- a/engines/freescape/games/dark/dark.cpp
+++ b/engines/freescape/games/dark/dark.cpp
@@ -23,6 +23,7 @@
#include "freescape/freescape.h"
#include "freescape/language/8bitDetokeniser.h"
+#include "freescape/objects/global.h"
#include "freescape/objects/connections.h"
namespace Freescape {
@@ -65,7 +66,7 @@ void DarkEngine::loadGlobalObjects(Common::SeekableReadStream *file, int offset)
assert(!_areaMap.contains(255));
ObjectMap *globalObjectsByID = new ObjectMap;
file->seek(offset);
- for (int i = 0; i < 22; i++) {
+ for (int i = 0; i < 23; i++) {
Object *gobj = load8bitObject(file);
assert(gobj);
assert(!globalObjectsByID->contains(gobj->getObjectID()));
@@ -76,6 +77,48 @@ void DarkEngine::loadGlobalObjects(Common::SeekableReadStream *file, int offset)
_areaMap[255] = new Area(255, 0, globalObjectsByID, nullptr);
}
+void DarkEngine::addECDs(Area *area) {
+ GlobalStructure *rs = (GlobalStructure *)area->entranceWithID(255);
+ debugC(1, kFreescapeDebugParser, "ECD positions:");
+ for (uint i = 0; i < rs->_structure.size(); i = i + 3) {
+ int x = 32 * rs->_structure[i];
+ int y = 32 * rs->_structure[i + 1];
+ int z = 32 * rs->_structure[i + 2];
+
+ debugC(1, kFreescapeDebugParser, "%d %d %d", x, y, z);
+ if (x == 0 && y == 0 && z == 0) {
+ debugC(1, kFreescapeDebugParser, "Skiping ECD zero position");
+ continue;
+ }
+ addECD(area, Math::Vector3d(x, y, z), i / 3);
+ }
+}
+
+void DarkEngine::addECD(Area *area, const Math::Vector3d position, int index) {
+ GeometricObject *obj = nullptr;
+ Math::Vector3d origin = position;
+
+ int16 id = 227 + index * 6;
+ int heightLastObject = 0;
+ for (int i = 0; i < 4; i++) {
+ debugC(1, kFreescapeDebugParser, "Adding object %d to room structure", id);
+ obj = (GeometricObject *)_areaMap[255]->objectWithID(id);
+ assert(obj);
+ // Set position for object
+ origin.setValue(0, origin.x());
+ origin.setValue(1, origin.y() + heightLastObject);
+ origin.setValue(2, origin.z());
+
+ obj = (GeometricObject *)obj->duplicate();
+ obj->setOrigin(origin);
+ obj->makeVisible();
+ area->addObject(obj);
+
+ heightLastObject = obj->getSize().y();
+ id--;
+ }
+}
+
void DarkEngine::initGameState() {
_flyMode = false;
_noClipMode = false;
diff --git a/engines/freescape/games/dark/dos.cpp b/engines/freescape/games/dark/dos.cpp
index 24c4396d079..220d6c3cabd 100644
--- a/engines/freescape/games/dark/dos.cpp
+++ b/engines/freescape/games/dark/dos.cpp
@@ -48,6 +48,12 @@ void DarkEngine::loadAssetsDOSDemo() {
load8bitBinary(&file, 0xa700, 16);
_border = load8bitBinImage(&file, 0x210);
_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
+
+ for (auto &it : _areaMap) {
+ if (!it._value->entranceWithID(255))
+ continue;
+ addECDs(it._value);
+ }
} else if (_renderMode == Common::kRenderCGA) {
//loadBundledImages();
file.open("DSIDEC.EXE");
Commit: 5e74f0e02535316b003bbb62a9634e66dedf7aed
https://github.com/scummvm/scummvm/commit/5e74f0e02535316b003bbb62a9634e66dedf7aed
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: better rendering of lines in OpenGL
Changed paths:
engines/freescape/gfx_opengl.cpp
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index 2848f48e9fb..0c09bb0f5ba 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -243,7 +243,9 @@ void OpenGLRenderer::renderFace(const Common::Array<Math::Vector3d> &vertices) {
copyToVertexArray(0, v0);
copyToVertexArray(1, v1);
glVertexPointer(3, GL_FLOAT, 0, _verts);
+ glLineWidth(MAX(1, g_system->getWidth() / 192));
glDrawArrays(GL_LINES, 0, 2);
+ glLineWidth(1);
glDisableClientState(GL_VERTEX_ARRAY);
return;
}
Commit: 8793df7b16f6610ea5d1960622c39c05465c3ced
https://github.com/scummvm/scummvm/commit/8793df7b16f6610ea5d1960622c39c05465c3ced
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: added ECDs for driller for dos
Changed paths:
engines/freescape/games/dark/dos.cpp
diff --git a/engines/freescape/games/dark/dos.cpp b/engines/freescape/games/dark/dos.cpp
index 220d6c3cabd..55c19ce6c5d 100644
--- a/engines/freescape/games/dark/dos.cpp
+++ b/engines/freescape/games/dark/dos.cpp
@@ -88,11 +88,11 @@ void DarkEngine::loadAssetsDOSFullGame() {
_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
// TODO: load objects
- /*for (auto &it : _areaMap) {
+ for (auto &it : _areaMap) {
if (!it._value->entranceWithID(255))
continue;
- it._value->addStructure(_areaMap[255]);
- }*/
+ addECDs(it._value);
+ }
} else if (_renderMode == Common::kRenderCGA) {
loadBundledImages();
file.open("DSIDEC.EXE");
Commit: 9967b61eaaa0065d9aa42637fff0e183ffacb193
https://github.com/scummvm/scummvm/commit/9967b61eaaa0065d9aa42637fff0e183ffacb193
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: added walls and simplified area change code for driller for dos
Changed paths:
engines/freescape/freescape.h
engines/freescape/games/dark/dark.cpp
engines/freescape/games/dark/dos.cpp
engines/freescape/language/8bitDetokeniser.cpp
engines/freescape/language/instruction.cpp
engines/freescape/language/instruction.h
engines/freescape/objects/geometricobject.cpp
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index d1c96cf705c..f8c7c95a376 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -522,7 +522,6 @@ public:
void titleScreen() override;
void gotoArea(uint16 areaID, int entranceID) override;
- void checkIfStillInArea() override;
void pressedKey(const int keycode) override;
void executePrint(FCLInstruction &instruction) override;
@@ -541,6 +540,7 @@ private:
void loadGlobalObjects(Common::SeekableReadStream *file, int offset);
void addECDs(Area *area);
void addECD(Area *area, const Math::Vector3d position, int index);
+ void addWalls(Area *area);
};
class EclipseEngine : public FreescapeEngine {
diff --git a/engines/freescape/games/dark/dark.cpp b/engines/freescape/games/dark/dark.cpp
index 48bee2a33ba..b0d5a396340 100644
--- a/engines/freescape/games/dark/dark.cpp
+++ b/engines/freescape/games/dark/dark.cpp
@@ -78,6 +78,9 @@ void DarkEngine::loadGlobalObjects(Common::SeekableReadStream *file, int offset)
}
void DarkEngine::addECDs(Area *area) {
+ if (!area->entranceWithID(255))
+ return;
+
GlobalStructure *rs = (GlobalStructure *)area->entranceWithID(255);
debugC(1, kFreescapeDebugParser, "ECD positions:");
for (uint i = 0; i < rs->_structure.size(); i = i + 3) {
@@ -94,6 +97,29 @@ void DarkEngine::addECDs(Area *area) {
}
}
+void DarkEngine::addWalls(Area *area) {
+ if (!area->entranceWithID(254))
+ return;
+
+ AreaConnections *cons = (AreaConnections *)area->entranceWithID(254);
+ debugC(1, kFreescapeDebugParser, "Adding walls for area %d:", area->getAreaID());
+ int id = 240;
+ for (uint i = 1; i < cons->_connections.size(); i = i + 2) {
+ int target = cons->_connections[i];
+ debugC(1, kFreescapeDebugParser, "Connection to %d using id: %d", target, id);
+ if (target > 0) {
+ area->addObjectFromArea(id, _areaMap[255]);
+ GeometricObject *gobj = (GeometricObject *)area->objectWithID(id);
+ assert((*(gobj->_condition[1]._thenInstructions))[0].getType() == Token::Type::GOTO);
+ assert((*(gobj->_condition[1]._thenInstructions))[0]._destination == 0);
+ (*(gobj->_condition[1]._thenInstructions))[0].setSource(target);
+ } else
+ area->addObjectFromArea(id + 1, _areaMap[255]);
+
+ id = id + 2;
+ }
+}
+
void DarkEngine::addECD(Area *area, const Math::Vector3d position, int index) {
GeometricObject *obj = nullptr;
Math::Vector3d origin = position;
@@ -220,30 +246,6 @@ void DarkEngine::pressedKey(const int keycode) {
}
}
-void DarkEngine::checkIfStillInArea() {
- AreaConnections *cons = (AreaConnections *)_currentArea->entranceWithID(254);
- if (!cons) {
- FreescapeEngine::checkIfStillInArea();
- return;
- }
-
- int nextAreaID = 0;
-
- if (_position.z() >= 4064 - 16)
- nextAreaID = cons->_connections[1];
- else if (_position.x() >= 4064 - 16)
- nextAreaID = cons->_connections[3];
- else if (_position.z() <= 16)
- nextAreaID = cons->_connections[5];
- else if (_position.x() <= 16)
- nextAreaID = cons->_connections[7];
-
- if (nextAreaID > 0)
- gotoArea(nextAreaID, 0);
- else
- FreescapeEngine::checkIfStillInArea();
-}
-
void DarkEngine::updateTimeVariables() {
// This function only executes "on collision" room/global conditions
int seconds, minutes, hours;
diff --git a/engines/freescape/games/dark/dos.cpp b/engines/freescape/games/dark/dos.cpp
index 55c19ce6c5d..b7b22563665 100644
--- a/engines/freescape/games/dark/dos.cpp
+++ b/engines/freescape/games/dark/dos.cpp
@@ -50,8 +50,7 @@ void DarkEngine::loadAssetsDOSDemo() {
_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
for (auto &it : _areaMap) {
- if (!it._value->entranceWithID(255))
- continue;
+ addWalls(it._value);
addECDs(it._value);
}
} else if (_renderMode == Common::kRenderCGA) {
@@ -89,8 +88,7 @@ void DarkEngine::loadAssetsDOSFullGame() {
// TODO: load objects
for (auto &it : _areaMap) {
- if (!it._value->entranceWithID(255))
- continue;
+ addWalls(it._value);
addECDs(it._value);
}
} else if (_renderMode == Common::kRenderCGA) {
diff --git a/engines/freescape/language/8bitDetokeniser.cpp b/engines/freescape/language/8bitDetokeniser.cpp
index 6b00ecc926e..16f57bf2924 100644
--- a/engines/freescape/language/8bitDetokeniser.cpp
+++ b/engines/freescape/language/8bitDetokeniser.cpp
@@ -42,7 +42,7 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
// we'll want to convert them into runs of "if shot? then", "if collided? then" or "if timer? then",
// and we'll want to start that from the top
FCLInstructionVector *conditionalInstructions = new FCLInstructionVector();
- FCLInstruction currentInstruction;
+ FCLInstruction currentInstruction = FCLInstruction(Token::UNKNOWN);
// this lookup table tells us how many argument bytes to read per opcode
uint8 argumentsRequiredByOpcode[49] =
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index a528ec48275..7b845bf28b1 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -27,6 +27,29 @@
namespace Freescape {
+FCLInstructionVector *duplicateCondition(FCLInstructionVector *condition) {
+ if (!condition)
+ return nullptr;
+
+ FCLInstructionVector *copy = new FCLInstructionVector();
+ for (uint i = 0; i < condition->size(); i++) {
+ copy->push_back((*condition)[i].duplicate());
+ }
+ return copy;
+}
+
+FCLInstruction FCLInstruction::duplicate() {
+ FCLInstruction copy(_type);
+ copy.setSource(_source);
+ copy.setDestination(_destination);
+ copy.setAdditional(_additional);
+
+ copy._thenInstructions = duplicateCondition(_thenInstructions);
+ copy._elseInstructions = duplicateCondition(_elseInstructions);
+
+ return copy;
+}
+
FCLInstruction::FCLInstruction(Token::Type type_) {
_source = 0;
_destination = 0;
diff --git a/engines/freescape/language/instruction.h b/engines/freescape/language/instruction.h
index c045cc7e2ff..e5e01ea2887 100644
--- a/engines/freescape/language/instruction.h
+++ b/engines/freescape/language/instruction.h
@@ -44,6 +44,8 @@ public:
Token::Type getType();
void setBranches(FCLInstructionVector *thenBranch, FCLInstructionVector *elseBranch);
+ FCLInstruction duplicate();
+
int32 _source;
int32 _additional;
int32 _destination;
diff --git a/engines/freescape/objects/geometricobject.cpp b/engines/freescape/objects/geometricobject.cpp
index ed19eeafd08..954f67755fb 100644
--- a/engines/freescape/objects/geometricobject.cpp
+++ b/engines/freescape/objects/geometricobject.cpp
@@ -26,6 +26,8 @@
namespace Freescape {
+extern FCLInstructionVector *duplicateCondition(FCLInstructionVector *condition);
+
int GeometricObject::numberOfColoursForObjectOfType(ObjectType type) {
switch (type) {
default:
@@ -186,14 +188,18 @@ void GeometricObject::scale(int factor) {
}
Object *GeometricObject::duplicate() {
- Common::Array<uint8> *colours_copy = nullptr;
- Common::Array<uint16> *ordinates_copy = nullptr;
+ Common::Array<uint8> *coloursCopy = nullptr;
+ Common::Array<uint16> *ordinatesCopy = nullptr;
+ FCLInstructionVector *conditionCopy = nullptr;
if (_colours)
- colours_copy = new Common::Array<uint8>(*_colours);
+ coloursCopy = new Common::Array<uint8>(*_colours);
if (_ordinates)
- ordinates_copy = new Common::Array<uint16>(*_ordinates);
+ ordinatesCopy = new Common::Array<uint16>(*_ordinates);
+
+ conditionCopy = duplicateCondition(&_condition);
+ assert(conditionCopy);
return new GeometricObject(
_type,
@@ -201,9 +207,9 @@ Object *GeometricObject::duplicate() {
_flags,
_origin,
_size,
- colours_copy,
- ordinates_copy,
- _condition,
+ coloursCopy,
+ ordinatesCopy,
+ *conditionCopy,
_conditionSource);
}
Commit: ef9b556cfadaf14caa07e07aee0c6fe55c61d4de
https://github.com/scummvm/scummvm/commit/ef9b556cfadaf14caa07e07aee0c6fe55c61d4de
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: re-use loadGlobalObjects for different games
Changed paths:
engines/freescape/freescape.h
engines/freescape/games/dark/dark.cpp
engines/freescape/games/dark/dos.cpp
engines/freescape/games/driller/amiga.cpp
engines/freescape/games/driller/atari.cpp
engines/freescape/games/driller/c64.cpp
engines/freescape/games/driller/cpc.cpp
engines/freescape/games/driller/dos.cpp
engines/freescape/games/driller/driller.cpp
engines/freescape/games/driller/zx.cpp
engines/freescape/loaders/8bitBinaryLoader.cpp
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index f8c7c95a376..ccb3af3942a 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -193,6 +193,7 @@ public:
void load8bitBinary(Common::SeekableReadStream *file, int offset, int ncolors);
Area *load8bitArea(Common::SeekableReadStream *file, uint16 ncolors);
Object *load8bitObject(Common::SeekableReadStream *file);
+ void loadGlobalObjects(Common::SeekableReadStream *file, int offset, int size);
void renderPixels8bitBinImage(Graphics::ManagedSurface *surface, int &i, int &j, uint8 pixels, int color);
void renderPixels8bitBinCGAImage(Graphics::ManagedSurface *surface, int &i, int &j, uint8 pixels, int color);
@@ -454,7 +455,6 @@ public:
Common::Error loadGameStreamExtended(Common::SeekableReadStream *stream) override;
private:
- void loadGlobalObjects(Common::SeekableReadStream *file, int offset);
bool drillDeployed(Area *area);
GeometricObject *_drillBase;
Math::Vector3d drillPosition();
@@ -537,7 +537,6 @@ public:
Common::Error loadGameStreamExtended(Common::SeekableReadStream *stream) override;
private:
- void loadGlobalObjects(Common::SeekableReadStream *file, int offset);
void addECDs(Area *area);
void addECD(Area *area, const Math::Vector3d position, int index);
void addWalls(Area *area);
diff --git a/engines/freescape/games/dark/dark.cpp b/engines/freescape/games/dark/dark.cpp
index b0d5a396340..1e17560ba1d 100644
--- a/engines/freescape/games/dark/dark.cpp
+++ b/engines/freescape/games/dark/dark.cpp
@@ -62,21 +62,6 @@ void DarkEngine::titleScreen() {
}
}
-void DarkEngine::loadGlobalObjects(Common::SeekableReadStream *file, int offset) {
- assert(!_areaMap.contains(255));
- ObjectMap *globalObjectsByID = new ObjectMap;
- file->seek(offset);
- for (int i = 0; i < 23; i++) {
- Object *gobj = load8bitObject(file);
- assert(gobj);
- assert(!globalObjectsByID->contains(gobj->getObjectID()));
- debugC(1, kFreescapeDebugParser, "Adding global object: %d", gobj->getObjectID());
- (*globalObjectsByID)[gobj->getObjectID()] = gobj;
- }
-
- _areaMap[255] = new Area(255, 0, globalObjectsByID, nullptr);
-}
-
void DarkEngine::addECDs(Area *area) {
if (!area->entranceWithID(255))
return;
diff --git a/engines/freescape/games/dark/dos.cpp b/engines/freescape/games/dark/dos.cpp
index b7b22563665..12881e46e46 100644
--- a/engines/freescape/games/dark/dos.cpp
+++ b/engines/freescape/games/dark/dos.cpp
@@ -44,7 +44,7 @@ void DarkEngine::loadAssetsDOSDemo() {
loadMessagesFixedSize(&file, 0x4525, 16, 27);
loadMessagesFixedSize(&file, 0x9959, 307, 5);
loadFonts(&file, 0xa598);
- loadGlobalObjects(&file, 0x3d04);
+ loadGlobalObjects(&file, 0x3d04, 23);
load8bitBinary(&file, 0xa700, 16);
_border = load8bitBinImage(&file, 0x210);
_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
@@ -81,7 +81,7 @@ void DarkEngine::loadAssetsDOSFullGame() {
loadFonts(&file, 0xa113);
loadMessagesFixedSize(&file, 0x4525, 16, 27);
- loadGlobalObjects(&file, 0x3d04);
+ loadGlobalObjects(&file, 0x3d04, 23);
load8bitBinary(&file, 0xa280, 16);
_border = load8bitBinImage(&file, 0x210);
_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
diff --git a/engines/freescape/games/driller/amiga.cpp b/engines/freescape/games/driller/amiga.cpp
index 28c1037ecc2..7402459aa18 100644
--- a/engines/freescape/games/driller/amiga.cpp
+++ b/engines/freescape/games/driller/amiga.cpp
@@ -44,7 +44,7 @@ void DrillerEngine::loadAssetsAmigaFullGame() {
loadFonts(&file, 0x8940);
loadMessagesFixedSize(&file, 0xc66e, 14, 20);
- loadGlobalObjects(&file, 0xbd62);
+ loadGlobalObjects(&file, 0xbd62, 8);
load8bitBinary(&file, 0x29c16, 16);
loadPalettes(&file, 0x297d4);
loadSoundsFx(&file, 0x30e80, 25);
@@ -69,7 +69,7 @@ void DrillerEngine::loadAssetsAmigaFullGame() {
loadFonts(&file, 0xa62);
loadMessagesFixedSize(&file, 0x499a, 14, 20);
- loadGlobalObjects(&file, 0x4098);
+ loadGlobalObjects(&file, 0x4098, 8);
load8bitBinary(&file, 0x21a3e, 16);
loadPalettes(&file, 0x215fc);
@@ -120,7 +120,7 @@ void DrillerEngine::loadAssetsAmigaDemo() {
loadFonts(&file, 0xa30);
loadMessagesFixedSize(&file, 0x3960, 14, 20);
- loadGlobalObjects(&file, 0x3716);
+ loadGlobalObjects(&file, 0x3716, 8);
file.close();
file.open("soundfx");
diff --git a/engines/freescape/games/driller/atari.cpp b/engines/freescape/games/driller/atari.cpp
index 6c2fe74a4ff..143920cb119 100644
--- a/engines/freescape/games/driller/atari.cpp
+++ b/engines/freescape/games/driller/atari.cpp
@@ -43,7 +43,7 @@ void DrillerEngine::loadAssetsAtariFullGame() {
loadFonts(&file, 0x8a32);
loadMessagesFixedSize(&file, 0xc5d8, 14, 20);
- loadGlobalObjects(&file, 0xbccc);
+ loadGlobalObjects(&file, 0xbccc, 8);
load8bitBinary(&file, 0x29b3c, 16);
loadPalettes(&file, 0x296fa);
loadSoundsFx(&file, 0x30da6, 25);
@@ -87,7 +87,7 @@ void DrillerEngine::loadAssetsAtariDemo() {
loadFonts(&file, 0x7bc);
loadMessagesFixedSize(&file, 0x3b90, 14, 20);
- loadGlobalObjects(&file, 0x3946);
+ loadGlobalObjects(&file, 0x3946, 8);
file.close();
file.open("soundfx");
diff --git a/engines/freescape/games/driller/c64.cpp b/engines/freescape/games/driller/c64.cpp
index 45c32204c1c..e52decdc5a7 100644
--- a/engines/freescape/games/driller/c64.cpp
+++ b/engines/freescape/games/driller/c64.cpp
@@ -38,13 +38,13 @@ void DrillerEngine::loadAssetsC64FullGame() {
loadMessagesFixedSize(&file, 0x167a, 14, 20);
//loadFonts(&file, 0xae54);
load8bitBinary(&file, 0x8e02, 4);
- loadGlobalObjects(&file, 0x1855);
+ loadGlobalObjects(&file, 0x1855, 8);
} else if (_targetName.hasPrefix("driller")) {
file.open("driller.c64.data");
loadMessagesFixedSize(&file, 0x167a - 0x400, 14, 20);
//loadFonts(&file, 0xae54);
load8bitBinary(&file, 0x8e02 - 0x400, 4);
- loadGlobalObjects(&file, 0x1855 - 0x400);
+ loadGlobalObjects(&file, 0x1855 - 0x400, 8);
} else
error("Unknown C64 release");
}
diff --git a/engines/freescape/games/driller/cpc.cpp b/engines/freescape/games/driller/cpc.cpp
index f441d8bc449..f9d95eef943 100644
--- a/engines/freescape/games/driller/cpc.cpp
+++ b/engines/freescape/games/driller/cpc.cpp
@@ -127,7 +127,7 @@ void DrillerEngine::loadAssetsCPCFullGame() {
loadMessagesFixedSize(&file, 0x214c, 14, 20);
loadFonts(&file, 0x5b69);
- loadGlobalObjects(&file, 0x1d07);
+ loadGlobalObjects(&file, 0x1d07, 8);
load8bitBinary(&file, 0x5ccb, 16);
}
diff --git a/engines/freescape/games/driller/dos.cpp b/engines/freescape/games/driller/dos.cpp
index cdd28d974c9..c96235196cf 100644
--- a/engines/freescape/games/driller/dos.cpp
+++ b/engines/freescape/games/driller/dos.cpp
@@ -286,7 +286,7 @@ void DrillerEngine::loadAssetsDOSFullGame() {
loadMessagesFixedSize(&file, 0x4135, 14, 20);
loadFonts(&file, 0x99dd);
- loadGlobalObjects(&file, 0x3b42);
+ loadGlobalObjects(&file, 0x3b42, 8);
load8bitBinary(&file, 0x9b40, 16);
_border = load8bitBinImage(&file, 0x210);
_border->setPalette((byte*)&kEGADefaultPaletteData, 0, 16);
@@ -311,7 +311,7 @@ void DrillerEngine::loadAssetsDOSFullGame() {
loadFonts(&file, 0x07a4a);
loadMessagesFixedSize(&file, 0x2585, 14, 20);
load8bitBinary(&file, 0x7bb0, 4);
- loadGlobalObjects(&file, 0x1fa2);
+ loadGlobalObjects(&file, 0x1fa2, 8);
_border = load8bitBinImage(&file, 0x210);
_border->setPalette((byte*)&kCGAPalettePinkBlueWhiteData, 0, 4);
} else
@@ -338,7 +338,7 @@ void DrillerEngine::loadAssetsDOSDemo() {
loadFonts(&file, 0x4eb0);
loadMessagesFixedSize(&file, 0x636, 14, 20);
load8bitBinary(&file, 0x55b0, 4);
- loadGlobalObjects(&file, 0x8c);
+ loadGlobalObjects(&file, 0x8c, 5);
_border = load8bitDemoImage(&file, 0x6220);
_border->setPalette((byte*)&kCGAPalettePinkBlueWhiteData, 0, 4);
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 490912727d5..5144aa8ba11 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -186,25 +186,6 @@ void DrillerEngine::gotoArea(uint16 areaID, int entranceID) {
resetInput();
}
-void DrillerEngine::loadGlobalObjects(Common::SeekableReadStream *file, int offset) {
- assert(!_areaMap.contains(255));
- ObjectMap *globalObjectsByID = new ObjectMap;
- file->seek(offset);
- for (int i = 0; i < 8; i++) {
- if (isDOS() && isDemo()) // The DOS demo has a few missing objects
- if (i == 5)
- break;
-
- Object *gobj = load8bitObject(file);
- assert(gobj);
- assert(!globalObjectsByID->contains(gobj->getObjectID()));
- debugC(1, kFreescapeDebugParser, "Adding global object: %d", gobj->getObjectID());
- (*globalObjectsByID)[gobj->getObjectID()] = gobj;
- }
-
- _areaMap[255] = new Area(255, 0, globalObjectsByID, nullptr);
-}
-
void DrillerEngine::loadAssetsFullGame() {
FreescapeEngine::loadAssetsFullGame();
/*
diff --git a/engines/freescape/games/driller/zx.cpp b/engines/freescape/games/driller/zx.cpp
index 65e933b81dc..519832b5957 100644
--- a/engines/freescape/games/driller/zx.cpp
+++ b/engines/freescape/games/driller/zx.cpp
@@ -64,9 +64,9 @@ void DrillerEngine::loadAssetsZXFullGame() {
loadFonts(&file, 0x63f0);
if (_variant & GF_ZX_DISC)
- loadGlobalObjects(&file, 0x1d13);
+ loadGlobalObjects(&file, 0x1d13, 8);
else
- loadGlobalObjects(&file, 0x1c93);
+ loadGlobalObjects(&file, 0x1c93, 8);
if (_variant & GF_ZX_RETAIL)
load8bitBinary(&file, 0x642c, 4);
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index d9e1157be65..64fe016df02 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -801,4 +801,20 @@ void FreescapeEngine::loadMessagesVariableSize(Common::SeekableReadStream *file,
}
}
+void FreescapeEngine::loadGlobalObjects(Common::SeekableReadStream *file, int offset, int size) {
+ assert(!_areaMap.contains(255));
+ ObjectMap *globalObjectsByID = new ObjectMap;
+ file->seek(offset);
+ for (int i = 0; i < size; i++) {
+ Object *gobj = load8bitObject(file);
+ assert(gobj);
+ assert(!globalObjectsByID->contains(gobj->getObjectID()));
+ debugC(1, kFreescapeDebugParser, "Adding global object: %d", gobj->getObjectID());
+ (*globalObjectsByID)[gobj->getObjectID()] = gobj;
+ }
+
+ _areaMap[255] = new Area(255, 0, globalObjectsByID, nullptr);
+}
+
+
} // namespace Freescape
Commit: 578330a20fd58a19ea4a69b6f413a7b795d42505
https://github.com/scummvm/scummvm/commit/578330a20fd58a19ea4a69b6f413a7b795d42505
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: initial implementation of the opengl shader renderer
Changed paths:
A engines/freescape/gfx_opengl_shaders.cpp
A engines/freescape/gfx_opengl_shaders.h
A engines/freescape/shaders/bitmap.fragment
A engines/freescape/shaders/bitmap.vertex
A engines/freescape/shaders/triangle.fragment
A engines/freescape/shaders/triangle.vertex
engines/freescape/games/palettes.cpp
engines/freescape/gfx.cpp
engines/freescape/module.mk
graphics/opengl/shader.cpp
diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index 2947a6c6268..e2fe6b8e3c8 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -209,6 +209,9 @@ byte kDrillerCGAPaletteRedGreenData[4][3] = {
};
void FreescapeEngine::swapPalette(uint16 levelID) {
+ if (!_border)
+ return;
+
if (isAmiga() || isAtariST()) {
// The following palette was not available in the demo, so we select another one
if (isDemo() && levelID == 32)
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 58068d0a0eb..b8b45a37179 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -932,6 +932,9 @@ Graphics::RendererType determinateRenderType() {
#if defined(USE_OPENGL_GAME)
Graphics::kRendererTypeOpenGL |
#endif
+#if defined(USE_OPENGL_SHADERS)
+ Graphics::kRendererTypeOpenGLShaders |
+#endif
#if defined(USE_TINYGL)
Graphics::kRendererTypeTinyGL |
#endif
@@ -947,6 +950,11 @@ Graphics::RendererType determinateRenderType() {
return matchingRendererType;
#endif
+ #if defined(USE_OPENGL_SHADERS)
+ if (matchingRendererType == Graphics::kRendererTypeOpenGLShaders)
+ return matchingRendererType;
+ #endif
+
#if defined(USE_TINYGL)
return Graphics::kRendererTypeTinyGL;
#endif
@@ -972,6 +980,12 @@ Renderer *createRenderer(int screenW, int screenH, Common::RenderMode renderMode
}
#endif
+ #if defined(USE_OPENGL_SHADERS)
+ if (rendererType == Graphics::kRendererTypeOpenGLShaders) {
+ return CreateGfxOpenGLShader(screenW, screenH, renderMode);
+ }
+ #endif
+
#if defined(USE_TINYGL)
if (rendererType == Graphics::kRendererTypeTinyGL) {
return CreateGfxTinyGL(screenW, screenH, renderMode);
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
new file mode 100644
index 00000000000..a30c22935db
--- /dev/null
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -0,0 +1,340 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+// Based on Phantasma code by Thomas Harte (2013),
+// available at https://github.com/TomHarte/Phantasma/ (MIT)
+
+#include "common/config-manager.h"
+#include "common/math.h"
+#include "common/system.h"
+#include "math/glmath.h"
+
+#include "freescape/objects/object.h"
+#include "freescape/gfx_opengl_shaders.h"
+#include "freescape/gfx_opengl_texture.h"
+
+namespace Freescape {
+
+static const GLfloat bitmapVertices[] = {
+ // XS YT
+ 0.0, 0.0,
+ 1.0, 0.0,
+ 0.0, 1.0,
+ 1.0, 1.0,
+};
+
+Renderer *CreateGfxOpenGLShader(int screenW, int screenH, Common::RenderMode renderMode) {
+ return new OpenGLShaderRenderer(screenW, screenH, renderMode);
+}
+
+OpenGLShaderRenderer::OpenGLShaderRenderer(int screenW, int screenH, Common::RenderMode renderMode) : Renderer(screenW, screenH, renderMode) {
+ _triangleShader = nullptr;
+ _triangleVBO = 0;
+
+ _bitmapShader = nullptr;
+ _bitmapVBO = 0;
+
+ _texturePixelFormat = OpenGLTexture::getRGBAPixelFormat();
+ _isAccelerated = true;
+}
+
+OpenGLShaderRenderer::~OpenGLShaderRenderer() {
+ OpenGL::Shader::freeBuffer(_triangleVBO);
+ delete _triangleShader;
+}
+
+Texture *OpenGLShaderRenderer::createTexture(const Graphics::Surface *surface) {
+ return new OpenGLTexture(surface);
+}
+
+void OpenGLShaderRenderer::freeTexture(Texture *texture) {
+ delete texture;
+}
+
+void OpenGLShaderRenderer::init() {
+ computeScreenViewport();
+
+ _verts = (Vertex *)malloc(sizeof(Vertex) * kVertexArraySize);
+
+ static const char *triangleAttributes[] = { "position", nullptr };
+ _triangleShader = OpenGL::Shader::fromFiles("triangle", triangleAttributes);
+ _triangleVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(Vertex) * kVertexArraySize, _verts, GL_DYNAMIC_DRAW);
+ // TODO: Check if 3 * sizeof(float) == sizeof(Vertex)
+ _triangleShader->enableVertexAttribute("position", _triangleVBO, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
+
+ static const char *bitmapAttributes[] = { "position", "texcoord", nullptr };
+ _bitmapShader = OpenGL::Shader::fromFiles("bitmap", bitmapAttributes);
+ _bitmapVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(bitmapVertices), bitmapVertices);
+ _bitmapShader->enableVertexAttribute("position", _bitmapVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
+ _bitmapShader->enableVertexAttribute("texcoord", _bitmapVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
+
+ glDisable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_SCISSOR_TEST);
+ setViewport(_viewport);
+}
+
+void OpenGLShaderRenderer::setViewport(const Common::Rect &rect) {
+ _viewport = Common::Rect(
+ _screenViewport.width() * rect.width() / _screenW,
+ _screenViewport.height() * rect.height() / _screenH
+ );
+
+ _viewport.translate(
+ _screenViewport.left + _screenViewport.width() * rect.left / _screenW,
+ _screenViewport.top + _screenViewport.height() * rect.top / _screenH
+ );
+
+ _unscaledViewport = rect;
+ glViewport(_viewport.left, g_system->getHeight() - _viewport.bottom, _viewport.width(), _viewport.height());
+ glScissor(_viewport.left, g_system->getHeight() - _viewport.bottom, _viewport.width(), _viewport.height());
+}
+
+void OpenGLShaderRenderer::drawTexturedRect2D(const Common::Rect &screenRect, const Common::Rect &textureRect, Texture *texture) {
+ OpenGLTexture *glTexture = static_cast<OpenGLTexture *>(texture);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+
+ _bitmapShader->use();
+ _bitmapShader->setUniform("flipY", glTexture->_upsideDown);
+
+ glDepthMask(GL_FALSE);
+
+ glBindTexture(GL_TEXTURE_2D, glTexture->_id);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ glDisable(GL_BLEND);
+ glDepthMask(GL_TRUE);
+ _bitmapShader->unbind();
+}
+
+void OpenGLShaderRenderer::updateProjectionMatrix(float fov, float nearClipPlane, float farClipPlane) {
+ float aspectRatio = _screenW / (float)_screenH;
+ float xmaxValue = nearClipPlane * tan(Common::deg2rad(fov) / 2);
+ float ymaxValue = xmaxValue / aspectRatio;
+ _projectionMatrix = Math::makeFrustumMatrix(xmaxValue, -xmaxValue, -ymaxValue, ymaxValue, nearClipPlane, farClipPlane);
+}
+
+void OpenGLShaderRenderer::positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest) {
+ Math::Vector3d up_vec(0, 1, 0);
+
+ Math::Matrix4 lookMatrix = Math::makeLookAtMatrix(pos, interest, up_vec);
+ Math::Matrix4 viewMatrix;
+ viewMatrix.translate(-pos);
+ viewMatrix.transpose();
+
+ _modelViewMatrix = viewMatrix * lookMatrix;
+
+ Math::Matrix4 proj = _projectionMatrix;
+ Math::Matrix4 model = _modelViewMatrix;
+ proj.transpose();
+ model.transpose();
+ _mvpMatrix = proj * model;
+ _mvpMatrix.transpose();
+}
+
+void OpenGLShaderRenderer::renderSensorShoot(byte color, const Math::Vector3d sensor, const Math::Vector3d player, const Common::Rect viewArea) {
+ /*glColor3ub(255, 255, 255);
+ glLineWidth(20);
+ polygonOffset(true);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ copyToVertexArray(0, sensor);
+ copyToVertexArray(1, player);
+ glVertexPointer(3, GL_FLOAT, 0, _verts);
+ glDrawArrays(GL_LINES, 0, 2);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ polygonOffset(false);
+ glLineWidth(1);*/
+}
+
+void OpenGLShaderRenderer::renderPlayerShoot(byte color, const Common::Point position, const Common::Rect viewArea) {
+ /*uint8 a, r, g, b;
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, _screenW, _screenH, 0, 0, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderZX) {
+ r = g = b = 255;
+ } else {
+ uint32 pixel = 0x0;
+ glReadPixels(g_system->getWidth() / 2, g_system->getHeight() / 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
+ _texturePixelFormat.colorToARGB(pixel, a, r, g, b);
+ color = indexFromColor(r, g, b);
+ readFromPalette((color + 3) % (_renderMode == Common::kRenderCGA ? 4 : 16), r, g, b);
+ }
+
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+
+ glColor3ub(r, g, b);
+
+ glLineWidth(5); // It will not work in every OpenGL implementation since the
+ // spec doesn't require support for line widths other than 1
+ glEnableClientState(GL_VERTEX_ARRAY);
+ copyToVertexArray(0, Math::Vector3d(viewArea.left, viewArea.height() + viewArea.top, 0));
+ copyToVertexArray(1, Math::Vector3d(position.x, position.y, 0));
+ copyToVertexArray(2, Math::Vector3d(viewArea.left, viewArea.height() + viewArea.top + 3, 0));
+ copyToVertexArray(3, Math::Vector3d(position.x, position.y, 0));
+
+ copyToVertexArray(4, Math::Vector3d(viewArea.right, viewArea.height() + viewArea.top, 0));
+ copyToVertexArray(5, Math::Vector3d(position.x, position.y, 0));
+ copyToVertexArray(6, Math::Vector3d(viewArea.right, viewArea.height() + viewArea.top + 3, 0));
+ copyToVertexArray(7, Math::Vector3d(position.x, position.y, 0));
+
+ glVertexPointer(3, GL_FLOAT, 0, _verts);
+ glDrawArrays(GL_LINES, 0, 8);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glLineWidth(1);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_TRUE);*/
+}
+
+void OpenGLShaderRenderer::renderFace(const Common::Array<Math::Vector3d> &vertices) {
+ assert(vertices.size() >= 2);
+ const Math::Vector3d &v0 = vertices[0];
+
+ /*if (vertices.size() == 2) {
+ const Math::Vector3d &v1 = vertices[1];
+ if (v0 == v1)
+ return;
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ copyToVertexArray(0, v0);
+ copyToVertexArray(1, v1);
+ glVertexPointer(3, GL_FLOAT, 0, _verts);
+ glLineWidth(MAX(1, g_system->getWidth() / 192));
+ glDrawArrays(GL_LINES, 0, 2);
+ glLineWidth(1);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ return;
+ }*/
+
+ //glEnableClientState(GL_VERTEX_ARRAY);
+ _triangleShader->use();
+ _triangleShader->setUniform("mvpMatrix", _mvpMatrix);
+ uint vi = 0;
+ for (uint i = 1; i < vertices.size() - 1; i++) { // no underflow since vertices.size() > 2
+ const Math::Vector3d &v1 = vertices[i];
+ const Math::Vector3d &v2 = vertices[i + 1];
+ vi = 3 * (i - 1); // no underflow since i >= 1
+ copyToVertexArray(vi + 0, v0);
+ copyToVertexArray(vi + 1, v1);
+ copyToVertexArray(vi + 2, v2);
+ }
+ glBindBuffer(GL_ARRAY_BUFFER, _triangleVBO);
+ glBufferData(GL_ARRAY_BUFFER, (vi + 3) * 3 * sizeof(float), _verts, GL_DYNAMIC_DRAW);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
+ //glEnableVertexAttribArray(0);
+
+ glDrawArrays(GL_TRIANGLES, 0, vi + 3);
+ //glDisableVertexAttribArray(0);
+ //glDisableClientState(GL_VERTEX_ARRAY);
+}
+
+void OpenGLShaderRenderer::polygonOffset(bool enabled) {
+ if (enabled) {
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(-10.0f, 1.0f);
+ } else {
+ glPolygonOffset(0, 0);
+ glDisable(GL_POLYGON_OFFSET_FILL);
+ }
+}
+
+void OpenGLShaderRenderer::setStippleData(byte *data) {
+ if (!data)
+ return;
+
+ //_variableStippleArray = data;
+ //for (int i = 0; i < 128; i++)
+ // _variableStippleArray[i] = data[(i / 16) % 4];
+}
+
+void OpenGLShaderRenderer::useStipple(bool enabled) {
+ /*if (enabled) {
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(0.0f, -1.0f);
+ glEnable(GL_POLYGON_STIPPLE);
+ if (_renderMode == Common::kRenderZX ||
+ _renderMode == Common::kRenderCPC ||
+ _renderMode == Common::kRenderCGA)
+ glPolygonStipple(_variableStippleArray);
+ else
+ glPolygonStipple(_defaultStippleArray);
+ } else {
+ glPolygonOffset(0, 0);
+ glDisable(GL_POLYGON_OFFSET_FILL);
+ glDisable(GL_POLYGON_STIPPLE);
+ }*/
+}
+
+void OpenGLShaderRenderer::useColor(uint8 r, uint8 g, uint8 b) {
+ Math::Vector3d color(r / 256.0, g / 256.0, b / 256.0);
+ _triangleShader->use();
+ _triangleShader->setUniform("color", color);
+}
+
+void OpenGLShaderRenderer::clear(uint8 color) {
+ uint8 r, g, b;
+
+ if (_colorRemaps && _colorRemaps->contains(color)) {
+ color = (*_colorRemaps)[color];
+ }
+
+ readFromPalette(color, r, g, b);
+ glClearColor(0, 0, 0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+void OpenGLShaderRenderer::drawFloor(uint8 color) {
+ /*uint8 r1, g1, b1, r2, g2, b2;
+ byte *stipple;
+ assert(getRGBAt(color, r1, g1, b1, r2, g2, b2, stipple)); // TODO: move check inside this function
+ glColor3ub(r1, g1, b1);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ copyToVertexArray(0, Math::Vector3d(-100000.0, 0.0, -100000.0));
+ copyToVertexArray(1, Math::Vector3d(100000.0, 0.0, -100000.0));
+ copyToVertexArray(2, Math::Vector3d(100000.0, 0.0, 100000.0));
+ copyToVertexArray(3, Math::Vector3d(-100000.0, 0.0, 100000.0));
+ glVertexPointer(3, GL_FLOAT, 0, _verts);
+ glDrawArrays(GL_QUADS, 0, 4);
+ glDisableClientState(GL_VERTEX_ARRAY);*/
+}
+
+void OpenGLShaderRenderer::flipBuffer() {}
+
+Graphics::Surface *OpenGLShaderRenderer::getScreenshot() {
+ Common::Rect screen = viewport();
+ Graphics::Surface *s = new Graphics::Surface();
+ s->create(screen.width(), screen.height(), OpenGLTexture::getRGBAPixelFormat());
+ glReadPixels(screen.left, screen.top, screen.width(), screen.height(), GL_RGBA, GL_UNSIGNED_BYTE, s->getPixels());
+ flipVertical(s);
+ return s;
+ return nullptr;
+}
+
+} // End of namespace Freescape
diff --git a/engines/freescape/gfx_opengl_shaders.h b/engines/freescape/gfx_opengl_shaders.h
new file mode 100644
index 00000000000..1084a8fb1cb
--- /dev/null
+++ b/engines/freescape/gfx_opengl_shaders.h
@@ -0,0 +1,100 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef FREESCAPE_GFX_OPENGL_SHADERS_H
+#define FREESCAPE_GFX_OPENGL_SHADERS_H
+
+#include "graphics/opengl/shader.h"
+#include "graphics/opengl/system_headers.h"
+#include "math/vector3d.h"
+#include "math/vector2d.h"
+
+#include "freescape/gfx.h"
+
+namespace Freescape {
+
+class OpenGLShaderRenderer : public Renderer {
+public:
+ OpenGLShaderRenderer(int screenW, int screenH, Common::RenderMode renderMode);
+ virtual ~OpenGLShaderRenderer();
+
+ Math::Matrix4 _projectionMatrix;
+ Math::Matrix4 _modelViewMatrix;
+ Math::Matrix4 _mvpMatrix;
+
+ struct Vertex {
+ GLfloat x;
+ GLfloat y;
+ GLfloat z;
+ };
+
+ void copyToVertexArray(uint idx, const Math::Vector3d &src) {
+ assert(idx < kVertexArraySize);
+ _verts[idx].x = src.x(); _verts[idx].y = src.y(); _verts[idx].z = src.z();
+ }
+
+ Vertex *_verts;
+
+ struct Coord {
+ GLfloat x;
+ GLfloat y;
+ };
+
+ /*Coord *_coords;
+
+ void copyToCoordArray(uint idx, const Math::Vector2d &src) {
+ assert(idx < kCoordsArraySize);
+ _coords[idx].x = src.getValue(0); _coords[idx].y = src.getValue(1);
+ }*/
+
+ OpenGL::Shader *_triangleShader;
+ OpenGL::Shader *_bitmapShader;
+ GLuint _triangleVBO;
+ GLuint _bitmapVBO;
+
+ virtual void init() override;
+ virtual void clear(uint8 color) override;
+ virtual void setViewport(const Common::Rect &rect) override;
+ virtual void positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest) override;
+ virtual void updateProjectionMatrix(float fov, float nearClipPlane, float farClipPlane) override;
+
+ virtual void useColor(uint8 r, uint8 g, uint8 b) override;
+ virtual void polygonOffset(bool enabled) override;
+ virtual void setStippleData(byte *data) override;
+ virtual void useStipple(bool enabled) override;
+
+ Texture *createTexture(const Graphics::Surface *surface) override;
+ void freeTexture(Texture *texture) override;
+ virtual void drawTexturedRect2D(const Common::Rect &screenRect, const Common::Rect &textureRect, Texture *texture) override;
+
+ virtual void renderSensorShoot(byte color, const Math::Vector3d sensor, const Math::Vector3d player, const Common::Rect viewPort) override;
+ virtual void renderPlayerShoot(byte color, const Common::Point position, const Common::Rect viewPort) override;
+ virtual void renderFace(const Common::Array<Math::Vector3d> &vertices) override;
+
+ virtual void flipBuffer() override;
+ virtual void drawFloor(uint8 color) override;
+
+ virtual Graphics::Surface *getScreenshot() override;
+};
+
+} // End of namespace Freescape
+
+#endif // FREESCAPE_GFX_OPENGL_SHADERS_H
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index 0695e5501b3..fe3a2a95cda 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -36,6 +36,11 @@ MODULE_OBJS += \
gfx_tinygl_texture.o
endif
+ifdef USE_OPENGL_SHADERS
+MODULE_OBJS += \
+ gfx_opengl_shaders.o
+endif
+
ifdef USE_OPENGL
MODULE_OBJS += \
gfx_opengl.o \
diff --git a/engines/freescape/shaders/bitmap.fragment b/engines/freescape/shaders/bitmap.fragment
new file mode 100644
index 00000000000..ac293f3685d
--- /dev/null
+++ b/engines/freescape/shaders/bitmap.fragment
@@ -0,0 +1,9 @@
+in vec2 Texcoord;
+
+OUTPUT
+
+uniform sampler2D tex;
+
+void main() {
+ outColor = texture(tex, Texcoord);
+}
diff --git a/engines/freescape/shaders/bitmap.vertex b/engines/freescape/shaders/bitmap.vertex
new file mode 100644
index 00000000000..7362dae979c
--- /dev/null
+++ b/engines/freescape/shaders/bitmap.vertex
@@ -0,0 +1,21 @@
+in vec2 position;
+in vec2 texcoord;
+
+uniform UBOOL flipY;
+
+out vec2 Texcoord;
+
+void main() {
+ Texcoord = texcoord;
+
+ vec2 pos = position;
+ // Coordinates are [0.0;1.0], transform to [-1.0; 1.0]
+ pos.x = pos.x * 2.0 - 1.0;
+ pos.y = -1.0 * (pos.y * 2.0 - 1.0);
+
+ if (UBOOL_TEST(flipY)) {
+ pos.y *= -1.0;
+ }
+
+ gl_Position = vec4(pos, 0.0, 1.0);
+}
diff --git a/engines/freescape/shaders/triangle.fragment b/engines/freescape/shaders/triangle.fragment
new file mode 100644
index 00000000000..aaf98049c01
--- /dev/null
+++ b/engines/freescape/shaders/triangle.fragment
@@ -0,0 +1,8 @@
+OUTPUT
+
+varying vec4 var_color;
+
+void main()
+{
+ outColor = var_color;
+}
\ No newline at end of file
diff --git a/engines/freescape/shaders/triangle.vertex b/engines/freescape/shaders/triangle.vertex
new file mode 100644
index 00000000000..6483e9a8adb
--- /dev/null
+++ b/engines/freescape/shaders/triangle.vertex
@@ -0,0 +1,12 @@
+in vec3 position;
+
+uniform mat4 mvpMatrix;
+uniform vec3 color;
+
+varying vec4 var_color;
+
+void main()
+{
+ var_color = vec4(color, 1.0);
+ gl_Position = mvpMatrix * vec4(position, 1.0);
+}
\ No newline at end of file
diff --git a/graphics/opengl/shader.cpp b/graphics/opengl/shader.cpp
index 652e4cac3b3..99f23e3c14a 100644
--- a/graphics/opengl/shader.cpp
+++ b/graphics/opengl/shader.cpp
@@ -92,6 +92,7 @@ static const GLchar *readFile(const Common::String &filename) {
SearchMan.addDirectory("STARK_SHADERS", "engines/stark", 0, 2);
SearchMan.addDirectory("WINTERMUTE_SHADERS", "engines/wintermute/base/gfx/opengl", 0, 2);
SearchMan.addDirectory("PLAYGROUND3D_SHADERS", "engines/playground3d", 0, 2);
+ SearchMan.addDirectory("FREESCAPE_SHADERS", "engines/freescape", 0, 2);
SearchMan.addDirectory("HPL1_SHADERS", "engines/hpl1/engine/impl", 0, 2);
#endif
@@ -111,6 +112,7 @@ static const GLchar *readFile(const Common::String &filename) {
SearchMan.remove("STARK_SHADERS");
SearchMan.remove("WINTERMUTE_SHADERS");
SearchMan.remove("PLAYGROUND3D_SHADERS");
+ SearchMan.remove("FREESCAPE_SHADERS");
SearchMan.remove("HPL1_SHADERS");
#endif
Commit: 1c763a01f95c4386a788f86f87efba8421392024
https://github.com/scummvm/scummvm/commit/1c763a01f95c4386a788f86f87efba8421392024
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: renamed shaders filenames and added them into shader.dat
Changed paths:
A engines/freescape/shaders/freescape_bitmap.fragment
A engines/freescape/shaders/freescape_bitmap.vertex
A engines/freescape/shaders/freescape_triangle.fragment
A engines/freescape/shaders/freescape_triangle.vertex
R engines/freescape/shaders/bitmap.fragment
R engines/freescape/shaders/bitmap.vertex
R engines/freescape/shaders/triangle.fragment
R engines/freescape/shaders/triangle.vertex
Makefile.common
devtools/create_project/xcode.cpp
dists/scummvm.rc
engines/freescape/gfx_opengl_shaders.cpp
diff --git a/Makefile.common b/Makefile.common
index d240c8f1a31..bca64b067eb 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -513,6 +513,9 @@ endif
ifdef ENABLE_HPL1
DIST_FILES_SHADERS+=$(wildcard $(srcdir)/engines/hpl1/engine/impl/shaders/*)
endif
+ifdef ENABLE_FREESCAPE
+DIST_FILES_SHADERS+=$(wildcard $(srcdir)/engines/freescape/shaders/*)
+endif
endif
.PHONY: all clean distclean plugins dist-src clean-toplevel manual
diff --git a/devtools/create_project/xcode.cpp b/devtools/create_project/xcode.cpp
index 82a99370d1f..63cf09da57e 100644
--- a/devtools/create_project/xcode.cpp
+++ b/devtools/create_project/xcode.cpp
@@ -1105,6 +1105,12 @@ XcodeProvider::ValueList& XcodeProvider::getResourceFiles(const BuildSetup &setu
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_sprite.fragment");
files.push_back("engines/wintermute/base/gfx/opengl/shaders/wme_sprite.vertex");
}
+ if (CONTAINS_DEFINE(setup.defines, "ENABLE_FREESCAPE")) {
+ files.push_back("engines/freescape/shaders/freescape_bitmap.fragment");
+ files.push_back("engines/freescape/shaders/freescape_bitmap.vertex");
+ files.push_back("engines/freescape/shaders/freescape_triangle.fragment");
+ files.push_back("engines/freescape/shaders/freescape_triange.vertex");
+ }
files.push_back("icons/scummvm.icns");
files.push_back("AUTHORS");
files.push_back("COPYING");
diff --git a/dists/scummvm.rc b/dists/scummvm.rc
index 9f3f801d0fe..047a37e990d 100644
--- a/dists/scummvm.rc
+++ b/dists/scummvm.rc
@@ -273,6 +273,12 @@ shaders/hpl1_refract_special.fragment FILE "engines/hpl1/engi
shaders/hpl1_refract_water.fragment FILE "engines/hpl1/engine/impl/shaders/hpl1_refract_water.fragment"
shaders/hpl1_refract_water.vertex FILE "engines/hpl1/engine/impl/shaders/hpl1_refract_water.vertex"
#endif
+#if PLUGIN_ENABLED_STATIC(FREESCAPE)
+shaders/freescape_bitmap.fragment FILE "engines/freescape/shaders/freescape_bitmap.fragment"
+shaders/freescape_bitmap.vertex FILE "engines/freescape/shaders/freescape_bitmap.vertex"
+shaders/freescape_triangle.fragment FILE "engines/freescape/shaders/freescape_cube.fragment"
+shaders/freescape_triangle.vertex FILE "engines/freescape/shaders/freescape_cube.vertex"
+#endif
#endif
#endif
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index a30c22935db..b6799bbfcfa 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -75,13 +75,13 @@ void OpenGLShaderRenderer::init() {
_verts = (Vertex *)malloc(sizeof(Vertex) * kVertexArraySize);
static const char *triangleAttributes[] = { "position", nullptr };
- _triangleShader = OpenGL::Shader::fromFiles("triangle", triangleAttributes);
+ _triangleShader = OpenGL::Shader::fromFiles("freescape_triangle", triangleAttributes);
_triangleVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(Vertex) * kVertexArraySize, _verts, GL_DYNAMIC_DRAW);
// TODO: Check if 3 * sizeof(float) == sizeof(Vertex)
_triangleShader->enableVertexAttribute("position", _triangleVBO, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
static const char *bitmapAttributes[] = { "position", "texcoord", nullptr };
- _bitmapShader = OpenGL::Shader::fromFiles("bitmap", bitmapAttributes);
+ _bitmapShader = OpenGL::Shader::fromFiles("freescape_bitmap", bitmapAttributes);
_bitmapVBO = OpenGL::Shader::createBuffer(GL_ARRAY_BUFFER, sizeof(bitmapVertices), bitmapVertices);
_bitmapShader->enableVertexAttribute("position", _bitmapVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
_bitmapShader->enableVertexAttribute("texcoord", _bitmapVBO, 2, GL_FLOAT, GL_TRUE, 2 * sizeof(float), 0);
diff --git a/engines/freescape/shaders/bitmap.fragment b/engines/freescape/shaders/freescape_bitmap.fragment
similarity index 100%
rename from engines/freescape/shaders/bitmap.fragment
rename to engines/freescape/shaders/freescape_bitmap.fragment
diff --git a/engines/freescape/shaders/bitmap.vertex b/engines/freescape/shaders/freescape_bitmap.vertex
similarity index 100%
rename from engines/freescape/shaders/bitmap.vertex
rename to engines/freescape/shaders/freescape_bitmap.vertex
diff --git a/engines/freescape/shaders/triangle.fragment b/engines/freescape/shaders/freescape_triangle.fragment
similarity index 100%
rename from engines/freescape/shaders/triangle.fragment
rename to engines/freescape/shaders/freescape_triangle.fragment
diff --git a/engines/freescape/shaders/triangle.vertex b/engines/freescape/shaders/freescape_triangle.vertex
similarity index 100%
rename from engines/freescape/shaders/triangle.vertex
rename to engines/freescape/shaders/freescape_triangle.vertex
Commit: 7049d28f3bcffccd8c9a22215af2cec422a9edeb
https://github.com/scummvm/scummvm/commit/7049d28f3bcffccd8c9a22215af2cec422a9edeb
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: implemented lines in shader renderer
Changed paths:
engines/freescape/gfx_opengl_shaders.cpp
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index b6799bbfcfa..e62e57d9e59 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -216,25 +216,28 @@ void OpenGLShaderRenderer::renderFace(const Common::Array<Math::Vector3d> &verti
assert(vertices.size() >= 2);
const Math::Vector3d &v0 = vertices[0];
- /*if (vertices.size() == 2) {
+ _triangleShader->use();
+ _triangleShader->setUniform("mvpMatrix", _mvpMatrix);
+
+ if (vertices.size() == 2) {
const Math::Vector3d &v1 = vertices[1];
if (v0 == v1)
return;
- glEnableClientState(GL_VERTEX_ARRAY);
copyToVertexArray(0, v0);
copyToVertexArray(1, v1);
- glVertexPointer(3, GL_FLOAT, 0, _verts);
+
glLineWidth(MAX(1, g_system->getWidth() / 192));
+
+ glBindBuffer(GL_ARRAY_BUFFER, _triangleVBO);
+ glBufferData(GL_ARRAY_BUFFER, 2 * 3 * sizeof(float), _verts, GL_DYNAMIC_DRAW);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
glDrawArrays(GL_LINES, 0, 2);
+
glLineWidth(1);
- glDisableClientState(GL_VERTEX_ARRAY);
return;
- }*/
+ }
- //glEnableClientState(GL_VERTEX_ARRAY);
- _triangleShader->use();
- _triangleShader->setUniform("mvpMatrix", _mvpMatrix);
uint vi = 0;
for (uint i = 1; i < vertices.size() - 1; i++) { // no underflow since vertices.size() > 2
const Math::Vector3d &v1 = vertices[i];
@@ -247,11 +250,8 @@ void OpenGLShaderRenderer::renderFace(const Common::Array<Math::Vector3d> &verti
glBindBuffer(GL_ARRAY_BUFFER, _triangleVBO);
glBufferData(GL_ARRAY_BUFFER, (vi + 3) * 3 * sizeof(float), _verts, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
- //glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, vi + 3);
- //glDisableVertexAttribArray(0);
- //glDisableClientState(GL_VERTEX_ARRAY);
}
void OpenGLShaderRenderer::polygonOffset(bool enabled) {
Commit: 8ceaf7831e32a13929b4c51e3d5eca66ba5a4780
https://github.com/scummvm/scummvm/commit/8ceaf7831e32a13929b4c51e3d5eca66ba5a4780
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: implemented player shoot in shader renderer
Changed paths:
engines/freescape/gfx_opengl_shaders.cpp
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index e62e57d9e59..1a1d0717074 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -167,14 +167,23 @@ void OpenGLShaderRenderer::renderSensorShoot(byte color, const Math::Vector3d se
glLineWidth(1);*/
}
+// TODO: move inside the shader?
+float remap(float f, float s) {
+ return 2. * f / s - 1;
+}
+
void OpenGLShaderRenderer::renderPlayerShoot(byte color, const Common::Point position, const Common::Rect viewArea) {
- /*uint8 a, r, g, b;
+ uint8 a, r, g, b;
+
+ Math::Matrix4 identity;
+ identity(0, 0) = 1.0;
+ identity(1, 1) = 1.0;
+ identity(2, 2) = 1.0;
+ identity(3, 3) = 1.0;
+
+ _triangleShader->use();
+ _triangleShader->setUniform("mvpMatrix", identity);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, _screenW, _screenH, 0, 0, 1);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderZX) {
r = g = b = 255;
} else {
@@ -188,28 +197,31 @@ void OpenGLShaderRenderer::renderPlayerShoot(byte color, const Common::Point pos
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
- glColor3ub(r, g, b);
+ useColor(r, g, b);
glLineWidth(5); // It will not work in every OpenGL implementation since the
// spec doesn't require support for line widths other than 1
- glEnableClientState(GL_VERTEX_ARRAY);
- copyToVertexArray(0, Math::Vector3d(viewArea.left, viewArea.height() + viewArea.top, 0));
- copyToVertexArray(1, Math::Vector3d(position.x, position.y, 0));
- copyToVertexArray(2, Math::Vector3d(viewArea.left, viewArea.height() + viewArea.top + 3, 0));
- copyToVertexArray(3, Math::Vector3d(position.x, position.y, 0));
+ copyToVertexArray(0, Math::Vector3d(remap(viewArea.left, _screenW), remap(viewArea.height() - viewArea.top, _screenH), 0));
+ copyToVertexArray(1, Math::Vector3d(remap(position.x, _screenW), remap(_screenH - position.y, _screenH), 0));
- copyToVertexArray(4, Math::Vector3d(viewArea.right, viewArea.height() + viewArea.top, 0));
- copyToVertexArray(5, Math::Vector3d(position.x, position.y, 0));
- copyToVertexArray(6, Math::Vector3d(viewArea.right, viewArea.height() + viewArea.top + 3, 0));
- copyToVertexArray(7, Math::Vector3d(position.x, position.y, 0));
+ copyToVertexArray(2, Math::Vector3d(remap(viewArea.left, _screenW), remap(viewArea.height() - viewArea.top + 3, _screenH), 0));
+ copyToVertexArray(3, Math::Vector3d(remap(position.x, _screenW), remap(_screenH - position.y, _screenH), 0));
- glVertexPointer(3, GL_FLOAT, 0, _verts);
+ copyToVertexArray(4, Math::Vector3d(remap(viewArea.right, _screenW), remap(_screenH - viewArea.bottom, _screenH), 0));
+ copyToVertexArray(5, Math::Vector3d(remap(position.x, _screenW), remap(_screenH - position.y, _screenH), 0));
+
+ copyToVertexArray(6, Math::Vector3d(remap(viewArea.right, _screenW), remap(_screenH - viewArea.bottom + 3, _screenH), 0));
+ copyToVertexArray(7, Math::Vector3d(remap(position.x, _screenW), remap(_screenH - position.y, _screenH), 0));
+
+ glBindBuffer(GL_ARRAY_BUFFER, _triangleVBO);
+ glBufferData(GL_ARRAY_BUFFER, 8 * 3 * sizeof(float), _verts, GL_DYNAMIC_DRAW);
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), nullptr);
glDrawArrays(GL_LINES, 0, 8);
- glDisableClientState(GL_VERTEX_ARRAY);
+
glLineWidth(1);
glEnable(GL_DEPTH_TEST);
- glDepthMask(GL_TRUE);*/
+ glDepthMask(GL_TRUE);
}
void OpenGLShaderRenderer::renderFace(const Common::Array<Math::Vector3d> &vertices) {
Commit: 119405cfb852063ff56aa565a748a3add239786e
https://github.com/scummvm/scummvm/commit/119405cfb852063ff56aa565a748a3add239786e
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: correctly deallocate shaders memory
Changed paths:
engines/freescape/gfx_opengl_shaders.cpp
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index 1a1d0717074..9e067cfd426 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -59,6 +59,9 @@ OpenGLShaderRenderer::OpenGLShaderRenderer(int screenW, int screenH, Common::Ren
OpenGLShaderRenderer::~OpenGLShaderRenderer() {
OpenGL::Shader::freeBuffer(_triangleVBO);
delete _triangleShader;
+ OpenGL::Shader::freeBuffer(_bitmapVBO);
+ delete _bitmapShader;
+ free(_verts);
}
Texture *OpenGLShaderRenderer::createTexture(const Graphics::Surface *surface) {
Commit: e6d694687198266ff0fa1696276932c36c0a5f57
https://github.com/scummvm/scummvm/commit/e6d694687198266ff0fa1696276932c36c0a5f57
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: loading of title and border images in castle for dos
Changed paths:
engines/freescape/freescape.h
engines/freescape/games/castle.cpp
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index ccb3af3942a..25a0c6ff0d1 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -464,20 +464,14 @@ private:
void addSkanner(Area *area);
void loadAssetsFullGame() override;
-
void loadAssetsAtariFullGame() override;
void loadAssetsAtariDemo() override;
-
void loadAssetsAmigaFullGame() override;
void loadAssetsAmigaDemo() override;
-
void loadAssetsDOSFullGame() override;
void loadAssetsDOSDemo() override;
-
void loadAssetsZXFullGame() override;
-
void loadAssetsCPCFullGame() override;
-
void loadAssetsC64FullGame() override;
void drawDOSUI(Graphics::Surface *surface) override;
@@ -560,6 +554,7 @@ class CastleEngine : public FreescapeEngine {
public:
CastleEngine(OSystem *syst, const ADGameDescription *gd);
+ void titleScreen() override;
void loadAssetsDOSFullGame() override;
void gotoArea(uint16 areaID, int entranceID) override;
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index e81afcff921..04c95a7b2cc 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -56,19 +56,36 @@ Common::SeekableReadStream *CastleEngine::decryptFile(const Common::String filen
return (new Common::MemoryReadStream(encryptedBuffer, size));
}
+extern byte kEGADefaultPaletteData[16][3];
+
void CastleEngine::loadAssetsDOSFullGame() {
+ Common::File file;
Common::SeekableReadStream *stream = nullptr;
- stream = decryptFile("CMLE");
- loadMessagesVariableSize(stream, 0x11, 164);
- delete stream;
+ if (_renderMode == Common::kRenderEGA) {
+ file.open("CMOE.DAT");
+ _title = load8bitBinImage(&file, 0x0);
+ _title->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
+
+ file.close();
+
+ file.open("CME.DAT");
+ _border = load8bitBinImage(&file, 0x0);
+ _border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
+
+ file.close();
- stream = decryptFile("CMEDF");
- load8bitBinary(stream, 0, 16);
- for (auto &it : _areaMap)
- it._value->addStructure(_areaMap[255]);
- delete stream;
+ stream = decryptFile("CMLE");
+ loadMessagesVariableSize(stream, 0x11, 164);
+ delete stream;
+ stream = decryptFile("CMEDF");
+ load8bitBinary(stream, 0, 16);
+ for (auto &it : _areaMap)
+ it._value->addStructure(_areaMap[255]);
+ delete stream;
+ } else
+ error("Not implemented yet");
// CPC
// file = gameDir.createReadStreamForMember("cm.bin");
// if (file == nullptr)
@@ -76,6 +93,18 @@ void CastleEngine::loadAssetsDOSFullGame() {
// load8bitBinary(file, 0x791a, 16);
}
+void CastleEngine::titleScreen() {
+ if (isAmiga() || isAtariST()) // These releases has their own screens
+ return;
+
+ if (_title) {
+ drawTitle();
+ _gfx->flipBuffer();
+ g_system->updateScreen();
+ g_system->delayMillis(3000);
+ }
+}
+
void CastleEngine::gotoArea(uint16 areaID, int entranceID) {
debugC(1, kFreescapeDebugMove, "Jumping to area: %d, entrance: %d", areaID, entranceID);
if (!_gameStateBits.contains(areaID))
Commit: 8ac1af2c570dad1e58374b40a90fd3ddba755210
https://github.com/scummvm/scummvm/commit/8ac1af2c570dad1e58374b40a90fd3ddba755210
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: show basic UI in castle for dos
Changed paths:
engines/freescape/freescape.h
engines/freescape/games/castle.cpp
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 25a0c6ff0d1..ca41cd9b7c9 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -556,6 +556,7 @@ public:
void titleScreen() override;
void loadAssetsDOSFullGame() override;
+ void drawUI() override;
void gotoArea(uint16 areaID, int entranceID) override;
Common::Error saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave = false) override;
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 04c95a7b2cc..a1e6f6555ff 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -63,6 +63,8 @@ void CastleEngine::loadAssetsDOSFullGame() {
Common::SeekableReadStream *stream = nullptr;
if (_renderMode == Common::kRenderEGA) {
+ _viewArea = Common::Rect(39, 31, 278, 150);
+
file.open("CMOE.DAT");
_title = load8bitBinImage(&file, 0x0);
_title->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
@@ -127,6 +129,28 @@ void CastleEngine::gotoArea(uint16 areaID, int entranceID) {
_gfx->_keyColor = 255;
}
+void CastleEngine::drawUI() {
+ _gfx->setViewport(_fullscreenViewArea);
+
+ Graphics::Surface *surface = new Graphics::Surface();
+ surface->create(_screenW, _screenH, _gfx->_texturePixelFormat);
+ uint32 gray = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0xA0, 0xA0, 0xA0);
+ surface->fillRect(_fullscreenViewArea, gray);
+ drawCrossair(surface);
+
+ if (!_uiTexture)
+ _uiTexture = _gfx->createTexture(surface);
+ else
+ _uiTexture->update(surface);
+
+ _gfx->drawTexturedRect2D(_fullscreenViewArea, _fullscreenViewArea, _uiTexture);
+
+ surface->free();
+ delete surface;
+
+ _gfx->setViewport(_viewArea);
+}
+
Common::Error CastleEngine::saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave) {
return Common::kNoError;
}
Commit: ee1d083a4d8c1e0a80c7b8a280a01bdd294a1ac1
https://github.com/scummvm/scummvm/commit/ee1d083a4d8c1e0a80c7b8a280a01bdd294a1ac1
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: properly initialize _verts in shader renderer
Changed paths:
engines/freescape/gfx_opengl_shaders.cpp
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index 9e067cfd426..53f263c56c1 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -46,6 +46,7 @@ Renderer *CreateGfxOpenGLShader(int screenW, int screenH, Common::RenderMode ren
}
OpenGLShaderRenderer::OpenGLShaderRenderer(int screenW, int screenH, Common::RenderMode renderMode) : Renderer(screenW, screenH, renderMode) {
+ _verts = nullptr;
_triangleShader = nullptr;
_triangleVBO = 0;
Commit: 03e42d15d4905564b48c42c5aac1b33c7d515b69
https://github.com/scummvm/scummvm/commit/03e42d15d4905564b48c42c5aac1b33c7d515b69
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
GRAPHICS: OPENGL: added another setUniform function to set an uniform value in shaders from an array of ints
Changed paths:
graphics/opengl/shader.h
diff --git a/graphics/opengl/shader.h b/graphics/opengl/shader.h
index 16d908ec63d..185bd4fb063 100644
--- a/graphics/opengl/shader.h
+++ b/graphics/opengl/shader.h
@@ -131,6 +131,17 @@ public:
}
}
+ bool setUniform(const Common::String &uniform, const int size, const int *array) {
+ GLint pos = getUniformLocation(uniform);
+ if (pos != -1) {
+ use();
+ GL_CALL(glUniform1iv(pos, size, array));
+ return true;
+ } else {
+ return false;
+ }
+ }
+
// Different name to avoid overload ambiguity
bool setUniform1f(const Common::String &uniform, float f) {
GLint pos = getUniformLocation(uniform);
Commit: f57126e2fc57cb86cf41b6bf57a37622cad3db47
https://github.com/scummvm/scummvm/commit/f57126e2fc57cb86cf41b6bf57a37622cad3db47
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: initial implementation of stipple patterns in shader renderer
Changed paths:
engines/freescape/gfx_opengl_shaders.cpp
engines/freescape/gfx_opengl_shaders.h
engines/freescape/shaders/freescape_triangle.fragment
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index 53f263c56c1..d14ee7dc874 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -186,6 +186,7 @@ void OpenGLShaderRenderer::renderPlayerShoot(byte color, const Common::Point pos
identity(3, 3) = 1.0;
_triangleShader->use();
+ _triangleShader->setUniform("useStipple", false);
_triangleShader->setUniform("mvpMatrix", identity);
if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderZX) {
@@ -281,30 +282,32 @@ void OpenGLShaderRenderer::polygonOffset(bool enabled) {
}
void OpenGLShaderRenderer::setStippleData(byte *data) {
+ _triangleShader->use();
if (!data)
return;
- //_variableStippleArray = data;
- //for (int i = 0; i < 128; i++)
- // _variableStippleArray[i] = data[(i / 16) % 4];
+ for (int i = 0; i < 8; i++) {
+ byte b = data[i];
+ for (int j = 0; j < 8; j++) {
+ //debug("%d", 8*i + j);
+ _variableStippleArray[8*i + j] = b & 0x1;
+ b = b >> 1;
+ }
+ }
+ _triangleShader->setUniform("stipple", 64, (const int*)&_variableStippleArray);
}
void OpenGLShaderRenderer::useStipple(bool enabled) {
- /*if (enabled) {
+ _triangleShader->use();
+ if (enabled) {
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0.0f, -1.0f);
- glEnable(GL_POLYGON_STIPPLE);
- if (_renderMode == Common::kRenderZX ||
- _renderMode == Common::kRenderCPC ||
- _renderMode == Common::kRenderCGA)
- glPolygonStipple(_variableStippleArray);
- else
- glPolygonStipple(_defaultStippleArray);
+ _triangleShader->setUniform("useStipple", true);
} else {
glPolygonOffset(0, 0);
glDisable(GL_POLYGON_OFFSET_FILL);
- glDisable(GL_POLYGON_STIPPLE);
- }*/
+ _triangleShader->setUniform("useStipple", false);
+ }
}
void OpenGLShaderRenderer::useColor(uint8 r, uint8 g, uint8 b) {
@@ -350,7 +353,6 @@ Graphics::Surface *OpenGLShaderRenderer::getScreenshot() {
glReadPixels(screen.left, screen.top, screen.width(), screen.height(), GL_RGBA, GL_UNSIGNED_BYTE, s->getPixels());
flipVertical(s);
return s;
- return nullptr;
}
} // End of namespace Freescape
diff --git a/engines/freescape/gfx_opengl_shaders.h b/engines/freescape/gfx_opengl_shaders.h
index 1084a8fb1cb..ae3592a6587 100644
--- a/engines/freescape/gfx_opengl_shaders.h
+++ b/engines/freescape/gfx_opengl_shaders.h
@@ -58,17 +58,11 @@ public:
GLfloat y;
};
- /*Coord *_coords;
-
- void copyToCoordArray(uint idx, const Math::Vector2d &src) {
- assert(idx < kCoordsArraySize);
- _coords[idx].x = src.getValue(0); _coords[idx].y = src.getValue(1);
- }*/
-
OpenGL::Shader *_triangleShader;
OpenGL::Shader *_bitmapShader;
GLuint _triangleVBO;
GLuint _bitmapVBO;
+ int _variableStippleArray[64];
virtual void init() override;
virtual void clear(uint8 color) override;
diff --git a/engines/freescape/shaders/freescape_triangle.fragment b/engines/freescape/shaders/freescape_triangle.fragment
index aaf98049c01..8ab397df899 100644
--- a/engines/freescape/shaders/freescape_triangle.fragment
+++ b/engines/freescape/shaders/freescape_triangle.fragment
@@ -1,8 +1,17 @@
OUTPUT
+uniform UBOOL useStipple;
+uniform int stipple[64];
+
varying vec4 var_color;
void main()
{
- outColor = var_color;
+ if (UBOOL_TEST(useStipple)) {
+ ivec2 coord = ivec2(gl_FragCoord.xy - 0.5);
+ if (stipple[int(mod(coord.x, 8) + mod(coord.y, 8) * 8)] == 0)
+ discard;
+ }
+
+ outColor = var_color;
}
\ No newline at end of file
Commit: f937d769b07147cb436bc2e3eab91e0b57698614
https://github.com/scummvm/scummvm/commit/f937d769b07147cb436bc2e3eab91e0b57698614
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: avoid crashing parsing driller conditions for zx
Changed paths:
engines/freescape/language/8bitDetokeniser.cpp
diff --git a/engines/freescape/language/8bitDetokeniser.cpp b/engines/freescape/language/8bitDetokeniser.cpp
index 16f57bf2924..988182045d5 100644
--- a/engines/freescape/language/8bitDetokeniser.cpp
+++ b/engines/freescape/language/8bitDetokeniser.cpp
@@ -54,7 +54,8 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
0, 0, 0, 0, 0, 0, 2, 2,
1};
- detokenisedStream += Common::String::format("CONDITION FLAG: %x\n", tokenisedCondition[0]);
+ if (sizeOfTokenisedContent > 0)
+ detokenisedStream += Common::String::format("CONDITION FLAG: %x\n", tokenisedCondition[0]);
Token::Type newConditional = Token::UNKNOWN;
Token::Type oldConditional = Token::UNKNOWN;
Commit: cb3c3e500255feedd91274c572794de74da2ed2f
https://github.com/scummvm/scummvm/commit/cb3c3e500255feedd91274c572794de74da2ed2f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: improved rendering of stipple in shader renderer
Changed paths:
engines/freescape/gfx_opengl_shaders.cpp
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index d14ee7dc874..d43f8966bbc 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -290,7 +290,7 @@ void OpenGLShaderRenderer::setStippleData(byte *data) {
byte b = data[i];
for (int j = 0; j < 8; j++) {
//debug("%d", 8*i + j);
- _variableStippleArray[8*i + j] = b & 0x1;
+ _variableStippleArray[i + 8*j] = b & 0x1;
b = b >> 1;
}
}
Commit: fdce543286769434676f1d7990269fef879db062
https://github.com/scummvm/scummvm/commit/fdce543286769434676f1d7990269fef879db062
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: fixed incorrect parsing of 8-bit conditions
Changed paths:
engines/freescape/games/dark/dark.cpp
engines/freescape/language/8bitDetokeniser.cpp
engines/freescape/language/instruction.cpp
diff --git a/engines/freescape/games/dark/dark.cpp b/engines/freescape/games/dark/dark.cpp
index 1e17560ba1d..55484da32d3 100644
--- a/engines/freescape/games/dark/dark.cpp
+++ b/engines/freescape/games/dark/dark.cpp
@@ -95,9 +95,9 @@ void DarkEngine::addWalls(Area *area) {
if (target > 0) {
area->addObjectFromArea(id, _areaMap[255]);
GeometricObject *gobj = (GeometricObject *)area->objectWithID(id);
- assert((*(gobj->_condition[1]._thenInstructions))[0].getType() == Token::Type::GOTO);
- assert((*(gobj->_condition[1]._thenInstructions))[0]._destination == 0);
- (*(gobj->_condition[1]._thenInstructions))[0].setSource(target);
+ assert((*(gobj->_condition[0]._thenInstructions))[0].getType() == Token::Type::GOTO);
+ assert((*(gobj->_condition[0]._thenInstructions))[0]._destination == 0);
+ (*(gobj->_condition[0]._thenInstructions))[0].setSource(target);
} else
area->addObjectFromArea(id + 1, _areaMap[255]);
diff --git a/engines/freescape/language/8bitDetokeniser.cpp b/engines/freescape/language/8bitDetokeniser.cpp
index 988182045d5..c4ac1c47621 100644
--- a/engines/freescape/language/8bitDetokeniser.cpp
+++ b/engines/freescape/language/8bitDetokeniser.cpp
@@ -80,8 +80,11 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
branch.setBranches(conditionalInstructions, nullptr);
instructions.push_back(branch);
- if (bytePointer > 0)
+ if (bytePointer > 0) {
detokenisedStream += "ENDIF\n";
+ // Allocate the next vector of instructions
+ conditionalInstructions = new FCLInstructionVector();
+ }
if (oldConditional == Token::SHOTQ)
detokenisedStream += "IF SHOT? THEN\n";
@@ -91,9 +94,6 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
detokenisedStream += "IF COLLIDED? THEN\n";
else
error("Invalid conditional: %x", oldConditional);
-
- // Allocate the next vector of instructions
- conditionalInstructions = new FCLInstructionVector();
}
// get the actual operation
@@ -421,17 +421,6 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
detokenisedStream += "\n";
}
- // if (!conditionalInstructions)
- // conditionalInstructions = new FCLInstructionVector();
-
- // conditionalInstructions->push_back(currentInstruction);
-
- FCLInstruction branch;
- branch = FCLInstruction(oldConditional);
-
- branch.setBranches(conditionalInstructions, nullptr);
- instructions.push_back(branch);
-
return detokenisedStream;
}
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index 7b845bf28b1..509e060f142 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -94,7 +94,12 @@ void FreescapeEngine::executeObjectConditions(GeometricObject *obj, bool shot, b
if (!obj->_conditionSource.empty()) {
_firstSound = true;
_objExecutingCodeSize = obj->getSize();
- debugC(1, kFreescapeDebugCode, "Executing with collision flag: %s", obj->_conditionSource.c_str());
+ if (collided)
+ debugC(1, kFreescapeDebugCode, "Executing with collision flag: %s", obj->_conditionSource.c_str());
+ else if (shot)
+ debugC(1, kFreescapeDebugCode, "Executing with shot flag: %s", obj->_conditionSource.c_str());
+ else
+ error("Neither shot or collided flag is set!");
executeCode(obj->_condition, shot, collided, false); // TODO: check this last parameter
}
}
@@ -124,7 +129,7 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
int codeSize = code.size();
while (ip <= codeSize - 1) {
FCLInstruction &instruction = code[ip];
- debugC(1, kFreescapeDebugCode, "Executing ip: %d in code with size: %d", ip, codeSize);
+ debugC(1, kFreescapeDebugCode, "Executing ip: %d with type %d in code with size: %d", ip, instruction.getType(), codeSize);
switch (instruction.getType()) {
default:
if (!isCastle())
Commit: 8260ca88281699f4abffde4ae997b8187199c77a
https://github.com/scummvm/scummvm/commit/8260ca88281699f4abffde4ae997b8187199c77a
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: make triangle shader more compatible with gles2
Changed paths:
engines/freescape/shaders/freescape_triangle.fragment
diff --git a/engines/freescape/shaders/freescape_triangle.fragment b/engines/freescape/shaders/freescape_triangle.fragment
index 8ab397df899..2088bdc4357 100644
--- a/engines/freescape/shaders/freescape_triangle.fragment
+++ b/engines/freescape/shaders/freescape_triangle.fragment
@@ -8,8 +8,8 @@ varying vec4 var_color;
void main()
{
if (UBOOL_TEST(useStipple)) {
- ivec2 coord = ivec2(gl_FragCoord.xy - 0.5);
- if (stipple[int(mod(coord.x, 8) + mod(coord.y, 8) * 8)] == 0)
+ vec2 coord = ivec2(gl_FragCoord.xy - 0.5);
+ if (stipple[int(mod(coord.x, 8.) + mod(coord.y, 8.) * 8)] == 0)
discard;
}
Commit: 1e28728f146b054d0f6538d43e5dab4e1c4fa173
https://github.com/scummvm/scummvm/commit/1e28728f146b054d0f6538d43e5dab4e1c4fa173
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: make triangle shader more compatible with gles2 (again)
Changed paths:
engines/freescape/shaders/freescape_triangle.fragment
diff --git a/engines/freescape/shaders/freescape_triangle.fragment b/engines/freescape/shaders/freescape_triangle.fragment
index 2088bdc4357..9ad098b111e 100644
--- a/engines/freescape/shaders/freescape_triangle.fragment
+++ b/engines/freescape/shaders/freescape_triangle.fragment
@@ -8,8 +8,8 @@ varying vec4 var_color;
void main()
{
if (UBOOL_TEST(useStipple)) {
- vec2 coord = ivec2(gl_FragCoord.xy - 0.5);
- if (stipple[int(mod(coord.x, 8.) + mod(coord.y, 8.) * 8)] == 0)
+ ivec2 coord = ivec2(gl_FragCoord.xy - 0.5);
+ if (stipple[int(mod(float(coord.x), 8.) + mod(float(coord.y), 8.) * 8.)] == 0)
discard;
}
Commit: 7fe579351eee2a4f4c0a4024866e086850ea3485
https://github.com/scummvm/scummvm/commit/7fe579351eee2a4f4c0a4024866e086850ea3485
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: added detection of some unsupported demos
Changed paths:
engines/freescape/detection.cpp
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index cdfcccba49d..8f9d8c06ddf 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -71,6 +71,18 @@ static const ADGameDescription gameDescriptions[] = {
GF_ZX_BUDGET,
GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
},
+ {
+ "driller",
+ "Not implemented yet",
+ {
+ {"DRILLER.ZX.DATA", 0, "e571795806ed8a30df0fa3109eaa8ffb", 36000},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformZX,
+ ADGF_UNSUPPORTED | ADGF_DEMO,
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
+ },
{
"driller",
"",
@@ -226,6 +238,20 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_DEMO,
GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
},
+ {
+ "driller",
+ "Packed data",
+ {
+ {"driller.prg", 0, "ae9b03e247def6f0793174b1cb4352b5", 1821},
+ {"data", 0, "0c927fbc6c390afd0d0c15b2d7f8766f", 10893},
+ {"demo.cmd", 0, "9c732dcdad26b36b537e632924cd8f0e", 745},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformAtariST,
+ ADGF_UNSUPPORTED | ADGF_DEMO,
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
+ },
{
"darkside",
"",
@@ -256,6 +282,18 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE | ADGF_DEMO,
GUIO3(GUIO_NOMIDI, GUIO_RENDEREGA, GUIO_RENDERCGA)
},
+ {
+ "darkside",
+ "Not implemented yet",
+ {
+ {"DARKSIDE.ZX.DATA", 0, "0e4d9b6e64ff24801272ff0b18a3caab", 29182},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformZX,
+ ADGF_UNSUPPORTED | ADGF_DEMO,
+ GUIO1(GUIO_NOMIDI)
+ },
{
"totaleclipse",
"",
Commit: e5d0ebefd770e7696666b9d51cff32e9609102d0
https://github.com/scummvm/scummvm/commit/e5d0ebefd770e7696666b9d51cff32e9609102d0
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: initial support for Dark Side ZX demo
Changed paths:
A engines/freescape/games/dark/zx.cpp
engines/freescape/assets.cpp
engines/freescape/detection.cpp
engines/freescape/freescape.h
engines/freescape/games/dark/dark.cpp
engines/freescape/games/dark/dos.cpp
engines/freescape/loaders/8bitBinaryLoader.cpp
engines/freescape/module.mk
diff --git a/engines/freescape/assets.cpp b/engines/freescape/assets.cpp
index d9e6e16931e..03369a113be 100644
--- a/engines/freescape/assets.cpp
+++ b/engines/freescape/assets.cpp
@@ -50,7 +50,7 @@ void FreescapeEngine::loadAssetsFullGame() {
} else if (isDOS()) {
loadAssetsDOSFullGame();
} else
- error("Invalid or unsupported render mode %s for Driller", Common::getRenderModeDescription(_renderMode));
+ error("Invalid or unsupported render mode %s", Common::getRenderModeDescription(_renderMode));
}
void FreescapeEngine::loadAssetsDemo() {
@@ -61,8 +61,10 @@ void FreescapeEngine::loadAssetsDemo() {
loadAssetsAtariDemo();
} else if (isDOS()) {
loadAssetsDOSDemo();
+ } else if (isSpectrum()) {
+ loadAssetsZXDemo();
} else
- error("Unsupported demo for Driller");
+ error("Unsupported demo");
}
void FreescapeEngine::loadAssetsAtariDemo() {
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index 8f9d8c06ddf..032e9bf425d 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -284,14 +284,14 @@ static const ADGameDescription gameDescriptions[] = {
},
{
"darkside",
- "Not implemented yet",
+ "Demo",
{
{"DARKSIDE.ZX.DATA", 0, "0e4d9b6e64ff24801272ff0b18a3caab", 29182},
AD_LISTEND
},
Common::EN_ANY,
Common::kPlatformZX,
- ADGF_UNSUPPORTED | ADGF_DEMO,
+ ADGF_UNSTABLE | ADGF_DEMO,
GUIO1(GUIO_NOMIDI)
},
{
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index ca41cd9b7c9..0d81cb0a5d0 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -519,13 +519,20 @@ public:
void pressedKey(const int keycode) override;
void executePrint(FCLInstruction &instruction) override;
+ void initDOS();
+ void initZX();
+
void loadAssetsDOSFullGame() override;
void loadAssetsDOSDemo() override;
+ void loadAssetsZXDemo() override;
+
int _lastTenSeconds;
void updateTimeVariables() override;
void drawDOSUI(Graphics::Surface *surface) override;
+ void drawZXUI(Graphics::Surface *surface) override;
+
void drawFullscreenMessage(Common::String message);
Common::Error saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave = false) override;
Common::Error loadGameStreamExtended(Common::SeekableReadStream *stream) override;
diff --git a/engines/freescape/games/dark/dark.cpp b/engines/freescape/games/dark/dark.cpp
index 55484da32d3..d0a36c145d0 100644
--- a/engines/freescape/games/dark/dark.cpp
+++ b/engines/freescape/games/dark/dark.cpp
@@ -29,7 +29,11 @@
namespace Freescape {
DarkEngine::DarkEngine(OSystem *syst, const ADGameDescription *gd) : FreescapeEngine(syst, gd) {
- _viewArea = Common::Rect(40, 24, 279, 124);
+ if (isDOS())
+ initDOS();
+ else if (isSpectrum())
+ initZX();
+
_playerHeightNumber = 1;
_playerHeights.push_back(16);
_playerHeights.push_back(48);
@@ -251,7 +255,7 @@ void DarkEngine::updateTimeVariables() {
void DarkEngine::borderScreen() {
if (_border) {
drawBorder();
- if (isDemo()) {
+ if (isDemo() && isDOS()) {
drawFullscreenMessage(_messagesList[27]);
drawFullscreenMessage(_messagesList[28]);
drawFullscreenMessage(_messagesList[29]);
diff --git a/engines/freescape/games/dark/dos.cpp b/engines/freescape/games/dark/dos.cpp
index 12881e46e46..28b5304478e 100644
--- a/engines/freescape/games/dark/dos.cpp
+++ b/engines/freescape/games/dark/dos.cpp
@@ -28,6 +28,13 @@ namespace Freescape {
extern byte kEGADefaultPaletteData[16][3];
+void DarkEngine::initDOS() {
+ if (_renderMode == Common::kRenderEGA)
+ _viewArea = Common::Rect(40, 24, 279, 124);
+ else
+ error("Invalid or unknown render mode");
+}
+
void DarkEngine::loadAssetsDOSDemo() {
Common::File file;
if (_renderMode == Common::kRenderEGA) {
diff --git a/engines/freescape/games/dark/zx.cpp b/engines/freescape/games/dark/zx.cpp
new file mode 100644
index 00000000000..e2f5211b146
--- /dev/null
+++ b/engines/freescape/games/dark/zx.cpp
@@ -0,0 +1,131 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/file.h"
+
+#include "freescape/freescape.h"
+#include "freescape/language/8bitDetokeniser.h"
+
+namespace Freescape {
+
+void DarkEngine::initZX() {
+ _viewArea = Common::Rect(56, 28, 265, 132);
+}
+
+void DarkEngine::loadAssetsZXDemo() {
+ Common::File file;
+
+ file.open("darkside.zx.title");
+ if (file.isOpen()) {
+ _title = loadAndCenterScrImage(&file);
+ } else
+ error("Unable to find darkside.zx.title");
+
+ file.close();
+ file.open("darkside.zx.border");
+ if (file.isOpen()) {
+ _border = loadAndCenterScrImage(&file);
+ } else
+ error("Unable to find driller.zx.border");
+ file.close();
+
+
+ file.open("darkside.zx.data");
+
+ if (!file.isOpen())
+ error("Failed to open darksize.zx.data");
+
+ loadMessagesFixedSize(&file, 0x56c, 19, 24);
+ loadMessagesFixedSize(&file, 0x5761, 264, 5);
+
+ loadFonts(&file, 0x6164);
+ //loadGlobalObjects(&file, 0x1d13, 8);
+ load8bitBinary(&file, 0x62c6, 4);
+ /*for (auto &it : _areaMap) {
+ addWalls(it._value);
+ addECDs(it._value);
+ }*/
+}
+
+void DarkEngine::drawZXUI(Graphics::Surface *surface) {
+ /*uint32 color = 1;
+ uint8 r, g, b;
+
+ _gfx->readFromPalette(color, r, g, b);
+ uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+ color = _currentArea->_usualBackgroundColor;
+ if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
+ color = (*_gfx->_colorRemaps)[color];
+ }
+
+ _gfx->readFromPalette(color, r, g, b);
+ uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+ int score = _gameStateVars[k8bitVariableScore];
+ drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 199, 137, front, back, surface);
+ drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 199, 145, front, back, surface);
+ drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 199, 153, front, back, surface);
+
+ drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 71, 168, front, back, surface);
+ drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 71, 177, front, back, surface);
+ drawStringInSurface(Common::String::format("%07d", score), 95, 8, front, back, surface);
+
+ int seconds, minutes, hours;
+ getTimeFromCountdown(seconds, minutes, hours);
+ // TODO: implement binary clock
+
+ Common::String message;
+ int deadline;
+ getLatestMessages(message, deadline);
+ if (deadline <= _countdown) {
+ drawStringInSurface(message, 112, 177, back, front, surface);
+ _temporaryMessages.push_back(message);
+ _temporaryMessageDeadlines.push_back(deadline);
+ } else
+ drawStringInSurface(_currentArea->_name, 112, 177, front, back, surface);
+
+ int energy = _gameStateVars[k8bitVariableEnergy]; // called fuel in this game
+ int shield = _gameStateVars[k8bitVariableShield];
+
+ _gfx->readFromPalette(9, r, g, b);
+ uint32 blue = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+ if (shield >= 0) {
+ Common::Rect shieldBar;
+ shieldBar = Common::Rect(72, 139, 151 - (k8bitMaxShield - shield), 146);
+ surface->fillRect(shieldBar, front);
+
+ shieldBar = Common::Rect(72, 140, 151 - (k8bitMaxShield - shield), 145);
+ surface->fillRect(shieldBar, blue);
+ }
+
+ if (energy >= 0) {
+ Common::Rect energyBar;
+ energyBar = Common::Rect(72, 147, 151 - (k8bitMaxEnergy - energy), 154);
+ surface->fillRect(energyBar, front);
+
+ energyBar = Common::Rect(72, 148, 151 - (k8bitMaxEnergy - energy), 153);
+ surface->fillRect(energyBar, blue);
+ }*/
+}
+
+} // End of namespace Freescape
\ No newline at end of file
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 64fe016df02..47bce668a63 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -757,7 +757,7 @@ void FreescapeEngine::loadMessagesFixedSize(Common::SeekableReadStream *file, in
file->read(buffer, size);
Common::String message = (const char *)buffer;
_messagesList.push_back(message);
- debugC(1, kFreescapeDebugParser, "%s", _messagesList[_messagesList.size() - 1].c_str());
+ debugC(1, kFreescapeDebugParser, "'%s'", _messagesList[_messagesList.size() - 1].c_str());
}
free(buffer);
}
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index fe3a2a95cda..cf02372b576 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -8,6 +8,7 @@ MODULE_OBJS := \
games/castle.o \
games/dark/dark.o \
games/dark/dos.o \
+ games/dark/zx.o \
games/driller/amiga.o \
games/driller/atari.o \
games/driller/c64.o \
Commit: 81ef1ec054fce6d347d28119aeaa2dcd60c5fe43
https://github.com/scummvm/scummvm/commit/81ef1ec054fce6d347d28119aeaa2dcd60c5fe43
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: started to implemented Dark Side UI in ZX spectrum
Changed paths:
engines/freescape/games/dark/zx.cpp
diff --git a/engines/freescape/games/dark/zx.cpp b/engines/freescape/games/dark/zx.cpp
index e2f5211b146..ce7800a8ae5 100644
--- a/engines/freescape/games/dark/zx.cpp
+++ b/engines/freescape/games/dark/zx.cpp
@@ -66,7 +66,7 @@ void DarkEngine::loadAssetsZXDemo() {
}
void DarkEngine::drawZXUI(Graphics::Surface *surface) {
- /*uint32 color = 1;
+ uint32 color = 7;
uint8 r, g, b;
_gfx->readFromPalette(color, r, g, b);
@@ -81,13 +81,13 @@ void DarkEngine::drawZXUI(Graphics::Surface *surface) {
uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
int score = _gameStateVars[k8bitVariableScore];
- drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 199, 137, front, back, surface);
- drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 199, 145, front, back, surface);
- drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 199, 153, front, back, surface);
+ drawStringInSurface(Common::String::format("%04d", int(2 * _position.x())), 191, 141, front, back, surface);
+ drawStringInSurface(Common::String::format("%04d", int(2 * _position.z())), 191, 149, front, back, surface);
+ drawStringInSurface(Common::String::format("%04d", int(2 * _position.y())), 191, 157, front, back, surface);
- drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 71, 168, front, back, surface);
- drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 71, 177, front, back, surface);
- drawStringInSurface(Common::String::format("%07d", score), 95, 8, front, back, surface);
+ drawStringInSurface(Common::String::format("%02d", int(_angleRotations[_angleRotationIndex])), 78, 165, front, back, surface);
+ drawStringInSurface(Common::String::format("%3d", _playerSteps[_playerStepIndex]), 78, 173, front, back, surface);
+ drawStringInSurface(Common::String::format("%07d", score), 94, 13, front, back, surface);
int seconds, minutes, hours;
getTimeFromCountdown(seconds, minutes, hours);
@@ -97,35 +97,32 @@ void DarkEngine::drawZXUI(Graphics::Surface *surface) {
int deadline;
getLatestMessages(message, deadline);
if (deadline <= _countdown) {
- drawStringInSurface(message, 112, 177, back, front, surface);
+ drawStringInSurface(message, 112, 173, back, front, surface);
_temporaryMessages.push_back(message);
_temporaryMessageDeadlines.push_back(deadline);
} else
- drawStringInSurface(_currentArea->_name, 112, 177, front, back, surface);
+ drawStringInSurface(_currentArea->_name, 112, 173, front, back, surface);
int energy = _gameStateVars[k8bitVariableEnergy]; // called fuel in this game
int shield = _gameStateVars[k8bitVariableShield];
- _gfx->readFromPalette(9, r, g, b);
- uint32 blue = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
-
if (shield >= 0) {
Common::Rect shieldBar;
- shieldBar = Common::Rect(72, 139, 151 - (k8bitMaxShield - shield), 146);
- surface->fillRect(shieldBar, front);
+ shieldBar = Common::Rect(80, 141, 151 - (k8bitMaxShield - shield), 147);
+ surface->fillRect(shieldBar, back);
- shieldBar = Common::Rect(72, 140, 151 - (k8bitMaxShield - shield), 145);
- surface->fillRect(shieldBar, blue);
+ shieldBar = Common::Rect(80, 142, 151 - (k8bitMaxShield - shield), 146);
+ surface->fillRect(shieldBar, front);
}
if (energy >= 0) {
Common::Rect energyBar;
energyBar = Common::Rect(72, 147, 151 - (k8bitMaxEnergy - energy), 154);
- surface->fillRect(energyBar, front);
+ surface->fillRect(energyBar, back);
energyBar = Common::Rect(72, 148, 151 - (k8bitMaxEnergy - energy), 153);
- surface->fillRect(energyBar, blue);
- }*/
+ surface->fillRect(energyBar, front);
+ }
}
} // End of namespace Freescape
\ No newline at end of file
Commit: 0eae3fbde3995a3b987e06d234a99a2fe57ebd54
https://github.com/scummvm/scummvm/commit/0eae3fbde3995a3b987e06d234a99a2fe57ebd54
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: attempt to fix effect execution when stepping up
Changed paths:
engines/freescape/movement.cpp
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index f914780359e..aa432f1e3ee 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -260,6 +260,19 @@ void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTim
if (stepUp) {
if (!isPlayingSound())
playSound(4, false);
+
+ positionY = _position.y();
+ int fallen;
+ for (fallen = 1; fallen < 64; fallen++) {
+ _position.set(_position.x(), positionY - fallen , _position.z());
+ if (tryStepDown(_position))
+ break;
+ }
+ assert(fallen < 64);
+ fallen++;
+ fallen++;
+ _position.set(_position.x(), positionY - fallen, _position.z());
+
debugC(1, kFreescapeDebugCode, "Runing effects:");
checkCollisions(true); // run the effects (again)
} else {
@@ -358,7 +371,7 @@ bool FreescapeEngine::checkCollisions(bool executeCode) {
// FIXME: find a better workaround of this
if (gobj->getSize().length() > 3000) {
if (largeObjectWasBlocking)
- break;
+ continue;
largeObjectWasBlocking = true;
}
Commit: d18b4fd29d13d2d5f234b0e8638c95a9fcd13481
https://github.com/scummvm/scummvm/commit/d18b4fd29d13d2d5f234b0e8638c95a9fcd13481
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: some fixes in the parsing of fcl opcodes
Changed paths:
engines/freescape/language/8bitDetokeniser.cpp
engines/freescape/language/instruction.cpp
diff --git a/engines/freescape/language/8bitDetokeniser.cpp b/engines/freescape/language/8bitDetokeniser.cpp
index c4ac1c47621..1d28314779c 100644
--- a/engines/freescape/language/8bitDetokeniser.cpp
+++ b/engines/freescape/language/8bitDetokeniser.cpp
@@ -77,15 +77,15 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
FCLInstruction branch;
branch = FCLInstruction(oldConditional);
- branch.setBranches(conditionalInstructions, nullptr);
- instructions.push_back(branch);
-
if (bytePointer > 0) {
detokenisedStream += "ENDIF\n";
// Allocate the next vector of instructions
conditionalInstructions = new FCLInstructionVector();
}
+ branch.setBranches(conditionalInstructions, nullptr);
+ instructions.push_back(branch);
+
if (oldConditional == Token::SHOTQ)
detokenisedStream += "IF SHOT? THEN\n";
else if (oldConditional == Token::TIMERQ)
@@ -124,6 +124,8 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
case 0:
detokenisedStream += "NOP ";
currentInstruction = FCLInstruction(Token::NOP);
+ conditionalInstructions->push_back(currentInstruction);
+ currentInstruction = FCLInstruction(Token::UNKNOWN);
break; // NOP
case 1: // add three-byte value to score
{
@@ -188,6 +190,7 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
case 9:
detokenisedStream += "ADDVAR (1, v";
+ detokenisedStream += Common::String::format("%d)", tokenisedCondition[bytePointer]);
currentInstruction = FCLInstruction(Token::ADDVAR);
currentInstruction.setSource(tokenisedCondition[bytePointer]);
currentInstruction.setDestination(1);
@@ -198,6 +201,7 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
break;
case 10:
detokenisedStream += "SUBVAR (1, v";
+ detokenisedStream += Common::String::format("%d)", tokenisedCondition[bytePointer]);
currentInstruction = FCLInstruction(Token::SUBVAR);
currentInstruction.setSource(tokenisedCondition[bytePointer]);
currentInstruction.setDestination(1);
@@ -357,8 +361,7 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
case 20:
detokenisedStream += "SETVAR ";
detokenisedStream += Common::String::format("(v%d, %d)", (int)tokenisedCondition[bytePointer], (int)tokenisedCondition[bytePointer + 1]);
- bytePointer += 2;
- numberOfArguments = 0;
+ currentInstruction = FCLInstruction(Token::SETVAR);
break;
case 35:
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index 509e060f142..5fc29ed61df 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -127,6 +127,7 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
assert(!(shot && collided));
int ip = 0;
int codeSize = code.size();
+ assert(codeSize > 0);
while (ip <= codeSize - 1) {
FCLInstruction &instruction = code[ip];
debugC(1, kFreescapeDebugCode, "Executing ip: %d with type %d in code with size: %d", ip, instruction.getType(), codeSize);
@@ -135,6 +136,10 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
if (!isCastle())
error("Instruction %x at ip: %d not implemented!", instruction.getType(), ip);
break;
+ case Token::NOP:
+ debugC(1, kFreescapeDebugCode, "Executing NOP at ip: %d", ip);
+ break;
+
case Token::COLLIDEDQ:
if (collided)
executeCode(*instruction._thenInstructions, shot, collided, timer);
@@ -199,6 +204,9 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
case Token::CLEARBIT:
executeClearBit(instruction);
break;
+ case Token::TOGGLEBIT:
+ executeToggleBit(instruction);
+ break;
case Token::PRINT:
executePrint(instruction);
break;
Commit: ea41d363b13efd8c74785a01183281342baadbd1
https://github.com/scummvm/scummvm/commit/ea41d363b13efd8c74785a01183281342baadbd1
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: correctly print the SETVAR opcode
Changed paths:
engines/freescape/language/8bitDetokeniser.cpp
diff --git a/engines/freescape/language/8bitDetokeniser.cpp b/engines/freescape/language/8bitDetokeniser.cpp
index 1d28314779c..3b76b2fa9e6 100644
--- a/engines/freescape/language/8bitDetokeniser.cpp
+++ b/engines/freescape/language/8bitDetokeniser.cpp
@@ -359,8 +359,7 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
break;
case 20:
- detokenisedStream += "SETVAR ";
- detokenisedStream += Common::String::format("(v%d, %d)", (int)tokenisedCondition[bytePointer], (int)tokenisedCondition[bytePointer + 1]);
+ detokenisedStream += "SETVAR (v";
currentInstruction = FCLInstruction(Token::SETVAR);
break;
Commit: ee159b6a0e05d6fa7ddb83266f6993f279b47558
https://github.com/scummvm/scummvm/commit/ee159b6a0e05d6fa7ddb83266f6993f279b47558
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: refactored clear code as drawBackground
Changed paths:
engines/freescape/area.cpp
engines/freescape/freescape.cpp
engines/freescape/games/castle.cpp
engines/freescape/games/eclipse.cpp
engines/freescape/gfx.cpp
engines/freescape/gfx.h
engines/freescape/gfx_opengl.cpp
engines/freescape/gfx_opengl.h
engines/freescape/gfx_opengl_shaders.cpp
engines/freescape/gfx_opengl_shaders.h
engines/freescape/gfx_tinygl.cpp
engines/freescape/gfx_tinygl.h
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 64304fb9b6e..c1aa7f9a0ee 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -223,7 +223,6 @@ void Area::resetArea() {
void Area::draw(Freescape::Renderer *gfx) {
- gfx->clear(_skyColor);
assert(_drawableObjects.size() > 0);
for (auto &obj : _drawableObjects) {
if (!obj->isDestroyed() && !obj->isInvisible()) {
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 661a2db9dff..da72e733d90 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -267,9 +267,9 @@ void FreescapeEngine::takeDamageFromSensor() {
void FreescapeEngine::drawBackground() {
_gfx->setViewport(_fullscreenViewArea);
- _gfx->clear(_currentArea->_usualBackgroundColor);
+ _gfx->drawBackground(_currentArea->_usualBackgroundColor);
_gfx->setViewport(_viewArea);
- _gfx->clear(_currentArea->_skyColor);
+ _gfx->drawBackground(_currentArea->_skyColor);
}
void FreescapeEngine::drawFrame() {
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index a1e6f6555ff..1aa53d527f9 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -124,7 +124,6 @@ void CastleEngine::gotoArea(uint16 areaID, int entranceID) {
if (_currentArea->_skyColor > 0 && _currentArea->_skyColor != 255) {
_gfx->_keyColor = 0;
- _gfx->clear(_currentArea->_skyColor);
} else
_gfx->_keyColor = 255;
}
diff --git a/engines/freescape/games/eclipse.cpp b/engines/freescape/games/eclipse.cpp
index 7f970e86209..0eff0b8a1b3 100644
--- a/engines/freescape/games/eclipse.cpp
+++ b/engines/freescape/games/eclipse.cpp
@@ -181,7 +181,6 @@ void EclipseEngine::gotoArea(uint16 areaID, int entranceID) {
if (_currentArea->_skyColor > 0 && _currentArea->_skyColor != 255) {
_gfx->_keyColor = 0;
- _gfx->clear(_currentArea->_skyColor);
} else
_gfx->_keyColor = 255;
}
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index b8b45a37179..ac69bafa823 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -925,6 +925,22 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
polygonOffset(false);
}
+void Renderer::drawBackground(uint8 color) {
+
+ if (_colorRemaps && _colorRemaps->contains(color)) {
+ color = (*_colorRemaps)[color];
+ }
+
+ byte *stipple = nullptr;
+ uint8 r1, g1, b1, r2, g2, b2;
+ bool render = getRGBAt(color, r1, g1, b1, r2, g2, b2, stipple);
+ if (!render)
+ r1 = g1 = b1 = 0;
+
+ assert(stipple == nullptr); // Unclear if this is ever used
+ clear(r1, g1, b1);
+}
+
Graphics::RendererType determinateRenderType() {
Common::String rendererConfig = ConfMan.get("renderer");
Graphics::RendererType desiredRendererType = Graphics::Renderer::parseTypeCode(rendererConfig);
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 6bae31840c9..0d3acc47099 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -91,8 +91,9 @@ public:
virtual void renderFace(const Common::Array<Math::Vector3d> &vertices) = 0;
void setColorRemaps(ColorReMap *colorRemaps);
- virtual void clear(uint8 color) = 0;
+ virtual void clear(uint8 r, uint8 g, uint8 b) = 0;
virtual void drawFloor(uint8 color) = 0;
+ virtual void drawBackground(uint8 color);
Common::Rect viewport() const;
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index 0c09bb0f5ba..75c6408d35f 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -306,14 +306,7 @@ void OpenGLRenderer::useColor(uint8 r, uint8 g, uint8 b) {
glColor3ub(r, g, b);
}
-void OpenGLRenderer::clear(uint8 color) {
- uint8 r, g, b;
-
- if (_colorRemaps && _colorRemaps->contains(color)) {
- color = (*_colorRemaps)[color];
- }
-
- readFromPalette(color, r, g, b);
+void OpenGLRenderer::clear(uint8 r, uint8 g, uint8 b) {
glClearColor(r / 255., g / 255., b / 255., 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
diff --git a/engines/freescape/gfx_opengl.h b/engines/freescape/gfx_opengl.h
index a3925a8d4ba..07536360988 100644
--- a/engines/freescape/gfx_opengl.h
+++ b/engines/freescape/gfx_opengl.h
@@ -82,7 +82,7 @@ public:
GLubyte *_variableStippleArray;
virtual void init() override;
- virtual void clear(uint8 color) override;
+ virtual void clear(uint8 r, uint8 g, uint8 b) override;
virtual void setViewport(const Common::Rect &rect) override;
virtual void positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest) override;
virtual void updateProjectionMatrix(float fov, float nearClipPlane, float farClipPlane) override;
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index d43f8966bbc..f46abb766fe 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -316,15 +316,8 @@ void OpenGLShaderRenderer::useColor(uint8 r, uint8 g, uint8 b) {
_triangleShader->setUniform("color", color);
}
-void OpenGLShaderRenderer::clear(uint8 color) {
- uint8 r, g, b;
-
- if (_colorRemaps && _colorRemaps->contains(color)) {
- color = (*_colorRemaps)[color];
- }
-
- readFromPalette(color, r, g, b);
- glClearColor(0, 0, 0, 1.0);
+void OpenGLShaderRenderer::clear(uint8 r, uint8 g, uint8 b) {
+ glClearColor(r / 255., g / 255., b / 255., 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
diff --git a/engines/freescape/gfx_opengl_shaders.h b/engines/freescape/gfx_opengl_shaders.h
index ae3592a6587..ddcfe4a15b5 100644
--- a/engines/freescape/gfx_opengl_shaders.h
+++ b/engines/freescape/gfx_opengl_shaders.h
@@ -65,7 +65,7 @@ public:
int _variableStippleArray[64];
virtual void init() override;
- virtual void clear(uint8 color) override;
+ virtual void clear(uint8 r, uint8 g, uint8 b) override;
virtual void setViewport(const Common::Rect &rect) override;
virtual void positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest) override;
virtual void updateProjectionMatrix(float fov, float nearClipPlane, float farClipPlane) override;
diff --git a/engines/freescape/gfx_tinygl.cpp b/engines/freescape/gfx_tinygl.cpp
index ad1c0f62195..92c19f70ebc 100644
--- a/engines/freescape/gfx_tinygl.cpp
+++ b/engines/freescape/gfx_tinygl.cpp
@@ -213,14 +213,7 @@ void TinyGLRenderer::useColor(uint8 r, uint8 g, uint8 b) {
tglColor3ub(r, g, b);
}
-void TinyGLRenderer::clear(uint8 color) {
- uint8 r, g, b;
-
- if (_colorRemaps && _colorRemaps->contains(color)) {
- color = (*_colorRemaps)[color];
- }
-
- readFromPalette(color, r, g, b);
+void TinyGLRenderer::clear(uint8 r, uint8 g, uint8 b) {
tglClearColor(r / 255., g / 255., b / 255., 1.0);
tglClear(TGL_COLOR_BUFFER_BIT | TGL_DEPTH_BUFFER_BIT);
}
diff --git a/engines/freescape/gfx_tinygl.h b/engines/freescape/gfx_tinygl.h
index e5a6f3d480e..ad65a171581 100644
--- a/engines/freescape/gfx_tinygl.h
+++ b/engines/freescape/gfx_tinygl.h
@@ -47,7 +47,7 @@ public:
Vertex *_verts;
virtual void init() override;
- virtual void clear(uint8 color) override;
+ virtual void clear(uint8 r, uint8 g, uint8 b) override;
virtual void setViewport(const Common::Rect &rect) override;
virtual void positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest) override;
virtual void updateProjectionMatrix(float fov, float nearClipPlane, float farClipPlane) override;
Commit: c57029b8e8c6df0c18780ec0b5cdef332d1c06cc
https://github.com/scummvm/scummvm/commit/c57029b8e8c6df0c18780ec0b5cdef332d1c06cc
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: improved image reading for castle in DOS/EGA
Changed paths:
engines/freescape/freescape.cpp
engines/freescape/freescape.h
engines/freescape/games/castle.cpp
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index da72e733d90..a5af1711f29 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -165,7 +165,6 @@ FreescapeEngine::~FreescapeEngine() {
delete _border;
}
-
if (_gfx->_isAccelerated) {
delete _borderTexture;
delete _uiTexture;
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 0d81cb0a5d0..eb1f87275d1 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -560,7 +560,10 @@ public:
class CastleEngine : public FreescapeEngine {
public:
CastleEngine(OSystem *syst, const ADGameDescription *gd);
+ ~CastleEngine();
+
+ Graphics::ManagedSurface *_option;
void titleScreen() override;
void loadAssetsDOSFullGame() override;
void drawUI() override;
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 1aa53d527f9..35bbc14f12d 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -36,6 +36,33 @@ CastleEngine::CastleEngine(OSystem *syst, const ADGameDescription *gd) : Freesca
_playerDepth = 8;
}
+CastleEngine::~CastleEngine() {
+ if (_option) {
+ _option->free();
+ delete _option;
+ }
+}
+
+byte kCastleTitleDOSPalette[16][3] = {
+ {0x00, 0x00, 0x00}, // correct!
+ {0x00, 0x00, 0xaa}, // correct!
+ {0x00, 0x00, 0x00}, // ????
+ {0x00, 0xaa, 0xaa}, // changed
+ {0x55, 0x55, 0x55}, // changed
+ {0x55, 0x55, 0xff}, // changed
+ {0xaa, 0xaa, 0xaa}, // changed
+ {0x55, 0xff, 0xff}, // changed
+ {0xff, 0x55, 0xff}, // changed
+ {0x00, 0x00, 0x00},
+ {0xff, 0xff, 0xff}, // changed
+ {0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00}
+};
+
+
Common::SeekableReadStream *CastleEngine::decryptFile(const Common::String filename) {
Common::File file;
file.open(filename);
@@ -65,16 +92,19 @@ void CastleEngine::loadAssetsDOSFullGame() {
if (_renderMode == Common::kRenderEGA) {
_viewArea = Common::Rect(39, 31, 278, 150);
- file.open("CMOE.DAT");
+ file.open("CMLE.DAT");
_title = load8bitBinImage(&file, 0x0);
- _title->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
+ _title->setPalette((byte *)&kCastleTitleDOSPalette, 0, 16);
+ file.close();
+ file.open("CMOE.DAT");
+ _option = load8bitBinImage(&file, 0x0);
+ _option->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
file.close();
file.open("CME.DAT");
_border = load8bitBinImage(&file, 0x0);
_border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
-
file.close();
stream = decryptFile("CMLE");
Commit: 73391bffd77f54ad70ff1f6691e6eb41d38abc5e
https://github.com/scummvm/scummvm/commit/73391bffd77f54ad70ff1f6691e6eb41d38abc5e
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: improved border palette for castle in DOS/EGA
Changed paths:
engines/freescape/freescape.cpp
engines/freescape/games/castle.cpp
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index a5af1711f29..007ba3d185f 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -643,7 +643,7 @@ void FreescapeEngine::processBorder() {
for (int i = 0; i < border->w; i++) {
for (int j = 0; j < border->h; j++) {
- if (border->getPixel(i, j) == black)
+ if (!isCastle() && border->getPixel(i, j) == black)
border->setPixel(i, j, transparent);
}
}
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 35bbc14f12d..c9b07f07587 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -62,6 +62,42 @@ byte kCastleTitleDOSPalette[16][3] = {
{0x00, 0x00, 0x00}
};
+byte kCastleOptionDOSPalette[16][3] = {
+ {0x00, 0x00, 0x00},
+ {0x00, 0x00, 0xaa},
+ {0x00, 0xaa, 0x00},
+ {0xaa, 0x00, 0x00},
+ {0x55, 0x55, 0x55},
+ {0xaa, 0x55, 0x00},
+ {0xaa, 0xaa, 0xaa},
+ {0xff, 0x55, 0x55},
+ {0x12, 0x34, 0x56},
+ {0xff, 0xff, 0x55},
+ {0xff, 0xff, 0xff},
+ {0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00}
+};
+
+byte kCastleBorderDOSPalette[16][3] = {
+ {0x00, 0x00, 0x00},
+ {0x00, 0x00, 0xaa},
+ {0x00, 0xaa, 0x00},
+ {0xaa, 0x00, 0x00},
+ {0x55, 0x55, 0x55},
+ {0xaa, 0x55, 0x00},
+ {0xaa, 0xaa, 0xaa}, // can be also green
+ {0xff, 0x55, 0x55},
+ {0x00, 0x00, 0x00},
+ {0xff, 0xff, 0x55},
+ {0xff, 0xff, 0xff},
+ {0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00}
+};
Common::SeekableReadStream *CastleEngine::decryptFile(const Common::String filename) {
Common::File file;
@@ -90,7 +126,7 @@ void CastleEngine::loadAssetsDOSFullGame() {
Common::SeekableReadStream *stream = nullptr;
if (_renderMode == Common::kRenderEGA) {
- _viewArea = Common::Rect(39, 31, 278, 150);
+ _viewArea = Common::Rect(40, 33, 280, 152);
file.open("CMLE.DAT");
_title = load8bitBinImage(&file, 0x0);
@@ -99,12 +135,12 @@ void CastleEngine::loadAssetsDOSFullGame() {
file.open("CMOE.DAT");
_option = load8bitBinImage(&file, 0x0);
- _option->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
+ _option->setPalette((byte *)&kCastleOptionDOSPalette, 0, 16);
file.close();
file.open("CME.DAT");
_border = load8bitBinImage(&file, 0x0);
- _border->setPalette((byte *)&kEGADefaultPaletteData, 0, 16);
+ _border->setPalette((byte *)&kCastleBorderDOSPalette, 0, 16);
file.close();
stream = decryptFile("CMLE");
Commit: c8afca45ec9c8e986843a9b465651a415fe4179e
https://github.com/scummvm/scummvm/commit/c8afca45ec9c8e986843a9b465651a415fe4179e
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: make sure the floor is available in area 2 of castle
Changed paths:
engines/freescape/area.cpp
engines/freescape/area.h
engines/freescape/games/castle.cpp
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index c1aa7f9a0ee..3039bc5c5e1 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -330,25 +330,29 @@ void Area::addObjectFromArea(int16 id, Area *global) {
}
}
+void Area::addFloor() {
+ int id = 0;
+ assert(!_objectsByID->contains(id));
+ Common::Array<uint8> *gColors = new Common::Array<uint8>;
+ for (int i = 0; i < 6; i++)
+ gColors->push_back(_groundColor);
+
+ Object *obj = (Object *)new GeometricObject(
+ ObjectType::kCubeType,
+ id,
+ 0, // flags
+ Math::Vector3d(0, -1, 0), // Position
+ Math::Vector3d(4128, 1, 4128), // size
+ gColors,
+ nullptr,
+ FCLInstructionVector());
+ (*_objectsByID)[id] = obj;
+ _drawableObjects.insert_at(0, obj);
+}
+
void Area::addStructure(Area *global) {
- Object *obj = nullptr;
if (!global || !_entrancesByID->contains(255)) {
- int id = 254;
- Common::Array<uint8> *gColors = new Common::Array<uint8>;
- for (int i = 0; i < 6; i++)
- gColors->push_back(_groundColor);
-
- obj = (Object *)new GeometricObject(
- ObjectType::kCubeType,
- id,
- 0, // flags
- Math::Vector3d(0, -1, 0), // Position
- Math::Vector3d(4128, 1, 4128), // size
- gColors,
- nullptr,
- FCLInstructionVector());
- (*_objectsByID)[id] = obj;
- _drawableObjects.insert_at(0, obj);
+ addFloor();
return;
}
GlobalStructure *rs = (GlobalStructure *)(*_entrancesByID)[255];
diff --git a/engines/freescape/area.h b/engines/freescape/area.h
index 49cffb6632a..950854432f9 100644
--- a/engines/freescape/area.h
+++ b/engines/freescape/area.h
@@ -57,6 +57,7 @@ public:
ObjectArray checkCollisions(const Math::AABB &boundingBox);
void addObjectFromArea(int16 id, Area *global);
void addObject(Object *obj);
+ void addFloor();
void addStructure(Area *global);
void removeObject(int16 id);
void resetArea();
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index c9b07f07587..a9fcdb495f8 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -151,6 +151,8 @@ void CastleEngine::loadAssetsDOSFullGame() {
load8bitBinary(stream, 0, 16);
for (auto &it : _areaMap)
it._value->addStructure(_areaMap[255]);
+
+ _areaMap[2]->addFloor();
delete stream;
} else
error("Not implemented yet");
Commit: bccfe4eb0b374d157c6011ac25666ac587c66546
https://github.com/scummvm/scummvm/commit/bccfe4eb0b374d157c6011ac25666ac587c66546
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: better rendering of EGA colors in castle
Changed paths:
engines/freescape/area.h
engines/freescape/games/castle.cpp
engines/freescape/gfx.cpp
engines/freescape/gfx.h
engines/freescape/loaders/8bitBinaryLoader.cpp
diff --git a/engines/freescape/area.h b/engines/freescape/area.h
index 950854432f9..294b73a5c88 100644
--- a/engines/freescape/area.h
+++ b/engines/freescape/area.h
@@ -80,6 +80,7 @@ public:
uint8 _underFireBackgroundColor;
uint8 _inkColor;
uint8 _paperColor;
+ uint8 _extraColor[4];
ColorReMap _colorRemaps;
private:
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index a9fcdb495f8..505c6bfd86a 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -194,6 +194,28 @@ void CastleEngine::gotoArea(uint16 areaID, int entranceID) {
_gfx->_keyColor = 0;
} else
_gfx->_keyColor = 255;
+
+ _lastPosition = _position;
+ _gameStateVars[0x1f] = 0;
+
+ if (areaID == _startArea && entranceID == _startEntrance) {
+ _yaw = 310;
+ _pitch = 0;
+ }
+
+ debugC(1, kFreescapeDebugMove, "starting player position: %f, %f, %f", _position.x(), _position.y(), _position.z());
+ clearTemporalMessages();
+ playSound(5, false);
+ // Ignore sky/ground fields
+ _gfx->_keyColor = 0;
+
+ _gfx->_colorPair[_currentArea->_underFireBackgroundColor] = _currentArea->_extraColor[0];
+ _gfx->_colorPair[_currentArea->_usualBackgroundColor] = _currentArea->_extraColor[1];
+ _gfx->_colorPair[_currentArea->_paperColor] = _currentArea->_extraColor[2];
+ _gfx->_colorPair[_currentArea->_inkColor] = _currentArea->_extraColor[3];
+
+ swapPalette(areaID);
+ resetInput();
}
void CastleEngine::drawUI() {
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index ac69bafa823..b84ae117b55 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -361,8 +361,7 @@ bool Renderer::getRGBAtCPC(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
return true;
}
-bool Renderer::getRGBAtEGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2) {
- // assert(index-1 < _colorMap->size());
+uint8 Renderer::mapEGAColor(uint8 index) {
byte *entry = (*_colorMap)[index - 1];
uint8 color = 0;
uint8 acc = 1;
@@ -376,10 +375,23 @@ bool Renderer::getRGBAtEGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &
entry++;
}
assert(color < 16);
- readFromPalette(color, r1, g1, b1);
- r2 = r1;
- g2 = g1;
- b2 = b1;
+ return color;
+}
+
+bool Renderer::getRGBAtEGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2) {
+ uint8 color;
+ if (_colorPair[index] > 0) {
+ color = mapEGAColor(_colorPair[index] & 0xf);
+ readFromPalette(color, r1, g1, b1);
+ color = mapEGAColor(_colorPair[index] >> 4);
+ readFromPalette(color, r2, g2, b2);
+ } else {
+ color = mapEGAColor(index);
+ readFromPalette(color, r1, g1, b1);
+ r2 = r1;
+ g2 = g1;
+ b2 = b1;
+ }
return true;
}
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 0d3acc47099..047cb82589f 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -100,6 +100,8 @@ public:
// palette
void readFromPalette(uint8 index, uint8 &r, uint8 &g, uint8 &b);
uint8 indexFromColor(uint8 r, uint8 g, uint8 b);
+ uint8 mapEGAColor(uint8 index);
+
bool getRGBAt(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple);
bool getRGBAtC64(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2);
bool getRGBAtCGA(uint8 index, uint8 &r1, uint8 &g1, uint8 &b1, uint8 &r2, uint8 &g2, uint8 &b2, byte *&stipple);
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 47bce668a63..e5265274b59 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -438,10 +438,12 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
// debug("Condition Ptr: %x", cPtr);
debugC(1, kFreescapeDebugParser, "Pos before first object: %lx", file->pos());
+ // Driller specific
uint8 gasPocketX = 0;
uint8 gasPocketY = 0;
uint8 gasPocketRadius = 0;
-
+ // Castle specific
+ uint8 extraColor[4];
if (isEclipse()) {
byte idx = file->readByte();
name = idx < 8 ? eclipseRoomName[idx] : eclipseRoomName[8];
@@ -471,10 +473,10 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
} else if (isCastle()) {
byte idx = file->readByte();
name = _messagesList[idx + 41];
- debug("byte: %d", file->readByte());
- debug("byte: %d", file->readByte());
- debug("byte: %d", file->readByte());
- debug("byte: %d", file->readByte());
+ extraColor[0] = file->readByte();
+ extraColor[1] = file->readByte();
+ extraColor[2] = file->readByte();
+ extraColor[3] = file->readByte();
}
debugC(1, kFreescapeDebugParser, "Area name: %s", name.c_str());
@@ -511,11 +513,17 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
area->_scale = scale;
area->_skyColor = skyColor;
area->_groundColor = groundColor;
+
area->_inkColor = inkColor;
area->_paperColor = paperColor;
area->_usualBackgroundColor = usualBackgroundColor;
area->_underFireBackgroundColor = underFireBackgroundColor;
+ area->_extraColor[0] = extraColor[0];
+ area->_extraColor[1] = extraColor[1];
+ area->_extraColor[2] = extraColor[2];
+ area->_extraColor[3] = extraColor[3];
+
// Driller specific
area->_gasPocketPosition = Common::Point(32 * gasPocketX, 32 * gasPocketY);
area->_gasPocketRadius = 32 * gasPocketRadius;
Commit: 99f9bb7eba960ef85e7df4c876d55cf886ac0531
https://github.com/scummvm/scummvm/commit/99f9bb7eba960ef85e7df4c876d55cf886ac0531
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: allow to reset color pairs, useful in castle EGA
Changed paths:
engines/freescape/games/castle.cpp
engines/freescape/gfx.cpp
engines/freescape/gfx.h
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 505c6bfd86a..7943c1a7578 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -208,6 +208,7 @@ void CastleEngine::gotoArea(uint16 areaID, int entranceID) {
playSound(5, false);
// Ignore sky/ground fields
_gfx->_keyColor = 0;
+ _gfx->clearColorPairArray();
_gfx->_colorPair[_currentArea->_underFireBackgroundColor] = _currentArea->_extraColor[0];
_gfx->_colorPair[_currentArea->_usualBackgroundColor] = _currentArea->_extraColor[1];
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index b84ae117b55..88d7304ba09 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -126,6 +126,11 @@ byte getCGAStipple(byte x, int back, int fore) {
return st;
}
+void Renderer::clearColorPairArray() {
+ for (int i = 0; i < 15; i++)
+ _colorPair[i] = 0;
+}
+
void Renderer::fillColorPairArray() {
for (int i = 4; i < 15; i++) {
byte *entry = (*_colorMap)[i];
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 047cb82589f..7e38d4d7812 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -119,6 +119,7 @@ public:
void setColorMap(ColorMap *colorMap_);
ColorMap *_colorMap;
ColorReMap *_colorRemaps;
+ void clearColorPairArray();
void fillColorPairArray();
byte _colorPair[16];
int _keyColor;
Commit: a42d72ad6ec12b4eb27110f84e2ef571d3605be4
https://github.com/scummvm/scummvm/commit/a42d72ad6ec12b4eb27110f84e2ef571d3605be4
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: improved rendering of rectangles and fixes
Changed paths:
engines/freescape/gfx.cpp
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 88d7304ba09..f4dde905eda 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -836,15 +836,6 @@ void Renderer::renderRectangle(const Math::Vector3d &origin, const Math::Vector3
vertices.push_back(Math::Vector3d(origin.x() + dx, origin.y() + dy, origin.z() + dz));
vertices.push_back(Math::Vector3d(origin.x() + size.x(), origin.y() + size.y(), origin.z() + size.z()));
- renderFace(vertices);
- if (r1 != r2 || g1 != g2 || b1 != b2) {
- useStipple(true);
- useColor(r2, g2, b2);
- renderFace(vertices);
- useStipple(false);
- }
-
- vertices.clear();
vertices.push_back(Math::Vector3d(origin.x(), origin.y(), origin.z()));
dx = dy = dz = 0.0;
@@ -954,7 +945,7 @@ void Renderer::drawBackground(uint8 color) {
if (!render)
r1 = g1 = b1 = 0;
- assert(stipple == nullptr); // Unclear if this is ever used
+ //assert(stipple == nullptr); // Unclear if this is ever used
clear(r1, g1, b1);
}
Commit: ef88a9886fd2b02ec6048ae06f1b04983a9cb063
https://github.com/scummvm/scummvm/commit/ef88a9886fd2b02ec6048ae06f1b04983a9cb063
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: disallow zero length conditions
Changed paths:
engines/freescape/loaders/8bitBinaryLoader.cpp
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index e5265274b59..35f44a3225b 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -534,11 +534,13 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
uint32 lengthOfCondition = readField(file, 8);
debugC(1, kFreescapeDebugParser, "length of condition: %d", lengthOfCondition);
// get the condition
- Common::Array<uint8> conditionArray = readArray(file, lengthOfCondition);
- Common::String conditionSource = detokenise8bitCondition(conditionArray, instructions);
- area->_conditions.push_back(instructions);
- area->_conditionSources.push_back(conditionSource);
- debugC(1, kFreescapeDebugParser, "%s", conditionSource.c_str());
+ if (lengthOfCondition > 0) {
+ Common::Array<uint8> conditionArray = readArray(file, lengthOfCondition);
+ Common::String conditionSource = detokenise8bitCondition(conditionArray, instructions);
+ area->_conditions.push_back(instructions);
+ area->_conditionSources.push_back(conditionSource);
+ debugC(1, kFreescapeDebugParser, "%s", conditionSource.c_str());
+ }
}
debugC(1, kFreescapeDebugParser, "End of area at %lx", file->pos());
@@ -625,12 +627,13 @@ void FreescapeEngine::load8bitBinary(Common::SeekableReadStream *file, int offse
uint32 lengthOfCondition = readField(file, 8);
debugC(1, kFreescapeDebugParser, "length of condition: %d at %lx", lengthOfCondition, file->pos());
// get the condition
- Common::Array<uint8> conditionArray = readArray(file, lengthOfCondition);
- // debug("Global condition %d", numConditions + 1);
- Common::String conditionSource = detokenise8bitCondition(conditionArray, instructions);
- _conditions.push_back(instructions);
- _conditionSources.push_back(conditionSource);
- debugC(1, kFreescapeDebugParser, "%s", conditionSource.c_str());
+ if (lengthOfCondition > 0) {
+ Common::Array<uint8> conditionArray = readArray(file, lengthOfCondition);
+ Common::String conditionSource = detokenise8bitCondition(conditionArray, instructions);
+ _conditions.push_back(instructions);
+ _conditionSources.push_back(conditionSource);
+ debugC(1, kFreescapeDebugParser, "%s", conditionSource.c_str());
+ }
}
if (isDriller()) {
Commit: 6963aad58476553cccebe0cf6cc5491415d88230
https://github.com/scummvm/scummvm/commit/6963aad58476553cccebe0cf6cc5491415d88230
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: allow to parse conditions using the ACTIVATED trigger for castle
Changed paths:
engines/freescape/games/driller/driller.cpp
engines/freescape/language/8bitDetokeniser.cpp
engines/freescape/language/8bitDetokeniser.h
engines/freescape/language/instruction.cpp
engines/freescape/loaders/8bitBinaryLoader.cpp
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 5144aa8ba11..902354fcce9 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -206,7 +206,7 @@ void DrillerEngine::loadAssetsFullGame() {
conditionArray.push_back(0x7f);
conditionArray.push_back(0x0);
- Common::String conditionSource = detokenise8bitCondition(conditionArray, instructions);
+ Common::String conditionSource = detokenise8bitCondition(conditionArray, instructions, false);
debugC(1, kFreescapeDebugParser, "%s", conditionSource.c_str());
_areaMap[18]->_conditions.push_back(instructions);
_areaMap[18]->_conditionSources.push_back(conditionSource);
diff --git a/engines/freescape/language/8bitDetokeniser.cpp b/engines/freescape/language/8bitDetokeniser.cpp
index 3b76b2fa9e6..2e97886037b 100644
--- a/engines/freescape/language/8bitDetokeniser.cpp
+++ b/engines/freescape/language/8bitDetokeniser.cpp
@@ -33,7 +33,7 @@ uint8 k8bitMaxVariable = 64;
uint8 k8bitMaxShield = 64;
uint8 k8bitMaxEnergy = 64;
-Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition, FCLInstructionVector &instructions) {
+Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition, FCLInstructionVector &instructions, bool enableActivated) {
Common::String detokenisedStream;
Common::Array<uint8>::size_type bytePointer = 0;
Common::Array<uint8>::size_type sizeOfTokenisedContent = tokenisedCondition.size();
@@ -63,7 +63,9 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
// get the conditional type of the next operation
uint8 conditionalByte = tokenisedCondition[bytePointer];
- if (conditionalByte & 0x80)
+ if ((conditionalByte & 0xc0) && enableActivated) {
+ newConditional = Token::ACTIVATEDQ;
+ } else if (conditionalByte & 0x80)
newConditional = Token::SHOTQ;
else if (conditionalByte & 0x40)
newConditional = Token::TIMERQ;
@@ -92,6 +94,8 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
detokenisedStream += "IF TIMER? THEN\n";
else if (oldConditional == Token::COLLIDEDQ)
detokenisedStream += "IF COLLIDED? THEN\n";
+ else if (oldConditional == Token::ACTIVATEDQ)
+ detokenisedStream += "IF ACTIVATED? THEN\n";
else
error("Invalid conditional: %x", oldConditional);
}
diff --git a/engines/freescape/language/8bitDetokeniser.h b/engines/freescape/language/8bitDetokeniser.h
index b0c1047bb40..08326c2d5c9 100644
--- a/engines/freescape/language/8bitDetokeniser.h
+++ b/engines/freescape/language/8bitDetokeniser.h
@@ -40,7 +40,7 @@ extern uint8 k8bitMaxVariable;
extern uint8 k8bitMaxShield;
extern uint8 k8bitMaxEnergy;
-Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition, FCLInstructionVector &instructions);
+Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition, FCLInstructionVector &instructions, bool enableActivated);
} // End of namespace Freescape
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index 5fc29ed61df..84f021f32a2 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -133,13 +133,20 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
debugC(1, kFreescapeDebugCode, "Executing ip: %d with type %d in code with size: %d", ip, instruction.getType(), codeSize);
switch (instruction.getType()) {
default:
- if (!isCastle())
- error("Instruction %x at ip: %d not implemented!", instruction.getType(), ip);
+ //if (!isCastle())
+ error("Instruction %x at ip: %d not implemented!", instruction.getType(), ip);
break;
case Token::NOP:
debugC(1, kFreescapeDebugCode, "Executing NOP at ip: %d", ip);
break;
+ case Token::ACTIVATEDQ:
+ if (collided) // TODO: implement interaction
+ executeCode(*instruction._thenInstructions, shot, collided, timer);
+ // else branch is always empty
+ assert(instruction._elseInstructions == nullptr);
+ break;
+
case Token::COLLIDEDQ:
if (collided)
executeCode(*instruction._thenInstructions, shot, collided, timer);
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 35f44a3225b..61265e7c4f2 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -187,7 +187,7 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
Common::String conditionSource;
if (byteSizeOfObject) {
Common::Array<uint8> conditionArray = readArray(file, byteSizeOfObject);
- conditionSource = detokenise8bitCondition(conditionArray, instructions);
+ conditionSource = detokenise8bitCondition(conditionArray, instructions, isCastle());
// instructions = getInstructions(conditionSource);
debugC(1, kFreescapeDebugParser, "%s", conditionSource.c_str());
}
@@ -257,7 +257,7 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
// grab the object condition, if there is one
if (byteSizeOfObject) {
Common::Array<uint8> conditionArray = readArray(file, byteSizeOfObject);
- conditionSource = detokenise8bitCondition(conditionArray, instructions);
+ conditionSource = detokenise8bitCondition(conditionArray, instructions, isCastle());
debugC(1, kFreescapeDebugParser, "%s", conditionSource.c_str());
}
debugC(1, kFreescapeDebugParser, "End of object at %lx", file->pos());
@@ -536,7 +536,7 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
// get the condition
if (lengthOfCondition > 0) {
Common::Array<uint8> conditionArray = readArray(file, lengthOfCondition);
- Common::String conditionSource = detokenise8bitCondition(conditionArray, instructions);
+ Common::String conditionSource = detokenise8bitCondition(conditionArray, instructions, isCastle());
area->_conditions.push_back(instructions);
area->_conditionSources.push_back(conditionSource);
debugC(1, kFreescapeDebugParser, "%s", conditionSource.c_str());
@@ -629,7 +629,7 @@ void FreescapeEngine::load8bitBinary(Common::SeekableReadStream *file, int offse
// get the condition
if (lengthOfCondition > 0) {
Common::Array<uint8> conditionArray = readArray(file, lengthOfCondition);
- Common::String conditionSource = detokenise8bitCondition(conditionArray, instructions);
+ Common::String conditionSource = detokenise8bitCondition(conditionArray, instructions, isCastle());
_conditions.push_back(instructions);
_conditionSources.push_back(conditionSource);
debugC(1, kFreescapeDebugParser, "%s", conditionSource.c_str());
Commit: d342614658b11c7f2b3128b2c4b17b45b7bf5deb
https://github.com/scummvm/scummvm/commit/d342614658b11c7f2b3128b2c4b17b45b7bf5deb
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: basic support for control flow opcodes of castle
Changed paths:
engines/freescape/freescape.h
engines/freescape/language/8bitDetokeniser.cpp
engines/freescape/language/instruction.cpp
engines/freescape/language/token.h
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index eb1f87275d1..385745bb4db 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -281,6 +281,7 @@ public:
void executeCode(FCLInstructionVector &code, bool shot, bool collided, bool timer);
// Instructions
+ bool checkIfGreaterOrEqual(FCLInstruction &instruction);
void executeIncrementVariable(FCLInstruction &instruction);
void executeDecrementVariable(FCLInstruction &instruction);
void executeSetVariable(FCLInstruction &instruction);
diff --git a/engines/freescape/language/8bitDetokeniser.cpp b/engines/freescape/language/8bitDetokeniser.cpp
index 2e97886037b..37b76ab9854 100644
--- a/engines/freescape/language/8bitDetokeniser.cpp
+++ b/engines/freescape/language/8bitDetokeniser.cpp
@@ -374,28 +374,32 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
case 44:
detokenisedStream += "ELSE ";
+ currentInstruction = FCLInstruction(Token::ELSE);
+ conditionalInstructions->push_back(currentInstruction);
+ currentInstruction = FCLInstruction(Token::UNKNOWN);
+ numberOfArguments = 0;
break;
case 45:
detokenisedStream += "ENDIF ";
+ currentInstruction = FCLInstruction(Token::ENDIF);
+ conditionalInstructions->push_back(currentInstruction);
+ currentInstruction = FCLInstruction(Token::UNKNOWN);
+ numberOfArguments = 0;
break;
case 46:
- detokenisedStream += "IFGTE ";
- detokenisedStream += Common::String::format("(v%d, %d)", (int)tokenisedCondition[bytePointer], (int)tokenisedCondition[bytePointer + 1]);
- bytePointer += 2;
- numberOfArguments = 0;
+ detokenisedStream += "IFGTE (v";
+ currentInstruction = FCLInstruction(Token::IFGTEQ);
break;
case 47:
- detokenisedStream += "IFLTE ";
- detokenisedStream += Common::String::format("(v%d, %d)", (int)tokenisedCondition[bytePointer], (int)tokenisedCondition[bytePointer + 1]);
- bytePointer += 2;
- numberOfArguments = 0;
+ detokenisedStream += "IFLTE (v";
+ currentInstruction = FCLInstruction(Token::IFGTEQ);
break;
case 48:
- detokenisedStream += "EXECUTE ";
+ detokenisedStream += "EXECUTE (";
currentInstruction = FCLInstruction(Token::EXECUTE);
break;
}
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index 84f021f32a2..b27b8bbffc9 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -126,11 +126,19 @@ void FreescapeEngine::executeLocalGlobalConditions(bool shot, bool collided, boo
void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool collided, bool timer) {
assert(!(shot && collided));
int ip = 0;
+ bool skip = false;
int codeSize = code.size();
assert(codeSize > 0);
while (ip <= codeSize - 1) {
FCLInstruction &instruction = code[ip];
debugC(1, kFreescapeDebugCode, "Executing ip: %d with type %d in code with size: %d", ip, instruction.getType(), codeSize);
+
+ if (skip && instruction.getType() != Token::ELSE && instruction.getType() != Token::ENDIF) {
+ debugC(1, kFreescapeDebugCode, "Instruction skipped!");
+ ip++;
+ continue;
+ }
+
switch (instruction.getType()) {
default:
//if (!isCastle())
@@ -141,7 +149,7 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
break;
case Token::ACTIVATEDQ:
- if (collided) // TODO: implement interaction
+ if (shot) // TODO: implement interaction
executeCode(*instruction._thenInstructions, shot, collided, timer);
// else branch is always empty
assert(instruction._elseInstructions == nullptr);
@@ -169,6 +177,18 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
if (executeEndIfNotEqual(instruction))
ip = codeSize;
break;
+ case Token::IFGTEQ:
+ skip = !checkIfGreaterOrEqual(instruction);
+ break;
+
+ case Token::ELSE:
+ skip = !skip;
+ break;
+
+ case Token::ENDIF:
+ skip = false;
+ break;
+
case Token::SWAPJET:
executeSwapJet(instruction);
break;
@@ -264,7 +284,7 @@ void FreescapeEngine::executeDelay(FCLInstruction &instruction) {
void FreescapeEngine::executePrint(FCLInstruction &instruction) {
uint16 index = instruction._source - 1;
- debugC(1, kFreescapeDebugCode, "Printing message %d", index);
+ debugC(1, kFreescapeDebugCode, "Printing message %d: \"%s\"", index, _messagesList[index].c_str());
_currentAreaMessages.clear();
_currentAreaMessages.push_back(_messagesList[index]);
}
@@ -335,6 +355,14 @@ bool FreescapeEngine::executeEndIfVisibilityIsEqual(FCLInstruction &instruction)
return (obj->isInvisible() == (value != 0));
}
+bool FreescapeEngine::checkIfGreaterOrEqual(FCLInstruction &instruction) {
+ uint16 variable = instruction._source;
+ uint16 value = instruction._destination;
+ debugC(1, kFreescapeDebugCode, "Check if variable %d is greater than equal to %d!", variable, value);
+ return (_gameStateVars[variable] >= value);
+}
+
+
bool FreescapeEngine::executeEndIfNotEqual(FCLInstruction &instruction) {
uint16 variable = instruction._source;
uint16 value = instruction._destination;
diff --git a/engines/freescape/language/token.h b/engines/freescape/language/token.h
index 77ec65b2dde..d108d93d780 100644
--- a/engines/freescape/language/token.h
+++ b/engines/freescape/language/token.h
@@ -80,8 +80,8 @@ public:
TRIGANIM,
UPDATEI,
VAREQ,
- VARGQ,
- VARLQ,
+ IFGTEQ,
+ IFGLEQ,
VISQ,
VIS,
WAIT,
Commit: 3a6fbca79c1b65e85ae55a7e495c2517cf505d5c
https://github.com/scummvm/scummvm/commit/3a6fbca79c1b65e85ae55a7e495c2517cf505d5c
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: refactored conditional handling to make it work with castle
Changed paths:
engines/freescape/freescape.h
engines/freescape/language/8bitDetokeniser.cpp
engines/freescape/language/8bitDetokeniser.h
engines/freescape/language/instruction.cpp
engines/freescape/language/token.h
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 385745bb4db..2bf19ab76ef 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -281,6 +281,7 @@ public:
void executeCode(FCLInstructionVector &code, bool shot, bool collided, bool timer);
// Instructions
+ bool checkConditional(FCLInstruction &instruction, bool shot, bool collided, bool timer, bool activated);
bool checkIfGreaterOrEqual(FCLInstruction &instruction);
void executeIncrementVariable(FCLInstruction &instruction);
void executeDecrementVariable(FCLInstruction &instruction);
diff --git a/engines/freescape/language/8bitDetokeniser.cpp b/engines/freescape/language/8bitDetokeniser.cpp
index 37b76ab9854..775140d972a 100644
--- a/engines/freescape/language/8bitDetokeniser.cpp
+++ b/engines/freescape/language/8bitDetokeniser.cpp
@@ -33,7 +33,7 @@ uint8 k8bitMaxVariable = 64;
uint8 k8bitMaxShield = 64;
uint8 k8bitMaxEnergy = 64;
-Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition, FCLInstructionVector &instructions, bool enableActivated) {
+Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition, FCLInstructionVector &instructions, bool multipleConditionals) {
Common::String detokenisedStream;
Common::Array<uint8>::size_type bytePointer = 0;
Common::Array<uint8>::size_type sizeOfTokenisedContent = tokenisedCondition.size();
@@ -56,28 +56,30 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
if (sizeOfTokenisedContent > 0)
detokenisedStream += Common::String::format("CONDITION FLAG: %x\n", tokenisedCondition[0]);
- Token::Type newConditional = Token::UNKNOWN;
- Token::Type oldConditional = Token::UNKNOWN;
+ uint16 newConditional = 0;
+ uint16 oldConditional = 0;
while (bytePointer < sizeOfTokenisedContent) {
// get the conditional type of the next operation
- uint8 conditionalByte = tokenisedCondition[bytePointer];
-
- if ((conditionalByte & 0xc0) && enableActivated) {
- newConditional = Token::ACTIVATEDQ;
- } else if (conditionalByte & 0x80)
- newConditional = Token::SHOTQ;
- else if (conditionalByte & 0x40)
- newConditional = Token::TIMERQ;
+ uint8 conditionalByte = tokenisedCondition[bytePointer] & 0xc0;
+ //detokenisedStream += Common::String::format("CONDITION FLAG: %x\n", conditionalByte);
+ newConditional = 0;
+
+ if (conditionalByte == 0x40)
+ newConditional = kConditionalTimeout;
+ else if (conditionalByte == 0x80)
+ newConditional = kConditionalShot;
+ else if (conditionalByte == 0xc0)
+ newConditional = kConditionalActivated;
else
- newConditional = Token::COLLIDEDQ;
+ newConditional = kConditionalCollided;
// if the conditional type has changed then end the old conditional,
// if we were in one, and begin a new one
if (bytePointer == 0 || newConditional != oldConditional) {
oldConditional = newConditional;
FCLInstruction branch;
- branch = FCLInstruction(oldConditional);
+ branch = FCLInstruction(Token::CONDITIONAL);
if (bytePointer > 0) {
detokenisedStream += "ENDIF\n";
@@ -86,18 +88,23 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
}
branch.setBranches(conditionalInstructions, nullptr);
+ branch.setSource(oldConditional); // conditional flag
instructions.push_back(branch);
- if (oldConditional == Token::SHOTQ)
- detokenisedStream += "IF SHOT? THEN\n";
- else if (oldConditional == Token::TIMERQ)
- detokenisedStream += "IF TIMER? THEN\n";
- else if (oldConditional == Token::COLLIDEDQ)
- detokenisedStream += "IF COLLIDED? THEN\n";
- else if (oldConditional == Token::ACTIVATEDQ)
- detokenisedStream += "IF ACTIVATED? THEN\n";
+ detokenisedStream += "IF ";
+
+ if (oldConditional & kConditionalShot)
+ detokenisedStream += "SHOT? ";
+ else if (oldConditional & kConditionalTimeout)
+ detokenisedStream += "TIMER? ";
+ else if (oldConditional & kConditionalCollided)
+ detokenisedStream += "COLLIDED? ";
+ else if (oldConditional & kConditionalActivated)
+ detokenisedStream += "ACTIVATED? ";
else
error("Invalid conditional: %x", oldConditional);
+
+ detokenisedStream += "THEN\n";
}
// get the actual operation
diff --git a/engines/freescape/language/8bitDetokeniser.h b/engines/freescape/language/8bitDetokeniser.h
index 08326c2d5c9..8ba7c11a3f0 100644
--- a/engines/freescape/language/8bitDetokeniser.h
+++ b/engines/freescape/language/8bitDetokeniser.h
@@ -36,6 +36,13 @@ enum {
k8bitVariableEnergyDrillerJet = 57
};
+enum {
+ kConditionalShot = 1 << 0,
+ kConditionalTimeout = 1 << 1,
+ kConditionalCollided = 1 << 2,
+ kConditionalActivated = 1 << 3,
+};
+
extern uint8 k8bitMaxVariable;
extern uint8 k8bitMaxShield;
extern uint8 k8bitMaxEnergy;
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index b27b8bbffc9..da9ed9ba5d4 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -148,31 +148,13 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
debugC(1, kFreescapeDebugCode, "Executing NOP at ip: %d", ip);
break;
- case Token::ACTIVATEDQ:
- if (shot) // TODO: implement interaction
+ case Token::CONDITIONAL:
+ if (checkConditional(instruction, shot, collided, timer, false)) // TODO: implement interaction
executeCode(*instruction._thenInstructions, shot, collided, timer);
// else branch is always empty
assert(instruction._elseInstructions == nullptr);
break;
- case Token::COLLIDEDQ:
- if (collided)
- executeCode(*instruction._thenInstructions, shot, collided, timer);
- // else branch is always empty
- assert(instruction._elseInstructions == nullptr);
- break;
- case Token::SHOTQ:
- if (shot)
- executeCode(*instruction._thenInstructions, shot, collided, timer);
- // else branch is always empty
- assert(instruction._elseInstructions == nullptr);
- break;
- case Token::TIMERQ:
- if (timer)
- executeCode(*instruction._thenInstructions, shot, collided, timer);
- // else branch is always empty
- assert(instruction._elseInstructions == nullptr);
- break;
case Token::VARNOTEQ:
if (executeEndIfNotEqual(instruction))
ip = codeSize;
@@ -355,6 +337,23 @@ bool FreescapeEngine::executeEndIfVisibilityIsEqual(FCLInstruction &instruction)
return (obj->isInvisible() == (value != 0));
}
+bool FreescapeEngine::checkConditional(FCLInstruction &instruction, bool shot, bool collided, bool timer, bool activated) {
+ uint16 conditional = instruction._source;
+ bool result = false;
+
+ if (conditional & kConditionalShot)
+ result |= shot;
+ if (conditional & kConditionalTimeout)
+ result |= timer;
+ if (conditional & kConditionalCollided)
+ result |= collided;
+ if (conditional & kConditionalActivated)
+ result |= activated;
+
+ debugC(1, kFreescapeDebugCode, "Check if conditional %x is true: %d!", conditional, result);
+ return result;
+}
+
bool FreescapeEngine::checkIfGreaterOrEqual(FCLInstruction &instruction) {
uint16 variable = instruction._source;
uint16 value = instruction._destination;
diff --git a/engines/freescape/language/token.h b/engines/freescape/language/token.h
index d108d93d780..a99d777b8bd 100644
--- a/engines/freescape/language/token.h
+++ b/engines/freescape/language/token.h
@@ -30,12 +30,11 @@ namespace Freescape {
struct Token {
public:
enum Type {
- ACTIVATEDQ,
ADDVAR,
AGAIN,
AND,
ANDV,
- COLLIDEDQ,
+ CONDITIONAL,
DELAY,
DESTROY,
DESTROYEDQ,
@@ -67,7 +66,6 @@ public:
SCREEN,
SOUND,
SETVAR,
- SHOTQ,
START,
STARTANIM,
STOPANIM,
@@ -75,7 +73,6 @@ public:
SUBVAR,
SYNCSND,
THEN,
- TIMERQ,
TOGVIS,
TRIGANIM,
UPDATEI,
Commit: 55d4acc6e796a19c3cc6c2c00823601bc76ffa30
https://github.com/scummvm/scummvm/commit/55d4acc6e796a19c3cc6c2c00823601bc76ffa30
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: added support for using different languages in castle (DOS)
Changed paths:
engines/freescape/detection.cpp
engines/freescape/freescape.cpp
engines/freescape/freescape.h
engines/freescape/games/castle.cpp
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index 032e9bf425d..097a5e98d48 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -346,7 +346,7 @@ static const ADGameDescription gameDescriptions[] = {
{"CMH.EXE", 0, "1f3b67e649e718e239ebfd7c56e96d47", 63040},
AD_LISTEND
},
- Common::EN_ANY,
+ Common::UNK_LANG,
Common::kPlatformDOS,
ADGF_UNSTABLE,
GUIO1(GUIO_NOMIDI)
@@ -619,6 +619,19 @@ public:
const DebugChannelDef *getDebugChannels() const override {
return debugFlagList;
}
+ DetectedGame toDetectedGame(const ADDetectedGame &adGame, ADDetectedGameExtraInfo *extraInfo) const override;
};
+DetectedGame FreescapeMetaEngineDetection::toDetectedGame(const ADDetectedGame &adGame, ADDetectedGameExtraInfo *extraInfo) const {
+ DetectedGame game = AdvancedMetaEngineDetection::toDetectedGame(adGame);
+
+ // The AdvancedDetector model only allows specifying a single supported game language.
+ if (game.gameId == "castlemaster" && game.language == Common::UNK_LANG) {
+ game.appendGUIOptions(Common::getGameGUIOptionsDescriptionLanguage(Common::EN_ANY));
+ game.appendGUIOptions(Common::getGameGUIOptionsDescriptionLanguage(Common::FR_FRA));
+ game.appendGUIOptions(Common::getGameGUIOptionsDescriptionLanguage(Common::DE_DEU));
+ }
+ return game;
+}
+
REGISTER_PLUGIN_STATIC(FREESCAPE_DETECTION, PLUGIN_TYPE_ENGINE_DETECTION, FreescapeMetaEngineDetection);
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 007ba3d185f..351b96692db 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -60,6 +60,8 @@ FreescapeEngine::FreescapeEngine(OSystem *syst, const ADGameDescription *gd)
_variant = gd->flags;
+ _language = Common::parseLanguage(ConfMan.get("language"));
+
if (!Common::parseBool(ConfMan.get("prerecorded_sounds"), _usePrerecordedSounds))
error("Failed to parse bool from prerecorded_sounds option");
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 2bf19ab76ef..66d56c02e82 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -95,6 +95,7 @@ public:
// Game selection
uint32 _variant;
+ Common::Language _language;
bool isDriller() { return _targetName.hasPrefix("driller") || _targetName.hasPrefix("spacestationoblivion"); }
bool isDark() { return _targetName.hasPrefix("darkside"); }
bool isEclipse() { return _targetName.hasPrefix("totaleclipse"); }
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 7943c1a7578..c5747264ea2 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -143,7 +143,23 @@ void CastleEngine::loadAssetsDOSFullGame() {
_border->setPalette((byte *)&kCastleBorderDOSPalette, 0, 16);
file.close();
- stream = decryptFile("CMLE");
+ switch (_language) {
+ case Common::ES_ESP:
+ stream = decryptFile("CMLS");
+ break;
+ case Common::FR_FRA:
+ stream = decryptFile("CMLF");
+ break;
+ case Common::DE_DEU:
+ stream = decryptFile("CMLG");
+ break;
+ case Common::EN_ANY:
+ stream = decryptFile("CMLE");
+ break;
+ default:
+ error("Invalid or unsupported language: %x", _language);
+ }
+
loadMessagesVariableSize(stream, 0x11, 164);
delete stream;
Commit: 746f694b6362ec31fd32d0042325eaad49a78b1b
https://github.com/scummvm/scummvm/commit/746f694b6362ec31fd32d0042325eaad49a78b1b
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: added support for parsing (hardcoded) font for castle (DOS)
Changed paths:
engines/freescape/freescape.cpp
engines/freescape/freescape.h
engines/freescape/games/castle.cpp
engines/freescape/loaders/8bitBinaryLoader.cpp
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 351b96692db..b0253e24604 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -722,15 +722,20 @@ void FreescapeEngine::drawStringInSurface(const Common::String &str, int x, int
Common::String ustr = str;
ustr.toUppercase();
+ int sizeX = 8;
+ int sizeY = isCastle() ? 8 : 6;
+ int sep = isCastle() ? 9 : 8;
+ int additional = isCastle() ? 0 : 1;
+
if (isDOS() || isSpectrum() || isCPC() || isC64()) {
for (uint32 c = 0; c < ustr.size(); c++) {
assert(ustr[c] >= 32);
- for (int j = 0; j < 6; j++) {
- for (int i = 0; i < 8; i++) {
- if (_font.get(48 * (offset + ustr[c] - 32) + 1 + j * 8 + i))
- surface->setPixel(x + 8 - i + 8 * c, y + j, fontColor);
+ for (int j = 0; j < sizeY; j++) {
+ for (int i = 0; i < sizeX; i++) {
+ if (_font.get(sizeX * sizeY * (offset + ustr[c] - 32) + additional + j * 8 + i))
+ surface->setPixel(x + 8 - i + sep * c, y + j, fontColor);
else
- surface->setPixel(x + 8 - i + 8 * c, y + j, backColor);
+ surface->setPixel(x + 8 - i + sep * c, y + j, backColor);
}
}
}
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 66d56c02e82..256c1d5338c 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -358,6 +358,7 @@ public:
void loadMessagesVariableSize(Common::SeekableReadStream *file, int offset, int number);
void loadFonts(Common::SeekableReadStream *file, int offset);
+ void loadFonts(byte *font, int charNumber);
Common::StringArray _currentAreaMessages;
Common::StringArray _currentEphymeralMessages;
Common::BitArray _font;
@@ -565,12 +566,13 @@ public:
CastleEngine(OSystem *syst, const ADGameDescription *gd);
~CastleEngine();
-
Graphics::ManagedSurface *_option;
+ void initGameState() override;
void titleScreen() override;
void loadAssetsDOSFullGame() override;
void drawUI() override;
+ void executePrint(FCLInstruction &instruction) override;
void gotoArea(uint16 areaID, int entranceID) override;
Common::Error saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave = false) override;
Common::Error loadGameStreamExtended(Common::SeekableReadStream *stream) override;
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index c5747264ea2..254db2de65b 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -23,6 +23,7 @@
#include "common/memstream.h"
#include "freescape/freescape.h"
+#include "freescape/language/8bitDetokeniser.h"
namespace Freescape {
@@ -99,6 +100,68 @@ byte kCastleBorderDOSPalette[16][3] = {
{0x00, 0x00, 0x00}
};
+byte kFreescapeCastleFont[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1c, 0x1c, 0x1c, 0x18, 0x18, 0x00, 0x18, 0x18,
+ 0x66, 0x66, 0x44, 0x22, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00,
+ 0x10, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x10, 0x00,
+ 0x3c, 0x42, 0x9d, 0xb1, 0xb1, 0x9d, 0x42, 0x3c,
+ 0x78, 0xcc, 0xcc, 0x78, 0xdb, 0xcf, 0xce, 0x7b,
+ 0x30, 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x20, 0x40, 0x40, 0x40, 0x40, 0x20, 0x10,
+ 0x10, 0x08, 0x04, 0x04, 0x04, 0x04, 0x08, 0x10,
+ 0x10, 0x54, 0x38, 0xfe, 0x38, 0x54, 0x10, 0x00,
+ 0x00, 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+ 0x18, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x18,
+ 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+ 0x9e, 0x61, 0x01, 0x7e, 0xe0, 0xc6, 0xe3, 0xfe,
+ 0xee, 0x73, 0x03, 0x3e, 0x03, 0x01, 0x7f, 0xe6,
+ 0x0e, 0x1c, 0x38, 0x71, 0xfd, 0xe6, 0x0c, 0x0c,
+ 0xfd, 0x86, 0x80, 0x7e, 0x07, 0x63, 0xc7, 0x7c,
+ 0x3d, 0x66, 0xc0, 0xf0, 0xfc, 0xc6, 0x66, 0x3c,
+ 0xb3, 0x4e, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x3c,
+ 0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc2, 0xfe, 0x4c,
+ 0x3c, 0x4e, 0xc6, 0xc6, 0x4e, 0x36, 0x46, 0x3c,
+ 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00,
+ 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x08, 0x10,
+ 0x03, 0x0c, 0x30, 0xc0, 0x30, 0x0c, 0x03, 0x00,
+ 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
+ 0xc0, 0x30, 0x0c, 0x03, 0x0c, 0x30, 0xc0, 0x00,
+ 0x7c, 0xc6, 0x06, 0x0c, 0x30, 0x30, 0x00, 0x30,
+ 0x00, 0x08, 0x0c, 0xfe, 0xff, 0xfe, 0x0c, 0x08,
+ 0x1e, 0x1c, 0x1e, 0x66, 0xbe, 0x26, 0x43, 0xe3,
+ 0xee, 0x73, 0x23, 0x3e, 0x23, 0x21, 0x7f, 0xe6,
+ 0x39, 0x6e, 0xc6, 0xc0, 0xc0, 0xc2, 0x63, 0x3e,
+ 0xec, 0x72, 0x23, 0x23, 0x23, 0x23, 0x72, 0xec,
+ 0xce, 0x7f, 0x61, 0x6c, 0x78, 0x61, 0x7f, 0xce,
+ 0xce, 0x7f, 0x61, 0x6c, 0x78, 0x60, 0x60, 0xf0,
+ 0x3d, 0x66, 0xc0, 0xc1, 0xce, 0xc6, 0x66, 0x3c,
+ 0xe7, 0x66, 0x66, 0x6e, 0x76, 0x66, 0x66, 0xe7,
+ 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x66,
+ 0x33, 0x1e, 0x0c, 0x8c, 0x4c, 0xcc, 0xdc, 0x78,
+ 0xf2, 0x67, 0x64, 0x68, 0x7e, 0x66, 0x66, 0xf3,
+ 0xd8, 0x70, 0x60, 0x60, 0x66, 0x61, 0xf3, 0x7e,
+ 0xc3, 0x66, 0x6e, 0x76, 0x56, 0x46, 0x46, 0xef,
+ 0x87, 0x62, 0x72, 0x7a, 0x5e, 0x4e, 0x46, 0xe1,
+ 0x18, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x18,
+ 0xec, 0x72, 0x63, 0x63, 0x72, 0x6c, 0x60, 0xf0,
+ 0x3c, 0x66, 0xc3, 0xc3, 0x66, 0x3c, 0x31, 0x1e,
+ 0xec, 0x72, 0x63, 0x63, 0x76, 0x6c, 0x66, 0xf1,
+ 0x79, 0x86, 0x80, 0x7e, 0x07, 0x63, 0xc7, 0x7c,
+ 0x01, 0x7f, 0xfe, 0x98, 0x58, 0x18, 0x18, 0x3c,
+ 0xf7, 0x62, 0x62, 0x62, 0x62, 0x62, 0xf2, 0x3c,
+ 0xf3, 0x61, 0x72, 0x72, 0x32, 0x32, 0x1c, 0x3e,
+ 0xc3, 0x62, 0x62, 0x6a, 0x6e, 0x76, 0x66, 0xc3,
+ 0xf3, 0x72, 0x3c, 0x38, 0x1c, 0x3c, 0x4e, 0xcf,
+ 0xe3, 0x72, 0x34, 0x38, 0x18, 0x18, 0x18, 0x3c,
+ 0x7f, 0x87, 0x0e, 0x1c, 0x38, 0x71, 0xfd, 0xe6,
+};
+
Common::SeekableReadStream *CastleEngine::decryptFile(const Common::String filename) {
Common::File file;
file.open(filename);
@@ -160,6 +223,7 @@ void CastleEngine::loadAssetsDOSFullGame() {
error("Invalid or unsupported language: %x", _language);
}
+ loadFonts(kFreescapeCastleFont, 59);
loadMessagesVariableSize(stream, 0x11, 164);
delete stream;
@@ -238,12 +302,36 @@ void CastleEngine::gotoArea(uint16 areaID, int entranceID) {
void CastleEngine::drawUI() {
_gfx->setViewport(_fullscreenViewArea);
+ uint32 color = 10;
+ uint8 r, g, b;
+
+ _gfx->readFromPalette(color, r, g, b);
+ uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
+ color = 0;
+
+ _gfx->readFromPalette(color, r, g, b);
+ uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
+
Graphics::Surface *surface = new Graphics::Surface();
surface->create(_screenW, _screenH, _gfx->_texturePixelFormat);
uint32 gray = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0xA0, 0xA0, 0xA0);
surface->fillRect(_fullscreenViewArea, gray);
drawCrossair(surface);
+ Common::Rect backRect(97, 181, 232, 190);
+ surface->fillRect(backRect, back);
+
+ Common::String message;
+ int deadline;
+ getLatestMessages(message, deadline);
+ if (deadline <= _countdown) {
+ drawStringInSurface(message, 97, 182, front, back, surface);
+ _temporaryMessages.push_back(message);
+ _temporaryMessageDeadlines.push_back(deadline);
+ } else
+ drawStringInSurface(_currentArea->_name, 97, 182, front, back, surface);
+
if (!_uiTexture)
_uiTexture = _gfx->createTexture(surface);
else
@@ -257,6 +345,48 @@ void CastleEngine::drawUI() {
_gfx->setViewport(_viewArea);
}
+void CastleEngine::initGameState() {
+ _flyMode = false;
+ _noClipMode = false;
+ _shootingFrames = 0;
+ _underFireFrames = 0;
+ _yaw = 0;
+ _pitch = 0;
+
+ for (int i = 0; i < k8bitMaxVariable; i++) // TODO: check maximum variable
+ _gameStateVars[i] = 0;
+
+ for (auto &it : _areaMap) {
+ it._value->resetArea();
+ _gameStateBits[it._key] = 0;
+ }
+
+ //_gameStateVars[k8bitVariableEnergy] = _initialFuel;
+ //_gameStateVars[k8bitVariableShield] = _initialShield;
+
+ _playerHeightNumber = 1;
+ _playerHeight = _playerHeights[_playerHeightNumber];
+ removeTimers();
+ startCountdown(_initialCountdown);
+ _lastMinute = 0;
+ _demoIndex = 0;
+ _demoEvents.clear();
+}
+
+void CastleEngine::executePrint(FCLInstruction &instruction) {
+ uint16 index = instruction._source;
+ _currentAreaMessages.clear();
+ if (index > 127) {
+ index = _messagesList.size() - (index - 254) - 2;
+ // TODO
+ //drawFullscreenMessage(_messagesList[index]);
+ return;
+ }
+ debugC(1, kFreescapeDebugCode, "Printing message %d: \"%s\"", index, _messagesList[index].c_str());
+ insertTemporaryMessage(_messagesList[index], _countdown - 3);
+}
+
+
Common::Error CastleEngine::saveGameStreamExtended(Common::WriteStream *stream, bool isAutosave) {
return Common::kNoError;
}
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 61265e7c4f2..bf54bcab306 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -664,7 +664,8 @@ void FreescapeEngine::load8bitBinary(Common::SeekableReadStream *file, int offse
_initialCountdown = 359999; // 99:59:59
} else if (isDark())
_initialCountdown = 2 * 3600; // 02:00:00
-
+ else if (isCastle())
+ _initialCountdown = 1000000000;
if (isAmiga() || isAtariST())
file->seek(offset + 0x190);
@@ -734,6 +735,17 @@ void FreescapeEngine::loadBundledImages() {
}*/
}
+void FreescapeEngine::loadFonts(byte *font, int charNumber) {
+ if (isDOS() || isSpectrum() || isCPC() || isC64()) {
+ _font.set_size(64 * charNumber);
+ _font.set_bits(font);
+ } else if (isAmiga() || isAtariST()) {
+ error("Not implemented yet");
+ }
+ _fontLoaded = true;
+}
+
+
void FreescapeEngine::loadFonts(Common::SeekableReadStream *file, int offset) {
file->seek(offset);
int charNumber = 60;
Commit: 764eb59b8e37be61c0c1e5f71ca7662763ee0385
https://github.com/scummvm/scummvm/commit/764eb59b8e37be61c0c1e5f71ca7662763ee0385
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: refactored castle (DOS) to use drawDOSUI
Changed paths:
engines/freescape/freescape.h
engines/freescape/games/castle.cpp
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 256c1d5338c..ff8d87ad6bf 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -570,7 +570,8 @@ public:
void initGameState() override;
void titleScreen() override;
void loadAssetsDOSFullGame() override;
- void drawUI() override;
+
+ void drawDOSUI(Graphics::Surface *surface) override;
void executePrint(FCLInstruction &instruction) override;
void gotoArea(uint16 areaID, int entranceID) override;
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 254db2de65b..173cb3c9c2a 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -299,9 +299,7 @@ void CastleEngine::gotoArea(uint16 areaID, int entranceID) {
resetInput();
}
-void CastleEngine::drawUI() {
- _gfx->setViewport(_fullscreenViewArea);
-
+void CastleEngine::drawDOSUI(Graphics::Surface *surface) {
uint32 color = 10;
uint8 r, g, b;
@@ -313,12 +311,6 @@ void CastleEngine::drawUI() {
_gfx->readFromPalette(color, r, g, b);
uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
- Graphics::Surface *surface = new Graphics::Surface();
- surface->create(_screenW, _screenH, _gfx->_texturePixelFormat);
- uint32 gray = _gfx->_texturePixelFormat.ARGBToColor(0x00, 0xA0, 0xA0, 0xA0);
- surface->fillRect(_fullscreenViewArea, gray);
- drawCrossair(surface);
-
Common::Rect backRect(97, 181, 232, 190);
surface->fillRect(backRect, back);
@@ -331,18 +323,6 @@ void CastleEngine::drawUI() {
_temporaryMessageDeadlines.push_back(deadline);
} else
drawStringInSurface(_currentArea->_name, 97, 182, front, back, surface);
-
- if (!_uiTexture)
- _uiTexture = _gfx->createTexture(surface);
- else
- _uiTexture->update(surface);
-
- _gfx->drawTexturedRect2D(_fullscreenViewArea, _fullscreenViewArea, _uiTexture);
-
- surface->free();
- delete surface;
-
- _gfx->setViewport(_viewArea);
}
void CastleEngine::initGameState() {
Commit: 9e2f4b760e4bb0da993814268009ac6ee0647010
https://github.com/scummvm/scummvm/commit/9e2f4b760e4bb0da993814268009ac6ee0647010
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: initial support for castle demo (EGA)
Changed paths:
engines/freescape/detection.cpp
engines/freescape/freescape.h
engines/freescape/games/castle.cpp
engines/freescape/language/8bitDetokeniser.cpp
engines/freescape/loaders/8bitBinaryLoader.cpp
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index 097a5e98d48..1ebd60ab679 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -335,6 +335,20 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSUPPORTED,
GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
},
+ {
+ "castlemaster",
+ "Demo",
+ {
+ {"CASTLE.EXE", 0, "cbcf475b2d993c831a34a5203d2643e1", 2022},
+ {"CMDC.EXE", 0, "278fd1a96c61db71d952af472164ac57", 56526},
+ {"CMDE.EXE", 0, "428555ba83bc64d69bc2f7cb385f04f2", 88590},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_UNSTABLE | ADGF_DEMO,
+ GUIO1(GUIO_NOMIDI)
+ },
{
"castlemaster",
"",
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index ff8d87ad6bf..7f5a2711797 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -570,6 +570,7 @@ public:
void initGameState() override;
void titleScreen() override;
void loadAssetsDOSFullGame() override;
+ void loadAssetsDOSDemo() override;
void drawDOSUI(Graphics::Surface *surface) override;
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 173cb3c9c2a..1e2dc7fef20 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -243,6 +243,46 @@ void CastleEngine::loadAssetsDOSFullGame() {
// load8bitBinary(file, 0x791a, 16);
}
+void CastleEngine::loadAssetsDOSDemo() {
+ Common::File file;
+ Common::SeekableReadStream *stream = nullptr;
+
+ if (_renderMode == Common::kRenderEGA) {
+ _viewArea = Common::Rect(40, 33, 280, 152);
+
+ file.open("CMLE.DAT");
+ _title = load8bitBinImage(&file, 0x0);
+ _title->setPalette((byte *)&kCastleTitleDOSPalette, 0, 16);
+ file.close();
+
+ file.open("CMOE.DAT");
+ _option = load8bitBinImage(&file, 0x0);
+ _option->setPalette((byte *)&kCastleOptionDOSPalette, 0, 16);
+ file.close();
+
+ file.open("CME.DAT");
+ _border = load8bitBinImage(&file, 0x0);
+ _border->setPalette((byte *)&kCastleBorderDOSPalette, 0, 16);
+ file.close();
+
+ stream = decryptFile("CMLD"); // Only english
+
+ loadFonts(kFreescapeCastleFont, 59);
+ loadMessagesVariableSize(stream, 0x11, 164);
+ delete stream;
+
+ stream = decryptFile("CDEDF");
+ load8bitBinary(stream, 0, 16);
+ for (auto &it : _areaMap)
+ it._value->addStructure(_areaMap[255]);
+
+ _areaMap[2]->addFloor();
+ delete stream;
+ } else
+ error("Not implemented yet");
+}
+
+
void CastleEngine::titleScreen() {
if (isAmiga() || isAtariST()) // These releases has their own screens
return;
diff --git a/engines/freescape/language/8bitDetokeniser.cpp b/engines/freescape/language/8bitDetokeniser.cpp
index 775140d972a..e74d4182fef 100644
--- a/engines/freescape/language/8bitDetokeniser.cpp
+++ b/engines/freescape/language/8bitDetokeniser.cpp
@@ -115,7 +115,7 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
// check we have enough bytes left to read
if (opcode > 48) {
debugC(1, kFreescapeDebugParser, "%s", detokenisedStream.c_str());
- if (opcode != 0x3f)
+ if (opcode != 0x3f && opcode != 0x3b)
error("ERROR: failed to read opcode: %x", opcode);
break;
}
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index bf54bcab306..21cb38ed360 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -553,7 +553,7 @@ void FreescapeEngine::load8bitBinary(Common::SeekableReadStream *file, int offse
debugC(1, kFreescapeDebugParser, "Number of areas: %d", numberOfAreas);
if (isDOS() && isCastle()) // Castle Master for DOS has an invalid number of areas
- numberOfAreas = 104;
+ numberOfAreas = isDemo() ? 31 : 104;
uint32 dbSize = readField(file, 16);
debugC(1, kFreescapeDebugParser, "Database ends at %x", dbSize);
Commit: 9dbe3433aa5b3b59367f445173256cc61169e8de
https://github.com/scummvm/scummvm/commit/9dbe3433aa5b3b59367f445173256cc61169e8de
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: expanded floor size
Changed paths:
engines/freescape/area.cpp
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 3039bc5c5e1..ac168712e88 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -341,8 +341,8 @@ void Area::addFloor() {
ObjectType::kCubeType,
id,
0, // flags
- Math::Vector3d(0, -1, 0), // Position
- Math::Vector3d(4128, 1, 4128), // size
+ Math::Vector3d(-4128, -1, -4128), // Position
+ Math::Vector3d(4128 * 4, 1, 4128 * 4), // size
gColors,
nullptr,
FCLInstructionVector());
Commit: 700c62949c959562188bd2907eae92413e98f2bd
https://github.com/scummvm/scummvm/commit/700c62949c959562188bd2907eae92413e98f2bd
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: initial detection of castle demo for amiga
Changed paths:
engines/freescape/detection.cpp
engines/freescape/freescape.h
engines/freescape/games/castle.cpp
engines/freescape/loaders/8bitBinaryLoader.cpp
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index 1ebd60ab679..01b3f1d2412 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -349,6 +349,33 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSTABLE | ADGF_DEMO,
GUIO1(GUIO_NOMIDI)
},
+ {
+ "castlemaster",
+ "Demo",
+ {
+ {"cm", 0, "936b6ca92be53f122bd904a3397137e2", 1552},
+ {"x", 0, "c8c811439da0cf8a193e35feb5b5c6dc", 353388},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformAmiga,
+ ADGF_UNSTABLE | ADGF_DEMO,
+ GUIO1(GUIO_NOMIDI)
+ },
+ // Stampede Amiga, Issue 1, July 1990
+ {
+ "castlemaster",
+ "Demo",
+ {
+ {"cm", 0, "b7e713a0742fa09aa81c9606bbbba4af", 4068},
+ {"x", 0, "c8c811439da0cf8a193e35feb5b5c6dc", 353388},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformAmiga,
+ ADGF_UNSTABLE | ADGF_DEMO,
+ GUIO1(GUIO_NOMIDI)
+ },
{
"castlemaster",
"",
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 7f5a2711797..383586298c2 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -571,6 +571,7 @@ public:
void titleScreen() override;
void loadAssetsDOSFullGame() override;
void loadAssetsDOSDemo() override;
+ void loadAssetsAmigaDemo() override;
void drawDOSUI(Graphics::Surface *surface) override;
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 1e2dc7fef20..4165ee42b2c 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -282,6 +282,34 @@ void CastleEngine::loadAssetsDOSDemo() {
error("Not implemented yet");
}
+void CastleEngine::loadAssetsAmigaDemo() {
+ Common::File file;
+ file.open("x");
+ if (!file.isOpen())
+ error("Failed to open 'x' file");
+
+ loadMessagesVariableSize(&file, 0x8bb2, 164);
+ load8bitBinary(&file, 0x162a6, 16);
+ assert(0);
+ //loadPalettes(&file, 0x0);
+
+ //file.close();
+ //file.open("driller");
+ //if (!file.isOpen())
+ // error("Failed to open 'driller' file");
+
+ //loadFonts(&file, 0xa30);
+ //loadMessagesFixedSize(&file, 0x3960, 14, 20);
+ //loadGlobalObjects(&file, 0x3716, 8);
+
+ file.close();
+ //file.open("soundfx");
+ //if (!file.isOpen())
+ // error("Failed to open 'soundfx' executable for Amiga");
+
+ //loadSoundsFx(&file, 0, 25);
+}
+
void CastleEngine::titleScreen() {
if (isAmiga() || isAtariST()) // These releases has their own screens
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 21cb38ed360..3c35b3d3497 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -471,12 +471,12 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
i++;
}
} else if (isCastle()) {
- byte idx = file->readByte();
+ byte idx = readField(file, 8);
name = _messagesList[idx + 41];
- extraColor[0] = file->readByte();
- extraColor[1] = file->readByte();
- extraColor[2] = file->readByte();
- extraColor[3] = file->readByte();
+ extraColor[0] = readField(file, 8);
+ extraColor[1] = readField(file, 8);
+ extraColor[2] = readField(file, 8);
+ extraColor[3] = readField(file, 8);
}
debugC(1, kFreescapeDebugParser, "Area name: %s", name.c_str());
Commit: 626f6721d16f5a5c6b4a6fd1b50ca4c1b055da9d
https://github.com/scummvm/scummvm/commit/626f6721d16f5a5c6b4a6fd1b50ca4c1b055da9d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: basic implementation of activation (only used in castle/crypt)
Changed paths:
engines/freescape/freescape.cpp
engines/freescape/freescape.h
engines/freescape/language/instruction.cpp
engines/freescape/movement.cpp
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index b0253e24604..841e33f3c00 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -515,6 +515,12 @@ void FreescapeEngine::processInput() {
}
break;
+ case Common::EVENT_RBUTTONDOWN:
+ if (_hasFallen || !isCastle())
+ break;
+ activate();
+ break;
+
default:
break;
}
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 383586298c2..97b00b2d94e 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -241,6 +241,7 @@ public:
float _lastFrame;
// Interaction
+ void activate();
void shoot();
void traverseEntrance(uint16 entranceID);
@@ -277,9 +278,9 @@ public:
bool checkCollisions(bool executeCode);
Math::Vector3d _objExecutingCodeSize;
virtual void executeMovementConditions();
- void executeObjectConditions(GeometricObject *obj, bool shot, bool collided);
+ void executeObjectConditions(GeometricObject *obj, bool shot, bool collided, bool activated);
void executeLocalGlobalConditions(bool shot, bool collided, bool timer);
- void executeCode(FCLInstructionVector &code, bool shot, bool collided, bool timer);
+ void executeCode(FCLInstructionVector &code, bool shot, bool collided, bool timer, bool activated);
// Instructions
bool checkConditional(FCLInstruction &instruction, bool shot, bool collided, bool timer, bool activated);
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index da9ed9ba5d4..beb817e9841 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -89,7 +89,7 @@ Token::Type FCLInstruction::getType() {
return _type;
}
-void FreescapeEngine::executeObjectConditions(GeometricObject *obj, bool shot, bool collided) {
+void FreescapeEngine::executeObjectConditions(GeometricObject *obj, bool shot, bool collided, bool activated) {
assert(obj != nullptr);
if (!obj->_conditionSource.empty()) {
_firstSound = true;
@@ -98,9 +98,11 @@ void FreescapeEngine::executeObjectConditions(GeometricObject *obj, bool shot, b
debugC(1, kFreescapeDebugCode, "Executing with collision flag: %s", obj->_conditionSource.c_str());
else if (shot)
debugC(1, kFreescapeDebugCode, "Executing with shot flag: %s", obj->_conditionSource.c_str());
+ else if (activated)
+ debugC(1, kFreescapeDebugCode, "Executing with activated flag: %s", obj->_conditionSource.c_str());
else
error("Neither shot or collided flag is set!");
- executeCode(obj->_condition, shot, collided, false); // TODO: check this last parameter
+ executeCode(obj->_condition, shot, collided, false, activated); // TODO: check this last parameter
}
}
@@ -113,17 +115,17 @@ void FreescapeEngine::executeLocalGlobalConditions(bool shot, bool collided, boo
for (uint i = 0; i < conditions.size(); i++) {
debugC(1, kFreescapeDebugCode, "%s", conditionSources[i].c_str());
- executeCode(conditions[i], shot, collided, timer);
+ executeCode(conditions[i], shot, collided, timer, false);
}
debugC(1, kFreescapeDebugCode, "Executing global conditions (%d)", _conditions.size());
for (uint i = 0; i < _conditions.size(); i++) {
debugC(1, kFreescapeDebugCode, "%s", _conditionSources[i].c_str());
- executeCode(_conditions[i], shot, collided, timer);
+ executeCode(_conditions[i], shot, collided, timer, false);
}
}
-void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool collided, bool timer) {
+void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool collided, bool timer, bool activated) {
assert(!(shot && collided));
int ip = 0;
bool skip = false;
@@ -149,8 +151,8 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
break;
case Token::CONDITIONAL:
- if (checkConditional(instruction, shot, collided, timer, false)) // TODO: implement interaction
- executeCode(*instruction._thenInstructions, shot, collided, timer);
+ if (checkConditional(instruction, shot, collided, timer, activated))
+ executeCode(*instruction._thenInstructions, shot, collided, timer, activated);
// else branch is always empty
assert(instruction._elseInstructions == nullptr);
break;
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index aa432f1e3ee..7d89bafe446 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -69,6 +69,29 @@ void FreescapeEngine::traverseEntrance(uint16 entranceID) {
_sensors = _currentArea->getSensors();
}
+void FreescapeEngine::activate() {
+ Common::Point center(_viewArea.left + _viewArea.width() / 2, _viewArea.top + _viewArea.height() / 2);
+ float xoffset = _crossairPosition.x - center.x;
+ float yoffset = _crossairPosition.y - center.y;
+ xoffset = xoffset * 0.33;
+ yoffset = yoffset * 0.50;
+
+ Math::Vector3d direction = directionToVector(_pitch - yoffset, _yaw - xoffset);
+ Math::Ray ray(_position, direction);
+ Object *interacted = _currentArea->shootRay(ray);
+ if (interacted) {
+ GeometricObject *gobj = (GeometricObject *)interacted;
+ debugC(1, kFreescapeDebugMove, "Interact with object %d with flags %x", gobj->getObjectID(), gobj->getObjectFlags());
+
+ if (!gobj->_conditionSource.empty())
+ debugC(1, kFreescapeDebugMove, "Must use interact = true when executing: %s", gobj->_conditionSource.c_str());
+
+ executeObjectConditions(gobj, false, false, true);
+ }
+ //executeLocalGlobalConditions(true, false, false); // Only execute "on shot" room/global conditions
+}
+
+
void FreescapeEngine::shoot() {
playSound(1, false);
g_system->delayMillis(2);
@@ -90,7 +113,7 @@ void FreescapeEngine::shoot() {
if (!gobj->_conditionSource.empty())
debugC(1, kFreescapeDebugMove, "Must use shot = true when executing: %s", gobj->_conditionSource.c_str());
- executeObjectConditions(gobj, true, false);
+ executeObjectConditions(gobj, true, false, false);
}
executeLocalGlobalConditions(true, false, false); // Only execute "on shot" room/global conditions
}
@@ -375,7 +398,7 @@ bool FreescapeEngine::checkCollisions(bool executeCode) {
largeObjectWasBlocking = true;
}
- executeObjectConditions(gobj, false, true);
+ executeObjectConditions(gobj, false, true, false);
if (areaID != _currentArea->getAreaID())
break;
Commit: acf7e1e9409084bdebdf4e5d1ca20fe4161f6c57
https://github.com/scummvm/scummvm/commit/acf7e1e9409084bdebdf4e5d1ca20fe4161f6c57
Author: Donovan Watteau (contrib at dwatteau.fr)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: Fix -Wformat warnings
Changed paths:
engines/freescape/loaders/8bitBinaryLoader.cpp
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 3c35b3d3497..e570d4dbb65 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -191,7 +191,7 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
// instructions = getInstructions(conditionSource);
debugC(1, kFreescapeDebugParser, "%s", conditionSource.c_str());
}
- debugC(1, kFreescapeDebugParser, "End of object at %lx", file->pos());
+ debugC(1, kFreescapeDebugParser, "End of object at %lx", long(file->pos()));
if (!GeometricObject::isPolygon(objectType))
position = 32 * position;
@@ -219,7 +219,7 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
byteSizeOfObject = 0;
}
assert(byteSizeOfObject == 0);
- debugC(1, kFreescapeDebugParser, "End of object at %lx", file->pos());
+ debugC(1, kFreescapeDebugParser, "End of object at %lx", long(file->pos()));
// create an entrance
return new Entrance(
objectID,
@@ -260,7 +260,7 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
conditionSource = detokenise8bitCondition(conditionArray, instructions, isCastle());
debugC(1, kFreescapeDebugParser, "%s", conditionSource.c_str());
}
- debugC(1, kFreescapeDebugParser, "End of object at %lx", file->pos());
+ debugC(1, kFreescapeDebugParser, "End of object at %lx", long(file->pos()));
// create an entrance
return new Sensor(
objectID,
@@ -436,7 +436,7 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
debugC(1, kFreescapeDebugParser, "Area %d", areaNumber);
debugC(1, kFreescapeDebugParser, "Flags: %d Objects: %d", areaFlags, numberOfObjects);
// debug("Condition Ptr: %x", cPtr);
- debugC(1, kFreescapeDebugParser, "Pos before first object: %lx", file->pos());
+ debugC(1, kFreescapeDebugParser, "Pos before first object: %lx", long(file->pos()));
// Driller specific
uint8 gasPocketX = 0;
@@ -543,7 +543,7 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
}
}
- debugC(1, kFreescapeDebugParser, "End of area at %lx", file->pos());
+ debugC(1, kFreescapeDebugParser, "End of area at %lx", long(file->pos()));
return area;
}
@@ -617,7 +617,7 @@ void FreescapeEngine::load8bitBinary(Common::SeekableReadStream *file, int offse
loadDemoData(file, offset + demoDataTable, 128); // TODO: check this size
file->seek(offset + globalByteCodeTable);
- debugC(1, kFreescapeDebugParser, "Position: %lx\n", file->pos());
+ debugC(1, kFreescapeDebugParser, "Position: %lx\n", long(file->pos()));
uint8 numConditions = readField(file, 8);
debugC(1, kFreescapeDebugParser, "%d global conditions", numConditions);
@@ -625,7 +625,7 @@ void FreescapeEngine::load8bitBinary(Common::SeekableReadStream *file, int offse
FCLInstructionVector instructions;
// get the length
uint32 lengthOfCondition = readField(file, 8);
- debugC(1, kFreescapeDebugParser, "length of condition: %d at %lx", lengthOfCondition, file->pos());
+ debugC(1, kFreescapeDebugParser, "length of condition: %d at %lx", lengthOfCondition, long(file->pos()));
// get the condition
if (lengthOfCondition > 0) {
Common::Array<uint8> conditionArray = readArray(file, lengthOfCondition);
@@ -673,7 +673,7 @@ void FreescapeEngine::load8bitBinary(Common::SeekableReadStream *file, int offse
file->seek(offset + 0xc8);
// file->seek(offset + 0x4f); //CPC
- debugC(1, kFreescapeDebugParser, "areas index at: %lx", file->pos());
+ debugC(1, kFreescapeDebugParser, "areas index at: %lx", long(file->pos()));
uint16 *fileOffsetForArea = new uint16[numberOfAreas];
for (uint16 area = 0; area < numberOfAreas; area++) {
fileOffsetForArea[area] = readField(file, 16);
Commit: f4555942b023422d40c4114951faafa852d798e2
https://github.com/scummvm/scummvm/commit/f4555942b023422d40c4114951faafa852d798e2
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: new collision code
Changed paths:
engines/freescape/area.cpp
engines/freescape/area.h
engines/freescape/freescape.h
engines/freescape/movement.cpp
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index ac168712e88..585256345ec 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -258,6 +258,121 @@ ObjectArray Area::checkCollisions(const Math::AABB &boundingBox) {
return collided;
}
+float lineToPlane(Math::Vector3d const &p, Math::Vector3d const &u, Math::Vector3d const &v, Math::Vector3d const &n) {
+ float NdotU = n.dotProduct(u);
+ if (NdotU == 0)
+ return INFINITY;
+
+ return n.dotProduct(v - p) / NdotU;
+}
+
+bool between(float x, float a, float b) {
+ return x >= a && x <= b;
+}
+
+float sweepAABB(Math::AABB const &a, Math::AABB const &b, Math::Vector3d const &direction, Math::Vector3d &normal) {
+ Math::Vector3d m = b.getMin() - a.getMax();
+ Math::Vector3d mh = a.getMax() - a.getMin() + b.getMax() - b.getMin();
+
+ float h = 1.0;
+ float s = 0.0;
+ Math::Vector3d zero;
+
+ // X min
+ s = lineToPlane(zero, direction, m, Math::Vector3d(-1, 0, 0));
+ if (s >= 0 && direction.x() > 0 && s < h && between(s * direction.y(), m.y(), m.y()+mh.y()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
+ h = s;
+ normal = Math::Vector3d(-1, 0, 0);
+ }
+
+ // X max
+ m.x() = m.x() + mh.x();
+ s = lineToPlane(zero, direction, m, Math::Vector3d(1, 0, 0));
+ if (s >= 0 && direction.x() < 0 && s < h && between(s * direction.y(), m.y(), m.y() + mh.y()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
+ h = s;
+ normal = Math::Vector3d(1, 0, 0);
+ }
+
+ m.x() = m.x() - mh.x();
+ // Y min
+ s = lineToPlane(zero, direction, m, Math::Vector3d(0, -1, 0));
+ if (s >= 0 && direction.y() > 0 && s < h && between(s * direction.x(), m.x(), m.x() + mh.x()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
+ h = s;
+ normal = Math::Vector3d(0, -1, 0);
+ }
+
+ // Y max
+ m.y() = m.y() + mh.y();
+ s = lineToPlane(zero, direction, m, Math::Vector3d(0, 1, 0));
+ if (s >= 0 && direction.y() < 0 && s < h && between(s * direction.x(), m.x(), m.x() + mh.x()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
+ h = s;
+ normal = Math::Vector3d(0, 1, 0);
+ }
+
+ m.y() = m.y() - mh.y();
+
+ // Z min
+ s = lineToPlane(zero, direction, m, Math::Vector3d(0, 0, -1));
+ if (s >= 0 && direction.z() > 0 && s < h && between(s * direction.x(), m.x() , m.x() + mh.x()) && between(s * direction.y(), m.y(), m.y() + mh.y())) {
+ h = s;
+ normal = Math::Vector3d(0, 0, -1);
+ }
+
+ // Z max
+ m.z() = m.z() + mh.z();
+ s = lineToPlane(zero, direction, m, Math::Vector3d(0, 0, 1));
+ if (s >= 0 && direction.z() < 0 && s < h && between(s * direction.x(), m.x(), m.x() + mh.x()) && between(s * direction.y(), m.y(), m.y() + mh.y())) {
+ h = s;
+ normal = Math::Vector3d(0, 0, 1);
+ }
+
+ //debug("%f", h);
+ return h;
+}
+
+Math::AABB createPlayerAABB(Math::Vector3d const position, int playerHeight) {
+ Math::AABB boundingBox(position, position);
+
+ Math::Vector3d v1(position.x() + 1, position.y() + 1, position.z() + 1);
+ Math::Vector3d v2(position.x() - 1, position.y() - playerHeight, position.z() - 1);
+
+ boundingBox.expand(v1);
+ boundingBox.expand(v2);
+ return boundingBox;
+}
+
+Math::Vector3d Area::resolveCollisions(const Math::Vector3d &lastPosition_, const Math::Vector3d &newPosition_, int playerHeight) {
+ Math::Vector3d position = newPosition_;
+ Math::Vector3d lastPosition = lastPosition_;
+
+ float epsilon = 1.5;
+ int i = 0;
+ while (true) {
+ float distance = 1.0;
+ Math::Vector3d normal;
+ Math::Vector3d direction = position - lastPosition;
+
+ Math::AABB boundingBox = createPlayerAABB(lastPosition, playerHeight);
+ for (auto &obj : _drawableObjects) {
+ if (!obj->isDestroyed() && !obj->isInvisible()) {
+ GeometricObject *gobj = (GeometricObject *)obj;
+ Math::Vector3d collidedNormal;
+ float collidedDistance = sweepAABB(boundingBox, gobj->_boundingBox, direction, collidedNormal);
+ if (collidedDistance < distance) {
+ distance = collidedDistance;
+ normal = collidedNormal;
+ }
+ }
+ }
+ position = lastPosition + distance * direction + epsilon * normal;
+ if (distance >= 1.0)
+ break;
+ i++;
+ assert(i <= 5);
+ }
+ return position;
+}
+
bool Area::checkInSight(const Math::Ray &ray, float maxDistance) {
Math::Vector3d direction = ray.getDirection();
direction.normalize();
diff --git a/engines/freescape/area.h b/engines/freescape/area.h
index 294b73a5c88..a6fa1e2fdc7 100644
--- a/engines/freescape/area.h
+++ b/engines/freescape/area.h
@@ -55,6 +55,7 @@ public:
Object *shootRay(const Math::Ray &ray);
bool checkInSight(const Math::Ray &ray, float maxDistance);
ObjectArray checkCollisions(const Math::AABB &boundingBox);
+ Math::Vector3d resolveCollisions(Math::Vector3d const &lastPosition, Math::Vector3d const &newPosition, int playerHeight);
void addObjectFromArea(int16 id, Area *global);
void addObject(Object *obj);
void addFloor();
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 97b00b2d94e..6e3d666dec9 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -225,6 +225,7 @@ public:
virtual void pressedKey(const int keycode);
virtual bool onScreenControls(Common::Point mouse);
void move(CameraMovement direction, uint8 scale, float deltaTime);
+ void resolveCollisions(Math::Vector3d newPosition);
virtual void checkIfStillInArea();
void changePlayerHeight(int index);
void increaseStepSize();
@@ -275,7 +276,7 @@ public:
Common::Array<Common::String> _conditionSources;
Common::Array<FCLInstructionVector> _conditions;
- bool checkCollisions(bool executeCode);
+ void runCollisionConditions(Math::Vector3d const lastPosition, Math::Vector3d const newPosition);
Math::Vector3d _objExecutingCodeSize;
virtual void executeMovementConditions();
void executeObjectConditions(GeometricObject *obj, bool shot, bool collided, bool activated);
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index 7d89bafe446..e5245723426 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -158,7 +158,7 @@ void FreescapeEngine::rise() {
changePlayerHeight(_playerHeightNumber);
}
- bool collided = checkCollisions(true) || _position.y() >= 2016;
+ bool collided = /*checkCollisions(true) ||*/ _position.y() >= 2016;
if (collided) {
if (_currentArea->getAreaID() == previousAreaID) {
if (_flyMode)
@@ -181,7 +181,7 @@ void FreescapeEngine::lower() {
if (_flyMode) {
_position.setValue(1, _position.y() - (_playerSteps[_playerStepIndex] * 0.5));
- bool collided = checkCollisions(true);
+ bool collided = false; //checkCollisions(true);
if (collided) {
if (_currentArea->getAreaID() == previousAreaID) {
_position = _lastPosition;
@@ -222,21 +222,26 @@ void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTim
stepFront.z() = floor(stepFront.z()) + 0.5;
float positionY = _position.y();
+ Math::Vector3d destination;
switch (direction) {
case kForwardMovement:
- _position = _position + stepFront;
+ destination = _position + stepFront;
break;
case kBackwardMovement:
- _position = _position - stepFront;
+ destination = _position - stepFront;
break;
case kRightMovement:
- _position = _position - stepRight;
+ destination = _position - stepRight;
break;
case kLeftMovement:
- _position = _position + stepRight;
+ destination = _position + stepRight;
break;
}
+ if (!_flyMode)
+ destination.y() = positionY;
+ resolveCollisions(destination);
+ /*
// restore y coordinate
if (!_flyMode)
_position.set(_position.x(), positionY, _position.z());
@@ -306,6 +311,7 @@ void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTim
}
}
}
+ */
_lastPosition = _position;
debugC(1, kFreescapeDebugMove, "new player position: %f, %f, %f", _position.x(), _position.y(), _position.z());
@@ -315,66 +321,64 @@ void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTim
clearGameBit(31);
}
-bool FreescapeEngine::checkFloor(Math::Vector3d currentPosition) {
- debugC(1, kFreescapeDebugMove, "Checking floor under the player");
- bool collided = checkCollisions(false);
- assert(!collided);
+void FreescapeEngine::resolveCollisions(Math::Vector3d const position) {
+ Math::Vector3d newPosition = position;
+ Math::Vector3d lastPosition = _lastPosition;
- _position.set(_position.x(), _position.y() - 2, _position.z());
- collided = checkCollisions(false);
- _position = currentPosition;
- return collided;
-}
+ int previousAreaID = _currentArea->getAreaID();
+ runCollisionConditions(lastPosition, newPosition);
+ if (_currentArea->getAreaID() != previousAreaID) {
+ return;
+ }
-bool FreescapeEngine::tryStepUp(Math::Vector3d currentPosition) {
- debugC(1, kFreescapeDebugMove, "Try to step up!");
- _position.set(_position.x(), _position.y() + 64, _position.z());
- bool collided = checkCollisions(false);
- if (collided) {
- _position = currentPosition;
- return false;
- } else {
- // Try to step down
- return true;
+ newPosition = _currentArea->resolveCollisions(lastPosition, newPosition, _playerHeight);
+
+ if (_flyMode) {
+ _position = newPosition;
+ return;
}
-}
-bool FreescapeEngine::tryStepDown(Math::Vector3d currentPosition) {
- debugC(1, kFreescapeDebugMove, "Try to step down!");
- _position.set(_position.x(), _position.y() - 1, _position.z());
- if (checkFloor(_position)) {
- return true;
- } else {
- _position = currentPosition;
- return false;
+ if ((lastPosition - newPosition).length() < 1) { // If the player has not moved
+ // Try to step up
+ newPosition = position;
+ newPosition.y() = newPosition.y() + 64;
+
+ lastPosition = _lastPosition;
+ lastPosition.y() = lastPosition.y() + 64;
+
+ newPosition = _currentArea->resolveCollisions(lastPosition, newPosition, _playerHeight);
}
-}
-bool FreescapeEngine::checkCollisions(bool executeCode) {
- if (_noClipMode)
- return false;
- Math::AABB boundingBox(_lastPosition, _lastPosition);
+ /*if ((lastPosition - newPosition).length() >= 1) { // Step up
+ playSound(4, false);
+ }*/
- Math::Vector3d v1(_position.x() + 1, _position.y() + 1, _position.z() + 1);
- Math::Vector3d v2(_position.x() - 1, _position.y() - _playerHeight, _position.z() - 1);
+ lastPosition = newPosition;
+ newPosition.y() = -8192;
+ newPosition = _currentArea->resolveCollisions(lastPosition, newPosition, _playerHeight);
+ int fallen = lastPosition.y() - newPosition.y();
- boundingBox.expand(v1);
- boundingBox.expand(v2);
- ObjectArray objs = _currentArea->checkCollisions(boundingBox);
- bool collided = !objs.empty();
+ if (fallen > 64)
+ _hasFallen = !_disableFalling;
- // If we don't need to execute code, we can finish here
- if (!executeCode) {
- return collided;
+ if (!_hasFallen && fallen > 0) {
+ // Position in Y was changed, let's re-run effects
+ runCollisionConditions(lastPosition, newPosition);
}
+ _position = newPosition;
+}
+
+void FreescapeEngine::runCollisionConditions(Math::Vector3d const lastPosition, Math::Vector3d const newPosition) {
+ if (_noClipMode)
+ return;
- // If we need to execute code, we need to make sure the bounding box touches the floor
- // so we will expand it and re-run the collision checking
- uint tolerance = 1;
- Math::Vector3d v3(_position.x() - 1, _position.y() - _playerHeight - tolerance, _position.z() - 1);
- boundingBox.expand(v3);
+ // We need to make sure the bounding box touches the floor so we will expand it and run the collision checking
+ uint tolerance = 3;
+ Math::Vector3d v(newPosition.x() - 1, newPosition.y() - _playerHeight - tolerance, newPosition.z() - 1);
+ Math::AABB boundingBox(lastPosition, lastPosition);
+ boundingBox.expand(v);
- objs = _currentArea->checkCollisions(boundingBox);
+ ObjectArray objs = _currentArea->checkCollisions(boundingBox);
// sort so the condition from those objects that are larger are executed last
struct {
@@ -393,7 +397,7 @@ bool FreescapeEngine::checkCollisions(bool executeCode) {
// The following check stops the player from going through big solid objects such as walls
// FIXME: find a better workaround of this
if (gobj->getSize().length() > 3000) {
- if (largeObjectWasBlocking)
+ if (largeObjectWasBlocking && !(isDriller() && _currentArea->getAreaID() == 14))
continue;
largeObjectWasBlocking = true;
}
@@ -403,9 +407,6 @@ bool FreescapeEngine::checkCollisions(bool executeCode) {
if (areaID != _currentArea->getAreaID())
break;
}
- // We still need to return the original result, not the collision using the expanded bounding box
- // This will avoid detecting the floor constantly
- return collided;
}
} // namespace Freescape
Commit: a68b228f5960e2af1a7e265d718365dd4def267b
https://github.com/scummvm/scummvm/commit/a68b228f5960e2af1a7e265d718365dd4def267b
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: remove spaces from area name when displaying info menu in driller
Changed paths:
engines/freescape/games/driller/driller.cpp
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 902354fcce9..42708de1e9f 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -245,7 +245,10 @@ void DrillerEngine::drawInfoMenu() {
_gfx->readFromPalette(color, r, g, b);
uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
- drawStringInSurface(Common::String::format("%10s : %s", "sector", _currentArea->_name.c_str()), 69, 25, front, black, surface);
+ Common::String areaName = _currentArea->_name;
+ areaName.trim();
+
+ drawStringInSurface(Common::String::format("%10s : %s", "sector", areaName.c_str()), 69, 25, front, black, surface);
Common::String rigStatus;
Common::String gasFound;
Common::String perTapped;
Commit: 12e0332415f8e608305b3e8a1a11791ddd1e5a98
https://github.com/scummvm/scummvm/commit/12e0332415f8e608305b3e8a1a11791ddd1e5a98
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: make sure end game area is properly renderer in driller
Changed paths:
engines/freescape/games/driller/driller.cpp
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 42708de1e9f..2721262e168 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -799,9 +799,15 @@ bool DrillerEngine::checkIfGameEnded() {
insertTemporaryMessage(_messagesList[19], _countdown - 2);
_gameStateVars[32] = 0; // Avoid repeating the message
}
- drawFrame();
- _gfx->flipBuffer();
- g_system->updateScreen();
+
+ // Draw a few frames
+ for (int i = 0; i < 10; i++) {
+ drawFrame();
+ _gfx->flipBuffer();
+ g_system->updateScreen();
+ g_system->delayMillis(10);
+ }
+
g_system->delayMillis(5000);
return true;
}
Commit: a7a4415acb053c06d46c275e930c7ad5030d6720
https://github.com/scummvm/scummvm/commit/a7a4415acb053c06d46c275e930c7ad5030d6720
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: palette fixes for driller cpc
Changed paths:
engines/freescape/games/driller/cpc.cpp
engines/freescape/games/palettes.cpp
diff --git a/engines/freescape/games/driller/cpc.cpp b/engines/freescape/games/driller/cpc.cpp
index f9d95eef943..e105189cd01 100644
--- a/engines/freescape/games/driller/cpc.cpp
+++ b/engines/freescape/games/driller/cpc.cpp
@@ -138,12 +138,12 @@ void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {
_gfx->selectColorFromFourColorPalette(color, r, g, b);
uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
- color = 0;
+ color = _currentArea->_usualBackgroundColor;
if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
color = (*_gfx->_colorRemaps)[color];
}
- _gfx->readFromPalette(color, r, g, b);
+ _gfx->selectColorFromFourColorPalette(color, r, g, b);
uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
int score = _gameStateVars[k8bitVariableScore];
diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index e2fe6b8e3c8..529f8f43284 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -74,13 +74,13 @@ byte kDrillerZXPalette[9][3] = {
};
byte kDrillerCPCPalette[32][3] = {
- {0x00, 0x00, 0x00}, // 0: special case?
+ {0x80, 0x80, 0x80}, // 0: special case?
{0x11, 0x22, 0x33},
{0x80, 0xff, 0x80}, // 2
{0xff, 0xff, 0x80}, // 3
{0x11, 0x22, 0x33},
{0xff, 0x00, 0x80}, // 5
- {0x00, 0xff, 0x80}, // 6
+ {0x00, 0x80, 0x00}, // 6
{0xff, 0x80, 0x80}, // 7
{0x11, 0x22, 0x33},
{0x11, 0x22, 0x33},
Commit: e5747d3916b20390dd7413325e7a93d8126f8d37
https://github.com/scummvm/scummvm/commit/e5747d3916b20390dd7413325e7a93d8126f8d37
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: color remap fixes for driller cpc/amiga/atari
Changed paths:
engines/freescape/freescape.cpp
engines/freescape/games/driller/cpc.cpp
engines/freescape/games/driller/driller.cpp
engines/freescape/games/palettes.cpp
engines/freescape/gfx.cpp
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 841e33f3c00..587c9d6e500 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -278,12 +278,13 @@ void FreescapeEngine::drawFrame() {
_gfx->positionCamera(_position, _position + _cameraFront);
if (_underFireFrames > 0) {
- int underFireColor = isDriller() && isDOS() ? 1
- : _currentArea->_underFireBackgroundColor;
- if (underFireColor < 16) {
- _currentArea->remapColor(_currentArea->_usualBackgroundColor, underFireColor);
- _currentArea->remapColor(_currentArea->_skyColor, underFireColor);
- }
+ int underFireColor = _currentArea->_underFireBackgroundColor;
+
+ if (isDriller() && (isDOS() || isAmiga() || isAtariST()))
+ underFireColor = 1;
+
+ _currentArea->remapColor(_currentArea->_usualBackgroundColor, underFireColor);
+ _currentArea->remapColor(_currentArea->_skyColor, underFireColor);
}
drawBackground();
diff --git a/engines/freescape/games/driller/cpc.cpp b/engines/freescape/games/driller/cpc.cpp
index e105189cd01..79016c4c0e7 100644
--- a/engines/freescape/games/driller/cpc.cpp
+++ b/engines/freescape/games/driller/cpc.cpp
@@ -132,10 +132,10 @@ void DrillerEngine::loadAssetsCPCFullGame() {
}
void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {
- uint32 color = 1;
+ uint32 color = _currentArea->_underFireBackgroundColor;
uint8 r, g, b;
- _gfx->selectColorFromFourColorPalette(color, r, g, b);
+ _gfx->readFromPalette(color, r, g, b);
uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
color = _currentArea->_usualBackgroundColor;
@@ -143,7 +143,7 @@ void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {
color = (*_gfx->_colorRemaps)[color];
}
- _gfx->selectColorFromFourColorPalette(color, r, g, b);
+ _gfx->readFromPalette(color, r, g, b);
uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
int score = _gameStateVars[k8bitVariableScore];
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 2721262e168..4eb1a81523a 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -180,8 +180,13 @@ void DrillerEngine::gotoArea(uint16 areaID, int entranceID) {
_gfx->setColorRemaps(&_currentArea->_colorRemaps);
swapPalette(areaID);
- _currentArea->_skyColor = 0;
- _currentArea->_usualBackgroundColor = 0;
+
+ if (isDOS() || isAmiga() || isAtariST()) {
+ _currentArea->_skyColor = 0;
+ _currentArea->_usualBackgroundColor = 0;
+ } else if (isCPC()) {
+ _currentArea->_skyColor = _currentArea->_usualBackgroundColor;
+ }
resetInput();
}
diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index 529f8f43284..0950f90e165 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -94,7 +94,7 @@ byte kDrillerCPCPalette[32][3] = {
{0x00, 0xff, 0x80}, // 17
{0x00, 0xff, 0x00}, // 18
{0x80, 0xff, 0xff}, // 19
- {0x11, 0x22, 0x33},
+ {0x00, 0x00, 0x00}, // 20
{0x00, 0x00, 0xff}, // 21
{0x00, 0x80, 0x00}, // 22
{0x00, 0x80, 0xff}, // 23
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index f4dde905eda..63a18892d60 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -934,19 +934,12 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
}
void Renderer::drawBackground(uint8 color) {
-
if (_colorRemaps && _colorRemaps->contains(color)) {
color = (*_colorRemaps)[color];
}
-
- byte *stipple = nullptr;
- uint8 r1, g1, b1, r2, g2, b2;
- bool render = getRGBAt(color, r1, g1, b1, r2, g2, b2, stipple);
- if (!render)
- r1 = g1 = b1 = 0;
-
- //assert(stipple == nullptr); // Unclear if this is ever used
- clear(r1, g1, b1);
+ uint8 r, g, b;
+ readFromPalette(color, r, g, b);
+ clear(r, g, b);
}
Graphics::RendererType determinateRenderType() {
Commit: 54d4dfc2a46ddfc5e7e6d42e134f82f9f9c5fe88
https://github.com/scummvm/scummvm/commit/54d4dfc2a46ddfc5e7e6d42e134f82f9f9c5fe88
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: info menu fixes for driller zx/amiga/atari
Changed paths:
engines/freescape/games/driller/driller.cpp
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 4eb1a81523a..3d4d2075e07 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -248,12 +248,18 @@ void DrillerEngine::drawInfoMenu() {
uint8 r, g, b;
_gfx->readFromPalette(color, r, g, b);
+ if (isAmiga() || isAtariST()) {
+ r = 0xFF;
+ g = 0xFF;
+ b = 0x55;
+ }
+
uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
Common::String areaName = _currentArea->_name;
areaName.trim();
- drawStringInSurface(Common::String::format("%10s : %s", "sector", areaName.c_str()), 69, 25, front, black, surface);
+ drawStringInSurface(Common::String::format("%10s : %s", "sector", areaName.c_str()), 59, 25, front, black, surface);
Common::String rigStatus;
Common::String gasFound;
Common::String perTapped;
@@ -284,10 +290,10 @@ void DrillerEngine::drawInfoMenu() {
break;
}
- drawStringInSurface(Common::String::format("%10s : %s", "rig status", rigStatus.c_str()), 69, 33, front, black, surface);
- drawStringInSurface(Common::String::format("%10s : %s", "gas found", gasFound.c_str()), 69, 41, front, black, surface);
- drawStringInSurface(Common::String::format("%10s : %s", "% tapped", perTapped.c_str()), 69, 49, front, black, surface);
- drawStringInSurface(Common::String::format("%10s : %s", "gas tapped", gasTapped.c_str()), 69, 57, front, black, surface);
+ drawStringInSurface(Common::String::format("%10s : %s", "rig status", rigStatus.c_str()), 59, 33, front, black, surface);
+ drawStringInSurface(Common::String::format("%10s : %s", "gas found", gasFound.c_str()), 59, 41, front, black, surface);
+ drawStringInSurface(Common::String::format("%10s : %s", "% tapped", perTapped.c_str()), 59, 49, front, black, surface);
+ drawStringInSurface(Common::String::format("%10s : %s", "gas tapped", gasTapped.c_str()), 59, 57, front, black, surface);
drawStringInSurface(Common::String::format("%13s : %d", "total sectors", 18), 84, 73, front, black, surface);
drawStringInSurface(Common::String::format("%13s : %d", "safe sectors", _gameStateVars[32]), 84, 81, front, black, surface);
@@ -298,7 +304,8 @@ void DrillerEngine::drawInfoMenu() {
} else if (isSpectrum()) {
drawStringInSurface("l-load s-save 1-abort", 76, 97, front, black, surface);
drawStringInSurface("any other key-continue", 76, 105, front, black, surface);
- }
+ } else if (isAmiga() || isAtariST())
+ drawStringInSurface("press any key to continue", 66, 97, front, black, surface);
_uiTexture->update(surface);
_gfx->setViewport(_fullscreenViewArea);
Commit: 0f7f13813b527a92219e7f61f67027a0cc2c0471
https://github.com/scummvm/scummvm/commit/0f7f13813b527a92219e7f61f67027a0cc2c0471
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: added missing items for driller cga palettes
Changed paths:
engines/freescape/games/palettes.cpp
diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index 0950f90e165..f66b90ed5af 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -176,19 +176,22 @@ static const struct CGAPalettteEntry {
{10, kDrillerCGAPalettePinkBlue},
{11, kDrillerCGAPaletteRedGreen},
{12, kDrillerCGAPalettePinkBlue},
-
+ {13, kDrillerCGAPaletteRedGreen},
{14, kDrillerCGAPalettePinkBlue},
-
+ {15, kDrillerCGAPaletteRedGreen},
{16, kDrillerCGAPalettePinkBlue},
-
+ {17, kDrillerCGAPalettePinkBlue},
+ {18, kDrillerCGAPalettePinkBlue},
{19, kDrillerCGAPaletteRedGreen},
{20, kDrillerCGAPalettePinkBlue},
{21, kDrillerCGAPaletteRedGreen},
{22, kDrillerCGAPalettePinkBlue},
{23, kDrillerCGAPaletteRedGreen},
-
+ {25, kDrillerCGAPalettePinkBlue},
+ {27, kDrillerCGAPaletteRedGreen},
{28, kDrillerCGAPalettePinkBlue},
+ {31, kDrillerCGAPaletteRedGreen},
{32, kDrillerCGAPalettePinkBlue},
{127, kDrillerCGAPaletteRedGreen},
{0, 0} // This marks the end
Commit: 0d01a9efdc7b5ebfe60b6a4de4e0f352d3f57296
https://github.com/scummvm/scummvm/commit/0d01a9efdc7b5ebfe60b6a4de4e0f352d3f57296
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: improved handling of entrance usage
Changed paths:
engines/freescape/language/instruction.cpp
engines/freescape/movement.cpp
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index beb817e9841..099a7744841 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -93,7 +93,7 @@ void FreescapeEngine::executeObjectConditions(GeometricObject *obj, bool shot, b
assert(obj != nullptr);
if (!obj->_conditionSource.empty()) {
_firstSound = true;
- _objExecutingCodeSize = obj->getSize();
+ _objExecutingCodeSize = collided ? obj->getSize() : Math::Vector3d();
if (collided)
debugC(1, kFreescapeDebugCode, "Executing with collision flag: %s", obj->_conditionSource.c_str());
else if (shot)
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index e5245723426..0737675a376 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -46,10 +46,10 @@ void FreescapeEngine::traverseEntrance(uint16 entranceID) {
}
_pitch = rotation.x();
- if (ABS(_objExecutingCodeSize.x()) <= ABS(_objExecutingCodeSize.z()))
- _yaw = rotation.y() - 90;
- else
+ if (_objExecutingCodeSize.length() == 0 || ABS(_objExecutingCodeSize.x()) > ABS(_objExecutingCodeSize.z()))
_yaw = rotation.y() + 90;
+ else
+ _yaw = rotation.y() - 90;
debugC(1, kFreescapeDebugMove, "entrace position: %f %f %f", _position.x(), _position.y(), _position.z());
Commit: e96d2199c3338080119416e78b0d58836e6d263f
https://github.com/scummvm/scummvm/commit/e96d2199c3338080119416e78b0d58836e6d263f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: improved handling of rise/fall
Changed paths:
engines/freescape/area.cpp
engines/freescape/movement.cpp
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 585256345ec..372d02584f6 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -330,20 +330,12 @@ float sweepAABB(Math::AABB const &a, Math::AABB const &b, Math::Vector3d const &
return h;
}
-Math::AABB createPlayerAABB(Math::Vector3d const position, int playerHeight) {
- Math::AABB boundingBox(position, position);
-
- Math::Vector3d v1(position.x() + 1, position.y() + 1, position.z() + 1);
- Math::Vector3d v2(position.x() - 1, position.y() - playerHeight, position.z() - 1);
-
- boundingBox.expand(v1);
- boundingBox.expand(v2);
- return boundingBox;
-}
+extern Math::AABB createPlayerAABB(Math::Vector3d const position, int playerHeight);
Math::Vector3d Area::resolveCollisions(const Math::Vector3d &lastPosition_, const Math::Vector3d &newPosition_, int playerHeight) {
Math::Vector3d position = newPosition_;
Math::Vector3d lastPosition = lastPosition_;
+ Math::AABB boundingBox = createPlayerAABB(lastPosition, playerHeight);
float epsilon = 1.5;
int i = 0;
@@ -352,7 +344,6 @@ Math::Vector3d Area::resolveCollisions(const Math::Vector3d &lastPosition_, cons
Math::Vector3d normal;
Math::Vector3d direction = position - lastPosition;
- Math::AABB boundingBox = createPlayerAABB(lastPosition, playerHeight);
for (auto &obj : _drawableObjects) {
if (!obj->isDestroyed() && !obj->isInvisible()) {
GeometricObject *gobj = (GeometricObject *)obj;
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index 0737675a376..c297bdb8d46 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -23,6 +23,17 @@
namespace Freescape {
+Math::AABB createPlayerAABB(Math::Vector3d const position, int playerHeight) {
+ Math::AABB boundingBox(position, position);
+
+ Math::Vector3d v1(position.x() + 1, position.y() + 1, position.z() + 1);
+ Math::Vector3d v2(position.x() - 1, position.y() - playerHeight, position.z() - 1);
+
+ boundingBox.expand(v1);
+ boundingBox.expand(v2);
+ return boundingBox;
+}
+
void FreescapeEngine::gotoArea(uint16 areaID, int entranceID) {
error("Function \"%s\" not implemented", __FUNCTION__);
}
@@ -149,27 +160,26 @@ void FreescapeEngine::rise() {
debugC(1, kFreescapeDebugMove, "playerHeightNumber: %d", _playerHeightNumber);
int previousAreaID = _currentArea->getAreaID();
if (_flyMode) {
- _position.setValue(1, _position.y() + _playerSteps[_playerStepIndex]);
+ Math::Vector3d destination = _position;
+ destination.y() = destination.y() + _playerSteps[_playerStepIndex];
+ resolveCollisions(destination);
} else {
if (_playerHeightNumber == int(_playerHeights.size()) - 1)
return;
_playerHeightNumber++;
changePlayerHeight(_playerHeightNumber);
- }
- bool collided = /*checkCollisions(true) ||*/ _position.y() >= 2016;
- if (collided) {
- if (_currentArea->getAreaID() == previousAreaID) {
- if (_flyMode)
- _position = _lastPosition;
- else {
+ Math::AABB boundingBox = createPlayerAABB(_position, _playerHeight);
+ ObjectArray objs = _currentArea->checkCollisions(boundingBox);
+ bool collided = objs.size() > 0;
+ if (collided) {
+ if (_currentArea->getAreaID() == previousAreaID) {
_playerHeightNumber--;
changePlayerHeight(_playerHeightNumber);
}
}
}
-
_lastPosition = _position;
debugC(1, kFreescapeDebugMove, "new player position: %f, %f, %f", _position.x(), _position.y(), _position.z());
executeMovementConditions();
@@ -177,16 +187,10 @@ void FreescapeEngine::rise() {
void FreescapeEngine::lower() {
debugC(1, kFreescapeDebugMove, "playerHeightNumber: %d", _playerHeightNumber);
- int previousAreaID = _currentArea->getAreaID();
-
if (_flyMode) {
- _position.setValue(1, _position.y() - (_playerSteps[_playerStepIndex] * 0.5));
- bool collided = false; //checkCollisions(true);
- if (collided) {
- if (_currentArea->getAreaID() == previousAreaID) {
- _position = _lastPosition;
- }
- }
+ Math::Vector3d destination = _position;
+ destination.y() = destination.y() - _playerSteps[_playerStepIndex];
+ resolveCollisions(destination);
} else {
if (_playerHeightNumber == 0)
return;
Commit: d0f9025cb95930b6e0c9dcab078deef819daf9a1
https://github.com/scummvm/scummvm/commit/d0f9025cb95930b6e0c9dcab078deef819daf9a1
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: initial parsing and rendering of group objects
Changed paths:
A engines/freescape/objects/group.cpp
engines/freescape/area.cpp
engines/freescape/area.h
engines/freescape/freescape.h
engines/freescape/language/instruction.cpp
engines/freescape/loaders/8bitBinaryLoader.cpp
engines/freescape/module.mk
engines/freescape/objects/geometricobject.cpp
engines/freescape/objects/group.h
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 372d02584f6..73748a8e012 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -226,11 +226,20 @@ void Area::draw(Freescape::Renderer *gfx) {
assert(_drawableObjects.size() > 0);
for (auto &obj : _drawableObjects) {
if (!obj->isDestroyed() && !obj->isInvisible()) {
- obj->draw(gfx);
+ if (obj->getType() != ObjectType::kGroupType)
+ obj->draw(gfx);
+ else
+ drawGroup(gfx, (Group *)obj);
}
}
}
+void Area::drawGroup(Freescape::Renderer *gfx, Group* group) {
+ for (auto &obj : group->_objects) {
+ obj->draw(gfx);
+ }
+}
+
Object *Area::shootRay(const Math::Ray &ray) {
float size = 16.0 * 8192.0; // TODO: check if this is max size
Object *collided = nullptr;
diff --git a/engines/freescape/area.h b/engines/freescape/area.h
index a6fa1e2fdc7..7b149696e2e 100644
--- a/engines/freescape/area.h
+++ b/engines/freescape/area.h
@@ -30,6 +30,8 @@
#include "freescape/language/instruction.h"
#include "freescape/objects/object.h"
+#include "freescape/objects/group.h"
+
namespace Freescape {
@@ -50,6 +52,7 @@ public:
void remapColor(int index, int color);
void unremapColor(int index);
void draw(Renderer *gfx);
+ void drawGroup(Renderer *gfx, Group *group);
void show();
Object *shootRay(const Math::Ray &ray);
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 6e3d666dec9..299cebcfbd9 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -286,6 +286,7 @@ public:
// Instructions
bool checkConditional(FCLInstruction &instruction, bool shot, bool collided, bool timer, bool activated);
bool checkIfGreaterOrEqual(FCLInstruction &instruction);
+ void executeExecute(FCLInstruction &instruction);
void executeIncrementVariable(FCLInstruction &instruction);
void executeDecrementVariable(FCLInstruction &instruction);
void executeSetVariable(FCLInstruction &instruction);
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index 099a7744841..e040fe6492c 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -203,6 +203,9 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
case Token::REDRAW:
executeRedraw(instruction);
break;
+ case Token::EXECUTE:
+ executeExecute(instruction);
+ break;
case Token::DELAY:
executeDelay(instruction);
break;
@@ -250,6 +253,12 @@ void FreescapeEngine::executeRedraw(FCLInstruction &instruction) {
waitForSounds();
}
+void FreescapeEngine::executeExecute(FCLInstruction &instruction) {
+ // TODO
+ uint16 objId = instruction._source;
+ debugC(1, kFreescapeDebugCode, "Executing instructions from object %d", objId);
+}
+
void FreescapeEngine::executeSound(FCLInstruction &instruction) {
if (_firstSound)
stopAllSounds();
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index e570d4dbb65..e5c15fc76ca 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -277,11 +277,23 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
case kGroupType:
debugC(1, kFreescapeDebugParser, "Object of type 'group'");
- file->seek(byteSizeOfObject, SEEK_CUR);
+ Common::Array<uint8> groupDataArray;
+ groupDataArray.push_back(uint8(position.x()));
+ groupDataArray.push_back(uint8(position.y()));
+ groupDataArray.push_back(uint8(position.z()));
+
+ groupDataArray.push_back(uint8(v.x()));
+ groupDataArray.push_back(uint8(v.y()));
+ groupDataArray.push_back(uint8(v.z()));
+
+ byteSizeOfObject++;
+ while(--byteSizeOfObject > 0)
+ groupDataArray.push_back(file->readByte());
+
return new Group(
objectID,
- position,
- v);
+ rawFlagsAndType,
+ groupDataArray);
break;
}
// Unreachable
@@ -486,6 +498,12 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
debugC(1, kFreescapeDebugParser, "Reading object: %d", object);
Object *newObject = load8bitObject(file);
+ if (newObject->getType() == ObjectType::kGroupType) {
+ Group *group = (Group *)newObject;
+ for (ObjectMap::iterator it = objectsByID->begin(); it != objectsByID->end(); ++it)
+ group->assemble(it->_value);
+ }
+
if (newObject) {
newObject->scale(scale);
if (newObject->getType() == kEntranceType) {
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index cf02372b576..3db7785ab67 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -26,6 +26,7 @@ MODULE_OBJS := \
movement.o \
neo.o \
objects/geometricobject.o \
+ objects/group.o \
objects/sensor.o \
scr.o \
sound.o \
diff --git a/engines/freescape/objects/geometricobject.cpp b/engines/freescape/objects/geometricobject.cpp
index 954f67755fb..422a541e804 100644
--- a/engines/freescape/objects/geometricobject.cpp
+++ b/engines/freescape/objects/geometricobject.cpp
@@ -171,6 +171,16 @@ GeometricObject::GeometricObject(
}
void GeometricObject::setOrigin(Math::Vector3d origin_) {
+ if (isPolygon(_type)) {
+ Math::Vector3d offset = origin_ - _origin;
+ offset = 32 * offset;
+ for (int i = 0; i < int(_ordinates->size()); i = i + 3) {
+ (*_ordinates)[i ] += uint16(offset.x());
+ (*_ordinates)[i + 1] += uint16(offset.y());
+ (*_ordinates)[i + 2] += uint16(offset.z());
+ }
+ }
+
_origin = origin_;
computeBoundingBox();
}
diff --git a/engines/freescape/objects/group.cpp b/engines/freescape/objects/group.cpp
new file mode 100644
index 00000000000..b080641418a
--- /dev/null
+++ b/engines/freescape/objects/group.cpp
@@ -0,0 +1,90 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include "freescape/freescape.h"
+#include "freescape/objects/group.h"
+#include "freescape/objects/geometricobject.h"
+
+namespace Freescape {
+
+Group::Group(uint16 objectID_, uint16 flags_, const Common::Array<byte> data_) {
+ _objectID = objectID_;
+ _flags = flags_;
+
+ int i;
+ for (i = 0; i < 9; i++) {
+ debugC(1, kFreescapeDebugParser, "group data[%d] = %d", i, data_[i]);
+ if (data_[i] > 0)
+ _objectIds.push_back(data_[i]);
+ /*else
+ break;*/
+ }
+ i = 9;
+ while (i < int(data_.size())) {
+ debugC(1, kFreescapeDebugParser, "group data[%d] = %d", i, data_[i]);
+
+ if (data_[i] >= _objectIds.size())
+ break;
+
+ _objects.push_back(nullptr);
+ //assert(data_[i] < _objectIds.size());
+ _objectIndices.push_back(data_[i]);
+
+ debug("data[%d] = %d", i + 1, data_[i + 1]);
+ debug("data[%d] = %d", i + 2, data_[i + 2]);
+ debug("data[%d] = %d", i + 3, data_[i + 3]);
+ Math::Vector3d position(data_[i + 1], data_[i + 2], data_[i + 3]);
+ _objectPositions.push_back(position);
+
+ i = i + 4;
+ }
+
+ if (isDestroyed()) // If the object is destroyed, restore it
+ restore();
+
+ _flags = _flags & ~0x80;
+ assert(!isInitiallyInvisible());
+ makeVisible();
+}
+
+void Group::assemble(Object *obj) {
+ int objectIndex = -1;
+ for (int i = 0; i < int(_objectIds.size()) ; i++) {
+ if (_objectIds[i] == obj->getObjectID()) {
+ objectIndex = i;
+ break;
+ }
+ }
+
+ if (objectIndex == -1)
+ return;
+
+ for (int i = 0; i < int(_objectIndices.size()) ; i++) {
+ int index = _objectIndices[i];
+ if (index == objectIndex) {
+ Object *duplicate = obj->duplicate();
+ Math::Vector3d position = _objectPositions[i];
+ duplicate->setOrigin(position);
+ _objects[i] = duplicate;
+ }
+ }
+}
+
+} // End of namespace Freescape
\ No newline at end of file
diff --git a/engines/freescape/objects/group.h b/engines/freescape/objects/group.h
index 514ca33542d..270485e276b 100644
--- a/engines/freescape/objects/group.h
+++ b/engines/freescape/objects/group.h
@@ -28,15 +28,16 @@ namespace Freescape {
class Group : public Object {
public:
- Group(uint16 objectID_,
- const Math::Vector3d &origin_,
- const Math::Vector3d &rotation_) {
- _objectID = objectID_;
- _origin = origin_;
- _rotation = rotation_;
- }
+ Group(uint16 objectID_, uint16 flags_, const Common::Array<byte> data_);
+ void assemble(Object *obj);
+
+ Common::Array<Object *> _objects;
+ Common::Array<Math::Vector3d> _objectPositions;
+ Common::Array<int16> _objectIndices;
+ Common::Array<int16> _objectIds;
ObjectType getType() override { return ObjectType::kGroupType; };
+ bool isDrawable() override { return true; }
void draw(Freescape::Renderer *gfx) override { error("cannot render Group"); };
void scale(int factor) override { warning("cannot scale Group"); };
Object *duplicate() override { error("cannot duplicate Group"); };
Commit: cbe4d4fd45f571874a7e3be884369ea76158e1d3
https://github.com/scummvm/scummvm/commit/cbe4d4fd45f571874a7e3be884369ea76158e1d3
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: improved rendering and scaling of group objects
Changed paths:
engines/freescape/area.cpp
engines/freescape/area.h
engines/freescape/freescape.cpp
engines/freescape/loaders/8bitBinaryLoader.cpp
engines/freescape/movement.cpp
engines/freescape/objects/group.cpp
engines/freescape/objects/group.h
engines/freescape/objects/object.h
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 73748a8e012..4fe400cbed5 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -222,21 +222,24 @@ void Area::resetArea() {
}
-void Area::draw(Freescape::Renderer *gfx) {
+void Area::draw(Freescape::Renderer *gfx, uint32 ticks) {
assert(_drawableObjects.size() > 0);
for (auto &obj : _drawableObjects) {
if (!obj->isDestroyed() && !obj->isInvisible()) {
if (obj->getType() != ObjectType::kGroupType)
obj->draw(gfx);
else
- drawGroup(gfx, (Group *)obj);
+ drawGroup(gfx, (Group *)obj, ticks);
}
}
}
-void Area::drawGroup(Freescape::Renderer *gfx, Group* group) {
- for (auto &obj : group->_objects) {
- obj->draw(gfx);
+void Area::drawGroup(Freescape::Renderer *gfx, Group* group, uint32 ticks) {
+ uint32 groupSize = group->_objects.size();
+ for (uint32 i = 0; i < groupSize ; i++) {
+ if ((ticks / 10) % (groupSize + 1) == i) {
+ group->_objects[i]->draw(gfx);
+ }
}
}
diff --git a/engines/freescape/area.h b/engines/freescape/area.h
index 7b149696e2e..d887065f651 100644
--- a/engines/freescape/area.h
+++ b/engines/freescape/area.h
@@ -51,8 +51,8 @@ public:
uint8 getScale();
void remapColor(int index, int color);
void unremapColor(int index);
- void draw(Renderer *gfx);
- void drawGroup(Renderer *gfx, Group *group);
+ void draw(Renderer *gfx, uint32 ticks);
+ void drawGroup(Renderer *gfx, Group *group, uint32 ticks);
void show();
Object *shootRay(const Math::Ray &ray);
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 587c9d6e500..f985adefcf8 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -288,7 +288,7 @@ void FreescapeEngine::drawFrame() {
}
drawBackground();
- _currentArea->draw(_gfx);
+ _currentArea->draw(_gfx, _ticks);
if (_underFireFrames > 0) {
for (auto &it : _sensors) {
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index e5c15fc76ca..c99ff34eafd 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -498,14 +498,14 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
debugC(1, kFreescapeDebugParser, "Reading object: %d", object);
Object *newObject = load8bitObject(file);
- if (newObject->getType() == ObjectType::kGroupType) {
- Group *group = (Group *)newObject;
- for (ObjectMap::iterator it = objectsByID->begin(); it != objectsByID->end(); ++it)
- group->assemble(it->_value);
- }
-
if (newObject) {
newObject->scale(scale);
+ if (newObject->getType() == ObjectType::kGroupType) {
+ Group *group = (Group *)newObject;
+ for (ObjectMap::iterator it = objectsByID->begin(); it != objectsByID->end(); ++it)
+ group->assemble(it->_value);
+ }
+
if (newObject->getType() == kEntranceType) {
if (entrancesByID->contains(newObject->getObjectID() & 0x7fff))
error("WARNING: replacing object id %d (%d)", newObject->getObjectID(), newObject->getObjectID() & 0x7fff);
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index c297bdb8d46..40086e378a2 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -326,6 +326,11 @@ void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTim
}
void FreescapeEngine::resolveCollisions(Math::Vector3d const position) {
+ if (_noClipMode) {
+ _position = position;
+ return;
+ }
+
Math::Vector3d newPosition = position;
Math::Vector3d lastPosition = _lastPosition;
@@ -373,9 +378,6 @@ void FreescapeEngine::resolveCollisions(Math::Vector3d const position) {
}
void FreescapeEngine::runCollisionConditions(Math::Vector3d const lastPosition, Math::Vector3d const newPosition) {
- if (_noClipMode)
- return;
-
// We need to make sure the bounding box touches the floor so we will expand it and run the collision checking
uint tolerance = 3;
Math::Vector3d v(newPosition.x() - 1, newPosition.y() - _playerHeight - tolerance, newPosition.z() - 1);
diff --git a/engines/freescape/objects/group.cpp b/engines/freescape/objects/group.cpp
index b080641418a..434a648b0d9 100644
--- a/engines/freescape/objects/group.cpp
+++ b/engines/freescape/objects/group.cpp
@@ -27,14 +27,13 @@ namespace Freescape {
Group::Group(uint16 objectID_, uint16 flags_, const Common::Array<byte> data_) {
_objectID = objectID_;
_flags = flags_;
+ _scale = 0;
int i;
for (i = 0; i < 9; i++) {
debugC(1, kFreescapeDebugParser, "group data[%d] = %d", i, data_[i]);
if (data_[i] > 0)
_objectIds.push_back(data_[i]);
- /*else
- break;*/
}
i = 9;
while (i < int(data_.size())) {
@@ -47,9 +46,9 @@ Group::Group(uint16 objectID_, uint16 flags_, const Common::Array<byte> data_) {
//assert(data_[i] < _objectIds.size());
_objectIndices.push_back(data_[i]);
- debug("data[%d] = %d", i + 1, data_[i + 1]);
- debug("data[%d] = %d", i + 2, data_[i + 2]);
- debug("data[%d] = %d", i + 3, data_[i + 3]);
+ debugC(1, kFreescapeDebugParser, "group data[%d] = %d", i + 1, data_[i + 1]);
+ debugC(1, kFreescapeDebugParser, "group data[%d] = %d", i + 2, data_[i + 2]);
+ debugC(1, kFreescapeDebugParser, "group data[%d] = %d", i + 3, data_[i + 3]);
Math::Vector3d position(data_[i + 1], data_[i + 2], data_[i + 3]);
_objectPositions.push_back(position);
@@ -59,8 +58,7 @@ Group::Group(uint16 objectID_, uint16 flags_, const Common::Array<byte> data_) {
if (isDestroyed()) // If the object is destroyed, restore it
restore();
- _flags = _flags & ~0x80;
- assert(!isInitiallyInvisible());
+ makeInitiallyVisible();
makeVisible();
}
@@ -80,11 +78,18 @@ void Group::assemble(Object *obj) {
int index = _objectIndices[i];
if (index == objectIndex) {
Object *duplicate = obj->duplicate();
+ assert(_scale > 0);
Math::Vector3d position = _objectPositions[i];
+
+ if (!GeometricObject::isPolygon(obj->getType()))
+ position = 32 * position / _scale;
+
duplicate->setOrigin(position);
+ assert(!duplicate->isDestroyed());
_objects[i] = duplicate;
}
}
+ obj->makeInitiallyInvisible();
}
} // End of namespace Freescape
\ No newline at end of file
diff --git a/engines/freescape/objects/group.h b/engines/freescape/objects/group.h
index 270485e276b..41ca55d527f 100644
--- a/engines/freescape/objects/group.h
+++ b/engines/freescape/objects/group.h
@@ -35,11 +35,12 @@ public:
Common::Array<Math::Vector3d> _objectPositions;
Common::Array<int16> _objectIndices;
Common::Array<int16> _objectIds;
+ int _scale;
ObjectType getType() override { return ObjectType::kGroupType; };
bool isDrawable() override { return true; }
void draw(Freescape::Renderer *gfx) override { error("cannot render Group"); };
- void scale(int factor) override { warning("cannot scale Group"); };
+ void scale(int scale_) override { _scale = scale_; };
Object *duplicate() override { error("cannot duplicate Group"); };
};
diff --git a/engines/freescape/objects/object.h b/engines/freescape/objects/object.h
index a21b844b28a..b03de78a649 100644
--- a/engines/freescape/objects/object.h
+++ b/engines/freescape/objects/object.h
@@ -71,6 +71,8 @@ public:
void makeInvisible() { _flags = _flags | 0x40; }
void makeVisible() { _flags = _flags & ~0x40; }
bool isInitiallyInvisible() { return _flags & 0x80; }
+ void makeInitiallyInvisible() { _flags = _flags | 0x80; }
+ void makeInitiallyVisible() { _flags = _flags & ~0x80; }
bool isDestroyed() { return _flags & 0x20; }
void destroy() { _flags = _flags | 0x20; }
void restore() { _flags = _flags & ~0x20; }
Commit: 2ed383c0d2d764b75bad864f61687d4b350ea5d9
https://github.com/scummvm/scummvm/commit/2ed383c0d2d764b75bad864f61687d4b350ea5d9
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: adjust aabb tolerance for castle
Changed paths:
engines/freescape/movement.cpp
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index 40086e378a2..ed0564cb815 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -379,7 +379,7 @@ void FreescapeEngine::resolveCollisions(Math::Vector3d const position) {
void FreescapeEngine::runCollisionConditions(Math::Vector3d const lastPosition, Math::Vector3d const newPosition) {
// We need to make sure the bounding box touches the floor so we will expand it and run the collision checking
- uint tolerance = 3;
+ uint tolerance = isCastle() ? 1 : 3;
Math::Vector3d v(newPosition.x() - 1, newPosition.y() - _playerHeight - tolerance, newPosition.z() - 1);
Math::AABB boundingBox(lastPosition, lastPosition);
boundingBox.expand(v);
Commit: c0995c3fa289b5ae0daefbbb8061212b54851280
https://github.com/scummvm/scummvm/commit/c0995c3fa289b5ae0daefbbb8061212b54851280
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: improved rendering of group animations
Changed paths:
engines/freescape/area.cpp
engines/freescape/loaders/8bitBinaryLoader.cpp
engines/freescape/objects/group.cpp
engines/freescape/objects/group.h
diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 4fe400cbed5..0777589a16b 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -236,10 +236,10 @@ void Area::draw(Freescape::Renderer *gfx, uint32 ticks) {
void Area::drawGroup(Freescape::Renderer *gfx, Group* group, uint32 ticks) {
uint32 groupSize = group->_objects.size();
+ uint32 frameSize = group->_objectPositions.size();
for (uint32 i = 0; i < groupSize ; i++) {
- if ((ticks / 10) % (groupSize + 1) == i) {
- group->_objects[i]->draw(gfx);
- }
+ group->assemble((ticks / 10) % frameSize, i);
+ group->_objects[i]->draw(gfx);
}
}
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index c99ff34eafd..a6289e30f35 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -503,7 +503,7 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
if (newObject->getType() == ObjectType::kGroupType) {
Group *group = (Group *)newObject;
for (ObjectMap::iterator it = objectsByID->begin(); it != objectsByID->end(); ++it)
- group->assemble(it->_value);
+ group->linkObject(it->_value);
}
if (newObject->getType() == kEntranceType) {
diff --git a/engines/freescape/objects/group.cpp b/engines/freescape/objects/group.cpp
index 434a648b0d9..a097259e301 100644
--- a/engines/freescape/objects/group.cpp
+++ b/engines/freescape/objects/group.cpp
@@ -36,14 +36,8 @@ Group::Group(uint16 objectID_, uint16 flags_, const Common::Array<byte> data_) {
_objectIds.push_back(data_[i]);
}
i = 9;
- while (i < int(data_.size())) {
- debugC(1, kFreescapeDebugParser, "group data[%d] = %d", i, data_[i]);
-
- if (data_[i] >= _objectIds.size())
- break;
-
- _objects.push_back(nullptr);
- //assert(data_[i] < _objectIds.size());
+ while (i < int(data_.size() - 4)) {
+ debugC(1, kFreescapeDebugParser, "group data[%d] = %d (index) ", i, data_[i]);
_objectIndices.push_back(data_[i]);
debugC(1, kFreescapeDebugParser, "group data[%d] = %d", i + 1, data_[i + 1]);
@@ -62,7 +56,7 @@ Group::Group(uint16 objectID_, uint16 flags_, const Common::Array<byte> data_) {
makeVisible();
}
-void Group::assemble(Object *obj) {
+void Group::linkObject(Object *obj) {
int objectIndex = -1;
for (int i = 0; i < int(_objectIds.size()) ; i++) {
if (_objectIds[i] == obj->getObjectID()) {
@@ -74,22 +68,20 @@ void Group::assemble(Object *obj) {
if (objectIndex == -1)
return;
- for (int i = 0; i < int(_objectIndices.size()) ; i++) {
- int index = _objectIndices[i];
- if (index == objectIndex) {
- Object *duplicate = obj->duplicate();
- assert(_scale > 0);
- Math::Vector3d position = _objectPositions[i];
+ obj->makeInitiallyVisible();
+ obj->makeVisible();
+ _objects.push_back(obj);
+}
- if (!GeometricObject::isPolygon(obj->getType()))
- position = 32 * position / _scale;
+void Group::assemble(int frame, int index) {
+ Object *obj = _objects[index];
+ Math::Vector3d position = _objectPositions[frame];
- duplicate->setOrigin(position);
- assert(!duplicate->isDestroyed());
- _objects[i] = duplicate;
- }
- }
- obj->makeInitiallyInvisible();
-}
+ if (!GeometricObject::isPolygon(obj->getType()))
+ position = 32 * position / _scale;
+ else
+ position = position / _scale;
+ obj->setOrigin(position);
+}
} // End of namespace Freescape
\ No newline at end of file
diff --git a/engines/freescape/objects/group.h b/engines/freescape/objects/group.h
index 41ca55d527f..09aad72adbd 100644
--- a/engines/freescape/objects/group.h
+++ b/engines/freescape/objects/group.h
@@ -29,7 +29,8 @@ namespace Freescape {
class Group : public Object {
public:
Group(uint16 objectID_, uint16 flags_, const Common::Array<byte> data_);
- void assemble(Object *obj);
+ void linkObject(Object *obj);
+ void assemble(int frame, int index);
Common::Array<Object *> _objects;
Common::Array<Math::Vector3d> _objectPositions;
Commit: 2bdef2ef4249e523ced5ec1b51b188939f1a79db
https://github.com/scummvm/scummvm/commit/2bdef2ef4249e523ced5ec1b51b188939f1a79db
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: added start animation opcode
Changed paths:
engines/freescape/language/8bitDetokeniser.cpp
diff --git a/engines/freescape/language/8bitDetokeniser.cpp b/engines/freescape/language/8bitDetokeniser.cpp
index e74d4182fef..2fc96f03c9c 100644
--- a/engines/freescape/language/8bitDetokeniser.cpp
+++ b/engines/freescape/language/8bitDetokeniser.cpp
@@ -50,7 +50,7 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
2, 1, 1, 2, 1, 1, 2, 1,
1, 2, 2, 1, 2, 0, 0, 0,
1, 1, 0, 1, 1, 1, 1, 1,
- 2, 2, 1, 1, 0, 0, 0, 0,
+ 2, 2, 1, 1, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 2, 2,
1};
@@ -115,7 +115,7 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
// check we have enough bytes left to read
if (opcode > 48) {
debugC(1, kFreescapeDebugParser, "%s", detokenisedStream.c_str());
- if (opcode != 0x3f && opcode != 0x3b)
+ if (opcode != 0x3f)
error("ERROR: failed to read opcode: %x", opcode);
break;
}
@@ -304,6 +304,11 @@ Common::String detokenise8bitCondition(Common::Array<uint8> &tokenisedCondition,
currentInstruction = FCLInstruction(Token::PRINT);
break;
+ case 37:
+ detokenisedStream += "STARTANIM (";
+ currentInstruction = FCLInstruction(Token::STARTANIM);
+ break;
+
case 12:
detokenisedStream += "SETBIT (";
currentInstruction = FCLInstruction(Token::SETBIT);
Commit: 1145730b6e44983e3980205dc87ef3b8bb0aa908
https://github.com/scummvm/scummvm/commit/1145730b6e44983e3980205dc87ef3b8bb0aa908
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: improved parsing of castle demo for amiga
Changed paths:
engines/freescape/games/castle.cpp
engines/freescape/games/palettes.cpp
engines/freescape/loaders/8bitBinaryLoader.cpp
engines/freescape/sound.cpp
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 4165ee42b2c..07c885f1abd 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -35,6 +35,7 @@ CastleEngine::CastleEngine(OSystem *syst, const ADGameDescription *gd) : Freesca
_playerWidth = 8;
_playerDepth = 8;
+ _option = nullptr;
}
CastleEngine::~CastleEngine() {
@@ -290,9 +291,7 @@ void CastleEngine::loadAssetsAmigaDemo() {
loadMessagesVariableSize(&file, 0x8bb2, 164);
load8bitBinary(&file, 0x162a6, 16);
- assert(0);
- //loadPalettes(&file, 0x0);
-
+ loadPalettes(&file, 0x151a6);
//file.close();
//file.open("driller");
//if (!file.isOpen())
diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index f66b90ed5af..ee93a325dd1 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -136,7 +136,7 @@ void FreescapeEngine::loadPalettes(Common::SeekableReadStream *file, int offset)
for (uint i = 0; i < _areaMap.size() + 2; i++) {
int label = readField(file, 8);
auto palette = new byte[16][3];
- debugC(1, kFreescapeDebugParser, "Loading palette for area: %d", label);
+ debugC(1, kFreescapeDebugParser, "Loading palette for area: %d at %lx", label, file->pos());
for (int c = 0; c < 16; c++) {
int v = file->readUint16BE();
r = (v & 0xf00) >> 8;
@@ -212,9 +212,6 @@ byte kDrillerCGAPaletteRedGreenData[4][3] = {
};
void FreescapeEngine::swapPalette(uint16 levelID) {
- if (!_border)
- return;
-
if (isAmiga() || isAtariST()) {
// The following palette was not available in the demo, so we select another one
if (isDemo() && levelID == 32)
@@ -226,6 +223,9 @@ void FreescapeEngine::swapPalette(uint16 levelID) {
_gfx->_paperColor = _areaMap[levelID]->_paperColor;
_gfx->_underFireBackgroundColor = _areaMap[levelID]->_underFireBackgroundColor;
+ if (!_border)
+ return;
+
byte *palette = (byte *)malloc(sizeof(byte) * 4 * 3);
for (int c = 0; c < 4; c++) {
byte r, g, b;
@@ -253,9 +253,14 @@ void FreescapeEngine::swapPalette(uint16 levelID) {
}
assert(entry->areaId == levelID);
+ if (!_border)
+ return;
_border->setPalette(_gfx->_palette, 0, 4);
processBorder();
} else if (isDOS() && _renderMode == Common::kRenderEGA) {
+ if (!_border)
+ return;
+
_border->setPalette(_gfx->_palette, 0, 4);
processBorder();
}
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index a6289e30f35..3e8574cad41 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -99,6 +99,13 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
error("Not enough bytes %d to read object %d with type %d", byteSizeOfObject, objectID, objectType);
}
+ if (objectType > ObjectType::kGroupType && isDemo()) {
+ // Castle DOS demo has an invalid object, which should not be parsed.
+ debugC(1, kFreescapeDebugParser, "WARNING: invalid object %d!", objectID);
+ readArray(file, byteSizeOfObject - 9);
+ return nullptr;
+ }
+
assert(byteSizeOfObject >= 9);
byteSizeOfObject = byteSizeOfObject - 9;
if (objectID == 255 && objectType == ObjectType::kEntranceType) {
@@ -114,7 +121,7 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
byteSizeOfObject++;
while(--byteSizeOfObject > 0)
- structureArray.push_back(file->readByte());
+ structureArray.push_back(readField(file, 8));
return new GlobalStructure(structureArray);
} else if (objectID == 254 && objectType == ObjectType::kEntranceType) {
debugC(1, kFreescapeDebugParser, "Found the area connections (objectID: 254 with size %d)", byteSizeOfObject + 6);
@@ -288,7 +295,7 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
byteSizeOfObject++;
while(--byteSizeOfObject > 0)
- groupDataArray.push_back(file->readByte());
+ groupDataArray.push_back(readField(file, 8));
return new Group(
objectID,
@@ -516,7 +523,7 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
error("WARNING: replacing object id %d", newObject->getObjectID());
(*objectsByID)[newObject->getObjectID()] = newObject;
}
- } else
+ } else if (!(isDemo() && isCastle()))
error("Failed to read an object!");
}
long int endLastObject = file->pos();
@@ -570,8 +577,13 @@ void FreescapeEngine::load8bitBinary(Common::SeekableReadStream *file, int offse
uint8 numberOfAreas = readField(file, 8);
debugC(1, kFreescapeDebugParser, "Number of areas: %d", numberOfAreas);
- if (isDOS() && isCastle()) // Castle Master for DOS has an invalid number of areas
- numberOfAreas = isDemo() ? 31 : 104;
+ // Castle Master seems to have invalid number of areas?
+ if (isCastle()) {
+ if (isDOS())
+ numberOfAreas = isDemo() ? 31 : 104;
+ else if (isAmiga())
+ numberOfAreas = isDemo() ? 86 : 104;
+ }
uint32 dbSize = readField(file, 16);
debugC(1, kFreescapeDebugParser, "Database ends at %x", dbSize);
diff --git a/engines/freescape/sound.cpp b/engines/freescape/sound.cpp
index f7be53a0b29..053d9668f72 100644
--- a/engines/freescape/sound.cpp
+++ b/engines/freescape/sound.cpp
@@ -239,6 +239,11 @@ void FreescapeEngine::playMusic(const Common::String filename) {
}
void FreescapeEngine::playSoundFx(int index, bool sync) {
+ if (_soundsFx.size() == 0) {
+ debugC(1, kFreescapeDebugMedia, "WARNING: Sounds are not loaded");
+ return;
+ }
+
int size = _soundsFx[index]->size;
int sampleRate = _soundsFx[index]->sampleRate;
byte *data = _soundsFx[index]->data;
Commit: c9bd9c62deebb0d62018ec3e24c0f53eb6e14858
https://github.com/scummvm/scummvm/commit/c9bd9c62deebb0d62018ec3e24c0f53eb6e14858
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: improved parsing of castle demo for amiga
Changed paths:
engines/freescape/games/castle.cpp
engines/freescape/loaders/8bitBinaryLoader.cpp
diff --git a/engines/freescape/games/castle.cpp b/engines/freescape/games/castle.cpp
index 07c885f1abd..d934042c997 100644
--- a/engines/freescape/games/castle.cpp
+++ b/engines/freescape/games/castle.cpp
@@ -292,21 +292,17 @@ void CastleEngine::loadAssetsAmigaDemo() {
loadMessagesVariableSize(&file, 0x8bb2, 164);
load8bitBinary(&file, 0x162a6, 16);
loadPalettes(&file, 0x151a6);
- //file.close();
- //file.open("driller");
- //if (!file.isOpen())
- // error("Failed to open 'driller' file");
-
- //loadFonts(&file, 0xa30);
- //loadMessagesFixedSize(&file, 0x3960, 14, 20);
- //loadGlobalObjects(&file, 0x3716, 8);
+ file.seek(0x2be96); // Area 255
+ _areaMap[255] = load8bitArea(&file, 16);
file.close();
- //file.open("soundfx");
- //if (!file.isOpen())
- // error("Failed to open 'soundfx' executable for Amiga");
- //loadSoundsFx(&file, 0, 25);
+
+ _areaMap[2]->_groundColor = 1;
+ for (auto &it : _areaMap)
+ it._value->addStructure(_areaMap[255]);
+
+ _areaMap[2]->addFloor();
}
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index 3e8574cad41..b6db29dbcec 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -491,7 +491,10 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
}
} else if (isCastle()) {
byte idx = readField(file, 8);
- name = _messagesList[idx + 41];
+ if (isAmiga())
+ name = _messagesList[idx + 51];
+ else
+ name = _messagesList[idx + 41];
extraColor[0] = readField(file, 8);
extraColor[1] = readField(file, 8);
extraColor[2] = readField(file, 8);
@@ -582,7 +585,7 @@ void FreescapeEngine::load8bitBinary(Common::SeekableReadStream *file, int offse
if (isDOS())
numberOfAreas = isDemo() ? 31 : 104;
else if (isAmiga())
- numberOfAreas = isDemo() ? 86 : 104;
+ numberOfAreas = isDemo() ? 87 : 104;
}
uint32 dbSize = readField(file, 16);
Commit: ababd0da8e34330d2c6ecd6d923d2a56eb684d1d
https://github.com/scummvm/scummvm/commit/ababd0da8e34330d2c6ecd6d923d2a56eb684d1d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: added code to decrypt dark for amiga/atari
Changed paths:
A engines/freescape/games/dark/amiga.cpp
engines/freescape/detection.cpp
engines/freescape/freescape.h
engines/freescape/module.mk
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index 01b3f1d2412..118996af34e 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -252,6 +252,19 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSUPPORTED | ADGF_DEMO,
GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
},
+ {
+ "darkside",
+ "",
+ {
+ {"0.DRK", 0, "9e51b8f93a9af886fb88ab92ed43cf01", 81544},
+ {"1.DRK", 0, "50bbaa2b19fc4072ad85efe93116e561", 280704},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformAmiga,
+ ADGF_UNSTABLE,
+ GUIO1(GUIO_NOMIDI)
+ },
{
"darkside",
"",
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 299cebcfbd9..d6816326828 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -531,6 +531,7 @@ public:
void loadAssetsDOSFullGame() override;
void loadAssetsDOSDemo() override;
+ void loadAssetsAmigaFullGame() override;
void loadAssetsZXDemo() override;
@@ -548,6 +549,7 @@ private:
void addECDs(Area *area);
void addECD(Area *area, const Math::Vector3d position, int index);
void addWalls(Area *area);
+ Common::SeekableReadStream *decryptFile(const Common::String filename);
};
class EclipseEngine : public FreescapeEngine {
diff --git a/engines/freescape/games/dark/amiga.cpp b/engines/freescape/games/dark/amiga.cpp
new file mode 100644
index 00000000000..fcc2b4c8f71
--- /dev/null
+++ b/engines/freescape/games/dark/amiga.cpp
@@ -0,0 +1,78 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include "common/file.h"
+#include "common/memstream.h"
+
+#include "freescape/freescape.h"
+#include "freescape/language/8bitDetokeniser.h"
+
+namespace Freescape {
+
+Common::SeekableReadStream *DarkEngine::decryptFile(const Common::String filename) {
+ Common::File file;
+ file.open(filename);
+ if (!file.isOpen())
+ error("Failed to open %s", filename.c_str());
+
+ int size = file.size();
+ byte *encryptedBuffer = (byte *)malloc(size);
+ file.read(encryptedBuffer, size);
+ file.close();
+
+ uint32 d7 = 0;
+ uint32 d6 = 0;
+ byte *a6 = encryptedBuffer;
+ byte *a5 = encryptedBuffer + size - 1;
+
+ while (a6 <= a5) {
+ uint64 d0 = (a6[0] << 24) | (a6[1] << 16) | (a6[2] << 8) | a6[3];
+ d0 = d0 + d6;
+ d0 = uint32(d0);
+ d0 = ((d0 << 3) & 0xFFFFFFFF) | ((d0 >> 29) & 0xFFFFFFFF);
+ d0 ^= 0x71049763;
+ d0 -= d7;
+ d0 = ((d0 << 16) & 0xFFFF0000) | ((d0 >> 16) & 0xFFFF);
+
+ a6[0] = byte((d0 >> 24) & 0xFF);
+ //debug("%c", a6[0]);
+ a6[1] = byte((d0 >> 16) & 0xFF);
+ //debug("%c", a6[1]);
+ a6[2] = byte((d0 >> 8) & 0xFF);
+ //debug("%c", a6[2]);
+ a6[3] = byte(d0 & 0xFF);
+ //debug("%c", a6[3]);
+
+ d6 += 5;
+ d6 = ((d6 >> 3) & 0xFFFFFFFF) | ((d6 << 29) & 0xFFFFFFFF);
+ d6 ^= 0x04000000;
+ d7 += 4;
+ a6 += 4;
+ }
+
+ return (new Common::MemoryReadStream(encryptedBuffer, size));
+}
+
+void DarkEngine::loadAssetsAmigaFullGame() {
+ Common::SeekableReadStream *stream = decryptFile("1.drk");
+ load8bitBinary(stream, 0x2e96a, 16);
+}
+
+} // End of namespace Freescape
\ No newline at end of file
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index 3db7785ab67..2cd78466e42 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -6,6 +6,7 @@ MODULE_OBJS := \
demo.o \
freescape.o \
games/castle.o \
+ games/dark/amiga.o \
games/dark/dark.o \
games/dark/dos.o \
games/dark/zx.o \
Commit: 8e675393dd639e25fc87f577778c4bee25e65fd4
https://github.com/scummvm/scummvm/commit/8e675393dd639e25fc87f577778c4bee25e65fd4
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: added code to decrypt some driller releases for atari
Changed paths:
engines/freescape/detection.cpp
engines/freescape/freescape.h
engines/freescape/games/driller/atari.cpp
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index 118996af34e..6577c2a919f 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -157,7 +157,20 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_NO_FLAGS,
GUIO4(GUIO_NOMIDI, GUIO_RENDEREGA, GUIO_RENDERCGA, GAMEOPTION_AUTOMATIC_DRILLING)
},
- {
+ { // Retail release
+ "driller",
+ "",
+ {
+ {"x.prg", 0, "d002983a8b652f25b18a09425db78c4c", 293159},
+ {"playseq.prg", 0, "535e9f6baf132831aa7fa066a06f242e", 973},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformAtariST,
+ GF_ATARI_RETAIL,
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
+ },
+ { // Budget release
"driller",
"",
{
@@ -167,7 +180,7 @@ static const ADGameDescription gameDescriptions[] = {
},
Common::EN_ANY,
Common::kPlatformAtariST,
- ADGF_NO_FLAGS,
+ GF_ATARI_BUDGET,
GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
},
{
@@ -340,7 +353,7 @@ static const ADGameDescription gameDescriptions[] = {
"spacestationoblivion",
"",
{
- {"x.prg", 0, "10c556ee637bf03bcc1a051277542102", 293264},
+ {"x.prg", 0, "bf546ee243c38f51d9beb25c203ccb93", 292624},
AD_LISTEND
},
Common::EN_ANY,
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index d6816326828..e011af256f7 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -427,6 +427,8 @@ enum DrillerReleaseFlags {
GF_CPC_RETAIL2 = (1 << 6),
GF_CPC_BUDGET = (1 << 7),
GF_CPC_VIRTUALWORLDS = (1 << 8),
+ GF_ATARI_RETAIL = (1 << 9),
+ GF_ATARI_BUDGET = (1 << 10),
};
class DrillerEngine : public FreescapeEngine {
@@ -509,6 +511,8 @@ private:
uint32 getPixel8bitTitleImage(int index);
void renderPixels8bitTitleImage(Graphics::ManagedSurface *surface, int &i, int &j, int pixels);
+
+ Common::SeekableReadStream *decryptFileAtari(const Common::String filename);
};
class DarkEngine : public FreescapeEngine {
diff --git a/engines/freescape/games/driller/atari.cpp b/engines/freescape/games/driller/atari.cpp
index 143920cb119..df588dd62b6 100644
--- a/engines/freescape/games/driller/atari.cpp
+++ b/engines/freescape/games/driller/atari.cpp
@@ -19,34 +19,83 @@
*
*/
#include "common/file.h"
+#include "common/memstream.h"
#include "freescape/freescape.h"
#include "freescape/language/8bitDetokeniser.h"
namespace Freescape {
-void DrillerEngine::loadAssetsAtariFullGame() {
+Common::SeekableReadStream *DrillerEngine::decryptFileAtari(const Common::String filename) {
Common::File file;
- file.open("x.prg");
-
+ file.open(filename);
if (!file.isOpen())
- error("Failed to open 'x.prg' executable for AtariST");
-
- _border = loadAndConvertNeoImage(&file, 0x1371a);
- byte *palette = (byte *)malloc(16 * 3);
- for (int i = 0; i < 16; i++) { // gray scale palette
- palette[i * 3 + 0] = i * (255 / 16);
- palette[i * 3 + 1] = i * (255 / 16);
- palette[i * 3 + 2] = i * (255 / 16);
+ error("Failed to open %s", filename.c_str());
+
+ int size = file.size();
+ byte *encryptedBuffer = (byte *)malloc(size);
+ file.read(encryptedBuffer, size);
+ file.close();
+
+ byte *a6 = encryptedBuffer + 0x118;
+ byte *a5 = encryptedBuffer + size - 4;
+ uint64 key = 0xb9f11bce;
+
+ while (a6 <= a5) {
+ uint64 d0 = (a6[0] << 24) | (a6[1] << 16) | (a6[2] << 8) | a6[3];
+ d0 += key;
+ d0 = uint32(d0);
+
+ a6[0] = byte((d0 >> 24) & 0xFF);
+ a6[1] = byte((d0 >> 16) & 0xFF);
+ a6[2] = byte((d0 >> 8) & 0xFF);
+ a6[3] = byte(d0 & 0xFF);
+
+ key += 0x51684624;
+ key = uint32(key);
+ a6 += 4;
+ }
+
+ return (new Common::MemoryReadStream(encryptedBuffer, size));
+}
+
+void DrillerEngine::loadAssetsAtariFullGame() {
+
+ if (_variant & GF_ATARI_RETAIL) {
+ Common::SeekableReadStream *stream = decryptFileAtari("x.prg");
+
+ _border = loadAndConvertNeoImage(stream, 0x14b96);
+ _title = loadAndConvertNeoImage(stream, 0x1c916);
+
+ loadFonts(stream, 0x8a92);
+ loadMessagesFixedSize(stream, 0xda22, 14, 20);
+ loadGlobalObjects(stream, 0xd116, 8);
+ load8bitBinary(stream, 0x2afb8, 16);
+ loadPalettes(stream, 0x2ab76);
+ //loadSoundsFx(&file, 0x30da6, 25);
+ } else if (_variant & GF_ATARI_BUDGET) {
+ Common::File file;
+ file.open("x.prg");
+
+ if (!file.isOpen())
+ error("Failed to open 'x.prg' executable for AtariST");
+
+ _border = loadAndConvertNeoImage(&file, 0x1371a);
+ byte *palette = (byte *)malloc(16 * 3);
+ for (int i = 0; i < 16; i++) { // gray scale palette
+ palette[i * 3 + 0] = i * (255 / 16);
+ palette[i * 3 + 1] = i * (255 / 16);
+ palette[i * 3 + 2] = i * (255 / 16);
+ }
+ _title = loadAndConvertNeoImage(&file, 0x10, palette);
+
+ loadFonts(&file, 0x8a32);
+ loadMessagesFixedSize(&file, 0xc5d8, 14, 20);
+ loadGlobalObjects(&file, 0xbccc, 8);
+ load8bitBinary(&file, 0x29b3c, 16);
+ loadPalettes(&file, 0x296fa);
+ loadSoundsFx(&file, 0x30da6, 25);
}
- _title = loadAndConvertNeoImage(&file, 0x10, palette);
-
- loadFonts(&file, 0x8a32);
- loadMessagesFixedSize(&file, 0xc5d8, 14, 20);
- loadGlobalObjects(&file, 0xbccc, 8);
- load8bitBinary(&file, 0x29b3c, 16);
- loadPalettes(&file, 0x296fa);
- loadSoundsFx(&file, 0x30da6, 25);
}
void DrillerEngine::loadAssetsAtariDemo() {
Commit: 82fd2ee5d44abdc5963b8c6deb9bd90217dc9f87
https://github.com/scummvm/scummvm/commit/82fd2ee5d44abdc5963b8c6deb9bd90217dc9f87
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: added better detection of driller releases for atari
Changed paths:
engines/freescape/detection.cpp
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index 6577c2a919f..6c70c1e1895 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -162,7 +162,6 @@ static const ADGameDescription gameDescriptions[] = {
"",
{
{"x.prg", 0, "d002983a8b652f25b18a09425db78c4c", 293159},
- {"playseq.prg", 0, "535e9f6baf132831aa7fa066a06f242e", 973},
AD_LISTEND
},
Common::EN_ANY,
@@ -175,7 +174,6 @@ static const ADGameDescription gameDescriptions[] = {
"",
{
{"x.prg", 0, "1a79e68e6c2c223c96de0ca2d65149ae", 293062},
- {"playseq.prg", 0, "535e9f6baf132831aa7fa066a06f242e", 973},
AD_LISTEND
},
Common::EN_ANY,
@@ -183,6 +181,19 @@ static const ADGameDescription gameDescriptions[] = {
GF_ATARI_BUDGET,
GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
},
+ { // Virtual Worlds release
+ "driller",
+ "This relese requieres unpacking, check the wiki for instructions:\nhttps://wiki.scummvm.org/index.php?title=Driller#AtariST_releases",
+ {
+ {"d.pak", 0, "607b44b9d31e0da5668b653e03d25efe", 706},
+ {"dril.all", 0, "65277222effa1eb4d73b234245001d75", 158158},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformAtariST,
+ ADGF_UNSUPPORTED,
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
+ },
{
"driller",
"",
@@ -361,6 +372,18 @@ static const ADGameDescription gameDescriptions[] = {
ADGF_UNSUPPORTED,
GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
},
+ {
+ "spacestationoblivion",
+ "",
+ {
+ {"x.prg", 0, "10c556ee637bf03bcc1a051277542102", 293264},
+ AD_LISTEND
+ },
+ Common::EN_ANY,
+ Common::kPlatformAtariST,
+ ADGF_UNSUPPORTED,
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
+ },
{
"castlemaster",
"Demo",
Commit: 40b73a35a785796f53490d5f4e7670a7bb874be3
https://github.com/scummvm/scummvm/commit/40b73a35a785796f53490d5f4e7670a7bb874be3
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: better detection of driller releases for atari
Changed paths:
engines/freescape/detection.cpp
engines/freescape/freescape.h
engines/freescape/games/driller/atari.cpp
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index 6c70c1e1895..49e3c5f1c29 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -376,12 +376,12 @@ static const ADGameDescription gameDescriptions[] = {
"spacestationoblivion",
"",
{
- {"x.prg", 0, "10c556ee637bf03bcc1a051277542102", 293264},
+ {"x.prg", 0, "7fc6ef316be4819d88d8031738571a50", 293264},
AD_LISTEND
},
Common::EN_ANY,
Common::kPlatformAtariST,
- ADGF_UNSUPPORTED,
+ GF_ATARI_BUDGET,
GUIO2(GUIO_NOMIDI, GAMEOPTION_AUTOMATIC_DRILLING)
},
{
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index e011af256f7..90bbdf1f1b3 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -96,6 +96,7 @@ public:
// Game selection
uint32 _variant;
Common::Language _language;
+ bool isSpaceStationOblivion() { return _targetName.hasPrefix("spacestationoblivion"); }
bool isDriller() { return _targetName.hasPrefix("driller") || _targetName.hasPrefix("spacestationoblivion"); }
bool isDark() { return _targetName.hasPrefix("darkside"); }
bool isEclipse() { return _targetName.hasPrefix("totaleclipse"); }
diff --git a/engines/freescape/games/driller/atari.cpp b/engines/freescape/games/driller/atari.cpp
index df588dd62b6..5cf36467991 100644
--- a/engines/freescape/games/driller/atari.cpp
+++ b/engines/freescape/games/driller/atari.cpp
@@ -80,21 +80,39 @@ void DrillerEngine::loadAssetsAtariFullGame() {
if (!file.isOpen())
error("Failed to open 'x.prg' executable for AtariST");
- _border = loadAndConvertNeoImage(&file, 0x1371a);
- byte *palette = (byte *)malloc(16 * 3);
- for (int i = 0; i < 16; i++) { // gray scale palette
- palette[i * 3 + 0] = i * (255 / 16);
- palette[i * 3 + 1] = i * (255 / 16);
- palette[i * 3 + 2] = i * (255 / 16);
+ if (isSpaceStationOblivion()) {
+ _border = loadAndConvertNeoImage(&file, 0x13544);
+ byte *palette = (byte *)malloc(16 * 3);
+ for (int i = 0; i < 16; i++) { // gray scale palette
+ palette[i * 3 + 0] = i * (255 / 16);
+ palette[i * 3 + 1] = i * (255 / 16);
+ palette[i * 3 + 2] = i * (255 / 16);
+ }
+ _title = loadAndConvertNeoImage(&file, 0x10, palette);
+
+ loadFonts(&file, 0x8a32 - 0x1d6);
+ loadMessagesFixedSize(&file, 0xc5d8 - 0x1da, 14, 20);
+ loadGlobalObjects(&file, 0xbccc - 0x1da, 8);
+ load8bitBinary(&file, 0x29b3c - 0x1d6, 16);
+ loadPalettes(&file, 0x296fa - 0x1d6);
+ loadSoundsFx(&file, 0x30da6 - 0x1d6, 25);
+ } else {
+ _border = loadAndConvertNeoImage(&file, 0x1371a);
+ byte *palette = (byte *)malloc(16 * 3);
+ for (int i = 0; i < 16; i++) { // gray scale palette
+ palette[i * 3 + 0] = i * (255 / 16);
+ palette[i * 3 + 1] = i * (255 / 16);
+ palette[i * 3 + 2] = i * (255 / 16);
+ }
+ _title = loadAndConvertNeoImage(&file, 0x10, palette);
+
+ loadFonts(&file, 0x8a32);
+ loadMessagesFixedSize(&file, 0xc5d8, 14, 20);
+ loadGlobalObjects(&file, 0xbccc, 8);
+ load8bitBinary(&file, 0x29b3c, 16);
+ loadPalettes(&file, 0x296fa);
+ loadSoundsFx(&file, 0x30da6, 25);
}
- _title = loadAndConvertNeoImage(&file, 0x10, palette);
-
- loadFonts(&file, 0x8a32);
- loadMessagesFixedSize(&file, 0xc5d8, 14, 20);
- loadGlobalObjects(&file, 0xbccc, 8);
- load8bitBinary(&file, 0x29b3c, 16);
- loadPalettes(&file, 0x296fa);
- loadSoundsFx(&file, 0x30da6, 25);
}
}
Commit: 7593592c455173b20f1d3c828f8dcc45428cf8f2
https://github.com/scummvm/scummvm/commit/7593592c455173b20f1d3c828f8dcc45428cf8f2
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: more precise timing of some fcl instructions
Changed paths:
engines/freescape/games/driller/driller.cpp
engines/freescape/language/instruction.cpp
engines/freescape/sound.cpp
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 3d4d2075e07..d66a3a71b25 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -433,6 +433,7 @@ void DrillerEngine::pressedKey(const int keycode) {
_gameStateVars[32]++;
} else
_drillStatusByArea[_currentArea->getAreaID()] = kDrillerRigOutOfPlace;
+ executeMovementConditions();
} else if (keycode == Common::KEYCODE_c) {
if (isDOS() && isDemo()) // No support for drilling here yet
return;
@@ -473,6 +474,7 @@ void DrillerEngine::pressedKey(const int keycode) {
uint32 scoreToRemove = uint32(maxScore * success) / 100;
assert(scoreToRemove <= uint32(_gameStateVars[k8bitVariableScore]));
_gameStateVars[k8bitVariableScore] -= scoreToRemove;
+ executeMovementConditions();
}
}
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index e040fe6492c..17ebb83f044 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -93,6 +93,7 @@ void FreescapeEngine::executeObjectConditions(GeometricObject *obj, bool shot, b
assert(obj != nullptr);
if (!obj->_conditionSource.empty()) {
_firstSound = true;
+ _syncSound = false;
_objExecutingCodeSize = collided ? obj->getSize() : Math::Vector3d();
if (collided)
debugC(1, kFreescapeDebugCode, "Executing with collision flag: %s", obj->_conditionSource.c_str());
@@ -250,7 +251,15 @@ void FreescapeEngine::executeRedraw(FCLInstruction &instruction) {
_gfx->flipBuffer();
g_system->updateScreen();
g_system->delayMillis(10);
- waitForSounds();
+
+ drawFrame();
+ _gfx->flipBuffer();
+ g_system->updateScreen();
+ g_system->delayMillis(isCPC() ? 100 : 10);
+
+ if (_syncSound) {
+ waitForSounds();
+ }
}
void FreescapeEngine::executeExecute(FCLInstruction &instruction) {
diff --git a/engines/freescape/sound.cpp b/engines/freescape/sound.cpp
index 053d9668f72..016be2cb3fc 100644
--- a/engines/freescape/sound.cpp
+++ b/engines/freescape/sound.cpp
@@ -38,7 +38,8 @@ void FreescapeEngine::playSound(int index, bool sync) {
_syncSound = sync;
return;
}
- waitForSounds();
+ if (_syncSound)
+ waitForSounds();
switch (index) {
case 1:
if (_usePrerecordedSounds) {
@@ -267,8 +268,13 @@ void FreescapeEngine::stopAllSounds() {
}
void FreescapeEngine::waitForSounds() {
- while (!_speaker->endOfStream())
- g_system->delayMillis(10);
+ if (_usePrerecordedSounds || isAmiga() || isAtariST())
+ while (_mixer->isSoundIDActive(-1))
+ g_system->delayMillis(10);
+ else {
+ while (!_speaker->endOfStream())
+ g_system->delayMillis(10);
+ }
}
bool FreescapeEngine::isPlayingSound() {
Commit: 7d3fc01cd167401d7f0dfd8ceaf00daacbd82f91
https://github.com/scummvm/scummvm/commit/7d3fc01cd167401d7f0dfd8ceaf00daacbd82f91
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: better code to transition between areas
Changed paths:
engines/freescape/movement.cpp
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index ed0564cb815..3202e203824 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -57,7 +57,9 @@ void FreescapeEngine::traverseEntrance(uint16 entranceID) {
}
_pitch = rotation.x();
- if (_objExecutingCodeSize.length() == 0 || ABS(_objExecutingCodeSize.x()) > ABS(_objExecutingCodeSize.z()))
+ if (rotation.y() > 0 && rotation.y() <= 45)
+ _yaw = rotation.y();
+ else if (rotation.y() <= 0 || (rotation.y() >= 180 && rotation.y() < 270))
_yaw = rotation.y() + 90;
else
_yaw = rotation.y() - 90;
Commit: 4486477a93cc751eaa7f025c428d383853217da9
https://github.com/scummvm/scummvm/commit/4486477a93cc751eaa7f025c428d383853217da9
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: correctly scale mouse position in opengl renderers
Changed paths:
engines/freescape/freescape.cpp
engines/freescape/gfx.h
engines/freescape/gfx_opengl.cpp
engines/freescape/gfx_opengl.h
engines/freescape/gfx_opengl_shaders.cpp
engines/freescape/gfx_opengl_shaders.h
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index f985adefcf8..73af6eb844b 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -468,22 +468,25 @@ void FreescapeEngine::processInput() {
if (_shootMode) {
{
bool shouldWarp = false;
- _crossairPosition = mousePos;
- if (mousePos.x < _viewArea.left) {
+ Common::Point resolution = _gfx->nativeResolution();
+ _crossairPosition.x = _screenW * mousePos.x / resolution.x;
+ _crossairPosition.y = _screenH * mousePos.y / resolution.y;
+
+ if (_crossairPosition.x < _viewArea.left) {
_crossairPosition.x = _viewArea.left + 1;
shouldWarp = true;
}
- if (mousePos.x > _viewArea.right) {
+ if (_crossairPosition.x > _viewArea.right) {
_crossairPosition.x = _viewArea.right - 1;
shouldWarp = true;
}
- if (mousePos.y < _viewArea.top) {
+ if (_crossairPosition.y < _viewArea.top) {
_crossairPosition.y = _viewArea.top + 1;
shouldWarp = true;
}
- if (mousePos.y > _viewArea.bottom) {
+ if (_crossairPosition.y > _viewArea.bottom) {
_crossairPosition.y = _viewArea.bottom - 1;
shouldWarp = true;
}
@@ -508,6 +511,9 @@ void FreescapeEngine::processInput() {
bool touchedScreenControls = false;
#if defined(__ANDROID__) || defined(IPHONE)
+ Common::Point resolution = _gfx->nativeResolution();
+ mousPos.x = _screenW * mousePos.x / resolution.x;
+ mousPos.y = _screenH * mousePos.y / resolution.y;
touchedScreenControls = onScreenControls(mousePos);
#endif
diff --git a/engines/freescape/gfx.h b/engines/freescape/gfx.h
index 7e38d4d7812..e269e45f486 100644
--- a/engines/freescape/gfx.h
+++ b/engines/freescape/gfx.h
@@ -96,6 +96,7 @@ public:
virtual void drawBackground(uint8 color);
Common::Rect viewport() const;
+ virtual Common::Point nativeResolution() { return Common::Point(_screenW, _screenH); }
// palette
void readFromPalette(uint8 index, uint8 &r, uint8 &g, uint8 &b);
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index 75c6408d35f..f00435c79fb 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -58,6 +58,12 @@ void OpenGLRenderer::freeTexture(Texture *texture) {
delete texture;
}
+Common::Point OpenGLRenderer::nativeResolution() {
+ GLint vect[4];
+ glGetIntegerv(GL_VIEWPORT, vect);
+ return Common::Point(vect[2], vect[3]);
+}
+
void OpenGLRenderer::init() {
computeScreenViewport();
diff --git a/engines/freescape/gfx_opengl.h b/engines/freescape/gfx_opengl.h
index 07536360988..1606bece443 100644
--- a/engines/freescape/gfx_opengl.h
+++ b/engines/freescape/gfx_opengl.h
@@ -84,6 +84,7 @@ public:
virtual void init() override;
virtual void clear(uint8 r, uint8 g, uint8 b) override;
virtual void setViewport(const Common::Rect &rect) override;
+ virtual Common::Point nativeResolution() override;
virtual void positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest) override;
virtual void updateProjectionMatrix(float fov, float nearClipPlane, float farClipPlane) override;
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index f46abb766fe..1055d4d2a96 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -73,6 +73,12 @@ void OpenGLShaderRenderer::freeTexture(Texture *texture) {
delete texture;
}
+Common::Point OpenGLShaderRenderer::nativeResolution() {
+ GLint vect[4];
+ glGetIntegerv(GL_VIEWPORT, vect);
+ return Common::Point(vect[2], vect[3]);
+}
+
void OpenGLShaderRenderer::init() {
computeScreenViewport();
diff --git a/engines/freescape/gfx_opengl_shaders.h b/engines/freescape/gfx_opengl_shaders.h
index ddcfe4a15b5..2ad2824b74e 100644
--- a/engines/freescape/gfx_opengl_shaders.h
+++ b/engines/freescape/gfx_opengl_shaders.h
@@ -67,6 +67,7 @@ public:
virtual void init() override;
virtual void clear(uint8 r, uint8 g, uint8 b) override;
virtual void setViewport(const Common::Rect &rect) override;
+ virtual Common::Point nativeResolution() override;
virtual void positionCamera(const Math::Vector3d &pos, const Math::Vector3d &interest) override;
virtual void updateProjectionMatrix(float fov, float nearClipPlane, float farClipPlane) override;
Commit: c36b35b28fad40f58c7ca03443fab026338bf7ca
https://github.com/scummvm/scummvm/commit/c36b35b28fad40f58c7ca03443fab026338bf7ca
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: fixes for driller demo
Changed paths:
engines/freescape/demo.cpp
engines/freescape/games/driller/driller.cpp
diff --git a/engines/freescape/demo.cpp b/engines/freescape/demo.cpp
index fc6cb1845eb..aa4227b1c59 100644
--- a/engines/freescape/demo.cpp
+++ b/engines/freescape/demo.cpp
@@ -40,12 +40,19 @@ void FreescapeEngine::generateDemoInput() {
if (_currentDemoInputCode >= 0x16 && _currentDemoInputCode <= 0x1a) {
event = decodeDOSMouseEvent(_currentDemoInputCode, _currentDemoInputRepetition);
+
+ Common::Point resolution = _gfx->nativeResolution();
+ event.mouse.x = resolution.x * event.mouse.x / _screenW;
+ event.mouse.y = resolution.y * event.mouse.y / _screenH ;
+
_demoEvents.push_back(event);
g_system->delayMillis(10);
_currentDemoInputRepetition = 0;
} else if (_currentDemoInputCode == 0x7f) {
// NOP
_currentDemoInputRepetition--;
+ } else if (_currentDemoInputCode == 0x0) {
+ _forceEndGame = true;
} else {
event = Common::Event();
event.type = Common::EVENT_KEYDOWN;
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index d66a3a71b25..4dfc8da6336 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -756,7 +756,8 @@ void DrillerEngine::initGameState() {
bool DrillerEngine::checkIfGameEnded() {
if (isDemo() && _demoMode)
- return (_demoData[_demoIndex + 1] == 0x5f);
+ if (_demoData[_demoIndex + 1] == 0x5f)
+ return true;
if (_countdown <= 0) {
insertTemporaryMessage(_messagesList[14], _countdown - 2);
@@ -800,12 +801,16 @@ bool DrillerEngine::checkIfGameEnded() {
if (_forceEndGame) {
_forceEndGame = false;
- insertTemporaryMessage(_messagesList[18], _countdown - 2);
- drawFrame();
- _gfx->flipBuffer();
- g_system->updateScreen();
- g_system->delayMillis(2000);
- gotoArea(127, 0);
+ if (isDemo())
+ return true;
+ else {
+ insertTemporaryMessage(_messagesList[18], _countdown - 2);
+ drawFrame();
+ _gfx->flipBuffer();
+ g_system->updateScreen();
+ g_system->delayMillis(2000);
+ gotoArea(127, 0);
+ }
}
if (_currentArea->getAreaID() == 127) {
Commit: 2d154c3b708cf90b7f7de68cf162e22e2f2617b1
https://github.com/scummvm/scummvm/commit/2d154c3b708cf90b7f7de68cf162e22e2f2617b1
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: Fix typo
Changed paths:
engines/freescape/freescape.cpp
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 73af6eb844b..ba2c019525c 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -512,8 +512,8 @@ void FreescapeEngine::processInput() {
#if defined(__ANDROID__) || defined(IPHONE)
Common::Point resolution = _gfx->nativeResolution();
- mousPos.x = _screenW * mousePos.x / resolution.x;
- mousPos.y = _screenH * mousePos.y / resolution.y;
+ mousePos.x = _screenW * mousePos.x / resolution.x;
+ mousePos.y = _screenH * mousePos.y / resolution.y;
touchedScreenControls = onScreenControls(mousePos);
#endif
Commit: fd50a5586bfc58161020f118eb2618eadefbe5c5
https://github.com/scummvm/scummvm/commit/fd50a5586bfc58161020f118eb2618eadefbe5c5
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: enable on screen controls in driller for all the scummvm platforms
Changed paths:
engines/freescape/freescape.cpp
diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index ba2c019525c..d030cf33de7 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -466,37 +466,9 @@ void FreescapeEngine::processInput() {
g_system->warpMouse(mousePos.x, mousePos.y);
if (_shootMode) {
- {
- bool shouldWarp = false;
- Common::Point resolution = _gfx->nativeResolution();
- _crossairPosition.x = _screenW * mousePos.x / resolution.x;
- _crossairPosition.y = _screenH * mousePos.y / resolution.y;
-
- if (_crossairPosition.x < _viewArea.left) {
- _crossairPosition.x = _viewArea.left + 1;
- shouldWarp = true;
- }
-
- if (_crossairPosition.x > _viewArea.right) {
- _crossairPosition.x = _viewArea.right - 1;
- shouldWarp = true;
- }
- if (_crossairPosition.y < _viewArea.top) {
- _crossairPosition.y = _viewArea.top + 1;
- shouldWarp = true;
- }
-
- if (_crossairPosition.y > _viewArea.bottom) {
- _crossairPosition.y = _viewArea.bottom - 1;
- shouldWarp = true;
- }
-
- if (shouldWarp) {
- g_system->warpMouse(_crossairPosition.x, _crossairPosition.y);
- g_system->getEventManager()->purgeMouseEvents();
- g_system->getEventManager()->purgeKeyboardEvents();
- }
- }
+ Common::Point resolution = _gfx->nativeResolution();
+ _crossairPosition.x = _screenW * mousePos.x / resolution.x;
+ _crossairPosition.y = _screenH * mousePos.y / resolution.y;
break;
}
@@ -510,12 +482,10 @@ void FreescapeEngine::processInput() {
{
bool touchedScreenControls = false;
- #if defined(__ANDROID__) || defined(IPHONE)
Common::Point resolution = _gfx->nativeResolution();
mousePos.x = _screenW * mousePos.x / resolution.x;
mousePos.y = _screenH * mousePos.y / resolution.y;
touchedScreenControls = onScreenControls(mousePos);
- #endif
if (!touchedScreenControls && _viewArea.contains(_crossairPosition))
shoot();
Commit: 60945611b9e507334c2a82cf537139f4cb539bb1
https://github.com/scummvm/scummvm/commit/60945611b9e507334c2a82cf537139f4cb539bb1
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
DRILLER: Remove newline from detection "extra" field
Changed paths:
engines/freescape/detection.cpp
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index 49e3c5f1c29..fe497d72499 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -183,7 +183,7 @@ static const ADGameDescription gameDescriptions[] = {
},
{ // Virtual Worlds release
"driller",
- "This relese requieres unpacking, check the wiki for instructions:\nhttps://wiki.scummvm.org/index.php?title=Driller#AtariST_releases",
+ "This relese requieres unpacking, check the wiki for instructions: https://wiki.scummvm.org/index.php?title=Driller#AtariST_releases",
{
{"d.pak", 0, "607b44b9d31e0da5668b653e03d25efe", 706},
{"dril.all", 0, "65277222effa1eb4d73b234245001d75", 158158},
Commit: 8ef39c1a0cedd3238a7bcfc859ee8a77994425a6
https://github.com/scummvm/scummvm/commit/8ef39c1a0cedd3238a7bcfc859ee8a77994425a6
Author: Donovan Watteau (contrib at dwatteau.fr)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: Fix typos in detection "extra" field
Changed paths:
engines/freescape/detection.cpp
diff --git a/engines/freescape/detection.cpp b/engines/freescape/detection.cpp
index fe497d72499..ad2a419ff0c 100644
--- a/engines/freescape/detection.cpp
+++ b/engines/freescape/detection.cpp
@@ -183,7 +183,7 @@ static const ADGameDescription gameDescriptions[] = {
},
{ // Virtual Worlds release
"driller",
- "This relese requieres unpacking, check the wiki for instructions: https://wiki.scummvm.org/index.php?title=Driller#AtariST_releases",
+ "This release requires unpacking, check the wiki for instructions: https://wiki.scummvm.org/index.php?title=Driller#AtariST_releases",
{
{"d.pak", 0, "607b44b9d31e0da5668b653e03d25efe", 706},
{"dril.all", 0, "65277222effa1eb4d73b234245001d75", 158158},
Commit: 60818c0e41d71a71fc5f2a218a78c373ceea1cb8
https://github.com/scummvm/scummvm/commit/60818c0e41d71a71fc5f2a218a78c373ceea1cb8
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: invert colors when rendering player shots in driller
Changed paths:
engines/freescape/gfx_opengl.cpp
engines/freescape/gfx_opengl_shaders.cpp
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index f00435c79fb..ff692cee8a4 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -192,7 +192,7 @@ void OpenGLRenderer::renderSensorShoot(byte color, const Math::Vector3d sensor,
}
void OpenGLRenderer::renderPlayerShoot(byte color, const Common::Point position, const Common::Rect viewArea) {
- uint8 a, r, g, b;
+ uint8 r, g, b;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
@@ -202,11 +202,8 @@ void OpenGLRenderer::renderPlayerShoot(byte color, const Common::Point position,
if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderZX) {
r = g = b = 255;
} else {
- uint32 pixel = 0x0;
- glReadPixels(g_system->getWidth() / 2, g_system->getHeight() / 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
- _texturePixelFormat.colorToARGB(pixel, a, r, g, b);
- color = indexFromColor(r, g, b);
- readFromPalette((color + 3) % (_renderMode == Common::kRenderCGA ? 4 : 16), r, g, b);
+ glEnable(GL_COLOR_LOGIC_OP);
+ glLogicOp(GL_INVERT);
}
glDisable(GL_DEPTH_TEST);
@@ -232,6 +229,7 @@ void OpenGLRenderer::renderPlayerShoot(byte color, const Common::Point position,
glDisableClientState(GL_VERTEX_ARRAY);
glLineWidth(1);
+ glDisable(GL_COLOR_LOGIC_OP);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index 1055d4d2a96..56c203b7955 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -183,7 +183,7 @@ float remap(float f, float s) {
}
void OpenGLShaderRenderer::renderPlayerShoot(byte color, const Common::Point position, const Common::Rect viewArea) {
- uint8 a, r, g, b;
+ uint8 r, g, b;
Math::Matrix4 identity;
identity(0, 0) = 1.0;
@@ -198,11 +198,8 @@ void OpenGLShaderRenderer::renderPlayerShoot(byte color, const Common::Point pos
if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderZX) {
r = g = b = 255;
} else {
- uint32 pixel = 0x0;
- glReadPixels(g_system->getWidth() / 2, g_system->getHeight() / 2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
- _texturePixelFormat.colorToARGB(pixel, a, r, g, b);
- color = indexFromColor(r, g, b);
- readFromPalette((color + 3) % (_renderMode == Common::kRenderCGA ? 4 : 16), r, g, b);
+ glEnable(GL_COLOR_LOGIC_OP);
+ glLogicOp(GL_INVERT);
}
glDisable(GL_DEPTH_TEST);
@@ -231,6 +228,7 @@ void OpenGLShaderRenderer::renderPlayerShoot(byte color, const Common::Point pos
glLineWidth(1);
+ glDisable(GL_COLOR_LOGIC_OP);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
}
Commit: 4c7152635257cc1859bd4d19fab7e6bc23325694
https://github.com/scummvm/scummvm/commit/4c7152635257cc1859bd4d19fab7e6bc23325694
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: added offsetOrigin function to avoid breaking setOrigin
Changed paths:
engines/freescape/objects/geometricobject.cpp
engines/freescape/objects/geometricobject.h
engines/freescape/objects/group.cpp
engines/freescape/objects/group.h
diff --git a/engines/freescape/objects/geometricobject.cpp b/engines/freescape/objects/geometricobject.cpp
index 422a541e804..08812353577 100644
--- a/engines/freescape/objects/geometricobject.cpp
+++ b/engines/freescape/objects/geometricobject.cpp
@@ -171,6 +171,11 @@ GeometricObject::GeometricObject(
}
void GeometricObject::setOrigin(Math::Vector3d origin_) {
+ _origin = origin_;
+ computeBoundingBox();
+}
+
+void GeometricObject::offsetOrigin(Math::Vector3d origin_) {
if (isPolygon(_type)) {
Math::Vector3d offset = origin_ - _origin;
offset = 32 * offset;
@@ -180,9 +185,7 @@ void GeometricObject::setOrigin(Math::Vector3d origin_) {
(*_ordinates)[i + 2] += uint16(offset.z());
}
}
-
- _origin = origin_;
- computeBoundingBox();
+ setOrigin(origin_);
}
void GeometricObject::scale(int factor) {
diff --git a/engines/freescape/objects/geometricobject.h b/engines/freescape/objects/geometricobject.h
index a7a0ed90f17..2c320241b88 100644
--- a/engines/freescape/objects/geometricobject.h
+++ b/engines/freescape/objects/geometricobject.h
@@ -49,6 +49,7 @@ public:
Common::String conditionSource = "");
virtual ~GeometricObject();
void setOrigin(Math::Vector3d origin) override;
+ void offsetOrigin(Math::Vector3d origin_);
Object *duplicate() override;
void scale(int factor) override;
diff --git a/engines/freescape/objects/group.cpp b/engines/freescape/objects/group.cpp
index a097259e301..7804a062bfa 100644
--- a/engines/freescape/objects/group.cpp
+++ b/engines/freescape/objects/group.cpp
@@ -30,12 +30,12 @@ Group::Group(uint16 objectID_, uint16 flags_, const Common::Array<byte> data_) {
_scale = 0;
int i;
- for (i = 0; i < 9; i++) {
+ for (i = 0; i < 5; i++) {
debugC(1, kFreescapeDebugParser, "group data[%d] = %d", i, data_[i]);
if (data_[i] > 0)
_objectIds.push_back(data_[i]);
}
- i = 9;
+ i = 5;
while (i < int(data_.size() - 4)) {
debugC(1, kFreescapeDebugParser, "group data[%d] = %d (index) ", i, data_[i]);
_objectIndices.push_back(data_[i]);
@@ -68,20 +68,21 @@ void Group::linkObject(Object *obj) {
if (objectIndex == -1)
return;
+ _origins.push_back(obj->getOrigin());
obj->makeInitiallyVisible();
obj->makeVisible();
_objects.push_back(obj);
}
void Group::assemble(int frame, int index) {
- Object *obj = _objects[index];
+ GeometricObject *gobj = (GeometricObject *)_objects[index];
Math::Vector3d position = _objectPositions[frame];
- if (!GeometricObject::isPolygon(obj->getType()))
+ if (!GeometricObject::isPolygon(gobj->getType()))
position = 32 * position / _scale;
else
position = position / _scale;
- obj->setOrigin(position);
+ gobj->offsetOrigin(position);
}
} // End of namespace Freescape
\ No newline at end of file
diff --git a/engines/freescape/objects/group.h b/engines/freescape/objects/group.h
index 09aad72adbd..04587dbc386 100644
--- a/engines/freescape/objects/group.h
+++ b/engines/freescape/objects/group.h
@@ -33,6 +33,7 @@ public:
void assemble(int frame, int index);
Common::Array<Object *> _objects;
+ Common::Array<Math::Vector3d> _origins;
Common::Array<Math::Vector3d> _objectPositions;
Common::Array<int16> _objectIndices;
Common::Array<int16> _objectIds;
Commit: 33e6c4a45685983b616ed32d5b491710da1f5183
https://github.com/scummvm/scummvm/commit/33e6c4a45685983b616ed32d5b491710da1f5183
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-07-03T22:18:13+02:00
Commit Message:
FREESCAPE: initialize r, g and b variables in renderPlayerShoot
Changed paths:
engines/freescape/gfx_opengl.cpp
engines/freescape/gfx_opengl_shaders.cpp
diff --git a/engines/freescape/gfx_opengl.cpp b/engines/freescape/gfx_opengl.cpp
index ff692cee8a4..2ec6dcfc289 100644
--- a/engines/freescape/gfx_opengl.cpp
+++ b/engines/freescape/gfx_opengl.cpp
@@ -202,6 +202,7 @@ void OpenGLRenderer::renderPlayerShoot(byte color, const Common::Point position,
if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderZX) {
r = g = b = 255;
} else {
+ r = g = b = 0;
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_INVERT);
}
diff --git a/engines/freescape/gfx_opengl_shaders.cpp b/engines/freescape/gfx_opengl_shaders.cpp
index 56c203b7955..7e75cdd9057 100644
--- a/engines/freescape/gfx_opengl_shaders.cpp
+++ b/engines/freescape/gfx_opengl_shaders.cpp
@@ -198,6 +198,7 @@ void OpenGLShaderRenderer::renderPlayerShoot(byte color, const Common::Point pos
if (_renderMode == Common::kRenderCGA || _renderMode == Common::kRenderZX) {
r = g = b = 255;
} else {
+ r = g = b = 0;
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_INVERT);
}
More information about the Scummvm-git-logs
mailing list