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