1 // license:BSD-3-Clause
2 // copyright-holders:Fabio Priuli,Acho A. Tang, R. Belmont
3
4 // K052109
5
6 #include "tiles_generic.h"
7 #include "konamiic.h"
8
9 static UINT8 *K052109Ram = NULL;
10
11 typedef void (*K052109_Callback)(INT32 Layer, INT32 Bank, INT32 *Code, INT32 *Colour, INT32 *xFlip, INT32 *Priority);
12 static K052109_Callback K052109Callback;
13 static INT32 K052109ScrollX[3];
14 static INT32 K052109ScrollY[3];
15 static UINT8 K052109ScrollCtrl;
16 static UINT8 K052109CharRomBank[4];
17 static UINT8 K052109CharRomBank2[4];
18 INT32 K052109RMRDLine;
19 static UINT8 K052109RomSubBank;
20 static UINT32 K052109RomMask;
21 static UINT8 *K052109Rom;
22 static UINT32 K052109RomExpMask;
23 static UINT8 *K052109RomExp;
24
25 static INT32 K052109FlipEnable;
26 INT32 K052109_irq_enabled;
27
28 static INT32 K052109ScrollXOff[3];
29 static INT32 K052109ScrollYOff[3];
30
31 static INT32 K052109EnableRows[3];
32 static INT32 K052109EnableLine[3];
33 static INT32 K052109ScrollRows[3][256];
34 static INT32 K052109EnableCols[3];
35 static INT32 K052109ScrollCols[3][64];
36
37 static INT32 has_extra_video_ram = 0; // xmen kludge
38
update_scroll_one(INT32 nLayer,INT32 control,INT32 ram_offset)39 static void update_scroll_one(INT32 nLayer, INT32 control, INT32 ram_offset)
40 {
41 K052109EnableLine[nLayer] = 0;
42 K052109EnableRows[nLayer] = 1;
43 K052109EnableCols[nLayer] = 1;
44
45 UINT8 *sourceram = K052109Ram + ram_offset;
46
47 if ((control & 0x03) == 0x02 || (control & 0x03) == 0x03)
48 {
49 K052109EnableLine[nLayer] = 1;
50
51 K052109EnableRows[nLayer] = 256;
52
53 INT32 andval = ((control & 0x03) == 0x02) ? 0xfff8 : 0xffff;
54 UINT8 *scrollram = &sourceram[0x1a00];
55 INT32 yscroll = sourceram[0x180c];
56
57 if (nLayer == 2 && (control & 0x03) == 0x02 && K052109ScrollCtrl == 0x70) {
58 yscroll = sourceram[0x1823]; // hack for suratk 2nd boss rotating star field
59 }
60
61 for (INT32 offs = 0; offs < 256; offs++)
62 {
63 INT32 xscroll = scrollram[2 * (offs & andval) + 0] + 256 * scrollram[2 * (offs & andval) + 1];
64 K052109ScrollRows[nLayer][(offs + yscroll)&0xff] = xscroll - 6;
65 }
66
67 K052109EnableCols[nLayer] = 1;
68 K052109ScrollCols[nLayer][0] = yscroll;
69 }
70 else if ((control & 0x04) == 0x04)
71 {
72 // K052109EnableLine[nLayer] = 1;
73
74 UINT8 *scrollram = &sourceram[0x1800];
75 INT32 xscroll = (sourceram[0x1a00] + 256 * sourceram[0x1a01]) - 6;
76
77 K052109EnableCols[nLayer] = 64;
78 for (INT32 offs = 0; offs < 512/8; offs++)
79 {
80 K052109ScrollCols[nLayer][(((offs*8)+xscroll)&0x1f8)/8] = scrollram[offs];
81 }
82
83 K052109EnableRows[nLayer] = 1;
84 K052109ScrollRows[nLayer][0] = K052109ScrollX[nLayer] = xscroll;
85 }
86 else
87 {
88 K052109EnableRows[nLayer] = K052109EnableCols[nLayer] = 1;
89 K052109ScrollX[nLayer] = (sourceram[0x1a00] + 256 * sourceram[0x1a01]) - 6;
90 K052109ScrollY[nLayer] = sourceram[0x180c];
91 }
92 }
93
K052109UpdateScroll()94 void K052109UpdateScroll()
95 {
96 update_scroll_one(1, K052109ScrollCtrl >> 0, 0x0000);
97 update_scroll_one(2, K052109ScrollCtrl >> 3, 0x2000);
98 }
99
K052109AdjustScroll(INT32 x,INT32 y)100 void K052109AdjustScroll(INT32 x, INT32 y)
101 {
102 for (INT32 i = 0; i < 3; i++) {
103 K052109ScrollXOff[i] = x;
104 K052109ScrollYOff[i] = y;
105 }
106 }
107
K052109RenderLayerLineScroll(INT32 nLayer,INT32 Flags,INT32 Priority)108 void K052109RenderLayerLineScroll(INT32 nLayer, INT32 Flags, INT32 Priority)
109 {
110 INT32 Category = Flags & 0xff;
111 INT32 Opaque = (Flags >> 16) & 1;
112
113 UINT32 *dst = konami_bitmap32;
114 UINT8 *pdst = konami_priority_bitmap;
115
116 INT32 ram_offset = nLayer * 0x800;
117
118 INT32 rowdiv = 256 / K052109EnableRows[nLayer];
119
120 for (INT32 y = 0; y < nScreenHeight; y++)
121 {
122 for (INT32 x = 0; x < nScreenWidth + 8; x+=8)
123 {
124 INT32 yy = (y + (K052109ScrollCols[nLayer][0] + K052109ScrollYOff[nLayer] + 16)) & 0xff;
125 INT32 xx = (x + (K052109ScrollRows[nLayer][yy/rowdiv] + K052109ScrollXOff[nLayer] + 104)) & 0x1ff;
126
127 INT32 TileIndex = (xx/8) + ((yy/8)*64);
128
129 INT32 Colour = K052109Ram[TileIndex + ram_offset];
130 INT32 Code = K052109Ram[TileIndex + 0x2000 + ram_offset] + (K052109Ram[TileIndex + 0x4000 + ram_offset] << 8);
131
132 INT32 Bank = K052109CharRomBank[(Colour & 0x0c) >> 2];
133 if (has_extra_video_ram) Bank = (Colour & 0x0c) >> 2; // kludge for X-Men
134
135 Colour = (Colour & 0xf3) | ((Bank & 0x03) << 2);
136 Bank >>= 2;
137
138 INT32 yFlip = Colour & 0x02;
139 INT32 xFlip = 0;
140 INT32 Prio = 0;
141
142 K052109Callback(nLayer, Bank, &Code, &Colour, &xFlip, &Prio);
143
144 if (Prio != Category && Category) continue;
145
146 if (xFlip && !(K052109FlipEnable & 1)) xFlip = 0;
147 if (yFlip && !(K052109FlipEnable & 2)) yFlip = 0;
148
149 UINT8 *src = K052109RomExp + ((Code & K052109RomExpMask) * 0x40) + ((yFlip ? (~yy & 7) : (yy & 7)) * 8);
150 UINT32 *pal = konami_palette32 + (Colour * 16);
151
152 if (xFlip) xFlip = 0x07;
153
154 INT32 xv = xx & 0x07;
155
156 for (INT32 dx = 0; dx < 8; dx++)
157 {
158 if ((x+dx-xv) < 0 || (x+dx-xv) >= nScreenWidth) continue;
159
160 INT32 pxl = src[dx^xFlip];
161 if (!Opaque && !pxl) continue;
162
163 dst[x+dx-xv] = pal[pxl];
164 pdst[x+dx-xv] = Priority;
165 }
166 }
167
168 pdst += nScreenWidth;
169 dst += nScreenWidth;
170 }
171 }
172
K052109RenderLayer(INT32 nLayer,INT32 Flags,INT32 Priority)173 void K052109RenderLayer(INT32 nLayer, INT32 Flags, INT32 Priority)
174 {
175 nLayer &= 0x03;
176
177 // Row and line scroll.
178 if (K052109EnableLine[nLayer]) {
179 K052109RenderLayerLineScroll(nLayer, Flags, Priority);
180 return;
181 }
182
183 INT32 EnableCategory = Flags & 0x100;
184 INT32 Category = Flags & 0xff;
185
186 INT32 Opaque = (Flags >> 16) & 1;
187 INT32 ram_offset = nLayer * 0x800;
188
189 INT32 mx, my, Bank, Code, Colour, x, y, xFlip = 0, yFlip, TileIndex = 0;
190
191 for (my = 0; my < 32; my++) {
192 for (mx = 0; mx < 64; mx++) {
193 TileIndex = (my << 6) | mx;
194
195 Colour = K052109Ram[TileIndex + ram_offset];
196 Code = K052109Ram[TileIndex + 0x2000 + ram_offset] + (K052109Ram[TileIndex + 0x4000 + ram_offset] << 8);
197
198 Bank = K052109CharRomBank[(Colour & 0x0c) >> 2];
199 if (has_extra_video_ram) Bank = (Colour & 0x0c) >> 2; // kludge for X-Men
200
201 Colour = (Colour & 0xf3) | ((Bank & 0x03) << 2);
202 Bank >>= 2;
203
204 yFlip = Colour & 0x02;
205
206 INT32 Prio = 0;
207
208 K052109Callback(nLayer, Bank, &Code, &Colour, &xFlip, &Prio);
209
210 if (Prio != Category && EnableCategory) continue;
211
212 if (xFlip && !(K052109FlipEnable & 1)) xFlip = 0;
213 if (yFlip && !(K052109FlipEnable & 2)) yFlip = 0;
214
215 x = 8 * mx;
216 y = 8 * my;
217
218 INT32 scrollx = K052109ScrollX[nLayer] + K052109ScrollXOff[nLayer];
219 INT32 scrolly = K052109ScrollYOff[nLayer];
220
221 x -= (scrollx + 104) & 0x1ff;
222 if (x < -7) x += 512;
223
224 if (K052109EnableCols[nLayer] == 64) {
225 scrolly += K052109ScrollCols[nLayer][((mx*8)&0x1ff)/8];
226 } else {
227 scrolly += K052109ScrollY[nLayer];
228 }
229
230 y -= (scrolly + 16) & 0xff;
231 if (y < -7) y += 256;
232
233 if (x >= nScreenWidth || y >= nScreenHeight) continue;
234
235 {
236 UINT32 *dst = konami_bitmap32 + y * nScreenWidth + x;
237 UINT8 *pri = konami_priority_bitmap + y * nScreenWidth + x;
238 UINT8 *gfx = K052109RomExp + (Code & K052109RomExpMask) * 0x40;
239
240 INT32 flip = 0;
241 if (xFlip) flip |= 0x07;
242 if (yFlip) flip |= 0x38;
243
244 UINT32 *pal = konami_palette32 + (Colour * 16);
245 INT32 trans = (Opaque) ? 0xffff : 0;
246
247 for (INT32 yy = 0; yy < 8; yy++, y++)
248 {
249 if (y >= 0 && y < nScreenHeight)
250 {
251 for (INT32 xx = 0; xx < 8; xx++)
252 {
253 if ((x+xx) >= 0 && (x+xx) < nScreenWidth)
254 {
255 INT32 pxl = gfx[((yy*8)+xx)^flip];
256
257 if (pxl != trans)
258 {
259 dst[xx] = pal[pxl];
260 pri[xx] = Priority;
261 }
262 }
263 }
264 }
265
266 dst += nScreenWidth;
267 pri += nScreenWidth;
268 }
269 }
270 }
271 }
272 }
273
K052109Read(UINT32 Offset)274 UINT8 K052109Read(UINT32 Offset)
275 {
276 if (Offset > 0x5fff) return 0;
277
278 if (K052109RMRDLine) {
279 INT32 Flags = 0;
280 INT32 Code = (Offset & 0x1fff) >> 5;
281 INT32 Colour = K052109RomSubBank;
282 INT32 Bank = K052109CharRomBank[(Colour & 0x0c) >> 2] >> 2;
283 Bank |= (K052109CharRomBank2[(Colour & 0x0c) >> 2] >> 2);
284
285 if (has_extra_video_ram)
286 Code |= Colour << 8; /* kludge for X-Men */
287 else
288 K052109Callback(0, Bank, &Code, &Colour, &Flags, &Flags /*actually priority*/);
289
290 INT32 Addr = (Code << 5) + (Offset & 0x1f);
291 Addr &= K052109RomMask;
292
293 return K052109Rom[Addr];
294 }
295
296 return K052109Ram[Offset];
297 }
298
K052109Write(UINT32 Offset,UINT8 Data)299 void K052109Write(UINT32 Offset, UINT8 Data)
300 {
301 if (Offset > 0x5fff) return;
302
303 K052109Ram[Offset] = Data;
304
305 if (Offset >= 0x4000) has_extra_video_ram = 1; /* kludge for X-Men */
306
307 if ((Offset & 0x1fff) >= 0x1800) {
308 switch (Offset) {
309 case 0x1c80: {
310 K052109ScrollCtrl = Data;
311 return;
312 }
313
314 case 0x1d00: {
315 K052109_irq_enabled = Data & 0x04;
316 return;
317 }
318
319 case 0x1d80: {
320 K052109CharRomBank[0] = Data & 0x0f;
321 K052109CharRomBank[1] = (Data >> 4) & 0x0f;
322 return;
323 }
324
325 case 0x1e00: // Normal..
326 case 0x3e00: // Suprise Attack
327 {
328 K052109RomSubBank = Data;
329 return;
330 }
331
332 case 0x1e80: {
333 // flip
334 K052109FlipEnable = ((Data & 0x06) >> 1);
335 return;
336 }
337
338 case 0x1f00: {
339 K052109CharRomBank[2] = Data & 0x0f;
340 K052109CharRomBank[3] = (Data >> 4) & 0x0f;
341 return;
342 }
343
344 case 0x3d80: // Surprise Attack (rom test)
345 {
346 // K052109CharRomBank2[0];
347 // K052109CharRomBank2[1];
348 return;
349 }
350
351 case 0x3f00: // Surprise Attack (rom test)
352 {
353 // K052109CharRomBank2[2];
354 // K052109CharRomBank2[3];
355 return;
356 }
357
358 case 0x180c:
359 case 0x180d:
360 case 0x1a00:
361 case 0x1a01:
362 case 0x380c:
363 case 0x380d:
364 case 0x3a00:
365 case 0x3a01: {
366 // Scroll Writes
367 return;
368 }
369
370 case 0x1c00: {
371 //???
372 return;
373 }
374 }
375 }
376 }
377
K052109SetCallback(void (* Callback)(INT32 Layer,INT32 Bank,INT32 * Code,INT32 * Colour,INT32 * xFlip,INT32 * Priority))378 void K052109SetCallback(void (*Callback)(INT32 Layer, INT32 Bank, INT32 *Code, INT32 *Colour, INT32 *xFlip, INT32 *Priority))
379 {
380 K052109Callback = Callback;
381 }
382
K052109Reset()383 void K052109Reset()
384 {
385 memset(K052109ScrollX, 0, 3 * sizeof(INT32));
386 memset(K052109ScrollY, 0, 3 * sizeof(INT32));
387 K052109ScrollCtrl = 0;
388 memset(K052109CharRomBank, 0, 4);
389 memset(K052109CharRomBank2,0, 4);
390 K052109RMRDLine = 0;
391 K052109RomSubBank = 0;
392 K052109_irq_enabled = 0;
393 memset (K052109Ram, 0, 0x6000);
394
395 memset (K052109EnableRows, 0, 3 * sizeof(INT32));
396 memset (K052109EnableLine, 0, 3 * sizeof(INT32));
397 memset (K052109ScrollRows, 0, 256 * 3 * sizeof(INT32));
398 memset (K052109EnableCols, 0, 3 * sizeof(INT32));
399 memset (K052109ScrollCols, 0, 64 * 3 * sizeof(INT32));
400 }
401
K052109GfxDecode(UINT8 * src,UINT8 * dst,INT32 nLen)402 void K052109GfxDecode(UINT8 *src, UINT8 *dst, INT32 nLen)
403 {
404 INT32 Plane[4] = { STEP4(24, -8) };
405 INT32 XOffs[8] = { STEP8(0, 1) };
406 INT32 YOffs[8] = { STEP8(0, 32) };
407
408 GfxDecode((nLen * 2) / (8 * 8), 4, 8, 8, Plane, XOffs, YOffs, 0x100, src, dst);
409 }
410
K052109Init(UINT8 * pRomSrc,UINT8 * pRomSrcExp,UINT32 RomMask)411 void K052109Init(UINT8 *pRomSrc, UINT8 *pRomSrcExp, UINT32 RomMask)
412 {
413 K052109Ram = (UINT8*)BurnMalloc(0x6000);
414
415 K052109RomMask = RomMask;
416 K052109RomExpMask = (RomMask * 2) / (8 * 8);
417
418 K052109Rom = pRomSrc;
419 K052109RomExp = pRomSrcExp;
420
421 KonamiIC_K052109InUse = 1;
422
423 for (INT32 i = 0; i < 3; i++) {
424 K052109ScrollXOff[i]=0;
425 K052109ScrollYOff[i]=0;
426 }
427
428 KonamiAllocateBitmaps();
429
430 has_extra_video_ram = 0;
431 }
432
K052109Exit()433 void K052109Exit()
434 {
435 BurnFree(K052109Ram);
436
437 K052109Callback = NULL;
438 K052109RomMask = 0;
439 K052109Rom = NULL;
440
441 memset(K052109ScrollX, 0, sizeof(K052109ScrollX));
442 memset(K052109ScrollY, 0, sizeof(K052109ScrollY));
443 K052109ScrollCtrl = 0;
444 memset(K052109CharRomBank, 0, 4);
445 K052109RMRDLine = 0;
446 K052109RomSubBank = 0;
447 K052109FlipEnable = 0;
448 K052109_irq_enabled = 0;
449
450 has_extra_video_ram = 0;
451 }
452
K052109Scan(INT32 nAction)453 void K052109Scan(INT32 nAction)
454 {
455 struct BurnArea ba;
456
457 if (nAction & ACB_MEMORY_RAM) {
458 memset(&ba, 0, sizeof(ba));
459 ba.Data = K052109Ram;
460 ba.nLen = 0x6000;
461 ba.szName = "K052109 Ram";
462 BurnAcb(&ba);
463 }
464
465 if (nAction & ACB_DRIVER_DATA) {
466 SCAN_VAR(K052109ScrollX);
467 SCAN_VAR(K052109ScrollY);
468 SCAN_VAR(K052109ScrollCtrl);
469 SCAN_VAR(K052109CharRomBank);
470 SCAN_VAR(K052109CharRomBank2);
471 SCAN_VAR(K052109RMRDLine);
472 SCAN_VAR(K052109RomSubBank);
473 SCAN_VAR(K052109FlipEnable);
474 SCAN_VAR(K052109_irq_enabled);
475 SCAN_VAR(has_extra_video_ram);
476
477 SCAN_VAR(K052109EnableRows);
478 SCAN_VAR(K052109EnableLine);
479 SCAN_VAR(K052109ScrollRows);
480 SCAN_VAR(K052109EnableCols);
481 SCAN_VAR(K052109ScrollCols);
482
483 }
484 }
485