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