Corrected cursor display errors introduced by revision 41204, reimplemented 16-bit cursor support in a less hacky, but still temporary way.

svn-id: r41209
This commit is contained in:
Jody Northup 2009-06-06 01:16:04 +00:00
parent 8ff3a568fa
commit 56e5920bba
8 changed files with 127 additions and 178 deletions

View File

@ -1404,49 +1404,19 @@ void OSystem_SDL::warpMouse(int x, int y) {
}
#ifdef ENABLE_16BIT
void OSystem_SDL::setMouseCursor16(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint16 keycolor, int cursorTargetScale) {
if (w == 0 || h == 0)
return;
_mouseCurState.hotX = hotspot_x;
_mouseCurState.hotY = hotspot_y;
_mouseKeyColor = keycolor;
_cursorTargetScale = cursorTargetScale;
if (_mouseCurState.w != (int)w || _mouseCurState.h != (int)h) {
_mouseCurState.w = w;
_mouseCurState.h = h;
if (_mouseOrigSurface)
SDL_FreeSurface(_mouseOrigSurface);
// Allocate bigger surface because AdvMame2x adds black pixel at [0,0]
_mouseOrigSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
_mouseCurState.w + 2,
_mouseCurState.h + 2,
16,
_hwscreen->format->Rmask,
_hwscreen->format->Gmask,
_hwscreen->format->Bmask,
_hwscreen->format->Amask);
if (_mouseOrigSurface == NULL)
error("allocating _mouseOrigSurface failed");
SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey);
void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, uint8 bitDepth) {
uint32 colmask = 0xFF;
uint8 byteDepth = bitDepth >> 3;
for (int i = byteDepth; i > 1; i--) {
colmask <<= 8;
colmask |= 0xFF;
}
keycolor &= colmask;
free(_mouseData);
_mouseData = (byte *)malloc(w * h * 2);
memcpy(_mouseData, buf, w * h * 2);
blitCursor();
}
#else
void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale) {
#endif
void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale) {
if (w == 0 || h == 0)
return;
@ -1480,14 +1450,24 @@ void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x,
}
free(_mouseData);
#ifdef ENABLE_16BIT
_mouseData = (byte *)malloc(w * h * byteDepth);
memcpy(_mouseData, buf, w * h * byteDepth);
blitCursor(bitDepth);
#else
_mouseData = (byte *)malloc(w * h);
memcpy(_mouseData, buf, w * h);
blitCursor();
#endif
}
#ifdef ENABLE_16BIT
void OSystem_SDL::blitCursor(uint8 bitDepth) {
#else
void OSystem_SDL::blitCursor() {
#endif
byte *dstPtr;
const byte *srcPtr = _mouseData;
byte color;
@ -1526,22 +1506,26 @@ void OSystem_SDL::blitCursor() {
for (j = 0; j < w; j++) {
color = *srcPtr;
#ifdef ENABLE_16BIT
if (color != _mouseKeyColor) { // transparent, don't draw
int8 r = ((*(uint16 *)srcPtr >> 10) & 0x1F) << 3;
int8 g = ((*(uint16 *)srcPtr >> 5) & 0x1F) << 3;
int8 b = (*(uint16 *)srcPtr & 0x1F) << 3;
*(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,
r, g, b);
if (bitDepth == 16) {
if (color != _mouseKeyColor) { // transparent, don't draw
int8 r = ((*(uint16 *)srcPtr >> 10) & 0x1F) << 3;
int8 g = ((*(uint16 *)srcPtr >> 5) & 0x1F) << 3;
int8 b = (*(uint16 *)srcPtr & 0x1F) << 3;
*(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,
r, g, b);
}
dstPtr += 2;
srcPtr += 2;
} else {
#endif
if (color != _mouseKeyColor) { // transparent, don't draw
*(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,
palette[color].r, palette[color].g, palette[color].b);
}
dstPtr += 2;
srcPtr++;
#ifdef ENABLE_16BIT
}
dstPtr += 2;
srcPtr += 2;
#else
if (color != _mouseKeyColor) { // transparent, don't draw
*(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,
palette[color].r, palette[color].g, palette[color].b);
}
dstPtr += 2;
srcPtr++;
#endif
}
dstPtr += _mouseOrigSurface->pitch - w * 2;

View File

@ -113,10 +113,10 @@ public:
// Set the bitmap that's used when drawing the cursor.
#ifdef ENABLE_16BIT
//HACK Made a second method as a quick and dirty workaround to avoid linker errors with engine libs
virtual void setMouseCursor16(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint16 keycolor, int cursorTargetScale); // overloaded by CE backend (FIXME)
#endif
virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, uint8 bitDepth = 8); // overloaded by CE backend (FIXME)
#else
virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale); // overloaded by CE backend (FIXME)
#endif
// Set colors of cursor palette
void setCursorPalette(const byte *colors, uint start, uint num);
@ -413,7 +413,11 @@ protected:
virtual void drawMouse(); // overloaded by CE backend
virtual void undrawMouse(); // overloaded by CE backend (FIXME)
#ifdef ENABLE_16BIT
virtual void blitCursor(uint8 bitDepth = 8); // overloaded by CE backend (FIXME)
#else
virtual void blitCursor(); // overloaded by CE backend (FIXME)
#endif
/** Set the position of the virtual mouse cursor. */
void setMousePos(int x, int y);

View File

@ -688,10 +688,10 @@ public:
* @param cursorTargetScale scale factor which cursor is designed for
*/
#ifdef ENABLE_16BIT
//HACK made a second method as a quick and dirty workaround to avoid linker errors with engine libs
virtual void setMouseCursor16(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint16 keycolor = 65535, int cursorTargetScale = 1) = 0;
#endif
virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int cursorTargetScale = 1, uint8 bitDepth = 8) = 0;
#else
virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int cursorTargetScale = 1) = 0;
#endif
/**

View File

@ -116,10 +116,11 @@ void ScummEngine::updateCursor() {
//HACK Had to make a second method to avoid many, many linker errors from other engines
//this requires ENABLE_16BIT to be defined in the Scumm project, again, because I #ifdef'ed
//the method's definition and declaration in cursorman.h
CursorMan.replaceCursor16(_grabbedCursor, _cursor.width, _cursor.height,
CursorMan.replaceCursorReal(_grabbedCursor, _cursor.width, _cursor.height,
_cursor.hotspotX, _cursor.hotspotY,
(_game.platform == Common::kPlatformNES ? _grabbedCursor[63] : transColor),
(_game.heversion == 70 ? 2 : 1));
(_game.heversion == 70 ? 2 : 1),
16);
} else {
CursorMan.replaceCursor(_grabbedCursor, _cursor.width, _cursor.height,
_cursor.hotspotX, _cursor.hotspotY,

View File

@ -56,42 +56,34 @@ bool CursorManager::showMouse(bool visible) {
// Should work, even if there's just a dummy cursor on the stack.
return g_system->showMouse(visible);
}
#ifdef ENABLE_16BIT
void CursorManager::pushCursor16(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint16 keycolor, int targetScale) {
Cursor16 *cur = new Cursor16(buf, w, h, hotspotX, hotspotY, keycolor, targetScale);
cur->_visible = isVisible();
_cursor16Stack.push(cur);
if (buf) {
g_system->setMouseCursor16(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale);
}
}
void CursorManager::popCursor16() {
if (_cursor16Stack.empty())
return;
Cursor16 *cur = _cursor16Stack.pop();
delete cur;
if (!_cursorStack.empty()) {
cur = _cursor16Stack.top();
g_system->setMouseCursor16(cur->_data, cur->_width, cur->_height, cur->_hotspotX, cur->_hotspotY, cur->_keycolor, cur->_targetScale);
}
g_system->showMouse(isVisible());
}
#endif
void CursorManager::pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetScale) {
#ifdef ENABLE_16BIT
pushCursorReal(buf,w,h,hotspotX,hotspotY,keycolor,targetScale,8);
}
void CursorManager::pushCursorReal(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int targetScale, uint8 bitDepth) {
uint32 colmask = 0xFF;
uint8 byteDepth = bitDepth >> 3;
for (int i = byteDepth; i > 1; i--) {
colmask <<= 8;
colmask |= 0xFF;
}
keycolor &= colmask;
Cursor *cur = new Cursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale, bitDepth);
#else
Cursor *cur = new Cursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale);
#endif
cur->_visible = isVisible();
_cursorStack.push(cur);
if (buf) {
#ifdef ENABLE_16BIT
g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale, bitDepth);
#else
g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale);
#endif
}
}
@ -104,7 +96,11 @@ void CursorManager::popCursor() {
if (!_cursorStack.empty()) {
cur = _cursorStack.top();
#ifdef ENABLE_16BIT
g_system->setMouseCursor(cur->_data, cur->_width, cur->_height, cur->_hotspotX, cur->_hotspotY, cur->_keycolor, cur->_targetScale, cur->_bitDepth);
#else
g_system->setMouseCursor(cur->_data, cur->_width, cur->_height, cur->_hotspotX, cur->_hotspotY, cur->_keycolor, cur->_targetScale);
#endif
}
g_system->showMouse(isVisible());
@ -127,48 +123,38 @@ void CursorManager::popAllCursors() {
g_system->showMouse(isVisible());
}
void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetScale) {
#ifdef ENABLE_16BIT
//HACK Made a separate method to avoid massive linker errors on every engine
void CursorManager::replaceCursor16(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint16 keycolor, int targetScale) {
replaceCursorReal(buf,w,h,hotspotX,hotspotY,keycolor,targetScale);
}
void CursorManager::replaceCursorReal(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int targetScale, uint8 bitDepth) {
uint32 colmask = 0xFF;
uint8 byteDepth = bitDepth >> 3;
for (int i = byteDepth; i > 1; i--) {
colmask <<= 8;
colmask |= 0xFF;
}
keycolor &= colmask;
#endif
if (_cursorStack.empty()) {
pushCursor16(buf, w, h, hotspotX, hotspotY, keycolor, targetScale);
#ifdef ENABLE_16BIT
pushCursorReal(buf, w, h, hotspotX, hotspotY, keycolor, targetScale, bitDepth);
#else
pushCursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale);
#endif
return;
}
Cursor *cur = _cursorStack.top();
uint size = w * h * 2;
if (cur->_size < size) {
delete[] cur->_data;
cur->_data = new byte[size];
cur->_size = size;
}
if (buf && cur->_data)
memcpy(cur->_data, buf, size);
cur->_width = w;
cur->_height = h;
cur->_hotspotX = hotspotX;
cur->_hotspotY = hotspotY;
cur->_keycolor = keycolor;
cur->_targetScale = targetScale;
g_system->setMouseCursor16(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale);
}
#ifdef ENABLE_16BIT
uint size = w * h * (bitDepth >> 3);
#else
uint size = w * h;
#endif
void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetScale) {
if (_cursorStack.empty()) {
pushCursor(buf, w, h, hotspotX, hotspotY, keycolor, targetScale);
return;
}
Cursor *cur = _cursorStack.top();
uint size = w * h;
if (cur->_size < size) {
delete[] cur->_data;
cur->_data = new byte[size];
@ -185,7 +171,11 @@ void CursorManager::replaceCursor(const byte *buf, uint w, uint h, int hotspotX,
cur->_keycolor = keycolor;
cur->_targetScale = targetScale;
#ifdef ENABLE_16BIT
g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale, bitDepth);
#else
g_system->setMouseCursor(cur->_data, w, h, hotspotX, hotspotY, keycolor, targetScale);
#endif
}
void CursorManager::disableCursorPalette(bool disable) {

View File

@ -57,6 +57,9 @@ public:
* cursor will be added to the stack, but not to the backend.
*/
void pushCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int targetScale = 1);
#ifdef ENABLE_16BIT
void pushCursorReal(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int targetScale = 1, uint8 bitDepth = 8);
#endif
/**
* Pop a cursor from the stack, and restore the previous one to the
@ -64,13 +67,6 @@ public:
*/
void popCursor();
#ifdef ENABLE_16BIT
//HACK This is such a incredible hack
//I really need to make the one method
//work under multiple bitdepths
void pushCursor16(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint16 keycolor = 65535, int targetScale = 1);
void popCursor16();
#endif
/**
* Replace the current cursor on the stack. If the stack is empty, the
* cursor is pushed instead. It's a slightly more optimized way of
@ -84,11 +80,11 @@ public:
* @param keycolor the index for the transparent color
* @param targetScale the scale for which the cursor is designed
*/
void replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int targetScale = 1);
#ifdef ENABLE_16BIT
//HACK made a separate method to avoid massive linker errors on every engine.
void replaceCursor16(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint16 keycolor = 65535, int targetScale = 1);
void replaceCursorReal(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int targetScale = 1, uint8 bitDepth = 8);
#endif
void replaceCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int targetScale = 1);
/**
* Pop all of the cursors and cursor palettes from their respective stacks.
@ -144,37 +140,7 @@ public:
private:
friend class Common::Singleton<SingletonBaseType>;
CursorManager();
#ifdef ENABLE_16BIT
struct Cursor16 {
byte *_data;
bool _visible;
uint _width;
uint _height;
int _hotspotX;
int _hotspotY;
uint16 _keycolor;
byte _targetScale;
uint _size;
Cursor16(const byte *data, uint w, uint h, int hotspotX, int hotspotY, uint16 keycolor = 65535, int targetScale = 1) {
_size = w * h * 2;
_data = new byte[_size];
if (data && _data)
memcpy(_data, data, _size);
_width = w;
_height = h;
_hotspotX = hotspotX;
_hotspotY = hotspotY;
_keycolor = keycolor;
_targetScale = targetScale;
}
~Cursor16() {
delete[] _data;
}
};
#endif
struct Cursor {
byte *_data;
bool _visible;
@ -182,13 +148,33 @@ private:
uint _height;
int _hotspotX;
int _hotspotY;
#ifdef ENABLE_16BIT
uint32 _keycolor;
uint8 _bitDepth;
#else
byte _keycolor;
#endif
byte _targetScale;
uint _size;
uint _size;
#ifdef ENABLE_16BIT
Cursor(const byte *data, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor = 0xFFFFFFFF, int targetScale = 1, uint8 bitDepth = 8) {
uint32 colmask = 0xFF;
uint8 byteDepth = bitDepth >> 3;
_size = w * h * byteDepth;
_bitDepth = bitDepth;
for (int i = byteDepth; i > 1; i--) {
colmask <<= 8;
colmask |= 0xFF;
}
_keycolor = keycolor & colmask;
#else
Cursor(const byte *data, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int targetScale = 1) {
_size = w * h;
_keycolor = keycolor;
#endif
_data = new byte[_size];
if (data && _data)
memcpy(_data, data, _size);
@ -196,7 +182,6 @@ private:
_height = h;
_hotspotX = hotspotX;
_hotspotY = hotspotY;
_keycolor = keycolor;
_targetScale = targetScale;
}
@ -234,9 +219,6 @@ private:
};
Common::Stack<Cursor *> _cursorStack;
#ifdef ENABLE_16BIT
Common::Stack<Cursor16 *> _cursor16Stack;
#endif
Common::Stack<Palette *> _cursorPaletteStack;
};

View File

@ -135,12 +135,8 @@ bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx)
delete _theme;
if (_useStdCursor) {
#ifdef ENABLE_16BIT
CursorMan.popCursor16();
#else
CursorMan.popCursorPalette();
CursorMan.popCursor();
#endif
}
//
@ -386,12 +382,8 @@ void GuiManager::saveState() {
void GuiManager::restoreState() {
if (_useStdCursor) {
#ifdef ENABLE_16BIT
CursorMan.popCursor16();
#else
CursorMan.popCursor();
CursorMan.popCursorPalette();
#endif
}
_system->updateScreen();

View File

@ -462,12 +462,8 @@ void ThemeEngine::disable() {
_system->hideOverlay();
if (_useCursor) {
#ifdef ENABLE_16BIT
CursorMan.popCursor16();
#else
CursorMan.popCursorPalette();
CursorMan.popCursor();
#endif
}
_enabled = false;