1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 /*
24  * This code is based on original Tony Tough source code
25  *
26  * Copyright (c) 1997-2003 Nayma Software
27  */
28 
29 #include "tony/gfxengine.h"
30 #include "tony/mpal/mpalutils.h"
31 #include "tony/tony.h"
32 
33 namespace Tony {
34 
35 /****************************************************************************\
36 *       RMGfxTask Methods
37 \****************************************************************************/
38 
RMGfxTask()39 RMGfxTask::RMGfxTask() {
40 	_nPrior = 0;
41 	_nInList = 0;
42 }
43 
priority()44 int RMGfxTask::priority() {
45 	return _nPrior;
46 }
47 
removeThis(CORO_PARAM,bool & result)48 void RMGfxTask::removeThis(CORO_PARAM, bool &result) {
49 	result = true;
50 }
51 
52 /**
53  * Registration
54  */
Register()55 void RMGfxTask::Register() {
56 	_nInList++;
57 }
58 
unregister()59 void RMGfxTask::unregister() {
60 	_nInList--;
61 	assert(_nInList >= 0);
62 }
63 
64 /****************************************************************************\
65 *       RMGfxTaskSetPrior Methods
66 \****************************************************************************/
67 
setPriority(int nPrior)68 void RMGfxTaskSetPrior::setPriority(int nPrior) {
69 	_nPrior = nPrior;
70 }
71 
72 /****************************************************************************\
73 *       RMGfxBuffer Methods
74 \****************************************************************************/
75 
RMGfxBuffer()76 RMGfxBuffer::RMGfxBuffer() {
77 	_dimx = _dimy = 0;
78 	_origBuf = _buf = NULL;
79 }
80 
~RMGfxBuffer()81 RMGfxBuffer::~RMGfxBuffer() {
82 	destroy();
83 }
84 
create(int dimx,int dimy,int nBpp)85 void RMGfxBuffer::create(int dimx, int dimy, int nBpp) {
86 	// Destroy the buffer it is already exists
87 	if (_buf != NULL)
88 		destroy();
89 
90 	// Copy the parameters in the private members
91 	_dimx = dimx;
92 	_dimy = dimy;
93 
94 	// Allocate a buffer
95 	_origBuf = _buf = new byte[_dimx * _dimy * nBpp / 8];
96 	assert(_buf != NULL);
97 	Common::fill(_origBuf, _origBuf + _dimx * _dimy * nBpp / 8, 0);
98 }
99 
destroy()100 void RMGfxBuffer::destroy() {
101 	if (_origBuf != NULL && _origBuf == _buf) {
102 		delete[] _origBuf;
103 		_origBuf = _buf = NULL;
104 	}
105 }
106 
offsetY(int nLines,int nBpp)107 void RMGfxBuffer::offsetY(int nLines, int nBpp) {
108 	_buf += nLines * getDimx() * nBpp / 8;
109 }
110 
operator byte*()111 RMGfxBuffer::operator byte *() {
112 	return _buf;
113 }
114 
operator void*()115 RMGfxBuffer::operator void *() {
116 	return (void *)_buf;
117 }
118 
RMGfxBuffer(int dimx,int dimy,int nBpp)119 RMGfxBuffer::RMGfxBuffer(int dimx, int dimy, int nBpp) {
120 	_origBuf = _buf = NULL;
121 	create(dimx, dimy, nBpp);
122 }
123 
getDimx()124 int RMGfxBuffer::getDimx() {
125 	return _dimx;
126 }
127 
getDimy()128 int RMGfxBuffer::getDimy() {
129 	return _dimy;
130 }
131 
132 /****************************************************************************\
133 *       RMGfxSourceBuffer Methods
134 \****************************************************************************/
135 
init(const byte * buf,int dimx,int dimy,bool bLoadPalette)136 int RMGfxSourceBuffer::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
137 	create(dimx, dimy, getBpp());
138 	memcpy(_buf, buf, dimx * dimy * getBpp() / 8);
139 
140 	// Invokes the method for preparing the surface (inherited)
141 	prepareImage();
142 
143 	return dimx * dimy * getBpp() / 8;
144 }
145 
init(Common::ReadStream & ds,int dimx,int dimy,bool bLoadPalette)146 void RMGfxSourceBuffer::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
147 	create(dimx, dimy, getBpp());
148 	ds.read(_buf, dimx * dimy * getBpp() / 8);
149 
150 	// Invokes the method for preparing the surface (inherited)
151 	prepareImage();
152 }
153 
~RMGfxSourceBuffer()154 RMGfxSourceBuffer::~RMGfxSourceBuffer() {
155 }
156 
prepareImage()157 void RMGfxSourceBuffer::prepareImage() {
158 	// Do nothing. Can be overloaded if necessary
159 }
160 
clip2D(int & x1,int & y1,int & u,int & v,int & width,int & height,bool bUseSrc,RMGfxTargetBuffer * buf)161 bool RMGfxSourceBuffer::clip2D(int &x1, int &y1, int &u, int &v, int &width, int &height, bool bUseSrc, RMGfxTargetBuffer *buf) {
162 	int destw, desth;
163 
164 	destw = buf->getDimx();
165 	desth = buf->getDimy();
166 
167 	if (!bUseSrc) {
168 		u = v = 0;
169 		width = _dimx;
170 		height = _dimy;
171 	}
172 
173 	if (x1 > destw - 1)
174 		return false;
175 
176 	if (y1 > desth - 1)
177 		return false;
178 
179 	if (x1 < 0) {
180 		width += x1;
181 		if (width < 0)
182 			return false;
183 		u -= x1;
184 		x1 = 0;
185 	}
186 
187 	if (y1 < 0) {
188 		height += y1;
189 		if (height < 0)
190 			return false;
191 		v -= y1;
192 		y1 = 0;
193 	}
194 
195 	if (x1 + width - 1 > destw - 1)
196 		width = destw - x1;
197 
198 	if (y1 + height - 1 > desth - 1)
199 		height = desth - y1;
200 
201 	return (width > 1 && height > 1);
202 }
203 
204 /**
205  * Initializes a surface by resource Id
206  *
207  * @param resID                 Resource ID
208  * @param dimx                  Buffer X dimension
209  * @param dimy                  Buffer Y dimension
210  */
init(uint32 resID,int dimx,int dimy,bool bLoadPalette)211 int RMGfxSourceBuffer::init(uint32 resID, int dimx, int dimy, bool bLoadPalette) {
212 	return init(RMRes(resID), dimx, dimy, bLoadPalette);
213 }
214 
offsetY(int nLines)215 void RMGfxSourceBuffer::offsetY(int nLines) {
216 	RMGfxBuffer::offsetY(nLines, getBpp());
217 }
218 
219 /****************************************************************************\
220 *       RMGfxWoodyBuffer Methods
221 \****************************************************************************/
222 
~RMGfxWoodyBuffer()223 RMGfxWoodyBuffer::~RMGfxWoodyBuffer() {
224 }
225 
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)226 void RMGfxWoodyBuffer::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
227 	CORO_BEGIN_CONTEXT;
228 	CORO_END_CONTEXT(_ctx);
229 
230 	CORO_BEGIN_CODE(_ctx);
231 
232 	// Draw the OT list
233 	CORO_INVOKE_0(drawOT);
234 
235 	// Draw itself into the target buffer
236 	CORO_INVOKE_2(RMGfxSourceBuffer16::draw, bigBuf, prim);
237 
238 	CORO_END_CODE;
239 }
240 
RMGfxWoodyBuffer()241 RMGfxWoodyBuffer::RMGfxWoodyBuffer() {
242 }
243 
RMGfxWoodyBuffer(int dimx,int dimy)244 RMGfxWoodyBuffer::RMGfxWoodyBuffer(int dimx, int dimy)
245 	: RMGfxBuffer(dimx, dimy, 16) {
246 }
247 
248 /****************************************************************************\
249 *       RMGfxTargetBuffer Methods
250 \****************************************************************************/
251 
RMGfxTargetBuffer()252 RMGfxTargetBuffer::RMGfxTargetBuffer() {
253 	_otlist = NULL;
254 	_otSize = 0;
255 	_trackDirtyRects = false;
256 }
257 
~RMGfxTargetBuffer()258 RMGfxTargetBuffer::~RMGfxTargetBuffer() {
259 	clearOT();
260 }
261 
clearOT()262 void RMGfxTargetBuffer::clearOT() {
263 	OTList *cur, *n;
264 
265 	cur = _otlist;
266 
267 	while (cur != NULL) {
268 		cur->_prim->_task->unregister();
269 		delete cur->_prim;
270 		n = cur->_next;
271 		delete cur;
272 		cur = n;
273 	}
274 
275 	_otlist = NULL;
276 }
277 
drawOT(CORO_PARAM)278 void RMGfxTargetBuffer::drawOT(CORO_PARAM) {
279 	CORO_BEGIN_CONTEXT;
280 	OTList *cur;
281 	OTList *prev;
282 	OTList *next;
283 	RMGfxPrimitive *myprim;
284 	bool result;
285 	CORO_END_CONTEXT(_ctx);
286 
287 	CORO_BEGIN_CODE(_ctx);
288 
289 	_ctx->prev = NULL;
290 	_ctx->cur = _otlist;
291 
292 	while (_ctx->cur != NULL) {
293 		// Call the task Draw method, passing it a copy of the original
294 		_ctx->myprim = _ctx->cur->_prim->duplicate();
295 		CORO_INVOKE_2(_ctx->cur->_prim->_task->draw, *this, _ctx->myprim);
296 		delete _ctx->myprim;
297 
298 		// Check if it's time to remove the task from the OT list
299 		CORO_INVOKE_1(_ctx->cur->_prim->_task->removeThis, _ctx->result);
300 		if (_ctx->result) {
301 			// De-register the task
302 			_ctx->cur->_prim->_task->unregister();
303 
304 			// Delete task, freeing the memory
305 			delete _ctx->cur->_prim;
306 			_ctx->next = _ctx->cur->_next;
307 			delete _ctx->cur;
308 
309 			// If it was the first item, update the list head
310 			if (_ctx->prev == NULL)
311 				_otlist = _ctx->next;
312 			// Otherwise update the next pinter of the previous item
313 			else
314 				_ctx->prev->_next = _ctx->next;
315 
316 			_ctx->cur = _ctx->next;
317 		} else {
318 			// Update the pointer to the previous item, and the current to the next
319 			_ctx->prev = _ctx->cur;
320 			_ctx->cur = _ctx->cur->_next;
321 		}
322 	}
323 
324 	CORO_END_CODE;
325 }
326 
addPrim(RMGfxPrimitive * prim)327 void RMGfxTargetBuffer::addPrim(RMGfxPrimitive *prim) {
328 	int nPrior;
329 	OTList *cur, *n;
330 
331 	// Warn of the OT listing
332 	prim->_task->Register();
333 
334 	// Check the priority
335 	nPrior = prim->_task->priority();
336 	n = new OTList(prim);
337 
338 	// Empty list
339 	if (_otlist == NULL) {
340 		_otlist = n;
341 		_otlist->_next = NULL;
342 	}
343 	// Inclusion in the head
344 	else if (nPrior < _otlist->_prim->_task->priority()) {
345 		n->_next = _otlist;
346 		_otlist = n;
347 	} else {
348 		cur = _otlist;
349 		while (cur->_next != NULL && nPrior > cur->_next->_prim->_task->priority())
350 			cur = cur->_next;
351 
352 		n->_next = cur->_next;
353 		cur->_next = n;
354 	}
355 }
356 
addDirtyRect(const Common::Rect & r)357 void RMGfxTargetBuffer::addDirtyRect(const Common::Rect &r) {
358 	assert(r.isValidRect());
359 	if (_trackDirtyRects && r.width() > 0 && r.height() > 0)
360 		_currentDirtyRects.push_back(r);
361 }
362 
getDirtyRects()363 Common::List<Common::Rect> &RMGfxTargetBuffer::getDirtyRects() {
364 	// Copy rects from both the current and previous frame into the output dirty rects list
365 	Common::List<Common::Rect>::iterator i;
366 	_dirtyRects.clear();
367 	for (i = _previousDirtyRects.begin(); i != _previousDirtyRects.end(); ++i)
368 		_dirtyRects.push_back(*i);
369 	for (i = _currentDirtyRects.begin(); i != _currentDirtyRects.end(); ++i)
370 		_dirtyRects.push_back(*i);
371 
372 	mergeDirtyRects();
373 	return _dirtyRects;
374 }
375 
376 /**
377  * Move the set of dirty rects from the finished current frame into the previous frame list.
378  */
clearDirtyRects()379 void RMGfxTargetBuffer::clearDirtyRects() {
380 	Common::List<Common::Rect>::iterator i;
381 	_previousDirtyRects.clear();
382 	for (i = _currentDirtyRects.begin(); i != _currentDirtyRects.end(); ++i)
383 		_previousDirtyRects.push_back(*i);
384 
385 	_currentDirtyRects.clear();
386 }
387 
388 /**
389  * Merges any clipping rectangles that overlap to try and reduce
390  * the total number of clip rectangles.
391  */
mergeDirtyRects()392 void RMGfxTargetBuffer::mergeDirtyRects() {
393 	if (_dirtyRects.size() <= 1)
394 		return;
395 
396 	Common::List<Common::Rect>::iterator rOuter, rInner;
397 
398 	for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
399 		rInner = rOuter;
400 		while (++rInner != _dirtyRects.end()) {
401 
402 			if ((*rOuter).intersects(*rInner)) {
403 				// these two rectangles overlap or
404 				// are next to each other - merge them
405 
406 				(*rOuter).extend(*rInner);
407 
408 				// remove the inner rect from the list
409 				_dirtyRects.erase(rInner);
410 
411 				// move back to beginning of list
412 				rInner = rOuter;
413 			}
414 		}
415 	}
416 }
417 
418 uint16 *RMGfxTargetBuffer::_precalcTable = NULL;
419 
420 /**
421  * Set up the black & white precalculated mapping table. This is only
422  * called if the user selects the black & white option.
423  */
createBWPrecalcTable()424 void RMGfxTargetBuffer::createBWPrecalcTable() {
425 	_precalcTable = new uint16[0x10000];
426 
427 	for (int i = 0; i < 0x10000; i++) {
428 		int r = (i >> 11) & 0x1F;
429 		int g = (i >> 6) & 0x1F;
430 		int b = i & 0x1F;
431 
432 		int min = MIN(r, MIN(g, b));
433 		int max = MAX(r, MAX(g, b));
434 
435 		min = (min + max) / 2;
436 
437 		r = CLIP(min + 8 - 8, 0, 0x1f);
438 		g = CLIP(min + 5 - 8, 0, 0x1f);
439 		b = CLIP(min + 0 - 8, 0, 0x1f);
440 
441 		_precalcTable[i] = (r << 11) | (g << 6) | b;
442 	}
443 }
444 
445 /**
446  * Frees the black & white precalculated mapping table.
447  */
freeBWPrecalcTable()448 void RMGfxTargetBuffer::freeBWPrecalcTable() {
449 	delete[] _precalcTable;
450 	_precalcTable = NULL;
451 }
452 
operator byte*()453 RMGfxTargetBuffer::operator byte *() {
454 	return _buf;
455 }
456 
operator void*()457 RMGfxTargetBuffer::operator void *() {
458 	return (void *)_buf;
459 }
460 
operator uint16*()461 RMGfxTargetBuffer::operator uint16 *() {
462 	// FIXME: This may not be endian safe
463 	return (uint16 *)_buf;
464 }
465 
466 /**
467  * Offseting buffer
468  */
offsetY(int nLines)469 void RMGfxTargetBuffer::offsetY(int nLines) {
470 	RMGfxBuffer::offsetY(nLines, 16);
471 }
472 
setTrackDirtyRects(bool v)473 void RMGfxTargetBuffer::setTrackDirtyRects(bool v) {
474 	_trackDirtyRects = v;
475 }
476 
getTrackDirtyRects() const477 bool RMGfxTargetBuffer::getTrackDirtyRects() const {
478 	return _trackDirtyRects;
479 }
480 
481 /****************************************************************************\
482 *               RMGfxSourceBufferPal Methods
483 \****************************************************************************/
484 
~RMGfxSourceBufferPal()485 RMGfxSourceBufferPal::~RMGfxSourceBufferPal() {
486 }
487 
loadPaletteWA(const byte * buf,bool bSwapped)488 int RMGfxSourceBufferPal::loadPaletteWA(const byte *buf, bool bSwapped) {
489 	if (bSwapped) {
490 		for (int i = 0; i < (1 << getBpp()); i++) {
491 			_pal[i * 3 + 0] = buf[i * 3 + 2];
492 			_pal[i * 3 + 1] = buf[i * 3 + 1];
493 			_pal[i * 3 + 2] = buf[i * 3 + 0];
494 		}
495 	} else {
496 		memcpy(_pal, buf, (1 << getBpp()) * 3);
497 	}
498 
499 	preparePalette();
500 
501 	return (1 << getBpp()) * 3;
502 }
503 
loadPalette(const byte * buf)504 int RMGfxSourceBufferPal::loadPalette(const byte *buf) {
505 	for (int i = 0; i < 256; i++)
506 		memcpy(_pal + i * 3, buf + i * 4, 3);
507 
508 	preparePalette();
509 
510 	return (1 << getBpp()) * 4;
511 }
512 
preparePalette()513 void RMGfxSourceBufferPal::preparePalette() {
514 	for (int i = 0; i < 256; i++) {
515 		// we convert 555 to 565 here.
516 		_palFinal[i] = (((int)_pal[i * 3 + 0] >> 3) <<  11) |
517 		                (((int)_pal[i * 3 + 1] >> 3) <<  6) |
518 		                (((int)_pal[i * 3 + 2] >> 3) <<  0);
519 	}
520 }
521 
init(const byte * buf,int dimx,int dimy,bool bLoadPalette)522 int RMGfxSourceBufferPal::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
523 	// Load the RAW image
524 	int read = RMGfxSourceBuffer::init(buf, dimx, dimy);
525 
526 	// Load the palette if necessary
527 	if (bLoadPalette)
528 		read += loadPaletteWA(&buf[read]);
529 
530 	return read;
531 }
532 
init(Common::ReadStream & ds,int dimx,int dimy,bool bLoadPalette)533 void RMGfxSourceBufferPal::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
534 	// Load the RAW image
535 	RMGfxSourceBuffer::init(ds, dimx, dimy);
536 
537 	// Load the palette if necessary
538 	if (bLoadPalette) {
539 		byte *suxpal = new byte[256 * 3];
540 		ds.read(suxpal, 256 * 3);
541 		loadPaletteWA(suxpal);
542 		delete[] suxpal;
543 	}
544 }
545 
loadPalette(uint32 resID)546 int RMGfxSourceBufferPal::loadPalette(uint32 resID) {
547 	return loadPalette(RMRes(resID));
548 }
549 
loadPaletteWA(uint32 resID,bool bSwapped)550 int RMGfxSourceBufferPal::loadPaletteWA(uint32 resID, bool bSwapped) {
551 	return loadPaletteWA(RMRes(resID), bSwapped);
552 }
553 
554 /****************************************************************************\
555 *               RMGfxSourceBuffer4 Methods
556 \****************************************************************************/
557 
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)558 void RMGfxSourceBuffer4::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
559 }
560 
RMGfxSourceBuffer4(int dimx,int dimy)561 RMGfxSourceBuffer4::RMGfxSourceBuffer4(int dimx, int dimy)
562 	: RMGfxBuffer(dimx, dimy, 4) {
563 	setPriority(0);
564 }
565 
566 /**
567  * Returns the number of bits per pixel of the surface
568  *
569  * @returns     Bit per pixel
570  */
getBpp()571 int RMGfxSourceBuffer4::getBpp() {
572 	return 4;
573 }
574 
create(int dimx,int dimy)575 void RMGfxSourceBuffer4::create(int dimx, int dimy) {
576 	RMGfxBuffer::create(dimx, dimy, 4);
577 }
578 
579 /****************************************************************************\
580 *               RMGfxSourceBuffer8 Methods
581 \****************************************************************************/
582 
~RMGfxSourceBuffer8()583 RMGfxSourceBuffer8::~RMGfxSourceBuffer8() {
584 }
585 
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)586 void RMGfxSourceBuffer8::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
587 	int width = 0, height = 0, u = 0, v = 0;
588 	int bufx = bigBuf.getDimx();
589 	uint16 *buf = bigBuf;
590 	byte *raw = _buf;
591 
592 	// Destination buffer
593 	RMRect dst;
594 	if (prim->haveDst())
595 		dst = prim->getDst();
596 
597 	// Clipping
598 	if (prim->haveSrc()) {
599 		u = prim->getSrc()._x1;
600 		v = prim->getSrc()._y1;
601 
602 		width = prim->getSrc().width();
603 		height = prim->getSrc().height();
604 	}
605 
606 	if (!clip2D(dst._x1, dst._y1, u, v, width, height, prim->haveSrc(), &bigBuf))
607 		return;
608 
609 	// Starting offset into the buffer
610 	buf += dst._y1 * bufx + dst._x1;
611 
612 	// Normal step
613 	if (_bTrasp0) {
614 		for (int y = 0; y < height; y++) {
615 			raw = _buf + (y + v) * _dimx + u;
616 
617 			for (int x = 0; x < width; x++) {
618 				if (*raw)
619 					*buf = _palFinal[*raw];
620 				buf++;
621 				raw++;
622 			}
623 
624 			buf += bufx - width;
625 		}
626 	} else {
627 		for (int y = 0; y < height; y++) {
628 			raw = _buf + (y + v) * _dimx + u;
629 
630 			for (int x = 0; x < width; x += 2) {
631 				buf[0] = _palFinal[raw[0]];
632 				buf[1] = _palFinal[raw[1]];
633 
634 				buf += 2;
635 				raw += 2;
636 			}
637 
638 			buf += bufx - width;
639 		}
640 	}
641 
642 	// Specify the drawn area
643 	bigBuf.addDirtyRect(Common::Rect(dst._x1, dst._y1, dst._x1 + width, dst._y1 + height));
644 }
645 
RMGfxSourceBuffer8(int dimx,int dimy)646 RMGfxSourceBuffer8::RMGfxSourceBuffer8(int dimx, int dimy)
647 	: RMGfxBuffer(dimx, dimy, 8) {
648 	setPriority(0);
649 	_bTrasp0 = false;
650 }
651 
RMGfxSourceBuffer8(bool bTrasp0)652 RMGfxSourceBuffer8::RMGfxSourceBuffer8(bool bTrasp0) {
653 	_bTrasp0 = bTrasp0;
654 }
655 
656 /**
657  * Returns the number of bits per pixel of the surface
658  *
659  * @returns     Bit per pixel
660  */
getBpp()661 int RMGfxSourceBuffer8::getBpp() {
662 	return 8;
663 }
664 
create(int dimx,int dimy)665 void RMGfxSourceBuffer8::create(int dimx, int dimy) {
666 	RMGfxBuffer::create(dimx, dimy, 8);
667 }
668 
669 #define GETRED(x)   (((x) >> 11) & 0x1F)
670 #define GETGREEN(x) (((x) >> 5) & 0x3F)
671 #define GETBLUE(x)   ((x) & 0x1F)
672 
673 /****************************************************************************\
674 *               RMGfxSourceBuffer8AB Methods
675 \****************************************************************************/
676 
~RMGfxSourceBuffer8AB()677 RMGfxSourceBuffer8AB::~RMGfxSourceBuffer8AB() {
678 }
679 
calcTrasp(int fore,int back)680 int RMGfxSourceBuffer8AB::calcTrasp(int fore, int back) {
681 	int r = (GETRED(fore) >> 2) + (GETRED(back) >> 1);
682 	int g = (GETGREEN(fore) >> 2) + (GETGREEN(back) >> 1);
683 	int b = (GETBLUE(fore) >> 2) + (GETBLUE(back) >> 1);
684 
685 	if (r > 0x1F)
686 		r = 0x1F;
687 
688 	if (g > 0x3F)
689 		g = 0x3F;
690 
691 	if (b > 0x1F)
692 		b = 0x1F;
693 
694 	return (r << 11) | (g << 5) | b;
695 }
696 
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)697 void RMGfxSourceBuffer8AB::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
698 	int width = 0, height = 0, u = 0, v = 0;
699 	int bufx = bigBuf.getDimx();
700 	uint16 *buf = bigBuf;
701 	byte *raw = _buf;
702 
703 	// Destination buffer
704 	RMRect dst;
705 	if (prim->haveDst())
706 		dst = prim->getDst();
707 
708 	// Clipping
709 	if (prim->haveSrc()) {
710 		u = prim->getSrc()._x1;
711 		v = prim->getSrc()._y1;
712 
713 		width = prim->getSrc().width();
714 		height = prim->getSrc().height();
715 	}
716 
717 	if (!clip2D(dst._x1, dst._y1, u, v, width, height, prim->haveSrc(), &bigBuf))
718 		return;
719 
720 	// Starting offset into the buffer
721 	buf += dst._y1 * bufx + dst._x1;
722 
723 	// Passaggio normale
724 	if (_bTrasp0) {
725 		for (int y = 0; y < height; y++) {
726 			raw = _buf + (y + v) * _dimx + u;
727 
728 			for (int x = 0; x < width; x++) {
729 				if (*raw)
730 					*buf = calcTrasp(_palFinal[*raw], *buf);
731 
732 				buf++;
733 				raw++;
734 			}
735 
736 			buf += bufx - width;
737 		}
738 	} else {
739 		for (int y = 0; y < height; y++) {
740 			raw = _buf + (y + v) * _dimx + u;
741 
742 			for (int x = 0; x < width; x += 2) {
743 				buf[0] = calcTrasp(_palFinal[raw[0]], buf[0]);
744 				buf[1] = calcTrasp(_palFinal[raw[1]], buf[1]);
745 
746 				buf += 2;
747 				raw += 2;
748 			}
749 
750 			buf += bufx - width;
751 		}
752 	}
753 
754 	// Specify the drawn area
755 	bigBuf.addDirtyRect(Common::Rect(dst._x1, dst._y1, dst._x1 + width, dst._y1 + height));
756 }
757 
758 /****************************************************************************\
759 *               RMGfxSourceBuffer8RLE Methods
760 \****************************************************************************/
761 
762 byte RMGfxSourceBuffer8RLE::_megaRLEBuf[512 * 1024];
763 
setAlphaBlendColor(int color)764 void RMGfxSourceBuffer8RLE::setAlphaBlendColor(int color) {
765 	_alphaBlendColor = color;
766 }
767 
RMGfxSourceBuffer8RLE()768 RMGfxSourceBuffer8RLE::RMGfxSourceBuffer8RLE() {
769 	_alphaBlendColor = -1;
770 	_bNeedRLECompress = true;
771 	_buf = NULL;
772 
773 	_alphaR = _alphaG = _alphaB = 0;
774 }
775 
~RMGfxSourceBuffer8RLE()776 RMGfxSourceBuffer8RLE::~RMGfxSourceBuffer8RLE() {
777 	if (_buf != NULL) {
778 		delete[] _buf;
779 		_buf = NULL;
780 	}
781 }
782 
init(const byte * buf,int dimx,int dimy,bool bLoadPalette)783 int RMGfxSourceBuffer8RLE::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
784 	return RMGfxSourceBufferPal::init(buf, dimx, dimy, bLoadPalette);
785 }
786 
init(Common::ReadStream & ds,int dimx,int dimy,bool bLoadPalette)787 void RMGfxSourceBuffer8RLE::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
788 	if (_bNeedRLECompress) {
789 		RMGfxSourceBufferPal::init(ds, dimx, dimy, bLoadPalette);
790 	} else {
791 		int size = ds.readSint32LE();
792 		_buf = new byte[size];
793 		ds.read(_buf, size);
794 
795 		_dimx = dimx;
796 		_dimy = dimy;
797 	}
798 }
799 
preparePalette()800 void RMGfxSourceBuffer8RLE::preparePalette() {
801 	// Invoke the parent method
802 	RMGfxSourceBuffer8::preparePalette();
803 
804 	// Handle RGB alpha blending
805 	if (_alphaBlendColor != -1) {
806 		_alphaR = (_palFinal[_alphaBlendColor] >> 11) & 0x1F;
807 		_alphaG = (_palFinal[_alphaBlendColor] >> 5) & 0x3F;
808 		_alphaB = (_palFinal[_alphaBlendColor]) & 0x1F;
809 	}
810 }
811 
prepareImage()812 void RMGfxSourceBuffer8RLE::prepareImage() {
813 	// Invoke the parent method
814 	RMGfxSourceBuffer::prepareImage();
815 
816 	// Compress
817 	compressRLE();
818 }
819 
setAlreadyCompressed()820 void RMGfxSourceBuffer8RLE::setAlreadyCompressed() {
821 	_bNeedRLECompress = false;
822 }
823 
compressRLE()824 void RMGfxSourceBuffer8RLE::compressRLE() {
825 	byte *cur;
826 	byte curdata;
827 	byte *src;
828 
829 	// Perform RLE compression for lines
830 	cur = _megaRLEBuf;
831 	src = _buf;
832 	for (int y = 0; y < _dimy; y++) {
833 		// Save the beginning of the line
834 		byte *startline = cur;
835 
836 		// Leave space for the length of the line
837 		cur += 2;
838 
839 		// It starts from the empty space
840 		curdata = 0;
841 		int rep = 0;
842 		byte *startsrc = src;
843 		for (int x = 0; x < _dimx;) {
844 			if ((curdata == 0 && *src == 0) || (curdata == 1 && *src == _alphaBlendColor)
845 			        || (curdata == 2 && (*src != _alphaBlendColor && *src != 0))) {
846 				src++;
847 				rep++;
848 				x++;
849 			} else {
850 				if (curdata == 0) {
851 					rleWriteTrasp(cur, rep);
852 					curdata++;
853 				} else if (curdata == 1) {
854 					rleWriteAlphaBlend(cur, rep);
855 					curdata++;
856 				} else {
857 					rleWriteData(cur, rep, startsrc);
858 					curdata = 0;
859 				}
860 
861 				rep = 0;
862 				startsrc = src;
863 			}
864 		}
865 
866 		// Pending data?
867 		if (curdata == 1) {
868 			rleWriteAlphaBlend(cur, rep);
869 			rleWriteData(cur, 0, NULL);
870 		}
871 
872 		if (curdata == 2) {
873 			rleWriteData(cur, rep, startsrc);
874 		}
875 
876 		// End of line
877 		rleWriteEOL(cur);
878 
879 		// Write the length of the line
880 		WRITE_LE_UINT16(startline, (uint16)(cur - startline));
881 	}
882 
883 	// Delete the original image
884 	delete[] _buf;
885 
886 	// Copy the compressed image
887 	int bufSize = cur - _megaRLEBuf;
888 	_buf = new byte[bufSize];
889 	Common::copy(_megaRLEBuf, _megaRLEBuf + bufSize, _buf);
890 }
891 
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)892 void RMGfxSourceBuffer8RLE::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
893 	byte *src;
894 	uint16 *buf = bigBuf;
895 	int u, v, width, height;
896 
897 	// Clipping
898 	int x1 = prim->getDst()._x1;
899 	int y1 = prim->getDst()._y1;
900 	if (!clip2D(x1, y1, u, v, width, height, false, &bigBuf))
901 		return;
902 
903 	// Go forward through the RLE lines
904 	src = _buf;
905 	for (int y = 0; y < v; y++)
906 		src += READ_LE_UINT16(src);
907 
908 	// Calculate the position in the destination buffer
909 	buf += y1 * bigBuf.getDimx();
910 
911 	// Loop
912 	if (prim->isFlipped()) {
913 // Eliminate horizontal clipping
914 //		width = m_dimx;
915 //		x1=prim->getDst()._x1;
916 
917 		// Clipping
918 		u = _dimx - (width + u);
919 		x1 = (prim->getDst()._x1 + _dimx - 1) - u;
920 
921 		if (width > x1)
922 			width = x1;
923 
924 		// Specify the drawn area
925 		bigBuf.addDirtyRect(Common::Rect(x1 - width, y1, x1 + 1, y1 + height));
926 
927 		for (int y = 0; y < height; y++) {
928 			// Decompression
929 			rleDecompressLineFlipped(buf + x1, src + 2, u, width);
930 
931 			// Next line
932 			src += READ_LE_UINT16(src);
933 
934 			// Skip to the next line
935 			buf += bigBuf.getDimx();
936 		}
937 	} else {
938 		// Specify the drawn area
939 		bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + width, y1 + height));
940 
941 		for (int y = 0; y < height; y++) {
942 			// Decompression
943 			rleDecompressLine(buf + x1, src + 2, u, width);
944 
945 			// Next line
946 			src += READ_LE_UINT16(src);
947 
948 			// Skip to the next line
949 			buf += bigBuf.getDimx();
950 		}
951 	}
952 }
953 
954 /****************************************************************************\
955 *               RMGfxSourceBuffer8RLEByte Methods
956 \****************************************************************************/
957 
~RMGfxSourceBuffer8RLEByte()958 RMGfxSourceBuffer8RLEByte::~RMGfxSourceBuffer8RLEByte() {
959 }
960 
rleWriteTrasp(byte * & cur,int rep)961 void RMGfxSourceBuffer8RLEByte::rleWriteTrasp(byte *&cur, int rep) {
962 	assert(rep < 255);
963 	*cur ++ = rep;
964 }
965 
rleWriteAlphaBlend(byte * & cur,int rep)966 void RMGfxSourceBuffer8RLEByte::rleWriteAlphaBlend(byte *&cur, int rep) {
967 	assert(rep < 255);
968 	*cur ++ = rep;
969 }
970 
rleWriteData(byte * & cur,int rep,byte * src)971 void RMGfxSourceBuffer8RLEByte::rleWriteData(byte *&cur, int rep, byte *src) {
972 	assert(rep < 256);
973 
974 	*cur ++ = rep;
975 	if (rep > 0) {
976 		memcpy(cur, src, rep);
977 		cur += rep;
978 		src += rep;
979 	}
980 
981 	return;
982 }
983 
rleWriteEOL(byte * & cur)984 void RMGfxSourceBuffer8RLEByte::rleWriteEOL(byte *&cur) {
985 	*cur ++ = 0xFF;
986 }
987 
rleDecompressLine(uint16 * dst,byte * src,int nStartSkip,int nLength)988 void RMGfxSourceBuffer8RLEByte::rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
989 	int n;
990 
991 	if (nStartSkip == 0)
992 		goto RLEByteDoTrasp;
993 
994 	while (1) {
995 		assert(nStartSkip > 0);
996 
997 		// TRASP
998 		n =  *src++;
999 		if (n == 0xFF)
1000 			return;
1001 
1002 		if (n >= nStartSkip) {
1003 			dst += n - nStartSkip;
1004 			nLength -= n - nStartSkip;
1005 			if (nLength > 0)
1006 				goto RLEByteDoAlpha;
1007 			else
1008 				return;
1009 		}
1010 		nStartSkip -= n;
1011 
1012 
1013 		assert(nStartSkip > 0);
1014 
1015 		// ALPHA
1016 		n = *src++;
1017 		if (n >= nStartSkip) {
1018 			n -= nStartSkip;
1019 			goto RLEByteDoAlpha2;
1020 		}
1021 		nStartSkip -= n;
1022 
1023 		assert(nStartSkip > 0);
1024 
1025 		// DATA
1026 		n = *src++;
1027 		if (n >= nStartSkip) {
1028 			src += nStartSkip;
1029 			n -= nStartSkip;
1030 			goto RLEByteDoCopy2;
1031 		}
1032 		nStartSkip -= n;
1033 		src += n;
1034 	}
1035 
1036 	while (1) {
1037 RLEByteDoTrasp:
1038 		// Get the trasp of s**t
1039 		n = *src++;
1040 
1041 		// EOL?
1042 		if (n == 0xFF)
1043 			return;
1044 
1045 		dst += n;
1046 		nLength -= n;
1047 		if (nLength <= 0)
1048 			return;
1049 
1050 RLEByteDoAlpha:
1051 		// Alpha
1052 		n = *src++;
1053 
1054 RLEByteDoAlpha2:
1055 		if (n > nLength)
1056 			n = nLength;
1057 		for (int i = 0; i < n; i++) {
1058 			int r = (*dst >> 11) & 0x1F;
1059 			int g = (*dst >> 5) & 0x3F;
1060 			int b = *dst & 0x1F;
1061 
1062 			r = (r >> 2) + (_alphaR >> 1);
1063 			g = (g >> 2) + (_alphaG >> 1);
1064 			b = (b >> 2) + (_alphaB >> 1);
1065 
1066 			*dst ++ = (r << 11) | (g << 5) | b;
1067 		}
1068 
1069 		nLength -= n;
1070 		if (!nLength)
1071 			return;
1072 		assert(nLength > 0);
1073 
1074 //RLEByteDoCopy:
1075 		// Copy the stuff
1076 		n = *src++;
1077 
1078 RLEByteDoCopy2:
1079 		if (n > nLength)
1080 			n = nLength;
1081 
1082 		for (int i = 0; i < n; i++)
1083 			*dst ++ = _palFinal[*src++];
1084 
1085 		nLength -= n;
1086 		if (!nLength)
1087 			return;
1088 		assert(nLength > 0);
1089 	}
1090 }
1091 
rleDecompressLineFlipped(uint16 * dst,byte * src,int nStartSkip,int nLength)1092 void RMGfxSourceBuffer8RLEByte::rleDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) {
1093 	int n;
1094 
1095 	if (nStartSkip == 0)
1096 		goto RLEByteFlippedDoTrasp;
1097 
1098 	while (1) {
1099 		assert(nStartSkip > 0);
1100 
1101 		// TRASP
1102 		n = *src++;
1103 		if (n == 0xFF)
1104 			return;
1105 
1106 		if (n >= nStartSkip) {
1107 			dst -= n - nStartSkip;
1108 			nLength -= n - nStartSkip;
1109 			if (nLength > 0)
1110 				goto RLEByteFlippedDoAlpha;
1111 			else
1112 				return;
1113 		}
1114 		nStartSkip -= n;
1115 
1116 
1117 		assert(nStartSkip > 0);
1118 
1119 		// ALPHA
1120 		n = *src++;
1121 		if (n >= nStartSkip) {
1122 			n -= nStartSkip;
1123 			goto RLEByteFlippedDoAlpha2;
1124 		}
1125 		nStartSkip -= n;
1126 
1127 		assert(nStartSkip > 0);
1128 
1129 		// DATA
1130 		n = *src++;
1131 		if (n >= nStartSkip) {
1132 			src += nStartSkip;
1133 			n -= nStartSkip;
1134 			goto RLEByteFlippedDoCopy2;
1135 		}
1136 		nStartSkip -= n;
1137 		src += n;
1138 	}
1139 
1140 	while (1) {
1141 RLEByteFlippedDoTrasp:
1142 		// Get the trasp of s**t
1143 		n = *src++;
1144 
1145 		// EOL?
1146 		if (n == 0xFF)
1147 			return;
1148 
1149 		dst -= n;
1150 		nLength -= n;
1151 		if (nLength <= 0)
1152 			return;
1153 
1154 RLEByteFlippedDoAlpha:
1155 		// Alpha
1156 		n = *src++;
1157 
1158 RLEByteFlippedDoAlpha2:
1159 		if (n > nLength)
1160 			n = nLength;
1161 		for (int i = 0; i < n; i++) {
1162 			int r = (*dst >> 11) & 0x1F;
1163 			int g = (*dst >> 5) & 0x3F;
1164 			int b = *dst & 0x1F;
1165 
1166 			r = (r >> 2) + (_alphaR >> 1);
1167 			g = (g >> 2) + (_alphaG >> 1);
1168 			b = (b >> 2) + (_alphaB >> 1);
1169 
1170 			*dst-- = (r << 11) | (g << 5) | b;
1171 		}
1172 
1173 		nLength -= n;
1174 		if (!nLength)
1175 			return;
1176 		assert(nLength > 0);
1177 
1178 //RLEByteFlippedDoCopy:
1179 		// Copy the data
1180 		n = *src++;
1181 
1182 RLEByteFlippedDoCopy2:
1183 		if (n > nLength)
1184 			n = nLength;
1185 
1186 		for (int i = 0; i < n; i++)
1187 			*dst-- = _palFinal[*src++];
1188 
1189 		nLength -= n;
1190 		if (!nLength)
1191 			return;
1192 		assert(nLength > 0);
1193 	}
1194 }
1195 
1196 /****************************************************************************\
1197 *               RMGfxSourceBuffer8RLEWord Methods
1198 \****************************************************************************/
1199 
~RMGfxSourceBuffer8RLEWord()1200 RMGfxSourceBuffer8RLEWord::~RMGfxSourceBuffer8RLEWord() {
1201 }
1202 
rleWriteTrasp(byte * & cur,int rep)1203 void RMGfxSourceBuffer8RLEWord::rleWriteTrasp(byte *&cur, int rep) {
1204 	WRITE_LE_UINT16(cur, rep);
1205 	cur += 2;
1206 }
1207 
rleWriteAlphaBlend(byte * & cur,int rep)1208 void RMGfxSourceBuffer8RLEWord::rleWriteAlphaBlend(byte *&cur, int rep) {
1209 	WRITE_LE_UINT16(cur, rep);
1210 	cur += 2;
1211 }
1212 
rleWriteData(byte * & cur,int rep,byte * src)1213 void RMGfxSourceBuffer8RLEWord::rleWriteData(byte *&cur, int rep, byte *src) {
1214 	WRITE_LE_UINT16(cur, rep);
1215 	cur += 2;
1216 
1217 	if (rep > 0) {
1218 		memcpy(cur, src, rep);
1219 		cur += rep;
1220 		src += rep;
1221 	}
1222 }
1223 
rleWriteEOL(byte * & cur)1224 void RMGfxSourceBuffer8RLEWord::rleWriteEOL(byte *&cur) {
1225 	*cur ++ = 0xFF;
1226 	*cur ++ = 0xFF;
1227 }
1228 
rleDecompressLine(uint16 * dst,byte * src,int nStartSkip,int nLength)1229 void RMGfxSourceBuffer8RLEWord::rleDecompressLine(uint16 *dst, byte *src, int nStartSkip, int nLength) {
1230 	int n;
1231 
1232 	if (nStartSkip == 0)
1233 		goto RLEWordDoTrasp;
1234 
1235 	while (1) {
1236 		assert(nStartSkip > 0);
1237 
1238 		// TRASP
1239 		n = READ_LE_UINT16(src);
1240 		src += 2;
1241 
1242 		if (n == 0xFFFF)
1243 			return;
1244 
1245 		if (n >= nStartSkip) {
1246 			dst += n - nStartSkip;
1247 			nLength -= n - nStartSkip;
1248 
1249 			if (nLength > 0)
1250 				goto RLEWordDoAlpha;
1251 			else
1252 				return;
1253 		}
1254 		nStartSkip -= n;
1255 
1256 		assert(nStartSkip > 0);
1257 
1258 		// ALPHA
1259 		n = READ_LE_UINT16(src);
1260 		src += 2;
1261 
1262 		if (n >= nStartSkip) {
1263 			n -= nStartSkip;
1264 			goto RLEWordDoAlpha2;
1265 		}
1266 		nStartSkip -= n;
1267 
1268 		// DATA
1269 		n = READ_LE_UINT16(src);
1270 		src += 2;
1271 
1272 		if (n >= nStartSkip) {
1273 			src += nStartSkip;
1274 			n -= nStartSkip;
1275 			goto RLEWordDoCopy2;
1276 		}
1277 		nStartSkip -= n;
1278 		src += n;
1279 	}
1280 
1281 	while (1) {
1282 RLEWordDoTrasp:
1283 		// Get the trasp of s**t
1284 		n = READ_LE_UINT16(src);
1285 		src += 2;
1286 
1287 		// EOL?
1288 		if (n == 0xFFFF)
1289 			return;
1290 
1291 		dst += n;
1292 
1293 		nLength -= n;
1294 		if (nLength <= 0)
1295 			return;
1296 
1297 RLEWordDoAlpha:
1298 		n = READ_LE_UINT16(src);
1299 		src += 2;
1300 
1301 RLEWordDoAlpha2:
1302 		if (n > nLength)
1303 			n = nLength;
1304 
1305 		for (int i = 0; i < n; i++) {
1306 			int r = (*dst >> 11) & 0x1F;
1307 			int g = (*dst >> 5) & 0x3F;
1308 			int b = *dst & 0x1F;
1309 
1310 			r = (r >> 2) + (_alphaR >> 1);
1311 			g = (g >> 2) + (_alphaG >> 1);
1312 			b = (b >> 2) + (_alphaB >> 1);
1313 
1314 			*dst++ = (r << 11) | (g << 5) | b;
1315 		}
1316 
1317 		nLength -= n;
1318 		if (!nLength)
1319 			return;
1320 
1321 		assert(nLength > 0);
1322 
1323 //RLEWordDoCopy:
1324 		// Copy the data
1325 		n = READ_LE_UINT16(src);
1326 		src += 2;
1327 
1328 RLEWordDoCopy2:
1329 		if (n > nLength)
1330 			n = nLength;
1331 
1332 		for (int i = 0; i < n; i++)
1333 			*dst++ = _palFinal[*src++];
1334 
1335 		nLength -= n;
1336 		if (!nLength)
1337 			return;
1338 
1339 		assert(nLength > 0);
1340 	}
1341 }
1342 
rleDecompressLineFlipped(uint16 * dst,byte * src,int nStartSkip,int nLength)1343 void RMGfxSourceBuffer8RLEWord::rleDecompressLineFlipped(uint16 *dst, byte *src, int nStartSkip, int nLength) {
1344 	int n;
1345 
1346 	if (nStartSkip == 0)
1347 		goto RLEWordFlippedDoTrasp;
1348 
1349 	while (1) {
1350 		assert(nStartSkip > 0);
1351 
1352 		// TRASP
1353 		n = READ_LE_UINT16(src);
1354 		src += 2;
1355 
1356 		if (n == 0xFFFF)
1357 			return;
1358 
1359 		if (n >= nStartSkip) {
1360 			dst -= n - nStartSkip;
1361 			nLength -= n - nStartSkip;
1362 
1363 			if (nLength > 0)
1364 				goto RLEWordFlippedDoAlpha;
1365 			else
1366 				return;
1367 		}
1368 		nStartSkip -= n;
1369 
1370 		assert(nStartSkip > 0);
1371 
1372 		// ALPHA
1373 		n = READ_LE_UINT16(src);
1374 		src += 2;
1375 
1376 		if (n >= nStartSkip) {
1377 			n -= nStartSkip;
1378 			goto RLEWordFlippedDoAlpha2;
1379 		}
1380 		nStartSkip -= n;
1381 
1382 		// DATA
1383 		n = READ_LE_UINT16(src);
1384 		src += 2;
1385 
1386 		if (n >= nStartSkip) {
1387 			src += nStartSkip;
1388 			n -= nStartSkip;
1389 			goto RLEWordFlippedDoCopy2;
1390 		}
1391 		nStartSkip -= n;
1392 		src += n;
1393 	}
1394 
1395 	while (1) {
1396 RLEWordFlippedDoTrasp:
1397 		// Get the trasp of s**t
1398 		n = READ_LE_UINT16(src);
1399 		src += 2;
1400 
1401 		// EOL?
1402 		if (n == 0xFFFF)
1403 			return;
1404 
1405 		dst -= n;
1406 
1407 		nLength -= n;
1408 		if (nLength <= 0)
1409 			return;
1410 
1411 RLEWordFlippedDoAlpha:
1412 		n = READ_LE_UINT16(src);
1413 		src += 2;
1414 
1415 RLEWordFlippedDoAlpha2:
1416 		if (n > nLength)
1417 			n = nLength;
1418 
1419 		for (int i = 0; i < n; i++) {
1420 			int r = (*dst >> 11) & 0x1F;
1421 			int g = (*dst >> 5) & 0x3F;
1422 			int b = *dst & 0x1F;
1423 
1424 			r = (r >> 2) + (_alphaR >> 1);
1425 			g = (g >> 2) + (_alphaG >> 1);
1426 			b = (b >> 2) + (_alphaB >> 1);
1427 
1428 			*dst-- = (r << 11) | (g << 5) | b;
1429 		}
1430 
1431 		nLength -= n;
1432 		if (!nLength)
1433 			return;
1434 
1435 		assert(nLength > 0);
1436 
1437 //RLEWordFlippedDoCopy:
1438 		// Copy the data
1439 		n = READ_LE_UINT16(src);
1440 		src += 2;
1441 
1442 RLEWordFlippedDoCopy2:
1443 		if (n > nLength)
1444 			n = nLength;
1445 
1446 		for (int i = 0; i < n; i++)
1447 			*dst-- = _palFinal[*src++];
1448 
1449 		nLength -= n;
1450 		if (!nLength)
1451 			return;
1452 
1453 		assert(nLength > 0);
1454 	}
1455 }
1456 
1457 /****************************************************************************\
1458 *               Methods for RMGfxSourceBuffer8RLEWord
1459 \****************************************************************************/
1460 
~RMGfxSourceBuffer8RLEWordAB()1461 RMGfxSourceBuffer8RLEWordAB::~RMGfxSourceBuffer8RLEWordAB() {
1462 }
1463 
rleDecompressLine(uint16 * dst,byte * src,int nStartSkip,int nLength)1464 void RMGfxSourceBuffer8RLEWordAB::rleDecompressLine(uint16 *dst, byte *src,  int nStartSkip, int nLength) {
1465 	int n;
1466 
1467 	if (!GLOBALS._bCfgTransparence) {
1468 		RMGfxSourceBuffer8RLEWord::rleDecompressLine(dst, src, nStartSkip, nLength);
1469 		return;
1470 	}
1471 
1472 	if (nStartSkip == 0)
1473 		goto RLEWordDoTrasp;
1474 
1475 	while (1) {
1476 		assert(nStartSkip > 0);
1477 
1478 		// TRASP
1479 		n = READ_LE_UINT16(src);
1480 		src += 2;
1481 
1482 		if (n == 0xFFFF)
1483 			return;
1484 
1485 		if (n >= nStartSkip) {
1486 			dst += n - nStartSkip;
1487 			nLength -= n - nStartSkip;
1488 
1489 			if (nLength > 0)
1490 				goto RLEWordDoAlpha;
1491 			else
1492 				return;
1493 		}
1494 		nStartSkip -= n;
1495 
1496 		assert(nStartSkip > 0);
1497 
1498 		// ALPHA
1499 		n = READ_LE_UINT16(src);
1500 		src += 2;
1501 
1502 		if (n >= nStartSkip) {
1503 			n -= nStartSkip;
1504 			goto RLEWordDoAlpha2;
1505 		}
1506 		nStartSkip -= n;
1507 
1508 		// DATA
1509 		n = READ_LE_UINT16(src);
1510 		src += 2;
1511 
1512 		if (n >= nStartSkip) {
1513 			src += nStartSkip;
1514 			n -= nStartSkip;
1515 			goto RLEWordDoCopy2;
1516 		}
1517 		nStartSkip -= n;
1518 		src += n;
1519 	}
1520 
1521 	while (1) {
1522 RLEWordDoTrasp:
1523 		// Get the trasp of s**t
1524 		n = READ_LE_UINT16(src);
1525 		src += 2;
1526 
1527 		// EOL?
1528 		if (n == 0xFFFF)
1529 			return;
1530 
1531 		dst += n;
1532 
1533 		nLength -= n;
1534 		if (nLength <= 0)
1535 			return;
1536 
1537 RLEWordDoAlpha:
1538 		n = READ_LE_UINT16(src);
1539 		src += 2;
1540 
1541 RLEWordDoAlpha2:
1542 		if (n > nLength)
1543 			n = nLength;
1544 
1545 		// @@@ SHOULD NOT BE THERE !!!!!
1546 		for (int i = 0; i < n; i++) {
1547 			int r = (*dst >> 11) & 0x1F;
1548 			int g = (*dst >> 5) & 0x3F;
1549 			int b = *dst & 0x1F;
1550 
1551 			r = (r >> 2) + (_alphaR >> 1);
1552 			g = (g >> 2) + (_alphaG >> 1);
1553 			b = (b >> 2) + (_alphaB >> 1);
1554 
1555 			*dst++ = (r << 11) | (g << 5) | b;
1556 		}
1557 
1558 		nLength -= n;
1559 		if (!nLength)
1560 			return;
1561 
1562 		assert(nLength > 0);
1563 
1564 //RLEWordDoCopy:
1565 		// Copy the data
1566 		n = READ_LE_UINT16(src);
1567 		src += 2;
1568 
1569 RLEWordDoCopy2:
1570 		if (n > nLength)
1571 			n = nLength;
1572 
1573 		for (int i = 0; i < n; i++) {
1574 			int r = (*dst >> 11) & 0x1F;
1575 			int g = (*dst >> 5) & 0x3F;
1576 			int b = *dst & 0x1F;
1577 
1578 			int r2 = (_palFinal[*src] >> 11) & 0x1F;
1579 			int g2 = (_palFinal[*src] >> 5) & 0x3F;
1580 			int b2 = _palFinal[*src] & 0x1F;
1581 
1582 			r = (r >> 1) + (r2 >> 1);
1583 			g = (g >> 1) + (g2 >> 1);
1584 			b = (b >> 1) + (b2 >> 1);
1585 
1586 			*dst ++ = (r << 11) | (g << 5) | b;
1587 			src++;
1588 		}
1589 
1590 		nLength -= n;
1591 		if (!nLength)
1592 			return;
1593 
1594 		assert(nLength > 0);
1595 	}
1596 }
1597 
1598 /****************************************************************************\
1599 *               Methods for RMGfxSourceBuffer8AA
1600 \****************************************************************************/
1601 
1602 byte RMGfxSourceBuffer8AA::_megaAABuf[256 * 1024];
1603 byte RMGfxSourceBuffer8AA::_megaAABuf2[64 * 1024];
1604 
prepareImage()1605 void RMGfxSourceBuffer8AA::prepareImage() {
1606 	// Invoke the parent method
1607 	RMGfxSourceBuffer::prepareImage();
1608 
1609 	// Prepare the buffer for anti-aliasing
1610 	calculateAA();
1611 }
1612 
calculateAA()1613 void RMGfxSourceBuffer8AA::calculateAA() {
1614 	byte *src, *srcaa;
1615 
1616 	// First pass: fill the edges
1617 	Common::fill(_megaAABuf, _megaAABuf + _dimx * _dimy, 0);
1618 
1619 	src = _buf;
1620 	srcaa = _megaAABuf;
1621 	for (int y = 0; y < _dimy; y++) {
1622 		for (int x = 0; x < _dimx; x++) {
1623 			if (*src == 0) {
1624 				if ((y > 0 && src[-_dimx] != 0) ||
1625 				    (y < _dimy - 1 && src[_dimx] != 0) ||
1626 				    (x > 0 && src[-1] != 0) ||
1627 				    (x < _dimx - 1 && src[1] != 0))
1628 					*srcaa = 1;
1629 			}
1630 
1631 			src++;
1632 			srcaa++;
1633 		}
1634 	}
1635 
1636 	src = _buf;
1637 	srcaa = _megaAABuf;
1638 	for (int y = 0; y < _dimy; y++) {
1639 		for (int x = 0; x < _dimx; x++) {
1640 			if (*src != 0) {
1641 				if ((y > 0 && srcaa[-_dimx] == 1) ||
1642 				    (y < _dimy - 1 && srcaa[_dimx] == 1) ||
1643 				    (x > 0 && srcaa[-1] == 1) ||
1644 				    (x < _dimx - 1 && srcaa[1] == 1))
1645 					*srcaa = 2;
1646 			}
1647 
1648 			src++;
1649 			srcaa++;
1650 		}
1651 	}
1652 
1653 	if (_aabuf != NULL)
1654 		delete[] _aabuf;
1655 
1656 	_aabuf = new byte[_dimx * _dimy];
1657 	memcpy(_aabuf, _megaAABuf, _dimx * _dimy);
1658 }
1659 
RMGfxSourceBuffer8AA()1660 RMGfxSourceBuffer8AA::RMGfxSourceBuffer8AA() : RMGfxSourceBuffer8() {
1661 	_aabuf = NULL;
1662 }
1663 
~RMGfxSourceBuffer8AA()1664 RMGfxSourceBuffer8AA::~RMGfxSourceBuffer8AA() {
1665 	if (_aabuf != NULL)
1666 		delete[] _aabuf;
1667 }
1668 
drawAA(RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)1669 void RMGfxSourceBuffer8AA::drawAA(RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
1670 	byte *src;
1671 	uint16 *mybuf;
1672 	uint16 *buf;
1673 	int u, v, width, height;
1674 
1675 	// Clip the sprite
1676 	int x1 = prim->getDst()._x1;
1677 	int y1 = prim->getDst()._y1;
1678 	if (!clip2D(x1, y1, u, v, width, height, false, &bigBuf))
1679 		return;
1680 
1681 	// Go forward through the RLE lines
1682 	src = _buf;
1683 	for (int y = 0; y < v; y++)
1684 		src += READ_LE_UINT16(src);
1685 
1686 	// Eliminate horizontal clipping
1687 	if (prim->isFlipped()) {
1688 		u = _dimx - (width + u);
1689 		x1 = (prim->getDst()._x1 + _dimx - 1) - u;
1690 
1691 		if (width > x1)
1692 			width = x1;
1693 
1694 		// Specify the drawn area
1695 		bigBuf.addDirtyRect(Common::Rect(x1 - width, y1, x1 + 1, y1 + height));
1696 	} else {
1697 		// Specify the drawn area
1698 		bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + width, y1 + height));
1699 	}
1700 
1701 	//width = _dimx;
1702 	//x1 = prim->getDst()._x1;
1703 
1704 	// Position into the destination buffer
1705 	buf = bigBuf;
1706 	buf += y1 * bigBuf.getDimx();
1707 
1708 	int step;
1709 	if (prim->isFlipped())
1710 		step = -1;
1711 	else
1712 		step = 1;
1713 
1714 	// Loop
1715 	buf += bigBuf.getDimx(); // Skip the first line
1716 	for (int y = 1; y < height - 1; y++) {
1717 		// if (prim->isFlipped())
1718 		//	mybuf=&buf[x1+m_dimx-1];
1719 		// else
1720 		mybuf = &buf[x1];
1721 
1722 		for (int x = 0; x < width; x++, mybuf += step) {
1723 			if (_aabuf[(y + v) * _dimx + x + u] == 2 && x != 0 && x != width - 1) {
1724 				int r = GETRED(mybuf[1]) + GETRED(mybuf[-1]) + GETRED(mybuf[-bigBuf.getDimx()]) + GETRED(mybuf[bigBuf.getDimx()]);
1725 				int g = GETGREEN(mybuf[1]) + GETGREEN(mybuf[-1]) + GETGREEN(mybuf[-bigBuf.getDimx()]) + GETGREEN(mybuf[bigBuf.getDimx()]);
1726 				int b = GETBLUE(mybuf[1]) + GETBLUE(mybuf[-1]) + GETBLUE(mybuf[-bigBuf.getDimx()]) + GETBLUE(mybuf[bigBuf.getDimx()]);
1727 
1728 				r += GETRED(mybuf[0]);
1729 				g += GETGREEN(mybuf[0]);
1730 				b += GETBLUE(mybuf[0]);
1731 
1732 				r /= 5;
1733 				g /= 5;
1734 				b /= 5;
1735 
1736 				mybuf[0] = (r << 11) | (g << 5) | b;
1737 			}
1738 		}
1739 
1740 		// Skip to the next line
1741 		buf += bigBuf.getDimx();
1742 	}
1743 
1744 	// Position into the destination buffer
1745 	buf = bigBuf;
1746 	buf += y1 * bigBuf.getDimx();
1747 
1748 	// Looppone
1749 	buf += bigBuf.getDimx();
1750 	for (int y = 1; y < height - 1; y++) {
1751 		// if (prim->isFlipped())
1752 		// 	mybuf=&buf[x1+m_dimx-1];
1753 		// else
1754 		mybuf = &buf[x1];
1755 
1756 		for (int x = 0; x < width; x++, mybuf += step) {
1757 			if (_aabuf[(y + v) * _dimx + x + u] == 1 && x != 0 && x != width - 1) {
1758 				int r = GETRED(mybuf[1]) + GETRED(mybuf[-1]) + GETRED(mybuf[-bigBuf.getDimx()]) + GETRED(mybuf[bigBuf.getDimx()]);
1759 				int g = GETGREEN(mybuf[1]) + GETGREEN(mybuf[-1]) + GETGREEN(mybuf[-bigBuf.getDimx()]) + GETGREEN(mybuf[bigBuf.getDimx()]);
1760 				int b = GETBLUE(mybuf[1]) + GETBLUE(mybuf[-1]) + GETBLUE(mybuf[-bigBuf.getDimx()]) + GETBLUE(mybuf[bigBuf.getDimx()]);
1761 
1762 				r += GETRED(mybuf[0]) * 2;
1763 				g += GETGREEN(mybuf[0]) * 2;
1764 				b += GETBLUE(mybuf[0]) * 2;
1765 
1766 				r /= 6;
1767 				g /= 6;
1768 				b /= 6;
1769 
1770 				mybuf[0] = (r << 11) | (g << 5) | b;
1771 			}
1772 		}
1773 
1774 		// Skip to the next line
1775 		buf += bigBuf.getDimx();
1776 	}
1777 }
1778 
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)1779 void RMGfxSourceBuffer8AA::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
1780 	CORO_BEGIN_CONTEXT;
1781 	CORO_END_CONTEXT(_ctx);
1782 
1783 	CORO_BEGIN_CODE(_ctx);
1784 
1785 	CORO_INVOKE_2(RMGfxSourceBuffer8::draw, bigBuf, prim);
1786 	drawAA(bigBuf, prim);
1787 
1788 	CORO_END_CODE;
1789 }
1790 
1791 /****************************************************************************\
1792 *               RMGfxSourceBuffer8RLEAA Methods
1793 \****************************************************************************/
1794 
~RMGfxSourceBuffer8RLEByteAA()1795 RMGfxSourceBuffer8RLEByteAA::~RMGfxSourceBuffer8RLEByteAA() {
1796 }
1797 
prepareImage()1798 void RMGfxSourceBuffer8RLEByteAA::prepareImage() {
1799 	RMGfxSourceBuffer::prepareImage();
1800 	calculateAA();
1801 	compressRLE();
1802 }
1803 
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)1804 void RMGfxSourceBuffer8RLEByteAA::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
1805 	CORO_BEGIN_CONTEXT;
1806 	CORO_END_CONTEXT(_ctx);
1807 
1808 	CORO_BEGIN_CODE(_ctx);
1809 
1810 	CORO_INVOKE_2(RMGfxSourceBuffer8RLE::draw, bigBuf, prim);
1811 	if (GLOBALS._bCfgAntiAlias)
1812 		drawAA(bigBuf, prim);
1813 
1814 	CORO_END_CODE;
1815 }
1816 
init(const byte * buf,int dimx,int dimy,bool bLoadPalette)1817 int RMGfxSourceBuffer8RLEByteAA::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
1818 	return RMGfxSourceBuffer8RLE::init(buf, dimx, dimy, bLoadPalette);
1819 }
1820 
init(Common::ReadStream & ds,int dimx,int dimy,bool bLoadPalette)1821 void RMGfxSourceBuffer8RLEByteAA::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
1822 	RMGfxSourceBuffer8RLE::init(ds, dimx, dimy, bLoadPalette);
1823 
1824 	if (!_bNeedRLECompress) {
1825 		// Load the anti-aliasing mask
1826 		_aabuf = new byte[dimx * dimy];
1827 		ds.read(_aabuf, dimx * dimy);
1828 	}
1829 }
1830 
~RMGfxSourceBuffer8RLEWordAA()1831 RMGfxSourceBuffer8RLEWordAA::~RMGfxSourceBuffer8RLEWordAA() {
1832 }
1833 
prepareImage()1834 void RMGfxSourceBuffer8RLEWordAA::prepareImage() {
1835 	RMGfxSourceBuffer::prepareImage();
1836 	calculateAA();
1837 	compressRLE();
1838 }
1839 
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)1840 void RMGfxSourceBuffer8RLEWordAA::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
1841 	CORO_BEGIN_CONTEXT;
1842 	CORO_END_CONTEXT(_ctx);
1843 
1844 	CORO_BEGIN_CODE(_ctx);
1845 
1846 	CORO_INVOKE_2(RMGfxSourceBuffer8RLE::draw, bigBuf, prim);
1847 	if (GLOBALS._bCfgAntiAlias)
1848 		drawAA(bigBuf, prim);
1849 
1850 	CORO_END_CODE;
1851 }
1852 
init(const byte * buf,int dimx,int dimy,bool bLoadPalette)1853 int RMGfxSourceBuffer8RLEWordAA::init(const byte *buf, int dimx, int dimy, bool bLoadPalette) {
1854 	return RMGfxSourceBuffer8RLE::init(buf, dimx, dimy, bLoadPalette);
1855 }
1856 
init(Common::ReadStream & ds,int dimx,int dimy,bool bLoadPalette)1857 void RMGfxSourceBuffer8RLEWordAA::init(Common::ReadStream &ds, int dimx, int dimy, bool bLoadPalette) {
1858 	RMGfxSourceBuffer8RLE::init(ds, dimx, dimy, bLoadPalette);
1859 
1860 	if (!_bNeedRLECompress) {
1861 		// Load the anti-aliasing mask
1862 		_aabuf = new byte[dimx * dimy];
1863 		ds.read(_aabuf, dimx * dimy);
1864 	}
1865 }
1866 
1867 /****************************************************************************\
1868 *               RMGfxSourceBuffer16 Methods
1869 \****************************************************************************/
1870 
RMGfxSourceBuffer16(bool bTrasp0)1871 RMGfxSourceBuffer16::RMGfxSourceBuffer16(bool bTrasp0) {
1872 	_bTrasp0 = bTrasp0;
1873 }
1874 
~RMGfxSourceBuffer16()1875 RMGfxSourceBuffer16::~RMGfxSourceBuffer16() {
1876 }
1877 
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)1878 void RMGfxSourceBuffer16::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
1879 	uint16 *buf = bigBuf;
1880 	uint16 *raw = (uint16 *)_buf;
1881 
1882 	int dimx = _dimx;
1883 	int dimy = _dimy;
1884 	int u = 0;
1885 	int v = 0;
1886 	int x1 = 0;
1887 	int y1 = 0;
1888 
1889 	if (prim->haveSrc()) {
1890 		u = prim->getSrc()._x1;
1891 		v = prim->getSrc()._y1;
1892 		dimx = prim->getSrc().width();
1893 		dimy = prim->getSrc().height();
1894 	}
1895 
1896 	if (prim->haveDst()) {
1897 		x1 = prim->getDst()._x1;
1898 		y1 = prim->getDst()._y1;
1899 	}
1900 
1901 	if (!clip2D(x1, y1, u, v, dimx, dimy, true, &bigBuf))
1902 		return;
1903 
1904 	raw += v * _dimx + u;
1905 	buf += y1 * bigBuf.getDimx() + x1;
1906 
1907 	if (_bTrasp0) {
1908 		for (int y = 0; y < dimy; y++) {
1909 			for (int x = 0; x < dimx;) {
1910 				while (x < dimx && raw[x] == 0)
1911 					x++;
1912 
1913 				while (x < dimx && raw[x] != 0) {
1914 					buf[x] = raw[x];
1915 					x++;
1916 				}
1917 			}
1918 
1919 			raw += _dimx;
1920 			buf += bigBuf.getDimx();
1921 		}
1922 	} else {
1923 		for (int y = 0; y < dimy; y++) {
1924 			Common::copy(raw, raw + dimx, buf);
1925 			buf += bigBuf.getDimx();
1926 			raw += _dimx;
1927 		}
1928 	}
1929 
1930 	// Specify the drawn area
1931 	bigBuf.addDirtyRect(Common::Rect(x1, y1, x1 + dimx, y1 + dimy));
1932 }
1933 
prepareImage()1934 void RMGfxSourceBuffer16::prepareImage() {
1935 	// Color space conversion if necessary!
1936 	uint16 *buf = (uint16 *)_buf;
1937 
1938 	// convert 555 to 565
1939 	for (int i = 0; i < _dimx * _dimy; i++) {
1940 		uint16 pixel = FROM_LE_16(buf[i]);
1941 		int r = (pixel >> 10) & 0x1F;
1942 		int g = (pixel >> 5) & 0x1F;
1943 		int b = pixel & 0x1F;
1944 
1945 		pixel = (r << 11) | (g << 6) | b;
1946 
1947 		buf[i] = pixel;
1948 	}
1949 }
1950 
RMGfxSourceBuffer16(int dimx,int dimy)1951 RMGfxSourceBuffer16::RMGfxSourceBuffer16(int dimx, int dimy)
1952 	: RMGfxBuffer(dimx, dimy, 16) {
1953 	setPriority(0);
1954 	_bTrasp0 = false;
1955 }
1956 
1957 /**
1958  * Returns the number of bits per pixel of the surface
1959  *
1960  * @returns     Bit per pixel
1961  */
getBpp()1962 int RMGfxSourceBuffer16::getBpp() {
1963 	return 16;
1964 }
1965 
create(int dimx,int dimy)1966 void RMGfxSourceBuffer16::create(int dimx, int dimy) {
1967 	RMGfxBuffer::create(dimx, dimy, 16);
1968 }
1969 
1970 /****************************************************************************\
1971 *               RMGfxBox Methods
1972 \****************************************************************************/
1973 
removeThis(CORO_PARAM,bool & result)1974 void RMGfxBox::removeThis(CORO_PARAM, bool &result) {
1975 	result = true;
1976 }
1977 
setColor(byte r,byte g,byte b)1978 void RMGfxBox::setColor(byte r, byte g, byte b) {
1979 	r >>= 3;
1980 	g >>= 3;
1981 	b >>= 3;
1982 	// These are hard-coded colors, so we convert 555 to 565.
1983 	_wFillColor = (r << 11) | (g << 6) | b;
1984 }
1985 
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive * prim)1986 void RMGfxBox::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *prim) {
1987 	uint16 *buf = bigBuf;
1988 	RMRect rcDst;
1989 
1990 	// It takes the destination rectangle
1991 	rcDst = prim->getDst();
1992 	buf += rcDst._y1 * bigBuf.getDimx() + rcDst._x1;
1993 
1994 	// Loop through the pixels
1995 	for (int j = 0; j < rcDst.height(); j++) {
1996 		for (int i = 0; i < rcDst.width(); i++)
1997 			*buf++ = _wFillColor;
1998 
1999 		buf += bigBuf.getDimx() - rcDst.width();
2000 	}
2001 
2002 	// Specify the drawn area
2003 	bigBuf.addDirtyRect(rcDst);
2004 }
2005 
2006 /****************************************************************************\
2007 *       RMGfxClearTask Methods
2008 \****************************************************************************/
2009 
priority()2010 int RMGfxClearTask::priority() {
2011 	// Maximum priority (must be done first)
2012 	return 1;
2013 }
2014 
draw(CORO_PARAM,RMGfxTargetBuffer & bigBuf,RMGfxPrimitive *)2015 void RMGfxClearTask::draw(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMGfxPrimitive *) {
2016 	// Clean the target buffer
2017 	Common::fill((byte *)bigBuf, (byte *)bigBuf + (bigBuf.getDimx() * bigBuf.getDimy() * 2), 0x0);
2018 	bigBuf.addDirtyRect(Common::Rect(bigBuf.getDimx(), bigBuf.getDimy()));
2019 }
2020 
removeThis(CORO_PARAM,bool & result)2021 void RMGfxClearTask::removeThis(CORO_PARAM, bool &result) {
2022 	// The task is fine to be removed
2023 	result = true;
2024 }
2025 
2026 /****************************************************************************\
2027 *       RMGfxPrimitive Methods
2028 \****************************************************************************/
2029 
RMGfxPrimitive()2030 RMGfxPrimitive::RMGfxPrimitive() {
2031 	_bFlag = 0;
2032 	_task = NULL;
2033 	_src.setEmpty();
2034 	_dst.setEmpty();
2035 	_bStretch = false;
2036 }
2037 
RMGfxPrimitive(RMGfxTask * task)2038 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task) {
2039 	_task = task;
2040 	_bFlag = 0;
2041 	_bStretch = false;
2042 }
2043 
RMGfxPrimitive(RMGfxTask * task,const RMRect & src,RMRect & dst)2044 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMRect &src, RMRect &dst) {
2045 	_task = task;
2046 	_src = src;
2047 	_dst = dst;
2048 	_bFlag = 0;
2049 	_bStretch = (src.width() != dst.width() || src.height() != dst.height());
2050 }
2051 
RMGfxPrimitive(RMGfxTask * task,const RMPoint & src,RMRect & dst)2052 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMPoint &src, RMRect &dst) {
2053 	_task = task;
2054 	_src.topLeft() = src;
2055 	_dst = dst;
2056 	_bFlag = 0;
2057 	_bStretch = false;
2058 }
2059 
RMGfxPrimitive(RMGfxTask * task,const RMPoint & src,RMPoint & dst)2060 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMPoint &src, RMPoint &dst) {
2061 	_task = task;
2062 	_src.topLeft() = src;
2063 	_dst.topLeft() = dst;
2064 	_bFlag = 0;
2065 	_bStretch = false;
2066 }
2067 
RMGfxPrimitive(RMGfxTask * task,const RMRect & src,RMPoint & dst)2068 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMRect &src, RMPoint &dst) {
2069 	_task = task;
2070 	_src = src;
2071 	_dst.topLeft() = dst;
2072 	_bFlag = 0;
2073 	_bStretch = false;
2074 }
2075 
RMGfxPrimitive(RMGfxTask * task,const RMRect & dst)2076 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMRect &dst) {
2077 	_task = task;
2078 	_dst = dst;
2079 	_src.setEmpty();
2080 	_bFlag = 0;
2081 	_bStretch = false;
2082 }
2083 
RMGfxPrimitive(RMGfxTask * task,const RMPoint & dst)2084 RMGfxPrimitive::RMGfxPrimitive(RMGfxTask *task, const RMPoint &dst) {
2085 	_task = task;
2086 	_dst.topLeft() = dst;
2087 	_src.setEmpty();
2088 	_bFlag = 0;
2089 	_bStretch = false;
2090 }
2091 
~RMGfxPrimitive()2092 RMGfxPrimitive::~RMGfxPrimitive() {
2093 }
2094 
setFlag(byte bFlag)2095 void RMGfxPrimitive::setFlag(byte bFlag) {
2096 	_bFlag = bFlag;
2097 }
2098 
setTask(RMGfxTask * task)2099 void RMGfxPrimitive::setTask(RMGfxTask *task) {
2100 	_task = task;
2101 }
2102 
setSrc(const RMRect & src)2103 void RMGfxPrimitive::setSrc(const RMRect &src) {
2104 	_src = src;
2105 }
2106 
setSrc(const RMPoint & src)2107 void RMGfxPrimitive::setSrc(const RMPoint &src) {
2108 	_src.topLeft() = src;
2109 }
2110 
setDst(const RMRect & dst)2111 void RMGfxPrimitive::setDst(const RMRect &dst) {
2112 	_dst = dst;
2113 }
2114 
setDst(const RMPoint & dst)2115 void RMGfxPrimitive::setDst(const RMPoint &dst) {
2116 	_dst.topLeft() = dst;
2117 }
2118 
setStretch(bool bStretch)2119 void RMGfxPrimitive::setStretch(bool bStretch) {
2120 	_bStretch = bStretch;
2121 }
2122 
haveDst()2123 bool RMGfxPrimitive::haveDst() {
2124 	return !_dst.isEmpty();
2125 }
2126 
getDst()2127 RMRect &RMGfxPrimitive::getDst() {
2128 	return _dst;
2129 }
2130 
haveSrc()2131 bool RMGfxPrimitive::haveSrc() {
2132 	return !_src.isEmpty();
2133 }
2134 
getSrc()2135 RMRect &RMGfxPrimitive::getSrc() {
2136 	return _src;
2137 }
2138 
2139 /**
2140  * Flags
2141  */
isFlipped()2142 bool RMGfxPrimitive::isFlipped() {
2143 	return _bFlag & 1;
2144 }
2145 
2146 /**
2147  * Duplicate
2148  */
duplicate()2149 RMGfxPrimitive *RMGfxPrimitive::duplicate() {
2150 	return new RMGfxPrimitive(*this);
2151 }
2152 
2153 } // End of namespace Tony
2154