Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/dreamcast/viddc.c
2 views
1
/* Copyright 2003-2006 Guillaume Duhamel
2
Copyright 2004-2009 Lawrence Sebald
3
Copyright 2004-2006 Theo Berkau
4
Copyright 2006 Fabien Coulon
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 "viddc.h"
24
#include "../debug.h"
25
#include "../vdp2.h"
26
27
#include <dc/video.h>
28
#include <dc/pvr.h>
29
#include <time.h>
30
#include <assert.h>
31
#include <string.h>
32
#include <kos/sem.h>
33
#include <arch/cache.h>
34
35
#include <stdio.h>
36
37
#define SAT2YAB1(temp) ((temp & 0x8000) | (temp & 0x1F) << 10 | \
38
(temp & 0x3E0) | (temp & 0x7C00) >> 10)
39
#define SAT2YAB32(alpha, temp) (alpha << 24 | (temp & 0x1F) << 3 | \
40
(temp & 0x3E0) << 6 | (temp & 0x7C00) << 9)
41
42
#define SAT2YAB2(dot1, dot2) ((dot1 & 0xF8) << 7 | (dot2 & 0xF800) >> 6 | \
43
(dot2 & 0x00F8) >> 3 | 0x8000)
44
#define SAT2YAB2_32(alpha, dot1, dot2) (alpha << 24 | ((dot1 & 0xFF) << 16) | \
45
(dot2 & 0xFF00) | (dot2 & 0xFF))
46
47
#define COLOR_ADDt32(b) (b > 0xFF ? 0xFF : (b < 0 ? 0 : b))
48
#define COLOR_ADDb32(b1,b2) COLOR_ADDt32((signed) (b1) + (b2))
49
50
#define COLOR_ADD32(l,r,g,b) COLOR_ADDb32((l & 0xFF), r) | \
51
(COLOR_ADDb32((l >> 8) & 0xFF, g) << 8) | \
52
(COLOR_ADDb32((l >> 16) & 0xFF, b) << 16) | \
53
(l & 0xFF000000)
54
55
#define COLOR_ADDt(b) (b > 0xF8 ? 0xF8 : (b < 0x08 ? 0 : b))
56
#define COLOR_ADDb(b1,b2) COLOR_ADDt((signed) (b1) + (b2))
57
#define COLOR_ADD(l,r,g,b) ((COLOR_ADDb((l >> 7) & 0xF8, \
58
r) & 0xF8) << 7) | \
59
((COLOR_ADDb((l >> 2) & 0xF8, \
60
g) & 0xF8) << 2) | \
61
((COLOR_ADDb((l << 3) & 0xF8, \
62
b) & 0xF8) >> 3) | \
63
(l & 0x8000)
64
65
66
static pvr_init_params_t pvr_params = {
67
/* Enable Opaque, Translucent, and Punch-Thru polygons with binsize 16 */
68
{ PVR_BINSIZE_16, PVR_BINSIZE_0, PVR_BINSIZE_16, PVR_BINSIZE_0,
69
PVR_BINSIZE_16 },
70
/* 512KB Vertex Buffer */
71
512 * 1024,
72
/* DMA Enabled */
73
1,
74
/* FSAA Disabled */
75
0
76
};
77
78
struct sprite_info {
79
uint32 pvr_base;
80
uint32 vdp1_base;
81
float uf, vf;
82
int w, h;
83
};
84
85
typedef struct {
86
int cellw, cellh;
87
int flipfunction;
88
int priority;
89
90
int mapwh;
91
int planew, planeh;
92
int pagewh;
93
int patternwh;
94
int patterndatasize;
95
int specialfunction;
96
u32 addr, charaddr, paladdr;
97
int colornumber;
98
int isbitmap;
99
u16 supplementdata;
100
int auxmode;
101
int enable;
102
int x, y;
103
int alpha;
104
int coloroffset;
105
int transparencyenable;
106
int specialprimode;
107
108
s32 cor;
109
s32 cog;
110
s32 cob;
111
112
float coordincx, coordincy;
113
void (* PlaneAddr)(void *, int);
114
u16 (* PostPixelFetchCalc)(void *, u16);
115
int patternpixelwh;
116
int draww;
117
int drawh;
118
} vdp2draw_struct;
119
120
static struct sprite_info cur_spr;
121
122
static struct sprite_info cache[1024];
123
int cached_spr = 0;
124
125
/* Polygon Headers */
126
static pvr_sprite_hdr_t op_poly_hdr;
127
static pvr_sprite_hdr_t tr_poly_hdr;
128
static pvr_sprite_hdr_t tr_sprite_hdr;
129
static pvr_sprite_hdr_t pt_sprite_hdr;
130
131
/* DMA Vertex Buffers 256KB Each */
132
static uint8 vbuf_opaque[1024 * 256] __attribute__((aligned(32)));
133
static uint8 vbuf_translucent[1024 * 256] __attribute__((aligned(32)));
134
static uint8 vbuf_punchthru[1024 * 256] __attribute__((aligned(32)));
135
136
/* VDP2 Framebuffer */
137
static uint16 *vdp2_fb;
138
static int vdp2_fbnum = 0;
139
static uint16 vdp2_fbs[2][512 * 256] __attribute__((aligned(32)));
140
static uint8 vdp2_prio[352][240];
141
static semaphore_t *dmadone;
142
143
static pvr_ptr_t vdp2_tex;
144
static uint32 cur_vdp2;
145
146
/* Priority levels, sprites drawn last get drawn on top */
147
static float priority_levels[8];
148
149
/* Texture space for VDP1 sprites */
150
static pvr_ptr_t tex_space;
151
static uint32 cur_addr;
152
153
/* Misc parameters */
154
static int vdp1cor = 0;
155
static int vdp1cog = 0;
156
static int vdp1cob = 0;
157
158
static int nbg0priority = 0;
159
static int nbg1priority = 0;
160
static int nbg2priority = 0;
161
static int nbg3priority = 0;
162
static int rbg0priority = 0;
163
164
static int vdp2width = 320;
165
static int vdp2height = 224;
166
167
/* Frame counter */
168
static time_t lastup;
169
static int framecount;
170
171
static int power_of_two(int num) {
172
int ret = 8;
173
174
while(ret < num)
175
ret <<= 1;
176
177
return ret;
178
}
179
180
static inline void vdp2putpixel(s32 x, s32 y, u16 color, int priority) {
181
vdp2_fb[(y * 512) + x] = color;
182
vdp2_prio[x][y] = (uint8) priority;
183
}
184
185
static u32 Vdp2ColorRamGetColor32(u32 colorindex, int alpha) {
186
switch(Vdp2Internal.ColorMode) {
187
case 0:
188
case 1:
189
{
190
u32 tmp;
191
colorindex <<= 1;
192
tmp = T2ReadWord(Vdp2ColorRam, colorindex & 0xFFF);
193
return SAT2YAB32(alpha, tmp);
194
}
195
case 2:
196
{
197
u32 tmp1, tmp2;
198
colorindex <<= 2;
199
colorindex &= 0xFFF;
200
tmp1 = T2ReadWord(Vdp2ColorRam, colorindex);
201
tmp2 = T2ReadWord(Vdp2ColorRam, colorindex+2);
202
return SAT2YAB2_32(alpha, tmp1, tmp2);
203
}
204
default:
205
break;
206
}
207
208
return 0;
209
}
210
211
static uint16 Vdp2ColorRamGetColor(u32 colorindex) {
212
u16 tmp;
213
214
switch(Vdp2Internal.ColorMode) {
215
case 0:
216
case 1:
217
{
218
colorindex <<= 1;
219
tmp = T2ReadWord(Vdp2ColorRam, colorindex & 0xFFF);
220
return SAT2YAB1(tmp) | 0x8000;
221
}
222
case 2:
223
{
224
u16 tmp2;
225
colorindex <<= 2;
226
colorindex &= 0xFFF;
227
tmp = T2ReadWord(Vdp2ColorRam, colorindex);
228
tmp2 = T2ReadWord(Vdp2ColorRam, colorindex+2);
229
return SAT2YAB2(tmp, tmp2) | 0x8000;
230
}
231
default:
232
break;
233
}
234
235
return 0;
236
}
237
238
static int Vdp1ReadTexture(vdp1cmd_struct *cmd, pvr_sprite_hdr_t *hdr) {
239
u32 charAddr = cmd->CMDSRCA << 3;
240
uint16 dot, dot2;
241
int queuepos = 0;
242
uint32 *store_queue;
243
uint32 cur_base;
244
u8 SPD = ((cmd->CMDPMOD & 0x40) != 0);
245
int k;
246
247
int wi = power_of_two(cur_spr.w);
248
int he = power_of_two(cur_spr.h);
249
250
for(k = 0; k < cached_spr; ++k) {
251
if(cache[k].vdp1_base == charAddr) {
252
if(cache[k].w == cur_spr.w && cache[k].h == cur_spr.h) {
253
cur_base = cache[k].pvr_base;
254
goto fillHeader;
255
}
256
}
257
}
258
259
cur_base = cur_addr;
260
261
/* Set up both Store Queues for transfer to VRAM */
262
QACR0 = 0x00000004;
263
QACR1 = 0x00000004;
264
265
switch((cmd->CMDPMOD >> 3) & 0x07) {
266
case 0:
267
{
268
// 4 bpp Bank mode
269
u16 temp;
270
u32 colorBank = cmd->CMDCOLR;
271
u32 colorOffset = (Vdp2Regs->CRAOFB & 0x70) << 4;
272
int i, j;
273
274
for(i = 0; i < cur_spr.h; ++i) {
275
store_queue = (uint32 *) (0xE0000000 |
276
(cur_addr & 0x03FFFFE0));
277
278
for(j = 0; j < cur_spr.w; j += 2) {
279
dot = T1ReadByte(Vdp1Ram, charAddr & 0x7FFFF);
280
281
if(((dot & 0xF) == 0) && !SPD) dot2 = 0;
282
else {
283
temp = Vdp2ColorRamGetColor(((dot & 0x0F) | colorBank) +
284
colorOffset);
285
dot2 = COLOR_ADD(temp, vdp1cor, vdp1cog, vdp1cob);
286
}
287
288
if(((dot >> 4) == 0) && !SPD) dot = 0;
289
else {
290
temp = Vdp2ColorRamGetColor(((dot >> 4) | colorBank) +
291
colorOffset);
292
dot = COLOR_ADD(temp, vdp1cor, vdp1cog, vdp1cob);
293
}
294
295
++charAddr;
296
297
store_queue[queuepos++] = dot | (dot2 << 16);
298
299
if(queuepos == 8) {
300
asm("pref @%0" : : "r"(store_queue));
301
queuepos = 0;
302
store_queue += 8;
303
}
304
}
305
306
if(queuepos) {
307
asm("pref @%0" : : "r"(store_queue));
308
queuepos = 0;
309
}
310
311
cur_addr += wi * 2;
312
}
313
break;
314
}
315
316
case 1:
317
{
318
// 4 bpp LUT mode
319
u16 temp;
320
u32 colorLut = cmd->CMDCOLR * 8;
321
int i, j;
322
323
for(i = 0; i < cur_spr.h; ++i) {
324
store_queue = (uint32 *) (0xE0000000 |
325
(cur_addr & 0x03FFFFE0));
326
327
for(j = 0; j < cur_spr.w; j += 2) {
328
dot = T1ReadByte(Vdp1Ram, charAddr & 0x7FFFF);
329
330
if(((dot & 0xF) == 0) && !SPD) dot2 = 0;
331
else {
332
temp = T1ReadWord(Vdp1Ram, ((dot & 0xF) * 2 +
333
colorLut) & 0x7FFFF);
334
335
if(temp & 0x8000)
336
dot2 = COLOR_ADD(SAT2YAB1(temp), vdp1cor, vdp1cog,
337
vdp1cob);
338
else
339
dot2 = COLOR_ADD(Vdp2ColorRamGetColor(temp),
340
vdp1cor, vdp1cog, vdp1cob);
341
}
342
343
if(((dot >> 4) == 0) && !SPD) dot = 0;
344
else {
345
temp = T1ReadWord(Vdp1Ram, ((dot >> 4) * 2 + colorLut) &
346
0x7FFFF);
347
if (temp & 0x8000)
348
dot = COLOR_ADD(SAT2YAB1(temp), vdp1cor, vdp1cog,
349
vdp1cob);
350
else
351
dot = COLOR_ADD(Vdp2ColorRamGetColor(temp), vdp1cor,
352
vdp1cog, vdp1cob);
353
}
354
355
++charAddr;
356
357
store_queue[queuepos++] = dot | (dot2 << 16);
358
359
if(queuepos == 8) {
360
asm("pref @%0" : : "r"(store_queue));
361
queuepos = 0;
362
store_queue += 8;
363
}
364
}
365
366
if(queuepos) {
367
asm("pref @%0" : : "r"(store_queue));
368
queuepos = 0;
369
}
370
371
cur_addr += wi * 2;
372
}
373
break;
374
}
375
376
case 2:
377
{
378
// 8 bpp (64 color) Bank mode
379
int i, j;
380
u32 colorBank = cmd->CMDCOLR;
381
u32 colorOffset = (Vdp2Regs->CRAOFB & 0x70) << 4;
382
u16 temp;
383
384
for(i = 0; i < cur_spr.h; ++i) {
385
store_queue = (uint32 *) (0xE0000000 |
386
(cur_addr & 0x03FFFFE0));
387
388
for(j = 0; j < cur_spr.w; j += 2) {
389
dot = T1ReadByte(Vdp1Ram, charAddr & 0x7FFFF) & 0x3F;
390
dot2 = T1ReadByte(Vdp1Ram, (charAddr + 1) & 0x7FFFF) & 0x3F;
391
charAddr = charAddr + 2;
392
393
if(dot || SPD) {
394
temp = Vdp2ColorRamGetColor((dot | colorBank) +
395
colorOffset);
396
dot = COLOR_ADD(temp, vdp1cor, vdp1cog, vdp1cob);
397
}
398
399
if(dot2 || SPD) {
400
temp = Vdp2ColorRamGetColor((dot2 | colorBank) +
401
colorOffset);
402
dot2 = COLOR_ADD(temp, vdp1cor, vdp1cog, vdp1cob);
403
}
404
405
store_queue[queuepos++] = dot | (dot2 << 16);
406
407
if(queuepos == 8) {
408
asm("pref @%0" : : "r"(store_queue));
409
queuepos = 0;
410
store_queue += 8;
411
}
412
}
413
414
if(queuepos) {
415
asm("pref @%0" : : "r"(store_queue));
416
queuepos = 0;
417
}
418
419
cur_addr += wi * 2;
420
}
421
break;
422
}
423
424
case 3:
425
{
426
// 8 bpp (128 color) Bank mode
427
int i, j;
428
u32 colorBank = cmd->CMDCOLR;
429
u32 colorOffset = (Vdp2Regs->CRAOFB & 0x70) << 4;
430
u16 temp;
431
432
for(i = 0; i < cur_spr.h; ++i) {
433
store_queue = (uint32 *) (0xE0000000 |
434
(cur_addr & 0x03FFFFE0));
435
436
for(j = 0; j < cur_spr.w; j += 2) {
437
dot = T1ReadByte(Vdp1Ram, charAddr & 0x7FFFF) & 0x7F;
438
dot2 = T1ReadByte(Vdp1Ram, (charAddr + 1) & 0x7FFFF) & 0x7F;
439
charAddr = charAddr + 2;
440
441
if(dot || SPD) {
442
temp = Vdp2ColorRamGetColor((dot | colorBank) +
443
colorOffset);
444
dot = COLOR_ADD(temp, vdp1cor, vdp1cog, vdp1cob);
445
}
446
447
if(dot2 || SPD) {
448
temp = Vdp2ColorRamGetColor((dot2 | colorBank) +
449
colorOffset);
450
dot2 = COLOR_ADD(temp, vdp1cor, vdp1cog, vdp1cob);
451
}
452
453
store_queue[queuepos++] = dot | (dot2 << 16);
454
455
if(queuepos == 8) {
456
asm("pref @%0" : : "r"(store_queue));
457
queuepos = 0;
458
store_queue += 8;
459
}
460
}
461
462
if(queuepos) {
463
asm("pref @%0" : : "r"(store_queue));
464
queuepos = 0;
465
}
466
467
cur_addr += wi * 2;
468
}
469
break;
470
}
471
472
case 4:
473
{
474
// 8 bpp (256 color) Bank mode
475
int i, j;
476
u32 colorBank = cmd->CMDCOLR;
477
u32 colorOffset = (Vdp2Regs->CRAOFB & 0x70) << 4;
478
u16 temp;
479
480
for(i = 0; i < cur_spr.h; ++i) {
481
store_queue = (uint32 *) (0xE0000000 |
482
(cur_addr & 0x03FFFFE0));
483
484
for(j = 0; j < cur_spr.w; j += 2) {
485
dot = T1ReadByte(Vdp1Ram, charAddr & 0x7FFFF);
486
dot2 = T1ReadByte(Vdp1Ram, (charAddr + 1) & 0x7FFFF);
487
charAddr = charAddr + 2;
488
489
if(dot || SPD) {
490
temp = Vdp2ColorRamGetColor((dot | colorBank) +
491
colorOffset);
492
dot = COLOR_ADD(temp, vdp1cor, vdp1cog, vdp1cob);
493
}
494
495
if(dot2 || SPD) {
496
temp = Vdp2ColorRamGetColor((dot2 | colorBank) +
497
colorOffset);
498
dot2 = COLOR_ADD(temp, vdp1cor, vdp1cog, vdp1cob);
499
}
500
501
store_queue[queuepos++] = dot | (dot2 << 16);
502
503
if(queuepos == 8) {
504
asm("pref @%0" : : "r"(store_queue));
505
queuepos = 0;
506
store_queue += 8;
507
}
508
}
509
510
if(queuepos) {
511
asm("pref @%0" : : "r"(store_queue));
512
queuepos = 0;
513
}
514
515
cur_addr += wi * 2;
516
}
517
break;
518
}
519
520
case 5:
521
{
522
// 16 bpp Bank mode
523
int i, j;
524
525
for(i = 0; i < cur_spr.h; ++i) {
526
store_queue = (uint32 *) (0xE0000000 |
527
(cur_addr & 0x03FFFFE0));
528
529
for(j = 0; j < cur_spr.w; j += 2) {
530
dot = T1ReadWord(Vdp1Ram, charAddr & 0x7FFFF);
531
dot2 = T1ReadWord(Vdp1Ram, (charAddr + 2) & 0x7FFFF);
532
charAddr = charAddr + 4;
533
534
if(dot || SPD)
535
dot = COLOR_ADD(SAT2YAB1(dot), vdp1cor, vdp1cog,
536
vdp1cob);
537
538
if(dot2 || SPD)
539
dot2 = COLOR_ADD(SAT2YAB1(dot2), vdp1cor, vdp1cog,
540
vdp1cob);
541
542
store_queue[queuepos++] = dot | (dot2 << 16);
543
544
if(queuepos == 8) {
545
asm("pref @%0" : : "r"(store_queue));
546
queuepos = 0;
547
store_queue += 8;
548
}
549
}
550
551
if(queuepos) {
552
asm("pref @%0" : : "r"(store_queue));
553
queuepos = 0;
554
}
555
556
cur_addr += wi * 2;
557
}
558
break;
559
}
560
561
default:
562
VDP1LOG("Unimplemented sprite color mode: %X\n",
563
(cmd->CMDPMOD >> 3) & 0x7);
564
return 0;
565
}
566
567
if(cached_spr < 1023) {
568
cache[cached_spr].vdp1_base = cmd->CMDSRCA << 3;
569
cache[cached_spr].pvr_base = cur_base;
570
cache[cached_spr].w = cur_spr.w;
571
cache[cached_spr].h = cur_spr.h;
572
573
cached_spr++;
574
}
575
576
fillHeader:
577
578
cur_spr.uf = (float) cur_spr.w / wi;
579
cur_spr.vf = (float) cur_spr.h / he;
580
581
hdr->mode2 &= (~(PVR_TA_PM2_USIZE_MASK | PVR_TA_PM2_VSIZE_MASK));
582
583
switch (wi) {
584
case 8: break;
585
case 16: hdr->mode2 |= (1 << PVR_TA_PM2_USIZE_SHIFT); break;
586
case 32: hdr->mode2 |= (2 << PVR_TA_PM2_USIZE_SHIFT); break;
587
case 64: hdr->mode2 |= (3 << PVR_TA_PM2_USIZE_SHIFT); break;
588
case 128: hdr->mode2 |= (4 << PVR_TA_PM2_USIZE_SHIFT); break;
589
case 256: hdr->mode2 |= (5 << PVR_TA_PM2_USIZE_SHIFT); break;
590
case 512: hdr->mode2 |= (6 << PVR_TA_PM2_USIZE_SHIFT); break;
591
case 1024: hdr->mode2 |= (7 << PVR_TA_PM2_USIZE_SHIFT); break;
592
default: assert_msg(0, "Invalid texture U size"); break;
593
}
594
595
switch (he) {
596
case 8: break;
597
case 16: hdr->mode2 |= (1 << PVR_TA_PM2_VSIZE_SHIFT); break;
598
case 32: hdr->mode2 |= (2 << PVR_TA_PM2_VSIZE_SHIFT); break;
599
case 64: hdr->mode2 |= (3 << PVR_TA_PM2_VSIZE_SHIFT); break;
600
case 128: hdr->mode2 |= (4 << PVR_TA_PM2_VSIZE_SHIFT); break;
601
case 256: hdr->mode2 |= (5 << PVR_TA_PM2_VSIZE_SHIFT); break;
602
case 512: hdr->mode2 |= (6 << PVR_TA_PM2_VSIZE_SHIFT); break;
603
case 1024: hdr->mode2 |= (7 << PVR_TA_PM2_VSIZE_SHIFT); break;
604
default: assert_msg(0, "Invalid texture V size"); break;
605
}
606
607
hdr->mode3 = ((cur_base & 0x00FFFFF8) >> 3) | (PVR_TXRFMT_NONTWIDDLED);
608
609
/* Make sure everything is aligned nicely... */
610
cur_addr = (cur_addr & 0x03FFFFE0) + 0x20;
611
612
return 1;
613
}
614
615
static u8 Vdp1ReadPriority(vdp1cmd_struct *cmd) {
616
u8 SPCLMD = Vdp2Regs->SPCTL;
617
u8 sprite_register;
618
u8 *sprprilist = (u8 *)&Vdp2Regs->PRISA;
619
620
if ((SPCLMD & 0x20) && (cmd->CMDCOLR & 0x8000)) {
621
// RGB data, use register 0
622
return Vdp2Regs->PRISA & 0x07;
623
}
624
else {
625
u8 sprite_type = SPCLMD & 0x0F;
626
switch(sprite_type) {
627
case 0:
628
sprite_register = ((cmd->CMDCOLR & 0x8000) |
629
(~cmd->CMDCOLR & 0x4000)) >> 14;
630
return sprprilist[sprite_register ^ 1] & 0x07;
631
break;
632
case 1:
633
sprite_register = ((cmd->CMDCOLR & 0xC000) |
634
(~cmd->CMDCOLR & 0x2000)) >> 13;
635
return sprprilist[sprite_register ^ 1] & 0x07;
636
break;
637
case 3:
638
sprite_register = ((cmd->CMDCOLR & 0x4000) |
639
(~cmd->CMDCOLR & 0x2000)) >> 13;
640
return sprprilist[sprite_register ^ 1] & 0x07;
641
break;
642
case 4:
643
sprite_register = ((cmd->CMDCOLR & 0x4000) |
644
(~cmd->CMDCOLR & 0x2000)) >> 13;
645
return sprprilist[sprite_register ^ 1] & 0x07;
646
break;
647
case 5:
648
sprite_register = ((cmd->CMDCOLR & 0x6000) |
649
(~cmd->CMDCOLR & 0x1000)) >> 12;
650
return sprprilist[sprite_register ^ 1] & 0x07;
651
break;
652
case 6:
653
sprite_register = ((cmd->CMDCOLR & 0x6000) |
654
(~cmd->CMDCOLR & 0x1000)) >> 12;
655
return sprprilist[sprite_register ^ 1] & 0x07;
656
break;
657
case 7:
658
sprite_register = ((cmd->CMDCOLR & 0x6000) |
659
(~cmd->CMDCOLR & 0x1000)) >> 12;
660
return sprprilist[sprite_register ^ 1] & 0x07;
661
break;
662
default:
663
VDP1LOG("sprite type %d not implemented\n", sprite_type);
664
return 0x07;
665
break;
666
}
667
}
668
}
669
670
/* This has all been imported from the vidsoft.c file. It will be updated,
671
hopefully (roughly) synchronized with updates to it */
672
673
//////////////////////////////////////////////////////////////////////////////
674
675
typedef struct
676
{
677
int xstart, ystart;
678
int xend, yend;
679
int pixeloffset;
680
int lineincrement;
681
} clipping_struct;
682
683
static void inline HandleClipping(vdp2draw_struct *info, clipping_struct *clip)
684
{
685
clip->pixeloffset=0;
686
clip->lineincrement=0;
687
688
// Handle clipping(both window and screen clipping)
689
if (info->x < 0)
690
{
691
clip->xstart = 0;
692
clip->xend = (info->x+info->cellw);
693
clip->pixeloffset = 0 - info->x;
694
clip->lineincrement = 0 - info->x;
695
}
696
else
697
{
698
clip->xstart = info->x;
699
700
if ((info->x+info->cellw) > vdp2width)
701
{
702
clip->xend = vdp2width;
703
clip->lineincrement = (info->x+info->cellw) - vdp2width;
704
}
705
else
706
clip->xend = (info->x+info->cellw);
707
}
708
709
if (info->y < 0)
710
{
711
clip->ystart = 0;
712
clip->yend = (info->y+info->cellh);
713
clip->pixeloffset = (info->cellw * (0 - info->y)) + clip->pixeloffset;
714
}
715
else
716
{
717
clip->ystart = info->y;
718
719
if ((info->y+info->cellh) >= vdp2height)
720
clip->yend = vdp2height;
721
else
722
clip->yend = (info->y+info->cellh);
723
}
724
}
725
726
//////////////////////////////////////////////////////////////////////////////
727
728
void Vdp2DrawScrollBitmap(vdp2draw_struct *info)
729
{
730
int i, i2;
731
clipping_struct clip;
732
733
HandleClipping(info, &clip);
734
735
switch (info->colornumber)
736
{
737
case 0: // 4 BPP(16 colors)
738
// fix me
739
printf("vdp2 bitmap 4 bpp draw\n");
740
return;
741
case 1: // 8 BPP(256 colors)
742
info->charaddr += clip.pixeloffset;
743
744
for (i = clip.ystart; i < clip.yend; i++)
745
{
746
for (i2 = clip.xstart; i2 < clip.xend; i2++)
747
{
748
u16 color = T1ReadByte(Vdp2Ram, info->charaddr);
749
info->charaddr++;
750
751
if (color == 0 && info->transparencyenable) {
752
vdp2putpixel(i2, i, 0, info->priority);
753
}
754
else {
755
color = Vdp2ColorRamGetColor(info->coloroffset + (info->paladdr | color));
756
vdp2putpixel(i2, i, info->PostPixelFetchCalc(info, color) | 0x8000, info->priority);
757
}
758
}
759
760
info->charaddr += clip.lineincrement;
761
}
762
763
return;
764
case 2:
765
printf("vdp2 bitmap 16bpp palette draw\n");
766
break;
767
case 3: // 15 BPP
768
clip.pixeloffset *= 2;
769
clip.lineincrement *= 2;
770
771
info->charaddr += clip.pixeloffset;
772
773
for (i = clip.ystart; i < clip.yend; i++)
774
{
775
for (i2 = clip.xstart; i2 < clip.xend; i2++)
776
{
777
u16 color = T1ReadWord(Vdp2Ram, info->charaddr);
778
info->charaddr += 2;
779
780
if ((color & 0x8000) == 0 && info->transparencyenable)
781
vdp2_fb[(i * vdp2width) + i2] = 0;
782
else
783
vdp2_fb[(i * vdp2width) + i2] = info->PostPixelFetchCalc(info, SAT2YAB1(color)) | 0x8000;
784
785
vdp2_prio[i][i2] = info->priority;
786
}
787
788
info->charaddr += clip.lineincrement;
789
}
790
791
return;
792
case 4: // 24 BPP
793
clip.pixeloffset *= 4;
794
clip.lineincrement *= 4;
795
796
info->charaddr += clip.pixeloffset;
797
798
for (i = clip.ystart; i < clip.yend; i++)
799
{
800
for (i2 = clip.xstart; i2 < clip.xend; i2++)
801
{
802
u32 color = T1ReadLong(Vdp2Ram, info->charaddr);
803
info->charaddr += 4;
804
805
if ((color & 0x80000000) == 0 && info->transparencyenable)
806
vdp2putpixel(i2, i, 0, info->priority);
807
else {
808
u16 dot = ((color & 0xF80000) >> 19 |
809
(color & 0x00F800) >> 6 |
810
(color & 0x0000F8) << 7 | 0x8000);
811
vdp2putpixel(i2, i, info->PostPixelFetchCalc(info, dot), info->priority);
812
}
813
}
814
815
info->charaddr += clip.lineincrement;
816
817
}
818
return;
819
default: break;
820
}
821
}
822
823
//////////////////////////////////////////////////////////////////////////////
824
825
#define Vdp2DrawCell4bpp(mask, shift) \
826
if ((dot & mask) == 0 && info->transparencyenable) { \
827
vdp2putpixel(i2, i, 0, info->priority); \
828
} \
829
else \
830
{ \
831
color = Vdp2ColorRamGetColor(info->coloroffset + (info->paladdr | ((dot & mask) >> shift))); \
832
vdp2putpixel(i2, i, info->PostPixelFetchCalc(info, color), info->priority); \
833
}
834
835
//////////////////////////////////////////////////////////////////////////////
836
837
static void Vdp2DrawCell(vdp2draw_struct *info)
838
{
839
u32 color;
840
int i, i2;
841
clipping_struct clip;
842
u32 newcharaddr;
843
844
HandleClipping(info, &clip);
845
846
if (info->flipfunction & 0x1)
847
{
848
// Horizontal flip
849
}
850
851
if (info->flipfunction & 0x2)
852
{
853
// Vertical flip
854
// clip.pixeloffset = (info.w * info.h) - clip.pixeloffset;
855
// clip.lineincrement = 0 - clip.lineincrement;
856
}
857
858
switch(info->colornumber)
859
{
860
case 0: // 4 BPP
861
if ((clip.lineincrement | clip.pixeloffset) == 0)
862
{
863
for (i = clip.ystart; i < clip.yend; i++)
864
{
865
u32 dot;
866
u16 color;
867
868
i2 = clip.xstart;
869
870
// Fetch Pixel 1/2/3/4/5/6/7/8
871
dot = T1ReadLong(Vdp2Ram, info->charaddr);
872
info->charaddr+=4;
873
874
// Draw 8 Pixels
875
Vdp2DrawCell4bpp(0xF0000000, 28)
876
i2++;
877
Vdp2DrawCell4bpp(0x0F000000, 24)
878
i2++;
879
Vdp2DrawCell4bpp(0x00F00000, 20)
880
i2++;
881
Vdp2DrawCell4bpp(0x000F0000, 16)
882
i2++;
883
Vdp2DrawCell4bpp(0x0000F000, 12)
884
i2++;
885
Vdp2DrawCell4bpp(0x00000F00, 8)
886
i2++;
887
Vdp2DrawCell4bpp(0x000000F0, 4)
888
i2++;
889
Vdp2DrawCell4bpp(0x0000000F, 0)
890
i2++;
891
}
892
}
893
else
894
{
895
u8 dot;
896
897
newcharaddr = info->charaddr + ((info->cellw * info->cellh) >> 1);
898
899
info->charaddr <<= 1;
900
info->charaddr += clip.pixeloffset;
901
902
for (i = clip.ystart; i < clip.yend; i++)
903
{
904
dot = T1ReadByte(Vdp2Ram, info->charaddr >> 1);
905
info->charaddr++;
906
907
for (i2 = clip.xstart; i2 < clip.xend; i2++)
908
{
909
u32 color;
910
911
// Draw two pixels
912
if(info->charaddr & 0x1)
913
{
914
Vdp2DrawCell4bpp(0xF0, 4)
915
info->charaddr++;
916
}
917
else
918
{
919
Vdp2DrawCell4bpp(0x0F, 0)
920
dot = T1ReadByte(Vdp2Ram, info->charaddr >> 1);
921
info->charaddr++;
922
}
923
}
924
info->charaddr += clip.lineincrement;
925
}
926
927
info->charaddr = newcharaddr;
928
}
929
break;
930
case 1: // 8 BPP
931
newcharaddr = info->charaddr + (info->cellw * info->cellh);
932
info->charaddr += clip.pixeloffset;
933
934
for (i = clip.ystart; i < clip.yend; i++)
935
{
936
for (i2 = clip.xstart; i2 < clip.xend; i2++)
937
{
938
u16 color = T1ReadByte(Vdp2Ram, info->charaddr);
939
info->charaddr++;
940
941
if (color == 0 && info->transparencyenable) {
942
vdp2putpixel(i2, i, 0, info->priority);
943
}
944
else {
945
color = Vdp2ColorRamGetColor(info->coloroffset + (info->paladdr | color));
946
vdp2putpixel(i2, i, info->PostPixelFetchCalc(info, color), info->priority);
947
}
948
}
949
950
info->charaddr += clip.lineincrement;
951
}
952
953
info->charaddr = newcharaddr;
954
955
break;
956
case 2: // 16 BPP(palette)
957
printf("vdp2 cell draw 16bpp palette\n");
958
break;
959
960
case 3: // 16 BPP(RGB)
961
printf("vdp2 cell draw 16bpp\n");
962
break;
963
case 4: // 32 BPP
964
newcharaddr = info->charaddr + (info->cellw * info->cellh);
965
info->charaddr += clip.pixeloffset;
966
967
for (i = clip.ystart; i < clip.yend; i++)
968
{
969
for (i2 = clip.xstart; i2 < clip.xend; i2++)
970
{
971
u16 dot1, dot2;
972
dot1 = T1ReadWord(Vdp2Ram, info->charaddr & 0x7FFFF);
973
info->charaddr += 2;
974
dot2 = T1ReadWord(Vdp2Ram, info->charaddr & 0x7FFFF);
975
info->charaddr += 2;
976
977
if (!(dot1 & 0x8000) && info->transparencyenable)
978
continue;
979
980
color = SAT2YAB2(dot1, dot2);
981
vdp2putpixel(i2, i, info->PostPixelFetchCalc(info, color), info->priority);
982
}
983
984
info->charaddr += clip.lineincrement;
985
}
986
987
info->charaddr = newcharaddr;
988
989
break;
990
}
991
}
992
993
//////////////////////////////////////////////////////////////////////////////
994
995
static void Vdp2DrawPattern(vdp2draw_struct *info)
996
{
997
// if (info->specialprimode == 1)
998
// tile.priority = (info->priority & 0xFFFFFFFE) | info->specialfunction;
999
// else
1000
// tile.priority = info->priority;
1001
1002
switch(info->patternwh)
1003
{
1004
case 1:
1005
Vdp2DrawCell(info);
1006
info->x += 8;
1007
info->y += 8;
1008
break;
1009
case 2:
1010
Vdp2DrawCell(info);
1011
info->x += 8;
1012
Vdp2DrawCell(info);
1013
info->x -= 8;
1014
info->y += 8;
1015
Vdp2DrawCell(info);
1016
info->x += 8;
1017
Vdp2DrawCell(info);
1018
info->x += 8;
1019
info->y += 8;
1020
break;
1021
}
1022
}
1023
1024
//////////////////////////////////////////////////////////////////////////////
1025
1026
static void Vdp2PatternAddr(vdp2draw_struct *info)
1027
{
1028
switch(info->patterndatasize)
1029
{
1030
case 1:
1031
{
1032
u16 tmp = T1ReadWord(Vdp2Ram, info->addr);
1033
1034
info->addr += 2;
1035
info->specialfunction = (info->supplementdata >> 9) & 0x1;
1036
1037
switch(info->colornumber)
1038
{
1039
case 0: // in 16 colors
1040
info->paladdr = ((tmp & 0xF000) >> 8) | ((info->supplementdata & 0xE0) << 3);
1041
break;
1042
default: // not in 16 colors
1043
info->paladdr = (tmp & 0x7000) >> 4;
1044
break;
1045
}
1046
1047
switch(info->auxmode)
1048
{
1049
case 0:
1050
info->flipfunction = (tmp & 0xC00) >> 10;
1051
1052
switch(info->patternwh)
1053
{
1054
case 1:
1055
info->charaddr = (tmp & 0x3FF) | ((info->supplementdata & 0x1F) << 10);
1056
break;
1057
case 2:
1058
info->charaddr = ((tmp & 0x3FF) << 2) | (info->supplementdata & 0x3) | ((info->supplementdata & 0x1C) << 10);
1059
break;
1060
}
1061
break;
1062
case 1:
1063
info->flipfunction = 0;
1064
1065
switch(info->patternwh)
1066
{
1067
case 1:
1068
info->charaddr = (tmp & 0xFFF) | ((info->supplementdata & 0x1C) << 10);
1069
break;
1070
case 2:
1071
info->charaddr = ((tmp & 0xFFF) << 2) | (info->supplementdata & 0x3) | ((info->supplementdata & 0x10) << 10);
1072
break;
1073
}
1074
break;
1075
}
1076
1077
break;
1078
}
1079
case 2: {
1080
u16 tmp1 = T1ReadWord(Vdp2Ram, info->addr);
1081
u16 tmp2 = T1ReadWord(Vdp2Ram, info->addr+2);
1082
info->addr += 4;
1083
info->charaddr = tmp2 & 0x7FFF;
1084
info->flipfunction = (tmp1 & 0xC000) >> 14;
1085
info->paladdr = (tmp1 & 0x7F) << 4;
1086
info->specialfunction = (tmp1 & 0x2000) >> 13;
1087
break;
1088
}
1089
}
1090
1091
if (!(Vdp2Regs->VRSIZE & 0x8000))
1092
info->charaddr &= 0x3FFF;
1093
1094
info->charaddr *= 0x20; // selon Runik
1095
}
1096
1097
//////////////////////////////////////////////////////////////////////////////
1098
1099
static void Vdp2DrawPage(vdp2draw_struct *info)
1100
{
1101
int X, Y;
1102
int i, j;
1103
1104
X = info->x;
1105
for(i = 0;i < info->pagewh;i++)
1106
{
1107
Y = info->y;
1108
info->x = X;
1109
for(j = 0;j < info->pagewh;j++)
1110
{
1111
info->y = Y;
1112
if ((info->x >= -info->patternpixelwh) &&
1113
(info->y >= -info->patternpixelwh) &&
1114
(info->x <= info->draww) &&
1115
(info->y <= info->drawh))
1116
{
1117
Vdp2PatternAddr(info);
1118
Vdp2DrawPattern(info);
1119
}
1120
else
1121
{
1122
info->addr += info->patterndatasize * 2;
1123
info->x += info->patternpixelwh;
1124
info->y += info->patternpixelwh;
1125
}
1126
}
1127
}
1128
}
1129
1130
//////////////////////////////////////////////////////////////////////////////
1131
1132
static void Vdp2DrawPlane(vdp2draw_struct *info)
1133
{
1134
int X, Y;
1135
int i, j;
1136
1137
X = info->x;
1138
for(i = 0;i < info->planeh;i++)
1139
{
1140
Y = info->y;
1141
info->x = X;
1142
for(j = 0;j < info->planew;j++)
1143
{
1144
info->y = Y;
1145
Vdp2DrawPage(info);
1146
}
1147
}
1148
}
1149
1150
//////////////////////////////////////////////////////////////////////////////
1151
1152
static void Vdp2DrawMap(vdp2draw_struct *info)
1153
{
1154
int i, j;
1155
int X, Y;
1156
u32 lastplane;
1157
1158
X = info->x;
1159
lastplane=0xFFFFFFFF;
1160
1161
info->patternpixelwh = 8 * info->patternwh;
1162
info->draww = (int)((float)vdp2width / info->coordincx);
1163
info->drawh = (int)((float)vdp2height / info->coordincy);
1164
1165
for(i = 0;i < info->mapwh;i++)
1166
{
1167
Y = info->y;
1168
info->x = X;
1169
for(j = 0;j < info->mapwh;j++)
1170
{
1171
info->y = Y;
1172
info->PlaneAddr(info, info->mapwh * i + j);
1173
if (info->addr != lastplane)
1174
{
1175
Vdp2DrawPlane(info);
1176
lastplane = info->addr;
1177
}
1178
}
1179
}
1180
}
1181
1182
static int VIDDCInit(void) {
1183
pvr_sprite_cxt_t op_poly_cxt, tr_poly_cxt;
1184
pvr_sprite_cxt_t pt_sprite_cxt, tr_sprite_cxt;
1185
1186
vid_set_mode(DM_320x240, PM_RGB565);
1187
1188
if(pvr_init(&pvr_params)) {
1189
fprintf(stderr, "VIDDCInit() - error initializing PVR\n");
1190
return -1;
1191
}
1192
1193
dmadone = sem_create(1);
1194
1195
pvr_set_vertbuf(PVR_LIST_OP_POLY, vbuf_opaque, 1024 * 256);
1196
pvr_set_vertbuf(PVR_LIST_TR_POLY, vbuf_translucent, 1024 * 256);
1197
pvr_set_vertbuf(PVR_LIST_PT_POLY, vbuf_punchthru, 1024 * 256);
1198
1199
tex_space = pvr_mem_malloc(1024 * 1024 * 2);
1200
vdp2_tex = pvr_mem_malloc(512 * 256 * 4 * 2);
1201
cur_addr = (uint32)tex_space;
1202
1203
printf("PVR Memory Available: %lu\n", pvr_mem_available());
1204
1205
sq_set(tex_space, 0xFF, 1024 * 1024 * 2);
1206
1207
pvr_sprite_cxt_col(&op_poly_cxt, PVR_LIST_OP_POLY);
1208
pvr_sprite_cxt_col(&tr_poly_cxt, PVR_LIST_TR_POLY);
1209
1210
op_poly_cxt.gen.culling = PVR_CULLING_NONE;
1211
tr_poly_cxt.gen.culling = PVR_CULLING_NONE;
1212
1213
pvr_sprite_compile(&op_poly_hdr, &op_poly_cxt);
1214
pvr_sprite_compile(&tr_poly_hdr, &tr_poly_cxt);
1215
1216
pvr_sprite_cxt_txr(&tr_sprite_cxt, PVR_LIST_TR_POLY, PVR_TXRFMT_ARGB1555 |
1217
PVR_TXRFMT_NONTWIDDLED, 1024, 1024, tex_space,
1218
PVR_FILTER_NONE);
1219
pvr_sprite_cxt_txr(&pt_sprite_cxt, PVR_LIST_PT_POLY, PVR_TXRFMT_ARGB1555 |
1220
PVR_TXRFMT_NONTWIDDLED, 1024, 1024, tex_space,
1221
PVR_FILTER_NONE);
1222
1223
pt_sprite_cxt.gen.culling = PVR_CULLING_NONE;
1224
tr_sprite_cxt.gen.culling = PVR_CULLING_NONE;
1225
1226
pvr_sprite_compile(&tr_sprite_hdr, &tr_sprite_cxt);
1227
pvr_sprite_compile(&pt_sprite_hdr, &pt_sprite_cxt);
1228
1229
tr_sprite_hdr.argb = PVR_PACK_COLOR(0.5f, 1.0f, 1.0f, 1.0f);
1230
1231
priority_levels[0] = 0.0f;
1232
priority_levels[1] = 1.0f;
1233
priority_levels[2] = 2.0f;
1234
priority_levels[3] = 3.0f;
1235
priority_levels[4] = 4.0f;
1236
priority_levels[5] = 5.0f;
1237
priority_levels[6] = 6.0f;
1238
priority_levels[7] = 7.0f;
1239
1240
framecount = 0;
1241
lastup = time(NULL);
1242
1243
return 0;
1244
}
1245
1246
static void VIDDCDeInit(void) {
1247
pvr_set_vertbuf(PVR_LIST_OP_POLY, NULL, 0);
1248
pvr_set_vertbuf(PVR_LIST_TR_POLY, NULL, 0);
1249
pvr_set_vertbuf(PVR_LIST_PT_POLY, NULL, 0);
1250
1251
pvr_mem_free(tex_space);
1252
sem_destroy(dmadone);
1253
1254
pvr_shutdown();
1255
vid_set_mode(DM_640x480, PM_RGB565);
1256
}
1257
1258
static void VIDDCResize(unsigned int w, unsigned int h, int unused) {
1259
}
1260
1261
static int VIDDCIsFullscreen(void) {
1262
return 1;
1263
}
1264
1265
static int VIDDCVdp1Reset(void) {
1266
return 0;
1267
}
1268
1269
static void VIDDCVdp1DrawStart(void) {
1270
if(Vdp2Regs->CLOFEN & 0x40) {
1271
// color offset enable
1272
if(Vdp2Regs->CLOFSL & 0x40) {
1273
// color offset B
1274
vdp1cor = Vdp2Regs->COBR & 0xFF;
1275
if(Vdp2Regs->COBR & 0x100)
1276
vdp1cor |= 0xFFFFFF00;
1277
1278
vdp1cog = Vdp2Regs->COBG & 0xFF;
1279
if(Vdp2Regs->COBG & 0x100)
1280
vdp1cog |= 0xFFFFFF00;
1281
1282
vdp1cob = Vdp2Regs->COBB & 0xFF;
1283
if(Vdp2Regs->COBB & 0x100)
1284
vdp1cob |= 0xFFFFFF00;
1285
}
1286
else {
1287
// color offset A
1288
vdp1cor = Vdp2Regs->COAR & 0xFF;
1289
if(Vdp2Regs->COAR & 0x100)
1290
vdp1cor |= 0xFFFFFF00;
1291
1292
vdp1cog = Vdp2Regs->COAG & 0xFF;
1293
if(Vdp2Regs->COAG & 0x100)
1294
vdp1cog |= 0xFFFFFF00;
1295
1296
vdp1cob = Vdp2Regs->COAB & 0xFF;
1297
if(Vdp2Regs->COAB & 0x100)
1298
vdp1cob |= 0xFFFFFF00;
1299
}
1300
}
1301
else // color offset disable
1302
vdp1cor = vdp1cog = vdp1cob = 0;
1303
}
1304
1305
static void VIDDCVdp1DrawEnd(void) {
1306
cached_spr = 0;
1307
priority_levels[0] = 0.0f;
1308
priority_levels[1] = 1.0f;
1309
priority_levels[2] = 2.0f;
1310
priority_levels[3] = 3.0f;
1311
priority_levels[4] = 4.0f;
1312
priority_levels[5] = 5.0f;
1313
priority_levels[6] = 6.0f;
1314
priority_levels[7] = 7.0f;
1315
}
1316
1317
static void VIDDCVdp1NormalSpriteDraw(void) {
1318
int x, y, num;
1319
u8 z;
1320
vdp1cmd_struct cmd;
1321
pvr_sprite_txr_t sprite;
1322
pvr_list_t list;
1323
1324
Vdp1ReadCommand(&cmd, Vdp1Regs->addr);
1325
1326
x = Vdp1Regs->localX + cmd.CMDXA;
1327
y = Vdp1Regs->localY + cmd.CMDYA;
1328
cur_spr.w = ((cmd.CMDSIZE >> 8) & 0x3F) << 3;
1329
cur_spr.h = cmd.CMDSIZE & 0xFF;
1330
1331
if ((cmd.CMDPMOD & 0x07) == 0x03) {
1332
list = PVR_LIST_TR_POLY;
1333
num = Vdp1ReadTexture(&cmd, &tr_sprite_hdr);
1334
1335
if(num == 0)
1336
return;
1337
else
1338
pvr_list_prim(PVR_LIST_TR_POLY, &tr_sprite_hdr,
1339
sizeof(pvr_sprite_hdr_t));
1340
}
1341
else {
1342
num = Vdp1ReadTexture(&cmd, &pt_sprite_hdr);
1343
list = PVR_LIST_PT_POLY;
1344
1345
if(num == 0)
1346
return;
1347
else
1348
pvr_list_prim(PVR_LIST_PT_POLY, &pt_sprite_hdr,
1349
sizeof(pvr_sprite_hdr_t));
1350
}
1351
1352
z = Vdp1ReadPriority(&cmd);
1353
1354
sprite.flags = PVR_CMD_VERTEX_EOL;
1355
sprite.ax = x;
1356
sprite.ay = y;
1357
sprite.az = priority_levels[z];
1358
1359
sprite.bx = x + cur_spr.w;
1360
sprite.by = y;
1361
sprite.bz = priority_levels[z];
1362
1363
sprite.cx = x + cur_spr.w;
1364
sprite.cy = y + cur_spr.h;
1365
sprite.cz = priority_levels[z];
1366
1367
sprite.dx = x;
1368
sprite.dy = y + cur_spr.h;
1369
1370
sprite.auv = PVR_PACK_16BIT_UV(((cmd.CMDCTRL & 0x0010) ? cur_spr.uf : 0.0f),
1371
((cmd.CMDCTRL & 0x0020) ? cur_spr.vf : 0.0f));
1372
sprite.buv = PVR_PACK_16BIT_UV(((cmd.CMDCTRL & 0x0010) ? 0.0f : cur_spr.uf),
1373
((cmd.CMDCTRL & 0x0020) ? cur_spr.vf : 0.0f));
1374
sprite.cuv = PVR_PACK_16BIT_UV(((cmd.CMDCTRL & 0x0010) ? 0.0f : cur_spr.uf),
1375
((cmd.CMDCTRL & 0x0020) ? 0.0f : cur_spr.vf));
1376
pvr_list_prim(list, &sprite, sizeof(sprite));
1377
1378
priority_levels[z] += 0.000001f;
1379
}
1380
1381
static void VIDDCVdp1ScaledSpriteDraw(void) {
1382
vdp1cmd_struct cmd;
1383
s16 rw = 0, rh = 0;
1384
s16 x, y;
1385
u8 z;
1386
pvr_sprite_txr_t sprite;
1387
pvr_list_t list;
1388
int num;
1389
1390
Vdp1ReadCommand(&cmd, Vdp1Regs->addr);
1391
1392
x = cmd.CMDXA + Vdp1Regs->localX;
1393
y = cmd.CMDYA + Vdp1Regs->localY;
1394
cur_spr.w = ((cmd.CMDSIZE >> 8) & 0x3F) * 8;
1395
cur_spr.h = cmd.CMDSIZE & 0xFF;
1396
1397
if((cmd.CMDPMOD & 0x07) == 0x03) {
1398
list = PVR_LIST_TR_POLY;
1399
num = Vdp1ReadTexture(&cmd, &tr_sprite_hdr);
1400
1401
if(num == 0)
1402
return;
1403
else
1404
pvr_list_prim(PVR_LIST_TR_POLY, &tr_sprite_hdr,
1405
sizeof(pvr_sprite_hdr_t));
1406
}
1407
else {
1408
num = Vdp1ReadTexture(&cmd, &pt_sprite_hdr);
1409
list = PVR_LIST_PT_POLY;
1410
1411
if(num == 0)
1412
return;
1413
else
1414
pvr_list_prim(PVR_LIST_PT_POLY, &pt_sprite_hdr,
1415
sizeof(pvr_sprite_hdr_t));
1416
}
1417
1418
// Setup Zoom Point
1419
switch ((cmd.CMDCTRL & 0xF00) >> 8) {
1420
case 0x0: // Only two coordinates
1421
rw = cmd.CMDXC - x + Vdp1Regs->localX + 1;
1422
rh = cmd.CMDYC - y + Vdp1Regs->localY + 1;
1423
break;
1424
case 0x5: // Upper-left
1425
rw = cmd.CMDXB + 1;
1426
rh = cmd.CMDYB + 1;
1427
break;
1428
case 0x6: // Upper-Center
1429
rw = cmd.CMDXB;
1430
rh = cmd.CMDYB;
1431
x = x - rw / 2;
1432
++rw;
1433
++rh;
1434
break;
1435
case 0x7: // Upper-Right
1436
rw = cmd.CMDXB;
1437
rh = cmd.CMDYB;
1438
x = x - rw;
1439
++rw;
1440
++rh;
1441
break;
1442
case 0x9: // Center-left
1443
rw = cmd.CMDXB;
1444
rh = cmd.CMDYB;
1445
y = y - rh / 2;
1446
++rw;
1447
++rh;
1448
break;
1449
case 0xA: // Center-center
1450
rw = cmd.CMDXB;
1451
rh = cmd.CMDYB;
1452
x = x - rw / 2;
1453
y = y - rh / 2;
1454
++rw;
1455
++rh;
1456
break;
1457
case 0xB: // Center-right
1458
rw = cmd.CMDXB;
1459
rh = cmd.CMDYB;
1460
x = x - rw;
1461
y = y - rh / 2;
1462
++rw;
1463
++rh;
1464
break;
1465
case 0xD: // Lower-left
1466
rw = cmd.CMDXB;
1467
rh = cmd.CMDYB;
1468
y = y - rh;
1469
++rw;
1470
++rh;
1471
break;
1472
case 0xE: // Lower-center
1473
rw = cmd.CMDXB;
1474
rh = cmd.CMDYB;
1475
x = x - rw / 2;
1476
y = y - rh;
1477
++rw;
1478
++rh;
1479
break;
1480
case 0xF: // Lower-right
1481
rw = cmd.CMDXB;
1482
rh = cmd.CMDYB;
1483
x = x - rw;
1484
y = y - rh;
1485
++rw;
1486
++rh;
1487
break;
1488
default:
1489
break;
1490
}
1491
1492
z = Vdp1ReadPriority(&cmd);
1493
1494
sprite.flags = PVR_CMD_VERTEX_EOL;
1495
sprite.ax = x;
1496
sprite.ay = y;
1497
sprite.az = priority_levels[z];
1498
1499
sprite.bx = x + rw;
1500
sprite.by = y;
1501
sprite.bz = priority_levels[z];
1502
1503
sprite.cx = x + rw;
1504
sprite.cy = y + rh;
1505
sprite.cz = priority_levels[z];
1506
1507
sprite.dx = x;
1508
sprite.dy = y + rh;
1509
1510
sprite.auv = PVR_PACK_16BIT_UV(((cmd.CMDCTRL & 0x0010) ? cur_spr.uf : 0.0f),
1511
((cmd.CMDCTRL & 0x0020) ? cur_spr.vf : 0.0f));
1512
sprite.buv = PVR_PACK_16BIT_UV(((cmd.CMDCTRL & 0x0010) ? 0.0f : cur_spr.uf),
1513
((cmd.CMDCTRL & 0x0020) ? cur_spr.vf : 0.0f));
1514
sprite.cuv = PVR_PACK_16BIT_UV(((cmd.CMDCTRL & 0x0010) ? 0.0f : cur_spr.uf),
1515
((cmd.CMDCTRL & 0x0020) ? 0.0f : cur_spr.vf));
1516
pvr_list_prim(list, &sprite, sizeof(sprite));
1517
1518
priority_levels[z] += 0.000001f;
1519
}
1520
1521
static void VIDDCVdp1DistortedSpriteDraw(void) {
1522
vdp1cmd_struct cmd;
1523
u8 z;
1524
pvr_sprite_txr_t sprite;
1525
pvr_list_t list;
1526
int num;
1527
1528
Vdp1ReadCommand(&cmd, Vdp1Regs->addr);
1529
1530
cur_spr.w = ((cmd.CMDSIZE >> 8) & 0x3F) * 8;
1531
cur_spr.h = cmd.CMDSIZE & 0xFF;
1532
1533
if((cmd.CMDPMOD & 0x7) == 0x3) {
1534
list = PVR_LIST_TR_POLY;
1535
num = Vdp1ReadTexture(&cmd, &tr_sprite_hdr);
1536
1537
if(num == 0)
1538
return;
1539
else
1540
pvr_list_prim(PVR_LIST_TR_POLY, &tr_sprite_hdr,
1541
sizeof(pvr_sprite_hdr_t));
1542
}
1543
else {
1544
num = Vdp1ReadTexture(&cmd, &pt_sprite_hdr);
1545
list = PVR_LIST_PT_POLY;
1546
1547
if(num == 0)
1548
return;
1549
else
1550
pvr_list_prim(PVR_LIST_PT_POLY, &pt_sprite_hdr,
1551
sizeof(pvr_sprite_hdr_t));
1552
}
1553
1554
z = Vdp1ReadPriority(&cmd);
1555
1556
sprite.flags = PVR_CMD_VERTEX_EOL;
1557
sprite.ax = cmd.CMDXA + Vdp1Regs->localX;
1558
sprite.ay = cmd.CMDYA + Vdp1Regs->localY;
1559
sprite.az = priority_levels[z];
1560
1561
sprite.bx = cmd.CMDXB + Vdp1Regs->localX + 1;
1562
sprite.by = cmd.CMDYB + Vdp1Regs->localY;
1563
sprite.bz = priority_levels[z];
1564
1565
sprite.cx = cmd.CMDXC + Vdp1Regs->localX + 1;
1566
sprite.cy = cmd.CMDYC + Vdp1Regs->localY + 1;
1567
sprite.cz = priority_levels[z];
1568
1569
sprite.dx = cmd.CMDXD + Vdp1Regs->localX;
1570
sprite.dy = cmd.CMDYD + Vdp1Regs->localY + 1;
1571
1572
sprite.auv = PVR_PACK_16BIT_UV(((cmd.CMDCTRL & 0x0010) ? cur_spr.uf : 0.0f),
1573
((cmd.CMDCTRL & 0x0020) ? cur_spr.vf : 0.0f));
1574
sprite.buv = PVR_PACK_16BIT_UV(((cmd.CMDCTRL & 0x0010) ? 0.0f : cur_spr.uf),
1575
((cmd.CMDCTRL & 0x0020) ? cur_spr.vf : 0.0f));
1576
sprite.cuv = PVR_PACK_16BIT_UV(((cmd.CMDCTRL & 0x0010) ? 0.0f : cur_spr.uf),
1577
((cmd.CMDCTRL & 0x0020) ? 0.0f : cur_spr.vf));
1578
pvr_list_prim(list, &sprite, sizeof(sprite));
1579
1580
priority_levels[z] += 0.000001f;
1581
}
1582
1583
static void VIDDCVdp1PolygonDraw(void) {
1584
s16 X[4];
1585
s16 Y[4];
1586
u16 color;
1587
u16 CMDPMOD;
1588
u8 alpha, z;
1589
pvr_list_t list;
1590
pvr_sprite_col_t spr;
1591
pvr_sprite_hdr_t *hdr;
1592
1593
X[0] = Vdp1Regs->localX + T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x0C);
1594
Y[0] = Vdp1Regs->localY + T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x0E);
1595
X[1] = Vdp1Regs->localX + T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x10);
1596
Y[1] = Vdp1Regs->localY + T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x12);
1597
X[2] = Vdp1Regs->localX + T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x14);
1598
Y[2] = Vdp1Regs->localY + T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x16);
1599
X[3] = Vdp1Regs->localX + T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x18);
1600
Y[3] = Vdp1Regs->localY + T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x1A);
1601
1602
color = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x06);
1603
CMDPMOD = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x04);
1604
1605
/* Don't bother rendering completely transparent polygons */
1606
if((!(color & 0x8000) && !(CMDPMOD & 0x0040)) || !color) {
1607
return;
1608
}
1609
1610
if((CMDPMOD & 0x0007) == 0x0003) {
1611
alpha = 0x80;
1612
list = PVR_LIST_TR_POLY;
1613
hdr = &tr_poly_hdr;
1614
}
1615
else {
1616
alpha = 0xFF;
1617
list = PVR_LIST_OP_POLY;
1618
hdr = &op_poly_hdr;
1619
}
1620
1621
if(color & 0x8000) {
1622
hdr->argb = COLOR_ADD32(SAT2YAB32(alpha, color), vdp1cor, vdp1cog,
1623
vdp1cob);
1624
}
1625
else {
1626
hdr->argb = COLOR_ADD32(Vdp2ColorRamGetColor32(color, alpha), vdp1cor,
1627
vdp1cog, vdp1cob);
1628
}
1629
1630
pvr_list_prim(list, hdr, sizeof(pvr_sprite_hdr_t));
1631
1632
z = Vdp2Regs->PRISA & 0x07;
1633
1634
spr.flags = PVR_CMD_VERTEX_EOL;
1635
spr.d1 = spr.d2 = spr.d3 = spr.d4 = 0;
1636
spr.az = spr.bz = spr.cz = priority_levels[z];
1637
1638
spr.ax = X[0];
1639
spr.ay = Y[0];
1640
spr.bx = X[1];
1641
spr.by = Y[1];
1642
spr.cx = X[2];
1643
spr.cy = Y[2];
1644
spr.dx = X[3];
1645
spr.dy = Y[3];
1646
1647
pvr_list_prim(list, &spr, sizeof(pvr_sprite_col_t));
1648
1649
priority_levels[z] += 0.000001f;
1650
}
1651
1652
static void VIDDCVdp1PolylineDraw(void) {
1653
}
1654
1655
static void VIDDCVdp1LineDraw(void) {
1656
}
1657
1658
static void VIDDCVdp1UserClipping(void) {
1659
Vdp1Regs->userclipX1 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x0C);
1660
Vdp1Regs->userclipY1 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x0E);
1661
Vdp1Regs->userclipX2 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x14);
1662
Vdp1Regs->userclipY2 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x16);
1663
}
1664
1665
static void VIDDCVdp1SystemClipping(void) {
1666
Vdp1Regs->systemclipX1 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x0C);
1667
Vdp1Regs->systemclipY1 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x0E);
1668
Vdp1Regs->systemclipX2 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x14);
1669
Vdp1Regs->systemclipY2 = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x16);
1670
}
1671
1672
static void VIDDCVdp1LocalCoordinate(void) {
1673
Vdp1Regs->localX = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x0C);
1674
Vdp1Regs->localY = T1ReadWord(Vdp1Ram, Vdp1Regs->addr + 0x0E);
1675
}
1676
1677
//////////////////////////////////////////////////////////////////////////////
1678
1679
static u16 DoNothing(void *info, u16 pixel)
1680
{
1681
return pixel;
1682
}
1683
1684
//////////////////////////////////////////////////////////////////////////////
1685
1686
static u16 DoColorOffset(void *info, u16 pixel)
1687
{
1688
return COLOR_ADD(pixel, ((vdp2draw_struct *)info)->cor,
1689
((vdp2draw_struct *)info)->cog,
1690
((vdp2draw_struct *)info)->cob);
1691
}
1692
1693
//////////////////////////////////////////////////////////////////////////////
1694
1695
static u16 DoColorCalc(void *info, u16 pixel)
1696
{
1697
// should be doing color calculation here
1698
return pixel;
1699
}
1700
1701
//////////////////////////////////////////////////////////////////////////////
1702
1703
static u16 DoColorCalcWithColorOffset(void *info, u16 pixel)
1704
{
1705
// should be doing color calculation here
1706
1707
return COLOR_ADD(pixel, ((vdp2draw_struct *)info)->cor,
1708
((vdp2draw_struct *)info)->cog,
1709
((vdp2draw_struct *)info)->cob);
1710
}
1711
1712
static void Vdp2DrawBackScreen() {
1713
u32 scrAddr;
1714
u16 dot;
1715
pvr_sprite_col_t spr;
1716
1717
if(Vdp2Regs->VRSIZE & 0x8000)
1718
scrAddr = (((Vdp2Regs->BKTAU & 0x07) << 16) | Vdp2Regs->BKTAL) << 1;
1719
else
1720
scrAddr = (((Vdp2Regs->BKTAU & 0x03) << 16) | Vdp2Regs->BKTAL) << 1;
1721
1722
if(Vdp2Regs->BKTAU & 0x8000) {
1723
int i;
1724
1725
for(i = 0; i < vdp2height; ++i) {
1726
dot = T1ReadWord(Vdp2Ram, scrAddr);
1727
scrAddr += 2;
1728
1729
op_poly_hdr.argb = SAT2YAB32(0xFF, dot);
1730
pvr_list_prim(PVR_LIST_OP_POLY, &op_poly_hdr,
1731
sizeof(pvr_sprite_hdr_t));
1732
1733
spr.flags = PVR_CMD_VERTEX_EOL;
1734
spr.ax = 0.0f;
1735
spr.ay = i + 1;
1736
spr.az = 0.1f;
1737
spr.bx = 0.0f;
1738
spr.by = i;
1739
spr.bz = 0.1f;
1740
spr.cx = vdp2width;
1741
spr.cy = i;
1742
spr.cz = 0.1f;
1743
spr.dx = vdp2width;
1744
spr.dy = i + 1;
1745
spr.d1 = spr.d2 = spr.d3 = spr.d4 = 0;
1746
pvr_list_prim(PVR_LIST_OP_POLY, &spr, sizeof(pvr_sprite_col_t));
1747
}
1748
}
1749
else {
1750
dot = T1ReadWord(Vdp2Ram, scrAddr);
1751
1752
op_poly_hdr.argb = SAT2YAB32(0xFF, dot);
1753
pvr_list_prim(PVR_LIST_OP_POLY, &op_poly_hdr, sizeof(pvr_sprite_hdr_t));
1754
1755
spr.flags = PVR_CMD_VERTEX_EOL;
1756
spr.ax = 0.0f;
1757
spr.ay = vdp2height;
1758
spr.az = 0.1f;
1759
spr.bx = 0.0f;
1760
spr.by = 0.0f;
1761
spr.bz = 0.1f;
1762
spr.cx = vdp2width;
1763
spr.cy = 0.0f;
1764
spr.cz = 0.1f;
1765
spr.dx = vdp2width;
1766
spr.dy = vdp2height;
1767
spr.d1 = spr.d2 = spr.d3 = spr.d4 = 0;
1768
pvr_list_prim(PVR_LIST_OP_POLY, &spr, sizeof(pvr_sprite_col_t));
1769
}
1770
}
1771
1772
static void Vdp2DrawLineColorScreen() {
1773
}
1774
1775
//////////////////////////////////////////////////////////////////////////////
1776
1777
static void Vdp2NBG0PlaneAddr(vdp2draw_struct *info, int i)
1778
{
1779
u32 offset = (Vdp2Regs->MPOFN & 0x7) << 6;
1780
u32 tmp=0;
1781
int deca;
1782
int multi;
1783
1784
switch(i)
1785
{
1786
case 0:
1787
tmp = offset | (Vdp2Regs->MPABN0 & 0xFF);
1788
break;
1789
case 1:
1790
tmp = offset | (Vdp2Regs->MPABN0 >> 8);
1791
break;
1792
case 2:
1793
tmp = offset | (Vdp2Regs->MPCDN0 & 0xFF);
1794
break;
1795
case 3:
1796
tmp = offset | (Vdp2Regs->MPCDN0 >> 8);
1797
break;
1798
}
1799
1800
deca = info->planeh + info->planew - 2;
1801
multi = info->planeh * info->planew;
1802
1803
//if (Vdp2Regs->VRSIZE & 0x8000)
1804
//{
1805
if (info->patterndatasize == 1)
1806
{
1807
if (info->patternwh == 1)
1808
info->addr = ((tmp & 0x3F) >> deca) * (multi * 0x2000);
1809
else
1810
info->addr = (tmp >> deca) * (multi * 0x800);
1811
}
1812
else
1813
{
1814
if (info->patternwh == 1)
1815
info->addr = ((tmp & 0x1F) >> deca) * (multi * 0x4000);
1816
else
1817
info->addr = ((tmp & 0x7F) >> deca) * (multi * 0x1000);
1818
}
1819
/*}
1820
else
1821
{
1822
if (info->patterndatasize == 1)
1823
{
1824
if (info->patternwh == 1)
1825
info->addr = ((tmp & 0x1F) >> deca) * (multi * 0x2000);
1826
else
1827
info->addr = ((tmp & 0x7F) >> deca) * (multi * 0x800);
1828
}
1829
else
1830
{
1831
if (info->patternwh == 1)
1832
info->addr = ((tmp & 0xF) >> deca) * (multi * 0x4000);
1833
else
1834
info->addr = ((tmp & 0x3F) >> deca) * (multi * 0x1000);
1835
}
1836
}*/
1837
}
1838
1839
//////////////////////////////////////////////////////////////////////////////
1840
1841
static int Vdp2DrawNBG0(void)
1842
{
1843
vdp2draw_struct info;
1844
1845
/* FIXME should start by checking if it's a normal
1846
* or rotate scroll screen
1847
*/
1848
info.enable = Vdp2Regs->BGON & 0x1;
1849
1850
if (!(info.enable & Vdp2External.disptoggle))
1851
return 0;
1852
1853
info.transparencyenable = !(Vdp2Regs->BGON & 0x100);
1854
info.specialprimode = Vdp2Regs->SFPRMD & 0x3;
1855
1856
info.colornumber = (Vdp2Regs->CHCTLA & 0x70) >> 4;
1857
1858
if((info.isbitmap = Vdp2Regs->CHCTLA & 0x2) != 0)
1859
{
1860
// Bitmap Mode
1861
1862
switch((Vdp2Regs->CHCTLA & 0xC) >> 2)
1863
{
1864
case 0: info.cellw = 512;
1865
info.cellh = 256;
1866
break;
1867
case 1: info.cellw = 512;
1868
info.cellh = 512;
1869
break;
1870
case 2: info.cellw = 1024;
1871
info.cellh = 256;
1872
break;
1873
case 3: info.cellw = 1024;
1874
info.cellh = 512;
1875
break;
1876
}
1877
1878
info.x = - ((Vdp2Regs->SCXIN0 & 0x7FF) % info.cellw);
1879
info.y = - ((Vdp2Regs->SCYIN0 & 0x7FF) % info.cellh);
1880
1881
info.charaddr = (Vdp2Regs->MPOFN & 0x7) * 0x20000;
1882
info.paladdr = (Vdp2Regs->BMPNA & 0x7) << 8;
1883
info.flipfunction = 0;
1884
info.specialfunction = 0;
1885
}
1886
else
1887
{
1888
// Tile Mode
1889
info.mapwh = 2;
1890
1891
switch(Vdp2Regs->PLSZ & 0x3)
1892
{
1893
case 0:
1894
info.planew = info.planeh = 1;
1895
break;
1896
case 1:
1897
info.planew = 2;
1898
info.planeh = 1;
1899
break;
1900
case 3:
1901
info.planew = info.planeh = 2;
1902
break;
1903
default: // Not sure what 0x2 does
1904
info.planew = info.planeh = 1;
1905
break;
1906
}
1907
1908
info.x = - ((Vdp2Regs->SCXIN0 & 0x7FF) % (512 * info.planew));
1909
info.y = - ((Vdp2Regs->SCYIN0 & 0x7FF) % (512 * info.planeh));
1910
1911
if(Vdp2Regs->PNCN0 & 0x8000)
1912
info.patterndatasize = 1;
1913
else
1914
info.patterndatasize = 2;
1915
1916
if(Vdp2Regs->CHCTLA & 0x1)
1917
info.patternwh = 2;
1918
else
1919
info.patternwh = 1;
1920
1921
info.pagewh = 64/info.patternwh;
1922
info.cellw = info.cellh = 8;
1923
info.supplementdata = Vdp2Regs->PNCN0 & 0x3FF;
1924
info.auxmode = (Vdp2Regs->PNCN0 & 0x4000) >> 14;
1925
}
1926
1927
if (Vdp2Regs->CCCTL & 0x1)
1928
info.alpha = ((~Vdp2Regs->CCRNA & 0x1F) << 3) + 0x7;
1929
else
1930
info.alpha = 0xFF;
1931
1932
info.coloroffset = (Vdp2Regs->CRAOFA & 0x7) << 8;
1933
1934
if (Vdp2Regs->CLOFEN & 0x1)
1935
{
1936
// color offset enable
1937
if (Vdp2Regs->CLOFSL & 0x1)
1938
{
1939
// color offset B
1940
info.cor = Vdp2Regs->COBR & 0xFF;
1941
if (Vdp2Regs->COBR & 0x100)
1942
info.cor |= 0xFFFFFF00;
1943
1944
info.cog = Vdp2Regs->COBG & 0xFF;
1945
if (Vdp2Regs->COBG & 0x100)
1946
info.cog |= 0xFFFFFF00;
1947
1948
info.cob = Vdp2Regs->COBB & 0xFF;
1949
if (Vdp2Regs->COBB & 0x100)
1950
info.cob |= 0xFFFFFF00;
1951
}
1952
else
1953
{
1954
// color offset A
1955
info.cor = Vdp2Regs->COAR & 0xFF;
1956
if (Vdp2Regs->COAR & 0x100)
1957
info.cor |= 0xFFFFFF00;
1958
1959
info.cog = Vdp2Regs->COAG & 0xFF;
1960
if (Vdp2Regs->COAG & 0x100)
1961
info.cog |= 0xFFFFFF00;
1962
1963
info.cob = Vdp2Regs->COAB & 0xFF;
1964
if (Vdp2Regs->COAB & 0x100)
1965
info.cob |= 0xFFFFFF00;
1966
}
1967
1968
if (Vdp2Regs->CCCTL & 0x1)
1969
info.PostPixelFetchCalc = &DoColorCalcWithColorOffset;
1970
else
1971
info.PostPixelFetchCalc = &DoColorOffset;
1972
}
1973
else // color offset disable
1974
{
1975
if (Vdp2Regs->CCCTL & 0x1)
1976
info.PostPixelFetchCalc = &DoColorCalc;
1977
else
1978
info.PostPixelFetchCalc = &DoNothing;
1979
}
1980
1981
info.coordincx = (float) 65536 / (Vdp2Regs->ZMXN0.all & 0x7FF00);
1982
info.coordincy = (float) 65536 / (Vdp2Regs->ZMYN0.all & 0x7FF00);
1983
1984
info.priority = nbg0priority;
1985
info.PlaneAddr = (void (*)(void *, int))&Vdp2NBG0PlaneAddr;
1986
1987
if (info.isbitmap)
1988
Vdp2DrawScrollBitmap(&info);
1989
else
1990
Vdp2DrawMap(&info);
1991
1992
return 1;
1993
}
1994
1995
//////////////////////////////////////////////////////////////////////////////
1996
1997
static void Vdp2NBG1PlaneAddr(vdp2draw_struct *info, int i)
1998
{
1999
u32 offset = (Vdp2Regs->MPOFN & 0x70) << 2;
2000
u32 tmp=0;
2001
int deca;
2002
int multi;
2003
2004
switch(i)
2005
{
2006
case 0:
2007
tmp = offset | (Vdp2Regs->MPABN1 & 0xFF);
2008
break;
2009
case 1:
2010
tmp = offset | (Vdp2Regs->MPABN1 >> 8);
2011
break;
2012
case 2:
2013
tmp = offset | (Vdp2Regs->MPCDN1 & 0xFF);
2014
break;
2015
case 3:
2016
tmp = offset | (Vdp2Regs->MPCDN1 >> 8);
2017
break;
2018
}
2019
2020
deca = info->planeh + info->planew - 2;
2021
multi = info->planeh * info->planew;
2022
2023
//if (Vdp2Regs->VRSIZE & 0x8000)
2024
//{
2025
if (info->patterndatasize == 1)
2026
{
2027
if (info->patternwh == 1)
2028
info->addr = ((tmp & 0x3F) >> deca) * (multi * 0x2000);
2029
else
2030
info->addr = (tmp >> deca) * (multi * 0x800);
2031
}
2032
else
2033
{
2034
if (info->patternwh == 1)
2035
info->addr = ((tmp & 0x1F) >> deca) * (multi * 0x4000);
2036
else
2037
info->addr = ((tmp & 0x7F) >> deca) * (multi * 0x1000);
2038
}
2039
/*}
2040
else
2041
{
2042
if (info->patterndatasize == 1)
2043
{
2044
if (info->patternwh == 1)
2045
info->addr = ((tmp & 0x1F) >> deca) * (multi * 0x2000);
2046
else
2047
info->addr = ((tmp & 0x7F) >> deca) * (multi * 0x800);
2048
}
2049
else
2050
{
2051
if (info->patternwh == 1)
2052
info->addr = ((tmp & 0xF) >> deca) * (multi * 0x4000);
2053
else
2054
info->addr = ((tmp & 0x3F) >> deca) * (multi * 0x1000);
2055
}
2056
}*/
2057
}
2058
2059
//////////////////////////////////////////////////////////////////////////////
2060
2061
static int Vdp2DrawNBG1(void)
2062
{
2063
vdp2draw_struct info;
2064
2065
info.enable = Vdp2Regs->BGON & 0x2;
2066
2067
if (!(info.enable & Vdp2External.disptoggle))
2068
return 0;
2069
2070
info.transparencyenable = !(Vdp2Regs->BGON & 0x200);
2071
info.specialprimode = (Vdp2Regs->SFPRMD >> 2) & 0x3;
2072
2073
info.colornumber = (Vdp2Regs->CHCTLA & 0x3000) >> 12;
2074
2075
if((info.isbitmap = Vdp2Regs->CHCTLA & 0x200) != 0)
2076
{
2077
switch((Vdp2Regs->CHCTLA & 0xC00) >> 10)
2078
{
2079
case 0: info.cellw = 512;
2080
info.cellh = 256;
2081
break;
2082
case 1: info.cellw = 512;
2083
info.cellh = 512;
2084
break;
2085
case 2: info.cellw = 1024;
2086
info.cellh = 256;
2087
break;
2088
case 3: info.cellw = 1024;
2089
info.cellh = 512;
2090
break;
2091
}
2092
2093
info.x = - ((Vdp2Regs->SCXIN1 & 0x7FF) % info.cellw);
2094
info.y = - ((Vdp2Regs->SCYIN1 & 0x7FF) % info.cellh);
2095
2096
info.charaddr = ((Vdp2Regs->MPOFN & 0x70) >> 4) * 0x20000;
2097
info.paladdr = Vdp2Regs->BMPNA & 0x700;
2098
info.flipfunction = 0;
2099
info.specialfunction = 0;
2100
}
2101
else
2102
{
2103
info.mapwh = 2;
2104
2105
switch((Vdp2Regs->PLSZ & 0xC) >> 2)
2106
{
2107
case 0:
2108
info.planew = info.planeh = 1;
2109
break;
2110
case 1:
2111
info.planew = 2;
2112
info.planeh = 1;
2113
break;
2114
case 3:
2115
info.planew = info.planeh = 2;
2116
break;
2117
default: // Not sure what 0x2 does
2118
info.planew = info.planeh = 1;
2119
break;
2120
}
2121
2122
info.x = - ((Vdp2Regs->SCXIN1 & 0x7FF) % (512 * info.planew));
2123
info.y = - ((Vdp2Regs->SCYIN1 & 0x7FF) % (512 * info.planeh));
2124
2125
if(Vdp2Regs->PNCN1 & 0x8000)
2126
info.patterndatasize = 1;
2127
else
2128
info.patterndatasize = 2;
2129
2130
if(Vdp2Regs->CHCTLA & 0x100)
2131
info.patternwh = 2;
2132
else
2133
info.patternwh = 1;
2134
2135
info.pagewh = 64/info.patternwh;
2136
info.cellw = info.cellh = 8;
2137
info.supplementdata = Vdp2Regs->PNCN1 & 0x3FF;
2138
info.auxmode = (Vdp2Regs->PNCN1 & 0x4000) >> 14;
2139
}
2140
2141
if (Vdp2Regs->CCCTL & 0x2)
2142
info.alpha = ((~Vdp2Regs->CCRNA & 0x1F00) >> 5) + 0x7;
2143
else
2144
info.alpha = 0xFF;
2145
2146
info.coloroffset = (Vdp2Regs->CRAOFA & 0x70) << 4;
2147
2148
if (Vdp2Regs->CLOFEN & 0x2)
2149
{
2150
// color offset enable
2151
if (Vdp2Regs->CLOFSL & 0x2)
2152
{
2153
// color offset B
2154
info.cor = Vdp2Regs->COBR & 0xFF;
2155
if (Vdp2Regs->COBR & 0x100)
2156
info.cor |= 0xFFFFFF00;
2157
2158
info.cog = Vdp2Regs->COBG & 0xFF;
2159
if (Vdp2Regs->COBG & 0x100)
2160
info.cog |= 0xFFFFFF00;
2161
2162
info.cob = Vdp2Regs->COBB & 0xFF;
2163
if (Vdp2Regs->COBB & 0x100)
2164
info.cob |= 0xFFFFFF00;
2165
}
2166
else
2167
{
2168
// color offset A
2169
info.cor = Vdp2Regs->COAR & 0xFF;
2170
if (Vdp2Regs->COAR & 0x100)
2171
info.cor |= 0xFFFFFF00;
2172
2173
info.cog = Vdp2Regs->COAG & 0xFF;
2174
if (Vdp2Regs->COAG & 0x100)
2175
info.cog |= 0xFFFFFF00;
2176
2177
info.cob = Vdp2Regs->COAB & 0xFF;
2178
if (Vdp2Regs->COAB & 0x100)
2179
info.cob |= 0xFFFFFF00;
2180
}
2181
2182
if (Vdp2Regs->CCCTL & 0x2)
2183
info.PostPixelFetchCalc = &DoColorCalcWithColorOffset;
2184
else
2185
info.PostPixelFetchCalc = &DoColorOffset;
2186
}
2187
else // color offset disable
2188
{
2189
if (Vdp2Regs->CCCTL & 0x2)
2190
info.PostPixelFetchCalc = &DoColorCalc;
2191
else
2192
info.PostPixelFetchCalc = &DoNothing;
2193
}
2194
2195
info.coordincx = (float) 65536 / (Vdp2Regs->ZMXN1.all & 0x7FF00);
2196
info.coordincy = (float) 65536 / (Vdp2Regs->ZMXN1.all & 0x7FF00);
2197
2198
info.priority = nbg1priority;
2199
info.PlaneAddr = (void (*)(void *, int))&Vdp2NBG1PlaneAddr;
2200
2201
if (info.isbitmap)
2202
{
2203
Vdp2DrawScrollBitmap(&info);
2204
/*
2205
// Handle Scroll Wrapping(Let's see if we even need do to it to begin
2206
// with)
2207
if (info.x < (vdp2width - info.cellw))
2208
{
2209
info.vertices[0] = (info.x+info.cellw) * info.coordincx;
2210
info.vertices[2] = (info.x + (info.cellw<<1)) * info.coordincx;
2211
info.vertices[4] = (info.x + (info.cellw<<1)) * info.coordincx;
2212
info.vertices[6] = (info.x+info.cellw) * info.coordincx;
2213
2214
YglCachedQuad((YglSprite *)&info, tmp);
2215
2216
if (info.y < (vdp2height - info.cellh))
2217
{
2218
info.vertices[1] = (info.y+info.cellh) * info.coordincy;
2219
info.vertices[3] = (info.y + (info.cellh<<1)) * info.coordincy;
2220
info.vertices[5] = (info.y + (info.cellh<<1)) * info.coordincy;
2221
info.vertices[7] = (info.y+info.cellh) * info.coordincy;
2222
2223
YglCachedQuad((YglSprite *)&info, tmp);
2224
}
2225
}
2226
else if (info.y < (vdp2height - info.cellh))
2227
{
2228
info.vertices[1] = (info.y+info.cellh) * info.coordincy;
2229
info.vertices[3] = (info.y + (info.cellh<<1)) * info.coordincy;
2230
info.vertices[5] = (info.y + (info.cellh<<1)) * info.coordincy;
2231
info.vertices[7] = (info.y+info.cellh) * info.coordincy;
2232
2233
YglCachedQuad((YglSprite *)&info, tmp);
2234
}
2235
*/
2236
}
2237
else
2238
Vdp2DrawMap(&info);
2239
2240
return 1;
2241
}
2242
2243
//////////////////////////////////////////////////////////////////////////////
2244
2245
static void Vdp2NBG2PlaneAddr(vdp2draw_struct *info, int i)
2246
{
2247
u32 offset = (Vdp2Regs->MPOFN & 0x700) >> 2;
2248
u32 tmp=0;
2249
int deca;
2250
int multi;
2251
2252
switch(i)
2253
{
2254
case 0:
2255
tmp = offset | (Vdp2Regs->MPABN2 & 0xFF);
2256
break;
2257
case 1:
2258
tmp = offset | (Vdp2Regs->MPABN2 >> 8);
2259
break;
2260
case 2:
2261
tmp = offset | (Vdp2Regs->MPCDN2 & 0xFF);
2262
break;
2263
case 3:
2264
tmp = offset | (Vdp2Regs->MPCDN2 >> 8);
2265
break;
2266
}
2267
2268
deca = info->planeh + info->planew - 2;
2269
multi = info->planeh * info->planew;
2270
2271
//if (Vdp2Regs->VRSIZE & 0x8000)
2272
//{
2273
if (info->patterndatasize == 1)
2274
{
2275
if (info->patternwh == 1)
2276
info->addr = ((tmp & 0x3F) >> deca) * (multi * 0x2000);
2277
else
2278
info->addr = (tmp >> deca) * (multi * 0x800);
2279
}
2280
else
2281
{
2282
if (info->patternwh == 1)
2283
info->addr = ((tmp & 0x1F) >> deca) * (multi * 0x4000);
2284
else
2285
info->addr = ((tmp & 0x7F) >> deca) * (multi * 0x1000);
2286
}
2287
/*}
2288
else
2289
{
2290
if (info->patterndatasize == 1)
2291
{
2292
if (info->patternwh == 1)
2293
info->addr = ((tmp & 0x1F) >> deca) * (multi * 0x2000);
2294
else
2295
info->addr = ((tmp & 0x7F) >> deca) * (multi * 0x800);
2296
}
2297
else
2298
{
2299
if (info->patternwh == 1)
2300
info->addr = ((tmp & 0xF) >> deca) * (multi * 0x4000);
2301
else
2302
info->addr = ((tmp & 0x3F) >> deca) * (multi * 0x1000);
2303
}
2304
}*/
2305
}
2306
2307
//////////////////////////////////////////////////////////////////////////////
2308
2309
static int Vdp2DrawNBG2(void)
2310
{
2311
vdp2draw_struct info;
2312
2313
info.enable = Vdp2Regs->BGON & 0x4;
2314
2315
if (!(info.enable & Vdp2External.disptoggle))
2316
return 0;
2317
2318
info.transparencyenable = !(Vdp2Regs->BGON & 0x400);
2319
info.specialprimode = (Vdp2Regs->SFPRMD >> 4) & 0x3;
2320
2321
info.colornumber = (Vdp2Regs->CHCTLB & 0x2) >> 1;
2322
info.mapwh = 2;
2323
2324
switch((Vdp2Regs->PLSZ & 0x30) >> 4)
2325
{
2326
case 0:
2327
info.planew = info.planeh = 1;
2328
break;
2329
case 1:
2330
info.planew = 2;
2331
info.planeh = 1;
2332
break;
2333
case 3:
2334
info.planew = info.planeh = 2;
2335
break;
2336
default: // Not sure what 0x2 does
2337
info.planew = info.planeh = 1;
2338
break;
2339
}
2340
info.x = - ((Vdp2Regs->SCXN2 & 0x7FF) % (512 * info.planew));
2341
info.y = - ((Vdp2Regs->SCYN2 & 0x7FF) % (512 * info.planeh));
2342
2343
if(Vdp2Regs->PNCN2 & 0x8000)
2344
info.patterndatasize = 1;
2345
else
2346
info.patterndatasize = 2;
2347
2348
if(Vdp2Regs->CHCTLB & 0x1)
2349
info.patternwh = 2;
2350
else
2351
info.patternwh = 1;
2352
2353
info.pagewh = 64/info.patternwh;
2354
info.cellw = info.cellh = 8;
2355
info.supplementdata = Vdp2Regs->PNCN2 & 0x3FF;
2356
info.auxmode = (Vdp2Regs->PNCN2 & 0x4000) >> 14;
2357
2358
if (Vdp2Regs->CCCTL & 0x4)
2359
info.alpha = ((~Vdp2Regs->CCRNB & 0x1F) << 3) + 0x7;
2360
else
2361
info.alpha = 0xFF;
2362
2363
info.coloroffset = Vdp2Regs->CRAOFA & 0x700;
2364
2365
if (Vdp2Regs->CLOFEN & 0x4)
2366
{
2367
// color offset enable
2368
if (Vdp2Regs->CLOFSL & 0x4)
2369
{
2370
// color offset B
2371
info.cor = Vdp2Regs->COBR & 0xFF;
2372
if (Vdp2Regs->COBR & 0x100)
2373
info.cor |= 0xFFFFFF00;
2374
2375
info.cog = Vdp2Regs->COBG & 0xFF;
2376
if (Vdp2Regs->COBG & 0x100)
2377
info.cog |= 0xFFFFFF00;
2378
2379
info.cob = Vdp2Regs->COBB & 0xFF;
2380
if (Vdp2Regs->COBB & 0x100)
2381
info.cob |= 0xFFFFFF00;
2382
}
2383
else
2384
{
2385
// color offset A
2386
info.cor = Vdp2Regs->COAR & 0xFF;
2387
if (Vdp2Regs->COAR & 0x100)
2388
info.cor |= 0xFFFFFF00;
2389
2390
info.cog = Vdp2Regs->COAG & 0xFF;
2391
if (Vdp2Regs->COAG & 0x100)
2392
info.cog |= 0xFFFFFF00;
2393
2394
info.cob = Vdp2Regs->COAB & 0xFF;
2395
if (Vdp2Regs->COAB & 0x100)
2396
info.cob |= 0xFFFFFF00;
2397
}
2398
2399
if (Vdp2Regs->CCCTL & 0x4)
2400
info.PostPixelFetchCalc = &DoColorCalcWithColorOffset;
2401
else
2402
info.PostPixelFetchCalc = &DoColorOffset;
2403
}
2404
else // color offset disable
2405
{
2406
if (Vdp2Regs->CCCTL & 0x4)
2407
info.PostPixelFetchCalc = &DoColorCalc;
2408
else
2409
info.PostPixelFetchCalc = &DoNothing;
2410
}
2411
2412
info.coordincx = info.coordincy = 1;
2413
2414
info.priority = nbg2priority;
2415
info.PlaneAddr = (void (*)(void *, int))&Vdp2NBG2PlaneAddr;
2416
2417
Vdp2DrawMap(&info);
2418
2419
return 1;
2420
}
2421
2422
//////////////////////////////////////////////////////////////////////////////
2423
2424
static void Vdp2NBG3PlaneAddr(vdp2draw_struct *info, int i)
2425
{
2426
u32 offset = (Vdp2Regs->MPOFN & 0x7000) >> 6;
2427
u32 tmp=0;
2428
int deca;
2429
int multi;
2430
2431
switch(i)
2432
{
2433
case 0:
2434
tmp = offset | (Vdp2Regs->MPABN3 & 0xFF);
2435
break;
2436
case 1:
2437
tmp = offset | (Vdp2Regs->MPABN3 >> 8);
2438
break;
2439
case 2:
2440
tmp = offset | (Vdp2Regs->MPCDN3 & 0xFF);
2441
break;
2442
case 3:
2443
tmp = offset | (Vdp2Regs->MPCDN3 >> 8);
2444
break;
2445
}
2446
2447
deca = info->planeh + info->planew - 2;
2448
multi = info->planeh * info->planew;
2449
2450
//if (Vdp2Regs->VRSIZE & 0x8000) {
2451
if (info->patterndatasize == 1) {
2452
if (info->patternwh == 1)
2453
info->addr = ((tmp & 0x3F) >> deca) * (multi * 0x2000);
2454
else
2455
info->addr = (tmp >> deca) * (multi * 0x800);
2456
}
2457
else {
2458
if (info->patternwh == 1)
2459
info->addr = ((tmp & 0x1F) >> deca) * (multi * 0x4000);
2460
else
2461
info->addr = ((tmp & 0x7F) >> deca) * (multi * 0x1000);
2462
}
2463
/*}
2464
else {
2465
if (info->patterndatasize == 1) {
2466
if (info->patternwh == 1)
2467
info->addr = ((tmp & 0x1F) >> deca) * (multi * 0x2000);
2468
else
2469
info->addr = ((tmp & 0x7F) >> deca) * (multi * 0x800);
2470
}
2471
else {
2472
if (info->patternwh == 1)
2473
info->addr = ((tmp & 0xF) >> deca) * (multi * 0x4000);
2474
else
2475
info->addr = ((tmp & 0x3F) >> deca) * (multi * 0x1000);
2476
}
2477
}*/
2478
}
2479
2480
//////////////////////////////////////////////////////////////////////////////
2481
2482
static int Vdp2DrawNBG3(void)
2483
{
2484
vdp2draw_struct info;
2485
2486
info.enable = Vdp2Regs->BGON & 0x8;
2487
2488
if (!(info.enable & Vdp2External.disptoggle))
2489
return 0;
2490
2491
info.transparencyenable = !(Vdp2Regs->BGON & 0x800);
2492
info.specialprimode = (Vdp2Regs->SFPRMD >> 6) & 0x3;
2493
2494
info.colornumber = (Vdp2Regs->CHCTLB & 0x20) >> 5;
2495
2496
info.mapwh = 2;
2497
2498
switch((Vdp2Regs->PLSZ & 0xC0) >> 6)
2499
{
2500
case 0:
2501
info.planew = info.planeh = 1;
2502
break;
2503
case 1:
2504
info.planew = 2;
2505
info.planeh = 1;
2506
break;
2507
case 3:
2508
info.planew = info.planeh = 2;
2509
break;
2510
default: // Not sure what 0x2 does
2511
info.planew = info.planeh = 1;
2512
break;
2513
}
2514
info.x = - ((Vdp2Regs->SCXN3 & 0x7FF) % (512 * info.planew));
2515
info.y = - ((Vdp2Regs->SCYN3 & 0x7FF) % (512 * info.planeh));
2516
2517
if(Vdp2Regs->PNCN3 & 0x8000)
2518
info.patterndatasize = 1;
2519
else
2520
info.patterndatasize = 2;
2521
2522
if(Vdp2Regs->CHCTLB & 0x10)
2523
info.patternwh = 2;
2524
else
2525
info.patternwh = 1;
2526
2527
info.pagewh = 64/info.patternwh;
2528
info.cellw = info.cellh = 8;
2529
info.supplementdata = Vdp2Regs->PNCN3 & 0x3FF;
2530
info.auxmode = (Vdp2Regs->PNCN3 & 0x4000) >> 14;
2531
2532
if (Vdp2Regs->CCCTL & 0x8)
2533
info.alpha = ((~Vdp2Regs->CCRNB & 0x1F00) >> 5) + 0x7;
2534
else
2535
info.alpha = 0xFF;
2536
2537
info.coloroffset = (Vdp2Regs->CRAOFA & 0x7000) >> 4;
2538
2539
if (Vdp2Regs->CLOFEN & 0x8)
2540
{
2541
// color offset enable
2542
if (Vdp2Regs->CLOFSL & 0x8)
2543
{
2544
// color offset B
2545
info.cor = Vdp2Regs->COBR & 0xFF;
2546
if (Vdp2Regs->COBR & 0x100)
2547
info.cor |= 0xFFFFFF00;
2548
2549
info.cog = Vdp2Regs->COBG & 0xFF;
2550
if (Vdp2Regs->COBG & 0x100)
2551
info.cog |= 0xFFFFFF00;
2552
2553
info.cob = Vdp2Regs->COBB & 0xFF;
2554
if (Vdp2Regs->COBB & 0x100)
2555
info.cob |= 0xFFFFFF00;
2556
}
2557
else
2558
{
2559
// color offset A
2560
info.cor = Vdp2Regs->COAR & 0xFF;
2561
if (Vdp2Regs->COAR & 0x100)
2562
info.cor |= 0xFFFFFF00;
2563
2564
info.cog = Vdp2Regs->COAG & 0xFF;
2565
if (Vdp2Regs->COAG & 0x100)
2566
info.cog |= 0xFFFFFF00;
2567
2568
info.cob = Vdp2Regs->COAB & 0xFF;
2569
if (Vdp2Regs->COAB & 0x100)
2570
info.cob |= 0xFFFFFF00;
2571
}
2572
2573
if (Vdp2Regs->CCCTL & 0x8)
2574
info.PostPixelFetchCalc = &DoColorCalcWithColorOffset;
2575
else
2576
info.PostPixelFetchCalc = &DoColorOffset;
2577
}
2578
else // color offset disable
2579
{
2580
if (Vdp2Regs->CCCTL & 0x8)
2581
info.PostPixelFetchCalc = &DoColorCalc;
2582
else
2583
info.PostPixelFetchCalc = &DoNothing;
2584
}
2585
2586
info.coordincx = info.coordincy = 1;
2587
2588
info.priority = nbg3priority;
2589
info.PlaneAddr = (void (*)(void *, int))&Vdp2NBG3PlaneAddr;
2590
2591
Vdp2DrawMap(&info);
2592
2593
return 1;
2594
}
2595
2596
static int VIDDCVdp2Reset(void) {
2597
return 0;
2598
}
2599
2600
static void VIDDCVdp2DrawStart(void) {
2601
cur_addr = (uint32) tex_space;
2602
cur_vdp2 = (uint32) vdp2_tex;
2603
2604
pvr_wait_ready();
2605
pvr_scene_begin();
2606
2607
Vdp2DrawBackScreen();
2608
Vdp2DrawLineColorScreen();
2609
}
2610
2611
static void VIDDCVdp2DrawEnd(void) {
2612
/* Make sure we don't have any texture dma still going on... */
2613
sem_wait(dmadone);
2614
sem_signal(dmadone);
2615
2616
pvr_scene_finish();
2617
2618
++framecount;
2619
2620
if(lastup + 10 <= time(NULL)) {
2621
printf("%d frames in %d seconds FPS: %f\n", framecount, time(NULL) -
2622
lastup, ((float)(framecount)) / (time(NULL) - lastup));
2623
framecount = 0;
2624
lastup = time(NULL);
2625
}
2626
}
2627
2628
static void dma_callback(ptr_t data __attribute__((unused))) {
2629
sem_signal(dmadone);
2630
}
2631
2632
static void Vdp2Draw(int priority) {
2633
pvr_sprite_txr_t sprite;
2634
2635
pt_sprite_hdr.mode2 &= (~(PVR_TA_PM2_USIZE_MASK | PVR_TA_PM2_VSIZE_MASK));
2636
pt_sprite_hdr.mode2 |= (6 << PVR_TA_PM2_USIZE_SHIFT) |
2637
(5 << PVR_TA_PM2_VSIZE_SHIFT);
2638
pt_sprite_hdr.mode3 = ((cur_vdp2 & 0x00FFFFF8) >> 3) |
2639
(PVR_TXRFMT_NONTWIDDLED);
2640
2641
pvr_list_prim(PVR_LIST_PT_POLY, &pt_sprite_hdr, sizeof(pvr_sprite_hdr_t));
2642
2643
sprite.flags = PVR_CMD_VERTEX_EOL;
2644
sprite.ax = 0;
2645
sprite.ay = 0;
2646
sprite.az = priority_levels[priority];
2647
2648
sprite.bx = vdp2width;
2649
sprite.by = 0;
2650
sprite.bz = priority_levels[priority];
2651
2652
sprite.cx = vdp2width;
2653
sprite.cy = vdp2height;
2654
sprite.cz = priority_levels[priority];
2655
2656
sprite.dx = 0;
2657
sprite.dy = vdp2height;
2658
2659
sprite.auv = PVR_PACK_16BIT_UV(0.0f, 0.0f);
2660
sprite.buv = PVR_PACK_16BIT_UV(vdp2width / 512.0f, 0.0f);
2661
sprite.cuv = PVR_PACK_16BIT_UV(vdp2width / 512.0f, vdp2height / 256.0f);
2662
pvr_list_prim(PVR_LIST_PT_POLY, &sprite, sizeof(pvr_sprite_txr_t));
2663
2664
priority_levels[priority] += 0.000001f;
2665
}
2666
2667
static void VIDDCVdp2DrawScreens(void) {
2668
int i;
2669
2670
vdp2_fb = vdp2_fbs[0];
2671
vdp2_fbnum = 0;
2672
2673
for(i = 1; i < 8; i++) {
2674
if(nbg3priority == i) {
2675
if(Vdp2DrawNBG3()) {
2676
dcache_flush_range((ptr_t)(vdp2_fb), 512 * 256 * 2);
2677
sem_wait(dmadone);
2678
2679
pvr_txr_load_dma(vdp2_fb, (pvr_ptr_t) cur_vdp2, 512 * 256 * 2,
2680
0, dma_callback, 0);
2681
2682
Vdp2Draw(i);
2683
2684
cur_vdp2 += 512 * 256 * 2;
2685
vdp2_fbnum ^= 1;
2686
vdp2_fb = vdp2_fbs[vdp2_fbnum];
2687
}
2688
}
2689
if(nbg2priority == i) {
2690
if(Vdp2DrawNBG2()) {
2691
dcache_flush_range((ptr_t)(vdp2_fb), 512 * 256 * 2);
2692
sem_wait(dmadone);
2693
2694
pvr_txr_load_dma(vdp2_fb, (pvr_ptr_t) cur_vdp2, 512 * 256 * 2,
2695
0, dma_callback, 0);
2696
2697
Vdp2Draw(i);
2698
2699
cur_vdp2 += 512 * 256 * 2;
2700
vdp2_fbnum ^= 1;
2701
vdp2_fb = vdp2_fbs[vdp2_fbnum];
2702
}
2703
}
2704
if(nbg1priority == i) {
2705
if(Vdp2DrawNBG1()) {
2706
dcache_flush_range((ptr_t)(vdp2_fb), 512 * 256 * 2);
2707
sem_wait(dmadone);
2708
2709
pvr_txr_load_dma(vdp2_fb, (pvr_ptr_t) cur_vdp2, 512 * 256 * 2,
2710
0, dma_callback, 0);
2711
2712
Vdp2Draw(i);
2713
2714
cur_vdp2 += 512 * 256 * 2;
2715
vdp2_fbnum ^= 1;
2716
vdp2_fb = vdp2_fbs[vdp2_fbnum];
2717
}
2718
}
2719
if(nbg0priority == i) {
2720
if(Vdp2DrawNBG0()) {
2721
dcache_flush_range((ptr_t)(vdp2_fb), 512 * 256 * 2);
2722
sem_wait(dmadone);
2723
2724
pvr_txr_load_dma(vdp2_fb, (pvr_ptr_t) cur_vdp2, 512 * 256 * 2,
2725
0, dma_callback, 0);
2726
2727
Vdp2Draw(i);
2728
2729
cur_vdp2 += 512 * 256 * 2;
2730
vdp2_fbnum ^= 1;
2731
vdp2_fb = vdp2_fbs[vdp2_fbnum];
2732
}
2733
}
2734
// if (rbg0priority == i)
2735
// Vdp2DrawRBG0();
2736
}
2737
}
2738
2739
static void VIDDCVdp2SetResolution(u16 TVMD) {
2740
int w = 0, h = 0;
2741
2742
switch(TVMD & 0x03) {
2743
case 0:
2744
w = 320;
2745
break;
2746
case 1:
2747
w = 352;
2748
break;
2749
case 2:
2750
w = 640;
2751
break;
2752
case 3:
2753
w = 704;
2754
break;
2755
}
2756
2757
switch((TVMD >> 4) & 0x03) {
2758
case 0:
2759
h = 224;
2760
break;
2761
case 1:
2762
h = 240;
2763
break;
2764
case 2:
2765
h = 256;
2766
break;
2767
}
2768
2769
switch((TVMD >> 6) & 0x03) {
2770
case 2:
2771
case 3:
2772
h <<= 1;
2773
default:
2774
break;
2775
}
2776
2777
vdp2width = w;
2778
vdp2height = h;
2779
2780
if(w > 352 || h > 256) {
2781
printf("Unsupported resolution set %d x %d\n", w, h);
2782
printf("Bailing out!\n");
2783
exit(-1);
2784
}
2785
}
2786
2787
static void VIDDCVdp2SetPriorityNBG0(int priority) {
2788
nbg0priority = priority;
2789
}
2790
2791
static void VIDDCVdp2SetPriorityNBG1(int priority) {
2792
nbg1priority = priority;
2793
}
2794
2795
static void VIDDCVdp2SetPriorityNBG2(int priority) {
2796
nbg2priority = priority;
2797
}
2798
2799
static void VIDDCVdp2SetPriorityNBG3(int priority) {
2800
nbg3priority = priority;
2801
}
2802
2803
static void VIDDCVdp2SetPriorityRBG0(int priority) {
2804
rbg0priority = priority;
2805
}
2806
2807
VideoInterface_struct VIDDC = {
2808
VIDCORE_DC,
2809
"Dreamcast PVR Video Interface",
2810
VIDDCInit,
2811
VIDDCDeInit,
2812
VIDDCResize,
2813
VIDDCIsFullscreen,
2814
VIDDCVdp1Reset,
2815
VIDDCVdp1DrawStart,
2816
VIDDCVdp1DrawEnd,
2817
VIDDCVdp1NormalSpriteDraw,
2818
VIDDCVdp1ScaledSpriteDraw,
2819
VIDDCVdp1DistortedSpriteDraw,
2820
VIDDCVdp1PolygonDraw,
2821
VIDDCVdp1PolylineDraw,
2822
VIDDCVdp1LineDraw,
2823
VIDDCVdp1UserClipping,
2824
VIDDCVdp1SystemClipping,
2825
VIDDCVdp1LocalCoordinate,
2826
VIDDCVdp2Reset,
2827
VIDDCVdp2DrawStart,
2828
VIDDCVdp2DrawEnd,
2829
VIDDCVdp2DrawScreens,
2830
VIDDCVdp2SetResolution,
2831
VIDDCVdp2SetPriorityNBG0,
2832
VIDDCVdp2SetPriorityNBG1,
2833
VIDDCVdp2SetPriorityNBG2,
2834
VIDDCVdp2SetPriorityNBG3,
2835
VIDDCVdp2SetPriorityRBG0
2836
};
2837
2838