1 /***************************************************************************************
2 * Genesis Plus
3 * Video Display Processor (pixel output rendering)
4 *
5 * Support for all TMS99xx modes, Mode 4 & Mode 5 rendering
6 *
7 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
8 * Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
9 *
10 * Redistribution and use of this code or any derivative works are permitted
11 * provided that the following conditions are met:
12 *
13 * - Redistributions may not be sold, nor may they be used in a commercial
14 * product or activity.
15 *
16 * - Redistributions that are modified from the original source must include the
17 * complete source code, including the source code for all components used by a
18 * binary built from the modified sources. However, as a special exception, the
19 * source code distributed need not include anything that is normally distributed
20 * (in either source or binary form) with the major components (compiler, kernel,
21 * and so on) of the operating system on which the executable runs, unless that
22 * component itself accompanies the executable.
23 *
24 * - Redistributions must reproduce the above copyright notice, this list of
25 * conditions and the following disclaimer in the documentation and/or other
26 * materials provided with the distribution.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 ****************************************************************************************/
41
42 #include "shared.h"
43 #include "md_ntsc.h"
44 #include "sms_ntsc.h"
45
46 extern int8 reset_do_not_clear_buffers;
47
48 #ifndef HAVE_NO_SPRITE_LIMIT
49 #define MAX_SPRITES_PER_LINE 20
50 #define TMS_MAX_SPRITES_PER_LINE 4
51 #define MODE4_MAX_SPRITES_PER_LINE 8
52 #define MODE5_MAX_SPRITES_PER_LINE (bitmap.viewport.w >> 4)
53 #define MODE5_MAX_SPRITE_PIXELS max_sprite_pixels
54 #endif
55
56 /*** NTSC Filters ***/
57 extern md_ntsc_t *md_ntsc;
58 extern sms_ntsc_t *sms_ntsc;
59
60
61 /* Output pixels type*/
62 #if defined(USE_8BPP_RENDERING)
63 #define PIXEL_OUT_T uint8
64 #elif defined(USE_32BPP_RENDERING)
65 #define PIXEL_OUT_T uint32
66 #else
67 #define PIXEL_OUT_T uint16
68 #endif
69
70
71 /* Pixel priority look-up tables information */
72 #define LUT_MAX (6)
73 #define LUT_SIZE (0x10000)
74
75
76 #ifdef ALIGN_LONG
77 #undef READ_LONG
78 #undef WRITE_LONG
79
READ_LONG(void * address)80 INLINE uint32 READ_LONG(void *address)
81 {
82 if ((uint32)address & 3)
83 {
84 #ifdef LSB_FIRST /* little endian version */
85 return ( *((uint8 *)address) +
86 (*((uint8 *)address+1) << 8) +
87 (*((uint8 *)address+2) << 16) +
88 (*((uint8 *)address+3) << 24) );
89 #else /* big endian version */
90 return ( *((uint8 *)address+3) +
91 (*((uint8 *)address+2) << 8) +
92 (*((uint8 *)address+1) << 16) +
93 (*((uint8 *)address) << 24) );
94 #endif /* LSB_FIRST */
95 }
96 else return *(uint32 *)address;
97 }
98
WRITE_LONG(void * address,uint32 data)99 INLINE void WRITE_LONG(void *address, uint32 data)
100 {
101 if ((uint32)address & 3)
102 {
103 #ifdef LSB_FIRST
104 *((uint8 *)address) = data;
105 *((uint8 *)address+1) = (data >> 8);
106 *((uint8 *)address+2) = (data >> 16);
107 *((uint8 *)address+3) = (data >> 24);
108 #else
109 *((uint8 *)address+3) = data;
110 *((uint8 *)address+2) = (data >> 8);
111 *((uint8 *)address+1) = (data >> 16);
112 *((uint8 *)address) = (data >> 24);
113 #endif /* LSB_FIRST */
114 return;
115 }
116 else *(uint32 *)address = data;
117 }
118
119 #endif /* ALIGN_LONG */
120
121
122 /* Draw 2-cell column (8-pixels high) */
123 /*
124 Pattern cache base address: VHN NNNNNNNN NNYYYxxx
125 with :
126 x = Pattern Pixel (0-7)
127 Y = Pattern Row (0-7)
128 N = Pattern Number (0-2047) from pattern attribute
129 H = Horizontal Flip bit from pattern attribute
130 V = Vertical Flip bit from pattern attribute
131 */
132 #define GET_LSB_TILE(ATTR, LINE) \
133 atex = atex_table[(ATTR >> 13) & 7]; \
134 src = (uint32 *)&bg_pattern_cache[(ATTR & 0x00001FFF) << 6 | (LINE)];
135 #define GET_MSB_TILE(ATTR, LINE) \
136 atex = atex_table[(ATTR >> 29) & 7]; \
137 src = (uint32 *)&bg_pattern_cache[(ATTR & 0x1FFF0000) >> 10 | (LINE)];
138
139 /* Draw 2-cell column (16 pixels high) */
140 /*
141 Pattern cache base address: VHN NNNNNNNN NYYYYxxx
142 with :
143 x = Pattern Pixel (0-7)
144 Y = Pattern Row (0-15)
145 N = Pattern Number (0-1023)
146 H = Horizontal Flip bit
147 V = Vertical Flip bit
148 */
149 #define GET_LSB_TILE_IM2(ATTR, LINE) \
150 atex = atex_table[(ATTR >> 13) & 7]; \
151 src = (uint32 *)&bg_pattern_cache[((ATTR & 0x000003FF) << 7 | (ATTR & 0x00001800) << 6 | (LINE)) ^ ((ATTR & 0x00001000) >> 6)];
152 #define GET_MSB_TILE_IM2(ATTR, LINE) \
153 atex = atex_table[(ATTR >> 29) & 7]; \
154 src = (uint32 *)&bg_pattern_cache[((ATTR & 0x03FF0000) >> 9 | (ATTR & 0x18000000) >> 10 | (LINE)) ^ ((ATTR & 0x10000000) >> 22)];
155
156 /*
157 One column = 2 tiles
158 Two pattern attributes are written in VRAM as two consecutives 16-bit words:
159
160 P = priority bit
161 C = color palette (2 bits)
162 V = Vertical Flip bit
163 H = Horizontal Flip bit
164 N = Pattern Number (11 bits)
165
166 (MSB) PCCVHNNN NNNNNNNN (LSB) (MSB) PCCVHNNN NNNNNNNN (LSB)
167 PATTERN1 PATTERN2
168
169 Both pattern attributes are read from VRAM as one 32-bit word:
170
171 LIT_ENDIAN: (MSB) PCCVHNNN NNNNNNNN PCCVHNNN NNNNNNNN (LSB)
172 PATTERN2 PATTERN1
173
174 BIG_ENDIAN: (MSB) PCCVHNNN NNNNNNNN PCCVHNNN NNNNNNNN (LSB)
175 PATTERN1 PATTERN2
176
177
178 In line buffers, one pixel = one byte: (msb) 0Pppcccc (lsb)
179 with:
180 P = priority bit (from pattern attribute)
181 p = color palette (from pattern attribute)
182 c = color data (from pattern cache)
183
184 One pattern = 8 pixels = 8 bytes = two 32-bit writes per pattern
185 */
186
187 #ifdef ALIGN_LONG
188 #ifdef LSB_FIRST
189 #define DRAW_COLUMN(ATTR, LINE) \
190 GET_LSB_TILE(ATTR, LINE) \
191 WRITE_LONG(dst, src[0] | atex); \
192 dst++; \
193 WRITE_LONG(dst, src[1] | atex); \
194 dst++; \
195 GET_MSB_TILE(ATTR, LINE) \
196 WRITE_LONG(dst, src[0] | atex); \
197 dst++; \
198 WRITE_LONG(dst, src[1] | atex); \
199 dst++;
200 #define DRAW_COLUMN_IM2(ATTR, LINE) \
201 GET_LSB_TILE_IM2(ATTR, LINE) \
202 WRITE_LONG(dst, src[0] | atex); \
203 dst++; \
204 WRITE_LONG(dst, src[1] | atex); \
205 dst++; \
206 GET_MSB_TILE_IM2(ATTR, LINE) \
207 WRITE_LONG(dst, src[0] | atex); \
208 dst++; \
209 WRITE_LONG(dst, src[1] | atex); \
210 dst++;
211 #else
212 #define DRAW_COLUMN(ATTR, LINE) \
213 GET_MSB_TILE(ATTR, LINE) \
214 WRITE_LONG(dst, src[0] | atex); \
215 dst++; \
216 WRITE_LONG(dst, src[1] | atex); \
217 dst++; \
218 GET_LSB_TILE(ATTR, LINE) \
219 WRITE_LONG(dst, src[0] | atex); \
220 dst++; \
221 WRITE_LONG(dst, src[1] | atex); \
222 dst++;
223 #define DRAW_COLUMN_IM2(ATTR, LINE) \
224 GET_MSB_TILE_IM2(ATTR, LINE) \
225 WRITE_LONG(dst, src[0] | atex); \
226 dst++; \
227 WRITE_LONG(dst, src[1] | atex); \
228 dst++; \
229 GET_LSB_TILE_IM2(ATTR, LINE) \
230 WRITE_LONG(dst, src[0] | atex); \
231 dst++; \
232 WRITE_LONG(dst, src[1] | atex); \
233 dst++;
234 #endif
235 #else /* NOT ALIGNED */
236 #ifdef LSB_FIRST
237 #define DRAW_COLUMN(ATTR, LINE) \
238 GET_LSB_TILE(ATTR, LINE) \
239 *dst++ = (src[0] | atex); \
240 *dst++ = (src[1] | atex); \
241 GET_MSB_TILE(ATTR, LINE) \
242 *dst++ = (src[0] | atex); \
243 *dst++ = (src[1] | atex);
244 #define DRAW_COLUMN_IM2(ATTR, LINE) \
245 GET_LSB_TILE_IM2(ATTR, LINE) \
246 *dst++ = (src[0] | atex); \
247 *dst++ = (src[1] | atex); \
248 GET_MSB_TILE_IM2(ATTR, LINE) \
249 *dst++ = (src[0] | atex); \
250 *dst++ = (src[1] | atex);
251 #else
252 #define DRAW_COLUMN(ATTR, LINE) \
253 GET_MSB_TILE(ATTR, LINE) \
254 *dst++ = (src[0] | atex); \
255 *dst++ = (src[1] | atex); \
256 GET_LSB_TILE(ATTR, LINE) \
257 *dst++ = (src[0] | atex); \
258 *dst++ = (src[1] | atex);
259 #define DRAW_COLUMN_IM2(ATTR, LINE) \
260 GET_MSB_TILE_IM2(ATTR, LINE) \
261 *dst++ = (src[0] | atex); \
262 *dst++ = (src[1] | atex); \
263 GET_LSB_TILE_IM2(ATTR, LINE) \
264 *dst++ = (src[0] | atex); \
265 *dst++ = (src[1] | atex);
266 #endif
267 #endif /* ALIGN_LONG */
268
269 #ifdef ALT_RENDERER
270 /* Draw background tiles directly using priority look-up table */
271 /* SRC_A = layer A rendered pixel line (4 bytes = 4 pixels at once) */
272 /* SRC_B = layer B cached pixel line (4 bytes = 4 pixels at once) */
273 /* Note: cache address is always aligned so no need to use READ_LONG macro */
274 /* This might be faster or slower than original method, depending on */
275 /* architecture (x86, PowerPC), cache size, memory access speed, etc... */
276
277 #ifdef LSB_FIRST
278 #define DRAW_BG_TILE(SRC_A, SRC_B) \
279 *lb++ = table[((SRC_B << 8) & 0xff00) | (SRC_A & 0xff)]; \
280 *lb++ = table[(SRC_B & 0xff00) | ((SRC_A >> 8) & 0xff)]; \
281 *lb++ = table[((SRC_B >> 8) & 0xff00) | ((SRC_A >> 16) & 0xff)]; \
282 *lb++ = table[((SRC_B >> 16) & 0xff00) | ((SRC_A >> 24) & 0xff)];
283 #else
284 #define DRAW_BG_TILE(SRC_A, SRC_B) \
285 *lb++ = table[((SRC_B >> 16) & 0xff00) | ((SRC_A >> 24) & 0xff)]; \
286 *lb++ = table[((SRC_B >> 8) & 0xff00) | ((SRC_A >> 16) & 0xff)]; \
287 *lb++ = table[(SRC_B & 0xff00) | ((SRC_A >> 8) & 0xff)]; \
288 *lb++ = table[((SRC_B << 8) & 0xff00) | (SRC_A & 0xff)];
289 #endif
290
291 #ifdef ALIGN_LONG
292 #ifdef LSB_FIRST
293 #define DRAW_BG_COLUMN(ATTR, LINE, SRC_A, SRC_B) \
294 GET_LSB_TILE(ATTR, LINE) \
295 SRC_A = READ_LONG((uint32 *)lb); \
296 SRC_B = (src[0] | atex); \
297 DRAW_BG_TILE(SRC_A, SRC_B) \
298 SRC_A = READ_LONG((uint32 *)lb); \
299 SRC_B = (src[1] | atex); \
300 DRAW_BG_TILE(SRC_A, SRC_B) \
301 GET_MSB_TILE(ATTR, LINE) \
302 SRC_A = READ_LONG((uint32 *)lb); \
303 SRC_B = (src[0] | atex); \
304 DRAW_BG_TILE(SRC_A, SRC_B) \
305 SRC_A = READ_LONG((uint32 *)lb); \
306 SRC_B = (src[1] | atex); \
307 DRAW_BG_TILE(SRC_A, SRC_B)
308 #define DRAW_BG_COLUMN_IM2(ATTR, LINE, SRC_A, SRC_B) \
309 GET_LSB_TILE_IM2(ATTR, LINE) \
310 SRC_A = READ_LONG((uint32 *)lb); \
311 SRC_B = (src[0] | atex); \
312 DRAW_BG_TILE(SRC_A, SRC_B) \
313 SRC_A = READ_LONG((uint32 *)lb); \
314 SRC_B = (src[1] | atex); \
315 DRAW_BG_TILE(SRC_A, SRC_B) \
316 GET_MSB_TILE_IM2(ATTR, LINE) \
317 SRC_A = READ_LONG((uint32 *)lb); \
318 SRC_B = (src[0] | atex); \
319 DRAW_BG_TILE(SRC_A, SRC_B) \
320 SRC_A = READ_LONG((uint32 *)lb); \
321 SRC_B = (src[1] | atex); \
322 DRAW_BG_TILE(SRC_A, SRC_B)
323 #else
324 #define DRAW_BG_COLUMN(ATTR, LINE, SRC_A, SRC_B) \
325 GET_MSB_TILE(ATTR, LINE) \
326 SRC_A = READ_LONG((uint32 *)lb); \
327 SRC_B = (src[0] | atex); \
328 DRAW_BG_TILE(SRC_A, SRC_B) \
329 SRC_A = READ_LONG((uint32 *)lb); \
330 SRC_B = (src[1] | atex); \
331 DRAW_BG_TILE(SRC_A, SRC_B) \
332 GET_LSB_TILE(ATTR, LINE) \
333 SRC_A = READ_LONG((uint32 *)lb); \
334 SRC_B = (src[0] | atex); \
335 DRAW_BG_TILE(SRC_A, SRC_B) \
336 SRC_A = READ_LONG((uint32 *)lb); \
337 SRC_B = (src[1] | atex); \
338 DRAW_BG_TILE(SRC_A, SRC_B)
339 #define DRAW_BG_COLUMN_IM2(ATTR, LINE, SRC_A, SRC_B) \
340 GET_MSB_TILE_IM2(ATTR, LINE) \
341 SRC_A = READ_LONG((uint32 *)lb); \
342 SRC_B = (src[0] | atex); \
343 DRAW_BG_TILE(SRC_A, SRC_B) \
344 SRC_A = READ_LONG((uint32 *)lb); \
345 SRC_B = (src[1] | atex); \
346 DRAW_BG_TILE(SRC_A, SRC_B) \
347 GET_LSB_TILE_IM2(ATTR, LINE) \
348 SRC_A = READ_LONG((uint32 *)lb); \
349 SRC_B = (src[0] | atex); \
350 DRAW_BG_TILE(SRC_A, SRC_B) \
351 SRC_A = READ_LONG((uint32 *)lb); \
352 SRC_B = (src[1] | atex); \
353 DRAW_BG_TILE(SRC_A, SRC_B)
354 #endif
355 #else /* NOT ALIGNED */
356 #ifdef LSB_FIRST
357 #define DRAW_BG_COLUMN(ATTR, LINE, SRC_A, SRC_B) \
358 GET_LSB_TILE(ATTR, LINE) \
359 SRC_A = *(uint32 *)(lb); \
360 SRC_B = (src[0] | atex); \
361 DRAW_BG_TILE(SRC_A, SRC_B) \
362 SRC_A = *(uint32 *)(lb); \
363 SRC_B = (src[1] | atex); \
364 DRAW_BG_TILE(SRC_A, SRC_B) \
365 GET_MSB_TILE(ATTR, LINE) \
366 SRC_A = *(uint32 *)(lb); \
367 SRC_B = (src[0] | atex); \
368 DRAW_BG_TILE(SRC_A, SRC_B) \
369 SRC_A = *(uint32 *)(lb); \
370 SRC_B = (src[1] | atex); \
371 DRAW_BG_TILE(SRC_A, SRC_B)
372 #define DRAW_BG_COLUMN_IM2(ATTR, LINE, SRC_A, SRC_B) \
373 GET_LSB_TILE_IM2(ATTR, LINE) \
374 SRC_A = *(uint32 *)(lb); \
375 SRC_B = (src[0] | atex); \
376 DRAW_BG_TILE(SRC_A, SRC_B) \
377 SRC_A = *(uint32 *)(lb); \
378 SRC_B = (src[1] | atex); \
379 DRAW_BG_TILE(SRC_A, SRC_B) \
380 GET_MSB_TILE_IM2(ATTR, LINE) \
381 SRC_A = *(uint32 *)(lb); \
382 SRC_B = (src[0] | atex); \
383 DRAW_BG_TILE(SRC_A, SRC_B) \
384 SRC_A = *(uint32 *)(lb); \
385 SRC_B = (src[1] | atex); \
386 DRAW_BG_TILE(SRC_A, SRC_B)
387 #else
388 #define DRAW_BG_COLUMN(ATTR, LINE, SRC_A, SRC_B) \
389 GET_MSB_TILE(ATTR, LINE) \
390 SRC_A = *(uint32 *)(lb); \
391 SRC_B = (src[0] | atex); \
392 DRAW_BG_TILE(SRC_A, SRC_B) \
393 SRC_A = *(uint32 *)(lb); \
394 SRC_B = (src[1] | atex); \
395 DRAW_BG_TILE(SRC_A, SRC_B) \
396 GET_LSB_TILE(ATTR, LINE) \
397 SRC_A = *(uint32 *)(lb); \
398 SRC_B = (src[0] | atex); \
399 DRAW_BG_TILE(SRC_A, SRC_B) \
400 SRC_A = *(uint32 *)(lb); \
401 SRC_B = (src[1] | atex); \
402 DRAW_BG_TILE(SRC_A, SRC_B)
403 #define DRAW_BG_COLUMN_IM2(ATTR, LINE, SRC_A, SRC_B) \
404 GET_MSB_TILE_IM2(ATTR, LINE) \
405 SRC_A = *(uint32 *)(lb); \
406 SRC_B = (src[0] | atex); \
407 DRAW_BG_TILE(SRC_A, SRC_B) \
408 SRC_A = *(uint32 *)(lb); \
409 SRC_B = (src[1] | atex); \
410 DRAW_BG_TILE(SRC_A, SRC_B) \
411 GET_LSB_TILE_IM2(ATTR, LINE) \
412 SRC_A = *(uint32 *)(lb); \
413 SRC_B = (src[0] | atex); \
414 DRAW_BG_TILE(SRC_A, SRC_B) \
415 SRC_A = *(uint32 *)(lb); \
416 SRC_B = (src[1] | atex); \
417 DRAW_BG_TILE(SRC_A, SRC_B)
418 #endif
419 #endif /* ALIGN_LONG */
420 #endif /* ALT_RENDERER */
421
422 #define DRAW_SPRITE_TILE(WIDTH,ATTR,TABLE) \
423 for (i=0;i<WIDTH;i++) \
424 { \
425 temp = *src++; \
426 if (temp & 0x0f) \
427 { \
428 temp |= (lb[i] << 8); \
429 lb[i] = TABLE[temp | ATTR]; \
430 status |= ((temp & 0x8000) >> 10); \
431 } \
432 }
433
434 #define DRAW_SPRITE_TILE_ACCURATE(WIDTH,ATTR,TABLE) \
435 for (i=0;i<WIDTH;i++) \
436 { \
437 temp = *src++; \
438 if (temp & 0x0f) \
439 { \
440 temp |= (lb[i] << 8); \
441 lb[i] = TABLE[temp | ATTR]; \
442 if ((temp & 0x8000) && !(status & 0x20)) \
443 { \
444 spr_col = (v_counter << 8) | ((xpos + i + 13) >> 1); \
445 status |= 0x20; \
446 } \
447 } \
448 }
449
450 #define DRAW_SPRITE_TILE_ACCURATE_2X(WIDTH,ATTR,TABLE) \
451 for (i=0;i<WIDTH;i+=2) \
452 { \
453 temp = *src++; \
454 if (temp & 0x0f) \
455 { \
456 temp |= (lb[i] << 8); \
457 lb[i] = TABLE[temp | ATTR]; \
458 if ((temp & 0x8000) && !(status & 0x20)) \
459 { \
460 spr_col = (v_counter << 8) | ((xpos + i + 13) >> 1); \
461 status |= 0x20; \
462 } \
463 temp &= 0x00FF; \
464 temp |= (lb[i+1] << 8); \
465 lb[i+1] = TABLE[temp | ATTR]; \
466 if ((temp & 0x8000) && !(status & 0x20)) \
467 { \
468 spr_col = (v_counter << 8) | ((xpos + i + 1 + 13) >> 1); \
469 status |= 0x20; \
470 } \
471 } \
472 }
473
474
475 /* Pixels conversion macro */
476 /* 4-bit color channels are either compressed to 2/3-bit or dithered to 5/6/8-bit equivalents */
477 /* 3:3:2 RGB */
478 #if defined(USE_8BPP_RENDERING)
479 #define MAKE_PIXEL(r,g,b) (((r) >> 1) << 5 | ((g) >> 1) << 2 | (b) >> 2)
480
481 /* 5:5:5 RGB */
482 #elif defined(USE_15BPP_RENDERING)
483 #if defined(USE_ABGR)
484 #define MAKE_PIXEL(r,g,b) ((1 << 15) | (b) << 11 | ((b) >> 3) << 10 | (g) << 6 | ((g) >> 3) << 5 | (r) << 1 | (r) >> 3)
485 #else
486 #define MAKE_PIXEL(r,g,b) ((1 << 15) | (r) << 11 | ((r) >> 3) << 10 | (g) << 6 | ((g) >> 3) << 5 | (b) << 1 | (b) >> 3)
487 #endif
488 /* 5:6:5 RGB */
489 #elif defined(USE_16BPP_RENDERING)
490 #define MAKE_PIXEL(r,g,b) ((r) << 12 | ((r) >> 3) << 11 | (g) << 7 | ((g) >> 2) << 5 | (b) << 1 | (b) >> 3)
491
492 /* 8:8:8 RGB */
493 #elif defined(USE_32BPP_RENDERING)
494 #define MAKE_PIXEL(r,g,b) ((0xff << 24) | (r) << 20 | (r) << 16 | (g) << 12 | (g) << 8 | (b) << 4 | (b))
495 #endif
496
497 /* Window & Plane A clipping */
498 static struct clip_t
499 {
500 uint8 left;
501 uint8 right;
502 uint8 enable;
503 } clip[2];
504
505 /* Pattern attribute (priority + palette bits) expansion table */
506 static const uint32 atex_table[] =
507 {
508 0x00000000,
509 0x10101010,
510 0x20202020,
511 0x30303030,
512 0x40404040,
513 0x50505050,
514 0x60606060,
515 0x70707070
516 };
517
518 /* fixed Master System palette for Modes 0,1,2,3 */
519 static const uint8 tms_crom[16] =
520 {
521 0x00, 0x00, 0x08, 0x0C,
522 0x10, 0x30, 0x01, 0x3C,
523 0x02, 0x03, 0x05, 0x0F,
524 0x04, 0x33, 0x15, 0x3F
525 };
526
527 /* original SG-1000 palette */
528 #if defined(USE_8BPP_RENDERING)
529 static const uint8 tms_palette[16] =
530 {
531 0x00, 0x00, 0x39, 0x79,
532 0x4B, 0x6F, 0xC9, 0x5B,
533 0xE9, 0xED, 0xD5, 0xD9,
534 0x35, 0xCE, 0xDA, 0xFF
535 };
536
537 #elif defined(USE_15BPP_RENDERING)
538 static const uint16 tms_palette[16] =
539 {
540 0x8000, 0x8000, 0x9308, 0xAF6F,
541 0xA95D, 0xBDDF, 0xE949, 0xA3BE,
542 0xFD4A, 0xFDEF, 0xEB0A, 0xF330,
543 0x92A7, 0xE177, 0xE739, 0xFFFF
544 };
545
546 #elif defined(USE_16BPP_RENDERING)
547 static const uint16 tms_palette[16] =
548 {
549 0x0000, 0x0000, 0x2648, 0x5ECF,
550 0x52BD, 0x7BBE, 0xD289, 0x475E,
551 0xF2AA, 0xFBCF, 0xD60A, 0xE670,
552 0x2567, 0xC2F7, 0xCE59, 0xFFFF
553 };
554
555 #elif defined(USE_32BPP_RENDERING)
556 static const uint32 tms_palette[16] =
557 {
558 0xFF000000, 0xFF000000, 0xFF21C842, 0xFF5EDC78,
559 0xFF5455ED, 0xFF7D76FC, 0xFFD4524D, 0xFF42EBF5,
560 0xFFFC5554, 0xFFFF7978, 0xFFD4C154, 0xFFE6CE80,
561 0xFF21B03B, 0xFFC95BB4, 0xFFCCCCCC, 0xFFFFFFFF
562 };
563 #endif
564
565 /* Cached and flipped patterns */
566 static uint8 ALIGNED_(4) bg_pattern_cache[0x80000];
567
568 /* Sprite pattern name offset look-up table (Mode 5) */
569 static uint8 name_lut[0x400];
570
571 /* Bitplane to packed pixel look-up table (Mode 4) */
572 static uint32 bp_lut[0x10000];
573
574 /* Layer priority pixel look-up tables */
575 static uint8 lut[LUT_MAX][LUT_SIZE];
576
577 /* Output pixel data look-up tables*/
578 static PIXEL_OUT_T pixel[0x100];
579 static PIXEL_OUT_T pixel_lut[3][0x200];
580 static PIXEL_OUT_T pixel_lut_m4[0x40];
581
582 /* Background & Sprite line buffers */
583 static uint8 linebuf[2][0x200];
584
585 /* Sprite limit flag */
586 static uint8 spr_ovr;
587
588 /* Sprite parsing lists */
589 typedef struct
590 {
591 uint16 ypos;
592 uint16 xpos;
593 uint16 attr;
594 uint16 size;
595 } object_info_t;
596
597 static object_info_t obj_info[2][MAX_SPRITES_PER_LINE];
598
599 /* Sprite Counter */
600 static uint8 object_count[2];
601
602 /* Sprite Collision Info */
603 uint16 spr_col;
604
605 /* Function pointers */
606 void (*render_bg)(int line);
607 void (*render_obj)(int line);
608 void (*parse_satb)(int line);
609 void (*update_bg_pattern_cache)(int index);
610
611
612 /*--------------------------------------------------------------------------*/
613 /* Sprite pattern name offset look-up table function (Mode 5) */
614 /*--------------------------------------------------------------------------*/
615
make_name_lut(void)616 static void make_name_lut(void)
617 {
618 int vcol, vrow;
619 int width, height;
620 int flipx, flipy;
621 int i;
622
623 for (i = 0; i < 0x400; i += 1)
624 {
625 /* Sprite settings */
626 vcol = i & 3;
627 vrow = (i >> 2) & 3;
628 height = (i >> 4) & 3;
629 width = (i >> 6) & 3;
630 flipx = (i >> 8) & 1;
631 flipy = (i >> 9) & 1;
632
633 if ((vrow > height) || vcol > width)
634 {
635 /* Invalid settings (unused) */
636 name_lut[i] = -1;
637 }
638 else
639 {
640 /* Adjust column & row index if sprite is flipped */
641 if(flipx) vcol = (width - vcol);
642 if(flipy) vrow = (height - vrow);
643
644 /* Pattern offset (pattern order is up->down->left->right) */
645 name_lut[i] = vrow + (vcol * (height + 1));
646 }
647 }
648 }
649
650
651 /*--------------------------------------------------------------------------*/
652 /* Bitplane to packed pixel look-up table function (Mode 4) */
653 /*--------------------------------------------------------------------------*/
654
make_bp_lut(void)655 static void make_bp_lut(void)
656 {
657 int x,i,j;
658 uint32 out;
659
660 /* ---------------------- */
661 /* Pattern color encoding */
662 /* -------------------------------------------------------------------------*/
663 /* 4 byteplanes are required to define one pattern line (8 pixels) */
664 /* A single pixel color is coded with 4 bits (c3 c2 c1 c0) */
665 /* Each bit is coming from byteplane bits, as explained below: */
666 /* pixel 0: c3 = bp3 bit 7, c2 = bp2 bit 7, c1 = bp1 bit 7, c0 = bp0 bit 7 */
667 /* pixel 1: c3 = bp3 bit 6, c2 = bp2 bit 6, c1 = bp1 bit 6, c0 = bp0 bit 6 */
668 /* ... */
669 /* pixel 7: c3 = bp3 bit 0, c2 = bp2 bit 0, c1 = bp1 bit 0, c0 = bp0 bit 0 */
670 /* -------------------------------------------------------------------------*/
671
672 for(i = 0; i < 0x100; i++)
673 for(j = 0; j < 0x100; j++)
674 {
675 out = 0;
676 for(x = 0; x < 8; x++)
677 {
678 /* pixel line data = hh00gg00ff00ee00dd00cc00bb00aa00 (32-bit) */
679 /* aa-hh = upper or lower 2-bit values of pixels 0-7 (shifted) */
680 out |= (j & (0x80 >> x)) ? (uint32)(8 << (x << 2)) : 0;
681 out |= (i & (0x80 >> x)) ? (uint32)(4 << (x << 2)) : 0;
682 }
683
684 /* i = low byte in VRAM (bp0 or bp2) */
685 /* j = high byte in VRAM (bp1 or bp3) */
686 #ifdef LSB_FIRST
687 bp_lut[(j << 8) | (i)] = out;
688 #else
689 bp_lut[(i << 8) | (j)] = out;
690 #endif
691 }
692 }
693
694
695 /*--------------------------------------------------------------------------*/
696 /* Layers priority pixel look-up tables functions */
697 /*--------------------------------------------------------------------------*/
698
699 /* Input (bx): d5-d0=color, d6=priority, d7=unused */
700 /* Input (ax): d5-d0=color, d6=priority, d7=unused */
701 /* Output: d5-d0=color, d6=priority, d7=zero */
make_lut_bg(uint32 bx,uint32 ax)702 static uint32 make_lut_bg(uint32 bx, uint32 ax)
703 {
704 int bf = (bx & 0x7F);
705 int bp = (bx & 0x40);
706 int b = (bx & 0x0F);
707
708 int af = (ax & 0x7F);
709 int ap = (ax & 0x40);
710 int a = (ax & 0x0F);
711
712 int c = (ap ? (a ? af : bf) : (bp ? (b ? bf : af) : (a ? af : bf)));
713
714 /* Strip palette & priority bits from transparent pixels */
715 if((c & 0x0F) == 0x00) c &= 0x80;
716
717 return (c);
718 }
719
720 /* Input (bx): d5-d0=color, d6=priority, d7=unused */
721 /* Input (sx): d5-d0=color, d6=priority, d7=unused */
722 /* Output: d5-d0=color, d6=priority, d7=intensity select (0=half/1=normal) */
make_lut_bg_ste(uint32 bx,uint32 ax)723 static uint32 make_lut_bg_ste(uint32 bx, uint32 ax)
724 {
725 int bf = (bx & 0x7F);
726 int bp = (bx & 0x40);
727 int b = (bx & 0x0F);
728
729 int af = (ax & 0x7F);
730 int ap = (ax & 0x40);
731 int a = (ax & 0x0F);
732
733 int c = (ap ? (a ? af : bf) : (bp ? (b ? bf : af) : (a ? af : bf)));
734
735 /* Half intensity when both pixels are low priority */
736 c |= ((ap | bp) << 1);
737
738 /* Strip palette & priority bits from transparent pixels */
739 if((c & 0x0F) == 0x00) c &= 0x80;
740
741 return (c);
742 }
743
744 /* Input (bx): d5-d0=color, d6=priority/1, d7=sprite pixel marker */
745 /* Input (sx): d5-d0=color, d6=priority, d7=unused */
746 /* Output: d5-d0=color, d6=priority, d7=sprite pixel marker */
make_lut_obj(uint32 bx,uint32 sx)747 static uint32 make_lut_obj(uint32 bx, uint32 sx)
748 {
749 int c;
750
751 int bf = (bx & 0x7F);
752 int bs = (bx & 0x80);
753 int sf = (sx & 0x7F);
754
755 if((sx & 0x0F) == 0) return bx;
756
757 c = (bs ? bf : sf);
758
759 /* Strip palette bits from transparent pixels */
760 if((c & 0x0F) == 0x00) c &= 0xC0;
761
762 return (c | 0x80);
763 }
764
765
766 /* Input (bx): d5-d0=color, d6=priority, d7=opaque sprite pixel marker */
767 /* Input (sx): d5-d0=color, d6=priority, d7=unused */
768 /* Output: d5-d0=color, d6=zero/priority, d7=opaque sprite pixel marker */
make_lut_bgobj(uint32 bx,uint32 sx)769 static uint32 make_lut_bgobj(uint32 bx, uint32 sx)
770 {
771 int c;
772
773 int bf = (bx & 0x3F);
774 int bs = (bx & 0x80);
775 int bp = (bx & 0x40);
776 int b = (bx & 0x0F);
777
778 int sf = (sx & 0x3F);
779 int sp = (sx & 0x40);
780 int s = (sx & 0x0F);
781
782 if(s == 0) return bx;
783
784 /* Previous sprite has higher priority */
785 if(bs) return bx;
786
787 c = (sp ? sf : (bp ? (b ? bf : sf) : sf));
788
789 /* Strip palette & priority bits from transparent pixels */
790 if((c & 0x0F) == 0x00) c &= 0x80;
791
792 return (c | 0x80);
793 }
794
795 /* Input (bx): d5-d0=color, d6=priority, d7=intensity (half/normal) */
796 /* Input (sx): d5-d0=color, d6=priority, d7=sprite marker */
797 /* Output: d5-d0=color, d6=intensity (half/normal), d7=(double/invalid) */
make_lut_bgobj_ste(uint32 bx,uint32 sx)798 static uint32 make_lut_bgobj_ste(uint32 bx, uint32 sx)
799 {
800 int c;
801
802 int bf = (bx & 0x3F);
803 int bp = (bx & 0x40);
804 int b = (bx & 0x0F);
805 int bi = (bx & 0x80) >> 1;
806
807 int sf = (sx & 0x3F);
808 int sp = (sx & 0x40);
809 int s = (sx & 0x0F);
810 int si = sp | bi;
811
812 if(sp)
813 {
814 if(s)
815 {
816 if((sf & 0x3E) == 0x3E)
817 {
818 if(sf & 1)
819 {
820 c = (bf | 0x00);
821 }
822 else
823 {
824 c = (bx & 0x80) ? (bf | 0x80) : (bf | 0x40);
825 }
826 }
827 else
828 {
829 if(sf == 0x0E || sf == 0x1E || sf == 0x2E)
830 {
831 c = (sf | 0x40);
832 }
833 else
834 {
835 c = (sf | si);
836 }
837 }
838 }
839 else
840 {
841 c = (bf | bi);
842 }
843 }
844 else
845 {
846 if(bp)
847 {
848 if(b)
849 {
850 c = (bf | bi);
851 }
852 else
853 {
854 if(s)
855 {
856 if((sf & 0x3E) == 0x3E)
857 {
858 if(sf & 1)
859 {
860 c = (bf | 0x00);
861 }
862 else
863 {
864 c = (bx & 0x80) ? (bf | 0x80) : (bf | 0x40);
865 }
866 }
867 else
868 {
869 if(sf == 0x0E || sf == 0x1E || sf == 0x2E)
870 {
871 c = (sf | 0x40);
872 }
873 else
874 {
875 c = (sf | si);
876 }
877 }
878 }
879 else
880 {
881 c = (bf | bi);
882 }
883 }
884 }
885 else
886 {
887 if(s)
888 {
889 if((sf & 0x3E) == 0x3E)
890 {
891 if(sf & 1)
892 {
893 c = (bf | 0x00);
894 }
895 else
896 {
897 c = (bx & 0x80) ? (bf | 0x80) : (bf | 0x40);
898 }
899 }
900 else
901 {
902 if(sf == 0x0E || sf == 0x1E || sf == 0x2E)
903 {
904 c = (sf | 0x40);
905 }
906 else
907 {
908 c = (sf | si);
909 }
910 }
911 }
912 else
913 {
914 c = (bf | bi);
915 }
916 }
917 }
918
919 if((c & 0x0f) == 0x00) c &= 0xC0;
920
921 return (c);
922 }
923
924 /* Input (bx): d3-d0=color, d4=palette, d5=priority, d6=zero, d7=sprite pixel marker */
925 /* Input (sx): d3-d0=color, d7-d4=zero */
926 /* Output: d3-d0=color, d4=palette, d5=zero/priority, d6=zero, d7=sprite pixel marker */
make_lut_bgobj_m4(uint32 bx,uint32 sx)927 static uint32 make_lut_bgobj_m4(uint32 bx, uint32 sx)
928 {
929 int c;
930
931 int bf = (bx & 0x3F);
932 int bs = (bx & 0x80);
933 int bp = (bx & 0x20);
934 int b = (bx & 0x0F);
935
936 int s = (sx & 0x0F);
937 int sf = (s | 0x10); /* force palette bit */
938
939 /* Transparent sprite pixel */
940 if(s == 0) return bx;
941
942 /* Previous sprite has higher priority */
943 if(bs) return bx;
944
945 /* note: priority bit is always 0 for Modes 0,1,2,3 */
946 c = (bp ? (b ? bf : sf) : sf);
947
948 return (c | 0x80);
949 }
950
951
952 /*--------------------------------------------------------------------------*/
953 /* Pixel layer merging function */
954 /*--------------------------------------------------------------------------*/
955
merge(uint8 * srca,uint8 * srcb,uint8 * dst,uint8 * table,int width)956 INLINE void merge(uint8 *srca, uint8 *srcb, uint8 *dst, uint8 *table, int width)
957 {
958 do
959 {
960 *dst++ = table[(*srcb++ << 8) | (*srca++)];
961 }
962 while (--width);
963 }
964
965
966 /*--------------------------------------------------------------------------*/
967 /* Pixel color lookup tables initialization */
968 /*--------------------------------------------------------------------------*/
969
palette_init(void)970 static void palette_init(void)
971 {
972 int r, g, b, i;
973
974 /************************************************/
975 /* Each R,G,B color channel is 4-bit with a */
976 /* total of 15 different intensity levels. */
977 /* */
978 /* Color intensity depends on the mode: */
979 /* */
980 /* normal : xxx0 (0-14) */
981 /* shadow : 0xxx (0-7) */
982 /* highlight: 1xxx - 1 (7-14) */
983 /* mode4 : xxxx(*) (0-15) */
984 /* GG mode : xxxx (0-15) */
985 /* */
986 /* with x = original CRAM value (2, 3 or 4-bit) */
987 /* (*) 2-bit CRAM value is expanded to 4-bit */
988 /************************************************/
989
990 /* Initialize Mode 5 pixel color look-up tables */
991 for (i = 0; i < 0x200; i++)
992 {
993 /* CRAM 9-bit value (BBBGGGRRR) */
994 r = (i >> 0) & 7;
995 g = (i >> 3) & 7;
996 b = (i >> 6) & 7;
997
998 /* Convert to output pixel format */
999 pixel_lut[0][i] = MAKE_PIXEL(r,g,b);
1000 pixel_lut[1][i] = MAKE_PIXEL(r<<1,g<<1,b<<1);
1001 pixel_lut[2][i] = MAKE_PIXEL(r+7,g+7,b+7);
1002 }
1003
1004 /* Initialize Mode 4 pixel color look-up table */
1005 for (i = 0; i < 0x40; i++)
1006 {
1007 /* CRAM 6-bit value (000BBGGRR) */
1008 r = (i >> 0) & 3;
1009 g = (i >> 2) & 3;
1010 b = (i >> 4) & 3;
1011
1012 /* Expand to full range & convert to output pixel format */
1013 pixel_lut_m4[i] = MAKE_PIXEL((r << 2) | r, (g << 2) | g, (b << 2) | b);
1014 }
1015 }
1016
1017
1018 /*--------------------------------------------------------------------------*/
1019 /* Color palette update functions */
1020 /*--------------------------------------------------------------------------*/
1021
color_update_m4(int index,unsigned int data)1022 void color_update_m4(int index, unsigned int data)
1023 {
1024 switch (system_hw)
1025 {
1026 case SYSTEM_GG:
1027 {
1028 /* CRAM value (BBBBGGGGRRRR) */
1029 int r = (data >> 0) & 0x0F;
1030 int g = (data >> 4) & 0x0F;
1031 int b = (data >> 8) & 0x0F;
1032
1033 /* Convert to output pixel */
1034 data = MAKE_PIXEL(r,g,b);
1035 break;
1036 }
1037
1038 case SYSTEM_SG:
1039 case SYSTEM_SGII:
1040 {
1041 /* Fixed TMS99xx palette */
1042 if (index & 0x0F)
1043 {
1044 /* Colors 1-15 */
1045 data = tms_palette[index & 0x0F];
1046 }
1047 else
1048 {
1049 /* Backdrop color */
1050 data = tms_palette[reg[7] & 0x0F];
1051 }
1052 break;
1053 }
1054
1055 default:
1056 {
1057 /* Test M4 bit */
1058 if (!(reg[0] & 0x04))
1059 {
1060 if (system_hw & SYSTEM_MD)
1061 {
1062 /* Invalid Mode (black screen) */
1063 data = 0x00;
1064 }
1065 else if (system_hw != SYSTEM_GGMS)
1066 {
1067 /* Fixed CRAM palette */
1068 if (index & 0x0F)
1069 {
1070 /* Colors 1-15 */
1071 data = tms_crom[index & 0x0F];
1072 }
1073 else
1074 {
1075 /* Backdrop color */
1076 data = tms_crom[reg[7] & 0x0F];
1077 }
1078 }
1079 }
1080
1081 /* Mode 4 palette */
1082 data = pixel_lut_m4[data & 0x3F];
1083 break;
1084 }
1085 }
1086
1087
1088 /* Input pixel: x0xiiiii (normal) or 01000000 (backdrop) */
1089 if (reg[0] & 0x04)
1090 {
1091 /* Mode 4 */
1092 pixel[0x00 | index] = data;
1093 pixel[0x20 | index] = data;
1094 pixel[0x80 | index] = data;
1095 pixel[0xA0 | index] = data;
1096 }
1097 else
1098 {
1099 /* TMS99xx modes (palette bit forced to 1 because Game Gear uses CRAM palette #1) */
1100 if ((index == 0x40) || (index == (0x10 | (reg[7] & 0x0F))))
1101 {
1102 /* Update backdrop color */
1103 pixel[0x40] = data;
1104
1105 /* Update transparent color */
1106 pixel[0x10] = data;
1107 pixel[0x30] = data;
1108 pixel[0x90] = data;
1109 pixel[0xB0] = data;
1110 }
1111
1112 if (index & 0x0F)
1113 {
1114 /* update non-transparent colors */
1115 pixel[0x00 | index] = data;
1116 pixel[0x20 | index] = data;
1117 pixel[0x80 | index] = data;
1118 pixel[0xA0 | index] = data;
1119 }
1120 }
1121 }
1122
color_update_m5(int index,unsigned int data)1123 void color_update_m5(int index, unsigned int data)
1124 {
1125 /* Palette Mode */
1126 if (!(reg[0] & 0x04))
1127 {
1128 /* Color value is limited to 00X00X00X */
1129 data &= 0x49;
1130 }
1131
1132 if(reg[12] & 0x08)
1133 {
1134 /* Mode 5 (Shadow/Normal/Highlight) */
1135 pixel[0x00 | index] = pixel_lut[0][data];
1136 pixel[0x40 | index] = pixel_lut[1][data];
1137 pixel[0x80 | index] = pixel_lut[2][data];
1138 }
1139 else
1140 {
1141 /* Mode 5 (Normal) */
1142 data = pixel_lut[1][data];
1143
1144 /* Input pixel: xxiiiiii */
1145 pixel[0x00 | index] = data;
1146 pixel[0x40 | index] = data;
1147 pixel[0x80 | index] = data;
1148 }
1149 }
1150
1151
1152 /*--------------------------------------------------------------------------*/
1153 /* Background layers rendering functions */
1154 /*--------------------------------------------------------------------------*/
1155
1156 /* Graphics I */
render_bg_m0(int line)1157 void render_bg_m0(int line)
1158 {
1159 uint8 color, name, pattern;
1160
1161 uint8 *lb = &linebuf[0][0x20];
1162 uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line & 0xF8) << 2)];
1163 uint8 *ct = &vram[((reg[3] << 6) & 0x3FC0)];
1164 uint8 *pg = &vram[((reg[4] << 11) & 0x3800) + (line & 7)];
1165
1166 /* 32 x 8 pixels */
1167 int width = 32;
1168
1169 do
1170 {
1171 name = *nt++;
1172 color = ct[name >> 3];
1173 pattern = pg[name << 3];
1174
1175 *lb++ = 0x10 | ((color >> (((pattern >> 7) & 1) << 2)) & 0x0F);
1176 *lb++ = 0x10 | ((color >> (((pattern >> 6) & 1) << 2)) & 0x0F);
1177 *lb++ = 0x10 | ((color >> (((pattern >> 5) & 1) << 2)) & 0x0F);
1178 *lb++ = 0x10 | ((color >> (((pattern >> 4) & 1) << 2)) & 0x0F);
1179 *lb++ = 0x10 | ((color >> (((pattern >> 3) & 1) << 2)) & 0x0F);
1180 *lb++ = 0x10 | ((color >> (((pattern >> 2) & 1) << 2)) & 0x0F);
1181 *lb++ = 0x10 | ((color >> (((pattern >> 1) & 1) << 2)) & 0x0F);
1182 *lb++ = 0x10 | ((color >> (((pattern >> 0) & 1) << 2)) & 0x0F);
1183 }
1184 while (--width);
1185 }
1186
1187 /* Text */
render_bg_m1(int line)1188 void render_bg_m1(int line)
1189 {
1190 uint8 pattern;
1191 uint8 color = reg[7];
1192
1193 uint8 *lb = &linebuf[0][0x20];
1194 uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line >> 3) * 40)];
1195 uint8 *pg = &vram[((reg[4] << 11) & 0x3800) + (line & 7)];
1196
1197 /* 40 x 6 pixels */
1198 int width = 40;
1199
1200 /* Left border (8 pixels) */
1201 memset (lb, 0x40, 8);
1202 lb += 8;
1203
1204 do
1205 {
1206 pattern = pg[*nt++ << 3];
1207
1208 *lb++ = 0x10 | ((color >> (((pattern >> 7) & 1) << 2)) & 0x0F);
1209 *lb++ = 0x10 | ((color >> (((pattern >> 6) & 1) << 2)) & 0x0F);
1210 *lb++ = 0x10 | ((color >> (((pattern >> 5) & 1) << 2)) & 0x0F);
1211 *lb++ = 0x10 | ((color >> (((pattern >> 4) & 1) << 2)) & 0x0F);
1212 *lb++ = 0x10 | ((color >> (((pattern >> 3) & 1) << 2)) & 0x0F);
1213 *lb++ = 0x10 | ((color >> (((pattern >> 2) & 1) << 2)) & 0x0F);
1214 }
1215 while (--width);
1216
1217 /* Right borders (8 pixels) */
1218 memset(lb, 0x40, 8);
1219 }
1220
1221 /* Text + extended PG */
render_bg_m1x(int line)1222 void render_bg_m1x(int line)
1223 {
1224 uint8 pattern;
1225 uint8 *pg;
1226
1227 uint8 color = reg[7];
1228
1229 uint8 *lb = &linebuf[0][0x20];
1230 uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line >> 3) * 40)];
1231
1232 uint16 pg_mask = ~0x3800 ^ (reg[4] << 11);
1233
1234 /* 40 x 6 pixels */
1235 int width = 40;
1236
1237 /* Unused bits used as a mask on TMS99xx & 315-5124 VDP only */
1238 if (system_hw > SYSTEM_SMS)
1239 {
1240 pg_mask |= 0x1800;
1241 }
1242
1243 pg = &vram[((0x2000 + ((line & 0xC0) << 5)) & pg_mask) + (line & 7)];
1244
1245 /* Left border (8 pixels) */
1246 memset (lb, 0x40, 8);
1247 lb += 8;
1248
1249 do
1250 {
1251 pattern = pg[*nt++ << 3];
1252
1253 *lb++ = 0x10 | ((color >> (((pattern >> 7) & 1) << 2)) & 0x0F);
1254 *lb++ = 0x10 | ((color >> (((pattern >> 6) & 1) << 2)) & 0x0F);
1255 *lb++ = 0x10 | ((color >> (((pattern >> 5) & 1) << 2)) & 0x0F);
1256 *lb++ = 0x10 | ((color >> (((pattern >> 4) & 1) << 2)) & 0x0F);
1257 *lb++ = 0x10 | ((color >> (((pattern >> 3) & 1) << 2)) & 0x0F);
1258 *lb++ = 0x10 | ((color >> (((pattern >> 2) & 1) << 2)) & 0x0F);
1259 }
1260 while (--width);
1261
1262 /* Right borders (8 pixels) */
1263 memset(lb, 0x40, 8);
1264 }
1265
1266 /* Graphics II */
render_bg_m2(int line)1267 void render_bg_m2(int line)
1268 {
1269 uint8 color, pattern;
1270 uint16 name;
1271 uint8 *ct, *pg;
1272
1273 uint8 *lb = &linebuf[0][0x20];
1274 uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line & 0xF8) << 2)];
1275
1276 uint16 ct_mask = ~0x3FC0 ^ (reg[3] << 6);
1277 uint16 pg_mask = ~0x3800 ^ (reg[4] << 11);
1278
1279 /* 32 x 8 pixels */
1280 int width = 32;
1281
1282 /* Unused bits used as a mask on TMS99xx & 315-5124 VDP only */
1283 if (system_hw > SYSTEM_SMS)
1284 {
1285 ct_mask |= 0x1FC0;
1286 pg_mask |= 0x1800;
1287 }
1288
1289 ct = &vram[((0x2000 + ((line & 0xC0) << 5)) & ct_mask) + (line & 7)];
1290 pg = &vram[((0x2000 + ((line & 0xC0) << 5)) & pg_mask) + (line & 7)];
1291
1292 do
1293 {
1294 name = *nt++ << 3 ;
1295 color = ct[name & ct_mask];
1296 pattern = pg[name];
1297
1298 *lb++ = 0x10 | ((color >> (((pattern >> 7) & 1) << 2)) & 0x0F);
1299 *lb++ = 0x10 | ((color >> (((pattern >> 6) & 1) << 2)) & 0x0F);
1300 *lb++ = 0x10 | ((color >> (((pattern >> 5) & 1) << 2)) & 0x0F);
1301 *lb++ = 0x10 | ((color >> (((pattern >> 4) & 1) << 2)) & 0x0F);
1302 *lb++ = 0x10 | ((color >> (((pattern >> 3) & 1) << 2)) & 0x0F);
1303 *lb++ = 0x10 | ((color >> (((pattern >> 2) & 1) << 2)) & 0x0F);
1304 *lb++ = 0x10 | ((color >> (((pattern >> 1) & 1) << 2)) & 0x0F);
1305 *lb++ = 0x10 | ((color >> (((pattern >> 0) & 1) << 2)) & 0x0F);
1306 }
1307 while (--width);
1308 }
1309
1310 /* Multicolor */
render_bg_m3(int line)1311 void render_bg_m3(int line)
1312 {
1313 uint8 color;
1314 uint8 *lb = &linebuf[0][0x20];
1315 uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line & 0xF8) << 2)];
1316 uint8 *pg = &vram[((reg[4] << 11) & 0x3800) + ((line >> 2) & 7)];
1317
1318 /* 32 x 8 pixels */
1319 int width = 32;
1320
1321 do
1322 {
1323 color = pg[*nt++ << 3];
1324
1325 *lb++ = 0x10 | ((color >> 4) & 0x0F);
1326 *lb++ = 0x10 | ((color >> 4) & 0x0F);
1327 *lb++ = 0x10 | ((color >> 4) & 0x0F);
1328 *lb++ = 0x10 | ((color >> 4) & 0x0F);
1329 *lb++ = 0x10 | ((color >> 0) & 0x0F);
1330 *lb++ = 0x10 | ((color >> 0) & 0x0F);
1331 *lb++ = 0x10 | ((color >> 0) & 0x0F);
1332 *lb++ = 0x10 | ((color >> 0) & 0x0F);
1333 }
1334 while (--width);
1335 }
1336
1337 /* Multicolor + extended PG */
render_bg_m3x(int line)1338 void render_bg_m3x(int line)
1339 {
1340 uint8 color;
1341 uint8 *pg;
1342
1343 uint8 *lb = &linebuf[0][0x20];
1344 uint8 *nt = &vram[((reg[2] << 10) & 0x3C00) + ((line & 0xF8) << 2)];
1345
1346 uint16 pg_mask = ~0x3800 ^ (reg[4] << 11);
1347
1348 /* 32 x 8 pixels */
1349 int width = 32;
1350
1351 /* Unused bits used as a mask on TMS99xx & 315-5124 VDP only */
1352 if (system_hw > SYSTEM_SMS)
1353 {
1354 pg_mask |= 0x1800;
1355 }
1356
1357 pg = &vram[((0x2000 + ((line & 0xC0) << 5)) & pg_mask) + ((line >> 2) & 7)];
1358
1359 do
1360 {
1361 color = pg[*nt++ << 3];
1362
1363 *lb++ = 0x10 | ((color >> 4) & 0x0F);
1364 *lb++ = 0x10 | ((color >> 4) & 0x0F);
1365 *lb++ = 0x10 | ((color >> 4) & 0x0F);
1366 *lb++ = 0x10 | ((color >> 4) & 0x0F);
1367 *lb++ = 0x10 | ((color >> 0) & 0x0F);
1368 *lb++ = 0x10 | ((color >> 0) & 0x0F);
1369 *lb++ = 0x10 | ((color >> 0) & 0x0F);
1370 *lb++ = 0x10 | ((color >> 0) & 0x0F);
1371 }
1372 while (--width);
1373 }
1374
1375 /* Invalid (2+3/1+2+3) */
render_bg_inv(int line)1376 void render_bg_inv(int line)
1377 {
1378 uint8 color = reg[7];
1379
1380 uint8 *lb = &linebuf[0][0x20];
1381
1382 /* 40 x 6 pixels */
1383 int width = 40;
1384
1385 /* Left border (8 pixels) */
1386 memset (lb, 0x40, 8);
1387 lb += 8;
1388
1389 do
1390 {
1391 *lb++ = 0x10 | ((color >> 4) & 0x0F);
1392 *lb++ = 0x10 | ((color >> 4) & 0x0F);
1393 *lb++ = 0x10 | ((color >> 4) & 0x0F);
1394 *lb++ = 0x10 | ((color >> 4) & 0x0F);
1395 *lb++ = 0x10 | ((color >> 0) & 0x0F);
1396 *lb++ = 0x10 | ((color >> 0) & 0x0F);
1397 }
1398 while (--width);
1399
1400 /* Right borders (8 pixels) */
1401 memset(lb, 0x40, 8);
1402 }
1403
1404 /* Mode 4 */
render_bg_m4(int line)1405 void render_bg_m4(int line)
1406 {
1407 int column;
1408 uint16 *nt;
1409 uint32 attr, atex, *src;
1410
1411 /* 32 x 8 pixels */
1412 int width = 32;
1413
1414 /* Horizontal scrolling */
1415 int index = ((reg[0] & 0x40) && (line < 0x10)) ? 0x100 : reg[0x08];
1416 int shift = index & 7;
1417
1418 /* Background line buffer */
1419 uint32 *dst = (uint32 *)&linebuf[0][0x20 + shift];
1420
1421 /* Vertical scrolling */
1422 int v_line = line + vscroll;
1423
1424 /* Pattern name table mask */
1425 uint16 nt_mask = ~0x3C00 ^ (reg[2] << 10);
1426
1427 /* Unused bits used as a mask on TMS99xx & 315-5124 VDP only */
1428 if (system_hw > SYSTEM_SMS)
1429 {
1430 nt_mask |= 0x400;
1431 }
1432
1433 /* Test for extended modes (Master System II & Game gear VDP only) */
1434 if (bitmap.viewport.h > 192)
1435 {
1436 /* Vertical scroll mask */
1437 v_line = v_line % 256;
1438
1439 /* Pattern name Table */
1440 nt = (uint16 *)&vram[(0x3700 & nt_mask) + ((v_line >> 3) << 6)];
1441 }
1442 else
1443 {
1444 /* Vertical scroll mask */
1445 v_line = v_line % 224;
1446
1447 /* Pattern name Table */
1448 nt = (uint16 *)&vram[(0x3800 + ((v_line >> 3) << 6)) & nt_mask];
1449 }
1450
1451 /* Pattern row index */
1452 v_line = (v_line & 7) << 3;
1453
1454 /* Tile column index */
1455 index = (0x100 - index) >> 3;
1456
1457 /* Clip left-most column if required */
1458 if (shift)
1459 {
1460 memset(&linebuf[0][0x20], 0, shift);
1461 index++;
1462 }
1463
1464 /* Draw tiles */
1465 for(column = 0; column < width; column++, index++)
1466 {
1467 /* Stop vertical scrolling for rightmost eight tiles */
1468 if((column == 24) && (reg[0] & 0x80))
1469 {
1470 /* Clear Pattern name table start address */
1471 if (bitmap.viewport.h > 192)
1472 {
1473 nt = (uint16 *)&vram[(0x3700 & nt_mask) + ((line >> 3) << 6)];
1474 }
1475 else
1476 {
1477 nt = (uint16 *)&vram[(0x3800 + ((line >> 3) << 6)) & nt_mask];
1478 }
1479
1480 /* Clear Pattern row index */
1481 v_line = (line & 7) << 3;
1482 }
1483
1484 /* Read name table attribute word */
1485 attr = nt[index % width];
1486 #ifndef LSB_FIRST
1487 attr = (((attr & 0xFF) << 8) | ((attr & 0xFF00) >> 8));
1488 #endif
1489
1490 /* Expand priority and palette bits */
1491 atex = atex_table[(attr >> 11) & 3];
1492
1493 /* Cached pattern data line (4 bytes = 4 pixels at once) */
1494 src = (uint32 *)&bg_pattern_cache[((attr & 0x7FF) << 6) | (v_line)];
1495
1496 /* Copy left & right half, adding the attribute bits in */
1497 #ifdef ALIGN_LONG
1498 WRITE_LONG(dst, src[0] | atex);
1499 dst++;
1500 WRITE_LONG(dst, src[1] | atex);
1501 dst++;
1502 #else
1503 *dst++ = (src[0] | atex);
1504 *dst++ = (src[1] | atex);
1505 #endif
1506 }
1507 }
1508
1509 /* Mode 5 */
1510 #ifndef ALT_RENDERER
render_bg_m5(int line)1511 void render_bg_m5(int line)
1512 {
1513 int column;
1514 uint32 atex, atbuf, *src, *dst;
1515
1516 /* Common data */
1517 uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
1518 uint32 yscroll = *(uint32 *)&vsram[0];
1519 uint32 pf_col_mask = playfield_col_mask;
1520 uint32 pf_row_mask = playfield_row_mask;
1521 uint32 pf_shift = playfield_shift;
1522
1523 /* Window & Plane A */
1524 int a = (reg[18] & 0x1F) << 3;
1525 int w = (reg[18] >> 7) & 1;
1526
1527 /* Plane B width */
1528 int start = 0;
1529 int end = bitmap.viewport.w >> 4;
1530
1531 /* Plane B scroll */
1532 #ifdef LSB_FIRST
1533 uint32 shift = (xscroll >> 16) & 0x0F;
1534 uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
1535 uint32 v_line = (line + (yscroll >> 16)) & pf_row_mask;
1536 #else
1537 uint32 shift = (xscroll & 0x0F);
1538 uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
1539 uint32 v_line = (line + yscroll) & pf_row_mask;
1540 #endif
1541
1542 /* Plane B name table */
1543 uint32 *nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
1544
1545 /* Pattern row index */
1546 v_line = (v_line & 7) << 3;
1547
1548 if(shift)
1549 {
1550 /* Plane B line buffer */
1551 dst = (uint32 *)&linebuf[0][0x10 + shift];
1552
1553 atbuf = nt[(index - 1) & pf_col_mask];
1554 DRAW_COLUMN(atbuf, v_line)
1555 }
1556 else
1557 {
1558 /* Plane B line buffer */
1559 dst = (uint32 *)&linebuf[0][0x20];
1560 }
1561
1562 for(column = 0; column < end; column++, index++)
1563 {
1564 atbuf = nt[index & pf_col_mask];
1565 DRAW_COLUMN(atbuf, v_line)
1566 }
1567
1568 if (w == (line >= a))
1569 {
1570 /* Window takes up entire line */
1571 a = 0;
1572 w = 1;
1573 }
1574 else
1575 {
1576 /* Window and Plane A share the line */
1577 a = clip[0].enable;
1578 w = clip[1].enable;
1579 }
1580
1581 /* Plane A */
1582 if (a)
1583 {
1584 /* Plane A width */
1585 start = clip[0].left;
1586 end = clip[0].right;
1587
1588 /* Plane A scroll */
1589 #ifdef LSB_FIRST
1590 shift = (xscroll & 0x0F);
1591 index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
1592 v_line = (line + yscroll) & pf_row_mask;
1593 #else
1594 shift = (xscroll >> 16) & 0x0F;
1595 index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
1596 v_line = (line + (yscroll >> 16)) & pf_row_mask;
1597 #endif
1598
1599 /* Plane A name table */
1600 nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
1601
1602 /* Pattern row index */
1603 v_line = (v_line & 7) << 3;
1604
1605 if(shift)
1606 {
1607 /* Plane A line buffer */
1608 dst = (uint32 *)&linebuf[1][0x10 + shift + (start << 4)];
1609
1610 /* Window bug */
1611 if (start)
1612 {
1613 atbuf = nt[index & pf_col_mask];
1614 }
1615 else
1616 {
1617 atbuf = nt[(index - 1) & pf_col_mask];
1618 }
1619
1620 DRAW_COLUMN(atbuf, v_line)
1621 }
1622 else
1623 {
1624 /* Plane A line buffer */
1625 dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
1626 }
1627
1628 for(column = start; column < end; column++, index++)
1629 {
1630 atbuf = nt[index & pf_col_mask];
1631 DRAW_COLUMN(atbuf, v_line)
1632 }
1633
1634 /* Window width */
1635 start = clip[1].left;
1636 end = clip[1].right;
1637 }
1638
1639 /* Window */
1640 if (w)
1641 {
1642 /* Window name table */
1643 nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
1644
1645 /* Pattern row index */
1646 v_line = (line & 7) << 3;
1647
1648 /* Plane A line buffer */
1649 dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
1650
1651 for(column = start; column < end; column++)
1652 {
1653 atbuf = nt[column];
1654 DRAW_COLUMN(atbuf, v_line)
1655 }
1656 }
1657
1658 /* Merge background layers */
1659 merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[(reg[12] & 0x08) >> 2], bitmap.viewport.w);
1660 }
1661
render_bg_m5_vs(int line)1662 void render_bg_m5_vs(int line)
1663 {
1664 int column;
1665 uint32 atex, atbuf, *src, *dst;
1666 uint32 v_line, *nt;
1667
1668 /* Common data */
1669 uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
1670 uint32 yscroll = 0;
1671 uint32 pf_col_mask = playfield_col_mask;
1672 uint32 pf_row_mask = playfield_row_mask;
1673 uint32 pf_shift = playfield_shift;
1674 uint32 *vs = (uint32 *)&vsram[0];
1675
1676 /* Window & Plane A */
1677 int a = (reg[18] & 0x1F) << 3;
1678 int w = (reg[18] >> 7) & 1;
1679
1680 /* Plane B width */
1681 int start = 0;
1682 int end = bitmap.viewport.w >> 4;
1683
1684 /* Plane B horizontal scroll */
1685 #ifdef LSB_FIRST
1686 uint32 shift = (xscroll >> 16) & 0x0F;
1687 uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
1688 #else
1689 uint32 shift = (xscroll & 0x0F);
1690 uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
1691 #endif
1692
1693 /* Left-most column vertical scrolling when partially shown horizontally (verified on PAL MD2) */
1694 /* TODO: check on Genesis 3 models since it apparently behaves differently */
1695 /* In H32 mode, vertical scrolling is disabled, in H40 mode, same value is used for both planes */
1696 /* See Formula One / Kawasaki Superbike Challenge (H32) & Gynoug / Cutie Suzuki no Ringside Angel (H40) */
1697 if (reg[12] & 1)
1698 {
1699 yscroll = vs[19] & (vs[19] >> 16);
1700 }
1701
1702 if(shift)
1703 {
1704 /* Plane B vertical scroll */
1705 v_line = (line + yscroll) & pf_row_mask;
1706
1707 /* Plane B name table */
1708 nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
1709
1710 /* Pattern row index */
1711 v_line = (v_line & 7) << 3;
1712
1713 /* Plane B line buffer */
1714 dst = (uint32 *)&linebuf[0][0x10 + shift];
1715
1716 atbuf = nt[(index - 1) & pf_col_mask];
1717 DRAW_COLUMN(atbuf, v_line)
1718 }
1719 else
1720 {
1721 /* Plane B line buffer */
1722 dst = (uint32 *)&linebuf[0][0x20];
1723 }
1724
1725 for(column = 0; column < end; column++, index++)
1726 {
1727 /* Plane B vertical scroll */
1728 #ifdef LSB_FIRST
1729 v_line = (line + (vs[column] >> 16)) & pf_row_mask;
1730 #else
1731 v_line = (line + vs[column]) & pf_row_mask;
1732 #endif
1733
1734 /* Plane B name table */
1735 nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
1736
1737 /* Pattern row index */
1738 v_line = (v_line & 7) << 3;
1739
1740 atbuf = nt[index & pf_col_mask];
1741 DRAW_COLUMN(atbuf, v_line)
1742 }
1743
1744 if (w == (line >= a))
1745 {
1746 /* Window takes up entire line */
1747 a = 0;
1748 w = 1;
1749 }
1750 else
1751 {
1752 /* Window and Plane A share the line */
1753 a = clip[0].enable;
1754 w = clip[1].enable;
1755 }
1756
1757 /* Plane A */
1758 if (a)
1759 {
1760 /* Plane A width */
1761 start = clip[0].left;
1762 end = clip[0].right;
1763
1764 /* Plane A horizontal scroll */
1765 #ifdef LSB_FIRST
1766 shift = (xscroll & 0x0F);
1767 index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
1768 #else
1769 shift = (xscroll >> 16) & 0x0F;
1770 index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
1771 #endif
1772
1773 if(shift)
1774 {
1775 /* Plane A vertical scroll */
1776 v_line = (line + yscroll) & pf_row_mask;
1777
1778 /* Plane A name table */
1779 nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
1780
1781 /* Pattern row index */
1782 v_line = (v_line & 7) << 3;
1783
1784 /* Plane A line buffer */
1785 dst = (uint32 *)&linebuf[1][0x10 + shift + (start << 4)];
1786
1787 /* Window bug */
1788 if (start)
1789 {
1790 atbuf = nt[index & pf_col_mask];
1791 }
1792 else
1793 {
1794 atbuf = nt[(index - 1) & pf_col_mask];
1795 }
1796
1797 DRAW_COLUMN(atbuf, v_line)
1798 }
1799 else
1800 {
1801 /* Plane A line buffer */
1802 dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
1803 }
1804
1805 for(column = start; column < end; column++, index++)
1806 {
1807 /* Plane A vertical scroll */
1808 #ifdef LSB_FIRST
1809 v_line = (line + vs[column]) & pf_row_mask;
1810 #else
1811 v_line = (line + (vs[column] >> 16)) & pf_row_mask;
1812 #endif
1813
1814 /* Plane A name table */
1815 nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
1816
1817 /* Pattern row index */
1818 v_line = (v_line & 7) << 3;
1819
1820 atbuf = nt[index & pf_col_mask];
1821 DRAW_COLUMN(atbuf, v_line)
1822 }
1823
1824 /* Window width */
1825 start = clip[1].left;
1826 end = clip[1].right;
1827 }
1828
1829 /* Window */
1830 if (w)
1831 {
1832 /* Window name table */
1833 nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
1834
1835 /* Pattern row index */
1836 v_line = (line & 7) << 3;
1837
1838 /* Plane A line buffer */
1839 dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
1840
1841 for(column = start; column < end; column++)
1842 {
1843 atbuf = nt[column];
1844 DRAW_COLUMN(atbuf, v_line)
1845 }
1846 }
1847
1848 /* Merge background layers */
1849 merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[(reg[12] & 0x08) >> 2], bitmap.viewport.w);
1850 }
1851
render_bg_m5_im2(int line)1852 void render_bg_m5_im2(int line)
1853 {
1854 int column;
1855 uint32 atex, atbuf, *src, *dst;
1856
1857 /* Common data */
1858 int odd = odd_frame;
1859 uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
1860 uint32 yscroll = *(uint32 *)&vsram[0];
1861 uint32 pf_col_mask = playfield_col_mask;
1862 uint32 pf_row_mask = playfield_row_mask;
1863 uint32 pf_shift = playfield_shift;
1864
1865 /* Window & Plane A */
1866 int a = (reg[18] & 0x1F) << 3;
1867 int w = (reg[18] >> 7) & 1;
1868
1869 /* Plane B width */
1870 int start = 0;
1871 int end = bitmap.viewport.w >> 4;
1872
1873 /* Plane B scroll */
1874 #ifdef LSB_FIRST
1875 uint32 shift = (xscroll >> 16) & 0x0F;
1876 uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
1877 uint32 v_line = (line + (yscroll >> 17)) & pf_row_mask;
1878 #else
1879 uint32 shift = (xscroll & 0x0F);
1880 uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
1881 uint32 v_line = (line + (yscroll >> 1)) & pf_row_mask;
1882 #endif
1883
1884 /* Plane B name table */
1885 uint32 *nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
1886
1887 /* Pattern row index */
1888 v_line = (((v_line & 7) << 1) | odd) << 3;
1889
1890 if(shift)
1891 {
1892 /* Plane B line buffer */
1893 dst = (uint32 *)&linebuf[0][0x10 + shift];
1894
1895 atbuf = nt[(index - 1) & pf_col_mask];
1896 DRAW_COLUMN_IM2(atbuf, v_line)
1897 }
1898 else
1899 {
1900 /* Plane B line buffer */
1901 dst = (uint32 *)&linebuf[0][0x20];
1902 }
1903
1904 for(column = 0; column < end; column++, index++)
1905 {
1906 atbuf = nt[index & pf_col_mask];
1907 DRAW_COLUMN_IM2(atbuf, v_line)
1908 }
1909
1910 if (w == (line >= a))
1911 {
1912 /* Window takes up entire line */
1913 a = 0;
1914 w = 1;
1915 }
1916 else
1917 {
1918 /* Window and Plane A share the line */
1919 a = clip[0].enable;
1920 w = clip[1].enable;
1921 }
1922
1923 /* Plane A */
1924 if (a)
1925 {
1926 /* Plane A width */
1927 start = clip[0].left;
1928 end = clip[0].right;
1929
1930 /* Plane A scroll */
1931 #ifdef LSB_FIRST
1932 shift = (xscroll & 0x0F);
1933 index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
1934 v_line = (line + (yscroll >> 1)) & pf_row_mask;
1935 #else
1936 shift = (xscroll >> 16) & 0x0F;
1937 index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
1938 v_line = (line + (yscroll >> 17)) & pf_row_mask;
1939 #endif
1940
1941 /* Plane A name table */
1942 nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
1943
1944 /* Pattern row index */
1945 v_line = (((v_line & 7) << 1) | odd) << 3;
1946
1947 if(shift)
1948 {
1949 /* Plane A line buffer */
1950 dst = (uint32 *)&linebuf[1][0x10 + shift + (start << 4)];
1951
1952 /* Window bug */
1953 if (start)
1954 {
1955 atbuf = nt[index & pf_col_mask];
1956 }
1957 else
1958 {
1959 atbuf = nt[(index - 1) & pf_col_mask];
1960 }
1961
1962 DRAW_COLUMN_IM2(atbuf, v_line)
1963 }
1964 else
1965 {
1966 /* Plane A line buffer */
1967 dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
1968 }
1969
1970 for(column = start; column < end; column++, index++)
1971 {
1972 atbuf = nt[index & pf_col_mask];
1973 DRAW_COLUMN_IM2(atbuf, v_line)
1974 }
1975
1976 /* Window width */
1977 start = clip[1].left;
1978 end = clip[1].right;
1979 }
1980
1981 /* Window */
1982 if (w)
1983 {
1984 /* Window name table */
1985 nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
1986
1987 /* Pattern row index */
1988 v_line = ((line & 7) << 1 | odd) << 3;
1989
1990 /* Plane A line buffer */
1991 dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
1992
1993 for(column = start; column < end; column++)
1994 {
1995 atbuf = nt[column];
1996 DRAW_COLUMN_IM2(atbuf, v_line)
1997 }
1998 }
1999
2000 /* Merge background layers */
2001 merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[(reg[12] & 0x08) >> 2], bitmap.viewport.w);
2002 }
2003
render_bg_m5_im2_vs(int line)2004 void render_bg_m5_im2_vs(int line)
2005 {
2006 int column;
2007 uint32 atex, atbuf, *src, *dst;
2008 uint32 v_line, *nt;
2009
2010 /* Common data */
2011 int odd = odd_frame;
2012 uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
2013 uint32 yscroll = 0;
2014 uint32 pf_col_mask = playfield_col_mask;
2015 uint32 pf_row_mask = playfield_row_mask;
2016 uint32 pf_shift = playfield_shift;
2017 uint32 *vs = (uint32 *)&vsram[0];
2018
2019 /* Window & Plane A */
2020 int a = (reg[18] & 0x1F) << 3;
2021 int w = (reg[18] >> 7) & 1;
2022
2023 /* Plane B width */
2024 int start = 0;
2025 int end = bitmap.viewport.w >> 4;
2026
2027 /* Plane B horizontal scroll */
2028 #ifdef LSB_FIRST
2029 uint32 shift = (xscroll >> 16) & 0x0F;
2030 uint32 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
2031 #else
2032 uint32 shift = (xscroll & 0x0F);
2033 uint32 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
2034 #endif
2035
2036 /* Left-most column vertical scrolling when partially shown horizontally (verified on PAL MD2) */
2037 /* TODO: check on Genesis 3 models since it apparently behaves differently */
2038 /* In H32 mode, vertical scrolling is disabled, in H40 mode, same value is used for both planes */
2039 /* See Formula One / Kawasaki Superbike Challenge (H32) & Gynoug / Cutie Suzuki no Ringside Angel (H40) */
2040 if (reg[12] & 1)
2041 {
2042 yscroll = (vs[19] >> 1) & (vs[19] >> 17);
2043 }
2044
2045 if(shift)
2046 {
2047 /* Plane B vertical scroll */
2048 v_line = (line + yscroll) & pf_row_mask;
2049
2050 /* Plane B name table */
2051 nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2052
2053 /* Pattern row index */
2054 v_line = (((v_line & 7) << 1) | odd) << 3;
2055
2056 /* Plane B line buffer */
2057 dst = (uint32 *)&linebuf[0][0x10 + shift];
2058
2059 atbuf = nt[(index - 1) & pf_col_mask];
2060 DRAW_COLUMN_IM2(atbuf, v_line)
2061 }
2062 else
2063 {
2064 /* Plane B line buffer */
2065 dst = (uint32 *)&linebuf[0][0x20];
2066 }
2067
2068 for(column = 0; column < end; column++, index++)
2069 {
2070 /* Plane B vertical scroll */
2071 #ifdef LSB_FIRST
2072 v_line = (line + (vs[column] >> 17)) & pf_row_mask;
2073 #else
2074 v_line = (line + (vs[column] >> 1)) & pf_row_mask;
2075 #endif
2076
2077 /* Plane B name table */
2078 nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2079
2080 /* Pattern row index */
2081 v_line = (((v_line & 7) << 1) | odd) << 3;
2082
2083 atbuf = nt[index & pf_col_mask];
2084 DRAW_COLUMN_IM2(atbuf, v_line)
2085 }
2086
2087 if (w == (line >= a))
2088 {
2089 /* Window takes up entire line */
2090 a = 0;
2091 w = 1;
2092 }
2093 else
2094 {
2095 /* Window and Plane A share the line */
2096 a = clip[0].enable;
2097 w = clip[1].enable;
2098 }
2099
2100 /* Plane A */
2101 if (a)
2102 {
2103 /* Plane A width */
2104 start = clip[0].left;
2105 end = clip[0].right;
2106
2107 /* Plane A horizontal scroll */
2108 #ifdef LSB_FIRST
2109 shift = (xscroll & 0x0F);
2110 index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
2111 #else
2112 shift = (xscroll >> 16) & 0x0F;
2113 index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
2114 #endif
2115
2116 if(shift)
2117 {
2118 /* Plane A vertical scroll */
2119 v_line = (line + yscroll) & pf_row_mask;
2120
2121 /* Plane A name table */
2122 nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2123
2124 /* Pattern row index */
2125 v_line = (((v_line & 7) << 1) | odd) << 3;
2126
2127 /* Plane A line buffer */
2128 dst = (uint32 *)&linebuf[1][0x10 + shift + (start << 4)];
2129
2130 /* Window bug */
2131 if (start)
2132 {
2133 atbuf = nt[index & pf_col_mask];
2134 }
2135 else
2136 {
2137 atbuf = nt[(index - 1) & pf_col_mask];
2138 }
2139
2140 DRAW_COLUMN_IM2(atbuf, v_line)
2141 }
2142 else
2143 {
2144 /* Plane A line buffer */
2145 dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
2146 }
2147
2148 for(column = start; column < end; column++, index++)
2149 {
2150 /* Plane A vertical scroll */
2151 #ifdef LSB_FIRST
2152 v_line = (line + (vs[column] >> 1)) & pf_row_mask;
2153 #else
2154 v_line = (line + (vs[column] >> 17)) & pf_row_mask;
2155 #endif
2156
2157 /* Plane A name table */
2158 nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2159
2160 /* Pattern row index */
2161 v_line = (((v_line & 7) << 1) | odd) << 3;
2162
2163 atbuf = nt[index & pf_col_mask];
2164 DRAW_COLUMN_IM2(atbuf, v_line)
2165 }
2166
2167 /* Window width */
2168 start = clip[1].left;
2169 end = clip[1].right;
2170 }
2171
2172 /* Window */
2173 if (w)
2174 {
2175 /* Window name table */
2176 nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
2177
2178 /* Pattern row index */
2179 v_line = ((line & 7) << 1 | odd) << 3;
2180
2181 /* Plane A line buffer */
2182 dst = (uint32 *)&linebuf[1][0x20 + (start << 4)];
2183
2184 for(column = start; column < end; column++)
2185 {
2186 atbuf = nt[column];
2187 DRAW_COLUMN_IM2(atbuf, v_line)
2188 }
2189 }
2190
2191 /* Merge background layers */
2192 merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[(reg[12] & 0x08) >> 2], bitmap.viewport.w);
2193 }
2194
2195 #else
2196
render_bg_m5(int line)2197 void render_bg_m5(int line)
2198 {
2199 int column, start, end;
2200 uint32 atex, atbuf, *src, *dst;
2201 uint32 shift, index, v_line, *nt;
2202 uint8 *lb;
2203
2204 /* Scroll Planes common data */
2205 uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
2206 uint32 yscroll = *(uint32 *)&vsram[0];
2207 uint32 pf_col_mask = playfield_col_mask;
2208 uint32 pf_row_mask = playfield_row_mask;
2209 uint32 pf_shift = playfield_shift;
2210
2211 /* Number of columns to draw */
2212 int width = bitmap.viewport.w >> 4;
2213
2214 /* Layer priority table */
2215 uint8 *table = lut[(reg[12] & 8) >> 2];
2216
2217 /* Window vertical range (cell 0-31) */
2218 int a = (reg[18] & 0x1F) << 3;
2219
2220 /* Window position (0=top, 1=bottom) */
2221 int w = (reg[18] >> 7) & 1;
2222
2223 /* Test against current line */
2224 if (w == (line >= a))
2225 {
2226 /* Window takes up entire line */
2227 a = 0;
2228 w = 1;
2229 }
2230 else
2231 {
2232 /* Window and Plane A share the line */
2233 a = clip[0].enable;
2234 w = clip[1].enable;
2235 }
2236
2237 /* Plane A */
2238 if (a)
2239 {
2240 /* Plane A width */
2241 start = clip[0].left;
2242 end = clip[0].right;
2243
2244 /* Plane A scroll */
2245 #ifdef LSB_FIRST
2246 shift = (xscroll & 0x0F);
2247 index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
2248 v_line = (line + yscroll) & pf_row_mask;
2249 #else
2250 shift = (xscroll >> 16) & 0x0F;
2251 index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
2252 v_line = (line + (yscroll >> 16)) & pf_row_mask;
2253 #endif
2254
2255 /* Background line buffer */
2256 dst = (uint32 *)&linebuf[0][0x20 + (start << 4) + shift];
2257
2258 /* Plane A name table */
2259 nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2260
2261 /* Pattern row index */
2262 v_line = (v_line & 7) << 3;
2263
2264 if(shift)
2265 {
2266 /* Left-most column is partially shown */
2267 dst -= 4;
2268
2269 /* Window bug */
2270 if (start)
2271 {
2272 atbuf = nt[index & pf_col_mask];
2273 }
2274 else
2275 {
2276 atbuf = nt[(index-1) & pf_col_mask];
2277 }
2278
2279 DRAW_COLUMN(atbuf, v_line)
2280 }
2281
2282 for(column = start; column < end; column++, index++)
2283 {
2284 atbuf = nt[index & pf_col_mask];
2285 DRAW_COLUMN(atbuf, v_line)
2286 }
2287
2288 /* Window width */
2289 start = clip[1].left;
2290 end = clip[1].right;
2291 }
2292 else
2293 {
2294 /* Window width */
2295 start = 0;
2296 end = width;
2297 }
2298
2299 /* Window Plane */
2300 if (w)
2301 {
2302 /* Background line buffer */
2303 dst = (uint32 *)&linebuf[0][0x20 + (start << 4)];
2304
2305 /* Window name table */
2306 nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
2307
2308 /* Pattern row index */
2309 v_line = (line & 7) << 3;
2310
2311 for(column = start; column < end; column++)
2312 {
2313 atbuf = nt[column];
2314 DRAW_COLUMN(atbuf, v_line)
2315 }
2316 }
2317
2318 /* Plane B scroll */
2319 #ifdef LSB_FIRST
2320 shift = (xscroll >> 16) & 0x0F;
2321 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
2322 v_line = (line + (yscroll >> 16)) & pf_row_mask;
2323 #else
2324 shift = (xscroll & 0x0F);
2325 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
2326 v_line = (line + yscroll) & pf_row_mask;
2327 #endif
2328
2329 /* Plane B name table */
2330 nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2331
2332 /* Pattern row index */
2333 v_line = (v_line & 7) << 3;
2334
2335 /* Background line buffer */
2336 lb = &linebuf[0][0x20];
2337
2338 if(shift)
2339 {
2340 /* Left-most column is partially shown */
2341 lb -= (0x10 - shift);
2342
2343 atbuf = nt[(index-1) & pf_col_mask];
2344 DRAW_BG_COLUMN(atbuf, v_line, xscroll, yscroll)
2345 }
2346
2347 for(column = 0; column < width; column++, index++)
2348 {
2349 atbuf = nt[index & pf_col_mask];
2350 DRAW_BG_COLUMN(atbuf, v_line, xscroll, yscroll)
2351 }
2352 }
2353
render_bg_m5_vs(int line)2354 void render_bg_m5_vs(int line)
2355 {
2356 int column, start, end;
2357 uint32 atex, atbuf, *src, *dst;
2358 uint32 shift, index, v_line, *nt;
2359 uint8 *lb;
2360
2361 /* Scroll Planes common data */
2362 uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
2363 uint32 yscroll = 0;
2364 uint32 pf_col_mask = playfield_col_mask;
2365 uint32 pf_row_mask = playfield_row_mask;
2366 uint32 pf_shift = playfield_shift;
2367 uint32 *vs = (uint32 *)&vsram[0];
2368
2369 /* Number of columns to draw */
2370 int width = bitmap.viewport.w >> 4;
2371
2372 /* Layer priority table */
2373 uint8 *table = lut[(reg[12] & 8) >> 2];
2374
2375 /* Window vertical range (cell 0-31) */
2376 int a = (reg[18] & 0x1F) << 3;
2377
2378 /* Window position (0=top, 1=bottom) */
2379 int w = (reg[18] >> 7) & 1;
2380
2381 /* Test against current line */
2382 if (w == (line >= a))
2383 {
2384 /* Window takes up entire line */
2385 a = 0;
2386 w = 1;
2387 }
2388 else
2389 {
2390 /* Window and Plane A share the line */
2391 a = clip[0].enable;
2392 w = clip[1].enable;
2393 }
2394
2395 /* Left-most column vertical scrolling when partially shown horizontally */
2396 /* Same value for both planes, only in 40-cell mode, verified on PAL MD2 */
2397 /* See Gynoug, Cutie Suzuki no Ringside Angel, Formula One, Kawasaki Superbike Challenge */
2398 if (reg[12] & 1)
2399 {
2400 yscroll = vs[19] & (vs[19] >> 16);
2401 }
2402
2403 /* Plane A*/
2404 if (a)
2405 {
2406 /* Plane A width */
2407 start = clip[0].left;
2408 end = clip[0].right;
2409
2410 /* Plane A horizontal scroll */
2411 #ifdef LSB_FIRST
2412 shift = (xscroll & 0x0F);
2413 index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
2414 #else
2415 shift = (xscroll >> 16) & 0x0F;
2416 index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
2417 #endif
2418
2419 /* Background line buffer */
2420 dst = (uint32 *)&linebuf[0][0x20 + (start << 4) + shift];
2421
2422 if(shift)
2423 {
2424 /* Left-most column is partially shown */
2425 dst -= 4;
2426
2427 /* Plane A vertical scroll */
2428 v_line = (line + yscroll) & pf_row_mask;
2429
2430 /* Plane A name table */
2431 nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2432
2433 /* Pattern row index */
2434 v_line = (v_line & 7) << 3;
2435
2436 /* Window bug */
2437 if (start)
2438 {
2439 atbuf = nt[index & pf_col_mask];
2440 }
2441 else
2442 {
2443 atbuf = nt[(index-1) & pf_col_mask];
2444 }
2445
2446 DRAW_COLUMN(atbuf, v_line)
2447 }
2448
2449 for(column = start; column < end; column++, index++)
2450 {
2451 /* Plane A vertical scroll */
2452 #ifdef LSB_FIRST
2453 v_line = (line + vs[column]) & pf_row_mask;
2454 #else
2455 v_line = (line + (vs[column] >> 16)) & pf_row_mask;
2456 #endif
2457
2458 /* Plane A name table */
2459 nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2460
2461 /* Pattern row index */
2462 v_line = (v_line & 7) << 3;
2463
2464 atbuf = nt[index & pf_col_mask];
2465 DRAW_COLUMN(atbuf, v_line)
2466 }
2467
2468 /* Window width */
2469 start = clip[1].left;
2470 end = clip[1].right;
2471 }
2472 else
2473 {
2474 /* Window width */
2475 start = 0;
2476 end = width;
2477 }
2478
2479 /* Window Plane */
2480 if (w)
2481 {
2482 /* Background line buffer */
2483 dst = (uint32 *)&linebuf[0][0x20 + (start << 4)];
2484
2485 /* Window name table */
2486 nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
2487
2488 /* Pattern row index */
2489 v_line = (line & 7) << 3;
2490
2491 for(column = start; column < end; column++)
2492 {
2493 atbuf = nt[column];
2494 DRAW_COLUMN(atbuf, v_line)
2495 }
2496 }
2497
2498 /* Plane B horizontal scroll */
2499 #ifdef LSB_FIRST
2500 shift = (xscroll >> 16) & 0x0F;
2501 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
2502 #else
2503 shift = (xscroll & 0x0F);
2504 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
2505 #endif
2506
2507 /* Background line buffer */
2508 lb = &linebuf[0][0x20];
2509
2510 if(shift)
2511 {
2512 /* Left-most column is partially shown */
2513 lb -= (0x10 - shift);
2514
2515 /* Plane B vertical scroll */
2516 v_line = (line + yscroll) & pf_row_mask;
2517
2518 /* Plane B name table */
2519 nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2520
2521 /* Pattern row index */
2522 v_line = (v_line & 7) << 3;
2523
2524 atbuf = nt[(index-1) & pf_col_mask];
2525 DRAW_BG_COLUMN(atbuf, v_line, xscroll, yscroll)
2526 }
2527
2528 for(column = 0; column < width; column++, index++)
2529 {
2530 /* Plane B vertical scroll */
2531 #ifdef LSB_FIRST
2532 v_line = (line + (vs[column] >> 16)) & pf_row_mask;
2533 #else
2534 v_line = (line + vs[column]) & pf_row_mask;
2535 #endif
2536
2537 /* Plane B name table */
2538 nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2539
2540 /* Pattern row index */
2541 v_line = (v_line & 7) << 3;
2542
2543 atbuf = nt[index & pf_col_mask];
2544 DRAW_BG_COLUMN(atbuf, v_line, xscroll, yscroll)
2545 }
2546 }
2547
render_bg_m5_im2(int line)2548 void render_bg_m5_im2(int line)
2549 {
2550 int column, start, end;
2551 uint32 atex, atbuf, *src, *dst;
2552 uint32 shift, index, v_line, *nt;
2553 uint8 *lb;
2554
2555 /* Scroll Planes common data */
2556 int odd = odd_frame;
2557 uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
2558 uint32 yscroll = *(uint32 *)&vsram[0];
2559 uint32 pf_col_mask = playfield_col_mask;
2560 uint32 pf_row_mask = playfield_row_mask;
2561 uint32 pf_shift = playfield_shift;
2562
2563 /* Number of columns to draw */
2564 int width = bitmap.viewport.w >> 4;
2565
2566 /* Layer priority table */
2567 uint8 *table = lut[(reg[12] & 8) >> 2];
2568
2569 /* Window vertical range (cell 0-31) */
2570 int a = (reg[18] & 0x1F) << 3;
2571
2572 /* Window position (0=top, 1=bottom) */
2573 int w = (reg[18] >> 7) & 1;
2574
2575 /* Test against current line */
2576 if (w == (line >= a))
2577 {
2578 /* Window takes up entire line */
2579 a = 0;
2580 w = 1;
2581 }
2582 else
2583 {
2584 /* Window and Plane A share the line */
2585 a = clip[0].enable;
2586 w = clip[1].enable;
2587 }
2588
2589 /* Plane A */
2590 if (a)
2591 {
2592 /* Plane A width */
2593 start = clip[0].left;
2594 end = clip[0].right;
2595
2596 /* Plane A scroll */
2597 #ifdef LSB_FIRST
2598 shift = (xscroll & 0x0F);
2599 index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
2600 v_line = (line + (yscroll >> 1)) & pf_row_mask;
2601 #else
2602 shift = (xscroll >> 16) & 0x0F;
2603 index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
2604 v_line = (line + (yscroll >> 17)) & pf_row_mask;
2605 #endif
2606
2607 /* Background line buffer */
2608 dst = (uint32 *)&linebuf[0][0x20 + (start << 4) + shift];
2609
2610 /* Plane A name table */
2611 nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2612
2613 /* Pattern row index */
2614 v_line = (((v_line & 7) << 1) | odd) << 3;
2615
2616 if(shift)
2617 {
2618 /* Left-most column is partially shown */
2619 dst -= 4;
2620
2621 /* Window bug */
2622 if (start)
2623 {
2624 atbuf = nt[index & pf_col_mask];
2625 }
2626 else
2627 {
2628 atbuf = nt[(index-1) & pf_col_mask];
2629 }
2630
2631 DRAW_COLUMN_IM2(atbuf, v_line)
2632 }
2633
2634 for(column = start; column < end; column++, index++)
2635 {
2636 atbuf = nt[index & pf_col_mask];
2637 DRAW_COLUMN_IM2(atbuf, v_line)
2638 }
2639
2640 /* Window width */
2641 start = clip[1].left;
2642 end = clip[1].right;
2643 }
2644 else
2645 {
2646 /* Window width */
2647 start = 0;
2648 end = width;
2649 }
2650
2651 /* Window Plane */
2652 if (w)
2653 {
2654 /* Background line buffer */
2655 dst = (uint32 *)&linebuf[0][0x20 + (start << 4)];
2656
2657 /* Window name table */
2658 nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
2659
2660 /* Pattern row index */
2661 v_line = ((line & 7) << 1 | odd) << 3;
2662
2663 for(column = start; column < end; column++)
2664 {
2665 atbuf = nt[column];
2666 DRAW_COLUMN_IM2(atbuf, v_line)
2667 }
2668 }
2669
2670 /* Plane B scroll */
2671 #ifdef LSB_FIRST
2672 shift = (xscroll >> 16) & 0x0F;
2673 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
2674 v_line = (line + (yscroll >> 17)) & pf_row_mask;
2675 #else
2676 shift = (xscroll & 0x0F);
2677 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
2678 v_line = (line + (yscroll >> 1)) & pf_row_mask;
2679 #endif
2680
2681 /* Plane B name table */
2682 nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2683
2684 /* Pattern row index */
2685 v_line = (((v_line & 7) << 1) | odd) << 3;
2686
2687 /* Background line buffer */
2688 lb = &linebuf[0][0x20];
2689
2690 if(shift)
2691 {
2692 /* Left-most column is partially shown */
2693 lb -= (0x10 - shift);
2694
2695 atbuf = nt[(index-1) & pf_col_mask];
2696 DRAW_BG_COLUMN_IM2(atbuf, v_line, xscroll, yscroll)
2697 }
2698
2699 for(column = 0; column < width; column++, index++)
2700 {
2701 atbuf = nt[index & pf_col_mask];
2702 DRAW_BG_COLUMN_IM2(atbuf, v_line, xscroll, yscroll)
2703 }
2704 }
2705
render_bg_m5_im2_vs(int line)2706 void render_bg_m5_im2_vs(int line)
2707 {
2708 int column, start, end;
2709 uint32 atex, atbuf, *src, *dst;
2710 uint32 shift, index, v_line, *nt;
2711 uint8 *lb;
2712
2713 /* common data */
2714 int odd = odd_frame;
2715 uint32 xscroll = *(uint32 *)&vram[hscb + ((line & hscroll_mask) << 2)];
2716 uint32 yscroll = 0;
2717 uint32 pf_col_mask = playfield_col_mask;
2718 uint32 pf_row_mask = playfield_row_mask;
2719 uint32 pf_shift = playfield_shift;
2720 uint32 *vs = (uint32 *)&vsram[0];
2721
2722 /* Number of columns to draw */
2723 int width = bitmap.viewport.w >> 4;
2724
2725 /* Layer priority table */
2726 uint8 *table = lut[(reg[12] & 8) >> 2];
2727
2728 /* Window vertical range (cell 0-31) */
2729 uint32 a = (reg[18] & 0x1F) << 3;
2730
2731 /* Window position (0=top, 1=bottom) */
2732 uint32 w = (reg[18] >> 7) & 1;
2733
2734 /* Test against current line */
2735 if (w == (line >= a))
2736 {
2737 /* Window takes up entire line */
2738 a = 0;
2739 w = 1;
2740 }
2741 else
2742 {
2743 /* Window and Plane A share the line */
2744 a = clip[0].enable;
2745 w = clip[1].enable;
2746 }
2747
2748 /* Left-most column vertical scrolling when partially shown horizontally */
2749 /* Same value for both planes, only in 40-cell mode, verified on PAL MD2 */
2750 /* See Gynoug, Cutie Suzuki no Ringside Angel, Formula One, Kawasaki Superbike Challenge */
2751 if (reg[12] & 1)
2752 {
2753 /* only in 40-cell mode, verified on MD2 */
2754 yscroll = (vs[19] >> 1) & (vs[19] >> 17);
2755 }
2756
2757 /* Plane A */
2758 if (a)
2759 {
2760 /* Plane A width */
2761 start = clip[0].left;
2762 end = clip[0].right;
2763
2764 /* Plane A horizontal scroll */
2765 #ifdef LSB_FIRST
2766 shift = (xscroll & 0x0F);
2767 index = pf_col_mask + start + 1 - ((xscroll >> 4) & pf_col_mask);
2768 #else
2769 shift = (xscroll >> 16) & 0x0F;
2770 index = pf_col_mask + start + 1 - ((xscroll >> 20) & pf_col_mask);
2771 #endif
2772
2773 /* Background line buffer */
2774 dst = (uint32 *)&linebuf[0][0x20 + (start << 4) + shift];
2775
2776 if(shift)
2777 {
2778 /* Left-most column is partially shown */
2779 dst -= 4;
2780
2781 /* Plane A vertical scroll */
2782 v_line = (line + yscroll) & pf_row_mask;
2783
2784 /* Plane A name table */
2785 nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2786
2787 /* Pattern row index */
2788 v_line = (((v_line & 7) << 1) | odd) << 3;
2789
2790 /* Window bug */
2791 if (start)
2792 {
2793 atbuf = nt[index & pf_col_mask];
2794 }
2795 else
2796 {
2797 atbuf = nt[(index-1) & pf_col_mask];
2798 }
2799
2800 DRAW_COLUMN_IM2(atbuf, v_line)
2801 }
2802
2803 for(column = start; column < end; column++, index++)
2804 {
2805 /* Plane A vertical scroll */
2806 #ifdef LSB_FIRST
2807 v_line = (line + (vs[column] >> 1)) & pf_row_mask;
2808 #else
2809 v_line = (line + (vs[column] >> 17)) & pf_row_mask;
2810 #endif
2811
2812 /* Plane A name table */
2813 nt = (uint32 *)&vram[ntab + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2814
2815 /* Pattern row index */
2816 v_line = (((v_line & 7) << 1) | odd) << 3;
2817
2818 atbuf = nt[index & pf_col_mask];
2819 DRAW_COLUMN_IM2(atbuf, v_line)
2820 }
2821
2822 /* Window width */
2823 start = clip[1].left;
2824 end = clip[1].right;
2825 }
2826 else
2827 {
2828 /* Window width */
2829 start = 0;
2830 end = width;
2831 }
2832
2833 /* Window Plane */
2834 if (w)
2835 {
2836 /* Background line buffer */
2837 dst = (uint32 *)&linebuf[0][0x20 + (start << 4)];
2838
2839 /* Window name table */
2840 nt = (uint32 *)&vram[ntwb | ((line >> 3) << (6 + (reg[12] & 1)))];
2841
2842 /* Pattern row index */
2843 v_line = ((line & 7) << 1 | odd) << 3;
2844
2845 for(column = start; column < end; column++)
2846 {
2847 atbuf = nt[column];
2848 DRAW_COLUMN_IM2(atbuf, v_line)
2849 }
2850 }
2851
2852 /* Plane B horizontal scroll */
2853 #ifdef LSB_FIRST
2854 shift = (xscroll >> 16) & 0x0F;
2855 index = pf_col_mask + 1 - ((xscroll >> 20) & pf_col_mask);
2856 #else
2857 shift = (xscroll & 0x0F);
2858 index = pf_col_mask + 1 - ((xscroll >> 4) & pf_col_mask);
2859 #endif
2860
2861 /* Background line buffer */
2862 lb = &linebuf[0][0x20];
2863
2864 if(shift)
2865 {
2866 /* Left-most column is partially shown */
2867 lb -= (0x10 - shift);
2868
2869 /* Plane B vertical scroll */
2870 v_line = (line + yscroll) & pf_row_mask;
2871
2872 /* Plane B name table */
2873 nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2874
2875 /* Pattern row index */
2876 v_line = (((v_line & 7) << 1) | odd) << 3;
2877
2878 atbuf = nt[(index-1) & pf_col_mask];
2879 DRAW_BG_COLUMN_IM2(atbuf, v_line, xscroll, yscroll)
2880 }
2881
2882 for(column = 0; column < width; column++, index++)
2883 {
2884 /* Plane B vertical scroll */
2885 #ifdef LSB_FIRST
2886 v_line = (line + (vs[column] >> 17)) & pf_row_mask;
2887 #else
2888 v_line = (line + (vs[column] >> 1)) & pf_row_mask;
2889 #endif
2890
2891 /* Plane B name table */
2892 nt = (uint32 *)&vram[ntbb + (((v_line >> 3) << pf_shift) & 0x1FC0)];
2893
2894 /* Pattern row index */
2895 v_line = (((v_line & 7) << 1) | odd) << 3;
2896
2897 atbuf = nt[index & pf_col_mask];
2898 DRAW_BG_COLUMN_IM2(atbuf, v_line, xscroll, yscroll)
2899 }
2900 }
2901 #endif
2902
2903
2904 /*--------------------------------------------------------------------------*/
2905 /* Sprite layer rendering functions */
2906 /*--------------------------------------------------------------------------*/
2907
render_obj_tms(int line)2908 void render_obj_tms(int line)
2909 {
2910 int x, start, end;
2911 uint8 *lb, *sg;
2912 uint8 color, pattern[2];
2913 uint16 temp;
2914
2915 /* Sprite list for current line */
2916 object_info_t *object_info = obj_info[line];
2917 int count = object_count[line];
2918
2919 /* Default sprite width (8 pixels) */
2920 int width = 8;
2921
2922 /* Adjust width for 16x16 sprites */
2923 width <<= ((reg[1] & 0x02) >> 1);
2924
2925 /* Adjust width for zoomed sprites */
2926 width <<= (reg[1] & 0x01);
2927
2928 /* Latch SOVR flag from previous line to VDP status */
2929 status |= spr_ovr;
2930
2931 /* Clear SOVR flag for current line */
2932 spr_ovr = 0;
2933
2934 /* Draw sprites in front-to-back order */
2935 while (count--)
2936 {
2937 /* Sprite X position */
2938 start = object_info->xpos;
2939
2940 /* Sprite Color + Early Clock bit */
2941 color = object_info->size;
2942
2943 /* X position shift (32 pixels) */
2944 start -= ((color & 0x80) >> 2);
2945
2946 /* Pointer to line buffer */
2947 lb = &linebuf[0][0x20 + start];
2948
2949 if ((start + width) > 256)
2950 {
2951 /* Clip sprites on right edge */
2952 end = 256 - start;
2953 start = 0;
2954 }
2955 else
2956 {
2957 end = width;
2958
2959 if (start < 0)
2960 {
2961 /* Clip sprites on left edge */
2962 start = 0 - start;
2963 }
2964 else
2965 {
2966 start = 0;
2967 }
2968 }
2969
2970 /* Sprite Color (0-15) */
2971 color &= 0x0F;
2972
2973 /* Sprite Pattern Name */
2974 temp = object_info->attr;
2975
2976 /* Mask two LSB for 16x16 sprites */
2977 temp &= ~((reg[1] & 0x02) >> 0);
2978 temp &= ~((reg[1] & 0x02) >> 1);
2979
2980 /* Pointer to sprite generator table */
2981 sg = (uint8 *)&vram[((reg[6] << 11) & 0x3800) | (temp << 3) | object_info->ypos];
2982
2983 /* Sprite Pattern data (2 x 8 pixels) */
2984 pattern[0] = sg[0x00];
2985 pattern[1] = sg[0x10];
2986
2987 if (reg[1] & 0x01)
2988 {
2989 /* Zoomed sprites are rendered at half speed */
2990 for (x=start; x<end; x+=2)
2991 {
2992 temp = pattern[(x >> 4) & 1];
2993 temp = (temp >> (7 - ((x >> 1) & 7))) & 0x01;
2994 temp = temp * color;
2995 temp |= (lb[x] << 8);
2996 lb[x] = lut[5][temp];
2997 status |= ((temp & 0x8000) >> 10);
2998 temp &= 0x00FF;
2999 temp |= (lb[x+1] << 8);
3000 lb[x+1] = lut[5][temp];
3001 status |= ((temp & 0x8000) >> 10);
3002 }
3003 }
3004 else
3005 {
3006 /* Normal sprites */
3007 for (x=start; x<end; x++)
3008 {
3009 temp = pattern[(x >> 3) & 1];
3010 temp = (temp >> (7 - (x & 7))) & 0x01;
3011 temp = temp * color;
3012 temp |= (lb[x] << 8);
3013 lb[x] = lut[5][temp];
3014 status |= ((temp & 0x8000) >> 10);
3015 }
3016 }
3017
3018 /* Next sprite entry */
3019 object_info++;
3020 }
3021
3022 /* handle Game Gear reduced screen (160x144) */
3023 if ((system_hw == SYSTEM_GG) && !config.gg_extra && (v_counter < bitmap.viewport.h))
3024 {
3025 int line = v_counter - (bitmap.viewport.h - 144) / 2;
3026 if ((line < 0) || (line >= 144))
3027 {
3028 memset(&linebuf[0][0x20], 0x40, 256);
3029 }
3030 else
3031 {
3032 if (bitmap.viewport.x > 0)
3033 {
3034 memset(&linebuf[0][0x20], 0x40, 48);
3035 memset(&linebuf[0][0x20+48+160], 0x40, 48);
3036 }
3037 }
3038 }
3039 }
3040
render_obj_m4(int line)3041 void render_obj_m4(int line)
3042 {
3043 int i, xpos, end;
3044 uint8 *src, *lb;
3045 uint16 temp;
3046
3047 /* Sprite list for current line */
3048 object_info_t *object_info = obj_info[line];
3049 int count = object_count[line];
3050
3051 /* Default sprite width */
3052 int width = 8;
3053
3054 /* Sprite Generator address mask (LSB is masked for 8x16 sprites) */
3055 uint16 sg_mask = (~0x1C0 ^ (reg[6] << 6)) & (~((reg[1] & 0x02) >> 1));
3056
3057 /* Zoomed sprites (not working on Genesis VDP) */
3058 if (system_hw < SYSTEM_MD)
3059 {
3060 width <<= (reg[1] & 0x01);
3061 }
3062
3063 /* Unused bits used as a mask on 315-5124 VDP only */
3064 if (system_hw > SYSTEM_SMS)
3065 {
3066 sg_mask |= 0xC0;
3067 }
3068
3069 /* Latch SOVR flag from previous line to VDP status */
3070 status |= spr_ovr;
3071
3072 /* Clear SOVR flag for current line */
3073 spr_ovr = 0;
3074
3075 /* Draw sprites in front-to-back order */
3076 while (count--)
3077 {
3078 /* Sprite pattern index */
3079 temp = (object_info->attr | 0x100) & sg_mask;
3080
3081 /* Pointer to pattern cache line */
3082 src = (uint8 *)&bg_pattern_cache[(temp << 6) | (object_info->ypos << 3)];
3083
3084 /* Sprite X position */
3085 xpos = object_info->xpos;
3086
3087 /* X position shift */
3088 xpos -= (reg[0] & 0x08);
3089
3090 if (xpos < 0)
3091 {
3092 /* Clip sprites on left edge */
3093 src = src - xpos;
3094 end = xpos + width;
3095 xpos = 0;
3096 }
3097 else if ((xpos + width) > 256)
3098 {
3099 /* Clip sprites on right edge */
3100 end = 256 - xpos;
3101 }
3102 else
3103 {
3104 /* Sprite maximal width */
3105 end = width;
3106 }
3107
3108 /* Pointer to line buffer */
3109 lb = &linebuf[0][0x20 + xpos];
3110
3111 if (width > 8)
3112 {
3113 /* Draw sprite pattern (zoomed sprites are rendered at half speed) */
3114 DRAW_SPRITE_TILE_ACCURATE_2X(end,0,lut[5])
3115
3116 /* 315-5124 VDP specific */
3117 if (system_hw < SYSTEM_SMS2)
3118 {
3119 /* only 4 first sprites can be zoomed */
3120 if (count == (object_count[line] - 4))
3121 {
3122 /* Set default width for remaining sprites */
3123 width = 8;
3124 }
3125 }
3126 }
3127 else
3128 {
3129 /* Draw sprite pattern */
3130 DRAW_SPRITE_TILE_ACCURATE(end,0,lut[5])
3131 }
3132
3133 /* Next sprite entry */
3134 object_info++;
3135 }
3136
3137 /* handle Game Gear reduced screen (160x144) */
3138 if ((system_hw == SYSTEM_GG) && !config.gg_extra && (v_counter < bitmap.viewport.h))
3139 {
3140 int line = v_counter - (bitmap.viewport.h - 144) / 2;
3141 if ((line < 0) || (line >= 144))
3142 {
3143 memset(&linebuf[0][0x20], 0x40, 256);
3144 }
3145 else
3146 {
3147 if (bitmap.viewport.x > 0)
3148 {
3149 memset(&linebuf[0][0x20], 0x40, 48);
3150 memset(&linebuf[0][0x20+48+160], 0x40, 48);
3151 }
3152 }
3153 }
3154 }
3155
render_obj_m5(int line)3156 void render_obj_m5(int line)
3157 {
3158 int i, column;
3159 int xpos, width;
3160 int pixelcount = 0;
3161 int masked = 0;
3162 int max_pixels = MODE5_MAX_SPRITE_PIXELS;
3163
3164 uint8 *src, *s, *lb;
3165 uint32 temp, v_line;
3166 uint32 attr, name, atex;
3167
3168 /* Sprite list for current line */
3169 object_info_t *object_info = obj_info[line];
3170 int count = object_count[line];
3171
3172 /* Draw sprites in front-to-back order */
3173 while (count--)
3174 {
3175 /* Sprite X position */
3176 xpos = object_info->xpos;
3177
3178 /* Sprite masking */
3179 if (xpos)
3180 {
3181 /* Requires at least one sprite with xpos > 0 */
3182 spr_ovr = 1;
3183 }
3184 else if (spr_ovr)
3185 {
3186 /* Remaining sprites are not drawn */
3187 masked = 1;
3188 }
3189
3190 /* Display area offset */
3191 xpos = xpos - 0x80;
3192
3193 /* Sprite size */
3194 temp = object_info->size;
3195
3196 /* Sprite width */
3197 width = 8 + ((temp & 0x0C) << 1);
3198
3199 /* Update pixel count (off-screen sprites are included) */
3200 pixelcount += width;
3201
3202 /* Is sprite across visible area ? */
3203 if (((xpos + width) > 0) && (xpos < bitmap.viewport.w) && !masked)
3204 {
3205 /* Sprite attributes */
3206 attr = object_info->attr;
3207
3208 /* Sprite vertical offset */
3209 v_line = object_info->ypos;
3210
3211 /* Sprite priority + palette bits */
3212 atex = (attr >> 9) & 0x70;
3213
3214 /* Pattern name base */
3215 name = attr & 0x07FF;
3216
3217 /* Mask vflip/hflip */
3218 attr &= 0x1800;
3219
3220 /* Pointer into pattern name offset look-up table */
3221 s = &name_lut[((attr >> 3) & 0x300) | (temp << 4) | ((v_line & 0x18) >> 1)];
3222
3223 /* Pointer into line buffer */
3224 lb = &linebuf[0][0x20 + xpos];
3225
3226 /* Max. number of sprite pixels rendered per line */
3227 if (pixelcount > max_pixels)
3228 {
3229 /* Adjust number of pixels to draw */
3230 width -= (pixelcount - max_pixels);
3231 }
3232
3233 /* Number of tiles to draw */
3234 width = width >> 3;
3235
3236 /* Pattern row index */
3237 v_line = (v_line & 7) << 3;
3238
3239 /* Draw sprite patterns */
3240 for (column = 0; column < width; column++, lb+=8)
3241 {
3242 temp = attr | ((name + s[column]) & 0x07FF);
3243 src = &bg_pattern_cache[(temp << 6) | (v_line)];
3244 DRAW_SPRITE_TILE(8,atex,lut[1])
3245 }
3246 }
3247
3248 /* Sprite limit */
3249 if (pixelcount >= max_pixels)
3250 {
3251 /* Sprite masking is effective on next line if max pixel width is reached */
3252 spr_ovr = (pixelcount >= bitmap.viewport.w);
3253
3254 /* Stop sprite rendering */
3255 return;
3256 }
3257
3258 /* Next sprite entry */
3259 object_info++;
3260 }
3261
3262 /* Clear sprite masking for next line */
3263 spr_ovr = 0;
3264 }
3265
render_obj_m5_ste(int line)3266 void render_obj_m5_ste(int line)
3267 {
3268 int i, column;
3269 int xpos, width;
3270 int pixelcount = 0;
3271 int masked = 0;
3272 int max_pixels = MODE5_MAX_SPRITE_PIXELS;
3273
3274 uint8 *src, *s, *lb;
3275 uint32 temp, v_line;
3276 uint32 attr, name, atex;
3277
3278 /* Sprite list for current line */
3279 object_info_t *object_info = obj_info[line];
3280 int count = object_count[line];
3281
3282 /* Clear sprite line buffer */
3283 memset(&linebuf[1][0], 0, bitmap.viewport.w + 0x40);
3284
3285 /* Draw sprites in front-to-back order */
3286 while (count--)
3287 {
3288 /* Sprite X position */
3289 xpos = object_info->xpos;
3290
3291 /* Sprite masking */
3292 if (xpos)
3293 {
3294 /* Requires at least one sprite with xpos > 0 */
3295 spr_ovr = 1;
3296 }
3297 else if (spr_ovr)
3298 {
3299 /* Remaining sprites are not drawn */
3300 masked = 1;
3301 }
3302
3303 /* Display area offset */
3304 xpos = xpos - 0x80;
3305
3306 /* Sprite size */
3307 temp = object_info->size;
3308
3309 /* Sprite width */
3310 width = 8 + ((temp & 0x0C) << 1);
3311
3312 /* Update pixel count (off-screen sprites are included) */
3313 pixelcount += width;
3314
3315 /* Is sprite across visible area ? */
3316 if (((xpos + width) > 0) && (xpos < bitmap.viewport.w) && !masked)
3317 {
3318 /* Sprite attributes */
3319 attr = object_info->attr;
3320
3321 /* Sprite vertical offset */
3322 v_line = object_info->ypos;
3323
3324 /* Sprite priority + palette bits */
3325 atex = (attr >> 9) & 0x70;
3326
3327 /* Pattern name base */
3328 name = attr & 0x07FF;
3329
3330 /* Mask vflip/hflip */
3331 attr &= 0x1800;
3332
3333 /* Pointer into pattern name offset look-up table */
3334 s = &name_lut[((attr >> 3) & 0x300) | (temp << 4) | ((v_line & 0x18) >> 1)];
3335
3336 /* Pointer into line buffer */
3337 lb = &linebuf[1][0x20 + xpos];
3338
3339 /* Adjust number of pixels to draw for sprite limit */
3340 if (pixelcount > max_pixels)
3341 {
3342 width -= (pixelcount - max_pixels);
3343 }
3344
3345 /* Number of tiles to draw */
3346 width = width >> 3;
3347
3348 /* Pattern row index */
3349 v_line = (v_line & 7) << 3;
3350
3351 /* Draw sprite patterns */
3352 for (column = 0; column < width; column++, lb+=8)
3353 {
3354 temp = attr | ((name + s[column]) & 0x07FF);
3355 src = &bg_pattern_cache[(temp << 6) | (v_line)];
3356 DRAW_SPRITE_TILE(8,atex,lut[3])
3357 }
3358 }
3359
3360 /* Sprite limit */
3361 if (pixelcount >= max_pixels)
3362 {
3363 /* Sprite masking is effective on next line if max pixel width is reached */
3364 spr_ovr = (pixelcount >= bitmap.viewport.w);
3365
3366 /* Merge background & sprite layers */
3367 merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[4], bitmap.viewport.w);
3368
3369 /* Stop sprite rendering */
3370 return;
3371 }
3372
3373 /* Next sprite entry */
3374 object_info++;
3375 }
3376
3377 /* Clear sprite masking for next line */
3378 spr_ovr = 0;
3379
3380 /* Merge background & sprite layers */
3381 merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[4], bitmap.viewport.w);
3382 }
3383
render_obj_m5_im2(int line)3384 void render_obj_m5_im2(int line)
3385 {
3386 int i, column;
3387 int xpos, width;
3388 int pixelcount = 0;
3389 int masked = 0;
3390 int odd = odd_frame;
3391 int max_pixels = MODE5_MAX_SPRITE_PIXELS;
3392
3393 uint8 *src, *s, *lb;
3394 uint32 temp, v_line;
3395 uint32 attr, name, atex;
3396
3397 /* Sprite list for current line */
3398 object_info_t *object_info = obj_info[line];
3399 int count = object_count[line];
3400
3401 /* Draw sprites in front-to-back order */
3402 while (count--)
3403 {
3404 /* Sprite X position */
3405 xpos = object_info->xpos;
3406
3407 /* Sprite masking */
3408 if (xpos)
3409 {
3410 /* Requires at least one sprite with xpos > 0 */
3411 spr_ovr = 1;
3412 }
3413 else if (spr_ovr)
3414 {
3415 /* Remaining sprites are not drawn */
3416 masked = 1;
3417 }
3418
3419 /* Display area offset */
3420 xpos = xpos - 0x80;
3421
3422 /* Sprite size */
3423 temp = object_info->size;
3424
3425 /* Sprite width */
3426 width = 8 + ((temp & 0x0C) << 1);
3427
3428 /* Update pixel count (off-screen sprites are included) */
3429 pixelcount += width;
3430
3431 /* Is sprite across visible area ? */
3432 if (((xpos + width) > 0) && (xpos < bitmap.viewport.w) && !masked)
3433 {
3434 /* Sprite attributes */
3435 attr = object_info->attr;
3436
3437 /* Sprite y offset */
3438 v_line = object_info->ypos;
3439
3440 /* Sprite priority + palette bits */
3441 atex = (attr >> 9) & 0x70;
3442
3443 /* Pattern name base */
3444 name = attr & 0x03FF;
3445
3446 /* Mask vflip/hflip */
3447 attr &= 0x1800;
3448
3449 /* Pattern name offset lookup table */
3450 s = &name_lut[((attr >> 3) & 0x300) | (temp << 4) | ((v_line & 0x18) >> 1)];
3451
3452 /* Pointer into line buffer */
3453 lb = &linebuf[0][0x20 + xpos];
3454
3455 /* Adjust width for sprite limit */
3456 if (pixelcount > max_pixels)
3457 {
3458 width -= (pixelcount - max_pixels);
3459 }
3460
3461 /* Number of tiles to draw */
3462 width = width >> 3;
3463
3464 /* Pattern row index */
3465 v_line = (((v_line & 7) << 1) | odd) << 3;
3466
3467 /* Render sprite patterns */
3468 for(column = 0; column < width; column ++, lb+=8)
3469 {
3470 temp = attr | (((name + s[column]) & 0x3ff) << 1);
3471 src = &bg_pattern_cache[((temp << 6) | (v_line)) ^ ((attr & 0x1000) >> 6)];
3472 DRAW_SPRITE_TILE(8,atex,lut[1])
3473 }
3474 }
3475
3476 /* Sprite Limit */
3477 if (pixelcount >= max_pixels)
3478 {
3479 /* Sprite masking is effective on next line if max pixel width is reached */
3480 spr_ovr = (pixelcount >= bitmap.viewport.w);
3481
3482 /* Stop sprite rendering */
3483 return;
3484 }
3485
3486 /* Next sprite entry */
3487 object_info++;
3488 }
3489
3490 /* Clear sprite masking for next line */
3491 spr_ovr = 0;
3492 }
3493
render_obj_m5_im2_ste(int line)3494 void render_obj_m5_im2_ste(int line)
3495 {
3496 int i, column;
3497 int xpos, width;
3498 int pixelcount = 0;
3499 int masked = 0;
3500 int odd = odd_frame;
3501 int max_pixels = MODE5_MAX_SPRITE_PIXELS;
3502
3503 uint8 *src, *s, *lb;
3504 uint32 temp, v_line;
3505 uint32 attr, name, atex;
3506
3507 /* Sprite list for current line */
3508 object_info_t *object_info = obj_info[line];
3509 int count = object_count[line];
3510
3511 /* Clear sprite line buffer */
3512 memset(&linebuf[1][0], 0, bitmap.viewport.w + 0x40);
3513
3514 /* Draw sprites in front-to-back order */
3515 while (count--)
3516 {
3517 /* Sprite X position */
3518 xpos = object_info->xpos;
3519
3520 /* Sprite masking */
3521 if (xpos)
3522 {
3523 /* Requires at least one sprite with xpos > 0 */
3524 spr_ovr = 1;
3525 }
3526 else if (spr_ovr)
3527 {
3528 /* Remaining sprites are not drawn */
3529 masked = 1;
3530 }
3531
3532 /* Display area offset */
3533 xpos = xpos - 0x80;
3534
3535 /* Sprite size */
3536 temp = object_info->size;
3537
3538 /* Sprite width */
3539 width = 8 + ((temp & 0x0C) << 1);
3540
3541 /* Update pixel count (off-screen sprites are included) */
3542 pixelcount += width;
3543
3544 /* Is sprite across visible area ? */
3545 if (((xpos + width) > 0) && (xpos < bitmap.viewport.w) && !masked)
3546 {
3547 /* Sprite attributes */
3548 attr = object_info->attr;
3549
3550 /* Sprite y offset */
3551 v_line = object_info->ypos;
3552
3553 /* Sprite priority + palette bits */
3554 atex = (attr >> 9) & 0x70;
3555
3556 /* Pattern name base */
3557 name = attr & 0x03FF;
3558
3559 /* Mask vflip/hflip */
3560 attr &= 0x1800;
3561
3562 /* Pattern name offset lookup table */
3563 s = &name_lut[((attr >> 3) & 0x300) | (temp << 4) | ((v_line & 0x18) >> 1)];
3564
3565 /* Pointer into line buffer */
3566 lb = &linebuf[1][0x20 + xpos];
3567
3568 /* Adjust width for sprite limit */
3569 if (pixelcount > max_pixels)
3570 {
3571 width -= (pixelcount - max_pixels);
3572 }
3573
3574 /* Number of tiles to draw */
3575 width = width >> 3;
3576
3577 /* Pattern row index */
3578 v_line = (((v_line & 7) << 1) | odd) << 3;
3579
3580 /* Render sprite patterns */
3581 for(column = 0; column < width; column ++, lb+=8)
3582 {
3583 temp = attr | (((name + s[column]) & 0x3ff) << 1);
3584 src = &bg_pattern_cache[((temp << 6) | (v_line)) ^ ((attr & 0x1000) >> 6)];
3585 DRAW_SPRITE_TILE(8,atex,lut[3])
3586 }
3587 }
3588
3589 /* Sprite Limit */
3590 if (pixelcount >= max_pixels)
3591 {
3592 /* Sprite masking is effective on next line if max pixel width is reached */
3593 spr_ovr = (pixelcount >= bitmap.viewport.w);
3594
3595 /* Merge background & sprite layers */
3596 merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[4], bitmap.viewport.w);
3597
3598 /* Stop sprite rendering */
3599 return;
3600 }
3601
3602 /* Next sprite entry */
3603 object_info++;
3604 }
3605
3606 /* Clear sprite masking for next line */
3607 spr_ovr = 0;
3608
3609 /* Merge background & sprite layers */
3610 merge(&linebuf[1][0x20], &linebuf[0][0x20], &linebuf[0][0x20], lut[4], bitmap.viewport.w);
3611 }
3612
3613
3614 /*--------------------------------------------------------------------------*/
3615 /* Sprites Parsing functions */
3616 /*--------------------------------------------------------------------------*/
3617
parse_satb_tms(int line)3618 void parse_satb_tms(int line)
3619 {
3620 int i = 0;
3621
3622 /* Sprite counter (4 max. per line) */
3623 int count = 0;
3624
3625 /* no sprites in Text modes */
3626 if (!(reg[1] & 0x10))
3627 {
3628 /* Y position */
3629 int ypos;
3630
3631 /* Sprite list for next line */
3632 object_info_t *object_info = obj_info[(line + 1) & 1];
3633
3634 /* Pointer to sprite attribute table */
3635 uint8 *st = &vram[(reg[5] << 7) & 0x3F80];
3636
3637 /* Sprite height (8 pixels by default) */
3638 int height = 8;
3639
3640 /* Adjust height for 16x16 sprites */
3641 height <<= ((reg[1] & 0x02) >> 1);
3642
3643 /* Adjust height for zoomed sprites */
3644 height <<= (reg[1] & 0x01);
3645
3646 /* Parse Sprite Table (32 entries) */
3647 do
3648 {
3649 /* Sprite Y position */
3650 ypos = st[i << 2];
3651
3652 /* Check end of sprite list marker */
3653 if (ypos == 0xD0)
3654 {
3655 break;
3656 }
3657
3658 /* Wrap Y coordinate for sprites > 256-32 */
3659 if (ypos >= 224)
3660 {
3661 ypos -= 256;
3662 }
3663
3664 /* Y range */
3665 ypos = line - ypos;
3666
3667 /* Sprite is visible on this line ? */
3668 if ((ypos >= 0) && (ypos < height))
3669 {
3670 /* Sprite overflow */
3671 if (count == TMS_MAX_SPRITES_PER_LINE)
3672 {
3673 /* Flag is set only during active area */
3674 if (line < bitmap.viewport.h)
3675 {
3676 spr_ovr = 0x40;
3677 }
3678 break;
3679 }
3680
3681 /* Adjust Y range back for zoomed sprites */
3682 ypos >>= (reg[1] & 0x01);
3683
3684 /* Store sprite attributes for later processing */
3685 object_info->ypos = ypos;
3686 object_info->xpos = st[(i << 2) + 1];
3687 object_info->attr = st[(i << 2) + 2];
3688 object_info->size = st[(i << 2) + 3];
3689
3690 /* Increment Sprite count */
3691 ++count;
3692
3693 /* Next sprite entry */
3694 object_info++;
3695 }
3696 }
3697 while (++i < 32);
3698 }
3699
3700 /* Update sprite count for next line */
3701 object_count[(line + 1) & 1] = count;
3702
3703 /* Insert number of last sprite entry processed */
3704 status = (status & 0xE0) | (i & 0x1F);
3705 }
3706
parse_satb_m4(int line)3707 void parse_satb_m4(int line)
3708 {
3709 int i = 0;
3710 uint8 *st;
3711
3712 /* Sprite counter (8 max. per line) */
3713 int count = 0;
3714
3715 /* Y position */
3716 int ypos;
3717
3718 /* Sprite list for next line */
3719 object_info_t *object_info = obj_info[(line + 1) & 1];
3720
3721 /* Sprite height (8x8 or 8x16) */
3722 int height = 8 + ((reg[1] & 0x02) << 2);
3723
3724 /* Sprite attribute table address mask */
3725 uint16 st_mask = ~0x3F80 ^ (reg[5] << 7);
3726
3727 /* Unused bits used as a mask on 315-5124 VDP only */
3728 if (system_hw > SYSTEM_SMS)
3729 {
3730 st_mask |= 0x80;
3731 }
3732
3733 /* Pointer to sprite attribute table */
3734 st = &vram[st_mask & 0x3F00];
3735
3736 /* Parse Sprite Table (64 entries) */
3737 do
3738 {
3739 /* Sprite Y position */
3740 ypos = st[i];
3741
3742 /* Check end of sprite list marker (no effect in extended modes) */
3743 if ((ypos == 208) && (bitmap.viewport.h == 192))
3744 {
3745 break;
3746 }
3747
3748 /* Wrap Y coordinate (NB: this is likely not 100% accurate and needs to be verified on real hardware) */
3749 if (ypos > (bitmap.viewport.h + 16))
3750 {
3751 ypos -= 256;
3752 }
3753
3754 /* Y range */
3755 ypos = line - ypos;
3756
3757 /* Adjust Y range for zoomed sprites (not working on Mega Drive VDP) */
3758 if (system_hw < SYSTEM_MD)
3759 {
3760 ypos >>= (reg[1] & 0x01);
3761 }
3762
3763 /* Check if sprite is visible on this line */
3764 if ((ypos >= 0) && (ypos < height))
3765 {
3766 /* Sprite overflow */
3767 if (count == MODE4_MAX_SPRITES_PER_LINE)
3768 {
3769 /* Flag is set only during active area */
3770 if ((line >= 0) && (line < bitmap.viewport.h))
3771 {
3772 spr_ovr = 0x40;
3773 }
3774 break;
3775 }
3776
3777 /* Store sprite attributes for later processing */
3778 object_info->ypos = ypos;
3779 object_info->xpos = st[(0x80 + (i << 1)) & st_mask];
3780 object_info->attr = st[(0x81 + (i << 1)) & st_mask];
3781
3782 /* Increment Sprite count */
3783 ++count;
3784
3785 /* Next sprite entry */
3786 object_info++;
3787 }
3788 }
3789 while (++i < 64);
3790
3791 /* Update sprite count for next line */
3792 object_count[(line + 1) & 1] = count;
3793 }
3794
parse_satb_m5(int line)3795 void parse_satb_m5(int line)
3796 {
3797 /* Y position */
3798 int ypos;
3799
3800 /* Sprite height (8,16,24,32 pixels)*/
3801 int height;
3802
3803 /* Sprite size data */
3804 int size;
3805
3806 /* Sprite link data */
3807 int link = 0;
3808
3809 /* Sprite counter */
3810 int count = 0;
3811
3812 /* max. number of rendered sprites (16 or 20 sprites per line by default) */
3813 int max = MODE5_MAX_SPRITES_PER_LINE;
3814
3815 /* max. number of parsed sprites (64 or 80 sprites per line by default) */
3816 int total = max_sprite_pixels >> 2;
3817
3818 /* Pointer to sprite attribute table */
3819 uint16 *p = (uint16 *) &vram[satb];
3820
3821 /* Pointer to internal RAM */
3822 uint16 *q = (uint16 *) &sat[0];
3823
3824 /* Sprite list for next line */
3825 object_info_t *object_info = obj_info[(line + 1) & 1];
3826
3827 /* Adjust line offset */
3828 line += 0x81;
3829
3830 do
3831 {
3832 /* Read Y position from internal SAT cache */
3833 ypos = (q[link] >> im2_flag) & 0x1FF;
3834
3835 /* Check if sprite Y position has been reached */
3836 if (line >= ypos)
3837 {
3838 /* Read sprite size from internal SAT cache */
3839 size = q[link + 1] >> 8;
3840
3841 /* Sprite height */
3842 height = 8 + ((size & 3) << 3);
3843
3844 /* Y range */
3845 ypos = line - ypos;
3846
3847 /* Check if sprite is visible on current line */
3848 if (ypos < height)
3849 {
3850 /* Sprite overflow */
3851 if (count == max)
3852 {
3853 status |= 0x40;
3854 break;
3855 }
3856
3857 /* Update sprite list (only name, attribute & xpos are parsed from VRAM) */
3858 object_info->attr = p[link + 2];
3859 object_info->xpos = p[link + 3] & 0x1ff;
3860 object_info->ypos = ypos;
3861 object_info->size = size & 0x0f;
3862
3863 /* Increment Sprite count */
3864 ++count;
3865
3866 /* Next sprite entry */
3867 object_info++;
3868 }
3869 }
3870
3871 /* Read link data from internal SAT cache */
3872 link = (q[link + 1] & 0x7F) << 2;
3873
3874 /* Stop parsing if link data points to first entry (#0) or after the last entry (#64 in H32 mode, #80 in H40 mode) */
3875 if ((link == 0) || (link >= bitmap.viewport.w)) break;
3876 }
3877 while (--total);
3878
3879 /* Update sprite count for next line (line value already incremented) */
3880 object_count[line & 1] = count;
3881 }
3882
3883
3884 /*--------------------------------------------------------------------------*/
3885 /* Pattern cache update function */
3886 /*--------------------------------------------------------------------------*/
3887
update_bg_pattern_cache_m4(int index)3888 void update_bg_pattern_cache_m4(int index)
3889 {
3890 int i;
3891 uint8 x, y, c;
3892 uint8 *dst;
3893 uint16 name, bp01, bp23;
3894 uint32 bp;
3895
3896 for(i = 0; i < index; i++)
3897 {
3898 /* Get modified pattern name index */
3899 name = bg_name_list[i];
3900
3901 /* Pattern cache base address */
3902 dst = &bg_pattern_cache[name << 6];
3903
3904 /* Check modified lines */
3905 for(y = 0; y < 8; y++)
3906 {
3907 if(bg_name_dirty[name] & (1 << y))
3908 {
3909 /* Byteplane data */
3910 bp01 = *(uint16 *)&vram[(name << 5) | (y << 2) | (0)];
3911 bp23 = *(uint16 *)&vram[(name << 5) | (y << 2) | (2)];
3912
3913 /* Convert to pixel line data (4 bytes = 8 pixels)*/
3914 /* (msb) p7p6 p5p4 p3p2 p1p0 (lsb) */
3915 bp = (bp_lut[bp01] >> 2) | (bp_lut[bp23]);
3916
3917 /* Update cached line (8 pixels = 8 bytes) */
3918 for(x = 0; x < 8; x++)
3919 {
3920 /* Extract pixel data */
3921 c = bp & 0x0F;
3922
3923 /* Pattern cache data (one pattern = 8 bytes) */
3924 /* byte0 <-> p0 p1 p2 p3 p4 p5 p6 p7 <-> byte7 (hflip = 0) */
3925 /* byte0 <-> p7 p6 p5 p4 p3 p2 p1 p0 <-> byte7 (hflip = 1) */
3926 dst[0x00000 | (y << 3) | (x)] = (c); /* vflip=0 & hflip=0 */
3927 dst[0x08000 | (y << 3) | (x ^ 7)] = (c); /* vflip=0 & hflip=1 */
3928 dst[0x10000 | ((y ^ 7) << 3) | (x)] = (c); /* vflip=1 & hflip=0 */
3929 dst[0x18000 | ((y ^ 7) << 3) | (x ^ 7)] = (c); /* vflip=1 & hflip=1 */
3930
3931 /* Next pixel */
3932 bp = bp >> 4;
3933 }
3934 }
3935 }
3936
3937 /* Clear modified pattern flag */
3938 bg_name_dirty[name] = 0;
3939 }
3940 }
3941
update_bg_pattern_cache_m5(int index)3942 void update_bg_pattern_cache_m5(int index)
3943 {
3944 int i;
3945 uint8 x, y, c;
3946 uint8 *dst;
3947 uint16 name;
3948 uint32 bp;
3949
3950 for(i = 0; i < index; i++)
3951 {
3952 /* Get modified pattern name index */
3953 name = bg_name_list[i];
3954
3955 /* Pattern cache base address */
3956 dst = &bg_pattern_cache[name << 6];
3957
3958 /* Check modified lines */
3959 for(y = 0; y < 8; y ++)
3960 {
3961 if(bg_name_dirty[name] & (1 << y))
3962 {
3963 /* Byteplane data (one pattern = 4 bytes) */
3964 /* LIT_ENDIAN: byte0 (lsb) p2p3 p0p1 p6p7 p4p5 (msb) byte3 */
3965 /* BIG_ENDIAN: byte0 (msb) p0p1 p2p3 p4p5 p6p7 (lsb) byte3 */
3966 bp = *(uint32 *)&vram[(name << 5) | (y << 2)];
3967
3968 /* Update cached line (8 pixels = 8 bytes) */
3969 for(x = 0; x < 8; x ++)
3970 {
3971 /* Extract pixel data */
3972 c = bp & 0x0F;
3973
3974 /* Pattern cache data (one pattern = 8 bytes) */
3975 /* byte0 <-> p0 p1 p2 p3 p4 p5 p6 p7 <-> byte7 (hflip = 0) */
3976 /* byte0 <-> p7 p6 p5 p4 p3 p2 p1 p0 <-> byte7 (hflip = 1) */
3977 #ifdef LSB_FIRST
3978 /* Byteplane data = (msb) p4p5 p6p7 p0p1 p2p3 (lsb) */
3979 dst[0x00000 | (y << 3) | (x ^ 3)] = (c); /* vflip=0, hflip=0 */
3980 dst[0x20000 | (y << 3) | (x ^ 4)] = (c); /* vflip=0, hflip=1 */
3981 dst[0x40000 | ((y ^ 7) << 3) | (x ^ 3)] = (c); /* vflip=1, hflip=0 */
3982 dst[0x60000 | ((y ^ 7) << 3) | (x ^ 4)] = (c); /* vflip=1, hflip=1 */
3983 #else
3984 /* Byteplane data = (msb) p0p1 p2p3 p4p5 p6p7 (lsb) */
3985 dst[0x00000 | (y << 3) | (x ^ 7)] = (c); /* vflip=0, hflip=0 */
3986 dst[0x20000 | (y << 3) | (x)] = (c); /* vflip=0, hflip=1 */
3987 dst[0x40000 | ((y ^ 7) << 3) | (x ^ 7)] = (c); /* vflip=1, hflip=0 */
3988 dst[0x60000 | ((y ^ 7) << 3) | (x)] = (c); /* vflip=1, hflip=1 */
3989 #endif
3990 /* Next pixel */
3991 bp = bp >> 4;
3992 }
3993 }
3994 }
3995
3996 /* Clear modified pattern flag */
3997 bg_name_dirty[name] = 0;
3998 }
3999 }
4000
4001
4002 /*--------------------------------------------------------------------------*/
4003 /* Window & Plane A clipping update function (Mode 5) */
4004 /*--------------------------------------------------------------------------*/
4005
window_clip(unsigned int data,unsigned int sw)4006 void window_clip(unsigned int data, unsigned int sw)
4007 {
4008 /* Window size and invert flags */
4009 int hp = (data & 0x1f);
4010 int hf = (data >> 7) & 1;
4011
4012 /* Perform horizontal clipping; the results are applied in reverse
4013 if the horizontal inversion flag is set
4014 */
4015 int a = hf;
4016 int w = hf ^ 1;
4017
4018 /* Display width (16 or 20 columns) */
4019 sw = 16 + (sw << 2);
4020
4021 if(hp)
4022 {
4023 if(hp > sw)
4024 {
4025 /* Plane W takes up entire line */
4026 clip[w].left = 0;
4027 clip[w].right = sw;
4028 clip[w].enable = 1;
4029 clip[a].enable = 0;
4030 }
4031 else
4032 {
4033 /* Plane W takes left side, Plane A takes right side */
4034 clip[w].left = 0;
4035 clip[a].right = sw;
4036 clip[a].left = clip[w].right = hp;
4037 clip[0].enable = clip[1].enable = 1;
4038 }
4039 }
4040 else
4041 {
4042 /* Plane A takes up entire line */
4043 clip[a].left = 0;
4044 clip[a].right = sw;
4045 clip[a].enable = 1;
4046 clip[w].enable = 0;
4047 }
4048 }
4049
4050
4051 /*--------------------------------------------------------------------------*/
4052 /* Init, reset routines */
4053 /*--------------------------------------------------------------------------*/
4054
render_init(void)4055 void render_init(void)
4056 {
4057 int bx, ax;
4058
4059 /* Initialize layers priority pixel look-up tables */
4060 uint16 index;
4061 for (bx = 0; bx < 0x100; bx++)
4062 {
4063 for (ax = 0; ax < 0x100; ax++)
4064 {
4065 index = (bx << 8) | (ax);
4066
4067 lut[0][index] = make_lut_bg(bx, ax);
4068 lut[1][index] = make_lut_bgobj(bx, ax);
4069 lut[2][index] = make_lut_bg_ste(bx, ax);
4070 lut[3][index] = make_lut_obj(bx, ax);
4071 lut[4][index] = make_lut_bgobj_ste(bx, ax);
4072 lut[5][index] = make_lut_bgobj_m4(bx,ax);
4073 }
4074 }
4075
4076 /* Initialize pixel color look-up tables */
4077 palette_init();
4078
4079 /* Make sprite pattern name index look-up table (Mode 5) */
4080 make_name_lut();
4081
4082 /* Make bitplane to pixel look-up table (Mode 4) */
4083 make_bp_lut();
4084 }
4085
render_reset(void)4086 void render_reset(void)
4087 {
4088 if (!reset_do_not_clear_buffers)
4089 {
4090 /* Clear display bitmap */
4091 memset(bitmap.data, 0, bitmap.pitch * bitmap.height);
4092
4093 /* Clear line buffers */
4094 memset(linebuf, 0, sizeof(linebuf));
4095
4096 /* Clear color palettes */
4097 memset(pixel, 0, sizeof(pixel));
4098
4099 /* Clear pattern cache */
4100 memset((char *)bg_pattern_cache, 0, sizeof(bg_pattern_cache));
4101 }
4102
4103 /* Reset Sprite infos */
4104 spr_ovr = spr_col = object_count[0] = object_count[1] = 0;
4105 }
4106
4107
4108 /*--------------------------------------------------------------------------*/
4109 /* Line rendering functions */
4110 /*--------------------------------------------------------------------------*/
4111
render_line(int line)4112 void render_line(int line)
4113 {
4114 /* Check display status */
4115 if (reg[1] & 0x40)
4116 {
4117 /* Update pattern cache */
4118 if (bg_list_index)
4119 {
4120 update_bg_pattern_cache(bg_list_index);
4121 bg_list_index = 0;
4122 }
4123
4124 /* Render BG layer(s) */
4125 render_bg(line);
4126
4127 /* Render sprite layer */
4128 render_obj(line & 1);
4129
4130 /* Left-most column blanking */
4131 if (reg[0] & 0x20)
4132 {
4133 if (system_hw > SYSTEM_SGII)
4134 {
4135 memset(&linebuf[0][0x20], 0x40, 8);
4136 }
4137 }
4138
4139 /* Parse sprites for next line */
4140 if (line < (bitmap.viewport.h - 1))
4141 {
4142 parse_satb(line);
4143 }
4144
4145 /* Horizontal borders */
4146 if (bitmap.viewport.x > 0)
4147 {
4148 memset(&linebuf[0][0x20 - bitmap.viewport.x], 0x40, bitmap.viewport.x);
4149 memset(&linebuf[0][0x20 + bitmap.viewport.w], 0x40, bitmap.viewport.x);
4150 }
4151 }
4152 else
4153 {
4154 /* Master System & Game Gear VDP specific */
4155 if (system_hw < SYSTEM_MD)
4156 {
4157 /* Update SOVR flag */
4158 status |= spr_ovr;
4159 spr_ovr = 0;
4160
4161 /* Sprites are still parsed when display is disabled */
4162 parse_satb(line);
4163 }
4164
4165 /* Blanked line */
4166 memset(&linebuf[0][0x20 - bitmap.viewport.x], 0x40, bitmap.viewport.w + 2*bitmap.viewport.x);
4167 }
4168
4169 /* Pixel color remapping */
4170 remap_line(line);
4171 }
4172
blank_line(int line,int offset,int width)4173 void blank_line(int line, int offset, int width)
4174 {
4175 memset(&linebuf[0][0x20 + offset], 0x40, width);
4176 remap_line(line);
4177 }
4178
remap_line(int line)4179 void remap_line(int line)
4180 {
4181 /* Line width */
4182 int width = bitmap.viewport.w + 2*bitmap.viewport.x;
4183
4184 /* Pixel line buffer */
4185 uint8 *src = &linebuf[0][0x20 - bitmap.viewport.x];
4186
4187 /* Adjust line offset in framebuffer */
4188 line = (line + bitmap.viewport.y) % lines_per_frame;
4189
4190 /* Take care of Game Gear reduced screen when overscan is disabled */
4191 if (line < 0) return;
4192
4193 /* Adjust for interlaced output */
4194 if (interlaced && config.render)
4195 {
4196 line = (line * 2) + odd_frame;
4197 }
4198
4199 #if defined(USE_15BPP_RENDERING) || defined(USE_16BPP_RENDERING)
4200 /* NTSC Filter (only supported for 15 or 16-bit pixels rendering) */
4201 if (config.ntsc)
4202 {
4203 if (reg[12] & 0x01)
4204 {
4205 md_ntsc_blit(md_ntsc, ( MD_NTSC_IN_T const * )pixel, src, width, line);
4206 }
4207 else
4208 {
4209 sms_ntsc_blit(sms_ntsc, ( SMS_NTSC_IN_T const * )pixel, src, width, line);
4210 }
4211 }
4212 else
4213 #endif
4214 {
4215 #ifdef CUSTOM_BLITTER
4216 CUSTOM_BLITTER(line, width, pixel, src)
4217 #else
4218 /* Convert VDP pixel data to output pixel format */
4219 PIXEL_OUT_T *dst = ((PIXEL_OUT_T *)&bitmap.data[(line * bitmap.pitch)]);
4220 if (config.lcd)
4221 {
4222 do
4223 {
4224 RENDER_PIXEL_LCD(src,dst,pixel,config.lcd);
4225 }
4226 while (--width);
4227 }
4228 else
4229 {
4230 do
4231 {
4232 *dst++ = pixel[*src++];
4233 }
4234 while (--width);
4235 }
4236 #endif
4237 }
4238 }
4239