1 // Video rendering module for Psikyo SH2 games
2 // Lots of code here and there ripped directly from MAME
3 // Thanks to David Haywood for the initial MAME driver
4 // as well as some other valuable pointers.
5 
6 #include "tiles_generic.h" // nScreenWidth & nScreenHeight
7 #include "psikyosh_render.h" // contains loads of macros
8 
9 UINT8 *pPsikyoshTiles;
10 UINT32  *pPsikyoshSpriteBuffer;
11 UINT32  *pPsikyoshBgRAM;
12 UINT32  *pPsikyoshVidRegs;
13 UINT32  *pPsikyoshPalRAM;
14 UINT32  *pPsikyoshZoomRAM;
15 
16 static UINT8 *DrvTransTab;
17 static UINT8 alphatable[0x100];
18 
19 static UINT16 *DrvPriBmp;
20 static UINT8 *DrvZoomBmp;
21 static INT32 nDrvZoomPrev = -1;
22 static UINT32  *DrvTmpDraw;
23 static UINT32  *DrvTmpDraw_ptr;
24 
25 static INT32 nGraphicsMin0;  // minimum tile number 4bpp
26 static INT32 nGraphicsMin1;  // for 8bpp
27 static INT32 nGraphicsSize;  // normal
28 static INT32 nGraphicsSize0; // for 4bpp
29 static INT32 nGraphicsSize1; // for 8bpp
30 
31 //--------------------------------------------------------------------------------
32 
alpha_blend(UINT32 d,UINT32 s,UINT32 p)33 static inline UINT32 alpha_blend(UINT32 d, UINT32 s, UINT32 p)
34 {
35 	if (p == 0) return d;
36 
37 	INT32 a = 256 - p;
38 
39 	return (((((s & 0xff00ff) * p) + ((d & 0xff00ff) * a)) & 0xff00ff00) |
40 		((((s & 0x00ff00) * p) + ((d & 0x00ff00) * a)) & 0x00ff0000)) >> 8;
41 }
42 
43 //--------------------------------------------------------------------------------
44 
draw_blendy_tile(INT32 gfx,INT32 code,INT32 color,INT32 sx,INT32 sy,INT32 fx,INT32 fy,INT32 alpha,INT32 z)45 static void draw_blendy_tile(INT32 gfx, INT32 code, INT32 color, INT32 sx, INT32 sy, INT32 fx, INT32 fy, INT32 alpha, INT32 z)
46 {
47 	color <<= 4;
48 	UINT32 *pal = pBurnDrvPalette + color;
49 
50 	if (gfx == 0) {
51 		code &= 0x7ffff;
52 		code -= nGraphicsMin0;
53 		if (code < 0 || code > nGraphicsSize0) return;
54 
55 		if (DrvTransTab[code >> 3] & (1 << (code & 7))) return;
56 
57 		UINT8 *src = pPsikyoshTiles + (code << 7);
58 
59 		INT32 inc = 8;
60 		if (fy) {
61 			inc = -8;
62 			src += 0x78;
63 		}
64 
65 		if (sx >= 0 && sx < (nScreenWidth-16) && sy >= 0 && sy <= (nScreenHeight-16)) {
66 			if (z > 0) {
67 				if (fx) {
68 					if (alpha == 0xff) {
69 						PUTPIXEL_4BPP_NORMAL_PRIO_FLIPX()
70 					} else if (alpha >= 0) {
71 						PUTPIXEL_4BPP_ALPHA_PRIO_FLIPX()
72 					} else {
73 						PUTPIXEL_4BPP_ALPHATAB_PRIO_FLIPX()
74 					}
75 				} else {
76 					if (alpha == 0xff) {
77 						PUTPIXEL_4BPP_NORMAL_PRIO()
78 					} else if (alpha >= 0) {
79 						PUTPIXEL_4BPP_ALPHA_PRIO()
80 					} else {
81 						PUTPIXEL_4BPP_ALPHATAB_PRIO()
82 					}
83 				}
84 			} else {
85 				if (fx) {
86 					if (alpha == 0xff) {
87 						PUTPIXEL_4BPP_NORMAL_FLIPX()
88 					} else if (alpha >= 0) {
89 						PUTPIXEL_4BPP_ALPHA_FLIPX()
90 					} else {
91 						PUTPIXEL_4BPP_ALPHATAB_FLIPX()
92 					}
93 				} else {
94 					if (alpha == 0xff) {
95 						PUTPIXEL_4BPP_NORMAL()
96 					} else if (alpha >= 0) {
97 						PUTPIXEL_4BPP_ALPHA()
98 					} else {
99 						PUTPIXEL_4BPP_ALPHATAB()
100 					}
101 				}
102 			}
103 		} else {
104 			if (z > 0) {
105 				if (fx) {
106 					if (alpha == 0xff) {
107 						PUTPIXEL_4BPP_NORMAL_PRIO_FLIPX_CLIP()
108 					} else if (alpha >= 0) {
109 						PUTPIXEL_4BPP_ALPHA_PRIO_FLIPX_CLIP()
110 					} else {
111 						PUTPIXEL_4BPP_ALPHATAB_PRIO_FLIPX_CLIP()
112 					}
113 				} else {
114 					if (alpha == 0xff) {
115 						PUTPIXEL_4BPP_NORMAL_PRIO_CLIP()
116 					} else if (alpha >= 0) {
117 						PUTPIXEL_4BPP_ALPHA_PRIO_CLIP()
118 					} else {
119 						PUTPIXEL_4BPP_ALPHATAB_PRIO_CLIP()
120 					}
121 				}
122 			} else {
123 				if (fx) {
124 					if (alpha == 0xff) {
125 						PUTPIXEL_4BPP_NORMAL_FLIPX_CLIP()
126 					} else if (alpha >= 0) {
127 						PUTPIXEL_4BPP_ALPHA_FLIPX_CLIP()
128 					} else {
129 						PUTPIXEL_4BPP_ALPHATAB_FLIPX_CLIP()
130 					}
131 				} else {
132 					if (alpha == 0xff) {
133 						PUTPIXEL_4BPP_NORMAL_CLIP()
134 					} else if (alpha >= 0) {
135 						PUTPIXEL_4BPP_ALPHA_CLIP()
136 					} else {
137 						PUTPIXEL_4BPP_ALPHATAB_CLIP()
138 					}
139 				}
140 			}
141 		}
142 	} else {
143 		code &= 0x3ffff;
144 		code -= nGraphicsMin1;
145 		if (code < 0 || code > nGraphicsSize0) return;
146 
147 		if (DrvTransTab[(code >> 3) + 0x10000] & (1 << (code & 7))) return;
148 
149 		UINT8 *src = pPsikyoshTiles + (code << 8);
150 
151 		INT32 inc = 16;
152 		if (fy) {
153 			inc = -16;
154 			src += 0xf0;
155 		}
156 
157 		if (sx >= 0 && sx < (nScreenWidth-16) && sy >= 0 && sy < (nScreenHeight-16)) {
158 			if (z > 0) {
159 				if (fx) {
160 					if (alpha == 0xff) {
161 						PUTPIXEL_8BPP_NORMAL_PRIO_FLIPX()
162 					} else if (alpha >= 0) {
163 						PUTPIXEL_8BPP_ALPHA_PRIO_FLIPX()
164 					} else {
165 						PUTPIXEL_8BPP_ALPHATAB_PRIO_FLIPX()
166 					}
167 				} else {
168 					if (alpha == 0xff) {
169 						PUTPIXEL_8BPP_NORMAL_PRIO()
170 					} else if (alpha >= 0) {
171 						PUTPIXEL_8BPP_ALPHA_PRIO()
172 					} else {
173 						PUTPIXEL_8BPP_ALPHATAB_PRIO()
174 					}
175 				}
176 			} else {
177 				if (fx) {
178 					if (alpha == 0xff) {
179 						PUTPIXEL_8BPP_NORMAL_FLIPX()
180 					} else if (alpha >= 0) {
181 						PUTPIXEL_8BPP_ALPHA_FLIPX()
182 					} else {
183 						PUTPIXEL_8BPP_ALPHATAB_FLIPX()
184 					}
185 				} else {
186 					if (alpha == 0xff) {
187 						PUTPIXEL_8BPP_NORMAL()
188 					} else if (alpha >= 0) {
189 						PUTPIXEL_8BPP_ALPHA()
190 					} else {
191 						PUTPIXEL_8BPP_ALPHATAB()
192 					}
193 				}
194 			}
195 		} else {
196 			if (z > 0) {
197 				if (fx) {
198 					if (alpha == 0xff) {
199 						PUTPIXEL_8BPP_NORMAL_PRIO_FLIPX_CLIP()
200 					} else if (alpha >= 0) {
201 						PUTPIXEL_8BPP_ALPHA_PRIO_FLIPX_CLIP()
202 					} else {
203 						PUTPIXEL_8BPP_ALPHATAB_PRIO_FLIPX_CLIP()
204 					}
205 				} else {
206 					if (alpha == 0xff) {
207 						PUTPIXEL_8BPP_NORMAL_PRIO_CLIP()
208 					} else if (alpha >= 0) {
209 						PUTPIXEL_8BPP_ALPHA_PRIO_CLIP()
210 					} else {
211 						PUTPIXEL_8BPP_ALPHATAB_PRIO_CLIP()
212 					}
213 				}
214 			} else {
215 				if (fx) {
216 					if (alpha == 0xff) {
217 						PUTPIXEL_8BPP_NORMAL_FLIPX_CLIP()
218 					} else if (alpha >= 0) {
219 						PUTPIXEL_8BPP_ALPHA_FLIPX_CLIP()
220 					} else {
221 						PUTPIXEL_8BPP_ALPHATAB_FLIPX_CLIP()
222 					}
223 				} else {
224 					if (alpha == 0xff) {
225 						PUTPIXEL_8BPP_NORMAL_CLIP()
226 					} else if (alpha >= 0) {
227 						PUTPIXEL_8BPP_ALPHA_CLIP()
228 					} else {
229 						PUTPIXEL_8BPP_ALPHATAB_CLIP()
230 					}
231 				}
232 			}
233 
234 		}
235 	}
236 }
237 
draw_prezoom(INT32 gfx,INT32 code,INT32 high,INT32 wide)238 static void draw_prezoom(INT32 gfx, INT32 code, INT32 high, INT32 wide)
239 {
240 	// these probably aren't the safest routines, but they should be pretty fast.
241 
242 	if (gfx) {
243 		INT32 tileno = (code & 0x3ffff) - nGraphicsMin1;
244 		if (tileno < 0 || tileno > nGraphicsSize1) tileno = 0;
245 		if (nDrvZoomPrev == tileno) return;
246 		nDrvZoomPrev = tileno;
247 		UINT32 *gfxptr = (UINT32*)(pPsikyoshTiles + (tileno << 8));
248 
249 		for (INT32 ytile = 0; ytile < high; ytile++)
250 		{
251 			for (INT32 xtile = 0; xtile < wide; xtile++)
252 			{
253 				UINT32 *dest = (UINT32*)(DrvZoomBmp + (ytile << 12) + (xtile << 4));
254 
255 				for (INT32 ypixel = 0; ypixel < 16; ypixel++, gfxptr += 4) {
256 
257 					dest[0] = gfxptr[0];
258 					dest[1] = gfxptr[1];
259 					dest[2] = gfxptr[2];
260 					dest[3] = gfxptr[3];
261 
262 					dest += 64;
263 				}
264 			}
265 		}
266 	} else {
267 		INT32 tileno = (code & 0x7ffff) - nGraphicsMin0;
268 		if (tileno < 0 || tileno > nGraphicsSize0) tileno = 0;
269 		if (nDrvZoomPrev == tileno) return;
270 		nDrvZoomPrev = tileno;
271 		UINT8 *gfxptr = pPsikyoshTiles + (tileno << 7);
272 		for (INT32 ytile = 0; ytile < high; ytile++)
273 		{
274 			for (INT32 xtile = 0; xtile < wide; xtile++)
275 			{
276 				UINT8 *dest = DrvZoomBmp + (ytile << 12) + (xtile << 4);
277 
278 				for (INT32 ypixel = 0; ypixel < 16; ypixel++, gfxptr += 8)
279 				{
280 					for (INT32 xpixel = 0; xpixel < 16; xpixel+=2)
281 					{
282 						INT32 c = gfxptr[xpixel>>1];
283 						dest[xpixel    ] = c >> 4;
284 						dest[xpixel + 1] = c & 0x0f;
285 					}
286 
287 					dest += 256;
288 				}
289 			}
290 		}
291 	}
292 }
293 
psikyosh_drawgfxzoom(INT32 gfx,UINT32 code,INT32 color,INT32 flipx,INT32 flipy,INT32 offsx,INT32 offsy,INT32 alpha,INT32 zoomx,INT32 zoomy,INT32 wide,INT32 high,INT32 z)294 static void psikyosh_drawgfxzoom(INT32 gfx, UINT32 code, INT32 color, INT32 flipx, INT32 flipy, INT32 offsx,
295 				 INT32 offsy, INT32 alpha, INT32 zoomx, INT32 zoomy, INT32 wide, INT32 high, INT32 z)
296 {
297 	if (~nBurnLayer & 8) return;
298 	if (!zoomx || !zoomy) return;
299 
300 	if (zoomx == 0x400 && zoomy == 0x400)
301 	{
302 		INT32 xstart, ystart, xend, yend, xinc, yinc, code_offset = 0;
303 
304 		if (flipx)	{ xstart = wide-1; xend = -1;   xinc = -1; }
305 		else		{ xstart = 0;      xend = wide; xinc = +1; }
306 
307 		if (flipy)	{ ystart = high-1; yend = -1;   yinc = -1; }
308 		else		{ ystart = 0;      yend = high; yinc = +1; }
309 
310 		for (INT32 ytile = ystart; ytile != yend; ytile += yinc )
311 		{
312 			for (INT32 xtile = xstart; xtile != xend; xtile += xinc )
313 			{
314 				INT32 sx = offsx + (xtile << 4);
315 				INT32 sy = offsy + (ytile << 4);
316 
317 				draw_blendy_tile(gfx, code + code_offset++, color, sx, sy, flipx, flipy, alpha, z);
318 			}
319 		}
320 	}
321 	else
322 	{
323 		draw_prezoom(gfx, code, high, wide);
324 
325 		{
326 			UINT32 *pal = pBurnDrvPalette + (color << 4);
327 
328 			INT32 sprite_screen_height = ((high << 24) / zoomy + 0x200) >> 10;
329 			INT32 sprite_screen_width  = ((wide << 24) / zoomx + 0x200) >> 10;
330 
331 			if (sprite_screen_width && sprite_screen_height)
332 			{
333 				INT32 sx = offsx;
334 				INT32 sy = offsy;
335 				INT32 ex = sx + sprite_screen_width;
336 				INT32 ey = sy + sprite_screen_height;
337 
338 				INT32 x_index_base;
339 				INT32 y_index;
340 
341 				INT32 dx, dy;
342 
343 				if (flipx) { x_index_base = (sprite_screen_width-1)*zoomx; dx = -zoomx; }
344 				else	   { x_index_base = 0; dx = zoomx; }
345 
346 				if (flipy) { y_index = (sprite_screen_height-1)*zoomy; dy = -zoomy; }
347 				else	   { y_index = 0; dy = zoomy; }
348 
349 				{
350 					if (sx < 0) {
351 						INT32 pixels = 0-sx;
352 						sx += pixels;
353 						x_index_base += pixels*dx;
354 					}
355 					if (sy < 0 ) {
356 						INT32 pixels = 0-sy;
357 						sy += pixels;
358 						y_index += pixels*dy;
359 					}
360 					if (ex > nScreenWidth) {
361 						INT32 pixels = ex-(nScreenWidth-1)-1;
362 						ex -= pixels;
363 					}
364 					if (ey > nScreenHeight)	{
365 						INT32 pixels = ey-(nScreenHeight-1)-1;
366 						ey -= pixels;
367 					}
368 				}
369 
370 				if (ex > sx)
371 				{
372 					if (alpha == 0xff) {
373 						if (z > 0) {
374 							PUTPIXEL_ZOOM_NORMAL_PRIO()
375 						} else {
376 							PUTPIXEL_ZOOM_NORMAL()
377 						}
378 					} else if (alpha >= 0) {
379 						if (z > 0) {
380 							PUTPIXEL_ZOOM_ALPHA_PRIO()
381 						} else {
382 							PUTPIXEL_ZOOM_ALPHA()
383 						}
384 					} else {
385 						if (z > 0) {
386 							PUTPIXEL_ZOOM_ALPHATAB_PRIO()
387 						} else {
388 							PUTPIXEL_ZOOM_ALPHATAB()
389 						}
390 					}
391 				}
392 			}
393 		}
394 	}
395 }
396 
draw_sprites(UINT8 req_pri)397 static void draw_sprites(UINT8 req_pri)
398 {
399 	UINT32   *src = pPsikyoshSpriteBuffer;
400 	UINT16 *list = (UINT16 *)src + 0x3800/2;
401 	UINT16 listlen = 0x800/2;
402 	UINT16 listcntr = 0;
403 	UINT16 *zoom_table = (UINT16 *)pPsikyoshZoomRAM;
404 	UINT8  *alpha_table = (UINT8 *)pPsikyoshVidRegs;
405 
406 	while (listcntr < listlen)
407 	{
408 		UINT32 xpos, ypos, high, wide, flpx, flpy, zoomx, zoomy, tnum, colr, dpth, pri;
409 		INT32 alpha;
410 
411 #ifdef LSB_FIRST
412 		UINT32 listdat = list[listcntr ^ 1];
413 #else
414 		UINT32 listdat = list[listcntr];
415 #endif
416 		UINT32 sprnum = (listdat & 0x03ff) << 2;
417 
418 		pri = (src[sprnum+1] & 0x00003000) >> 12;
419 		pri = (pPsikyoshVidRegs[2] << (pri << 2)) >> 28;
420 
421 		if (pri == req_pri)
422 		{
423 			ypos  = (src[sprnum+0] & 0x03ff0000) >> 16;
424 			xpos  = (src[sprnum+0] & 0x000003ff);
425 			high  =((src[sprnum+1] & 0x0f000000) >> 24) + 1;
426 			wide  =((src[sprnum+1] & 0x00000f00) >>  8) + 1;
427 			flpy  = (src[sprnum+1] & 0x80000000) >> 31;
428 			flpx  = (src[sprnum+1] & 0x00008000) >> 15;
429 			zoomy = (src[sprnum+1] & 0x00ff0000) >> 16;
430 			zoomx = (src[sprnum+1] & 0x000000ff);
431 			tnum  = (src[sprnum+2] & 0x0007ffff);
432 			dpth  = (src[sprnum+2] & 0x00800000) >> 23;
433 			colr  = (src[sprnum+2] & 0xff000000) >> 24;
434 			alpha = (src[sprnum+2] & 0x00700000) >> 20;
435 
436 			if (ypos & 0x200) ypos -= 0x400;
437 			if (xpos & 0x200) xpos -= 0x400;
438 
439 #ifdef LSB_FIRST
440 			alpha = alpha_table[alpha ^ 3];
441 #else
442 			alpha = alpha_table[alpha];
443 #endif
444 
445 			if (alpha & 0x80) {
446 				alpha = -1;
447 			} else {
448 				alpha = alphatable[alpha | 0xc0];
449 			}
450 
451 #ifdef LSB_FIRST
452 			if (zoom_table[zoomy ^ 1] && zoom_table[zoomx ^ 1])
453 #else
454 			if (zoom_table[zoomy] && zoom_table[zoomx])
455 #endif
456 			{
457 #ifdef LSB_FIRST
458 				psikyosh_drawgfxzoom(dpth, tnum, colr, flpx, flpy, xpos, ypos, alpha,
459 					(UINT32)zoom_table[zoomx ^ 1],(UINT32)zoom_table[zoomy ^ 1], wide, high, listcntr);
460 #else
461 				psikyosh_drawgfxzoom(dpth, tnum, colr, flpx, flpy, xpos, ypos, alpha,
462 					(UINT32)zoom_table[zoomx],(UINT32)zoom_table[zoomy], wide, high, listcntr);
463 #endif
464 			}
465 		}
466 
467 		listcntr++;
468 		if (listdat & 0x4000) break;
469 	}
470 }
471 
draw_layer(INT32 layer,INT32 bank,INT32 alpha,INT32 scrollx,INT32 scrolly)472 static void draw_layer(INT32 layer, INT32 bank, INT32 alpha, INT32 scrollx, INT32 scrolly)
473 {
474 	if ((bank < 0x0c) || (bank > 0x1f)) return;
475 
476 	if (alpha & 0x80) {
477 		alpha = -1;
478 	} else {
479 		alpha = alphatable[alpha | 0xc0];
480 	}
481 
482 	INT32 attr = pPsikyoshVidRegs[7] << (layer << 2);
483 	INT32 gfx  = attr & 0x00004000;
484 	INT32 size =(attr & 0x00001000) ? 32 : 16;
485 	INT32 wide = size * 16;
486 
487 	for (INT32 offs = 0; offs < size * 32; offs++) {
488 		INT32 sx = (offs & 0x1f) << 4;
489 		INT32 sy = (offs >> 5) << 4;
490 
491 		sx = (sx + scrollx) & 0x1ff;
492 		sy = (sy + scrolly) & (wide-1);
493 		if (sx >= nScreenWidth)  sx -= 0x200;
494 		if (sy >= nScreenHeight) sy -= wide;
495 		if (sx < -15 || sy < -15) continue;
496 
497 		UINT32 code  = pPsikyoshBgRAM[(bank*0x800)/4 + offs - 0x4000/4];
498 
499 		draw_blendy_tile(gfx, code & 0x7ffff, (code >> 24), sx, sy, 0, 0, alpha, 0);
500 	}
501 }
502 
draw_bglayer(INT32 layer)503 static void draw_bglayer(INT32 layer)
504 {
505 	if (!(nBurnLayer & 1)) return;
506 
507 	INT32 scrollx, scrolly, bank, alpha;
508 	INT32 scrollbank = ((pPsikyoshVidRegs[6] << (layer << 3)) >> 24) & 0x7f;
509 	INT32 offset = (scrollbank == 0x0b) ? 0x200 : 0;
510 
511 	bank    = (pPsikyoshBgRAM[0x17f0/4 + offset + layer] & 0x000000ff);
512 	alpha   = (pPsikyoshBgRAM[0x17f0/4 + offset + layer] & 0x0000bf00) >> 8;
513 	scrollx = (pPsikyoshBgRAM[0x13f0/4 + offset + layer] & 0x000001ff);
514 	scrolly = (pPsikyoshBgRAM[0x13f0/4 + offset + layer] & 0x03ff0000) >> 16;
515 
516 	if (scrollbank == 0x0d) scrollx += 0x08;
517 
518 	draw_layer(layer, bank, alpha, scrollx, scrolly);
519 }
520 
draw_bglayertext(INT32 layer)521 static void draw_bglayertext(INT32 layer)
522 {
523 	if (~nBurnLayer & 2) return;
524 
525 	INT32 scrollx, scrolly, bank, alpha;
526 	INT32 scrollbank = ((pPsikyoshVidRegs[6] << (layer << 3)) >> 24) & 0x7f;
527 
528 	bank    = (pPsikyoshBgRAM[(scrollbank*0x800)/4 + 0x0400/4 - 0x4000/4] & 0x000000ff);
529 	alpha   = (pPsikyoshBgRAM[(scrollbank*0x800)/4 + 0x0400/4 - 0x4000/4] & 0x0000bf00) >> 8;
530 	scrollx = (pPsikyoshBgRAM[(scrollbank*0x800)/4 - 0x4000/4           ] & 0x000001ff);
531 	scrolly = (pPsikyoshBgRAM[(scrollbank*0x800)/4 - 0x4000/4           ] & 0x03ff0000) >> 16;
532 
533 	draw_layer(layer, bank, alpha, scrollx, scrolly);
534 
535 	bank    = (pPsikyoshBgRAM[(scrollbank*0x800)/4 + 0x0400/4 + 0x20/4 - 0x4000/4] & 0x000000ff);
536 	alpha   = (pPsikyoshBgRAM[(scrollbank*0x800)/4 + 0x0400/4 + 0x20/4 - 0x4000/4] & 0x0000bf00) >> 8;
537 	scrollx = (pPsikyoshBgRAM[(scrollbank*0x800)/4 - 0x4000/4 + 0x20/4           ] & 0x000001ff);
538 	scrolly = (pPsikyoshBgRAM[(scrollbank*0x800)/4 - 0x4000/4 + 0x20/4           ] & 0x03ff0000) >> 16;
539 
540 	draw_layer(layer, bank, alpha, scrollx, scrolly);
541 }
542 
draw_bglayerscroll(INT32 layer)543 static void draw_bglayerscroll(INT32 layer)
544 {
545 	if (!(nBurnLayer & 4)) return;
546 
547 	INT32 scrollx, bank, alpha;
548 	INT32 scrollbank = ((pPsikyoshVidRegs[6] << (layer << 3)) >> 24) & 0x7f;
549 
550 	bank    = (pPsikyoshBgRAM[(scrollbank*0x800)/4 + 0x0400/4 - 0x4000/4] & 0x000000ff);
551 	alpha   = (pPsikyoshBgRAM[(scrollbank*0x800)/4 + 0x0400/4 - 0x4000/4] & 0x0000bf00) >> 8;
552 	scrollx = (pPsikyoshBgRAM[(scrollbank*0x800)/4 - 0x4000/4           ] & 0x000001ff);
553 //	scrolly = (pPsikyoshBgRAM[(scrollbank*0x800)/4 - 0x4000/4           ] & 0x03ff0000) >> 16;
554 
555 	draw_layer(layer, bank, alpha, scrollx, 0);
556 }
557 
draw_background(UINT8 req_pri)558 static void draw_background(UINT8 req_pri)
559 {
560 	for (INT32 i = 0; i < 3; i++)
561 	{
562 		if (!((pPsikyoshVidRegs[7] << (i << 2)) & 0x8000))
563 			continue;
564 
565 		INT32 bgtype = ((pPsikyoshVidRegs[6] << (i << 3)) >> 24) & 0x7f;
566 
567 		switch (bgtype)
568 		{
569 			case 0x0a: // Normal
570 				if((pPsikyoshBgRAM[0x17f0/4 + (i*0x04)/4] >> 24) == req_pri)
571 					draw_bglayer(i);
572 				break;
573 
574 			case 0x0b: // Alt / Normal
575 				if((pPsikyoshBgRAM[0x1ff0/4 + (i*0x04)/4] >> 24) == req_pri)
576 					draw_bglayer(i);
577 				break;
578 
579 			case 0x0c: // Using normal for now
580 			case 0x0d: // Using normal for now
581 				if((pPsikyoshBgRAM[(bgtype*0x800)/4 + 0x400/4 - 0x4000/4] >> 24) == req_pri)
582 					draw_bglayertext(i);
583 				break;
584 
585 			case 0x0e:
586 			case 0x10: case 0x11: case 0x12: case 0x13:
587 			case 0x14: case 0x15: case 0x16: case 0x17:
588 			case 0x18: case 0x19: case 0x1a: case 0x1b:
589 			case 0x1c: case 0x1d: case 0x1e: case 0x1f:
590 				if((pPsikyoshBgRAM[(bgtype*0x800)/4 + 0x400/4 - 0x4000/4] >> 24) == req_pri)
591 					draw_bglayerscroll(i);
592 				break;
593 		}
594 	}
595 }
596 
prelineblend()597 static void prelineblend()
598 {
599 	UINT32 *linefill = pPsikyoshBgRAM;
600 	UINT32 *destline = DrvTmpDraw;
601 
602 	for (INT32 y = 0; y < nScreenHeight; y++, destline+=nScreenWidth) {
603 		if (linefill[y] & 0xff) {
604 			for (INT32 x = 0; x < nScreenWidth; x++) {
605 				destline[x] = linefill[y] >> 8;
606 			}
607 		}
608 	}
609 }
610 
postlineblend()611 static void postlineblend()
612 {
613 	UINT32 *lineblend = pPsikyoshBgRAM + 0x0400/4;
614 	UINT32 *destline = DrvTmpDraw;
615 
616 	for (INT32 y = 0; y < nScreenHeight; y++, destline+=nScreenWidth) {
617 		if (lineblend[y] & 0x80) {
618 			for (INT32 x = 0; x < nScreenWidth; x++) {
619 				destline[x] = lineblend[y] >> 8;
620 			}
621 		}
622 		else if (lineblend[y] & 0x7f) {
623 			for (INT32 x = 0; x < nScreenWidth; x++) {
624 				destline[x] = alpha_blend(destline[x], lineblend[y] >> 8, (lineblend[y] & 0x7f) << 1);
625 			}
626 		}
627 	}
628 }
629 
PsikyoshDraw()630 INT32 PsikyoshDraw()
631 {
632 	{
633 		for (INT32 i = 0; i < 0x5000 / 4; i++) {
634 			pBurnDrvPalette[i] = pPsikyoshPalRAM[i] >> 8;
635 		}
636 	}
637 
638 	if (nBurnBpp == 4) {
639 		DrvTmpDraw = (UINT32*)pBurnDraw;
640 	} else {
641 		DrvTmpDraw = DrvTmpDraw_ptr;
642 	}
643 
644 	memset (DrvTmpDraw, 0, nScreenWidth * nScreenHeight * sizeof(UINT32));
645 	memset (DrvPriBmp, 0, nScreenWidth * nScreenHeight * sizeof(INT16));
646 
647 	UINT32 *psikyosh_vidregs = pPsikyoshVidRegs;
648 
649 	prelineblend();
650 
651 	for (UINT32 i = 0; i < 8; i++) {
652 		draw_sprites(i);
653 		draw_background(i);
654 		if ((psikyosh_vidregs[2] & 0x0f) == i) postlineblend();
655 	}
656 
657 	if (nBurnBpp < 4) {
658 		for (INT32 i = 0; i < nScreenWidth * nScreenHeight; i++) {
659 			INT32 d = DrvTmpDraw[i];
660 			PutPix(pBurnDraw + i * nBurnBpp, BurnHighCol(d>>16, d>>8, d, 0));
661 		}
662 	}
663 
664 	return 0;
665 }
666 
fill_alphatable()667 static void fill_alphatable()
668 {
669 	for (INT32 i = 0; i < 0xc0; i++)
670 		alphatable[i] = 0xff;
671 
672 	for (INT32 i = 0; i < 0x40; i++) {
673 		alphatable[i | 0xc0] = ((0x3f - i) * 0xff) / 0x3f;
674 	}
675 }
676 
calculate_transtab()677 static void calculate_transtab()
678 {
679 	DrvTransTab = (UINT8*)BurnMalloc(0x18000);
680 
681 	memset (DrvTransTab, 0xff, 0x18000);
682 
683 	// first calculate all 4bpp tiles
684 	for (INT32 i = 0; i < nGraphicsSize; i+= 0x80) {
685 		for (INT32 j = 0; j < 0x80; j++) {
686 			if (pPsikyoshTiles[i + j]) {
687 				DrvTransTab[(i>>10) + 0x00000] &= ~(1 << ((i >> 7) & 7));
688 				break;
689 			}
690 		}
691 	}
692 
693 	// next, calculate all 8bpp tiles
694 	for (INT32 i = 0; i < nGraphicsSize; i+= 0x100) {
695 		for (INT32 j = 0; j < 0x100; j++) {
696 			if (pPsikyoshTiles[i + j]) {
697 				DrvTransTab[(i>>11) + 0x10000] &= ~(1 << ((i >> 8) & 7));
698 				break;
699 			}
700 		}
701 	}
702 }
703 
PsikyoshVideoInit(INT32 gfx_max,INT32 gfx_min)704 void PsikyoshVideoInit(INT32 gfx_max, INT32 gfx_min)
705 {
706 	DrvZoomBmp	= (UINT8 *)BurnMalloc(16 * 16 * 16 * 16);
707 	DrvPriBmp	= (UINT16*)BurnMalloc(320 * 240 * sizeof(INT16));
708 	DrvTmpDraw_ptr	= (UINT32  *)BurnMalloc(320 * 240 * sizeof(UINT32));
709 
710 	if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) {
711 		BurnDrvGetVisibleSize(&nScreenHeight, &nScreenWidth);
712 	} else {
713 		BurnDrvGetVisibleSize(&nScreenWidth, &nScreenHeight);
714 	}
715 
716 	nGraphicsSize  = gfx_max - gfx_min;
717 	nGraphicsMin0  = (gfx_min / 128);
718 	nGraphicsMin1  = (gfx_min / 256);
719 	nGraphicsSize0 = (nGraphicsSize / 128) - 1;
720 	nGraphicsSize1 = (nGraphicsSize / 256) - 1;
721 
722 	calculate_transtab();
723 	fill_alphatable();
724 }
725 
PsikyoshVideoExit()726 void PsikyoshVideoExit()
727 {
728 	BurnFree (DrvZoomBmp);
729 	BurnFree (DrvPriBmp);
730 	BurnFree (DrvTmpDraw_ptr);
731 	DrvTmpDraw = NULL;
732 	BurnFree (DrvTransTab);
733 
734 	nDrvZoomPrev		= -1;
735 	pPsikyoshTiles		= NULL;
736 	pPsikyoshSpriteBuffer	= NULL;
737 	pPsikyoshBgRAM		= NULL;
738 	pPsikyoshVidRegs	= NULL;
739 	pPsikyoshPalRAM		= NULL;
740 	pPsikyoshZoomRAM	= NULL;
741 	pBurnDrvPalette		= NULL;
742 
743 	nScreenWidth = nScreenHeight = 0;
744 }
745