Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/cocoa/vidgcd.c
2 views
1
/* Copyright 2003-2004 Guillaume Duhamel
2
Copyright 2004-2008 Theo Berkau
3
Copyright 2006 Fabien Coulon
4
Copyright 2010 Lawrence Sebald
5
6
This file is part of Yabause.
7
8
Yabause is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
12
13
Yabause is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
17
18
You should have received a copy of the GNU General Public License
19
along with Yabause; if not, write to the Free Software
20
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
*/
22
23
#include <dispatch/dispatch.h>
24
25
#include "vidgcd.h"
26
#include "vidshared.h"
27
#include "debug.h"
28
#include "vdp2.h"
29
30
#ifdef HAVE_LIBGL
31
#define USE_OPENGL
32
#endif
33
34
#ifdef USE_OPENGL
35
#include "ygl.h"
36
#endif
37
38
#include "yui.h"
39
40
#include <stdlib.h>
41
#include <stdarg.h>
42
#include <limits.h>
43
44
#if defined WORDS_BIGENDIAN
45
static INLINE u32 COLSAT2YAB16(int priority,u32 temp) { return (priority | (temp & 0x7C00) << 1 | (temp & 0x3E0) << 14 | (temp & 0x1F) << 27); }
46
static INLINE u32 COLSAT2YAB32(int priority,u32 temp) { return (((temp & 0xFF) << 24) | ((temp & 0xFF00) << 8) | ((temp & 0xFF0000) >> 8) | priority); }
47
static INLINE u32 COLSAT2YAB32_2(int priority,u32 temp1,u32 temp2) { return (((temp2 & 0xFF) << 24) | ((temp2 & 0xFF00) << 8) | ((temp1 & 0xFF) << 8) | priority); }
48
static INLINE u32 COLSATSTRIPPRIORITY(u32 pixel) { return (pixel | 0xFF); }
49
#else
50
static INLINE u32 COLSAT2YAB16(int priority,u32 temp) { return (priority << 24 | (temp & 0x1F) << 3 | (temp & 0x3E0) << 6 | (temp & 0x7C00) << 9); }
51
static INLINE u32 COLSAT2YAB32(int priority, u32 temp) { return (priority << 24 | (temp & 0xFF0000) | (temp & 0xFF00) | (temp & 0xFF)); }
52
static INLINE u32 COLSAT2YAB32_2(int priority,u32 temp1,u32 temp2) { return (priority << 24 | ((temp1 & 0xFF) << 16) | (temp2 & 0xFF00) | (temp2 & 0xFF)); }
53
static INLINE u32 COLSATSTRIPPRIORITY(u32 pixel) { return (0xFF000000 | pixel); }
54
#endif
55
56
#define COLOR_ADDt(b) (b>0xFF?0xFF:(b<0?0:b))
57
#define COLOR_ADDb(b1,b2) COLOR_ADDt((signed) (b1) + (b2))
58
#ifdef WORDS_BIGENDIAN
59
#define COLOR_ADD(l,r,g,b) (COLOR_ADDb(l & 0xFF, r) << 24) | \
60
(COLOR_ADDb((l >> 8) & 0xFF, g) << 16) | \
61
(COLOR_ADDb((l >> 16) & 0xFF, b) << 8) | \
62
((l >> 24) & 0xFF)
63
#else
64
#define COLOR_ADD(l,r,g,b) COLOR_ADDb((l & 0xFF), r) | \
65
(COLOR_ADDb((l >> 8) & 0xFF, g) << 8) | \
66
(COLOR_ADDb((l >> 16) & 0xFF, b) << 16) | \
67
(l & 0xFF000000)
68
#endif
69
70
static void PushUserClipping(int mode);
71
static void PopUserClipping(void);
72
73
int VIDGCDInit(void);
74
void VIDGCDDeInit(void);
75
void VIDGCDResize(unsigned int, unsigned int, int);
76
int VIDGCDIsFullscreen(void);
77
int VIDGCDVdp1Reset(void);
78
void VIDGCDVdp1DrawStart(void);
79
void VIDGCDVdp1DrawEnd(void);
80
void VIDGCDVdp1NormalSpriteDraw(void);
81
void VIDGCDVdp1ScaledSpriteDraw(void);
82
void VIDGCDVdp1DistortedSpriteDraw(void);
83
void VIDGCDVdp1PolygonDraw(void);
84
void VIDGCDVdp1PolylineDraw(void);
85
void VIDGCDVdp1LineDraw(void);
86
void VIDGCDVdp1UserClipping(void);
87
void VIDGCDVdp1SystemClipping(void);
88
void VIDGCDVdp1LocalCoordinate(void);
89
int VIDGCDVdp2Reset(void);
90
void VIDGCDVdp2DrawStart(void);
91
void VIDGCDVdp2DrawEnd(void);
92
void VIDGCDVdp2DrawScreens(void);
93
void VIDGCDVdp2SetResolution(u16 TVMD);
94
void FASTCALL VIDGCDVdp2SetPriorityNBG0(int priority);
95
void FASTCALL VIDGCDVdp2SetPriorityNBG1(int priority);
96
void FASTCALL VIDGCDVdp2SetPriorityNBG2(int priority);
97
void FASTCALL VIDGCDVdp2SetPriorityNBG3(int priority);
98
void FASTCALL VIDGCDVdp2SetPriorityRBG0(int priority);
99
void VIDGCDOnScreenDebugMessage(char *string, ...);
100
void VIDGCDGetGlSize(int *width, int *height);
101
void VIDGCDVdp1SwapFrameBuffer(void);
102
void VIDGCDVdp1EraseFrameBuffer(void);
103
104
VideoInterface_struct VIDGCD = {
105
VIDCORE_GCD,
106
"Grand Central Dispatch Software Video Interface",
107
VIDGCDInit,
108
VIDGCDDeInit,
109
VIDGCDResize,
110
VIDGCDIsFullscreen,
111
VIDGCDVdp1Reset,
112
VIDGCDVdp1DrawStart,
113
VIDGCDVdp1DrawEnd,
114
VIDGCDVdp1NormalSpriteDraw,
115
VIDGCDVdp1ScaledSpriteDraw,
116
VIDGCDVdp1DistortedSpriteDraw,
117
//for the actual hardware, polygons are essentially identical to distorted sprites
118
//the actual hardware draws using diagonal lines, which is why using half-transparent processing
119
//on distorted sprites and polygons is not recommended since the hardware overdraws to prevent gaps
120
//thus, with half-transparent processing some pixels will be processed more than once, producing moire patterns in the drawn shapes
121
VIDGCDVdp1DistortedSpriteDraw,
122
VIDGCDVdp1PolylineDraw,
123
VIDGCDVdp1LineDraw,
124
VIDGCDVdp1UserClipping,
125
VIDGCDVdp1SystemClipping,
126
VIDGCDVdp1LocalCoordinate,
127
VIDGCDVdp2Reset,
128
VIDGCDVdp2DrawStart,
129
VIDGCDVdp2DrawEnd,
130
VIDGCDVdp2DrawScreens,
131
VIDGCDVdp2SetResolution,
132
VIDGCDVdp2SetPriorityNBG0,
133
VIDGCDVdp2SetPriorityNBG1,
134
VIDGCDVdp2SetPriorityNBG2,
135
VIDGCDVdp2SetPriorityNBG3,
136
VIDGCDVdp2SetPriorityRBG0,
137
VIDGCDOnScreenDebugMessage,
138
VIDGCDGetGlSize,
139
};
140
141
static u32 *dispbuffer=NULL;
142
static u8 *vdp1framebuffer[2]= { NULL, NULL };
143
static u8 *vdp1frontframebuffer;
144
static u8 *vdp1backframebuffer;
145
static u32 *vdp2framebuffer=NULL;
146
147
static int vdp1width;
148
static int vdp1height;
149
static int vdp1clipxstart;
150
static int vdp1clipxend;
151
static int vdp1clipystart;
152
static int vdp1clipyend;
153
static int vdp1pixelsize;
154
static int vdp1spritetype;
155
int vdp2width;
156
int vdp2height;
157
static int nbg0priority=0;
158
static int nbg1priority=0;
159
static int nbg2priority=0;
160
static int nbg3priority=0;
161
static int rbg0priority=0;
162
#ifdef USE_OPENGL
163
static int outputwidth;
164
static int outputheight;
165
#endif
166
static int resxratio;
167
static int resyratio;
168
169
static char message[512];
170
static int msglength;
171
172
typedef struct { s16 x; s16 y; } vdp1vertex;
173
174
typedef struct
175
{
176
int pagepixelwh, pagepixelwh_bits, pagepixelwh_mask;
177
int planepixelwidth, planepixelwidth_bits, planepixelwidth_mask;
178
int planepixelheight, planepixelheight_bits, planepixelheight_mask;
179
int screenwidth;
180
int screenheight;
181
int oldcellx, oldcelly, oldcellcheck;
182
int xmask, ymask;
183
u32 planetbl[16];
184
} screeninfo_struct;
185
186
struct {
187
vdp2draw_struct info;
188
u8 prioritytable[8];
189
u32 coloroffset;
190
int islinewindow;
191
clipping_struct clip[2];
192
u32 linewnd0addr, linewnd1addr;
193
int priosused[8];
194
} vdp1draw_info;
195
196
//////////////////////////////////////////////////////////////////////////////
197
198
static INLINE void vdp2putpixel32(s32 x, s32 y, u32 color, int priority)
199
{
200
vdp2framebuffer[(y * vdp2width) + x] = COLSAT2YAB32(priority, color);
201
}
202
203
//////////////////////////////////////////////////////////////////////////////
204
205
static INLINE u8 Vdp2GetPixelPriority(u32 pixel)
206
{
207
#if defined WORDS_BIGENDIAN
208
return pixel;
209
#else
210
return pixel >> 24;
211
#endif
212
}
213
214
//////////////////////////////////////////////////////////////////////////////
215
216
static INLINE void puthline16(s32 x, s32 y, s32 width, u16 color, int priority)
217
{
218
u32 *buffer = vdp2framebuffer + (y * vdp2width) + x;
219
u32 dot=COLSAT2YAB16(priority, color);
220
int i;
221
222
for (i = 0; i < width; i++)
223
buffer[i] = dot;
224
}
225
226
//////////////////////////////////////////////////////////////////////////////
227
228
static INLINE u32 FASTCALL Vdp2ColorRamGetColor(u32 addr)
229
{
230
switch(Vdp2Internal.ColorMode)
231
{
232
case 0:
233
{
234
u32 tmp;
235
addr <<= 1;
236
tmp = T2ReadWord(Vdp2ColorRam, addr & 0xFFF);
237
return (((tmp & 0x1F) << 3) | ((tmp & 0x03E0) << 6) | ((tmp & 0x7C00) << 9));
238
}
239
case 1:
240
{
241
u32 tmp;
242
addr <<= 1;
243
tmp = T2ReadWord(Vdp2ColorRam, addr & 0xFFF);
244
return (((tmp & 0x1F) << 3) | ((tmp & 0x03E0) << 6) | ((tmp & 0x7C00) << 9));
245
}
246
case 2:
247
{
248
addr <<= 2;
249
return T2ReadLong(Vdp2ColorRam, addr & 0xFFF);
250
}
251
default: break;
252
}
253
254
return 0;
255
}
256
257
//////////////////////////////////////////////////////////////////////////////
258
259
static INLINE void Vdp2PatternAddr(vdp2draw_struct *info)
260
{
261
switch(info->patterndatasize)
262
{
263
case 1:
264
{
265
u16 tmp = T1ReadWord(Vdp2Ram, info->addr);
266
267
info->addr += 2;
268
info->specialfunction = (info->supplementdata >> 9) & 0x1;
269
270
switch(info->colornumber)
271
{
272
case 0: // in 16 colors
273
info->paladdr = ((tmp & 0xF000) >> 8) | ((info->supplementdata & 0xE0) << 3);
274
break;
275
default: // not in 16 colors
276
info->paladdr = (tmp & 0x7000) >> 4;
277
break;
278
}
279
280
switch(info->auxmode)
281
{
282
case 0:
283
info->flipfunction = (tmp & 0xC00) >> 10;
284
285
switch(info->patternwh)
286
{
287
case 1:
288
info->charaddr = (tmp & 0x3FF) | ((info->supplementdata & 0x1F) << 10);
289
break;
290
case 2:
291
info->charaddr = ((tmp & 0x3FF) << 2) | (info->supplementdata & 0x3) | ((info->supplementdata & 0x1C) << 10);
292
break;
293
}
294
break;
295
case 1:
296
info->flipfunction = 0;
297
298
switch(info->patternwh)
299
{
300
case 1:
301
info->charaddr = (tmp & 0xFFF) | ((info->supplementdata & 0x1C) << 10);
302
break;
303
case 2:
304
info->charaddr = ((tmp & 0xFFF) << 2) | (info->supplementdata & 0x3) | ((info->supplementdata & 0x10) << 10);
305
break;
306
}
307
break;
308
}
309
310
break;
311
}
312
case 2: {
313
u16 tmp1 = T1ReadWord(Vdp2Ram, info->addr);
314
u16 tmp2 = T1ReadWord(Vdp2Ram, info->addr+2);
315
info->addr += 4;
316
info->charaddr = tmp2 & 0x7FFF;
317
info->flipfunction = (tmp1 & 0xC000) >> 14;
318
info->paladdr = (tmp1 & 0x7F) << 4;
319
info->specialfunction = (tmp1 & 0x2000) >> 13;
320
break;
321
}
322
}
323
324
if (!(Vdp2Regs->VRSIZE & 0x8000))
325
info->charaddr &= 0x3FFF;
326
327
info->charaddr *= 0x20; // selon Runik
328
if (info->specialprimode == 1) {
329
info->priority = (info->priority & 0xE) | (info->specialfunction & 1);
330
}
331
}
332
333
//////////////////////////////////////////////////////////////////////////////
334
335
static INLINE u32 FASTCALL DoNothing(UNUSED void *info, u32 pixel)
336
{
337
return pixel;
338
}
339
340
//////////////////////////////////////////////////////////////////////////////
341
342
static INLINE u32 FASTCALL DoColorOffset(void *info, u32 pixel)
343
{
344
return COLOR_ADD(pixel, ((vdp2draw_struct *)info)->cor,
345
((vdp2draw_struct *)info)->cog,
346
((vdp2draw_struct *)info)->cob);
347
}
348
349
//////////////////////////////////////////////////////////////////////////////
350
351
static INLINE u32 FASTCALL DoColorCalc(void *info, u32 pixel)
352
{
353
#if 0
354
u8 oldr, oldg, oldb;
355
u8 r, g, b;
356
u32 oldpixel = 0x00FFFFFF; // fix me
357
358
static int topratio[32] = {
359
31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16,
360
15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
361
};
362
static int bottomratio[32] = {
363
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
364
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
365
};
366
367
// separate color components for top and second pixel
368
r = (pixel & 0xFF) * topratio[((vdp2draw_struct *)info)->alpha] >> 5;
369
g = ((pixel >> 8) & 0xFF) * topratio[((vdp2draw_struct *)info)->alpha] >> 5;
370
b = ((pixel >> 16) & 0xFF) * topratio[((vdp2draw_struct *)info)->alpha] >> 5;
371
372
#ifdef WORDS_BIGENDIAN
373
oldr = ((oldpixel >> 24) & 0xFF) * bottomratio[((vdp2draw_struct *)info)->alpha] >> 5;
374
oldg = ((oldpixel >> 16) & 0xFF) * bottomratio[((vdp2draw_struct *)info)->alpha] >> 5;
375
oldb = ((oldpixel >> 8) & 0xFF) * bottomratio[((vdp2draw_struct *)info)->alpha] >> 5;
376
#else
377
oldr = (oldpixel & 0xFF) * bottomratio[((vdp2draw_struct *)info)->alpha] >> 5;
378
oldg = ((oldpixel >> 8) & 0xFF) * bottomratio[((vdp2draw_struct *)info)->alpha] >> 5;
379
oldb = ((oldpixel >> 16) & 0xFF) * bottomratio[((vdp2draw_struct *)info)->alpha] >> 5;
380
#endif
381
382
// add color components and reform the pixel
383
pixel = ((b + oldb) << 16) | ((g + oldg) << 8) | (r + oldr);
384
#endif
385
return pixel;
386
}
387
388
//////////////////////////////////////////////////////////////////////////////
389
390
static INLINE u32 FASTCALL DoColorCalcWithColorOffset(void *info, u32 pixel)
391
{
392
pixel = DoColorCalc(info, pixel);
393
394
return COLOR_ADD(pixel, ((vdp2draw_struct *)info)->cor,
395
((vdp2draw_struct *)info)->cog,
396
((vdp2draw_struct *)info)->cob);
397
}
398
399
//////////////////////////////////////////////////////////////////////////////
400
401
static INLINE void ReadVdp2ColorOffset(vdp2draw_struct *info, int clofmask, int ccmask)
402
{
403
if (Vdp2Regs->CLOFEN & clofmask)
404
{
405
// color offset enable
406
if (Vdp2Regs->CLOFSL & clofmask)
407
{
408
// color offset B
409
info->cor = Vdp2Regs->COBR & 0xFF;
410
if (Vdp2Regs->COBR & 0x100)
411
info->cor |= 0xFFFFFF00;
412
413
info->cog = Vdp2Regs->COBG & 0xFF;
414
if (Vdp2Regs->COBG & 0x100)
415
info->cog |= 0xFFFFFF00;
416
417
info->cob = Vdp2Regs->COBB & 0xFF;
418
if (Vdp2Regs->COBB & 0x100)
419
info->cob |= 0xFFFFFF00;
420
}
421
else
422
{
423
// color offset A
424
info->cor = Vdp2Regs->COAR & 0xFF;
425
if (Vdp2Regs->COAR & 0x100)
426
info->cor |= 0xFFFFFF00;
427
428
info->cog = Vdp2Regs->COAG & 0xFF;
429
if (Vdp2Regs->COAG & 0x100)
430
info->cog |= 0xFFFFFF00;
431
432
info->cob = Vdp2Regs->COAB & 0xFF;
433
if (Vdp2Regs->COAB & 0x100)
434
info->cob |= 0xFFFFFF00;
435
}
436
437
if (info->cor == 0 && info->cog == 0 && info->cob == 0)
438
{
439
if (Vdp2Regs->CCCTL & ccmask)
440
info->PostPixelFetchCalc = &DoColorCalc;
441
else
442
info->PostPixelFetchCalc = &DoNothing;
443
}
444
else
445
{
446
if (Vdp2Regs->CCCTL & ccmask)
447
info->PostPixelFetchCalc = &DoColorCalcWithColorOffset;
448
else
449
info->PostPixelFetchCalc = &DoColorOffset;
450
}
451
}
452
else // color offset disable
453
{
454
if (Vdp2Regs->CCCTL & ccmask)
455
info->PostPixelFetchCalc = &DoColorCalc;
456
else
457
info->PostPixelFetchCalc = &DoNothing;
458
}
459
460
}
461
462
//////////////////////////////////////////////////////////////////////////////
463
464
static INLINE int Vdp2FetchPixel(vdp2draw_struct *info, int x, int y, u32 *color)
465
{
466
u32 dot;
467
468
switch(info->colornumber)
469
{
470
case 0: // 4 BPP
471
dot = T1ReadByte(Vdp2Ram, ((info->charaddr + ((y * info->cellw) + x) / 2) & 0x7FFFF));
472
if (!(x & 0x1)) dot >>= 4;
473
if (!(dot & 0xF) && info->transparencyenable) return 0;
474
else
475
{
476
*color = Vdp2ColorRamGetColor(info->coloroffset + (info->paladdr | (dot & 0xF)));
477
return 1;
478
}
479
case 1: // 8 BPP
480
dot = T1ReadByte(Vdp2Ram, ((info->charaddr + (y * info->cellw) + x) & 0x7FFFF));
481
if (!(dot & 0xFF) && info->transparencyenable) return 0;
482
else
483
{
484
*color = Vdp2ColorRamGetColor(info->coloroffset + (info->paladdr | (dot & 0xFF)));
485
return 1;
486
}
487
case 2: // 16 BPP(palette)
488
dot = T1ReadWord(Vdp2Ram, ((info->charaddr + ((y * info->cellw) + x) * 2) & 0x7FFFF));
489
if ((dot == 0) && info->transparencyenable) return 0;
490
else
491
{
492
*color = Vdp2ColorRamGetColor(info->coloroffset + dot);
493
return 1;
494
}
495
case 3: // 16 BPP(RGB)
496
dot = T1ReadWord(Vdp2Ram, ((info->charaddr + ((y * info->cellw) + x) * 2) & 0x7FFFF));
497
if (!(dot & 0x8000) && info->transparencyenable) return 0;
498
else
499
{
500
*color = COLSAT2YAB16(0, dot);
501
return 1;
502
}
503
case 4: // 32 BPP
504
dot = T1ReadLong(Vdp2Ram, ((info->charaddr + ((y * info->cellw) + x) * 4) & 0x7FFFF));
505
if (!(dot & 0x80000000) && info->transparencyenable) return 0;
506
else
507
{
508
*color = COLSAT2YAB32(0, dot);
509
return 1;
510
}
511
default:
512
return 0;
513
}
514
}
515
516
//////////////////////////////////////////////////////////////////////////////
517
518
static INLINE int TestWindow(int wctl, int enablemask, int inoutmask, clipping_struct *clip, int x, int y)
519
{
520
if (wctl & enablemask)
521
{
522
if (wctl & inoutmask)
523
{
524
// Draw inside of window
525
if (x < clip->xstart || x > clip->xend ||
526
y < clip->ystart || y > clip->yend)
527
return 0;
528
}
529
else
530
{
531
// Draw outside of window
532
if (x >= clip->xstart && x <= clip->xend &&
533
y >= clip->ystart && y <= clip->yend)
534
return 0;
535
536
//it seems to overflow vertically on hardware
537
if(clip->yend > vdp2height && (x >= clip->xstart && x <= clip->xend ))
538
return 0;
539
}
540
}
541
return 1;
542
}
543
544
//////////////////////////////////////////////////////////////////////////////
545
546
static INLINE void GeneratePlaneAddrTable(vdp2draw_struct *info, u32 *planetbl)
547
{
548
int i;
549
550
for (i = 0; i < (info->mapwh*info->mapwh); i++)
551
{
552
info->PlaneAddr(info, i);
553
planetbl[i] = info->addr;
554
}
555
}
556
557
//////////////////////////////////////////////////////////////////////////////
558
559
static INLINE void FASTCALL Vdp2MapCalcXY(vdp2draw_struct *info, int *x, int *y,
560
screeninfo_struct *sinfo)
561
{
562
int planenum;
563
const int pagesize_bits=info->pagewh_bits*2;
564
const int cellwh=(2 + info->patternwh);
565
566
const int check = ((y[0] >> cellwh) << 16) | (x[0] >> cellwh);
567
//if ((x[0] >> cellwh) != sinfo->oldcellx || (y[0] >> cellwh) != sinfo->oldcelly)
568
if(check != sinfo->oldcellcheck)
569
{
570
sinfo->oldcellx = x[0] >> cellwh;
571
sinfo->oldcelly = y[0] >> cellwh;
572
sinfo->oldcellcheck = (sinfo->oldcelly << 16) | sinfo->oldcellx;
573
574
// Calculate which plane we're dealing with
575
planenum = ((y[0] >> sinfo->planepixelheight_bits) * info->mapwh) + (x[0] >> sinfo->planepixelwidth_bits);
576
x[0] = (x[0] & sinfo->planepixelwidth_mask);
577
y[0] = (y[0] & sinfo->planepixelheight_mask);
578
579
// Fetch and decode pattern name data
580
info->addr = sinfo->planetbl[planenum];
581
582
// Figure out which page it's on(if plane size is not 1x1)
583
info->addr += (( ((y[0] >> sinfo->pagepixelwh_bits) << pagesize_bits) << info->planew_bits) +
584
( (x[0] >> sinfo->pagepixelwh_bits) << pagesize_bits) +
585
(((y[0] & sinfo->pagepixelwh_mask) >> cellwh) << info->pagewh_bits) +
586
((x[0] & sinfo->pagepixelwh_mask) >> cellwh)) << (info->patterndatasize_bits+1);
587
588
Vdp2PatternAddr(info); // Heh, this could be optimized
589
}
590
591
// Figure out which pixel in the tile we want
592
if (info->patternwh == 1)
593
{
594
x[0] &= 8-1;
595
y[0] &= 8-1;
596
597
switch(info->flipfunction & 0x3)
598
{
599
case 0: //none
600
break;
601
case 1: //horizontal flip
602
x[0] = 8 - 1 - x[0];
603
break;
604
case 2: // vertical flip
605
y[0] = 8 - 1 - y[0];
606
break;
607
case 3: //flip both
608
x[0] = 8 - 1 - x[0];
609
y[0] = 8 - 1 - y[0];
610
break;
611
}
612
}
613
else
614
{
615
if (info->flipfunction)
616
{
617
y[0] &= 16 - 1;
618
if (info->flipfunction & 0x2)
619
{
620
if (!(y[0] & 8))
621
y[0] = 8 - 1 - y[0] + 16;
622
else
623
y[0] = 16 - 1 - y[0];
624
}
625
else if (y[0] & 8)
626
y[0] += 8;
627
628
if (info->flipfunction & 0x1)
629
{
630
if (!(x[0] & 8))
631
y[0] += 8;
632
633
x[0] &= 8-1;
634
x[0] = 8 - 1 - x[0];
635
}
636
else if (x[0] & 8)
637
{
638
y[0] += 8;
639
x[0] &= 8-1;
640
}
641
else
642
x[0] &= 8-1;
643
}
644
else
645
{
646
y[0] &= 16 - 1;
647
648
if (y[0] & 8)
649
y[0] += 8;
650
if (x[0] & 8)
651
y[0] += 8;
652
x[0] &= 8-1;
653
}
654
}
655
}
656
657
//////////////////////////////////////////////////////////////////////////////
658
659
static INLINE void SetupScreenVars(vdp2draw_struct *info, screeninfo_struct *sinfo)
660
{
661
if (!info->isbitmap)
662
{
663
sinfo->pagepixelwh=64*8;
664
sinfo->pagepixelwh_bits = 9;
665
sinfo->pagepixelwh_mask = 511;
666
667
sinfo->planepixelwidth=info->planew*sinfo->pagepixelwh;
668
sinfo->planepixelwidth_bits = 8+info->planew;
669
sinfo->planepixelwidth_mask = (1<<(sinfo->planepixelwidth_bits))-1;
670
671
sinfo->planepixelheight=info->planeh*sinfo->pagepixelwh;
672
sinfo->planepixelheight_bits = 8+info->planeh;
673
sinfo->planepixelheight_mask = (1<<(sinfo->planepixelheight_bits))-1;
674
675
sinfo->screenwidth=info->mapwh*sinfo->planepixelwidth;
676
sinfo->screenheight=info->mapwh*sinfo->planepixelheight;
677
sinfo->oldcellx=-1;
678
sinfo->oldcelly=-1;
679
sinfo->xmask = sinfo->screenwidth-1;
680
sinfo->ymask = sinfo->screenheight-1;
681
GeneratePlaneAddrTable(info, sinfo->planetbl);
682
}
683
else
684
{
685
sinfo->pagepixelwh = 0;
686
sinfo->pagepixelwh_bits = 0;
687
sinfo->pagepixelwh_mask = 0;
688
sinfo->planepixelwidth=0;
689
sinfo->planepixelwidth_bits=0;
690
sinfo->planepixelwidth_mask=0;
691
sinfo->planepixelheight=0;
692
sinfo->planepixelheight_bits=0;
693
sinfo->planepixelheight_mask=0;
694
sinfo->screenwidth=0;
695
sinfo->screenheight=0;
696
sinfo->oldcellx=0;
697
sinfo->oldcelly=0;
698
sinfo->oldcellcheck=0;
699
sinfo->xmask = info->cellw-1;
700
sinfo->ymask = info->cellh-1;
701
}
702
}
703
704
//////////////////////////////////////////////////////////////////////////////
705
706
/* FIXME: This function will not work on Big Endian systems. Since its only here
707
in vidgcd, and the only thing that this vidcore will work on right now is
708
Mac OS X 10.6 (which is only available for Little Endian systems), its ok for
709
the time being... */
710
static INLINE u32 FASTCALL Vdp2Blend(vdp2draw_struct *info, u32 src, u32 dst) {
711
u32 alpha, s1, s2, d1, d2, o1, o2, pri;
712
713
pri = Vdp2GetPixelPriority(dst);
714
715
/* If we're not doing color calculation on this plane, then there's no need
716
to do any blending... */
717
if(info->PostPixelFetchCalc != &DoColorCalc &&
718
info->PostPixelFetchCalc != &DoColorCalcWithColorOffset) {
719
/* If the old pixel is of higher priority, use it. */
720
if(pri > info->priority) {
721
return dst;
722
}
723
724
return src;
725
}
726
727
if(pri < info->priority) {
728
pri = info->priority;
729
}
730
731
alpha = 255 - (((info->alpha) << 3) + 0x07);
732
733
/* Magic alpha blending! */
734
s1 = src & 0x00FF00FF;
735
s2 = src & 0x0000FF00;
736
d1 = dst & 0x00FF00FF;
737
d2 = dst & 0x0000FF00;
738
739
o1 = (d1 + (((s1 - d1) * alpha) >> 8)) & 0x00FF00FF;
740
o2 = (d2 + (((s2 - d2) * alpha) >> 8)) & 0x0000FF00;
741
742
return o1 | o2 | (pri << 24);
743
}
744
745
//////////////////////////////////////////////////////////////////////////////
746
747
static void FASTCALL GCDVdp2DrawScroll(vdp2draw_struct *_info, u32 *_textdata, int width, int height)
748
{
749
int i, j;
750
clipping_struct _clip[2], _clip1, _clip2;
751
u32 _linewnd0addr, _linewnd1addr;
752
screeninfo_struct _sinfo;
753
int scrollx, scrolly;
754
int *mosaic_y, *mosaic_x;
755
int linescrollmult = (_info->islinescroll & 1) +
756
((_info->islinescroll & 2) >> 1) + ((_info->islinescroll & 4) >> 2);
757
758
_info->coordincx *= (float)resxratio;
759
_info->coordincy *= (float)resyratio;
760
761
SetupScreenVars(_info, &_sinfo);
762
763
scrollx = _info->x;
764
scrolly = _info->y;
765
766
_clip[0].xstart = _clip[0].ystart = _clip[0].xend = _clip[0].yend = 0;
767
_clip[1].xstart = _clip[1].ystart = _clip[1].xend = _clip[1].yend = 0;
768
ReadWindowData(_info->wctl, _clip);
769
_clip1 = _clip[0];
770
_clip2 = _clip[1];
771
_linewnd0addr = _linewnd1addr = 0;
772
ReadLineWindowData(&_info->islinewindow, _info->wctl, &_linewnd0addr, &_linewnd1addr);
773
774
{
775
static int tables_initialized = 0;
776
static int mosaic_table[16][1024];
777
if(!tables_initialized)
778
{
779
tables_initialized = 1;
780
for(i=0;i<16;i++)
781
{
782
int m = i+1;
783
for(j=0;j<1024;j++)
784
mosaic_table[i][j] = j/m*m;
785
}
786
}
787
mosaic_x = mosaic_table[_info->mosaicxmask-1];
788
mosaic_y = mosaic_table[_info->mosaicymask-1];
789
}
790
791
dispatch_apply(height, dispatch_get_global_queue(2, 0), ^(size_t j) {
792
int x, y, i;
793
u32 *textdata = _textdata + (j * width);
794
u32 linewnd0addr = _linewnd0addr, linewnd1addr = _linewnd1addr;
795
screeninfo_struct sinfo = _sinfo;
796
clipping_struct clip[2] = { _clip1, _clip2 };
797
vdp2draw_struct inf = *_info;
798
vdp2draw_struct *info = &inf;
799
int Y;
800
int linescrollx = 0;
801
802
// if line window is enabled, adjust clipping values
803
if(info->islinewindow) {
804
// Fetch new xstart and xend values from table
805
if (info->islinewindow & 0x1)
806
{
807
// Window 0
808
linewnd0addr = _linewnd0addr + j * 4;
809
clip[0].xstart = (T1ReadWord(Vdp2Ram, linewnd0addr) & 0x3FF) >> 1; // fix me
810
linewnd0addr += 2;
811
clip[0].xend = (T1ReadWord(Vdp2Ram, linewnd0addr) & 0x3FF) >> 1; // fix me
812
}
813
if (info->islinewindow & 0x2)
814
{
815
// Window 1
816
linewnd1addr = _linewnd1addr + j * 4;
817
clip[1].xstart = (T1ReadWord(Vdp2Ram, linewnd1addr) & 0x3FF) >> 1; // fix me
818
linewnd1addr += 2;
819
clip[1].xend = (T1ReadWord(Vdp2Ram, linewnd1addr) & 0x3FF) >> 1; // fix me
820
}
821
}
822
823
// precalculate the coordinate for the line(it's faster) and do line
824
// scroll
825
if (info->islinescroll)
826
{
827
/* Figure out where we actually are in the line scroll table. */
828
info->linescrolltbl += linescrollmult * (j << 2);
829
830
if (info->islinescroll & 0x1)
831
{
832
linescrollx = (T1ReadLong(Vdp2Ram, info->linescrolltbl) >> 16) & 0x7FF;
833
info->linescrolltbl += 4;
834
}
835
if (info->islinescroll & 0x2)
836
{
837
info->y = (T1ReadWord(Vdp2Ram, info->linescrolltbl) & 0x7FF) + scrolly;
838
info->linescrolltbl += 4;
839
y = info->y;
840
}
841
else
842
//y = info->y+((int)(info->coordincy *(float)(info->mosaicymask > 1 ? (j / info->mosaicymask * info->mosaicymask) : j)));
843
y = info->y + info->coordincy*mosaic_y[j];
844
if (info->islinescroll & 0x4)
845
{
846
info->coordincx = (T1ReadLong(Vdp2Ram, info->linescrolltbl) & 0x7FF00) / (float)65536.0;
847
info->linescrolltbl += 4;
848
}
849
}
850
else
851
//y = info->y+((int)(info->coordincy *(float)(info->mosaicymask > 1 ? (j / info->mosaicymask * info->mosaicymask) : j)));
852
y = info->y + info->coordincy * mosaic_y[j];
853
854
y &= sinfo.ymask;
855
856
if (info->isverticalscroll)
857
{
858
// this is *wrong*, vertical scroll use a different value per cell
859
// info->verticalscrolltbl should be incremented by info->verticalscrollinc
860
// each time there's a cell change and reseted at the end of the line...
861
// or something like that :)
862
y += T1ReadLong(Vdp2Ram, info->verticalscrolltbl) >> 16;
863
y &= 0x1FF;
864
}
865
866
Y=y;
867
868
for (i = 0; i < width; i++)
869
{
870
u32 color;
871
872
// See if screen position is clipped, if it isn't, continue
873
// AND window logic
874
if(!TestWindow(info->wctl, 0x2, 0x1, &clip[0], i, j) && !TestWindow(info->wctl, 0x8, 0x4, &clip[1], i, j) && (info->wctl & 0x80) == 0x80)
875
{
876
textdata++;
877
continue;
878
}
879
//OR window logic
880
else if ((info->wctl & 0x80) == 0)
881
{
882
if (!TestWindow(info->wctl, 0x2, 0x1, &clip[0], i, j))
883
{
884
textdata++;
885
continue;
886
}
887
888
// Window 1
889
if (!TestWindow(info->wctl, 0x8, 0x4, &clip[1], i,j))
890
{
891
textdata++;
892
continue;
893
}
894
}
895
896
//x = info->x+((int)(info->coordincx*(float)((info->mosaicxmask > 1) ? (i / info->mosaicxmask * info->mosaicxmask) : i)));
897
x = info->x + mosaic_x[i]*info->coordincx;
898
x &= sinfo.xmask;
899
900
if (linescrollx) {
901
x += linescrollx;
902
x &= 0x3FF;
903
}
904
905
if (!info->isbitmap)
906
{
907
// Tile
908
y=Y;
909
// need to calculate this without history!
910
Vdp2MapCalcXY(info, &x, &y, &sinfo);
911
}
912
913
// If priority of screen is less than current top pixel and per
914
// pixel priority isn't used, skip it
915
#ifndef CRAB_REWRITE
916
if (Vdp2GetPixelPriority(textdata[0]) > info->priority)
917
{
918
textdata++;
919
continue;
920
}
921
#endif
922
923
// Fetch Pixel, if it isn't transparent, continue
924
if (!Vdp2FetchPixel(info, x, y, &color))
925
{
926
textdata++;
927
continue;
928
}
929
930
// check special priority somewhere here
931
932
// Apply color offset and color calculation/special color calculation
933
// and then continue.
934
// We almost need to know well ahead of time what the top
935
// and second pixel is in order to work this.
936
937
#ifndef CRAB_REWRITE
938
textdata[0] = COLSAT2YAB32(info->priority, info->PostPixelFetchCalc(info, color));
939
textdata++;
940
#else
941
color = COLSAT2YAB32(info->priority, info->PostPixelFetchCalc(info, color));
942
*textdata++ = Vdp2Blend(info, color, *textdata);
943
#endif
944
}
945
});
946
}
947
948
//////////////////////////////////////////////////////////////////////////////
949
950
static void SetupRotationInfo(vdp2draw_struct *info, vdp2rotationparameterfp_struct *p)
951
{
952
if (info->rotatenum == 0)
953
{
954
Vdp2ReadRotationTableFP(0, p);
955
info->PlaneAddr = (void FASTCALL (*)(void *, int))&Vdp2ParameterAPlaneAddr;
956
}
957
else
958
{
959
Vdp2ReadRotationTableFP(1, &p[1]);
960
info->PlaneAddr = (void FASTCALL (*)(void *, int))&Vdp2ParameterBPlaneAddr;
961
}
962
}
963
964
//////////////////////////////////////////////////////////////////////////////
965
966
static void FASTCALL Vdp2DrawRotationFP(vdp2draw_struct *info, vdp2rotationparameterfp_struct *parameter)
967
{
968
int i, j;
969
int x, y;
970
screeninfo_struct sinfo;
971
vdp2rotationparameterfp_struct *p=&parameter[info->rotatenum];
972
973
SetupRotationInfo(info, parameter);
974
975
if (!p->coefenab)
976
{
977
fixed32 xmul, ymul, C, F;
978
979
// Since coefficients aren't being used, we can simplify the drawing process
980
if (IsScreenRotatedFP(p))
981
{
982
// No rotation
983
info->x = touint(mulfixed(p->kx, (p->Xst - p->Px)) + p->Px + p->Mx);
984
info->y = touint(mulfixed(p->ky, (p->Yst - p->Py)) + p->Py + p->My);
985
info->coordincx = tofloat(p->kx);
986
info->coordincy = tofloat(p->ky);
987
}
988
else
989
{
990
u32 *textdata=vdp2framebuffer;
991
992
GenerateRotatedVarFP(p, &xmul, &ymul, &C, &F);
993
994
// Do simple rotation
995
CalculateRotationValuesFP(p);
996
997
SetupScreenVars(info, &sinfo);
998
999
for (j = 0; j < vdp2height; j++)
1000
{
1001
for (i = 0; i < vdp2width; i++)
1002
{
1003
u32 color;
1004
1005
x = GenerateRotatedXPosFP(p, i, xmul, ymul, C) & sinfo.xmask;
1006
y = GenerateRotatedYPosFP(p, i, xmul, ymul, F) & sinfo.ymask;
1007
xmul += p->deltaXst;
1008
1009
// Convert coordinates into graphics
1010
if (!info->isbitmap)
1011
{
1012
// Tile
1013
Vdp2MapCalcXY(info, &x, &y, &sinfo);
1014
}
1015
1016
// If priority of screen is less than current top pixel and per
1017
// pixel priority isn't used, skip it
1018
if (Vdp2GetPixelPriority(textdata[0]) > info->priority)
1019
{
1020
textdata++;
1021
continue;
1022
}
1023
1024
// Fetch pixel
1025
if (!Vdp2FetchPixel(info, x, y, &color))
1026
{
1027
textdata++;
1028
continue;
1029
}
1030
1031
textdata[0] = COLSAT2YAB32(info->priority, info->PostPixelFetchCalc(info, color));
1032
textdata++;
1033
}
1034
ymul += p->deltaYst;
1035
}
1036
1037
return;
1038
}
1039
}
1040
else
1041
{
1042
fixed32 xmul, ymul, C, F;
1043
fixed32 coefx, coefy;
1044
u32 *textdata=vdp2framebuffer;
1045
1046
GenerateRotatedVarFP(p, &xmul, &ymul, &C, &F);
1047
1048
// Rotation using Coefficient Tables(now this stuff just gets wacky. It
1049
// has to be done in software, no exceptions)
1050
CalculateRotationValuesFP(p);
1051
1052
SetupScreenVars(info, &sinfo);
1053
coefx = coefy = 0;
1054
1055
for (j = 0; j < vdp2height; j++)
1056
{
1057
if (p->deltaKAx == 0)
1058
{
1059
Vdp2ReadCoefficientFP(p,
1060
p->coeftbladdr +
1061
touint(coefy) *
1062
p->coefdatasize);
1063
}
1064
1065
for (i = 0; i < vdp2width; i++)
1066
{
1067
u32 color;
1068
1069
if (p->deltaKAx != 0)
1070
{
1071
Vdp2ReadCoefficientFP(p,
1072
p->coeftbladdr +
1073
toint(coefy + coefx) *
1074
p->coefdatasize);
1075
coefx += p->deltaKAx;
1076
}
1077
1078
if (p->msb)
1079
{
1080
textdata++;
1081
continue;
1082
}
1083
1084
x = GenerateRotatedXPosFP(p, i, xmul, ymul, C) & sinfo.xmask;
1085
y = GenerateRotatedYPosFP(p, i, xmul, ymul, F) & sinfo.ymask;
1086
xmul += p->deltaXst;
1087
1088
// Convert coordinates into graphics
1089
if (!info->isbitmap)
1090
{
1091
// Tile
1092
Vdp2MapCalcXY(info, &x, &y, &sinfo);
1093
}
1094
1095
// If priority of screen is less than current top pixel and per
1096
// pixel priority isn't used, skip it
1097
if (Vdp2GetPixelPriority(textdata[0]) > info->priority)
1098
{
1099
textdata++;
1100
continue;
1101
}
1102
1103
// Fetch pixel
1104
if (!Vdp2FetchPixel(info, x, y, &color))
1105
{
1106
textdata++;
1107
continue;
1108
}
1109
1110
textdata[0] = COLSAT2YAB32(info->priority, info->PostPixelFetchCalc(info, color));
1111
textdata++;
1112
}
1113
ymul += p->deltaYst;
1114
coefx = 0;
1115
coefy += p->deltaKAst;
1116
}
1117
return;
1118
}
1119
1120
GCDVdp2DrawScroll(info, vdp2framebuffer, vdp2width, vdp2height);
1121
}
1122
1123
//////////////////////////////////////////////////////////////////////////////
1124
1125
static void Vdp2DrawBackScreen(void)
1126
{
1127
int i;
1128
1129
// Only draw black if TVMD's DISP and BDCLMD bits are cleared
1130
if ((Vdp2Regs->TVMD & 0x8000) == 0 && (Vdp2Regs->TVMD & 0x100) == 0)
1131
{
1132
// Draw Black
1133
for (i = 0; i < (vdp2width * vdp2height); i++)
1134
vdp2framebuffer[i] = 0;
1135
}
1136
else
1137
{
1138
// Draw Back Screen
1139
u32 scrAddr;
1140
u16 dot;
1141
1142
if (Vdp2Regs->VRSIZE & 0x8000)
1143
scrAddr = (((Vdp2Regs->BKTAU & 0x7) << 16) | Vdp2Regs->BKTAL) * 2;
1144
else
1145
scrAddr = (((Vdp2Regs->BKTAU & 0x3) << 16) | Vdp2Regs->BKTAL) * 2;
1146
1147
if (Vdp2Regs->BKTAU & 0x8000)
1148
{
1149
// Per Line
1150
for (i = 0; i < vdp2height; i++)
1151
{
1152
dot = T1ReadWord(Vdp2Ram, scrAddr);
1153
scrAddr += 2;
1154
1155
puthline16(0, i, vdp2width, dot, 0);
1156
}
1157
}
1158
else
1159
{
1160
// Single Color
1161
dot = T1ReadWord(Vdp2Ram, scrAddr);
1162
1163
for (i = 0; i < (vdp2width * vdp2height); i++)
1164
vdp2framebuffer[i] = COLSAT2YAB16(0, dot);
1165
}
1166
}
1167
}
1168
1169
//////////////////////////////////////////////////////////////////////////////
1170
1171
static void Vdp2DrawNBG0(void)
1172
{
1173
vdp2draw_struct info;
1174
vdp2rotationparameterfp_struct parameter[2];
1175
1176
if (Vdp2Regs->BGON & 0x20)
1177
{
1178
// RBG1 mode
1179
info.enable = Vdp2Regs->BGON & 0x20;
1180
1181
// Read in Parameter B
1182
Vdp2ReadRotationTableFP(1, &parameter[1]);
1183
1184
if((info.isbitmap = Vdp2Regs->CHCTLA & 0x2) != 0)
1185
{
1186
// Bitmap Mode
1187
ReadBitmapSize(&info, Vdp2Regs->CHCTLA >> 2, 0x3);
1188
1189
info.charaddr = (Vdp2Regs->MPOFR & 0x70) * 0x2000;
1190
info.paladdr = (Vdp2Regs->BMPNA & 0x7) << 8;
1191
info.flipfunction = 0;
1192
info.specialfunction = 0;
1193
}
1194
else
1195
{
1196
// Tile Mode
1197
info.mapwh = 4;
1198
ReadPlaneSize(&info, Vdp2Regs->PLSZ >> 12);
1199
ReadPatternData(&info, Vdp2Regs->PNCN0, Vdp2Regs->CHCTLA & 0x1);
1200
}
1201
1202
info.rotatenum = 1;
1203
info.rotatemode = 0;
1204
info.PlaneAddr = (void FASTCALL (*)(void *, int))&Vdp2ParameterBPlaneAddr;
1205
}
1206
else if (Vdp2Regs->BGON & 0x1)
1207
{
1208
// NBG0 mode
1209
info.enable = Vdp2Regs->BGON & 0x1;
1210
1211
if((info.isbitmap = Vdp2Regs->CHCTLA & 0x2) != 0)
1212
{
1213
// Bitmap Mode
1214
ReadBitmapSize(&info, Vdp2Regs->CHCTLA >> 2, 0x3);
1215
1216
info.x = Vdp2Regs->SCXIN0 & 0x7FF;
1217
info.y = Vdp2Regs->SCYIN0 & 0x7FF;
1218
1219
info.charaddr = (Vdp2Regs->MPOFN & 0x7) * 0x20000;
1220
info.paladdr = (Vdp2Regs->BMPNA & 0x7) << 8;
1221
info.flipfunction = 0;
1222
info.specialfunction = 0;
1223
}
1224
else
1225
{
1226
// Tile Mode
1227
info.mapwh = 2;
1228
1229
ReadPlaneSize(&info, Vdp2Regs->PLSZ);
1230
1231
info.x = Vdp2Regs->SCXIN0 & 0x7FF;
1232
info.y = Vdp2Regs->SCYIN0 & 0x7FF;
1233
ReadPatternData(&info, Vdp2Regs->PNCN0, Vdp2Regs->CHCTLA & 0x1);
1234
}
1235
1236
info.coordincx = (Vdp2Regs->ZMXN0.all & 0x7FF00) / (float) 65536;
1237
info.coordincy = (Vdp2Regs->ZMYN0.all & 0x7FF00) / (float) 65536;
1238
info.PlaneAddr = (void FASTCALL (*)(void *, int))&Vdp2NBG0PlaneAddr;
1239
}
1240
else
1241
// Not enabled
1242
return;
1243
1244
info.transparencyenable = !(Vdp2Regs->BGON & 0x100);
1245
info.specialprimode = Vdp2Regs->SFPRMD & 0x3;
1246
1247
info.colornumber = (Vdp2Regs->CHCTLA & 0x70) >> 4;
1248
1249
if (Vdp2Regs->CCCTL & 0x1)
1250
info.alpha = Vdp2Regs->CCRNA & 0x1F;
1251
1252
info.coloroffset = (Vdp2Regs->CRAOFA & 0x7) << 8;
1253
ReadVdp2ColorOffset(&info, 0x1, 0x1);
1254
info.priority = nbg0priority;
1255
1256
if (!(info.enable & Vdp2External.disptoggle))
1257
return;
1258
1259
ReadMosaicData(&info, 0x1);
1260
ReadLineScrollData(&info, Vdp2Regs->SCRCTL & 0xFF, Vdp2Regs->LSTA0.all);
1261
if (Vdp2Regs->SCRCTL & 1)
1262
{
1263
info.isverticalscroll = 1;
1264
info.verticalscrolltbl = (Vdp2Regs->VCSTA.all & 0x7FFFE) << 1;
1265
if (Vdp2Regs->SCRCTL & 0x100)
1266
info.verticalscrollinc = 8;
1267
else
1268
info.verticalscrollinc = 4;
1269
}
1270
else
1271
info.isverticalscroll = 0;
1272
info.wctl = Vdp2Regs->WCTLA;
1273
1274
if (info.enable == 1)
1275
{
1276
// NBG0 draw
1277
GCDVdp2DrawScroll(&info, vdp2framebuffer, vdp2width, vdp2height);
1278
}
1279
else
1280
{
1281
// RBG1 draw
1282
Vdp2DrawRotationFP(&info, parameter);
1283
}
1284
}
1285
1286
//////////////////////////////////////////////////////////////////////////////
1287
1288
static void Vdp2DrawNBG1(void)
1289
{
1290
vdp2draw_struct info;
1291
1292
info.enable = Vdp2Regs->BGON & 0x2;
1293
info.transparencyenable = !(Vdp2Regs->BGON & 0x200);
1294
info.specialprimode = (Vdp2Regs->SFPRMD >> 2) & 0x3;
1295
1296
info.colornumber = (Vdp2Regs->CHCTLA & 0x3000) >> 12;
1297
1298
if((info.isbitmap = Vdp2Regs->CHCTLA & 0x200) != 0)
1299
{
1300
ReadBitmapSize(&info, Vdp2Regs->CHCTLA >> 10, 0x3);
1301
1302
info.x = Vdp2Regs->SCXIN1 & 0x7FF;
1303
info.y = Vdp2Regs->SCYIN1 & 0x7FF;
1304
1305
info.charaddr = ((Vdp2Regs->MPOFN & 0x70) >> 4) * 0x20000;
1306
info.paladdr = Vdp2Regs->BMPNA & 0x700;
1307
info.flipfunction = 0;
1308
info.specialfunction = 0;
1309
}
1310
else
1311
{
1312
info.mapwh = 2;
1313
1314
ReadPlaneSize(&info, Vdp2Regs->PLSZ >> 2);
1315
1316
info.x = Vdp2Regs->SCXIN1 & 0x7FF;
1317
info.y = Vdp2Regs->SCYIN1 & 0x7FF;
1318
1319
ReadPatternData(&info, Vdp2Regs->PNCN1, Vdp2Regs->CHCTLA & 0x100);
1320
}
1321
1322
if (Vdp2Regs->CCCTL & 0x2)
1323
info.alpha = (Vdp2Regs->CCRNA >> 8) & 0x1F;
1324
1325
info.coloroffset = (Vdp2Regs->CRAOFA & 0x70) << 4;
1326
ReadVdp2ColorOffset(&info, 0x2, 0x2);
1327
info.coordincx = (Vdp2Regs->ZMXN1.all & 0x7FF00) / (float) 65536;
1328
info.coordincy = (Vdp2Regs->ZMYN1.all & 0x7FF00) / (float) 65536;
1329
1330
info.priority = nbg1priority;
1331
info.PlaneAddr = (void FASTCALL (*)(void *, int))&Vdp2NBG1PlaneAddr;
1332
1333
if (!(info.enable & Vdp2External.disptoggle))
1334
return;
1335
1336
ReadMosaicData(&info, 0x2);
1337
ReadLineScrollData(&info, Vdp2Regs->SCRCTL >> 8, Vdp2Regs->LSTA1.all);
1338
if (Vdp2Regs->SCRCTL & 0x100)
1339
{
1340
info.isverticalscroll = 1;
1341
if (Vdp2Regs->SCRCTL & 0x1)
1342
{
1343
info.verticalscrolltbl = 4 + ((Vdp2Regs->VCSTA.all & 0x7FFFE) << 1);
1344
info.verticalscrollinc = 8;
1345
}
1346
else
1347
{
1348
info.verticalscrolltbl = (Vdp2Regs->VCSTA.all & 0x7FFFE) << 1;
1349
info.verticalscrollinc = 4;
1350
}
1351
}
1352
else
1353
info.isverticalscroll = 0;
1354
info.wctl = Vdp2Regs->WCTLA >> 8;
1355
1356
GCDVdp2DrawScroll(&info, vdp2framebuffer, vdp2width, vdp2height);
1357
}
1358
1359
//////////////////////////////////////////////////////////////////////////////
1360
1361
static void Vdp2DrawNBG2(void)
1362
{
1363
vdp2draw_struct info;
1364
1365
info.enable = Vdp2Regs->BGON & 0x4;
1366
info.transparencyenable = !(Vdp2Regs->BGON & 0x400);
1367
info.specialprimode = (Vdp2Regs->SFPRMD >> 4) & 0x3;
1368
1369
info.colornumber = (Vdp2Regs->CHCTLB & 0x2) >> 1;
1370
info.mapwh = 2;
1371
1372
ReadPlaneSize(&info, Vdp2Regs->PLSZ >> 4);
1373
info.x = Vdp2Regs->SCXN2 & 0x7FF;
1374
info.y = Vdp2Regs->SCYN2 & 0x7FF;
1375
ReadPatternData(&info, Vdp2Regs->PNCN2, Vdp2Regs->CHCTLB & 0x1);
1376
1377
if (Vdp2Regs->CCCTL & 0x4)
1378
info.alpha = Vdp2Regs->CCRNB & 0x1F;
1379
1380
info.coloroffset = Vdp2Regs->CRAOFA & 0x700;
1381
ReadVdp2ColorOffset(&info, 0x4, 0x4);
1382
info.coordincx = info.coordincy = 1;
1383
1384
info.priority = nbg2priority;
1385
info.PlaneAddr = (void FASTCALL (*)(void *, int))&Vdp2NBG2PlaneAddr;
1386
1387
if (!(info.enable & Vdp2External.disptoggle))
1388
return;
1389
1390
ReadMosaicData(&info, 0x4);
1391
info.islinescroll = 0;
1392
info.isverticalscroll = 0;
1393
info.wctl = Vdp2Regs->WCTLB;
1394
info.isbitmap = 0;
1395
1396
GCDVdp2DrawScroll(&info, vdp2framebuffer, vdp2width, vdp2height);
1397
}
1398
1399
//////////////////////////////////////////////////////////////////////////////
1400
1401
static void Vdp2DrawNBG3(void)
1402
{
1403
vdp2draw_struct info;
1404
1405
info.enable = Vdp2Regs->BGON & 0x8;
1406
info.transparencyenable = !(Vdp2Regs->BGON & 0x800);
1407
info.specialprimode = (Vdp2Regs->SFPRMD >> 6) & 0x3;
1408
1409
info.colornumber = (Vdp2Regs->CHCTLB & 0x20) >> 5;
1410
1411
info.mapwh = 2;
1412
1413
ReadPlaneSize(&info, Vdp2Regs->PLSZ >> 6);
1414
info.x = Vdp2Regs->SCXN3 & 0x7FF;
1415
info.y = Vdp2Regs->SCYN3 & 0x7FF;
1416
ReadPatternData(&info, Vdp2Regs->PNCN3, Vdp2Regs->CHCTLB & 0x10);
1417
1418
if (Vdp2Regs->CCCTL & 0x8)
1419
info.alpha = (Vdp2Regs->CCRNB >> 8) & 0x1F;
1420
1421
info.coloroffset = (Vdp2Regs->CRAOFA & 0x7000) >> 4;
1422
ReadVdp2ColorOffset(&info, 0x8, 0x8);
1423
info.coordincx = info.coordincy = 1;
1424
1425
info.priority = nbg3priority;
1426
info.PlaneAddr = (void FASTCALL (*)(void *, int))&Vdp2NBG3PlaneAddr;
1427
1428
if (!(info.enable & Vdp2External.disptoggle))
1429
return;
1430
1431
ReadMosaicData(&info, 0x8);
1432
info.islinescroll = 0;
1433
info.isverticalscroll = 0;
1434
info.wctl = Vdp2Regs->WCTLB >> 8;
1435
info.isbitmap = 0;
1436
1437
GCDVdp2DrawScroll(&info, vdp2framebuffer, vdp2width, vdp2height);
1438
}
1439
1440
//////////////////////////////////////////////////////////////////////////////
1441
1442
static void Vdp2DrawRBG0(void)
1443
{
1444
vdp2draw_struct info;
1445
vdp2rotationparameterfp_struct parameter[2];
1446
1447
info.enable = Vdp2Regs->BGON & 0x10;
1448
info.priority = rbg0priority;
1449
if (!(info.enable & Vdp2External.disptoggle))
1450
return;
1451
info.transparencyenable = !(Vdp2Regs->BGON & 0x1000);
1452
info.specialprimode = (Vdp2Regs->SFPRMD >> 8) & 0x3;
1453
1454
info.colornumber = (Vdp2Regs->CHCTLB & 0x7000) >> 12;
1455
1456
// Figure out which Rotation Parameter we're using
1457
switch (Vdp2Regs->RPMD & 0x3)
1458
{
1459
case 0:
1460
// Parameter A
1461
info.rotatenum = 0;
1462
info.rotatemode = 0;
1463
info.PlaneAddr = (void FASTCALL (*)(void *, int))&Vdp2ParameterAPlaneAddr;
1464
break;
1465
case 1:
1466
// Parameter B
1467
info.rotatenum = 1;
1468
info.rotatemode = 0;
1469
info.PlaneAddr = (void FASTCALL (*)(void *, int))&Vdp2ParameterBPlaneAddr;
1470
break;
1471
case 2:
1472
// Parameter A+B switched via coefficients
1473
case 3:
1474
// Parameter A+B switched via rotation parameter window
1475
default:
1476
info.rotatenum = 0;
1477
info.rotatemode = 1 + (Vdp2Regs->RPMD & 0x1);
1478
info.PlaneAddr = (void FASTCALL (*)(void *, int))&Vdp2ParameterAPlaneAddr;
1479
break;
1480
}
1481
1482
Vdp2ReadRotationTableFP(info.rotatenum, &parameter[info.rotatenum]);
1483
1484
if((info.isbitmap = Vdp2Regs->CHCTLB & 0x200) != 0)
1485
{
1486
// Bitmap Mode
1487
ReadBitmapSize(&info, Vdp2Regs->CHCTLB >> 10, 0x1);
1488
1489
if (info.rotatenum == 0)
1490
// Parameter A
1491
info.charaddr = (Vdp2Regs->MPOFR & 0x7) * 0x20000;
1492
else
1493
// Parameter B
1494
info.charaddr = (Vdp2Regs->MPOFR & 0x70) * 0x2000;
1495
1496
info.paladdr = (Vdp2Regs->BMPNB & 0x7) << 8;
1497
info.flipfunction = 0;
1498
info.specialfunction = 0;
1499
}
1500
else
1501
{
1502
// Tile Mode
1503
info.mapwh = 4;
1504
1505
if (info.rotatenum == 0)
1506
// Parameter A
1507
ReadPlaneSize(&info, Vdp2Regs->PLSZ >> 8);
1508
else
1509
// Parameter B
1510
ReadPlaneSize(&info, Vdp2Regs->PLSZ >> 12);
1511
1512
ReadPatternData(&info, Vdp2Regs->PNCR, Vdp2Regs->CHCTLB & 0x100);
1513
}
1514
1515
if (Vdp2Regs->CCCTL & 0x10)
1516
info.alpha = Vdp2Regs->CCRR & 0x1F;
1517
1518
info.coloroffset = (Vdp2Regs->CRAOFB & 0x7) << 8;
1519
1520
ReadVdp2ColorOffset(&info, 0x10, 0x10);
1521
info.coordincx = info.coordincy = 1;
1522
1523
ReadMosaicData(&info, 0x10);
1524
info.islinescroll = 0;
1525
info.isverticalscroll = 0;
1526
info.wctl = Vdp2Regs->WCTLC;
1527
1528
Vdp2DrawRotationFP(&info, parameter);
1529
}
1530
1531
//////////////////////////////////////////////////////////////////////////////
1532
1533
int VIDGCDInit(void)
1534
{
1535
// Initialize output buffer
1536
if ((dispbuffer = (u32 *)calloc(sizeof(u32), 704 * 512)) == NULL)
1537
return -1;
1538
1539
// Initialize VDP1 framebuffer 1
1540
if ((vdp1framebuffer[0] = (u8 *)calloc(sizeof(u8), 0x40000)) == NULL)
1541
return -1;
1542
1543
// Initialize VDP1 framebuffer 2
1544
if ((vdp1framebuffer[1] = (u8 *)calloc(sizeof(u8), 0x40000)) == NULL)
1545
return -1;
1546
1547
// Initialize VDP2 framebuffer
1548
if ((vdp2framebuffer = (u32 *)calloc(sizeof(u32), 704 * 512)) == NULL)
1549
return -1;
1550
1551
vdp1backframebuffer = vdp1framebuffer[0];
1552
vdp1frontframebuffer = vdp1framebuffer[1];
1553
vdp2width = 320;
1554
vdp2height = 224;
1555
1556
#ifdef USE_OPENGL
1557
YuiSetVideoAttribute(DOUBLEBUFFER, 1);
1558
1559
if (!YglScreenInit(8, 8, 8, 24))
1560
{
1561
if (!YglScreenInit(4, 4, 4, 24))
1562
{
1563
if (!YglScreenInit(5, 6, 5, 16))
1564
{
1565
YuiErrorMsg("Couldn't set GL mode\n");
1566
return -1;
1567
}
1568
}
1569
}
1570
1571
glClear(GL_COLOR_BUFFER_BIT);
1572
1573
glMatrixMode(GL_PROJECTION);
1574
glLoadIdentity();
1575
glOrtho(0, 320, 224, 0, 1, 0);
1576
1577
glMatrixMode(GL_TEXTURE);
1578
glLoadIdentity();
1579
glOrtho(-320, 320, -224, 224, 1, 0);
1580
outputwidth = 320;
1581
outputheight = 224;
1582
msglength = 0;
1583
#endif
1584
1585
return 0;
1586
}
1587
1588
//////////////////////////////////////////////////////////////////////////////
1589
1590
void VIDGCDDeInit(void)
1591
{
1592
if (dispbuffer)
1593
{
1594
free(dispbuffer);
1595
dispbuffer = NULL;
1596
}
1597
1598
if (vdp1framebuffer[0])
1599
free(vdp1framebuffer[0]);
1600
1601
if (vdp1framebuffer[1])
1602
free(vdp1framebuffer[1]);
1603
1604
if (vdp2framebuffer)
1605
free(vdp2framebuffer);
1606
}
1607
1608
//////////////////////////////////////////////////////////////////////////////
1609
1610
static int IsFullscreen = 0;
1611
1612
void VIDGCDResize(unsigned int w, unsigned int h, int on)
1613
{
1614
#ifdef USE_OPENGL
1615
IsFullscreen = on;
1616
1617
if (on)
1618
YuiSetVideoMode(w, h, 32, 1);
1619
else
1620
YuiSetVideoMode(w, h, 32, 0);
1621
1622
glClear(GL_COLOR_BUFFER_BIT);
1623
1624
glMatrixMode(GL_PROJECTION);
1625
glLoadIdentity();
1626
glOrtho(0, w, h, 0, 1, 0);
1627
1628
glMatrixMode(GL_TEXTURE);
1629
glLoadIdentity();
1630
glOrtho(-w, w, -h, h, 1, 0);
1631
1632
glViewport(0, 0, w, h);
1633
outputwidth = w;
1634
outputheight = h;
1635
#endif
1636
}
1637
1638
//////////////////////////////////////////////////////////////////////////////
1639
1640
int VIDGCDIsFullscreen(void) {
1641
return IsFullscreen;
1642
}
1643
1644
//////////////////////////////////////////////////////////////////////////////
1645
1646
int VIDGCDVdp1Reset(void)
1647
{
1648
vdp1clipxstart = 0;
1649
vdp1clipxend = 512;
1650
vdp1clipystart = 0;
1651
vdp1clipyend = 256;
1652
1653
return 0;
1654
}
1655
1656
//////////////////////////////////////////////////////////////////////////////
1657
1658
void VIDGCDVdp1DrawStart(void)
1659
{
1660
if (Vdp1Regs->TVMR & 0x1)
1661
{
1662
if (Vdp1Regs->TVMR & 0x2)
1663
{
1664
// Rotation 8-bit
1665
vdp1width = 512;
1666
vdp1height = 512;
1667
}
1668
else
1669
{
1670
// Normal 8-bit
1671
vdp1width = 1024;
1672
vdp1width = 256;
1673
}
1674
1675
vdp1pixelsize = 1;
1676
}
1677
else
1678
{
1679
// Rotation/Normal 16-bit
1680
vdp1width = 512;
1681
vdp1height = 256;
1682
vdp1pixelsize = 2;
1683
}
1684
1685
VIDGCDVdp1EraseFrameBuffer();
1686
}
1687
1688
//////////////////////////////////////////////////////////////////////////////
1689
1690
void VIDGCDVdp1DrawEnd(void)
1691
{
1692
}
1693
1694
//////////////////////////////////////////////////////////////////////////////
1695
1696
static INLINE u16 Vdp1ReadPattern16( u32 base, u32 offset ) {
1697
1698
u16 dot = T1ReadByte(Vdp1Ram, ( base + (offset>>1)) & 0x7FFFF);
1699
if ((offset & 0x1) == 0) dot >>= 4; // Even pixel
1700
else dot &= 0xF; // Odd pixel
1701
return dot;
1702
}
1703
1704
static INLINE u16 Vdp1ReadPattern64( u32 base, u32 offset ) {
1705
1706
return T1ReadByte(Vdp1Ram, ( base + offset ) & 0x7FFFF) & 0x3F;
1707
}
1708
1709
static INLINE u16 Vdp1ReadPattern128( u32 base, u32 offset ) {
1710
1711
return T1ReadByte(Vdp1Ram, ( base + offset ) & 0x7FFFF) & 0x7F;
1712
}
1713
1714
static INLINE u16 Vdp1ReadPattern256( u32 base, u32 offset ) {
1715
1716
return T1ReadByte(Vdp1Ram, ( base + offset ) & 0x7FFFF) & 0xFF;
1717
}
1718
1719
static INLINE u16 Vdp1ReadPattern64k( u32 base, u32 offset ) {
1720
1721
return T1ReadWord(Vdp1Ram, ( base + 2*offset) & 0x7FFFF);
1722
}
1723
1724
////////////////////////////////////////////////////////////////////////////////
1725
1726
static INLINE u32 alphablend16(u32 d, u32 s, u32 level)
1727
{
1728
int r,g,b,sr,sg,sb,dr,dg,db;
1729
1730
int invlevel = 256-level;
1731
sr = s & 0x001f; dr = d & 0x001f;
1732
r = (sr*level + dr*invlevel)>>8; r&= 0x1f;
1733
sg = s & 0x03e0; dg = d & 0x03e0;
1734
g = (sg*level + dg*invlevel)>>8; g&= 0x03e0;
1735
sb = s & 0x7c00; db = d & 0x7c00;
1736
b = (sb*level + db*invlevel)>>8; b&= 0x7c00;
1737
return r|g|b;
1738
}
1739
1740
typedef struct _COLOR_PARAMS
1741
{
1742
double r,g,b;
1743
} COLOR_PARAMS;
1744
1745
COLOR_PARAMS leftColumnColor;
1746
1747
vdp1cmd_struct cmd;
1748
1749
int currentPixel;
1750
int currentPixelIsVisible;
1751
int characterWidth;
1752
int characterHeight;
1753
1754
static int getpixel(int linenumber, int currentlineindex) {
1755
1756
u32 characterAddress;
1757
u32 colorlut;
1758
u16 colorbank;
1759
u8 SPD;
1760
int endcode;
1761
int endcodesEnabled;
1762
int untexturedColor = 0;
1763
int isTextured = 1;
1764
int currentShape = cmd.CMDCTRL & 0x7;
1765
int flip;
1766
1767
characterAddress = cmd.CMDSRCA << 3;
1768
colorbank = cmd.CMDCOLR;
1769
colorlut = (u32)colorbank << 3;
1770
SPD = ((cmd.CMDPMOD & 0x40) != 0);//show the actual color of transparent pixels if 1 (they won't be drawn transparent)
1771
endcodesEnabled = (( cmd.CMDPMOD & 0x80) == 0 )?1:0;
1772
flip = (cmd.CMDCTRL & 0x30) >> 4;
1773
1774
//4 polygon, 5 polyline or 6 line
1775
if(currentShape == 4 || currentShape == 5 || currentShape == 6) {
1776
isTextured = 0;
1777
untexturedColor = cmd.CMDCOLR;
1778
}
1779
1780
switch( flip ) {
1781
case 1:
1782
// Horizontal flipping
1783
currentlineindex = characterWidth - currentlineindex-1;
1784
break;
1785
case 2:
1786
// Vertical flipping
1787
linenumber = characterHeight - linenumber-1;
1788
1789
break;
1790
case 3:
1791
// Horizontal/Vertical flipping
1792
linenumber = characterHeight - linenumber-1;
1793
currentlineindex = characterWidth - currentlineindex-1;
1794
break;
1795
}
1796
1797
switch ((cmd.CMDPMOD >> 3) & 0x7)
1798
{
1799
case 0x0: //4bpp bank
1800
endcode = 0xf;
1801
currentPixel = Vdp1ReadPattern16( characterAddress + (linenumber*(characterWidth>>1)), currentlineindex );
1802
if(isTextured && endcodesEnabled && currentPixel == endcode)
1803
return 1;
1804
if (!((currentPixel == 0) && !SPD))
1805
currentPixel = colorbank | currentPixel;
1806
currentPixelIsVisible = 0xf;
1807
break;
1808
1809
case 0x1://4bpp lut
1810
endcode = 0xf;
1811
currentPixel = Vdp1ReadPattern16( characterAddress + (linenumber*(characterWidth>>1)), currentlineindex );
1812
if(isTextured && endcodesEnabled && currentPixel == endcode)
1813
return 1;
1814
if (!(currentPixel == 0 && !SPD))
1815
currentPixel = T1ReadWord(Vdp1Ram, (currentPixel * 2 + colorlut) & 0x7FFFF);
1816
currentPixelIsVisible = 0xffff;
1817
break;
1818
case 0x2://8pp bank (64 color)
1819
//is there a hardware bug with endcodes in this color mode?
1820
//there are white lines around some characters in scud
1821
//using an endcode of 63 eliminates the white lines
1822
//but also causes some dropout due to endcodes being triggered that aren't triggered on hardware
1823
//the closest thing i can do to match the hardware is make all pixels with color index 63 transparent
1824
//this needs more hardware testing
1825
1826
endcode = 63;
1827
currentPixel = Vdp1ReadPattern64( characterAddress + (linenumber*(characterWidth)), currentlineindex );
1828
if(isTextured && endcodesEnabled && currentPixel == endcode)
1829
currentPixel = 0;
1830
// return 1;
1831
if (!((currentPixel == 0) && !SPD))
1832
currentPixel = colorbank | currentPixel;
1833
currentPixelIsVisible = 0x3f;
1834
break;
1835
case 0x3://128 color
1836
endcode = 0xff;
1837
currentPixel = Vdp1ReadPattern128( characterAddress + (linenumber*characterWidth), currentlineindex );
1838
if(isTextured && endcodesEnabled && currentPixel == endcode)
1839
return 1;
1840
if (!((currentPixel == 0) && !SPD))
1841
currentPixel = colorbank | currentPixel;
1842
currentPixelIsVisible = 0x7f;
1843
break;
1844
case 0x4://256 color
1845
endcode = 0xff;
1846
currentPixel = Vdp1ReadPattern256( characterAddress + (linenumber*characterWidth), currentlineindex );
1847
if(isTextured && endcodesEnabled && currentPixel == endcode)
1848
return 1;
1849
currentPixelIsVisible = 0xff;
1850
if (!((currentPixel == 0) && !SPD))
1851
currentPixel = colorbank | currentPixel;
1852
break;
1853
case 0x5://16bpp bank
1854
endcode = 0x7fff;
1855
currentPixel = Vdp1ReadPattern64k( characterAddress + (linenumber*characterWidth*2), currentlineindex );
1856
if(isTextured && endcodesEnabled && currentPixel == endcode)
1857
return 1;
1858
currentPixelIsVisible = 0xffff;
1859
break;
1860
}
1861
1862
if(!isTextured)
1863
currentPixel = untexturedColor;
1864
1865
//force the MSB to be on if MSBON is set
1866
currentPixel |= cmd.CMDPMOD & (1 << 15);
1867
1868
return 0;
1869
}
1870
1871
static int gouraudAdjust( int color, int tableValue )
1872
{
1873
color += (tableValue - 0x10);
1874
1875
if ( color < 0 ) color = 0;
1876
if ( color > 0x1f ) color = 0x1f;
1877
1878
return color;
1879
}
1880
1881
static void putpixel(int x, int y) {
1882
1883
u16* iPix = &((u16 *)vdp1backframebuffer)[(y * vdp1width) + x];
1884
int mesh = cmd.CMDPMOD & 0x0100;
1885
int SPD = ((cmd.CMDPMOD & 0x40) != 0);//show the actual color of transparent pixels if 1 (they won't be drawn transparent)
1886
int currentShape = cmd.CMDCTRL & 0x7;
1887
int isTextured=1;
1888
1889
if(mesh && (x^y)&1)
1890
return;
1891
1892
if(currentShape == 4 || currentShape == 5 || currentShape == 6)
1893
isTextured = 0;
1894
1895
if (cmd.CMDPMOD & 0x0400) PushUserClipping((cmd.CMDPMOD >> 9) & 0x1);
1896
1897
if (x >= vdp1clipxstart &&
1898
x < vdp1clipxend &&
1899
y >= vdp1clipystart &&
1900
y < vdp1clipyend)
1901
{}
1902
else
1903
return;
1904
1905
if (cmd.CMDPMOD & 0x0400) PopUserClipping();
1906
1907
1908
if ( SPD || (currentPixel & currentPixelIsVisible))
1909
{
1910
switch( cmd.CMDPMOD & 0x7 )//we want bits 0,1,2
1911
{
1912
case 0: // replace
1913
if (!((currentPixel == 0) && !SPD))
1914
*(iPix) = currentPixel;
1915
break;
1916
case 1: // shadow, TODO
1917
*(iPix) = currentPixel;
1918
break;
1919
case 2: // half luminance
1920
*(iPix) = ((currentPixel & ~0x8421) >> 1) | (1 << 15);
1921
break;
1922
case 3: // half transparent
1923
if ( *(iPix) & (1 << 15) )//only if MSB of framebuffer data is set
1924
*(iPix) = alphablend16( *(iPix), currentPixel, (1 << 7) ) | (1 << 15);
1925
else
1926
*(iPix) = currentPixel;
1927
break;
1928
case 4: //gouraud
1929
#define COLOR(r,g,b) (((r)&0x1F)|(((g)&0x1F)<<5)|(((b)&0x1F)<<10) |0x8000 )
1930
1931
//handle the special case demonstrated in the sgl chrome demo
1932
//if we are in a paletted bank mode and the other two colors are unused, adjust the index value instead of rgb
1933
if(
1934
(((cmd.CMDPMOD >> 3) & 0x7) != 5) &&
1935
(((cmd.CMDPMOD >> 3) & 0x7) != 1) &&
1936
(int)leftColumnColor.g == 16 &&
1937
(int)leftColumnColor.b == 16)
1938
{
1939
int c = (int)(leftColumnColor.r-0x10);
1940
if(c < 0) c = 0;
1941
currentPixel = currentPixel+c;
1942
*(iPix) = currentPixel;
1943
break;
1944
}
1945
*(iPix) = COLOR(
1946
gouraudAdjust(
1947
currentPixel&0x001F,
1948
(int)leftColumnColor.r),
1949
1950
gouraudAdjust(
1951
(currentPixel&0x03e0) >> 5,
1952
(int)leftColumnColor.g),
1953
1954
gouraudAdjust(
1955
(currentPixel&0x7c00) >> 10,
1956
(int)leftColumnColor.b)
1957
);
1958
break;
1959
default:
1960
*(iPix) = alphablend16( COLOR((int)leftColumnColor.r,(int)leftColumnColor.g, (int)leftColumnColor.b), currentPixel, (1 << 7) ) | (1 << 15);
1961
break;
1962
}
1963
1964
if(*iPix & 0x8000) {
1965
vdp1draw_info.priosused[vdp1draw_info.prioritytable[0]] = 1;
1966
}
1967
else if(*iPix) {
1968
u16 p = *iPix;
1969
int s, prio, c;
1970
1971
Vdp1ProcessSpritePixel(vdp1spritetype, &p, &s, &prio, &c);
1972
vdp1draw_info.priosused[prio] = 1;
1973
}
1974
}
1975
}
1976
1977
//TODO consolidate the following 3 functions
1978
static int bresenham( int x1, int y1, int x2, int y2, int x[], int y[])
1979
{
1980
int dx, dy, xf, yf, a, b, c, i;
1981
1982
if (x2>x1) {
1983
dx = x2-x1;
1984
xf = 1;
1985
}
1986
else {
1987
dx = x1-x2;
1988
xf = -1;
1989
}
1990
1991
if (y2>y1) {
1992
dy = y2-y1;
1993
yf = 1;
1994
}
1995
else {
1996
dy = y1-y2;
1997
yf = -1;
1998
}
1999
2000
//burning rangers tries to draw huge shapes
2001
//this will at least let it run
2002
if(dx > 999 || dy > 999)
2003
return INT_MAX;
2004
2005
if (dx>dy) {
2006
a = dy+dy;
2007
c = a-dx;
2008
b = c-dx;
2009
for (i=0;i<=dx;i++) {
2010
x[i] = x1; y[i] = y1;
2011
x1 += xf;
2012
if (c<0) {
2013
c += a;
2014
}
2015
else {
2016
c += b;
2017
y1 += yf;
2018
}
2019
}
2020
return dx+1;
2021
}
2022
else {
2023
a = dx+dx;
2024
c = a-dy;
2025
b = c-dy;
2026
for (i=0;i<=dy;i++) {
2027
x[i] = x1; y[i] = y1;
2028
y1 += yf;
2029
if (c<0) {
2030
c += a;
2031
}
2032
else {
2033
c += b;
2034
x1 += xf;
2035
}
2036
}
2037
return dy+1;
2038
}
2039
}
2040
2041
static int DrawLine( int x1, int y1, int x2, int y2, double linenumber, double texturestep, double xredstep, double xgreenstep, double xbluestep)
2042
{
2043
int dx, dy, xf, yf, a, b, c, i;
2044
int endcodesdetected=0;
2045
int previousStep = 123456789;
2046
2047
if (x2>x1) {
2048
dx = x2-x1;
2049
xf = 1;
2050
}
2051
else {
2052
dx = x1-x2;
2053
xf = -1;
2054
}
2055
2056
if (y2>y1) {
2057
dy = y2-y1;
2058
yf = 1;
2059
}
2060
else {
2061
dy = y1-y2;
2062
yf = -1;
2063
}
2064
2065
if (dx>dy) {
2066
a = dy+dy;
2067
c = a-dx;
2068
b = c-dx;
2069
for (i=0;i<=dx;i++) {
2070
leftColumnColor.r+=xredstep;
2071
leftColumnColor.g+=xgreenstep;
2072
leftColumnColor.b+=xbluestep;
2073
2074
if(getpixel(linenumber,(int)i*texturestep)) {
2075
if(currentPixel != previousStep) {
2076
previousStep = (int)i*texturestep;
2077
endcodesdetected++;
2078
}
2079
}
2080
else
2081
putpixel(x1,y1);
2082
2083
previousStep = currentPixel;
2084
2085
if(endcodesdetected==2)
2086
break;
2087
2088
x1 += xf;
2089
if (c<0) {
2090
c += a;
2091
}
2092
else {
2093
getpixel(linenumber,(int)i*texturestep);
2094
putpixel(x1,y1);
2095
c += b;
2096
y1 += yf;
2097
/*
2098
//same as sega's way, but just move the code down here instead
2099
//and use the pixel we already have instead of the next one
2100
if(xf>1&&yf>1) putpixel(x1,y1-1); //case 1
2101
if(xf<1&&yf<1) putpixel(x1,y1+1); //case 2
2102
if(xf<1&&yf>1) putpixel(x1+1,y1); //case 7
2103
if(xf>1&&yf<1) putpixel(x1-1,y1); //case 8*/
2104
}
2105
}
2106
return dx+1;
2107
}
2108
else {
2109
a = dx+dx;
2110
c = a-dy;
2111
b = c-dy;
2112
for (i=0;i<=dy;i++) {
2113
leftColumnColor.r+=xredstep;
2114
leftColumnColor.g+=xgreenstep;
2115
leftColumnColor.b+=xbluestep;
2116
2117
if(getpixel(linenumber,(int)i*texturestep)) {
2118
if(currentPixel != previousStep) {
2119
previousStep = (int)i*texturestep;
2120
endcodesdetected++;
2121
}
2122
}
2123
else
2124
putpixel(x1,y1);
2125
2126
previousStep = currentPixel;
2127
2128
if(endcodesdetected==2)
2129
break;
2130
2131
y1 += yf;
2132
if (c<0) {
2133
c += a;
2134
}
2135
else {
2136
getpixel(linenumber,(int)i*texturestep);
2137
putpixel(x1,y1);
2138
c += b;
2139
x1 += xf;
2140
/*
2141
if(xf>1&&yf>1) putpixel(x1,y1-1); //case 3
2142
if(xf<1&&yf<1) putpixel(x1,y1+1); //case 4
2143
if(xf<1&&yf>1) putpixel(x1+1,y1); //case 5
2144
if(xf>1&&yf<1) putpixel(x1-1,y1); //case 6*/
2145
2146
}
2147
}
2148
return dy+1;
2149
}
2150
}
2151
2152
static int getlinelength(int x1, int y1, int x2, int y2) {
2153
int dx, dy, xf, yf, a, b, c, i;
2154
2155
if (x2>x1) {
2156
dx = x2-x1;
2157
xf = 1;
2158
}
2159
else {
2160
dx = x1-x2;
2161
xf = -1;
2162
}
2163
2164
if (y2>y1) {
2165
dy = y2-y1;
2166
yf = 1;
2167
}
2168
else {
2169
dy = y1-y2;
2170
yf = -1;
2171
}
2172
2173
if (dx>dy) {
2174
a = dy+dy;
2175
c = a-dx;
2176
b = c-dx;
2177
for (i=0;i<=dx;i++) {
2178
2179
x1 += xf;
2180
if (c<0) {
2181
c += a;
2182
}
2183
else {
2184
c += b;
2185
y1 += yf;
2186
}
2187
}
2188
return dx+1;
2189
}
2190
else {
2191
a = dx+dx;
2192
c = a-dy;
2193
b = c-dy;
2194
for (i=0;i<=dy;i++) {
2195
y1 += yf;
2196
if (c<0) {
2197
c += a;
2198
}
2199
else {
2200
c += b;
2201
x1 += xf;
2202
}
2203
}
2204
return dy+1;
2205
}
2206
}
2207
2208
static INLINE double interpolate(double start, double end, int numberofsteps) {
2209
2210
double stepvalue = 0;
2211
2212
if(numberofsteps == 0)
2213
return 1;
2214
2215
stepvalue = (end - start) / numberofsteps;
2216
2217
return stepvalue;
2218
}
2219
2220
typedef union _COLOR { // xbgr x555
2221
struct {
2222
#ifdef WORDS_BIGENDIAN
2223
u16 x:1;
2224
u16 b:5;
2225
u16 g:5;
2226
u16 r:5;
2227
#else
2228
u16 r:5;
2229
u16 g:5;
2230
u16 b:5;
2231
u16 x:1;
2232
#endif
2233
};
2234
u16 value;
2235
} COLOR;
2236
2237
2238
COLOR gouraudA;
2239
COLOR gouraudB;
2240
COLOR gouraudC;
2241
COLOR gouraudD;
2242
2243
static void gouraudTable(void)
2244
{
2245
int gouraudTableAddress;
2246
2247
Vdp1ReadCommand(&cmd, Vdp1Regs->addr);
2248
2249
gouraudTableAddress = (((unsigned int)cmd.CMDGRDA) << 3);
2250
2251
gouraudA.value = T1ReadWord(Vdp1Ram,gouraudTableAddress);
2252
gouraudB.value = T1ReadWord(Vdp1Ram,gouraudTableAddress+2);
2253
gouraudC.value = T1ReadWord(Vdp1Ram,gouraudTableAddress+4);
2254
gouraudD.value = T1ReadWord(Vdp1Ram,gouraudTableAddress+6);
2255
}
2256
2257
int xleft[1000];
2258
int yleft[1000];
2259
int xright[1000];
2260
int yright[1000];
2261
2262
//a real vdp1 draws with arbitrary lines
2263
//this is why endcodes are possible
2264
//this is also the reason why half-transparent shading causes moire patterns
2265
//and the reason why gouraud shading can be applied to a single line draw command
2266
static void drawQuad(s32 tl_x, s32 tl_y, s32 bl_x, s32 bl_y, s32 tr_x, s32 tr_y, s32 br_x, s32 br_y){
2267
2268
int totalleft;
2269
int totalright;
2270
int total;
2271
int i;
2272
2273
COLOR_PARAMS topLeftToBottomLeftColorStep = {0,0,0}, topRightToBottomRightColorStep = {0,0,0};
2274
2275
//how quickly we step through the line arrays
2276
double leftLineStep = 1;
2277
double rightLineStep = 1;
2278
2279
//a lookup table for the gouraud colors
2280
COLOR colors[4];
2281
2282
Vdp1ReadCommand(&cmd, Vdp1Regs->addr);
2283
characterWidth = ((cmd.CMDSIZE >> 8) & 0x3F) * 8;
2284
characterHeight = cmd.CMDSIZE & 0xFF;
2285
2286
totalleft = bresenham(tl_x,tl_y,bl_x,bl_y,xleft,yleft);
2287
totalright = bresenham(tr_x,tr_y,br_x,br_y,xright,yright);
2288
2289
//just for now since burning rangers will freeze up trying to draw huge shapes
2290
if(totalleft == INT_MAX || totalright == INT_MAX)
2291
return;
2292
2293
total = totalleft > totalright ? totalleft : totalright;
2294
2295
2296
if(cmd.CMDPMOD & (1 << 2)) {
2297
2298
gouraudTable();
2299
2300
{ colors[0] = gouraudA; colors[1] = gouraudD; colors[2] = gouraudB; colors[3] = gouraudC; }
2301
2302
topLeftToBottomLeftColorStep.r = interpolate(colors[0].r,colors[1].r,total);
2303
topLeftToBottomLeftColorStep.g = interpolate(colors[0].g,colors[1].g,total);
2304
topLeftToBottomLeftColorStep.b = interpolate(colors[0].b,colors[1].b,total);
2305
2306
topRightToBottomRightColorStep.r = interpolate(colors[2].r,colors[3].r,total);
2307
topRightToBottomRightColorStep.g = interpolate(colors[2].g,colors[3].g,total);
2308
topRightToBottomRightColorStep.b = interpolate(colors[2].b,colors[3].b,total);
2309
}
2310
2311
//we have to step the equivalent of less than one pixel on the shorter side
2312
//to make sure textures stretch properly and the shape is correct
2313
if(total == totalleft && totalleft != totalright) {
2314
//left side is larger
2315
leftLineStep = 1;
2316
rightLineStep = (double)totalright / totalleft;
2317
}
2318
else if(totalleft != totalright){
2319
//right side is larger
2320
rightLineStep = 1;
2321
leftLineStep = (double)totalleft / totalright;
2322
}
2323
2324
for(i = 0; i < total; i++) {
2325
2326
int xlinelength;
2327
2328
double xtexturestep;
2329
double ytexturestep;
2330
2331
COLOR_PARAMS rightColumnColor;
2332
2333
COLOR_PARAMS leftToRightStep = {0,0,0};
2334
2335
//get the length of the line we are about to draw
2336
xlinelength = getlinelength(
2337
xleft[(int)(i*leftLineStep)],
2338
yleft[(int)(i*leftLineStep)],
2339
xright[(int)(i*rightLineStep)],
2340
yright[(int)(i*rightLineStep)]);
2341
2342
//so from 0 to the width of the texture / the length of the line is how far we need to step
2343
xtexturestep=interpolate(0,characterWidth,xlinelength);
2344
2345
//now we need to interpolate the y texture coordinate across multiple lines
2346
ytexturestep=interpolate(0,characterHeight,total);
2347
2348
//gouraud interpolation
2349
if(cmd.CMDPMOD & (1 << 2)) {
2350
2351
//for each new line we need to step once more through each column
2352
//and add the orignal color + the number of steps taken times the step value to the bottom of the shape
2353
//to get the current colors to use to interpolate across the line
2354
2355
leftColumnColor.r = colors[0].r +(topLeftToBottomLeftColorStep.r*i);
2356
leftColumnColor.g = colors[0].g +(topLeftToBottomLeftColorStep.g*i);
2357
leftColumnColor.b = colors[0].b +(topLeftToBottomLeftColorStep.b*i);
2358
2359
rightColumnColor.r = colors[2].r +(topRightToBottomRightColorStep.r*i);
2360
rightColumnColor.g = colors[2].g +(topRightToBottomRightColorStep.g*i);
2361
rightColumnColor.b = colors[2].b +(topRightToBottomRightColorStep.b*i);
2362
2363
//interpolate colors across to get the right step values
2364
leftToRightStep.r = interpolate(leftColumnColor.r,rightColumnColor.r,xlinelength);
2365
leftToRightStep.g = interpolate(leftColumnColor.g,rightColumnColor.g,xlinelength);
2366
leftToRightStep.b = interpolate(leftColumnColor.b,rightColumnColor.b,xlinelength);
2367
}
2368
2369
DrawLine(
2370
xleft[(int)(i*leftLineStep)],
2371
yleft[(int)(i*leftLineStep)],
2372
xright[(int)(i*rightLineStep)],
2373
yright[(int)(i*rightLineStep)],
2374
ytexturestep*i,
2375
xtexturestep,
2376
leftToRightStep.r,
2377
leftToRightStep.g,
2378
leftToRightStep.b
2379
);
2380
}
2381
}
2382
2383
void VIDGCDVdp1NormalSpriteDraw() {
2384
2385
s16 topLeftx,topLefty,topRightx,topRighty,bottomRightx,bottomRighty,bottomLeftx,bottomLefty;
2386
int spriteWidth;
2387
int spriteHeight;
2388
Vdp1ReadCommand(&cmd, Vdp1Regs->addr);
2389
2390
topLeftx = cmd.CMDXA + Vdp1Regs->localX;
2391
topLefty = cmd.CMDYA + Vdp1Regs->localY;
2392
spriteWidth = ((cmd.CMDSIZE >> 8) & 0x3F) * 8;
2393
spriteHeight = cmd.CMDSIZE & 0xFF;
2394
2395
topRightx = topLeftx + (spriteWidth - 1);
2396
topRighty = topLefty;
2397
bottomRightx = topLeftx + (spriteWidth - 1);
2398
bottomRighty = topLefty + (spriteHeight - 1);
2399
bottomLeftx = topLeftx;
2400
bottomLefty = topLefty + (spriteHeight - 1);
2401
2402
drawQuad(topLeftx,topLefty,bottomLeftx,bottomLefty,topRightx,topRighty,bottomRightx,bottomRighty);
2403
}
2404
2405
void VIDGCDVdp1ScaledSpriteDraw(){
2406
2407
s32 topLeftx,topLefty,topRightx,topRighty,bottomRightx,bottomRighty,bottomLeftx,bottomLefty;
2408
int spriteWidth;
2409
int spriteHeight;
2410
int x0,y0,x1,y1;
2411
Vdp1ReadCommand(&cmd, Vdp1Regs->addr);
2412
2413
x0 = cmd.CMDXA + Vdp1Regs->localX;
2414
y0 = cmd.CMDYA + Vdp1Regs->localY;
2415
2416
switch ((cmd.CMDCTRL >> 8) & 0xF)
2417
{
2418
case 0x0: // Only two coordinates
2419
default:
2420
x1 = ((int)cmd.CMDXC) - x0 + Vdp1Regs->localX + 1;
2421
y1 = ((int)cmd.CMDYC) - y0 + Vdp1Regs->localY + 1;
2422
break;
2423
case 0x5: // Upper-left
2424
x1 = ((int)cmd.CMDXB) + 1;
2425
y1 = ((int)cmd.CMDYB) + 1;
2426
break;
2427
case 0x6: // Upper-Center
2428
x1 = ((int)cmd.CMDXB);
2429
y1 = ((int)cmd.CMDYB);
2430
x0 = x0 - x1/2;
2431
x1++;
2432
y1++;
2433
break;
2434
case 0x7: // Upper-Right
2435
x1 = ((int)cmd.CMDXB);
2436
y1 = ((int)cmd.CMDYB);
2437
x0 = x0 - x1;
2438
x1++;
2439
y1++;
2440
break;
2441
case 0x9: // Center-left
2442
x1 = ((int)cmd.CMDXB);
2443
y1 = ((int)cmd.CMDYB);
2444
y0 = y0 - y1/2;
2445
x1++;
2446
y1++;
2447
break;
2448
case 0xA: // Center-center
2449
x1 = ((int)cmd.CMDXB);
2450
y1 = ((int)cmd.CMDYB);
2451
x0 = x0 - x1/2;
2452
y0 = y0 - y1/2;
2453
x1++;
2454
y1++;
2455
break;
2456
case 0xB: // Center-right
2457
x1 = ((int)cmd.CMDXB);
2458
y1 = ((int)cmd.CMDYB);
2459
x0 = x0 - x1;
2460
y0 = y0 - y1/2;
2461
x1++;
2462
y1++;
2463
break;
2464
case 0xD: // Lower-left
2465
x1 = ((int)cmd.CMDXB);
2466
y1 = ((int)cmd.CMDYB);
2467
y0 = y0 - y1;
2468
x1++;
2469
y1++;
2470
break;
2471
case 0xE: // Lower-center
2472
x1 = ((int)cmd.CMDXB);
2473
y1 = ((int)cmd.CMDYB);
2474
x0 = x0 - x1/2;
2475
y0 = y0 - y1;
2476
x1++;
2477
y1++;
2478
break;
2479
case 0xF: // Lower-right
2480
x1 = ((int)cmd.CMDXB);
2481
y1 = ((int)cmd.CMDYB);
2482
x0 = x0 - x1;
2483
y0 = y0 - y1;
2484
x1++;
2485
y1++;
2486
break;
2487
}
2488
2489
spriteWidth = ((cmd.CMDSIZE >> 8) & 0x3F) * 8;
2490
spriteHeight = cmd.CMDSIZE & 0xFF;
2491
2492
topLeftx = x0;
2493
topLefty = y0;
2494
2495
topRightx = x1 + x0 - 1;
2496
topRighty = topLefty;
2497
2498
bottomRightx = x1 + x0 - 1;
2499
bottomRighty = y1 + y0 - 1;
2500
2501
bottomLeftx = topLeftx;
2502
bottomLefty = y1 + y0 - 1;
2503
2504
drawQuad(topLeftx,topLefty,bottomLeftx,bottomLefty,topRightx,topRighty,bottomRightx,bottomRighty);
2505
}
2506
2507
void VIDGCDVdp1DistortedSpriteDraw() {
2508
2509
s32 xa,ya,xb,yb,xc,yc,xd,yd;
2510
2511
Vdp1ReadCommand(&cmd, Vdp1Regs->addr);
2512
2513
xa = (s32)(cmd.CMDXA + Vdp1Regs->localX);
2514
ya = (s32)(cmd.CMDYA + Vdp1Regs->localY);
2515
2516
xb = (s32)(cmd.CMDXB + Vdp1Regs->localX);
2517
yb = (s32)(cmd.CMDYB + Vdp1Regs->localY);
2518
2519
xc = (s32)(cmd.CMDXC + Vdp1Regs->localX);
2520
yc = (s32)(cmd.CMDYC + Vdp1Regs->localY);
2521
2522
xd = (s32)(cmd.CMDXD + Vdp1Regs->localX);
2523
yd = (s32)(cmd.CMDYD + Vdp1Regs->localY);
2524
2525
drawQuad(xa,ya,xd,yd,xb,yb,xc,yc);
2526
}
2527
2528
static void gouraudLineSetup(double * redstep, double * greenstep, double * bluestep, int length, COLOR table1, COLOR table2) {
2529
2530
gouraudTable();
2531
2532
*redstep =interpolate(table1.r,table2.r,length);
2533
*greenstep =interpolate(table1.g,table2.g,length);
2534
*bluestep =interpolate(table1.b,table2.b,length);
2535
2536
leftColumnColor.r = table1.r;
2537
leftColumnColor.g = table1.g;
2538
leftColumnColor.b = table1.b;
2539
}
2540
2541
void VIDGCDVdp1PolylineDraw(void)
2542
{
2543
int X[4];
2544
int Y[4];
2545
double redstep = 0, greenstep = 0, bluestep = 0;
2546
int length;
2547
2548
Vdp1ReadCommand(&cmd, Vdp1Regs->addr);
2549
2550
X[0] = (int)Vdp1Regs->localX + (int)((s16)T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x0C));
2551
Y[0] = (int)Vdp1Regs->localY + (int)((s16)T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x0E));
2552
X[1] = (int)Vdp1Regs->localX + (int)((s16)T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x10));
2553
Y[1] = (int)Vdp1Regs->localY + (int)((s16)T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x12));
2554
X[2] = (int)Vdp1Regs->localX + (int)((s16)T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x14));
2555
Y[2] = (int)Vdp1Regs->localY + (int)((s16)T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x16));
2556
X[3] = (int)Vdp1Regs->localX + (int)((s16)T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x18));
2557
Y[3] = (int)Vdp1Regs->localY + (int)((s16)T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x1A));
2558
2559
length = getlinelength(X[0], Y[0], X[1], Y[1]);
2560
gouraudLineSetup(&redstep,&greenstep,&bluestep,length, gouraudA, gouraudB);
2561
DrawLine(X[0], Y[0], X[1], Y[1], 0,0,redstep,greenstep,bluestep);
2562
2563
length = getlinelength(X[1], Y[1], X[2], Y[2]);
2564
gouraudLineSetup(&redstep,&greenstep,&bluestep,length, gouraudB, gouraudC);
2565
DrawLine(X[1], Y[1], X[2], Y[2], 0,0,redstep,greenstep,bluestep);
2566
2567
length = getlinelength(X[2], Y[2], X[3], Y[3]);
2568
gouraudLineSetup(&redstep,&greenstep,&bluestep,length, gouraudD, gouraudC);
2569
DrawLine(X[3], Y[3], X[2], Y[2], 0,0,redstep,greenstep,bluestep);
2570
2571
length = getlinelength(X[3], Y[3], X[0], Y[0]);
2572
gouraudLineSetup(&redstep,&greenstep,&bluestep,length, gouraudA,gouraudD);
2573
DrawLine(X[0], Y[0], X[3], Y[3], 0,0,redstep,greenstep,bluestep);
2574
}
2575
2576
void VIDGCDVdp1LineDraw(void)
2577
{
2578
int x1, y1, x2, y2;
2579
double redstep = 0, greenstep = 0, bluestep = 0;
2580
int length;
2581
2582
Vdp1ReadCommand(&cmd, Vdp1Regs->addr);
2583
2584
x1 = (int)Vdp1Regs->localX + (int)((s16)T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x0C));
2585
y1 = (int)Vdp1Regs->localY + (int)((s16)T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x0E));
2586
x2 = (int)Vdp1Regs->localX + (int)((s16)T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x10));
2587
y2 = (int)Vdp1Regs->localY + (int)((s16)T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x12));
2588
2589
length = getlinelength(x1, y1, x2, y2);
2590
gouraudLineSetup(&redstep,&bluestep,&greenstep,length, gouraudA, gouraudB);
2591
DrawLine(x1, y1, x2, y2, 0,0,redstep,greenstep,bluestep);
2592
}
2593
2594
//////////////////////////////////////////////////////////////////////////////
2595
2596
void VIDGCDVdp1UserClipping(void)
2597
{
2598
Vdp1Regs->userclipX1 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0xC);
2599
Vdp1Regs->userclipY1 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0xE);
2600
Vdp1Regs->userclipX2 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x14);
2601
Vdp1Regs->userclipY2 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x16);
2602
2603
#if 0
2604
vdp1clipxstart = Vdp1Regs->userclipX1;
2605
vdp1clipxend = Vdp1Regs->userclipX2;
2606
vdp1clipystart = Vdp1Regs->userclipY1;
2607
vdp1clipyend = Vdp1Regs->userclipY2;
2608
2609
// This needs work
2610
if (vdp1clipxstart > Vdp1Regs->systemclipX1)
2611
vdp1clipxstart = Vdp1Regs->userclipX1;
2612
else
2613
vdp1clipxstart = Vdp1Regs->systemclipX1;
2614
2615
if (vdp1clipxend < Vdp1Regs->systemclipX2)
2616
vdp1clipxend = Vdp1Regs->userclipX2;
2617
else
2618
vdp1clipxend = Vdp1Regs->systemclipX2;
2619
2620
if (vdp1clipystart > Vdp1Regs->systemclipY1)
2621
vdp1clipystart = Vdp1Regs->userclipY1;
2622
else
2623
vdp1clipystart = Vdp1Regs->systemclipY1;
2624
2625
if (vdp1clipyend < Vdp1Regs->systemclipY2)
2626
vdp1clipyend = Vdp1Regs->userclipY2;
2627
else
2628
vdp1clipyend = Vdp1Regs->systemclipY2;
2629
#endif
2630
}
2631
2632
//////////////////////////////////////////////////////////////////////////////
2633
2634
static void PushUserClipping(int mode)
2635
{
2636
if (mode == 1)
2637
{
2638
VDP1LOG("User clipping mode 1 not implemented\n");
2639
return;
2640
}
2641
2642
vdp1clipxstart = Vdp1Regs->userclipX1;
2643
vdp1clipxend = Vdp1Regs->userclipX2;
2644
vdp1clipystart = Vdp1Regs->userclipY1;
2645
vdp1clipyend = Vdp1Regs->userclipY2;
2646
2647
// This needs work
2648
if (vdp1clipxstart > Vdp1Regs->systemclipX1)
2649
vdp1clipxstart = Vdp1Regs->userclipX1;
2650
else
2651
vdp1clipxstart = Vdp1Regs->systemclipX1;
2652
2653
if (vdp1clipxend < Vdp1Regs->systemclipX2)
2654
vdp1clipxend = Vdp1Regs->userclipX2;
2655
else
2656
vdp1clipxend = Vdp1Regs->systemclipX2;
2657
2658
if (vdp1clipystart > Vdp1Regs->systemclipY1)
2659
vdp1clipystart = Vdp1Regs->userclipY1;
2660
else
2661
vdp1clipystart = Vdp1Regs->systemclipY1;
2662
2663
if (vdp1clipyend < Vdp1Regs->systemclipY2)
2664
vdp1clipyend = Vdp1Regs->userclipY2;
2665
else
2666
vdp1clipyend = Vdp1Regs->systemclipY2;
2667
}
2668
2669
//////////////////////////////////////////////////////////////////////////////
2670
2671
static void PopUserClipping(void)
2672
{
2673
vdp1clipxstart = Vdp1Regs->systemclipX1;
2674
vdp1clipxend = Vdp1Regs->systemclipX2;
2675
vdp1clipystart = Vdp1Regs->systemclipY1;
2676
vdp1clipyend = Vdp1Regs->systemclipY2;
2677
}
2678
2679
//////////////////////////////////////////////////////////////////////////////
2680
2681
void VIDGCDVdp1SystemClipping(void)
2682
{
2683
Vdp1Regs->systemclipX1 = 0;
2684
Vdp1Regs->systemclipY1 = 0;
2685
Vdp1Regs->systemclipX2 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x14);
2686
Vdp1Regs->systemclipY2 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x16);
2687
2688
vdp1clipxstart = Vdp1Regs->systemclipX1;
2689
vdp1clipxend = Vdp1Regs->systemclipX2;
2690
vdp1clipystart = Vdp1Regs->systemclipY1;
2691
vdp1clipyend = Vdp1Regs->systemclipY2;
2692
}
2693
2694
//////////////////////////////////////////////////////////////////////////////
2695
2696
void VIDGCDVdp1LocalCoordinate(void)
2697
{
2698
Vdp1Regs->localX = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0xC);
2699
Vdp1Regs->localY = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0xE);
2700
}
2701
2702
//////////////////////////////////////////////////////////////////////////////
2703
2704
int VIDGCDVdp2Reset(void)
2705
{
2706
return 0;
2707
}
2708
2709
//////////////////////////////////////////////////////////////////////////////
2710
2711
void VIDGCDVdp2DrawStart(void)
2712
{
2713
int wctl;
2714
Vdp2DrawBackScreen();
2715
2716
vdp1draw_info.prioritytable[0] = Vdp2Regs->PRISA & 0x7;
2717
vdp1draw_info.prioritytable[1] = (Vdp2Regs->PRISA >> 8) & 0x7;
2718
vdp1draw_info.prioritytable[2] = Vdp2Regs->PRISB & 0x7;
2719
vdp1draw_info.prioritytable[3] = (Vdp2Regs->PRISB >> 8) & 0x7;
2720
vdp1draw_info.prioritytable[4] = Vdp2Regs->PRISC & 0x7;
2721
vdp1draw_info.prioritytable[5] = (Vdp2Regs->PRISC >> 8) & 0x7;
2722
vdp1draw_info.prioritytable[6] = Vdp2Regs->PRISD & 0x7;
2723
vdp1draw_info.prioritytable[7] = (Vdp2Regs->PRISD >> 8) & 0x7;
2724
2725
vdp1draw_info.coloroffset = (Vdp2Regs->CRAOFB & 0x70) << 4;
2726
vdp1spritetype = Vdp2Regs->SPCTL & 0xF;
2727
2728
if(Vdp2Regs->CLOFEN & 0x40) {
2729
// color offset enable
2730
if(Vdp2Regs->CLOFSL & 0x40) {
2731
// color offset B
2732
vdp1draw_info.info.cor = Vdp2Regs->COBR & 0xFF;
2733
if(Vdp2Regs->COBR & 0x100)
2734
vdp1draw_info.info.cor |= 0xFFFFFF00;
2735
2736
vdp1draw_info.info.cog = Vdp2Regs->COBG & 0xFF;
2737
if(Vdp2Regs->COBG & 0x100)
2738
vdp1draw_info.info.cog |= 0xFFFFFF00;
2739
2740
vdp1draw_info.info.cob = Vdp2Regs->COBB & 0xFF;
2741
if(Vdp2Regs->COBB & 0x100)
2742
vdp1draw_info.info.cob |= 0xFFFFFF00;
2743
}
2744
else {
2745
// color offset A
2746
vdp1draw_info.info.cor = Vdp2Regs->COAR & 0xFF;
2747
if(Vdp2Regs->COAR & 0x100)
2748
vdp1draw_info.info.cor |= 0xFFFFFF00;
2749
2750
vdp1draw_info.info.cog = Vdp2Regs->COAG & 0xFF;
2751
if(Vdp2Regs->COAG & 0x100)
2752
vdp1draw_info.info.cog |= 0xFFFFFF00;
2753
2754
vdp1draw_info.info.cob = Vdp2Regs->COAB & 0xFF;
2755
if(Vdp2Regs->COAB & 0x100)
2756
vdp1draw_info.info.cob |= 0xFFFFFF00;
2757
}
2758
2759
if(vdp1draw_info.info.cor == 0 && vdp1draw_info.info.cog == 0 && vdp1draw_info.info.cob == 0) {
2760
if(Vdp2Regs->CCCTL & 0x40)
2761
vdp1draw_info.info.PostPixelFetchCalc = &DoColorCalc;
2762
else
2763
vdp1draw_info.info.PostPixelFetchCalc = &DoNothing;
2764
}
2765
else {
2766
if(Vdp2Regs->CCCTL & 0x40)
2767
vdp1draw_info.info.PostPixelFetchCalc = &DoColorCalcWithColorOffset;
2768
else
2769
vdp1draw_info.info.PostPixelFetchCalc = &DoColorOffset;
2770
}
2771
}
2772
else { // color offset disable
2773
if(Vdp2Regs->CCCTL & 0x40)
2774
vdp1draw_info.info.PostPixelFetchCalc = &DoColorCalc;
2775
else
2776
vdp1draw_info.info.PostPixelFetchCalc = &DoNothing;
2777
}
2778
2779
wctl = Vdp2Regs->WCTLC >> 8;
2780
vdp1draw_info.clip[0].xstart = vdp1draw_info.clip[0].ystart = 0;
2781
vdp1draw_info.clip[0].xend = vdp1draw_info.clip[0].yend = 0;
2782
vdp1draw_info.clip[1].xstart = vdp1draw_info.clip[1].ystart = 0;
2783
vdp1draw_info.clip[1].xend = vdp1draw_info.clip[1].yend = 0;
2784
ReadWindowData(wctl, vdp1draw_info.clip);
2785
vdp1draw_info.linewnd0addr = vdp1draw_info.linewnd1addr = 0;
2786
ReadLineWindowData(&vdp1draw_info.islinewindow, wctl, &vdp1draw_info.linewnd0addr, &vdp1draw_info.linewnd1addr);
2787
}
2788
2789
//////////////////////////////////////////////////////////////////////////////
2790
2791
void VIDGCDVdp2DrawEnd(void)
2792
{
2793
#ifndef CRAB_REWRITE
2794
int i, i2;
2795
u16 pixel;
2796
u8 prioritytable[8];
2797
u32 vdp1coloroffset;
2798
int colormode = Vdp2Regs->SPCTL & 0x20;
2799
vdp2draw_struct info;
2800
u32 *dst=dispbuffer;
2801
u32 *vdp2src=vdp2framebuffer;
2802
int islinewindow;
2803
clipping_struct clip[2];
2804
u32 linewnd0addr, linewnd1addr;
2805
int wctl;
2806
2807
// Figure out whether to draw vdp1 framebuffer or vdp2 framebuffer pixels
2808
// based on priority
2809
if (Vdp1External.disptoggle)
2810
{
2811
prioritytable[0] = Vdp2Regs->PRISA & 0x7;
2812
prioritytable[1] = (Vdp2Regs->PRISA >> 8) & 0x7;
2813
prioritytable[2] = Vdp2Regs->PRISB & 0x7;
2814
prioritytable[3] = (Vdp2Regs->PRISB >> 8) & 0x7;
2815
prioritytable[4] = Vdp2Regs->PRISC & 0x7;
2816
prioritytable[5] = (Vdp2Regs->PRISC >> 8) & 0x7;
2817
prioritytable[6] = Vdp2Regs->PRISD & 0x7;
2818
prioritytable[7] = (Vdp2Regs->PRISD >> 8) & 0x7;
2819
2820
vdp1coloroffset = (Vdp2Regs->CRAOFB & 0x70) << 4;
2821
vdp1spritetype = Vdp2Regs->SPCTL & 0xF;
2822
2823
if (Vdp2Regs->CLOFEN & 0x40)
2824
{
2825
// color offset enable
2826
if (Vdp2Regs->CLOFSL & 0x40)
2827
{
2828
// color offset B
2829
info.cor = Vdp2Regs->COBR & 0xFF;
2830
if (Vdp2Regs->COBR & 0x100)
2831
info.cor |= 0xFFFFFF00;
2832
2833
info.cog = Vdp2Regs->COBG & 0xFF;
2834
if (Vdp2Regs->COBG & 0x100)
2835
info.cog |= 0xFFFFFF00;
2836
2837
info.cob = Vdp2Regs->COBB & 0xFF;
2838
if (Vdp2Regs->COBB & 0x100)
2839
info.cob |= 0xFFFFFF00;
2840
}
2841
else
2842
{
2843
// color offset A
2844
info.cor = Vdp2Regs->COAR & 0xFF;
2845
if (Vdp2Regs->COAR & 0x100)
2846
info.cor |= 0xFFFFFF00;
2847
2848
info.cog = Vdp2Regs->COAG & 0xFF;
2849
if (Vdp2Regs->COAG & 0x100)
2850
info.cog |= 0xFFFFFF00;
2851
2852
info.cob = Vdp2Regs->COAB & 0xFF;
2853
if (Vdp2Regs->COAB & 0x100)
2854
info.cob |= 0xFFFFFF00;
2855
}
2856
2857
if (info.cor == 0 && info.cog == 0 && info.cob == 0)
2858
{
2859
if (Vdp2Regs->CCCTL & 0x40)
2860
info.PostPixelFetchCalc = &DoColorCalc;
2861
else
2862
info.PostPixelFetchCalc = &DoNothing;
2863
}
2864
else
2865
{
2866
if (Vdp2Regs->CCCTL & 0x40)
2867
info.PostPixelFetchCalc = &DoColorCalcWithColorOffset;
2868
else
2869
info.PostPixelFetchCalc = &DoColorOffset;
2870
}
2871
}
2872
else // color offset disable
2873
{
2874
if (Vdp2Regs->CCCTL & 0x40)
2875
info.PostPixelFetchCalc = &DoColorCalc;
2876
else
2877
info.PostPixelFetchCalc = &DoNothing;
2878
}
2879
2880
wctl = Vdp2Regs->WCTLC >> 8;
2881
clip[0].xstart = clip[0].ystart = clip[0].xend = clip[0].yend = 0;
2882
clip[1].xstart = clip[1].ystart = clip[1].xend = clip[1].yend = 0;
2883
ReadWindowData(wctl, clip);
2884
linewnd0addr = linewnd1addr = 0;
2885
ReadLineWindowData(&islinewindow, wctl, &linewnd0addr, &linewnd1addr);
2886
2887
for (i2 = 0; i2 < vdp2height; i2++)
2888
{
2889
ReadLineWindowClip(islinewindow, clip, &linewnd0addr, &linewnd1addr);
2890
2891
for (i = 0; i < vdp2width; i++)
2892
{
2893
// See if screen position is clipped, if it isn't, continue
2894
// Window 0
2895
if (!TestWindow(wctl, 0x2, 0x1, &clip[0], i, i2))
2896
{
2897
dst[0] = COLSATSTRIPPRIORITY(vdp2src[0]);
2898
vdp2src++;
2899
dst++;
2900
continue;
2901
}
2902
2903
// Window 1
2904
if (!TestWindow(wctl, 0x8, 0x4, &clip[1], i, i2))
2905
{
2906
vdp2src++;
2907
dst[0] = COLSATSTRIPPRIORITY(vdp2src[0]);
2908
dst++;
2909
continue;
2910
}
2911
2912
if (vdp1pixelsize == 2)
2913
{
2914
// 16-bit pixel size
2915
pixel = ((u16 *)vdp1frontframebuffer)[(i2 * vdp1width) + i];
2916
2917
if (pixel == 0)
2918
dst[0] = COLSATSTRIPPRIORITY(vdp2src[0]);
2919
else if (pixel & 0x8000 && colormode)
2920
{
2921
// 16 BPP
2922
if (prioritytable[0] >= Vdp2GetPixelPriority(vdp2src[0]))
2923
{
2924
// if pixel is 0x8000, only draw pixel if sprite window
2925
// is disabled/sprite type 2-7. sprite types 0 and 1 are
2926
// -always- drawn and sprite types 8-F are always
2927
// transparent.
2928
if (pixel != 0x8000 || vdp1spritetype < 2 || (vdp1spritetype < 8 && !(Vdp2Regs->SPCTL & 0x10)))
2929
dst[0] = info.PostPixelFetchCalc(&info, COLSAT2YAB16(0xFF, pixel));
2930
else
2931
dst[0] = COLSATSTRIPPRIORITY(vdp2src[0]);
2932
}
2933
else
2934
dst[0] = COLSATSTRIPPRIORITY(vdp2src[0]);
2935
}
2936
else
2937
{
2938
// Color bank
2939
int priority;
2940
int shadow;
2941
int colorcalc;
2942
priority = 0; // Avoid compiler warning
2943
Vdp1ProcessSpritePixel(vdp1spritetype, &pixel, &shadow, &priority, &colorcalc);
2944
if (prioritytable[priority] >= Vdp2GetPixelPriority(vdp2src[0]))
2945
dst[0] = info.PostPixelFetchCalc(&info, COLSAT2YAB32(0xFF, Vdp2ColorRamGetColor(vdp1coloroffset + pixel)));
2946
else
2947
dst[0] = COLSATSTRIPPRIORITY(vdp2src[0]);
2948
}
2949
}
2950
else
2951
{
2952
// 8-bit pixel size
2953
pixel = vdp1frontframebuffer[(i2 * vdp1width) + i];
2954
2955
if (pixel == 0)
2956
dst[0] = COLSATSTRIPPRIORITY(vdp2src[0]);
2957
else
2958
{
2959
// Color bank(fix me)
2960
LOG("8-bit Color Bank draw - %02X\n", pixel);
2961
dst[0] = COLSATSTRIPPRIORITY(vdp2src[0]);
2962
}
2963
}
2964
vdp2src++;
2965
dst++;
2966
}
2967
}
2968
}
2969
else
2970
{
2971
// Render VDP2 only
2972
for (i = 0; i < (vdp2width*vdp2height); i++)
2973
dispbuffer[i] = COLSATSTRIPPRIORITY(vdp2framebuffer[i]);
2974
}
2975
#endif
2976
2977
VIDGCDVdp1SwapFrameBuffer();
2978
2979
if (OSDUseBuffer())
2980
OSDDisplayMessages(dispbuffer, vdp2width, vdp2height);
2981
2982
#ifdef USE_OPENGL
2983
glRasterPos2i(0, 0);
2984
glPixelZoom((float)outputwidth / (float)vdp2width, 0 - ((float)outputheight / (float)vdp2height));
2985
#ifndef CRAB_REWRITE
2986
glDrawPixels(vdp2width, vdp2height, GL_RGBA, GL_UNSIGNED_BYTE, dispbuffer);
2987
#else
2988
glDisable(GL_BLEND);
2989
glDrawPixels(vdp2width, vdp2height, GL_RGBA, GL_UNSIGNED_BYTE, vdp2framebuffer);
2990
#endif
2991
2992
if (! OSDUseBuffer())
2993
OSDDisplayMessages(NULL, -1, -1);
2994
#endif
2995
2996
YuiSwapBuffers();
2997
}
2998
2999
/* FIXME: Support Vdp1 8-bit mode sometime... */
3000
static void Vdp1DrawPriority(int prio) {
3001
int colormode = Vdp2Regs->SPCTL & 0x20;
3002
vdp2draw_struct *info = &vdp1draw_info.info;
3003
int islinewindow = vdp1draw_info.islinewindow;
3004
int wctl= Vdp2Regs->WCTLC >> 8;
3005
3006
// Figure out whether to draw vdp1 framebuffer or vdp2 framebuffer pixels
3007
// based on priority
3008
if(Vdp1External.disptoggle) {
3009
dispatch_apply(vdp2height, dispatch_get_global_queue(2, 0), ^(size_t i2) {
3010
u16 *fb16 = (u16 *)(vdp1frontframebuffer) + (i2 * vdp1width);
3011
u32 *fb = vdp2framebuffer + (i2 * vdp2width);
3012
int i;
3013
u16 pixel;
3014
u32 linewnd0addr = vdp1draw_info.linewnd0addr;
3015
u32 linewnd1addr = vdp1draw_info.linewnd1addr;
3016
3017
ReadLineWindowClip(islinewindow, vdp1draw_info.clip, &linewnd0addr, &linewnd1addr);
3018
3019
for(i = 0; i < vdp2width; ++i, ++fb16, ++fb) {
3020
// See if screen position is clipped, if it isn't, continue
3021
// Window 0
3022
if(!TestWindow(wctl, 0x2, 0x1, &vdp1draw_info.clip[0], i, i2)) {
3023
continue;
3024
}
3025
3026
// Window 1
3027
if(!TestWindow(wctl, 0x8, 0x4, &vdp1draw_info.clip[1], i, i2)) {
3028
continue;
3029
}
3030
3031
if (vdp1pixelsize == 2) {
3032
// 16-bit pixel size
3033
pixel = *fb16;
3034
3035
if(pixel & 0x8000 && colormode && vdp1draw_info.prioritytable[0] == prio &&
3036
prio >= Vdp2GetPixelPriority(*fb)) {
3037
// 16 BPP
3038
// if pixel is 0x8000, only draw pixel if sprite window
3039
// is disabled/sprite type 2-7. sprite types 0 and 1 are
3040
// -always- drawn and sprite types 8-F are always
3041
// transparent.
3042
if(pixel != 0x8000 || vdp1spritetype < 2 || (vdp1spritetype < 8 && !(Vdp2Regs->SPCTL & 0x10)))
3043
*fb = info->PostPixelFetchCalc(info, COLSAT2YAB16(0xFF, pixel));
3044
}
3045
else if(pixel) {
3046
// Color bank
3047
int priority;
3048
int shadow;
3049
int colorcalc;
3050
priority = 0; // Avoid compiler warning
3051
Vdp1ProcessSpritePixel(vdp1spritetype, &pixel, &shadow, &priority, &colorcalc);
3052
priority = vdp1draw_info.prioritytable[priority];
3053
if(priority == prio && priority >= Vdp2GetPixelPriority(*fb))
3054
*fb = info->PostPixelFetchCalc(info, COLSAT2YAB32(0xFF, Vdp2ColorRamGetColor(vdp1draw_info.coloroffset + pixel)));
3055
}
3056
}
3057
//else
3058
//{
3059
// // 8-bit pixel size
3060
// pixel = vdp1frontframebuffer[(i2 * vdp1width) + i];
3061
//
3062
// if (pixel == 0)
3063
// dst[0] = COLSATSTRIPPRIORITY(vdp2src[0]);
3064
// else
3065
// {
3066
// // Color bank(fix me)
3067
// LOG("8-bit Color Bank draw - %02X\n", pixel);
3068
// dst[0] = COLSATSTRIPPRIORITY(vdp2src[0]);
3069
// }
3070
//}
3071
}
3072
});
3073
}
3074
}
3075
3076
//////////////////////////////////////////////////////////////////////////////
3077
3078
void VIDGCDVdp2DrawScreens(void)
3079
{
3080
int i;
3081
3082
/* Draw all the screens, from the lowest priority one forward. */
3083
for(i = 1; i < 8; ++i)
3084
{
3085
if (nbg3priority == i)
3086
Vdp2DrawNBG3();
3087
if (nbg2priority == i)
3088
Vdp2DrawNBG2();
3089
if (nbg1priority == i)
3090
Vdp2DrawNBG1();
3091
if (nbg0priority == i)
3092
Vdp2DrawNBG0();
3093
if (rbg0priority == i)
3094
Vdp2DrawRBG0();
3095
3096
/* Draw anything in VDP1 that should be shown at this priority level. */
3097
if(vdp1draw_info.priosused[i])
3098
Vdp1DrawPriority(i);
3099
vdp1draw_info.priosused[i] = 0;
3100
}
3101
}
3102
3103
//////////////////////////////////////////////////////////////////////////////
3104
3105
void VIDGCDVdp2SetResolution(u16 TVMD)
3106
{
3107
// This needs some work
3108
3109
// Horizontal Resolution
3110
switch (TVMD & 0x7)
3111
{
3112
case 0:
3113
vdp2width = 320;
3114
resxratio=1;
3115
break;
3116
case 1:
3117
vdp2width = 352;
3118
resxratio=1;
3119
break;
3120
case 2: // 640
3121
vdp2width = 320;
3122
resxratio=2;
3123
break;
3124
case 3: // 704
3125
vdp2width = 352;
3126
resxratio=2;
3127
break;
3128
case 4:
3129
vdp2width = 320;
3130
resxratio=1;
3131
break;
3132
case 5:
3133
vdp2width = 352;
3134
resxratio=1;
3135
break;
3136
case 6: // 640
3137
vdp2width = 320;
3138
resxratio=2;
3139
break;
3140
case 7: // 704
3141
vdp2width = 352;
3142
resxratio=2;
3143
break;
3144
}
3145
3146
// Vertical Resolution
3147
switch ((TVMD >> 4) & 0x3)
3148
{
3149
case 0:
3150
vdp2height = 224;
3151
break;
3152
case 1:
3153
vdp2height = 240;
3154
break;
3155
case 2:
3156
vdp2height = 256;
3157
break;
3158
default: break;
3159
}
3160
resyratio=1;
3161
3162
// Check for interlace
3163
switch ((TVMD >> 6) & 0x3)
3164
{
3165
case 3: // Double-density Interlace
3166
// vdp2height *= 2;
3167
resyratio=2;
3168
break;
3169
case 2: // Single-density Interlace
3170
case 0: // Non-interlace
3171
default: break;
3172
}
3173
}
3174
3175
//////////////////////////////////////////////////////////////////////////////
3176
3177
void FASTCALL VIDGCDVdp2SetPriorityNBG0(int priority)
3178
{
3179
nbg0priority = priority;
3180
}
3181
3182
//////////////////////////////////////////////////////////////////////////////
3183
3184
void FASTCALL VIDGCDVdp2SetPriorityNBG1(int priority)
3185
{
3186
nbg1priority = priority;
3187
}
3188
3189
//////////////////////////////////////////////////////////////////////////////
3190
3191
void FASTCALL VIDGCDVdp2SetPriorityNBG2(int priority)
3192
{
3193
nbg2priority = priority;
3194
}
3195
3196
//////////////////////////////////////////////////////////////////////////////
3197
3198
void FASTCALL VIDGCDVdp2SetPriorityNBG3(int priority)
3199
{
3200
nbg3priority = priority;
3201
}
3202
3203
//////////////////////////////////////////////////////////////////////////////
3204
3205
void FASTCALL VIDGCDVdp2SetPriorityRBG0(int priority)
3206
{
3207
rbg0priority = priority;
3208
}
3209
3210
//////////////////////////////////////////////////////////////////////////////
3211
3212
void VIDGCDOnScreenDebugMessage(char *string, ...)
3213
{
3214
va_list arglist;
3215
3216
va_start(arglist, string);
3217
vsprintf(message, string, arglist);
3218
va_end(arglist);
3219
msglength = strlen(message);
3220
}
3221
3222
//////////////////////////////////////////////////////////////////////////////
3223
3224
void VIDGCDGetScreenSize(int *width, int *height)
3225
{
3226
*width = vdp2width;
3227
*height = vdp2height;
3228
}
3229
3230
//////////////////////////////////////////////////////////////////////////////
3231
3232
void VIDGCDVdp1SwapFrameBuffer(void)
3233
{
3234
u8 *temp = vdp1frontframebuffer;
3235
vdp1frontframebuffer = vdp1backframebuffer;
3236
vdp1backframebuffer = temp;
3237
}
3238
3239
//////////////////////////////////////////////////////////////////////////////
3240
3241
void VIDGCDVdp1EraseFrameBuffer(void)
3242
{
3243
int s, s2;
3244
int w,h;
3245
3246
h = (Vdp1Regs->EWRR & 0x1FF) + 1;
3247
if (h > vdp1height) h = vdp1height;
3248
w = ((Vdp1Regs->EWRR >> 6) & 0x3F8) + 8;
3249
if (w > vdp1width) w = vdp1width;
3250
3251
s = Vdp1Regs->EWLR & 0x1FF;
3252
s2 = (Vdp1Regs->EWLR >> 6) & 0x1F8;
3253
3254
dispatch_apply(h - s, dispatch_get_global_queue(2, 0), ^(size_t i2) {
3255
int i;
3256
i2 += s;
3257
for (i = s2; i < w; i++) {
3258
((u16 *)vdp1backframebuffer)[(i2 * vdp1width) + i] = Vdp1Regs->EWDR;
3259
}
3260
});
3261
}
3262
3263
//////////////////////////////////////////////////////////////////////////////
3264
3265
void VIDGCDGetGlSize(int *width, int *height)
3266
{
3267
#ifdef USE_OPENGL
3268
*width = outputwidth;
3269
*height = outputheight;
3270
#else
3271
*width = vdp2width;
3272
*height = vdp2height;
3273
#endif
3274
}
3275
3276