SCUMM: Add practice mode box for Mac Loom

Unlike the PC version, the practice mode box appears to be hard-coded in
the Mac version. The script that draws the box in the PC version just
sets variables in the Mac version. This implementation is based on
screenshots.

To keep things a bit saner, I've split out the Mac-specific drawing to
its own file.
This commit is contained in:
Torbjörn Andersson 2021-05-17 10:41:54 +02:00 committed by Eugene Sandulenko
parent 620d885eac
commit cdfe9b5b4c
7 changed files with 150 additions and 48 deletions

View file

@ -1616,6 +1616,10 @@ void CharsetRendererMac::printChar(int chr, bool ignoreCharsetMask) {
// figure out what the original does here. The "c" looks like // figure out what the original does here. The "c" looks like
// it's shadowed in the normal way, but everything else looks // it's shadowed in the normal way, but everything else looks
// kind-of-but-not-quite outlined instead. Weird. // kind-of-but-not-quite outlined instead. Weird.
//
// Even weirder, I've seen screenshots where there is no
// shadowing at all. I'll just keep it like this for now,
// because it makes the notes stand out a bit better.
if ((chr >= 16 && chr <= 23) || chr == 60 || chr == 95) if ((chr >= 16 && chr <= 23) || chr == 60 || chr == 95)
enableShadow = true; enableShadow = true;
@ -1681,6 +1685,10 @@ void CharsetRendererMac::printChar(int chr, bool ignoreCharsetMask) {
_lastTop = _top; _lastTop = _top;
} }
void CharsetRendererMac::drawChar(int chr, Graphics::Surface &s, int x, int y) {
_macFont.drawChar(&s, chr, x, y, _color);
}
void CharsetRendererMac::setColor(byte color) { void CharsetRendererMac::setColor(byte color) {
_color = color; _color = color;
_enableShadow = false; _enableShadow = false;

View file

@ -288,6 +288,7 @@ public:
int getFontHeight() override; int getFontHeight() override;
int getCharWidth(uint16 chr) override; int getCharWidth(uint16 chr) override;
void printChar(int chr, bool ignoreCharsetMask) override; void printChar(int chr, bool ignoreCharsetMask) override;
void drawChar(int chr, Graphics::Surface &s, int x, int y) override;
void setColor(byte color) override; void setColor(byte color) override;
}; };

View file

@ -785,54 +785,6 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
_system->copyRectToScreen(src, pitch, x, y, width, height); _system->copyRectToScreen(src, pitch, x, y, width, height);
} }
void ScummEngine::mac_drawStripToScreen(VirtScreen *vs, int top, int x, int y, int width, int height) {
const byte *pixels = vs->getPixels(x, top);
const byte *ts = (byte *)_textSurface.getBasePtr(x * 2, y * 2);
byte *mac = (byte *)_macScreen->getBasePtr(x * 2, y * 2);
int pixelsPitch = vs->pitch;
int tsPitch = _textSurface.pitch;
int macPitch = _macScreen->pitch;
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
if (ts[2 * w] == CHARSET_MASK_TRANSPARENCY)
mac[2 * w] = pixels[w];
if (ts[2 * w + 1] == CHARSET_MASK_TRANSPARENCY)
mac[2 * w + 1] = pixels[w];
if (ts[2 * w + tsPitch] == CHARSET_MASK_TRANSPARENCY)
mac[2 * w + macPitch] = pixels[w];
if (ts[2 * w + tsPitch + 1] == CHARSET_MASK_TRANSPARENCY)
mac[2 * w + macPitch + 1] = pixels[w];
}
pixels += pixelsPitch;
ts += tsPitch * 2;
mac += macPitch * 2;
}
_system->copyRectToScreen(_macScreen->getBasePtr(x * 2, y * 2), _macScreen->pitch, x * 2, y * 2, width * 2, height * 2);
}
void ScummEngine::mac_restoreCharsetBg() {
_nextLeft = _string[0].xpos;
_nextTop = _string[0].ypos + _screenTop;
if (_charset->_hasMask) {
_charset->_hasMask = false;
_charset->_str.left = -1;
_charset->_left = -1;
clearTextSurface();
VirtScreen *vs = &_virtscr[_charset->_textScreenID];
if (!vs->h)
return;
markRectAsDirty(vs->number, Common::Rect(vs->w, vs->h), USAGE_BIT_RESTORED);
}
}
// CGA // CGA
// indy3 loom maniac monkey1 zak // indy3 loom maniac monkey1 zak
// //

121
engines/scumm/gfx_mac.cpp Normal file
View file

