1 #include "neogeo.h"
2
3 UINT8* NeoTextROMBIOS;
4 UINT8* NeoTextROM[MAX_SLOT];
5
6 INT32 nNeoTextROMSize[MAX_SLOT] = { 0, };
7 bool bBIOSTextROMEnabled;
8
9 static UINT8* NeoTextROMCurrent;
10
11 static INT8* NeoTextTileAttrib[MAX_SLOT] = { NULL, };
12 static INT8* NeoTextTileAttribBIOS = NULL;
13 static INT8* NeoTextTileAttribActive = NULL;
14 static INT32 nBankswitch[MAX_SLOT] = { 0, };
15
16 static INT32 nBankLookupAddress[40];
17 static INT32 nBankLookupShift[40];
18
19 static UINT8* pTile;
20 static UINT8* pTileData;
21 static UINT32* pTilePalette;
22 static UINT32 nTransparent;
23
24 typedef void (*RenderTileFunction)();
25 static RenderTileFunction RenderTile;
26
27 static INT32 nLastBPP = 0;
28
29 static INT32 nMinX, nMaxX;
30
alpha_blend(UINT32 d,UINT32 s,UINT32 p)31 static inline UINT32 alpha_blend(UINT32 d, UINT32 s, UINT32 p)
32 {
33 INT32 a = 255 - p;
34
35 return (((((s & 0xff00ff) * p) + ((d & 0xff00ff) * a)) & 0xff00ff00) +
36 ((((s & 0x00ff00) * p) + ((d & 0x00ff00) * a)) & 0x00ff0000)) >> 8;
37 }
38
39 #define BPP 16
40 #include "neo_text_render.h"
41 #undef BPP
42
43 #define BPP 24
44 #include "neo_text_render.h"
45 #undef BPP
46
47 #define BPP 32
48 #include "neo_text_render.h"
49 #undef BPP
50
NeoRenderText()51 INT32 NeoRenderText()
52 {
53 INT32 x, y;
54 UINT8* pTextROM;
55 INT8* pTileAttrib;
56 UINT8* pCurrentRow = pBurnDraw;
57 UINT32* pTextPalette = NeoPalette;
58 UINT32 nTileDown = nBurnPitch << 3;
59 UINT32 nTileLeft = nBurnBpp << 3;
60 UINT16* pTileRow = (UINT16*)(NeoGraphicsRAM + 0xE000);
61
62 if (!(nBurnLayer & 2)) {
63 return 0;
64 }
65
66 if (nLastBPP != nBurnBpp ) {
67 nLastBPP = nBurnBpp;
68
69 switch (nBurnBpp) {
70 case 2:
71 RenderTile = *RenderTile16;
72 break;
73 case 3:
74 RenderTile = *RenderTile24;
75 break;
76 case 4:
77 RenderTile = *RenderTile32;
78 break;
79 default:
80 return 1;
81 }
82 }
83
84 if (!bBIOSTextROMEnabled && nBankswitch[nNeoActiveSlot]) {
85
86 if (!NeoTextROMCurrent) {
87 return 0;
88 }
89
90 if (nBankswitch[nNeoActiveSlot] == 1) {
91
92 // Garou, Metal Slug 3, Metal Slug 4
93
94 INT32 nOffset[32];
95 INT32 nBank = (3 << 12);
96 INT32 z = 0;
97
98 y = 0;
99 while (y < 32) {
100 if (*((UINT16*)(NeoGraphicsRAM + 0xEA00 + z)) == 0x0200 && (*((UINT16*)(NeoGraphicsRAM + 0xEB00 + z)) & 0xFF00) == 0xFF00) {
101 nBank = ((*((UINT16*)(NeoGraphicsRAM + 0xEB00 + z)) & 3) ^ 3) << 12;
102 nOffset[y++] = nBank;
103 }
104 nOffset[y++] = nBank;
105 z += 4;
106 }
107
108 for (y = 2, pTileRow += 2; y < 30; y++, pCurrentRow += nTileDown, pTileRow++) {
109 pTextROM = NeoTextROMCurrent + (nOffset[y - 2] << 5);
110 pTileAttrib = NeoTextTileAttribActive + nOffset[y - 2];
111 for (x = nMinX, pTile = pCurrentRow; x < nMaxX; x++, pTile += nTileLeft) {
112 UINT32 nTile = pTileRow[x << 5];
113 INT32 nPalette = nTile & 0xF000;
114 nTile &= 0x0FFF;
115 nTransparent = (UINT8)pTileAttrib[nTile];
116 if (nTransparent != 1) {
117 pTileData = pTextROM + (nTile << 5);
118 pTilePalette = &pTextPalette[nPalette >> 8];
119 RenderTile();
120 }
121 }
122 }
123 } else {
124
125 // KOF2000
126
127 UINT16* pBankInfo = (UINT16*)(NeoGraphicsRAM + 0xEA00) + 1;
128 pTextROM = NeoTextROMCurrent;
129 pTileAttrib = NeoTextTileAttribActive;
130
131 for (y = 2, pTileRow += 2; y < 30; y++, pCurrentRow += nTileDown, pTileRow++, pBankInfo++) {
132 for (x = nMinX, pTile = pCurrentRow; x < nMaxX; x++, pTile += nTileLeft) {
133 UINT32 nTile = pTileRow[x << 5];
134 INT32 nPalette = nTile & 0xF000;
135 nTile &= 0x0FFF;
136 nTile += (((pBankInfo[nBankLookupAddress[x]] >> nBankLookupShift[x]) & 3) ^ 3) << 12;
137 nTransparent = (UINT8)pTileAttrib[nTile];
138 if (nTransparent != 1) {
139 pTileData = pTextROM + (nTile << 5);
140 pTilePalette = &pTextPalette[nPalette >> 8];
141 RenderTile();
142 }
143 }
144 }
145 }
146 } else {
147 if (bBIOSTextROMEnabled) {
148 pTextROM = NeoTextROMBIOS;
149 pTileAttrib = NeoTextTileAttribBIOS;
150 } else {
151 pTextROM = NeoTextROMCurrent;
152 pTileAttrib = NeoTextTileAttribActive;
153 }
154 if (!pTextROM) {
155 return 0;
156 }
157
158 for (y = 2, pTileRow += 2; y < 30; y++, pCurrentRow += nTileDown, pTileRow++) {
159 for (x = nMinX, pTile = pCurrentRow; x < nMaxX; x++, pTile += nTileLeft) {
160 UINT32 nTile = pTileRow[x << 5];
161 INT32 nPalette = nTile & 0xF000;
162 nTile &= 0xFFF;
163 nTransparent = (UINT8)pTileAttrib[nTile];
164 if (nTransparent != 1) {
165 pTileData = pTextROM + (nTile << 5);
166 pTilePalette = &pTextPalette[nPalette >> 8];
167 RenderTile();
168 }
169 }
170 }
171 }
172
173 return 0;
174 }
175
NeoExitText(INT32 nSlot)176 void NeoExitText(INT32 nSlot)
177 {
178 BurnFree(NeoTextTileAttribBIOS);
179 BurnFree(NeoTextTileAttrib[nSlot]);
180 NeoTextTileAttribActive = NULL;
181 }
182
NeoUpdateTextAttribBIOS(INT32 nOffset,INT32 nSize)183 static void NeoUpdateTextAttribBIOS(INT32 nOffset, INT32 nSize)
184 {
185 for (INT32 i = nOffset & ~31; i < nOffset + nSize; i += 32) {
186 NeoTextTileAttribBIOS[i >> 5] = (((INT64*)NeoTextROMBIOS)[(i >> 3) + 0] ||
187 ((INT64*)NeoTextROMBIOS)[(i >> 3) + 1] ||
188 ((INT64*)NeoTextROMBIOS)[(i >> 3) + 2] ||
189 ((INT64*)NeoTextROMBIOS)[(i >> 3) + 3])
190 ? 0 : 1;
191 }
192 }
193
NeoUpdateTextAttribOne(const INT32 nOffset)194 static inline void NeoUpdateTextAttribOne(const INT32 nOffset)
195 {
196 NeoTextTileAttribActive[nOffset >> 5] = 1;
197
198 for (INT32 i = nOffset; i < nOffset + 32; i += 4) {
199 if (*((UINT32*)(NeoTextROMCurrent + i))) {
200 NeoTextTileAttribActive[nOffset >> 5] = 0;
201 break;
202 }
203 }
204 }
205
NeoUpdateTextAttrib(INT32 nOffset,INT32 nSize)206 static void NeoUpdateTextAttrib(INT32 nOffset, INT32 nSize)
207 {
208 nOffset &= ~0x1F;
209
210 for (INT32 i = nOffset; i < nOffset + nSize; i += 32) {
211 NeoUpdateTextAttribOne(i);
212 }
213 }
214
NeoUpdateTextOne(INT32 nOffset,const UINT8 byteValue)215 void NeoUpdateTextOne(INT32 nOffset, const UINT8 byteValue)
216 {
217 nOffset = (nOffset & ~0x1F) | (((nOffset ^ 0x10) & 0x18) >> 3) | ((nOffset & 0x07) << 2);
218
219 if (byteValue) {
220 NeoTextTileAttribActive[nOffset >> 5] = 0;
221 } else {
222 if (NeoTextTileAttribActive[nOffset >> 5] == 0 && NeoTextROMCurrent[nOffset]) {
223 NeoTextTileAttribActive[nOffset >> 5] = 1;
224 NeoUpdateTextAttribOne(nOffset);
225 }
226 }
227
228 NeoTextROMCurrent[nOffset] = byteValue;
229 }
230
NeoTextDecodeTile(const UINT8 * pData,UINT8 * pDest)231 static inline void NeoTextDecodeTile(const UINT8* pData, UINT8* pDest)
232 {
233 UINT8 nBuffer[32];
234
235 for (INT32 i = 0; i < 8; i++) {
236 nBuffer[0 + i * 4] = pData[16 + i];
237 nBuffer[1 + i * 4] = pData[24 + i];
238 nBuffer[2 + i * 4] = pData[ 0 + i];
239 nBuffer[3 + i * 4] = pData[ 8 + i];
240 }
241
242 for (INT32 i = 0; i < 32; i++) {
243 pDest[i] = nBuffer[i] << 4;
244 pDest[i] |= nBuffer[i] >> 4;
245 }
246 }
247
NeoDecodeTextBIOS(INT32 nOffset,const INT32 nSize,UINT8 * pData)248 void NeoDecodeTextBIOS(INT32 nOffset, const INT32 nSize, UINT8* pData)
249 {
250 UINT8* pEnd = pData + nSize;
251
252 for (UINT8* pDest = NeoTextROMBIOS + (nOffset & ~0x1F); pData < pEnd; pData += 32, pDest += 32) {
253 NeoTextDecodeTile(pData, pDest);
254 }
255
256 // if (NeoTextTileAttribBIOS) {
257 // NeoUpdateTextAttribBIOS(0, nSize);
258 // }
259 }
260
NeoDecodeText(INT32 nOffset,const INT32 nSize,UINT8 * pData,UINT8 * pDest)261 void NeoDecodeText(INT32 nOffset, const INT32 nSize, UINT8* pData, UINT8* pDest)
262 {
263 UINT8* pEnd = pData + nSize;
264
265 for (pData += (nOffset & ~0x1F); pData < pEnd; pData += 32, pDest += 32) {
266 NeoTextDecodeTile(pData, pDest);
267 }
268 }
269
NeoUpdateText(INT32 nOffset,const INT32 nSize,UINT8 * pData,UINT8 * pDest)270 void NeoUpdateText(INT32 nOffset, const INT32 nSize, UINT8* pData, UINT8* pDest)
271 {
272 NeoDecodeText(nOffset, nSize, pData, pDest);
273 if (NeoTextTileAttribActive) {
274 NeoUpdateTextAttrib((nOffset & ~0x1F), nSize);
275 }
276 }
277
NeoSetTextSlot(INT32 nSlot)278 void NeoSetTextSlot(INT32 nSlot)
279 {
280 NeoTextROMCurrent = NeoTextROM[nSlot];
281 NeoTextTileAttribActive = NeoTextTileAttrib[nSlot];
282 }
283
NeoTextBlendInit(INT32 nSlot)284 static void NeoTextBlendInit(INT32 nSlot)
285 {
286 char filename[256];
287
288 sprintf (filename, "support/blend/%s.blde", BurnDrvGetTextA(DRV_NAME));
289
290 FILE *fa = fopen(filename, "rt");
291
292 if (fa == NULL) {
293 sprintf (filename, "support/blend/%s.blde", BurnDrvGetTextA(DRV_PARENT));
294
295 fa = fopen(filename, "rt");
296
297 if (fa == NULL) {
298 return;
299 }
300 }
301
302 bprintf (PRINT_IMPORTANT, _T("Using text blending (.bld) table!\n"));
303
304 char szLine[64];
305
306 INT32 table[4] = { 0, 0xff-0x3f, 0xff-0x7f, 0xff-0x7f }; // last one 7f?
307
308 while (1)
309 {
310 if (fgets (szLine, 64, fa) == NULL) break;
311
312 if (strncmp ("Game", szLine, 4) == 0) continue; // don't care
313 if (strncmp ("Name", szLine, 4) == 0) continue; // don't care
314 if (szLine[0] == ';') continue; // comment (also don't care)
315
316 INT32 type;
317 UINT32 min,max,k, single_entry = (UINT32)-1;
318
319 for (k = 0; k < strlen(szLine); k++) {
320 if (szLine[k] == '-') { single_entry = k+1; break; }
321 }
322
323 /* if (single_entry < 0) {
324 sscanf(szLine,"%x %d",&max,&type);
325 min = max;
326 } else {*/
327 sscanf(szLine,"%x",&min);
328 sscanf(szLine+single_entry,"%x %d",&max,&type);
329 // }
330
331 for (k = min; k <= max && k < ((UINT32)nNeoTextROMSize[nSlot]/0x20); k++) {
332 if (NeoTextTileAttrib[nSlot][k] != 1) // ?
333 NeoTextTileAttrib[nSlot][k] = table[type&3];
334 }
335 }
336
337 fclose (fa);
338 }
339
NeoInitText(INT32 nSlot)340 INT32 NeoInitText(INT32 nSlot)
341 {
342 if (nSlot < 0) {
343 NeoTextTileAttribBIOS = (INT8*)BurnMalloc(0x1000);
344 for (INT32 i = 0; i < 0x1000; i++) {
345 NeoTextTileAttribBIOS[i] = 1;
346 }
347 NeoUpdateTextAttribBIOS(0, 0x020000);
348
349 return 0;
350 }
351
352 INT32 nTileNum = nNeoTextROMSize[nSlot] >> 5;
353
354 // NeoExitText(nSlot);
355
356 NeoTextTileAttrib[nSlot] = (INT8*)BurnMalloc((nTileNum < 0x1000) ? 0x1000 : nTileNum);
357
358 if (nNeoScreenWidth == 304) {
359 nMinX = 1;
360 nMaxX = 39;
361 } else {
362 nMinX = 0;
363 nMaxX = 40;
364 }
365
366 // Set up tile attributes
367
368 NeoTextROMCurrent = NeoTextROM[nSlot];
369 NeoTextTileAttribActive = NeoTextTileAttrib[nSlot];
370 for (INT32 i = 0; i < ((nTileNum < 0x1000) ? 0x1000 : nTileNum); i++) {
371 NeoTextTileAttribActive[i] = 1;
372 }
373 NeoUpdateTextAttrib(0, nNeoTextROMSize[nSlot]);
374
375 NeoTextBlendInit(nSlot);
376
377 // Set up tile bankswitching
378
379 nBankswitch[nSlot] = 0;
380 if (nNeoTextROMSize[nSlot] > 0x040000) {
381 // if (BurnDrvGetHardwareCode() & HARDWARE_SNK_CMC50) {
382 if (BurnDrvGetHardwareCode() & HARDWARE_SNK_ALTERNATE_TEXT) {
383 nBankswitch[nSlot] = 2;
384
385 // Precompute lookup-tables
386 for (INT32 x = nMinX; x < nMaxX; x++) {
387 nBankLookupAddress[x] = (x / 6) << 5;
388 nBankLookupShift[x] = (5 - (x % 6)) << 1;
389 }
390
391 } else {
392 nBankswitch[nSlot] = 1;
393 }
394 }
395
396 return 0;
397 }
398