mirror of
https://github.com/libretro/scummvm.git
synced 2025-05-14 01:55:55 +00:00

touches a lot of the code, of course, and adds yet another global variable (temporarily, I hope), but everything still seems to work. Knock on wood. svn-id: r10806
283 lines
6.9 KiB
C++
283 lines
6.9 KiB
C++
/* Copyright (C) 1994-2003 Revolution Software Ltd
|
|
*
|
|
* 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.
|
|
*
|
|
* 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* $Header$
|
|
*/
|
|
|
|
#include "stdafx.h"
|
|
#include "bs2/driver/driver96.h"
|
|
#include "bs2/driver/d_draw.h"
|
|
#include "bs2/driver/render.h"
|
|
#include "bs2/driver/menu.h"
|
|
#include "bs2/sword2.h"
|
|
|
|
namespace Sword2 {
|
|
|
|
#define MAX_MOUSE_EVENTS 16
|
|
#define MOUSEFLASHFRAME 6
|
|
|
|
static uint8 mouseBacklog = 0;
|
|
static uint8 mouseLogPos = 0;
|
|
static _mouseEvent mouseLog[MAX_MOUSE_EVENTS];
|
|
|
|
void Display::resetRenderEngine(void) {
|
|
_parallaxScrollX = 0;
|
|
_parallaxScrollY = 0;
|
|
_scrollX = 0;
|
|
_scrollY = 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// Logs the mouse button event passed in buttons. The button events are
|
|
// defined as RD_LEFTBUTTONDOWN, RD_LEFTBUTTONUP, RD_RIGHTBUTTONDOWN and
|
|
// RD_RIGHTBUTTONUP.
|
|
// --------------------------------------------------------------------------
|
|
|
|
void LogMouseEvent(uint16 buttons) {
|
|
_mouseEvent *me;
|
|
|
|
// We need to leave the one, which is the current event, alone!
|
|
if (mouseBacklog == MAX_MOUSE_EVENTS - 1)
|
|
return;
|
|
|
|
me = &mouseLog[(mouseBacklog + mouseLogPos) % MAX_MOUSE_EVENTS];
|
|
me->buttons = buttons;
|
|
mouseBacklog++;
|
|
}
|
|
|
|
// FIXME: The original code used 0 for transparency, while our backend uses
|
|
// 0xFF. That means that parts of the mouse cursor that weren't meant to be
|
|
// transparent may be now.
|
|
|
|
void Display::decompressMouse(uint8 *decomp, uint8 *comp, int width, int height, int pitch, int xOff, int yOff) {
|
|
int32 size = width * height;
|
|
int32 i = 0;
|
|
int x = 0;
|
|
int y = 0;
|
|
|
|
while (i < size) {
|
|
if (*comp > 183) {
|
|
decomp[(y + yOff) * pitch + x + xOff] = *comp++;
|
|
if (++x >= width) {
|
|
x = 0;
|
|
y++;
|
|
}
|
|
i++;
|
|
} else {
|
|
x += *comp;
|
|
while (x >= width) {
|
|
y++;
|
|
x -= width;
|
|
}
|
|
i += *comp++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Display::drawMouse(void) {
|
|
if (!_mouseAnim && !_luggageAnim)
|
|
return;
|
|
|
|
// When an object is used in the game, the mouse cursor should be a
|
|
// combination of a standard mouse cursor and a luggage cursor.
|
|
//
|
|
// However, judging by the original code luggage cursors can also
|
|
// appear on their own. I have no idea which cases though.
|
|
|
|
uint16 mouse_width = 0;
|
|
uint16 mouse_height = 0;
|
|
uint16 hotspot_x = 0;
|
|
uint16 hotspot_y = 0;
|
|
int deltaX = 0;
|
|
int deltaY = 0;
|
|
|
|
if (_mouseAnim) {
|
|
hotspot_x = _mouseAnim->xHotSpot;
|
|
hotspot_y = _mouseAnim->yHotSpot;
|
|
mouse_width = _mouseAnim->mousew;
|
|
mouse_height = _mouseAnim->mouseh;
|
|
}
|
|
|
|
if (_luggageAnim) {
|
|
if (!_mouseAnim) {
|
|
hotspot_x = _luggageAnim->xHotSpot;
|
|
hotspot_y = _luggageAnim->yHotSpot;
|
|
}
|
|
if (_luggageAnim->mousew > mouse_width)
|
|
mouse_width = _luggageAnim->mousew;
|
|
if (_luggageAnim->mouseh > mouse_height)
|
|
mouse_height = _luggageAnim->mouseh;
|
|
}
|
|
|
|
if (_mouseAnim && _luggageAnim) {
|
|
deltaX = _mouseAnim->xHotSpot - _luggageAnim->xHotSpot;
|
|
deltaY = _mouseAnim->yHotSpot - _luggageAnim->yHotSpot;
|
|
}
|
|
|
|
assert(deltaX >= 0);
|
|
assert(deltaY >= 0);
|
|
|
|
// HACK for maximum cursor size. (The SDL backend imposes this
|
|
// restriction)
|
|
|
|
if (mouse_width + deltaX > MAX_MOUSE_W)
|
|
deltaX = 80 - mouse_width;
|
|
if (mouse_height + deltaY > MAX_MOUSE_H)
|
|
deltaY = 80 - mouse_height;
|
|
|
|
mouse_width += deltaX;
|
|
mouse_height += deltaY;
|
|
|
|
if ((uint32) (mouse_width * mouse_height) > sizeof(_mouseData)) {
|
|
warning("Mouse cursor too large");
|
|
return;
|
|
}
|
|
|
|
memset(_mouseData, 0xFF, mouse_width * mouse_height);
|
|
|
|
if (_luggageAnim)
|
|
decompressMouse(_mouseData, (uint8 *) _luggageAnim + READ_LE_UINT32(_luggageOffset), _luggageAnim->mousew,
|
|
_luggageAnim->mouseh, mouse_width, deltaX, deltaY);
|
|
|
|
if (_mouseAnim)
|
|
decompressMouse(_mouseData, _mouseSprite, _mouseAnim->mousew, _mouseAnim->mouseh, mouse_width);
|
|
|
|
g_system->set_mouse_cursor(_mouseData, mouse_width, mouse_height, hotspot_x, hotspot_y);
|
|
}
|
|
|
|
/**
|
|
* Get the next pending mouse event.
|
|
* @return a pointer to the mouse event, or NULL of there is none
|
|
*/
|
|
|
|
_mouseEvent *MouseEvent(void) {
|
|
_mouseEvent *me;
|
|
|
|
if (mouseBacklog) {
|
|
me = &mouseLog[mouseLogPos];
|
|
if (++mouseLogPos == MAX_MOUSE_EVENTS)
|
|
mouseLogPos = 0;
|
|
|
|
mouseBacklog--;
|
|
return me;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
uint8 CheckForMouseEvents(void) {
|
|
return mouseBacklog; // return the number of mouse events waiting
|
|
}
|
|
|
|
/**
|
|
* Animates the current mouse pointer
|
|
*/
|
|
|
|
int32 Display::animateMouse(void) {
|
|
uint8 prevMouseFrame = _mouseFrame;
|
|
|
|
if (!_mouseAnim)
|
|
return RDERR_UNKNOWN;
|
|
|
|
if (++_mouseFrame == _mouseAnim->noAnimFrames)
|
|
_mouseFrame = MOUSEFLASHFRAME;
|
|
|
|
_mouseSprite = (uint8 *) _mouseAnim + READ_LE_UINT32(_mouseOffsets + _mouseFrame);
|
|
|
|
if (_mouseFrame != prevMouseFrame)
|
|
drawMouse();
|
|
|
|
return RD_OK;
|
|
}
|
|
|
|
/**
|
|
* Sets the mouse cursor animation.
|
|
* @param ma a pointer to the animation data, or NULL to clear the current one
|
|
* @param size the size of the mouse animation data
|
|
* @param mouseFlash RDMOUSE_FLASH or RDMOUSE_NOFLASH, depending on whether
|
|
* or not there is a lead-in animation
|
|
*/
|
|
|
|
int32 Display::setMouseAnim(uint8 *ma, int32 size, int32 mouseFlash) {
|
|
if (_mouseAnim) {
|
|
free(_mouseAnim);
|
|
_mouseAnim = NULL;
|
|
}
|
|
|
|
if (ma) {
|
|
if (mouseFlash == RDMOUSE_FLASH)
|
|
_mouseFrame = 0;
|
|
else
|
|
_mouseFrame = MOUSEFLASHFRAME;
|
|
|
|
_mouseAnim = (struct _mouseAnim *) malloc(size);
|
|
if (!_mouseAnim)
|
|
return RDERR_OUTOFMEMORY;
|
|
|
|
memcpy((uint8 *) _mouseAnim, ma, size);
|
|
_mouseOffsets = (int32 *) ((uint8 *) _mouseAnim + sizeof(struct _mouseAnim));
|
|
|
|
animateMouse();
|
|
drawMouse();
|
|
|
|
g_system->show_mouse(true);
|
|
} else {
|
|
if (_luggageAnim)
|
|
drawMouse();
|
|
else
|
|
g_system->show_mouse(false);
|
|
}
|
|
|
|
return RD_OK;
|
|
}
|
|
|
|
/**
|
|
* Sets the "luggage" animation to accompany the mouse animation. Luggage
|
|
* sprites are of the same format as mouse sprites.
|
|
* @param ma a pointer to the animation data, or NULL to clear the current one
|
|
* @param size the size of the animation data
|
|
*/
|
|
|
|
int32 Display::setLuggageAnim(uint8 *ma, int32 size) {
|
|
if (_luggageAnim) {
|
|
free(_luggageAnim);
|
|
_luggageAnim = NULL;
|
|
}
|
|
|
|
if (ma) {
|
|
_luggageAnim = (struct _mouseAnim *) malloc(size);
|
|
if (!_luggageAnim)
|
|
return RDERR_OUTOFMEMORY;
|
|
|
|
memcpy((uint8 *) _luggageAnim, ma, size);
|
|
_luggageOffset = (int32 *) ((uint8 *) _luggageAnim + sizeof(struct _mouseAnim));
|
|
|
|
animateMouse();
|
|
drawMouse();
|
|
|
|
g_system->show_mouse(true);
|
|
} else {
|
|
if (_mouseAnim)
|
|
drawMouse();
|
|
else
|
|
g_system->show_mouse(false);
|
|
}
|
|
|
|
return RD_OK;
|
|
}
|
|
|
|
} // End of namespace Sword2
|