Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-video-z64/src/rdp.cpp
2 views
1
/*
2
* z64
3
*
4
* Copyright (C) 2007 ziggy
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License along
17
* with this program; if not, write to the Free Software Foundation, Inc.,
18
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
*
20
**/
21
22
#include "rdp.h"
23
#include "rgl.h"
24
25
#include <string.h>
26
27
const char *rdpImageFormats[] =
28
{ "RGBA", "YUV", "CI", "IA", "I", "???", "???", "???" };
29
30
rdpState_t rdpState;
31
uint32_t rdpChanged;
32
//rdpColor_t rdpTlut[1024];
33
uint8_t rdpTmem[4*0x1000];
34
int rdpFbFormat;
35
int rdpFbSize;
36
int rdpFbWidth;
37
uint32_t rdpFbAddress;
38
uint32_t rdpZbAddress;
39
int rdpTiFormat;
40
int rdpTiSize;
41
int rdpTiWidth;
42
uint32_t rdpTiAddress;
43
rdpTile_t rdpTiles[8];
44
int rdpTileSet;
45
46
struct area_t {
47
int start, stop;
48
uint32_t from;
49
int fromLine, fromFormat, fromSize;
50
};
51
52
#define MAX_TMEM_AREAS 16
53
static area_t tmemAreas[MAX_TMEM_AREAS];
54
static int nbTmemAreas;
55
56
#ifdef RDP_DEBUG
57
int rdp_dump;
58
#endif
59
60
#define MAXCMD 0x100000
61
static uint32_t rdp_cmd_data[MAXCMD+44];
62
static volatile int rdp_cmd_ptr = 0;
63
static volatile int rdp_cmd_cur = 0;
64
static int rdp_cmd_left = 0;
65
66
#ifdef RDP_DEBUG
67
uint32_t rdpTraceBuf[0x100000];
68
int rdpTracePos;
69
#endif
70
71
72
static void MarkTmemArea(int start, int stop, uint32_t from, uint32_t fromLine,
73
int fromFormat, int fromSize)
74
{
75
int i;
76
77
// remove areas that intersect
78
for (i=0; i<nbTmemAreas; i++)
79
while (i<nbTmemAreas &&
80
tmemAreas[i].start<stop && tmemAreas[i].stop>start) {
81
memmove(tmemAreas+i, tmemAreas+i+1, nbTmemAreas-i-1);
82
nbTmemAreas--;
83
}
84
85
DUMP("marking tmem %x --> %x rdram %x\n", start, stop, from);
86
87
// add new area
88
//rglAssert(nbTmemAreas < MAX_TMEM_AREAS);
89
if (nbTmemAreas == MAX_TMEM_AREAS) {
90
LOG("tmem areas buffer full, clearing\n");
91
nbTmemAreas = 0;
92
}
93
tmemAreas[nbTmemAreas].start = start;
94
tmemAreas[nbTmemAreas].stop = stop;
95
tmemAreas[nbTmemAreas].from = from;
96
tmemAreas[nbTmemAreas].fromLine = fromLine;
97
tmemAreas[nbTmemAreas].fromFormat = fromFormat;
98
tmemAreas[nbTmemAreas].fromSize = fromSize;
99
nbTmemAreas++;
100
}
101
102
uint32_t rdpGetTmemOrigin(int tmem, int * line, int * stop, int * format, int * size)
103
{
104
int i;
105
for (i=0; i<nbTmemAreas; i++)
106
if (tmemAreas[i].start == tmem) {
107
*line = tmemAreas[i].fromLine;
108
*stop = tmemAreas[i].stop;
109
*format = tmemAreas[i].fromFormat;
110
*size = tmemAreas[i].fromSize;
111
return tmemAreas[i].from;
112
}
113
114
return ~0;
115
}
116
117
inline uint32_t READ_RDP_DATA(uint32_t address)
118
{
119
if (dp_status & 0x1) // XBUS_DMEM_DMA enabled
120
{
121
return rsp_dmem[(address & 0xfff) / 4];
122
}
123
else
124
{
125
return rdram[(address / 4)];
126
}
127
}
128
129
static const int rdp_command_length[64] =
130
{
131
8, // 0x00, No Op
132
8, // 0x01, ???
133
8, // 0x02, ???
134
8, // 0x03, ???
135
8, // 0x04, ???
136
8, // 0x05, ???
137
8, // 0x06, ???
138
8, // 0x07, ???
139
32, // 0x08, Non-Shaded Triangle
140
32+16, // 0x09, Non-Shaded, Z-Buffered Triangle
141
32+64, // 0x0a, Textured Triangle
142
32+64+16, // 0x0b, Textured, Z-Buffered Triangle
143
32+64, // 0x0c, Shaded Triangle
144
32+64+16, // 0x0d, Shaded, Z-Buffered Triangle
145
32+64+64, // 0x0e, Shaded+Textured Triangle
146
32+64+64+16,// 0x0f, Shaded+Textured, Z-Buffered Triangle
147
8, // 0x10, ???
148
8, // 0x11, ???
149
8, // 0x12, ???
150
8, // 0x13, ???
151
8, // 0x14, ???
152
8, // 0x15, ???
153
8, // 0x16, ???
154
8, // 0x17, ???
155
8, // 0x18, ???
156
8, // 0x19, ???
157
8, // 0x1a, ???
158
8, // 0x1b, ???
159
8, // 0x1c, ???
160
8, // 0x1d, ???
161
8, // 0x1e, ???
162
8, // 0x1f, ???
163
8, // 0x20, ???
164
8, // 0x21, ???
165
8, // 0x22, ???
166
8, // 0x23, ???
167
16, // 0x24, Texture_Rectangle
168
16, // 0x25, Texture_Rectangle_Flip
169
8, // 0x26, Sync_Load
170
8, // 0x27, Sync_Pipe
171
8, // 0x28, Sync_Tile
172
8, // 0x29, Sync_Full
173
8, // 0x2a, Set_Key_GB
174
8, // 0x2b, Set_Key_R
175
8, // 0x2c, Set_Convert
176
8, // 0x2d, Set_Scissor
177
8, // 0x2e, Set_Prim_Depth
178
8, // 0x2f, Set_Other_Modes
179
8, // 0x30, Load_TLUT
180
8, // 0x31, ???
181
8, // 0x32, Set_Tile_Size
182
8, // 0x33, Load_Block
183
8, // 0x34, Load_Tile
184
8, // 0x35, Set_Tile
185
8, // 0x36, Fill_Rectangle
186
8, // 0x37, Set_Fill_Color
187
8, // 0x38, Set_Fog_Color
188
8, // 0x39, Set_Blend_Color
189
8, // 0x3a, Set_Prim_Color
190
8, // 0x3b, Set_Env_Color
191
8, // 0x3c, Set_Combine
192
8, // 0x3d, Set_Texture_Image
193
8, // 0x3e, Set_Mask_Image
194
8 // 0x3f, Set_Color_Image
195
};
196
197
/*****************************************************************************/
198
199
////////////////////////
200
// RDP COMMANDS
201
////////////////////////
202
203
static void rdp_invalid(uint32_t w1, uint32_t w2)
204
{
205
LOGERROR("RDP: invalid command %d, %08X %08X\n", (w1 >> 24) & 0x3f, w1, w2);
206
}
207
208
static void rdp_noop(uint32_t w1, uint32_t w2)
209
{
210
211
}
212
213
static void triangle(uint32_t w1, uint32_t w2, int shade, int texture, int zbuffer)
214
{
215
rglTriangle(w1, w2, shade, texture, zbuffer, rdp_cmd_data + rdp_cmd_cur);
216
}
217
218
static void rdp_tri_noshade(uint32_t w1, uint32_t w2)
219
{
220
triangle(w1, w2, 0, 0, 0);
221
}
222
223
static void rdp_tri_noshade_z(uint32_t w1, uint32_t w2)
224
{
225
triangle(w1, w2, 0, 0, 1);
226
}
227
228
static void rdp_tri_tex(uint32_t w1, uint32_t w2)
229
{
230
triangle(w1, w2, 0, 1, 0);
231
}
232
233
static void rdp_tri_tex_z(uint32_t w1, uint32_t w2)
234
{
235
triangle(w1, w2, 0, 1, 1);
236
}
237
238
static void rdp_tri_shade(uint32_t w1, uint32_t w2)
239
{
240
triangle(w1, w2, 1, 0, 0);
241
}
242
243
static void rdp_tri_shade_z(uint32_t w1, uint32_t w2)
244
{
245
triangle(w1, w2, 1, 0, 1);
246
}
247
248
static void rdp_tri_texshade(uint32_t w1, uint32_t w2)
249
{
250
triangle(w1, w2, 1, 1, 0);
251
}
252
253
static void rdp_tri_texshade_z(uint32_t w1, uint32_t w2)
254
{
255
triangle(w1, w2, 1, 1, 1);
256
}
257
258
static void rdp_tex_rect(uint32_t w1, uint32_t w2)
259
{
260
uint32_t w3, w4;
261
rdpTexRect_t rect;
262
263
w3 = rdp_cmd_data[rdp_cmd_cur+2];
264
w4 = rdp_cmd_data[rdp_cmd_cur+3];
265
266
rect.tilenum = (w2 >> 24) & 0x7;
267
rect.xl = (w1 >> 12) & 0xfff;
268
rect.yl = (w1 >> 0) & 0xfff;
269
rect.xh = (w2 >> 12) & 0xfff;
270
rect.yh = (w2 >> 0) & 0xfff;
271
rect.s = (w3 >> 16) & 0xffff;
272
rect.t = (w3 >> 0) & 0xffff;
273
rect.dsdx = (w4 >> 16) & 0xffff;
274
rect.dtdy = (w4 >> 0) & 0xffff;
275
276
rglTextureRectangle(&rect, 0);
277
}
278
279
static void rdp_tex_rect_flip(uint32_t w1, uint32_t w2)
280
{
281
uint32_t w3, w4;
282
rdpTexRect_t rect;
283
284
w3 = rdp_cmd_data[rdp_cmd_cur+2];
285
w4 = rdp_cmd_data[rdp_cmd_cur+3];
286
287
rect.tilenum = (w2 >> 24) & 0x7;
288
rect.xl = (w1 >> 12) & 0xfff;
289
rect.yl = (w1 >> 0) & 0xfff;
290
rect.xh = (w2 >> 12) & 0xfff;
291
rect.yh = (w2 >> 0) & 0xfff;
292
rect.t = (w3 >> 16) & 0xffff;
293
rect.s = (w3 >> 0) & 0xffff;
294
rect.dtdy = (w4 >> 16) & 0xffff;
295
rect.dsdx = (w4 >> 0) & 0xffff;
296
297
rglTextureRectangle(&rect, 1);
298
}
299
300
static void rdp_sync_load(uint32_t w1, uint32_t w2)
301
{
302
// Nothing to do?
303
}
304
305
static void rdp_sync_pipe(uint32_t w1, uint32_t w2)
306
{
307
// Nothing to do?
308
}
309
310
static void rdp_sync_tile(uint32_t w1, uint32_t w2)
311
{
312
// Nothing to do?
313
}
314
315
void rdpSignalFullSync();
316
void rdpWaitFullSync();
317
#ifdef RDP_DEBUG
318
int nbFullSync;
319
#endif
320
static void rdp_sync_full(uint32_t w1, uint32_t w2)
321
{
322
//printf("full sync\n");
323
rglFullSync();
324
rglUpdate();
325
326
if (rglSettings.async)
327
rdpSignalFullSync();
328
else {
329
*gfx.MI_INTR_REG |= 0x20;
330
gfx.CheckInterrupts();
331
}
332
#ifdef RDP_DEBUG
333
nbFullSync++;
334
#endif
335
}
336
337
static void rdp_set_key_gb(uint32_t w1, uint32_t w2)
338
{
339
//osd_die("RDP: unhandled command set_key_gb, %08X %08X\n", w1, w2);
340
}
341
342
static void rdp_set_key_r(uint32_t w1, uint32_t w2)
343
{
344
//osd_die("RDP: unhandled command set_key_r, %08X %08X\n", w1, w2);
345
}
346
347
static void rdp_set_convert(uint32_t w1, uint32_t w2)
348
{
349
rdpState.k5 = w2&0xff;
350
//osd_die("RDP: unhandled command set_convert, %08X %08X\n", w1, w2);
351
}
352
353
static void rdp_set_scissor(uint32_t w1, uint32_t w2)
354
{
355
rdpChanged |= RDP_BITS_CLIP;
356
rdpState.clipMode = (w2 >> 24) & 3;
357
rdpState.clip.xh = (w1 >> 12) & 0xfff;
358
rdpState.clip.yh = (w1 >> 0) & 0xfff;
359
rdpState.clip.xl = (w2 >> 12) & 0xfff;
360
rdpState.clip.yl = (w2 >> 0) & 0xfff;
361
// TODO: handle f & o?
362
}
363
364
static void rdp_set_prim_depth(uint32_t w1, uint32_t w2)
365
{
366
rdpChanged |= RDP_BITS_MISC;
367
rdpState.primitiveZ = (uint16_t)(w2 >> 16);
368
rdpState.primitiveDeltaZ = (uint16_t)(w1);
369
}
370
371
static void rdp_set_other_modes(uint32_t w1, uint32_t w2)
372
{
373
rdpChanged |= RDP_BITS_OTHER_MODES;
374
rdpState.otherModes.w1 = w1;
375
rdpState.otherModes.w2 = w2;
376
}
377
378
static void rdp_load_tlut(uint32_t w1, uint32_t w2)
379
{
380
int tilenum = (w2 >> 24) & 0x7;
381
382
rdpChanged |= RDP_BITS_TILE_SETTINGS;
383
384
#define tile rdpTiles[tilenum]
385
//rdpTile_t tile;
386
tile.sl = (w1 >> 12) & 0xfff;
387
tile.tl = (w1 >> 0) & 0xfff;
388
tile.sh = (w2 >> 12) & 0xfff;
389
tile.th = (w2 >> 0) & 0xfff;
390
391
int i;
392
393
rdpChanged |= RDP_BITS_TLUT;
394
395
int count = ((tile.sh - tile.sl + 4) >>2) * ((tile.th - tile.tl + 4) >>2);
396
397
switch (rdpTiSize)
398
{
399
case RDP_PIXEL_SIZE_16BIT:
400
{
401
uint16_t *src = (uint16_t *)&rdram[(rdpTiAddress + (tile.tl >>2) * rdpTiWidth * 2 + ((tile.sl >>2) << rdpTiSize >> 1))/4];
402
uint16_t *dst = (uint16_t *)(rdpTmem + rdpTiles[tilenum].tmem);
403
404
// printf("loading TLUT from %x --> %x\n",
405
// tile.th * rdpTiWidth / 2 + (tile.sh << rdpTiSize >> 1)/4
406
407
for (i=0; i < count; i++)
408
{
409
dst[i*4] = src[i^1];
410
}
411
break;
412
}
413
default: LOGERROR("RDP: load_tlut: size = %d\n", rdpTiSize);
414
}
415
#undef tile
416
}
417
418
static void rdp_set_tile_size(uint32_t w1, uint32_t w2)
419
{
420
int tilenum = (w2 >> 24) & 0x7;
421
422
rdpChanged |= RDP_BITS_TILE_SETTINGS;
423
424
#define tile rdpTiles[tilenum]
425
tile.sl = (w1 >> 12) & 0xfff;
426
tile.tl = (w1 >> 0) & 0xfff;
427
tile.sh = (w2 >> 12) & 0xfff;
428
tile.th = (w2 >> 0) & 0xfff;
429
#undef tile
430
}
431
432
static void rdp_load_block(uint32_t w1, uint32_t w2)
433
{
434
int i, width;
435
uint16_t sl, sh, tl, dxt;
436
int tilenum = (w2 >> 24) & 0x7;
437
uint32_t *src, *tc;
438
int tb;
439
440
rdpChanged |= RDP_BITS_TMEM;
441
442
sl = ((w1 >> 12) & 0xfff);
443
tl = ((w1 >> 0) & 0xfff) << 11;
444
sh = ((w2 >> 12) & 0xfff);
445
dxt = ((w2 >> 0) & 0xfff);
446
447
width = (sh - sl + 1) << rdpTiSize >> 1;
448
449
src = (uint32_t*)&rdram[0];
450
tc = (uint32_t*)rdpTmem;
451
tb = rdpTiles[tilenum].tmem/4;
452
453
//printf("Load block to %x width %x\n", rdpTiles[tilenum].tmem, width);
454
455
MarkTmemArea(rdpTiles[tilenum].tmem, rdpTiles[tilenum].tmem + width,
456
tl * rdpTiWidth*4 + rdpTiAddress + sl*4, 0, ~0, ~0);
457
458
if (tb+width/4 > 0x1000/4) {
459
LOG("load_block : fixup too large width\n");
460
width = 0x1000-tb*4;
461
}
462
463
if (dxt != 0)
464
{
465
int j=0;
466
467
//rglAssert(tb+width/4 <= 0x1000/4);
468
469
int swap = rdpTiles[tilenum].size == 3? 2 : 1;
470
471
for (i=0; i < width / 4; i+=2)
472
{
473
int t = j >> 11;
474
475
tc[(((tb+i) + 0) ^ ((t & 1) ? swap : 0))&0x3ff] =
476
src[rdpTiAddress / 4 + ((tl * rdpTiWidth) / 4) + sl + i + 0];
477
tc[(((tb+i) + 1) ^ ((t & 1) ? swap : 0))&0x3ff] =
478
src[rdpTiAddress / 4 + ((tl * rdpTiWidth) / 4) + sl + i + 1];
479
480
j += dxt;
481
}
482
}
483
else
484
{
485
//rglAssert(tb+width/4 <= 0x1000/4);
486
for (i=0; i < width / 4; i++)
487
{
488
tc[(tb+i)&0x3ff] = src[((tl * rdpTiWidth) / 4) + rdpTiAddress / 4 + sl + i];
489
}
490
}
491
}
492
493
static void rdp_load_tile(uint32_t w1, uint32_t w2)
494
{
495
int i, j;
496
uint16_t sl, sh, tl, th;
497
int width, height;
498
int tilenum = (w2 >> 24) & 0x7;
499
int line;
500
501
rdpChanged |= RDP_BITS_TMEM;
502
503
sl = ((w1 >> 12) & 0xfff) / 4;
504
tl = ((w1 >> 0) & 0xfff) / 4;
505
sh = ((w2 >> 12) & 0xfff) / 4;
506
th = ((w2 >> 0) & 0xfff) / 4;
507
508
width = (sh - sl) + 1;
509
height = (th - tl) + 1;
510
511
// printf("Load tile to %x line %x height %d\n",
512
// rdpTiles[tilenum].tmem,
513
// rdpTiles[tilenum].line,
514
// height);
515
516
rdpTiles[tilenum].size = rdpTiSize; // CHECK THIS
517
line = rdpTiles[tilenum].line;
518
switch (rdpTiles[tilenum].size /*rdpTiSize*/)
519
{
520
case RDP_PIXEL_SIZE_8BIT:
521
{
522
uint8_t *src = (uint8_t*)&rdram[0];
523
uint8_t *tc = (uint8_t*)rdpTmem;
524
int tb = rdpTiles[tilenum].tmem;
525
526
MarkTmemArea(tb, tb + height*line, rdpTiAddress + tl * rdpTiWidth + sl,
527
rdpTiWidth, rdpTiFormat, rdpTiSize);
528
529
if (tb + (line * (height-1) + width) > 4096)
530
{
531
LOGERROR("rdp_load_tile 8-bit: tmem %04X, width %d, height %d = %d\n", rdpTiles[tilenum].tmem, width, height, width*height);
532
height = (4096-tb)/line;
533
}
534
535
for (j=0; j < height; j++)
536
{
537
int tline = tb + (rdpTiles[tilenum].line * j);
538
int s = ((j + tl) * rdpTiWidth) + sl;
539
540
for (i=0; i < width; i++)
541
{
542
tc[(((tline+i) ^ BYTE_ADDR_XOR) ^ ((j & 1) ? 4 : 0))&0xfff] = src[(rdpTiAddress + s++) ^ BYTE_ADDR_XOR];
543
}
544
}
545
break;
546
}
547
case RDP_PIXEL_SIZE_16BIT:
548
{
549
uint16_t *src = (uint16_t*)&rdram[0];
550
uint16_t *tc = (uint16_t*)rdpTmem;
551
int tb = (rdpTiles[tilenum].tmem / 2);
552
553
if (tb + (line/2 * (height-1) + width) > 2048)
554
{
555
LOGERROR("rdp_load_tile 16-bit: tmem %04X, width %d, height %d = %d\n", rdpTiles[tilenum].tmem, width, height, width*height);
556
height = (2048 - tb) / (line/2);
557
}
558
559
MarkTmemArea(tb*2, tb*2 + height*line,
560
rdpTiAddress + (tl * rdpTiWidth + sl)*2,
561
rdpTiWidth*2, rdpTiFormat, rdpTiSize);
562
563
for (j=0; j < height; j++)
564
{
565
int tline = tb + ((rdpTiles[tilenum].line / 2) * j);
566
int s = ((j + tl) * rdpTiWidth) + sl;
567
568
for (i=0; i < width; i++)
569
{
570
tc[(((tline+i) ^ WORD_ADDR_XOR) ^ ((j & 1) ? 2 : 0))&0x7ff] = src[(rdpTiAddress / 2 + s++) ^ WORD_ADDR_XOR];
571
}
572
}
573
break;
574
}
575
case RDP_PIXEL_SIZE_32BIT:
576
{
577
uint32_t *src = (uint32_t*)&rdram[0];
578
uint32_t *tc = (uint32_t*)rdpTmem;
579
int tb = (rdpTiles[tilenum].tmem / 4);
580
581
MarkTmemArea(tb*4, tb*4 + height*line*2,
582
rdpTiAddress + (tl * rdpTiWidth + sl)*4,
583
rdpTiWidth*4, rdpTiFormat, rdpTiSize);
584
585
if (tb + (line/2 * (height-1) + width) > 1024)
586
{
587
rdp_log(M64MSG_ERROR, "rdp_load_tile 32-bit: tmem %04X, width %d, height %d = %d\n", rdpTiles[tilenum].tmem, width, height, width*height);
588
}
589
590
for (j=0; j < height; j++)
591
{
592
int tline = tb + ((rdpTiles[tilenum].line / 2) * j);
593
int s = ((j + tl) * rdpTiWidth) + sl;
594
595
for (i=0; i < width; i++)
596
{
597
tc[((tline+i) ^ ((j & 1) ? 2 : 0))&0x3ff] = src[(rdpTiAddress / 4 + s++)];
598
}
599
}
600
break;
601
}
602
603
default:
604
rdp_log(M64MSG_ERROR, "RDP: load_tile: size = %d\n", rdpTiSize);
605
}
606
}
607
608
static void rdp_set_tile(uint32_t w1, uint32_t w2)
609
{
610
int tilenum = (w2 >> 24) & 0x7;
611
//int i;
612
613
rdpChanged |= RDP_BITS_TILE_SETTINGS;
614
rdpTileSet |= 1<<tilenum;
615
616
#define tile rdpTiles[tilenum]
617
tile.format = (w1 >> 21) & 0x7;
618
tile.size = (w1 >> 19) & 0x3;
619
tile.line = ((w1 >> 9) & 0x1ff) * 8;
620
tile.tmem = ((w1 >> 0) & 0x1ff) * 8;
621
tile.palette= (w2 >> 20) & 0xf;
622
tile.ct = (w2 >> 19) & 0x1;
623
tile.mt = (w2 >> 18) & 0x1;
624
tile.mask_t = (w2 >> 14) & 0xf;
625
tile.shift_t= (w2 >> 10) & 0xf;
626
if (tile.shift_t >= 12) tile.shift_t -= 16;
627
tile.cs = (w2 >> 9) & 0x1;
628
tile.ms = (w2 >> 8) & 0x1;
629
tile.mask_s = (w2 >> 4) & 0xf;
630
tile.shift_s= (w2 >> 0) & 0xf;
631
if (tile.shift_s >= 12) tile.shift_s -= 16;
632
#undef tile
633
}
634
635
static void rdp_fill_rect(uint32_t w1, uint32_t w2)
636
{
637
rdpRect_t rect;
638
rect.xl = (w1 >> 12) & 0xfff;
639
rect.yl = (w1 >> 0) & 0xfff;
640
rect.xh = (w2 >> 12) & 0xfff;
641
rect.yh = (w2 >> 0) & 0xfff;
642
643
rglFillRectangle(&rect);
644
}
645
646
static void rdp_set_fill_color(uint32_t w1, uint32_t w2)
647
{
648
rdpChanged |= RDP_BITS_FILL_COLOR;
649
rdpState.fillColor = w2;
650
}
651
652
static void rdp_set_fog_color(uint32_t w1, uint32_t w2)
653
{
654
rdpChanged |= RDP_BITS_FOG_COLOR;
655
rdpState.fogColor = w2;
656
}
657
658
static void rdp_set_blend_color(uint32_t w1, uint32_t w2)
659
{
660
rdpChanged |= RDP_BITS_BLEND_COLOR;
661
rdpState.blendColor = w2;
662
}
663
664
static void rdp_set_prim_color(uint32_t w1, uint32_t w2)
665
{
666
rdpChanged |= RDP_BITS_PRIM_COLOR;
667
// TODO: prim min level, prim_level
668
rdpState.primColor = w2;
669
}
670
671
static void rdp_set_env_color(uint32_t w1, uint32_t w2)
672
{
673
rdpChanged |= RDP_BITS_ENV_COLOR;
674
rdpState.envColor = w2;
675
}
676
677
static void rdp_set_combine(uint32_t w1, uint32_t w2)
678
{
679
rdpChanged |= RDP_BITS_COMBINE_MODES;
680
681
rdpState.combineModes.w1 = w1;
682
rdpState.combineModes.w2 = w2;
683
}
684
685
static void rdp_set_texture_image(uint32_t w1, uint32_t w2)
686
{
687
rdpChanged |= RDP_BITS_TI_SETTINGS;
688
689
rdpTiFormat = (w1 >> 21) & 0x7;
690
rdpTiSize = (w1 >> 19) & 0x3;
691
rdpTiWidth = (w1 & 0x3ff) + 1;
692
rdpTiAddress = w2 & 0x01ffffff;
693
}
694
695
static void rdp_set_mask_image(uint32_t w1, uint32_t w2)
696
{
697
rdpChanged |= RDP_BITS_ZB_SETTINGS;
698
rdpZbAddress = w2 & 0x01ffffff;
699
}
700
701
static void rdp_set_color_image(uint32_t w1, uint32_t w2)
702
{
703
rdpChanged |= RDP_BITS_FB_SETTINGS;
704
rdpFbFormat = (w1 >> 21) & 0x7;
705
rdpFbSize = (w1 >> 19) & 0x3;
706
rdpFbWidth = (w1 & 0x3ff) + 1;
707
rdpFbAddress = w2 & 0x01ffffff;
708
}
709
710
/*****************************************************************************/
711
712
static void (* rdp_command_table[64])(uint32_t w1, uint32_t w2) =
713
{
714
/* 0x00 */
715
rdp_noop, rdp_invalid, rdp_invalid, rdp_invalid,
716
rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
717
rdp_tri_noshade, rdp_tri_noshade_z, rdp_tri_tex, rdp_tri_tex_z,
718
rdp_tri_shade, rdp_tri_shade_z, rdp_tri_texshade, rdp_tri_texshade_z,
719
/* 0x10 */
720
rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
721
rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
722
rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
723
rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
724
/* 0x20 */
725
rdp_invalid, rdp_invalid, rdp_invalid, rdp_invalid,
726
rdp_tex_rect, rdp_tex_rect_flip, rdp_sync_load, rdp_sync_pipe,
727
rdp_sync_tile, rdp_sync_full, rdp_set_key_gb, rdp_set_key_r,
728
rdp_set_convert, rdp_set_scissor, rdp_set_prim_depth, rdp_set_other_modes,
729
/* 0x30 */
730
rdp_load_tlut, rdp_invalid, rdp_set_tile_size, rdp_load_block,
731
rdp_load_tile, rdp_set_tile, rdp_fill_rect, rdp_set_fill_color,
732
rdp_set_fog_color, rdp_set_blend_color, rdp_set_prim_color, rdp_set_env_color,
733
rdp_set_combine, rdp_set_texture_image, rdp_set_mask_image, rdp_set_color_image
734
};
735
736
void rdp_process_list(void)
737
{
738
//int i;
739
uint32_t cmd;//, length, cmd_length;
740
741
rglUpdateStatus();
742
if (!rglSettings.threaded)
743
rdp_store_list();
744
745
if (rglStatus == RGL_STATUS_CLOSED)
746
return;
747
748
// this causes problem with depth writeback in zelda mm
749
// but is necessary for in fisherman
750
rglUpdate();
751
752
while (rdp_cmd_cur != rdp_cmd_ptr)
753
{
754
cmd = (rdp_cmd_data[rdp_cmd_cur] >> 24) & 0x3f;
755
// if (((rdp_cmd_data[rdp_cmd_cur] >> 24) & 0xc0) != 0xc0)
756
// {
757
// LOGERROR("rdp_process_list: invalid rdp command %08X at %08X\n", rdp_cmd_data[rdp_cmd_cur], dp_start+(rdp_cmd_cur * 4));
758
// }
759
760
if ((((rdp_cmd_ptr-rdp_cmd_cur)&(MAXCMD-1)) * 4) < rdp_command_length[cmd])
761
{
762
// LOGERROR("rdp_process_list: not enough rdp command data: cur = %d, ptr = %d, expected = %d\n", rdp_cmd_cur, rdp_cmd_ptr, rdp_command_length[cmd]);
763
// return;
764
break;
765
}
766
767
#ifdef RDP_DEBUG
768
if (rdp_dump)
769
{
770
char string[4000];
771
int rdp_dasm(uint32_t * rdp_cmd_data, int rdp_cmd_cur, int length, char *buffer);
772
rdp_dasm(rdp_cmd_data, rdp_cmd_cur, rdp_command_length[cmd], string);
773
774
fprintf(stderr, "%08X: %08X %08X %s\n", dp_start+(rdp_cmd_cur * 4), rdp_cmd_data[rdp_cmd_cur+0], rdp_cmd_data[rdp_cmd_cur+1], string);
775
}
776
#endif
777
778
#ifdef RDP_DEBUG
779
memcpy(rdpTraceBuf+rdpTracePos, rdp_cmd_data+rdp_cmd_cur, rdp_command_length[cmd]);
780
#endif
781
782
if (rdp_cmd_cur + rdp_command_length[cmd]/4 > MAXCMD)
783
memcpy(rdp_cmd_data + MAXCMD, rdp_cmd_data, rdp_command_length[cmd] - (MAXCMD - rdp_cmd_cur)*4);
784
785
// execute the command
786
rdp_command_table[cmd](rdp_cmd_data[rdp_cmd_cur+0], rdp_cmd_data[rdp_cmd_cur+1]);
787
788
#ifdef RDP_DEBUG
789
rdpTracePos += rdp_command_length[cmd] / 4;
790
rglAssert(rdpTracePos < sizeof(rdpTraceBuf)/sizeof(rdpTraceBuf[0]));
791
#endif
792
793
rdp_cmd_cur = (rdp_cmd_cur + rdp_command_length[cmd] / 4) & (MAXCMD-1);
794
}
795
796
// dp_current = dp_end;
797
// dp_start = dp_end;
798
dp_start = dp_current;
799
800
dp_status &= ~0x0002;
801
}
802
803
int rdp_store_list(void)
804
{
805
uint32_t i;
806
uint32_t data, cmd, length;
807
int sync = 0;
808
809
// while (dp_current < dp_end) {
810
811
// }
812
// dp_status &= ~0x0002;
813
814
length = dp_end - dp_current;
815
816
// LOG("rdp start %x cur %x end %x length %d dp_status %x\n",
817
// dp_start, dp_current, dp_end,
818
// length, dp_status);
819
820
if (dp_end <= dp_current) {
821
return 0;
822
}
823
824
// load command data
825
for (i=0; i < length; i += 4)
826
{
827
data = READ_RDP_DATA(dp_current + i);
828
if (rglSettings.async) {
829
if (rdp_cmd_left) {
830
rdp_cmd_left--;
831
} else {
832
cmd = (data >> 24) & 0x3f;
833
rdp_cmd_left = rdp_command_length[cmd]/4-1;
834
if (cmd == 0x29) // full_sync
835
sync = 1;
836
}
837
}
838
rdp_cmd_data[rdp_cmd_ptr] = data;
839
rdp_cmd_ptr = (rdp_cmd_ptr + 1) & (MAXCMD-1);
840
}
841
842
dp_current += length;
843
844
return sync;
845
}
846
847
848
int rdp_init()
849
{
850
rdp_cmd_cur = rdp_cmd_ptr = 0;
851
rdp_cmd_left = 0;
852
#ifdef RDP_DEBUG
853
rdpTracePos = 0;
854
#endif
855
nbTmemAreas = 0;
856
return rglInit();
857
}
858
859
860