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  * aint32 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  * Based on the original sources
23  *   Faery Tale II -- The Halls of the Dead
24  *   (c) 1993-1996 The Wyrmkeep Entertainment Co.
25  */
26 
27 #include "common/debug.h"
28 #include "common/memstream.h"
29 #include "graphics/surface.h"
30 
31 #include "saga2/saga2.h"
32 #include "saga2/gdraw.h"
33 
34 namespace Saga2 {
35 
_BltPixels(uint8 * srcPtr,uint32 srcMod,uint8 * dstPtr,uint32 dstMod,uint32 width,uint32 height)36 void _BltPixels(uint8 *srcPtr, uint32 srcMod, uint8 *dstPtr, uint32 dstMod, uint32 width, uint32 height) {
37 	for (uint y = 0; y < height; y++) {
38 		uint8 *src = srcPtr + srcMod * y;
39 		uint8 *dst = dstPtr + dstMod * y;
40 		for (uint x = 0; x < width; x++) {
41 			*dst++ = *src++;
42 		}
43 	}
44 }
45 
_BltPixelsT(uint8 * srcPtr,uint32 srcMod,uint8 * dstPtr,uint32 dstMod,uint32 width,uint32 height)46 void _BltPixelsT(uint8 *srcPtr, uint32 srcMod, uint8 *dstPtr, uint32 dstMod, uint32 width, uint32 height) {
47 	for (uint y = 0; y < height; y++) {
48 		uint8 *src = srcPtr + srcMod * y;
49 		uint8 *dst = dstPtr + dstMod * y;
50 		for (uint x = 0; x < width; x++) {
51 			byte c = *src++;
52 
53 			if (c == 0)
54 				dst++;
55 			else
56 				*dst++ = c;
57 		}
58 	}
59 }
60 
_FillRect(uint8 * dstPtr,uint32 dstMod,uint32 width,uint32 height,uint32 color)61 void _FillRect(uint8 *dstPtr, uint32 dstMod, uint32 width, uint32 height, uint32 color) {
62 	for (uint y = 0; y < height; y++) {
63 		memset(dstPtr, color, width);
64 
65 		dstPtr += dstMod;
66 	}
67 }
68 
_HLine(uint8 * dstPtr,uint32 width,uint32 color)69 void _HLine(uint8 *dstPtr, uint32 width, uint32 color) {
70 	memset(dstPtr, color, width);
71 }
72 
unpackImage(gPixelMap & map,int16 width,int16 rowCount,int8 * srcData)73 void unpackImage(gPixelMap &map, int16 width, int16 rowCount, int8 *srcData) {
74 	int8  *dest = (int8 *)map.data;
75 	int16 bytecount = (width + 1) & ~1;
76 	int16 rowMod = map.size.x - bytecount;
77 
78 	while (rowCount--) {
79 		for (int16 k = 0; k < bytecount;) {
80 			int16 p = *srcData++;
81 
82 			if (p == -128)
83 				continue;
84 			else if (p >= 0) {
85 				p++;
86 				k += p;
87 				while (p--)
88 					*dest++ = *srcData++;
89 			} else {
90 				p = 1 - p;
91 				k += p;
92 				while (p--)
93 					*dest++ = *srcData;
94 				srcData++;
95 			}
96 		}
97 
98 		if (bytecount & 1)
99 			srcData++;
100 		dest += rowMod;
101 	}
102 }
103 
unpackImage(gPixelMap * map,int32 width,int32 rowCount,int8 * srcData)104 void unpackImage(gPixelMap *map, int32 width, int32 rowCount, int8 *srcData) {
105 	unpackImage(*map, (int16)width, (int16)rowCount, srcData);
106 }
107 
108 #define DEBUGPACK 0
109 
unpackSprite(gPixelMap * map,uint8 * sprData,uint32 dataSize)110 void unpackSprite(gPixelMap *map, uint8 *sprData, uint32 dataSize) {
111 	byte *dst = map->data;
112 	int bytes = map->size.x * map->size.y;
113 	bool fail = false;
114 
115 	if (!sprData) {
116 		warning("unpackSprite(): empty sprData");
117 		return;
118 	}
119 
120 	Common::MemoryReadStream stream(sprData, dataSize);
121 
122 	while (true) {
123 		byte trans = stream.readByte();
124 
125 		if (stream.eos()) {
126 			warning("unpackSprite: premature end of data");
127 			fail = true;
128 			break;
129 		}
130 
131 		if (bytes < trans) {
132 #if DEBUGPACK
133 			warning("unpackSprite: too many trans %d < %d for %dx%d (src %d bytes)", bytes, trans, map->size.x, map->size.y, dataSize);
134 #endif
135 			fail = true;
136 			break;
137 		}
138 		memset(dst, 0, trans);
139 		dst += trans;
140 		bytes -= trans;
141 
142 		if (bytes < 0)
143 			break;
144 
145 		byte fill = stream.readByte();
146 
147 		if (stream.eos()) {
148 			warning("unpackSprite: premature end of data");
149 			fail = true;
150 			break;
151 		}
152 		if (bytes < fill) {
153 #if DEBUGPACK
154 			warning("unpackSprite: too many fill %d < %d for %dx%d (src %d bytes)", bytes, fill, map->size.x, map->size.y, dataSize);
155 #endif
156 			fill = bytes;
157 			fail = true;
158 		}
159 		if (stream.read(dst, fill) != fill) {
160 			warning("unpackSprite: premature end of data");
161 			fail = true;
162 			break;
163 		}
164 		dst += fill;
165 		bytes -= fill;
166 
167 		if (bytes <= 0)
168 			break;
169 	}
170 
171 	if (!stream.eos()) {
172 #if DEBUGPACK
173 		warning("unpackSprite: %d bytes left", stream.size() - stream.pos());
174 #endif
175 		fail = true;
176 	}
177 
178 	if (fail) {
179 #if DEBUGPACK
180 		Graphics::Surface surf;
181 		surf.w = map->size.x;
182 		surf.h = map->size.y;
183 		surf.pitch = map->size.x;
184 		surf.format = Graphics::PixelFormat::createFormatCLUT8();
185 
186 		surf.setPixels(map->data);
187 
188 		surf.debugPrint();
189 #endif
190 	}
191 }
192 
drawTile(gPixelMap * map,int32 x,int32 y,int32 height,uint8 * srcData,bool mask)193 void drawTile(gPixelMap *map, int32 x, int32 y, int32 height, uint8 *srcData, bool mask) {
194 	const byte *tilePointer;
195 	const byte *readPointer;
196 	byte *drawPointer;
197 	Point32 drawPoint;
198 	int widthCount;
199 	int row, col, count, lowBound;
200 	int bgRunCount;
201 	int fgRunCount;
202 	const int32 SAGA_ISOTILE_WIDTH = 64;
203 	Point16 point(x - 32, y);
204 
205 	if (point.x + SAGA_ISOTILE_WIDTH < 0)
206 		return;
207 
208 	if (point.x - SAGA_ISOTILE_WIDTH >= map->size.x)
209 		return;
210 
211 	tilePointer = srcData;
212 
213 	drawPoint = point;
214 
215 	drawPoint.y -= height;
216 
217 	if (drawPoint.y >= map->size.y)
218 		return;
219 
220 	readPointer = tilePointer;
221 	lowBound = MIN((int)(drawPoint.y + height), (int)map->size.y);
222 	for (row = drawPoint.y; row < lowBound; row++) {
223 		widthCount = 0;
224 		if (row >= 0) {
225 			drawPointer = map->data + drawPoint.x + (row * map->size.x);
226 			col = drawPoint.x;
227 			for (;;) {
228 				bgRunCount = *readPointer++;
229 				widthCount += bgRunCount;
230 				if (widthCount >= SAGA_ISOTILE_WIDTH)
231 					break;
232 
233 				drawPointer += bgRunCount;
234 				col += bgRunCount;
235 				fgRunCount = *readPointer++;
236 				widthCount += fgRunCount;
237 
238 				count = 0;
239 				int colDiff = - col;
240 				if (colDiff > 0) {
241 					if (colDiff > fgRunCount)
242 						colDiff = fgRunCount;
243 
244 					count = colDiff;
245 					col += colDiff;
246 				}
247 
248 				colDiff = map->size.x - col;
249 				if (colDiff > 0) {
250 					int countDiff = fgRunCount - count;
251 					if (colDiff > countDiff)
252 						colDiff = countDiff;
253 
254 					if (colDiff > 0) {
255 						byte *dst = (byte *)(drawPointer + count);
256 						if (mask)
257 							memset(dst, 0, colDiff);
258 						else
259 							memcpy(dst, (readPointer + count), colDiff);
260 						col += colDiff;
261 					}
262 				}
263 
264 				readPointer += fgRunCount;
265 				drawPointer += fgRunCount;
266 			}
267 		} else {
268 			for (;;) {
269 				bgRunCount = *readPointer++;
270 				widthCount += bgRunCount;
271 				if (widthCount >= SAGA_ISOTILE_WIDTH)
272 					break;
273 
274 				fgRunCount = *readPointer++;
275 				widthCount += fgRunCount;
276 
277 				readPointer += fgRunCount;
278 			}
279 		}
280 	}
281 
282 	// Compute dirty rect
283 	int rectX = MAX<int>(drawPoint.x, 0);
284 	int rectY = MAX<int>(drawPoint.y, 0);
285 	int rectX2 = MIN<int>(drawPoint.x + SAGA_ISOTILE_WIDTH, map->size.x);
286 	int rectY2 = lowBound;
287 	debugC(3, kDebugTiles, "Rect = (%d,%d,%d,%d)", rectX, rectY, rectX2, rectY2);
288 
289 #if 0
290 	Graphics::Surface sur;
291 	sur.create(map->size.x, map->size.y, Graphics::PixelFormat::createFormatCLUT8());
292 	sur.setPixels(map->data);
293 	//sur.debugPrint();
294 	g_system->copyRectToScreen(sur.getPixels(), sur.pitch, 0, 0, sur.w, sur.h);
295 	g_system->updateScreen();
296 #endif
297 }
298 
299 
maskTile(gPixelMap * map,int32 x,int32 y,int32 height,uint8 * srcData)300 void maskTile(gPixelMap *map, int32 x, int32 y, int32 height, uint8 *srcData) {
301 	drawTile(map, x, y, height, srcData, true);
302 }
303 
TBlit(gPixelMap * dstMap,gPixelMap * srcMap,int32 xpos,int32 ypos)304 void TBlit(gPixelMap *dstMap, gPixelMap *srcMap, int32 xpos, int32 ypos) {
305 	int16 w = srcMap->size.x;
306 	int16 h = srcMap->size.y;
307 	int32 offset = 0;
308 
309 	if (ypos < 0) {
310 		h += ypos;
311 		offset -= (ypos * w);
312 		ypos = 0;
313 	}
314 
315 	if (xpos < 0) {
316 		w += xpos;
317 		offset -= xpos;
318 		xpos = 0;
319 	}
320 
321 	if (w > dstMap->size.x - xpos)
322 		w = dstMap->size.x - xpos;
323 	if (h > dstMap->size.y - ypos)
324 		h = dstMap->size.y - ypos;
325 	if (w < 0 || h < 0)
326 		return;
327 
328 	int16 dstMod = dstMap->size.x - w;
329 	int16 srcMod = srcMap->size.x - w;
330 
331 	byte *srcPtr = srcMap->data + offset;
332 	byte *dstPtr = dstMap->data + xpos + ypos * dstMap->size.x;
333 
334 	for (int16 y = 0; y < h; y++) {
335 		for (int16 x = 0; x < w; x++) {
336 			byte c = *srcPtr++;
337 
338 			if (c == 0)
339 				dstPtr++;
340 			else
341 				*dstPtr++ = c;
342 		}
343 		dstPtr += dstMod;
344 		srcPtr += srcMod;
345 	}
346 }
347 
TBlit4(gPixelMap * d,gPixelMap * s,int32 x,int32 y)348 void TBlit4(gPixelMap *d, gPixelMap *s, int32 x, int32 y) {
349 	TBlit(d, s, x, y);
350 }
351 
compositePixels(gPixelMap * compMap,gPixelMap * sprMap,int32 xpos,int32 ypos,byte * lookup)352 void compositePixels(gPixelMap *compMap, gPixelMap *sprMap, int32 xpos, int32 ypos, byte *lookup) {
353 	byte *srcPtr = sprMap->data;
354 	byte *dstPtr = compMap->data + xpos + ypos * compMap->size.x;
355 	int16 rowMod = compMap->size.x - sprMap->size.x;
356 
357 	for (int16 y = 0; y < sprMap->size.y; y++) {
358 		for (int16 x = 0; x < sprMap->size.x; x++) {
359 			byte c = *srcPtr++;
360 
361 			if (c == 0)
362 				dstPtr++;
363 			else
364 				*dstPtr++ = lookup[ c ];
365 		}
366 		dstPtr += rowMod;
367 	}
368 }
369 
compositePixelsRvs(gPixelMap * compMap,gPixelMap * sprMap,int32 xpos,int32 ypos,byte * lookup)370 void compositePixelsRvs(gPixelMap *compMap, gPixelMap *sprMap, int32 xpos, int32 ypos, byte *lookup) {
371 	byte *srcPtr = sprMap->data + sprMap->bytes();
372 	byte *dstPtr = compMap->data + xpos + (ypos + sprMap->size.y) * compMap->size.x;
373 
374 	int16 rowMod = compMap->size.x + sprMap->size.x;
375 
376 	for (int16 y = 0; y < sprMap->size.y; y++) {
377 		dstPtr -= rowMod;
378 
379 		for (int16 x = 0; x < sprMap->size.x; x++) {
380 			byte c = *--srcPtr;
381 
382 			if (c == 0)
383 				dstPtr++;
384 			else
385 				*dstPtr++ = lookup[c];
386 		}
387 	}
388 }
389 
initGraphics(void)390 bool initGraphics(void) {
391 	warning("STUB: initGraphics()");
392 	return false;
393 }
394 
initProcessResources(void)395 bool initProcessResources(void) {
396         return true;
397 }
398 
termProcessResources(void)399 void termProcessResources(void) {
400 }
401 
402 } // end of namespace Saga2
403