1 #include "genesis_vid.h"
2 #include "burnint.h"
3
4 INT32 GenesisScreenNumber;
5 UINT32 *GenesisPalette = NULL;
6 UINT16 *GenesisPaletteRaw = NULL;
7 UINT16 GenesisPaletteBase;
8 UINT8 VdpBgColour;
9
10 UINT8 *VdpVRAM = NULL;
11 UINT8 *VdpVSRAM = NULL;
12 UINT16 *VdpTransLookup = NULL;
13 UINT8 GenesisVdpRegs[32];
14 UINT16 GenesisBgPalLookup[4];
15 UINT16 GenesisSpPalLookup[4];
16 UINT32 VdpScrollABase;
17 UINT32 VdpScrollBBase;
18 UINT32 VdpWindowBase;
19 UINT32 VdpSpriteBase;
20
21 INT32 VdpHScrollMask;
22 UINT32 VdpHScrollSize;
23 UINT32 VdpHScrollBase;
24 UINT8 VdpVScrollMode;
25
26 UINT8 VdpWindowWidth;
27 UINT8 VdpScrollWidth;
28 UINT8 VdpScrollHeight;
29 UINT8 VdpWindowRight;
30 UINT8 VdpWindowDown;
31 UINT32 VdpWindowHPos;
32 UINT32 VdpWindowVPos;
33
34 UINT8 VdpCmdPart;
35 UINT8 VdpCode;
36 UINT32 VdpAddress;
37
38 #define VRAM_SIZE 0x10000
39 #define VRAM_MASK (VRAM_SIZE - 1)
40 #define VSRAM_SIZE 0x80
41 #define VSRAM_MASK (VSRAM_SIZE - 1)
42 #define CRAM_SIZE 0x40
43
44 #define VDP_VRAM_BYTE(x) (VdpVRAM[(x) & VRAM_MASK])
45 #define VDP_VSRAM_BYTE(x) (VdpVSRAM[(x) & VSRAM_MASK])
46 #define VDP_VRAM_WORD(x) ((VDP_VRAM_BYTE(x) << 8) | VDP_VRAM_BYTE((x) + 1))
47 #define VDP_VSRAM_WORD(x) ((VDP_VSRAM_BYTE(x) << 8) | VDP_VSRAM_BYTE((x) + 1))
48
49 #define EXTRACT_PIXEL(x,i) (((x) >> (((i) ^ 1) * 4)) & 0x0f)
50
VdpRegisterWrite(INT32 d,INT32)51 static void VdpRegisterWrite(INT32 d, INT32 /*vBlank*/)
52 {
53 UINT8 RegNum = (d & 0x1f00) >> 8;
54 UINT8 RegDat = d & 0x00ff;
55
56 GenesisVdpRegs[RegNum] = RegDat;
57
58 switch (RegNum) {
59 case 0x01: {
60 // Video Modes
61 return;
62 }
63
64 case 0x02: {
65 // Scroll A Name Table Base
66 VdpScrollABase = (RegDat & 0x38) << 10;
67 return;
68 }
69
70 case 0x03: {
71 // Window Name Table Base
72 VdpWindowBase = (RegDat & 0x3e) << 10;
73 return;
74 }
75
76 case 0x04: {
77 // Scroll B Name Table Base
78 VdpScrollBBase = (RegDat & 0x07) << 13;
79 return;
80 }
81
82 case 0x05: {
83 // Sprite Table Base
84 VdpSpriteBase = (RegDat & 0x7e) << 9;
85 return;
86 }
87
88 case 0x07: {
89 // BG Colour
90 VdpBgColour = RegDat & 0x3f;
91 return;
92 }
93
94 case 0x0b: {
95 // Scroll Modes
96 static const UINT16 MaskTable[4] = { 0x000, 0x007, 0xff8, 0xfff };
97 VdpVScrollMode = (RegDat & 0x04) >> 2;
98 VdpHScrollMask = MaskTable[RegDat & 3];
99 VdpHScrollSize = 4 * ((VdpHScrollMask < 224) ? (VdpHScrollMask + 1) : 224);
100 return;
101 }
102
103 case 0x0c: {
104 // Video Modes
105 switch (RegDat & 0x81) {
106 case 0x00: {
107 // 32 cell
108 VdpWindowWidth = 32;
109 return;
110 }
111
112 case 0x01: {
113 // 40 cell corrupted
114 VdpWindowWidth = 64;
115 return;
116 }
117
118 case 0x80: {
119 // illegal
120 VdpWindowWidth = 64;
121 return;
122 }
123
124 case 0x81: {
125 // 40 cell
126 VdpWindowWidth = 64;
127 return;
128 }
129 }
130 return;
131 }
132
133 case 0x0d: {
134 // H Scroll Base
135 VdpHScrollBase = (RegDat & 0x3f) << 10;
136 return;
137 }
138
139 case 0x10: {
140 // Scroll Size
141 static const UINT8 SizeTable[4] = { 32, 64, 128, 128 };
142 VdpScrollWidth = SizeTable[RegDat & 0x03];
143 VdpScrollHeight = SizeTable[(RegDat & 0x30) >> 4];
144 return;
145 }
146
147 case 0x11: {
148 // Window H Pos
149 VdpWindowRight = RegDat & 0x80;
150 VdpWindowHPos = (RegDat & 0x1f) << 4;
151 return;
152 }
153
154 case 012: {
155 // Window V Pos
156 VdpWindowDown = RegDat & 0x80;
157 VdpWindowVPos = (RegDat & 0x1f) << 3;
158 return;
159 }
160 }
161 }
162
VDPDataRead()163 static UINT16 VDPDataRead()
164 {
165 INT32 read = 0;
166
167 VdpCmdPart = 0;
168
169 switch (VdpCode & 0xf) {
170 case 0x00: {
171 read = VDP_VRAM_WORD(VdpAddress & ~1);
172 break;
173 }
174
175 case 0x04: {
176 read = VDP_VSRAM_WORD(VdpAddress & ~1);
177 break;
178 }
179
180 // default: {
181 // bprintf(PRINT_NORMAL, _T("Genesis VDP Data Read %x\n"), VdpCode);
182 // }
183 }
184
185 VdpAddress += GenesisVdpRegs[15];
186 return read;
187 }
188
VDPControlRead()189 static UINT16 VDPControlRead()
190 {
191 INT32 status = 0x3600;
192
193 VdpCmdPart = 0;
194
195 // If Vblank status |= 0x8
196 // if Hblank status |= 0x4
197
198 return status;
199 }
200
GenesisVDPRead(UINT32 offset)201 UINT16 GenesisVDPRead(UINT32 offset)
202 {
203 switch(offset) {
204 case 0x00:
205 case 0x01: {
206 return VDPDataRead();
207 }
208
209 case 0x02:
210 case 0x03: {
211 return VDPControlRead();
212 }
213 }
214
215 // bprintf(PRINT_NORMAL, _T("Genesis VDP Read %x\n"), offset);
216
217 return 0;
218 }
219
VDPControlWrite(UINT16 data)220 static void VDPControlWrite(UINT16 data)
221 {
222 if (!VdpCmdPart) {
223 if ((data & 0xc000) == 0x8000) {
224 VdpRegisterWrite(data, 0);
225 } else {
226 VdpCode = (VdpCode & 0x3c) | ((data >> 14) & 0x03);
227 VdpAddress = (VdpAddress & 0xc000) | (data & 0x3fff);
228 VdpCmdPart = 1;
229 }
230 } else {
231 VdpCode = (VdpCode & 0x03) | ((data >> 2) & 0x3c);
232 VdpAddress = (VdpAddress & 0x3fff) | ((data << 14) & 0xc000);
233 VdpCmdPart = 0;
234 // DMA Stuff here
235 }
236 }
237
pal3bit(UINT8 bits)238 inline static UINT8 pal3bit(UINT8 bits)
239 {
240 bits &= 7;
241 return (bits << 5) | (bits << 2) | (bits >> 1);
242 }
243
GenesisPaletteRecalc()244 void GenesisPaletteRecalc()
245 {
246 for (INT32 i = 0; i < CRAM_SIZE; i++) {
247 UINT16 data = GenesisPaletteRaw[i];
248
249 GenesisPalette[i + GenesisPaletteBase] = BurnHighCol(pal3bit(data >> 1), pal3bit(data >> 5), pal3bit(data >> 9), 0);
250 }
251 }
252
VDPDataWrite(UINT16 data)253 static void VDPDataWrite(UINT16 data)
254 {
255 VdpCmdPart = 0;
256
257 // DMA Stuff here
258
259 switch (VdpCode & 0xf) {
260 case 0x01: {
261 if (VdpAddress & 1) data = ((data & 0xff) << 8) | ((data >> 8) & 0xff);
262 VDP_VRAM_BYTE(VdpAddress & ~1) = data >> 8;
263 VDP_VRAM_BYTE(VdpAddress | 1 ) = data;
264 break;
265 }
266
267 case 0x03: {
268 INT32 offset = (VdpAddress >> 1) % CRAM_SIZE;
269 //palette_set_color(Machine, offset + genesis_palette_base, pal3bit(data >> 1), pal3bit(data >> 5), pal3bit(data >> 9));
270 //System16Palette[offset + 0x1800 /*GenesisPaletteBase*/] = BurnHighCol(pal3bit(data >> 1), pal3bit(data >> 5), pal3bit(data >> 9), 0);
271 GenesisPalette[offset + GenesisPaletteBase] = BurnHighCol(pal3bit(data >> 1), pal3bit(data >> 5), pal3bit(data >> 9), 0);
272 GenesisPaletteRaw[offset] = data;
273 break;
274 }
275
276 case 0x05: {
277 if (VdpAddress & 1) data = ((data & 0xff) << 8) | ((data >> 8) & 0xff);
278 VDP_VSRAM_BYTE(VdpAddress & ~1) = data >> 8;
279 VDP_VSRAM_BYTE(VdpAddress | 1) = data;
280 break;
281 }
282
283 // default: {
284 // bprintf(PRINT_NORMAL, _T("Genesis VDP Data Write %x\n"), VdpCode);
285 // }
286 }
287
288 VdpAddress += GenesisVdpRegs[15];
289 }
290
GenesisVDPWrite(UINT32 offset,UINT16 data)291 void GenesisVDPWrite(UINT32 offset, UINT16 data)
292 {
293 switch (offset) {
294 case 0x00:
295 case 0x01: {
296 VDPDataWrite(data);
297 return;
298 }
299
300 case 0x02:
301 case 0x03: {
302 VDPControlWrite(data);
303 return;
304 }
305 }
306
307 // bprintf(PRINT_NORMAL, _T("Genesis VDP Write %x\n"), data);
308 }
309
StartGenesisVDP(INT32 ScreenNum,UINT32 * pal)310 INT32 StartGenesisVDP(INT32 ScreenNum, UINT32* pal)
311 {
312 INT32 i;
313
314 GenesisScreenNumber = ScreenNum;
315
316 GenesisPalette = pal;
317
318 VdpVRAM = (UINT8*)BurnMalloc(VRAM_SIZE);
319 VdpVSRAM = (UINT8*)BurnMalloc(VSRAM_SIZE);
320 VdpTransLookup = (UINT16*)BurnMalloc(0x1000 * sizeof(UINT16));
321 GenesisPaletteRaw = (UINT16*)BurnMalloc(CRAM_SIZE * sizeof(UINT16));
322
323 // Init the transparency lookup table
324 for (i = 0; i < 0x1000; i++) {
325 INT32 OriginalColour = i & 0x7ff;
326 INT32 HalfBright = i & 0x800;
327
328 if (OriginalColour & 0x100)
329 VdpTransLookup[i] = OriginalColour;
330 else if (HalfBright)
331 VdpTransLookup[i] = OriginalColour | 0x800;
332 else
333 VdpTransLookup[i] = OriginalColour | 0x1000;
334 }
335
336 // Reset Palettes
337 GenesisPaletteBase = 0;
338 GenesisBgPalLookup[0] = GenesisSpPalLookup[0] = 0x00;
339 GenesisBgPalLookup[1] = GenesisSpPalLookup[1] = 0x10;
340 GenesisBgPalLookup[2] = GenesisSpPalLookup[2] = 0x20;
341 GenesisBgPalLookup[3] = GenesisSpPalLookup[3] = 0x30;
342
343 // Reset VDP
344 GenesisVDPReset();
345
346 return 0;
347 }
348
GenesisVDPReset()349 void GenesisVDPReset()
350 {
351 static const UINT8 VdpInit[24] =
352 {
353 0x04, 0x44, 0x30, 0x3C, 0x07, 0x6C, 0x00, 0x00,
354 0x00, 0x00, 0xFF, 0x00, 0x01, 0x37, 0x00, 0x02,
355 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x80,
356 };
357
358 memset(VdpVRAM, 0, VRAM_SIZE);
359 memset(VdpVSRAM, 0, VSRAM_SIZE);
360 memset(GenesisPaletteRaw, 0, CRAM_SIZE * sizeof(UINT16));
361
362 // Reset VDP
363 for (INT32 i = 0; i < 24; i++) {
364 VdpRegisterWrite(0x8000 | (i << 8) | VdpInit[i], 1);
365 }
366
367 VdpCmdPart = 0;
368 VdpCode = 0;
369 VdpAddress = 0;
370 }
371
GenesisVDPExit()372 void GenesisVDPExit()
373 {
374 BurnFree(VdpVRAM);
375 BurnFree(VdpVSRAM);
376 BurnFree(VdpTransLookup);
377 BurnFree(GenesisPaletteRaw);
378
379 memset(GenesisVdpRegs, 0, sizeof(GenesisVdpRegs));
380 memset(GenesisBgPalLookup, 0, sizeof(GenesisBgPalLookup));
381 memset(GenesisSpPalLookup, 0, sizeof(GenesisSpPalLookup));
382
383 GenesisPalette = NULL;
384
385 GenesisScreenNumber = 0;
386 GenesisPaletteBase = 0;
387 VdpBgColour = 0;
388 VdpScrollABase = 0;
389 VdpScrollBBase = 0;
390 VdpWindowBase = 0;
391 VdpSpriteBase = 0;
392 VdpHScrollMask = 0;
393 VdpHScrollSize = 0;
394 VdpHScrollBase = 0;
395 VdpVScrollMode = 0;
396 VdpWindowWidth = 0;
397 VdpScrollWidth = 0;
398 VdpScrollHeight = 0;
399 VdpWindowRight = 0;
400 VdpWindowDown = 0;
401 VdpWindowHPos = 0;
402 VdpWindowVPos = 0;
403 VdpCmdPart = 0;
404 VdpCode = 0;
405 VdpAddress = 0;
406 }
407
GenesisVDPScan()408 void GenesisVDPScan()
409 {
410 ScanVar(VdpVRAM, VRAM_SIZE, "GenVDP VRAM");
411 ScanVar(VdpVSRAM, VSRAM_SIZE, "GenVDP VSRAM");
412 ScanVar(GenesisPaletteRaw, CRAM_SIZE * sizeof(UINT16), "GenVDPPalette");
413
414 SCAN_VAR(GenesisVdpRegs);
415
416 SCAN_VAR(VdpBgColour);
417 SCAN_VAR(VdpScrollABase);
418 SCAN_VAR(VdpScrollBBase);
419 SCAN_VAR(VdpWindowBase);
420 SCAN_VAR(VdpSpriteBase);
421 SCAN_VAR(VdpHScrollMask);
422 SCAN_VAR(VdpHScrollSize);
423 SCAN_VAR(VdpHScrollBase);
424 SCAN_VAR(VdpVScrollMode);
425 SCAN_VAR(VdpWindowWidth);
426 SCAN_VAR(VdpScrollWidth);
427 SCAN_VAR(VdpScrollHeight);
428 SCAN_VAR(VdpWindowRight);
429 SCAN_VAR(VdpWindowDown);
430 SCAN_VAR(VdpWindowHPos);
431 SCAN_VAR(VdpWindowVPos);
432 SCAN_VAR(VdpCmdPart);
433 SCAN_VAR(VdpCode);
434 SCAN_VAR(VdpAddress);
435 }
436
vdp_gethscroll(INT32 plane,INT32 line)437 inline INT32 vdp_gethscroll(INT32 plane, INT32 line)
438 {
439 line &= VdpHScrollMask;
440 return 0x400 - (VDP_VRAM_WORD(VdpHScrollBase + (4 * line) + plane) & 0x3ff);
441 }
442
443
444 /* Note: We expect plane = 0 for Scroll A, plane = 2 for Scroll B
445 A Column is 8 Pixels Wide */
vdp_getvscroll(INT32 plane,INT32 column)446 static INT32 vdp_getvscroll(INT32 plane, INT32 column)
447 {
448 UINT32 vsramoffset;
449
450 switch (VdpVScrollMode)
451 {
452 case 0x00: /* Overall Scroll */
453 return VDP_VSRAM_WORD(plane) & 0x7ff;
454
455 case 0x01: /* Column Scroll */
456 if (column == 40) column = 39; /* Fix Minor Innacuracy Only affects PotoPoto */
457 vsramoffset = (4 * (column >> 1)) + plane;
458 return VDP_VSRAM_WORD(vsramoffset) & 0x7ff;
459 }
460 return 0;
461 }
462
get_scroll_tiles(UINT32 line,INT32 scrollnum,UINT32 scrollbase,UINT32 * tiles,INT32 * offset)463 static void get_scroll_tiles(UINT32 line, INT32 scrollnum, UINT32 scrollbase, UINT32 *tiles, INT32 *offset)
464 {
465 INT32 linehscroll = vdp_gethscroll(scrollnum, line);
466 INT32 column;
467
468 /* adjust for partial tiles and then pre-divide hscroll to get the tile offset */
469 *offset = -(linehscroll % 8);
470 linehscroll /= 8;
471
472 /* loop over columns */
473 for (column = 0; column < 41; column++)
474 {
475 INT32 columnvscroll = vdp_getvscroll(scrollnum, (column - (linehscroll & 1)) & 0x3f) + line;
476
477 /* determine the base of the tilemap row */
478 INT32 temp = ((columnvscroll / 8) & (VdpScrollHeight - 1)) * VdpScrollWidth;
479 INT32 tilebase = scrollbase + 2 * temp;
480
481 /* offset into the tilemap based on the column */
482 temp = (linehscroll + column) & (VdpScrollWidth - 1);
483 tilebase += 2 * temp;
484
485 /* get the tile info */
486 *tiles++ = ((columnvscroll % 8) << 16) | VDP_VRAM_WORD(tilebase);
487 }
488 }
489
get_window_tiles(UINT32 line,UINT32 scrollbase,UINT32 * tiles)490 static void get_window_tiles(UINT32 line, UINT32 scrollbase, UINT32 *tiles)
491 {
492 INT32 column;
493
494 /* loop over columns */
495 for (column = 0; column < 40; column++)
496 {
497 /* determine the base of the tilemap row */
498 INT32 temp = (line / 8) * VdpWindowWidth + column;
499 INT32 tilebase = scrollbase + 2 * temp;
500
501 /* get the tile info */
502 *tiles++ = ((line % 8) << 16) | VDP_VRAM_WORD(tilebase);
503 }
504 }
505
drawline_tiles(UINT32 * tiles,UINT16 * bmap,UINT32 pri,INT32 offset,INT32 lclip,INT32 rclip)506 static void drawline_tiles(UINT32 *tiles, UINT16 *bmap, UINT32 pri, INT32 offset, INT32 lclip, INT32 rclip)
507 {
508 /* adjust for the 8-pixel slop */
509 bmap += offset;
510 if (lclip > rclip)
511 return;
512
513 /* loop over columns */
514 for ( ; offset < 320; offset += 8, bmap += 8)
515 {
516 UINT32 tile = *tiles++;
517
518 /* if the tile is the correct priority, draw it */
519 if (((tile >> 15) & 1) == pri && offset < 320)
520 {
521 INT32 colbase = GenesisBgPalLookup[(tile & 0x6000) >> 13];
522 UINT32 *tp = (UINT32 *)&VDP_VRAM_BYTE((tile & 0x7ff) * 32);
523 UINT32 mytile;
524 INT32 col;
525
526 /* vertical flipping */
527 if (!(tile & 0x1000))
528 mytile = BURN_ENDIAN_SWAP_INT32(tp[tile >> 16]);
529 else
530 mytile = BURN_ENDIAN_SWAP_INT32(tp[(tile >> 16) ^ 7]);
531
532 /* skip if all-transparent */
533 if (!mytile)
534 continue;
535
536 /* non-clipped */
537 if (offset >= lclip && offset <= rclip - 7)
538 {
539 /* non-flipped */
540 if (!(tile & 0x0800))
541 {
542 col = EXTRACT_PIXEL(mytile, 0); if (col) bmap[0] = colbase + col;
543 col = EXTRACT_PIXEL(mytile, 1); if (col) bmap[1] = colbase + col;
544 col = EXTRACT_PIXEL(mytile, 2); if (col) bmap[2] = colbase + col;
545 col = EXTRACT_PIXEL(mytile, 3); if (col) bmap[3] = colbase + col;
546 col = EXTRACT_PIXEL(mytile, 4); if (col) bmap[4] = colbase + col;
547 col = EXTRACT_PIXEL(mytile, 5); if (col) bmap[5] = colbase + col;
548 col = EXTRACT_PIXEL(mytile, 6); if (col) bmap[6] = colbase + col;
549 col = EXTRACT_PIXEL(mytile, 7); if (col) bmap[7] = colbase + col;
550 }
551
552 /* horizontal flip */
553 else
554 {
555 col = EXTRACT_PIXEL(mytile, 7); if (col) bmap[0] = colbase + col;
556 col = EXTRACT_PIXEL(mytile, 6); if (col) bmap[1] = colbase + col;
557 col = EXTRACT_PIXEL(mytile, 5); if (col) bmap[2] = colbase + col;
558 col = EXTRACT_PIXEL(mytile, 4); if (col) bmap[3] = colbase + col;
559 col = EXTRACT_PIXEL(mytile, 3); if (col) bmap[4] = colbase + col;
560 col = EXTRACT_PIXEL(mytile, 2); if (col) bmap[5] = colbase + col;
561 col = EXTRACT_PIXEL(mytile, 1); if (col) bmap[6] = colbase + col;
562 col = EXTRACT_PIXEL(mytile, 0); if (col) bmap[7] = colbase + col;
563 }
564 }
565
566 /* clipped */
567 else if (offset >= lclip - 8 && offset <= rclip)
568 {
569 /* non-flipped */
570 if (!(tile & 0x0800))
571 {
572 col = EXTRACT_PIXEL(mytile, 0); if (col && (offset + 0) >= lclip && (offset + 0) <= rclip) bmap[0] = colbase + col;
573 col = EXTRACT_PIXEL(mytile, 1); if (col && (offset + 1) >= lclip && (offset + 1) <= rclip) bmap[1] = colbase + col;
574 col = EXTRACT_PIXEL(mytile, 2); if (col && (offset + 2) >= lclip && (offset + 2) <= rclip) bmap[2] = colbase + col;
575 col = EXTRACT_PIXEL(mytile, 3); if (col && (offset + 3) >= lclip && (offset + 3) <= rclip) bmap[3] = colbase + col;
576 col = EXTRACT_PIXEL(mytile, 4); if (col && (offset + 4) >= lclip && (offset + 4) <= rclip) bmap[4] = colbase + col;
577 col = EXTRACT_PIXEL(mytile, 5); if (col && (offset + 5) >= lclip && (offset + 5) <= rclip) bmap[5] = colbase + col;
578 col = EXTRACT_PIXEL(mytile, 6); if (col && (offset + 6) >= lclip && (offset + 6) <= rclip) bmap[6] = colbase + col;
579 col = EXTRACT_PIXEL(mytile, 7); if (col && (offset + 7) >= lclip && (offset + 7) <= rclip) bmap[7] = colbase + col;
580 }
581
582 /* horizontal flip */
583 else
584 {
585 col = EXTRACT_PIXEL(mytile, 7); if (col && (offset + 0) >= lclip && (offset + 0) <= rclip) bmap[0] = colbase + col;
586 col = EXTRACT_PIXEL(mytile, 6); if (col && (offset + 1) >= lclip && (offset + 1) <= rclip) bmap[1] = colbase + col;
587 col = EXTRACT_PIXEL(mytile, 5); if (col && (offset + 2) >= lclip && (offset + 2) <= rclip) bmap[2] = colbase + col;
588 col = EXTRACT_PIXEL(mytile, 4); if (col && (offset + 3) >= lclip && (offset + 3) <= rclip) bmap[3] = colbase + col;
589 col = EXTRACT_PIXEL(mytile, 3); if (col && (offset + 4) >= lclip && (offset + 4) <= rclip) bmap[4] = colbase + col;
590 col = EXTRACT_PIXEL(mytile, 2); if (col && (offset + 5) >= lclip && (offset + 5) <= rclip) bmap[5] = colbase + col;
591 col = EXTRACT_PIXEL(mytile, 1); if (col && (offset + 6) >= lclip && (offset + 6) <= rclip) bmap[6] = colbase + col;
592 col = EXTRACT_PIXEL(mytile, 0); if (col && (offset + 7) >= lclip && (offset + 7) <= rclip) bmap[7] = colbase + col;
593 }
594 }
595 }
596 }
597 }
598
draw8pixs(UINT16 * bmap,INT32 patno,INT32,INT32 colbase,INT32 patline)599 static void draw8pixs(UINT16 *bmap, INT32 patno, INT32 /*priority*/, INT32 colbase, INT32 patline)
600 {
601 UINT32 tile = BURN_ENDIAN_SWAP_INT32(*(UINT32 *)&VDP_VRAM_BYTE(patno * 32 + 4 * patline));
602 INT32 col;
603
604 /* skip if all-transparent */
605 if (!tile)
606 return;
607
608 /* non-transparent */
609 if ((colbase & 0x30) != 0x30 || !(GenesisVdpRegs[12] & 0x08))
610 {
611 col = EXTRACT_PIXEL(tile, 0); if (col) bmap[0] = colbase + col;
612 col = EXTRACT_PIXEL(tile, 1); if (col) bmap[1] = colbase + col;
613 col = EXTRACT_PIXEL(tile, 2); if (col) bmap[2] = colbase + col;
614 col = EXTRACT_PIXEL(tile, 3); if (col) bmap[3] = colbase + col;
615 col = EXTRACT_PIXEL(tile, 4); if (col) bmap[4] = colbase + col;
616 col = EXTRACT_PIXEL(tile, 5); if (col) bmap[5] = colbase + col;
617 col = EXTRACT_PIXEL(tile, 6); if (col) bmap[6] = colbase + col;
618 col = EXTRACT_PIXEL(tile, 7); if (col) bmap[7] = colbase + col;
619 }
620
621 /* transparent */
622 else
623 {
624 col = EXTRACT_PIXEL(tile, 0);
625 if (col)
626 {
627 if (col < 0x0e) bmap[0] = colbase + col;
628 else bmap[0] = VdpTransLookup[((col & 1) << 11) | (bmap[0] & 0x7ff)];
629 }
630 col = EXTRACT_PIXEL(tile, 1);
631 if (col)
632 {
633 if (col < 0x0e) bmap[1] = colbase + col;
634 else bmap[1] = VdpTransLookup[((col & 1) << 11) | (bmap[1] & 0x7ff)];
635 }
636 col = EXTRACT_PIXEL(tile, 2);
637 if (col)
638 {
639 if (col < 0x0e) bmap[2] = colbase + col;
640 else bmap[2] = VdpTransLookup[((col & 1) << 11) | (bmap[2] & 0x7ff)];
641 }
642 col = EXTRACT_PIXEL(tile, 3);
643 if (col)
644 {
645 if (col < 0x0e) bmap[3] = colbase + col;
646 else bmap[3] = VdpTransLookup[((col & 1) << 11) | (bmap[3] & 0x7ff)];
647 }
648 col = EXTRACT_PIXEL(tile, 4);
649 if (col)
650 {
651 if (col < 0x0e) bmap[4] = colbase + col;
652 else bmap[4] = VdpTransLookup[((col & 1) << 11) | (bmap[4] & 0x7ff)];
653 }
654 col = EXTRACT_PIXEL(tile, 5);
655 if (col)
656 {
657 if (col < 0x0e) bmap[5] = colbase + col;
658 else bmap[5] = VdpTransLookup[((col & 1) << 11) | (bmap[5] & 0x7ff)];
659 }
660 col = EXTRACT_PIXEL(tile, 6);
661 if (col)
662 {
663 if (col < 0x0e) bmap[6] = colbase + col;
664 else bmap[6] = VdpTransLookup[((col & 1) << 11) | (bmap[6] & 0x7ff)];
665 }
666 col = EXTRACT_PIXEL(tile, 7);
667 if (col)
668 {
669 if (col < 0x0e) bmap[7] = colbase + col;
670 else bmap[7] = VdpTransLookup[((col & 1) << 11) | (bmap[7] & 0x7ff)];
671 }
672 }
673 }
674
675
676 /* draw a horizontally-flipped section of a sprite */
draw8pixs_hflip(UINT16 * bmap,INT32 patno,INT32,INT32 colbase,INT32 patline)677 static void draw8pixs_hflip(UINT16 *bmap, INT32 patno, INT32 /*priority*/, INT32 colbase, INT32 patline)
678 {
679 UINT32 tile = BURN_ENDIAN_SWAP_INT32(*(UINT32 *)&VDP_VRAM_BYTE(patno * 32 + 4 * patline));
680 INT32 col;
681
682 /* skip if all-transparent */
683 if (!tile)
684 return;
685
686 /* non-transparent */
687 if ((colbase & 0x30) != 0x30 || !(GenesisVdpRegs[12] & 0x08))
688 {
689 col = EXTRACT_PIXEL(tile, 7); if (col) bmap[0] = colbase + col;
690 col = EXTRACT_PIXEL(tile, 6); if (col) bmap[1] = colbase + col;
691 col = EXTRACT_PIXEL(tile, 5); if (col) bmap[2] = colbase + col;
692 col = EXTRACT_PIXEL(tile, 4); if (col) bmap[3] = colbase + col;
693 col = EXTRACT_PIXEL(tile, 3); if (col) bmap[4] = colbase + col;
694 col = EXTRACT_PIXEL(tile, 2); if (col) bmap[5] = colbase + col;
695 col = EXTRACT_PIXEL(tile, 1); if (col) bmap[6] = colbase + col;
696 col = EXTRACT_PIXEL(tile, 0); if (col) bmap[7] = colbase + col;
697 }
698
699 /* transparent */
700 else
701 {
702 col = EXTRACT_PIXEL(tile, 7);
703 if (col)
704 {
705 if (col < 0x0e) bmap[0] = colbase + col;
706 else bmap[0] = VdpTransLookup[((col & 1) << 11) | (bmap[0] & 0x7ff)];
707 }
708 col = EXTRACT_PIXEL(tile, 6);
709 if (col)
710 {
711 if (col < 0x0e) bmap[1] = colbase + col;
712 else bmap[1] = VdpTransLookup[((col & 1) << 11) | (bmap[1] & 0x7ff)];
713 }
714 col = EXTRACT_PIXEL(tile, 5);
715 if (col)
716 {
717 if (col < 0x0e) bmap[2] = colbase + col;
718 else bmap[2] = VdpTransLookup[((col & 1) << 11) | (bmap[2] & 0x7ff)];
719 }
720 col = EXTRACT_PIXEL(tile, 4);
721 if (col)
722 {
723 if (col < 0x0e) bmap[3] = colbase + col;
724 else bmap[3] = VdpTransLookup[((col & 1) << 11) | (bmap[3] & 0x7ff)];
725 }
726 col = EXTRACT_PIXEL(tile, 3);
727 if (col)
728 {
729 if (col < 0x0e) bmap[4] = colbase + col;
730 else bmap[4] = VdpTransLookup[((col & 1) << 11) | (bmap[4] & 0x7ff)];
731 }
732 col = EXTRACT_PIXEL(tile, 2);
733 if (col)
734 {
735 if (col < 0x0e) bmap[5] = colbase + col;
736 else bmap[5] = VdpTransLookup[((col & 1) << 11) | (bmap[5] & 0x7ff)];
737 }
738 col = EXTRACT_PIXEL(tile, 1);
739 if (col)
740 {
741 if (col < 0x0e) bmap[6] = colbase + col;
742 else bmap[6] = VdpTransLookup[((col & 1) << 11) | (bmap[6] & 0x7ff)];
743 }
744 col = EXTRACT_PIXEL(tile, 0);
745 if (col)
746 {
747 if (col < 0x0e) bmap[7] = colbase + col;
748 else bmap[7] = VdpTransLookup[((col & 1) << 11) | (bmap[7] & 0x7ff)];
749 }
750 }
751 }
752
drawline_sprite(INT32 line,UINT16 * bmap,INT32 priority,UINT8 * spritebase)753 static void drawline_sprite(INT32 line, UINT16 *bmap, INT32 priority, UINT8 *spritebase)
754 {
755 INT32 spriteypos = (((spritebase[0] & 0x01) << 8) | spritebase[1]) - 0x80;
756 INT32 spritexpos = (((spritebase[6] & 0x01) << 8) | spritebase[7]) - 0x80;
757 INT32 spriteheight = ((spritebase[2] & 0x03) + 1) * 8;
758 INT32 spritewidth = (((spritebase[2] & 0x0c) >> 2) + 1) * 8;
759 INT32 spriteattr, patno, patflip, patline, colbase, x;
760
761 /* skip if out of range */
762 if (line < spriteypos || line >= spriteypos + spriteheight)
763 return;
764 if (spritexpos + spritewidth < 0 || spritexpos >= 320)
765 return;
766
767 /* extract the remaining data */
768 spriteattr = (spritebase[4] << 8) | spritebase[5];
769 patno = spriteattr & 0x07FF;
770 patflip = (spriteattr & 0x1800) >> 11;
771 patline = line - spriteypos;
772
773 /* determine the color base */
774 colbase = GenesisSpPalLookup[(spriteattr & 0x6000) >> 13];
775
776 /* adjust for the X position */
777 spritewidth >>= 3;
778 spriteheight >>= 3;
779
780 /* switch off the flip mode */
781 bmap += spritexpos;
782 switch (patflip)
783 {
784 case 0x00: /* No Flip */
785 for (x = 0; x < spritewidth; x++, bmap += 8)
786 {
787 if (spritexpos >= -7 && spritexpos < 320)
788 draw8pixs(bmap, patno, priority, colbase, patline);
789 spritexpos += 8;
790 patno += spriteheight;
791 }
792 break;
793
794 case 0x01: /* Horizontal Flip */
795 patno += spriteheight * (spritewidth - 1);
796 for (x = 0; x < spritewidth; x++, bmap += 8)
797 {
798 if (spritexpos >= -7 && spritexpos < 320)
799 draw8pixs_hflip(bmap, patno, priority, colbase, patline);
800 spritexpos += 8;
801 patno -= spriteheight;
802 }
803 break;
804
805 case 0x02: /* Vertical Flip */
806 patline = 8 * spriteheight - patline - 1;
807 for (x = 0; x < spritewidth; x++, bmap += 8)
808 {
809 if (spritexpos >= -7 && spritexpos < 320)
810 draw8pixs(bmap, patno, priority, colbase, patline);
811 spritexpos += 8;
812 patno += spriteheight;
813 }
814 break;
815
816 case 0x03: /* Both Flip */
817 patno += spriteheight * (spritewidth - 1);
818 patline = 8 * spriteheight - patline - 1;
819 for (x = 0; x < spritewidth; x++, bmap += 8)
820 {
821 if (spritexpos >= -7 && spritexpos < 320)
822 draw8pixs_hflip(bmap, patno, priority, colbase, patline);
823 spritexpos += 8;
824 patno -= spriteheight;
825 }
826 break;
827 }
828 }
829
vdp_drawline(UINT16 * bitmap,UINT32 line,INT32 bgfill)830 void vdp_drawline(UINT16 *bitmap, UINT32 line, INT32 bgfill)
831 {
832 INT32 lowsprites, highsprites, link;
833 UINT32 scrolla_tiles[41], scrollb_tiles[41], window_tiles[41];
834 INT32 scrolla_offset, scrollb_offset;
835 UINT8 *lowlist[81], *highlist[81];
836 INT32 bgcolor = bgfill ? bgfill : GenesisBgPalLookup[0];
837 INT32 window_lclip, window_rclip;
838 INT32 scrolla_lclip, scrolla_rclip;
839 INT32 column, sprite;
840
841 /* clear to the background color */
842 for (column = 0; column < 320; column++)
843 bitmap[column] = bgcolor;
844
845 /* if display is disabled, stop */
846 if (!(GenesisVdpRegs[1] & 0x40)) {
847 return;
848 }
849
850 /* Sprites need to be Drawn in Reverse order .. may as well sort them here */
851 link = lowsprites = highsprites = 0;
852 for (sprite = 0; sprite < 80; sprite++)
853 {
854 UINT8 *spritebase = &VDP_VRAM_BYTE(VdpSpriteBase + 8 * link);
855
856 /* sort into high/low priorities */
857 if (spritebase[4] & 0x0080)
858 highlist[++highsprites] = spritebase;
859 else
860 lowlist[++lowsprites] = spritebase;
861
862 /* get the link; if 0, stop processing */
863 link = spritebase[3] & 0x7F;
864 if (!link)
865 break;
866 }
867
868 /* get tiles for the B scroll layer */
869 get_scroll_tiles(line, 2, VdpScrollBBase, scrollb_tiles, &scrollb_offset);
870
871 /* get tiles for the A scroll layer */
872 get_scroll_tiles(line, 0, VdpScrollABase, scrolla_tiles, &scrolla_offset);
873
874 /* get tiles for the window layer */
875 get_window_tiles(line, VdpWindowBase, window_tiles);
876
877 /* compute the windowing for this line */
878 if ((VdpWindowDown && line >= VdpWindowVPos) || (!VdpWindowDown && line < VdpWindowVPos))
879 window_lclip = 0, window_rclip = 320 - 1;
880 else if (VdpWindowRight)
881 window_lclip = VdpWindowHPos, window_rclip = 320 - 1;
882 else
883 window_lclip = 0, window_rclip = VdpWindowHPos - 1;
884
885 /* compute the clipping of the scroll A layer */
886 if (window_lclip == 0)
887 {
888 scrolla_lclip = window_rclip + 1;
889 scrolla_rclip = 320 - 1;
890 }
891 else
892 {
893 scrolla_lclip = 0;
894 scrolla_rclip = window_lclip - 1;
895 }
896
897 /* Scroll B Low */
898 drawline_tiles(scrollb_tiles, bitmap, 0, scrollb_offset, 0, 320 - 1);
899
900 /* Scroll A Low */
901 drawline_tiles(scrolla_tiles, bitmap, 0, scrolla_offset, scrolla_lclip, scrolla_rclip);
902
903 /* Window Low */
904 drawline_tiles(window_tiles, bitmap, 0, 0, window_lclip, window_rclip);
905
906 /* Sprites Low */
907 for (sprite = lowsprites; sprite > 0; sprite--)
908 drawline_sprite(line, bitmap, 0, lowlist[sprite]);
909
910 /* Scroll B High */
911 drawline_tiles(scrollb_tiles, bitmap, 1, scrollb_offset, 0, 320 - 1);
912
913 /* Scroll A High */
914 drawline_tiles(scrolla_tiles, bitmap, 1, scrolla_offset, scrolla_lclip, scrolla_rclip);
915
916 /* Window High */
917 drawline_tiles(window_tiles, bitmap, 1, 0, window_lclip, window_rclip);
918
919 /* Sprites High */
920 for (sprite = highsprites; sprite > 0; sprite--)
921 drawline_sprite(line, bitmap, 1, highlist[sprite]);
922 }
923