mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
All of the builtin palette lookup tables have been reversed, to match the original layout of the tables in the Director 4 projector executable. This corresponds with the colour indexing used in Lingo. Likewise, the code to load palettes from the cast no longer reads the colours in reverse order, and shiftPalette no longer expects the start index to be after the end index. DirectorEngine::transformColor still exists to upgrade to 32-bit colour, but no longer reverses the palette index. The missing builtin 16-color palettes from Director 4 have been added.
256 lines
7.1 KiB
C++
256 lines
7.1 KiB
C++
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "image/image_decoder.h"
|
|
|
|
#include "graphics/wincursor.h"
|
|
|
|
#include "director/director.h"
|
|
#include "director/cursor.h"
|
|
#include "director/movie.h"
|
|
#include "director/castmember.h"
|
|
|
|
namespace Director {
|
|
|
|
Cursor::Cursor() {
|
|
_keyColor = 0xff;
|
|
|
|
_cursorResId = Datum(0);
|
|
_cursorType = Graphics::kMacCursorArrow;
|
|
|
|
_usePalette = false;
|
|
}
|
|
|
|
CursorRef Cursor::getRef() {
|
|
CursorRef res;
|
|
res._cursorType = _cursorType;
|
|
res._cursorResId = _cursorResId;
|
|
return res;
|
|
}
|
|
|
|
bool Cursor::operator==(const Cursor &c) {
|
|
return _cursorType == c._cursorType &&
|
|
c._cursorResId == _cursorResId;
|
|
}
|
|
|
|
bool Cursor::operator==(const CursorRef &c) {
|
|
return _cursorType == c._cursorType &&
|
|
c._cursorResId == _cursorResId;
|
|
}
|
|
|
|
void Cursor::readFromCast(Datum cursorCasts) {
|
|
if (cursorCasts.type != ARRAY || cursorCasts.u.farr->arr.size() != 2 ) {
|
|
warning("Cursor::readFromCast: Needs array of 2");
|
|
return;
|
|
}
|
|
if (_cursorResId == cursorCasts)
|
|
return;
|
|
|
|
CastMemberID cursorId = cursorCasts.u.farr->arr[0].asMemberID();
|
|
CastMemberID maskId = cursorCasts.u.farr->arr[1].asMemberID();
|
|
|
|
CastMember *cursorCast = g_director->getCurrentMovie()->getCastMember(cursorId);
|
|
CastMember *maskCast = g_director->getCurrentMovie()->getCastMember(maskId);
|
|
|
|
if (!cursorCast || cursorCast->_type != kCastBitmap) {
|
|
warning("Cursor::readFromCast: No bitmap cast for cursor");
|
|
return;
|
|
} else if (!maskCast || maskCast->_type != kCastBitmap) {
|
|
warning("Cursor::readFromCast: No bitmap mask for cursor");
|
|
return;
|
|
}
|
|
|
|
_usePalette = false;
|
|
_keyColor = 3;
|
|
|
|
resetCursor(Graphics::kMacCursorCustom, true, cursorCasts);
|
|
|
|
BitmapCastMember *cursorBitmap = (BitmapCastMember *)cursorCast;
|
|
BitmapCastMember *maskBitmap = (BitmapCastMember *)maskCast;
|
|
|
|
_surface = new byte[getWidth() * getHeight()];
|
|
byte *dst = _surface;
|
|
|
|
for (int y = 0; y < 16; y++) {
|
|
const byte *cursor = nullptr, *mask = nullptr;
|
|
|
|
if (y < cursorBitmap->_img->getSurface()->h &&
|
|
y < maskBitmap->_img->getSurface()->h) {
|
|
cursor = (const byte *)cursorBitmap->_img->getSurface()->getBasePtr(0, y);
|
|
mask = (const byte *)maskBitmap->_img->getSurface()->getBasePtr(0, y);
|
|
}
|
|
|
|
for (int x = 0; x < 16; x++) {
|
|
if (x >= cursorBitmap->_img->getSurface()->w ||
|
|
x >= maskBitmap->_img->getSurface()->w) {
|
|
cursor = mask = nullptr;
|
|
}
|
|
|
|
if (!cursor) {
|
|
*dst = 3;
|
|
} else {
|
|
*dst = *mask ? (*cursor ? 0 : 1) : 3;
|
|
cursor++;
|
|
mask++;
|
|
}
|
|
dst++;
|
|
}
|
|
}
|
|
|
|
BitmapCastMember *bc = (BitmapCastMember *)(cursorCast);
|
|
_hotspotX = bc->_regX - bc->_initialRect.left;
|
|
_hotspotY = bc->_regY - bc->_initialRect.top;
|
|
}
|
|
|
|
void Cursor::readBuiltinType(Datum resourceId) {
|
|
if (resourceId.equalTo(_cursorResId))
|
|
return;
|
|
|
|
if (resourceId.type != INT) {
|
|
warning("readBuiltinType: failed to read cursor. It's not type int");
|
|
}
|
|
|
|
|
|
switch(resourceId.asInt()) {
|
|
case -1:
|
|
case 0:
|
|
resetCursor(Graphics::kMacCursorArrow, true, resourceId);
|
|
break;
|
|
case 1:
|
|
resetCursor(Graphics::kMacCursorBeam, true, resourceId);
|
|
break;
|
|
case 2:
|
|
resetCursor(Graphics::kMacCursorCrossHair, true, resourceId);
|
|
break;
|
|
case 3:
|
|
resetCursor(Graphics::kMacCursorCrossBar, true, resourceId);
|
|
break;
|
|
case 4:
|
|
resetCursor(Graphics::kMacCursorWatch, true, resourceId);
|
|
break;
|
|
case 200:
|
|
resetCursor(Graphics::kMacCursorOff, true, resourceId);
|
|
break;
|
|
default:
|
|
warning("Cursor::readBuiltinType failed to read cursor %d", resourceId.asInt());
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Cursor::readFromResource(Datum resourceId) {
|
|
if (resourceId == _cursorResId)
|
|
return;
|
|
|
|
if (resourceId.type != INT) {
|
|
warning("Cursor:readFromResource is not of type INT");
|
|
return;
|
|
}
|
|
switch(resourceId.asInt()) {
|
|
case -1:
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
case 200:
|
|
readBuiltinType(resourceId);
|
|
break;
|
|
default:
|
|
bool readSuccessful = false;
|
|
|
|
for (Common::HashMap<Common::String, Archive *, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo>::iterator it = g_director->_allOpenResFiles.begin(); it != g_director->_allOpenResFiles.end(); ++it) {
|
|
MacArchive *arch = (MacArchive *)it->_value;
|
|
Common::SeekableReadStreamEndian *cursorStream = nullptr;
|
|
if (arch->hasResource(MKTAG('C', 'U', 'R', 'S'), resourceId.asInt()))
|
|
cursorStream = arch->getResource(MKTAG('C', 'U', 'R', 'S'), resourceId.asInt());
|
|
|
|
if (!cursorStream && arch->hasResource(MKTAG('C', 'R', 'S', 'R'), resourceId.asInt()))
|
|
cursorStream = arch->getResource(MKTAG('C', 'R', 'S', 'R'), resourceId.asInt());
|
|
|
|
if (cursorStream && readFromStream(*((Common::SeekableReadStream *)cursorStream), false, 0)) {
|
|
_usePalette = true;
|
|
_keyColor = 0xff;
|
|
readSuccessful = true;
|
|
|
|
resetCursor(Graphics::kMacCursorCustom, false, resourceId);
|
|
delete cursorStream;
|
|
break;
|
|
}
|
|
delete cursorStream;
|
|
}
|
|
|
|
// TODO: figure out where to read custom cursor in windows platform
|
|
// currently, let's just set arrow for default one.
|
|
if (g_director->getPlatform() == Common::kPlatformWindows) {
|
|
resetCursor(Graphics::kMacCursorArrow, true, resourceId);
|
|
break;
|
|
}
|
|
|
|
// for win platform, try the cursor from exe
|
|
if (!readSuccessful && g_director->getPlatform() == Common::kPlatformWindows) {
|
|
// i'm not sure, in jman we have cursor id 2, 3, 4. and custom cursor id 128 129 130
|
|
uint id = (resourceId.asInt() & 0x7f) + 2;
|
|
for (uint i = 0; i < g_director->_winCursor.size(); i++) {
|
|
for (uint j = 0; j < g_director->_winCursor[i]->cursors.size(); j++) {
|
|
if (id == g_director->_winCursor[i]->cursors[j].id.getID()) {
|
|
resetCursor(Graphics::kMacCursorCustom, false, Datum((int)id));
|
|
readSuccessful = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// fallback method. try to use builtin cursor by regarding resourceId as a single byte.
|
|
if (!readSuccessful)
|
|
readBuiltinType(resourceId.asInt() & 0x7f);
|
|
}
|
|
}
|
|
|
|
void Cursor::resetCursor(Graphics::MacCursorType type, bool shouldClear, Datum resId) {
|
|
if (shouldClear)
|
|
clear();
|
|
|
|
_cursorType = type;
|
|
if (_cursorType != Graphics::kMacCursorCustom)
|
|
_usePalette = false;
|
|
|
|
_cursorResId = resId;
|
|
|
|
_hotspotX = 0;
|
|
_hotspotY = 0;
|
|
}
|
|
|
|
CursorRef::CursorRef() {
|
|
_cursorType = Graphics::kMacCursorArrow;
|
|
_cursorResId = Datum(0);
|
|
}
|
|
|
|
bool CursorRef::operator==(const Cursor &c) {
|
|
return _cursorType == c._cursorType &&
|
|
c._cursorResId == _cursorResId;
|
|
}
|
|
|
|
bool CursorRef::operator==(const CursorRef &c) {
|
|
return _cursorType == c._cursorType &&
|
|
c._cursorResId == _cursorResId;
|
|
}
|
|
|
|
} // End of namespace Director
|