@ -0,0 +1,121 @@
/* 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 2
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "common/system.h"
#include "scumm/charset.h"
#include "scumm/usage_bits.h"
namespace Scumm {
void ScummEngine::mac_drawStripToScreen(VirtScreen *vs, int top, int x, int y, int width, int height) {
const byte *pixels = vs->getPixels(x, top);
const byte *ts = (byte *)_textSurface.getBasePtr(x * 2, y * 2);
byte *mac = (byte *)_macScreen->getBasePtr(x * 2, y * 2);
int pixelsPitch = vs->pitch;
int tsPitch = _textSurface.pitch;
int macPitch = _macScreen->pitch;
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
if (ts[2 * w] == CHARSET_MASK_TRANSPARENCY)
mac[2 * w] = pixels[w];
if (ts[2 * w + 1] == CHARSET_MASK_TRANSPARENCY)
mac[2 * w + 1] = pixels[w];
if (ts[2 * w + tsPitch] == CHARSET_MASK_TRANSPARENCY)
mac[2 * w + macPitch] = pixels[w];
if (ts[2 * w + tsPitch + 1] == CHARSET_MASK_TRANSPARENCY)
mac[2 * w + macPitch + 1] = pixels[w];
}
pixels += pixelsPitch;
ts += tsPitch * 2;
mac += macPitch * 2;
}
_system->copyRectToScreen(_macScreen->getBasePtr(x * 2, y * 2), _macScreen->pitch, x * 2, y * 2, width * 2, height * 2);
}
void ScummEngine::mac_restoreCharsetBg() {
_nextLeft = _string[0].xpos;
_nextTop = _string[0].ypos + _screenTop;
if (_charset->_hasMask) {
_charset->_hasMask = false;
_charset->_str.left = -1;
_charset->_left = -1;
clearTextSurface();
VirtScreen *vs = &_virtscr[_charset->_textScreenID];
if (!vs->h)
return;
markRectAsDirty(vs->number, Common::Rect(vs->w, vs->h), USAGE_BIT_RESTORED);
}
}
void ScummEngine::mac_drawLoomPracticeMode() {
// In practice mode, the game shows the notes as they are being played.
// In the DOS version, this is drawn by script 27 but the Mac version
// just sets variables 50 and 54. I'm not sure what the difference
// between the two is.
int x = 216;
int y = 377;
int width = 62;
int height = 22;
int var = 50;
byte *ptr = (byte *)_macScreen->getBasePtr(x, y);
int pitch = _macScreen->pitch;
_macScreen->fillRect(Common::Rect(x, y, x + width, y + height), 0);
if (VAR(var)) {
for (int w = 1; w < width - 1; w++) {
ptr[w] = 7;
ptr[w + pitch * (height - 1)] = 7;
}
for (int h = 1; h < height - 1; h++) {
ptr[h * pitch] = 7;
ptr[h * pitch + width - 1] = 7;
}
// Draw the notes
int colors[] = { 4, 12, 14, 10, 11, 3, 9, 15 };
for (int i = 0; i < 4; i++) {
int note = (VAR(var) >> (4 * i)) & 0x0F;
if (note >= 2 && note <= 9) {
_charset->setColor(colors[note - 2]);
_charset->drawChar(14 + note, *_macScreen, i * 13 + x + 8, y + 4);
}
}
}
_system->copyRectToScreen(ptr, pitch, x, y, width, height);
}
} // End of namespace Scumm

View file

@ -16,6 +16,7 @@ MODULE_OBJS := \
dialogs.o \ dialogs.o \
file.o \ file.o \
file_nes.o \ file_nes.o \
gfx_mac.o \
gfx_towns.o \ gfx_towns.o \
gfx.o \ gfx.o \
he/resource_he.o \ he/resource_he.o \

View file

@ -651,6 +651,23 @@ void ScummEngine::writeVar(uint var, int value) {
_scummVars[var] = value; _scummVars[var] = value;
// Unlike the PC version, the Macintosh version of Loom appears
// to hard-code the drawing of the practice mode box. This is
// handled by script 27 in both versions, but wherease the PC
// version draws the notes, the the Mac version this just sets
// variables 50 and 54.
//
// In this script, the variables are set to the same value but
// it appears that only variable 50 is cleared when the box is
// supposed to disappear. I don't know what the purpose of
// variable 54 is.
if (_game.id == GID_LOOM && _game.platform == Common::kPlatformMacintosh) {
if (VAR(128) == 0 && var == 50) {
mac_drawLoomPracticeMode();
}
}
if ((_varwatch == (int)var || _varwatch == 0) && _currentScript < NUM_SCRIPT_SLOT) { if ((_varwatch == (int)var || _varwatch == 0) && _currentScript < NUM_SCRIPT_SLOT) {
if (vm.slot[_currentScript].number < 100) if (vm.slot[_currentScript].number < 100)
debug(1, "vars[%d] = %d (via script-%d)", var, value, vm.slot[_currentScript].number); debug(1, "vars[%d] = %d (via script-%d)", var, value, vm.slot[_currentScript].number);

View file

@ -955,6 +955,8 @@ protected:
void drawStripToScreen(VirtScreen *vs, int x, int width, int top, int bottom); void drawStripToScreen(VirtScreen *vs, int x, int width, int top, int bottom);
void mac_drawStripToScreen(VirtScreen *vs, int top, int x, int y, int width, int height); void mac_drawStripToScreen(VirtScreen *vs, int top, int x, int y, int width, int height);
void mac_restoreCharsetBg(); void mac_restoreCharsetBg();
void mac_drawLoomPracticeMode();
void ditherCGA(byte *dst, int dstPitch, int x, int y, int width, int height) const; void ditherCGA(byte *dst, int dstPitch, int x, int y, int width, int height) const;
public: public: