scummvm/engines/tony/gfxcore.cpp
2012-05-21 23:54:32 +02:00

1961 lines
39 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.
*
*/
/*
* This code is based on original Tony Tough source code
*
* Copyright (c) 1997-2003 Nayma Software
*/
#include "tony/gfxengine.h"
#include "tony/mpal/mpalutils.h"
#include "tony/tony.h"
namespace Tony {
/****************************************************************************\
* RMGfxTask Methods
\****************************************************************************/
RMGfxTask::RMGfxTask() {
m_nPrior = 0;
m_nInList = 0;
}
int RMGfxTask::Priority() {
return m_nPrior;
}
void RMGfxTask::RemoveThis(CORO_PARAM, bool &result) {
result = true;
}
/****************************************************************************\
* RMGfxTaskSetPrior Methods
\****************************************************************************/
void RMGfxTaskSetPrior::SetPriority(int nPrior) {
m_nPrior = nPrior;
}
/****************************************************************************\
* RMGfxBuffer Methods
\****************************************************************************/
RMGfxBuffer::RMGfxBuffer() {
m_dimx = m_dimy = 0;
m_bUseDDraw = false;
m_origBuf = m_buf = NULL;
}
RMGfxBuffer::~RMGfxBuffer() {
Destroy();
}
void RMGfxBuffer::Create(int dimx, int dimy, int nBpp, bool bUseDDraw) {
// Destroy the buffer it is already exists
if (m_buf != NULL)
Destroy();
// Copy the parameters in the private members
m_dimx = dimx;
m_dimy = dimy;
m_bUseDDraw = bUseDDraw;
if (!m_bUseDDraw) {
// Allocate a buffer
m_origBuf = m_buf = new byte[m_dimx * m_dimy * nBpp / 8];
assert(m_buf != NULL);
Common::fill(m_origBuf, m_origBuf + m_dimx * m_dimy * nBpp / 8, 0);
}
}
void RMGfxBuffer::Destroy(void) {
if (!m_bUseDDraw) {
if (m_origBuf != NULL && m_origBuf == m_buf) {
delete[] m_origBuf;
m_origBuf = m_buf = NULL;
}
}
}
void RMGfxBuffer::Lock(void) {
if (m_bUseDDraw) {
// Manages acceleration
}
}
void RMGfxBuffer::Unlock(void) {
if (m_bUseDDraw) {
// Manages acceleration
}
}
void RMGfxBuffer::OffsetY(int nLines, int nBpp) {
m_buf += nLines * Dimx() * nBpp / 8;
}
RMGfxBuffer::operator byte *() {
return m_buf;
}
RMGfxBuffer::operator void *() {
return (void *)m_buf;
}
RMGfxBuffer::RMGfxBuffer(int dimx, int dimy, int nBpp, bool bUseDDraw) {
Create(dimx, dimy, nBpp, bUseDDraw);
}
/****************************************************************************\
* RMGfxSourceBuffer Methods
\****************************************************************************/
int RMGfxSourceBuffer::Init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
Create(dimx, dimy, Bpp());
CopyMemory(m_buf, buf, dimx * dimy * Bpp() / 8);
// Invokes the method for preparing the surface (inherited)
PrepareImage();
return dimx * dimy * Bpp() / 8;
}
void RMGfxSourceBuffer::Init(RMDataStream &ds, int dimx, int dimy, bool bLoadPalette) {
Create(dimx, dimy, Bpp());
ds.Read(m_buf, dimx * dimy * Bpp() / 8);
// Invokes the method for preparing the surface (inherited)
PrepareImage();
}
RMGfxSourceBuffer::~RMGfxSourceBuffer() {
}
void RMGfxSourceBuffer::PrepareImage(void) {
// Do nothing. Can be overloaded if necessary
}
bool RMGfxSourceBuffer::Clip2D(int &x1, int &y1, int &u, int &v, int &width, int &height, bool bUseSrc, RMGfxTargetBuffer *buf) {
int destw, desth;
destw = buf->Dimx();
desth = buf->Dimy();
if (!bUseSrc) {
u = v = 0;
width = m_dimx;
height = m_dimy;
}
if (x1 > destw - 1)
return false;
if (y1 > desth - 1)
return false;
if (x1 < 0) {
width += x1;
if (width < 0)
return false;
u -= x1;
x1 = 0;
}
if (y1 < 0) {
height += y1;
if (height < 0)
return false;
v -= y1;
y1 = 0;
}
if (x1 + width - 1 > destw - 1)
width = destw - x1;
if (y1 + height - 1 > desth - 1)
height = desth - y1;
return true;
}
/**
* Initialises a surface by resource Id
*
* @param resID Resource ID
* @param dimx Buffer X dimension
* @param dimy Buffer Y dimension
*/
int RMGfxSourceBuffer::Init(uint32 resID, int dimx, int dimy, bool bLoadPalette) {
return Init(RMRes(resID), dimx, dimy, bLoadPalette);
}
/****************************************************************************\
* RMGfxWoodyBuffer Methods
\****************************************************************************/
RMGfxWoodyBuffer::~RMGfxWoodyBuffer() {
}
void RMGfxWoodyBuffer::Draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
// Draw the OT list
CORO_INVOKE_0(DrawOT);
// Draw itself into the target buffer
CORO_INVOKE_2(RMGfxSourceBuffer16::Draw, bigBuf, prim);
CORO_END_CODE;
}
RMGfxWoodyBuffer::RMGfxWoodyBuffer() {
}
RMGfxWoodyBuffer::RMGfxWoodyBuffer(int dimx, int dimy, bool bUseDDraw)
: RMGfxBuffer(dimx, dimy, 16, bUseDDraw) {
}
/****************************************************************************\
* RMGfxTargetBuffer Methods
\****************************************************************************/
RMGfxClearTask RMGfxTargetBuffer::taskClear;
RMGfxTargetBuffer::RMGfxTargetBuffer() {
otlist = NULL;
m_otSize = 0;
// csModifyingOT = g_system->createMutex();
}
RMGfxTargetBuffer::~RMGfxTargetBuffer() {
ClearOT();
// g_system->deleteMutex(csModifyingOT);
}
void RMGfxTargetBuffer::ClearOT(void) {
OTList *cur, *n;
// g_system->lockMutex(csModifyingOT);
cur = otlist;
while (cur != NULL) {
cur->prim->m_task->Unregister();
delete cur->prim;
n = cur->next;
delete cur;
cur = n;
}
otlist = NULL;
// g_system->unlockMutex(csModifyingOT);
}
void RMGfxTargetBuffer::DrawOT(CORO_PARAM) {
CORO_BEGIN_CONTEXT;
OTList *cur;
OTList *prev;
OTList *next;
RMGfxPrimitive *myprim;
bool result;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
_ctx->prev = NULL;
_ctx->cur = otlist;
// Lock the buffer to access it
Lock();
// g_system->lockMutex(csModifyingOT);
while (_ctx->cur != NULL) {
// Call the task Draw method, passing it a copy of the original
_ctx->myprim = _ctx->cur->prim->Duplicate();
CORO_INVOKE_2(_ctx->cur->prim->m_task->Draw, *this, _ctx->myprim);
delete _ctx->myprim;
// Check if it's time to remove the task from the OT list
CORO_INVOKE_1(_ctx->cur->prim->m_task->RemoveThis, _ctx->result);
if (_ctx->result) {
// De-register the task
_ctx->cur->prim->m_task->Unregister();
// Delete task, freeing the memory
delete _ctx->cur->prim;
_ctx->next = _ctx->cur->next;
delete _ctx->cur;
// If it was the first item, update the list head
if (_ctx->prev == NULL)
otlist = _ctx->next;
// Otherwise update the next pinter of the previous item
else
_ctx->prev->next = _ctx->next;
_ctx->cur = _ctx->next;
} else {
// Update the pointer to the previous item, and the current to the next
_ctx->prev = _ctx->cur;
_ctx->cur = _ctx->cur->next;
}
}
// g_system->unlockMutex(csModifyingOT);
//Unlock after writing
Unlock();
CORO_END_CODE;
}
void RMGfxTargetBuffer::AddPrim(RMGfxPrimitive *prim) {
int nPrior;
OTList *cur, *n;
// g_system->lockMutex(csModifyingOT);
// Warn of the OT listing
prim->m_task->Register();
// Check the priority
nPrior = prim->m_task->Priority();
n = new OTList(prim);
// Empty list
if (otlist == NULL) {
otlist = n;
otlist->next = NULL;
}
// Inclusion in the head
else if (nPrior < otlist->prim->m_task->Priority()) {
n->next = otlist;
otlist = n;
} else {
cur = otlist;
while (cur->next != NULL && nPrior > cur->next->prim->m_task->Priority())
cur = cur->next;
n->next = cur->next;
cur->next = n;
}
// g_system->unlockMutex(csModifyingOT);
}
void RMGfxTargetBuffer::AddClearTask(void) {
AddPrim(new RMGfxPrimitive(&taskClear));
}
/****************************************************************************\
* RMGfxSourceBufferPal Methods
\****************************************************************************/
RMGfxSourceBufferPal::~RMGfxSourceBufferPal() {
}
int RMGfxSourceBufferPal::LoadPaletteWA(const byte *buf, bool bSwapped) {
int i;
if (bSwapped)
for (i = 0; i < (1 << Bpp()); i++) {
m_pal[i * 3 + 0] = buf[i * 3 + 2];
m_pal[i * 3 + 1] = buf[i * 3 + 1];
m_pal[i * 3 + 2] = buf[i * 3 + 0];
}
else
CopyMemory(m_pal, buf, (1 << Bpp()) * 3);
PreparePalette();
return (1 << Bpp()) * 3;
}
int RMGfxSourceBufferPal::LoadPalette(const byte *buf) {
int i;
for (i = 0; i < 256; i++)
CopyMemory(m_pal + i * 3, buf + i * 4, 3);
PreparePalette();
return (1 << Bpp()) * 4;
}
void RMGfxSourceBufferPal::PreparePalette(void) {
int i;
for (i = 0; i < 256; i++) {
m_palFinal[i] = (((int)m_pal[i * 3 + 0] >> 3) << 10) |
(((int)m_pal[i * 3 + 1] >> 3) << 5) |
(((int)m_pal[i * 3 + 2] >> 3) << 0);
}
}
int RMGfxSourceBufferPal::Init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
int read;
// Load the RAW image
read = RMGfxSourceBuffer::Init(buf, dimx, dimy);
// Load the palette if necessary
if (bLoadPalette)
read += LoadPaletteWA(&buf[read]);
return read;
}
void RMGfxSourceBufferPal::Init(RMDataStream &ds, int dimx, int dimy, bool bLoadPalette) {
// Load the RAW image
RMGfxSourceBuffer::Init(ds, dimx, dimy);
// Load the palette if necessary
if (bLoadPalette) {
byte *suxpal = new byte[256 * 3];
ds.Read(suxpal, 256 * 3);
LoadPaletteWA(suxpal);
delete[] suxpal;
}
}
int RMGfxSourceBufferPal::LoadPalette(uint32 resID) {
return LoadPalette(RMRes(resID));
}
int RMGfxSourceBufferPal::LoadPaletteWA(uint32 resID, bool bSwapped) {
return LoadPaletteWA(RMRes(resID), bSwapped);
}
/****************************************************************************\
* RMGfxSourceBuffer4 Methods
\****************************************************************************/
void RMGfxSourceBuffer4::Draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
}
RMGfxSourceBuffer4::RMGfxSourceBuffer4(int dimx, int dimy, bool bUseDDraw)
: RMGfxBuffer(dimx, dimy, 4, bUseDDraw) {
SetPriority(0);
}
/**
* Returns the number of bits per pixel of the surface
*
* @returns Bit per pixel
*/
int RMGfxSourceBuffer4::Bpp() {
return 4;
}
void RMGfxSourceBuffer4::Create(int dimx, int dimy, bool bUseDDraw) {
RMGfxBuffer::Create(dimx, dimy, 4, bUseDDraw);
}
/****************************************************************************\
* RMGfxSourceBuffer8 Methods
\****************************************************************************/
RMGfxSourceBuffer8::~RMGfxSourceBuffer8() {
}
void RMGfxSourceBuffer8::Draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
int x, y, width, height, u, v;
int bufx = bigBuf.Dimx();
uint16 *buf = bigBuf;
byte *raw = m_buf;
// Destination buffer
RMRect dst;
if (prim->HaveDst())
dst = prim->Dst();
// Clipping
if (prim->HaveSrc()) {
u = prim->Src().x1;
v = prim->Src().y1;
width = prim->Src().Width();
height = prim->Src().Height();
}
if (!Clip2D(dst.x1, dst.y1, u, v, width, height, prim->HaveSrc(), &bigBuf))
return;
// Starting offset into the buffer
buf += dst.y1 * bufx + dst.x1;
// Normal step
if (m_bTrasp0) {
for (y = 0; y < height; y++) {
raw = m_buf + (y + v) * m_dimx + u;
for (x = 0; x < width; x++) {
if (*raw) *buf = m_palFinal[*raw];
buf++;
raw++;
}
buf += bufx - width;
}
} else {
for (y = 0; y < height; y++) {
raw = m_buf + (y + v) * m_dimx + u;
for (x = 0; x < width; x += 2) {
buf[0] = m_palFinal[raw[0]];
buf[1] = m_palFinal[raw[1]];
buf += 2;
raw += 2;
}
buf += bufx - width;
}
}
}
RMGfxSourceBuffer8::RMGfxSourceBuffer8(int dimx, int dimy, bool bUseDDraw)
: RMGfxBuffer(dimx, dimy, 8, bUseDDraw) {
SetPriority(0);
}
RMGfxSourceBuffer8::RMGfxSourceBuffer8(bool bTrasp0) {
m_bTrasp0 = bTrasp0;
}
/**
* Returns the number of bits per pixel of the surface
*
* @returns Bit per pixel
*/
int RMGfxSourceBuffer8::Bpp() {
return 8;
}
void RMGfxSourceBuffer8::Create(int dimx, int dimy, bool bUseDDraw) {
RMGfxBuffer::Create(dimx, dimy, 8, bUseDDraw);
}
#define GETRED(x) (((x) >> 10) & 0x1F)
#define GETGREEN(x) (((x) >> 5) & 0x1F)
#define GETBLUE(x) ((x) & 0x1F)
/****************************************************************************\
* RMGfxSourceBuffer8AB Methods
\****************************************************************************/
RMGfxSourceBuffer8AB::~RMGfxSourceBuffer8AB() {
}
int RMGfxSourceBuffer8AB::CalcTrasp(int fore, int back) {
int r, g, b;
r = (GETRED(fore) >> 2) + (GETRED(back) >> 1);
g = (GETGREEN(fore) >> 2) + (GETGREEN(back) >> 1);
b = (GETBLUE(fore) >> 2) + (GETBLUE(back) >> 1);
if (r > 0x1F) r = 0x1F;
if (g > 0x1F) g = 0x1F;
if (b > 0x1F) b = 0x1F;
return (r << 10) | (g << 5) | b;
}
void RMGfxSourceBuffer8AB::Draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
int x, y, width, height, u, v;
int bufx = bigBuf.Dimx();
uint16 *buf = bigBuf;
byte *raw = m_buf;
// Destination buffer
RMRect dst;
if (prim->HaveDst())
dst = prim->Dst();
// Clipping
if (prim->HaveSrc()) {
u = prim->Src().x1;
v = prim->Src().y1;
width = prim->Src().Width();
height = prim->Src().Height();
}
if (!Clip2D(dst.x1, dst.y1, u, v, width, height, prim->HaveSrc(), &bigBuf))
return;
// Starting offset into the buffer
buf += dst.y1 * bufx + dst.x1;
// Passaggio normale
if (m_bTrasp0) {
for (y = 0; y < height; y++) {
raw = m_buf + (y + v) * m_dimx + u;
for (x = 0; x < width; x++) {
if (*raw) *buf = CalcTrasp(m_palFinal[*raw], *buf);
buf++;
raw++;
}
buf += bufx - width;
}
} else {
for (y = 0; y < height; y++) {
raw = m_buf + (y + v) * m_dimx + u;
for (x = 0; x < width; x += 2) {
buf[0] = CalcTrasp(m_palFinal[raw[0]], buf[0]);
buf[1] = CalcTrasp(m_palFinal[raw[1]], buf[1]);
buf += 2;
raw += 2;
}
buf += bufx - width;
}
}
return;
}
/****************************************************************************\
* RMGfxSourceBuffer8RLE Methods
\****************************************************************************/
byte RMGfxSourceBuffer8RLE::MegaRLEBuf[512 * 1024];
void RMGfxSourceBuffer8RLE::SetAlphaBlendColor(int color) {
alphaBlendColor = color;
}
RMGfxSourceBuffer8RLE::RMGfxSourceBuffer8RLE() {
alphaBlendColor = -1;
bNeedRLECompress = true;
m_buf = NULL;
}
RMGfxSourceBuffer8RLE::~RMGfxSourceBuffer8RLE() {
if (m_buf != NULL) {
delete[] m_buf;
m_buf = NULL;
}
}
int RMGfxSourceBuffer8RLE::Init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
return RMGfxSourceBufferPal::Init(buf, dimx, dimy, bLoadPalette);
}
void RMGfxSourceBuffer8RLE::Init(RMDataStream &ds, int dimx, int dimy, bool bLoadPalette) {
if (bNeedRLECompress) {
RMGfxSourceBufferPal::Init(ds, dimx, dimy, bLoadPalette);
} else {
int size;
ds >> size;
m_buf = new byte[size];
ds.Read(m_buf, size);
m_dimx = dimx;
m_dimy = dimy;
}
}
void RMGfxSourceBuffer8RLE::PreparePalette(void) {
// Invoke the parent method
RMGfxSourceBuffer8::PreparePalette();
// Handle RGB alpha blending
if (alphaBlendColor != -1) {
alphaR = (m_palFinal[alphaBlendColor] >> 10) & 0x1F;
alphaG = (m_palFinal[alphaBlendColor] >> 5) & 0x1F;
alphaB = (m_palFinal[alphaBlendColor]) & 0x1F;
}
}
void RMGfxSourceBuffer8RLE::PrepareImage(void) {
// Invoke the parent method
RMGfxSourceBuffer::PrepareImage();
// Compress
CompressRLE();
}
void RMGfxSourceBuffer8RLE::SetAlreadyCompressed(void) {
bNeedRLECompress = false;
}
void RMGfxSourceBuffer8RLE::CompressRLE(void) {
int x, y;
byte *startline;
byte *cur;
byte curdata;
byte *src;
byte *startsrc;
int rep;
// Perform RLE compression for lines
cur = MegaRLEBuf;
src = m_buf;
for (y = 0; y < m_dimy; y++) {
// Save the beginning of the line
startline = cur;
// Leave space for the length of the line
cur += 2;
// It starts from the empty space
curdata = 0;
rep = 0;
startsrc = src;
for (x = 0; x < m_dimx;) {
if ((curdata == 0 && *src == 0) || (curdata == 1 && *src == alphaBlendColor)
|| (curdata == 2 && (*src != alphaBlendColor && *src != 0))) {
src++;
rep++;
x++;
} else {
if (curdata == 0) {
RLEWriteTrasp(cur, rep);
curdata++;
} else if (curdata == 1) {
RLEWriteAlphaBlend(cur, rep);
curdata++;
} else {
RLEWriteData(cur, rep, startsrc);
curdata = 0;
}
rep = 0;
startsrc = src;
}
}
// Pending data?
if (curdata == 1) {
RLEWriteAlphaBlend(cur, rep);
RLEWriteData(cur, 0, NULL);
}
if (curdata == 2) {
RLEWriteData(cur, rep, startsrc);
}
// End of line
RLEWriteEOL(cur);
// Write the length of the line
WRITE_LE_UINT16(startline, (uint16)(cur - startline));
}
// Delete the original image
delete[] m_buf;
// Copy the compressed image
x = cur - MegaRLEBuf;
m_buf = new byte[x];
Common::copy(MegaRLEBuf, MegaRLEBuf + x, m_buf);
}
void RMGfxSourceBuffer8RLE::Draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
int y;
byte *src;
uint16 *buf = bigBuf;
int x1, y1, u, v, width, height;
// Clipping
x1 = prim->Dst().x1;
y1 = prim->Dst().y1;
if (!Clip2D(x1, y1, u, v, width, height, false, &bigBuf))
return;
// Go forward through the RLE lines
src = m_buf;
for (y = 0; y < v; y++)
src += READ_LE_UINT16(src);
// Calculate the position in the destination buffer
buf += y1 * bigBuf.Dimx();
// Loop
if (prim->IsFlipped()) {
// Eliminate horizontal clipping
// width = m_dimx;
// x1=prim->Dst().x1;
// Clipping
u = m_dimx - (width + u);
x1 = (prim->Dst().x1 + m_dimx - 1) - u;
for (y = 0; y < height; y++) {
// Decompressione
RLEDecompressLineFlipped(buf + x1, src + 2, u, width);
// Next line
src += READ_LE_UINT16(src);
// Skip to the next line
buf += bigBuf.Dimx();
}
} else {
for (y = 0; y < height; y++) {
// Decompression
RLEDecompressLine(buf + x1, src + 2, u, width);
// Next line
src += READ_LE_UINT16(src);
// Skip to the next line
buf += bigBuf.Dimx();
}
}
}
/****************************************************************************\
* RMGfxSourceBuffer8RLEByte Methods
\****************************************************************************/
RMGfxSourceBuffer8RLEByte::~RMGfxSourceBuffer8RLEByte() {
}
void RMGfxSourceBuffer8RLEByte::RLEWriteTrasp(byte *&cur, int rep) {
assert(rep < 255);
*cur ++ = rep;
}
void RMGfxSourceBuffer8RLEByte::RLEWriteAlphaBlend(byte *&cur, int rep) {
assert(rep < 255);
*cur ++ = rep;
}
void RMGfxSourceBuffer8RLEByte::RLEWriteData(byte *&cur, int rep, byte *src) {
assert(rep < 256);
*cur ++ = rep;
if (rep > 0) {
CopyMemory(cur, src, rep);
cur += rep;
src += rep;
}
return;
}
void RMGfxSourceBuffer8RLEByte::RLEWriteEOL(byte *&cur) {
*cur ++ = 0xFF;
}
void RMGfxSourceBuffer8RLEByte::RLEDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
int i, n;
int r, g, b;
if (nStartSkip == 0)
goto RLEByteDoTrasp;
while (1) {
assert(nStartSkip > 0);
// TRASP
n = *src++;
if (n == 0xFF)
return;
if (n >= nStartSkip) {
dst += n - nStartSkip;
nLength -= n - nStartSkip;
if (nLength > 0)
goto RLEByteDoAlpha;
else
return;
}
nStartSkip -= n;
assert(nStartSkip > 0);
// ALPHA
n = *src++;
if (n >= nStartSkip) {
n -= nStartSkip;
goto RLEByteDoAlpha2;
}
nStartSkip -= n;
assert(nStartSkip > 0);
// DATA
n = *src++;
if (n >= nStartSkip) {
src += nStartSkip;
n -= nStartSkip;
goto RLEByteDoCopy2;
}
nStartSkip -= n;
src += n;
}
while (1) {
RLEByteDoTrasp:
// Get the trasp of s**t
n = *src++;
// EOL?
if (n == 0xFF)
return;
dst += n;
nLength -= n;
if (nLength <= 0)
return;
RLEByteDoAlpha:
// Alpha
n = *src++;
RLEByteDoAlpha2:
if (n > nLength)
n = nLength;
for (i = 0; i < n; i++) {
r = (*dst >> 10) & 0x1F;
g = (*dst >> 5) & 0x1F;
b = *dst & 0x1F;
r = (r >> 2) + (alphaR >> 1);
g = (g >> 2) + (alphaG >> 1);
b = (b >> 2) + (alphaB >> 1);
*dst ++ = (r << 10) | (g << 5) | b;
}
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
//RLEByteDoCopy:
// Copy the stuff
n = *src++;
RLEByteDoCopy2:
if (n > nLength)
n = nLength;
for (i = 0; i < n; i++)
*dst ++ = m_palFinal[*src++];
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
}
}
void RMGfxSourceBuffer8RLEByte::RLEDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) {
int i, n;
int r, g, b;
if (nStartSkip == 0)
goto RLEByteFlippedDoTrasp;
while (1) {
assert(nStartSkip > 0);
// TRASP
n = *src++;
if (n == 0xFF)
return;
if (n >= nStartSkip) {
dst -= n - nStartSkip;
nLength -= n - nStartSkip;
if (nLength > 0)
goto RLEByteFlippedDoAlpha;
else
return;
}
nStartSkip -= n;
assert(nStartSkip > 0);
// ALPHA
n = *src++;
if (n >= nStartSkip) {
n -= nStartSkip;
goto RLEByteFlippedDoAlpha2;
}
nStartSkip -= n;
assert(nStartSkip > 0);
// DATA
n = *src++;
if (n >= nStartSkip) {
src += nStartSkip;
n -= nStartSkip;
goto RLEByteFlippedDoCopy2;
}
nStartSkip -= n;
src += n;
}
while (1) {
RLEByteFlippedDoTrasp:
// Get the trasp of s**t
n = *src++;
// EOL?
if (n == 0xFF)
return;
dst -= n;
nLength -= n;
if (nLength <= 0)
return;
RLEByteFlippedDoAlpha:
// Alpha
n = *src++;
RLEByteFlippedDoAlpha2:
if (n > nLength)
n = nLength;
for (i = 0; i < n; i++) {
r = (*dst >> 10) & 0x1F;
g = (*dst >> 5) & 0x1F;
b = *dst & 0x1F;
r = (r >> 2) + (alphaR >> 1);
g = (g >> 2) + (alphaG >> 1);
b = (b >> 2) + (alphaB >> 1);
*dst-- = (r << 10) | (g << 5) | b;
}
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
//RLEByteFlippedDoCopy:
// Copy the data
n = *src++;
RLEByteFlippedDoCopy2:
if (n > nLength)
n = nLength;
for (i = 0; i < n; i++)
*dst -- = m_palFinal[*src++];
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
}
}
/****************************************************************************\
* RMGfxSourceBuffer8RLEWord Methods
\****************************************************************************/
RMGfxSourceBuffer8RLEWord::~RMGfxSourceBuffer8RLEWord() {
}
void RMGfxSourceBuffer8RLEWord::RLEWriteTrasp(byte *&cur, int rep) {
WRITE_LE_UINT16(cur, rep);
cur += 2;
}
void RMGfxSourceBuffer8RLEWord::RLEWriteAlphaBlend(byte *&cur, int rep) {
WRITE_LE_UINT16(cur, rep);
cur += 2;
}
void RMGfxSourceBuffer8RLEWord::RLEWriteData(byte *&cur, int rep, byte *src) {
WRITE_LE_UINT16(cur, rep);
cur += 2;
if (rep > 0) {
CopyMemory(cur, src, rep);
cur += rep;
src += rep;
}
}
void RMGfxSourceBuffer8RLEWord::RLEWriteEOL(byte *&cur) {
*cur ++ = 0xFF;
*cur ++ = 0xFF;
}
void RMGfxSourceBuffer8RLEWord::RLEDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
int i, n;
int r, g, b;
if (nStartSkip == 0)
goto RLEWordDoTrasp;
while (1) {
assert(nStartSkip > 0);
// TRASP
n = READ_LE_UINT16(src);
src += 2;
if (n == 0xFFFF)
return;
if (n >= nStartSkip) {
dst += n - nStartSkip;
nLength -= n - nStartSkip;
if (nLength > 0)
goto RLEWordDoAlpha;
else
return;
}
nStartSkip -= n;
assert(nStartSkip > 0);
// ALPHA
n = READ_LE_UINT16(src);
src += 2;
if (n >= nStartSkip) {
n -= nStartSkip;
goto RLEWordDoAlpha2;
}
nStartSkip -= n;
// DATA
n = READ_LE_UINT16(src);
src += 2;
if (n >= nStartSkip) {
src += nStartSkip;
n -= nStartSkip;
goto RLEWordDoCopy2;
}
nStartSkip -= n;
src += n;
}
while (1) {
RLEWordDoTrasp:
// Get the trasp of s**t
n = READ_LE_UINT16(src);
src += 2;
// EOL?
if (n == 0xFFFF)
return;
dst += n;
nLength -= n;
if (nLength <= 0)
return;
RLEWordDoAlpha:
n = READ_LE_UINT16(src);
src += 2;
RLEWordDoAlpha2:
if (n > nLength)
n = nLength;
for (i = 0; i < n; i++) {
r = (*dst >> 10) & 0x1F;
g = (*dst >> 5) & 0x1F;
b = *dst & 0x1F;
r = (r >> 2) + (alphaR >> 1);
g = (g >> 2) + (alphaG >> 1);
b = (b >> 2) + (alphaB >> 1);
*dst++ = (r << 10) | (g << 5) | b;
}
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
//RLEWordDoCopy:
// Copy the data
n = READ_LE_UINT16(src);
src += 2;
RLEWordDoCopy2:
if (n > nLength)
n = nLength;
for (i = 0; i < n; i++)
*dst ++ = m_palFinal[*src++];
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
}
}
void RMGfxSourceBuffer8RLEWord::RLEDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) {
int i, n;
int r, g, b;
if (nStartSkip == 0)
goto RLEWordFlippedDoTrasp;
while (1) {
assert(nStartSkip > 0);
// TRASP
n = READ_LE_UINT16(src);
src += 2;
if (n == 0xFFFF)
return;
if (n >= nStartSkip) {
dst -= n - nStartSkip;
nLength -= n - nStartSkip;
if (nLength > 0)
goto RLEWordFlippedDoAlpha;
else
return;
}
nStartSkip -= n;
assert(nStartSkip > 0);
// ALPHA
n = READ_LE_UINT16(src);
src += 2;
if (n >= nStartSkip) {
n -= nStartSkip;
goto RLEWordFlippedDoAlpha2;
}
nStartSkip -= n;
// DATA
n = READ_LE_UINT16(src);
src += 2;
if (n >= nStartSkip) {
src += nStartSkip;
n -= nStartSkip;
goto RLEWordFlippedDoCopy2;
}
nStartSkip -= n;
src += n;
}
while (1) {
RLEWordFlippedDoTrasp:
// Get the trasp of s**t
n = READ_LE_UINT16(src);
src += 2;
// EOL?
if (n == 0xFFFF)
return;
dst -= n;
nLength -= n;
if (nLength <= 0)
return;
RLEWordFlippedDoAlpha:
n = READ_LE_UINT16(src);
src += 2;
RLEWordFlippedDoAlpha2:
if (n > nLength)
n = nLength;
for (i = 0; i < n; i++) {
r = (*dst >> 10) & 0x1F;
g = (*dst >> 5) & 0x1F;
b = *dst & 0x1F;
r = (r >> 2) + (alphaR >> 1);
g = (g >> 2) + (alphaG >> 1);
b = (b >> 2) + (alphaB >> 1);
*dst-- = (r << 10) | (g << 5) | b;
}
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
//RLEWordFlippedDoCopy:
// Copy the data
n = READ_LE_UINT16(src);
src += 2;
RLEWordFlippedDoCopy2:
if (n > nLength)
n = nLength;
for (i = 0; i < n; i++)
*dst -- = m_palFinal[*src++];
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
}
}
/****************************************************************************\
* Metodi di RMGfxSourceBuffer8RLEWord
\****************************************************************************/
RMGfxSourceBuffer8RLEWordAB::~RMGfxSourceBuffer8RLEWordAB() {
}
void RMGfxSourceBuffer8RLEWordAB::RLEDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
int i, n;
int r, g, b, r2, g2, b2;
if (!GLOBALS.bCfgTransparence) {
RMGfxSourceBuffer8RLEWord::RLEDecompressLine(dst, src, nStartSkip, nLength);
return;
}
if (nStartSkip == 0)
goto RLEWordDoTrasp;
while (1) {
assert(nStartSkip > 0);
// TRASP
n = READ_LE_UINT16(src);
src += 2;
if (n == 0xFFFF)
return;
if (n >= nStartSkip) {
dst += n - nStartSkip;
nLength -= n - nStartSkip;
if (nLength > 0)
goto RLEWordDoAlpha;
else
return;
}
nStartSkip -= n;
assert(nStartSkip > 0);
// ALPHA
n = READ_LE_UINT16(src);
src += 2;
if (n >= nStartSkip) {
n -= nStartSkip;
goto RLEWordDoAlpha2;
}
nStartSkip -= n;
// DATA
n = READ_LE_UINT16(src);
src += 2;
if (n >= nStartSkip) {
src += nStartSkip;
n -= nStartSkip;
goto RLEWordDoCopy2;
}
nStartSkip -= n;
src += n;
}
while (1) {
RLEWordDoTrasp:
// Get the trasp of s**t
n = READ_LE_UINT16(src);
src += 2;
// EOL?
if (n == 0xFFFF)
return;
dst += n;
nLength -= n;
if (nLength <= 0)
return;
RLEWordDoAlpha:
n = READ_LE_UINT16(src);
src += 2;
RLEWordDoAlpha2:
if (n > nLength)
n = nLength;
// @@@ SHOULD NOT BE THERE !!!!!
for (i = 0; i < n; i++) {
r = (*dst >> 10) & 0x1F;
g = (*dst >> 5) & 0x1F;
b = *dst & 0x1F;
r = (r >> 2) + (alphaR >> 1);
g = (g >> 2) + (alphaG >> 1);
b = (b >> 2) + (alphaB >> 1);
*dst++ = (r << 10) | (g << 5) | b;
}
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
//RLEWordDoCopy:
// Copy the data
n = READ_LE_UINT16(src);
src += 2;
RLEWordDoCopy2:
if (n > nLength)
n = nLength;
for (i = 0; i < n; i++) {
r = (*dst >> 10) & 0x1F;
g = (*dst >> 5) & 0x1F;
b = *dst & 0x1F;
r2 = (m_palFinal[*src] >> 10) & 0x1F;
g2 = (m_palFinal[*src] >> 5) & 0x1F;
b2 = m_palFinal[*src] & 0x1F;
r = (r >> 1) + (r2 >> 1);
g = (g >> 1) + (g2 >> 1);
b = (b >> 1) + (b2 >> 1);
*dst ++ = (r << 10) | (g << 5) | b;
src++;
}
nLength -= n;
if (!nLength)
return;
assert(nLength > 0);
}
}
/****************************************************************************\
* Metodi di RMGfxSourceBuffer8AA
\****************************************************************************/
byte RMGfxSourceBuffer8AA::MegaAABuf[256 * 1024];
byte RMGfxSourceBuffer8AA::MegaAABuf2[64 * 1024];
void RMGfxSourceBuffer8AA::PrepareImage(void) {
// Invoke the parent method
RMGfxSourceBuffer::PrepareImage();
// Prepare the buffer for anti-aliasing
CalculateAA();
}
void RMGfxSourceBuffer8AA::CalculateAA(void) {
// I suck, you suck, he sucks, we suck, they all suck ---> ANTI ALIASING SUX!
// ************************************************************
int x, y;
byte *src, *srcaa;
/* First pass: fill the edges */
Common::fill(MegaAABuf, MegaAABuf + m_dimx * m_dimy, 0);
src = m_buf;
srcaa = MegaAABuf;
for (y = 0; y < m_dimy; y++) {
for (x = 0; x < m_dimx; x++) {
if (*src == 0) {
if ((y > 0 && src[-m_dimx] != 0) ||
(y < m_dimy - 1 && src[m_dimx] != 0) ||
(x > 0 && src[-1] != 0) ||
(x < m_dimx - 1 && src[1] != 0))
*srcaa = 1;
}
src++;
srcaa++;
}
}
src = m_buf;
srcaa = MegaAABuf;
for (y = 0; y < m_dimy; y++) {
for (x = 0; x < m_dimx; x++) {
if (*src != 0) {
if ((y > 0 && srcaa[-m_dimx] == 1) ||
(y < m_dimy - 1 && srcaa[m_dimx] == 1) ||
(x > 0 && srcaa[-1] == 1) ||
(x < m_dimx - 1 && srcaa[1] == 1))
*srcaa = 2;
}
src++;
srcaa++;
}
}
if (m_aabuf != NULL)
delete[] m_aabuf;
m_aabuf = new byte[m_dimx * m_dimy];
CopyMemory(m_aabuf, MegaAABuf, m_dimx * m_dimy);
}
RMGfxSourceBuffer8AA::RMGfxSourceBuffer8AA() : RMGfxSourceBuffer8() {
m_aabuf = NULL;
}
RMGfxSourceBuffer8AA::~RMGfxSourceBuffer8AA() {
if (m_aabuf != NULL)
delete[] m_aabuf;
}
void RMGfxSourceBuffer8AA::DrawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
int x, y;
byte *src;
uint16 *mybuf;
uint16 *buf;
int x1, y1, u, v, width, height;
int r, g, b;
int step;
// Clip the sprite
x1 = prim->Dst().x1;
y1 = prim->Dst().y1;
if (!Clip2D(x1, y1, u, v, width, height, false, &bigBuf))
return;
// Go forward through the RLE lines
src = m_buf;
for (y = 0; y < v; y++)
src += READ_LE_UINT16(src);
// Eliminate horizontal clipping
if (prim->IsFlipped()) {
u = m_dimx - (width + u);
x1 = (prim->Dst().x1 + m_dimx - 1) - u;
}
// width = m_dimx;
// x1=prim->Dst().x1;
// Poisition into the destination buffer
buf = bigBuf;
buf += y1 * bigBuf.Dimx();
if (prim->IsFlipped())
step = -1;
else
step = 1;
// Loop
buf += bigBuf.Dimx(); // Skip the first line
for (y = 1; y < height - 1; y++) {
/*
if (prim->IsFlipped())
mybuf=&buf[x1+m_dimx-1];
else
*/
mybuf = &buf[x1];
for (x = 0; x < width; x++, mybuf += step)
if (m_aabuf[(y + v) * m_dimx + x + u] == 2 && x != 0 && x != width - 1) {
r = GETRED(mybuf[1]) + GETRED(mybuf[-1]) + GETRED(mybuf[-bigBuf.Dimx()]) + GETRED(mybuf[bigBuf.Dimx()]);
g = GETGREEN(mybuf[1]) + GETGREEN(mybuf[-1]) + GETGREEN(mybuf[-bigBuf.Dimx()]) + GETGREEN(mybuf[bigBuf.Dimx()]);
b = GETBLUE(mybuf[1]) + GETBLUE(mybuf[-1]) + GETBLUE(mybuf[-bigBuf.Dimx()]) + GETBLUE(mybuf[bigBuf.Dimx()]);
r += GETRED(mybuf[0]);
g += GETGREEN(mybuf[0]);
b += GETBLUE(mybuf[0]);
r /= 5;
g /= 5;
b /= 5;
if (r > 31) r = 31;
if (g > 31) g = 31;
if (b > 31) b = 31;
mybuf[0] = (r << 10) | (g << 5) | b;
}
// Skip to the next line
buf += bigBuf.Dimx();
}
// Position into the destination buffer
buf = bigBuf;
buf += y1 * bigBuf.Dimx();
// Looppone
buf += bigBuf.Dimx();
for (y = 1; y < height - 1; y++) {
/*
if (prim->IsFlipped())
mybuf=&buf[x1+m_dimx-1];
else
*/
mybuf = &buf[x1];
for (x = 0; x < width; x++, mybuf += step)
if (m_aabuf[(y + v) * m_dimx + x + u] == 1 && x != 0 && x != width - 1) {
r = GETRED(mybuf[1]) + GETRED(mybuf[-1]) + GETRED(mybuf[-bigBuf.Dimx()]) + GETRED(mybuf[bigBuf.Dimx()]);
g = GETGREEN(mybuf[1]) + GETGREEN(mybuf[-1]) + GETGREEN(mybuf[-bigBuf.Dimx()]) + GETGREEN(mybuf[bigBuf.Dimx()]);
b = GETBLUE(mybuf[1]) + GETBLUE(mybuf[-1]) + GETBLUE(mybuf[-bigBuf.Dimx()]) + GETBLUE(mybuf[bigBuf.Dimx()]);
r += GETRED(mybuf[0]) * 2;
g += GETGREEN(mybuf[0]) * 2;
b += GETBLUE(mybuf[0]) * 2;
r /= 6;
g /= 6;
b /= 6;
if (r > 31) r = 31;
if (g > 31) g = 31;
if (b > 31) b = 31;
mybuf[0] = (r << 10) | (g << 5) | b;
}
// Skippa alla linea successiva
buf += bigBuf.Dimx();
}
}
void RMGfxSourceBuffer8AA::Draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_2(RMGfxSourceBuffer8::Draw, bigBuf, prim);
DrawAA(bigBuf, prim);
CORO_END_CODE;
}
/****************************************************************************\
* RMGfxSourceBuffer8RLEAA Methods
\****************************************************************************/
RMGfxSourceBuffer8RLEByteAA::~RMGfxSourceBuffer8RLEByteAA() {
}
void RMGfxSourceBuffer8RLEByteAA::PrepareImage(void) {
RMGfxSourceBuffer::PrepareImage();
CalculateAA();
CompressRLE();
}
void RMGfxSourceBuffer8RLEByteAA::Draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_2(RMGfxSourceBuffer8RLE::Draw, bigBuf, prim);
if (GLOBALS.bCfgAntiAlias)
DrawAA(bigBuf, prim);
CORO_END_CODE;
}
int RMGfxSourceBuffer8RLEByteAA::Init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
return RMGfxSourceBuffer8RLE::Init(buf, dimx, dimy, bLoadPalette);
}
void RMGfxSourceBuffer8RLEByteAA::Init(RMDataStream &ds, int dimx, int dimy, bool bLoadPalette) {
RMGfxSourceBuffer8RLE::Init(ds, dimx, dimy, bLoadPalette);
if (!bNeedRLECompress) {
// Load the anti-aliasing mask
m_aabuf = new byte[dimx * dimy];
ds.Read(m_aabuf, dimx * dimy);
}
}
RMGfxSourceBuffer8RLEWordAA::~RMGfxSourceBuffer8RLEWordAA() {
}
void RMGfxSourceBuffer8RLEWordAA::PrepareImage(void) {
RMGfxSourceBuffer::PrepareImage();
CalculateAA();
CompressRLE();
}
void RMGfxSourceBuffer8RLEWordAA::Draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
CORO_BEGIN_CONTEXT;
CORO_END_CONTEXT(_ctx);
CORO_BEGIN_CODE(_ctx);
CORO_INVOKE_2(RMGfxSourceBuffer8RLE::Draw, bigBuf, prim);
if (GLOBALS.bCfgAntiAlias)
DrawAA(bigBuf, prim);
CORO_END_CODE;
}
int RMGfxSourceBuffer8RLEWordAA::Init(byte *buf, int dimx, int dimy, bool bLoadPalette) {
return RMGfxSourceBuffer8RLE::Init(buf, dimx, dimy, bLoadPalette);
}
void RMGfxSourceBuffer8RLEWordAA::Init(RMDataStream &ds, int dimx, int dimy, bool bLoadPalette) {
RMGfxSourceBuffer8RLE::Init(ds, dimx, dimy, bLoadPalette);
if (!bNeedRLECompress) {
// Load the anti-aliasing mask
m_aabuf = new byte[dimx * dimy];
ds.Read(m_aabuf, dimx * dimy);
}
}
/****************************************************************************\
* RMGfxSourceBuffer16 Methods
\****************************************************************************/
RMGfxSourceBuffer16::RMGfxSourceBuffer16(bool bTrasp0) {
m_bTrasp0 = bTrasp0;
}
RMGfxSourceBuffer16::~RMGfxSourceBuffer16() {
}
void RMGfxSourceBuffer16::Draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
int x, y;
uint16 *buf = bigBuf;
uint16 *raw = (uint16 *)m_buf;
int dimx, dimy;
int u, v;
int x1, y1;
dimx = m_dimx;
dimy = m_dimy;
u = 0;
v = 0;
x1 = 0;
y1 = 0;
if (prim->HaveSrc()) {
u = prim->Src().x1;
v = prim->Src().y1;
dimx = prim->Src().Width();
dimy = prim->Src().Height();
}
if (prim->HaveDst()) {
x1 = prim->Dst().x1;
y1 = prim->Dst().y1;
}
if (!Clip2D(x1, y1, u, v, dimx, dimy, true, &bigBuf))
return;
raw += v * m_dimx + u;
buf += y1 * bigBuf.Dimx() + x1;
if (m_bTrasp0) {
for (y = 0; y < dimy; y++) {
for (x = 0; x < dimx;) {
while (x < dimx && raw[x] == 0)
x++;
while (x < dimx && raw[x] != 0) {
buf[x] = raw[x];
x++;
}
}
raw += m_dimx;
buf += bigBuf.Dimx();
}
} else {
for (y = 0; y < dimy; y++) {
Common::copy(raw, raw + dimx, buf);
buf += bigBuf.Dimx();
raw += m_dimx;
}
}
}
void RMGfxSourceBuffer16::PrepareImage(void) {
// Colour space conversion if necessary!
int i;
uint16 *buf = (uint16 *)m_buf;
for (i = 0; i < m_dimx * m_dimy; i++)
WRITE_LE_UINT16(&buf[i], FROM_LE_16(buf[i]) & 0x7FFF);
}
RMGfxSourceBuffer16::RMGfxSourceBuffer16(int dimx, int dimy, bool bUseDDraw)
: RMGfxBuffer(dimx, dimy, 16, bUseDDraw) {
SetPriority(0);
}
/**
* Returns the number of bits per pixel of the surface
*
* @returns Bit per pixel
*/
int RMGfxSourceBuffer16::Bpp() {
return 16;
}
void RMGfxSourceBuffer16::Create(int dimx, int dimy, bool bUseDDraw) {
RMGfxBuffer::Create(dimx, dimy, 16, bUseDDraw);
}
/****************************************************************************\
* RMGfxBox Methods
\****************************************************************************/
void RMGfxBox::RemoveThis(CORO_PARAM, bool &result) {
result = true;
}
void RMGfxBox::SetColor(byte r, byte g, byte b) {
r >>= 3;
g >>= 3;
b >>= 3;
wFillColor = (r << 10) | (g << 5) | b;
}
void RMGfxBox::Draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
int i, j;
uint16 *buf = bigBuf;
RMRect rcDst;
// It takes the destination rectangle
rcDst = prim->Dst();
buf += rcDst.y1 * bigBuf.Dimx() + rcDst.x1;
// Loop through the pixels
for (j = 0; j < rcDst.Height(); j++) {
for (i = 0; i < rcDst.Width(); i++)
*buf ++ = wFillColor;
buf += bigBuf.Dimx() - rcDst.Width();
}
}
/****************************************************************************\
* RMGfxClearTask Methods
\****************************************************************************/
int RMGfxClearTask::Priority() {
// Maximum priority (must be done first)
return 1;
}
void RMGfxClearTask::Draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *) {
// Clean the target buffer
Common::fill((byte *)bigBuf, (byte *)bigBuf + (bigBuf.Dimx() * bigBuf.Dimy() * 2), 0x0);
}
void RMGfxClearTask::RemoveThis(CORO_PARAM, bool &result) {
// The task is fine to be removed
result = true;
}
} // End of namespace Tony