2010-01-31 12:35:15 +00:00
|
|
|
/* 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.
|
|
|
|
*
|
|
|
|
* $URL$
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "common/util.h"
|
|
|
|
#include "common/stack.h"
|
|
|
|
#include "graphics/primitives.h"
|
|
|
|
|
|
|
|
#include "sci/sci.h"
|
|
|
|
#include "sci/engine/state.h"
|
|
|
|
#include "sci/engine/selector.h"
|
|
|
|
#include "sci/graphics/cache.h"
|
|
|
|
#include "sci/graphics/ports.h"
|
|
|
|
#include "sci/graphics/paint16.h"
|
|
|
|
#include "sci/graphics/animate.h"
|
|
|
|
#include "sci/graphics/font.h"
|
|
|
|
#include "sci/graphics/picture.h"
|
|
|
|
#include "sci/graphics/view.h"
|
|
|
|
#include "sci/graphics/screen.h"
|
|
|
|
#include "sci/graphics/palette.h"
|
|
|
|
#include "sci/graphics/text.h"
|
|
|
|
|
|
|
|
namespace Sci {
|
|
|
|
|
2010-01-31 16:21:11 +00:00
|
|
|
GfxPaint16::GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, GfxCache *cache, GfxPorts *ports, GfxScreen *screen, GfxPalette *palette)
|
2010-01-31 12:35:15 +00:00
|
|
|
: _resMan(resMan), _segMan(segMan), _kernel(kernel), _cache(cache), _ports(ports), _screen(screen), _palette(palette) {
|
|
|
|
}
|
|
|
|
|
|
|
|
GfxPaint16::~GfxPaint16() {
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::init(Text *text) {
|
|
|
|
_text = text;
|
|
|
|
|
|
|
|
_EGAdrawingVisualize = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::setEGAdrawingVisualize(bool state) {
|
|
|
|
_EGAdrawingVisualize = state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::drawPicture(GuiResourceId pictureId, int16 animationNr, bool mirroredFlag, bool addToFlag, GuiResourceId paletteId) {
|
|
|
|
SciGuiPicture *picture = new SciGuiPicture(_resMan, _ports, _screen, _palette, pictureId, _EGAdrawingVisualize);
|
|
|
|
|
|
|
|
// do we add to a picture? if not -> clear screen with white
|
|
|
|
if (!addToFlag)
|
|
|
|
clearScreen(_screen->getColorWhite());
|
|
|
|
|
|
|
|
picture->draw(animationNr, mirroredFlag, addToFlag, paletteId);
|
|
|
|
delete picture;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This one is the only one that updates screen!
|
|
|
|
void GfxPaint16::drawCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) {
|
|
|
|
View *view = _cache->getView(viewId);
|
|
|
|
Common::Rect celRect;
|
|
|
|
|
|
|
|
if (view) {
|
|
|
|
celRect.left = leftPos;
|
|
|
|
celRect.top = topPos;
|
|
|
|
celRect.right = celRect.left + view->getWidth(loopNo, celNo);
|
|
|
|
celRect.bottom = celRect.top + view->getHeight(loopNo, celNo);
|
|
|
|
|
|
|
|
drawCel(view, loopNo, celNo, celRect, priority, paletteNo, scaleX, scaleY);
|
|
|
|
|
|
|
|
if (getSciVersion() >= SCI_VERSION_1_1) {
|
|
|
|
if (!_screen->_picNotValidSci11) {
|
|
|
|
bitsShow(celRect);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!_screen->_picNotValid)
|
|
|
|
bitsShow(celRect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This version of drawCel is not supposed to call BitsShow()!
|
|
|
|
void GfxPaint16::drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) {
|
|
|
|
drawCel(_cache->getView(viewId), loopNo, celNo, celRect, priority, paletteNo, scaleX, scaleY);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This version of drawCel is not supposed to call BitsShow()!
|
|
|
|
void GfxPaint16::drawCel(View *view, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) {
|
|
|
|
Common::Rect clipRect = celRect;
|
|
|
|
clipRect.clip(_ports->_curPort->rect);
|
|
|
|
if (clipRect.isEmpty()) // nothing to draw
|
|
|
|
return;
|
|
|
|
|
|
|
|
Common::Rect clipRectTranslated = clipRect;
|
|
|
|
_ports->offsetRect(clipRectTranslated);
|
|
|
|
if (scaleX == 128 && scaleY == 128) {
|
|
|
|
view->draw(celRect, clipRect, clipRectTranslated, loopNo, celNo, priority, paletteNo, false);
|
|
|
|
} else {
|
|
|
|
view->drawScaled(celRect, clipRect, clipRectTranslated, loopNo, celNo, priority, scaleX, scaleY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is used as replacement for drawCelAndShow() when hires-cels are drawn to screen
|
|
|
|
// Hires-cels are available only SCI 1.1+
|
|
|
|
void GfxPaint16::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, reg_t upscaledHiresHandle, uint16 scaleX, uint16 scaleY) {
|
|
|
|
View *view = _cache->getView(viewId);
|
|
|
|
Common::Rect celRect, curPortRect, clipRect, clipRectTranslated;
|
|
|
|
Common::Point curPortPos;
|
|
|
|
bool upscaledHiresHack = false;
|
|
|
|
|
|
|
|
if (view) {
|
|
|
|
if ((leftPos == 0) && (topPos == 0)) {
|
|
|
|
// HACK: in kq6, we get leftPos&topPos == 0 SOMETIMES, that's why we need to get coordinates from upscaledHiresHandle
|
|
|
|
// I'm not sure if this is what we are supposed to do or if there is some other bug that actually makes
|
|
|
|
// coordinates to be 0 in the first place
|
|
|
|
byte *memoryPtr = NULL;
|
|
|
|
memoryPtr = kmem(_segMan, upscaledHiresHandle);
|
|
|
|
if (memoryPtr) {
|
|
|
|
Common::Rect upscaledHiresRect;
|
|
|
|
_screen->bitsGetRect(memoryPtr, &upscaledHiresRect);
|
|
|
|
leftPos = upscaledHiresRect.left;
|
|
|
|
topPos = upscaledHiresRect.top;
|
|
|
|
upscaledHiresHack = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
celRect.left = leftPos;
|
|
|
|
celRect.top = topPos;
|
|
|
|
celRect.right = celRect.left + view->getWidth(loopNo, celNo);
|
|
|
|
celRect.bottom = celRect.top + view->getHeight(loopNo, celNo);
|
|
|
|
// adjust curPort to upscaled hires
|
|
|
|
clipRect = celRect;
|
|
|
|
curPortRect = _ports->_curPort->rect;
|
|
|
|
curPortRect.top *= 2; curPortRect.bottom *= 2; curPortRect.bottom++;
|
|
|
|
curPortRect.left *= 2; curPortRect.right *= 2; curPortRect.right++;
|
|
|
|
clipRect.clip(curPortRect);
|
|
|
|
if (clipRect.isEmpty()) // nothing to draw
|
|
|
|
return;
|
|
|
|
|
|
|
|
clipRectTranslated = clipRect;
|
|
|
|
if (!upscaledHiresHack) {
|
|
|
|
curPortPos.x = _ports->_curPort->left * 2; curPortPos.y = _ports->_curPort->top * 2;
|
|
|
|
clipRectTranslated.top += curPortPos.y; clipRectTranslated.bottom += curPortPos.y;
|
|
|
|
clipRectTranslated.left += curPortPos.x; clipRectTranslated.right += curPortPos.x;
|
|
|
|
}
|
|
|
|
|
|
|
|
view->draw(celRect, clipRect, clipRectTranslated, loopNo, celNo, priority, paletteNo, true);
|
|
|
|
if (!_screen->_picNotValidSci11) {
|
|
|
|
_screen->copyDisplayRectToScreen(clipRectTranslated);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::clearScreen(byte color) {
|
|
|
|
fillRect(_ports->_curPort->rect, SCI_SCREEN_MASK_ALL, color, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::invertRect(const Common::Rect &rect) {
|
|
|
|
int16 oldpenmode = _ports->_curPort->penMode;
|
|
|
|
_ports->_curPort->penMode = 2;
|
|
|
|
fillRect(rect, 1, _ports->_curPort->penClr, _ports->_curPort->backClr);
|
|
|
|
_ports->_curPort->penMode = oldpenmode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::eraseRect(const Common::Rect &rect) {
|
|
|
|
fillRect(rect, 1, _ports->_curPort->backClr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::paintRect(const Common::Rect &rect) {
|
|
|
|
fillRect(rect, 1, _ports->_curPort->penClr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::fillRect(const Common::Rect &rect, int16 drawFlags, byte clrPen, byte clrBack, byte bControl) {
|
|
|
|
Common::Rect r = rect;
|
|
|
|
r.clip(_ports->_curPort->rect);
|
|
|
|
if (r.isEmpty()) // nothing to fill
|
|
|
|
return;
|
|
|
|
|
|
|
|
int16 oldPenMode = _ports->_curPort->penMode;
|
|
|
|
_ports->offsetRect(r);
|
|
|
|
int16 x, y;
|
|
|
|
byte curVisual;
|
|
|
|
|
|
|
|
// Doing visual first
|
|
|
|
if (drawFlags & SCI_SCREEN_MASK_VISUAL) {
|
|
|
|
if (oldPenMode == 2) { // invert mode
|
|
|
|
for (y = r.top; y < r.bottom; y++) {
|
|
|
|
for (x = r.left; x < r.right; x++) {
|
|
|
|
curVisual = _screen->getVisual(x, y);
|
|
|
|
if (curVisual == clrPen) {
|
|
|
|
_screen->putPixel(x, y, 1, clrBack, 0, 0);
|
|
|
|
} else if (curVisual == clrBack) {
|
|
|
|
_screen->putPixel(x, y, 1, clrPen, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else { // just fill rect with ClrPen
|
|
|
|
for (y = r.top; y < r.bottom; y++) {
|
|
|
|
for (x = r.left; x < r.right; x++) {
|
|
|
|
_screen->putPixel(x, y, 1, clrPen, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (drawFlags < 2)
|
|
|
|
return;
|
|
|
|
drawFlags &= SCI_SCREEN_MASK_PRIORITY|SCI_SCREEN_MASK_CONTROL;
|
|
|
|
|
|
|
|
if (oldPenMode != 2) {
|
|
|
|
for (y = r.top; y < r.bottom; y++) {
|
|
|
|
for (x = r.left; x < r.right; x++) {
|
|
|
|
_screen->putPixel(x, y, drawFlags, 0, clrBack, bControl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (y = r.top; y < r.bottom; y++) {
|
|
|
|
for (x = r.left; x < r.right; x++) {
|
|
|
|
_screen->putPixel(x, y, drawFlags, 0, !_screen->getPriority(x, y), !_screen->getControl(x, y));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::frameRect(const Common::Rect &rect) {
|
|
|
|
Common::Rect r;
|
|
|
|
// left
|
|
|
|
r = rect;
|
|
|
|
r.right = rect.left + 1;
|
|
|
|
paintRect(r);
|
|
|
|
// right
|
|
|
|
r.right = rect.right;
|
|
|
|
r.left = rect.right - 1;
|
|
|
|
paintRect(r);
|
|
|
|
//top
|
|
|
|
r.left = rect.left;
|
|
|
|
r.bottom = rect.top + 1;
|
|
|
|
paintRect(r);
|
|
|
|
//bottom
|
|
|
|
r.bottom = rect.bottom;
|
|
|
|
r.top = rect.bottom - 1;
|
|
|
|
paintRect(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::bitsShow(const Common::Rect &rect) {
|
|
|
|
Common::Rect workerRect(rect.left, rect.top, rect.right, rect.bottom);
|
|
|
|
workerRect.clip(_ports->_curPort->rect);
|
|
|
|
if (workerRect.isEmpty()) // nothing to show
|
|
|
|
return;
|
|
|
|
|
|
|
|
_ports->offsetRect(workerRect);
|
|
|
|
_screen->copyRectToScreen(workerRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::bitsShowHires(const Common::Rect &rect) {
|
|
|
|
_screen->copyDisplayRectToScreen(rect);
|
|
|
|
}
|
|
|
|
|
|
|
|
reg_t GfxPaint16::bitsSave(const Common::Rect &rect, byte screenMask) {
|
|
|
|
reg_t memoryId;
|
|
|
|
byte *memoryPtr;
|
|
|
|
int size;
|
|
|
|
|
|
|
|
Common::Rect workerRect(rect.left, rect.top, rect.right, rect.bottom);
|
|
|
|
workerRect.clip(_ports->_curPort->rect);
|
|
|
|
if (workerRect.isEmpty()) // nothing to save
|
|
|
|
return NULL_REG;
|
|
|
|
|
|
|
|
if (screenMask == SCI_SCREEN_MASK_DISPLAY) {
|
|
|
|
// Adjust rect to upscaled hires, but dont adjust according to port
|
|
|
|
workerRect.top *= 2; workerRect.bottom *= 2; workerRect.bottom++;
|
|
|
|
workerRect.left *= 2; workerRect.right *= 2; workerRect.right++;
|
|
|
|
} else {
|
|
|
|
_ports->offsetRect(workerRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
// now actually ask _screen how much space it will need for saving
|
|
|
|
size = _screen->bitsGetDataSize(workerRect, screenMask);
|
|
|
|
|
|
|
|
memoryId = kalloc(_segMan, "SaveBits()", size);
|
|
|
|
memoryPtr = kmem(_segMan, memoryId);
|
|
|
|
_screen->bitsSave(workerRect, screenMask, memoryPtr);
|
|
|
|
return memoryId;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::bitsGetRect(reg_t memoryHandle, Common::Rect *destRect) {
|
|
|
|
byte *memoryPtr = NULL;
|
|
|
|
|
|
|
|
if (!memoryHandle.isNull()) {
|
|
|
|
memoryPtr = kmem(_segMan, memoryHandle);
|
|
|
|
|
|
|
|
if (memoryPtr) {
|
|
|
|
_screen->bitsGetRect(memoryPtr, destRect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::bitsRestore(reg_t memoryHandle) {
|
|
|
|
byte *memoryPtr = NULL;
|
|
|
|
|
|
|
|
if (!memoryHandle.isNull()) {
|
|
|
|
memoryPtr = kmem(_segMan, memoryHandle);
|
|
|
|
|
|
|
|
if (memoryPtr) {
|
|
|
|
_screen->bitsRestore(memoryPtr);
|
|
|
|
kfree(_segMan, memoryHandle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GfxPaint16::bitsFree(reg_t memoryHandle) {
|
|
|
|
if (!memoryHandle.isNull()) {
|
|
|
|
kfree(_segMan, memoryHandle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // End of namespace Sci
|