mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 13:50:13 +00:00
SCI32: Implement SCI32 cursor support
This commit is contained in:
parent
9bfeb3c297
commit
80d9182554
@ -421,6 +421,8 @@ reg_t kStubNull(EngineState *s, int argc, reg_t *argv);
|
||||
|
||||
#ifdef ENABLE_SCI32
|
||||
// SCI2 Kernel Functions
|
||||
reg_t kSetCursor32(EngineState *s, int argc, reg_t *argv);
|
||||
|
||||
reg_t kDoAudio32(EngineState *s, int argc, reg_t *argv);
|
||||
reg_t kDoAudioInit(EngineState *s, int argc, reg_t *argv);
|
||||
reg_t kDoAudioWaitForPlay(EngineState *s, int argc, reg_t *argv);
|
||||
|
@ -693,10 +693,11 @@ static SciKernelMapEntry s_kernelMap[] = {
|
||||
{ MAP_CALL(Said), SIG_EVERYWHERE, "[r0]", NULL, NULL },
|
||||
{ MAP_CALL(SaveGame), SIG_EVERYWHERE, "[r0]i[r0](r0)", NULL, NULL },
|
||||
{ MAP_CALL(ScriptID), SIG_EVERYWHERE, "[io](i)", NULL, NULL },
|
||||
{ MAP_CALL(SetCursor), SIG_SINCE_SCI21, SIGFOR_ALL, "i(i)([io])(i*)", NULL, NULL },
|
||||
// TODO: SCI2.1 may supply an object optionally (mother goose sci21 right on startup) - find out why
|
||||
{ MAP_CALL(SetCursor), SIG_SCI11, SIGFOR_ALL, "i(i)(i)(i)(iiiiii)", NULL, NULL },
|
||||
{ MAP_CALL(SetCursor), SIG_EVERYWHERE, "i(i)(i)(i)(i)", NULL, kSetCursor_workarounds },
|
||||
{ MAP_CALL(SetCursor), SIG_SCI16, SIGFOR_ALL, "i(i)(i)(i)(i)", NULL, kSetCursor_workarounds },
|
||||
#ifdef ENABLE_SCI32
|
||||
{ "SetCursor", kSetCursor32, SIG_SCI32, SIGFOR_ALL, "i(i)(i)(i)", NULL, kSetCursor_workarounds },
|
||||
#endif
|
||||
{ MAP_CALL(SetDebug), SIG_EVERYWHERE, "(i*)", NULL, NULL },
|
||||
{ MAP_CALL(SetJump), SIG_EVERYWHERE, "oiii", NULL, NULL },
|
||||
{ MAP_CALL(SetMenu), SIG_EVERYWHERE, "i(.*)", NULL, NULL },
|
||||
|
@ -86,11 +86,14 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
|
||||
#ifdef ENABLE_SCI32
|
||||
if (getSciVersion() >= SCI_VERSION_2)
|
||||
mousePos = curEvent.mousePosSci;
|
||||
else
|
||||
else {
|
||||
#endif
|
||||
mousePos = curEvent.mousePos;
|
||||
// Limit the mouse cursor position, if necessary
|
||||
g_sci->_gfxCursor->refreshPosition();
|
||||
// Limit the mouse cursor position, if necessary
|
||||
g_sci->_gfxCursor->refreshPosition();
|
||||
#ifdef ENABLE_SCI32
|
||||
}
|
||||
#endif
|
||||
|
||||
if (g_sci->getVocabulary())
|
||||
g_sci->getVocabulary()->parser_event = NULL_REG; // Invalidate parser event
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include "sci/graphics/compare.h"
|
||||
#include "sci/graphics/controls16.h"
|
||||
#include "sci/graphics/coordadjuster.h"
|
||||
#include "sci/graphics/cursor.h"
|
||||
#include "sci/graphics/palette.h"
|
||||
#include "sci/graphics/paint16.h"
|
||||
#include "sci/graphics/picture.h"
|
||||
@ -48,6 +47,7 @@
|
||||
#include "sci/graphics/text16.h"
|
||||
#include "sci/graphics/view.h"
|
||||
#ifdef ENABLE_SCI32
|
||||
#include "sci/graphics/cursor32.h"
|
||||
#include "sci/graphics/celobj32.h"
|
||||
#include "sci/graphics/controls32.h"
|
||||
#include "sci/graphics/font.h" // TODO: remove once kBitmap is moved in a separate class
|
||||
@ -64,6 +64,44 @@ namespace Sci {
|
||||
|
||||
extern void showScummVMDialog(const Common::String &message);
|
||||
|
||||
reg_t kSetCursor32(EngineState *s, int argc, reg_t *argv) {
|
||||
switch (argc) {
|
||||
case 1: {
|
||||
if (argv[0].toSint16() == -2) {
|
||||
g_sci->_gfxCursor32->clearRestrictedArea();
|
||||
} else {
|
||||
if (argv[0].isNull()) {
|
||||
g_sci->_gfxCursor32->hide();
|
||||
} else {
|
||||
g_sci->_gfxCursor32->show();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
const Common::Point position(argv[0].toSint16(), argv[1].toSint16());
|
||||
g_sci->_gfxCursor32->setPosition(position);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
g_sci->_gfxCursor32->setView(argv[0].toUint16(), argv[1].toSint16(), argv[2].toSint16());
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
const Common::Rect restrictRect(argv[0].toSint16(),
|
||||
argv[1].toSint16(),
|
||||
argv[2].toSint16() + 1,
|
||||
argv[3].toSint16() + 1);
|
||||
g_sci->_gfxCursor32->setRestrictedArea(restrictRect);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
error("kSetCursor: Invalid number of arguments (%d)", argc);
|
||||
}
|
||||
|
||||
return s->r_acc;
|
||||
}
|
||||
|
||||
reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv) {
|
||||
const Buffer &buffer = g_sci->_gfxFrameout->getCurrentBuffer();
|
||||
if (buffer.screenWidth < 640 || buffer.screenHeight < 400)
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "sci/sound/music.h"
|
||||
|
||||
#ifdef ENABLE_SCI32
|
||||
#include "sci/graphics/cursor32.h"
|
||||
#include "sci/graphics/frameout.h"
|
||||
#include "sci/graphics/palette32.h"
|
||||
#include "sci/graphics/remap32.h"
|
||||
@ -889,6 +890,29 @@ void GfxRemap32::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
_needsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GfxCursor32::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
if (s.getVersion() < 37) {
|
||||
return;
|
||||
}
|
||||
|
||||
s.syncAsSint32LE(_hideCount);
|
||||
s.syncAsSint16LE(_restrictedArea.left);
|
||||
s.syncAsSint16LE(_restrictedArea.top);
|
||||
s.syncAsSint16LE(_restrictedArea.right);
|
||||
s.syncAsSint16LE(_restrictedArea.bottom);
|
||||
s.syncAsUint16LE(_cursorInfo.resourceId);
|
||||
s.syncAsUint16LE(_cursorInfo.loopNo);
|
||||
s.syncAsUint16LE(_cursorInfo.celNo);
|
||||
|
||||
if (s.isLoading()) {
|
||||
hide();
|
||||
setView(_cursorInfo.resourceId, _cursorInfo.loopNo, _cursorInfo.celNo);
|
||||
if (!_hideCount) {
|
||||
show();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void GfxPorts::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
|
@ -37,7 +37,7 @@ struct EngineState;
|
||||
*
|
||||
* Version - new/changed feature
|
||||
* =============================
|
||||
* 37 - Segment entry data changed to pointers
|
||||
* 37 - Segment entry data changed to pointers, SCI32 cursor
|
||||
* 36 - SCI32 bitmap segment
|
||||
* 35 - SCI32 remap
|
||||
* 34 - SCI32 palettes, and store play time in ticks
|
||||
|
@ -688,6 +688,7 @@ const SciWorkaroundEntry kPaletteUnsetFlag_workarounds[] = {
|
||||
// gameID, room,script,lvl, object-name, method-name, local-call-signature, index, workaround
|
||||
const SciWorkaroundEntry kSetCursor_workarounds[] = {
|
||||
{ GID_KQ5, -1, 768, 0, "KQCursor", "init", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // CD: gets called with 4 additional "900d" parameters
|
||||
{ GID_MOTHERGOOSEHIRES,0, 0, -1, "MG", "setCursor", NULL, 0, { WORKAROUND_STILLCALL, 0 } }, // At the start of the game, an object is passed as the cel number
|
||||
SCI_WORKAROUNDENTRY_TERMINATOR
|
||||
};
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "sci/engine/state.h"
|
||||
#include "sci/engine/kernel.h"
|
||||
#ifdef ENABLE_SCI32
|
||||
#include "sci/graphics/cursor32.h"
|
||||
#include "sci/graphics/frameout.h"
|
||||
#endif
|
||||
#include "sci/graphics/screen.h"
|
||||
@ -168,9 +169,17 @@ SciEvent EventManager::getScummVMEvent() {
|
||||
if (getSciVersion() >= SCI_VERSION_2) {
|
||||
const Buffer &screen = g_sci->_gfxFrameout->getCurrentBuffer();
|
||||
|
||||
if (ev.type == Common::EVENT_MOUSEMOVE) {
|
||||
// This will clamp `mousePos` according to the restricted zone,
|
||||
// so any cursor or screen item associated with the mouse position
|
||||
// does not bounce when it hits the edge (or ignore the edge)
|
||||
g_sci->_gfxCursor32->deviceMoved(mousePos);
|
||||
}
|
||||
|
||||
Common::Point mousePosSci = mousePos;
|
||||
mulru(mousePosSci, Ratio(screen.scriptWidth, screen.screenWidth), Ratio(screen.scriptHeight, screen.screenHeight));
|
||||
noEvent.mousePosSci = input.mousePosSci = mousePosSci;
|
||||
|
||||
} else {
|
||||
#endif
|
||||
g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x);
|
||||
|
367
engines/sci/graphics/cursor32.cpp
Normal file
367
engines/sci/graphics/cursor32.cpp
Normal file
@ -0,0 +1,367 @@
|
||||
/* 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/system.h"
|
||||
#include "graphics/cursorman.h"
|
||||
#include "sci/graphics/celobj32.h"
|
||||
#include "sci/graphics/cursor32.h"
|
||||
#include "sci/graphics/frameout.h"
|
||||
|
||||
namespace Sci {
|
||||
|
||||
GfxCursor32::GfxCursor32() :
|
||||
_hideCount(0),
|
||||
_position(0, 0),
|
||||
_writeToVMAP(false) {
|
||||
CursorMan.showMouse(false);
|
||||
}
|
||||
|
||||
void GfxCursor32::init(const Buffer &vmap) {
|
||||
_vmap = vmap;
|
||||
_vmapRegion.rect = Common::Rect(_vmap.screenWidth, _vmap.screenHeight);
|
||||
_vmapRegion.data = (byte *)_vmap.getPixels();
|
||||
_restrictedArea = _vmapRegion.rect;
|
||||
}
|
||||
|
||||
GfxCursor32::~GfxCursor32() {
|
||||
CursorMan.showMouse(true);
|
||||
free(_cursor.data);
|
||||
free(_cursorBack.data);
|
||||
free(_drawBuff1.data);
|
||||
free(_drawBuff2.data);
|
||||
free(_savedVmapRegion.data);
|
||||
}
|
||||
|
||||
void GfxCursor32::hide() {
|
||||
if (_hideCount++) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_cursorBack.rect.isEmpty()) {
|
||||
drawToHardware(_cursorBack);
|
||||
}
|
||||
}
|
||||
|
||||
void GfxCursor32::revealCursor() {
|
||||
_cursorBack.rect = _cursor.rect;
|
||||
_cursorBack.rect.clip(_vmapRegion.rect);
|
||||
if (_cursorBack.rect.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
readVideo(_cursorBack);
|
||||
_drawBuff1.rect = _cursor.rect;
|
||||
copy(_drawBuff1, _cursorBack);
|
||||
paint(_drawBuff1, _cursor);
|
||||
drawToHardware(_drawBuff1);
|
||||
}
|
||||
|
||||
void GfxCursor32::paint(DrawRegion &target, const DrawRegion &source) {
|
||||
if (source.rect.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Common::Rect drawRect(source.rect);
|
||||
drawRect.clip(target.rect);
|
||||
if (drawRect.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int16 sourceXOffset = drawRect.left - source.rect.left;
|
||||
const int16 sourceYOffset = drawRect.top - source.rect.top;
|
||||
const int16 drawRectWidth = drawRect.width();
|
||||
const int16 drawRectHeight = drawRect.height();
|
||||
|
||||
byte *targetPixel = target.data + ((drawRect.top - target.rect.top) * target.rect.width()) + (drawRect.left - target.rect.left);
|
||||
const byte *sourcePixel = source.data + (sourceYOffset * source.rect.width()) + sourceXOffset;
|
||||
const uint8 skipColor = source.skipColor;
|
||||
|
||||
const int16 sourceStride = source.rect.width() - drawRectWidth;
|
||||
const int16 targetStride = target.rect.width() - drawRectWidth;
|
||||
|
||||
for (int16 y = 0; y < drawRectHeight; ++y) {
|
||||
for (int16 x = 0; x < drawRectWidth; ++x) {
|
||||
if (*sourcePixel != skipColor) {
|
||||
*targetPixel = *sourcePixel;
|
||||
}
|
||||
++targetPixel;
|
||||
++sourcePixel;
|
||||
}
|
||||
sourcePixel += sourceStride;
|
||||
targetPixel += targetStride;
|
||||
}
|
||||
}
|
||||
|
||||
void GfxCursor32::drawToHardware(const DrawRegion &source) {
|
||||
Common::Rect drawRect(source.rect);
|
||||
drawRect.clip(_vmapRegion.rect);
|
||||
const int16 sourceXOffset = drawRect.left - source.rect.left;
|
||||
const int16 sourceYOffset = drawRect.top - source.rect.top;
|
||||
byte *sourcePixel = source.data + (sourceYOffset * source.rect.width()) + sourceXOffset;
|
||||
|
||||
g_system->copyRectToScreen(sourcePixel, source.rect.width(), drawRect.left, drawRect.top, drawRect.width(), drawRect.height());
|
||||
}
|
||||
|
||||
void GfxCursor32::unhide() {
|
||||
if (_hideCount == 0 || --_hideCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
_cursor.rect.moveTo(_position.x - _hotSpot.x, _position.y - _hotSpot.y);
|
||||
revealCursor();
|
||||
}
|
||||
|
||||
void GfxCursor32::show() {
|
||||
if (_hideCount) {
|
||||
_hideCount = 0;
|
||||
_cursor.rect.moveTo(_position.x - _hotSpot.x, _position.y - _hotSpot.y);
|
||||
revealCursor();
|
||||
}
|
||||
}
|
||||
|
||||
void GfxCursor32::setRestrictedArea(const Common::Rect &rect) {
|
||||
_restrictedArea = rect;
|
||||
|
||||
const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
|
||||
const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
|
||||
const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
|
||||
const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
|
||||
|
||||
mulru(_restrictedArea, Ratio(screenWidth, scriptWidth), Ratio(screenHeight, scriptHeight), 0);
|
||||
|
||||
if (_position.x < rect.left) {
|
||||
_position.x = rect.left;
|
||||
}
|
||||
if (_position.x >= rect.right) {
|
||||
_position.x = rect.right - 1;
|
||||
}
|
||||
if (_position.y < rect.top) {
|
||||
_position.y = rect.top;
|
||||
}
|
||||
if (_position.y >= rect.bottom) {
|
||||
_position.y = rect.bottom - 1;
|
||||
}
|
||||
|
||||
g_system->warpMouse(_position.x, _position.y);
|
||||
}
|
||||
|
||||
void GfxCursor32::clearRestrictedArea() {
|
||||
_restrictedArea = _vmapRegion.rect;
|
||||
}
|
||||
|
||||
void GfxCursor32::setView(const GuiResourceId viewId, const int16 loopNo, const int16 celNo) {
|
||||
hide();
|
||||
|
||||
_cursorInfo.resourceId = viewId;
|
||||
_cursorInfo.loopNo = loopNo;
|
||||
_cursorInfo.celNo = celNo;
|
||||
|
||||
if (viewId != -1) {
|
||||
CelObjView view(viewId, loopNo, celNo);
|
||||
|
||||
_hotSpot = view._displace;
|
||||
_width = view._width;
|
||||
_height = view._height;
|
||||
|
||||
_cursor.data = (byte *)realloc(_cursor.data, _width * _height);
|
||||
_cursor.rect = Common::Rect(_width, _height);
|
||||
memset(_cursor.data, 255, _width * _height);
|
||||
_cursor.skipColor = 255;
|
||||
|
||||
Buffer target(_width, _height, _cursor.data);
|
||||
view.draw(target, _cursor.rect, Common::Point(0, 0), false);
|
||||
} else {
|
||||
_hotSpot = Common::Point(0, 0);
|
||||
_width = _height = 1;
|
||||
_cursor.data = (byte *)realloc(_cursor.data, _width * _height);
|
||||
_cursor.rect = Common::Rect(_width, _height);
|
||||
*_cursor.data = _cursor.skipColor;
|
||||
_cursorBack.rect = _cursor.rect;
|
||||
_cursorBack.rect.clip(_vmapRegion.rect);
|
||||
if (!_cursorBack.rect.isEmpty()) {
|
||||
readVideo(_cursorBack);
|
||||
}
|
||||
}
|
||||
|
||||
_cursorBack.data = (byte *)realloc(_cursorBack.data, _width * _height);
|
||||
_drawBuff1.data = (byte *)realloc(_drawBuff1.data, _width * _height);
|
||||
_drawBuff2.data = (byte *)realloc(_drawBuff2.data, _width * _height * 4);
|
||||
_savedVmapRegion.data = (byte *)realloc(_savedVmapRegion.data, _width * _height);
|
||||
|
||||
unhide();
|
||||
}
|
||||
|
||||
void GfxCursor32::readVideo(DrawRegion &target) {
|
||||
if (g_sci->_gfxFrameout->_frameNowVisible) {
|
||||
copy(target, _vmapRegion);
|
||||
} else {
|
||||
// NOTE: SSCI would read the background for the cursor directly out of
|
||||
// video memory here, but as far as can be determined, this does not
|
||||
// seem to actually be necessary for proper cursor rendering
|
||||
}
|
||||
}
|
||||
|
||||
void GfxCursor32::copy(DrawRegion &target, const DrawRegion &source) {
|
||||
if (source.rect.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Common::Rect drawRect(source.rect);
|
||||
drawRect.clip(target.rect);
|
||||
if (drawRect.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int16 sourceXOffset = drawRect.left - source.rect.left;
|
||||
const int16 sourceYOffset = drawRect.top - source.rect.top;
|
||||
const int16 drawWidth = drawRect.width();
|
||||
const int16 drawHeight = drawRect.height();
|
||||
|
||||
byte *targetPixel = target.data + ((drawRect.top - target.rect.top) * target.rect.width()) + (drawRect.left - target.rect.left);
|
||||
const byte *sourcePixel = source.data + (sourceYOffset * source.rect.width()) + sourceXOffset;
|
||||
|
||||
const int16 sourceStride = source.rect.width();
|
||||
const int16 targetStride = target.rect.width();
|
||||
|
||||
for (int y = 0; y < drawHeight; ++y) {
|
||||
memcpy(targetPixel, sourcePixel, drawWidth);
|
||||
targetPixel += targetStride;
|
||||
sourcePixel += sourceStride;
|
||||
}
|
||||
}
|
||||
|
||||
void GfxCursor32::setPosition(const Common::Point &position) {
|
||||
const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
|
||||
const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
|
||||
const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
|
||||
const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
|
||||
|
||||
_position.x = (position.x * Ratio(screenWidth, scriptWidth)).toInt();
|
||||
_position.y = (position.y * Ratio(screenHeight, scriptHeight)).toInt();
|
||||
|
||||
g_system->warpMouse(_position.x, _position.y);
|
||||
}
|
||||
|
||||
void GfxCursor32::gonnaPaint(Common::Rect paintRect) {
|
||||
if (!_hideCount && !_writeToVMAP && !_cursorBack.rect.isEmpty()) {
|
||||
paintRect.left &= ~3;
|
||||
paintRect.right |= 3;
|
||||
if (_cursorBack.rect.intersects(paintRect)) {
|
||||
_writeToVMAP = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GfxCursor32::paintStarting() {
|
||||
if (_writeToVMAP) {
|
||||
_savedVmapRegion.rect = _cursor.rect;
|
||||
copy(_savedVmapRegion, _vmapRegion);
|
||||
paint(_vmapRegion, _cursor);
|
||||
}
|
||||
}
|
||||
|
||||
void GfxCursor32::donePainting() {
|
||||
if (_writeToVMAP) {
|
||||
copy(_vmapRegion, _savedVmapRegion);
|
||||
_savedVmapRegion.rect = Common::Rect();
|
||||
_writeToVMAP = false;
|
||||
}
|
||||
|
||||
if (!_hideCount && !_cursorBack.rect.isEmpty()) {
|
||||
copy(_cursorBack, _vmapRegion);
|
||||
}
|
||||
}
|
||||
|
||||
void GfxCursor32::deviceMoved(Common::Point &position) {
|
||||
if (position.x < _restrictedArea.left) {
|
||||
position.x = _restrictedArea.left;
|
||||
}
|
||||
if (position.x >= _restrictedArea.right) {
|
||||
position.x = _restrictedArea.right - 1;
|
||||
}
|
||||
if (position.y < _restrictedArea.top) {
|
||||
position.y = _restrictedArea.top;
|
||||
}
|
||||
if (position.y >= _restrictedArea.bottom) {
|
||||
position.y = _restrictedArea.bottom - 1;
|
||||
}
|
||||
|
||||
_position = position;
|
||||
|
||||
g_system->warpMouse(position.x, position.y);
|
||||
move();
|
||||
}
|
||||
|
||||
void GfxCursor32::move() {
|
||||
if (_hideCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If it was off the screen, just show it and return
|
||||
_cursor.rect.moveTo(_position.x - _hotSpot.x, _position.y - _hotSpot.y);
|
||||
if (_cursorBack.rect.isEmpty()) {
|
||||
revealCursor();
|
||||
return;
|
||||
}
|
||||
|
||||
// If we just moved entirely off screen, remove background & return
|
||||
if (!_cursor.rect.intersects(_vmapRegion.rect)) {
|
||||
drawToHardware(_cursorBack);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_cursor.rect.intersects(_cursorBack.rect)) {
|
||||
_drawBuff1.rect = _cursor.rect;
|
||||
_drawBuff1.rect.clip(_vmapRegion.rect);
|
||||
readVideo(_drawBuff1);
|
||||
|
||||
_drawBuff2.rect = _drawBuff1.rect;
|
||||
copy(_drawBuff2, _drawBuff1);
|
||||
|
||||
paint(_drawBuff1, _cursor);
|
||||
drawToHardware(_drawBuff1);
|
||||
|
||||
// erase
|
||||
drawToHardware(_cursorBack);
|
||||
|
||||
_cursorBack.rect = _cursor.rect;
|
||||
_cursorBack.rect.clip(_vmapRegion.rect);
|
||||
copy(_cursorBack, _drawBuff2);
|
||||
} else {
|
||||
Common::Rect mergedRect(_cursorBack.rect);
|
||||
mergedRect.extend(_cursor.rect);
|
||||
mergedRect.clip(_vmapRegion.rect);
|
||||
|
||||
_drawBuff2.rect = mergedRect;
|
||||
readVideo(_drawBuff2);
|
||||
|
||||
copy(_drawBuff2, _cursorBack);
|
||||
|
||||
_cursorBack.rect = _cursor.rect;
|
||||
_cursorBack.rect.clip(_vmapRegion.rect);
|
||||
copy(_cursorBack, _drawBuff2);
|
||||
|
||||
paint(_drawBuff2, _cursor);
|
||||
drawToHardware(_drawBuff2);
|
||||
}
|
||||
}
|
||||
} // End of namespace Sci
|
248
engines/sci/graphics/cursor32.h
Normal file
248
engines/sci/graphics/cursor32.h
Normal file
@ -0,0 +1,248 @@
|
||||
/* 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCI_GRAPHICS_CURSOR32_H
|
||||
#define SCI_GRAPHICS_CURSOR32_H
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/serializer.h"
|
||||
#include "sci/graphics/helpers.h"
|
||||
|
||||
namespace Sci {
|
||||
|
||||
class GfxCursor32 : Common::Serializable {
|
||||
public:
|
||||
GfxCursor32();
|
||||
~GfxCursor32();
|
||||
|
||||
/**
|
||||
* Initialises the cursor system with the given
|
||||
* buffer to use as the output buffer for
|
||||
* rendering the cursor.
|
||||
*/
|
||||
void init(const Buffer &vmap);
|
||||
|
||||
/**
|
||||
* Called when the hardware mouse moves.
|
||||
*/
|
||||
void deviceMoved(Common::Point &position);
|
||||
|
||||
/**
|
||||
* Called by GfxFrameout once for each show
|
||||
* rectangle that is going to be drawn to
|
||||
* hardware.
|
||||
*/
|
||||
void gonnaPaint(Common::Rect paintRect);
|
||||
|
||||
/**
|
||||
* Called by GfxFrameout when the rendering to
|
||||
* hardware begins.
|
||||
*/
|
||||
void paintStarting();
|
||||
|
||||
/**
|
||||
* Called by GfxFrameout when the output buffer
|
||||
* has finished rendering to hardware.
|
||||
*/
|
||||
void donePainting();
|
||||
|
||||
/**
|
||||
* Hides the cursor. Each call to `hide` will
|
||||
* increment a hide counter, which must be
|
||||
* returned to 0 before the cursor will be
|
||||
* shown again.
|
||||
*/
|
||||
void hide();
|
||||
|
||||
/**
|
||||
* Shows the cursor, if the hide counter is
|
||||
* returned to 0.
|
||||
*/
|
||||
void unhide();
|
||||
|
||||
/**
|
||||
* Shows the cursor regardless of the state of
|
||||
* the hide counter.
|
||||
*/
|
||||
void show();
|
||||
|
||||
/**
|
||||
* Sets the view used to render the cursor.
|
||||
*/
|
||||
void setView(const GuiResourceId viewId, const int16 loopNo, const int16 celNo);
|
||||
|
||||
/**
|
||||
* Explicitly sets the position of the cursor,
|
||||
* in game script coordinates.
|
||||
*/
|
||||
void setPosition(const Common::Point &position);
|
||||
|
||||
/**
|
||||
* Sets the region that the mouse is allowed
|
||||
* to move within.
|
||||
*/
|
||||
void setRestrictedArea(const Common::Rect &rect);
|
||||
|
||||
/**
|
||||
* Removes restrictions on mouse movement.
|
||||
*/
|
||||
void clearRestrictedArea();
|
||||
|
||||
virtual void saveLoadWithSerializer(Common::Serializer &ser);
|
||||
|
||||
private:
|
||||
struct DrawRegion {
|
||||
Common::Rect rect;
|
||||
byte *data;
|
||||
uint8 skipColor;
|
||||
|
||||
DrawRegion() : rect(), data(nullptr) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Information about the current cursor.
|
||||
* Used to restore cursor when loading a
|
||||
* savegame.
|
||||
*/
|
||||
CelInfo32 _cursorInfo;
|
||||
|
||||
/**
|
||||
* Content behind the cursor? TODO
|
||||
*/
|
||||
DrawRegion _cursorBack;
|
||||
|
||||
/**
|
||||
* Scratch buffer.
|
||||
*/
|
||||
DrawRegion _drawBuff1;
|
||||
|
||||
/**
|
||||
* Scratch buffer 2.
|
||||
*/
|
||||
DrawRegion _drawBuff2;
|
||||
|
||||
/**
|
||||
* A draw region representing the current
|
||||
* output buffer.
|
||||
*/
|
||||
DrawRegion _vmapRegion;
|
||||
|
||||
/**
|
||||
* The content behind the cursor in the
|
||||
* output buffer.
|
||||
*/
|
||||
DrawRegion _savedVmapRegion;
|
||||
|
||||
/**
|
||||
* The cursor bitmap.
|
||||
*/
|
||||
DrawRegion _cursor;
|
||||
|
||||
/**
|
||||
* The width and height of the cursor,
|
||||
* in screen coordinates.
|
||||
*/
|
||||
int16 _width, _height;
|
||||
|
||||
/**
|
||||
* The output buffer where the cursor is
|
||||
* rendered.
|
||||
*/
|
||||
Buffer _vmap;
|
||||
|
||||
/**
|
||||
* The number of times the cursor has been
|
||||
* hidden.
|
||||
*/
|
||||
int _hideCount;
|
||||
|
||||
/**
|
||||
* The rendered position of the cursor, in
|
||||
* screen coordinates.
|
||||
*/
|
||||
Common::Point _position;
|
||||
|
||||
/**
|
||||
* The position of the cursor hot spot, relative
|
||||
* to the cursor origin, in screen pixels.
|
||||
*/
|
||||
Common::Point _hotSpot;
|
||||
|
||||
/**
|
||||
* The area within which the cursor is allowed
|
||||
* to move, in screen pixels.
|
||||
*/
|
||||
Common::Rect _restrictedArea;
|
||||
|
||||
/**
|
||||
* Indicates whether or not the cursor needs to
|
||||
* be repainted on the output buffer due to a
|
||||
* change of graphics in the area underneath the
|
||||
* cursor.
|
||||
*/
|
||||
bool _writeToVMAP;
|
||||
|
||||
/**
|
||||
* Reads data from the output buffer or hardware
|
||||
* to the given draw region.
|
||||
*/
|
||||
void readVideo(DrawRegion &target);
|
||||
|
||||
/**
|
||||
* Reads data from the output buffer to the
|
||||
* given draw region.
|
||||
*/
|
||||
void readVideoFromVmap(DrawRegion &target);
|
||||
|
||||
/**
|
||||
* Copies pixel data from the given source to
|
||||
* the given target.
|
||||
*/
|
||||
void copy(DrawRegion &target, const DrawRegion &source);
|
||||
|
||||
/**
|
||||
* Draws from the given source onto the given
|
||||
* target, skipping pixels in the source that
|
||||
* match the `skipColor` property.
|
||||
*/
|
||||
void paint(DrawRegion &target, const DrawRegion &source);
|
||||
|
||||
/**
|
||||
* Draws the cursor to the position it was
|
||||
* drawn to prior to moving offscreen or being
|
||||
* hidden by a call to `hide`.
|
||||
*/
|
||||
void revealCursor();
|
||||
|
||||
/**
|
||||
* Draws the given source to the output buffer.
|
||||
*/
|
||||
void drawToHardware(const DrawRegion &source);
|
||||
|
||||
/**
|
||||
* Renders the cursor at its new location.
|
||||
*/
|
||||
void move();
|
||||
};
|
||||
|
||||
} // End of namespace Sci
|
||||
#endif
|
@ -42,6 +42,7 @@
|
||||
#include "sci/graphics/cache.h"
|
||||
#include "sci/graphics/coordadjuster.h"
|
||||
#include "sci/graphics/compare.h"
|
||||
#include "sci/graphics/cursor32.h"
|
||||
#include "sci/graphics/font.h"
|
||||
#include "sci/graphics/screen.h"
|
||||
#include "sci/graphics/paint32.h"
|
||||
@ -56,9 +57,10 @@
|
||||
|
||||
namespace Sci {
|
||||
|
||||
GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxPalette32 *palette, GfxTransitions32 *transitions) :
|
||||
GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxPalette32 *palette, GfxTransitions32 *transitions, GfxCursor32 *cursor) :
|
||||
_isHiRes(ConfMan.getBool("enable_high_resolution_graphics")),
|
||||
_palette(palette),
|
||||
_cursor(cursor),
|
||||
_resMan(resMan),
|
||||
_segMan(segMan),
|
||||
_transitions(transitions),
|
||||
@ -1120,6 +1122,10 @@ void GfxFrameout::mergeToShowList(const Common::Rect &drawRect, RectList &showLi
|
||||
}
|
||||
|
||||
void GfxFrameout::showBits() {
|
||||
if (!_showList.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (RectList::const_iterator rect = _showList.begin(); rect != _showList.end(); ++rect) {
|
||||
Common::Rect rounded(**rect);
|
||||
// NOTE: SCI engine used BR-inclusive rects so used slightly
|
||||
@ -1127,13 +1133,10 @@ void GfxFrameout::showBits() {
|
||||
// was always even.
|
||||
rounded.left &= ~1;
|
||||
rounded.right = (rounded.right + 1) & ~1;
|
||||
|
||||
// TODO:
|
||||
// _cursor->GonnaPaint(rounded);
|
||||
_cursor->gonnaPaint(rounded);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// _cursor->PaintStarting();
|
||||
_cursor->paintStarting();
|
||||
|
||||
for (RectList::const_iterator rect = _showList.begin(); rect != _showList.end(); ++rect) {
|
||||
Common::Rect rounded(**rect);
|
||||
@ -1155,8 +1158,7 @@ void GfxFrameout::showBits() {
|
||||
g_system->copyRectToScreen(sourceBuffer, _currentBuffer.screenWidth, rounded.left, rounded.top, rounded.width(), rounded.height());
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// _cursor->DonePainting();
|
||||
_cursor->donePainting();
|
||||
|
||||
_showList.clear();
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ namespace Sci {
|
||||
typedef Common::Array<DrawList> ScreenItemListList;
|
||||
typedef Common::Array<RectList> EraseListList;
|
||||
|
||||
class GfxCursor32;
|
||||
class GfxCoordAdjuster32;
|
||||
class GfxTransitions32;
|
||||
struct PlaneShowStyle;
|
||||
@ -40,13 +41,14 @@ struct PlaneShowStyle;
|
||||
*/
|
||||
class GfxFrameout {
|
||||
private:
|
||||
GfxCursor32 *_cursor;
|
||||
GfxCoordAdjuster32 *_coordAdjuster;
|
||||
GfxPalette32 *_palette;
|
||||
ResourceManager *_resMan;
|
||||
SegManager *_segMan;
|
||||
|
||||
public:
|
||||
GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxPalette32 *palette, GfxTransitions32 *transitions);
|
||||
GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAdjuster *coordAdjuster, GfxPalette32 *palette, GfxTransitions32 *transitions, GfxCursor32 *cursor);
|
||||
~GfxFrameout();
|
||||
|
||||
bool _isHiRes;
|
||||
@ -195,13 +197,6 @@ private:
|
||||
*/
|
||||
bool _remapOccurred;
|
||||
|
||||
/**
|
||||
* Whether or not the data in the current buffer is what
|
||||
* is visible to the user. During rendering updates,
|
||||
* this flag is set to false.
|
||||
*/
|
||||
bool _frameNowVisible;
|
||||
|
||||
/**
|
||||
* TODO: Document
|
||||
* TODO: Depending upon if the engine ever modifies this
|
||||
@ -308,6 +303,13 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Whether or not the data in the current buffer is what
|
||||
* is visible to the user. During rendering updates,
|
||||
* this flag is set to false.
|
||||
*/
|
||||
bool _frameNowVisible;
|
||||
|
||||
/**
|
||||
* Whether palMorphFrameOut should be used instead of
|
||||
* frameOut for rendering. Used by kMorphOn to
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include "sci/engine/vm_types.h" // for reg_t
|
||||
#include "sci/event.h" // for SciEvent, EventManager, SCI_...
|
||||
#include "sci/graphics/celobj32.h" // for CelInfo32, ::kLowResX, ::kLo...
|
||||
#include "sci/graphics/cursor.h" // for GfxCursor
|
||||
#include "sci/graphics/cursor32.h" // for GfxCursor32
|
||||
#include "sci/graphics/frameout.h" // for GfxFrameout
|
||||
#include "sci/graphics/helpers.h" // for Color, Palette
|
||||
#include "sci/graphics/palette32.h" // for GfxPalette32
|
||||
@ -597,7 +597,7 @@ VMDPlayer::IOStatus VMDPlayer::close() {
|
||||
}
|
||||
|
||||
if (!_showCursor) {
|
||||
g_sci->_gfxCursor->kernelShow();
|
||||
g_sci->_gfxCursor32->unhide();
|
||||
}
|
||||
|
||||
_lastYieldedFrameNo = 0;
|
||||
@ -658,7 +658,7 @@ VMDPlayer::EventFlags VMDPlayer::playUntilEvent(const EventFlags flags) {
|
||||
_isInitialized = true;
|
||||
|
||||
if (!_showCursor) {
|
||||
g_sci->_gfxCursor->kernelHide();
|
||||
g_sci->_gfxCursor32->hide();
|
||||
}
|
||||
|
||||
Common::Rect vmdRect(_x,
|
||||
|
@ -93,6 +93,7 @@ MODULE_OBJS += \
|
||||
graphics/text32.o \
|
||||
graphics/transitions32.o \
|
||||
graphics/video32.o \
|
||||
graphics/cursor32.o \
|
||||
sound/audio32.o \
|
||||
sound/decoders/sol.o \
|
||||
video/robot_decoder.o
|
||||
|
@ -65,6 +65,7 @@
|
||||
|
||||
#ifdef ENABLE_SCI32
|
||||
#include "sci/graphics/controls32.h"
|
||||
#include "sci/graphics/cursor32.h"
|
||||
#include "sci/graphics/frameout.h"
|
||||
#include "sci/graphics/palette32.h"
|
||||
#include "sci/graphics/remap32.h"
|
||||
@ -96,6 +97,7 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gam
|
||||
#ifdef ENABLE_SCI32
|
||||
_audio32 = nullptr;
|
||||
_video32 = nullptr;
|
||||
_gfxCursor32 = nullptr;
|
||||
#endif
|
||||
_features = 0;
|
||||
_resMan = 0;
|
||||
@ -176,6 +178,7 @@ SciEngine::~SciEngine() {
|
||||
// destruction of screen items in the Video32 destructor relies on these
|
||||
// components
|
||||
delete _video32;
|
||||
delete _gfxCursor32;
|
||||
delete _gfxPalette32;
|
||||
delete _gfxTransitions32;
|
||||
delete _gfxFrameout;
|
||||
@ -708,6 +711,7 @@ void SciEngine::initGraphics() {
|
||||
_gfxPalette32 = 0;
|
||||
_gfxRemap32 = 0;
|
||||
_gfxTransitions32 = 0;
|
||||
_gfxCursor32 = 0;
|
||||
#endif
|
||||
|
||||
if (hasMacIconBar())
|
||||
@ -727,23 +731,25 @@ void SciEngine::initGraphics() {
|
||||
#endif
|
||||
|
||||
_gfxCache = new GfxCache(_resMan, _gfxScreen, _gfxPalette16);
|
||||
_gfxCursor = new GfxCursor(_resMan, _gfxPalette16, _gfxScreen);
|
||||
|
||||
#ifdef ENABLE_SCI32
|
||||
if (getSciVersion() >= SCI_VERSION_2) {
|
||||
// SCI32 graphic objects creation
|
||||
_gfxCoordAdjuster = new GfxCoordAdjuster32(_gamestate->_segMan);
|
||||
_gfxCursor->init(_gfxCoordAdjuster, _eventMan);
|
||||
_gfxCursor32 = new GfxCursor32();
|
||||
_gfxCompare = new GfxCompare(_gamestate->_segMan, _gfxCache, _gfxScreen, _gfxCoordAdjuster);
|
||||
_gfxPaint32 = new GfxPaint32(_gamestate->_segMan);
|
||||
_robotDecoder = new RobotDecoder(getPlatform() == Common::kPlatformMacintosh);
|
||||
_gfxTransitions32 = new GfxTransitions32(_gamestate->_segMan);
|
||||
_gfxFrameout = new GfxFrameout(_gamestate->_segMan, _resMan, _gfxCoordAdjuster, _gfxPalette32, _gfxTransitions32);
|
||||
_gfxFrameout = new GfxFrameout(_gamestate->_segMan, _resMan, _gfxCoordAdjuster, _gfxPalette32, _gfxTransitions32, _gfxCursor32);
|
||||
_gfxCursor32->init(_gfxFrameout->getCurrentBuffer());
|
||||
_gfxText32 = new GfxText32(_gamestate->_segMan, _gfxCache);
|
||||
_gfxControls32 = new GfxControls32(_gamestate->_segMan, _gfxCache, _gfxText32);
|
||||
_gfxFrameout->run();
|
||||
} else {
|
||||
#endif
|
||||
_gfxCursor = new GfxCursor(_resMan, _gfxPalette16, _gfxScreen);
|
||||
|
||||
// SCI0-SCI1.1 graphic objects creation
|
||||
_gfxPorts = new GfxPorts(_gamestate->_segMan, _gfxScreen);
|
||||
_gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts);
|
||||
|
@ -98,6 +98,7 @@ class GfxFrameout;
|
||||
class Audio32;
|
||||
class Video32;
|
||||
class GfxTransitions32;
|
||||
class GfxCursor32;
|
||||
#endif
|
||||
|
||||
// our engine debug levels
|
||||
@ -391,6 +392,7 @@ public:
|
||||
RobotDecoder *_robotDecoder;
|
||||
GfxFrameout *_gfxFrameout; // kFrameout and the like for 32-bit gfx
|
||||
GfxTransitions32 *_gfxTransitions32;
|
||||
GfxCursor32 *_gfxCursor32;
|
||||
#endif
|
||||
|
||||
AudioPlayer *_audio;
|
||||
|
Loading…
Reference in New Issue
Block a user