76 #define INTERNAL_FB_ADDR 0x300000000ULL 77 #define PVR_FB_TICK_SHIFT 18 79 #define PVR_VBLANK_HZ 60.0 83 #define VRAM_SIZE (8*1048576) 86 #define PVR_DMA_MEMLENGTH 0x100 87 #define N_PVR_DMA_REGS (PVR_DMA_MEMLENGTH / sizeof(uint32_t)) 90 #define PVR_COUNT 0x04 92 #define PVR_LMMODE0 0x84 93 #define PVR_LMMODE1 0x88 136 uint32_t
ta[64 /
sizeof(uint32_t)];
158 #define REG(x) (d->reg[(x)/sizeof(uint32_t)]) 159 #define DEFAULT_WRITE REG(relative_addr) = idata; 168 const int channel = 2;
169 uint32_t sar = cpu->
cd.
sh.
dmac_sar[channel] & 0x1fffffff;
170 uint32_t dar = cpu->
cd.
sh.
dmac_dar[channel] & 0x1fffffff;
171 uint32_t count = cpu->
cd.
sh.
dmac_tcr[channel] & 0x1fffffff;
173 int transmit_size = 1;
174 int src_delta = 0, dst_delta = 0;
175 int cause_interrupt = chcr &
CHCR_IE;
179 for (
int dmaChannel = 0; dmaChannel < 4; ++dmaChannel)
181 fatal(
"{# dma channel %i: sar=%08x dar=%08x count=%08x chcr=%08x #}\n",
192 fatal(
"pvr_dma_transfer: SH4 dma not enabled?\n");
210 default:
fatal(
"Unimplemented transmit size?! CHCR[%i] = 0x%08x\n",
219 default:
fatal(
"Unimplemented destination delta?! CHCR[%i] = 0x%08x\n",
228 default:
fatal(
"Unimplemented source delta?! CHCR[%i] = 0x%08x\n",
233 src_delta *= transmit_size;
234 dst_delta *= transmit_size;
240 if (dar != 0x10000000) {
243 dar = 0x04000000 | (dar & 0x007fffff);
245 dst_delta = src_delta;
247 uint8_t *buf = (uint8_t*) malloc(transmit_size);
270 unsigned char buf[
sizeof(uint32_t)];
272 size_t chunksize = transmit_size;
274 if (chunksize >
sizeof(uint32_t))
275 chunksize =
sizeof(uint32_t);
277 for (ofs = 0; ofs < transmit_size; ofs += chunksize) {
281 dev_pvr_ta_access(cpu, cpu->
mem, ofs, buf, chunksize,
304 fatal(
"Unimplemented SH4 RS DMAC: 0x%08x (PVR)\n",
305 (
int) (chcr & CHCR_RS));
309 if (cause_interrupt) {
310 fatal(
"TODO: pvr sh4 dmac interrupt!\n");
319 uint64_t idata = 0, odata = 0;
326 odata = d->
dma_reg[relative_addr /
sizeof(uint32_t)];
328 switch (relative_addr) {
332 debug(
"[ pvr_dma: ADDR set to 0x%08x ]\n",
339 debug(
"[ pvr_dma: COUNT set to 0x%08x ]\n",
346 debug(
"[ pvr_dma: MODE set to 0x%08x ]\n",
359 if (writeflag ==
MEM_WRITE && idata != 0x0cff0000) {
360 fatal(
"[ pvr_dma: TODO: unknown_0x%02x set to " 361 "0x%08x ]\n", (
int) relative_addr, (
int) idata);
373 if (writeflag ==
MEM_WRITE && idata != 0) {
374 fatal(
"[ pvr_dma: TODO: unknown_0x%02x set to " 375 "0x%08x ]\n", (
int) relative_addr, (
int) idata);
381 if (writeflag ==
MEM_WRITE && idata != 0) {
382 fatal(
"[ pvr_dma: TODO: LMMODE0 set to " 383 "0x%08x ]\n", (
int) idata);
389 if (writeflag ==
MEM_WRITE && idata != 0) {
390 fatal(
"[ pvr_dma: TODO: LMMODE1 set to " 391 "0x%08x ]\n", (
int) idata);
398 fatal(
"[ pvr_dma: write to 0x8c: TODO ]\n");
403 odata = 0x11 * (random() & 1);
408 if (writeflag ==
MEM_WRITE && idata != 0) {
409 fatal(
"[ pvr_dma: TODO: unknown_0x%02x set to " 410 "0x%08x ]\n", (
int) relative_addr, (
int) idata);
416 if (writeflag ==
MEM_WRITE && idata != 0x80000000) {
417 fatal(
"[ pvr_dma: TODO: unknown_0x%02x set to " 418 "0x%08x ]\n", (
int) relative_addr, (
int) idata);
425 if (writeflag ==
MEM_WRITE && idata != 0) {
426 fatal(
"[ pvr_dma: TODO: unknown_0x%02x set to " 427 "0x%08x ]\n", (
int) relative_addr, (
int) idata);
432 default:
if (writeflag ==
MEM_READ) {
433 fatal(
"[ pvr_dma: read from addr 0x%x ]\n",
436 fatal(
"[ pvr_dma: write to addr 0x%x: 0x%x ]\n",
437 (
int)relative_addr, (
int)idata);
445 d->
dma_reg[relative_addr /
sizeof(uint32_t)] = idata;
457 uint64_t idata = 0, odata = 0;
464 odata = d->
dma_more_reg[relative_addr /
sizeof(uint32_t)];
466 switch (relative_addr) {
478 if (writeflag ==
MEM_WRITE && idata != 0)
480 fatal(
"PVR other DMA mode (?):\n");
491 default:
if (writeflag ==
MEM_READ) {
492 fatal(
"[ pvr_dma_more: read from addr 0x%x ]\n",
495 fatal(
"[ pvr_dma_more: write to addr 0x%x: 0x%x ]\n",
496 (
int)relative_addr, (
int)idata);
504 d->
dma_more_reg[relative_addr /
sizeof(uint32_t)] = idata;
530 static void pvr_vblank_timer_tick(
struct timer *t,
void *extra)
572 bool settingsChanged = d->
xsize != old_xsize ||
573 d->
ysize != old_ysize ||
576 if (!settingsChanged)
592 case 0:
debug(
"RGB0555 (16-bit)");
break;
593 case 1:
debug(
"RGB565 (16-bit)");
break;
594 case 2:
debug(
"RGB888 (24-bit)");
break;
595 case 3:
debug(
"RGB0888 (32-bit)");
break;
602 #ifdef DEBUG_RENDER_AS_WIRE_FRAME 604 static void line(
struct pvr_data *d,
int x1,
int y1,
int x2,
int y2)
608 for (i=0; i<256; i++) {
609 int px = (i * x2 + (256-i) * x1) >> 8;
610 int py = (i * y2 + (256-i) * y1) >> 8;
611 if (px > 0 && py > 0 && px < d->
xsize && py < d->
ysize) {
612 int ofs = fb_base + (px + py * d->
xsize) *
624 static void simpleline(
struct pvr_data *d,
int y,
double x1,
double x2,
625 double z1,
double z2,
double r1,
double r2,
double g1,
double g2,
626 double b1,
double b2)
628 if (y < 0 || y >= d->
ysize || (x1 < 0 && x2 < 0)
634 double tmpf = x1; x1 = x2; x2 = tmpf;
635 tmpf = z1; z1 = z2; z2 = tmpf;
636 tmpf = r1; r1 = r2; r2 = tmpf;
637 tmpf = g1; g1 = g2; g2 = tmpf;
638 tmpf = b1; b1 = b2; b2 = tmpf;
648 double dz12 = (x2 - x1 != 0) ? ( (
double)(z2 - z1) / (
double)(x2 - x1) ) : 0;
649 double dr12 = (x2 - x1 != 0) ? ( (
double)(r2 - r1) / (
double)(x2 - x1) ) : 0;
650 double dg12 = (x2 - x1 != 0) ? ( (
double)(g2 - g1) / (
double)(x2 - x1) ) : 0;
651 double db12 = (x2 - x1 != 0) ? ( (
double)(b2 - b1) / (
double)(x2 - x1) ) : 0;
652 double z = z1, r = r1, g = g1, b = b1;
653 for (
int x = x1; x <= x2; ++x) {
654 if (x > 0 && x < d->
xsize) {
655 int ofs = x + y * d->
xsize;
656 if (d->
vram_z[ofs] <= z) {
670 int ri = r, gi = g, bi = b;
676 if (ri < 0) ri = 0;
if (ri > 255) ri = 255;
677 if (gi < 0) gi = 0;
if (gi > 255) gi = 255;
678 if (bi < 0) bi = 0;
if (bi > 255) bi = 255;
679 int color = ((ri >> 3) << 11) + ((gi >> 2) << 5) + (bi >> 3);
687 z += dz12; r += dr12; g += dg12; b += db12;
691 static void texturedline(
struct pvr_data *d,
692 int texture_pixelformat,
bool twiddled,
int stride,
693 int texture,
int texture_xsize,
int texture_ysize,
694 int y,
int x1,
int x2,
double z1,
double z2,
695 double u1,
double u2,
double v1,
double v2)
697 if (y < 0 || y >= d->
ysize || (x1 < 0 && x2 < 0)
703 int tmp = x1; x1 = x2; x2 = tmp;
704 double tmpf = z1; z1 = z2; z2 = tmpf;
705 tmpf = u1; u1 = u2; u2 = tmpf;
706 tmpf = v1; v1 = v2; v2 = tmpf;
709 int bytesperpixel = 2;
711 switch (texture_pixelformat)
728 double dz12 = (x2 - x1 != 0) ? ( (
double)(z2 - z1) / (
double)(x2 - x1) ) : 0;
729 double du12 = (x2 - x1 != 0) ? ( (
double)(u2 - u1) / (
double)(x2 - x1) ) : 0;
730 double dv12 = (x2 - x1 != 0) ? ( (
double)(v2 - v1) / (
double)(x2 - x1) ) : 0;
732 double z = z1, u = u1, v = v1;
734 for (
int x = x1; x <= x2; ++x) {
735 if (x > 0 && x < d->
xsize) {
736 int ofs = x + y * d->
xsize;
737 if (d->
vram_z[ofs] <= z) {
743 int texturex = u * texture_xsize;
744 texturex &= (texture_xsize-1);
745 int texturey = v * texture_ysize;
746 texturey &= (texture_ysize-1);
751 (texturex&1)|((texturex&2)<<1)|((texturex&4)<<2)|((texturex&8)<<3)|((texturex&16)<<4)|
752 ((texturex&32)<<5)|((texturex&64)<<6)|((texturex&128)<<7)|((texturex&256)<<8)|((texturex&512)<<9);
754 (texturey&1)|((texturey&2)<<1)|((texturey&4)<<2)|((texturey&8)<<3)|((texturey&16)<<4)|
755 ((texturey&32)<<5)|((texturey&64)<<6)|((texturey&128)<<7)|((texturey&256)<<8)|((texturey&512)<<9);
756 textureofs = texturex * 2 + texturey;
759 textureofs = texturex + texturey * stride;
761 textureofs = texturex + texturey * texture_xsize;
764 textureofs *= bytesperpixel;
766 int addr = texture + textureofs;
767 addr = ((addr & 4) << 20) | (addr & 3) | ((addr & 0x7ffff8) >> 1);
769 int a = 255, r = 64, g = 64, b = 64;
770 switch (texture_pixelformat)
775 a = (color >> 15) & 0x1 ? 255 : 0;
776 r = (color >> 10) & 0x1f;
777 g = ((color >> 5) & 0x1f) << 1;
784 r = (color >> 11) & 0x1f;
785 g = (color >> 5) & 0x3f;
792 a = ((color >> 12) & 15) * 0x11;
793 r = ((color >> 8) & 15) << 1;
794 g = ((color >> 4) & 15) << 2;
795 b = ((color) & 15) << 1;
803 uint16_t c16 = *((uint16_t*)base + index8bpp);
804 uint16_t c32 = *((uint32_t*)base + index8bpp);
805 switch (palette_cfg) {
807 a = (c16 >> 15) & 0x1 ? 255 : 0;
808 r = (c16 >> 10) & 0x1f;
809 g = ((c16 >> 5) & 0x1f) << 1;
813 r = (c16 >> 11) & 0x1f;
814 g = (c16 >> 5) & 0x3f;
818 a = ((c16 >> 12) & 15) * 0x11;
819 r = ((c16 >> 8) & 15) << 1;
820 g = ((c16 >> 4) & 15) << 2;
821 b = ((c16) & 15) << 1;
824 a = (c32 >> 24) & 255;
825 r = ((c32 >> 16) & 255) >> 3;
826 g = ((c32 >> 8) & 255) >> 2;
827 b = ((c32) & 255) >> 3;
833 fatal(
"pvr: unimplemented texture_pixelformat %i\n", texture_pixelformat);
841 int color = (r << 11) + (g << 5) + (b);
847 int oldr = (oldcolor >> 11) & 0x1f;
848 int oldg = (oldcolor >> 5) & 0x3f;
849 int oldb = (oldcolor) & 0x1f;
850 r = (a * r + oldr * (255 - a)) / 255;
851 g = (a * g + oldg * (255 - a)) / 255;
852 b = (a * b + oldb * (255 - a)) / 255;
853 int color = (r << 11) + (g << 5) + (b);
868 static void pvr_render_triangle(
struct pvr_data *d,
869 int x1,
int y1,
double z1,
int r1,
int g1,
int b1,
870 int x2,
int y2,
double z2,
int r2,
int g2,
int b2,
871 int x3,
int y3,
double z3,
int r3,
int g3,
int b3)
875 int tmp = x1; x1 = x2; x2 = tmp;
876 tmp = y1; y1 = y2; y2 = tmp;
877 tmp = r1; r1 = r2; r2 = tmp;
878 tmp = g1; g1 = g2; g2 = tmp;
879 tmp = b1; b1 = b2; b2 = tmp;
880 double tmpf = z1; z1 = z2; z2 = tmpf;
884 int tmp = x1; x1 = x3; x3 = tmp;
885 tmp = y1; y1 = y3; y3 = tmp;
886 tmp = r1; r1 = r3; r3 = tmp;
887 tmp = g1; g1 = g3; g3 = tmp;
888 tmp = b1; b1 = b3; b3 = tmp;
889 double tmpf = z1; z1 = z3; z3 = tmpf;
893 int tmp = x2; x2 = x3; x3 = tmp;
894 tmp = y2; y2 = y3; y3 = tmp;
895 tmp = r2; r2 = r3; r3 = tmp;
896 tmp = g2; g2 = g3; g3 = tmp;
897 tmp = b2; b2 = b3; b3 = tmp;
898 double tmpf = z2; z2 = z3; z3 = tmpf;
901 if (y3 < 0 || y1 >= d->
ysize)
904 double dx12 = (y2-y1 != 0) ? ( (x2 - x1) / (double)(y2 - y1) ) : 0.0;
905 double dx13 = (y3-y1 != 0) ? ( (x3 - x1) / (double)(y3 - y1) ) : 0.0;
906 double dx23 = (y3-y2 != 0) ? ( (x3 - x2) / (double)(y3 - y2) ) : 0.0;
908 double dz12 = (y2-y1 != 0) ? ( (z2 - z1) / (double)(y2 - y1) ) : 0.0;
909 double dz13 = (y3-y1 != 0) ? ( (z3 - z1) / (double)(y3 - y1) ) : 0.0;
910 double dz23 = (y3-y2 != 0) ? ( (z3 - z2) / (double)(y3 - y2) ) : 0.0;
912 double dr12 = (y2-y1 != 0) ? ( (r2 - r1) / (double)(y2 - y1) ) : 0.0;
913 double dr13 = (y3-y1 != 0) ? ( (r3 - r1) / (double)(y3 - y1) ) : 0.0;
914 double dr23 = (y3-y2 != 0) ? ( (r3 - r2) / (double)(y3 - y2) ) : 0.0;
916 double dg12 = (y2-y1 != 0) ? ( (g2 - g1) / (double)(y2 - y1) ) : 0.0;
917 double dg13 = (y3-y1 != 0) ? ( (g3 - g1) / (double)(y3 - y1) ) : 0.0;
918 double dg23 = (y3-y2 != 0) ? ( (g3 - g2) / (double)(y3 - y2) ) : 0.0;
920 double db12 = (y2-y1 != 0) ? ( (b2 - b1) / (double)(y2 - y1) ) : 0.0;
921 double db13 = (y3-y1 != 0) ? ( (b3 - b1) / (double)(y3 - y1) ) : 0.0;
922 double db23 = (y3-y2 != 0) ? ( (b3 - b2) / (double)(y3 - y2) ) : 0.0;
924 double startx = x1, startz = z1, startr = r1, startg = g1, startb = b1;
925 double stopx = x1, stopz = z1, stopr = r1, stopg = g1, stopb = b1;
926 for (
int y = y1; y < y2; ++y)
928 simpleline(d, y, startx, stopx, startz, stopz, startr, stopr, startg, stopg, startb, stopb);
929 startx += dx13; startz += dz13; startr += dr13; startg += dg13; startb += db13;
930 stopx += dx12; stopz += dz12; stopr += dr12; stopg += dg12; stopb += db12;
933 stopx = x2; stopz = z2; stopr = r2; stopg = g2; stopb = b2;
934 for (
int y = y2; y < y3; ++y)
936 simpleline(d, y, startx, stopx, startz, stopz, startr, stopr, startg, stopg, startb, stopb);
937 startx += dx13; startz += dz13; startr += dr13; startg += dg13; startb += db13;
938 stopx += dx23; stopz += dz23; stopr += dr23; stopg += dg23; stopb += db23;
941 #ifdef DEBUG_RENDER_AS_WIRE_FRAME 943 line(d, x1, y1, x2, y2);
944 line(d, x1, y1, x3, y3);
945 line(d, x2, y2, x3, y3);
951 static void pvr_render_triangle_textured(
struct pvr_data *d,
952 int texture_pixelformat,
bool twiddled,
int stride,
953 int texture,
int texture_xsize,
int texture_ysize,
954 int x1,
int y1,
double z1,
double u1,
double v1,
955 int x2,
int y2,
double z2,
double u2,
double v2,
956 int x3,
int y3,
double z3,
double u3,
double v3)
960 int tmp = x1; x1 = x2; x2 = tmp;
961 tmp = y1; y1 = y2; y2 = tmp;
962 double tmpf = z1; z1 = z2; z2 = tmpf;
963 tmpf = u1; u1 = u2; u2 = tmpf;
964 tmpf = v1; v1 = v2; v2 = tmpf;
968 int tmp = x1; x1 = x3; x3 = tmp;
969 tmp = y1; y1 = y3; y3 = tmp;
970 double tmpf = z1; z1 = z3; z3 = tmpf;
971 tmpf = u1; u1 = u3; u3 = tmpf;
972 tmpf = v1; v1 = v3; v3 = tmpf;
976 int tmp = x2; x2 = x3; x3 = tmp;
977 tmp = y2; y2 = y3; y3 = tmp;
978 double tmpf = z2; z2 = z3; z3 = tmpf;
979 tmpf = u2; u2 = u3; u3 = tmpf;
980 tmpf = v2; v2 = v3; v3 = tmpf;
983 if (y3 < 0 || y1 >= d->
ysize)
986 double dx12 = (y2-y1 != 0) ? ( (x2 - x1) / (double)(y2 - y1) ) : 0.0;
987 double dx13 = (y3-y1 != 0) ? ( (x3 - x1) / (double)(y3 - y1) ) : 0.0;
988 double dx23 = (y3-y2 != 0) ? ( (x3 - x2) / (double)(y3 - y2) ) : 0.0;
990 double dz12 = (y2-y1 != 0) ? ( (z2 - z1) / (double)(y2 - y1) ) : 0.0;
991 double dz13 = (y3-y1 != 0) ? ( (z3 - z1) / (double)(y3 - y1) ) : 0.0;
992 double dz23 = (y3-y2 != 0) ? ( (z3 - z2) / (double)(y3 - y2) ) : 0.0;
994 double du12 = (y2-y1 != 0) ? ( (u2 - u1) / (double)(y2 - y1) ) : 0.0;
995 double du13 = (y3-y1 != 0) ? ( (u3 - u1) / (double)(y3 - y1) ) : 0.0;
996 double du23 = (y3-y2 != 0) ? ( (u3 - u2) / (double)(y3 - y2) ) : 0.0;
998 double dv12 = (y2-y1 != 0) ? ( (v2 - v1) / (double)(y2 - y1) ) : 0.0;
999 double dv13 = (y3-y1 != 0) ? ( (v3 - v1) / (double)(y3 - y1) ) : 0.0;
1000 double dv23 = (y3-y2 != 0) ? ( (v3 - v2) / (double)(y3 - y2) ) : 0.0;
1002 double startx = x1, startz = z1, startu = u1, startv = v1;
1003 double stopx = x1, stopz = z1, stopu = u1, stopv = v1;
1005 for (
int y = y1; y < y2; ++y)
1007 texturedline(d, texture_pixelformat, twiddled, stride, texture, texture_xsize, texture_ysize, y, startx, stopx, startz, stopz, startu, stopu, startv, stopv);
1008 startx += dx13; startz += dz13; startu += du13; startv += dv13;
1009 stopx += dx12; stopz += dz12; stopu += du12; stopv += dv12;
1012 stopx = x2; stopz = z2; stopu = u2; stopv = v2;
1013 for (
int y = y2; y < y3; ++y)
1015 texturedline(d, texture_pixelformat, twiddled, stride, texture, texture_xsize, texture_ysize, y, startx, stopx, startz, stopz, startu, stopu, startv, stopv);
1016 startx += dx13; startz += dz13; startu += du13; startv += dv13;
1017 stopx += dx23; stopz += dz23; stopu += du23; stopv += dv23;
1020 #ifdef DEBUG_RENDER_AS_WIRE_FRAME 1022 line(d, x1, y1, x2, y2);
1023 line(d, x1, y1, x3, y3);
1024 line(d, x2, y2, x3, y3);
1029 static void pvr_clear_ta_commands(
struct pvr_data* d)
1049 printf(
"pvr: only RGB565 rendering has been implemented\n");
1056 int striplength = 0;
1061 bool texture =
false;
1068 int cullingmode = 0;
1078 int texture_usize = 0, texture_vsize = 0;
1081 bool texture_mipmap =
false;
1082 bool texture_vq_compression =
false;
1083 int texture_pixelformat = 0;
1084 bool texture_twiddled =
false;
1085 bool texture_stride =
false;
1086 uint32_t textureAddr = 0;
1088 int vertex_index = 0;
1089 int wf_x[4], wf_y[4];
double wf_z[4], wf_u[4], wf_v[4];
1090 int wf_r[4], wf_g[4], wf_b[4];
1092 double baseRed = 0.0, baseGreen = 0.0, baseBlue = 0.0;
1094 debug(
"[ pvr_render: rendering to FB offset 0x%x, " 1095 "%i Tile Accelerator commands ]\n", fb_base, d->
n_ta_commands);
1114 for (
int q = 0; q < d->
xsize * d->
ysize; ++q)
1121 int cmd = (list[0] >> 29) & 7;
1141 listtype = (list[0] >> 24) & 7;
1142 striplength = (list[0] >> 18) & 3;
1143 striplength = striplength == 2 ? 4 : (
1144 striplength == 3 ? 6 : (striplength + 1));
1145 clipmode = (list[0] >> 16) & 3;
1146 modifier = (list[0] >> 7) & 1;
1147 modifier_mode = (list[0] >> 6) & 1;
1148 color_type = (list[0] >> 4) & 3;
1149 texture = list[0] & 8;
1150 specular = list[0] & 4;
1151 shading = list[0] & 2;
1152 uv_format = list[0] & 1;
1155 fatal(
"\nTA polygon listtype %i, ", listtype);
1156 fatal(
"striplength %i, ", striplength);
1157 fatal(
"clipmode %i, ", clipmode);
1158 fatal(
"modifier %i, ", modifier);
1159 fatal(
"modifier_mode %i,\n", modifier_mode);
1160 fatal(
" color_type %i, ", color_type);
1161 fatal(
"texture %s, ", texture ?
"TRUE" :
"false");
1162 fatal(
"specular %s, ", specular ?
"TRUE" :
"false");
1163 fatal(
"shading %s, ", shading ?
"TRUE" :
"false");
1164 fatal(
"uv_format %s\n", uv_format ?
"TRUE" :
"false");
1168 depthmode = (list[1] >> 29) & 7;
1169 cullingmode = (list[1] >> 27) & 3;
1170 zwrite = ! ((list[1] >> 26) & 1);
1171 texture1 = (list[1] >> 25) & 1;
1172 specular1 = (list[1] >> 24) & 1;
1173 shading1 = (list[1] >> 23) & 1;
1174 uv_format1 = (list[1] >> 22) & 1;
1175 dcalcexact = (list[1] >> 20) & 1;
1178 fatal(
" depthmode %i, ", depthmode);
1179 fatal(
"cullingmode %i, ", cullingmode);
1180 fatal(
"zwrite %s, ", zwrite ?
"TRUE" :
"false");
1181 fatal(
"texture1 %s\n", texture1 ?
"TRUE" :
"false");
1182 fatal(
" specular1 %s, ", specular1 ?
"TRUE" :
"false");
1183 fatal(
"shading1 %s, ", shading1 ?
"TRUE" :
"false");
1184 fatal(
"uv_format1 %s, ", uv_format1 ?
"TRUE" :
"false");
1185 fatal(
"dcalcexact %s\n", dcalcexact ?
"TRUE" :
"false");
1189 fatal(
"pvr: no zwrite? not implemented yet.\n");
1204 fog = (list[2] >> 22) & 3;
1213 texture_usize = 8 << ((list[2] >> 3) & 7);
1214 texture_vsize = 8 << (list[2] & 7);
1217 texture_mipmap = (list[3] >> 31) & 1;
1218 texture_vq_compression = (list[3] >> 30) & 1;
1219 texture_pixelformat = (list[3] >> 27) & 7;
1220 texture_twiddled = ! ((list[3] >> 26) & 1);
1221 texture_stride = (list[3] >> 25) & 1;
1222 textureAddr = (list[3] << 3) & 0x7fffff;
1225 fatal(
" texture: mipmap %s, ", texture_mipmap ?
"TRUE" :
"false");
1226 fatal(
"vq_compression %s, ", texture_vq_compression ?
"TRUE" :
"false");
1227 fatal(
"pixelformat %i, ", texture_pixelformat);
1228 fatal(
"twiddled %s\n", texture_twiddled ?
"TRUE" :
"false");
1229 fatal(
" stride %s, ", texture_stride ?
"TRUE" :
"false");
1230 fatal(
"textureAddr 0x%08x\n", textureAddr);
1234 fatal(
"[ pvr: fog type %i not yet implemented ]\n", fog);
1236 if (texture_vq_compression) {
1237 fatal(
"pvr: texture_vq_compression not supported yet\n");
1245 baseRed = r.
f * 255;
1246 baseGreen = g.
f * 255;
1247 baseBlue = b.
f * 255;
1258 if (listtype != 0 && listtype != 2 && listtype != 4)
1261 bool eos = (list[0] >> 28) & 1;
1267 wf_x[vertex_index] = fx.
f;
1268 wf_y[vertex_index] = fy.
f;
1269 wf_z[vertex_index] = fz.
f;
1272 fatal(
"TA vertex %f %f %f%s\n", fx.
f, fy.
f, fz.
f,
1273 eos ?
" end_of_strip" :
"");
1279 wf_u[vertex_index] = u.
f;
1280 wf_v[vertex_index] = v.
f;
1282 if (color_type == 0) {
1283 wf_r[vertex_index] = (list[6] >> 16) & 255;
1284 wf_g[vertex_index] = (list[6] >> 8) & 255;
1285 wf_b[vertex_index] = (list[6]) & 255;
1286 }
else if (color_type == 1) {
1290 wf_r[vertex_index] = v.
f * 255;
1291 wf_g[vertex_index] = extra1.
f * 255;
1292 wf_b[vertex_index] = extra2.
f * 255;
1293 }
else if (color_type == 2) {
1295 wf_r[vertex_index] = extra1.
f * baseRed;
1296 wf_g[vertex_index] = extra1.
f * baseGreen;
1297 wf_b[vertex_index] = extra1.
f * baseBlue;
1300 wf_r[vertex_index] = 255;
1301 wf_g[vertex_index] = 0;
1302 wf_b[vertex_index] = 0;
1308 if (vertex_index >= 3) {
1311 float crossProduct =
1312 ((wf_x[1] - wf_x[0])*(wf_y[2] - wf_y[0])) -
1313 ((wf_y[1] - wf_y[0])*(wf_x[2] - wf_x[0]));
1319 bool culled =
false;
1320 if (cullingmode == 2) {
1321 if (crossProduct < 0)
1324 }
else if (cullingmode == 3) {
1325 if (crossProduct > 0)
1332 pvr_render_triangle_textured(d,
1333 texture_pixelformat, texture_twiddled, texture_stride ? (32*modulo_mask) : 0,
1334 textureAddr, texture_usize, texture_vsize,
1335 wf_x[0], wf_y[0], wf_z[0], wf_u[0], wf_v[0],
1336 wf_x[1], wf_y[1], wf_z[1], wf_u[1], wf_v[1],
1337 wf_x[2], wf_y[2], wf_z[2], wf_u[2], wf_v[2]);
1339 pvr_render_triangle(d,
1340 wf_x[0], wf_y[0], wf_z[0], wf_r[0], wf_g[0], wf_b[0],
1341 wf_x[1], wf_y[1], wf_z[1], wf_r[1], wf_g[1], wf_b[1],
1342 wf_x[2], wf_y[2], wf_z[2], wf_r[2], wf_g[2], wf_b[2]);
1352 wf_x[0] = wf_x[1]; wf_y[0] = wf_y[1]; wf_z[0] = wf_z[1];
1353 wf_u[0] = wf_u[1]; wf_v[0] = wf_v[1];
1354 wf_r[0] = wf_r[1]; wf_g[0] = wf_g[1]; wf_b[0] = wf_b[1];
1356 wf_x[1] = wf_x[2]; wf_y[1] = wf_y[2]; wf_z[1] = wf_z[2];
1357 wf_u[1] = wf_u[2]; wf_v[1] = wf_v[2];
1358 wf_r[1] = wf_r[2]; wf_g[1] = wf_g[2]; wf_b[1] = wf_b[2];
1365 fatal(
"pvr_render: unimplemented list cmd %i\n", cmd);
1370 pvr_clear_ta_commands(d);
1382 static void pvr_reset_ta(
struct pvr_data *d)
1385 pvr_clear_ta_commands(d);
1394 static void pvr_reset(
struct pvr_data *d)
1413 static void pvr_tilebuf_debugdump(
struct pvr_data *d)
1421 uint32_t *p = (uint32_t*) (d->
vram + tilebuf);
1423 fatal(
"PVR tile buffer debug dump:\n");
1425 for (
int i = 0; i < 24; ++i)
1426 fatal(
" %08x", *p++);
1434 fatal(
" Tile %i,%i:", x, y);
1435 for (
int i = 0; i < 6; ++i)
1436 fatal(
" %08x", *p++);
1452 static void pvr_ta_command(
struct cpu *
cpu,
struct pvr_data *d,
int list_ofs)
1454 uint32_t *
ta = &d->
ta[list_ofs];
1461 for (i = 0; i < 8; ++i)
1462 fatal(
" %08x", (
int) ta[i]);
1491 int cmd = (ta[0] >> 29) & 7;
1506 }
else if (cmd == 4) {
1516 uint64_t idata = 0, odata = 0;
1518 if (len !=
sizeof(uint32_t)) {
1519 fatal(
"pvr_ta access len = %i: TODO\n", (
int) len);
1525 relative_addr &= (
sizeof(d->
ta) - 1);
1530 fatal(
"[ pvr_ta: WRITE addr=%08x value=%08x ]\n",
1531 (
int)relative_addr, (
int)idata);
1535 d->
ta[relative_addr /
sizeof(uint32_t)] = idata;
1540 if (relative_addr == 0x1c)
1541 pvr_ta_command(cpu, d, 0);
1542 if (relative_addr == 0x3c)
1543 pvr_ta_command(cpu, d, 8);
1545 odata = d->
ta[relative_addr /
sizeof(uint32_t)];
1548 fatal(
"[ pvr_ta: READ addr=%08x value=%08x ]\n", (
int)relative_addr, (
int)odata);
1559 uint64_t idata = 0, odata = 0;
1566 odata = d->
reg[relative_addr /
sizeof(uint32_t)];
1584 switch (relative_addr) {
1600 debug(
"[ pvr: RESET ");
1614 debug(
"[ pvr: STARTRENDER ]\n");
1617 fatal(
"[ pvr: huh? read from STARTRENDER ]\n");
1624 debug(
"[ pvr: OB_ADDR set to 0x%08" PRIx32
" ]\n",
1626 if (idata & ~PVR_OB_ADDR_MASK) {
1627 fatal(
"[ pvr: OB_ADDR: Fatal error: Unknown" 1628 " bits set: 0x%08" PRIx32
" ]\n",
1629 (uint32_t)(idata & ~PVR_OB_ADDR_MASK));
1639 debug(
"[ pvr: TILEBUF_ADDR set to 0x%08" PRIx32
" ]\n",
1641 if (idata & ~PVR_TILEBUF_ADDR_MASK) {
1642 fatal(
"[ pvr: TILEBUF_ADDR: Unknown" 1643 " bits set: 0x%08" PRIx32
" ]\n",
1644 (uint32_t)(idata & ~PVR_TILEBUF_ADDR_MASK));
1649 pvr_tilebuf_debugdump(d);
1655 debug(
"[ pvr: SPANSORT: ");
1661 debug(
"TSP_CACHE_ENABLE ");
1669 debug(
"[ pvr: BRDCOLR set to 0x%06" PRIx32
" ]\n",
1691 debug(
"[ pvr: DIWMODE set to: ");
1693 debug(
"strip_buffer_enabled=%i, ",
1698 debug(
"pixelmode=");
1700 case 0:
debug(
"RGB0555 (16-bit)");
break;
1701 case 1:
debug(
"RGB565 (16-bit)");
break;
1702 case 2:
debug(
"RGB888 (24-bit)");
break;
1703 case 3:
debug(
"RGB0888 (32-bit)");
break;
1717 debug(
"[ pvr: DIWSIZE set to modulo=%i, " 1718 "width=%i, height=%i ]\n", (
int)
1730 debug(
"[ pvr: FB_RENDER_ADDR1 set to 0x%08" PRIx32
1731 " ]\n", (
int) idata);
1738 debug(
"[ pvr: FB_RENDER_ADDR2 set to 0x%08" PRIx32
1739 " ]\n", (
int) idata);
1746 debug(
"[ pvr: FB_CLIP_X set to min=%i, " 1758 debug(
"[ pvr: FB_CLIP_Y set to min=%i, " 1770 debug(
"[ pvr: SHADOW set to enable=%i, " 1782 debug(
"[ pvr: OBJECT_CLIP 0x%08x ]\n", (
int)idata);
1789 debug(
"[ pvr: OB_CFG 0x%08x ]\n", (
int)idata);
1796 debug(
"[ pvr: UNKNOWN_80 0x%08x ]\n", (
int)idata);
1803 debug(
"[ pvr: UNKNOWN_84 0x%08x ]\n", (
int)idata);
1810 debug(
"[ pvr: BGPLANE_Z 0x%08x ]\n", (
int)idata);
1817 debug(
"[ pvr: BGPLANE_CFG 0x%08x ]\n", (
int)idata);
1824 debug(
"[ pvr: ISP_CFG 0x%08x ]\n", (
int)idata);
1831 debug(
"[ pvr: VRAM_CFG1 set to 0x%08" PRIx32,
1834 fatal(
"{ VRAM_CFG1 = 0x%08" PRIx32
" is not " 1835 "yet implemented! }", (
int) idata);
1843 debug(
"[ pvr: VRAM_CFG2 set to 0x%08" PRIx32,
1846 fatal(
"{ VRAM_CFG2 = 0x%08" PRIx32
" is not " 1847 "yet implemented! }", (
int) idata);
1855 debug(
"[ pvr: VRAM_CFG3 set to 0x%08" PRIx32,
1858 fatal(
"{ VRAM_CFG3 = 0x%08" PRIx32
" is not " 1859 "yet implemented! }", (
int) idata);
1868 debug(
"[ pvr: FOG_TABLE_COL set to 0x%06" PRIx32
" ]\n",
1877 debug(
"[ pvr: FOG_VERTEX_COL set to 0x%06" PRIx32
" ]\n",
1886 debug(
"[ pvr: FOG_DENSITY set to 0x%08" PRIx32
" ]\n",
1895 debug(
"[ pvr: CLAMP_MAX set to 0x%06" PRIx32
" ]\n",
1904 debug(
"[ pvr: CLAMP_MIN set to 0x%06" PRIx32
" ]\n",
1912 debug(
"[ pvr: PVRREG_FB_RENDER_CFG set to 0x%08x ]\n",
1921 debug(
"[ pvr: PVRREG_FB_RENDER_MODULO set to %i ]\n",
1930 debug(
"[ pvr: DIWADDRL set to 0x%08" PRIx32
" ]\n",
1939 debug(
"[ pvr: DIWADDRS set to 0x%08" PRIx32
" ]\n",
1952 debug(
"[ pvr: RASEVTPOS pos1=%i pos2=%i ]\n",
1969 debug(
"[ pvr: SYNCCONF set to: ");
1975 default:
debug(
"*UNKNOWN*");
break;
1989 debug(
"[ pvr: BRDHORZ start=%i stop=%i ]\n",
1999 debug(
"[ pvr: SYNCSIZE v=%i h=%i ]\n",
2009 debug(
"[ pvr: BRDVERT start=%i stop=%i ]\n",
2019 debug(
"[ pvr: SYNCH_WIDTH 0x%08x ]\n", (
int)idata);
2026 debug(
"[ pvr: TSP_CFG 0x%08x ]\n", (
int)idata);
2036 fatal(
"PVRREG_DIWCONF magic not set to " 2037 "Magic value. 0x%08x\n", (
int)idata);
2041 debug(
"[ pvr: PVRREG_DIWCONF: BLANK: TODO ]\n");
2051 debug(
"[ pvr: DIWHSTRT hpos=%i (%s) ]\n",
2052 v, v == 174?
"PAL" :
2054 (v == 144?
"VGA" :
"unknown!")));
2061 debug(
"[ pvr: DIWVSTRT v2=%i v1=%i ]\n",
2071 debug(
"[ pvr: SCALER_CFG 0x%08x ]\n", (
int)idata);
2078 debug(
"[ pvr: PALETTE_CFG 0x%08x ]\n", (
int)idata);
2090 debug(
"[ pvr: MAGIC_110 set to 0x%08" PRIx32,
2093 fatal(
"{ MAGIC_110 = 0x%08" PRIx32
" is not " 2094 "yet implemented! }", (
int) idata);
2102 debug(
"[ pvr: TA_LUMINANCE set to 0x%08" PRIx32
" ]\n",
2111 fatal(
"[ pvr: UNEXPECTED bits in " 2112 "TA_OPB_START: 0x%08x ]\n", (
int)idata);
2116 debug(
"[ pvr: TA_OPB_START set to 0x%x ]\n",
2125 fatal(
"[ pvr: UNEXPECTED bits in " 2126 "TA_OB_START: 0x%08x ]\n", (
int)idata);
2130 debug(
"[ pvr: TA_OB_START set to 0x%x ]\n",
2139 debug(
"[ pvr: TA_OPB_END set to 0x%x ]\n",
2148 debug(
"[ pvr: TA_OB_END set to 0x%x ]\n",
2157 debug(
"[ pvr: TA_OPB_POS set to 0x%x ]\n",
2166 debug(
"[ pvr: TA_OB_POS set to 0x%x ]\n",
2175 debug(
"[ pvr: TA_OPL_INIT set to 0x%x ]\n",
2187 debug(
"[ pvr: TILEBUF_SIZE set to %i x %i ]\n",
2195 debug(
"[ pvr: TA_OPB_CFG set to 0x%x ]\n",
2203 debug(
"[ pvr: TA_INIT ]\n");
2208 if (idata != PVR_TA_INIT && idata != 0)
2209 fatal(
"{ TA_INIT = 0x%08" PRIx32
" is not " 2210 "yet implemented! }", (
int) idata);
2222 default:
if (writeflag ==
MEM_READ) {
2223 fatal(
"[ pvr: read from UNIMPLEMENTED addr 0x%x ]\n",
2224 (
int)relative_addr);
2226 fatal(
"[ pvr: write to UNIMPLEMENTED addr 0x%x: 0x%x" 2227 " ]\n", (
int)relative_addr, (
int)idata);
2251 if ((int64_t)high >= 0 && (int64_t)low <
2252 bytes_per_line * d->
ysize) {
2260 new_y1 = low / bytes_per_line;
2261 new_y2 = high / bytes_per_line + 1;
2279 uint64_t high, low = (uint64_t)(int64_t) -1;
2284 uint8_t *
vram = (uint8_t *) d->
vram;
2320 int x, y, b = rgb & 0xff, g = (rgb >> 8) & 0xff, r = rgb >> 16;
2323 for (y=0; y<d->
fb->
ysize; y++) {
2324 int xskip = y < PVR_MARGIN || y >=
2326 for (x=0; x<d->
fb->
xsize; x++) {
2344 if ((int64_t)low != -1)
2369 int fo = fb_ofs, vo = vram_ofs;
2370 for (p=0; p<pixels_to_copy; p++) {
2379 vram_ofs += bytes_per_line;
2389 int fo = fb_ofs, vo = vram_ofs;
2390 for (p=0; p<pixels_to_copy; p++) {
2399 vram_ofs += bytes_per_line;
2410 memcpy(fb+fb_ofs,
vram+(vram_ofs%
VRAM_SIZE), 3*pixels_to_copy);
2411 vram_ofs += bytes_per_line;
2421 int fo = fb_ofs, vo = vram_ofs;
2422 for (p=0; p<pixels_to_copy; p++) {
2429 vram_ofs += bytes_per_line;
2468 for (i=0; i<len; i++) {
2469 int addr = relative_addr + i;
2470 addr = ((addr & 4) << 20) | (addr & 3)
2471 | ((addr & 0x7ffff8) >> 1);
2478 if (len <
sizeof(uint16_t))
2479 fatal(
"pvr_vram_alt: write of less than 16 bits attempted?\n");
2485 for (i=0; i<len; i++) {
2486 int addr = relative_addr + i;
2487 addr = ((addr & 4) << 20) | (addr & 3) | ((addr & 0x7ffff8) >> 1);
2507 memcpy(
data, d->
vram + relative_addr, len);
2512 if (len <
sizeof(uint16_t))
2513 fatal(
"pvr_vram: write of less than 16 bits attempted?\n");
2523 memcpy(d->
vram + relative_addr,
data, len);
2537 memset(d, 0,
sizeof(
struct pvr_data));
2551 VRAM_SIZE, dev_pvr_vram_access, (
void *)d,
2557 VRAM_SIZE, dev_pvr_vram_alt_access, (
void *)d_alt,
2562 0x10000000, 0x800000, dev_pvr_ta_access, d,
DM_DEFAULT, NULL);
2575 d->bytes_per_pixel = 2;
2580 24,
"Dreamcast PVR");
#define PVR_SPANSORT_SPAN0
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
void * zeroed_alloc(size_t s)
void pvr_extend_update_region(struct pvr_data *d, uint64_t low, uint64_t high)
void fatal(const char *fmt,...)
size_t allocated_ta_commands
#define DIWSIZE_LPF_SHIFT
#define PVRREG_SCALER_CFG
#define PVR_PALETTE_CFG_MODE_ARGB1555
#define BRDHORZ_START_SHIFT
#define PVRREG_SYNCH_WIDTH
#define PVR_PALETTE_CFG_MODE_ARGB8888
#define PVRREG_BGPLANE_CFG
#define DIWSIZE_MODULO_SHIFT
#define TA_OPB_CFG_TRANSPOLY_MASK
#define RASEVTPOS_POS2_MASK
struct vfb_data * dev_fb_init(struct machine *machine, struct memory *mem, uint64_t baseaddr, int vfb_type, int visible_xsize, int visible_ysize, int xsize, int ysize, int bit_depth, const char *name)
#define TA_OPB_CFG_PUNCHTHROUGH_MASK
void pvr_fb_invalidate(struct pvr_data *d, int start, int stop)
#define PVR_FB_TICK_SHIFT
#define PVRREG_FOG_TABLE_COL
uint32_t dmac_sar[N_SH4_DMA_CHANNELS]
#define TA_OPB_CFG_OPAQUEPOLY_MASK
#define PVRREG_UNKNOWN_84
#define PVR_PALETTE_CFG_MODE_ARGB4444
#define DIWMODE_COL_SHIFT
#define BRDVERT_STOP_MASK
#define TILEBUF_SIZE_HEIGHT_MASK
void ieee_interpret_float_value(uint64_t x, struct ieee_float_value *fvp, int fmt)
int vblank_interrupts_pending
#define PVRREG_FOG_VERTEX_COL
#define SYNCCONF_BC_SHIFT
#define PVRREG_FB_RENDER_MODULO
#define SYSASIC_TRIGGER_EVENT(e)
#define SYSASIC_EVENT_VBLINT
#define TA_OPB_CFG_OPAQUEMOD_MASK
#define RASEVTPOS_POS1_MASK
#define TILEBUF_SIZE_HEIGHT_SHIFT
#define CHECK_ALLOCATION(ptr)
#define BRDVERT_START_SHIFT
#define PVR_SPANSORT_TSP_CACHE_ENABLE
#define PVRREG_UNKNOWN_80
#define SYSASIC_EVENT_RENDERDONE
#define PVRREG_STARTRENDER
#define SYSASIC_EVENT_TRANSMODDONE
#define SYSASIC_EVENT_PVR_PTDONE
int(* memory_rw)(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int cache_flags)
#define PVRREG_OBJECT_CLIP
#define DM_READS_HAVE_NO_SIDE_EFFECTS
#define TILEBUF_SIZE_WIDTH_MASK
uint32_t dma_reg[N_PVR_DMA_REGS]
uint32_t dmac_chcr[N_SH4_DMA_CHANNELS]
void pvr_geometry_updated(struct pvr_data *d)
#define SYSASIC_EVENT_PVR_DMA
#define DIWVSTRT_HPOS_MASK
struct timer * timer_add(double freq, void(*timer_tick)(struct timer *timer, void *extra), void *extra)
#define BRDVERT_START_MASK
#define PVRREG_FOG_DENSITY
uint32_t reg[PVRREG_REGSIZE/sizeof(uint32_t)]
#define DM_DYNTRANS_WRITE_OK
#define PVR_DMA_MEMLENGTH
#define TA_OPB_CFG_TRANSMOD_MASK
#define DIWSIZE_DPL_SHIFT
void pvr_ta_init(struct cpu *cpu, struct pvr_data *d)
#define BRDHORZ_STOP_MASK
#define SYSASIC_EVENT_TRANSDONE
#define PVR_TILEBUF_ADDR_MASK
#define SHADOW_INTENSITY_MASK
#define CHCR_SM_DECREMENTED
#define TSP_CFG_MODULO_MASK
void pvr_dma_transfer(struct cpu *cpu, struct pvr_data *d)
#define PVR_SPANSORT_SPAN1
#define FB_RENDER_CFG_RENDER_MODE_MASK
#define TA_OPB_START_MASK
#define SYSASIC_EVENT_PVR_SCANINT2
#define SYSASIC_EVENT_OPAQUEDONE
uint32_t dmac_dar[N_SH4_DMA_CHANNELS]
#define FB_CLIP_XY_MAX_MASK
#define DIWVSTRT_V2_SHIFT
#define PVRREG_TA_OPB_END
uint32_t dmac_tcr[N_SH4_DMA_CHANNELS]
#define DIWCONF_MAGIC_MASK
#define SYSASIC_EVENT_OPAQUEMODDONE
#define SYSASIC_EVENT_PVR_SCANINT1
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
#define FB_CLIP_XY_MIN_MASK
#define PVRREG_PALETTE_CFG
unsigned char * framebuffer
#define PVR_FOG_TABLE_SIZE
#define CHCR_DM_DECREMENTED
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
struct timer * vblank_timer
#define PVRREG_TILEBUF_ADDR
#define PVRREG_TILEBUF_SIZE
void memory_device_dyntrans_access(struct cpu *, struct memory *mem, void *extra, uint64_t *low, uint64_t *high)
uint32_t dma_more_reg[N_PVR_DMA_REGS]
addr & if(addr >=0x24 &&page !=NULL)
#define VRAM_CFG1_GOOD_REFRESH_VALUE
uint32_t ta[64/sizeof(uint32_t)]
#define PVR_TA_OPL_INIT_MASK
#define PVR_PALETTE_CFG_MODE_MASK
#define PVRREG_FB_RENDER_CFG
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
#define RASEVTPOS_POS1_SHIFT
#define CHCR_DM_INCREMENTED
#define CHCR_SM_INCREMENTED
#define PVRREG_TA_OPB_CFG
#define PVRREG_FB_RENDER_ADDR2
#define PVRREG_TA_OB_START
#define PVRREG_TA_OPB_START
#define PVRREG_TA_LUMINANCE
#define BRDHORZ_START_MASK
#define VRAM_CFG2_UNKNOWN_MAGIC
#define PVRREG_FB_RENDER_ADDR1
#define PVRREG_TA_OPL_INIT
#define PVR_PALETTE_CFG_MODE_RGB565
#define FB_CLIP_XY_MAX_SHIFT
void pvr_render(struct cpu *cpu, struct pvr_data *d)
#define VRAM_CFG3_UNKNOWN_MAGIC
#define PVRREG_TA_OPB_POS