1 #include "toaplan.h"
2 
3 INT32 ToaOpaquePriority;
4 
5 static UINT8* pTile;
6 static UINT32* pTileData;
7 static UINT32* pTilePalette;
8 
9 INT32 Rallybik = 0;
10 INT32 Hellfire = 0;
11 
12 typedef void (*RenderTileFunction)();
13 static RenderTileFunction* RenderTile;
14 
15 static INT32 nTileXPos, nTileYPos;
16 
17 // Include the tile rendering functions
18 #include "toa_gp9001_func.h"
19 
20 static INT32 nLastBPP = 0;
21 
22 struct ToaTile {
23 	UINT32 nTileAttrib;
24 	INT16 nTileXPos;
25 	INT16 nTileYPos;
26 };
27 
28 extern UINT32* ToaPalette2;
29 
30 // ----------------------------------------------------------------------------
31 // Rally Bike custom sprite function
32 
rallybik_draw_sprites(INT32 priority)33 static void rallybik_draw_sprites(INT32 priority)
34 {
35 	UINT16 *sprite = (UINT16*)FCU2RAM;
36 
37 	for (INT32 offs = 0; offs < (0x1000/2); offs += 4)
38 	{
39 		INT32 attrib = sprite[offs + 1];
40 
41 		if ((attrib & 0x0c00) == priority)
42 		{
43 			INT32 sy = (sprite[offs + 3] >> 7) & 0x1ff;
44 
45 			if (sy != 0x0100)
46 			{
47 				INT32 code	= sprite[offs] & 0x7ff;
48 				INT32 color	= attrib & 0x3f;
49 				INT32 sx		= (sprite[offs + 2] >> 7) & 0x1ff;
50 				INT32 flipx	= attrib & 0x100;
51 				INT32 flipy	= attrib & 0x200;
52 				if (flipx) sx -= 15;
53 
54 				sx -= 31;
55 				sy -= 16;
56 
57 				if (sy < -15 || sx < -15 || sy >= 240 || sx >= 320) continue;
58 
59 				{
60 					INT32 flip = 0;
61 					if (flipx) flip |= 0x0f;
62 					if (flipy) flip |= 0xf0;
63 					UINT8 *gfx = FCU2ROM + (code * 0x100);
64 
65 					pTilePalette = &ToaPalette2[color << 4];
66 
67 					for (INT32 y = 0; y < 16; y++, sy++) {
68 						if (sy < 0 || sy >= 240) continue;
69 
70 						for (INT32 x = 0; x < 16; x++, sx++) {
71 							if (sx < 0 || sx >= 320) continue;
72 
73 							INT32 pxl = gfx[((y * 16) + x) ^ flip];
74 
75 							if (pxl) {
76 								PutPix(pBurnDraw + ((sy * 320) + sx) * nBurnBpp, pTilePalette[pxl]);
77 							}
78 						}
79 						sx -= 16;
80 					}
81 				}
82 			}
83 		}
84 	}
85 }
86 
87 
88 // ----------------------------------------------------------------------------
89 // FCU-2 functions
90 
91 UINT8* FCU2ROM;
92 UINT32 nFCU2ROMSize;
93 static UINT8* FCU2TileAttrib;
94 
95 static UINT32 nFCU2MaxSprite;
96 
97 UINT8* FCU2RAM;
98 UINT8* FCU2RAMSize;
99 UINT32 FCU2Pointer;
100 
101 static UINT8* pFCU2SpriteBuffer;
102 
103 static UINT16** pFCU2SpriteQueue[16];
104 static UINT16** pFCU2SpriteQueueData = NULL;
105 
106 INT32 nFCU2SpriteXOffset = 0, nFCU2SpriteYOffset = 0;
107 
FCU2PrepareSprites()108 static void FCU2PrepareSprites()
109 {
110 	UINT16* pSpriteInfo;
111 	INT32 nSprite;
112 
113 	for (INT32 nPriority = 0; nPriority < 16; nPriority++) {
114 		pFCU2SpriteQueue[nPriority] = &pFCU2SpriteQueueData[(nPriority << 8) + nPriority];
115 	}
116 
117 	for (nSprite = 0, pSpriteInfo = (UINT16*)pFCU2SpriteBuffer; nSprite < 0x0100; nSprite++, pSpriteInfo += 4) {
118 		if (!(pSpriteInfo[0] & 0x8000)) {				// Sprite is enabled
119 			*pFCU2SpriteQueue[pSpriteInfo[1] >> 12]++ = pSpriteInfo;
120 		}
121 	}
122 }
123 
FCU2RenderSpriteQueue(INT32 nPriority)124 static void FCU2RenderSpriteQueue(INT32 nPriority)
125 {
126 	UINT16* pSpriteInfo;
127 	UINT8* pSpriteData;
128 	INT32 nSpriteXPos, nSpriteYPos;
129 	INT32 nSpriteXSize, nSpriteYSize;
130 	UINT32 nSpriteNumber;
131 	INT32 x, y, s;
132 
133 	*pFCU2SpriteQueue[nPriority] = NULL;
134 	pFCU2SpriteQueue[nPriority] = &pFCU2SpriteQueueData[(nPriority << 8) + nPriority];
135 
136 	while ((pSpriteInfo = *pFCU2SpriteQueue[nPriority]++) != NULL) {
137 
138 		pTilePalette = &ToaPalette2[(pSpriteInfo[1] & 0x3F) << 4];
139 		nSpriteNumber = pSpriteInfo[0] & nFCU2MaxSprite;
140 
141 		pSpriteData = FCU2ROM + (nSpriteNumber << 5);
142 
143 		s = (pSpriteInfo[1] & 0x0FC0) >> 6;
144 
145 		nSpriteXSize = ((((UINT16*)FCU2RAMSize)[s] >> 0) & 0x0F);
146 		nSpriteYSize = ((((UINT16*)FCU2RAMSize)[s] >> 4) & 0x0F);
147 
148 		nSpriteXPos = (pSpriteInfo[2] >> 7) + nFCU2SpriteXOffset;
149 		nSpriteXPos &= 0x01FF;
150 		nSpriteYPos = (pSpriteInfo[3] >> 7) + nFCU2SpriteYOffset;
151 		nSpriteYPos &= 0x01FF;
152 
153 		if (Hellfire) nSpriteYPos -= 16;
154 
155 		if (nSpriteXPos > 384) {
156 			nSpriteXPos -= 0x0200;
157 		}
158 		if (nSpriteYPos > 384) {
159 			nSpriteYPos -= 0x0200;
160 		}
161 
162 //		if (nSpriteNumber) {
163 //			printf("Sprite\t0x%04X\n", nSpriteNumber);
164 //			printf("xp: %4i, yp: %4i\n", nSpriteXPos, nSpriteYPos);
165 //			printf("xs: %4i, ys: %4i\n", nSpriteXSize, nSpriteYSize);
166 //		}
167 
168 		for (y = 0, nTileYPos = nSpriteYPos; y < nSpriteYSize; y++, nTileYPos += 8) {
169 			for (x = 0, nTileXPos = nSpriteXPos; x < nSpriteXSize; x++, nTileXPos += 8, nSpriteNumber++, pSpriteData += 32) {
170 				if (nSpriteNumber > nFCU2MaxSprite) {
171 					break;
172 				}
173 				if (FCU2TileAttrib[nSpriteNumber]) {
174 					// Skip tile if it's completely off the screen
175 					if (!(nTileXPos <= -8 || nTileXPos >= 320 || nTileYPos <= -8 || nTileYPos >= 240)) {
176 						pTileData = (UINT32*)pSpriteData;
177 						pTile = pBurnBitmap + (nTileXPos * nBurnColumn) + (nTileYPos * nBurnRow);
178 						if (nTileXPos < 0 || nTileXPos > 312 || nTileYPos < 0 || nTileYPos > 232) {
179 							RenderTile[1]();
180 						} else {
181 							RenderTile[0]();
182 						}
183 					}
184 				}
185 			}
186 		}
187 	}
188 }
189 
190 // ----------------------------------------------------------------------------
191 // BCU-2 functions
192 
193 UINT8* BCU2ROM;
194 UINT32 nBCU2ROMSize;
195 static UINT8* BCU2TileAttrib;
196 
197 static UINT32 nBCU2MaxTile;
198 
199 UINT8* BCU2RAM;
200 
201 UINT16 BCU2Reg[8];
202 
203 UINT32 BCU2Pointer;
204 
205 static ToaTile* pBCU2TileQueue[16];
206 static ToaTile* pBCU2TileQueueData = NULL;
207 
208 INT32 nBCU2TileXOffset = 0, nBCU2TileYOffset = 0;
209 
BCU2QueueLayer(UINT16 * pTilemap,INT32 nXPos,INT32 nYPos)210 static void BCU2QueueLayer(UINT16* pTilemap, INT32 nXPos, INT32 nYPos)
211 {
212 	if (Hellfire) nYPos += 16;
213 
214 	INT32 x, y;
215 	INT32 nTileRow, nTileColumn;
216 	UINT32 nTileNumber, nTileAttrib;
217 
218 	for (y = 0; y < 31; y++) {
219 
220 		nTileRow = (((nYPos >> 3) + y) << 7) & 0x1F80;
221 
222 		for (x = 0; x < 41; x++) {
223 			nTileColumn = (((nXPos >> 3) + x) << 1) & 0x7E;
224 			nTileNumber = pTilemap[nTileRow + nTileColumn + 1];
225 			nTileAttrib = pTilemap[nTileRow + nTileColumn];
226 
227 			// Rallybik uses hidden tiles to do the background fades on the titlescreen.
228 			if ((!(nTileNumber & 0x8000) && (nTileAttrib & 0xF000)) || Rallybik) {
229 				pBCU2TileQueue[nTileAttrib >> 12]->nTileAttrib = (nTileAttrib << 16) | nTileNumber;
230 				pBCU2TileQueue[nTileAttrib >> 12]->nTileXPos = (x << 3) - (nXPos & 7);
231 				pBCU2TileQueue[nTileAttrib >> 12]->nTileYPos = (y << 3) - (nYPos & 7);
232 				pBCU2TileQueue[nTileAttrib >> 12]++;
233 			}
234 		}
235 	}
236 }
237 
BCU2PrepareTiles()238 static void BCU2PrepareTiles()
239 {
240 	for (INT32 nPriority = 0; nPriority < 16; nPriority++) {
241 		pBCU2TileQueue[nPriority] = &pBCU2TileQueueData[nPriority * 1280 * 4];
242 	}
243 
244 	BCU2QueueLayer((UINT16*)(BCU2RAM + 0xC000), (BCU2Reg[6] >> 7) - nBCU2TileXOffset + nLayer3XOffset, (BCU2Reg[7] >> 7) - nBCU2TileYOffset + nLayer3YOffset);
245 	BCU2QueueLayer((UINT16*)(BCU2RAM + 0x8000), (BCU2Reg[4] >> 7) - nBCU2TileXOffset + nLayer2XOffset, (BCU2Reg[5] >> 7) - nBCU2TileYOffset + nLayer2YOffset);
246 	BCU2QueueLayer((UINT16*)(BCU2RAM + 0x4000), (BCU2Reg[2] >> 7) - nBCU2TileXOffset + nLayer1XOffset, (BCU2Reg[3] >> 7) - nBCU2TileYOffset + nLayer1YOffset);
247 	BCU2QueueLayer((UINT16*)(BCU2RAM + 0x0000), (BCU2Reg[0] >> 7) - nBCU2TileXOffset + nLayer0XOffset, (BCU2Reg[1] >> 7) - nBCU2TileYOffset + nLayer0YOffset);
248 }
249 
BCU2RenderTileQueue(INT32 nPriority)250 static void BCU2RenderTileQueue(INT32 nPriority)
251 {
252 	UINT32 nTileNumber, nTileAttrib;
253 	UINT8* pTileStart;
254 	UINT8 nOpacity;
255 
256 	pBCU2TileQueue[nPriority]->nTileAttrib = 0;
257 	pBCU2TileQueue[nPriority] = &pBCU2TileQueueData[nPriority * 1280 * 4];
258 
259 	while ((nTileAttrib = pBCU2TileQueue[nPriority]->nTileAttrib) != 0) {
260 		nTileXPos = pBCU2TileQueue[nPriority]->nTileXPos;
261 		nTileYPos = pBCU2TileQueue[nPriority]->nTileYPos;
262 		pBCU2TileQueue[nPriority]++;
263 
264 		nTileNumber = nTileAttrib & nBCU2MaxTile;
265 
266 		pTileStart = BCU2ROM + (nTileNumber << 5);
267 		pTilePalette = &ToaPalette[(nTileAttrib >> 12) & 0x03F0];
268 
269 		pTile = pBurnBitmap + (nTileXPos * nBurnColumn) + (nTileYPos * nBurnRow);
270 
271 		if ((nOpacity = BCU2TileAttrib[nTileNumber]) != 0 || nPriority < ToaOpaquePriority) {
272 			if (nPriority < ToaOpaquePriority) nOpacity = 9;
273 
274 			pTileData = (UINT32*)pTileStart;
275 			if (nTileXPos >= 0 && nTileXPos < 312 && nTileYPos >= 0 && nTileYPos < 232) {
276 				RenderTile[nOpacity - 1]();
277 			} else {
278 				if (nTileXPos > -8 && nTileXPos < 320 && nTileYPos > -8 && nTileYPos < 240) {
279 					RenderTile[nOpacity]();
280 				}
281 			}
282 		}
283 	}
284 }
285 
ToaBufferFCU2Sprites()286 void ToaBufferFCU2Sprites()
287 {
288 	memcpy(pFCU2SpriteBuffer, FCU2RAM, 0x0800);
289 }
290 
ToaRenderBCU2()291 INT32 ToaRenderBCU2()
292 {
293 	if (nLastBPP != nBurnBpp ) {
294 		nLastBPP = nBurnBpp;
295 
296 #ifdef DRIVER_ROTATION
297 		if (bRotatedScreen) {
298 			RenderTile = RenderTile_ROT270[nBurnBpp - 2];
299 		} else {
300 			RenderTile = RenderTile_ROT0[nBurnBpp - 2];
301 		}
302 #else
303 		RenderTile = RenderTile_ROT0[nBurnBpp - 2];
304 #endif
305 	}
306 
307 	BCU2PrepareTiles();
308 	if (!Rallybik) {
309 		FCU2PrepareSprites();
310 	}
311 
312 	for (INT32 nPriority = 0; nPriority < 16; nPriority++) {
313 		if (Rallybik) {
314 			rallybik_draw_sprites(nPriority << 8);
315 		} else {
316 			FCU2RenderSpriteQueue(nPriority);
317 		}
318 		BCU2RenderTileQueue(nPriority);
319 	}
320 
321 	return 0;
322 }
323 
ToaInitBCU2()324 INT32 ToaInitBCU2()
325 {
326 	INT32 nSize;
327 
328 	nLastBPP = 0;
329 
330 	nBCU2MaxTile = (nBCU2ROMSize - 1) >> 5;
331 
332 	nSize = 1280 * 4 * 0x10 * sizeof(ToaTile);
333 	pBCU2TileQueueData = (ToaTile*)BurnMalloc(nSize);
334 	memset(pBCU2TileQueueData, 0, nSize);
335 
336 	BCU2TileAttrib = (UINT8*)BurnMalloc(32768);
337 	memset(BCU2TileAttrib, 0, 32768);
338 	for (UINT32 j = 0; j < (nBCU2ROMSize >> 5); j++) {
339 		bool bTransparent = true, bSolid = true;
340 		INT32 nTwoPixels;
341 		for (UINT32 k = (j << 5); k < ((j << 5) + 32); k++) {
342 			if ((nTwoPixels = BCU2ROM[k]) != 0) {
343 				bTransparent = false;
344 			}
345 			if ((nTwoPixels & 0xF0) == 0 || (nTwoPixels & 0x0F) == 0) {
346 				bSolid = false;
347 			}
348 		}
349 		if (bTransparent) {
350 			BCU2TileAttrib[j] = 0;
351 		} else {
352 			if (bSolid) {
353 				BCU2TileAttrib[j] = 9;
354 			} else {
355 				BCU2TileAttrib[j] = 1;
356 			}
357 		}
358 	}
359 
360 	nFCU2MaxSprite = (nFCU2ROMSize - 1) >> 5;
361 
362 	nSize = 0x10 * 0x101 * sizeof(UINT16*);
363 	pFCU2SpriteQueueData = (UINT16**)BurnMalloc(nSize);
364 	memset(pFCU2SpriteQueueData, 0, nSize);
365 
366 	pFCU2SpriteBuffer = (UINT8*)BurnMalloc(0x0800);
367 
368 	FCU2TileAttrib = (UINT8*)BurnMalloc(32768);
369 	memset(FCU2TileAttrib, 0, 32768);
370 	for (UINT32 j = 0; j < (nFCU2ROMSize >> 5); j++) {
371 		bool bTransparent = true, bSolid = true;
372 		INT32 nTwoPixels;
373 		for (UINT32 k = (j << 5); k < ((j << 5) + 32); k++) {
374 			if ((nTwoPixels = FCU2ROM[k]) != 0) {
375 				bTransparent = false;
376 			}
377 			if ((nTwoPixels & 0xF0) == 0 || (nTwoPixels & 0x0F) == 0) {
378 				bSolid = false;
379 			}
380 		}
381 		if (bTransparent) {
382 			FCU2TileAttrib[j] = 0;
383 		} else {
384 			if (bSolid) {
385 				FCU2TileAttrib[j] = 9;
386 			} else {
387 				FCU2TileAttrib[j] = 1;
388 			}
389 		}
390 	}
391 
392 	if (!nLayer0XOffset) {
393 		nLayer0XOffset = 0x01EF + 6;
394 	}
395 	if (!nLayer1XOffset) {
396 		nLayer1XOffset = 0x01EF + 4;
397 	}
398 	if (!nLayer2XOffset) {
399 		nLayer2XOffset = 0x01EF + 2;
400 	}
401 	if (!nLayer3XOffset) {
402 		nLayer3XOffset = 0x01EF + 0;
403 	}
404 
405 	if (!nLayer0YOffset) {
406 		nLayer0YOffset = 0x0101;
407 	}
408 	if (!nLayer1YOffset) {
409 		nLayer1YOffset = 0x0101;
410 	}
411 	if (!nLayer2YOffset) {
412 		nLayer2YOffset = 0x0101;
413 	}
414 	if (!nLayer3YOffset) {
415 		nLayer3YOffset = 0x0101;
416 	}
417 
418 	ToaOpaquePriority = 0;
419 
420 	return 0;
421 }
422 
ToaExitBCU2()423 INT32 ToaExitBCU2()
424 {
425 	nLayer0XOffset = 0;
426 	nLayer1XOffset = 0;
427 	nLayer2XOffset = 0;
428 	nLayer3XOffset = 0;
429 	nLayer0YOffset = 0;
430 	nLayer1YOffset = 0;
431 	nLayer2YOffset = 0;
432 	nLayer3YOffset = 0;
433 
434 	nFCU2SpriteXOffset = 0;
435 	nFCU2SpriteYOffset = 0;
436 
437 	BurnFree(pBCU2TileQueueData);
438 	BurnFree(BCU2TileAttrib);
439 	BurnFree(pFCU2SpriteQueueData);
440 	BurnFree(pFCU2SpriteBuffer);
441 	BurnFree(FCU2TileAttrib);
442 
443 	return 0;
444 }
445 
ToaScanBCU2(INT32 nAction,INT32 * pnMin)446 INT32 ToaScanBCU2(INT32 nAction, INT32* pnMin)
447 {
448     if (nAction & ACB_VOLATILE) {		// Scan volatile data
449         if (pnMin) {
450             *pnMin = 0x029496;
451         }
452 
453         SCAN_VAR(BCU2Pointer);
454         SCAN_VAR(FCU2Pointer);
455         SCAN_VAR(BCU2Reg);
456         SCAN_VAR(ToaOpaquePriority);
457         SCAN_VAR(nLayer0XOffset);
458         SCAN_VAR(nLayer1XOffset);
459         SCAN_VAR(nLayer2XOffset);
460         SCAN_VAR(nLayer3XOffset);
461         SCAN_VAR(nLayer0YOffset);
462         SCAN_VAR(nLayer1YOffset);
463         SCAN_VAR(nLayer2YOffset);
464         SCAN_VAR(nLayer3YOffset);
465         SCAN_VAR(nBCU2TileXOffset);
466         SCAN_VAR(nBCU2TileYOffset);
467         SCAN_VAR(nSpriteXOffset);
468         SCAN_VAR(nSpriteYOffset);
469         SCAN_VAR(nSpritePriority);
470     }
471 
472     return 0;
473 }
474