diff options
-rw-r--r-- | scumm/charset.cpp | 57 | ||||
-rw-r--r-- | scumm/charset.h | 26 | ||||
-rw-r--r-- | scumm/cursor.cpp | 72 | ||||
-rw-r--r-- | scumm/script_v5.cpp | 14 | ||||
-rw-r--r-- | scumm/scumm.h | 2 |
5 files changed, 106 insertions, 65 deletions
diff --git a/scumm/charset.cpp b/scumm/charset.cpp index ac90b4bb5b..da9b4febb9 100644 --- a/scumm/charset.cpp +++ b/scumm/charset.cpp @@ -74,10 +74,10 @@ void CharsetRendererV3::setCurID(byte id) { if (_fontPtr == 0) error("CharsetRendererCommon::setCurID: charset %d not found!", id); - _nbChars = _fontPtr[4]; + _numChars = _fontPtr[4]; _fontPtr += 6; _widthTable = _fontPtr; - _fontPtr += _nbChars; + _fontPtr += _numChars; } // do spacing for variable width old-style font @@ -981,12 +981,12 @@ void CharsetRendererV3::printChar(int chr) { } if (_ignoreCharsetMask || !vs->hasTwoBuffers) { dest_ptr = vs->getPixels(_left, drawTop); + drawBits1(*vs, dest_ptr, char_ptr, drawTop, 8, 8); } else { dest_ptr = (byte *)_vm->gdi._textSurface.pixels + _top * _vm->gdi._textSurface.pitch + _left; + drawBits1(_vm->gdi._textSurface, dest_ptr, char_ptr, drawTop, 8, 8); } - drawBits1(vs, dest_ptr, char_ptr, drawTop, 8, 8); - if (_str.left > _left) _str.left = _left; @@ -1002,6 +1002,14 @@ void CharsetRendererV3::printChar(int chr) { _str.bottom = _top + height; } +void CharsetRendererV3::drawChar(int chr, const Graphics::Surface &s, int x, int y) { + byte *char_ptr, *dest_ptr; + char_ptr = _fontPtr + chr * 8; + dest_ptr = (byte *)s.pixels + y * s.pitch + x; + drawBits1(s, dest_ptr, char_ptr, y, 8, 8); +} + + void CharsetRendererClassic::printChar(int chr) { int width, height, origWidth, origHeight; int offsX, offsY; @@ -1101,15 +1109,15 @@ void CharsetRendererClassic::printChar(int chr) { dst = (byte *)_vm->gdi._textSurface.pixels + (_top - _vm->_screenTop) * _vm->gdi._textSurface.pitch + _left; } - back = dst; if (_blitAlso && vs->hasTwoBuffers) { + back = dst; dst = vs->getBackPixels(_left, drawTop); } if (is2byte) { - drawBits1(vs, dst, charPtr, drawTop, origWidth, origHeight); + drawBits1(*vs, dst, charPtr, drawTop, origWidth, origHeight); } else { - drawBitsN(vs, dst, charPtr, *_fontPtr, drawTop, origWidth, origHeight); + drawBitsN(*vs, dst, charPtr, *_fontPtr, drawTop, origWidth, origHeight); } if (_blitAlso && vs->hasTwoBuffers) { @@ -1143,7 +1151,26 @@ void CharsetRendererClassic::printChar(int chr) { _top -= offsY; } -void CharsetRendererClassic::drawBitsN(VirtScreen *vs, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height) { +void CharsetRendererClassic::drawChar(int chr, const Graphics::Surface &s, int x, int y) { + const byte *charPtr; + byte *dst; + + uint32 charOffs = READ_LE_UINT32(_fontPtr + chr * 4 + 4); + assert(charOffs < 0x10000); + if (!charOffs) + return; + charPtr = _fontPtr + charOffs; + + int width = charPtr[0]; + int height = charPtr[1]; + + charPtr += 4; // Skip over char header + + dst = (byte *)s.pixels + y * s.pitch + x; + drawBitsN(s, dst, charPtr, *_fontPtr, y, width, height); +} + +void CharsetRendererClassic::drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height) { int y, x; int color; byte numbits, bits; @@ -1152,7 +1179,7 @@ void CharsetRendererClassic::drawBitsN(VirtScreen *vs, byte *dst, const byte *sr bits = *src++; numbits = 8; - for (y = 0; y < height && y + drawTop < vs->h; y++) { + for (y = 0; y < height && y + drawTop < s.h; y++) { for (x = 0; x < width; x++) { color = (bits >> (8 - bpp)) & 0xFF; @@ -1167,30 +1194,30 @@ void CharsetRendererClassic::drawBitsN(VirtScreen *vs, byte *dst, const byte *sr numbits = 8; } } - dst += vs->pitch - width; + dst += s.pitch - width; } } -void CharsetRendererCommon::drawBits1(VirtScreen *vs, byte *dst, const byte *src, int drawTop, int width, int height) { +void CharsetRendererCommon::drawBits1(const Graphics::Surface &s, byte *dst, const byte *src, int drawTop, int width, int height) { int y, x; byte bits = 0; - for (y = 0; y < height && y + drawTop < vs->h; y++) { + for (y = 0; y < height && y + drawTop < s.h; y++) { for (x = 0; x < width; x++) { if ((x % 8) == 0) bits = *src++; if ((bits & revBitMask[x % 8]) && y + drawTop >= 0) { if (_dropShadow) { *(dst + 1) = _shadowColor; - *(dst + vs->pitch) = _shadowColor; - *(dst + vs->pitch + 1) = _shadowColor; + *(dst + s.pitch) = _shadowColor; + *(dst + s.pitch + 1) = _shadowColor; } *dst = _color; } dst++; } - dst += vs->pitch - width; + dst += s.pitch - width; } } diff --git a/scumm/charset.h b/scumm/charset.h index 116d4e3dfe..66c506e73c 100644 --- a/scumm/charset.h +++ b/scumm/charset.h @@ -61,8 +61,6 @@ protected: ScummEngine *_vm; byte _curId; - virtual int getCharWidth(byte chr) = 0; - public: CharsetRenderer(ScummEngine *vm); virtual ~CharsetRenderer() {} @@ -71,6 +69,7 @@ public: void clearCharsetMask(); virtual void printChar(int chr) = 0; + virtual void drawChar(int chr, const Graphics::Surface &s, int x, int y) {} int getStringWidth(int a, const byte *str); void addLinebreaks(int a, byte *str, int pos, int maxwidth); @@ -79,6 +78,7 @@ public: int getCurID() { return _curId; } virtual int getFontHeight() = 0; + virtual int getCharWidth(byte chr) = 0; virtual void setColor(byte color) { _color = color; } }; @@ -87,7 +87,7 @@ class CharsetRendererCommon : public CharsetRenderer { protected: byte *_fontPtr; - void drawBits1(VirtScreen *vs, byte *dst, const byte *src, int drawTop, int width, int height); + void drawBits1(const Graphics::Surface &s, byte *dst, const byte *src, int drawTop, int width, int height); public: CharsetRendererCommon(ScummEngine *vm) : CharsetRenderer(vm) {} @@ -99,46 +99,43 @@ public: class CharsetRendererClassic : public CharsetRendererCommon { protected: - int getCharWidth(byte chr); - - void drawBitsN(VirtScreen *vs, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height); + void drawBitsN(const Graphics::Surface &s, byte *dst, const byte *src, byte bpp, int drawTop, int width, int height); public: CharsetRendererClassic(ScummEngine *vm) : CharsetRendererCommon(vm) {} void printChar(int chr); + void drawChar(int chr, const Graphics::Surface &s, int x, int y); + + int getCharWidth(byte chr); }; class CharsetRendererV3 : public CharsetRendererCommon { protected: - int _nbChars; + int _numChars; byte *_widthTable; - int getCharWidth(byte chr); - public: CharsetRendererV3(ScummEngine *vm) : CharsetRendererCommon(vm) {} void printChar(int chr); + void drawChar(int chr, const Graphics::Surface &s, int x, int y); void setCurID(byte id); void setColor(byte color); int getFontHeight() { return 8; } + int getCharWidth(byte chr); }; class CharsetRendererV2 : public CharsetRendererV3 { -protected: - int getCharWidth(byte chr) { return 8; } - public: CharsetRendererV2(ScummEngine *vm, Common::Language language); void setCurID(byte id) {} + int getCharWidth(byte chr) { return 8; } }; class CharsetRendererNut : public CharsetRenderer { protected: - int getCharWidth(byte chr); - NutRenderer *_fr[5]; NutRenderer *_current; @@ -151,6 +148,7 @@ public: void setCurID(byte id); int getFontHeight(); + int getCharWidth(byte chr); }; } // End of namespace Scumm diff --git a/scumm/cursor.cpp b/scumm/cursor.cpp index 63e20c7c66..5a86396f57 100644 --- a/scumm/cursor.cpp +++ b/scumm/cursor.cpp @@ -21,6 +21,7 @@ #include "stdafx.h" #include "scumm/bomp.h" +#include "scumm/charset.h" #include "scumm/intern.h" #include "scumm/object.h" #include "scumm/scumm.h" @@ -41,7 +42,7 @@ static const byte default_cursor_colors[4] = { -static const uint16 default_cursor_images[5][16] = { +static uint16 default_cursor_images[5][16] = { /* cross-hair */ { 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0000, 0x7e3f, 0x0000, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0080, 0x0000 }, @@ -81,13 +82,6 @@ void ScummEngine::animateCursor() { } } -void ScummEngine::setCursor(int cursor) { - if (cursor >= 0 && cursor <= 3) - _currentCursor = cursor; - else - warning("setCursor(%d)", cursor); -} - void ScummEngine::setCursorHotspot(int x, int y) { _cursor.hotspotX = x; _cursor.hotspotY = y; @@ -259,6 +253,48 @@ void ScummEngine_v6::useBompCursor(const byte *im, int width, int height) { updateCursor(); } +void ScummEngine::redefineBuiltinCursorFromChar(int index, int chr) { + // Cursor image in both Looms are based on images from charset. + // For now we don't handle them. + if (_gameId != GID_LOOM && _gameId != GID_LOOM256) { + // FIXME: Actually: is this opcode ever called by a non-Loom game? + // Which V3-V5 game besides Loom makes use of custom cursors, ever? + warning("V3--V5 SO_CURSOR_IMAGE(%d,%d) called - tell Fingolfin where you saw this!", index, chr); + } + +// const int oldID = _charset->getCurID(); + + if (_version == 3) { + _charset->setCurID(0); + } else if (_version >= 4) { + _charset->setCurID(1); + } + + Graphics::Surface s; + byte buf[16*16]; + memset(buf, 123, 16*16); + s.pixels = buf; + s.w = _charset->getCharWidth(chr); + s.h = _charset->getFontHeight(); + s.pitch = s.w; + assert(s.w <= 16 && s.h <= 16); + s.bytesPerPixel = 1; + + _charset->drawChar(chr, s, 0, 0); + + uint16 *ptr = default_cursor_images[index]; + memset(ptr, 0, 16 * sizeof(uint16)); + for (int h = 0; h < s.h; h++) { + for (int w = 0; w < s.w; w++) { + if (buf[s.pitch * h + w] != 123) + *ptr |= 1 << (16 - w); + } + ptr++; + } + +// _charset->setCurID(oldID); +} + void ScummEngine::setBuiltinCursor(int idx) { int i, j; byte color; @@ -270,25 +306,7 @@ void ScummEngine::setBuiltinCursor(int idx) { else color = default_cursor_colors[idx]; - // FIXME: None of the stock cursors are right for Loom. Why is that? - // Fingolfing says: because it sets different cursor shapes -- - // check the SO_CURSOR_IMAGE opcode in script_v5.cpp; if we implement - // that, this problem should be gone... - - if (_gameId == GID_LOOM || _gameId == GID_LOOM256) { - int w = 0; - - _cursor.width = 8; - _cursor.height = 8; - _cursor.hotspotX = 0; - _cursor.hotspotY = 0; - - for (i = 0; i < 8; i++) { - w += (i >= 6) ? -2 : 1; - for (j = 0; j < w; j++) - _grabbedCursor[i * 8 + j] = color; - } - } else if (_version <= 2) { + if (_version <= 2) { _cursor.width = 23; _cursor.height = 21; _cursor.hotspotX = 11; diff --git a/scumm/script_v5.cpp b/scumm/script_v5.cpp index 41dcd6beab..f16df1a04c 100644 --- a/scumm/script_v5.cpp +++ b/scumm/script_v5.cpp @@ -677,13 +677,7 @@ void ScummEngine_v5::o5_cursorCommand() { case 10: // SO_CURSOR_IMAGE i = getVarOrDirectByte(PARAM_1); // Cursor number j = getVarOrDirectByte(PARAM_2); // Charset letter to use - // Cursor image in both Looms are based on images from charset. - // For now we don't handle them. - if (_gameId != GID_LOOM && _gameId != GID_LOOM256) { - // FIXME: Actually: is this opcode ever called by a non-Loom game? - // Which V3-V5 game besides Loom makes use of custom cursors, ever? - warning("V3--V5 SO_CURSOR_IMAGE(%d,%d) called - tell Fingolfin where you saw this!", i, j); - } + redefineBuiltinCursorFromChar(i, j); break; case 11: // SO_CURSOR_HOTSPOT i = getVarOrDirectByte(PARAM_1); @@ -692,7 +686,11 @@ void ScummEngine_v5::o5_cursorCommand() { setCursorHotspot(j, k); break; case 12: // SO_CURSOR_SET - setCursor(getVarOrDirectByte(PARAM_1)); + i = getVarOrDirectByte(PARAM_1); + if (i >= 0 && i <= 3) + _currentCursor = i; + else + error("SO_CURSOR_SET: unsupported cursor id %d", i); break; case 13: // SO_CHARSET_SET initCharset(getVarOrDirectByte(PARAM_1)); diff --git a/scumm/scumm.h b/scumm/scumm.h index aba9be3aad..5f71c9f2e8 100644 --- a/scumm/scumm.h +++ b/scumm/scumm.h @@ -936,12 +936,12 @@ protected: void darkenPalette(int redScale, int greenScale, int blueScale, int startColor, int endColor); void desaturatePalette(int hueScale, int satScale, int lightScale, int startColor, int endColor); - void setCursor(int cursor); void setCursorHotspot(int x, int y); void setCursorTransparency(int a); void setupCursor(); void setBuiltinCursor(int index); + void redefineBuiltinCursorFromChar(int index, int chr); void grabCursor(int x, int y, int w, int h); void setCursorFromBuffer(byte *ptr, int width, int height, int pitch); |