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