1 // FBAlpha Toggable Shifter and Gear Display
2 //
3 // For how-to, search BurnShift in konami/d_chqflag.cpp :)
4 //
5 
6 #include "burnint.h"
7 #include "burn_shift.h"
8 
9 INT32 BurnShiftEnabled = 1; // enable/disable rendering
10 INT32 bBurnShiftStatus; // current status of shifter
11 
12 static INT32 prev_shift;
13 
14 static INT32 shift_alpha_level;
15 static INT32 shift_alpha_level2;
16 static INT32 shift_alpha_level_grey;
17 static INT32 shift_alpha_level2_grey;
18 static INT32 shift_color;
19 static INT32 shift_size;
20 static INT32 shift_position0;
21 static INT32 shift_position;
22 static INT32 shift_xpos;
23 static INT32 shift_ypos;
24 static INT32 shift_xadv;
25 static INT32 shift_yadv;
26 
27 static INT32 nScreenWidth, nScreenHeight;
28 static INT32 screen_flipped;
29 static INT32 screen_vertical;
30 static INT32 flipscreen = -1;
31 static INT32 colortab[10] = { 0, 0, 0x42f4f4, 0xffffff, 0x0000ff, 0x9200f4, 0xf4f400, 0xf45900, 0x00d8f4, 0 };
32 static INT32 lhtimer = 0; // color-cycle effect counter
33 
34 #define a 0,
35 #define b 1,
36 #define c 2,
37 #define d 3,
38 UINT8 BurnGearRender[8*8];
39 #if 0
40 // small font
41 UINT8 BurnGearL[8*8] = {
42 	  a a a a a a a a
43 	  a a a a a a a a
44 	  a a a b c a a a
45 	  a a a b c a a a
46 	  a a a b c c c a
47 	  a a a b b b c a
48 	  a a a c c c c a
49 	  a a a a a a a a };
50 
51 UINT8 BurnGearH[8*8] = {
52 	  a a a a a a a a
53 	  a a a a a a a a
54 	  a a a b c b c a
55 	  a a a b b b c a
56 	  a a a b c b c a
57 	  a a a c c c c a
58 	  a a a a a a a a
59 	  a a a a a a a a };
60 #endif
61 #if 0
62 // blocky font (Gab75)
63 UINT8 BurnGearL[8*8] = {
64 	  b b d a a d a a
65 	  b b d a a d a a
66 	  d d d d d d d d
67 	  b b d a a d a a
68 	  b b d a a d a a
69 	  d d d d d d d d
70 	  b b d b b d b b
71 	  b b d b b d b b };
72 
73 UINT8 BurnGearH[8*8] = {
74 	  b b d a a d b b
75 	  b b d a a d b b
76 	  d d d d d d d d
77 	  b b d b b d b b
78 	  b b d b b d b b
79 	  d d d d d d d d
80 	  b b d a a d b b
81 	  b b d a a d b b };
82 #endif
83 #if 1
84 // Shadow font (Gab75)
85 UINT8 BurnGearL[8*8] = {
86 	  a a a a a a a a
87 	  a a b b a a a a
88 	  a a b b c a a a
89 	  a a b b c a a a
90 	  a a b b c a a a
91 	  a a b b b b a a
92 	  a a a c c c c a
93 	  a a a a a a a a };
94 
95 UINT8 BurnGearH[8*8] = {
96 	  a a a a a a a a
97 	  a b b a a b b a
98 	  a b b c a b b c
99 	  a b b b b b b c
100 	  a b b c c b b c
101 	  a b b c a b b c
102 	  a a c c a a c c
103 	  a a a a a a a a };
104 #endif
105 #undef b
106 #undef a
107 #undef c
108 #undef d
109 
alpha_blend32(UINT32 d,UINT32 col)110 static UINT32 alpha_blend32(UINT32 d, UINT32 col)
111 {
112 	if (col == 3) col = 3 /*0x1f1f1f*/; else
113 	if (col == 2) col = 0; else
114 		if (lhtimer == 0) col = colortab[1]; else
115 		col = colortab[lhtimer/2];
116 
117 
118 	if (col == 3) { // handle grey with a lighter transparency
119 		col = 0x1f1f1f;
120 		return (((((col & 0xff00ff) * shift_alpha_level_grey) + ((d & 0xff00ff) * shift_alpha_level2_grey)) & 0xff00ff00) |
121 				((((col & 0x00ff00) * shift_alpha_level_grey) + ((d & 0x00ff00) * shift_alpha_level2_grey)) & 0x00ff0000)) >> 8;
122 	}
123 
124 	return (((((col & 0xff00ff) * shift_alpha_level) + ((d & 0xff00ff) * shift_alpha_level2)) & 0xff00ff00) |
125 		((((col & 0x00ff00) * shift_alpha_level) + ((d & 0x00ff00) * shift_alpha_level2)) & 0x00ff0000)) >> 8;
126 }
127 
set_shift_draw_position()128 static void set_shift_draw_position()
129 {
130 	shift_position = shift_position0;
131 
132 	if (screen_flipped ^ flipscreen) {
133 		switch (shift_position & 3) {
134 			case SHIFT_POSITION_TOP_LEFT: shift_position = SHIFT_POSITION_BOTTOM_RIGHT; break;
135 			case SHIFT_POSITION_TOP_RIGHT: shift_position = SHIFT_POSITION_BOTTOM_LEFT; break;
136 			case SHIFT_POSITION_BOTTOM_LEFT: shift_position = SHIFT_POSITION_TOP_RIGHT; break;
137 			case SHIFT_POSITION_BOTTOM_RIGHT: shift_position = SHIFT_POSITION_TOP_LEFT; break;
138 		}
139 	}
140 
141 	if (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) {
142 		BurnDrvGetVisibleSize(&nScreenHeight, &nScreenWidth);
143 
144 		screen_vertical = 1;
145 
146 		shift_xadv = 0;
147 		shift_yadv = shift_size + 1;
148 
149 		switch (shift_position & 3)
150 		{
151 			case SHIFT_POSITION_TOP_LEFT:
152 				shift_xpos = (nScreenWidth - 1) - shift_size;
153 				shift_ypos = 1;
154 			break;
155 
156 			case SHIFT_POSITION_BOTTOM_RIGHT:
157 				shift_xpos = 1;
158 				shift_ypos = (nScreenHeight - 1) - (shift_yadv * 1);
159 			break;
160 
161 			case SHIFT_POSITION_BOTTOM_LEFT:
162 				shift_xpos = 1;
163 				shift_ypos = 1;
164 			break;
165 
166 			case SHIFT_POSITION_TOP_RIGHT:
167 			default:
168 				shift_xpos = (nScreenWidth  - 1) - shift_size;
169 				shift_ypos = (nScreenHeight - 1) - (shift_yadv * 1);
170 			break;
171 		}
172 	} else {
173 		BurnDrvGetVisibleSize(&nScreenWidth, &nScreenHeight);
174 
175 		screen_vertical = 0;
176 
177 		shift_xadv = shift_size + 1;
178 		shift_yadv = 0;
179 
180 		switch (shift_position & 3)
181 		{
182 			case SHIFT_POSITION_BOTTOM_LEFT:
183 				shift_xpos = 1;
184 				shift_ypos = (nScreenHeight - 1) - shift_size;
185 //				shift_ypos;
186 			break;
187 
188 			case SHIFT_POSITION_TOP_RIGHT:
189 				shift_xpos = (nScreenWidth - 1) - (shift_xadv * 1);
190 				shift_ypos = 1;
191 			break;
192 
193 			case SHIFT_POSITION_TOP_LEFT:
194 				shift_xpos = 1;
195 				shift_ypos = 1;
196 			break;
197 
198 			case SHIFT_POSITION_BOTTOM_RIGHT:
199 			default:
200 				shift_xpos = (nScreenWidth  - 1) - (shift_xadv * 1);
201 				shift_ypos = (nScreenHeight - 1) - shift_size;
202 			break;
203 		}
204 	}
205 }
206 
BurnShiftSetFlipscreen(INT32 flip)207 void BurnShiftSetFlipscreen(INT32 flip)
208 {
209 #if defined FBA_DEBUG
210 	if (!Debug_BurnShiftInitted) bprintf(PRINT_ERROR, _T("BurnShiftSetFlipscreen called without init\n"));
211 #endif
212 
213 	flip = flip ? 1 : 0;
214 
215 	if (flipscreen != flip) {
216 		flipscreen = flip;
217 		set_shift_draw_position();
218 	}
219 }
220 
BurnShiftReset()221 void BurnShiftReset()
222 {
223 #if defined FBA_DEBUG
224 	if (!Debug_BurnShiftInitted) bprintf(PRINT_ERROR, _T("BurnShiftReset called without init\n"));
225 #endif
226 
227 	prev_shift = 0;
228 
229 	BurnShiftSetStatus(0);
230 
231 	BurnShiftSetFlipscreen(0);
232 
233 	lhtimer = 0;
234 }
235 
BurnShiftInit(INT32 position,INT32 color,INT32 transparency)236 void BurnShiftInit(INT32 position, INT32 color, INT32 transparency)
237 {
238 	Debug_BurnShiftInitted = 1;
239 
240 	colortab[1] = shift_color = color;
241 
242 	shift_size = 8;
243 	shift_position0 = position;
244 
245 	shift_alpha_level = (255 * transparency) / 100;
246 	shift_alpha_level2 = 256 - shift_alpha_level;
247 
248 	shift_alpha_level_grey = (255 * 20) / 100;
249 	shift_alpha_level2_grey = 256 - shift_alpha_level_grey;
250 
251 	screen_flipped = (BurnDrvGetFlags() & BDF_ORIENTATION_FLIPPED) ? 1 : 0;
252 	screen_vertical = (BurnDrvGetFlags() & BDF_ORIENTATION_VERTICAL) ? 1 : 0;
253 
254 	BurnShiftReset();
255 }
256 
BurnShiftInitDefault()257 void BurnShiftInitDefault()
258 {
259 	BurnShiftInit(SHIFT_POSITION_BOTTOM_RIGHT, SHIFT_COLOR_GREEN, 80);
260 }
261 
BurnShiftInputCheckToggle(UINT8 shiftinput)262 INT32 BurnShiftInputCheckToggle(UINT8 shiftinput)
263 {
264 	if (prev_shift != shiftinput && shiftinput) {
265 		bBurnShiftStatus = !bBurnShiftStatus;
266 		BurnShiftSetStatus(bBurnShiftStatus);
267 	}
268 
269 	prev_shift = shiftinput;
270 
271 	return bBurnShiftStatus;
272 }
273 
BurnShiftSetStatus(UINT32 status)274 void BurnShiftSetStatus(UINT32 status)
275 {
276 #if defined FBA_DEBUG
277 	if (!Debug_BurnShiftInitted) bprintf(PRINT_ERROR, _T("BurnShiftSetStatus called without init\n"));
278 #endif
279 
280 	bBurnShiftStatus = status ? 1 : 0;
281 
282 	UINT8 *source = (status) ? &BurnGearH[0] : &BurnGearL[0];
283 
284 	for (UINT8 y = 0; y < 8; y++)
285 		for (UINT8 x = 0; x < 8; x++)
286 		{
287 			if ((screen_flipped ^ flipscreen)) {
288 				if (screen_vertical)
289 				{ // flipped + vertical
290 					BurnGearRender[(y * 8) + x] = source[(x * 8) + (7-y)];
291 				}
292 				else
293 				{ // flipped
294 					BurnGearRender[(y * 8) + x] = source[(y * 8) + (7-x)];
295 				}
296 			} else if (screen_vertical)
297 			{ // vertical
298 				BurnGearRender[(y * 8) + x] = source[(x * 8) + y];
299 			} else
300 			{ // normal
301 				BurnGearRender[(y * 8) + x] = source[(y * 8) + x];
302 			}
303 		}
304     lhtimer = (nBurnFPS < 4500) ? 10 : 19; // for color effects
305 }
306 
BurnShiftExit()307 void BurnShiftExit()
308 {
309 #if defined FBA_DEBUG
310 	if (!Debug_BurnShiftInitted) bprintf(PRINT_ERROR, _T("BurnShiftExit called without init\n"));
311 #endif
312 
313 	shift_alpha_level = 0;
314 	shift_alpha_level2 = 0;
315 	shift_alpha_level_grey = 0;
316 	shift_alpha_level2_grey = 0;
317 	shift_color = 0;
318 	shift_size = 0;
319 	shift_position = 0;
320 	shift_position0 = 0;
321 
322 	shift_xpos = 0;
323 	shift_ypos = 0;
324 
325 	screen_flipped = 0;
326 	nScreenWidth = 0;
327 	nScreenHeight = 0;
328 	lhtimer = 0;
329 
330 	flipscreen = -1;
331 
332 	Debug_BurnShiftInitted = 0;
333 }
334 
BurnShiftRender()335 void BurnShiftRender()
336 {
337 #if defined FBA_DEBUG
338 	if (!Debug_BurnShiftInitted) bprintf(PRINT_ERROR, _T("BurnShiftRender called without init\n"));
339 #endif
340 
341 	if (!BurnShiftEnabled) return;
342 
343 	INT32 xpos = shift_xpos;
344 	INT32 ypos = shift_ypos;
345 	INT32 color = BurnHighCol((shift_color >> 16) & 0xff, (shift_color >> 8) & 0xff, (shift_color >> 0) & 0xff, 0);
346 
347 	{
348 		if (xpos < 0 || xpos > (nScreenWidth - shift_size)) return;
349 
350 		{
351 			for (INT32 y = 0; y < 8; y++)
352 			{
353 				UINT8 *ptr = pBurnDraw + (((ypos + y) * nScreenWidth) + xpos) * nBurnBpp;
354 
355 				for (INT32 x = 0; x < 8; x++) {
356 					if (BurnGearRender[(y*8)+x])
357 					{
358 						if (nBurnBpp >= 4)
359 						{
360 							*((UINT32*)ptr) = alpha_blend32(*((UINT32*)ptr), BurnGearRender[(y*8)+x]);
361 						}
362 						else if (nBurnBpp == 3)
363 						{
364 							UINT32 t = alpha_blend32((ptr[2] << 16) | (ptr[1] << 8) | ptr[0], BurnGearRender[(y*8)+x]);
365 
366 							ptr[2] = t >> 16;
367 							ptr[1] = t >> 8;
368 							ptr[0] = t >> 0;
369 						}
370 						else if (nBurnBpp == 2 && BurnGearRender[(y*8)+x] == 1) // alpha blend not supported for 16-bit
371 						{
372 							*((UINT16*)ptr) =  color;
373 						}
374 					}
375 					ptr += nBurnBpp;
376 				}
377 			}
378 		}
379 
380 		xpos += shift_xadv;
381 		ypos += shift_yadv;
382 	}
383 	if (lhtimer > 0) lhtimer--;
384 }
385 
BurnShiftRenderDoubleSize()386 void BurnShiftRenderDoubleSize()
387 {
388 #if defined FBA_DEBUG
389 	if (!Debug_BurnShiftInitted) bprintf(PRINT_ERROR, _T("BurnShiftRender called without init\n"));
390 #endif
391 
392 	if (!BurnShiftEnabled) return;
393 
394     if (shift_size == 8) { // need to re-init some things for 16x16 mode
395         shift_size = 16;
396         set_shift_draw_position();
397     }
398 
399 	INT32 xpos = shift_xpos;
400 	INT32 ypos = shift_ypos;
401 	INT32 color = BurnHighCol((shift_color >> 16) & 0xff, (shift_color >> 8) & 0xff, (shift_color >> 0) & 0xff, 0);
402 
403 	{
404 		if (xpos < 0 || xpos > (nScreenWidth - shift_size)) return;
405 
406 		{
407 			for (INT32 y = 0; y < 16; y++)
408 			{
409 				UINT8 *ptr = pBurnDraw + (((ypos + y) * nScreenWidth) + xpos) * nBurnBpp;
410 
411 				for (INT32 x = 0; x < 16; x++) {
412 					if (BurnGearRender[((y/2)*8)+(x/2)])
413 					{
414 						if (nBurnBpp >= 4)
415 						{
416 							*((UINT32*)ptr) = alpha_blend32(*((UINT32*)ptr), BurnGearRender[((y/2)*8)+(x/2)]);
417 						}
418 						else if (nBurnBpp == 3)
419 						{
420 							UINT32 t = alpha_blend32((ptr[2] << 16) | (ptr[1] << 8) | ptr[0], BurnGearRender[((y/2)*8)+(x/2)]);
421 
422 							ptr[2] = t >> 16;
423 							ptr[1] = t >> 8;
424 							ptr[0] = t >> 0;
425 						}
426 						else if (nBurnBpp == 2 && BurnGearRender[((y/2)*8)+(x/2)] == 1) // alpha blend not supported for 16-bit
427 						{
428 							*((UINT16*)ptr) =  color;
429 						}
430 					}
431 					ptr += nBurnBpp;
432 				}
433 			}
434 		}
435 
436 		xpos += shift_xadv;
437 		ypos += shift_yadv;
438 	}
439 	if (lhtimer > 0) lhtimer--;
440 }
441 
BurnShiftScan(INT32 nAction)442 INT32 BurnShiftScan(INT32 nAction)
443 {
444 #if defined FBA_DEBUG
445 	if (!Debug_BurnShiftInitted) bprintf(PRINT_ERROR, _T("BurnShiftScan called without init\n"));
446 #endif
447 
448 	if (nAction & ACB_DRIVER_DATA) {
449 		SCAN_VAR(bBurnShiftStatus);
450 	}
451 
452 	if (nAction & ACB_WRITE) {
453 		BurnShiftSetStatus(bBurnShiftStatus);
454 		lhtimer = 0;
455 	}
456 
457 	return 0;
458 }
459