SCUMM/FM-TOWNS: disable new graphics code in DS port

svn-id: r53033
This commit is contained in:
Florian Kagerer 2010-10-05 19:04:52 +00:00
parent b749b28c09
commit 5af782c5d2
18 changed files with 519 additions and 333 deletions

View file

@ -2159,9 +2159,11 @@ void ScummEngine::stopTalk() {
((ScummEngine_v7 *)this)->clearSubtitleQueue();
#endif
} else {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns)
towns_restoreCharsetBg();
else
#endif
restoreCharsetBg();
}
}

View file

@ -52,6 +52,9 @@ void ScummEngine::loadCJKFont() {
_newLineCharacter = 0;
if (_game.version <= 5 && _game.platform == Common::kPlatformFMTowns && _language == Common::JA_JPN) { // FM-TOWNS v3 / v5 Kanji
#ifdef DISABLE_TOWNS_DUAL_LAYER_MODE
error("FM-Towns Kanji font drawing requires dual graphics layer support which is disabled in this build");
#endif
int numChar = 256 * 32;
_2byteWidth = 16;
_2byteHeight = 16;
@ -655,11 +658,13 @@ void CharsetRendererV3::setColor(byte color) {
} else
useShadow = false;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_vm->_game.platform == Common::kPlatformFMTowns) {
_color = (_color & 0x0f) | ((_color & 0x0f) << 4);
if (_color == 0)
_color = 0x88;
}
#endif
enableShadow(useShadow);
@ -678,7 +683,12 @@ void CharsetRendererPCE::setColor(byte color) {
void CharsetRendererCommon::enableShadow(bool enable) {
if (enable) {
if (_vm->_game.platform == Common::kPlatformFMTowns) {
_shadowColor = _vm->_game.version == 5 ? _vm->_townsCharsetColorMap[0] : 0x88;
_shadowColor =
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
_vm->_game.version == 5 ? _vm->_townsCharsetColorMap[0] : 0x88;
#else
8;
#endif
_shadowMode = kFMTOWNSShadowMode;
} else {
_shadowColor = 0;
@ -750,7 +760,11 @@ void CharsetRendererV3::printChar(int chr, bool ignoreCharsetMask) {
_textScreenID = vs->number;
}
if ((_vm->_game.platform != Common::kPlatformFMTowns || (_vm->_game.id == GID_LOOM && !is2byte)) && (ignoreCharsetMask || !vs->hasTwoBuffers)) {
if (
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
(_vm->_game.platform != Common::kPlatformFMTowns || (_vm->_game.id == GID_LOOM && !is2byte)) &&
#endif
(ignoreCharsetMask || !vs->hasTwoBuffers)) {
dst = vs->getPixels(_left, drawTop);
drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight, vs->bytesPerPixel);
} else {
@ -807,6 +821,7 @@ void CharsetRenderer::translateColor() {
}
}
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
void CharsetRenderer::processTownsCharsetColors(uint8 bytesPerPixel) {
if (_vm->_game.platform == Common::kPlatformFMTowns) {
for (int i = 0; i < (1 << bytesPerPixel); i++) {
@ -827,6 +842,7 @@ void CharsetRenderer::processTownsCharsetColors(uint8 bytesPerPixel) {
}
}
}
#endif
void CharsetRenderer::saveLoadWithSerializer(Serializer *ser) {
static const SaveLoadEntry charsetRendererEntries[] = {
@ -863,7 +879,9 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
_vm->_charsetColorMap[1] = _color;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
processTownsCharsetColors(_bytesPerPixel);
#endif
if (is2byte) {
enableShadow(true);
@ -936,7 +954,11 @@ void CharsetRendererClassic::printChar(int chr, bool ignoreCharsetMask) {
// This check for kPlatformFMTowns and kMainVirtScreen is at least required for the chat with
// the navigator's head in front of the ghost ship in Monkey Island 1
if (!ignoreCharsetMask || (_vm->_game.platform == Common::kPlatformFMTowns && vs->number == kMainVirtScreen)) {
if (!ignoreCharsetMask
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|| (_vm->_game.platform == Common::kPlatformFMTowns && vs->number == kMainVirtScreen)
#endif
) {
_hasMask = true;
_textScreenID = vs->number;
}
@ -992,7 +1014,11 @@ void CharsetRendererClassic::printCharIntern(bool is2byte, const byte *charPtr,
} else {
Graphics::Surface dstSurface;
Graphics::Surface backSurface;
if (_vm->_game.platform != Common::kPlatformFMTowns && (ignoreCharsetMask || !vs->hasTwoBuffers) && !(_vm->_useCJKMode && _vm->_textSurfaceMultiplier == 2)) {
if (
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
_vm->_game.platform != Common::kPlatformFMTowns &&
#endif
(ignoreCharsetMask || !vs->hasTwoBuffers) && !(_vm->_useCJKMode && _vm->_textSurfaceMultiplier == 2)) {
dstSurface = *vs;
dstPtr = vs->getPixels(_left, drawTop);
} else {
@ -1095,7 +1121,11 @@ void CharsetRendererClassic::drawBitsN(const Graphics::Surface &s, byte *dst, co
assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8);
bits = *src++;
numbits = 8;
byte *cmap = (_vm->_game.platform == Common::kPlatformFMTowns) ? _vm->_townsCharsetColorMap : _vm->_charsetColorMap;
byte *cmap =
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
(_vm->_game.platform == Common::kPlatformFMTowns) ? _vm->_townsCharsetColorMap :
#endif
_vm->_charsetColorMap;
for (y = 0; y < height && y + drawTop < s.h; y++) {
for (x = 0; x < width; x++) {
@ -1119,7 +1149,11 @@ void CharsetRendererClassic::drawBitsN(const Graphics::Surface &s, byte *dst, co
void CharsetRendererCommon::drawBits1(const Graphics::Surface &s, byte *dst, const byte *src, int drawTop, int width, int height, uint8 bitDepth) {
int y, x;
byte bits = 0;
uint8 col = (_vm->_game.platform == Common::kPlatformFMTowns && _vm->_game.version == 5) ? _vm->_townsCharsetColorMap[1] : _color;
uint8 col =
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
(_vm->_game.platform == Common::kPlatformFMTowns && _vm->_game.version == 5) ? _vm->_townsCharsetColorMap[1] :
#endif
_color;
for (y = 0; y < height && y + drawTop < s.h; y++) {
for (x = 0; x < width; x++) {

View file

@ -79,7 +79,10 @@ public:
int getStringWidth(int a, const byte *str);
void addLinebreaks(int a, byte *str, int pos, int maxwidth);
void translateColor();
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
void processTownsCharsetColors(uint8 bytesPerPixel);
#endif
virtual void setCurID(int32 id) = 0;
int getCurID() { return _curId; }

View file

@ -559,9 +559,11 @@ void ScummEngine_v5::setBuiltinCursor(int idx) {
byte r, g, b;
colorPCEToRGB(default_pce_cursor_colors[idx], &r, &g, &b);
color = get16BitColor(r, g, b);
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
} else if (_game.platform == Common::kPlatformFMTowns) {
byte *palEntry = &_textPalette[default_cursor_colors[idx] * 3];
color = get16BitColor(palEntry[0], palEntry[1], palEntry[2]);
#endif
} else {
color = _16BitPalette[default_cursor_colors[idx]];
}

View file

@ -322,6 +322,7 @@ void ScummEngine::initScreens(int b, int h) {
_res->nukeResource(rtBuffer, i + 5);
}
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_townsScreen) {
if (!_townsClearLayerFlag && (h - b != _virtscr[kMainVirtScreen].h))
_townsScreen->clearLayer(0);
@ -331,6 +332,7 @@ void ScummEngine::initScreens(int b, int h) {
_townsScreen->clearLayer(1);
}
}
#endif
if (!getResourceAddress(rtBuffer, 4)) {
// Since the size of screen 3 is fixed, there is no need to reallocate
@ -643,10 +645,13 @@ void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, i
#ifdef USE_ARM_GFX_ASM
asmDrawStripToScreen(height, width, text, src, _compositeBuf, vs->pitch, width, _textSurface.pitch);
#else
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns) {
towns_drawStripToScreen(vs, x, y, x, top, width, height);
return;
} else if (_bytesPerPixelOutput == 2) {
} else
#endif
if (_bytesPerPixelOutput == 2) {
const byte *srcPtr = (const byte *)src;
const byte *textPtr = (byte *)_textSurface.getBasePtr(x * m, y * m);
byte *dstPtr = _compositeBuf;
@ -1009,8 +1014,10 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) {
if (rect.left > vs->w)
return;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns && _game.id == GID_MONKEY && vs->number == kVerbVirtScreen && rect.bottom <= 154)
rect.right = 320;
#endif
// Convert 'rect' to local (virtual screen) coordinates
rect.top -= vs->topline;
@ -1031,20 +1038,25 @@ void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) {
if (vs->hasTwoBuffers && _currentRoom != 0 && isLightOn()) {
blit(screenBuf, vs->pitch, vs->getBackPixels(rect.left, rect.top), vs->pitch, width, height, vs->bytesPerPixel);
if (vs->number == kMainVirtScreen && _charset->_hasMask) {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns) {
byte *mask = (byte *)_textSurface.getBasePtr(rect.left * _textSurfaceMultiplier, (rect.top + vs->topline) * _textSurfaceMultiplier);
fill(mask, _textSurface.pitch, 0, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel);
} else {
} else
#endif
{
byte *mask = (byte *)_textSurface.getBasePtr(rect.left, rect.top - _screenTop);
fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel);
}
}
} else {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns) {
backColor |= (backColor << 4);
byte *mask = (byte *)_textSurface.getBasePtr(rect.left * _textSurfaceMultiplier, (rect.top + vs->topline) * _textSurfaceMultiplier);
fill(mask, _textSurface.pitch, backColor, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.bytesPerPixel);
}
#endif
if (_game.features & GF_16BIT_COLOR)
fill(screenBuf, vs->pitch, _16BitPalette[backColor], width, height, vs->bytesPerPixel);
@ -1097,10 +1109,16 @@ void ScummEngine::clearCharsetMask() {
}
void ScummEngine::clearTextSurface() {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_townsScreen)
_townsScreen->fillLayerRect(1, 0, 0, _textSurface.w, _textSurface.h, 0);
#endif
fill((byte*)_textSurface.pixels, _textSurface.pitch, _game.platform == Common::kPlatformFMTowns ? 0 : CHARSET_MASK_TRANSPARENCY, _textSurface.w, _textSurface.h, _textSurface.bytesPerPixel);
fill((byte*)_textSurface.pixels, _textSurface.pitch,
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
_game.platform == Common::kPlatformFMTowns ? 0 :
#endif
CHARSET_MASK_TRANSPARENCY, _textSurface.w, _textSurface.h, _textSurface.bytesPerPixel);
}
byte *ScummEngine::getMaskBuffer(int x, int y, int z) {
@ -1258,13 +1276,20 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {
// is definitely not capable of passing a parameter of -1 (color range is 0 - 255).
// Just to make sure I don't break anything I restrict the code change to FM-Towns
// version 5 games where this change is necessary to fix certain long standing bugs.
if (color == -1 || (color >= 254 && _game.platform == Common::kPlatformFMTowns && (_game.id == GID_MONKEY2 || _game.id == GID_INDY4))) {
if (color == -1
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|| (color >= 254 && _game.platform == Common::kPlatformFMTowns && (_game.id == GID_MONKEY2 || _game.id == GID_INDY4))
#endif
) {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns) {
if (color == 254) {
color = color;
towns_setupPalCycleField(x, y, x2, y2);
}
} else {
} else
#endif
{
if (vs->number != kMainVirtScreen)
error("can only copy bg to main window");
@ -1306,6 +1331,7 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {
if (_game.features & GF_16BIT_COLOR) {
fill(backbuff, vs->pitch, _16BitPalette[color], width, height, vs->bytesPerPixel);
} else {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns) {
color = ((color & 0x0f) << 4) | (color & 0x0f);
byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop + vs->topline) * _textSurfaceMultiplier);
@ -1314,6 +1340,7 @@ void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {
if (_game.id == GID_MONKEY2 || _game.id == GID_INDY4 || ((_game.id == GID_INDY3 || _game.id == GID_ZAK) && vs->number != kTextVirtScreen) || (_game.id == GID_LOOM && vs->number == kMainVirtScreen))
return;
}
#endif
fill(backbuff, vs->pitch, color, width, height, vs->bytesPerPixel);
}
@ -1723,10 +1750,12 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const
warning("Gdi::drawBitmap, strip drawn to %d below window bottom %d", y + height, vs->h);
}
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_vm->_townsPaletteFlags & 2) {
int cx = (x - _vm->_screenStartStrip) << 3;
_vm->_textSurface.fillRect(Common::Rect(cx * _vm->_textSurfaceMultiplier, y * _vm->_textSurfaceMultiplier, (cx + width - 1) * _vm->_textSurfaceMultiplier, (y + height - 1) * _vm->_textSurfaceMultiplier), 0);
}
#endif
_vertStripNextInc = height * vs->pitch - 1 * vs->bytesPerPixel;
@ -3678,8 +3707,10 @@ void ScummEngine::fadeOut(int effect) {
if (_game.version < 7)
camera._last.x = camera._cur.x;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.version == 3 && _game.platform == Common::kPlatformFMTowns)
_textSurface.fillRect(Common::Rect(0, vs->topline * _textSurfaceMultiplier, _textSurface.pitch, (vs->topline + vs->h) * _textSurfaceMultiplier), 0);
#endif
// TheDig can disable fadeIn(), and may call fadeOut() several times
// successively. Disabling the _screenEffectFlag check forces the screen
@ -3883,9 +3914,11 @@ void ScummEngine::dissolveEffect(int width, int height) {
x = offsets[i] % vs->pitch;
y = offsets[i] / vs->pitch;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns)
towns_drawStripToScreen(vs, x, y + vs->topline, x, y, width, height);
else
#endif
_system->copyRectToScreen(vs->getPixels(x, y), vs->pitch, x, y + vs->topline, width, height);
@ -3926,10 +3959,12 @@ void ScummEngine::scrollEffect(int dir) {
y = 1 + step;
while (y < vs->h) {
moveScreen(0, -step, vs->h);
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_townsScreen) {
towns_drawStripToScreen(vs, 0, vs->topline + vs->h - step, 0, y - step, vs->w, step);
} else {
} else
#endif
{
src = vs->getPixels(0, y - step);
_system->copyRectToScreen(src,
vsPitch,
@ -3947,10 +3982,12 @@ void ScummEngine::scrollEffect(int dir) {
y = 1 + step;
while (y < vs->h) {
moveScreen(0, step, vs->h);
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_townsScreen) {
towns_drawStripToScreen(vs, 0, vs->topline, 0, vs->h - y, vs->w, step);
} else {
} else
#endif
{
src = vs->getPixels(0, vs->h - y);
_system->copyRectToScreen(src,
vsPitch,
@ -3969,9 +4006,12 @@ void ScummEngine::scrollEffect(int dir) {
while (x < vs->w) {
moveScreen(-step, 0, vs->h);
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_townsScreen) {
towns_drawStripToScreen(vs, vs->w - step, vs->topline, x - step, 0, step, vs->h);
} else {
} else
#endif
{
src = vs->getPixels(x - step, 0);
_system->copyRectToScreen(src,
vsPitch,
@ -3990,9 +4030,12 @@ void ScummEngine::scrollEffect(int dir) {
while (x < vs->w) {
moveScreen(step, 0, vs->h);
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_townsScreen) {
towns_drawStripToScreen(vs, 0, vs->topline, vs->w - x, 0, step, vs->h);
} else {
} else
#endif
{
src = vs->getPixels(vs->w - x, 0);
_system->copyRectToScreen(src,
vsPitch,

View file

@ -424,9 +424,9 @@ public:
};
#endif
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
// Helper class for FM-Towns output (required for specific hardware effects like
// switching graphics layers on and off).
class TownsScreen {
public:
TownsScreen(OSystem *system, int width, int height, int bpp);
@ -482,6 +482,7 @@ private:
Common::List<Common::Rect> _dirtyRects;
OSystem *_system;
};
#endif // DISABLE_TOWNS_DUAL_LAYER_MODE
} // End of namespace Scumm

View file

@ -29,6 +29,8 @@
#include "scumm/util.h"
#include "scumm/resource.h"
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
namespace Scumm {
void ScummEngine::towns_drawStripToScreen(VirtScreen *vs, int dstX, int dstY, int srcX, int srcY, int width, int height) {
@ -516,3 +518,5 @@ uint16 TownsScreen::calc16BitColor(const uint8 *palEntry) {
#undef FULL_REDRAW
} // End of namespace Scumm
#endif // DISABLE_TOWNS_DUAL_LAYER_MODE

View file

@ -141,6 +141,7 @@ void ScummEngine::resetPalette() {
};
#ifdef USE_RGB_COLOR
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
static const byte tableTownsV3Palette[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x00, 0xA0, 0xA0,
0xA0, 0x00, 0x00, 0xA0, 0x00, 0xA0, 0xA0, 0x60, 0x00, 0xA0, 0xA0, 0xA0,
@ -154,6 +155,7 @@ void ScummEngine::resetPalette() {
0x57, 0x3F, 0x57, 0x57, 0x57, 0xFF, 0x57, 0xFF, 0x57, 0x57, 0xFF, 0xFF,
0xFF, 0x57, 0x57, 0xD6, 0x94, 0x40, 0xFF, 0xFF, 0x57, 0xFF, 0xFF, 0xFF
};
#endif
#endif
if (_game.version <= 1) {
@ -215,6 +217,7 @@ void ScummEngine::resetPalette() {
// else we initialise and then lock down the first 16 colors.
if (_renderMode != Common::kRenderEGA)
setPaletteFromTable(tableAmigaMIPalette, sizeof(tableAmigaMIPalette) / 3);
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
} else if (_game.platform == Common::kPlatformFMTowns) {
if (_game.id == GID_INDY4 || _game.id == GID_MONKEY2)
_townsClearLayerFlag = 0;
@ -226,6 +229,7 @@ void ScummEngine::resetPalette() {
#endif
_townsScreen->toggleLayers(_townsActiveLayerFlags);
#endif // DISABLE_TOWNS_DUAL_LAYER_MODE
}
setDirtyColors(0, 255);
}
@ -493,8 +497,10 @@ void ScummEngine::cyclePalette() {
int valueToAdd;
int i, j;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns && (!_townsPaletteFlags & 1))
return;
#endif
valueToAdd = VAR(VAR_TIMER);
if (valueToAdd < VAR(VAR_TIMER_NEXT))
@ -537,8 +543,10 @@ void ScummEngine::moveMemInPalRes(int start, int end, byte direction) {
}
void ScummEngine::palManipulateInit(int resID, int start, int end, int time) {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns && (!_townsPaletteFlags & 1))
return;
#endif
byte *string1 = getStringAddress(resID);
byte *string2 = getStringAddress(resID + 1);
@ -1008,8 +1016,10 @@ void ScummEngine::setCurrentPalette(int palindex) {
if (_game.id == GID_LOOM && _game.platform == Common::kPlatformPCEngine) {
setPCEPaletteFromPtr(pals);
#ifdef USE_RGB_COLOR
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
} else if (_game.platform == Common::kPlatformFMTowns) {
towns_setPaletteFromPtr(pals);
#endif
#endif
} else {
setPaletteFromPtr(pals);
@ -1111,6 +1121,7 @@ void ScummEngine::updatePalette() {
_palDirtyMin = 256;
#ifdef USE_RGB_COLOR
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns) {
p = palette_colors;
for (i = first; i < first + num; ++i) {
@ -1119,6 +1130,7 @@ void ScummEngine::updatePalette() {
}
return;
}
#endif
#endif
_system->setPalette(palette_colors, first, num);

View file

@ -29,205 +29,15 @@
namespace Scumm {
Player_Towns::Player_Towns(ScummEngine *vm, Audio::Mixer *mixer) : _vm(vm) {
_cdaCurrentSound = _eupCurrentSound = _cdaNumLoops = 0;
_cdaForceRestart = 0;
Player_Towns::Player_Towns(ScummEngine *vm) : _vm(vm) {
memset(_pcmCurrentSound, 0, sizeof(_pcmCurrentSound));
_cdaVolLeft = _cdaVolRight = 0;
_eupVolLeft = _eupVolRight = 0;
memset(&_ovrCur, 0, sizeof(SoundOvrParameters));
_soundOverride = 0;
if (_vm->_game.version == 3) {
_soundOverride = new SoundOvrParameters[200];
memset(_soundOverride, 0, 200 * sizeof(SoundOvrParameters));
}
_eupLooping = false;
_unkFlags = 0x33;
_driver = new TownsEuphonyDriver(mixer);
}
Player_Towns::~Player_Towns() {
delete[] _soundOverride;
delete _driver;
}
bool Player_Towns::init() {
if (!_driver)
return false;
if (!_driver->init())
return false;
_driver->reserveSoundEffectChannels(8);
// Treat all 6 fm channels and all 8 pcm channels as sound effect channels
// since music seems to exist as CD audio only in the games which use this
// MusicEngine implementation.
_driver->intf()->setSoundEffectChanMask(-1);
setVolumeCD(255, 255);
return true;
}
void Player_Towns::setMusicVolume(int vol) {
_driver->setMusicVolume(vol);
}
void Player_Towns::setSfxVolume(int vol) {
_driver->setSoundEffectVolume(vol);
}
void Player_Towns::startSound(int sound) {
uint8 *ptr = _vm->getResourceAddress(rtSound, sound);
if (_vm->_game.version != 3) {
ptr += 2;
} else if (_soundOverride && sound > 0 && sound < 200) {
memcpy(&_ovrCur, &_soundOverride[sound], sizeof(SoundOvrParameters));
memset(&_soundOverride[sound], 0, sizeof(SoundOvrParameters));
}
int type = ptr[13];
if (type == 0) {
playPcmTrack(sound, ptr + 6);
} else if (type == 1) {
playEuphonyTrack(sound, ptr + 6);
} else if (type == 2) {
playCdaTrack(sound, ptr + 6);
}
memset(&_ovrCur, 0, sizeof(SoundOvrParameters));
}
void Player_Towns::stopSound(int sound) {
if (sound == 0 || sound == _cdaCurrentSound) {
_cdaCurrentSound = 0;
_vm->_sound->stopCD();
_vm->_sound->stopCDTimer();
}
if (sound != 0 && sound == _eupCurrentSound) {
_eupCurrentSound = 0;
_eupLooping = false;
_driver->stopParser();
}
stopPcmTrack(sound);
}
void Player_Towns::stopAllSounds() {
_cdaCurrentSound = 0;
_vm->_sound->stopCD();
_vm->_sound->stopCDTimer();
_eupCurrentSound = 0;
_eupLooping = false;
_driver->stopParser();
stopPcmTrack(0);
}
int Player_Towns::getSoundStatus(int sound) const {
if (sound == _cdaCurrentSound)
return _vm->_sound->pollCD();
if (sound == _eupCurrentSound)
return _driver->parserIsPlaying() ? 1 : 0;
for (int i = 1; i < 9; i++) {
if (_pcmCurrentSound[i].index == sound)
return _driver->soundEffectIsPlaying(i + 0x3f) ? 1 : 0;
}
return 0;
}
int32 Player_Towns::doCommand(int numargs, int args[]) {
int32 res = 0;
switch (args[0]) {
case 2:
_driver->intf()->callback(73, 0);
break;
case 3:
restartLoopingSounds();
break;
case 8:
startSound(args[1]);
break;
case 9:
_vm->_sound->stopSound(args[1]);
break;
case 11:
stopPcmTrack(0);
break;
case 14:
startSoundEx(args[1], args[2], args[3], args[4]);
break;
case 15:
stopSoundSuspendLooping(args[1]);
break;
default:
warning("Player_Towns::doCommand: Unknown command %d", args[0]);
break;
}
return res;
}
void Player_Towns::setVolumeCD(int left, int right) {
_cdaVolLeft = left & 0xff;
_cdaVolRight = right & 0xff;
_driver->setOutputVolume(1, left >> 1, right >> 1);
}
void Player_Towns::setSoundVolume(int sound, int left, int right) {
if (_soundOverride && sound > 0 && sound < 200) {
_soundOverride[sound].vLeft = left;
_soundOverride[sound].vRight = right;
}
}
void Player_Towns::setSoundNote(int sound, int note) {
if (_soundOverride && sound > 0 && sound < 200)
_soundOverride[sound].note = note;
_intf = 0;
}
void Player_Towns::saveLoadWithSerializer(Serializer *ser) {
_cdaCurrentSoundTemp = (_vm->_sound->pollCD() && _cdaNumLoops > 1) ? _cdaCurrentSound & 0xff : 0;
_cdaNumLoopsTemp = _cdaNumLoops & 0xff;
static const SaveLoadEntry cdEntries[] = {
MKLINE(Player_Towns, _cdaCurrentSoundTemp, sleUint8, VER(81)),
MKLINE(Player_Towns, _cdaNumLoopsTemp, sleUint8, VER(81)),
MKLINE(Player_Towns, _cdaVolLeft, sleUint8, VER(81)),
MKLINE(Player_Towns, _cdaVolRight, sleUint8, VER(81)),
MKEND()
};
ser->saveLoadEntries(this, cdEntries);
if (!_eupLooping && !_driver->parserIsPlaying())
_eupCurrentSound = 0;
static const SaveLoadEntry eupEntries[] = {
MKLINE(Player_Towns, _eupCurrentSound, sleUint8, VER(81)),
MKLINE(Player_Towns, _eupLooping, sleUint8, VER(81)),
MKLINE(Player_Towns, _eupVolLeft, sleUint8, VER(81)),
MKLINE(Player_Towns, _eupVolRight, sleUint8, VER(81)),
MKEND()
};
ser->saveLoadEntries(this, eupEntries);
static const SaveLoadEntry pcmEntries[] = {
MKLINE(PcmCurrentSound, index, sleInt16, VER(81)),
MKLINE(PcmCurrentSound, chan, sleInt16, VER(81)),
@ -244,10 +54,10 @@ void Player_Towns::saveLoadWithSerializer(Serializer *ser) {
if (!_pcmCurrentSound[i].index)
continue;
if (_driver->soundEffectIsPlaying(i + 0x3f))
if (_intf->callback(40, i + 0x3f))
continue;
_driver->stopSoundEffect(i + 0x3f);
_intf->callback(39, i + 0x3f);
_pcmCurrentSound[i].index = 0;
}
@ -256,31 +66,6 @@ void Player_Towns::saveLoadWithSerializer(Serializer *ser) {
}
void Player_Towns::restoreAfterLoad() {
setVolumeCD(_cdaVolLeft, _cdaVolRight);
if (_cdaCurrentSoundTemp) {
uint8 *ptr = _vm->getResourceAddress(rtSound, _cdaCurrentSoundTemp) + 6;
if (_vm->_game.version != 3)
ptr += 2;
if (ptr[7] == 2) {
playCdaTrack(_cdaCurrentSoundTemp, ptr, true);
_cdaCurrentSound = _cdaCurrentSoundTemp;
_cdaNumLoops = _cdaNumLoopsTemp;
}
}
if (_eupCurrentSound) {
uint8 *ptr = _vm->getResourceAddress(rtSound, _eupCurrentSound) + 6;
if (_vm->_game.version != 3)
ptr += 2;
if (ptr[7] == 1) {
setSoundVolume(_eupCurrentSound, _eupVolLeft, _eupVolRight);
playEuphonyTrack(_eupCurrentSound, ptr);
}
}
for (int i = 1; i < 9; i++) {
if (!_pcmCurrentSound[i].index)
continue;
@ -299,6 +84,56 @@ void Player_Towns::restoreAfterLoad() {
}
}
void Player_Towns::playPcmTrack(int sound, const uint8 *data, int velo, int pan, int note) {
const uint8 *ptr = data;
const uint8 *sfxData = ptr + 16;
int note2, velocity;
if (velo)
velocity = velo;
else if (_ovrCur.vLeft + _ovrCur.vRight)
velocity = (_ovrCur.vLeft + _ovrCur.vRight) >> 2;
else
velocity = ptr[8] >> 1;
int numChan = ptr[14];
for (int i = 0; i < numChan; i++) {
int chan = getNextFreePcmChannel(sound, i);
if (!chan)
return;
_intf->callback(70, _unkFlags);
_intf->callback(3, chan + 0x3f, pan);
if (note)
note2 = note;
else if (_ovrCur.note)
note2 = _ovrCur.note;
else
note2 = sfxData[28];
_intf->callback(37, chan + 0x3f, note2, velocity, sfxData);
_pcmCurrentSound[chan].note = note2;
_pcmCurrentSound[chan].velo = velocity;
_pcmCurrentSound[chan].pan = pan;
_pcmCurrentSound[chan].paused = 0;
_pcmCurrentSound[chan].looping = READ_LE_UINT32(&sfxData[20]) ? 1 : 0;
sfxData += (READ_LE_UINT32(&sfxData[12]) + 32);
}
}
void Player_Towns::stopPcmTrack(int sound) {
for (int i = 1; i < 9; i++) {
if (sound == _pcmCurrentSound[i].index || !sound) {
_intf->callback(39, i + 0x3f);
_pcmCurrentSound[i].index = 0;
}
}
}
int Player_Towns::getNextFreePcmChannel(int sound, int sfxChanRelIndex) {
int chan = 0;
for (int i = 8; i; i--) {
@ -307,7 +142,7 @@ int Player_Towns::getNextFreePcmChannel(int sound, int sfxChanRelIndex) {
continue;
}
if (_driver->soundEffectIsPlaying(i + 0x3f))
if (_intf->callback(40, i + 0x3f))
continue;
chan = i;
@ -341,7 +176,237 @@ int Player_Towns::getNextFreePcmChannel(int sound, int sfxChanRelIndex) {
return chan;
}
void Player_Towns::restartLoopingSounds() {
Player_Towns_v1::Player_Towns_v1(ScummEngine *vm, Audio::Mixer *mixer) : Player_Towns(vm) {
_cdaCurrentSound = _eupCurrentSound = _cdaNumLoops = 0;
_cdaForceRestart = 0;
_cdaVolLeft = _cdaVolRight = 0;
_eupVolLeft = _eupVolRight = 0;
if (_vm->_game.version == 3) {
_soundOverride = new SoundOvrParameters[200];
memset(_soundOverride, 0, 200 * sizeof(SoundOvrParameters));
}
_eupLooping = false;
_driver = new TownsEuphonyDriver(mixer);
}
Player_Towns_v1::~Player_Towns_v1() {
delete[] _soundOverride;
delete _driver;
}
bool Player_Towns_v1::init() {
if (!_driver)
return false;
if (!_driver->init())
return false;
_driver->reserveSoundEffectChannels(8);
_intf = _driver->intf();
// Treat all 6 fm channels and all 8 pcm channels as sound effect channels
// since music seems to exist as CD audio only in the games which use this
// MusicEngine implementation.
_intf->setSoundEffectChanMask(-1);
setVolumeCD(255, 255);
return true;
}
void Player_Towns_v1::setMusicVolume(int vol) {
_driver->setMusicVolume(vol);
}
void Player_Towns_v1::setSfxVolume(int vol) {
_driver->setSoundEffectVolume(vol);
}
void Player_Towns_v1::startSound(int sound) {
uint8 *ptr = _vm->getResourceAddress(rtSound, sound);
if (_vm->_game.version != 3) {
ptr += 2;
} else if (_soundOverride && sound > 0 && sound < 200) {
memcpy(&_ovrCur, &_soundOverride[sound], sizeof(SoundOvrParameters));
memset(&_soundOverride[sound], 0, sizeof(SoundOvrParameters));
}
int type = ptr[13];
if (type == 0) {
playPcmTrack(sound, ptr + 6);
} else if (type == 1) {
playEuphonyTrack(sound, ptr + 6);
} else if (type == 2) {
playCdaTrack(sound, ptr + 6);
}
memset(&_ovrCur, 0, sizeof(SoundOvrParameters));
}
void Player_Towns_v1::stopSound(int sound) {
if (sound == 0 || sound == _cdaCurrentSound) {
_cdaCurrentSound = 0;
_vm->_sound->stopCD();
_vm->_sound->stopCDTimer();
}
if (sound != 0 && sound == _eupCurrentSound) {
_eupCurrentSound = 0;
_eupLooping = false;
_driver->stopParser();
}
stopPcmTrack(sound);
}
void Player_Towns_v1::stopAllSounds() {
_cdaCurrentSound = 0;
_vm->_sound->stopCD();
_vm->_sound->stopCDTimer();
_eupCurrentSound = 0;
_eupLooping = false;
_driver->stopParser();
stopPcmTrack(0);
}
int Player_Towns_v1::getSoundStatus(int sound) const {
if (sound == _cdaCurrentSound)
return _vm->_sound->pollCD();
if (sound == _eupCurrentSound)
return _driver->parserIsPlaying() ? 1 : 0;
for (int i = 1; i < 9; i++) {
if (_pcmCurrentSound[i].index == sound)
return _driver->soundEffectIsPlaying(i + 0x3f) ? 1 : 0;
}
return 0;
}
int32 Player_Towns_v1::doCommand(int numargs, int args[]) {
int32 res = 0;
switch (args[0]) {
case 2:
_driver->intf()->callback(73, 0);
break;
case 3:
restartLoopingSounds();
break;
case 8:
startSound(args[1]);
break;
case 9:
_vm->_sound->stopSound(args[1]);
break;
case 11:
stopPcmTrack(0);
break;
case 14:
startSoundEx(args[1], args[2], args[3], args[4]);
break;
case 15:
stopSoundSuspendLooping(args[1]);
break;
default:
warning("Player_Towns_v1::doCommand: Unknown command %d", args[0]);
break;
}
return res;
}
void Player_Towns_v1::setVolumeCD(int left, int right) {
_cdaVolLeft = left & 0xff;
_cdaVolRight = right & 0xff;
_driver->setOutputVolume(1, left >> 1, right >> 1);
}
void Player_Towns_v1::setSoundVolume(int sound, int left, int right) {
if (_soundOverride && sound > 0 && sound < 200) {
_soundOverride[sound].vLeft = left;
_soundOverride[sound].vRight = right;
}
}
void Player_Towns_v1::setSoundNote(int sound, int note) {
if (_soundOverride && sound > 0 && sound < 200)
_soundOverride[sound].note = note;
}
void Player_Towns_v1::saveLoadWithSerializer(Serializer *ser) {
_cdaCurrentSoundTemp = (_vm->_sound->pollCD() && _cdaNumLoops > 1) ? _cdaCurrentSound & 0xff : 0;
_cdaNumLoopsTemp = _cdaNumLoops & 0xff;
static const SaveLoadEntry cdEntries[] = {
MKLINE(Player_Towns_v1, _cdaCurrentSoundTemp, sleUint8, VER(81)),
MKLINE(Player_Towns_v1, _cdaNumLoopsTemp, sleUint8, VER(81)),
MKLINE(Player_Towns_v1, _cdaVolLeft, sleUint8, VER(81)),
MKLINE(Player_Towns_v1, _cdaVolRight, sleUint8, VER(81)),
MKEND()
};
ser->saveLoadEntries(this, cdEntries);
if (!_eupLooping && !_driver->parserIsPlaying())
_eupCurrentSound = 0;
static const SaveLoadEntry eupEntries[] = {
MKLINE(Player_Towns_v1, _eupCurrentSound, sleUint8, VER(81)),
MKLINE(Player_Towns_v1, _eupLooping, sleUint8, VER(81)),
MKLINE(Player_Towns_v1, _eupVolLeft, sleUint8, VER(81)),
MKLINE(Player_Towns_v1, _eupVolRight, sleUint8, VER(81)),
MKEND()
};
ser->saveLoadEntries(this, eupEntries);
Player_Towns::saveLoadWithSerializer(ser);
}
void Player_Towns_v1::restoreAfterLoad() {
setVolumeCD(_cdaVolLeft, _cdaVolRight);
if (_cdaCurrentSoundTemp) {
uint8 *ptr = _vm->getResourceAddress(rtSound, _cdaCurrentSoundTemp) + 6;
if (_vm->_game.version != 3)
ptr += 2;
if (ptr[7] == 2) {
playCdaTrack(_cdaCurrentSoundTemp, ptr, true);
_cdaCurrentSound = _cdaCurrentSoundTemp;
_cdaNumLoops = _cdaNumLoopsTemp;
}
}
if (_eupCurrentSound) {
uint8 *ptr = _vm->getResourceAddress(rtSound, _eupCurrentSound) + 6;
if (_vm->_game.version != 3)
ptr += 2;
if (ptr[7] == 1) {
setSoundVolume(_eupCurrentSound, _eupVolLeft, _eupVolRight);
playEuphonyTrack(_eupCurrentSound, ptr);
}
}
Player_Towns::restoreAfterLoad();
}
void Player_Towns_v1::restartLoopingSounds() {
if (_cdaNumLoops && !_cdaForceRestart)
_cdaForceRestart = 1;
@ -368,7 +433,7 @@ void Player_Towns::restartLoopingSounds() {
_driver->intf()->callback(73, 1);
}
void Player_Towns::startSoundEx(int sound, int velo, int pan, int note) {
void Player_Towns_v1::startSoundEx(int sound, int velo, int pan, int note) {
uint8 *ptr = _vm->getResourceAddress(rtSound, sound) + 2;
if (pan > 99)
@ -405,7 +470,7 @@ void Player_Towns::startSoundEx(int sound, int velo, int pan, int note) {
}
}
void Player_Towns::stopSoundSuspendLooping(int sound) {
void Player_Towns_v1::stopSoundSuspendLooping(int sound) {
if (!sound) {
return;
} else if (sound == _cdaCurrentSound) {
@ -426,7 +491,7 @@ void Player_Towns::stopSoundSuspendLooping(int sound) {
}
}
void Player_Towns::playEuphonyTrack(int sound, const uint8 *data) {
void Player_Towns_v1::playEuphonyTrack(int sound, const uint8 *data) {
const uint8 *pos = data + 16;
const uint8 *src = pos + data[14] * 48;
const uint8 *trackData = src + 150;
@ -474,48 +539,7 @@ void Player_Towns::playEuphonyTrack(int sound, const uint8 *data) {
_eupCurrentSound = sound;
}
void Player_Towns::playPcmTrack(int sound, const uint8 *data, int velo, int pan, int note) {
const uint8 *ptr = data;
const uint8 *sfxData = ptr + 16;
int note2, velocity;
if (velo)
velocity = velo;
else if (_ovrCur.vLeft + _ovrCur.vRight)
velocity = (_ovrCur.vLeft + _ovrCur.vRight) >> 2;
else
velocity = ptr[8] >> 1;
int numChan = ptr[14];
for (int i = 0; i < numChan; i++) {
int chan = getNextFreePcmChannel(sound, i);
if (!chan)
return;
_driver->intf()->callback(70, _unkFlags);
_driver->chanPanPos(chan + 0x3f, pan);
if (note)
note2 = note;
else if (_ovrCur.note)
note2 = _ovrCur.note;
else
note2 = sfxData[28];
_driver->playSoundEffect(chan + 0x3f, note2, velocity, sfxData);
_pcmCurrentSound[chan].note = note2;
_pcmCurrentSound[chan].velo = velocity;
_pcmCurrentSound[chan].pan = pan;
_pcmCurrentSound[chan].paused = 0;
_pcmCurrentSound[chan].looping = READ_LE_UINT32(&sfxData[20]) ? 1 : 0;
sfxData += (READ_LE_UINT32(&sfxData[12]) + 32);
}
}
void Player_Towns::playCdaTrack(int sound, const uint8 *data, bool skipTrackVelo) {
void Player_Towns_v1::playCdaTrack(int sound, const uint8 *data, bool skipTrackVelo) {
const uint8 *ptr = data;
if (!sound)
@ -543,14 +567,5 @@ void Player_Towns::playCdaTrack(int sound, const uint8 *data, bool skipTrackVelo
_cdaCurrentSound = sound;
}
void Player_Towns::stopPcmTrack(int sound) {
for (int i = 1; i < 9; i++) {
if (sound == _pcmCurrentSound[i].index || !sound) {
_driver->stopSoundEffect(i + 0x3f);
_pcmCurrentSound[i].index = 0;
}
}
}
} // End of namespace Scumm

View file

@ -32,10 +32,50 @@
namespace Scumm {
class Player_Towns : public MusicEngine {
class Player_Towns {
public:
Player_Towns(ScummEngine *vm, Audio::Mixer *mixer);
virtual ~Player_Towns();
Player_Towns(ScummEngine *vm);
virtual ~Player_Towns() {}
virtual void saveLoadWithSerializer(Serializer *ser);
virtual void restoreAfterLoad();
protected:
void playPcmTrack(int sound, const uint8 *data, int velo = 0, int pan = 64, int note = 0);
void stopPcmTrack(int sound);
int getNextFreePcmChannel(int sound, int sfxChanRelIndex);
struct PcmCurrentSound {
uint16 index;
uint16 chan;
uint8 note;
uint8 velo;
uint8 pan;
uint8 paused;
uint8 looping;
uint32 priority;
} _pcmCurrentSound[9];
struct SoundOvrParameters {
uint8 vLeft;
uint8 vRight;
uint8 note;
};
uint8 _unkFlags;
SoundOvrParameters *_soundOverride;
SoundOvrParameters _ovrCur;
TownsAudioInterface *_intf;
ScummEngine *_vm;
};
class Player_Towns_v1 : public Player_Towns, public MusicEngine {
public:
Player_Towns_v1(ScummEngine *vm, Audio::Mixer *mixer);
virtual ~Player_Towns_v1();
bool init();
@ -49,7 +89,7 @@ public:
int getCurrentCdaSound() { return _cdaCurrentSound; }
int getCurrentCdaVolume() { return (_cdaVolLeft + _cdaVolRight + 1) >> 1; }
virtual int32 doCommand(int numargs, int args[]);
int32 doCommand(int numargs, int args[]);
void setVolumeCD(int left, int right);
void setSoundVolume(int sound, int left, int right);
@ -60,45 +100,17 @@ public:
TownsEuphonyDriver *driver() { return _driver; }
protected:
virtual int getNextFreePcmChannel(int sound, int sfxChanRelIndex);
private:
void restartLoopingSounds();
void startSoundEx(int sound, int velo, int pan, int note);
void stopSoundSuspendLooping(int sound);
void playEuphonyTrack(int sound, const uint8 *data);
void playPcmTrack(int sound, const uint8 *data, int velo = 0, int pan = 64, int note = 0);
void playCdaTrack(int sound, const uint8 *data, bool skipTrackVelo = false);
void stopPcmTrack(int sound);
uint8 _cdaVolLeft;
uint8 _cdaVolRight;
struct SoundOvrParameters {
uint8 vLeft;
uint8 vRight;
uint8 note;
};
SoundOvrParameters *_soundOverride;
SoundOvrParameters _ovrCur;
uint8 _unkFlags;
struct PcmCurrentSound {
uint16 index;
uint16 chan;
uint8 note;
uint8 velo;
uint8 pan;
uint8 paused;
uint8 looping;
uint32 priority;
} _pcmCurrentSound[9];
uint8 _eupCurrentSound;
uint8 _eupLooping;
uint8 _eupVolLeft;
@ -112,7 +124,6 @@ private:
uint8 _cdaNumLoopsTemp;
TownsEuphonyDriver *_driver;
ScummEngine *_vm;
};
} // End of namespace Scumm

View file

@ -195,7 +195,9 @@ void ScummEngine::startScene(int room, Actor *a, int objectNr) {
_egoPositioned = false;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
towns_resetPalCycleFields();
#endif
runEntryScript();
if (_game.version >= 1 && _game.version <= 2) {

View file

@ -1298,6 +1298,7 @@ void ScummEngine::saveOrLoad(Serializer *s) {
s->saveLoadArrayOf(_16BitPalette, 512, sizeof(_16BitPalette[0]), sleUint16);
}
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
// FM-Towns specific (extra palette data, color cycle data, etc.)
if (s->getVersion() >= VER(82)) {
const SaveLoadEntry townsFields[] = {
@ -1323,6 +1324,7 @@ void ScummEngine::saveOrLoad(Serializer *s) {
s->saveLoadArrayOf(_townsCharsetColorMap, 16, sizeof(_townsCharsetColorMap[0]), sleUint8);
s->saveLoadEntries(this, townsExtraEntries);
}
#endif
if (_shadowPaletteSize) {
s->saveLoadArrayOf(_shadowPalette, _shadowPaletteSize, 1, sleByte);

View file

@ -114,8 +114,10 @@ void ScummEngine_v4::o4_oldRoomEffect() {
if (_game.platform == Common::kPlatformFMTowns && _game.version == 3) {
if (a == 4) {
_textSurface.fillRect(Common::Rect(0, 0, _textSurface.w * _textSurfaceMultiplier, _textSurface.h * _textSurfaceMultiplier), 0);
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_townsScreen)
_townsScreen->clearLayer(1);
#endif
return;
}
}

View file

@ -1712,6 +1712,7 @@ void ScummEngine_v5::o5_roomOps() {
case 10: // SO_ROOM_FADE
a = getVarOrDirectWord(PARAM_1);
if (a) {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns) {
switch (a) {
case 8:
@ -1762,6 +1763,7 @@ void ScummEngine_v5::o5_roomOps() {
return;
}
}
#endif // DISABLE_TOWNS_DUAL_LAYER_MODE
_switchRoomEffect = (byte)(a & 0xFF);
_switchRoomEffect2 = (byte)(a >> 8);
} else {

View file

@ -278,7 +278,9 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_hePalettes = NULL;
_hePaletteSlot = 0;
_16BitPalette = NULL;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
_townsScreen = 0;
#endif
_shadowPalette = NULL;
_shadowPaletteSize = 0;
memset(_currentPalette, 0, sizeof(_currentPalette));
@ -319,12 +321,14 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_skipDrawObject = 0;
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
_townsPaletteFlags = 0;
_townsClearLayerFlag = 1;
_townsActiveLayerFlags = 3;
memset(&_curStringRect, -1, sizeof(Common::Rect));
memset(&_cyclRects, 0, 16 * sizeof(Common::Rect));
_numCyclRects = 0;
#endif
//
// Init all VARS to 0xFF
@ -544,8 +548,10 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr)
_bytesPerPixelOutput = _bytesPerPixel = (_game.features & GF_16BIT_COLOR) ? 2 : 1;
#ifdef USE_RGB_COLOR
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns)
_bytesPerPixelOutput = 2;
#endif
#endif
// Allocate gfx compositing buffer (not needed for V7/V8 games).
@ -622,7 +628,9 @@ ScummEngine::~ScummEngine() {
free(_16BitPalette);
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
delete _townsScreen;
#endif
delete _debugger;
@ -1130,7 +1138,11 @@ Common::Error ScummEngine::init() {
screenWidth *= _textSurfaceMultiplier;
screenHeight *= _textSurfaceMultiplier;
}
if (_game.features & GF_16BIT_COLOR || _game.platform == Common::kPlatformFMTowns) {
if (_game.features & GF_16BIT_COLOR
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|| _game.platform == Common::kPlatformFMTowns
#endif
) {
#ifdef USE_RGB_COLOR
Graphics::PixelFormat format = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
initGraphics(screenWidth, screenHeight, screenWidth > 320, &format);
@ -1145,6 +1157,10 @@ Common::Error ScummEngine::init() {
}
#endif
} else {
#ifdef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns && _game.version == 5)
error("This game requires dual graphics layer support which is disabled in this build");
#endif
initGraphics(screenWidth, screenHeight, (screenWidth > 320));
}
}
@ -1340,16 +1356,22 @@ void ScummEngine::resetScumm() {
debug(9, "resetScumm");
#ifdef USE_RGB_COLOR
if (_game.features & GF_16BIT_COLOR || _game.platform == Common::kPlatformFMTowns)
if (_game.features & GF_16BIT_COLOR
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|| _game.platform == Common::kPlatformFMTowns
#endif
)
_16BitPalette = (uint16 *)calloc(512, sizeof(uint16));
#endif
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns) {
delete _townsScreen;
_townsScreen = new TownsScreen(_system, _screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier, _bytesPerPixelOutput);
_townsScreen->setupLayer(0, _screenWidth, _screenHeight, (_bytesPerPixelOutput == 2) ? 32767 : 256);
_townsScreen->setupLayer(1, _screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier, 16, _textPalette);
}
#endif
if (_game.version == 0) {
initScreens(8, 144);
@ -1789,7 +1811,7 @@ void ScummEngine::setupMusic(int midi) {
} else if (_game.platform == Common::kPlatform3DO && _game.heversion <= 62) {
// 3DO versions use digital music and sound samples.
} else if (_game.platform == Common::kPlatformFMTowns && (_game.version == 3 || _game.id == GID_MONKEY)) {
_musicEngine = _townsPlayer = new Player_Towns(this, _mixer);
_musicEngine = _townsPlayer = new Player_Towns_v1(this, _mixer);
if (!_townsPlayer->init())
error("Failed to initialize FM-Towns audio driver");
} else if (_game.version >= 3 && _game.heversion <= 62) {
@ -1953,8 +1975,10 @@ void ScummEngine::waitForTimer(int msec_delay) {
_sound->updateCD(); // Loop CD Audio if needed
parseEvents();
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_townsScreen)
_townsScreen->update();
#endif
_system->updateScreen();
if (_system->getMillis() >= start_time + msec_delay)
@ -2083,7 +2107,9 @@ load_game:
goto load_game;
}
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
towns_processPalCycleField();
#endif
if (_currentRoom == 0) {
if (_game.version > 3)
@ -2473,8 +2499,10 @@ void ScummEngine::pauseEngineIntern(bool pause) {
// Update the screen to make it less likely that the player will see a
// brief cursor palette glitch when the GUI is disabled.
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_townsScreen)
_townsScreen->update();
#endif
_system->updateScreen();

View file

@ -43,6 +43,17 @@
#include "sound/mididrv.h"
#ifdef __DS__
/* This disables the dual layer mode which is used in FM-Towns versions
* of SCUMM games and which emulates the behaviour of the original code.
* The only purpose is code size reduction for certain backends.
* SCUMM 3 (FM-Towns) games will run in normal (DOS VGA) mode, which should
* work just fine in most situations. Some glitches might occur. SCUMM 5 games
* will not work without dual layer (and 16 bit color) support.
*/
#define DISABLE_TOWNS_DUAL_LAYER_MODE
#endif
namespace GUI {
class Dialog;
}
@ -70,7 +81,7 @@ class CharsetRenderer;
class IMuse;
class IMuseDigital;
class MusicEngine;
class Player_Towns;
class Player_Towns_v1;
class ScummEngine;
class ScummDebugger;
class Serializer;
@ -427,7 +438,7 @@ public:
IMuse *_imuse;
IMuseDigital *_imuseDigital;
MusicEngine *_musicEngine;
Player_Towns *_townsPlayer;
Player_Towns_v1 *_townsPlayer;
Sound *_sound;
VerbSlot *_verbs;
@ -1401,6 +1412,7 @@ public:
byte VAR_NUM_GLOBAL_OBJS;
// FM-Towns specific
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
public:
bool towns_isRectInStringBox(int x1, int y1, int x2, int y2);
byte _townsPaletteFlags;
@ -1429,6 +1441,7 @@ protected:
static const uint8 _townsLayer2Mask[];
TownsScreen *_townsScreen;
#endif // DISABLE_TOWNS_DUAL_LAYER_MODE
};
} // End of namespace Scumm

View file

@ -508,8 +508,10 @@ void ScummEngine::CHARSET_1() {
if (_game.version >= 5)
memcpy(_charsetColorMap, _charsetData[_charset->getCurID()], 4);
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_keepText && _game.platform == Common::kPlatformFMTowns)
memcpy(&_charset->_str, &_curStringRect, sizeof(Common::Rect));
#endif
if (_talkDelay)
return;
@ -542,9 +544,11 @@ void ScummEngine::CHARSET_1() {
_nextTop = _string[0].ypos + _screenTop;
#endif
} else {
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns)
towns_restoreCharsetBg();
else
#endif
restoreCharsetBg();
}
}
@ -666,8 +670,10 @@ void ScummEngine::CHARSET_1() {
}
}
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
if (_game.platform == Common::kPlatformFMTowns && (c == 0 || c == 2 || c == 3))
memcpy(&_curStringRect, &_charset->_str, sizeof(Common::Rect));
#endif
#ifdef ENABLE_SCUMM_7_8
if (_game.version >= 7 && subtitleLine != subtitleBuffer) {

View file

@ -1451,7 +1451,11 @@ void ScummEngine::restoreVerbBG(int verb) {
VerbSlot *vs;
vs = &_verbs[verb];
uint8 col = ((_game.platform == Common::kPlatformFMTowns) && (_game.id == GID_MONKEY2 || _game.id == GID_INDY4) && (vs->bkcolor == _townsOverrideShadowColor)) ? 0 : vs->bkcolor;
uint8 col =
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
((_game.platform == Common::kPlatformFMTowns) && (_game.id == GID_MONKEY2 || _game.id == GID_INDY4) && (vs->bkcolor == _townsOverrideShadowColor)) ? 0 :
#endif
vs->bkcolor;
if (vs->oldRect.left != -1) {
restoreBackground(vs->oldRect, col);