2007-05-30 21:56:52 +00:00
|
|
|
/* 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.
|
2001-10-09 14:30:12 +00:00
|
|
|
*
|
|
|
|
* 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.
|
2014-02-18 01:34:24 +00:00
|
|
|
*
|
2001-10-09 14:30:12 +00:00
|
|
|
* 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.
|
2014-02-18 01:34:24 +00:00
|
|
|
*
|
2001-10-09 14:30:12 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2005-10-18 01:30:26 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2001-10-09 14:30:12 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2004-12-27 22:08:20 +00:00
|
|
|
#include "common/system.h"
|
2003-10-03 18:33:57 +00:00
|
|
|
#include "scumm/actor.h"
|
|
|
|
#include "scumm/charset.h"
|
2008-05-06 03:00:26 +00:00
|
|
|
#ifdef ENABLE_HE
|
2006-02-15 00:57:50 +00:00
|
|
|
#include "scumm/he/intern_he.h"
|
2006-02-04 12:11:10 +00:00
|
|
|
#endif
|
2003-10-03 18:33:57 +00:00
|
|
|
#include "scumm/resource.h"
|
2012-02-04 14:40:36 +00:00
|
|
|
#include "scumm/scumm_v0.h"
|
2009-03-20 16:33:58 +00:00
|
|
|
#include "scumm/scumm_v5.h"
|
|
|
|
#include "scumm/scumm_v6.h"
|
2003-10-03 18:33:57 +00:00
|
|
|
#include "scumm/usage_bits.h"
|
2006-02-15 00:57:50 +00:00
|
|
|
#include "scumm/he/wiz_he.h"
|
2006-09-18 19:16:31 +00:00
|
|
|
#include "scumm/util.h"
|
2007-07-10 20:20:50 +00:00
|
|
|
|
|
|
|
#ifdef USE_ARM_GFX_ASM
|
2011-04-23 01:28:26 +00:00
|
|
|
|
|
|
|
#ifndef IPHONE
|
|
|
|
#define asmDrawStripToScreen _asmDrawStripToScreen
|
|
|
|
#define asmCopy8Col _asmCopy8Col
|
|
|
|
#endif
|
|
|
|
|
2009-07-12 15:59:56 +00:00
|
|
|
extern "C" void asmDrawStripToScreen(int height, int width, void const* text, void const* src, byte* dst,
|
2007-07-10 20:20:50 +00:00
|
|
|
int vsPitch, int vmScreenWidth, int textSurfacePitch);
|
2009-08-21 22:56:09 +00:00
|
|
|
extern "C" void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height, uint8 bitDepth);
|
2007-07-10 20:20:50 +00:00
|
|
|
#endif /* USE_ARM_GFX_ASM */
|
2003-10-03 18:33:57 +00:00
|
|
|
|
|
|
|
namespace Scumm {
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2009-06-04 01:05:47 +00:00
|
|
|
static void blit(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h, uint8 bitDepth);
|
|
|
|
static void fill(byte *dst, int dstPitch, uint16 color, int w, int h, uint8 bitDepth);
|
2008-08-16 11:37:36 +00:00
|
|
|
#ifndef USE_ARM_GFX_ASM
|
2009-06-04 01:05:47 +00:00
|
|
|
static void copy8Col(byte *dst, int dstPitch, const byte *src, int height, uint8 bitDepth);
|
2008-02-03 12:30:11 +00:00
|
|
|
#endif
|
2009-06-04 01:05:47 +00:00
|
|
|
static void clear8Col(byte *dst, int dstPitch, int height, uint8 bitDepth);
|
2004-09-22 17:57:20 +00:00
|
|
|
|
2007-07-08 21:42:39 +00:00
|
|
|
static void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height);
|
2004-10-04 14:39:42 +00:00
|
|
|
|
2004-01-03 22:45:23 +00:00
|
|
|
struct StripTable {
|
|
|
|
int offsets[160];
|
|
|
|
int run[160];
|
|
|
|
int color[160];
|
|
|
|
int zoffsets[120]; // FIXME: Why only 120 here?
|
|
|
|
int zrun[120]; // FIXME: Why only 120 here?
|
|
|
|
};
|
|
|
|
|
2002-09-09 11:15:12 +00:00
|
|
|
enum {
|
|
|
|
kScrolltime = 500, // ms scrolling is supposed to take
|
2006-06-22 00:03:13 +00:00
|
|
|
kPictureDelay = 20,
|
|
|
|
kFadeDelay = 4 // 1/4th of a jiffie
|
2002-09-09 11:15:12 +00:00
|
|
|
};
|
|
|
|
|
2002-12-15 23:40:37 +00:00
|
|
|
#define NUM_SHAKE_POSITIONS 8
|
|
|
|
static const int8 shake_positions[NUM_SHAKE_POSITIONS] = {
|
|
|
|
0, 1 * 2, 2 * 2, 1 * 2, 0 * 2, 2 * 2, 3 * 2, 1 * 2
|
|
|
|
};
|
|
|
|
|
2003-05-30 20:13:29 +00:00
|
|
|
/**
|
2004-09-20 19:32:26 +00:00
|
|
|
* The following structs define four basic fades/transitions used by
|
2003-01-05 21:18:53 +00:00
|
|
|
* transitionEffect(), each looking differently to the user.
|
|
|
|
* Note that the stripTables contain strip numbers, and they assume
|
|
|
|
* that the screen has 40 vertical strips (i.e. 320 pixel), and 25 horizontal
|
|
|
|
* strips (i.e. 200 pixel). There is a hack in transitionEffect that
|
|
|
|
* makes it work correctly in games which have a different screen height
|
|
|
|
* (for example, 240 pixel), but nothing is done regarding the width, so this
|
|
|
|
* code won't work correctly in COMI. Also, the number of iteration depends
|
|
|
|
* on min(vertStrips, horizStrips}. So the 13 is derived from 25/2, rounded up.
|
|
|
|
* And the 25 = min(25,40). Hence for Zak256 instead of 13 and 25, the values
|
2004-09-20 19:32:26 +00:00
|
|
|
* 15 and 30 should be used, and for COMI probably 30 and 60.
|
2003-01-05 21:18:53 +00:00
|
|
|
*/
|
|
|
|
struct TransitionEffect {
|
|
|
|
byte numOfIterations;
|
|
|
|
int8 deltaTable[16]; // four times l / t / r / b
|
|
|
|
byte stripTable[16]; // ditto
|
2002-12-15 23:40:37 +00:00
|
|
|
};
|
2003-05-30 20:13:29 +00:00
|
|
|
|
2005-03-21 00:27:39 +00:00
|
|
|
static const TransitionEffect transitionEffects[6] = {
|
2003-01-05 21:18:53 +00:00
|
|
|
// Iris effect (looks like an opening/closing camera iris)
|
|
|
|
{
|
|
|
|
13, // Number of iterations
|
|
|
|
{
|
|
|
|
1, 1, -1, 1,
|
|
|
|
-1, 1, -1, -1,
|
|
|
|
1, -1, -1, -1,
|
|
|
|
1, 1, 1, -1
|
|
|
|
},
|
|
|
|
{
|
|
|
|
0, 0, 39, 0,
|
|
|
|
39, 0, 39, 24,
|
|
|
|
0, 24, 39, 24,
|
|
|
|
0, 0, 0, 24
|
|
|
|
}
|
|
|
|
},
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2003-01-05 21:18:53 +00:00
|
|
|
// Box wipe (a box expands from the upper-left corner to the lower-right corner)
|
|
|
|
{
|
|
|
|
25, // Number of iterations
|
|
|
|
{
|
|
|
|
0, 1, 2, 1,
|
|
|
|
2, 0, 2, 1,
|
|
|
|
2, 0, 2, 1,
|
|
|
|
0, 0, 0, 0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
1, 0, 1, 0,
|
|
|
|
255, 0, 0, 0
|
|
|
|
}
|
|
|
|
},
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2003-01-05 21:18:53 +00:00
|
|
|
// Box wipe (a box expands from the lower-right corner to the upper-left corner)
|
|
|
|
{
|
|
|
|
25, // Number of iterations
|
|
|
|
{
|
|
|
|
-2, -1, 0, -1,
|
|
|
|
-2, -1, -2, 0,
|
|
|
|
-2, -1, -2, 0,
|
|
|
|
0, 0, 0, 0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
39, 24, 39, 24,
|
|
|
|
39, 24, 39, 24,
|
|
|
|
38, 24, 38, 24,
|
|
|
|
255, 0, 0, 0
|
|
|
|
}
|
|
|
|
},
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2003-01-05 21:18:53 +00:00
|
|
|
// Inverse box wipe
|
|
|
|
{
|
|
|
|
25, // Number of iterations
|
|
|
|
{
|
|
|
|
0, -1, -2, -1,
|
|
|
|
-2, 0, -2, -1,
|
|
|
|
-2, 0, -2, -1,
|
|
|
|
0, 0, 0, 0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
0, 24, 39, 24,
|
|
|
|
39, 0, 39, 24,
|
|
|
|
38, 0, 38, 24,
|
|
|
|
255, 0, 0, 0
|
|
|
|
}
|
2003-06-06 12:27:33 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// Inverse iris effect, specially tailored for V1/V2 games
|
|
|
|
{
|
2004-01-05 00:45:17 +00:00
|
|
|
9, // Number of iterations
|
2003-06-06 12:27:33 +00:00
|
|
|
{
|
|
|
|
-1, -1, 1, -1,
|
|
|
|
-1, 1, 1, 1,
|
|
|
|
-1, -1, -1, 1,
|
|
|
|
1, -1, 1, 1
|
|
|
|
},
|
|
|
|
{
|
|
|
|
7, 7, 32, 7,
|
|
|
|
7, 8, 32, 8,
|
|
|
|
7, 8, 7, 8,
|
|
|
|
32, 7, 32, 8
|
|
|
|
}
|
2005-03-21 00:27:39 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// Horizontal wipe (a box expands from left to right side). For MM NES
|
|
|
|
{
|
2005-03-24 03:22:32 +00:00
|
|
|
16, // Number of iterations
|
2005-03-21 00:27:39 +00:00
|
|
|
{
|
|
|
|
2, 0, 2, 0,
|
|
|
|
2, 0, 2, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
0, 0, 0, 15,
|
|
|
|
1, 0, 1, 15,
|
|
|
|
255, 0, 0, 0,
|
|
|
|
255, 0, 0, 0
|
|
|
|
}
|
2003-01-05 21:18:53 +00:00
|
|
|
}
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2002-12-15 23:40:37 +00:00
|
|
|
};
|
|
|
|
|
2004-01-04 13:49:03 +00:00
|
|
|
|
2006-09-18 21:20:21 +00:00
|
|
|
Gdi::Gdi(ScummEngine *vm) : _vm(vm) {
|
2006-09-18 19:16:31 +00:00
|
|
|
_numZBuffer = 0;
|
|
|
|
memset(_imgBufOffs, 0, sizeof(_imgBufOffs));
|
|
|
|
_numStrips = 0;
|
|
|
|
|
2005-09-19 00:29:41 +00:00
|
|
|
_paletteMod = 0;
|
2003-10-13 12:56:53 +00:00
|
|
|
_roomPalette = vm->_roomPalette;
|
2006-09-18 22:22:35 +00:00
|
|
|
_transparentColor = 255;
|
2006-09-18 19:16:31 +00:00
|
|
|
_decomp_shr = 0;
|
|
|
|
_decomp_mask = 0;
|
|
|
|
_vertStripNextInc = 0;
|
|
|
|
_zbufferDisabled = false;
|
|
|
|
_objectMode = false;
|
2009-10-27 09:17:09 +00:00
|
|
|
_distaff = false;
|
2006-09-18 22:06:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Gdi::~Gdi() {
|
2003-10-13 12:56:53 +00:00
|
|
|
}
|
|
|
|
|
2011-05-11 12:02:21 +00:00
|
|
|
GdiHE::GdiHE(ScummEngine *vm) : Gdi(vm), _tmskPtr(0) {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-09-18 21:20:21 +00:00
|
|
|
GdiNES::GdiNES(ScummEngine *vm) : Gdi(vm) {
|
|
|
|
memset(&_NES, 0, sizeof(_NES));
|
|
|
|
}
|
|
|
|
|
2009-11-22 11:43:12 +00:00
|
|
|
#ifdef USE_RGB_COLOR
|
2009-10-21 12:59:10 +00:00
|
|
|
GdiPCEngine::GdiPCEngine(ScummEngine *vm) : Gdi(vm) {
|
|
|
|
memset(&_PCE, 0, sizeof(_PCE));
|
|
|
|
}
|
|
|
|
|
|
|
|
GdiPCEngine::~GdiPCEngine() {
|
2009-10-27 09:17:09 +00:00
|
|
|
free(_PCE.roomTiles);
|
|
|
|
free(_PCE.staffTiles);
|
2009-10-26 02:45:26 +00:00
|
|
|
free(_PCE.masks);
|
2009-10-21 12:59:10 +00:00
|
|
|
}
|
2009-11-22 11:43:12 +00:00
|
|
|
#endif
|
2009-10-21 12:59:10 +00:00
|
|
|
|
2006-09-18 22:06:39 +00:00
|
|
|
GdiV1::GdiV1(ScummEngine *vm) : Gdi(vm) {
|
2012-02-04 17:34:08 +00:00
|
|
|
memset(&_V1, 0, sizeof(_V1));
|
2006-09-18 22:06:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GdiV2::GdiV2(ScummEngine *vm) : Gdi(vm) {
|
|
|
|
_roomStrips = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
GdiV2::~GdiV2() {
|
2005-03-25 01:52:20 +00:00
|
|
|
free(_roomStrips);
|
|
|
|
}
|
|
|
|
|
2009-11-22 11:43:12 +00:00
|
|
|
#ifdef USE_RGB_COLOR
|
2011-06-18 17:44:18 +00:00
|
|
|
GdiHE16bit::GdiHE16bit(ScummEngine *vm) : GdiHE(vm) {
|
2009-06-05 10:13:19 +00:00
|
|
|
}
|
2009-11-22 11:43:12 +00:00
|
|
|
#endif
|
2009-06-05 10:13:19 +00:00
|
|
|
|
2005-03-25 01:52:20 +00:00
|
|
|
void Gdi::init() {
|
|
|
|
_numStrips = _vm->_screenWidth / 8;
|
|
|
|
|
|
|
|
// Increase the number of screen strips by one; needed for smooth scrolling
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_vm->_game.version >= 7) {
|
2005-03-25 01:52:20 +00:00
|
|
|
// We now have mostly working smooth scrolling code in place for V7+ games
|
|
|
|
// (i.e. The Dig, Full Throttle and COMI). It seems to work very well so far.
|
|
|
|
//
|
|
|
|
// To understand how we achieve smooth scrolling, first note that with it, the
|
|
|
|
// virtual screen strips don't match the display screen strips anymore. To
|
|
|
|
// overcome that problem, we simply use a screen pitch that is 8 pixel wider
|
|
|
|
// than the actual screen width, and always draw one strip more than needed to
|
2007-02-02 12:51:44 +00:00
|
|
|
// the backbuf (thus we have to treat the right border seperately).
|
2005-03-25 01:52:20 +00:00
|
|
|
_numStrips += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-18 22:22:35 +00:00
|
|
|
void Gdi::roomChanged(byte *roomptr) {
|
2005-03-25 01:52:20 +00:00
|
|
|
}
|
|
|
|
|
2006-09-18 22:22:35 +00:00
|
|
|
void GdiNES::roomChanged(byte *roomptr) {
|
2006-09-18 21:20:21 +00:00
|
|
|
decodeNESGfx(roomptr);
|
|
|
|
}
|
2005-03-25 01:52:20 +00:00
|
|
|
|
2009-11-22 11:43:12 +00:00
|
|
|
#ifdef USE_RGB_COLOR
|
2009-10-21 12:59:10 +00:00
|
|
|
void GdiPCEngine::roomChanged(byte *roomptr) {
|
|
|
|
decodePCEngineGfx(roomptr);
|
|
|
|
}
|
2009-11-22 11:43:12 +00:00
|
|
|
#endif
|
2009-10-21 12:59:10 +00:00
|
|
|
|
2009-10-27 09:17:09 +00:00
|
|
|
void Gdi::loadTiles(byte *roomptr) {
|
|
|
|
}
|
|
|
|
|
2009-11-22 11:43:12 +00:00
|
|
|
#ifdef USE_RGB_COLOR
|
2009-10-27 09:17:09 +00:00
|
|
|
void GdiPCEngine::loadTiles(byte *roomptr) {
|
2011-04-12 14:53:15 +00:00
|
|
|
decodePCEngineTileData(_vm->findResourceData(MKTAG('T','I','L','E'), roomptr));
|
2009-10-27 09:17:09 +00:00
|
|
|
}
|
2009-11-22 11:43:12 +00:00
|
|
|
#endif
|
2009-10-27 09:17:09 +00:00
|
|
|
|
2006-09-18 22:22:35 +00:00
|
|
|
void GdiV1::roomChanged(byte *roomptr) {
|
2006-09-18 22:06:39 +00:00
|
|
|
for (int i = 0; i < 4; i++){
|
2012-02-04 17:34:08 +00:00
|
|
|
_V1.colors[i] = roomptr[6 + i];
|
2006-09-18 22:06:39 +00:00
|
|
|
}
|
2012-02-04 17:34:08 +00:00
|
|
|
decodeV1Gfx(roomptr + READ_LE_UINT16(roomptr + 10), _V1.charMap, 2048);
|
|
|
|
decodeV1Gfx(roomptr + READ_LE_UINT16(roomptr + 12), _V1.picMap, roomptr[4] * roomptr[5]);
|
|
|
|
decodeV1Gfx(roomptr + READ_LE_UINT16(roomptr + 14), _V1.colorMap, roomptr[4] * roomptr[5]);
|
|
|
|
decodeV1Gfx(roomptr + READ_LE_UINT16(roomptr + 16), _V1.maskMap, roomptr[4] * roomptr[5]);
|
2008-01-27 19:47:41 +00:00
|
|
|
|
2007-12-23 16:02:58 +00:00
|
|
|
// Read the mask data. The 16bit length value seems to always be 8 too big.
|
|
|
|
// See bug #1837375 for details on this.
|
|
|
|
const byte *maskPtr = roomptr + READ_LE_UINT16(roomptr + 18);
|
2012-02-04 17:34:08 +00:00
|
|
|
decodeV1Gfx(maskPtr + 2, _V1.maskChar, READ_LE_UINT16(maskPtr) - 8);
|
2006-09-18 22:06:39 +00:00
|
|
|
_objectMode = true;
|
|
|
|
}
|
|
|
|
|
2006-09-18 22:22:35 +00:00
|
|
|
void GdiV2::roomChanged(byte *roomptr) {
|
|
|
|
_roomStrips = generateStripTable(roomptr + READ_LE_UINT16(roomptr + 0x0A),
|
|
|
|
_vm->_roomWidth, _vm->_roomHeight, _roomStrips);
|
2006-09-18 22:06:39 +00:00
|
|
|
}
|
|
|
|
|
2005-03-25 01:52:20 +00:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark --- Virtual Screens ---
|
|
|
|
#pragma mark -
|
|
|
|
|
|
|
|
|
2004-01-04 14:49:14 +00:00
|
|
|
void ScummEngine::initScreens(int b, int h) {
|
2001-10-09 14:30:12 +00:00
|
|
|
int i;
|
2005-03-24 04:53:28 +00:00
|
|
|
int adj = 0;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
|
|
|
for (i = 0; i < 3; i++) {
|
2006-09-17 20:36:48 +00:00
|
|
|
_res->nukeResource(rtBuffer, i + 1);
|
|
|
|
_res->nukeResource(rtBuffer, i + 5);
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2010-10-05 19:04:52 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_townsScreen) {
|
|
|
|
if (!_townsClearLayerFlag && (h - b != _virtscr[kMainVirtScreen].h))
|
|
|
|
_townsScreen->clearLayer(0);
|
|
|
|
|
2010-10-02 23:18:15 +00:00
|
|
|
if (_game.id != GID_MONKEY) {
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
_textSurface.fillRect(Common::Rect(0, 0, _textSurface.w * _textSurfaceMultiplier, _textSurface.h * _textSurfaceMultiplier), 0);
|
|
|
|
_townsScreen->clearLayer(1);
|
|
|
|
}
|
|
|
|
}
|
2010-10-05 19:04:52 +00:00
|
|
|
#endif
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
if (!getResourceAddress(rtBuffer, 4)) {
|
2004-01-04 13:09:02 +00:00
|
|
|
// Since the size of screen 3 is fixed, there is no need to reallocate
|
|
|
|
// it if its size changed.
|
|
|
|
// Not sure what it is good for, though. I think it may have been used
|
|
|
|
// in pre-V7 for the games messages (like 'Pause', Yes/No dialogs,
|
|
|
|
// version display, etc.). I don't know about V7, maybe the same is the
|
|
|
|
// case there. If so, we could probably just remove it completely.
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.version >= 7) {
|
2005-04-26 15:52:55 +00:00
|
|
|
initVirtScreen(kUnkVirtScreen, (_screenHeight / 2) - 10, _screenWidth, 13, false, false);
|
2002-10-27 18:41:27 +00:00
|
|
|
} else {
|
2005-04-26 15:52:55 +00:00
|
|
|
initVirtScreen(kUnkVirtScreen, 80, _screenWidth, 13, false, false);
|
2002-10-27 18:41:27 +00:00
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
2005-03-13 23:18:59 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if ((_game.platform == Common::kPlatformNES) && (h != _screenHeight)) {
|
2005-04-30 15:04:16 +00:00
|
|
|
// This is a hack to shift the whole screen downwards to match the original.
|
|
|
|
// Otherwise we would have to do lots of coordinate adjustments all over
|
|
|
|
// the code.
|
2005-03-24 04:53:28 +00:00
|
|
|
adj = 16;
|
2005-04-26 15:52:55 +00:00
|
|
|
initVirtScreen(kUnkVirtScreen, 0, _screenWidth, adj, false, false);
|
2005-03-24 04:53:28 +00:00
|
|
|
}
|
2001-10-10 10:02:33 +00:00
|
|
|
|
2005-04-26 15:52:55 +00:00
|
|
|
initVirtScreen(kMainVirtScreen, b + adj, _screenWidth, h - b, true, true);
|
|
|
|
initVirtScreen(kTextVirtScreen, adj, _screenWidth, b, false, false);
|
|
|
|
initVirtScreen(kVerbVirtScreen, h + adj, _screenWidth, _screenHeight - h - adj, false, false);
|
2001-10-10 10:02:33 +00:00
|
|
|
_screenB = b;
|
|
|
|
_screenH = h;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2006-09-17 20:22:47 +00:00
|
|
|
_gdi->init();
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2005-04-26 15:52:55 +00:00
|
|
|
void ScummEngine::initVirtScreen(VirtScreenNumber slot, int top, int width, int height, bool twobufs,
|
2003-03-06 17:58:13 +00:00
|
|
|
bool scrollable) {
|
2007-09-08 11:15:27 +00:00
|
|
|
VirtScreen *vs = &_virtscr[slot];
|
2001-10-09 14:30:12 +00:00
|
|
|
int size;
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
assert(height >= 0);
|
|
|
|
assert(slot >= 0 && slot < 4);
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.version >= 7) {
|
2004-08-08 22:10:38 +00:00
|
|
|
if (slot == kMainVirtScreen && (_roomHeight != 0))
|
2003-05-10 21:49:59 +00:00
|
|
|
height = _roomHeight;
|
2002-10-13 11:28:39 +00:00
|
|
|
}
|
|
|
|
|
2001-10-26 17:34:50 +00:00
|
|
|
vs->number = slot;
|
2004-08-14 19:42:00 +00:00
|
|
|
vs->w = width;
|
2001-10-09 14:30:12 +00:00
|
|
|
vs->topline = top;
|
2004-08-14 19:42:00 +00:00
|
|
|
vs->h = height;
|
2004-01-06 11:47:34 +00:00
|
|
|
vs->hasTwoBuffers = twobufs;
|
2001-10-09 14:30:12 +00:00
|
|
|
vs->xstart = 0;
|
2002-03-20 22:58:41 +00:00
|
|
|
vs->backBuf = NULL;
|
2011-04-18 13:48:46 +00:00
|
|
|
if (_game.features & GF_16BIT_COLOR)
|
|
|
|
vs->format = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
|
|
|
|
else
|
|
|
|
vs->format = Graphics::PixelFormat::createFormatCLUT8();
|
2011-04-17 15:29:09 +00:00
|
|
|
vs->pitch = width * vs->format.bytesPerPixel;
|
2004-10-01 20:40:03 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.version >= 7) {
|
2007-02-02 12:51:44 +00:00
|
|
|
// Increase the pitch by one; needed to accomodate the extra screen
|
|
|
|
// strip which we use to implement smooth scrolling. See Gdi::init().
|
2004-09-24 07:36:29 +00:00
|
|
|
vs->pitch += 8;
|
2004-09-24 22:31:42 +00:00
|
|
|
}
|
2002-03-14 13:57:28 +00:00
|
|
|
|
2004-08-14 19:42:00 +00:00
|
|
|
size = vs->pitch * vs->h;
|
2004-01-06 12:16:28 +00:00
|
|
|
if (scrollable) {
|
2004-01-04 13:09:02 +00:00
|
|
|
// Allow enough spaces so that rooms can be up to 4 resp. 8 screens
|
2007-02-02 12:51:44 +00:00
|
|
|
// wide. To achieve horizontal scrolling, SCUMM uses a neat trick:
|
2004-01-04 13:09:02 +00:00
|
|
|
// only the offset into the screen buffer (xstart) is changed. That way
|
|
|
|
// very little of the screen has to be redrawn, and we have a very low
|
|
|
|
// memory overhead (namely for every pixel we want to scroll, we need
|
|
|
|
// one additional byte in the buffer).
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.version >= 7) {
|
2004-08-14 19:42:00 +00:00
|
|
|
size += vs->pitch * 8;
|
2002-12-21 01:11:42 +00:00
|
|
|
} else {
|
2004-08-14 19:42:00 +00:00
|
|
|
size += vs->pitch * 4;
|
2002-12-21 01:11:42 +00:00
|
|
|
}
|
2002-10-27 10:31:07 +00:00
|
|
|
}
|
2003-03-06 17:58:13 +00:00
|
|
|
|
2006-09-17 20:36:48 +00:00
|
|
|
_res->createResource(rtBuffer, slot + 1, size);
|
2013-08-03 01:48:41 +00:00
|
|
|
vs->setPixels(getResourceAddress(rtBuffer, slot + 1));
|
2013-08-04 00:29:13 +00:00
|
|
|
memset(vs->getBasePtr(0, 0), 0, size); // reset background
|
2001-10-09 14:30:12 +00:00
|
|
|
|
|
|
|
if (twobufs) {
|
2006-09-17 20:36:48 +00:00
|
|
|
vs->backBuf = _res->createResource(rtBuffer, slot + 5, size);
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (slot != 3) {
|
2003-10-13 12:56:53 +00:00
|
|
|
vs->setDirtyRange(0, height);
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
VirtScreen *ScummEngine::findVirtScreen(int y) {
|
2007-09-08 11:15:27 +00:00
|
|
|
VirtScreen *vs = _virtscr;
|
2002-12-15 23:40:37 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 3; i++, vs++) {
|
2004-08-14 19:42:00 +00:00
|
|
|
if (y >= vs->topline && y < vs->topline + vs->h) {
|
2002-12-21 01:11:42 +00:00
|
|
|
return vs;
|
2002-12-15 23:40:37 +00:00
|
|
|
}
|
|
|
|
}
|
2002-12-21 01:11:42 +00:00
|
|
|
return NULL;
|
2002-12-15 23:40:37 +00:00
|
|
|
}
|
|
|
|
|
2004-01-03 22:45:23 +00:00
|
|
|
void ScummEngine::markRectAsDirty(VirtScreenNumber virt, int left, int right, int top, int bottom, int dirtybit) {
|
2007-09-08 11:15:27 +00:00
|
|
|
VirtScreen *vs = &_virtscr[virt];
|
2002-12-15 23:40:37 +00:00
|
|
|
int lp, rp;
|
|
|
|
|
2003-05-30 02:01:45 +00:00
|
|
|
if (left > right || top > bottom)
|
|
|
|
return;
|
2004-08-14 19:42:00 +00:00
|
|
|
if (top > vs->h || bottom < 0)
|
2002-12-15 23:40:37 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (top < 0)
|
|
|
|
top = 0;
|
2004-08-14 19:42:00 +00:00
|
|
|
if (bottom > vs->h)
|
|
|
|
bottom = vs->h;
|
2002-12-15 23:40:37 +00:00
|
|
|
|
2004-01-03 22:45:23 +00:00
|
|
|
if (virt == kMainVirtScreen && dirtybit) {
|
2004-10-01 20:40:03 +00:00
|
|
|
|
2003-11-16 20:52:57 +00:00
|
|
|
lp = left / 8 + _screenStartStrip;
|
2002-12-15 23:40:37 +00:00
|
|
|
if (lp < 0)
|
|
|
|
lp = 0;
|
2004-10-01 20:40:03 +00:00
|
|
|
|
2004-09-26 20:32:57 +00:00
|
|
|
rp = (right + vs->xstart) / 8;
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.version >= 7) {
|
2002-12-15 23:40:37 +00:00
|
|
|
if (rp > 409)
|
|
|
|
rp = 409;
|
|
|
|
} else {
|
|
|
|
if (rp >= 200)
|
|
|
|
rp = 200;
|
|
|
|
}
|
2003-01-14 10:06:56 +00:00
|
|
|
for (; lp <= rp; lp++)
|
|
|
|
setGfxUsageBit(lp, dirtybit);
|
2002-12-15 23:40:37 +00:00
|
|
|
}
|
|
|
|
|
2003-11-07 02:11:41 +00:00
|
|
|
// The following code used to be in the separate method setVirtscreenDirty
|
2003-11-16 20:52:57 +00:00
|
|
|
lp = left / 8;
|
|
|
|
rp = right / 8;
|
2002-12-15 23:40:37 +00:00
|
|
|
|
2006-09-17 20:22:47 +00:00
|
|
|
if ((lp >= _gdi->_numStrips) || (rp < 0))
|
2002-12-15 23:40:37 +00:00
|
|
|
return;
|
|
|
|
if (lp < 0)
|
|
|
|
lp = 0;
|
2006-09-17 20:22:47 +00:00
|
|
|
if (rp >= _gdi->_numStrips)
|
|
|
|
rp = _gdi->_numStrips - 1;
|
2002-12-15 23:40:37 +00:00
|
|
|
|
|
|
|
while (lp <= rp) {
|
|
|
|
if (top < vs->tdirty[lp])
|
|
|
|
vs->tdirty[lp] = top;
|
|
|
|
if (bottom > vs->bdirty[lp])
|
|
|
|
vs->bdirty[lp] = bottom;
|
|
|
|
lp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-01-03 21:22:07 +00:00
|
|
|
/**
|
|
|
|
* Update all dirty screen areas. This method blits all of the internal engine
|
|
|
|
* graphics to the actual display, as needed. In addition, the 'shaking'
|
|
|
|
* code in the backend is controlled from here.
|
|
|
|
*/
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine::drawDirtyScreenParts() {
|
2004-01-03 21:22:07 +00:00
|
|
|
// Update verbs
|
|
|
|
updateDirtyScreen(kVerbVirtScreen);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-01-06 12:08:35 +00:00
|
|
|
// Update the conversation area (at the top of the screen)
|
|
|
|
updateDirtyScreen(kTextVirtScreen);
|
2004-01-03 21:22:07 +00:00
|
|
|
|
|
|
|
// Update game area ("stage")
|
2007-02-10 02:05:59 +00:00
|
|
|
if (camera._last.x != camera._cur.x || (_game.version >= 7 && (camera._cur.y != camera._last.y))) {
|
2004-01-03 21:22:07 +00:00
|
|
|
// Camera moved: redraw everything
|
2007-09-08 11:15:27 +00:00
|
|
|
VirtScreen *vs = &_virtscr[kMainVirtScreen];
|
2005-03-25 01:27:28 +00:00
|
|
|
drawStripToScreen(vs, 0, vs->w, 0, vs->h);
|
2004-08-14 19:42:00 +00:00
|
|
|
vs->setDirtyRange(vs->h, 0);
|
2001-10-09 14:30:12 +00:00
|
|
|
} else {
|
2004-01-03 21:22:07 +00:00
|
|
|
updateDirtyScreen(kMainVirtScreen);
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
2001-12-28 15:26:28 +00:00
|
|
|
|
2004-01-03 21:22:07 +00:00
|
|
|
// Handle shaking
|
2002-12-25 21:04:47 +00:00
|
|
|
if (_shakeEnabled) {
|
2004-01-03 21:22:07 +00:00
|
|
|
_shakeFrame = (_shakeFrame + 1) % NUM_SHAKE_POSITIONS;
|
2004-09-28 20:19:37 +00:00
|
|
|
_system->setShakePos(shake_positions[_shakeFrame]);
|
2002-07-28 15:39:44 +00:00
|
|
|
} else if (!_shakeEnabled &&_shakeFrame != 0) {
|
|
|
|
_shakeFrame = 0;
|
2004-09-28 20:19:37 +00:00
|
|
|
_system->setShakePos(0);
|
2001-12-28 15:26:28 +00:00
|
|
|
}
|
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2005-04-28 22:34:56 +00:00
|
|
|
void ScummEngine_v6::drawDirtyScreenParts() {
|
|
|
|
// For the Full Throttle credits to work properly, the blast
|
|
|
|
// texts have to be drawn before the blast objects. Unless
|
|
|
|
// someone can think of a better way to achieve this effect.
|
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.version >= 7 && VAR(VAR_BLAST_ABOVE_TEXT) == 1) {
|
2005-04-28 22:34:56 +00:00
|
|
|
drawBlastTexts();
|
|
|
|
drawBlastObjects();
|
2007-12-31 01:20:24 +00:00
|
|
|
if (_game.version == 8) {
|
|
|
|
// Does this case ever happen? We need to draw the
|
|
|
|
// actor over the blast object, so we're forced to
|
|
|
|
// also draw it over the subtitles.
|
|
|
|
processUpperActors();
|
|
|
|
}
|
2005-04-28 22:34:56 +00:00
|
|
|
} else {
|
|
|
|
drawBlastObjects();
|
2007-12-30 22:22:38 +00:00
|
|
|
if (_game.version == 8) {
|
|
|
|
// Do this before drawing blast texts. Subtitles go on
|
|
|
|
// top of the CoMI verb coin, e.g. when Murray is
|
|
|
|
// talking to himself early in the game.
|
|
|
|
processUpperActors();
|
|
|
|
}
|
2005-04-28 22:34:56 +00:00
|
|
|
drawBlastTexts();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call the original method.
|
|
|
|
ScummEngine::drawDirtyScreenParts();
|
|
|
|
|
|
|
|
// Remove all blasted objects/text again.
|
|
|
|
removeBlastTexts();
|
|
|
|
removeBlastObjects();
|
|
|
|
}
|
|
|
|
|
2003-05-30 20:13:29 +00:00
|
|
|
/**
|
2004-01-03 21:22:07 +00:00
|
|
|
* Blit the dirty data from the given VirtScreen to the display. If the camera moved,
|
2003-05-30 20:13:29 +00:00
|
|
|
* a full blit is done, otherwise only the visible dirty areas are updated.
|
|
|
|
*/
|
2005-03-25 01:27:28 +00:00
|
|
|
void ScummEngine::updateDirtyScreen(VirtScreenNumber slot) {
|
2007-09-08 11:15:27 +00:00
|
|
|
VirtScreen *vs = &_virtscr[slot];
|
2005-03-25 01:27:28 +00:00
|
|
|
|
2004-01-03 21:22:07 +00:00
|
|
|
// Do nothing for unused virtual screens
|
2004-08-14 19:42:00 +00:00
|
|
|
if (vs->h == 0)
|
2001-10-09 14:30:12 +00:00
|
|
|
return;
|
|
|
|
|
2004-01-03 21:22:07 +00:00
|
|
|
int i;
|
|
|
|
int w = 8;
|
|
|
|
int start = 0;
|
|
|
|
|
2006-09-17 20:22:47 +00:00
|
|
|
for (i = 0; i < _gdi->_numStrips; i++) {
|
2004-01-03 21:22:07 +00:00
|
|
|
if (vs->bdirty[i]) {
|
|
|
|
const int top = vs->tdirty[i];
|
2004-01-05 00:45:17 +00:00
|
|
|
const int bottom = vs->bdirty[i];
|
2004-08-14 19:42:00 +00:00
|
|
|
vs->tdirty[i] = vs->h;
|
2004-01-03 21:22:07 +00:00
|
|
|
vs->bdirty[i] = 0;
|
2006-09-17 20:22:47 +00:00
|
|
|
if (i != (_gdi->_numStrips - 1) && vs->bdirty[i + 1] == bottom && vs->tdirty[i + 1] == top) {
|
2011-05-25 13:56:31 +00:00
|
|
|
// Simple optimizations: if two or more neighboring strips
|
2004-01-08 00:48:37 +00:00
|
|
|
// form one bigger rectangle, coalesce them.
|
2004-01-03 21:22:07 +00:00
|
|
|
w += 8;
|
|
|
|
continue;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
2004-01-08 00:48:37 +00:00
|
|
|
drawStripToScreen(vs, start * 8, w, top, bottom);
|
2004-01-03 21:22:07 +00:00
|
|
|
w = 8;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
2004-01-03 21:22:07 +00:00
|
|
|
start = i + 1;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-05-30 20:13:29 +00:00
|
|
|
/**
|
|
|
|
* Blit the specified rectangle from the given virtual screen to the display.
|
2004-01-08 00:48:37 +00:00
|
|
|
* Note: t and b are in *virtual screen* coordinates, while x is relative to
|
|
|
|
* the *real screen*. This is due to the way tdirty/vdirty work: they are
|
|
|
|
* arrays which map 'strips' (sections of the real screen) to dirty areas as
|
|
|
|
* specified by top/bottom coordinate in the virtual screen.
|
2003-05-30 20:13:29 +00:00
|
|
|
*/
|
2005-03-25 01:27:28 +00:00
|
|
|
void ScummEngine::drawStripToScreen(VirtScreen *vs, int x, int width, int top, int bottom) {
|
2002-04-23 23:58:31 +00:00
|
|
|
|
2007-07-08 21:42:39 +00:00
|
|
|
// Short-circuit if nothing has to be drawn
|
|
|
|
if (bottom <= top || top >= vs->h)
|
2001-10-26 17:34:50 +00:00
|
|
|
return;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2007-07-08 21:42:39 +00:00
|
|
|
// Some paranoia checks
|
|
|
|
assert(top >= 0 && bottom <= vs->h);
|
2004-09-24 07:36:29 +00:00
|
|
|
assert(x >= 0 && width <= vs->pitch);
|
2013-08-03 00:36:43 +00:00
|
|
|
assert(_textSurface.getPixels());
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2007-07-08 21:42:39 +00:00
|
|
|
// Perform some clipping
|
2004-09-27 22:29:35 +00:00
|
|
|
if (width > vs->w - x)
|
2004-09-26 12:49:43 +00:00
|
|
|
width = vs->w - x;
|
2005-03-25 01:27:28 +00:00
|
|
|
if (top < _screenTop)
|
|
|
|
top = _screenTop;
|
|
|
|
if (bottom > _screenTop + _screenHeight)
|
|
|
|
bottom = _screenTop + _screenHeight;
|
2004-08-10 23:51:52 +00:00
|
|
|
|
|
|
|
// Convert the vertical coordinates to real screen coords
|
2005-03-25 01:27:28 +00:00
|
|
|
int y = vs->topline + top - _screenTop;
|
2005-02-20 00:17:22 +00:00
|
|
|
int height = bottom - top;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2007-07-25 19:56:43 +00:00
|
|
|
if (width <= 0 || height <= 0)
|
2005-11-08 22:15:49 +00:00
|
|
|
return;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2009-07-01 20:51:04 +00:00
|
|
|
const void *src = vs->getPixels(x, top);
|
2007-07-10 00:39:12 +00:00
|
|
|
int m = _textSurfaceMultiplier;
|
|
|
|
int vsPitch;
|
2007-07-09 21:56:35 +00:00
|
|
|
int pitch = vs->pitch;
|
2011-04-17 15:29:09 +00:00
|
|
|
vsPitch = vs->pitch - width * vs->format.bytesPerPixel;
|
2007-07-10 00:39:12 +00:00
|
|
|
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2007-07-09 21:56:35 +00:00
|
|
|
if (_game.version < 7) {
|
2007-07-08 22:13:50 +00:00
|
|
|
// For The Dig, FT and COMI, we just blit everything to the screen at once.
|
|
|
|
// For older games, things are more complicated. First off, we need to
|
|
|
|
// deal with the _textSurface, which needs to be composited over the
|
|
|
|
// screen contents. Secondly, a rendering mode might be active, which
|
|
|
|
// means a filter has to be applied.
|
|
|
|
|
2007-07-09 09:21:25 +00:00
|
|
|
// Compute pointer to the text surface
|
2007-07-08 22:13:50 +00:00
|
|
|
assert(_compositeBuf);
|
2009-07-01 20:51:04 +00:00
|
|
|
const void *text = _textSurface.getBasePtr(x * m, y * m);
|
2007-07-08 22:13:50 +00:00
|
|
|
|
2007-07-09 21:56:35 +00:00
|
|
|
// The values x, width, etc. are all multiples of 8 at this point,
|
|
|
|
// so loop unrolloing might be a good idea...
|
2009-03-19 22:49:26 +00:00
|
|
|
assert(IS_ALIGNED(text, 4));
|
2007-07-09 21:56:35 +00:00
|
|
|
assert(0 == (width & 3));
|
|
|
|
|
|
|
|
// Compose the text over the game graphics
|
2010-10-05 19:04:52 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_game.platform == Common::kPlatformFMTowns) {
|
|
|
|
towns_drawStripToScreen(vs, x, y, x, top, width, height);
|
2011-06-19 22:59:48 +00:00
|
|
|
return;
|
2010-10-05 19:04:52 +00:00
|
|
|
} else
|
2011-06-19 22:59:48 +00:00
|
|
|
#endif
|
2011-06-15 20:01:24 +00:00
|
|
|
if (_outputPixelFormat.bytesPerPixel == 2) {
|
2009-10-28 04:57:54 +00:00
|
|
|
const byte *srcPtr = (const byte *)src;
|
|
|
|
const byte *textPtr = (byte *)_textSurface.getBasePtr(x * m, y * m);
|
|
|
|
byte *dstPtr = _compositeBuf;
|
|
|
|
|
|
|
|
for (int h = 0; h < height * m; ++h) {
|
|
|
|
for (int w = 0; w < width * m; ++w) {
|
|
|
|
uint16 tmp = *textPtr++;
|
2009-11-22 08:36:14 +00:00
|
|
|
if (tmp == CHARSET_MASK_TRANSPARENCY) {
|
2009-10-28 04:57:54 +00:00
|
|
|
tmp = READ_UINT16(srcPtr);
|
2009-11-22 08:36:14 +00:00
|
|
|
WRITE_UINT16(dstPtr, tmp); dstPtr += 2;
|
|
|
|
} else if (_game.heversion != 0) {
|
|
|
|
error ("16Bit Color HE Game using old charset");
|
|
|
|
} else {
|
|
|
|
WRITE_UINT16(dstPtr, _16BitPalette[tmp]); dstPtr += 2;
|
|
|
|
}
|
2011-04-17 15:29:09 +00:00
|
|
|
srcPtr += vs->format.bytesPerPixel;
|
2009-06-04 01:05:47 +00:00
|
|
|
}
|
2009-10-28 04:57:54 +00:00
|
|
|
srcPtr += vsPitch;
|
|
|
|
textPtr += _textSurface.pitch - width * m;
|
2009-06-04 01:05:47 +00:00
|
|
|
}
|
2012-02-26 11:59:19 +00:00
|
|
|
} else {
|
2011-06-18 11:12:13 +00:00
|
|
|
#ifdef USE_ARM_GFX_ASM
|
2012-02-26 11:59:19 +00:00
|
|
|
asmDrawStripToScreen(height, width, text, src, _compositeBuf, vs->pitch, width, _textSurface.pitch);
|
2011-06-18 11:12:13 +00:00
|
|
|
#else
|
2009-10-28 04:57:54 +00:00
|
|
|
// We blit four pixels at a time, for improved performance.
|
|
|
|
const uint32 *src32 = (const uint32 *)src;
|
|
|
|
uint32 *dst32 = (uint32 *)_compositeBuf;
|
|
|
|
|
|
|
|
vsPitch >>= 2;
|
|
|
|
|
2009-06-04 01:05:47 +00:00
|
|
|
const uint32 *text32 = (const uint32 *)text;
|
|
|
|
const int textPitch = (_textSurface.pitch - width * m) >> 2;
|
|
|
|
for (int h = height * m; h > 0; --h) {
|
|
|
|
for (int w = width * m; w > 0; w -= 4) {
|
|
|
|
uint32 temp = *text32++;
|
|
|
|
|
|
|
|
// Generate a byte mask for those text pixels (bytes) with
|
|
|
|
// value CHARSET_MASK_TRANSPARENCY. In the end, each byte
|
|
|
|
// in mask will be either equal to 0x00 or 0xFF.
|
|
|
|
// Doing it this way avoids branches and bytewise operations,
|
|
|
|
// at the cost of readability ;).
|
|
|
|
uint32 mask = temp ^ CHARSET_MASK_TRANSPARENCY_32;
|
|
|
|
mask = (((mask & 0x7f7f7f7f) + 0x7f7f7f7f) | mask) & 0x80808080;
|
|
|
|
mask = ((mask >> 7) + 0x7f7f7f7f) ^ 0x80808080;
|
|
|
|
|
|
|
|
// The following line is equivalent to this code:
|
|
|
|
// *dst32++ = (*src32++ & mask) | (temp & ~mask);
|
|
|
|
// However, some compilers can generate somewhat better
|
|
|
|
// machine code for this equivalent statement:
|
|
|
|
*dst32++ = ((temp ^ *src32++) & mask) ^ temp;
|
|
|
|
}
|
|
|
|
src32 += vsPitch;
|
|
|
|
text32 += textPitch;
|
2006-01-02 23:36:33 +00:00
|
|
|
}
|
2006-07-09 11:47:17 +00:00
|
|
|
#endif
|
2012-02-26 11:59:19 +00:00
|
|
|
}
|
2007-07-09 09:21:25 +00:00
|
|
|
src = _compositeBuf;
|
2011-04-17 15:29:09 +00:00
|
|
|
pitch = width * vs->format.bytesPerPixel;
|
2007-07-08 22:13:50 +00:00
|
|
|
|
|
|
|
if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
|
2007-07-09 09:21:25 +00:00
|
|
|
ditherHerc(_compositeBuf, _herculesBuf, width, &x, &y, &width, &height);
|
2007-07-08 22:13:50 +00:00
|
|
|
|
2011-06-21 14:57:42 +00:00
|
|
|
src = _herculesBuf + x + y * kHercWidth;
|
|
|
|
pitch = kHercWidth;
|
2007-07-08 22:13:50 +00:00
|
|
|
|
|
|
|
// center image on the screen
|
2011-06-21 14:57:42 +00:00
|
|
|
x += (kHercWidth - _screenWidth * 2) / 2; // (720 - 320*2)/2 = 40
|
2007-07-10 00:39:12 +00:00
|
|
|
} else if (_useCJKMode && m == 2) {
|
|
|
|
pitch *= m;
|
|
|
|
x *= m;
|
|
|
|
y *= m;
|
|
|
|
width *= m;
|
|
|
|
height *= m;
|
2007-07-08 22:13:50 +00:00
|
|
|
} else {
|
|
|
|
if (_renderMode == Common::kRenderCGA)
|
2007-07-09 09:21:25 +00:00
|
|
|
ditherCGA(_compositeBuf, width, x, y, width, height);
|
2007-07-08 22:13:50 +00:00
|
|
|
|
|
|
|
// HACK: This is dirty hack which renders narrow NES rooms centered
|
|
|
|
// NES can address negative number strips and that poses problem for
|
|
|
|
// our code. So instead of adding zillions of fixes and potentially
|
|
|
|
// breaking other games, we shift it right at the rendering stage.
|
|
|
|
if ((_game.platform == Common::kPlatformNES) && (((_NESStartStrip > 0) && (vs->number == kMainVirtScreen)) || (vs->number == kTextVirtScreen))) {
|
|
|
|
x += 16;
|
|
|
|
while (x + width >= _screenWidth)
|
|
|
|
width -= 16;
|
2008-08-02 21:57:35 +00:00
|
|
|
if (width <= 0)
|
2007-07-08 22:13:50 +00:00
|
|
|
return;
|
2009-08-11 10:28:15 +00:00
|
|
|
|
|
|
|
// HACK: In this way we won't get a screen with dirty side strips when
|
|
|
|
// loading a narrow room in a full screen room.
|
2010-01-25 01:39:44 +00:00
|
|
|
if (width == 224 && height == 240 && x == 16) {
|
2009-08-11 10:28:15 +00:00
|
|
|
char blackbuf[16 * 240];
|
2009-08-11 10:51:49 +00:00
|
|
|
memset(blackbuf, 0, 16 * 240); // Prepare a buffer 16px wide and 240px high, to fit on a lateral strip
|
2009-08-11 10:28:15 +00:00
|
|
|
|
|
|
|
width = 240; // Fix right strip
|
2012-06-16 00:36:31 +00:00
|
|
|
_system->copyRectToScreen(blackbuf, 16, 0, 0, 16, 240); // Fix left strip
|
2009-08-11 10:28:15 +00:00
|
|
|
}
|
2007-07-08 22:13:50 +00:00
|
|
|
}
|
|
|
|
|
2005-03-24 03:22:32 +00:00
|
|
|
}
|
2005-02-20 00:17:22 +00:00
|
|
|
}
|
2007-07-09 21:56:35 +00:00
|
|
|
|
|
|
|
// Finally blit the whole thing to the screen
|
2012-06-16 00:36:31 +00:00
|
|
|
_system->copyRectToScreen(src, pitch, x, y, width, height);
|
2002-12-15 23:40:37 +00:00
|
|
|
}
|
|
|
|
|
2005-02-20 00:17:22 +00:00
|
|
|
// CGA
|
|
|
|
// indy3 loom maniac monkey1 zak
|
|
|
|
//
|
|
|
|
// Herc (720x350)
|
|
|
|
// maniac monkey1 zak
|
|
|
|
//
|
|
|
|
// EGA
|
|
|
|
// monkey2 loom maniac monkey1 atlantis indy3 zak loomcd
|
|
|
|
|
2007-02-02 12:51:44 +00:00
|
|
|
static const byte cgaDither[2][2][16] = {
|
|
|
|
{{0, 1, 0, 1, 2, 2, 0, 0, 3, 1, 3, 1, 3, 2, 1, 3},
|
|
|
|
{0, 0, 1, 1, 0, 2, 2, 3, 0, 3, 1, 1, 3, 3, 1, 3}},
|
|
|
|
{{0, 0, 1, 1, 0, 2, 2, 3, 0, 3, 1, 1, 3, 3, 1, 3},
|
|
|
|
{0, 1, 0, 1, 2, 2, 0, 0, 3, 1, 1, 1, 3, 2, 1, 3}}};
|
|
|
|
|
2005-02-20 00:17:22 +00:00
|
|
|
// CGA dithers 4x4 square with direct substitutes
|
|
|
|
// Odd lines have colors swapped, so there will be checkered patterns.
|
|
|
|
// But apparently there is a mistake for 10th color.
|
2005-03-28 20:18:36 +00:00
|
|
|
void ScummEngine::ditherCGA(byte *dst, int dstPitch, int x, int y, int width, int height) const {
|
2005-02-20 00:17:22 +00:00
|
|
|
byte *ptr;
|
|
|
|
int idx1, idx2;
|
|
|
|
|
|
|
|
for (int y1 = 0; y1 < height; y1++) {
|
|
|
|
ptr = dst + y1 * dstPitch;
|
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.version == 2)
|
2005-02-20 01:37:47 +00:00
|
|
|
idx1 = 0;
|
2007-07-08 21:42:39 +00:00
|
|
|
else
|
|
|
|
idx1 = (y + y1) % 2;
|
2005-02-20 01:37:47 +00:00
|
|
|
|
2005-02-20 00:17:22 +00:00
|
|
|
for (int x1 = 0; x1 < width; x1++) {
|
|
|
|
idx2 = (x + x1) % 2;
|
2005-06-21 16:46:04 +00:00
|
|
|
*ptr = cgaDither[idx1][idx2][*ptr & 0xF];
|
|
|
|
ptr++;
|
2005-02-20 00:17:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hercules dithering. It uses same dithering tables but output is 1bpp and
|
|
|
|
// it stretches in this way:
|
|
|
|
// aaaa0
|
|
|
|
// aa aaaa1
|
|
|
|
// bb bbbb0 Here 0 and 1 mean dithering table row number
|
|
|
|
// cc --> bbbb1
|
|
|
|
// dd cccc0
|
|
|
|
// cccc1
|
|
|
|
// dddd0
|
2007-07-08 21:42:39 +00:00
|
|
|
void ditherHerc(byte *src, byte *hercbuf, int srcPitch, int *x, int *y, int *width, int *height) {
|
2005-02-20 00:17:22 +00:00
|
|
|
byte *srcptr, *dstptr;
|
2007-07-08 21:42:39 +00:00
|
|
|
const int xo = *x, yo = *y, widtho = *width, heighto = *height;
|
|
|
|
int dsty = yo*2 - yo/4;
|
|
|
|
|
|
|
|
for (int y1 = 0; y1 < heighto;) {
|
2011-06-21 14:57:42 +00:00
|
|
|
assert(dsty < kHercHeight);
|
2005-02-20 00:17:22 +00:00
|
|
|
|
|
|
|
srcptr = src + y1 * srcPitch;
|
2011-06-21 14:57:42 +00:00
|
|
|
dstptr = hercbuf + dsty * kHercWidth + xo * 2;
|
2005-02-20 00:17:22 +00:00
|
|
|
|
2007-07-08 21:42:39 +00:00
|
|
|
const int idx1 = (dsty % 7) % 2;
|
2005-02-20 00:17:22 +00:00
|
|
|
for (int x1 = 0; x1 < widtho; x1++) {
|
2007-07-08 21:42:39 +00:00
|
|
|
const int idx2 = (xo + x1) % 2;
|
|
|
|
const byte tmp = cgaDither[idx1][idx2][*srcptr & 0xF];
|
|
|
|
*dstptr++ = tmp >> 1;
|
|
|
|
*dstptr++ = tmp & 0x1;
|
2005-02-20 00:17:22 +00:00
|
|
|
srcptr++;
|
|
|
|
}
|
|
|
|
if (idx1 || dsty % 7 == 6)
|
|
|
|
y1++;
|
|
|
|
dsty++;
|
|
|
|
}
|
2007-07-08 21:42:39 +00:00
|
|
|
|
|
|
|
*x *= 2;
|
|
|
|
*y = yo*2 - yo/4;
|
|
|
|
*width *= 2;
|
|
|
|
*height = dsty - *y;
|
2005-02-20 00:17:22 +00:00
|
|
|
}
|
|
|
|
|
2002-12-15 23:40:37 +00:00
|
|
|
#pragma mark -
|
2004-01-04 14:35:46 +00:00
|
|
|
#pragma mark --- Background buffers & charset mask ---
|
|
|
|
#pragma mark -
|
|
|
|
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine::initBGBuffers(int height) {
|
2003-05-28 20:01:47 +00:00
|
|
|
const byte *ptr;
|
2002-12-15 23:40:37 +00:00
|
|
|
int size, itemsize, i;
|
|
|
|
byte *room;
|
2002-12-09 01:27:40 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.version >= 7) {
|
2004-01-05 00:03:18 +00:00
|
|
|
// Resize main virtual screen in V7 games. This is necessary
|
|
|
|
// because in V7, rooms may be higher than one screen, so we have
|
|
|
|
// to accomodate for that.
|
2007-09-08 11:15:27 +00:00
|
|
|
initVirtScreen(kMainVirtScreen, _virtscr[kMainVirtScreen].topline, _screenWidth, height, true, true);
|
2004-01-05 00:03:18 +00:00
|
|
|
}
|
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.heversion >= 70)
|
2004-08-30 00:10:36 +00:00
|
|
|
room = getResourceAddress(rtRoomImage, _roomResource);
|
2004-06-23 01:36:57 +00:00
|
|
|
else
|
|
|
|
room = getResourceAddress(rtRoom, _roomResource);
|
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.version <= 3) {
|
2006-09-17 20:22:47 +00:00
|
|
|
_gdi->_numZBuffer = 2;
|
2006-02-20 16:51:30 +00:00
|
|
|
} else if (_game.features & GF_SMALL_HEADER) {
|
2002-12-15 23:40:37 +00:00
|
|
|
int off;
|
2011-04-12 14:53:15 +00:00
|
|
|
ptr = findResourceData(MKTAG('S','M','A','P'), room);
|
2006-09-17 20:22:47 +00:00
|
|
|
_gdi->_numZBuffer = 0;
|
2003-04-24 18:53:21 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.features & GF_16COLOR)
|
2003-04-24 18:53:21 +00:00
|
|
|
off = READ_LE_UINT16(ptr);
|
|
|
|
else
|
2003-04-09 19:14:05 +00:00
|
|
|
off = READ_LE_UINT32(ptr);
|
2003-04-24 18:53:21 +00:00
|
|
|
|
2006-09-17 20:22:47 +00:00
|
|
|
while (off && _gdi->_numZBuffer < 4) {
|
|
|
|
_gdi->_numZBuffer++;
|
2003-04-24 18:53:21 +00:00
|
|
|
ptr += off;
|
|
|
|
off = READ_LE_UINT16(ptr);
|
2002-12-15 23:40:37 +00:00
|
|
|
}
|
2006-02-20 16:51:30 +00:00
|
|
|
} else if (_game.version == 8) {
|
2002-12-24 07:53:29 +00:00
|
|
|
// in V8 there is no RMIH and num z buffers is in RMHD
|
2011-04-12 14:53:15 +00:00
|
|
|
ptr = findResource(MKTAG('R','M','H','D'), room);
|
2006-09-17 20:22:47 +00:00
|
|
|
_gdi->_numZBuffer = READ_LE_UINT32(ptr + 24) + 1;
|
2006-02-20 16:51:30 +00:00
|
|
|
} else if (_game.heversion >= 70) {
|
2011-04-12 14:53:15 +00:00
|
|
|
ptr = findResource(MKTAG('R','M','I','H'), room);
|
2006-09-17 20:22:47 +00:00
|
|
|
_gdi->_numZBuffer = READ_LE_UINT16(ptr + 8) + 1;
|
2002-12-15 23:40:37 +00:00
|
|
|
} else {
|
2011-04-12 14:53:15 +00:00
|
|
|
ptr = findResource(MKTAG('R','M','I','H'), findResource(MKTAG('R','M','I','M'), room));
|
2006-09-17 20:22:47 +00:00
|
|
|
_gdi->_numZBuffer = READ_LE_UINT16(ptr + 8) + 1;
|
2002-12-15 23:40:37 +00:00
|
|
|
}
|
2006-09-17 20:22:47 +00:00
|
|
|
assert(_gdi->_numZBuffer >= 1 && _gdi->_numZBuffer <= 8);
|
2001-12-27 17:51:58 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.version >= 7)
|
2006-09-17 20:22:47 +00:00
|
|
|
itemsize = (_roomHeight + 10) * _gdi->_numStrips;
|
2002-12-15 23:40:37 +00:00
|
|
|
else
|
2006-09-17 20:22:47 +00:00
|
|
|
itemsize = (_roomHeight + 4) * _gdi->_numStrips;
|
2001-12-27 17:51:58 +00:00
|
|
|
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2006-09-17 20:22:47 +00:00
|
|
|
size = itemsize * _gdi->_numZBuffer;
|
2006-09-17 20:36:48 +00:00
|
|
|
memset(_res->createResource(rtBuffer, 9, size), 0, size);
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2006-09-17 20:22:47 +00:00
|
|
|
for (i = 0; i < (int)ARRAYSIZE(_gdi->_imgBufOffs); i++) {
|
|
|
|
if (i < _gdi->_numZBuffer)
|
|
|
|
_gdi->_imgBufOffs[i] = i * itemsize;
|
2002-12-15 23:40:37 +00:00
|
|
|
else
|
2006-09-17 20:22:47 +00:00
|
|
|
_gdi->_imgBufOffs[i] = (_gdi->_numZBuffer - 1) * itemsize;
|
2002-12-15 23:40:37 +00:00
|
|
|
}
|
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2003-05-30 20:13:29 +00:00
|
|
|
/**
|
|
|
|
* Redraw background as needed, i.e. the left/right sides if scrolling took place etc.
|
|
|
|
* Note that this only updated the virtual screen, not the actual display.
|
|
|
|
*/
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine::redrawBGAreas() {
|
2001-10-09 14:30:12 +00:00
|
|
|
int i;
|
2002-03-06 12:24:56 +00:00
|
|
|
int diff;
|
2004-10-17 04:35:36 +00:00
|
|
|
int val = 0;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2007-02-10 02:05:59 +00:00
|
|
|
if (_game.id != GID_PASS && _game.version >= 4 && _game.version <= 6) {
|
2007-02-02 12:51:44 +00:00
|
|
|
// Starting with V4 games (with the exception of the PASS demo), text
|
|
|
|
// is drawn over the game graphics (as opposed to be drawn in a
|
|
|
|
// separate region of the screen). So, when scrolling in one of these
|
|
|
|
// games (pre-new camera system), if actor text is visible (as indicated
|
|
|
|
// by the _hasMask flag), we first remove it before proceeding.
|
2007-02-10 02:05:59 +00:00
|
|
|
if (camera._cur.x != camera._last.x && _charset->_hasMask)
|
2002-03-05 23:41:41 +00:00
|
|
|
stopTalk();
|
2007-02-02 12:51:44 +00:00
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-12-21 01:11:42 +00:00
|
|
|
// Redraw parts of the background which are marked as dirty.
|
2004-09-18 22:42:45 +00:00
|
|
|
if (!_fullRedraw && _bgNeedsRedraw) {
|
2006-09-17 20:22:47 +00:00
|
|
|
for (i = 0; i != _gdi->_numStrips; i++) {
|
2003-01-14 10:06:56 +00:00
|
|
|
if (testGfxUsageBit(_screenStartStrip + i, USAGE_BIT_DIRTY)) {
|
2001-10-09 14:30:12 +00:00
|
|
|
redrawBGStrip(i, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-02-10 02:05:59 +00:00
|
|
|
if (_game.version >= 7) {
|
2003-11-16 20:52:57 +00:00
|
|
|
diff = camera._cur.x / 8 - camera._last.x / 8;
|
2006-09-17 20:22:47 +00:00
|
|
|
if (_fullRedraw || ABS(diff) >= _gdi->_numStrips) {
|
2004-09-18 22:42:45 +00:00
|
|
|
_bgNeedsRedraw = false;
|
2006-09-17 20:22:47 +00:00
|
|
|
redrawBGStrip(0, _gdi->_numStrips);
|
2005-11-18 00:01:46 +00:00
|
|
|
} else if (diff > 0) {
|
|
|
|
val = -diff;
|
2006-09-17 20:22:47 +00:00
|
|
|
redrawBGStrip(_gdi->_numStrips - diff, diff);
|
2005-11-18 00:01:46 +00:00
|
|
|
} else if (diff < 0) {
|
|
|
|
val = -diff;
|
|
|
|
redrawBGStrip(0, -diff);
|
2002-03-05 23:41:41 +00:00
|
|
|
}
|
|
|
|
} else {
|
2005-11-18 00:01:46 +00:00
|
|
|
diff = camera._cur.x - camera._last.x;
|
|
|
|
if (!_fullRedraw && diff == 8) {
|
|
|
|
val = -1;
|
2006-09-17 20:22:47 +00:00
|
|
|
redrawBGStrip(_gdi->_numStrips - 1, 1);
|
2005-11-18 00:01:46 +00:00
|
|
|
} else if (!_fullRedraw && diff == -8) {
|
|
|
|
val = +1;
|
2002-03-05 23:41:41 +00:00
|
|
|
redrawBGStrip(0, 1);
|
2005-11-18 00:01:46 +00:00
|
|
|
} else if (_fullRedraw || diff != 0) {
|
2006-06-19 07:45:40 +00:00
|
|
|
if (_game.version <= 5) {
|
|
|
|
((ScummEngine_v5 *)this)->clearFlashlight();
|
|
|
|
}
|
2004-09-18 22:42:45 +00:00
|
|
|
_bgNeedsRedraw = false;
|
2006-09-17 20:22:47 +00:00
|
|
|
redrawBGStrip(0, _gdi->_numStrips);
|
2002-03-05 23:41:41 +00:00
|
|
|
}
|
2001-12-27 17:51:58 +00:00
|
|
|
}
|
|
|
|
|
2001-10-09 14:30:12 +00:00
|
|
|
drawRoomObjects(val);
|
2004-09-18 22:42:45 +00:00
|
|
|
_bgNeedsRedraw = false;
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2008-05-06 03:00:26 +00:00
|
|
|
#ifdef ENABLE_HE
|
2005-04-29 01:36:30 +00:00
|
|
|
void ScummEngine_v71he::redrawBGAreas() {
|
2004-10-17 05:04:49 +00:00
|
|
|
if (camera._cur.x != camera._last.x && _charset->_hasMask)
|
|
|
|
stopTalk();
|
|
|
|
|
|
|
|
byte *room = getResourceAddress(rtRoomImage, _roomResource) + _IM00_offs;
|
2005-04-02 14:24:43 +00:00
|
|
|
if (_fullRedraw) {
|
|
|
|
_bgNeedsRedraw = false;
|
2007-09-08 11:15:27 +00:00
|
|
|
_gdi->drawBMAPBg(room, &_virtscr[kMainVirtScreen]);
|
2004-10-17 05:04:49 +00:00
|
|
|
}
|
|
|
|
|
2005-04-02 14:24:43 +00:00
|
|
|
drawRoomObjects(0);
|
2004-10-17 05:04:49 +00:00
|
|
|
_bgNeedsRedraw = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScummEngine_v72he::redrawBGAreas() {
|
2005-04-29 01:45:38 +00:00
|
|
|
ScummEngine_v71he::redrawBGAreas();
|
2005-05-23 03:33:08 +00:00
|
|
|
_wiz->flushWizBuffer();
|
2004-10-17 05:04:49 +00:00
|
|
|
}
|
2005-05-14 14:06:37 +00:00
|
|
|
#endif
|
2004-10-17 05:04:49 +00:00
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine::redrawBGStrip(int start, int num) {
|
2004-06-23 01:36:57 +00:00
|
|
|
byte *room;
|
|
|
|
|
2002-12-15 23:40:37 +00:00
|
|
|
int s = _screenStartStrip + start;
|
|
|
|
|
|
|
|
for (int i = 0; i < num; i++)
|
2003-01-14 10:06:56 +00:00
|
|
|
setGfxUsageBit(s + i, USAGE_BIT_DIRTY);
|
2002-12-15 23:40:37 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.heversion >= 70)
|
2004-08-30 00:10:36 +00:00
|
|
|
room = getResourceAddress(rtRoomImage, _roomResource);
|
2004-06-23 01:36:57 +00:00
|
|
|
else
|
|
|
|
room = getResourceAddress(rtRoom, _roomResource);
|
|
|
|
|
2007-09-08 11:15:27 +00:00
|
|
|
_gdi->drawBitmap(room + _IM00_offs, &_virtscr[kMainVirtScreen], s, 0, _roomWidth, _virtscr[kMainVirtScreen].h, s, num, 0);
|
2002-12-15 23:40:37 +00:00
|
|
|
}
|
|
|
|
|
2006-09-17 23:35:09 +00:00
|
|
|
void ScummEngine::restoreBackground(Common::Rect rect, byte backColor) {
|
2002-12-15 23:40:37 +00:00
|
|
|
VirtScreen *vs;
|
2004-04-08 23:43:30 +00:00
|
|
|
byte *screenBuf;
|
2002-12-15 23:40:37 +00:00
|
|
|
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (rect.top < 0)
|
2003-05-15 22:30:32 +00:00
|
|
|
rect.top = 0;
|
2003-06-08 15:17:14 +00:00
|
|
|
if (rect.left >= rect.right || rect.top >= rect.bottom)
|
|
|
|
return;
|
2002-12-15 23:40:37 +00:00
|
|
|
|
2003-05-15 22:30:32 +00:00
|
|
|
if ((vs = findVirtScreen(rect.top)) == NULL)
|
2002-12-15 23:40:37 +00:00
|
|
|
return;
|
|
|
|
|
2004-08-14 19:42:00 +00:00
|
|
|
if (rect.left > vs->w)
|
2004-01-08 03:24:41 +00:00
|
|
|
return;
|
2011-06-19 22:59:48 +00:00
|
|
|
|
2011-08-26 03:51:08 +00:00
|
|
|
// Indy4 Amiga always uses the room or verb palette map to match colors to
|
|
|
|
// the currently setup palette, thus we need to select it over here too.
|
|
|
|
// Done like the original interpreter.
|
|
|
|
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
|
|
|
if (vs->number == kVerbVirtScreen)
|
|
|
|
backColor = _verbPalette[backColor];
|
|
|
|
else
|
|
|
|
backColor = _roomPalette[backColor];
|
|
|
|
}
|
|
|
|
|
2004-04-08 23:43:30 +00:00
|
|
|
// Convert 'rect' to local (virtual screen) coordinates
|
|
|
|
rect.top -= vs->topline;
|
|
|
|
rect.bottom -= vs->topline;
|
2002-12-15 23:40:37 +00:00
|
|
|
|
2004-08-14 19:42:00 +00:00
|
|
|
rect.clip(vs->w, vs->h);
|
2002-12-15 23:40:37 +00:00
|
|
|
|
2010-10-17 13:08:00 +00:00
|
|
|
const int height = rect.height();
|
|
|
|
const int width = rect.width();
|
|
|
|
|
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
|
|
|
if (_game.platform == Common::kPlatformFMTowns && _game.id == GID_MONKEY && vs->number == kVerbVirtScreen && rect.bottom <= 154)
|
2010-11-05 00:36:23 +00:00
|
|
|
rect.right = 319;
|
2010-10-17 13:08:00 +00:00
|
|
|
#endif
|
|
|
|
|
2004-01-08 03:24:41 +00:00
|
|
|
markRectAsDirty(vs->number, rect, USAGE_BIT_RESTORED);
|
2002-12-15 23:40:37 +00:00
|
|
|
|
2004-08-14 19:42:00 +00:00
|
|
|
screenBuf = vs->getPixels(rect.left, rect.top);
|
2002-12-15 23:40:37 +00:00
|
|
|
|
2004-04-08 23:43:30 +00:00
|
|
|
if (!height)
|
|
|
|
return;
|
2002-12-15 23:40:37 +00:00
|
|
|
|
2004-01-08 21:44:03 +00:00
|
|
|
if (vs->hasTwoBuffers && _currentRoom != 0 && isLightOn()) {
|
2011-04-17 15:29:09 +00:00
|
|
|
blit(screenBuf, vs->pitch, vs->getBackPixels(rect.left, rect.top), vs->pitch, width, height, vs->format.bytesPerPixel);
|
2004-04-08 23:43:30 +00:00
|
|
|
if (vs->number == kMainVirtScreen && _charset->_hasMask) {
|
2010-10-05 19:04:52 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_game.platform == Common::kPlatformFMTowns) {
|
|
|
|
byte *mask = (byte *)_textSurface.getBasePtr(rect.left * _textSurfaceMultiplier, (rect.top + vs->topline) * _textSurfaceMultiplier);
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(mask, _textSurface.pitch, 0, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.format.bytesPerPixel);
|
2010-10-05 19:04:52 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
byte *mask = (byte *)_textSurface.getBasePtr(rect.left, rect.top - _screenTop);
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.format.bytesPerPixel);
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
}
|
2002-12-15 23:40:37 +00:00
|
|
|
}
|
|
|
|
} else {
|
2010-10-05 19:04:52 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_game.platform == Common::kPlatformFMTowns) {
|
|
|
|
backColor |= (backColor << 4);
|
|
|
|
byte *mask = (byte *)_textSurface.getBasePtr(rect.left * _textSurfaceMultiplier, (rect.top + vs->topline) * _textSurfaceMultiplier);
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(mask, _textSurface.pitch, backColor, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.format.bytesPerPixel);
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
}
|
2010-10-05 19:04:52 +00:00
|
|
|
#endif
|
2011-06-19 22:59:48 +00:00
|
|
|
|
2009-10-26 09:11:18 +00:00
|
|
|
if (_game.features & GF_16BIT_COLOR)
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(screenBuf, vs->pitch, _16BitPalette[backColor], width, height, vs->format.bytesPerPixel);
|
2009-10-26 09:11:18 +00:00
|
|
|
else
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(screenBuf, vs->pitch, backColor, width, height, vs->format.bytesPerPixel);
|
2002-12-15 23:40:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-01-28 20:11:31 +00:00
|
|
|
void ScummEngine::restoreCharsetBg() {
|
|
|
|
_nextLeft = _string[0].xpos;
|
|
|
|
_nextTop = _string[0].ypos + _screenTop;
|
2004-04-08 23:43:30 +00:00
|
|
|
|
2007-01-28 20:11:31 +00:00
|
|
|
if (_charset->_hasMask) {
|
|
|
|
_charset->_hasMask = false;
|
|
|
|
_charset->_str.left = -1;
|
|
|
|
_charset->_left = -1;
|
2004-01-08 21:21:40 +00:00
|
|
|
|
2004-04-08 23:43:30 +00:00
|
|
|
// Restore background on the whole text area. This code is based on
|
2006-09-17 23:35:09 +00:00
|
|
|
// restoreBackground(), but was changed to only restore those parts which are
|
2004-04-08 23:43:30 +00:00
|
|
|
// currently covered by the charset mask.
|
|
|
|
|
2007-09-08 11:15:27 +00:00
|
|
|
VirtScreen *vs = &_virtscr[_charset->_textScreenID];
|
2004-08-14 19:42:00 +00:00
|
|
|
if (!vs->h)
|
2004-04-08 23:43:30 +00:00
|
|
|
return;
|
|
|
|
|
2007-01-28 20:11:31 +00:00
|
|
|
markRectAsDirty(vs->number, Common::Rect(vs->w, vs->h), USAGE_BIT_RESTORED);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-08-14 19:42:00 +00:00
|
|
|
byte *screenBuf = vs->getPixels(0, 0);
|
2004-04-08 23:43:30 +00:00
|
|
|
|
2007-01-28 20:11:31 +00:00
|
|
|
if (vs->hasTwoBuffers && _currentRoom != 0 && isLightOn()) {
|
2004-11-21 17:47:05 +00:00
|
|
|
if (vs->number != kMainVirtScreen) {
|
2004-04-08 23:43:30 +00:00
|
|
|
// Restore from back buffer
|
2004-08-14 20:02:40 +00:00
|
|
|
const byte *backBuf = vs->getBackPixels(0, 0);
|
2011-04-17 15:29:09 +00:00
|
|
|
blit(screenBuf, vs->pitch, backBuf, vs->pitch, vs->w, vs->h, vs->format.bytesPerPixel);
|
2004-04-08 23:43:30 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Clear area
|
2005-03-24 03:22:32 +00:00
|
|
|
memset(screenBuf, 0, vs->h * vs->pitch);
|
2004-04-08 23:43:30 +00:00
|
|
|
}
|
2004-11-21 17:47:05 +00:00
|
|
|
|
|
|
|
if (vs->hasTwoBuffers) {
|
|
|
|
// Clean out the charset mask
|
2005-04-05 07:53:46 +00:00
|
|
|
clearTextSurface();
|
2004-11-21 17:47:05 +00:00
|
|
|
}
|
2004-04-08 23:43:30 +00:00
|
|
|
}
|
2004-01-08 21:21:40 +00:00
|
|
|
}
|
|
|
|
|
2007-01-28 20:11:31 +00:00
|
|
|
void ScummEngine::clearCharsetMask() {
|
|
|
|
memset(getResourceAddress(rtBuffer, 9), 0, _gdi->_imgBufOffs[1]);
|
2004-01-03 22:45:23 +00:00
|
|
|
}
|
|
|
|
|
2007-01-28 20:11:31 +00:00
|
|
|
void ScummEngine::clearTextSurface() {
|
2010-10-05 19:04:52 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_townsScreen)
|
|
|
|
_townsScreen->fillLayerRect(1, 0, 0, _textSurface.w, _textSurface.h, 0);
|
2010-10-05 19:04:52 +00:00
|
|
|
#endif
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
|
2013-08-03 00:36:43 +00:00
|
|
|
fill((byte *)_textSurface.getPixels(), _textSurface.pitch,
|
2010-10-05 19:04:52 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
|
|
|
_game.platform == Common::kPlatformFMTowns ? 0 :
|
2011-06-19 22:59:48 +00:00
|
|
|
#endif
|
2011-04-17 15:29:09 +00:00
|
|
|
CHARSET_MASK_TRANSPARENCY, _textSurface.w, _textSurface.h, _textSurface.format.bytesPerPixel);
|
2005-04-05 07:53:46 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
byte *ScummEngine::getMaskBuffer(int x, int y, int z) {
|
2007-09-08 11:15:27 +00:00
|
|
|
return _gdi->getMaskBuffer((x + _virtscr[kMainVirtScreen].xstart) / 8, y, z);
|
2002-12-15 23:40:37 +00:00
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2004-01-04 13:49:03 +00:00
|
|
|
byte *Gdi::getMaskBuffer(int x, int y, int z) {
|
|
|
|
return _vm->getResourceAddress(rtBuffer, 9)
|
|
|
|
+ x + y * _numStrips + _imgBufOffs[z];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#pragma mark -
|
|
|
|
#pragma mark --- Misc ---
|
|
|
|
#pragma mark -
|
|
|
|
|
2009-06-04 01:05:47 +00:00
|
|
|
static void blit(byte *dst, int dstPitch, const byte *src, int srcPitch, int w, int h, uint8 bitDepth) {
|
2004-09-18 21:40:07 +00:00
|
|
|
assert(w > 0);
|
2004-01-04 13:49:03 +00:00
|
|
|
assert(h > 0);
|
|
|
|
assert(src != NULL);
|
|
|
|
assert(dst != NULL);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2009-06-04 01:05:47 +00:00
|
|
|
if ((w * bitDepth == srcPitch) && (w * bitDepth == dstPitch)) {
|
|
|
|
memcpy(dst, src, w * h * bitDepth);
|
2004-08-14 19:42:00 +00:00
|
|
|
} else {
|
2004-01-04 13:49:03 +00:00
|
|
|
do {
|
2009-06-04 01:05:47 +00:00
|
|
|
memcpy(dst, src, w * bitDepth);
|
2004-08-14 19:42:00 +00:00
|
|
|
dst += dstPitch;
|
|
|
|
src += srcPitch;
|
2004-01-04 13:49:03 +00:00
|
|
|
} while (--h);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-04 01:05:47 +00:00
|
|
|
static void fill(byte *dst, int dstPitch, uint16 color, int w, int h, uint8 bitDepth) {
|
2004-08-15 16:07:30 +00:00
|
|
|
assert(h > 0);
|
|
|
|
assert(dst != NULL);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2009-06-04 01:05:47 +00:00
|
|
|
if (bitDepth == 2) {
|
2004-08-15 16:07:30 +00:00
|
|
|
do {
|
2009-06-04 01:05:47 +00:00
|
|
|
for (int i = 0; i < w; i++)
|
|
|
|
WRITE_UINT16(dst + i * 2, color);
|
2004-08-15 16:07:30 +00:00
|
|
|
dst += dstPitch;
|
|
|
|
} while (--h);
|
2009-06-04 01:05:47 +00:00
|
|
|
} else {
|
|
|
|
if (w == dstPitch) {
|
|
|
|
memset(dst, color, w * h);
|
|
|
|
} else {
|
|
|
|
do {
|
|
|
|
memset(dst, color, w);
|
|
|
|
dst += dstPitch;
|
|
|
|
} while (--h);
|
|
|
|
}
|
2004-08-15 16:07:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-16 11:37:36 +00:00
|
|
|
#ifdef USE_ARM_GFX_ASM
|
2007-07-10 20:20:50 +00:00
|
|
|
|
2009-08-21 22:29:28 +00:00
|
|
|
#define copy8Col(A,B,C,D,E) asmCopy8Col(A,B,C,D,E)
|
2007-07-10 20:20:50 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
|
2009-06-04 01:05:47 +00:00
|
|
|
static void copy8Col(byte *dst, int dstPitch, const byte *src, int height, uint8 bitDepth) {
|
2006-07-09 11:47:17 +00:00
|
|
|
|
2004-09-22 17:57:20 +00:00
|
|
|
do {
|
|
|
|
#if defined(SCUMM_NEED_ALIGNMENT)
|
2009-06-04 01:05:47 +00:00
|
|
|
memcpy(dst, src, 8 * bitDepth);
|
2004-09-22 17:57:20 +00:00
|
|
|
#else
|
|
|
|
((uint32 *)dst)[0] = ((const uint32 *)src)[0];
|
|
|
|
((uint32 *)dst)[1] = ((const uint32 *)src)[1];
|
2009-06-04 01:05:47 +00:00
|
|
|
if (bitDepth == 2) {
|
|
|
|
((uint32 *)dst)[2] = ((const uint32 *)src)[2];
|
|
|
|
((uint32 *)dst)[3] = ((const uint32 *)src)[3];
|
|
|
|
}
|
2004-09-22 17:57:20 +00:00
|
|
|
#endif
|
|
|
|
dst += dstPitch;
|
|
|
|
src += dstPitch;
|
|
|
|
} while (--height);
|
|
|
|
}
|
|
|
|
|
2008-08-16 11:37:36 +00:00
|
|
|
#endif /* USE_ARM_GFX_ASM */
|
2007-07-10 20:20:50 +00:00
|
|
|
|
2009-06-04 01:05:47 +00:00
|
|
|
static void clear8Col(byte *dst, int dstPitch, int height, uint8 bitDepth) {
|
2004-09-22 17:57:20 +00:00
|
|
|
do {
|
|
|
|
#if defined(SCUMM_NEED_ALIGNMENT)
|
2009-06-04 01:05:47 +00:00
|
|
|
memset(dst, 0, 8 * bitDepth);
|
2004-09-22 17:57:20 +00:00
|
|
|
#else
|
|
|
|
((uint32 *)dst)[0] = 0;
|
|
|
|
((uint32 *)dst)[1] = 0;
|
2009-06-04 01:05:47 +00:00
|
|
|
if (bitDepth == 2) {
|
|
|
|
((uint32 *)dst)[2] = 0;
|
|
|
|
((uint32 *)dst)[3] = 0;
|
|
|
|
}
|
2004-09-22 17:57:20 +00:00
|
|
|
#endif
|
|
|
|
dst += dstPitch;
|
|
|
|
} while (--height);
|
|
|
|
}
|
|
|
|
|
2004-01-04 13:49:03 +00:00
|
|
|
void ScummEngine::drawBox(int x, int y, int x2, int y2, int color) {
|
|
|
|
int width, height;
|
|
|
|
VirtScreen *vs;
|
|
|
|
byte *backbuff, *bgbuff;
|
|
|
|
|
|
|
|
if ((vs = findVirtScreen(y)) == NULL)
|
|
|
|
return;
|
|
|
|
|
2011-08-26 03:51:08 +00:00
|
|
|
// Indy4 Amiga always uses the room or verb palette map to match colors to
|
|
|
|
// the currently setup palette, thus we need to select it over here too.
|
|
|
|
// Done like the original interpreter.
|
|
|
|
if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) {
|
|
|
|
if (vs->number == kVerbVirtScreen)
|
|
|
|
color = _verbPalette[color];
|
|
|
|
else
|
|
|
|
color = _roomPalette[color];
|
|
|
|
}
|
|
|
|
|
2004-01-04 13:49:03 +00:00
|
|
|
if (x > x2)
|
|
|
|
SWAP(x, x2);
|
|
|
|
|
|
|
|
if (y > y2)
|
|
|
|
SWAP(y, y2);
|
|
|
|
|
|
|
|
x2++;
|
|
|
|
y2++;
|
|
|
|
|
|
|
|
// Adjust for the topline of the VirtScreen
|
|
|
|
y -= vs->topline;
|
|
|
|
y2 -= vs->topline;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-01-04 13:49:03 +00:00
|
|
|
// Clip the coordinates
|
|
|
|
if (x < 0)
|
|
|
|
x = 0;
|
2004-08-14 19:42:00 +00:00
|
|
|
else if (x >= vs->w)
|
2004-01-04 13:49:03 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (x2 < 0)
|
|
|
|
return;
|
2004-08-14 19:42:00 +00:00
|
|
|
else if (x2 > vs->w)
|
|
|
|
x2 = vs->w;
|
2004-01-04 13:49:03 +00:00
|
|
|
|
|
|
|
if (y < 0)
|
|
|
|
y = 0;
|
2004-08-14 19:42:00 +00:00
|
|
|
else if (y > vs->h)
|
2004-01-04 13:49:03 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (y2 < 0)
|
|
|
|
return;
|
2004-08-14 19:42:00 +00:00
|
|
|
else if (y2 > vs->h)
|
|
|
|
y2 = vs->h;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-10-03 17:25:24 +00:00
|
|
|
width = x2 - x;
|
|
|
|
height = y2 - y;
|
|
|
|
|
|
|
|
// This will happen in the Sam & Max intro - see bug #1039162 - where
|
|
|
|
// it would trigger an assertion in blit().
|
|
|
|
|
|
|
|
if (width <= 0 || height <= 0)
|
|
|
|
return;
|
|
|
|
|
2004-01-08 03:24:41 +00:00
|
|
|
markRectAsDirty(vs->number, x, x2, y, y2);
|
2004-01-04 13:49:03 +00:00
|
|
|
|
2004-08-14 19:42:00 +00:00
|
|
|
backbuff = vs->getPixels(x, y);
|
2005-05-22 10:38:57 +00:00
|
|
|
bgbuff = vs->getBackPixels(x, y);
|
2004-01-04 13:49:03 +00:00
|
|
|
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
// A check for -1 might be wrong in all cases since o5_drawBox() in its current form
|
|
|
|
// 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.
|
2010-10-05 19:04:52 +00:00
|
|
|
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
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_game.platform == Common::kPlatformFMTowns) {
|
2011-03-22 14:53:43 +00:00
|
|
|
if (color == 254)
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
towns_setupPalCycleField(x, y, x2, y2);
|
2010-10-05 19:04:52 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (vs->number != kMainVirtScreen)
|
|
|
|
error("can only copy bg to main window");
|
|
|
|
|
2011-04-17 15:29:09 +00:00
|
|
|
blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->format.bytesPerPixel);
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_charset->_hasMask) {
|
|
|
|
byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop) * _textSurfaceMultiplier);
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(mask, _textSurface.pitch, CHARSET_MASK_TRANSPARENCY, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.format.bytesPerPixel);
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
}
|
2005-03-06 23:36:37 +00:00
|
|
|
}
|
2008-01-06 13:27:42 +00:00
|
|
|
} else if (_game.heversion >= 72) {
|
2005-10-18 13:56:10 +00:00
|
|
|
// Flags are used for different methods in HE games
|
2007-03-23 03:06:10 +00:00
|
|
|
uint32 flags = color;
|
|
|
|
if ((flags & 0x2000) || (flags & 0x4000000)) {
|
2011-04-17 15:29:09 +00:00
|
|
|
blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->format.bytesPerPixel);
|
2007-03-23 03:06:10 +00:00
|
|
|
} else if ((flags & 0x4000) || (flags & 0x2000000)) {
|
2011-04-17 15:29:09 +00:00
|
|
|
blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height, vs->format.bytesPerPixel);
|
2007-03-23 03:06:10 +00:00
|
|
|
} else if ((flags & 0x8000) || (flags & 0x1000000)) {
|
|
|
|
flags &= (flags & 0x1000000) ? 0xFFFFFF : 0x7FFF;
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(backbuff, vs->pitch, flags, width, height, vs->format.bytesPerPixel);
|
|
|
|
fill(bgbuff, vs->pitch, flags, width, height, vs->format.bytesPerPixel);
|
2005-10-18 13:56:10 +00:00
|
|
|
} else {
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(backbuff, vs->pitch, flags, width, height, vs->format.bytesPerPixel);
|
2005-10-18 13:56:10 +00:00
|
|
|
}
|
2008-01-06 13:27:42 +00:00
|
|
|
} else if (_game.heversion >= 60) {
|
2005-10-18 13:56:10 +00:00
|
|
|
// Flags are used for different methods in HE games
|
2007-03-23 03:06:10 +00:00
|
|
|
uint16 flags = color;
|
2005-10-18 13:56:10 +00:00
|
|
|
if (flags & 0x2000) {
|
2011-04-17 15:29:09 +00:00
|
|
|
blit(backbuff, vs->pitch, bgbuff, vs->pitch, width, height, vs->format.bytesPerPixel);
|
2005-10-18 13:56:10 +00:00
|
|
|
} else if (flags & 0x4000) {
|
2011-04-17 15:29:09 +00:00
|
|
|
blit(bgbuff, vs->pitch, backbuff, vs->pitch, width, height, vs->format.bytesPerPixel);
|
2005-10-18 13:56:10 +00:00
|
|
|
} else if (flags & 0x8000) {
|
|
|
|
flags &= 0x7FFF;
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(backbuff, vs->pitch, flags, width, height, vs->format.bytesPerPixel);
|
|
|
|
fill(bgbuff, vs->pitch, flags, width, height, vs->format.bytesPerPixel);
|
2005-05-22 10:38:57 +00:00
|
|
|
} else {
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(backbuff, vs->pitch, flags, width, height, vs->format.bytesPerPixel);
|
2005-05-22 10:38:57 +00:00
|
|
|
}
|
2007-03-23 03:06:10 +00:00
|
|
|
} else {
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_game.features & GF_16BIT_COLOR) {
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(backbuff, vs->pitch, _16BitPalette[color], width, height, vs->format.bytesPerPixel);
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
} else {
|
2010-10-05 19:04:52 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_game.platform == Common::kPlatformFMTowns) {
|
|
|
|
color = ((color & 0x0f) << 4) | (color & 0x0f);
|
|
|
|
byte *mask = (byte *)_textSurface.getBasePtr(x * _textSurfaceMultiplier, (y - _screenTop + vs->topline) * _textSurfaceMultiplier);
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(mask, _textSurface.pitch, color, width * _textSurfaceMultiplier, height * _textSurfaceMultiplier, _textSurface.format.bytesPerPixel);
|
2011-06-19 22:59:48 +00:00
|
|
|
|
2010-10-03 14:32:09 +00:00
|
|
|
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))
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
return;
|
|
|
|
}
|
2010-10-05 19:04:52 +00:00
|
|
|
#endif
|
2011-06-19 22:59:48 +00:00
|
|
|
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(backbuff, vs->pitch, color, width, height, vs->format.bytesPerPixel);
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
}
|
2004-01-04 13:49:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-21 06:50:50 +00:00
|
|
|
/**
|
|
|
|
* Moves the screen content by the offset specified via dx/dy.
|
|
|
|
* Only the region from x=0 till x=height-1 is affected.
|
|
|
|
* @param dx the horizontal offset.
|
|
|
|
* @param dy the vertical offset.
|
|
|
|
* @param height the number of lines which in which the move will be done.
|
|
|
|
*/
|
|
|
|
void ScummEngine::moveScreen(int dx, int dy, int height) {
|
|
|
|
// Short circuit check - do we have to do anything anyway?
|
|
|
|
if ((dx == 0 && dy == 0) || height <= 0)
|
|
|
|
return;
|
|
|
|
|
2007-06-19 22:39:59 +00:00
|
|
|
Graphics::Surface *screen = _system->lockScreen();
|
|
|
|
if (!screen)
|
|
|
|
return;
|
|
|
|
screen->move(dx, dy, height);
|
|
|
|
_system->unlockScreen();
|
2006-06-21 06:50:50 +00:00
|
|
|
}
|
|
|
|
|
2006-06-19 07:45:40 +00:00
|
|
|
void ScummEngine_v5::clearFlashlight() {
|
|
|
|
_flashlight.isDrawn = false;
|
|
|
|
_flashlight.buffer = NULL;
|
|
|
|
}
|
|
|
|
|
2006-04-29 13:01:35 +00:00
|
|
|
void ScummEngine_v5::drawFlashlight() {
|
2004-08-14 19:42:00 +00:00
|
|
|
int i, j, x, y;
|
2007-09-08 11:15:27 +00:00
|
|
|
VirtScreen *vs = &_virtscr[kMainVirtScreen];
|
2004-01-04 13:49:03 +00:00
|
|
|
|
|
|
|
// Remove the flash light first if it was previously drawn
|
|
|
|
if (_flashlight.isDrawn) {
|
|
|
|
markRectAsDirty(kMainVirtScreen, _flashlight.x, _flashlight.x + _flashlight.w,
|
|
|
|
_flashlight.y, _flashlight.y + _flashlight.h, USAGE_BIT_DIRTY);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-01-04 13:49:03 +00:00
|
|
|
if (_flashlight.buffer) {
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(_flashlight.buffer, vs->pitch, 0, _flashlight.w, _flashlight.h, vs->format.bytesPerPixel);
|
2004-01-04 13:49:03 +00:00
|
|
|
}
|
|
|
|
_flashlight.isDrawn = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_flashlight.xStrips == 0 || _flashlight.yStrips == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Calculate the area of the flashlight
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.id == GID_ZAK || _game.id == GID_MANIAC) {
|
2004-01-04 13:49:03 +00:00
|
|
|
x = _mouse.x + vs->xstart;
|
|
|
|
y = _mouse.y - vs->topline;
|
|
|
|
} else {
|
|
|
|
Actor *a = derefActor(VAR(VAR_EGO), "drawFlashlight");
|
2006-11-19 00:39:48 +00:00
|
|
|
x = a->getPos().x;
|
|
|
|
y = a->getPos().y;
|
2004-01-04 13:49:03 +00:00
|
|
|
}
|
|
|
|
_flashlight.w = _flashlight.xStrips * 8;
|
|
|
|
_flashlight.h = _flashlight.yStrips * 8;
|
|
|
|
_flashlight.x = x - _flashlight.w / 2 - _screenStartStrip * 8;
|
|
|
|
_flashlight.y = y - _flashlight.h / 2;
|
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.id == GID_LOOM)
|
2004-01-04 13:49:03 +00:00
|
|
|
_flashlight.y -= 12;
|
|
|
|
|
|
|
|
// Clip the flashlight at the borders
|
|
|
|
if (_flashlight.x < 0)
|
|
|
|
_flashlight.x = 0;
|
2006-09-17 20:22:47 +00:00
|
|
|
else if (_flashlight.x + _flashlight.w > _gdi->_numStrips * 8)
|
|
|
|
_flashlight.x = _gdi->_numStrips * 8 - _flashlight.w;
|
2004-01-04 13:49:03 +00:00
|
|
|
if (_flashlight.y < 0)
|
|
|
|
_flashlight.y = 0;
|
2004-08-14 19:42:00 +00:00
|
|
|
else if (_flashlight.y + _flashlight.h> vs->h)
|
|
|
|
_flashlight.y = vs->h - _flashlight.h;
|
2004-01-04 13:49:03 +00:00
|
|
|
|
|
|
|
// Redraw any actors "under" the flashlight
|
|
|
|
for (i = _flashlight.x / 8; i < (_flashlight.x + _flashlight.w) / 8; i++) {
|
2006-09-17 20:22:47 +00:00
|
|
|
assert(0 <= i && i < _gdi->_numStrips);
|
2004-01-04 13:49:03 +00:00
|
|
|
setGfxUsageBit(_screenStartStrip + i, USAGE_BIT_DIRTY);
|
|
|
|
vs->tdirty[i] = 0;
|
2004-08-14 19:42:00 +00:00
|
|
|
vs->bdirty[i] = vs->h;
|
2004-01-04 13:49:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
byte *bgbak;
|
2004-08-14 19:42:00 +00:00
|
|
|
_flashlight.buffer = vs->getPixels(_flashlight.x, _flashlight.y);
|
|
|
|
bgbak = vs->getBackPixels(_flashlight.x, _flashlight.y);
|
2004-01-04 13:49:03 +00:00
|
|
|
|
2011-04-17 15:29:09 +00:00
|
|
|
blit(_flashlight.buffer, vs->pitch, bgbak, vs->pitch, _flashlight.w, _flashlight.h, vs->format.bytesPerPixel);
|
2004-01-04 13:49:03 +00:00
|
|
|
|
|
|
|
// Round the corners. To do so, we simply hard-code a set of nicely
|
|
|
|
// rounded corners.
|
2004-07-18 17:08:00 +00:00
|
|
|
static const int corner_data[] = { 8, 6, 4, 3, 2, 2, 1, 1 };
|
2004-01-04 13:49:03 +00:00
|
|
|
int minrow = 0;
|
2011-04-17 15:29:09 +00:00
|
|
|
int maxcol = (_flashlight.w - 1) * vs->format.bytesPerPixel;
|
2004-08-14 19:42:00 +00:00
|
|
|
int maxrow = (_flashlight.h - 1) * vs->pitch;
|
2004-01-04 13:49:03 +00:00
|
|
|
|
2004-08-14 19:42:00 +00:00
|
|
|
for (i = 0; i < 8; i++, minrow += vs->pitch, maxrow -= vs->pitch) {
|
2004-01-04 13:49:03 +00:00
|
|
|
int d = corner_data[i];
|
|
|
|
|
|
|
|
for (j = 0; j < d; j++) {
|
2011-04-17 15:29:09 +00:00
|
|
|
if (vs->format.bytesPerPixel == 2) {
|
2009-10-31 13:34:31 +00:00
|
|
|
WRITE_UINT16(&_flashlight.buffer[minrow + 2 * j], 0);
|
|
|
|
WRITE_UINT16(&_flashlight.buffer[minrow + maxcol - 2 * j], 0);
|
|
|
|
WRITE_UINT16(&_flashlight.buffer[maxrow + 2 * j], 0);
|
|
|
|
WRITE_UINT16(&_flashlight.buffer[maxrow + maxcol - 2 * j], 0);
|
|
|
|
} else {
|
|
|
|
_flashlight.buffer[minrow + j] = 0;
|
|
|
|
_flashlight.buffer[minrow + maxcol - j] = 0;
|
|
|
|
_flashlight.buffer[maxrow + j] = 0;
|
|
|
|
_flashlight.buffer[maxrow + maxcol - j] = 0;
|
|
|
|
}
|
2004-01-04 13:49:03 +00:00
|
|
|
}
|
|
|
|
}
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-01-04 13:49:03 +00:00
|
|
|
_flashlight.isDrawn = true;
|
|
|
|
}
|
2003-06-01 14:30:26 +00:00
|
|
|
|
2012-02-04 14:40:36 +00:00
|
|
|
int ScummEngine_v0::getCurrentLights() const {
|
|
|
|
// V0 Maniac doesn't have a ScummVar for VAR_CURRENT_LIGHTS, and just uses
|
|
|
|
// an internal variable. Emulate this to prevent overwriting script vars...
|
|
|
|
// And V6 games do not use the "lights" at all. There, the whole screen is
|
|
|
|
// always visible, and actors are always colored, so we fake the correct
|
|
|
|
// light value for it.
|
|
|
|
return _currentLights;
|
|
|
|
}
|
|
|
|
|
2006-03-14 12:06:37 +00:00
|
|
|
int ScummEngine::getCurrentLights() const {
|
2012-02-04 14:40:36 +00:00
|
|
|
if (_game.version >= 6)
|
2006-03-14 14:06:44 +00:00
|
|
|
return LIGHTMODE_room_lights_on | LIGHTMODE_actor_use_colors;
|
2006-03-14 12:06:37 +00:00
|
|
|
else
|
|
|
|
return VAR(VAR_CURRENT_LIGHTS);
|
|
|
|
}
|
|
|
|
|
2004-01-08 21:21:40 +00:00
|
|
|
bool ScummEngine::isLightOn() const {
|
2006-03-24 18:33:47 +00:00
|
|
|
return (getCurrentLights() & LIGHTMODE_room_lights_on) != 0;
|
2004-01-08 21:21:40 +00:00
|
|
|
}
|
|
|
|
|
2004-09-26 00:06:51 +00:00
|
|
|
void ScummEngine::setShake(int mode) {
|
|
|
|
if (_shakeEnabled != (mode != 0))
|
|
|
|
_fullRedraw = true;
|
|
|
|
|
|
|
|
_shakeEnabled = mode != 0;
|
|
|
|
_shakeFrame = 0;
|
2004-09-28 20:19:37 +00:00
|
|
|
_system->setShakePos(0);
|
2004-09-26 00:06:51 +00:00
|
|
|
}
|
|
|
|
|
2003-05-15 23:50:16 +00:00
|
|
|
#pragma mark -
|
|
|
|
#pragma mark --- Image drawing ---
|
|
|
|
#pragma mark -
|
|
|
|
|
2004-08-08 13:24:41 +00:00
|
|
|
|
2006-09-18 22:06:39 +00:00
|
|
|
void Gdi::prepareDrawBitmap(const byte *ptr, VirtScreen *vs,
|
|
|
|
const int x, const int y, const int width, const int height,
|
|
|
|
int stripnr, int numstrip) {
|
2007-02-02 12:51:44 +00:00
|
|
|
// Do nothing by default
|
2006-09-18 22:06:39 +00:00
|
|
|
}
|
|
|
|
|
2011-05-11 12:02:21 +00:00
|
|
|
void GdiHE::prepareDrawBitmap(const byte *ptr, VirtScreen *vs,
|
|
|
|
const int x, const int y, const int width, const int height,
|
|
|
|
int stripnr, int numstrip) {
|
|
|
|
if (_vm->_game.heversion >= 72) {
|
|
|
|
_tmskPtr = _vm->findResource(MKTAG('T','M','S','K'), ptr);
|
|
|
|
} else
|
|
|
|
_tmskPtr = 0;
|
|
|
|
}
|
|
|
|
|
2006-09-18 22:06:39 +00:00
|
|
|
void GdiV1::prepareDrawBitmap(const byte *ptr, VirtScreen *vs,
|
|
|
|
const int x, const int y, const int width, const int height,
|
|
|
|
int stripnr, int numstrip) {
|
|
|
|
if (_objectMode) {
|
2012-02-04 17:34:08 +00:00
|
|
|
decodeV1Gfx(ptr, _V1.objectMap, (width / 8) * (height / 8) * 3);
|
2006-09-18 22:06:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GdiNES::prepareDrawBitmap(const byte *ptr, VirtScreen *vs,
|
|
|
|
const int x, const int y, const int width, const int height,
|
|
|
|
int stripnr, int numstrip) {
|
|
|
|
if (_objectMode) {
|
2007-02-16 02:26:42 +00:00
|
|
|
decodeNESObject(ptr, x - stripnr, y, width, height);
|
2006-09-18 22:06:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-22 11:43:12 +00:00
|
|
|
#ifdef USE_RGB_COLOR
|
2009-10-21 12:59:10 +00:00
|
|
|
void GdiPCEngine::prepareDrawBitmap(const byte *ptr, VirtScreen *vs,
|
|
|
|
const int x, const int y, const int width, const int height,
|
|
|
|
int stripnr, int numstrip) {
|
|
|
|
if (_objectMode) {
|
|
|
|
decodePCEngineObject(ptr, x - stripnr, y, width, height);
|
|
|
|
}
|
|
|
|
}
|
2009-11-22 11:43:12 +00:00
|
|
|
#endif
|
2006-09-18 22:06:39 +00:00
|
|
|
|
|
|
|
void GdiV2::prepareDrawBitmap(const byte *ptr, VirtScreen *vs,
|
|
|
|
const int x, const int y, const int width, const int height,
|
|
|
|
int stripnr, int numstrip) {
|
|
|
|
//
|
|
|
|
// Since V3, all graphics data was encoded in strips, which is very efficient
|
|
|
|
// for redrawing only parts of the screen. However, V2 is different: here
|
|
|
|
// the whole graphics are encoded as one big chunk. That makes it rather
|
2010-07-14 16:57:16 +00:00
|
|
|
// difficult to draw only parts of a room/object. We handle the V2 graphics
|
2006-09-18 22:06:39 +00:00
|
|
|
// differently from all other (newer) graphic formats for this reason.
|
|
|
|
//
|
2005-03-25 01:52:20 +00:00
|
|
|
StripTable *table = (_objectMode ? 0 : _roomStrips);
|
2004-08-08 13:24:41 +00:00
|
|
|
const int left = (stripnr * 8);
|
|
|
|
const int right = left + (numstrip * 8);
|
|
|
|
byte *dst;
|
|
|
|
byte *mask_ptr;
|
|
|
|
const byte *src;
|
|
|
|
byte color, data = 0;
|
|
|
|
int run;
|
|
|
|
bool dither = false;
|
|
|
|
byte dither_table[128];
|
|
|
|
byte *ptr_dither_table;
|
|
|
|
int theX, theY, maxX;
|
|
|
|
|
|
|
|
memset(dither_table, 0, sizeof(dither_table));
|
|
|
|
|
|
|
|
if (vs->hasTwoBuffers)
|
2004-08-14 19:42:00 +00:00
|
|
|
dst = vs->backBuf + y * vs->pitch + x * 8;
|
2004-08-08 13:24:41 +00:00
|
|
|
else
|
2013-08-04 00:29:13 +00:00
|
|
|
dst = (byte *)vs->getBasePtr(x * 8, y);
|
2004-08-08 13:24:41 +00:00
|
|
|
|
|
|
|
mask_ptr = getMaskBuffer(x, y, 1);
|
|
|
|
|
|
|
|
|
|
|
|
if (table) {
|
|
|
|
run = table->run[stripnr];
|
|
|
|
color = table->color[stripnr];
|
|
|
|
src = ptr + table->offsets[stripnr];
|
|
|
|
theX = left;
|
|
|
|
maxX = right;
|
|
|
|
} else {
|
|
|
|
run = 1;
|
|
|
|
color = 0;
|
|
|
|
src = ptr;
|
|
|
|
theX = 0;
|
|
|
|
maxX = width;
|
|
|
|
}
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-08-08 13:24:41 +00:00
|
|
|
// Decode and draw the image data.
|
|
|
|
assert(height <= 128);
|
|
|
|
for (; theX < maxX; theX++) {
|
|
|
|
ptr_dither_table = dither_table;
|
|
|
|
for (theY = 0; theY < height; theY++) {
|
|
|
|
if (--run == 0) {
|
|
|
|
data = *src++;
|
|
|
|
if (data & 0x80) {
|
|
|
|
run = data & 0x7f;
|
|
|
|
dither = true;
|
|
|
|
} else {
|
|
|
|
run = data >> 4;
|
|
|
|
dither = false;
|
|
|
|
}
|
|
|
|
color = _roomPalette[data & 0x0f];
|
|
|
|
if (run == 0) {
|
|
|
|
run = *src++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!dither) {
|
|
|
|
*ptr_dither_table = color;
|
|
|
|
}
|
|
|
|
if (left <= theX && theX < right) {
|
|
|
|
*dst = *ptr_dither_table++;
|
2004-08-14 19:42:00 +00:00
|
|
|
dst += vs->pitch;
|
2004-08-08 13:24:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (left <= theX && theX < right) {
|
|
|
|
dst -= _vertStripNextInc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Draw mask (zplane) data
|
|
|
|
theY = 0;
|
|
|
|
|
|
|
|
if (table) {
|
|
|
|
src = ptr + table->zoffsets[stripnr];
|
|
|
|
run = table->zrun[stripnr];
|
|
|
|
theX = left;
|
|
|
|
} else {
|
|
|
|
run = *src++;
|
|
|
|
theX = 0;
|
|
|
|
}
|
|
|
|
while (theX < right) {
|
|
|
|
const byte runFlag = run & 0x80;
|
|
|
|
if (runFlag) {
|
|
|
|
run &= 0x7f;
|
|
|
|
data = *src++;
|
|
|
|
}
|
|
|
|
do {
|
|
|
|
if (!runFlag)
|
|
|
|
data = *src++;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-08-08 13:24:41 +00:00
|
|
|
if (left <= theX) {
|
|
|
|
*mask_ptr = data;
|
|
|
|
mask_ptr += _numStrips;
|
|
|
|
}
|
|
|
|
theY++;
|
|
|
|
if (theY >= height) {
|
|
|
|
if (left <= theX) {
|
|
|
|
mask_ptr -= _numStrips * height - 1;
|
|
|
|
}
|
|
|
|
theY = 0;
|
|
|
|
theX += 8;
|
|
|
|
if (theX >= right)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (--run);
|
|
|
|
run = *src++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-27 01:26:05 +00:00
|
|
|
int Gdi::getZPlanes(const byte *ptr, const byte *zplane_list[9], bool bmapImage) const {
|
2001-10-26 17:34:50 +00:00
|
|
|
int numzbuf;
|
2004-09-19 21:14:51 +00:00
|
|
|
int i;
|
2002-04-24 04:26:09 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if ((_vm->_game.features & GF_SMALL_HEADER) || _vm->_game.version == 8)
|
2004-09-27 01:26:05 +00:00
|
|
|
zplane_list[0] = ptr;
|
|
|
|
else if (bmapImage)
|
2011-04-12 14:53:15 +00:00
|
|
|
zplane_list[0] = _vm->findResource(MKTAG('B','M','A','P'), ptr);
|
2004-09-27 01:26:05 +00:00
|
|
|
else
|
2011-04-12 14:53:15 +00:00
|
|
|
zplane_list[0] = _vm->findResource(MKTAG('S','M','A','P'), ptr);
|
2003-04-24 18:53:21 +00:00
|
|
|
|
2003-05-15 21:31:03 +00:00
|
|
|
if (_zbufferDisabled)
|
2003-04-24 14:33:31 +00:00
|
|
|
numzbuf = 0;
|
2006-02-20 16:51:30 +00:00
|
|
|
else if (_numZBuffer <= 1 || (_vm->_game.version <= 2))
|
2003-04-26 10:43:59 +00:00
|
|
|
numzbuf = _numZBuffer;
|
2003-04-24 18:53:21 +00:00
|
|
|
else {
|
|
|
|
numzbuf = _numZBuffer;
|
2004-09-19 21:14:51 +00:00
|
|
|
assert(numzbuf <= 9);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2009-10-26 02:45:26 +00:00
|
|
|
if (_vm->_game.id == GID_LOOM && _vm->_game.platform == Common::kPlatformPCEngine) {
|
|
|
|
zplane_list[1] = 0;
|
|
|
|
} else if (_vm->_game.features & GF_SMALL_HEADER) {
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_vm->_game.features & GF_16COLOR)
|
2004-09-19 21:14:51 +00:00
|
|
|
zplane_list[1] = ptr + READ_LE_UINT16(ptr);
|
2005-04-20 19:59:18 +00:00
|
|
|
else {
|
2004-09-19 21:14:51 +00:00
|
|
|
zplane_list[1] = ptr + READ_LE_UINT32(ptr);
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_vm->_game.features & GF_OLD256) {
|
2005-04-20 19:59:18 +00:00
|
|
|
if (0 == READ_LE_UINT32(zplane_list[1]))
|
|
|
|
zplane_list[1] = 0;
|
|
|
|
}
|
2003-09-27 20:31:19 +00:00
|
|
|
}
|
2003-04-24 18:53:21 +00:00
|
|
|
for (i = 2; i < numzbuf; i++) {
|
|
|
|
zplane_list[i] = zplane_list[i-1] + READ_LE_UINT16(zplane_list[i-1]);
|
2003-04-10 19:30:01 +00:00
|
|
|
}
|
2006-02-20 16:51:30 +00:00
|
|
|
} else if (_vm->_game.version == 8) {
|
2003-04-24 18:53:21 +00:00
|
|
|
// Find the OFFS chunk of the ZPLN chunk
|
2004-09-19 21:14:51 +00:00
|
|
|
const byte *zplnOffsChunkStart = ptr + 24 + READ_BE_UINT32(ptr + 12);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2003-04-24 18:53:21 +00:00
|
|
|
// Each ZPLN contains a WRAP chunk, which has (as always) an OFFS subchunk pointing
|
|
|
|
// at ZSTR chunks. These once more contain a WRAP chunk which contains nothing but
|
|
|
|
// an OFFS chunk. The content of this OFFS chunk contains the offsets to the
|
|
|
|
// Z-planes.
|
|
|
|
// We do not directly make use of this, but rather hard code offsets (like we do
|
|
|
|
// for all other Scumm-versions, too). Clearly this is a bit hackish, but works
|
|
|
|
// well enough, and there is no reason to assume that there are any cases where it
|
|
|
|
// might fail. Still, doing this properly would have the advantage of catching
|
|
|
|
// invalid/damaged data files, and allow us to exit gracefully instead of segfaulting.
|
|
|
|
for (i = 1; i < numzbuf; i++) {
|
|
|
|
zplane_list[i] = zplnOffsChunkStart + READ_LE_UINT32(zplnOffsChunkStart + 4 + i*4) + 16;
|
2002-07-28 12:43:35 +00:00
|
|
|
}
|
2002-04-17 16:02:29 +00:00
|
|
|
} else {
|
2003-04-24 18:53:21 +00:00
|
|
|
const uint32 zplane_tags[] = {
|
2011-04-12 14:53:15 +00:00
|
|
|
MKTAG('Z','P','0','0'),
|
|
|
|
MKTAG('Z','P','0','1'),
|
|
|
|
MKTAG('Z','P','0','2'),
|
|
|
|
MKTAG('Z','P','0','3'),
|
|
|
|
MKTAG('Z','P','0','4')
|
2003-04-24 18:53:21 +00:00
|
|
|
};
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2003-04-24 18:53:21 +00:00
|
|
|
for (i = 1; i < numzbuf; i++) {
|
2004-06-23 01:36:57 +00:00
|
|
|
zplane_list[i] = _vm->findResource(zplane_tags[i], ptr);
|
2003-04-24 18:53:21 +00:00
|
|
|
}
|
2002-04-17 16:02:29 +00:00
|
|
|
}
|
2001-10-26 17:34:50 +00:00
|
|
|
}
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-09-19 21:14:51 +00:00
|
|
|
return numzbuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Draw a bitmap onto a virtual screen. This is main drawing method for room backgrounds
|
|
|
|
* and objects, used throughout all SCUMM versions.
|
|
|
|
*/
|
2006-09-18 21:46:44 +00:00
|
|
|
void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, const int y, const int width, const int height,
|
2005-03-25 01:52:20 +00:00
|
|
|
int stripnr, int numstrip, byte flag) {
|
2004-09-19 21:14:51 +00:00
|
|
|
assert(ptr);
|
|
|
|
assert(height > 0);
|
2006-09-18 22:06:39 +00:00
|
|
|
|
2004-10-07 21:20:44 +00:00
|
|
|
byte *dstPtr;
|
2004-09-19 21:14:51 +00:00
|
|
|
const byte *smap_ptr;
|
|
|
|
const byte *zplane_list[9];
|
|
|
|
int numzbuf;
|
|
|
|
int sx;
|
2006-01-01 09:55:56 +00:00
|
|
|
bool transpStrip = false;
|
2004-09-19 21:14:51 +00:00
|
|
|
|
|
|
|
// Check whether lights are turned on or not
|
|
|
|
const bool lightsOn = _vm->isLightOn();
|
|
|
|
|
2013-08-26 09:32:26 +00:00
|
|
|
if ((_vm->_game.features & GF_SMALL_HEADER) || _vm->_game.version == 8) {
|
2004-09-19 21:14:51 +00:00
|
|
|
smap_ptr = ptr;
|
2006-09-18 22:06:39 +00:00
|
|
|
} else {
|
2011-04-12 14:53:15 +00:00
|
|
|
smap_ptr = _vm->findResource(MKTAG('S','M','A','P'), ptr);
|
2006-09-18 22:06:39 +00:00
|
|
|
assert(smap_ptr);
|
|
|
|
}
|
2004-09-19 21:14:51 +00:00
|
|
|
|
2009-10-26 02:45:26 +00:00
|
|
|
numzbuf = getZPlanes(ptr, zplane_list, false);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2006-09-18 22:06:39 +00:00
|
|
|
if (y + height > vs->h) {
|
|
|
|
warning("Gdi::drawBitmap, strip drawn to %d below window bottom %d", y + height, vs->h);
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2010-10-05 19:04:52 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
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);
|
|
|
|
}
|
2010-10-05 19:04:52 +00:00
|
|
|
#endif
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
|
2011-04-17 15:29:09 +00:00
|
|
|
_vertStripNextInc = height * vs->pitch - 1 * vs->format.bytesPerPixel;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2006-09-18 22:06:39 +00:00
|
|
|
_objectMode = (flag & dbObjectMode) == dbObjectMode;
|
|
|
|
prepareDrawBitmap(ptr, vs, x, y, width, height, stripnr, numstrip);
|
2003-05-10 14:30:58 +00:00
|
|
|
|
2004-09-22 17:57:20 +00:00
|
|
|
sx = x - vs->xstart / 8;
|
|
|
|
if (sx < 0) {
|
|
|
|
numstrip -= -sx;
|
|
|
|
x += -sx;
|
|
|
|
stripnr += -sx;
|
|
|
|
sx = 0;
|
|
|
|
}
|
2002-10-27 15:16:49 +00:00
|
|
|
|
2005-05-14 22:55:39 +00:00
|
|
|
// Compute the number of strips we have to iterate over.
|
|
|
|
// TODO/FIXME: The computation of its initial value looks very fishy.
|
|
|
|
// It was added as a kind of hack to fix some corner cases, but it compares
|
|
|
|
// the room width to the virtual screen width; but the former should always
|
|
|
|
// be bigger than the latter (except for MM NES, maybe)... strange
|
|
|
|
int limit = MAX(_vm->_roomWidth, (int) vs->w) / 8 - x;
|
|
|
|
if (limit > numstrip)
|
|
|
|
limit = numstrip;
|
|
|
|
if (limit > _numStrips - sx)
|
|
|
|
limit = _numStrips - sx;
|
2006-09-18 19:16:31 +00:00
|
|
|
for (int k = 0; k < limit; ++k, ++stripnr, ++sx, ++x) {
|
|
|
|
if (y < vs->tdirty[sx])
|
|
|
|
vs->tdirty[sx] = y;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2006-09-18 22:06:39 +00:00
|
|
|
if (y + height > vs->bdirty[sx])
|
|
|
|
vs->bdirty[sx] = y + height;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2004-10-07 21:20:44 +00:00
|
|
|
// In the case of a double buffered virtual screen, we draw to
|
|
|
|
// the backbuffer, otherwise to the primary surface memory.
|
2004-01-06 11:47:34 +00:00
|
|
|
if (vs->hasTwoBuffers)
|
2011-04-17 15:29:09 +00:00
|
|
|
dstPtr = vs->backBuf + y * vs->pitch + (x * 8 * vs->format.bytesPerPixel);
|
2002-08-20 02:20:40 +00:00
|
|
|
else
|
2013-08-04 00:29:13 +00:00
|
|
|
dstPtr = (byte *)vs->getBasePtr(x * 8, y);
|
2006-09-18 19:16:31 +00:00
|
|
|
|
|
|
|
transpStrip = drawStrip(dstPtr, vs, x, y, width, height, stripnr, smap_ptr);
|
|
|
|
|
2006-09-18 21:20:21 +00:00
|
|
|
// COMI and HE games only uses flag value
|
|
|
|
if (_vm->_game.version == 8 || _vm->_game.heversion >= 60)
|
|
|
|
transpStrip = true;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2006-09-18 19:16:31 +00:00
|
|
|
if (vs->hasTwoBuffers) {
|
2013-08-04 00:29:13 +00:00
|
|
|
byte *frontBuf = (byte *)vs->getBasePtr(x * 8, y);
|
2006-09-18 19:16:31 +00:00
|
|
|
if (lightsOn)
|
2011-04-17 15:29:09 +00:00
|
|
|
copy8Col(frontBuf, vs->pitch, dstPtr, height, vs->format.bytesPerPixel);
|
2006-09-18 19:16:31 +00:00
|
|
|
else
|
2011-04-17 15:29:09 +00:00
|
|
|
clear8Col(frontBuf, vs->pitch, height, vs->format.bytesPerPixel);
|
2006-09-18 19:16:31 +00:00
|
|
|
}
|
|
|
|
|
2011-05-11 12:02:21 +00:00
|
|
|
decodeMask(x, y, width, height, stripnr, numzbuf, zplane_list, transpStrip, flag);
|
2006-09-18 19:16:31 +00:00
|
|
|
|
2006-09-18 21:46:44 +00:00
|
|
|
#if 0
|
2006-09-18 19:16:31 +00:00
|
|
|
// HACK: blit mask(s) onto normal screen. Useful to debug masking
|
2006-09-18 21:20:21 +00:00
|
|
|
for (int i = 0; i < numzbuf; i++) {
|
2006-09-18 19:16:31 +00:00
|
|
|
byte *dst1, *dst2;
|
|
|
|
|
2006-09-18 21:20:21 +00:00
|
|
|
dst1 = dst2 = (byte *)vs->pixels + y * vs->pitch + x * 8;
|
2006-09-18 19:16:31 +00:00
|
|
|
if (vs->hasTwoBuffers)
|
|
|
|
dst2 = vs->backBuf + y * vs->pitch + x * 8;
|
2006-09-18 21:20:21 +00:00
|
|
|
byte *mask_ptr = getMaskBuffer(x, y, i);
|
2006-09-18 19:16:31 +00:00
|
|
|
|
|
|
|
for (int h = 0; h < height; h++) {
|
|
|
|
int maskbits = *mask_ptr;
|
|
|
|
for (int j = 0; j < 8; j++) {
|
|
|
|
if (maskbits & 0x80)
|
|
|
|
dst1[j] = dst2[j] = 12 + i;
|
|
|
|
maskbits <<= 1;
|
|
|
|
}
|
|
|
|
dst1 += vs->pitch;
|
|
|
|
dst2 += vs->pitch;
|
|
|
|
mask_ptr += _numStrips;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Gdi::drawStrip(byte *dstPtr, VirtScreen *vs, int x, int y, const int width, const int height,
|
|
|
|
int stripnr, const byte *smap_ptr) {
|
2006-09-18 22:06:39 +00:00
|
|
|
// Do some input verification and make sure the strip/strip offset
|
|
|
|
// are actually valid. Normally, this should never be a problem,
|
|
|
|
// but if e.g. a savegame gets corrupted, we can easily get into
|
|
|
|
// trouble here. See also bug #795214.
|
|
|
|
int offset = -1, smapLen;
|
2009-10-21 12:59:10 +00:00
|
|
|
if (_vm->_game.features & GF_16COLOR) {
|
2006-09-18 22:06:39 +00:00
|
|
|
smapLen = READ_LE_UINT16(smap_ptr);
|
2007-03-03 12:59:48 +00:00
|
|
|
if (stripnr * 2 + 2 < smapLen) {
|
2006-09-18 22:06:39 +00:00
|
|
|
offset = READ_LE_UINT16(smap_ptr + stripnr * 2 + 2);
|
2007-03-03 12:59:48 +00:00
|
|
|
}
|
2006-09-18 22:06:39 +00:00
|
|
|
} else if (_vm->_game.features & GF_SMALL_HEADER) {
|
|
|
|
smapLen = READ_LE_UINT32(smap_ptr);
|
|
|
|
if (stripnr * 4 + 4 < smapLen)
|
|
|
|
offset = READ_LE_UINT32(smap_ptr + stripnr * 4 + 4);
|
2013-08-26 09:32:26 +00:00
|
|
|
} else if (_vm->_game.version == 8) {
|
|
|
|
smapLen = READ_BE_UINT32(smap_ptr + 4);
|
|
|
|
// Skip to the BSTR->WRAP->OFFS chunk
|
|
|
|
smap_ptr += 24;
|
|
|
|
if (stripnr * 4 + 8 < smapLen)
|
|
|
|
offset = READ_LE_UINT32(smap_ptr + stripnr * 4 + 8);
|
2006-09-18 19:17:55 +00:00
|
|
|
} else {
|
2013-08-18 07:28:54 +00:00
|
|
|
smapLen = READ_BE_UINT32(smap_ptr + 4);
|
2006-09-18 22:06:39 +00:00
|
|
|
if (stripnr * 4 + 8 < smapLen)
|
|
|
|
offset = READ_LE_UINT32(smap_ptr + stripnr * 4 + 8);
|
2006-09-18 19:17:55 +00:00
|
|
|
}
|
2010-08-23 10:00:19 +00:00
|
|
|
assertRange(0, offset, smapLen-1, "screen strip");
|
2006-09-18 19:17:55 +00:00
|
|
|
|
2011-08-26 03:51:08 +00:00
|
|
|
// Indy4 Amiga always uses the room or verb palette map to match colors to
|
|
|
|
// the currently setup palette, thus we need to select it over here too.
|
|
|
|
// Done like the original interpreter.
|
|
|
|
if (_vm->_game.platform == Common::kPlatformAmiga && _vm->_game.id == GID_INDY4) {
|
|
|
|
if (vs->number == kVerbVirtScreen)
|
|
|
|
_roomPalette = _vm->_verbPalette;
|
|
|
|
else
|
|
|
|
_roomPalette = _vm->_roomPalette;
|
|
|
|
}
|
|
|
|
|
2006-09-18 22:06:39 +00:00
|
|
|
return decompressBitmap(dstPtr, vs->pitch, smap_ptr + offset, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GdiNES::drawStrip(byte *dstPtr, VirtScreen *vs, int x, int y, const int width, const int height,
|
|
|
|
int stripnr, const byte *smap_ptr) {
|
|
|
|
byte *mask_ptr = getMaskBuffer(x, y, 1);
|
|
|
|
drawStripNES(dstPtr, mask_ptr, vs->pitch, stripnr, y, height);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-11-22 11:43:12 +00:00
|
|
|
#ifdef USE_RGB_COLOR
|
2009-10-21 12:59:10 +00:00
|
|
|
bool GdiPCEngine::drawStrip(byte *dstPtr, VirtScreen *vs, int x, int y, const int width, const int height,
|
|
|
|
int stripnr, const byte *smap_ptr) {
|
|
|
|
byte *mask_ptr = getMaskBuffer(x, y, 1);
|
|
|
|
drawStripPCEngine(dstPtr, mask_ptr, vs->pitch, stripnr, y, height);
|
|
|
|
return false;
|
|
|
|
}
|
2009-11-22 11:43:12 +00:00
|
|
|
#endif
|
2009-10-21 12:59:10 +00:00
|
|
|
|
2006-09-18 22:06:39 +00:00
|
|
|
bool GdiV1::drawStrip(byte *dstPtr, VirtScreen *vs, int x, int y, const int width, const int height,
|
|
|
|
int stripnr, const byte *smap_ptr) {
|
|
|
|
if (_objectMode)
|
2012-02-04 17:34:08 +00:00
|
|
|
drawStripV1Object(dstPtr, vs->pitch, stripnr, width, height);
|
2006-09-18 22:06:39 +00:00
|
|
|
else
|
2012-02-04 17:34:08 +00:00
|
|
|
drawStripV1Background(dstPtr, vs->pitch, stripnr, height);
|
2006-09-18 22:06:39 +00:00
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GdiV2::drawStrip(byte *dstPtr, VirtScreen *vs, int x, int y, const int width, const int height,
|
|
|
|
int stripnr, const byte *smap_ptr) {
|
|
|
|
// Do nothing here for V2 games - drawing was already handled.
|
|
|
|
return false;
|
2006-09-18 19:16:31 +00:00
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2006-09-18 19:16:31 +00:00
|
|
|
void Gdi::decodeMask(int x, int y, const int width, const int height,
|
|
|
|
int stripnr, int numzbuf, const byte *zplane_list[9],
|
2011-05-11 12:02:21 +00:00
|
|
|
bool transpStrip, byte flag) {
|
2006-09-18 19:16:31 +00:00
|
|
|
int i;
|
|
|
|
byte *mask_ptr;
|
|
|
|
const byte *z_plane_ptr;
|
2002-04-17 16:02:29 +00:00
|
|
|
|
2006-09-18 22:06:39 +00:00
|
|
|
if (flag & dbDrawMaskOnAll) {
|
2006-09-18 19:17:55 +00:00
|
|
|
// Sam & Max uses dbDrawMaskOnAll for things like the inventory
|
|
|
|
// box and the speech icons. While these objects only have one
|
|
|
|
// mask, it should be applied to all the Z-planes in the room,
|
|
|
|
// i.e. they should mask every actor.
|
|
|
|
//
|
|
|
|
// This flag used to be called dbDrawMaskOnBoth, and all it
|
|
|
|
// would do was to mask Z-plane 0. (Z-plane 1 would also be
|
|
|
|
// masked, because what is now the else-clause used to be run
|
|
|
|
// always.) While this seems to be the only way there is to
|
|
|
|
// mask Z-plane 0, this wasn't good enough since actors in
|
|
|
|
// Z-planes >= 2 would not be masked.
|
|
|
|
//
|
|
|
|
// The flag is also used by The Dig and Full Throttle, but I
|
|
|
|
// don't know what for. At the time of writing, these games
|
|
|
|
// are still too unstable for me to investigate.
|
2002-09-29 15:20:02 +00:00
|
|
|
|
2006-09-18 19:17:55 +00:00
|
|
|
if (_vm->_game.version == 8)
|
|
|
|
z_plane_ptr = zplane_list[1] + READ_LE_UINT32(zplane_list[1] + stripnr * 4 + 8);
|
|
|
|
else
|
|
|
|
z_plane_ptr = zplane_list[1] + READ_LE_UINT16(zplane_list[1] + stripnr * 2 + 8);
|
|
|
|
for (i = 0; i < numzbuf; i++) {
|
|
|
|
mask_ptr = getMaskBuffer(x, y, i);
|
|
|
|
if (transpStrip && (flag & dbAllowMaskOr))
|
|
|
|
decompressMaskImgOr(mask_ptr, z_plane_ptr, height);
|
|
|
|
else
|
|
|
|
decompressMaskImg(mask_ptr, z_plane_ptr, height);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 1; i < numzbuf; i++) {
|
|
|
|
uint32 offs;
|
|
|
|
|
|
|
|
if (!zplane_list[i])
|
|
|
|
continue;
|
2002-09-29 15:20:02 +00:00
|
|
|
|
2006-09-18 19:17:55 +00:00
|
|
|
if (_vm->_game.features & GF_OLD_BUNDLE)
|
|
|
|
offs = READ_LE_UINT16(zplane_list[i] + stripnr * 2);
|
|
|
|
else if (_vm->_game.features & GF_OLD256)
|
|
|
|
offs = READ_LE_UINT16(zplane_list[i] + stripnr * 2 + 4);
|
|
|
|
else if (_vm->_game.features & GF_SMALL_HEADER)
|
|
|
|
offs = READ_LE_UINT16(zplane_list[i] + stripnr * 2 + 2);
|
|
|
|
else if (_vm->_game.version == 8)
|
|
|
|
offs = READ_LE_UINT32(zplane_list[i] + stripnr * 4 + 8);
|
|
|
|
else
|
|
|
|
offs = READ_LE_UINT16(zplane_list[i] + stripnr * 2 + 8);
|
|
|
|
|
|
|
|
mask_ptr = getMaskBuffer(x, y, i);
|
2002-09-29 15:20:02 +00:00
|
|
|
|
2006-09-18 19:17:55 +00:00
|
|
|
if (offs) {
|
|
|
|
z_plane_ptr = zplane_list[i] + offs;
|
2002-12-31 16:44:55 +00:00
|
|
|
|
2011-05-11 12:02:21 +00:00
|
|
|
if (transpStrip && (flag & dbAllowMaskOr)) {
|
2006-09-18 19:17:55 +00:00
|
|
|
decompressMaskImgOr(mask_ptr, z_plane_ptr, height);
|
2002-09-29 15:20:02 +00:00
|
|
|
} else {
|
2006-09-18 19:17:55 +00:00
|
|
|
decompressMaskImg(mask_ptr, z_plane_ptr, height);
|
2002-09-29 15:20:02 +00:00
|
|
|
}
|
2006-09-18 19:17:55 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
if (!(transpStrip && (flag & dbAllowMaskOr)))
|
|
|
|
for (int h = 0; h < height; h++)
|
|
|
|
mask_ptr[h * _numStrips] = 0;
|
2002-04-17 16:02:29 +00:00
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
2006-09-18 19:17:55 +00:00
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2011-05-11 12:02:21 +00:00
|
|
|
void GdiHE::decodeMask(int x, int y, const int width, const int height,
|
|
|
|
int stripnr, int numzbuf, const byte *zplane_list[9],
|
|
|
|
bool transpStrip, byte flag) {
|
|
|
|
int i;
|
|
|
|
byte *mask_ptr;
|
|
|
|
const byte *z_plane_ptr;
|
|
|
|
|
|
|
|
for (i = 1; i < numzbuf; i++) {
|
|
|
|
uint32 offs;
|
|
|
|
|
|
|
|
if (!zplane_list[i])
|
|
|
|
continue;
|
|
|
|
|
|
|
|
offs = READ_LE_UINT16(zplane_list[i] + stripnr * 2 + 8);
|
|
|
|
|
|
|
|
mask_ptr = getMaskBuffer(x, y, i);
|
|
|
|
|
|
|
|
if (offs) {
|
|
|
|
z_plane_ptr = zplane_list[i] + offs;
|
|
|
|
|
|
|
|
if (_tmskPtr) {
|
|
|
|
const byte *tmsk = _tmskPtr + READ_LE_UINT16(_tmskPtr + stripnr * 2 + 8);
|
|
|
|
decompressTMSK(mask_ptr, tmsk, z_plane_ptr, height);
|
|
|
|
} else if (transpStrip && (flag & dbAllowMaskOr)) {
|
|
|
|
decompressMaskImgOr(mask_ptr, z_plane_ptr, height);
|
|
|
|
} else {
|
|
|
|
decompressMaskImg(mask_ptr, z_plane_ptr, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (!(transpStrip && (flag & dbAllowMaskOr)))
|
|
|
|
for (int h = 0; h < height; h++)
|
|
|
|
mask_ptr[h * _numStrips] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-18 22:06:39 +00:00
|
|
|
void GdiNES::decodeMask(int x, int y, const int width, const int height,
|
|
|
|
int stripnr, int numzbuf, const byte *zplane_list[9],
|
2011-05-11 12:02:21 +00:00
|
|
|
bool transpStrip, byte flag) {
|
2006-09-18 21:20:21 +00:00
|
|
|
byte *mask_ptr = getMaskBuffer(x, y, 1);
|
2006-09-18 22:06:39 +00:00
|
|
|
drawStripNESMask(mask_ptr, stripnr, y, height);
|
2006-09-18 21:20:21 +00:00
|
|
|
}
|
|
|
|
|
2009-11-22 11:43:12 +00:00
|
|
|
#ifdef USE_RGB_COLOR
|
2009-10-21 12:59:10 +00:00
|
|
|
void GdiPCEngine::decodeMask(int x, int y, const int width, const int height,
|
|
|
|
int stripnr, int numzbuf, const byte *zplane_list[9],
|
2011-05-11 12:02:21 +00:00
|
|
|
bool transpStrip, byte flag) {
|
2009-10-21 12:59:10 +00:00
|
|
|
byte *mask_ptr = getMaskBuffer(x, y, 1);
|
|
|
|
drawStripPCEngineMask(mask_ptr, stripnr, y, height);
|
|
|
|
}
|
2009-11-22 11:43:12 +00:00
|
|
|
#endif
|
2009-10-21 12:59:10 +00:00
|
|
|
|
2006-09-18 22:06:39 +00:00
|
|
|
void GdiV1::decodeMask(int x, int y, const int width, const int height,
|
2006-09-18 21:20:21 +00:00
|
|
|
int stripnr, int numzbuf, const byte *zplane_list[9],
|
2011-05-11 12:02:21 +00:00
|
|
|
bool transpStrip, byte flag) {
|
2006-09-18 21:20:21 +00:00
|
|
|
byte *mask_ptr = getMaskBuffer(x, y, 1);
|
2012-02-04 17:34:08 +00:00
|
|
|
drawStripV1Mask(mask_ptr, stripnr, width, height);
|
2006-09-18 22:06:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void GdiV2::decodeMask(int x, int y, const int width, const int height,
|
|
|
|
int stripnr, int numzbuf, const byte *zplane_list[9],
|
2011-05-11 12:02:21 +00:00
|
|
|
bool transpStrip, byte flag) {
|
2006-09-18 22:06:39 +00:00
|
|
|
// Do nothing here for V2 games - zplane was already handled.
|
2006-09-18 21:20:21 +00:00
|
|
|
}
|
|
|
|
|
2008-05-06 03:00:26 +00:00
|
|
|
#ifdef ENABLE_HE
|
2004-08-26 02:47:49 +00:00
|
|
|
/**
|
|
|
|
* Draw a bitmap onto a virtual screen. This is main drawing method for room backgrounds
|
2006-03-16 12:08:25 +00:00
|
|
|
* used throughout HE71+ versions.
|
2004-09-19 20:17:57 +00:00
|
|
|
*
|
2004-10-07 16:09:30 +00:00
|
|
|
* @note This function essentially is a stripped down & special cased version of
|
|
|
|
* the generic Gdi::drawBitmap() method.
|
2004-08-26 02:47:49 +00:00
|
|
|
*/
|
2005-03-26 06:00:58 +00:00
|
|
|
void Gdi::drawBMAPBg(const byte *ptr, VirtScreen *vs) {
|
2004-08-26 02:47:49 +00:00
|
|
|
const byte *z_plane_ptr;
|
|
|
|
byte *mask_ptr;
|
|
|
|
const byte *zplane_list[9];
|
|
|
|
|
2011-04-12 14:53:15 +00:00
|
|
|
const byte *bmap_ptr = _vm->findResourceData(MKTAG('B','M','A','P'), ptr);
|
2004-10-04 14:02:37 +00:00
|
|
|
assert(bmap_ptr);
|
2004-08-26 02:47:49 +00:00
|
|
|
|
2005-03-26 06:00:58 +00:00
|
|
|
byte code = *bmap_ptr++;
|
2006-03-16 12:12:05 +00:00
|
|
|
byte *dst = vs->getBackPixels(0, 0);
|
2004-08-26 03:21:33 +00:00
|
|
|
|
2004-10-07 16:09:30 +00:00
|
|
|
// The following few lines more or less duplicate decompressBitmap(), only
|
2004-09-19 20:17:57 +00:00
|
|
|
// for an area spanning multiple strips. In particular, the codecs 13 & 14
|
2004-09-30 23:30:59 +00:00
|
|
|
// in decompressBitmap call drawStripHE()
|
2004-10-08 10:49:30 +00:00
|
|
|
_decomp_shr = code % 10;
|
|
|
|
_decomp_mask = 0xFF >> (8 - _decomp_shr);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-10-08 10:49:30 +00:00
|
|
|
switch (code) {
|
2006-01-16 08:48:47 +00:00
|
|
|
case 134:
|
|
|
|
case 135:
|
|
|
|
case 136:
|
|
|
|
case 137:
|
|
|
|
case 138:
|
2005-03-26 06:00:58 +00:00
|
|
|
drawStripHE(dst, vs->pitch, bmap_ptr, vs->w, vs->h, false);
|
2004-10-08 10:49:30 +00:00
|
|
|
break;
|
2006-01-16 08:48:47 +00:00
|
|
|
case 144:
|
|
|
|
case 145:
|
|
|
|
case 146:
|
|
|
|
case 147:
|
|
|
|
case 148:
|
2005-03-26 06:00:58 +00:00
|
|
|
drawStripHE(dst, vs->pitch, bmap_ptr, vs->w, vs->h, true);
|
2004-10-08 10:49:30 +00:00
|
|
|
break;
|
2006-01-16 08:48:47 +00:00
|
|
|
case 150:
|
2011-04-17 15:29:09 +00:00
|
|
|
fill(dst, vs->pitch, *bmap_ptr, vs->w, vs->h, vs->format.bytesPerPixel);
|
2004-10-08 10:49:30 +00:00
|
|
|
break;
|
|
|
|
default:
|
2005-09-03 17:29:35 +00:00
|
|
|
// Alternative russian freddi3 uses badly formatted bitmaps
|
2005-08-14 01:41:52 +00:00
|
|
|
debug(0, "Gdi::drawBMAPBg: default case %d", code);
|
2004-08-26 02:47:49 +00:00
|
|
|
}
|
2004-10-08 10:49:30 +00:00
|
|
|
|
2006-09-17 23:35:09 +00:00
|
|
|
((ScummEngine_v71he *)_vm)->restoreBackgroundHE(Common::Rect(vs->w, vs->h));
|
2004-08-26 02:47:49 +00:00
|
|
|
|
2004-09-28 21:42:34 +00:00
|
|
|
int numzbuf = getZPlanes(ptr, zplane_list, true);
|
|
|
|
if (numzbuf <= 1)
|
2004-08-26 02:47:49 +00:00
|
|
|
return;
|
|
|
|
|
2004-09-27 01:26:05 +00:00
|
|
|
uint32 offs;
|
2006-03-13 02:22:22 +00:00
|
|
|
for (int stripnr = 0; stripnr < _numStrips; stripnr++) {
|
2004-09-28 21:42:34 +00:00
|
|
|
for (int i = 1; i < numzbuf; i++) {
|
2004-09-19 21:14:51 +00:00
|
|
|
if (!zplane_list[i])
|
2004-08-26 02:47:49 +00:00
|
|
|
continue;
|
|
|
|
|
2004-09-19 21:14:51 +00:00
|
|
|
offs = READ_LE_UINT16(zplane_list[i] + stripnr * 2 + 8);
|
|
|
|
mask_ptr = getMaskBuffer(stripnr, 0, i);
|
2004-08-26 02:47:49 +00:00
|
|
|
|
|
|
|
if (offs) {
|
2004-09-19 21:14:51 +00:00
|
|
|
z_plane_ptr = zplane_list[i] + offs;
|
2004-08-26 02:47:49 +00:00
|
|
|
decompressMaskImg(mask_ptr, z_plane_ptr, vs->h);
|
|
|
|
}
|
|
|
|
}
|
2006-03-13 02:22:22 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
// HACK: blit mask(s) onto normal screen. Useful to debug masking
|
|
|
|
for (int i = 0; i < numzbuf; i++) {
|
|
|
|
byte *dst1 = (byte *)vs->pixels + stripnr * 8;
|
|
|
|
byte *dst2 = vs->backBuf + stripnr * 8;
|
|
|
|
|
|
|
|
mask_ptr = getMaskBuffer(stripnr, 0, i);
|
|
|
|
for (int h = 0; h < vs->h; h++) {
|
|
|
|
int maskbits = *mask_ptr;
|
|
|
|
for (int j = 0; j < 8; j++) {
|
|
|
|
if (maskbits & 0x80)
|
|
|
|
dst1[j] = dst2[j] = 12 + i;
|
|
|
|
maskbits <<= 1;
|
|
|
|
}
|
|
|
|
dst1 += vs->pitch;
|
|
|
|
dst2 += vs->pitch;
|
|
|
|
mask_ptr += _numStrips;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2004-08-26 02:47:49 +00:00
|
|
|
}
|
|
|
|
|
2004-09-05 17:39:54 +00:00
|
|
|
void Gdi::drawBMAPObject(const byte *ptr, VirtScreen *vs, int obj, int x, int y, int w, int h) {
|
2011-04-12 14:53:15 +00:00
|
|
|
const byte *bmap_ptr = _vm->findResourceData(MKTAG('B','M','A','P'), ptr);
|
2004-10-04 14:02:37 +00:00
|
|
|
assert(bmap_ptr);
|
2004-09-05 17:39:54 +00:00
|
|
|
|
2004-10-07 06:54:33 +00:00
|
|
|
byte code = *bmap_ptr++;
|
2009-09-25 09:13:33 +00:00
|
|
|
int scrX = _vm->_screenStartStrip * 8 * _vm->_bytesPerPixel;
|
2004-09-05 17:39:54 +00:00
|
|
|
|
|
|
|
if (code == 8 || code == 9) {
|
|
|
|
Common::Rect rScreen(0, 0, vs->w, vs->h);
|
2007-09-08 11:15:27 +00:00
|
|
|
byte *dst = (byte *)_vm->_virtscr[kMainVirtScreen].backBuf + scrX;
|
2009-09-25 09:13:33 +00:00
|
|
|
Wiz::copyWizImage(dst, bmap_ptr, vs->pitch, kDstScreen, vs->w, vs->h, x - scrX, y, w, h, &rScreen, 0, 0, 0, _vm->_bytesPerPixel);
|
2004-09-05 17:39:54 +00:00
|
|
|
}
|
|
|
|
|
2004-09-06 10:52:52 +00:00
|
|
|
Common::Rect rect1(x, y, x + w, y + h);
|
2004-09-05 17:39:54 +00:00
|
|
|
Common::Rect rect2(scrX, 0, vs->w + scrX, vs->h);
|
|
|
|
|
2004-09-06 10:52:52 +00:00
|
|
|
if (rect1.intersects(rect2)) {
|
2005-03-26 06:00:58 +00:00
|
|
|
rect1.clip(rect2);
|
2004-09-05 17:39:54 +00:00
|
|
|
rect1.left -= rect2.left;
|
|
|
|
rect1.right -= rect2.left;
|
|
|
|
rect1.top -= rect2.top;
|
|
|
|
rect1.bottom -= rect2.top;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2006-09-17 23:35:09 +00:00
|
|
|
((ScummEngine_v71he *)_vm)->restoreBackgroundHE(rect1);
|
2004-09-05 17:39:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-17 23:35:09 +00:00
|
|
|
void ScummEngine_v70he::restoreBackgroundHE(Common::Rect rect, int dirtybit) {
|
2005-03-06 00:46:13 +00:00
|
|
|
byte *src, *dst;
|
2007-09-08 11:15:27 +00:00
|
|
|
VirtScreen *vs = &_virtscr[kMainVirtScreen];
|
2005-03-06 00:46:13 +00:00
|
|
|
|
|
|
|
if (rect.top > vs->h || rect.bottom < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (rect.left > vs->w || rect.right < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
rect.left = MAX(0, (int)rect.left);
|
|
|
|
rect.left = MIN((int)rect.left, (int)vs->w - 1);
|
|
|
|
|
|
|
|
rect.right = MAX(0, (int)rect.right);
|
|
|
|
rect.right = MIN((int)rect.right, (int)vs->w);
|
|
|
|
|
|
|
|
rect.top = MAX(0, (int)rect.top);
|
|
|
|
rect.top = MIN((int)rect.top, (int)vs->h - 1);
|
|
|
|
|
|
|
|
rect.bottom = MAX(0, (int)rect.bottom);
|
|
|
|
rect.bottom = MIN((int)rect.bottom, (int)vs->h);
|
|
|
|
|
2004-10-07 16:09:30 +00:00
|
|
|
const int rw = rect.width();
|
|
|
|
const int rh = rect.height();
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2005-03-06 00:46:13 +00:00
|
|
|
if (rw == 0 || rh == 0)
|
|
|
|
return;
|
|
|
|
|
2007-09-08 11:15:27 +00:00
|
|
|
src = _virtscr[kMainVirtScreen].getBackPixels(rect.left, rect.top);
|
|
|
|
dst = _virtscr[kMainVirtScreen].getPixels(rect.left, rect.top);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2006-09-17 23:35:09 +00:00
|
|
|
assert(rw <= _screenWidth && rw > 0);
|
|
|
|
assert(rh <= _screenHeight && rh > 0);
|
2011-04-17 15:29:09 +00:00
|
|
|
blit(dst, _virtscr[kMainVirtScreen].pitch, src, _virtscr[kMainVirtScreen].pitch, rw, rh, vs->format.bytesPerPixel);
|
2006-09-17 23:35:09 +00:00
|
|
|
markRectAsDirty(kMainVirtScreen, rect, dirtybit);
|
2004-08-26 02:47:49 +00:00
|
|
|
}
|
2006-09-18 19:22:40 +00:00
|
|
|
#endif
|
2004-08-26 02:47:49 +00:00
|
|
|
|
2004-01-04 14:35:46 +00:00
|
|
|
/**
|
|
|
|
* Reset the background behind an actor or blast object.
|
|
|
|
*/
|
|
|
|
void Gdi::resetBackground(int top, int bottom, int strip) {
|
2007-09-08 11:15:27 +00:00
|
|
|
VirtScreen *vs = &_vm->_virtscr[kMainVirtScreen];
|
2004-01-04 14:35:46 +00:00
|
|
|
byte *backbuff_ptr, *bgbak_ptr;
|
2004-08-14 19:42:00 +00:00
|
|
|
int numLinesToProcess;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2005-08-10 22:13:55 +00:00
|
|
|
if (top < 0)
|
|
|
|
top = 0;
|
|
|
|
|
|
|
|
if (bottom > vs->h)
|
2005-04-26 13:16:02 +00:00
|
|
|
bottom = vs->h;
|
|
|
|
|
|
|
|
if (top >= bottom)
|
|
|
|
return;
|
2004-01-04 14:35:46 +00:00
|
|
|
|
|
|
|
assert(0 <= strip && strip < _numStrips);
|
|
|
|
|
|
|
|
if (top < vs->tdirty[strip])
|
|
|
|
vs->tdirty[strip] = top;
|
|
|
|
|
|
|
|
if (bottom > vs->bdirty[strip])
|
|
|
|
vs->bdirty[strip] = bottom;
|
|
|
|
|
2011-04-17 15:29:09 +00:00
|
|
|
bgbak_ptr = (byte *)vs->backBuf + top * vs->pitch + (strip + vs->xstart/8) * 8 * vs->format.bytesPerPixel;
|
2013-08-04 00:29:13 +00:00
|
|
|
backbuff_ptr = (byte *)vs->getBasePtr((strip + vs->xstart/8) * 8, top);
|
2004-01-04 14:35:46 +00:00
|
|
|
|
|
|
|
numLinesToProcess = bottom - top;
|
|
|
|
if (numLinesToProcess) {
|
2004-01-08 21:21:40 +00:00
|
|
|
if (_vm->isLightOn()) {
|
2011-04-17 15:29:09 +00:00
|
|
|
copy8Col(backbuff_ptr, vs->pitch, bgbak_ptr, numLinesToProcess, vs->format.bytesPerPixel);
|
2004-01-04 14:35:46 +00:00
|
|
|
} else {
|
2011-04-17 15:29:09 +00:00
|
|
|
clear8Col(backbuff_ptr, vs->pitch, numLinesToProcess, vs->format.bytesPerPixel);
|
2004-01-04 14:35:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-26 00:06:51 +00:00
|
|
|
bool Gdi::decompressBitmap(byte *dst, int dstPitch, const byte *src, int numLinesToProcess) {
|
|
|
|
assert(numLinesToProcess);
|
2007-03-03 12:59:48 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_vm->_game.features & GF_16COLOR) {
|
2005-03-09 21:10:16 +00:00
|
|
|
drawStripEGA(dst, dstPitch, src, numLinesToProcess);
|
|
|
|
return false;
|
|
|
|
}
|
2003-06-04 21:45:29 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if ((_vm->_game.platform == Common::kPlatformAmiga) && (_vm->_game.version >= 4))
|
2005-09-19 00:29:41 +00:00
|
|
|
_paletteMod = 16;
|
|
|
|
else
|
|
|
|
_paletteMod = 0;
|
|
|
|
|
2006-01-16 08:48:47 +00:00
|
|
|
byte code = *src++;
|
|
|
|
bool transpStrip = false;
|
|
|
|
_decomp_shr = code % 10;
|
|
|
|
_decomp_mask = 0xFF >> (8 - _decomp_shr);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2006-01-16 08:48:47 +00:00
|
|
|
switch (code) {
|
|
|
|
case 1:
|
|
|
|
drawStripRaw(dst, dstPitch, src, numLinesToProcess, false);
|
|
|
|
break;
|
2003-06-04 21:45:29 +00:00
|
|
|
|
2006-01-16 08:48:47 +00:00
|
|
|
case 2:
|
|
|
|
unkDecode8(dst, dstPitch, src, numLinesToProcess); /* Ender - Zak256/Indy256 */
|
|
|
|
break;
|
2006-01-01 09:51:11 +00:00
|
|
|
|
2006-01-16 08:48:47 +00:00
|
|
|
case 3:
|
|
|
|
unkDecode9(dst, dstPitch, src, numLinesToProcess); /* Ender - Zak256/Indy256 */
|
|
|
|
break;
|
2006-01-01 09:51:11 +00:00
|
|
|
|
2006-01-16 08:48:47 +00:00
|
|
|
case 4:
|
|
|
|
unkDecode10(dst, dstPitch, src, numLinesToProcess); /* Ender - Zak256/Indy256 */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 7:
|
|
|
|
unkDecode11(dst, dstPitch, src, numLinesToProcess); /* Ender - Zak256/Indy256 */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
// Used in 3DO versions of HE games
|
|
|
|
transpStrip = true;
|
|
|
|
drawStrip3DO(dst, dstPitch, src, numLinesToProcess, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 9:
|
|
|
|
drawStrip3DO(dst, dstPitch, src, numLinesToProcess, false);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 10:
|
|
|
|
// Used in Amiga version of Monkey Island 1
|
|
|
|
drawStripEGA(dst, dstPitch, src, numLinesToProcess);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 14:
|
|
|
|
case 15:
|
|
|
|
case 16:
|
|
|
|
case 17:
|
|
|
|
case 18:
|
|
|
|
drawStripBasicV(dst, dstPitch, src, numLinesToProcess, false);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 24:
|
|
|
|
case 25:
|
|
|
|
case 26:
|
|
|
|
case 27:
|
|
|
|
case 28:
|
|
|
|
drawStripBasicH(dst, dstPitch, src, numLinesToProcess, false);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 34:
|
|
|
|
case 35:
|
|
|
|
case 36:
|
|
|
|
case 37:
|
|
|
|
case 38:
|
|
|
|
transpStrip = true;
|
|
|
|
drawStripBasicV(dst, dstPitch, src, numLinesToProcess, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 44:
|
|
|
|
case 45:
|
|
|
|
case 46:
|
|
|
|
case 47:
|
|
|
|
case 48:
|
|
|
|
transpStrip = true;
|
|
|
|
drawStripBasicH(dst, dstPitch, src, numLinesToProcess, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 64:
|
|
|
|
case 65:
|
|
|
|
case 66:
|
|
|
|
case 67:
|
|
|
|
case 68:
|
|
|
|
case 104:
|
|
|
|
case 105:
|
|
|
|
case 106:
|
|
|
|
case 107:
|
|
|
|
case 108:
|
|
|
|
drawStripComplex(dst, dstPitch, src, numLinesToProcess, false);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 84:
|
|
|
|
case 85:
|
|
|
|
case 86:
|
|
|
|
case 87:
|
|
|
|
case 88:
|
|
|
|
case 124:
|
|
|
|
case 125:
|
|
|
|
case 126:
|
|
|
|
case 127:
|
|
|
|
case 128:
|
|
|
|
transpStrip = true;
|
|
|
|
drawStripComplex(dst, dstPitch, src, numLinesToProcess, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 134:
|
|
|
|
case 135:
|
|
|
|
case 136:
|
|
|
|
case 137:
|
|
|
|
case 138:
|
|
|
|
drawStripHE(dst, dstPitch, src, 8, numLinesToProcess, false);
|
|
|
|
break;
|
|
|
|
|
2006-01-28 22:39:26 +00:00
|
|
|
case 143: // Triggered by Russian water
|
2006-01-16 08:48:47 +00:00
|
|
|
case 144:
|
|
|
|
case 145:
|
|
|
|
case 146:
|
|
|
|
case 147:
|
|
|
|
case 148:
|
|
|
|
transpStrip = true;
|
|
|
|
drawStripHE(dst, dstPitch, src, 8, numLinesToProcess, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 149:
|
|
|
|
drawStripRaw(dst, dstPitch, src, numLinesToProcess, true);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
error("Gdi::decompressBitmap: default case %d", code);
|
2004-09-26 00:06:51 +00:00
|
|
|
}
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2006-01-01 09:55:56 +00:00
|
|
|
return transpStrip;
|
2004-09-26 00:06:51 +00:00
|
|
|
}
|
2003-06-04 21:45:29 +00:00
|
|
|
|
2004-09-26 00:06:51 +00:00
|
|
|
void Gdi::decompressMaskImg(byte *dst, const byte *src, int height) const {
|
|
|
|
byte b, c;
|
2003-06-04 21:45:29 +00:00
|
|
|
|
2004-09-26 00:06:51 +00:00
|
|
|
while (height) {
|
|
|
|
b = *src++;
|
2003-06-04 21:45:29 +00:00
|
|
|
|
2004-09-26 00:06:51 +00:00
|
|
|
if (b & 0x80) {
|
|
|
|
b &= 0x7F;
|
|
|
|
c = *src++;
|
|
|
|
|
|
|
|
do {
|
|
|
|
*dst = c;
|
|
|
|
dst += _numStrips;
|
|
|
|
--height;
|
|
|
|
} while (--b && height);
|
|
|
|
} else {
|
|
|
|
do {
|
|
|
|
*dst = *src++;
|
|
|
|
dst += _numStrips;
|
|
|
|
--height;
|
|
|
|
} while (--b && height);
|
2003-06-04 21:45:29 +00:00
|
|
|
}
|
|
|
|
}
|
2004-09-26 00:06:51 +00:00
|
|
|
}
|
2003-06-04 21:45:29 +00:00
|
|
|
|
2011-05-11 12:02:21 +00:00
|
|
|
void GdiHE::decompressTMSK(byte *dst, const byte *tmsk, const byte *src, int height) const {
|
2005-05-21 14:14:03 +00:00
|
|
|
byte srcbits = 0;
|
|
|
|
byte srcFlag = 0;
|
|
|
|
byte maskFlag = 0;
|
2005-05-21 09:05:58 +00:00
|
|
|
|
2005-05-21 14:14:03 +00:00
|
|
|
byte srcCount = 0;
|
|
|
|
byte maskCount = 0;
|
|
|
|
byte maskbits = 0;
|
2005-05-21 09:05:58 +00:00
|
|
|
|
|
|
|
while (height) {
|
2005-05-21 14:14:03 +00:00
|
|
|
if (srcCount == 0) {
|
|
|
|
srcCount = *src++;
|
|
|
|
srcFlag = srcCount & 0x80;
|
|
|
|
if (srcFlag) {
|
|
|
|
srcCount &= 0x7F;
|
|
|
|
srcbits = *src++;
|
2005-05-21 09:05:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-05-21 14:14:03 +00:00
|
|
|
if (srcFlag == 0) {
|
|
|
|
srcbits = *src++;
|
2005-05-21 09:05:58 +00:00
|
|
|
}
|
|
|
|
|
2005-05-21 14:14:03 +00:00
|
|
|
srcCount--;
|
|
|
|
|
|
|
|
if (maskCount == 0) {
|
|
|
|
maskCount = *tmsk++;
|
|
|
|
maskFlag = maskCount & 0x80;
|
|
|
|
if (maskFlag) {
|
|
|
|
maskCount &= 0x7F;
|
|
|
|
maskbits = *tmsk++;
|
2005-05-21 09:05:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-05-21 14:14:03 +00:00
|
|
|
if (maskFlag == 0) {
|
|
|
|
maskbits = *tmsk++;
|
2005-05-21 09:05:58 +00:00
|
|
|
}
|
|
|
|
|
2005-05-21 14:14:03 +00:00
|
|
|
maskCount--;
|
2005-05-21 09:05:58 +00:00
|
|
|
|
2005-10-19 07:06:10 +00:00
|
|
|
*dst |= srcbits;
|
|
|
|
*dst &= ~maskbits;
|
2005-05-21 09:05:58 +00:00
|
|
|
|
2005-10-19 07:06:10 +00:00
|
|
|
dst += _numStrips;
|
2005-05-21 09:05:58 +00:00
|
|
|
height--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-26 00:06:51 +00:00
|
|
|
void Gdi::decompressMaskImgOr(byte *dst, const byte *src, int height) const {
|
|
|
|
byte b, c;
|
|
|
|
|
|
|
|
while (height) {
|
|
|
|
b = *src++;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-09-26 00:06:51 +00:00
|
|
|
if (b & 0x80) {
|
|
|
|
b &= 0x7F;
|
|
|
|
c = *src++;
|
|
|
|
|
|
|
|
do {
|
|
|
|
*dst |= c;
|
|
|
|
dst += _numStrips;
|
|
|
|
--height;
|
|
|
|
} while (--b && height);
|
|
|
|
} else {
|
|
|
|
do {
|
|
|
|
*dst |= *src++;
|
|
|
|
dst += _numStrips;
|
|
|
|
--height;
|
|
|
|
} while (--b && height);
|
2003-06-04 21:45:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-18 21:20:21 +00:00
|
|
|
static void decodeNESTileData(const byte *src, byte *dest) {
|
2005-03-13 23:18:59 +00:00
|
|
|
int len = READ_LE_UINT16(src); src += 2;
|
|
|
|
const byte *end = src + len;
|
2005-03-24 03:22:32 +00:00
|
|
|
src++; // skip number-of-tiles byte, assume it is correct
|
2005-03-13 23:18:59 +00:00
|
|
|
while (src < end) {
|
|
|
|
byte data = *src++;
|
|
|
|
for (int j = 0; j < (data & 0x7F); j++)
|
|
|
|
*dest++ = (data & 0x80) ? (*src++) : (*src);
|
|
|
|
if (!(data & 0x80))
|
|
|
|
src++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-03-16 03:20:32 +00:00
|
|
|
void ScummEngine::decodeNESBaseTiles() {
|
|
|
|
byte *basetiles = getResourceAddress(rtCostume, 37);
|
|
|
|
_NESBaseTiles = basetiles[2];
|
2005-03-24 03:22:32 +00:00
|
|
|
decodeNESTileData(basetiles, _NESPatTable[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const int v1MMNEScostTables[2][6] = {
|
2010-10-23 15:46:50 +00:00
|
|
|
/* desc lens offs data gfx pal */
|
2005-03-24 03:22:32 +00:00
|
|
|
{ 25, 27, 29, 31, 33, 35},
|
|
|
|
{ 26, 28, 30, 32, 34, 36}
|
|
|
|
};
|
2006-09-18 21:20:21 +00:00
|
|
|
|
2005-03-24 03:22:32 +00:00
|
|
|
void ScummEngine::NES_loadCostumeSet(int n) {
|
|
|
|
int i;
|
|
|
|
_NESCostumeSet = n;
|
|
|
|
|
|
|
|
_NEScostdesc = getResourceAddress(rtCostume, v1MMNEScostTables[n][0]) + 2;
|
|
|
|
_NEScostlens = getResourceAddress(rtCostume, v1MMNEScostTables[n][1]) + 2;
|
|
|
|
_NEScostoffs = getResourceAddress(rtCostume, v1MMNEScostTables[n][2]) + 2;
|
|
|
|
_NEScostdata = getResourceAddress(rtCostume, v1MMNEScostTables[n][3]) + 2;
|
|
|
|
decodeNESTileData(getResourceAddress(rtCostume, v1MMNEScostTables[n][4]), _NESPatTable[0]);
|
|
|
|
byte *palette = getResourceAddress(rtCostume, v1MMNEScostTables[n][5]) + 2;
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
|
|
byte c = *palette++;
|
2005-03-25 22:25:40 +00:00
|
|
|
if (c == 0x1D) // HACK - switch around colors 0x00 and 0x1D
|
|
|
|
c = 0; // so we don't need a zillion extra checks
|
|
|
|
else if (c == 0)// for determining the proper background color
|
|
|
|
c = 0x1D;
|
2005-03-24 03:22:32 +00:00
|
|
|
_NESPalette[1][i] = c;
|
|
|
|
}
|
|
|
|
|
2005-03-16 03:20:32 +00:00
|
|
|
}
|
|
|
|
|
2006-09-18 21:20:21 +00:00
|
|
|
void GdiNES::decodeNESGfx(const byte *room) {
|
2005-03-13 23:18:59 +00:00
|
|
|
const byte *gdata = room + READ_LE_UINT16(room + 0x0A);
|
|
|
|
int tileset = *gdata++;
|
|
|
|
int width = READ_LE_UINT16(room + 0x04);
|
2005-03-14 11:46:10 +00:00
|
|
|
// int height = READ_LE_UINT16(room + 0x06);
|
2005-03-15 21:48:06 +00:00
|
|
|
int i, j, n;
|
2005-03-13 23:18:59 +00:00
|
|
|
|
2005-03-24 03:22:32 +00:00
|
|
|
// We have narrow room. so expand it
|
|
|
|
if (width < 32) {
|
|
|
|
_vm->_NESStartStrip = (32 - width) >> 1;
|
|
|
|
} else {
|
|
|
|
_vm->_NESStartStrip = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
decodeNESTileData(_vm->getResourceAddress(rtCostume, 37 + tileset), _vm->_NESPatTable[1] + _vm->_NESBaseTiles * 16);
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
|
|
byte c = *gdata++;
|
|
|
|
if (c == 0x0D)
|
|
|
|
c = 0x1D;
|
|
|
|
|
|
|
|
if (c == 0x1D) // HACK - switch around colors 0x00 and 0x1D
|
|
|
|
c = 0; // so we don't need a zillion extra checks
|
|
|
|
else if (c == 0) // for determining the proper background color
|
|
|
|
c = 0x1D;
|
|
|
|
|
|
|
|
_vm->_NESPalette[0][i] = c;
|
|
|
|
}
|
2005-03-15 08:21:48 +00:00
|
|
|
for (i = 0; i < 16; i++) {
|
2005-03-28 20:27:12 +00:00
|
|
|
_NES.nametable[i][0] = _NES.nametable[i][1] = 0;
|
2005-03-15 21:48:06 +00:00
|
|
|
n = 0;
|
2005-03-13 23:18:59 +00:00
|
|
|
while (n < width) {
|
|
|
|
byte data = *gdata++;
|
2005-03-15 21:48:06 +00:00
|
|
|
for (j = 0; j < (data & 0x7F); j++)
|
2005-03-28 20:27:12 +00:00
|
|
|
_NES.nametable[i][2 + n++] = (data & 0x80) ? (*gdata++) : (*gdata);
|
2005-03-13 23:18:59 +00:00
|
|
|
if (!(data & 0x80))
|
|
|
|
gdata++;
|
|
|
|
}
|
2005-03-28 20:27:12 +00:00
|
|
|
_NES.nametable[i][width+2] = _NES.nametable[i][width+3] = 0;
|
2005-03-13 23:18:59 +00:00
|
|
|
}
|
2005-05-18 23:17:04 +00:00
|
|
|
memcpy(_NES.nametableObj,_NES.nametable, 16*64);
|
2005-03-13 23:18:59 +00:00
|
|
|
|
|
|
|
const byte *adata = room + READ_LE_UINT16(room + 0x0C);
|
2005-03-15 21:48:06 +00:00
|
|
|
for (n = 0; n < 64;) {
|
2005-03-13 23:18:59 +00:00
|
|
|
byte data = *adata++;
|
2005-03-15 21:48:06 +00:00
|
|
|
for (j = 0; j < (data & 0x7F); j++)
|
2005-03-28 20:27:12 +00:00
|
|
|
_NES.attributes[n++] = (data & 0x80) ? (*adata++) : (*adata);
|
2005-03-13 23:18:59 +00:00
|
|
|
if (!(n & 7) && (width == 0x1C))
|
|
|
|
n += 8;
|
|
|
|
if (!(data & 0x80))
|
|
|
|
adata++;
|
|
|
|
}
|
2005-05-18 20:40:50 +00:00
|
|
|
memcpy(_NES.attributesObj, _NES.attributes, 64);
|
2005-03-13 23:18:59 +00:00
|
|
|
|
2005-03-21 23:51:48 +00:00
|
|
|
const byte *mdata = room + READ_LE_UINT16(room + 0x0E);
|
|
|
|
int mask = *mdata++;
|
2005-03-22 21:07:00 +00:00
|
|
|
if (mask == 0) {
|
2005-03-28 20:27:12 +00:00
|
|
|
_NES.hasmask = false;
|
2005-03-21 23:51:48 +00:00
|
|
|
return;
|
|
|
|
}
|
2005-03-28 20:27:12 +00:00
|
|
|
_NES.hasmask = true;
|
2005-03-22 21:07:00 +00:00
|
|
|
if (mask != 1)
|
2006-04-04 22:04:51 +00:00
|
|
|
debug(0,"NES room %i has irregular mask count %i",_vm->_currentRoom,mask);
|
2005-03-21 23:51:48 +00:00
|
|
|
int mwidth = *mdata++;
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
|
|
n = 0;
|
|
|
|
while (n < mwidth) {
|
|
|
|
byte data = *mdata++;
|
|
|
|
for (j = 0; j < (data & 0x7F); j++)
|
2005-03-28 20:27:12 +00:00
|
|
|
_NES.masktable[i][n++] = (data & 0x80) ? (*mdata++) : (*mdata);
|
2005-03-21 23:51:48 +00:00
|
|
|
if (!(data & 0x80))
|
|
|
|
mdata++;
|
|
|
|
}
|
|
|
|
}
|
2005-05-18 23:17:04 +00:00
|
|
|
memcpy(_NES.masktableObj, _NES.masktable, 16*8);
|
2005-03-13 23:18:59 +00:00
|
|
|
}
|
|
|
|
|
2006-09-18 21:20:21 +00:00
|
|
|
void GdiNES::decodeNESObject(const byte *ptr, int xpos, int ypos, int width, int height) {
|
2005-03-22 21:07:00 +00:00
|
|
|
int x, y;
|
2005-03-16 02:14:35 +00:00
|
|
|
|
2005-03-28 20:27:12 +00:00
|
|
|
_NES.objX = xpos;
|
2005-03-22 21:07:00 +00:00
|
|
|
|
|
|
|
// decode tile update data
|
2005-05-18 23:17:04 +00:00
|
|
|
width /= 8;
|
2005-03-16 02:14:35 +00:00
|
|
|
ypos /= 8;
|
|
|
|
height /= 8;
|
2005-05-18 23:17:04 +00:00
|
|
|
|
2005-03-16 02:14:35 +00:00
|
|
|
for (y = ypos; y < ypos + height; y++) {
|
2005-03-22 21:07:00 +00:00
|
|
|
x = xpos;
|
2005-03-16 02:14:35 +00:00
|
|
|
while (x < xpos + width) {
|
|
|
|
byte len = *ptr++;
|
|
|
|
for (int i = 0; i < (len & 0x7F); i++)
|
2005-03-28 20:27:12 +00:00
|
|
|
_NES.nametableObj[y][2 + x++] = (len & 0x80) ? (*ptr++) : (*ptr);
|
2005-03-16 02:14:35 +00:00
|
|
|
if (!(len & 0x80))
|
|
|
|
ptr++;
|
|
|
|
}
|
|
|
|
}
|
2005-03-22 21:07:00 +00:00
|
|
|
|
|
|
|
int ax, ay;
|
|
|
|
// decode attribute update data
|
|
|
|
y = height / 2;
|
|
|
|
ay = ypos;
|
|
|
|
while (y) {
|
|
|
|
ax = xpos + 2;
|
|
|
|
x = 0;
|
|
|
|
int adata = 0;
|
|
|
|
while (x < (width >> 1)) {
|
|
|
|
if (!(x & 3))
|
|
|
|
adata = *ptr++;
|
2005-03-28 20:27:12 +00:00
|
|
|
byte *dest = &_NES.attributesObj[((ay << 2) & 0x30) | ((ax >> 2) & 0xF)];
|
2005-03-22 21:07:00 +00:00
|
|
|
|
|
|
|
int aand = 3;
|
|
|
|
int aor = adata & 3;
|
|
|
|
if (ay & 0x02) {
|
|
|
|
aand <<= 4;
|
|
|
|
aor <<= 4;
|
|
|
|
}
|
|
|
|
if (ax & 0x02) {
|
|
|
|
aand <<= 2;
|
|
|
|
aor <<= 2;
|
|
|
|
}
|
|
|
|
*dest = ((~aand) & *dest) | aor;
|
|
|
|
|
|
|
|
adata >>= 2;
|
|
|
|
ax += 2;
|
|
|
|
x++;
|
|
|
|
}
|
|
|
|
ay += 2;
|
|
|
|
y--;
|
|
|
|
}
|
|
|
|
|
|
|
|
// decode mask update data
|
2005-03-28 20:27:12 +00:00
|
|
|
if (!_NES.hasmask)
|
2005-03-22 21:07:00 +00:00
|
|
|
return;
|
|
|
|
int mx, mwidth;
|
|
|
|
int lmask, rmask;
|
|
|
|
mx = *ptr++;
|
|
|
|
mwidth = *ptr++;
|
|
|
|
lmask = *ptr++;
|
|
|
|
rmask = *ptr++;
|
|
|
|
|
2006-09-18 21:20:21 +00:00
|
|
|
for (y = 0; y < height; ++y) {
|
2005-03-28 20:27:12 +00:00
|
|
|
byte *dest = &_NES.masktableObj[y + ypos][mx];
|
2005-05-18 23:17:04 +00:00
|
|
|
*dest = (*dest & lmask) | *ptr++;
|
|
|
|
dest++;
|
2005-03-22 21:07:00 +00:00
|
|
|
for (x = 1; x < mwidth; x++) {
|
|
|
|
if (x + 1 == mwidth)
|
2005-05-18 23:17:04 +00:00
|
|
|
*dest = (*dest & rmask) | *ptr++;
|
2005-03-22 21:07:00 +00:00
|
|
|
else
|
2005-05-18 23:17:04 +00:00
|
|
|
*dest = *ptr++;
|
|
|
|
dest++;
|
2005-03-22 21:07:00 +00:00
|
|
|
}
|
2006-09-18 21:20:21 +00:00
|
|
|
}
|
2005-03-16 02:14:35 +00:00
|
|
|
}
|
|
|
|
|
2006-09-18 21:20:21 +00:00
|
|
|
void GdiNES::drawStripNES(byte *dst, byte *mask, int dstPitch, int stripnr, int top, int height) {
|
2005-03-16 02:14:35 +00:00
|
|
|
top /= 8;
|
2005-03-13 23:18:59 +00:00
|
|
|
height /= 8;
|
|
|
|
int x = stripnr + 2; // NES version has a 2 tile gap on each edge
|
2005-03-15 04:05:15 +00:00
|
|
|
|
2005-03-25 00:56:03 +00:00
|
|
|
if (_objectMode)
|
2005-03-28 20:27:12 +00:00
|
|
|
x += _NES.objX; // for objects, need to start at the left edge of the object, not the screen
|
2005-03-15 21:15:37 +00:00
|
|
|
if (x > 63) {
|
2005-03-15 04:05:15 +00:00
|
|
|
debug(0,"NES tried to render invalid strip %i",stripnr);
|
|
|
|
return;
|
|
|
|
}
|
2005-03-16 02:14:35 +00:00
|
|
|
for (int y = top; y < top + height; y++) {
|
2005-03-28 20:27:12 +00:00
|
|
|
int palette = ((_objectMode ? _NES.attributesObj : _NES.attributes)[((y << 2) & 0x30) | ((x >> 2) & 0xF)] >> (((y & 2) << 1) | (x & 2))) & 0x3;
|
|
|
|
int tile = (_objectMode ? _NES.nametableObj : _NES.nametable)[y][x];
|
2005-03-13 23:18:59 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < 8; i++) {
|
2005-03-24 03:22:32 +00:00
|
|
|
byte c0 = _vm->_NESPatTable[1][tile * 16 + i];
|
|
|
|
byte c1 = _vm->_NESPatTable[1][tile * 16 + i + 8];
|
2005-03-13 23:18:59 +00:00
|
|
|
for (int j = 0; j < 8; j++)
|
2005-03-24 03:22:32 +00:00
|
|
|
dst[j] = _vm->_NESPalette[0][((c0 >> (7 - j)) & 1) | (((c1 >> (7 - j)) & 1) << 1) | (palette << 2)];
|
2005-03-13 23:18:59 +00:00
|
|
|
dst += dstPitch;
|
2005-03-26 03:49:06 +00:00
|
|
|
*mask = c0 | c1;
|
|
|
|
mask += _numStrips;
|
2005-03-13 23:18:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-18 21:20:21 +00:00
|
|
|
void GdiNES::drawStripNESMask(byte *dst, int stripnr, int top, int height) const {
|
2005-05-18 23:17:04 +00:00
|
|
|
top /= 8;
|
2005-03-21 23:51:48 +00:00
|
|
|
height /= 8;
|
2005-05-18 23:17:04 +00:00
|
|
|
int x = stripnr; // masks, unlike room graphics, should NOT be adjusted
|
2005-03-22 21:07:00 +00:00
|
|
|
|
2005-03-25 00:56:03 +00:00
|
|
|
if (_objectMode)
|
2005-03-28 20:27:12 +00:00
|
|
|
x += _NES.objX; // for objects, need to start at the left edge of the object, not the screen
|
2005-03-21 23:51:48 +00:00
|
|
|
if (x > 63) {
|
|
|
|
debug(0,"NES tried to mask invalid strip %i",stripnr);
|
|
|
|
return;
|
|
|
|
}
|
2005-05-18 23:17:04 +00:00
|
|
|
for (int y = top; y < top + height; y++) {
|
2005-05-18 23:57:17 +00:00
|
|
|
byte c;
|
|
|
|
if (_NES.hasmask)
|
|
|
|
c = (((_objectMode ? _NES.masktableObj : _NES.masktable)[y][x >> 3] >> (x & 7)) & 1) ? 0xFF : 0x00;
|
|
|
|
else
|
|
|
|
c = 0;
|
|
|
|
|
2005-03-21 23:51:48 +00:00
|
|
|
for (int i = 0; i < 8; i++) {
|
2005-05-18 23:17:04 +00:00
|
|
|
*dst &= c;
|
2005-03-21 23:51:48 +00:00
|
|
|
dst += _numStrips;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-22 11:43:12 +00:00
|
|
|
#ifdef USE_RGB_COLOR
|
2009-10-21 12:59:10 +00:00
|
|
|
void readOffsetTable(const byte *ptr, uint16 **table, int *count) {
|
|
|
|
int pos = 0;
|
|
|
|
*count = READ_LE_UINT16(ptr) / 2 + 1;
|
2012-02-15 15:53:31 +00:00
|
|
|
*table = (uint16 *)malloc(*count * sizeof(uint16));
|
2009-10-21 12:59:10 +00:00
|
|
|
for (int i = 0; i < *count; i++) {
|
|
|
|
(*table)[i] = READ_LE_UINT16(ptr + pos) + pos + 2;
|
|
|
|
pos += 2;
|
2010-01-25 01:39:44 +00:00
|
|
|
}
|
2009-10-21 12:59:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void decodeTileColor(byte cmd, byte *colors, int *rowIndex, int numRows) {
|
|
|
|
colors[(*rowIndex)++] = ((cmd) >> 4) & 0xF;
|
|
|
|
if (*rowIndex < numRows)
|
|
|
|
colors[(*rowIndex)++] = (cmd) & 0xF;
|
|
|
|
}
|
|
|
|
|
2009-10-26 10:15:05 +00:00
|
|
|
void GdiPCEngine::decodeStrip(const byte *ptr, uint16 *tiles, byte *colors, uint16 *masks, int numRows, bool isObject) {
|
2009-10-21 12:59:10 +00:00
|
|
|
int loopCnt;
|
|
|
|
uint16 lastTileData;
|
2010-01-25 01:39:44 +00:00
|
|
|
|
2009-10-26 02:45:26 +00:00
|
|
|
/*
|
|
|
|
* read tiles indices
|
|
|
|
*/
|
|
|
|
|
2009-10-21 12:59:10 +00:00
|
|
|
int rowIndex = 0;
|
|
|
|
if (isObject) {
|
|
|
|
loopCnt = numRows;
|
|
|
|
} else {
|
|
|
|
tiles[rowIndex++] = 0;
|
|
|
|
tiles[numRows - 1] = 0;
|
|
|
|
loopCnt = numRows - 1;
|
|
|
|
}
|
2010-01-25 01:39:44 +00:00
|
|
|
|
2009-10-21 12:59:10 +00:00
|
|
|
while (true) {
|
|
|
|
uint16 cmd = READ_LE_UINT16(ptr);
|
|
|
|
ptr += 2;
|
|
|
|
if (cmd & 0x8000) {
|
|
|
|
tiles[rowIndex - 1] = cmd & 0x0FFF;
|
|
|
|
} else if (cmd & 0x4000) {
|
2010-01-25 01:39:44 +00:00
|
|
|
tiles[numRows - 1] = cmd & 0x0FFF;
|
2009-10-21 12:59:10 +00:00
|
|
|
} else {
|
|
|
|
tiles[rowIndex++] = cmd;
|
|
|
|
lastTileData = cmd;
|
|
|
|
break;
|
|
|
|
}
|
2010-01-25 01:39:44 +00:00
|
|
|
}
|
|
|
|
|
2009-10-21 12:59:10 +00:00
|
|
|
while (rowIndex < loopCnt) {
|
|
|
|
byte cmd = *ptr++;
|
|
|
|
int cnt = cmd & 0x1F;
|
2010-01-25 01:39:44 +00:00
|
|
|
|
2009-10-21 12:59:10 +00:00
|
|
|
if (cmd & 0x80) {
|
|
|
|
for (int i = 0; i < cnt; ++i) {
|
|
|
|
tiles[rowIndex++] = lastTileData;
|
2010-01-25 01:39:44 +00:00
|
|
|
}
|
2009-10-21 12:59:10 +00:00
|
|
|
} else if (cmd & 0x40) {
|
|
|
|
for (int i = 0; i < cnt; ++i) {
|
|
|
|
++lastTileData;
|
|
|
|
tiles[rowIndex++] = lastTileData;
|
2010-01-25 01:39:44 +00:00
|
|
|
}
|
2009-10-21 12:59:10 +00:00
|
|
|
} else {
|
|
|
|
for (int i = 0; i < cnt; ++i) {
|
|
|
|
lastTileData = READ_LE_UINT16(ptr);
|
|
|
|
ptr += 2;
|
|
|
|
tiles[rowIndex++] = lastTileData;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* read palette data
|
|
|
|
*/
|
2010-01-25 01:39:44 +00:00
|
|
|
|
|
|
|
rowIndex = 0;
|
2009-10-21 12:59:10 +00:00
|
|
|
byte cmd = *ptr++;
|
|
|
|
if (cmd == 0xFE) {
|
|
|
|
while (rowIndex < numRows) {
|
|
|
|
decodeTileColor(*ptr++, colors, &rowIndex, numRows);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
byte lastCmd = cmd;
|
|
|
|
decodeTileColor(cmd, colors, &rowIndex, numRows);
|
|
|
|
while (rowIndex < numRows) {
|
|
|
|
cmd = *ptr++;
|
|
|
|
int cnt = cmd & 0x1F;
|
|
|
|
if (cmd & 0x80) {
|
|
|
|
for (int j = 0; j < cnt; ++j) {
|
|
|
|
decodeTileColor(lastCmd, colors, &rowIndex, numRows);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int j = 0; j < cnt; ++j) {
|
|
|
|
cmd = *ptr++;
|
|
|
|
decodeTileColor(cmd, colors, &rowIndex, numRows);
|
|
|
|
}
|
|
|
|
lastCmd = cmd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-01-25 01:39:44 +00:00
|
|
|
|
2009-10-21 12:59:10 +00:00
|
|
|
/*
|
2009-10-26 02:45:26 +00:00
|
|
|
* read mask indices
|
2009-10-21 12:59:10 +00:00
|
|
|
*/
|
2010-01-25 01:39:44 +00:00
|
|
|
|
2009-10-31 13:15:49 +00:00
|
|
|
if (_distaff || _PCE.maskIDSize == 0 || numRows > 18) {
|
2009-10-21 12:59:10 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-10-31 13:15:49 +00:00
|
|
|
|
2009-10-21 12:59:10 +00:00
|
|
|
rowIndex = 0;
|
|
|
|
while (rowIndex < numRows) {
|
|
|
|
cmd = *ptr++;
|
|
|
|
int cnt = cmd & 0x1F;
|
|
|
|
if (cmd & 0x80) {
|
|
|
|
uint16 value;
|
|
|
|
if (cmd & 0x60) {
|
|
|
|
value = (cmd & 0x40) ? 0 : 0xFF;
|
2009-10-26 10:15:05 +00:00
|
|
|
} else if (_PCE.maskIDSize == 1) {
|
2009-10-21 12:59:10 +00:00
|
|
|
value = *ptr++;
|
|
|
|
} else {
|
|
|
|
value = READ_LE_UINT16(ptr);
|
|
|
|
ptr += 2;
|
|
|
|
}
|
|
|
|
for (int i = 0; i < cnt; ++i) {
|
|
|
|
masks[rowIndex++] = value;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int i = 0; i < cnt; ++i) {
|
2009-10-26 10:15:05 +00:00
|
|
|
if (_PCE.maskIDSize == 1) {
|
2009-10-21 12:59:10 +00:00
|
|
|
masks[rowIndex++] = *ptr++;
|
|
|
|
} else {
|
|
|
|
masks[rowIndex++] = READ_LE_UINT16(ptr);
|
|
|
|
ptr += 2;
|
|
|
|
}
|
2010-01-25 01:39:44 +00:00
|
|
|
}
|
2009-10-21 12:59:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GdiPCEngine::decodePCEngineGfx(const byte *room) {
|
|
|
|
uint16* stripOffsets;
|
|
|
|
|
2011-04-12 14:53:15 +00:00
|
|
|
decodePCEngineTileData(_vm->findResourceData(MKTAG('T','I','L','E'), room));
|
|
|
|
decodePCEngineMaskData(_vm->findResourceData(MKTAG('Z','P','0','0'), room));
|
2009-10-21 12:59:10 +00:00
|
|
|
|
2011-04-12 14:53:15 +00:00
|
|
|
const byte* smap_ptr = _vm->findResourceData(MKTAG('I','M','0','0'), room);
|
2010-03-22 23:03:09 +00:00
|
|
|
smap_ptr++; // roomID
|
2009-10-21 12:59:10 +00:00
|
|
|
int numStrips = *smap_ptr++;
|
|
|
|
int numRows = *smap_ptr++;
|
2009-10-26 10:15:05 +00:00
|
|
|
_PCE.maskIDSize = *smap_ptr++;
|
2010-03-22 23:03:09 +00:00
|
|
|
smap_ptr++; // unknown
|
2010-01-25 01:39:44 +00:00
|
|
|
|
2009-10-21 12:59:10 +00:00
|
|
|
memset(_PCE.nametable, 0, sizeof(_PCE.nametable));
|
|
|
|
memset(_PCE.colortable, 0, sizeof(_PCE.colortable));
|
|
|
|
readOffsetTable(smap_ptr, &stripOffsets, &numStrips);
|
|
|
|
for (int i = 0; i < numStrips; ++i) {
|
2010-01-25 01:39:44 +00:00
|
|
|
const byte *tilePtr = smap_ptr + stripOffsets[i];
|
|
|
|
decodeStrip(tilePtr,
|
|
|
|
&_PCE.nametable[i * numRows],
|
2009-10-21 12:59:10 +00:00
|
|
|
&_PCE.colortable[i * numRows],
|
|
|
|
&_PCE.masktable[i * numRows],
|
|
|
|
numRows,
|
|
|
|
false);
|
|
|
|
}
|
|
|
|
free(stripOffsets);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GdiPCEngine::decodePCEngineObject(const byte *ptr, int xpos, int ypos, int width, int height) {
|
|
|
|
uint16 *stripOffsets;
|
|
|
|
int numStrips;
|
|
|
|
int numRows = height / 8;
|
|
|
|
|
|
|
|
memset(_PCE.nametableObj, 0, sizeof(_PCE.nametableObj));
|
|
|
|
memset(_PCE.colortableObj, 0, sizeof(_PCE.colortableObj));
|
|
|
|
readOffsetTable(ptr, &stripOffsets, &numStrips);
|
|
|
|
for (int i = 0; i < numStrips; ++i) {
|
|
|
|
const byte *tilePtr = ptr + stripOffsets[i];
|
2010-01-25 01:39:44 +00:00
|
|
|
decodeStrip(tilePtr,
|
|
|
|
&_PCE.nametableObj[i * numRows],
|
|
|
|
&_PCE.colortableObj[i * numRows],
|
|
|
|
&_PCE.masktableObj[i * numRows],
|
2009-10-21 12:59:10 +00:00
|
|
|
numRows,
|
|
|
|
true);
|
|
|
|
}
|
|
|
|
free(stripOffsets);
|
|
|
|
}
|
|
|
|
|
2010-07-14 16:55:32 +00:00
|
|
|
void GdiPCEngine::setTileData(byte *tile, int index, byte byte0, byte byte1) {
|
2009-10-21 12:59:10 +00:00
|
|
|
int row = index % 8;
|
|
|
|
int plane = (index / 8) * 2;
|
|
|
|
int plane02Bit, plane13Bit;
|
|
|
|
for (int col = 0; col < 8; ++col) {
|
|
|
|
plane02Bit = (byte0 >> (7-col)) & 0x1; // plane=0: bit0, plane=2: bit2
|
|
|
|
plane13Bit = (byte1 >> (7-col)) & 0x1; // plane=0: bit1, plane=2: bit3
|
|
|
|
tile[row * 8 + col] |= plane02Bit << (plane + 0);
|
2010-01-25 01:39:44 +00:00
|
|
|
tile[row * 8 + col] |= plane13Bit << (plane + 1);
|
2009-10-21 12:59:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GdiPCEngine::decodePCEngineTileData(const byte *ptr) {
|
|
|
|
const byte *tilePtr;
|
|
|
|
byte* tile;
|
|
|
|
uint16* tileOffsets;
|
|
|
|
byte byte0, byte1;
|
|
|
|
|
|
|
|
readOffsetTable(ptr, &tileOffsets, &_PCE.numTiles);
|
2010-01-25 01:39:44 +00:00
|
|
|
|
2009-10-27 09:17:09 +00:00
|
|
|
if (_distaff) {
|
|
|
|
free(_PCE.staffTiles);
|
2012-02-15 15:53:31 +00:00
|
|
|
_PCE.staffTiles = (byte *)calloc(_PCE.numTiles * 8 * 8, sizeof(byte));
|
2009-10-27 09:17:09 +00:00
|
|
|
} else {
|
|
|
|
free(_PCE.roomTiles);
|
2012-02-15 15:53:31 +00:00
|
|
|
_PCE.roomTiles = (byte *)calloc(_PCE.numTiles * 8 * 8, sizeof(byte));
|
2009-10-27 09:17:09 +00:00
|
|
|
}
|
2009-10-26 02:45:26 +00:00
|
|
|
|
2009-10-21 12:59:10 +00:00
|
|
|
for (int i = 0; i < _PCE.numTiles; ++i) {
|
2009-10-27 09:17:09 +00:00
|
|
|
tile = (_distaff) ? &_PCE.staffTiles[i * 64] : &_PCE.roomTiles[i * 64];
|
2009-10-21 12:59:10 +00:00
|
|
|
tilePtr = ptr + tileOffsets[i];
|
2009-10-26 02:45:26 +00:00
|
|
|
|
2009-10-21 12:59:10 +00:00
|
|
|
int index = 0;
|
|
|
|
while (index < 16) {
|
|
|
|
byte cmd = *tilePtr++;
|
|
|
|
byte cnt = (cmd & 0x0F) + 1;
|
|
|
|
if (cmd & 0x80) {
|
|
|
|
byte0 = (cmd & 0x10) ? 0 : *tilePtr++;
|
|
|
|
byte1 = (cmd & 0x40) ? 0 : *tilePtr++;
|
|
|
|
while (cnt--) {
|
|
|
|
setTileData(tile, index++, byte0, byte1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
while (cnt--) {
|
|
|
|
byte0 = (cmd & 0x10) ? 0 : *tilePtr++;
|
|
|
|
byte1 = (cmd & 0x40) ? 0 : *tilePtr++;
|
|
|
|
setTileData(tile, index++, byte0, byte1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(tileOffsets);
|
|
|
|
}
|
|
|
|
|
2009-10-26 02:45:26 +00:00
|
|
|
void GdiPCEngine::decodePCEngineMaskData(const byte *ptr) {
|
|
|
|
const byte *maskPtr;
|
|
|
|
byte* mask;
|
|
|
|
uint16* maskOffsets;
|
|
|
|
|
|
|
|
if (!ptr) {
|
|
|
|
_PCE.numMasks = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
readOffsetTable(ptr, &maskOffsets, &_PCE.numMasks);
|
|
|
|
|
|
|
|
free(_PCE.masks);
|
2012-02-15 15:53:31 +00:00
|
|
|
_PCE.masks = (byte *)malloc(_PCE.numMasks * 8 * sizeof(byte));
|
2009-10-26 02:45:26 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < _PCE.numMasks; ++i) {
|
|
|
|
mask = &_PCE.masks[i * 8];
|
|
|
|
maskPtr = ptr + maskOffsets[i];
|
|
|
|
|
|
|
|
int index = 0;
|
|
|
|
while (index < 8) {
|
|
|
|
byte cmd = *maskPtr++;
|
|
|
|
int cnt = cmd & 0x1F;
|
|
|
|
if (cmd & 0x80) {
|
|
|
|
byte value;
|
|
|
|
if (cmd & 0x60)
|
|
|
|
value = (cmd & 0x40) ? 0x00 : 0xFF;
|
|
|
|
else
|
|
|
|
value = *maskPtr++;
|
|
|
|
for (int j = 0; j < cnt; ++j)
|
|
|
|
mask[index++] = ~value;
|
|
|
|
} else {
|
|
|
|
for (int j = 0; j < cnt; ++j)
|
|
|
|
mask[index++] = ~*maskPtr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(maskOffsets);
|
|
|
|
}
|
|
|
|
|
2009-10-21 12:59:10 +00:00
|
|
|
void GdiPCEngine::drawStripPCEngine(byte *dst, byte *mask, int dstPitch, int stripnr, int top, int height) {
|
|
|
|
uint16 tileIdx;
|
|
|
|
byte *tile;
|
|
|
|
int paletteIdx, paletteOffset, paletteEntry;
|
|
|
|
height /= 8;
|
|
|
|
|
2009-10-26 02:45:26 +00:00
|
|
|
for (int y = 0; y < height; y++) {
|
|
|
|
tileIdx = (_objectMode ? _PCE.nametableObj : _PCE.nametable)[stripnr * height + y];
|
2009-10-27 09:17:09 +00:00
|
|
|
tile = (_distaff) ? &_PCE.staffTiles[tileIdx * 64] : &_PCE.roomTiles[tileIdx * 64];
|
2009-10-26 02:45:26 +00:00
|
|
|
paletteIdx = (_objectMode ? _PCE.colortableObj : _PCE.colortable)[stripnr * height + y];
|
2009-10-21 12:59:10 +00:00
|
|
|
paletteOffset = paletteIdx * 16;
|
|
|
|
for (int row = 0; row < 8; row++) {
|
|
|
|
for (int col = 0; col < 8; col++) {
|
|
|
|
paletteEntry = tile[row * 8 + col];
|
2009-10-26 09:11:18 +00:00
|
|
|
WRITE_UINT16(dst + col * 2, _vm->_16BitPalette[paletteOffset + paletteEntry]);
|
2009-10-21 12:59:10 +00:00
|
|
|
}
|
|
|
|
dst += dstPitch;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GdiPCEngine::drawStripPCEngineMask(byte *dst, int stripnr, int top, int height) const {
|
2009-10-26 02:45:26 +00:00
|
|
|
uint16 maskIdx;
|
|
|
|
height /= 8;
|
|
|
|
|
|
|
|
for (int y = 0; y < height; y++) {
|
|
|
|
maskIdx = (_objectMode ? _PCE.masktableObj : _PCE.masktable)[stripnr * height + y];
|
|
|
|
for (int row = 0; row < 8; row++) {
|
|
|
|
if (_PCE.numMasks > 0)
|
|
|
|
*dst = _PCE.masks[maskIdx * 8 + row];
|
|
|
|
else
|
|
|
|
*dst = 0;
|
|
|
|
dst += _numStrips;
|
|
|
|
}
|
|
|
|
}
|
2009-10-21 12:59:10 +00:00
|
|
|
}
|
2009-11-22 11:43:12 +00:00
|
|
|
#endif
|
2009-10-21 12:59:10 +00:00
|
|
|
|
2012-02-04 17:34:08 +00:00
|
|
|
void GdiV1::drawStripV1Background(byte *dst, int dstPitch, int stripnr, int height) {
|
2003-08-25 14:27:29 +00:00
|
|
|
int charIdx;
|
2003-11-16 20:52:57 +00:00
|
|
|
height /= 8;
|
2003-06-06 20:55:39 +00:00
|
|
|
for (int y = 0; y < height; y++) {
|
2012-02-04 17:34:08 +00:00
|
|
|
_V1.colors[3] = (_V1.colorMap[y + stripnr * height] & 7);
|
2003-08-29 06:46:12 +00:00
|
|
|
// Check for room color change in V1 zak
|
2003-10-13 12:56:53 +00:00
|
|
|
if (_roomPalette[0] == 255) {
|
2012-02-04 17:34:08 +00:00
|
|
|
_V1.colors[2] = _roomPalette[2];
|
|
|
|
_V1.colors[1] = _roomPalette[1];
|
2003-08-26 15:56:37 +00:00
|
|
|
}
|
2003-08-29 06:46:12 +00:00
|
|
|
|
2012-02-04 17:34:08 +00:00
|
|
|
charIdx = _V1.picMap[y + stripnr * height] * 8;
|
2003-06-06 20:55:39 +00:00
|
|
|
for (int i = 0; i < 8; i++) {
|
2012-02-04 17:34:08 +00:00
|
|
|
byte c = _V1.charMap[charIdx + i];
|
|
|
|
dst[0] = dst[1] = _V1.colors[(c >> 6) & 3];
|
|
|
|
dst[2] = dst[3] = _V1.colors[(c >> 4) & 3];
|
|
|
|
dst[4] = dst[5] = _V1.colors[(c >> 2) & 3];
|
|
|
|
dst[6] = dst[7] = _V1.colors[(c >> 0) & 3];
|
2004-09-22 17:57:20 +00:00
|
|
|
dst += dstPitch;
|
2003-06-05 17:22:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-04 17:34:08 +00:00
|
|
|
void GdiV1::drawStripV1Object(byte *dst, int dstPitch, int stripnr, int width, int height) {
|
2003-08-25 14:27:29 +00:00
|
|
|
int charIdx;
|
2003-11-16 20:52:57 +00:00
|
|
|
height /= 8;
|
|
|
|
width /= 8;
|
2003-06-06 20:55:39 +00:00
|
|
|
for (int y = 0; y < height; y++) {
|
2012-02-04 17:34:08 +00:00
|
|
|
_V1.colors[3] = (_V1.objectMap[(y + height) * width + stripnr] & 7);
|
|
|
|
charIdx = _V1.objectMap[y * width + stripnr] * 8;
|
2003-06-06 20:55:39 +00:00
|
|
|
for (int i = 0; i < 8; i++) {
|
2012-02-04 17:34:08 +00:00
|
|
|
byte c = _V1.charMap[charIdx + i];
|
|
|
|
dst[0] = dst[1] = _V1.colors[(c >> 6) & 3];
|
|
|
|
dst[2] = dst[3] = _V1.colors[(c >> 4) & 3];
|
|
|
|
dst[4] = dst[5] = _V1.colors[(c >> 2) & 3];
|
|
|
|
dst[6] = dst[7] = _V1.colors[(c >> 0) & 3];
|
2004-09-22 17:57:20 +00:00
|
|
|
dst += dstPitch;
|
2003-06-06 05:27:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-04 17:34:08 +00:00
|
|
|
void GdiV1::drawStripV1Mask(byte *dst, int stripnr, int width, int height) const {
|
2003-08-25 14:27:29 +00:00
|
|
|
int maskIdx;
|
2003-11-16 20:52:57 +00:00
|
|
|
height /= 8;
|
|
|
|
width /= 8;
|
2003-06-06 20:55:39 +00:00
|
|
|
for (int y = 0; y < height; y++) {
|
2005-03-25 00:56:03 +00:00
|
|
|
if (_objectMode)
|
2012-02-04 17:34:08 +00:00
|
|
|
maskIdx = _V1.objectMap[(y + 2 * height) * width + stripnr] * 8;
|
2003-08-25 14:27:29 +00:00
|
|
|
else
|
2012-02-04 17:34:08 +00:00
|
|
|
maskIdx = _V1.maskMap[y + stripnr * height] * 8;
|
2003-06-06 20:55:39 +00:00
|
|
|
for (int i = 0; i < 8; i++) {
|
2012-02-04 17:34:08 +00:00
|
|
|
byte c = _V1.maskChar[maskIdx + i];
|
2003-08-25 14:27:29 +00:00
|
|
|
|
2012-02-04 17:34:08 +00:00
|
|
|
// V1/V0 masks are inverted compared to what ScummVM expects
|
2003-08-25 20:18:44 +00:00
|
|
|
*dst = c ^ 0xFF;
|
2003-08-18 15:10:22 +00:00
|
|
|
dst += _numStrips;
|
2003-06-05 17:22:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-04 17:34:08 +00:00
|
|
|
void GdiV1::decodeV1Gfx(const byte *src, byte *dst, int size) const {
|
2003-06-05 17:22:15 +00:00
|
|
|
int x, z;
|
|
|
|
byte color, run, common[4];
|
|
|
|
|
2003-06-07 00:49:36 +00:00
|
|
|
for (z = 0; z < 4; z++) {
|
2003-06-05 17:22:15 +00:00
|
|
|
common[z] = *src++;
|
|
|
|
}
|
|
|
|
|
|
|
|
x = 0;
|
2003-08-25 20:18:44 +00:00
|
|
|
while (x < size) {
|
|
|
|
run = *src++;
|
|
|
|
if (run & 0x80) {
|
|
|
|
color = common[(run >> 5) & 3];
|
|
|
|
run &= 0x1F;
|
|
|
|
for (z = 0; z <= run; z++) {
|
|
|
|
dst[x++] = color;
|
2003-06-05 17:22:15 +00:00
|
|
|
}
|
2003-08-25 20:18:44 +00:00
|
|
|
} else if (run & 0x40) {
|
|
|
|
run &= 0x3F;
|
|
|
|
color = *src++;
|
|
|
|
for (z = 0; z <= run; z++) {
|
|
|
|
dst[x++] = color;
|
2003-06-05 17:22:15 +00:00
|
|
|
}
|
|
|
|
} else {
|
2003-08-25 20:18:44 +00:00
|
|
|
for (z = 0; z <= run; z++) {
|
|
|
|
dst[x++] = *src++;
|
2003-06-05 17:22:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-06-04 21:45:29 +00:00
|
|
|
|
2004-09-26 00:06:51 +00:00
|
|
|
/**
|
|
|
|
* Create and fill a table with offsets to the graphic and mask strips in the
|
|
|
|
* given V2 EGA bitmap.
|
|
|
|
* @param src the V2 EGA bitmap
|
|
|
|
* @param width the width of the bitmap
|
|
|
|
* @param height the height of the bitmap
|
|
|
|
* @param table the strip table to fill
|
|
|
|
* @return filled strip table
|
|
|
|
*/
|
2006-09-18 22:06:39 +00:00
|
|
|
StripTable *GdiV2::generateStripTable(const byte *src, int width, int height, StripTable *table) const {
|
2004-09-26 00:06:51 +00:00
|
|
|
|
|
|
|
// If no strip table was given to use, allocate a new one
|
|
|
|
if (table == 0)
|
|
|
|
table = (StripTable *)calloc(1, sizeof(StripTable));
|
|
|
|
|
|
|
|
const byte *bitmapStart = src;
|
|
|
|
byte color = 0, data = 0;
|
|
|
|
int x, y, length = 0;
|
|
|
|
byte run = 1;
|
|
|
|
|
|
|
|
// Decode the graphics strips, and memorize the run/color values
|
|
|
|
// as well as the byte offset.
|
2011-02-07 23:01:06 +00:00
|
|
|
for (x = 0; x < width; x++) {
|
2004-09-26 00:06:51 +00:00
|
|
|
|
|
|
|
if ((x % 8) == 0) {
|
|
|
|
assert(x / 8 < 160);
|
|
|
|
table->run[x / 8] = run;
|
|
|
|
table->color[x / 8] = color;
|
|
|
|
table->offsets[x / 8] = src - bitmapStart;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (y = 0; y < height; y++) {
|
|
|
|
if (--run == 0) {
|
|
|
|
data = *src++;
|
|
|
|
if (data & 0x80) {
|
|
|
|
run = data & 0x7f;
|
|
|
|
} else {
|
|
|
|
run = data >> 4;
|
|
|
|
}
|
|
|
|
if (run == 0) {
|
|
|
|
run = *src++;
|
|
|
|
}
|
|
|
|
color = data & 0x0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The mask data follows immediately after the graphics.
|
|
|
|
x = 0;
|
|
|
|
y = height;
|
|
|
|
width /= 8;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-09-26 00:06:51 +00:00
|
|
|
for (;;) {
|
|
|
|
length = *src++;
|
|
|
|
const byte runFlag = length & 0x80;
|
|
|
|
if (runFlag) {
|
|
|
|
length &= 0x7f;
|
|
|
|
data = *src++;
|
|
|
|
}
|
|
|
|
do {
|
|
|
|
if (!runFlag)
|
|
|
|
data = *src++;
|
|
|
|
if (y == height) {
|
|
|
|
assert(x < 120);
|
|
|
|
table->zoffsets[x] = src - bitmapStart - 1;
|
|
|
|
table->zrun[x] = length | runFlag;
|
|
|
|
}
|
|
|
|
if (--y == 0) {
|
|
|
|
if (--width == 0)
|
|
|
|
return table;
|
|
|
|
x++;
|
|
|
|
y = height;
|
|
|
|
}
|
|
|
|
} while (--length);
|
|
|
|
}
|
|
|
|
|
|
|
|
return table;
|
|
|
|
}
|
|
|
|
|
2004-09-24 21:35:37 +00:00
|
|
|
void Gdi::drawStripEGA(byte *dst, int dstPitch, const byte *src, int height) const {
|
2003-04-10 11:34:51 +00:00
|
|
|
byte color = 0;
|
2003-04-12 11:44:15 +00:00
|
|
|
int run = 0, x = 0, y = 0, z;
|
2003-04-10 11:34:51 +00:00
|
|
|
|
2003-06-07 00:49:36 +00:00
|
|
|
while (x < 8) {
|
2003-04-10 11:34:51 +00:00
|
|
|
color = *src++;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2003-06-07 00:49:36 +00:00
|
|
|
if (color & 0x80) {
|
2003-04-10 11:34:51 +00:00
|
|
|
run = color & 0x3f;
|
|
|
|
|
2003-06-07 00:49:36 +00:00
|
|
|
if (color & 0x40) {
|
2003-04-10 11:34:51 +00:00
|
|
|
color = *src++;
|
|
|
|
|
2003-06-07 00:49:36 +00:00
|
|
|
if (run == 0) {
|
2003-04-10 11:34:51 +00:00
|
|
|
run = *src++;
|
|
|
|
}
|
2003-06-07 00:49:36 +00:00
|
|
|
for (z = 0; z < run; z++) {
|
2009-09-25 00:31:46 +00:00
|
|
|
*(dst + y * dstPitch + x) = (z & 1) ? _roomPalette[(color & 0xf) + _paletteMod] : _roomPalette[(color >> 4) + _paletteMod];
|
2003-04-10 11:34:51 +00:00
|
|
|
|
|
|
|
y++;
|
2003-06-07 00:49:36 +00:00
|
|
|
if (y >= height) {
|
2003-04-10 11:34:51 +00:00
|
|
|
y = 0;
|
|
|
|
x++;
|
2003-04-09 19:14:05 +00:00
|
|
|
}
|
|
|
|
}
|
2003-04-12 11:44:15 +00:00
|
|
|
} else {
|
2003-06-07 00:49:36 +00:00
|
|
|
if (run == 0) {
|
2003-04-09 19:14:05 +00:00
|
|
|
run = *src++;
|
|
|
|
}
|
2003-04-10 11:34:51 +00:00
|
|
|
|
2003-06-07 00:49:36 +00:00
|
|
|
for (z = 0; z < run; z++) {
|
2005-09-19 00:35:12 +00:00
|
|
|
*(dst + y * dstPitch + x) = *(dst + y * dstPitch + x - 1);
|
2003-04-12 11:44:15 +00:00
|
|
|
|
2003-04-10 11:34:51 +00:00
|
|
|
y++;
|
2003-06-07 00:49:36 +00:00
|
|
|
if (y >= height) {
|
2003-04-10 11:34:51 +00:00
|
|
|
y = 0;
|
|
|
|
x++;
|
|
|
|
}
|
2003-04-12 11:44:15 +00:00
|
|
|
}
|
2003-04-09 19:14:05 +00:00
|
|
|
}
|
2003-04-12 11:44:15 +00:00
|
|
|
} else {
|
2003-04-10 11:34:51 +00:00
|
|
|
run = color >> 4;
|
2003-06-07 00:49:36 +00:00
|
|
|
if (run == 0) {
|
2003-04-10 11:34:51 +00:00
|
|
|
run = *src++;
|
|
|
|
}
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2003-06-07 00:49:36 +00:00
|
|
|
for (z = 0; z < run; z++) {
|
2009-09-25 00:31:46 +00:00
|
|
|
*(dst + y * dstPitch + x) = _roomPalette[(color & 0xf) + _paletteMod];
|
2003-04-10 11:34:51 +00:00
|
|
|
|
2003-04-12 11:44:15 +00:00
|
|
|
y++;
|
2003-06-07 00:49:36 +00:00
|
|
|
if (y >= height) {
|
2003-04-10 11:34:51 +00:00
|
|
|
y = 0;
|
|
|
|
x++;
|
|
|
|
}
|
2003-04-09 19:14:05 +00:00
|
|
|
}
|
2003-04-10 11:34:51 +00:00
|
|
|
}
|
2003-04-09 19:14:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-18 21:40:07 +00:00
|
|
|
#define READ_BIT (shift--, dataBit = data & 1, data >>= 1, dataBit)
|
2004-09-30 23:30:59 +00:00
|
|
|
#define FILL_BITS(n) do { \
|
|
|
|
if (shift < n) { \
|
|
|
|
data |= *src++ << shift; \
|
|
|
|
shift += 8; \
|
|
|
|
} \
|
2004-09-18 21:40:07 +00:00
|
|
|
} while (0)
|
|
|
|
|
2004-09-25 11:20:38 +00:00
|
|
|
// NOTE: drawStripHE is actually very similar to drawStripComplex
|
2004-09-30 23:30:59 +00:00
|
|
|
void Gdi::drawStripHE(byte *dst, int dstPitch, const byte *src, int width, int height, const bool transpCheck) const {
|
|
|
|
static const int delta_color[] = { -4, -3, -2, -1, 1, 2, 3, 4 };
|
|
|
|
uint32 dataBit, data;
|
2004-09-18 21:40:07 +00:00
|
|
|
byte color;
|
2004-09-30 23:30:59 +00:00
|
|
|
int shift;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-09-30 23:30:59 +00:00
|
|
|
color = *src++;
|
2004-09-19 20:17:57 +00:00
|
|
|
data = READ_LE_UINT24(src);
|
|
|
|
src += 3;
|
|
|
|
shift = 24;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2004-09-30 23:30:59 +00:00
|
|
|
int x = width;
|
|
|
|
while (1) {
|
2009-06-05 10:13:19 +00:00
|
|
|
if (!transpCheck || color != _transparentColor)
|
|
|
|
writeRoomColor(dst, color);
|
2009-09-25 09:13:33 +00:00
|
|
|
dst += _vm->_bytesPerPixel;
|
2004-09-30 23:30:59 +00:00
|
|
|
--x;
|
|
|
|
if (x == 0) {
|
|
|
|
x = width;
|
2009-09-25 09:13:33 +00:00
|
|
|
dst += dstPitch - width * _vm->_bytesPerPixel;
|
2004-09-30 23:30:59 +00:00
|
|
|
--height;
|
|
|
|
if (height == 0)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
FILL_BITS(1);
|
|
|
|
if (READ_BIT) {
|
|
|
|
FILL_BITS(1);
|
2004-09-19 20:17:57 +00:00
|
|
|
if (READ_BIT) {
|
2004-09-30 23:30:59 +00:00
|
|
|
FILL_BITS(3);
|
|
|
|
color += delta_color[data & 7];
|
|
|
|
shift -= 3;
|
|
|
|
data >>= 3;
|
|
|
|
} else {
|
|
|
|
FILL_BITS(_decomp_shr);
|
|
|
|
color = data & _decomp_mask;
|
|
|
|
shift -= _decomp_shr;
|
|
|
|
data >>= _decomp_shr;
|
2004-09-19 20:17:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-09-18 21:40:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#undef READ_BIT
|
|
|
|
#undef FILL_BITS
|
|
|
|
|
|
|
|
|
2004-09-24 21:35:37 +00:00
|
|
|
void Gdi::drawStrip3DO(byte *dst, int dstPitch, const byte *src, int height, const bool transpCheck) const {
|
2004-11-21 21:40:51 +00:00
|
|
|
if (height == 0)
|
2004-09-18 21:40:07 +00:00
|
|
|
return;
|
|
|
|
|
2004-11-21 21:40:51 +00:00
|
|
|
int decSize = height * 8;
|
|
|
|
int curSize = 0;
|
2004-09-18 21:40:07 +00:00
|
|
|
|
|
|
|
do {
|
2004-11-21 21:40:51 +00:00
|
|
|
uint8 data = *src++;
|
|
|
|
uint8 rle = data & 1;
|
|
|
|
int len = (data >> 1) + 1;
|
2004-09-18 21:40:07 +00:00
|
|
|
|
2004-11-21 21:40:51 +00:00
|
|
|
len = MIN(decSize, len);
|
|
|
|
decSize -= len;
|
2004-09-18 21:40:07 +00:00
|
|
|
|
2004-11-21 21:40:51 +00:00
|
|
|
if (!rle) {
|
|
|
|
for (; len > 0; len--, src++, dst++) {
|
2004-09-18 21:40:07 +00:00
|
|
|
if (!transpCheck || *src != _transparentColor)
|
|
|
|
*dst = _roomPalette[*src];
|
2004-11-21 21:40:51 +00:00
|
|
|
curSize++;
|
|
|
|
if (!(curSize & 7))
|
|
|
|
dst += dstPitch - 8; // Next row
|
2004-09-18 21:40:07 +00:00
|
|
|
}
|
|
|
|
} else {
|
2004-11-21 21:40:51 +00:00
|
|
|
byte color = *src++;
|
|
|
|
for (; len > 0; len--, dst++) {
|
2004-09-18 21:40:07 +00:00
|
|
|
if (!transpCheck || color != _transparentColor)
|
|
|
|
*dst = _roomPalette[color];
|
2004-11-21 21:40:51 +00:00
|
|
|
curSize++;
|
|
|
|
if (!(curSize & 7))
|
|
|
|
dst += dstPitch - 8; // Next row
|
2004-09-18 21:40:07 +00:00
|
|
|
}
|
|
|
|
}
|
2004-11-21 21:40:51 +00:00
|
|
|
} while (decSize > 0);
|
2004-09-18 21:40:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-08 21:59:32 +00:00
|
|
|
#define READ_BIT (cl--, bit = bits & 1, bits >>= 1, bit)
|
|
|
|
#define FILL_BITS do { \
|
|
|
|
if (cl <= 8) { \
|
|
|
|
bits |= (*src++ << cl); \
|
|
|
|
cl += 8; \
|
|
|
|
} \
|
2003-10-13 11:59:48 +00:00
|
|
|
} while (0)
|
2003-03-06 17:58:13 +00:00
|
|
|
|
2004-09-25 11:33:50 +00:00
|
|
|
void Gdi::drawStripComplex(byte *dst, int dstPitch, const byte *src, int height, const bool transpCheck) const {
|
2001-10-09 14:30:12 +00:00
|
|
|
byte color = *src++;
|
|
|
|
uint bits = *src++;
|
|
|
|
byte cl = 8;
|
|
|
|
byte bit;
|
2002-04-11 17:19:16 +00:00
|
|
|
byte incm, reps;
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
do {
|
2002-12-31 04:45:21 +00:00
|
|
|
int x = 8;
|
2001-10-09 14:30:12 +00:00
|
|
|
do {
|
2002-12-16 01:25:21 +00:00
|
|
|
FILL_BITS;
|
2009-06-05 10:13:19 +00:00
|
|
|
if (!transpCheck || color != _transparentColor)
|
|
|
|
writeRoomColor(dst, color);
|
2009-09-25 09:13:33 +00:00
|
|
|
dst += _vm->_bytesPerPixel;
|
2001-10-16 10:01:48 +00:00
|
|
|
|
2002-12-31 04:36:14 +00:00
|
|
|
againPos:
|
2002-04-11 17:19:16 +00:00
|
|
|
if (!READ_BIT) {
|
2002-12-31 04:59:23 +00:00
|
|
|
} else if (!READ_BIT) {
|
|
|
|
FILL_BITS;
|
|
|
|
color = bits & _decomp_mask;
|
|
|
|
bits >>= _decomp_shr;
|
|
|
|
cl -= _decomp_shr;
|
|
|
|
} else {
|
2002-04-11 17:19:16 +00:00
|
|
|
incm = (bits & 7) - 4;
|
|
|
|
cl -= 3;
|
|
|
|
bits >>= 3;
|
2001-10-16 10:01:48 +00:00
|
|
|
if (incm) {
|
|
|
|
color += incm;
|
|
|
|
} else {
|
2002-12-16 01:25:21 +00:00
|
|
|
FILL_BITS;
|
|
|
|
reps = bits & 0xFF;
|
2002-12-31 04:19:46 +00:00
|
|
|
do {
|
2002-12-31 04:45:21 +00:00
|
|
|
if (!--x) {
|
|
|
|
x = 8;
|
2009-09-25 09:13:33 +00:00
|
|
|
dst += dstPitch - 8 * _vm->_bytesPerPixel;
|
2002-12-31 04:19:46 +00:00
|
|
|
if (!--height)
|
|
|
|
return;
|
|
|
|
}
|
2009-06-05 10:13:19 +00:00
|
|
|
if (!transpCheck || color != _transparentColor)
|
|
|
|
writeRoomColor(dst, color);
|
2009-09-25 09:13:33 +00:00
|
|
|
dst += _vm->_bytesPerPixel;
|
2002-12-31 04:19:46 +00:00
|
|
|
} while (--reps);
|
2002-04-11 17:19:16 +00:00
|
|
|
bits >>= 8;
|
|
|
|
bits |= (*src++) << (cl - 8);
|
2001-10-16 10:01:48 +00:00
|
|
|
goto againPos;
|
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
2002-12-31 04:45:21 +00:00
|
|
|
} while (--x);
|
2009-09-25 09:13:33 +00:00
|
|
|
dst += dstPitch - 8 * _vm->_bytesPerPixel;
|
2002-12-16 01:25:21 +00:00
|
|
|
} while (--height);
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
2001-10-16 10:01:48 +00:00
|
|
|
|
2004-09-25 11:40:40 +00:00
|
|
|
void Gdi::drawStripBasicH(byte *dst, int dstPitch, const byte *src, int height, const bool transpCheck) const {
|
2001-10-09 14:30:12 +00:00
|
|
|
byte color = *src++;
|
|
|
|
uint bits = *src++;
|
|
|
|
byte cl = 8;
|
|
|
|
byte bit;
|
2002-12-31 04:59:23 +00:00
|
|
|
int8 inc = -1;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
|
|
|
do {
|
2002-12-31 14:59:06 +00:00
|
|
|
int x = 8;
|
2001-10-09 14:30:12 +00:00
|
|
|
do {
|
2002-12-16 01:25:21 +00:00
|
|
|
FILL_BITS;
|
2009-06-05 10:13:19 +00:00
|
|
|
if (!transpCheck || color != _transparentColor)
|
|
|
|
writeRoomColor(dst, color);
|
2009-09-25 09:13:33 +00:00
|
|
|
dst += _vm->_bytesPerPixel;
|
2002-04-11 17:19:16 +00:00
|
|
|
if (!READ_BIT) {
|
|
|
|
} else if (!READ_BIT) {
|
2002-12-16 01:25:21 +00:00
|
|
|
FILL_BITS;
|
|
|
|
color = bits & _decomp_mask;
|
2001-10-26 17:34:50 +00:00
|
|
|
bits >>= _decomp_shr;
|
|
|
|
cl -= _decomp_shr;
|
2001-10-09 14:30:12 +00:00
|
|
|
inc = -1;
|
|
|
|
} else if (!READ_BIT) {
|
|
|
|
color += inc;
|
|
|
|
} else {
|
|
|
|
inc = -inc;
|
|
|
|
color += inc;
|
|
|
|
}
|
2002-12-31 04:45:21 +00:00
|
|
|
} while (--x);
|
2009-09-25 09:13:33 +00:00
|
|
|
dst += dstPitch - 8 * _vm->_bytesPerPixel;
|
2002-12-16 01:25:21 +00:00
|
|
|
} while (--height);
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2004-09-25 11:40:40 +00:00
|
|
|
void Gdi::drawStripBasicV(byte *dst, int dstPitch, const byte *src, int height, const bool transpCheck) const {
|
2002-12-31 14:59:06 +00:00
|
|
|
byte color = *src++;
|
|
|
|
uint bits = *src++;
|
|
|
|
byte cl = 8;
|
|
|
|
byte bit;
|
|
|
|
int8 inc = -1;
|
|
|
|
|
|
|
|
int x = 8;
|
|
|
|
do {
|
|
|
|
int h = height;
|
|
|
|
do {
|
|
|
|
FILL_BITS;
|
2009-06-05 10:13:19 +00:00
|
|
|
if (!transpCheck || color != _transparentColor)
|
|
|
|
writeRoomColor(dst, color);
|
2004-09-22 17:57:20 +00:00
|
|
|
dst += dstPitch;
|
2002-12-31 14:59:06 +00:00
|
|
|
if (!READ_BIT) {
|
|
|
|
} else if (!READ_BIT) {
|
|
|
|
FILL_BITS;
|
|
|
|
color = bits & _decomp_mask;
|
|
|
|
bits >>= _decomp_shr;
|
|
|
|
cl -= _decomp_shr;
|
|
|
|
inc = -1;
|
|
|
|
} else if (!READ_BIT) {
|
|
|
|
color += inc;
|
|
|
|
} else {
|
|
|
|
inc = -inc;
|
|
|
|
color += inc;
|
|
|
|
}
|
|
|
|
} while (--h);
|
|
|
|
dst -= _vertStripNextInc;
|
|
|
|
} while (--x);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef READ_BIT
|
|
|
|
#undef FILL_BITS
|
|
|
|
|
2002-03-09 09:15:34 +00:00
|
|
|
/* Ender - Zak256/Indy256 decoders */
|
2004-09-18 21:40:07 +00:00
|
|
|
#define READ_BIT_256 \
|
2003-09-05 22:53:25 +00:00
|
|
|
do { \
|
|
|
|
if ((mask <<= 1) == 256) { \
|
|
|
|
buffer = *src++; \
|
|
|
|
mask = 1; \
|
|
|
|
} \
|
|
|
|
bits = ((buffer & mask) != 0); \
|
|
|
|
} while (0)
|
|
|
|
|
2004-09-18 21:40:07 +00:00
|
|
|
#define READ_N_BITS(n, c) \
|
|
|
|
do { \
|
|
|
|
c = 0; \
|
|
|
|
for (int b = 0; b < n; b++) { \
|
|
|
|
READ_BIT_256; \
|
|
|
|
c += (bits << b); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2003-09-05 22:53:25 +00:00
|
|
|
#define NEXT_ROW \
|
|
|
|
do { \
|
2004-09-22 17:57:20 +00:00
|
|
|
dst += dstPitch; \
|
2003-09-05 22:53:25 +00:00
|
|
|
if (--h == 0) { \
|
|
|
|
if (!--x) \
|
|
|
|
return; \
|
|
|
|
dst -= _vertStripNextInc; \
|
|
|
|
h = height; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
2002-03-09 09:15:34 +00:00
|
|
|
|
2006-01-01 09:51:11 +00:00
|
|
|
void Gdi::drawStripRaw(byte *dst, int dstPitch, const byte *src, int height, const bool transpCheck) const {
|
|
|
|
int x;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_vm->_game.features & GF_OLD256) {
|
2004-09-18 21:40:07 +00:00
|
|
|
uint h = height;
|
2006-01-01 09:51:11 +00:00
|
|
|
x = 8;
|
2002-04-11 17:19:16 +00:00
|
|
|
for (;;) {
|
2006-07-31 12:53:15 +00:00
|
|
|
*dst = _roomPalette[*src++];
|
2003-09-05 22:53:25 +00:00
|
|
|
NEXT_ROW;
|
2002-12-16 01:25:21 +00:00
|
|
|
}
|
2005-04-20 19:59:18 +00:00
|
|
|
} else {
|
|
|
|
do {
|
2006-01-01 09:51:11 +00:00
|
|
|
for (x = 0; x < 8; x ++) {
|
|
|
|
byte color = *src++;
|
2009-06-05 10:13:19 +00:00
|
|
|
if (!transpCheck || color != _transparentColor)
|
2009-09-25 09:13:33 +00:00
|
|
|
writeRoomColor(dst + x * _vm->_bytesPerPixel, color);
|
2006-01-01 09:51:11 +00:00
|
|
|
}
|
2005-04-20 19:59:18 +00:00
|
|
|
dst += dstPitch;
|
|
|
|
} while (--height);
|
2002-03-09 09:15:34 +00:00
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2004-09-24 21:35:37 +00:00
|
|
|
void Gdi::unkDecode8(byte *dst, int dstPitch, const byte *src, int height) const {
|
2002-12-16 01:25:21 +00:00
|
|
|
uint h = height;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2002-12-31 04:45:21 +00:00
|
|
|
int x = 8;
|
2002-04-11 17:19:16 +00:00
|
|
|
for (;;) {
|
|
|
|
uint run = (*src++) + 1;
|
|
|
|
byte color = *src++;
|
|
|
|
|
|
|
|
do {
|
2003-10-13 12:56:53 +00:00
|
|
|
*dst = _roomPalette[color];
|
2003-09-05 22:53:25 +00:00
|
|
|
NEXT_ROW;
|
2002-12-16 01:25:21 +00:00
|
|
|
} while (--run);
|
2002-04-11 17:19:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-24 21:35:37 +00:00
|
|
|
void Gdi::unkDecode9(byte *dst, int dstPitch, const byte *src, int height) const {
|
2004-09-18 21:40:07 +00:00
|
|
|
byte c, bits, color, run;
|
|
|
|
int i;
|
2002-04-11 17:19:16 +00:00
|
|
|
uint buffer = 0, mask = 128;
|
2002-12-16 01:25:21 +00:00
|
|
|
int h = height;
|
2013-01-02 18:28:25 +00:00
|
|
|
run = 0;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2002-12-31 04:45:21 +00:00
|
|
|
int x = 8;
|
2002-04-11 17:19:16 +00:00
|
|
|
for (;;) {
|
2004-09-18 21:40:07 +00:00
|
|
|
READ_N_BITS(4, c);
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2003-05-30 20:13:29 +00:00
|
|
|
switch (c >> 2) {
|
2002-04-11 17:19:16 +00:00
|
|
|
case 0:
|
2004-09-18 21:40:07 +00:00
|
|
|
READ_N_BITS(4, color);
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i < ((c & 3) + 2); i++) {
|
2003-10-13 12:56:53 +00:00
|
|
|
*dst = _roomPalette[run * 16 + color];
|
2003-09-05 22:53:25 +00:00
|
|
|
NEXT_ROW;
|
2002-12-16 01:25:21 +00:00
|
|
|
}
|
2002-04-11 17:19:16 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
for (i = 0; i < ((c & 3) + 1); i++) {
|
2004-09-18 21:40:07 +00:00
|
|
|
READ_N_BITS(4, color);
|
2003-10-13 12:56:53 +00:00
|
|
|
*dst = _roomPalette[run * 16 + color];
|
2003-09-05 22:53:25 +00:00
|
|
|
NEXT_ROW;
|
2002-12-16 01:25:21 +00:00
|
|
|
}
|
2002-04-11 17:19:16 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
2004-09-18 21:40:07 +00:00
|
|
|
READ_N_BITS(4, run);
|
2002-04-11 17:19:16 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-24 21:35:37 +00:00
|
|
|
void Gdi::unkDecode10(byte *dst, int dstPitch, const byte *src, int height) const {
|
2002-04-11 17:19:16 +00:00
|
|
|
int i;
|
2004-09-18 21:40:07 +00:00
|
|
|
byte local_palette[256], numcolors = *src++;
|
2002-12-16 01:25:21 +00:00
|
|
|
uint h = height;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
|
|
|
for (i = 0; i < numcolors; i++)
|
|
|
|
local_palette[i] = *src++;
|
|
|
|
|
2002-12-31 04:45:21 +00:00
|
|
|
int x = 8;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
byte color = *src++;
|
|
|
|
if (color < numcolors) {
|
2003-10-13 12:56:53 +00:00
|
|
|
*dst = _roomPalette[local_palette[color]];
|
2003-09-05 22:53:25 +00:00
|
|
|
NEXT_ROW;
|
2002-12-16 01:25:21 +00:00
|
|
|
} else {
|
2002-04-11 17:19:16 +00:00
|
|
|
uint run = color - numcolors + 1;
|
|
|
|
color = *src++;
|
|
|
|
do {
|
2003-10-13 12:56:53 +00:00
|
|
|
*dst = _roomPalette[color];
|
2003-09-05 22:53:25 +00:00
|
|
|
NEXT_ROW;
|
2002-12-16 01:25:21 +00:00
|
|
|
} while (--run);
|
2002-04-11 17:19:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-09-24 21:35:37 +00:00
|
|
|
void Gdi::unkDecode11(byte *dst, int dstPitch, const byte *src, int height) const {
|
2002-04-11 17:19:16 +00:00
|
|
|
int bits, i;
|
|
|
|
uint buffer = 0, mask = 128;
|
2004-09-18 21:40:07 +00:00
|
|
|
byte inc = 1, color = *src++;
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2002-12-31 04:45:21 +00:00
|
|
|
int x = 8;
|
2002-04-11 17:19:16 +00:00
|
|
|
do {
|
2002-12-16 01:25:21 +00:00
|
|
|
int h = height;
|
2002-04-11 17:19:16 +00:00
|
|
|
do {
|
2003-10-13 12:56:53 +00:00
|
|
|
*dst = _roomPalette[color];
|
2004-09-22 17:57:20 +00:00
|
|
|
dst += dstPitch;
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i < 3; i++) {
|
2004-09-18 21:40:07 +00:00
|
|
|
READ_BIT_256;
|
2002-12-16 01:25:21 +00:00
|
|
|
if (!bits)
|
|
|
|
break;
|
2002-04-11 17:19:16 +00:00
|
|
|
}
|
|
|
|
switch (i) {
|
|
|
|
case 1:
|
|
|
|
inc = -inc;
|
|
|
|
color -= inc;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
color -= inc;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
inc = 1;
|
2004-09-18 21:40:07 +00:00
|
|
|
READ_N_BITS(8, color);
|
2002-04-11 17:19:16 +00:00
|
|
|
break;
|
|
|
|
}
|
2002-12-16 01:25:21 +00:00
|
|
|
} while (--h);
|
2002-04-11 17:19:16 +00:00
|
|
|
dst -= _vertStripNextInc;
|
2002-12-31 04:45:21 +00:00
|
|
|
} while (--x);
|
2002-02-12 18:20:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#undef NEXT_ROW
|
2004-09-18 21:40:07 +00:00
|
|
|
#undef READ_BIT_256
|
2001-10-09 14:30:12 +00:00
|
|
|
|
2009-11-22 11:43:12 +00:00
|
|
|
#ifdef USE_RGB_COLOR
|
2011-06-18 17:44:18 +00:00
|
|
|
void GdiHE16bit::writeRoomColor(byte *dst, byte color) const {
|
2009-06-05 10:13:19 +00:00
|
|
|
WRITE_UINT16(dst, READ_LE_UINT16(_vm->_hePalettes + 2048 + color * 2));
|
|
|
|
}
|
2009-11-22 11:43:12 +00:00
|
|
|
#endif
|
2009-06-05 10:13:19 +00:00
|
|
|
|
|
|
|
void Gdi::writeRoomColor(byte *dst, byte color) const {
|
2009-09-25 01:00:34 +00:00
|
|
|
// As described in bug #1294513 "FOA/Amiga: Palette problem (Regression)"
|
|
|
|
// the original AMIGA version of Indy4: The Fate of Atlantis allowed
|
|
|
|
// overflowing of the palette index. To have the same result in our code,
|
|
|
|
// we need to do an logical AND 0xFF here to keep the result in [0, 255].
|
2009-09-25 00:50:51 +00:00
|
|
|
*dst = _roomPalette[(color + _paletteMod) & 0xFF];
|
2009-06-05 10:13:19 +00:00
|
|
|
}
|
|
|
|
|
2004-09-26 00:06:51 +00:00
|
|
|
|
2002-12-15 23:40:37 +00:00
|
|
|
#pragma mark -
|
2002-12-16 19:53:41 +00:00
|
|
|
#pragma mark --- Transition effects ---
|
2002-12-15 23:40:37 +00:00
|
|
|
#pragma mark -
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine::fadeIn(int effect) {
|
2006-06-21 10:28:09 +00:00
|
|
|
if (_disableFadeInEffect) {
|
|
|
|
// fadeIn() calls can be disabled in TheDig after a SMUSH movie
|
|
|
|
// has been played. Like the original interpreter, we introduce
|
|
|
|
// an extra flag to handle this.
|
|
|
|
_disableFadeInEffect = false;
|
|
|
|
_doEffect = false;
|
|
|
|
_screenEffectFlag = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-04-02 15:23:36 +00:00
|
|
|
updatePalette();
|
2003-05-24 16:11:47 +00:00
|
|
|
|
2002-12-15 23:40:37 +00:00
|
|
|
switch (effect) {
|
2003-08-21 13:39:21 +00:00
|
|
|
case 0:
|
|
|
|
// seems to do nothing
|
|
|
|
break;
|
2002-12-15 23:40:37 +00:00
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
case 4:
|
2003-06-05 18:30:29 +00:00
|
|
|
case 5:
|
2005-03-21 00:27:39 +00:00
|
|
|
case 6:
|
2003-06-07 22:56:47 +00:00
|
|
|
// Some of the transition effects won't work properly unless
|
|
|
|
// the screen is marked as clean first. At first I thought I
|
|
|
|
// could safely do this every time fadeIn() was called, but
|
|
|
|
// that broke the FOA intro. Probably other things as well.
|
|
|
|
//
|
|
|
|
// Hopefully it's safe to do it at this point, at least.
|
2007-09-08 11:15:27 +00:00
|
|
|
_virtscr[kMainVirtScreen].setDirtyRange(0, 0);
|
2008-01-28 00:14:17 +00:00
|
|
|
transitionEffect(effect - 1);
|
2002-12-15 23:40:37 +00:00
|
|
|
break;
|
|
|
|
case 128:
|
|
|
|
unkScreenEffect6();
|
|
|
|
break;
|
2003-08-21 13:39:21 +00:00
|
|
|
case 129:
|
|
|
|
break;
|
2002-12-15 23:40:37 +00:00
|
|
|
case 130:
|
|
|
|
case 131:
|
|
|
|
case 132:
|
|
|
|
case 133:
|
|
|
|
scrollEffect(133 - effect);
|
|
|
|
break;
|
|
|
|
case 134:
|
|
|
|
dissolveEffect(1, 1);
|
|
|
|
break;
|
|
|
|
case 135:
|
2007-09-08 11:15:27 +00:00
|
|
|
dissolveEffect(1, _virtscr[kMainVirtScreen].h);
|
2002-12-15 23:40:37 +00:00
|
|
|
break;
|
|
|
|
default:
|
2005-08-14 01:41:52 +00:00
|
|
|
error("Unknown screen effect, %d", effect);
|
2002-12-15 23:40:37 +00:00
|
|
|
}
|
|
|
|
_screenEffectFlag = true;
|
2001-10-17 10:07:40 +00:00
|
|
|
}
|
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine::fadeOut(int effect) {
|
2007-09-08 11:15:27 +00:00
|
|
|
VirtScreen *vs = &_virtscr[kMainVirtScreen];
|
2001-10-17 10:07:40 +00:00
|
|
|
|
2003-06-07 22:56:47 +00:00
|
|
|
vs->setDirtyRange(0, 0);
|
2007-02-10 02:05:59 +00:00
|
|
|
if (_game.version < 7)
|
2002-12-15 23:40:37 +00:00
|
|
|
camera._last.x = camera._cur.x;
|
2002-07-07 20:32:26 +00:00
|
|
|
|
2010-10-05 19:04:52 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
2010-10-02 23:18:15 +00:00
|
|
|
if (_game.version == 3 && _game.platform == Common::kPlatformFMTowns)
|
|
|
|
_textSurface.fillRect(Common::Rect(0, vs->topline * _textSurfaceMultiplier, _textSurface.pitch, (vs->topline + vs->h) * _textSurfaceMultiplier), 0);
|
2010-10-05 19:04:52 +00:00
|
|
|
#endif
|
2010-10-02 23:18:15 +00:00
|
|
|
|
2008-01-28 00:14:17 +00:00
|
|
|
// TheDig can disable fadeIn(), and may call fadeOut() several times
|
|
|
|
// successively. Disabling the _screenEffectFlag check forces the screen
|
|
|
|
// to get cleared. This fixes glitches, at least, in the first cutscenes
|
|
|
|
// when bypassed of FT and TheDig.
|
|
|
|
if ((_game.version == 7 || _screenEffectFlag) && effect != 0) {
|
2003-05-24 16:11:47 +00:00
|
|
|
// Fill screen 0 with black
|
2004-08-14 19:42:00 +00:00
|
|
|
memset(vs->getPixels(0, 0), 0, vs->pitch * vs->h);
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2003-05-24 16:11:47 +00:00
|
|
|
// Fade to black with the specified effect, if any.
|
|
|
|
switch (effect) {
|
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
case 3:
|
|
|
|
case 4:
|
2003-06-05 18:30:29 +00:00
|
|
|
case 5:
|
2005-03-21 00:27:39 +00:00
|
|
|
case 6:
|
2003-05-24 16:11:47 +00:00
|
|
|
transitionEffect(effect - 1);
|
|
|
|
break;
|
|
|
|
case 128:
|
|
|
|
unkScreenEffect6();
|
|
|
|
break;
|
|
|
|
case 129:
|
|
|
|
// Just blit screen 0 to the display (i.e. display will be black)
|
2004-08-14 19:42:00 +00:00
|
|
|
vs->setDirtyRange(0, vs->h);
|
2004-01-03 21:22:07 +00:00
|
|
|
updateDirtyScreen(kMainVirtScreen);
|
2010-10-20 15:39:08 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
|
|
|
if (_townsScreen)
|
|
|
|
_townsScreen->update();
|
|
|
|
#endif
|
2003-05-24 16:11:47 +00:00
|
|
|
break;
|
|
|
|
case 134:
|
|
|
|
dissolveEffect(1, 1);
|
|
|
|
break;
|
|
|
|
case 135:
|
2007-09-08 11:15:27 +00:00
|
|
|
dissolveEffect(1, _virtscr[kMainVirtScreen].h);
|
2003-05-24 16:11:47 +00:00
|
|
|
break;
|
|
|
|
default:
|
2005-08-14 01:41:52 +00:00
|
|
|
error("fadeOut: default case %d", effect);
|
2003-05-24 16:11:47 +00:00
|
|
|
}
|
|
|
|
}
|
2001-10-17 10:07:40 +00:00
|
|
|
|
2003-05-24 16:11:47 +00:00
|
|
|
// Update the palette at the end (once we faded to black) to avoid
|
|
|
|
// some nasty effects when the palette is changed
|
|
|
|
updatePalette();
|
2001-10-17 10:07:40 +00:00
|
|
|
|
2003-05-24 16:11:47 +00:00
|
|
|
_screenEffectFlag = false;
|
2002-12-15 23:40:37 +00:00
|
|
|
}
|
2002-07-07 20:32:26 +00:00
|
|
|
|
2003-05-30 20:13:29 +00:00
|
|
|
/**
|
|
|
|
* Perform a transition effect. There are four different effects possible:
|
2002-05-22 22:36:58 +00:00
|
|
|
* 0: Iris effect
|
2003-01-05 21:18:53 +00:00
|
|
|
* 1: Box wipe (a black box expands from the upper-left corner to the lower-right corner)
|
|
|
|
* 2: Box wipe (a black box expands from the lower-right corner to the upper-left corner)
|
|
|
|
* 3: Inverse box wipe
|
|
|
|
* All effects operate on 8x8 blocks of the screen. These blocks are updated
|
|
|
|
* in a certain order; the exact order determines how the effect appears to the user.
|
2003-05-30 20:13:29 +00:00
|
|
|
* @param a the transition effect to perform
|
2002-05-22 22:36:58 +00:00
|
|
|
*/
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine::transitionEffect(int a) {
|
2002-07-07 20:32:26 +00:00
|
|
|
int delta[16]; // Offset applied during each iteration
|
2001-10-17 10:07:40 +00:00
|
|
|
int tab_2[16];
|
2002-04-11 17:19:16 +00:00
|
|
|
int i, j;
|
2001-10-17 10:07:40 +00:00
|
|
|
int bottom;
|
2002-04-11 17:19:16 +00:00
|
|
|
int l, t, r, b;
|
2007-09-08 11:15:27 +00:00
|
|
|
const int height = MIN((int)_virtscr[kMainVirtScreen].h, _screenHeight);
|
2006-06-22 00:03:13 +00:00
|
|
|
const int delay = (VAR_FADE_DELAY != 0xFF) ? VAR(VAR_FADE_DELAY) * kFadeDelay : kPictureDelay;
|
2001-10-17 10:07:40 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i < 16; i++) {
|
2003-01-05 21:18:53 +00:00
|
|
|
delta[i] = transitionEffects[a].deltaTable[i];
|
|
|
|
j = transitionEffects[a].stripTable[i];
|
2002-04-11 17:19:16 +00:00
|
|
|
if (j == 24)
|
2004-01-08 00:48:37 +00:00
|
|
|
j = height / 8 - 1;
|
2001-10-17 10:07:40 +00:00
|
|
|
tab_2[i] = j;
|
|
|
|
}
|
|
|
|
|
2004-01-08 00:48:37 +00:00
|
|
|
bottom = height / 8;
|
2003-01-05 21:18:53 +00:00
|
|
|
for (j = 0; j < transitionEffects[a].numOfIterations; j++) {
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
l = tab_2[i * 4];
|
|
|
|
t = tab_2[i * 4 + 1];
|
|
|
|
r = tab_2[i * 4 + 2];
|
|
|
|
b = tab_2[i * 4 + 3];
|
2006-01-06 15:02:07 +00:00
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
if (t == b) {
|
2001-10-17 10:07:40 +00:00
|
|
|
while (l <= r) {
|
2006-09-17 20:22:47 +00:00
|
|
|
if (l >= 0 && l < _gdi->_numStrips && t < bottom) {
|
2007-09-08 11:15:27 +00:00
|
|
|
_virtscr[kMainVirtScreen].tdirty[l] = _screenTop + t * 8;
|
|
|
|
_virtscr[kMainVirtScreen].bdirty[l] = _screenTop + (b + 1) * 8;
|
2001-10-17 10:07:40 +00:00
|
|
|
}
|
|
|
|
l++;
|
|
|
|
}
|
|
|
|
} else {
|
2006-09-17 20:22:47 +00:00
|
|
|
if (l < 0 || l >= _gdi->_numStrips || b <= t)
|
2001-10-17 10:07:40 +00:00
|
|
|
continue;
|
2002-04-11 17:19:16 +00:00
|
|
|
if (b > bottom)
|
|
|
|
b = bottom;
|
2003-06-05 18:30:29 +00:00
|
|
|
if (t < 0)
|
|
|
|
t = 0;
|
2008-01-28 00:14:17 +00:00
|
|
|
_virtscr[kMainVirtScreen].tdirty[l] = _screenTop + t * 8;
|
2007-09-08 11:15:27 +00:00
|
|
|
_virtscr[kMainVirtScreen].bdirty[l] = _screenTop + (b + 1) * 8;
|
2001-10-17 10:07:40 +00:00
|
|
|
}
|
2004-01-03 21:22:07 +00:00
|
|
|
updateDirtyScreen(kMainVirtScreen);
|
2001-10-17 10:07:40 +00:00
|
|
|
}
|
|
|
|
|
2002-04-11 17:19:16 +00:00
|
|
|
for (i = 0; i < 16; i++)
|
2002-05-22 22:36:58 +00:00
|
|
|
tab_2[i] += delta[i];
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2006-06-21 10:28:09 +00:00
|
|
|
// Draw the current state to the screen and wait a few secs so the
|
|
|
|
// user can watch the effect taking place.
|
2006-06-22 00:03:13 +00:00
|
|
|
waitForTimer(delay);
|
2001-10-17 10:07:40 +00:00
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
|
|
|
|
2003-05-30 20:13:29 +00:00
|
|
|
/**
|
|
|
|
* Update width*height areas of the screen, in random order, until the whole
|
|
|
|
* screen has been updated. For instance:
|
2007-09-19 08:40:12 +00:00
|
|
|
*
|
2003-05-30 20:13:29 +00:00
|
|
|
* dissolveEffect(1, 1) produces a pixel-by-pixel dissolve
|
|
|
|
* dissolveEffect(8, 8) produces a square-by-square dissolve
|
|
|
|
* dissolveEffect(virtsrc[0].width, 1) produces a line-by-line dissolve
|
|
|
|
*/
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine::dissolveEffect(int width, int height) {
|
2007-09-08 11:15:27 +00:00
|
|
|
VirtScreen *vs = &_virtscr[kMainVirtScreen];
|
2002-08-25 18:40:23 +00:00
|
|
|
int *offsets;
|
|
|
|
int blits_before_refresh, blits;
|
|
|
|
int x, y;
|
|
|
|
int w, h;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
// There's probably some less memory-hungry way of doing this. But
|
|
|
|
// since we're only dealing with relatively small images, it shouldn't
|
|
|
|
// be too bad.
|
|
|
|
|
2004-08-14 19:42:00 +00:00
|
|
|
w = vs->w / width;
|
|
|
|
h = vs->h / height;
|
2002-08-25 18:40:23 +00:00
|
|
|
|
2003-06-09 01:32:36 +00:00
|
|
|
// When used correctly, vs->width % width and vs->height % height
|
2002-08-25 18:40:23 +00:00
|
|
|
// should both be zero, but just to be safe...
|
|
|
|
|
2004-08-14 19:42:00 +00:00
|
|
|
if (vs->w % width)
|
2002-08-25 18:40:23 +00:00
|
|
|
w++;
|
|
|
|
|
2004-08-14 19:42:00 +00:00
|
|
|
if (vs->h % height)
|
2002-08-25 18:40:23 +00:00
|
|
|
h++;
|
|
|
|
|
|
|
|
offsets = (int *) malloc(w * h * sizeof(int));
|
2005-08-14 01:41:52 +00:00
|
|
|
if (offsets == NULL)
|
|
|
|
error("dissolveEffect: out of memory");
|
2002-08-25 18:40:23 +00:00
|
|
|
|
|
|
|
// Create a permutation of offsets into the frame buffer
|
|
|
|
|
|
|
|
if (width == 1 && height == 1) {
|
|
|
|
// Optimized case for pixel-by-pixel dissolve
|
|
|
|
|
2004-08-14 19:42:00 +00:00
|
|
|
for (i = 0; i < vs->w * vs->h; i++)
|
2002-08-25 18:40:23 +00:00
|
|
|
offsets[i] = i;
|
|
|
|
|
|
|
|
for (i = 1; i < w * h; i++) {
|
|
|
|
int j;
|
|
|
|
|
2002-12-01 14:57:50 +00:00
|
|
|
j = _rnd.getRandomNumber(i - 1);
|
2002-08-25 18:40:23 +00:00
|
|
|
offsets[i] = offsets[j];
|
|
|
|
offsets[j] = i;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int *offsets2;
|
|
|
|
|
2004-08-14 19:42:00 +00:00
|
|
|
for (i = 0, x = 0; x < vs->w; x += width)
|
|
|
|
for (y = 0; y < vs->h; y += height)
|
|
|
|
offsets[i++] = y * vs->pitch + x;
|
2002-08-25 18:40:23 +00:00
|
|
|
|
|
|
|
offsets2 = (int *) malloc(w * h * sizeof(int));
|
2005-08-14 01:41:52 +00:00
|
|
|
if (offsets2 == NULL)
|
|
|
|
error("dissolveEffect: out of memory");
|
2002-08-25 18:40:23 +00:00
|
|
|
|
|
|
|
memcpy(offsets2, offsets, w * h * sizeof(int));
|
|
|
|
|
|
|
|
for (i = 1; i < w * h; i++) {
|
|
|
|
int j;
|
|
|
|
|
2002-12-01 14:57:50 +00:00
|
|
|
j = _rnd.getRandomNumber(i - 1);
|
2002-08-25 18:40:23 +00:00
|
|
|
offsets[i] = offsets[j];
|
|
|
|
offsets[j] = offsets2[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
free(offsets2);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Blit the image piece by piece to the screen. The idea here is that
|
|
|
|
// the whole update should take about a quarter of a second, assuming
|
|
|
|
// most of the time is spent in waitForTimer(). It looks good to me,
|
|
|
|
// but might still need some tuning.
|
|
|
|
|
|
|
|
blits = 0;
|
|
|
|
blits_before_refresh = (3 * w * h) / 25;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2003-06-07 11:59:56 +00:00
|
|
|
// Speed up the effect for CD Loom since it uses it so often. I don't
|
|
|
|
// think the original had any delay at all, so on modern hardware it
|
|
|
|
// wasn't even noticeable.
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.id == GID_LOOM && (_game.version == 4))
|
2003-06-07 11:59:56 +00:00
|
|
|
blits_before_refresh *= 2;
|
2002-08-25 18:40:23 +00:00
|
|
|
|
|
|
|
for (i = 0; i < w * h; i++) {
|
2004-08-14 19:42:00 +00:00
|
|
|
x = offsets[i] % vs->pitch;
|
|
|
|
y = offsets[i] / vs->pitch;
|
2007-07-10 00:39:12 +00:00
|
|
|
|
2010-10-05 19:04:52 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_game.platform == Common::kPlatformFMTowns)
|
|
|
|
towns_drawStripToScreen(vs, x, y + vs->topline, x, y, width, height);
|
|
|
|
else
|
2010-10-05 19:04:52 +00:00
|
|
|
#endif
|
2007-07-10 00:39:12 +00:00
|
|
|
_system->copyRectToScreen(vs->getPixels(x, y), vs->pitch, x, y + vs->topline, width, height);
|
|
|
|
|
2002-08-25 18:40:23 +00:00
|
|
|
|
|
|
|
if (++blits >= blits_before_refresh) {
|
|
|
|
blits = 0;
|
|
|
|
waitForTimer(30);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(offsets);
|
|
|
|
|
|
|
|
if (blits != 0) {
|
|
|
|
waitForTimer(30);
|
|
|
|
}
|
2001-10-09 14:30:12 +00:00
|
|
|
}
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine::scrollEffect(int dir) {
|
2007-09-08 11:15:27 +00:00
|
|
|
VirtScreen *vs = &_virtscr[kMainVirtScreen];
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2002-12-15 23:40:37 +00:00
|
|
|
int x, y;
|
|
|
|
int step;
|
2006-06-22 00:03:13 +00:00
|
|
|
const int delay = (VAR_FADE_DELAY != 0xFF) ? VAR(VAR_FADE_DELAY) * kFadeDelay : kPictureDelay;
|
2002-04-24 04:26:09 +00:00
|
|
|
|
2002-12-15 23:40:37 +00:00
|
|
|
if ((dir == 0) || (dir == 1))
|
2004-08-14 19:42:00 +00:00
|
|
|
step = vs->h;
|
2002-12-15 23:40:37 +00:00
|
|
|
else
|
2004-08-14 19:42:00 +00:00
|
|
|
step = vs->w;
|
2002-04-24 04:26:09 +00:00
|
|
|
|
2006-06-22 00:03:13 +00:00
|
|
|
step = (step * delay) / kScrolltime;
|
2002-04-24 04:26:09 +00:00
|
|
|
|
2007-07-10 00:39:12 +00:00
|
|
|
byte *src;
|
|
|
|
int m = _textSurfaceMultiplier;
|
|
|
|
int vsPitch = vs->pitch;
|
|
|
|
|
2002-12-15 23:40:37 +00:00
|
|
|
switch (dir) {
|
|
|
|
case 0:
|
|
|
|
//up
|
2006-06-21 06:50:50 +00:00
|
|
|
y = 1 + step;
|
2004-08-14 19:42:00 +00:00
|
|
|
while (y < vs->h) {
|
2006-06-21 06:50:50 +00:00
|
|
|
moveScreen(0, -step, vs->h);
|
2011-06-19 22:59:48 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_townsScreen) {
|
|
|
|
towns_drawStripToScreen(vs, 0, vs->topline + vs->h - step, 0, y - step, vs->w, step);
|
2010-10-05 19:04:52 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
src = vs->getPixels(0, y - step);
|
|
|
|
_system->copyRectToScreen(src,
|
|
|
|
vsPitch,
|
|
|
|
0, (vs->h - step) * m,
|
|
|
|
vs->w * m, step * m);
|
|
|
|
_system->updateScreen();
|
2007-07-10 00:39:12 +00:00
|
|
|
}
|
2011-06-19 22:59:48 +00:00
|
|
|
|
2006-06-22 00:03:13 +00:00
|
|
|
waitForTimer(delay);
|
2002-12-15 23:40:37 +00:00
|
|
|
y += step;
|
2002-03-05 23:05:55 +00:00
|
|
|
}
|
2002-12-15 23:40:37 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
// down
|
2006-06-21 06:50:50 +00:00
|
|
|
y = 1 + step;
|
2004-08-14 19:42:00 +00:00
|
|
|
while (y < vs->h) {
|
2006-06-21 06:50:50 +00:00
|
|
|
moveScreen(0, step, vs->h);
|
2010-10-05 19:04:52 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_townsScreen) {
|
|
|
|
towns_drawStripToScreen(vs, 0, vs->topline, 0, vs->h - y, vs->w, step);
|
2010-10-05 19:04:52 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
src = vs->getPixels(0, vs->h - y);
|
|
|
|
_system->copyRectToScreen(src,
|
|
|
|
vsPitch,
|
|
|
|
0, 0,
|
|
|
|
vs->w * m, step * m);
|
|
|
|
_system->updateScreen();
|
2007-07-10 00:39:12 +00:00
|
|
|
}
|
2011-06-19 22:59:48 +00:00
|
|
|
|
2006-06-22 00:03:13 +00:00
|
|
|
waitForTimer(delay);
|
2002-12-15 23:40:37 +00:00
|
|
|
y += step;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
// left
|
2006-06-21 06:50:50 +00:00
|
|
|
x = 1 + step;
|
2004-08-14 19:42:00 +00:00
|
|
|
while (x < vs->w) {
|
2006-06-21 06:50:50 +00:00
|
|
|
moveScreen(-step, 0, vs->h);
|
2010-10-05 19:04:52 +00:00
|
|
|
|
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_townsScreen) {
|
|
|
|
towns_drawStripToScreen(vs, vs->w - step, vs->topline, x - step, 0, step, vs->h);
|
2010-10-05 19:04:52 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
src = vs->getPixels(x - step, 0);
|
|
|
|
_system->copyRectToScreen(src,
|
|
|
|
vsPitch,
|
|
|
|
(vs->w - step) * m, 0,
|
|
|
|
step * m, vs->h * m);
|
|
|
|
_system->updateScreen();
|
2007-07-10 00:39:12 +00:00
|
|
|
}
|
2002-04-11 17:19:16 +00:00
|
|
|
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
waitForTimer(delay);
|
2002-12-15 23:40:37 +00:00
|
|
|
x += step;
|
2002-03-05 23:05:55 +00:00
|
|
|
}
|
2002-12-15 23:40:37 +00:00
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
// right
|
2006-06-21 06:50:50 +00:00
|
|
|
x = 1 + step;
|
2004-08-14 19:42:00 +00:00
|
|
|
while (x < vs->w) {
|
2006-06-21 06:50:50 +00:00
|
|
|
moveScreen(step, 0, vs->h);
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2010-10-05 19:04:52 +00:00
|
|
|
#ifndef DISABLE_TOWNS_DUAL_LAYER_MODE
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
if (_townsScreen) {
|
|
|
|
towns_drawStripToScreen(vs, 0, vs->topline, vs->w - x, 0, step, vs->h);
|
2010-10-05 19:04:52 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
src = vs->getPixels(vs->w - x, 0);
|
|
|
|
_system->copyRectToScreen(src,
|
|
|
|
vsPitch,
|
|
|
|
0, 0,
|
|
|
|
step, vs->h);
|
|
|
|
_system->updateScreen();
|
2011-06-19 22:59:48 +00:00
|
|
|
}
|
SCUMM/FM-TOWNS: fix palette and other graphics issues
This commit should fix at least the following bugs/feature requests: #1032859, #1252088, #1055391, #1315968, #1315938, #1742106, #812891.
The FM-Towns version of Scumm games use a mixed graphics mode with 2 layers (one with 32767 colors and one with 16 colors). Among other things I have added a screen output class which emulates this dual layer approach which allows specific hardware effects like enabling and disabling layers (e.g. in the voodoo priestess scene in MI1).
Old savegames (saved before this update) will load, but you’ll encounter palette glitches in the verb/inventory screen, since the 16 color palette for layer 2 is not contained in your savegame. This will be true at least for version 5 games. Certain scene change actions (which require the verb/inventory part to be redrawn) might correct this (e.g. try looking at the treasure map in MI1 and closing it). Version 3 games should be okay, since they use a static text palette which is never changed and which will be reset after loading a savegame.
This update requires a USE_RGB_COLORS setting for proper operation. 8 bit users will get a warning that they’ll have to expect palette glitches . Apart from that the engine in 8 bit mode should not only still work okay, but also benefit from some of the other (non palette related) improvements (e.g. bug #1032859 should be fixed even in 8 bit mode).
Japanese font drawing hasn’t been improved much yet. This will be a separate task.
svn-id: r52966
2010-10-01 19:24:52 +00:00
|
|
|
|
|
|
|
waitForTimer(delay);
|
2002-12-15 23:40:37 +00:00
|
|
|
x += step;
|
2002-03-05 23:05:55 +00:00
|
|
|
}
|
2002-12-15 23:40:37 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2003-10-02 22:42:03 +00:00
|
|
|
void ScummEngine::unkScreenEffect6() {
|
2003-06-07 11:59:56 +00:00
|
|
|
// CD Loom (but not EGA Loom!) uses a more fine-grained dissolve
|
2006-02-20 16:51:30 +00:00
|
|
|
if (_game.id == GID_LOOM && (_game.version == 4))
|
2002-12-15 23:40:37 +00:00
|
|
|
dissolveEffect(1, 1);
|
|
|
|
else
|
|
|
|
dissolveEffect(8, 4);
|
|
|
|
}
|
2002-04-11 17:19:16 +00:00
|
|
|
|
2003-10-09 14:17:06 +00:00
|
|
|
} // End of namespace Scumm
|