mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-25 19:25:20 +00:00
e1c36a52b5
- User option to force Hercules hires font for any rendering mode - Also change mouse cursor hotspots from 1,1 to 0,0 - Fix inaccuracy in mouse controlled game menu - Change render_Block(), drawBox(), drawDisplayRect() to use upper Y instead of lower Y. Original AGI uses lower Y, but upper Y makes upscaling way easier.
554 lines
16 KiB
C++
554 lines
16 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 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 "agi/agi.h"
|
|
#include "agi/sprite.h"
|
|
#include "agi/graphics.h"
|
|
#include "agi/text.h"
|
|
|
|
namespace Agi {
|
|
|
|
SpritesMgr::SpritesMgr(AgiEngine *agi, GfxMgr *gfx) {
|
|
_vm = agi;
|
|
_gfx = gfx;
|
|
}
|
|
|
|
SpritesMgr::~SpritesMgr() {
|
|
_spriteRegularList.clear();
|
|
_spriteStaticList.clear();
|
|
}
|
|
|
|
static bool sortSpriteHelper(const Sprite &entry1, const Sprite &entry2) {
|
|
if (entry1.sortOrder == entry2.sortOrder) {
|
|
// If sort-order is the same, we sort according to given order
|
|
// which makes this sort stable.
|
|
return entry1.givenOrderNr < entry2.givenOrderNr;
|
|
}
|
|
return entry1.sortOrder < entry2.sortOrder;
|
|
}
|
|
|
|
void SpritesMgr::buildRegularSpriteList() {
|
|
ScreenObjEntry *screenObj = NULL;
|
|
uint16 givenOrderNr = 0;
|
|
|
|
freeList(_spriteRegularList);
|
|
for (screenObj = _vm->_game.screenObjTable; screenObj < &_vm->_game.screenObjTable[SCREENOBJECTS_MAX]; screenObj++) {
|
|
if ((screenObj->flags & (fAnimated | fUpdate | fDrawn)) == (fAnimated | fUpdate | fDrawn)) {
|
|
buildSpriteListAdd(givenOrderNr, screenObj, _spriteRegularList);
|
|
givenOrderNr++;
|
|
}
|
|
}
|
|
|
|
// Now sort this list
|
|
Common::sort(_spriteRegularList.begin(), _spriteRegularList.end(), sortSpriteHelper);
|
|
// warning("buildRegular: %d", _spriteRegularList.size());
|
|
}
|
|
|
|
void SpritesMgr::buildStaticSpriteList() {
|
|
ScreenObjEntry *screenObj = NULL;
|
|
uint16 givenOrderNr = 0;
|
|
|
|
freeList(_spriteStaticList);
|
|
for (screenObj = _vm->_game.screenObjTable; screenObj < &_vm->_game.screenObjTable[SCREENOBJECTS_MAX]; screenObj++) {
|
|
if ((screenObj->flags & (fAnimated | fUpdate | fDrawn)) == (fAnimated | fDrawn)) { // DIFFERENCE IN HERE!
|
|
buildSpriteListAdd(givenOrderNr, screenObj, _spriteStaticList);
|
|
givenOrderNr++;
|
|
}
|
|
}
|
|
|
|
// Now sort this list
|
|
Common::sort(_spriteStaticList.begin(), _spriteStaticList.end(), sortSpriteHelper);
|
|
}
|
|
|
|
void SpritesMgr::buildAllSpriteLists() {
|
|
buildStaticSpriteList();
|
|
buildRegularSpriteList();
|
|
}
|
|
|
|
void SpritesMgr::buildSpriteListAdd(uint16 givenOrderNr, ScreenObjEntry *screenObj, SpriteList &spriteList) {
|
|
Sprite spriteEntry;
|
|
|
|
// Check, if screen object points to currently loaded view, if not don't add it
|
|
if (!(_vm->_game.dirView[screenObj->currentViewNr].flags & RES_LOADED))
|
|
return;
|
|
|
|
spriteEntry.givenOrderNr = givenOrderNr;
|
|
// warning("sprite add objNr %d", screenObjPtr->objectNr);
|
|
if (screenObj->flags & fFixedPriority) {
|
|
spriteEntry.sortOrder = _gfx->priorityToY(screenObj->priority);
|
|
// warning(" - priorityToY (fixed) %d -> %d", screenObj->priority, spriteEntry.sortOrder);
|
|
} else {
|
|
spriteEntry.sortOrder = screenObj->yPos;
|
|
// warning(" - Ypos %d -> %d", screenObjPtr->yPos, spriteEntry.sortOrder);
|
|
}
|
|
|
|
spriteEntry.screenObjPtr = screenObj;
|
|
spriteEntry.xPos = screenObj->xPos;
|
|
spriteEntry.yPos = (screenObj->yPos) - (screenObj->ySize) + 1;
|
|
spriteEntry.xSize = screenObj->xSize;
|
|
spriteEntry.ySize = screenObj->ySize;
|
|
|
|
// Checking, if xPos/yPos/right/bottom are valid and do not go outside of playscreen (visual screen)
|
|
// Original AGI did not do this (but it then resulted in memory corruption)
|
|
if (spriteEntry.xPos < 0) {
|
|
warning("buildSpriteListAdd(): ignoring screen obj %d, b/c xPos (%d) < 0", screenObj->objectNr, spriteEntry.xPos);
|
|
return;
|
|
}
|
|
if (spriteEntry.yPos < 0) {
|
|
warning("buildSpriteListAdd(): ignoring screen obj %d, b/c yPos (%d) < 0", screenObj->objectNr, spriteEntry.yPos);
|
|
return;
|
|
}
|
|
int16 xRight = spriteEntry.xPos + spriteEntry.xSize;
|
|
if (xRight > SCRIPT_HEIGHT) {
|
|
warning("buildSpriteListAdd(): ignoring screen obj %d, b/c rightPos (%d) > %d", screenObj->objectNr, xRight, SCRIPT_WIDTH);
|
|
return;
|
|
}
|
|
int16 yBottom = spriteEntry.yPos + spriteEntry.ySize;
|
|
if (yBottom > SCRIPT_HEIGHT) {
|
|
warning("buildSpriteListAdd(): ignoring screen obj %d, b/c bottomPos (%d) > %d", screenObj->objectNr, yBottom, SCRIPT_HEIGHT);
|
|
return;
|
|
}
|
|
|
|
// warning("list-add: %d, %d, original yPos: %d, ySize: %d", spriteEntry.xPos, spriteEntry.yPos, screenObj->yPos, screenObj->ySize);
|
|
spriteEntry.backgroundBuffer = (uint8 *)malloc(spriteEntry.xSize * spriteEntry.ySize * 2); // for visual + priority data
|
|
assert(spriteEntry.backgroundBuffer);
|
|
spriteList.push_back(spriteEntry);
|
|
}
|
|
|
|
void SpritesMgr::freeList(SpriteList &spriteList) {
|
|
SpriteList::iterator iter;
|
|
for (iter = spriteList.reverse_begin(); iter != spriteList.end(); iter--) {
|
|
Sprite &sprite = *iter;
|
|
|
|
free(sprite.backgroundBuffer);
|
|
}
|
|
spriteList.clear();
|
|
}
|
|
|
|
void SpritesMgr::freeRegularSprites() {
|
|
freeList(_spriteRegularList);
|
|
}
|
|
|
|
void SpritesMgr::freeStaticSprites() {
|
|
freeList(_spriteStaticList);
|
|
}
|
|
|
|
void SpritesMgr::freeAllSprites() {
|
|
freeList(_spriteRegularList);
|
|
freeList(_spriteStaticList);
|
|
}
|
|
|
|
void SpritesMgr::eraseSprites(SpriteList &spriteList) {
|
|
SpriteList::iterator iter;
|
|
// warning("eraseSprites - count %d", spriteList.size());
|
|
for (iter = spriteList.reverse_begin(); iter != spriteList.end(); iter--) {
|
|
Sprite &sprite = *iter;
|
|
_gfx->block_restore(sprite.xPos, sprite.yPos, sprite.xSize, sprite.ySize, sprite.backgroundBuffer);
|
|
}
|
|
|
|
freeList(spriteList);
|
|
}
|
|
|
|
/**
|
|
* Erase updating sprites.
|
|
* This function follows the list of all updating sprites and restores
|
|
* the visible and priority data of their background buffers back to
|
|
* the AGI screen.
|
|
*
|
|
* @see erase_nonupd_sprites()
|
|
* @see erase_both()
|
|
*/
|
|
void SpritesMgr::eraseRegularSprites() {
|
|
eraseSprites(_spriteRegularList);
|
|
}
|
|
|
|
void SpritesMgr::eraseStaticSprites() {
|
|
eraseSprites(_spriteStaticList);
|
|
}
|
|
|
|
void SpritesMgr::eraseSprites() {
|
|
eraseSprites(_spriteRegularList);
|
|
eraseSprites(_spriteStaticList);
|
|
}
|
|
|
|
/**
|
|
* Draw all sprites in the given list.
|
|
*/
|
|
void SpritesMgr::drawSprites(SpriteList &spriteList) {
|
|
SpriteList::iterator iter;
|
|
// warning("drawSprites");
|
|
|
|
for (iter = spriteList.begin(); iter != spriteList.end(); ++iter) {
|
|
Sprite &sprite = *iter;
|
|
ScreenObjEntry *screenObj = sprite.screenObjPtr;
|
|
|
|
_gfx->block_save(sprite.xPos, sprite.yPos, sprite.xSize, sprite.ySize, sprite.backgroundBuffer);
|
|
//debugC(8, kDebugLevelSprites, "drawSprites(): s->v->entry = %d (prio %d)", s->viewPtr->entry, s->viewPtr->priority);
|
|
// warning("sprite %d (view %d), priority %d, sort %d, givenOrder %d", screenObj->objectNr, screenObj->currentView, screenObj->priority, sprite.sortOrder, sprite.givenOrderNr);
|
|
drawCel(screenObj);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Blit updating sprites.
|
|
* This function follows the list of all updating sprites and blits
|
|
* them on the AGI screen.
|
|
*
|
|
* @see blit_nonupd_sprites()
|
|
* @see blit_both()
|
|
*/
|
|
void SpritesMgr::drawRegularSpriteList() {
|
|
debugC(7, kDebugLevelSprites, "drawRegularSpriteList()");
|
|
drawSprites(_spriteRegularList);
|
|
}
|
|
|
|
void SpritesMgr::drawStaticSpriteList() {
|
|
//debugC(7, kDebugLevelSprites, "drawRegularSpriteList()");
|
|
drawSprites(_spriteStaticList);
|
|
}
|
|
|
|
void SpritesMgr::drawAllSpriteLists() {
|
|
drawSprites(_spriteStaticList);
|
|
drawSprites(_spriteRegularList);
|
|
}
|
|
|
|
void SpritesMgr::drawCel(ScreenObjEntry *screenObj) {
|
|
int16 curX = screenObj->xPos;
|
|
int16 baseX = screenObj->xPos;
|
|
int16 curY = screenObj->yPos;
|
|
AgiViewCel *celPtr = screenObj->celData;
|
|
byte *celDataPtr = celPtr->rawBitmap;
|
|
uint8 remainingCelHeight = celPtr->height;
|
|
uint8 celWidth = celPtr->width;
|
|
byte celClearKey = celPtr->clearKey;
|
|
byte viewPriority = screenObj->priority;
|
|
byte screenPriority = 0;
|
|
byte curColor = 0;
|
|
byte isViewHidden = true;
|
|
|
|
// Adjust vertical position, given yPos is lower left, but we need upper left
|
|
curY = curY - celPtr->height + 1;
|
|
|
|
while (remainingCelHeight) {
|
|
for (int16 loopX = 0; loopX < celWidth; loopX++) {
|
|
curColor = *celDataPtr++;
|
|
|
|
if (curColor != celClearKey) {
|
|
screenPriority = _gfx->getPriority(curX, curY);
|
|
if (screenPriority <= 2) {
|
|
// control data found
|
|
if (_gfx->checkControlPixel(curX, curY, viewPriority)) {
|
|
_gfx->putPixel(curX, curY, GFX_SCREEN_MASK_VISUAL, curColor, 0);
|
|
isViewHidden = false;
|
|
}
|
|
} else if (screenPriority <= viewPriority) {
|
|
_gfx->putPixel(curX, curY, GFX_SCREEN_MASK_ALL, curColor, viewPriority);
|
|
isViewHidden = false;
|
|
}
|
|
|
|
}
|
|
curX++;
|
|
}
|
|
|
|
// go to next vertical position
|
|
remainingCelHeight--;
|
|
curX = baseX;
|
|
curY++;
|
|
}
|
|
|
|
if (screenObj->objectNr == 0) { // if ego, update if ego is visible at the moment
|
|
_vm->setFlag(VM_FLAG_EGO_INVISIBLE, isViewHidden);
|
|
}
|
|
}
|
|
|
|
|
|
void SpritesMgr::showSprite(ScreenObjEntry *screenObj) {
|
|
int16 x = 0;
|
|
int16 y = 0;
|
|
int16 width = 0;
|
|
int16 height = 0;
|
|
|
|
int16 view_height_prev = 0;
|
|
int16 view_width_prev = 0;
|
|
|
|
int16 y2 = 0;
|
|
int16 height1 = 0;
|
|
int16 height2 = 0;
|
|
|
|
int16 x2 = 0;
|
|
int16 width1 = 0;
|
|
int16 width2 = 0;
|
|
|
|
if (!_vm->_game.pictureShown)
|
|
return;
|
|
|
|
view_height_prev = screenObj->ySize_prev;
|
|
view_width_prev = screenObj->xSize_prev;
|
|
|
|
screenObj->ySize_prev = screenObj->ySize;
|
|
screenObj->xSize_prev = screenObj->xSize;
|
|
|
|
if (screenObj->yPos < screenObj->yPos_prev) {
|
|
y = screenObj->yPos_prev;
|
|
y2 = screenObj->yPos;
|
|
|
|
height1 = view_height_prev;
|
|
height2 = screenObj->ySize;
|
|
} else {
|
|
y = screenObj->yPos;
|
|
y2 = screenObj->yPos_prev;
|
|
|
|
height1 = screenObj->ySize;
|
|
height2 = view_height_prev;
|
|
}
|
|
|
|
if ((y2 - height2) > (y - height1)) {
|
|
height = height1;
|
|
} else {
|
|
height = y - y2 + height2;
|
|
}
|
|
|
|
if (screenObj->xPos > screenObj->xPos_prev) {
|
|
x = screenObj->xPos_prev;
|
|
x2 = screenObj->xPos;
|
|
width1 = view_width_prev;
|
|
width2 = screenObj->xSize;
|
|
} else {
|
|
x = screenObj->xPos;
|
|
x2 = screenObj->xPos_prev;
|
|
width1 = screenObj->xSize;
|
|
width2 = view_width_prev;
|
|
}
|
|
|
|
if ((x2 + width2) < (x + width1)) {
|
|
width = width1;
|
|
} else {
|
|
width = width2 + x2 - x;
|
|
}
|
|
|
|
if ((x + width) > 161) {
|
|
width = 161 - x;
|
|
}
|
|
|
|
if (1 < (height - y)) {
|
|
height = y + 1;
|
|
}
|
|
|
|
// render this block
|
|
int16 upperY = y - height + 1;
|
|
_gfx->render_Block(x, upperY, width, height);
|
|
}
|
|
|
|
void SpritesMgr::showSprites(SpriteList &spriteList) {
|
|
SpriteList::iterator iter;
|
|
ScreenObjEntry *screenObjPtr = NULL;
|
|
|
|
for (iter = spriteList.begin(); iter != spriteList.end(); ++iter) {
|
|
Sprite &sprite = *iter;
|
|
screenObjPtr = sprite.screenObjPtr;
|
|
|
|
showSprite(screenObjPtr);
|
|
|
|
if (screenObjPtr->stepTimeCount == screenObjPtr->stepTime) {
|
|
if ((screenObjPtr->xPos == screenObjPtr->xPos_prev) && (screenObjPtr->yPos == screenObjPtr->yPos_prev)) {
|
|
screenObjPtr->flags |= fDidntMove;
|
|
} else {
|
|
screenObjPtr->xPos_prev = screenObjPtr->xPos;
|
|
screenObjPtr->yPos_prev = screenObjPtr->yPos;
|
|
screenObjPtr->flags &= ~fDidntMove;
|
|
}
|
|
}
|
|
}
|
|
g_system->updateScreen();
|
|
//g_system->delayMillis(20);
|
|
}
|
|
|
|
void SpritesMgr::showRegularSpriteList() {
|
|
debugC(7, kDebugLevelSprites, "showRegularSpriteList()");
|
|
showSprites(_spriteRegularList);
|
|
}
|
|
|
|
void SpritesMgr::showStaticSpriteList() {
|
|
debugC(7, kDebugLevelSprites, "showStaticSpriteList()");
|
|
showSprites(_spriteStaticList);
|
|
}
|
|
|
|
void SpritesMgr::showAllSpriteLists() {
|
|
showSprites(_spriteStaticList);
|
|
showSprites(_spriteRegularList);
|
|
}
|
|
|
|
/**
|
|
* Show object and description
|
|
* This function shows an object from the player's inventory, displaying
|
|
* a message box with the object description.
|
|
* @param n Number of the object to show
|
|
*/
|
|
void SpritesMgr::showObject(int16 viewNr) {
|
|
ScreenObjEntry screenObj;
|
|
uint8 *backgroundBuffer = NULL;
|
|
|
|
_vm->agiLoadResource(RESOURCETYPE_VIEW, viewNr);
|
|
_vm->setView(&screenObj, viewNr);
|
|
|
|
screenObj.ySize_prev = screenObj.celData->height;
|
|
screenObj.xSize_prev = screenObj.celData->width;
|
|
screenObj.xPos_prev = ((SCRIPT_WIDTH - 1) - screenObj.xSize) / 2;
|
|
screenObj.xPos = screenObj.xPos_prev;
|
|
screenObj.yPos_prev = SCRIPT_HEIGHT - 1;
|
|
screenObj.yPos = screenObj.yPos_prev;
|
|
screenObj.priority = 15;
|
|
screenObj.flags = fFixedPriority; // Original AGI did "| fFixedPriority" on uninitialized memory
|
|
screenObj.objectNr = 255; // ???
|
|
|
|
backgroundBuffer = (uint8 *)malloc(screenObj.xSize * screenObj.ySize * 2); // for visual + priority data
|
|
|
|
_gfx->block_save(screenObj.xPos, (screenObj.yPos - screenObj.ySize + 1), screenObj.xSize, screenObj.ySize, backgroundBuffer);
|
|
drawCel(&screenObj);
|
|
showSprite(&screenObj);
|
|
|
|
_vm->_text->messageBox((char *)_vm->_game.views[viewNr].description);
|
|
|
|
_gfx->block_restore(screenObj.xPos, (screenObj.yPos - screenObj.ySize + 1), screenObj.xSize, screenObj.ySize, backgroundBuffer);
|
|
showSprite(&screenObj);
|
|
|
|
free(backgroundBuffer);
|
|
}
|
|
|
|
/**
|
|
* Add view to picture.
|
|
* This function is used to implement the add.to.pic AGI command. It
|
|
* copies the specified cel from a view resource on the current picture.
|
|
* This cel is not a sprite, it can't be moved or removed.
|
|
* @param view number of view resource
|
|
* @param loop number of loop in the specified view resource
|
|
* @param cel number of cel in the specified loop
|
|
* @param x x coordinate to place the view
|
|
* @param y y coordinate to place the view
|
|
* @param pri priority to use
|
|
* @param mar if < 4, create a margin around the the base of the cel
|
|
*/
|
|
void SpritesMgr::addToPic(int16 viewNr, int16 loopNr, int16 celNr, int16 xPos, int16 yPos, int16 priority, int16 border) {
|
|
debugC(3, kDebugLevelSprites, "addToPic(view=%d, loop=%d, cel=%d, x=%d, y=%d, pri=%d, border=%d)", viewNr, loopNr, celNr, xPos, yPos, priority, border);
|
|
|
|
_vm->recordImageStackCall(ADD_VIEW, viewNr, loopNr, celNr, xPos, yPos, priority, border);
|
|
|
|
ScreenObjEntry *screenObj = &_vm->_game.addToPicView;
|
|
screenObj->objectNr = -1; // addToPic-view
|
|
|
|
_vm->setView(screenObj, viewNr);
|
|
_vm->setLoop(screenObj, loopNr);
|
|
_vm->setCel(screenObj, celNr);
|
|
|
|
screenObj->xSize_prev = screenObj->xSize;
|
|
screenObj->ySize_prev = screenObj->ySize;
|
|
screenObj->xPos_prev = xPos;
|
|
screenObj->xPos = xPos;
|
|
screenObj->yPos_prev = yPos;
|
|
screenObj->yPos = yPos;
|
|
screenObj->flags = fIgnoreObjects | fIgnoreHorizon | fFixedPriority;
|
|
screenObj->priority = 15;
|
|
_vm->fixPosition(screenObj);
|
|
if (priority == 0) {
|
|
screenObj->flags = fIgnoreHorizon;
|
|
}
|
|
screenObj->priority = priority;
|
|
|
|
eraseSprites();
|
|
|
|
// bugs related to this code: required by Gold Rush (see Sarien bug #587558)
|
|
if (screenObj->priority == 0) {
|
|
screenObj->priority = _gfx->priorityFromY(screenObj->yPos);
|
|
}
|
|
drawCel(screenObj);
|
|
|
|
if (border <= 3) {
|
|
// Create priority-box
|
|
addToPicDrawPriorityBox(screenObj, border);
|
|
}
|
|
buildAllSpriteLists();
|
|
drawAllSpriteLists();
|
|
showSprite(screenObj);
|
|
}
|
|
|
|
// bugs previously related to this:
|
|
// Sarien bug #247)
|
|
void SpritesMgr::addToPicDrawPriorityBox(ScreenObjEntry *screenObj, int16 border) {
|
|
int16 priorityFromY = _gfx->priorityFromY(screenObj->yPos);
|
|
int16 priorityHeight = 0;
|
|
int16 curY = 0;
|
|
int16 curX = 0;
|
|
int16 height = 0;
|
|
int16 width = 0;
|
|
int16 offsetX = 0;
|
|
|
|
// Figure out the height of the box
|
|
curY = screenObj->yPos;
|
|
do {
|
|
priorityHeight++;
|
|
if (curY <= 0)
|
|
break;
|
|
curY--;
|
|
} while (_gfx->priorityFromY(curY) == priorityFromY);
|
|
|
|
// box height may not be larger than the actual view
|
|
if (screenObj->ySize < priorityHeight)
|
|
priorityHeight = screenObj->ySize;
|
|
|
|
// now actually draw lower horizontal line
|
|
curY = screenObj->yPos;
|
|
curX = screenObj->xPos;
|
|
|
|
width = screenObj->xSize;
|
|
while (width) {
|
|
_gfx->putPixel(curX, curY, GFX_SCREEN_MASK_PRIORITY, 0, border);
|
|
curX++;
|
|
width--;
|
|
}
|
|
|
|
if (priorityHeight > 1) {
|
|
// Actual rectangle is needed
|
|
curY = screenObj->yPos;
|
|
curX = screenObj->xPos;
|
|
offsetX = screenObj->xSize - 1;
|
|
|
|
height = priorityHeight - 1;
|
|
while (height) {
|
|
curY--;
|
|
height--;
|
|
_gfx->putPixel(curX, curY, GFX_SCREEN_MASK_PRIORITY, 0, border); // left line
|
|
_gfx->putPixel(curX + offsetX, curY, GFX_SCREEN_MASK_PRIORITY, 0, border); // right line
|
|
}
|
|
|
|
// and finally the upper horizontal line
|
|
width = screenObj->xSize - 2;
|
|
curX++;
|
|
while (width > 0) {
|
|
_gfx->putPixel(curX, curY, GFX_SCREEN_MASK_PRIORITY, 0, border);
|
|
curX++;
|
|
width--;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // End of namespace Agi
|