Patch #1003866 (SCUMM: New text rendering code (fixes various bugs))
svn-id: r14521
This commit is contained in:
parent
f8cc6c2241
commit
835ef5f012
14 changed files with 151 additions and 306 deletions
22
NEWS
22
NEWS
|
@ -2,20 +2,26 @@ For a more comprehensive changelog for the latest experimental CVS code, see:
|
||||||
http://scummvm.sourceforge.net/daily/ChangeLog
|
http://scummvm.sourceforge.net/daily/ChangeLog
|
||||||
|
|
||||||
0.??
|
0.??
|
||||||
|
New Games:
|
||||||
|
- Added SAGA engine (for the games and "I Have No Mouth and I Must Scream"
|
||||||
|
and "Inherit the Earth")
|
||||||
|
|
||||||
General:
|
General:
|
||||||
- Added support for FLAC (losless) encoded audio files
|
- Added support for FLAC (losless) encoded audio files
|
||||||
- Added an 'On Screen Display' to the SDL backend
|
- Added an 'On Screen Display' to the SDL backend
|
||||||
- Rewrote the backend API partially
|
- Partially rewrote the backend API
|
||||||
- Comments in config files are preserved now
|
- Comments in config files are preserved now
|
||||||
- Updated AdvMame scalers based on scale2x 2.0 - AdvMame3x looks nicer now
|
- Updated AdvMame scalers based on scale2x 2.0 - AdvMame3x looks nicer now,
|
||||||
- Added MMX i386 assembler HQ2x and HQ3x scalers
|
and AdvMame2x is MMX accelerated
|
||||||
- Alt-x and Ctrl-z quit keys disabled in favour of Ctrl-q on non
|
- Added MMX i386 assembler versions of the HQ2x and HQ3x scalers
|
||||||
Mac OS X unices (including Linux)
|
- Alt-x and Ctrl-z quit keys disabled in favour of Ctrl-q on unix like
|
||||||
|
operating systems, like Linux (exception: Mac OS X still uses Cmd-q)
|
||||||
|
|
||||||
SCUMM:
|
SCUMM:
|
||||||
- Old zak256 target removed, use zakTowns instead
|
- Old zak256 target removed, use zakTowns instead
|
||||||
- Added support for the special container file format used in mac version
|
- Added support for the special container file format used in the macintosh
|
||||||
(thus you do not have to use rescumm anymore)
|
versions of some games (thus you do not have to use rescumm anymore)
|
||||||
|
- Partially rewrote the text engine, fixing various bugs
|
||||||
|
|
||||||
Queen:
|
Queen:
|
||||||
- Various fixes [TODO: Somebody of the Queen team please fill this in]
|
- Various fixes [TODO: Somebody of the Queen team please fill this in]
|
||||||
|
@ -43,7 +49,7 @@ For a more comprehensive changelog for the latest experimental CVS code, see:
|
||||||
same file handle, e.g. in the Sam & Max intro when using monster.sog.
|
same file handle, e.g. in the Sam & Max intro when using monster.sog.
|
||||||
|
|
||||||
SCUMM:
|
SCUMM:
|
||||||
- Many SCUMM game engine fixes.
|
- As usual: many SCUMM game engine fixes.
|
||||||
- Added graphics decoders for 3DO Humongous Entertainment games
|
- Added graphics decoders for 3DO Humongous Entertainment games
|
||||||
- Numerous Humongous Entertainment games fixes
|
- Numerous Humongous Entertainment games fixes
|
||||||
- Fixed bug in Full Throttle, so battle difficulty matches original
|
- Fixed bug in Full Throttle, so battle difficulty matches original
|
||||||
|
|
9
TODO
9
TODO
|
@ -230,15 +230,6 @@ SCUMM
|
||||||
details
|
details
|
||||||
* V7-8 games: Implement smooth horizontal scrolling (instead of scrolling in
|
* V7-8 games: Implement smooth horizontal scrolling (instead of scrolling in
|
||||||
increments of 8 pixels). See bug #629417.
|
increments of 8 pixels). See bug #629417.
|
||||||
* COMI (maybe V7 games, too?): "Fix" CHARSET_1 behaviour when the room scrolls.
|
|
||||||
In particular, when text is drawn via CHARSET_1 and then scrolling takes
|
|
||||||
place, the text scrolls, too - but it really should stay fixed. There are
|
|
||||||
several ways to do this that I can think of. One would be to use an overlay
|
|
||||||
screen (i.e. use virtscreen 3, which isn't used at all currently) to draw
|
|
||||||
the text; then "compose" that screen over the main screen.
|
|
||||||
Or constantly (well, at least whenever the camera moves) redraw the text.
|
|
||||||
That would require buffering the text; maybe the blast text code could be
|
|
||||||
reused for this...
|
|
||||||
* Add tool and support for compress *.la* file resources (ex. sounds) to fit
|
* Add tool and support for compress *.la* file resources (ex. sounds) to fit
|
||||||
on small devices
|
on small devices
|
||||||
* Fix codec44 for nut fonts
|
* Fix codec44 for nut fonts
|
||||||
|
|
|
@ -385,7 +385,7 @@ void AkosRenderer::codec1_genericDecode() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
masked = (y < 0 || y >= _outheight) || (v1.mask_ptr && ((mask[0] | mask[v1.imgbufoffs]) & maskbit));
|
masked = (y < 0 || y >= _outheight) || (v1.mask_ptr && (*mask & maskbit));
|
||||||
|
|
||||||
if (color && !masked && !skip_column) {
|
if (color && !masked && !skip_column) {
|
||||||
pcolor = palette[color];
|
pcolor = palette[color];
|
||||||
|
@ -781,8 +781,7 @@ byte AkosRenderer::codec1(int xmoveCur, int ymoveCur) {
|
||||||
|
|
||||||
v1.destptr = _outptr + v1.y * _outwidth + v1.x;
|
v1.destptr = _outptr + v1.y * _outwidth + v1.x;
|
||||||
|
|
||||||
v1.mask_ptr = _vm->getMaskBuffer(0, v1.y, 0);
|
v1.mask_ptr = _vm->getMaskBuffer(0, v1.y, _zbuf);
|
||||||
v1.imgbufoffs = _vm->gdi._imgBufOffs[_zbuf];
|
|
||||||
|
|
||||||
codec1_genericDecode();
|
codec1_genericDecode();
|
||||||
|
|
||||||
|
@ -847,9 +846,7 @@ byte AkosRenderer::codec5(int xmoveCur, int ymoveCur) {
|
||||||
}
|
}
|
||||||
bdd.y = _actorY + ymoveCur;
|
bdd.y = _actorY + ymoveCur;
|
||||||
|
|
||||||
if (_zbuf != 0) {
|
|
||||||
bdd.maskPtr = _vm->getMaskBuffer(0, 0, _zbuf);
|
bdd.maskPtr = _vm->getMaskBuffer(0, 0, _zbuf);
|
||||||
}
|
|
||||||
_vm->drawBomp(bdd, !_mirror);
|
_vm->drawBomp(bdd, !_mirror);
|
||||||
|
|
||||||
_vm->_bompActorPalettePtr = NULL;
|
_vm->_bompActorPalettePtr = NULL;
|
||||||
|
@ -930,7 +927,7 @@ void AkosRenderer::akos16Decompress(byte *dest, int32 pitch, const byte *src, in
|
||||||
int32 numskip_before, int32 numskip_after, byte transparency, int maskLeft, int maskTop, int zBuf) {
|
int32 numskip_before, int32 numskip_after, byte transparency, int maskLeft, int maskTop, int zBuf) {
|
||||||
byte *tmp_buf = akos16.buffer;
|
byte *tmp_buf = akos16.buffer;
|
||||||
int maskpitch;
|
int maskpitch;
|
||||||
byte *maskptr = 0, *charsetMask = 0;
|
byte *maskptr;
|
||||||
const byte maskbit = revBitMask[maskLeft & 7];
|
const byte maskbit = revBitMask[maskLeft & 7];
|
||||||
|
|
||||||
if (dir < 0) {
|
if (dir < 0) {
|
||||||
|
@ -946,19 +943,13 @@ void AkosRenderer::akos16Decompress(byte *dest, int32 pitch, const byte *src, in
|
||||||
|
|
||||||
maskpitch = _numStrips;
|
maskpitch = _numStrips;
|
||||||
|
|
||||||
charsetMask = _vm->getMaskBuffer(maskLeft, maskTop, 0);
|
|
||||||
if (zBuf != 0)
|
|
||||||
maskptr = _vm->getMaskBuffer(maskLeft, maskTop, zBuf);
|
maskptr = _vm->getMaskBuffer(maskLeft, maskTop, zBuf);
|
||||||
|
|
||||||
assert(t_height > 0);
|
assert(t_height > 0);
|
||||||
assert(t_width > 0);
|
assert(t_width > 0);
|
||||||
while (t_height--) {
|
while (t_height--) {
|
||||||
akos16DecodeLine(tmp_buf, t_width, dir);
|
akos16DecodeLine(tmp_buf, t_width, dir);
|
||||||
bompApplyMask(akos16.buffer, charsetMask, maskbit, t_width, transparency);
|
|
||||||
if (maskptr) {
|
|
||||||
bompApplyMask(akos16.buffer, maskptr, maskbit, t_width, transparency);
|
bompApplyMask(akos16.buffer, maskptr, maskbit, t_width, transparency);
|
||||||
maskptr += maskpitch;
|
|
||||||
}
|
|
||||||
bool HE7Check = (_vm->_heversion == 70);
|
bool HE7Check = (_vm->_heversion == 70);
|
||||||
bompApplyShadow(_shadow_mode, _shadow_table, akos16.buffer, dest, t_width, transparency, HE7Check);
|
bompApplyShadow(_shadow_mode, _shadow_table, akos16.buffer, dest, t_width, transparency, HE7Check);
|
||||||
|
|
||||||
|
@ -966,7 +957,7 @@ void AkosRenderer::akos16Decompress(byte *dest, int32 pitch, const byte *src, in
|
||||||
akos16SkipData(numskip_after);
|
akos16SkipData(numskip_after);
|
||||||
}
|
}
|
||||||
dest += pitch;
|
dest += pitch;
|
||||||
charsetMask += maskpitch;
|
maskptr += maskpitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,6 @@ protected:
|
||||||
int skip_width;
|
int skip_width;
|
||||||
byte *destptr;
|
byte *destptr;
|
||||||
const byte *mask_ptr;
|
const byte *mask_ptr;
|
||||||
int imgbufoffs;
|
|
||||||
} v1;
|
} v1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -199,7 +199,6 @@ void ScummEngine::drawBomp(const BompDrawData &bd, bool mirror) {
|
||||||
const byte *src;
|
const byte *src;
|
||||||
byte *dst;
|
byte *dst;
|
||||||
byte *mask = 0;
|
byte *mask = 0;
|
||||||
byte *charset_mask;
|
|
||||||
Common::Rect clip;
|
Common::Rect clip;
|
||||||
byte *scalingYPtr = bd.scalingYPtr;
|
byte *scalingYPtr = bd.scalingYPtr;
|
||||||
byte skip_y_bits = 0x80;
|
byte skip_y_bits = 0x80;
|
||||||
|
@ -234,10 +233,7 @@ void ScummEngine::drawBomp(const BompDrawData &bd, bool mirror) {
|
||||||
|
|
||||||
const byte maskbit = revBitMask[(bd.x + clip.left) & 7];
|
const byte maskbit = revBitMask[(bd.x + clip.left) & 7];
|
||||||
|
|
||||||
// Always mask against the charset mask
|
// Mask against any additionally imposed mask
|
||||||
charset_mask = getMaskBuffer(bd.x + clip.left, bd.y, 0);
|
|
||||||
|
|
||||||
// Also mask against any additionally imposed mask
|
|
||||||
if (bd.maskPtr) {
|
if (bd.maskPtr) {
|
||||||
mask = bd.maskPtr + (bd.y * gdi._numStrips) + ((bd.x + clip.left) / 8);
|
mask = bd.maskPtr + (bd.y * gdi._numStrips) + ((bd.x + clip.left) / 8);
|
||||||
}
|
}
|
||||||
|
@ -310,7 +306,6 @@ void ScummEngine::drawBomp(const BompDrawData &bd, bool mirror) {
|
||||||
// Replace the parts of the line which are masked with the transparency color
|
// Replace the parts of the line which are masked with the transparency color
|
||||||
if (bd.maskPtr)
|
if (bd.maskPtr)
|
||||||
bompApplyMask(line_ptr, mask, maskbit, width, 255);
|
bompApplyMask(line_ptr, mask, maskbit, width, 255);
|
||||||
bompApplyMask(line_ptr, charset_mask, maskbit, width, 255);
|
|
||||||
|
|
||||||
// Apply custom color map, if available
|
// Apply custom color map, if available
|
||||||
if (_bompActorPalettePtr)
|
if (_bompActorPalettePtr)
|
||||||
|
@ -324,7 +319,6 @@ void ScummEngine::drawBomp(const BompDrawData &bd, bool mirror) {
|
||||||
// Advance to the next line
|
// Advance to the next line
|
||||||
pos_y++;
|
pos_y++;
|
||||||
mask += gdi._numStrips;
|
mask += gdi._numStrips;
|
||||||
charset_mask += gdi._numStrips;
|
|
||||||
dst += bd.outwidth;
|
dst += bd.outwidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -944,7 +944,7 @@ void CharsetRendererV3::setColor(byte color)
|
||||||
void CharsetRendererV3::printChar(int chr) {
|
void CharsetRendererV3::printChar(int chr) {
|
||||||
// Indy3 / Zak256 / Loom
|
// Indy3 / Zak256 / Loom
|
||||||
VirtScreen *vs;
|
VirtScreen *vs;
|
||||||
byte *char_ptr, *dest_ptr, *mask_ptr;
|
byte *char_ptr, *dest_ptr;
|
||||||
int width, height;
|
int width, height;
|
||||||
int drawTop;
|
int drawTop;
|
||||||
|
|
||||||
|
@ -972,8 +972,6 @@ void CharsetRendererV3::printChar(int chr) {
|
||||||
|
|
||||||
drawTop = _top - vs->topline;
|
drawTop = _top - vs->topline;
|
||||||
char_ptr = _fontPtr + chr * 8;
|
char_ptr = _fontPtr + chr * 8;
|
||||||
dest_ptr = vs->screenPtr + vs->xstart + drawTop * vs->width + _left;
|
|
||||||
mask_ptr = _vm->getMaskBuffer(_left, drawTop, 0);
|
|
||||||
|
|
||||||
_vm->markRectAsDirty(vs->number, _left, _left + width, drawTop, drawTop + height);
|
_vm->markRectAsDirty(vs->number, _left, _left + width, drawTop, drawTop + height);
|
||||||
|
|
||||||
|
@ -981,8 +979,13 @@ void CharsetRendererV3::printChar(int chr) {
|
||||||
_hasMask = true;
|
_hasMask = true;
|
||||||
_textScreenID = vs->number;
|
_textScreenID = vs->number;
|
||||||
}
|
}
|
||||||
|
if (_ignoreCharsetMask || !vs->hasTwoBuffers) {
|
||||||
|
dest_ptr = vs->screenPtr + vs->xstart + drawTop * vs->width + _left;
|
||||||
|
} else {
|
||||||
|
dest_ptr = (byte *)_vm->gdi._textSurface.pixels + drawTop * _vm->gdi._textSurface.pitch + _left;
|
||||||
|
}
|
||||||
|
|
||||||
drawBits1(vs, dest_ptr, char_ptr, mask_ptr, drawTop, 8, 8);
|
drawBits1(vs, dest_ptr, char_ptr, drawTop, 8, 8);
|
||||||
|
|
||||||
if (_str.left > _left)
|
if (_str.left > _left)
|
||||||
_str.left = _left;
|
_str.left = _left;
|
||||||
|
@ -1085,24 +1088,29 @@ void CharsetRendererClassic::printChar(int chr) {
|
||||||
|
|
||||||
_vm->markRectAsDirty(vs->number, _left, _left + width, drawTop, drawTop + height + offsY);
|
_vm->markRectAsDirty(vs->number, _left, _left + width, drawTop, drawTop + height + offsY);
|
||||||
|
|
||||||
|
byte *dst;
|
||||||
|
byte *back;
|
||||||
|
|
||||||
if (!_ignoreCharsetMask) {
|
if (!_ignoreCharsetMask) {
|
||||||
_hasMask = true;
|
_hasMask = true;
|
||||||
_textScreenID = vs->number;
|
_textScreenID = vs->number;
|
||||||
}
|
}
|
||||||
|
if (_ignoreCharsetMask || !vs->hasTwoBuffers) {
|
||||||
|
dst = vs->screenPtr + vs->xstart + drawTop * vs->width + _left;
|
||||||
|
} else {
|
||||||
|
dst = (byte *)_vm->gdi._textSurface.pixels + drawTop * _vm->gdi._textSurface.pitch + _left;
|
||||||
|
}
|
||||||
|
|
||||||
byte *mask = _vm->getMaskBuffer(_left, drawTop, 0);
|
back = dst;
|
||||||
byte *dst = vs->screenPtr + vs->xstart + drawTop * vs->width + _left;
|
|
||||||
|
|
||||||
byte *back = dst;
|
|
||||||
if (_blitAlso && vs->hasTwoBuffers) {
|
if (_blitAlso && vs->hasTwoBuffers) {
|
||||||
dst = vs->backBuf + vs->xstart + drawTop * vs->width + _left;
|
dst = vs->backBuf + vs->xstart + drawTop * vs->width + _left;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is2byte) {
|
if (is2byte) {
|
||||||
drawBits1(vs, dst, charPtr, mask, drawTop, origWidth, origHeight);
|
drawBits1(vs, dst, charPtr, drawTop, origWidth, origHeight);
|
||||||
} else {
|
} else {
|
||||||
byte bpp = *_fontPtr;
|
byte bpp = *_fontPtr;
|
||||||
drawBitsN(vs, dst, charPtr, mask, bpp, drawTop, origWidth, origHeight);
|
drawBitsN(vs, dst, charPtr, bpp, drawTop, origWidth, origHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_blitAlso && vs->hasTwoBuffers) {
|
if (_blitAlso && vs->hasTwoBuffers) {
|
||||||
|
@ -1128,30 +1136,21 @@ void CharsetRendererClassic::printChar(int chr) {
|
||||||
_top -= offsY;
|
_top -= offsY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharsetRendererClassic::drawBitsN(VirtScreen *vs, byte *dst, const byte *src, byte *mask, byte bpp, int drawTop, int width, int height) {
|
void CharsetRendererClassic::drawBitsN(VirtScreen *vs, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height) {
|
||||||
byte maskmask;
|
|
||||||
int y, x;
|
int y, x;
|
||||||
int maskpos;
|
|
||||||
int color;
|
int color;
|
||||||
byte numbits, bits;
|
byte numbits, bits;
|
||||||
bool useMask = (vs->number == kMainVirtScreen && !_ignoreCharsetMask);
|
|
||||||
|
|
||||||
assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8);
|
assert(bpp == 1 || bpp == 2 || bpp == 4 || bpp == 8);
|
||||||
bits = *src++;
|
bits = *src++;
|
||||||
numbits = 8;
|
numbits = 8;
|
||||||
|
|
||||||
for (y = 0; y < height && y + drawTop < vs->height; y++) {
|
for (y = 0; y < height && y + drawTop < vs->height; y++) {
|
||||||
maskmask = revBitMask[_left & 7];
|
|
||||||
maskpos = 0;
|
|
||||||
|
|
||||||
for (x = 0; x < width; x++) {
|
for (x = 0; x < width; x++) {
|
||||||
color = (bits >> (8 - bpp)) & 0xFF;
|
color = (bits >> (8 - bpp)) & 0xFF;
|
||||||
|
|
||||||
if (color && y + drawTop >= 0) {
|
if (color && y + drawTop >= 0) {
|
||||||
*dst = _vm->_charsetColorMap[color];
|
*dst = _vm->_charsetColorMap[color];
|
||||||
if (useMask) {
|
|
||||||
mask[maskpos] |= maskmask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dst++;
|
dst++;
|
||||||
bits <<= bpp;
|
bits <<= bpp;
|
||||||
|
@ -1160,28 +1159,16 @@ void CharsetRendererClassic::drawBitsN(VirtScreen *vs, byte *dst, const byte *sr
|
||||||
bits = *src++;
|
bits = *src++;
|
||||||
numbits = 8;
|
numbits = 8;
|
||||||
}
|
}
|
||||||
maskmask >>= 1;
|
|
||||||
if (maskmask == 0) {
|
|
||||||
maskmask = 0x80;
|
|
||||||
maskpos++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dst += vs->width - width;
|
dst += vs->width - width;
|
||||||
mask += _vm->gdi._numStrips;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharsetRendererCommon::drawBits1(VirtScreen *vs, byte *dst, const byte *src, byte *mask, int drawTop, int width, int height) {
|
void CharsetRendererCommon::drawBits1(VirtScreen *vs, byte *dst, const byte *src, int drawTop, int width, int height) {
|
||||||
byte maskmask;
|
|
||||||
int y, x;
|
int y, x;
|
||||||
int maskpos;
|
|
||||||
byte bits = 0;
|
byte bits = 0;
|
||||||
bool useMask = (vs->number == kMainVirtScreen && !_ignoreCharsetMask);
|
|
||||||
|
|
||||||
for (y = 0; y < height && y + drawTop < vs->height; y++) {
|
for (y = 0; y < height && y + drawTop < vs->height; y++) {
|
||||||
maskmask = revBitMask[_left & 7];
|
|
||||||
maskpos = 0;
|
|
||||||
|
|
||||||
for (x = 0; x < width; x++) {
|
for (x = 0; x < width; x++) {
|
||||||
if ((x % 8) == 0)
|
if ((x % 8) == 0)
|
||||||
bits = *src++;
|
bits = *src++;
|
||||||
|
@ -1192,30 +1179,11 @@ void CharsetRendererCommon::drawBits1(VirtScreen *vs, byte *dst, const byte *src
|
||||||
*(dst + vs->width + 1) = _shadowColor;
|
*(dst + vs->width + 1) = _shadowColor;
|
||||||
}
|
}
|
||||||
*dst = _color;
|
*dst = _color;
|
||||||
if (useMask) {
|
|
||||||
mask[maskpos] |= maskmask;
|
|
||||||
if (_dropShadow) {
|
|
||||||
mask[maskpos + _vm->gdi._numStrips] |= maskmask;
|
|
||||||
if (maskmask == 1) {
|
|
||||||
mask[maskpos + 1] |= 0x80;
|
|
||||||
mask[maskpos + _vm->gdi._numStrips + 1] |= 0x80;
|
|
||||||
} else {
|
|
||||||
mask[maskpos] |= (maskmask >> 1);
|
|
||||||
mask[maskpos + _vm->gdi._numStrips] |= (maskmask >> 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dst++;
|
dst++;
|
||||||
maskmask >>= 1;
|
|
||||||
if (maskmask == 0) {
|
|
||||||
maskmask = 0x80;
|
|
||||||
maskpos++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dst += vs->width - width;
|
dst += vs->width - width;
|
||||||
mask += _vm->gdi._numStrips;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1293,12 +1261,23 @@ void CharsetRendererNut::printChar(int chr) {
|
||||||
shadow.right = _left + width + 2;
|
shadow.right = _left + width + 2;
|
||||||
shadow.bottom = _top + height + 2;
|
shadow.bottom = _top + height + 2;
|
||||||
|
|
||||||
|
Graphics::Surface s;
|
||||||
if (!_ignoreCharsetMask) {
|
if (!_ignoreCharsetMask) {
|
||||||
_hasMask = true;
|
_hasMask = true;
|
||||||
_textScreenID = kMainVirtScreen;
|
_textScreenID = kMainVirtScreen;
|
||||||
}
|
}
|
||||||
|
if (_ignoreCharsetMask) {
|
||||||
|
VirtScreen *vs = &_vm->virtscr[kMainVirtScreen];
|
||||||
|
s.pixels = vs->screenPtr + vs->xstart + _vm->_screenTop * vs->width;
|
||||||
|
s.w = vs->width;
|
||||||
|
s.h = vs->height;
|
||||||
|
s.pitch = vs->width;
|
||||||
|
s.bytesPerPixel = 1;
|
||||||
|
} else {
|
||||||
|
s = _vm->gdi._textSurface;
|
||||||
|
}
|
||||||
|
|
||||||
_current->drawShadowChar(chr, _left, _top, _color, !_ignoreCharsetMask, _curId != 3);
|
_current->drawShadowChar(s, chr, _left, _top, _color, _curId != 3);
|
||||||
_vm->markRectAsDirty(kMainVirtScreen, shadow);
|
_vm->markRectAsDirty(kMainVirtScreen, shadow);
|
||||||
|
|
||||||
if (_str.left > _left)
|
if (_str.left > _left)
|
||||||
|
|
|
@ -69,7 +69,6 @@ public:
|
||||||
|
|
||||||
void restoreCharsetBg();
|
void restoreCharsetBg();
|
||||||
void clearCharsetMask();
|
void clearCharsetMask();
|
||||||
bool hasCharsetMask(int left, int top, int right, int bottom);
|
|
||||||
|
|
||||||
virtual void printChar(int chr) = 0;
|
virtual void printChar(int chr) = 0;
|
||||||
|
|
||||||
|
@ -88,7 +87,7 @@ class CharsetRendererCommon : public CharsetRenderer {
|
||||||
protected:
|
protected:
|
||||||
byte *_fontPtr;
|
byte *_fontPtr;
|
||||||
|
|
||||||
void drawBits1(VirtScreen *vs, byte *dst, const byte *src, byte *mask, int drawTop, int width, int height);
|
void drawBits1(VirtScreen *vs, byte *dst, const byte *src, int drawTop, int width, int height);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CharsetRendererCommon(ScummEngine *vm) : CharsetRenderer(vm) {}
|
CharsetRendererCommon(ScummEngine *vm) : CharsetRenderer(vm) {}
|
||||||
|
@ -102,7 +101,7 @@ class CharsetRendererClassic : public CharsetRendererCommon {
|
||||||
protected:
|
protected:
|
||||||
int getCharWidth(byte chr);
|
int getCharWidth(byte chr);
|
||||||
|
|
||||||
void drawBitsN(VirtScreen *vs, byte *dst, const byte *src, byte *mask, byte bpp, int drawTop, int width, int height);
|
void drawBitsN(VirtScreen *vs, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {}
|
CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {}
|
||||||
|
|
|
@ -284,8 +284,7 @@ byte CostumeRenderer::mainRoutine(int xmoveCur, int ymoveCur) {
|
||||||
|
|
||||||
v1.destptr = _outptr + v1.y * _outwidth + v1.x;
|
v1.destptr = _outptr + v1.y * _outwidth + v1.x;
|
||||||
|
|
||||||
v1.mask_ptr = _vm->getMaskBuffer(0, v1.y, 0);
|
v1.mask_ptr = _vm->getMaskBuffer(0, v1.y, _zbuf);
|
||||||
v1.imgbufoffs = _vm->gdi._imgBufOffs[_zbuf];
|
|
||||||
|
|
||||||
CHECK_HEAP
|
CHECK_HEAP
|
||||||
|
|
||||||
|
@ -350,7 +349,7 @@ static const int v1MMActorPalatte2[25] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MASK_AT(xoff) \
|
#define MASK_AT(xoff) \
|
||||||
(mask && (mask[((v1.x + xoff) / 8) + v1.imgbufoffs] & revBitMask[(v1.x + xoff) & 7]))
|
(mask && (mask[((v1.x + xoff) / 8)] & revBitMask[(v1.x + xoff) & 7]))
|
||||||
#define LINE(c,p) \
|
#define LINE(c,p) \
|
||||||
pcolor = (color >> c) & 3; \
|
pcolor = (color >> c) & 3; \
|
||||||
if (pcolor) { \
|
if (pcolor) { \
|
||||||
|
@ -467,7 +466,7 @@ void CostumeRenderer::proc3() {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (_scaleY == 255 || *scaleytab++ < _scaleY) {
|
if (_scaleY == 255 || *scaleytab++ < _scaleY) {
|
||||||
masked = (y < 0 || y >= _outheight) || (v1.mask_ptr && ((mask[0] | mask[v1.imgbufoffs]) & maskbit));
|
masked = (y < 0 || y >= _outheight) || (v1.mask_ptr && (mask[0] & maskbit));
|
||||||
|
|
||||||
if (color && !masked) {
|
if (color && !masked) {
|
||||||
// FIXME: Fully implement _shadow_mode.in Sam & Max
|
// FIXME: Fully implement _shadow_mode.in Sam & Max
|
||||||
|
@ -536,7 +535,7 @@ void CostumeRenderer::proc3_ami() {
|
||||||
len = *src++;
|
len = *src++;
|
||||||
do {
|
do {
|
||||||
if (_scaleY == 255 || cost_scaleTable[_scaleIndexY] < _scaleY) {
|
if (_scaleY == 255 || cost_scaleTable[_scaleIndexY] < _scaleY) {
|
||||||
masked = (y < 0 || y >= _outheight) || (v1.mask_ptr && ((mask[0] | mask[v1.imgbufoffs]) & maskbit));
|
masked = (y < 0 || y >= _outheight) || (v1.mask_ptr && (mask[0] & maskbit));
|
||||||
|
|
||||||
if (color && v1.x >= 0 && v1.x < _outwidth && !masked) {
|
if (color && v1.x >= 0 && v1.x < _outwidth && !masked) {
|
||||||
*dst = _palette[color];
|
*dst = _palette[color];
|
||||||
|
|
190
scumm/gfx.cpp
190
scumm/gfx.cpp
|
@ -156,49 +156,12 @@ static const TransitionEffect transitionEffects[5] = {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline void copy8PixelsWithMasking(byte *dst, const byte *src, byte maskbits) {
|
|
||||||
if (!(maskbits & 0x80))
|
|
||||||
dst[0] = src[0];
|
|
||||||
if (!(maskbits & 0x40))
|
|
||||||
dst[1] = src[1];
|
|
||||||
if (!(maskbits & 0x20))
|
|
||||||
dst[2] = src[2];
|
|
||||||
if (!(maskbits & 0x10))
|
|
||||||
dst[3] = src[3];
|
|
||||||
if (!(maskbits & 0x08))
|
|
||||||
dst[4] = src[4];
|
|
||||||
if (!(maskbits & 0x04))
|
|
||||||
dst[5] = src[5];
|
|
||||||
if (!(maskbits & 0x02))
|
|
||||||
dst[6] = src[6];
|
|
||||||
if (!(maskbits & 0x01))
|
|
||||||
dst[7] = src[7];
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void clear8PixelsWithMasking(byte *dst, const byte color, byte maskbits) {
|
|
||||||
if (!(maskbits & 0x80))
|
|
||||||
dst[0] = color;
|
|
||||||
if (!(maskbits & 0x40))
|
|
||||||
dst[1] = color;
|
|
||||||
if (!(maskbits & 0x20))
|
|
||||||
dst[2] = color;
|
|
||||||
if (!(maskbits & 0x10))
|
|
||||||
dst[3] = color;
|
|
||||||
if (!(maskbits & 0x08))
|
|
||||||
dst[4] = color;
|
|
||||||
if (!(maskbits & 0x04))
|
|
||||||
dst[5] = color;
|
|
||||||
if (!(maskbits & 0x02))
|
|
||||||
dst[6] = color;
|
|
||||||
if (!(maskbits & 0x01))
|
|
||||||
dst[7] = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark --- Virtual Screens ---
|
#pragma mark --- Virtual Screens ---
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
#define CHARSET_MASK_TRANSPARENCY 254
|
||||||
|
|
||||||
Gdi::Gdi(ScummEngine *vm) {
|
Gdi::Gdi(ScummEngine *vm) {
|
||||||
memset(this, 0, sizeof(*this));
|
memset(this, 0, sizeof(*this));
|
||||||
|
@ -206,6 +169,9 @@ Gdi::Gdi(ScummEngine *vm) {
|
||||||
_roomPalette = vm->_roomPalette;
|
_roomPalette = vm->_roomPalette;
|
||||||
if ((vm->_features & GF_AMIGA) && (vm->_version >= 4))
|
if ((vm->_features & GF_AMIGA) && (vm->_version >= 4))
|
||||||
_roomPalette += 16;
|
_roomPalette += 16;
|
||||||
|
|
||||||
|
_compositeBuf = 0;
|
||||||
|
_textSurface.pixels = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScummEngine::initScreens(int b, int h) {
|
void ScummEngine::initScreens(int b, int h) {
|
||||||
|
@ -235,8 +201,26 @@ void ScummEngine::initScreens(int b, int h) {
|
||||||
|
|
||||||
_screenB = b;
|
_screenB = b;
|
||||||
_screenH = h;
|
_screenH = h;
|
||||||
|
|
||||||
|
gdi.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Gdi::init() {
|
||||||
|
const int size = _vm->_screenWidth * _vm->_screenHeight;
|
||||||
|
free(_compositeBuf);
|
||||||
|
free(_textSurface.pixels);
|
||||||
|
_compositeBuf = (byte *)malloc(size);
|
||||||
|
_textSurface.pixels = malloc(size);
|
||||||
|
memset(_compositeBuf, CHARSET_MASK_TRANSPARENCY, size);
|
||||||
|
memset(_textSurface.pixels, CHARSET_MASK_TRANSPARENCY, size);
|
||||||
|
|
||||||
|
_textSurface.w = _vm->_screenWidth;
|
||||||
|
_textSurface.h = _vm->_screenHeight;
|
||||||
|
_textSurface.pitch = _vm->_screenWidth;
|
||||||
|
_textSurface.bytesPerPixel = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ScummEngine::initVirtScreen(VirtScreenNumber slot, int number, int top, int width, int height, bool twobufs,
|
void ScummEngine::initVirtScreen(VirtScreenNumber slot, int number, int top, int width, int height, bool twobufs,
|
||||||
bool scrollable) {
|
bool scrollable) {
|
||||||
VirtScreen *vs = &virtscr[slot];
|
VirtScreen *vs = &virtscr[slot];
|
||||||
|
@ -246,7 +230,7 @@ void ScummEngine::initVirtScreen(VirtScreenNumber slot, int number, int top, int
|
||||||
assert(slot >= 0 && slot < 4);
|
assert(slot >= 0 && slot < 4);
|
||||||
|
|
||||||
if (_version >= 7) {
|
if (_version >= 7) {
|
||||||
if (slot == 0 && (_roomHeight != 0))
|
if (slot == kMainVirtScreen && (_roomHeight != 0))
|
||||||
height = _roomHeight;
|
height = _roomHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,8 +415,7 @@ void Gdi::updateDirtyScreen(VirtScreen *vs) {
|
||||||
* specified by top/bottom coordinate in the virtual screen.
|
* specified by top/bottom coordinate in the virtual screen.
|
||||||
*/
|
*/
|
||||||
void Gdi::drawStripToScreen(VirtScreen *vs, int x, int width, int top, int bottom) {
|
void Gdi::drawStripToScreen(VirtScreen *vs, int x, int width, int top, int bottom) {
|
||||||
byte *ptr;
|
const int height = bottom - top;
|
||||||
int height;
|
|
||||||
|
|
||||||
if (bottom <= top)
|
if (bottom <= top)
|
||||||
return;
|
return;
|
||||||
|
@ -442,11 +425,33 @@ void Gdi::drawStripToScreen(VirtScreen *vs, int x, int width, int top, int botto
|
||||||
|
|
||||||
assert(top >= 0 && bottom <= vs->height); // Paranoia checks
|
assert(top >= 0 && bottom <= vs->height); // Paranoia checks
|
||||||
|
|
||||||
height = bottom - top;
|
|
||||||
// We don't clip height and width here, rather we rely on the backend to
|
// We don't clip height and width here, rather we rely on the backend to
|
||||||
// perform any needed clipping.
|
// perform any needed clipping.
|
||||||
ptr = vs->screenPtr + (x + vs->xstart) + top * vs->width;
|
const int y = vs->topline + top - _vm->_screenTop;
|
||||||
_vm->_system->copyRectToScreen(ptr, vs->width, x, vs->topline + top - _vm->_screenTop, width, height);
|
const byte *src = vs->screenPtr + (x + vs->xstart) + top * vs->width;
|
||||||
|
|
||||||
|
assert(_textSurface.pixels);
|
||||||
|
assert(_compositeBuf);
|
||||||
|
Common::Rect r(x, y, x+width, y+height);
|
||||||
|
r.clip(Common::Rect(_textSurface.w, _textSurface.h));
|
||||||
|
// TODO: is this enough clipping?
|
||||||
|
|
||||||
|
byte *dst = _compositeBuf + x + y * _vm->_screenWidth;
|
||||||
|
const byte *text = (byte *)_textSurface.pixels + x + y * _textSurface.pitch;
|
||||||
|
|
||||||
|
for (int h = 0; h < r.height(); ++h) {
|
||||||
|
for (int w = 0; w < r.width(); ++w) {
|
||||||
|
if (text[w] == CHARSET_MASK_TRANSPARENCY)
|
||||||
|
dst[w] = src[w];
|
||||||
|
else
|
||||||
|
dst[w] = text[w];
|
||||||
|
}
|
||||||
|
src += vs->width;
|
||||||
|
dst += _vm->_screenWidth;
|
||||||
|
text += _textSurface.pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
_vm->_system->copyRectToScreen(_compositeBuf + x + y * _vm->_screenWidth, _vm->_screenWidth, x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
@ -633,14 +638,12 @@ void ScummEngine::restoreBG(Common::Rect rect, byte backColor) {
|
||||||
// be optimized to (rect.right - rect.left) / 8 and
|
// be optimized to (rect.right - rect.left) / 8 and
|
||||||
// thus to width / 8, but that's not the case since
|
// thus to width / 8, but that's not the case since
|
||||||
// we are dealing with integer math here.
|
// we are dealing with integer math here.
|
||||||
const int mask_width = ((rect.right + 7) / 8) - (rect.left / 8);
|
const int mask_width = rect.width();
|
||||||
|
byte *mask = (byte *)gdi._textSurface.pixels + gdi._textSurface.pitch * rect.top + rect.left;
|
||||||
byte *mask = getMaskBuffer(rect.left, rect.top, 0);
|
while (height--) {
|
||||||
|
memset(mask, CHARSET_MASK_TRANSPARENCY, mask_width);
|
||||||
do {
|
mask += gdi._textSurface.pitch;
|
||||||
memset(mask, 0, mask_width);
|
}
|
||||||
mask += gdi._numStrips;
|
|
||||||
} while (--height);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while (height--) {
|
while (height--) {
|
||||||
|
@ -663,9 +666,7 @@ void CharsetRenderer::restoreCharsetBg() {
|
||||||
// restoreBG(), but was changed to only restore those parts which are
|
// restoreBG(), but was changed to only restore those parts which are
|
||||||
// currently covered by the charset mask.
|
// currently covered by the charset mask.
|
||||||
|
|
||||||
// Loop over first three virtual screens
|
|
||||||
VirtScreen *vs = &_vm->virtscr[_textScreenID];
|
VirtScreen *vs = &_vm->virtscr[_textScreenID];
|
||||||
|
|
||||||
if (!vs->height)
|
if (!vs->height)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -677,27 +678,8 @@ void CharsetRenderer::restoreCharsetBg() {
|
||||||
const byte *backBuf = vs->backBuf + vs->xstart;
|
const byte *backBuf = vs->backBuf + vs->xstart;
|
||||||
|
|
||||||
if (vs->number == kMainVirtScreen) {
|
if (vs->number == kMainVirtScreen) {
|
||||||
// Restore from back buffer, but only those parts which are
|
// Clean out the charset mask
|
||||||
// currently covered by the charset mask. In addition, we
|
memset(_vm->gdi._textSurface.pixels, CHARSET_MASK_TRANSPARENCY, _vm->gdi._textSurface.pitch * _vm->gdi._textSurface.h);
|
||||||
// clean out the charset mask
|
|
||||||
|
|
||||||
const int mask_width = _vm->gdi._numStrips;
|
|
||||||
byte *mask = _vm->getMaskBuffer(0, 0, 0);
|
|
||||||
assert(vs->width == 8 * _vm->gdi._numStrips);
|
|
||||||
|
|
||||||
int height = vs->height;
|
|
||||||
while (height--) {
|
|
||||||
for (int w = 0; w < mask_width; ++w) {
|
|
||||||
const byte maskbits = mask[w];
|
|
||||||
if (maskbits) {
|
|
||||||
copy8PixelsWithMasking(screenBuf + w*8, backBuf + w*8, ~maskbits);
|
|
||||||
mask[w] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
screenBuf += vs->width;
|
|
||||||
backBuf += vs->width;
|
|
||||||
mask += _vm->gdi._numStrips;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Restore from back buffer
|
// Restore from back buffer
|
||||||
_vm->blit(screenBuf, backBuf, vs->width, vs->height);
|
_vm->blit(screenBuf, backBuf, vs->width, vs->height);
|
||||||
|
@ -713,10 +695,6 @@ void CharsetRenderer::clearCharsetMask() {
|
||||||
memset(_vm->getResourceAddress(rtBuffer, 9), 0, _vm->gdi._imgBufOffs[1]);
|
memset(_vm->getResourceAddress(rtBuffer, 9), 0, _vm->gdi._imgBufOffs[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharsetRenderer::hasCharsetMask(int left, int top, int right, int bottom) {
|
|
||||||
return _hasMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte *ScummEngine::getMaskBuffer(int x, int y, int z) {
|
byte *ScummEngine::getMaskBuffer(int x, int y, int z) {
|
||||||
return gdi.getMaskBuffer(x / 8, y, z) + _screenStartStrip;
|
return gdi.getMaskBuffer(x / 8, y, z) + _screenStartStrip;
|
||||||
}
|
}
|
||||||
|
@ -1170,22 +1148,13 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mask_ptr = getMaskBuffer(x, y);
|
|
||||||
|
|
||||||
CHECK_HEAP;
|
CHECK_HEAP;
|
||||||
if (vs->hasTwoBuffers) {
|
if (vs->hasTwoBuffers) {
|
||||||
if (_vm->_charset->hasCharsetMask(sx * 8, y, (sx + 1) * 8, bottom)) {
|
|
||||||
if (flag & dbClear || !lightsOn)
|
|
||||||
clear8ColWithMasking(backbuff_ptr, height, mask_ptr);
|
|
||||||
else
|
|
||||||
draw8ColWithMasking(backbuff_ptr, bgbak_ptr, height, mask_ptr);
|
|
||||||
} else {
|
|
||||||
if (flag & dbClear || !lightsOn)
|
if (flag & dbClear || !lightsOn)
|
||||||
clear8Col(backbuff_ptr, height);
|
clear8Col(backbuff_ptr, height);
|
||||||
else
|
else
|
||||||
draw8Col(backbuff_ptr, bgbak_ptr, height);
|
draw8Col(backbuff_ptr, bgbak_ptr, height);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
CHECK_HEAP;
|
CHECK_HEAP;
|
||||||
|
|
||||||
if (_vm->_version == 1) {
|
if (_vm->_version == 1) {
|
||||||
|
@ -1304,16 +1273,12 @@ void Gdi::resetBackground(int top, int bottom, int strip) {
|
||||||
vs->bdirty[strip] = bottom;
|
vs->bdirty[strip] = bottom;
|
||||||
|
|
||||||
offs = top * vs->width + vs->xstart + strip * 8;
|
offs = top * vs->width + vs->xstart + strip * 8;
|
||||||
byte *mask_ptr = _vm->getMaskBuffer(strip * 8, top, 0);
|
|
||||||
bgbak_ptr = vs->backBuf + offs;
|
bgbak_ptr = vs->backBuf + offs;
|
||||||
backbuff_ptr = vs->screenPtr + offs;
|
backbuff_ptr = vs->screenPtr + offs;
|
||||||
|
|
||||||
numLinesToProcess = bottom - top;
|
numLinesToProcess = bottom - top;
|
||||||
if (numLinesToProcess) {
|
if (numLinesToProcess) {
|
||||||
if (_vm->isLightOn()) {
|
if (_vm->isLightOn()) {
|
||||||
if (_vm->_charset->hasCharsetMask(strip * 8, top, (strip + 1) * 8, bottom))
|
|
||||||
draw8ColWithMasking(backbuff_ptr, bgbak_ptr, numLinesToProcess, mask_ptr);
|
|
||||||
else
|
|
||||||
draw8Col(backbuff_ptr, bgbak_ptr, numLinesToProcess);
|
draw8Col(backbuff_ptr, bgbak_ptr, numLinesToProcess);
|
||||||
} else {
|
} else {
|
||||||
clear8Col(backbuff_ptr, numLinesToProcess);
|
clear8Col(backbuff_ptr, numLinesToProcess);
|
||||||
|
@ -1654,47 +1619,6 @@ bool Gdi::decompressBitmap(byte *bgbak_ptr, const byte *src, int numLinesToProce
|
||||||
return useOrDecompress;
|
return useOrDecompress;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gdi::draw8ColWithMasking(byte *dst, const byte *src, int height, byte *mask) {
|
|
||||||
byte maskbits;
|
|
||||||
|
|
||||||
do {
|
|
||||||
maskbits = *mask;
|
|
||||||
if (maskbits) {
|
|
||||||
copy8PixelsWithMasking(dst, src, maskbits);
|
|
||||||
} else {
|
|
||||||
#if defined(SCUMM_NEED_ALIGNMENT)
|
|
||||||
memcpy(dst, src, 8);
|
|
||||||
#else
|
|
||||||
((uint32 *)dst)[0] = ((const uint32 *)src)[0];
|
|
||||||
((uint32 *)dst)[1] = ((const uint32 *)src)[1];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
src += _vm->_screenWidth;
|
|
||||||
dst += _vm->_screenWidth;
|
|
||||||
mask += _numStrips;
|
|
||||||
} while (--height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gdi::clear8ColWithMasking(byte *dst, int height, byte *mask) {
|
|
||||||
byte maskbits;
|
|
||||||
|
|
||||||
do {
|
|
||||||
maskbits = *mask;
|
|
||||||
if (maskbits) {
|
|
||||||
clear8PixelsWithMasking(dst, 0, maskbits);
|
|
||||||
} else {
|
|
||||||
#if defined(SCUMM_NEED_ALIGNMENT)
|
|
||||||
memset(dst, 0, 8);
|
|
||||||
#else
|
|
||||||
((uint32 *)dst)[0] = 0;
|
|
||||||
((uint32 *)dst)[1] = 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
dst += _vm->_screenWidth;
|
|
||||||
mask += _numStrips;
|
|
||||||
} while (--height);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gdi::draw8Col(byte *dst, const byte *src, int height) {
|
void Gdi::draw8Col(byte *dst, const byte *src, int height) {
|
||||||
do {
|
do {
|
||||||
#if defined(SCUMM_NEED_ALIGNMENT)
|
#if defined(SCUMM_NEED_ALIGNMENT)
|
||||||
|
|
11
scumm/gfx.h
11
scumm/gfx.h
|
@ -24,6 +24,7 @@
|
||||||
#define GFX_H
|
#define GFX_H
|
||||||
|
|
||||||
#include "common/rect.h"
|
#include "common/rect.h"
|
||||||
|
#include "graphics/surface.h"
|
||||||
|
|
||||||
namespace Scumm {
|
namespace Scumm {
|
||||||
|
|
||||||
|
@ -217,7 +218,11 @@ public:
|
||||||
|
|
||||||
Gdi(ScummEngine *vm);
|
Gdi(ScummEngine *vm);
|
||||||
|
|
||||||
|
Graphics::Surface _textSurface;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
byte *_compositeBuf;
|
||||||
|
|
||||||
byte *_roomPalette;
|
byte *_roomPalette;
|
||||||
byte _decomp_shr, _decomp_mask;
|
byte _decomp_shr, _decomp_mask;
|
||||||
byte _transparentColor;
|
byte _transparentColor;
|
||||||
|
@ -251,9 +256,7 @@ protected:
|
||||||
void decodeStrip3DO(byte *dst, const byte *src, int height, byte transpCheck);
|
void decodeStrip3DO(byte *dst, const byte *src, int height, byte transpCheck);
|
||||||
void decodeStripHE(byte *dst, const byte *src, int height, byte transpCheck);
|
void decodeStripHE(byte *dst, const byte *src, int height, byte transpCheck);
|
||||||
|
|
||||||
void draw8ColWithMasking(byte *dst, const byte *src, int height, byte *mask);
|
|
||||||
void draw8Col(byte *dst, const byte *src, int height);
|
void draw8Col(byte *dst, const byte *src, int height);
|
||||||
void clear8ColWithMasking(byte *dst, int height, byte *mask);
|
|
||||||
void clear8Col(byte *dst, int height);
|
void clear8Col(byte *dst, int height);
|
||||||
void decompressMaskImgOr(byte *dst, const byte *src, int height);
|
void decompressMaskImgOr(byte *dst, const byte *src, int height);
|
||||||
void decompressMaskImg(byte *dst, const byte *src, int height);
|
void decompressMaskImg(byte *dst, const byte *src, int height);
|
||||||
|
@ -261,9 +264,11 @@ protected:
|
||||||
void drawStripToScreen(VirtScreen *vs, int x, int w, int t, int b);
|
void drawStripToScreen(VirtScreen *vs, int x, int w, int t, int b);
|
||||||
void updateDirtyScreen(VirtScreen *vs);
|
void updateDirtyScreen(VirtScreen *vs);
|
||||||
|
|
||||||
byte *getMaskBuffer(int x, int y, int z = 0);
|
byte *getMaskBuffer(int x, int y, int z);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void init();
|
||||||
|
|
||||||
void drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int width, const int height,
|
void drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int width, const int height,
|
||||||
int stripnr, int numstrip, byte flag, StripTable *table = 0);
|
int stripnr, int numstrip, byte flag, StripTable *table = 0);
|
||||||
void drawBitmapV2Helper(const byte *ptr, VirtScreen *vs, int x, int y, const int width, const int height,
|
void drawBitmapV2Helper(const byte *ptr, VirtScreen *vs, int x, int y, const int width, const int height,
|
||||||
|
|
|
@ -239,16 +239,13 @@ int NutRenderer::getCharHeight(byte c) {
|
||||||
return _chars[c].height;
|
return _chars[c].height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NutRenderer::drawShadowChar(int c, int x, int y, byte color, bool useMask, bool showShadow) {
|
void NutRenderer::drawShadowChar(const Graphics::Surface &s, int c, int x, int y, byte color, bool showShadow) {
|
||||||
debug(8, "NutRenderer::drawShadowChar('%c', %d, %d, %d, %d, %d) called", c, x, y, (int)color, useMask, showShadow);
|
debug(8, "NutRenderer::drawShadowChar('%c', %d, %d, %d, %d) called", c, x, y, (int)color, showShadow);
|
||||||
if (!_loaded) {
|
if (!_loaded) {
|
||||||
warning("NutRenderer::drawShadowChar() Font is not loaded");
|
warning("NutRenderer::drawShadowChar() Font is not loaded");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtScreen *vs = &_vm->virtscr[kMainVirtScreen];
|
|
||||||
byte *dst, *mask = NULL;
|
|
||||||
|
|
||||||
// HACK: we draw the character a total of 7 times: 6 times shifted
|
// HACK: we draw the character a total of 7 times: 6 times shifted
|
||||||
// and in black for the shadow, and once in the right color and position.
|
// and in black for the shadow, and once in the right color and position.
|
||||||
// This way we achieve the exact look as the original CMI had. However,
|
// This way we achieve the exact look as the original CMI had. However,
|
||||||
|
@ -268,18 +265,10 @@ void NutRenderer::drawShadowChar(int c, int x, int y, byte color, bool useMask,
|
||||||
y += offsetY[i];
|
y += offsetY[i];
|
||||||
color = cTable[i];
|
color = cTable[i];
|
||||||
|
|
||||||
if (y >= vs->height || x >= vs->width) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst = vs->screenPtr + y * vs->width + x + vs->xstart;
|
|
||||||
if (useMask)
|
|
||||||
mask = _vm->getMaskBuffer(x, y, 0);
|
|
||||||
|
|
||||||
if (c >= 256 && _vm->_CJKMode)
|
if (c >= 256 && _vm->_CJKMode)
|
||||||
draw2byte(dst, mask, c, x, y - _vm->_screenTop, color);
|
draw2byte(s, c, x, y, color);
|
||||||
else
|
else
|
||||||
drawChar(dst, mask, (byte)c, x, y - _vm->_screenTop, color);
|
drawChar(s, (byte)c, x, y, color);
|
||||||
|
|
||||||
x -= offsetX[i];
|
x -= offsetX[i];
|
||||||
y -= offsetY[i];
|
y -= offsetY[i];
|
||||||
|
@ -318,15 +307,13 @@ void NutRenderer::drawFrame(byte *dst, int c, int x, int y) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NutRenderer::drawChar(byte *dst, byte *mask, byte c, int x, int y, byte color) {
|
void NutRenderer::drawChar(const Graphics::Surface &s, byte c, int x, int y, byte color) {
|
||||||
const int width = MIN(_chars[c].width, _vm->_screenWidth - x);
|
byte *dst = (byte *)s.pixels + y * s.pitch + x;
|
||||||
const int height = MIN(_chars[c].height, _vm->_screenHeight - y);
|
const int width = MIN(_chars[c].width, s.w - x);
|
||||||
|
const int height = MIN(_chars[c].height, s.h - y);
|
||||||
const byte *src = _chars[c].src;
|
const byte *src = _chars[c].src;
|
||||||
const int srcPitch = _chars[c].width;
|
const int srcPitch = _chars[c].width;
|
||||||
|
|
||||||
byte maskmask;
|
|
||||||
int maskpos;
|
|
||||||
|
|
||||||
const int minX = x < 0 ? -x : 0;
|
const int minX = x < 0 ? -x : 0;
|
||||||
const int minY = y < 0 ? -y : 0;
|
const int minY = y < 0 ? -y : 0;
|
||||||
|
|
||||||
|
@ -336,75 +323,47 @@ void NutRenderer::drawChar(byte *dst, byte *mask, byte c, int x, int y, byte col
|
||||||
|
|
||||||
if (minY) {
|
if (minY) {
|
||||||
src += minY * srcPitch;
|
src += minY * srcPitch;
|
||||||
dst += minY * _vm->_screenWidth;
|
dst += minY * s.pitch;
|
||||||
if (mask)
|
|
||||||
mask += minY * _vm->gdi._numStrips;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int ty = minY; ty < height; ty++) {
|
for (int ty = minY; ty < height; ty++) {
|
||||||
maskmask = revBitMask[(x + minX) & 7];
|
|
||||||
maskpos = (x%8 + minX) / 8;
|
|
||||||
for (int tx = minX; tx < width; tx++) {
|
for (int tx = minX; tx < width; tx++) {
|
||||||
if (src[tx] != 0) {
|
if (src[tx] != 0) {
|
||||||
dst[tx] = color;
|
dst[tx] = color;
|
||||||
if (mask)
|
|
||||||
mask[maskpos] |= maskmask;
|
|
||||||
}
|
|
||||||
maskmask >>= 1;
|
|
||||||
if (maskmask == 0) {
|
|
||||||
maskmask = 0x80;
|
|
||||||
maskpos++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
src += srcPitch;
|
src += srcPitch;
|
||||||
dst += _vm->_screenWidth;
|
dst += s.pitch;
|
||||||
if (mask)
|
|
||||||
mask += _vm->gdi._numStrips;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NutRenderer::draw2byte(byte *dst, byte *mask, int c, int x, int y, byte color) {
|
void NutRenderer::draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color) {
|
||||||
if (!_loaded) {
|
if (!_loaded) {
|
||||||
debug(2, "NutRenderer::draw2byte() Font is not loaded");
|
debug(2, "NutRenderer::draw2byte() Font is not loaded");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte *dst = (byte *)s.pixels + y * s.pitch + x;
|
||||||
const int width = _vm->_2byteWidth;
|
const int width = _vm->_2byteWidth;
|
||||||
const int height = MIN(_vm->_2byteHeight, _vm->_screenHeight - y);
|
const int height = MIN(_vm->_2byteHeight, s.h - y);
|
||||||
byte *src = _vm->get2byteCharPtr(c);
|
byte *src = _vm->get2byteCharPtr(c);
|
||||||
byte bits = 0;
|
byte bits = 0;
|
||||||
|
|
||||||
byte maskmask;
|
|
||||||
int maskpos;
|
|
||||||
|
|
||||||
if (height <= 0 || width <= 0) {
|
if (height <= 0 || width <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int ty = 0; ty < height; ty++) {
|
for (int ty = 0; ty < height; ty++) {
|
||||||
maskmask = revBitMask[x & 7];
|
|
||||||
maskpos = 0;
|
|
||||||
for (int tx = 0; tx < width; tx++) {
|
for (int tx = 0; tx < width; tx++) {
|
||||||
if ((tx & 7) == 0)
|
if ((tx & 7) == 0)
|
||||||
bits = *src++;
|
bits = *src++;
|
||||||
if (x + tx < 0 || x + tx >= _vm->_screenWidth || y + ty < 0)
|
if (x + tx < 0 || x + tx >= s.w || y + ty < 0)
|
||||||
continue;
|
continue;
|
||||||
if (bits & revBitMask[tx & 7]) {
|
if (bits & revBitMask[tx & 7]) {
|
||||||
dst[tx] = color;
|
dst[tx] = color;
|
||||||
if (mask) {
|
|
||||||
mask[maskpos] |= maskmask;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dst += s.pitch;
|
||||||
maskmask >>= 1;
|
|
||||||
if (maskmask == 0) {
|
|
||||||
maskmask = 0x80;
|
|
||||||
maskpos++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dst += _vm->_screenWidth;
|
|
||||||
if (mask)
|
|
||||||
mask += _vm->gdi._numStrips;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#define NUT_RENDERER_H
|
#define NUT_RENDERER_H
|
||||||
|
|
||||||
#include "common/file.h"
|
#include "common/file.h"
|
||||||
|
#include "graphics/surface.h"
|
||||||
|
|
||||||
namespace Scumm {
|
namespace Scumm {
|
||||||
|
|
||||||
|
@ -43,8 +44,8 @@ protected:
|
||||||
|
|
||||||
int32 decodeCodec44(byte *dst, const byte *src, uint32 length);
|
int32 decodeCodec44(byte *dst, const byte *src, uint32 length);
|
||||||
|
|
||||||
void drawChar(byte *dst, byte *mask, byte c, int x, int y, byte color);
|
void drawChar(const Graphics::Surface &s, byte c, int x, int y, byte color);
|
||||||
void draw2byte(byte *dst, byte *mask, int c, int x, int y, byte color);
|
void draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NutRenderer(ScummEngine *vm);
|
NutRenderer(ScummEngine *vm);
|
||||||
|
@ -54,7 +55,7 @@ public:
|
||||||
bool loadFont(const char *filename);
|
bool loadFont(const char *filename);
|
||||||
|
|
||||||
void drawFrame(byte *dst, int c, int x, int y);
|
void drawFrame(byte *dst, int c, int x, int y);
|
||||||
void drawShadowChar(int c, int x, int y, byte color, bool useMask, bool showShadow);
|
void drawShadowChar(const Graphics::Surface &s, int c, int x, int y, byte color, bool showShadow);
|
||||||
|
|
||||||
int getCharWidth(byte c);
|
int getCharWidth(byte c);
|
||||||
int getCharHeight(byte c);
|
int getCharHeight(byte c);
|
||||||
|
|
|
@ -2652,13 +2652,13 @@ void ScummEngine::initRoomSubBlocks() {
|
||||||
|
|
||||||
// Transparent color
|
// Transparent color
|
||||||
if (_features & GF_OLD_BUNDLE)
|
if (_features & GF_OLD_BUNDLE)
|
||||||
gdi._transparentColor = 255; // TODO - FIXME
|
gdi._transparentColor = 255;
|
||||||
else {
|
else {
|
||||||
ptr = findResourceData(MKID('TRNS'), roomptr);
|
ptr = findResourceData(MKID('TRNS'), roomptr);
|
||||||
if (ptr)
|
if (ptr)
|
||||||
gdi._transparentColor = ptr[0];
|
gdi._transparentColor = ptr[0];
|
||||||
else if (_version == 8)
|
else if (_version == 8)
|
||||||
gdi._transparentColor = 5; // FIXME
|
gdi._transparentColor = 5;
|
||||||
else
|
else
|
||||||
gdi._transparentColor = 255;
|
gdi._transparentColor = 255;
|
||||||
}
|
}
|
||||||
|
|
|
@ -419,8 +419,6 @@ void ScummEngine::drawVerb(int verb, int mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScummEngine::restoreVerbBG(int verb) {
|
void ScummEngine::restoreVerbBG(int verb) {
|
||||||
if (_version >= 7)
|
|
||||||
return;
|
|
||||||
|
|
||||||
VerbSlot *vs;
|
VerbSlot *vs;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue