dev_pvr.cc Source File

Back to the index.

dev_pvr.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2018 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * COMMENT: PowerVR CLX2 (graphics controller used in the Dreamcast)
29  *
30  * Implemented by reading http://www.ludd.luth.se/~jlo/dc/powervr-reg.txt and
31  * http://mc.pp.se/dc/pvr.html, source code of various demos and KallistiOS,
32  * attempting to run the PROM from my own Dreamcast, and doing a lot of
33  * guessing.
34  *
35  * TODO: Almost everything
36  *
37  * x) Change resolution during runtime (PAL/NTSC/???)
38  *
39  * x) Lots of work on the 3D "Tile Accelerator" engine.
40  * Recognize commands and turn into OpenGL or similar
41  * commands on the host?
42  * Wire-frame when running on a host without XGL?
43  *
44  * Multiple lists of various kinds (6?).
45  * Lists growing downwards!
46  * Pixel clip for rendering.
47  * Real Rendering, using OpenGL if possible.
48  * Tile bins... with 6 pointers for each tile (?)
49  * PVR DMA.
50  * Textures.
51  * ...
52  */
53 
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 
58 #include "cpu.h"
59 #include "device.h"
60 #include "devices.h"
61 #include "float_emul.h"
62 #include "machine.h"
63 #include "memory.h"
64 #include "misc.h"
65 #include "timer.h"
66 
69 
70 
71 /* For debugging: */
72 //#define DEBUG_RENDER_AS_WIRE_FRAME // Renders 3-corner textured polygons as wire-frame
73 //#define TA_DEBUG // Dumps TA commands
74 //#define debug fatal // Dumps debug even without -v.
75 
76 #define INTERNAL_FB_ADDR 0x300000000ULL
77 #define PVR_FB_TICK_SHIFT 18
78 
79 #define PVR_VBLANK_HZ 60.0
80 
81 #define PVR_MARGIN 16
82 
83 #define VRAM_SIZE (8*1048576)
84 
85 /* DMA: */
86 #define PVR_DMA_MEMLENGTH 0x100
87 #define N_PVR_DMA_REGS (PVR_DMA_MEMLENGTH / sizeof(uint32_t))
88 
89 #define PVR_ADDR 0x00
90 #define PVR_COUNT 0x04
91 #define PVR_MODE 0x08
92 #define PVR_LMMODE0 0x84
93 #define PVR_LMMODE1 0x88
94 
95 
96 struct pvr_data {
97  struct vfb_data *fb;
102 
105 
106  /* PVR registers: */
107  uint32_t reg[PVRREG_REGSIZE / sizeof(uint32_t)];
108 
109  /* Calculated by pvr_geometry_updated(): */
110  int xsize, ysize;
112 
113  /* Cached values (from registers): */
114  /* DIWMODE: */
119  int extend;
123  /* BRDCOLR: */
125  /* SYNCCONF: */
131  /* TILEBUF_SIZE: */
134 
135  /* Current Tile Accelerator Command (64 bytes): */
136  uint32_t ta[64 / sizeof(uint32_t)];
137 
138  /* Stored list of TA commands: */
140  uint32_t *ta_commands;
143 
144  /* Video RAM and Z information: */
145  uint8_t *vram;
146  double *vram_z;
147 
148  /* DMA registers: */
151 };
152 
153 struct pvr_data_alt {
154  struct pvr_data *d;
155 };
156 
157 
158 #define REG(x) (d->reg[(x)/sizeof(uint32_t)])
159 #define DEFAULT_WRITE REG(relative_addr) = idata;
160 
161 
162 /* Forward declaration. */
163 DEVICE_ACCESS(pvr_ta);
164 
165 
166 void pvr_dma_transfer(struct cpu *cpu, struct pvr_data *d)
167 {
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;
172  uint32_t chcr = cpu->cd.sh.dmac_chcr[channel];
173  int transmit_size = 1;
174  int src_delta = 0, dst_delta = 0;
175  int cause_interrupt = chcr & CHCR_IE;
176 
177 #if 0
178  // Dump all SH4 DMA channels, for debugging:
179  for (int dmaChannel = 0; dmaChannel < 4; ++dmaChannel)
180  {
181  fatal("{# dma channel %i: sar=%08x dar=%08x count=%08x chcr=%08x #}\n",
182  dmaChannel,
183  cpu->cd.sh.dmac_sar[dmaChannel],
184  cpu->cd.sh.dmac_dar[dmaChannel],
185  cpu->cd.sh.dmac_tcr[dmaChannel],
186  cpu->cd.sh.dmac_chcr[dmaChannel]);
187  }
188 #endif
189 
190  /* DMAC not enabled? */
191  if (!(chcr & CHCR_TD)) {
192  fatal("pvr_dma_transfer: SH4 dma not enabled?\n");
193  exit(1);
194  }
195 
196  /* Transfer End already set? Then don't transfer again. */
197  if (chcr & CHCR_TE)
198  return;
199 
200  /* Special case: 0 means 16777216: */
201  if (count == 0)
202  count = 16777216;
203 
204  switch (chcr & CHCR_TS) {
205  case CHCR_TS_8BYTE: transmit_size = 8; break;
206  case CHCR_TS_1BYTE: transmit_size = 1; break;
207  case CHCR_TS_2BYTE: transmit_size = 2; break;
208  case CHCR_TS_4BYTE: transmit_size = 4; break;
209  case CHCR_TS_32BYTE: transmit_size = 32; break;
210  default: fatal("Unimplemented transmit size?! CHCR[%i] = 0x%08x\n",
211  channel, chcr);
212  exit(1);
213  }
214 
215  switch (chcr & CHCR_DM) {
216  case CHCR_DM_FIXED: dst_delta = 0; break;
217  case CHCR_DM_INCREMENTED: dst_delta = 1; break;
218  case CHCR_DM_DECREMENTED: dst_delta = -1; break;
219  default: fatal("Unimplemented destination delta?! CHCR[%i] = 0x%08x\n",
220  channel, chcr);
221  exit(1);
222  }
223 
224  switch (chcr & CHCR_SM) {
225  case CHCR_SM_FIXED: src_delta = 0; break;
226  case CHCR_SM_INCREMENTED: src_delta = 1; break;
227  case CHCR_SM_DECREMENTED: src_delta = -1; break;
228  default: fatal("Unimplemented source delta?! CHCR[%i] = 0x%08x\n",
229  channel, chcr);
230  exit(1);
231  }
232 
233  src_delta *= transmit_size;
234  dst_delta *= transmit_size;
235 
236  switch (chcr & CHCR_RS) {
237  case 0x200:
238  dar = d->dma_reg[PVR_ADDR / sizeof(uint32_t)];
239 
240  if (dar != 0x10000000) {
241  //fatal("[ NOTE: DMA to non-TA: dar=%08x (delta %i), sar=%08x (delta %i) ]\n",
242  // (int)dar, (int)dst_delta, (int)sar, (int)src_delta);
243  dar = 0x04000000 | (dar & 0x007fffff);
244  if (dst_delta == 0)
245  dst_delta = src_delta;
246 
247  uint8_t *buf = (uint8_t*) malloc(transmit_size);
248  while (count > 0) {
249  // printf("sar = %08x dar = %08x\n", (int)sar, (int)dar);
250 
251  cpu->memory_rw(cpu, cpu->mem, sar, buf,
252  transmit_size, MEM_READ, NO_EXCEPTIONS | PHYSICAL);
253  // for (int i = 0; i < transmit_size; ++i)
254  // printf("%02x ", buf[i]);
255  // printf("\n");
256 
257  cpu->memory_rw(cpu, cpu->mem, dar, buf,
258  transmit_size, MEM_WRITE, NO_EXCEPTIONS | PHYSICAL);
259 
260  count --;
261  sar += src_delta;
262  dar += dst_delta;
263  }
264 
265  free(buf);
266 
267  break;
268  } else {
269  while (count > 0) {
270  unsigned char buf[sizeof(uint32_t)];
271  int ofs;
272  size_t chunksize = transmit_size;
273 
274  if (chunksize > sizeof(uint32_t))
275  chunksize = sizeof(uint32_t);
276 
277  for (ofs = 0; ofs < transmit_size; ofs += chunksize) {
278  cpu->memory_rw(cpu, cpu->mem, sar + ofs, buf,
279  chunksize, MEM_READ, NO_EXCEPTIONS | PHYSICAL);
280 
281  dev_pvr_ta_access(cpu, cpu->mem, ofs, buf, chunksize,
282  MEM_WRITE, d);
283  }
284 
285  count --;
286  sar += src_delta;
287  }
288  }
289 
290  // Transfer End. TODO: _EXACTLY_ what happens at the end of
291  // a transfer?
292  cpu->cd.sh.dmac_chcr[channel] |= CHCR_TE;
293  cpu->cd.sh.dmac_chcr[channel] &= ~CHCR_TD;
294  cpu->cd.sh.dmac_sar[channel] = sar;
295  cpu->cd.sh.dmac_tcr[channel] = count;
296 
297  // d->dma_reg[PVR_ADDR / sizeof(uint32_t)] = ???;
298  d->dma_reg[PVR_COUNT / sizeof(uint32_t)] = 0;
299 
301 
302  break;
303  default:
304  fatal("Unimplemented SH4 RS DMAC: 0x%08x (PVR)\n",
305  (int) (chcr & CHCR_RS));
306  exit(1);
307  }
308 
309  if (cause_interrupt) {
310  fatal("TODO: pvr sh4 dmac interrupt!\n");
311  exit(1);
312  }
313 }
314 
315 
317 {
318  struct pvr_data *d = (struct pvr_data *) extra;
319  uint64_t idata = 0, odata = 0;
320 
321  if (writeflag == MEM_WRITE)
322  idata = memory_readmax64(cpu, data, len);
323 
324  /* Default read: */
325  if (writeflag == MEM_READ)
326  odata = d->dma_reg[relative_addr / sizeof(uint32_t)];
327 
328  switch (relative_addr) {
329 
330  case PVR_ADDR:
331  if (writeflag == MEM_WRITE) {
332  debug("[ pvr_dma: ADDR set to 0x%08x ]\n",
333  (int) idata);
334  }
335  break;
336 
337  case PVR_COUNT:
338  if (writeflag == MEM_WRITE) {
339  debug("[ pvr_dma: COUNT set to 0x%08x ]\n",
340  (int) idata);
341  }
342  break;
343 
344  case PVR_MODE:
345  if (writeflag == MEM_WRITE) {
346  debug("[ pvr_dma: MODE set to 0x%08x ]\n",
347  (int) idata);
348  if (idata != 0) {
349  pvr_dma_transfer(cpu, d);
350  idata = 0;
351  }
352  }
353  break;
354 
355  /* These are written to by the Dreamcast ROM, but I have not
356  found them documented anywhere. */
357  case 0x10:
358  case 0x14:
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);
362  exit(1);
363  }
364  break;
365 
366  case 0x18:
367  case 0x1c:
368  case 0x20:
369  case 0x40:
370  case 0x44:
371  case 0x48:
372  case 0x4c:
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);
376  exit(1);
377  }
378  break;
379 
380  case PVR_LMMODE0: /* 0x84 */
381  if (writeflag == MEM_WRITE && idata != 0) {
382  fatal("[ pvr_dma: TODO: LMMODE0 set to "
383  "0x%08x ]\n", (int) idata);
384  exit(1);
385  }
386  break;
387 
388  case PVR_LMMODE1: /* 0x88 */
389  if (writeflag == MEM_WRITE && idata != 0) {
390  fatal("[ pvr_dma: TODO: LMMODE1 set to "
391  "0x%08x ]\n", (int) idata);
392  exit(1);
393  }
394  break;
395 
396  case 0x8c:
397  if (writeflag == MEM_WRITE) {
398  fatal("[ pvr_dma: write to 0x8c: TODO ]\n");
399  exit(1);
400  } else {
401  /* 0x20 means G2 DMA in progress? */
402  /* 0x11 = mask which has to do with AICA */
403  odata = 0x11 * (random() & 1);
404  }
405  break;
406 
407  case 0x9c:
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);
411  exit(1);
412  }
413  break;
414 
415  case 0xa0:
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);
419  exit(1);
420  }
421  break;
422 
423  case 0xa4:
424  case 0xac:
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);
428  exit(1);
429  }
430  break;
431 
432  default:if (writeflag == MEM_READ) {
433  fatal("[ pvr_dma: read from addr 0x%x ]\n",
434  (int)relative_addr);
435  } else {
436  fatal("[ pvr_dma: write to addr 0x%x: 0x%x ]\n",
437  (int)relative_addr, (int)idata);
438  }
439 
440  exit(1);
441  }
442 
443  /* Default write: */
444  if (writeflag == MEM_WRITE)
445  d->dma_reg[relative_addr / sizeof(uint32_t)] = idata;
446 
447  if (writeflag == MEM_READ)
448  memory_writemax64(cpu, data, len, odata);
449 
450  return 1;
451 }
452 
453 
454 DEVICE_ACCESS(pvr_dma_more)
455 {
456  struct pvr_data *d = (struct pvr_data *) extra;
457  uint64_t idata = 0, odata = 0;
458 
459  if (writeflag == MEM_WRITE)
460  idata = memory_readmax64(cpu, data, len);
461 
462  /* Default read: */
463  if (writeflag == MEM_READ)
464  odata = d->dma_more_reg[relative_addr / sizeof(uint32_t)];
465 
466  switch (relative_addr) {
467 
468  case 0x00: // 0x04ff0000
469  case 0x04: // 0x0cff0000
470  case 0x08: // 0x00000020
471  case 0x0c: // 0x00000000
472  case 0x10: // 0x00000000
473  case 0x80: // 0x67027f00
474  break;
475 
476  case 0x14:
477  case 0x18:
478  if (writeflag == MEM_WRITE && idata != 0)
479  {
480  fatal("PVR other DMA mode (?):\n");
481  fatal("0x00: %08x\n", d->dma_more_reg[0x00/4]);
482  fatal("0x04: %08x\n", d->dma_more_reg[0x04/4]);
483  fatal("0x08: %08x\n", d->dma_more_reg[0x08/4]);
484  fatal("0x0c: %08x\n", d->dma_more_reg[0x0c/4]);
485  fatal("0x10: %08x\n", d->dma_more_reg[0x10/4]);
486  fatal("0x14: %08x\n", d->dma_more_reg[0x14/4]);
487  exit(1);
488  }
489  break;
490 
491  default:if (writeflag == MEM_READ) {
492  fatal("[ pvr_dma_more: read from addr 0x%x ]\n",
493  (int)relative_addr);
494  } else {
495  fatal("[ pvr_dma_more: write to addr 0x%x: 0x%x ]\n",
496  (int)relative_addr, (int)idata);
497  }
498 
499  exit(1);
500  }
501 
502  /* Default write: */
503  if (writeflag == MEM_WRITE)
504  d->dma_more_reg[relative_addr / sizeof(uint32_t)] = idata;
505 
506  if (writeflag == MEM_READ)
507  memory_writemax64(cpu, data, len, odata);
508 
509  return 1;
510 }
511 
512 
513 /*
514  * pvr_fb_invalidate():
515  */
516 void pvr_fb_invalidate(struct pvr_data *d, int start, int stop)
517 {
518  d->fb_update_x1 = d->fb_update_y1 = 0;
519  d->fb_update_x2 = d->xsize - 1;
520  d->fb_update_y2 = d->ysize - 1;
521 }
522 
523 
524 /*
525  * pvr_vblank_timer_tick():
526  *
527  * This function is called PVR_VBLANK_HZ times per real-world second. Its job
528  * is to fake vertical retrace interrupts.
529  */
530 static void pvr_vblank_timer_tick(struct timer *t, void *extra)
531 {
532  struct pvr_data *d = (struct pvr_data *) extra;
534 }
535 
536 
537 /*
538  * pvr_geometry_updated():
539  *
540  * This function should be called every time a register is written to which
541  * affects the framebuffer geometry (size, bit-depth, starting position, etc).
542  */
544 {
545  int old_xsize = d->xsize, old_ysize = d->ysize, oldbpp = d->bytes_per_pixel;
546 
547  /* Make sure to redraw border on geometry changes. */
548  d->border_updated = 1;
549 
552 
553  /* E.g. 319x479 => 320x480 */
554  d->xsize = (d->xsize + 1) * sizeof(uint32_t);
555  d->ysize ++;
556 
557  switch (d->pixelmode) {
558  case 0:
559  case 1: d->bytes_per_pixel = 2; break;
560  case 2: d->bytes_per_pixel = 3; break;
561  case 3: d->bytes_per_pixel = 4; break;
562  }
563 
564  d->xsize /= d->bytes_per_pixel;
565 
567  d->xsize /= 2;
568 
569  if (d->line_double)
570  d->ysize /= 2;
571 
572  bool settingsChanged = d->xsize != old_xsize ||
573  d->ysize != old_ysize ||
574  d->bytes_per_pixel != oldbpp;
575 
576  if (!settingsChanged)
577  return;
578 
579  /* Scrap Z buffer if we have one. */
580  if (d->vram_z == NULL) {
581  free(d->vram_z);
582  d->vram_z = NULL;
583  }
584 
585  /* Only show geometry debug message if output is enabled: */
586  if (!d->video_enabled || !d->display_enabled)
587  return;
588 
589  debug("[ pvr_geometry_updated: %i x %i, ", d->xsize, d->ysize);
590 
591  switch (d->pixelmode) {
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;
596  }
597 
598  debug(" ]\n");
599 }
600 
601 
602 #ifdef DEBUG_RENDER_AS_WIRE_FRAME
603 /* Ugly quick-hack: */
604 static void line(struct pvr_data *d, int x1, int y1, int x2, int y2)
605 {
606  int fb_base = REG(PVRREG_FB_RENDER_ADDR1);
607  int i;
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) *
613  d->bytes_per_pixel;
614  d->vram[(ofs+0) % VRAM_SIZE] = 255;
615  d->vram[(ofs+1) % VRAM_SIZE] = 255;
616  }
617  }
618 }
619 #endif
620 
621 
622 // Ugly quick-hack z-buffer line drawer, for triangles.
623 // Assumes 16-bit color.
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)
627 {
628  if (y < 0 || y >= d->ysize || (x1 < 0 && x2 < 0)
629  || (x1 >= d->xsize && x2 >= d->xsize))
630  return;
631 
632  int fb_base = REG(PVRREG_FB_RENDER_ADDR1);
633  if (x1 > x2) {
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;
639  }
640 
641  // uint32_t fogDensity = REG(PVRREG_FOG_DENSITY);
642  // double scale_factor = 255.0; // TODO: take fogDensity into account.
643  // uint32_t fogColor = REG(PVRREG_FOG_TABLE_COL);
644  // int fog_r = (fogColor >> 16) & 255;
645  // int fog_g = (fogColor >> 8) & 255;
646  // int fog_b = fogColor & 255;
647 
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) {
657  d->vram_z[ofs] = z;
658 
659  // z = 1/w
660  // int v = z * scale_factor;
661  // printf("z=%f v=%i\n", z, v);
662  // if (v < 0) v = 0;
663  // if (v > 255) v = 255;
664  // v >>= 1;
665 
666  // int fogvalues = d->reg[PVRREG_FOG_TABLE / sizeof(uint32_t) + v];
667  // printf("fogv = %04x\n", fogvalues);
668 
669  // NOTE/TODO: Hardcoded for 565 pixelformat.
670  int ri = r, gi = g, bi = b;
671  // int a = (fogvalues >> 8) & 255;
672  // ri = ((fog_r * a) + (ri * (255 - a))) >> 8;
673  // gi = ((fog_g * a) + (gi * (255 - a))) >> 8;
674  // bi = ((fog_b * a) + (bi * (255 - a))) >> 8;
675 
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);
680 
681  int fbofs = fb_base + ofs * d->bytes_per_pixel;
682  d->vram[(fbofs+0) % VRAM_SIZE] = color & 255;
683  d->vram[(fbofs+1) % VRAM_SIZE] = color >> 8;
684  }
685  }
686 
687  z += dz12; r += dr12; g += dg12; b += db12;
688  }
689 }
690 
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)
696 {
697  if (y < 0 || y >= d->ysize || (x1 < 0 && x2 < 0)
698  || (x1 >= d->xsize && x2 >= d->xsize))
699  return;
700 
701  int fb_base = REG(PVRREG_FB_RENDER_ADDR1);
702  if (x1 > x2) {
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;
707  }
708 
709  int bytesperpixel = 2;
710 
711  switch (texture_pixelformat)
712  {
713  case 0: // ARGB1555
714  case 1: // RGB565
715  case 2: // ARGB4444
716  bytesperpixel = 2;
717  break;
718  case 6: // 8-bit palette
719  bytesperpixel = 1;
720  break;
721  default:
722  // TODO
723  break;
724  }
725 
726  int palette_cfg = d->reg[PVRREG_PALETTE_CFG / sizeof(uint32_t)] & PVR_PALETTE_CFG_MODE_MASK;
727 
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;
731 
732  double z = z1, u = u1, v = v1;
733 
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) {
738  d->vram_z[ofs] = z;
739 
740  int fbofs = fb_base + ofs * d->bytes_per_pixel;
741 
742  // Get color from texture:
743  int texturex = u * texture_xsize;
744  texturex &= (texture_xsize-1);
745  int texturey = v * texture_ysize;
746  texturey &= (texture_ysize-1);
747 
748  int textureofs;
749  if (twiddled) {
750  texturex =
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);
753  texturey =
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;
757  } else {
758  if (stride > 0)
759  textureofs = texturex + texturey * stride;
760  else
761  textureofs = texturex + texturey * texture_xsize;
762  }
763 
764  textureofs *= bytesperpixel; // 2 bytes per pixel.
765 
766  int addr = texture + textureofs;
767  addr = ((addr & 4) << 20) | (addr & 3) | ((addr & 0x7ffff8) >> 1);
768 
769  int a = 255, r = 64, g = 64, b = 64;
770  switch (texture_pixelformat)
771  {
772  case 0: // ARGB1555:
773  {
774  int color = d->vram[addr] + (d->vram[addr+1] << 8);
775  a = (color >> 15) & 0x1 ? 255 : 0;
776  r = (color >> 10) & 0x1f;
777  g = ((color >> 5) & 0x1f) << 1;
778  b = (color) & 0x1f;
779  }
780  break;
781  case 1: // RGB565:
782  {
783  int color = d->vram[addr] + (d->vram[addr+1] << 8);
784  r = (color >> 11) & 0x1f;
785  g = (color >> 5) & 0x3f;
786  b = (color) & 0x1f;
787  }
788  break;
789  case 2: // ARGB4444:
790  {
791  int color = d->vram[addr] + (d->vram[addr+1] << 8);
792  a = ((color >> 12) & 15) * 0x11;
793  r = ((color >> 8) & 15) << 1;
794  g = ((color >> 4) & 15) << 2;
795  b = ((color) & 15) << 1;
796  }
797  break;
798  case 6:
799  {
800  // TODO: multiple palette banks? Endianness?
801  int index8bpp = d->vram[addr];
802  char* base = (char*)&d->reg[PVRREG_PALETTE / sizeof(uint32_t)];
803  uint16_t c16 = *((uint16_t*)(void*)base + index8bpp);
804  uint16_t c32 = *((uint32_t*)(void*)base + index8bpp);
805  switch (palette_cfg) {
807  a = (c16 >> 15) & 0x1 ? 255 : 0;
808  r = (c16 >> 10) & 0x1f;
809  g = ((c16 >> 5) & 0x1f) << 1;
810  b = (c16) & 0x1f;
811  break;
813  r = (c16 >> 11) & 0x1f;
814  g = (c16 >> 5) & 0x3f;
815  b = (c16) & 0x1f;
816  break;
818  a = ((c16 >> 12) & 15) * 0x11;
819  r = ((c16 >> 8) & 15) << 1;
820  g = ((c16 >> 4) & 15) << 2;
821  b = ((c16) & 15) << 1;
822  break;
824  a = (c32 >> 24) & 255;
825  r = ((c32 >> 16) & 255) >> 3;
826  g = ((c32 >> 8) & 255) >> 2;
827  b = ((c32) & 255) >> 3;
828  break;
829  }
830  }
831  break;
832  default:
833  fatal("pvr: unimplemented texture_pixelformat %i\n", texture_pixelformat);
834  exit(1);
835  }
836 
837  if (a == 255)
838  {
839  // Output as RGB565:
840  // TODO: Support other formats.
841  int color = (r << 11) + (g << 5) + (b);
842  d->vram[(fbofs+0) % VRAM_SIZE] = color & 255;
843  d->vram[(fbofs+1) % VRAM_SIZE] = color >> 8;
844  } else if (a > 0) {
845  int oldcolor = d->vram[(fbofs+0) % VRAM_SIZE];
846  oldcolor += (d->vram[(fbofs+1) % VRAM_SIZE] << 8);
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);
854  d->vram[(fbofs+0) % VRAM_SIZE] = color & 255;
855  d->vram[(fbofs+1) % VRAM_SIZE] = color >> 8;
856  }
857  }
858  }
859 
860  z += dz12;
861  u += du12;
862  v += dv12;
863  }
864 }
865 
866 
867 // Slow software rendering, for debugging:
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)
872 {
873  // Easiest if 1, 2, 3 are in order top to bottom.
874  if (y2 < y1) {
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;
881  }
882 
883  if (y3 < y1) {
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;
890  }
891 
892  if (y3 < y2) {
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;
899  }
900 
901  if (y3 < 0 || y1 >= d->ysize)
902  return;
903 
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;
907 
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;
911 
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;
915 
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;
919 
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;
923 
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)
927  {
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;
931  }
932 
933  stopx = x2; stopz = z2; stopr = r2; stopg = g2; stopb = b2;
934  for (int y = y2; y < y3; ++y)
935  {
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;
939  }
940 
941 #ifdef DEBUG_RENDER_AS_WIRE_FRAME
942  // Wire-frame test:
943  line(d, x1, y1, x2, y2);
944  line(d, x1, y1, x3, y3);
945  line(d, x2, y2, x3, y3);
946 #endif
947 }
948 
949 
950 // Slow software rendering, for debugging:
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)
957 {
958  // Easiest if 1, 2, 3 are in order top to bottom.
959  if (y2 < y1) {
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;
965  }
966 
967  if (y3 < y1) {
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;
973  }
974 
975  if (y3 < y2) {
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;
981  }
982 
983  if (y3 < 0 || y1 >= d->ysize)
984  return;
985 
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;
989 
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;
993 
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;
997 
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;
1001 
1002  double startx = x1, startz = z1, startu = u1, startv = v1;
1003  double stopx = x1, stopz = z1, stopu = u1, stopv = v1;
1004 
1005  for (int y = y1; y < y2; ++y)
1006  {
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;
1010  }
1011 
1012  stopx = x2; stopz = z2; stopu = u2; stopv = v2;
1013  for (int y = y2; y < y3; ++y)
1014  {
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;
1018  }
1019 
1020 #ifdef DEBUG_RENDER_AS_WIRE_FRAME
1021  // Wire-frame test:
1022  line(d, x1, y1, x2, y2);
1023  line(d, x1, y1, x3, y3);
1024  line(d, x2, y2, x3, y3);
1025 #endif
1026 }
1027 
1028 
1029 static void pvr_clear_ta_commands(struct pvr_data* d)
1030 {
1031  d->n_ta_commands = 0;
1032 }
1033 
1034 
1035 /*
1036  * pvr_render():
1037  *
1038  * Render from the Object Buffer to the framebuffer.
1039  *
1040  * TODO: This function is totally bogus so far, the format of the Object
1041  * Buffer is just a quick made-up hack to see if it works at all.
1042  */
1043 void pvr_render(struct cpu *cpu, struct pvr_data *d)
1044 {
1045  int fb_render_cfg = REG(PVRREG_FB_RENDER_CFG);
1046  int fb_base = REG(PVRREG_FB_RENDER_ADDR1);
1047 
1048  if ((fb_render_cfg & FB_RENDER_CFG_RENDER_MODE_MASK) != 0x1) {
1049  printf("pvr: only RGB565 rendering has been implemented\n");
1050  exit(1);
1051  }
1052 
1053  // Settings for the current polygon being rendered:
1054  // Word 0:
1055  int listtype = 0;
1056  int striplength = 0;
1057  int clipmode;
1058  int modifier;
1059  int modifier_mode;
1060  int color_type = 0;
1061  bool texture = false;
1062  bool specular;
1063  bool shading;
1064  bool uv_format;
1065 
1066  // Word 1:
1067  int depthmode;
1068  int cullingmode = 0;
1069  bool zwrite;
1070  bool texture1;
1071  bool specular1;
1072  bool shading1;
1073  bool uv_format1;
1074  bool dcalcexact;
1075 
1076  // Word 2:
1077  int fog = 0;
1078  int texture_usize = 0, texture_vsize = 0;
1079 
1080  // Word 3:
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;
1087 
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];
1091 
1092  double baseRed = 0.0, baseGreen = 0.0, baseBlue = 0.0;
1093 
1094  debug("[ pvr_render: rendering to FB offset 0x%x, "
1095  "%i Tile Accelerator commands ]\n", fb_base, d->n_ta_commands);
1096 
1097  /*
1098  * Clear all pixels first.
1099  * TODO: Maybe only clear the specific tiles that are in use by
1100  * the tile accelerator?
1101  * TODO: What background color to use? See KOS' pvr_misc.c for
1102  * how KOS sets the background.
1103  */
1104  memset(d->vram + fb_base, 0x00, d->xsize * d->ysize * d->bytes_per_pixel);
1105 
1106  /* Clear Z as well: */
1107  if (d->vram_z == NULL) {
1108  d->vram_z = (double*) malloc(sizeof(double) * d->xsize * d->ysize);
1109  }
1110 
1111  uint32_t bgplaneZ = REG(PVRREG_BGPLANE_Z);
1112  struct ieee_float_value backgroundz;
1113  ieee_interpret_float_value(bgplaneZ, &backgroundz, IEEE_FMT_S);
1114  for (int q = 0; q < d->xsize * d->ysize; ++q)
1115  d->vram_z[q] = backgroundz.f;
1116 
1117  // Using names from http://www.ludd.luth.se/~jlo/dc/ta-intro.txt.
1118  for (size_t index = 0; index < d->n_ta_commands; ++index) {
1119  // list points to 8 or 16 words.
1120  uint32_t* list = &d->ta_commands[index * 16];
1121  int cmd = (list[0] >> 29) & 7;
1122 
1123  switch (cmd)
1124  {
1125  case 0: // END_OF_LIST
1126  // Interrupt event already triggered in pvr_ta_command().
1127 #ifdef TA_DEBUG
1128  fatal("\nTA end_of_list (list type %i)\n", d->current_list_type);
1129 #endif
1130  break;
1131 
1132  case 1: // USER_CLIP
1133  // TODO: Ignoring for now.
1134  break;
1135 
1136  case 4: // polygon or modifier volume
1137  {
1138  vertex_index = 0;
1139 
1140  // List Word 0:
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;
1153 
1154 #ifdef TA_DEBUG
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");
1165 #endif
1166 
1167  // List Word 1:
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;
1176 
1177 #ifdef TA_DEBUG
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");
1186 #endif
1187 
1188  if (!zwrite) {
1189  fatal("pvr: no zwrite? not implemented yet.\n");
1190  exit(1);
1191  }
1192 
1193  // For now, trust texture and ignore texture1.
1194  // if (texture != texture1) {
1195  // fatal("pvr: texture != texture1. what to do?\n");
1196  // exit(1);
1197  // }
1198 
1199  // List Word 2:
1200  // TODO: srcblend (31-29)
1201  // TODO: dstblend (28-26)
1202  // TODO: srcmode (25)
1203  // TODO: dstmode (24)
1204  fog = (list[2] >> 22) & 3;
1205  // TODO: clamp (21)
1206  // TODO: alpha (20)
1207  // TODO: texture alpha (19)
1208  // TODO: uv flip (18-17)
1209  // TODO: uv clamp (16-15)
1210  // TODO: filter (14-12)
1211  // TODO: mipmap (11-8)
1212  // TODO: texture shading (7-6)
1213  texture_usize = 8 << ((list[2] >> 3) & 7);
1214  texture_vsize = 8 << (list[2] & 7);
1215 
1216  // List Word 3:
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;
1223 
1224 #ifdef TA_DEBUG
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);
1231 #endif
1232 
1233  if (fog != 2)
1234  fatal("[ pvr: fog type %i not yet implemented ]\n", fog);
1235 
1236  if (texture_vq_compression) {
1237  fatal("pvr: texture_vq_compression not supported yet\n");
1238  // exit(1);
1239  }
1240 
1241  struct ieee_float_value r, g, b;
1242  ieee_interpret_float_value(list[5], &r, IEEE_FMT_S);
1243  ieee_interpret_float_value(list[6], &g, IEEE_FMT_S);
1244  ieee_interpret_float_value(list[7], &b, IEEE_FMT_S);
1245  baseRed = r.f * 255;
1246  baseGreen = g.f * 255;
1247  baseBlue = b.f * 255;
1248  // printf("rgb = %f %f %f\n", r.f, g.f, b.f);
1249  break;
1250  }
1251 
1252  case 7: // vertex
1253  {
1254  // MAJOR TODO:
1255  // How to select which one of the 18 (!) types listed
1256  // in http://www.ludd.luth.se/~jlo/dc/ta-intro.txt to
1257  // use?
1258  if (listtype != 0 && listtype != 2 && listtype != 4)
1259  break;
1260 
1261  bool eos = (list[0] >> 28) & 1;
1262 
1263  struct ieee_float_value fx, fy, fz, u, v, extra1, extra2;
1264  ieee_interpret_float_value(list[1], &fx, IEEE_FMT_S);
1265  ieee_interpret_float_value(list[2], &fy, IEEE_FMT_S);
1266  ieee_interpret_float_value(list[3], &fz, IEEE_FMT_S);
1267  wf_x[vertex_index] = fx.f;
1268  wf_y[vertex_index] = fy.f;
1269  wf_z[vertex_index] = fz.f;
1270 
1271 #ifdef TA_DEBUG
1272  fatal("TA vertex %f %f %f%s\n", fx.f, fy.f, fz.f,
1273  eos ? " end_of_strip" : "");
1274 #endif
1275 
1276  if (texture) {
1277  ieee_interpret_float_value(list[4], &u, IEEE_FMT_S);
1278  ieee_interpret_float_value(list[5], &v, IEEE_FMT_S);
1279  wf_u[vertex_index] = u.f;
1280  wf_v[vertex_index] = v.f;
1281  } else {
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) {
1287  ieee_interpret_float_value(list[5], &v, IEEE_FMT_S);
1288  ieee_interpret_float_value(list[6], &extra1, IEEE_FMT_S);
1289  ieee_interpret_float_value(list[7], &extra2, IEEE_FMT_S);
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) {
1294  ieee_interpret_float_value(list[6], &extra1, IEEE_FMT_S);
1295  wf_r[vertex_index] = extra1.f * baseRed;
1296  wf_g[vertex_index] = extra1.f * baseGreen;
1297  wf_b[vertex_index] = extra1.f * baseBlue;
1298  } else {
1299  // "Intensity from previous face". TODO. Red for now.
1300  wf_r[vertex_index] = 255;
1301  wf_g[vertex_index] = 0;
1302  wf_b[vertex_index] = 0;
1303  }
1304  }
1305 
1306  vertex_index ++;
1307 
1308  if (vertex_index >= 3) {
1309  int modulo_mask = REG(PVRREG_TSP_CFG) & TSP_CFG_MODULO_MASK;
1310 
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]));
1314 
1315  // Hm. TODO: Instead of flipping back and forth between
1316  // clockwise and counter-clockwise culling, perhaps there
1317  // is some smarter way of assigning the three points
1318  // instead of 012 => 12x...?
1319  bool culled = false;
1320  if (cullingmode == 2) {
1321  if (crossProduct < 0)
1322  culled = true;
1323  cullingmode = 3;
1324  } else if (cullingmode == 3) {
1325  if (crossProduct > 0)
1326  culled = true;
1327  cullingmode = 2;
1328  }
1329 
1330  if (!culled) {
1331  if (texture)
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]);
1338  else
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]);
1343  }
1344 
1345  if (eos) {
1346  // End of strip.
1347  vertex_index = 0;
1348  } else {
1349  // Not a closing vertex, then move points 1 and 2
1350  // into slots 0 and 1, so that the stripe can continue.
1351  vertex_index = 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];
1355 
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];
1359  }
1360  }
1361  break;
1362  }
1363 
1364  default:
1365  fatal("pvr_render: unimplemented list cmd %i\n", cmd);
1366  exit(1);
1367  }
1368  }
1369 
1370  pvr_clear_ta_commands(d);
1371 
1372  // TODO: RENDERDONE is 2. How about other events?
1374 }
1375 
1376 
1377 /*
1378  * pvr_reset_ta():
1379  *
1380  * Reset the Tile Accelerator.
1381  */
1382 static void pvr_reset_ta(struct pvr_data *d)
1383 {
1385  pvr_clear_ta_commands(d);
1386 }
1387 
1388 
1389 /*
1390  * pvr_reset():
1391  *
1392  * Reset the PVR.
1393  */
1394 static void pvr_reset(struct pvr_data *d)
1395 {
1396  /* TODO */
1397 }
1398 
1399 
1400 /*
1401  * pvr_ta_init():
1402  *
1403  * Initialize the Tile Accelerator. This makes the TA ready to receive
1404  * commands (via address 0x10000000).
1405  */
1406 void pvr_ta_init(struct cpu *cpu, struct pvr_data *d)
1407 {
1410 }
1411 
1412 
1413 static void pvr_tilebuf_debugdump(struct pvr_data *d)
1414 {
1415  return;
1416 
1417  // According to Marcus Comstedt's "tatest":
1418  // 24 word header (before the TILEBUF_ADDR pointer), followed by
1419  // 6 words for each tile.
1420  uint32_t tilebuf = REG(PVRREG_TILEBUF_ADDR) & PVR_TILEBUF_ADDR_MASK;
1421 
1422  // TODO: endianness
1423  uint32_t *p = (uint32_t*) (d->vram + tilebuf);
1424 
1425  fatal("PVR tile buffer debug dump:\n");
1426  p -= 24;
1427  for (int i = 0; i < 24; ++i)
1428  fatal(" %08x", *p++);
1429 
1430  fatal("\n%i x %i tiles:\n", d->tilebuf_xsize, d->tilebuf_ysize);
1431 
1432  for (int x = 0; x < d->tilebuf_xsize; ++x)
1433  {
1434  for (int y = 0; y < d->tilebuf_ysize; ++y)
1435  {
1436  fatal(" Tile %i,%i:", x, y);
1437  for (int i = 0; i < 6; ++i)
1438  fatal(" %08x", *p++);
1439  fatal("\n");
1440  }
1441  }
1442 }
1443 
1444 
1445 /*
1446  * pvr_ta_command():
1447  *
1448  * Someone has written a [complete] 32-byte or 64-byte command to the Tile
1449  * Accelerator memory area. The real hardware probably outputs
1450  * "compiled commands" into the Object list and Object Pointer list.
1451  * For now, just put all the commands in a plain array, and then later execute
1452  * them in pvr_render().
1453  */
1454 static void pvr_ta_command(struct cpu *cpu, struct pvr_data *d, int list_ofs)
1455 {
1456  uint32_t *ta = &d->ta[list_ofs];
1457 
1458 #ifdef TA_DEBUG
1459  /* Dump the Tile Accelerator command for debugging: */
1460  {
1461  int i;
1462  fatal("TA cmd:");
1463  for (i = 0; i < 8; ++i)
1464  fatal(" %08x", (int) ta[i]);
1465  fatal("\n");
1466  }
1467 #endif
1468 
1469  // ob_ofs = REG(PVRREG_TA_OB_POS);
1470  // REG(PVRREG_TA_OB_POS) = ob_ofs + sizeof(uint64_t);
1471 
1472  if (d->ta_commands == NULL) {
1473  d->allocated_ta_commands = 2048;
1474  d->ta_commands = (uint32_t *) malloc(64 * d->allocated_ta_commands);
1475  d->n_ta_commands = 0;
1476  }
1477 
1478  if (d->n_ta_commands + 1 >= d->allocated_ta_commands) {
1479  d->allocated_ta_commands *= 2;
1480  d->ta_commands = (uint32_t *) realloc(d->ta_commands, 64 * d->allocated_ta_commands);
1481  }
1482 
1483  // Hack: I don't understand yet what separates a 32-byte transfer
1484  // vs two individual 32-byte transfers vs a 64-byte transfer.
1485  // TODO: For now, really only support 32-byte transfers... :(
1486  memcpy(d->ta_commands + 16 * d->n_ta_commands, ta, 32);
1487  memset(d->ta_commands + 16 * d->n_ta_commands + 8, 0, 32);
1488  d->n_ta_commands ++;
1489 
1490  // We need to keep track of the current list type though, and respond
1491  // with an event once we reach an end_of_list command. All other
1492  // commands are handled in pvr_render() for now.
1493  int cmd = (ta[0] >> 29) & 7;
1494  if (cmd == 0) {
1495  // cmd 0: end of list
1496  uint32_t opb_cfg = REG(PVRREG_TA_OPB_CFG);
1497 
1498  if (d->current_list_type == 0 && opb_cfg & TA_OPB_CFG_OPAQUEPOLY_MASK)
1500  if (d->current_list_type == 1 && opb_cfg & TA_OPB_CFG_OPAQUEMOD_MASK)
1502  if (d->current_list_type == 2 && opb_cfg & TA_OPB_CFG_TRANSPOLY_MASK)
1504  if (d->current_list_type == 3 && opb_cfg & TA_OPB_CFG_TRANSMOD_MASK)
1506  if (d->current_list_type == 4 && opb_cfg & TA_OPB_CFG_PUNCHTHROUGH_MASK)
1508  } else if (cmd == 4) {
1509  // cmd 4: polygon or modifier volume
1510  d->current_list_type = (ta[0] >> 24) & 7;
1511  }
1512 }
1513 
1514 
1516 {
1517  struct pvr_data *d = (struct pvr_data *) extra;
1518  uint64_t idata = 0, odata = 0;
1519 
1520  if (len != sizeof(uint32_t)) {
1521  fatal("pvr_ta access len = %i: TODO\n", (int) len);
1522  exit(1);
1523  }
1524 
1525  // Tile Accelerator commands can be sent to 0x10000000 through
1526  // 0x107fffff, it seems, but the SH4 store queues only have 64 bytes.
1527  relative_addr &= (sizeof(d->ta) - 1);
1528 
1529  if (writeflag == MEM_WRITE) {
1530  idata = memory_readmax64(cpu, data, len);
1531 #if 0
1532  fatal("[ pvr_ta: WRITE addr=%08x value=%08x ]\n",
1533  (int)relative_addr, (int)idata);
1534 #endif
1535 
1536  /* Write to the tile accelerator command buffer: */
1537  d->ta[relative_addr / sizeof(uint32_t)] = idata;
1538 
1539  // Execute the command, after a complete write.
1540  // (Note: This assumes that commands are written from low
1541  // address to high.)
1542  if (relative_addr == 0x1c)
1543  pvr_ta_command(cpu, d, 0);
1544  if (relative_addr == 0x3c)
1545  pvr_ta_command(cpu, d, 8);
1546  } else {
1547  odata = d->ta[relative_addr / sizeof(uint32_t)];
1548  memory_writemax64(cpu, data, len, odata);
1549 #if 1
1550  fatal("[ pvr_ta: READ addr=%08x value=%08x ]\n", (int)relative_addr, (int)odata);
1551 #endif
1552  }
1553 
1554  return 1;
1555 }
1556 
1557 
1559 {
1560  struct pvr_data *d = (struct pvr_data *) extra;
1561  uint64_t idata = 0, odata = 0;
1562 
1563  if (writeflag == MEM_WRITE)
1564  idata = memory_readmax64(cpu, data, len);
1565 
1566  /* Default read action: Read from reg[]: */
1567  if (writeflag == MEM_READ)
1568  odata = d->reg[relative_addr / sizeof(uint32_t)];
1569 
1570  /* Fog table access: */
1571  if (relative_addr >= PVRREG_FOG_TABLE &&
1572  relative_addr < PVRREG_FOG_TABLE + PVR_FOG_TABLE_SIZE) {
1573  if (writeflag == MEM_WRITE)
1574  DEFAULT_WRITE;
1575  goto return_ok;
1576  }
1577 
1578  /* Palette access: */
1579  if (relative_addr >= PVRREG_PALETTE &&
1580  relative_addr < PVRREG_PALETTE + PVR_PALETTE_SIZE) {
1581  if (writeflag == MEM_WRITE)
1582  DEFAULT_WRITE;
1583  goto return_ok;
1584  }
1585 
1586  switch (relative_addr) {
1587 
1588  case PVRREG_ID:
1589  /* ID for Set 5.xx versions of the Dreamcast, according
1590  to http://www.ludd.luth.se/~jlo/dc/powervr-reg.txt: */
1591  odata = 0x17fd11db;
1592  break;
1593 
1594  case PVRREG_REVISION:
1595  /* Revision 1.1, for Dreamcast Set 5.2x. */
1596  odata = 0x00000011;
1597  break;
1598 
1599  case PVRREG_RESET:
1600  if (writeflag == MEM_WRITE) {
1601  if (idata != 0) {
1602  debug("[ pvr: RESET ");
1603  if (idata & PVR_RESET_PVR)
1604  pvr_reset(d);
1605  if (idata & PVR_RESET_TA)
1606  pvr_reset_ta(d);
1607  debug("]\n");
1608  }
1609  idata = 0;
1610  DEFAULT_WRITE;
1611  }
1612  break;
1613 
1614  case PVRREG_STARTRENDER:
1615  if (writeflag == MEM_WRITE) {
1616  debug("[ pvr: STARTRENDER ]\n");
1617  pvr_render(cpu, d);
1618  } else {
1619  fatal("[ pvr: huh? read from STARTRENDER ]\n");
1620  exit(1);
1621  }
1622  break;
1623 
1624  case PVRREG_OB_ADDR:
1625  if (writeflag == MEM_WRITE) {
1626  debug("[ pvr: OB_ADDR set to 0x%08" PRIx32" ]\n",
1627  (uint32_t)(idata & PVR_OB_ADDR_MASK));
1628  if (idata & ~PVR_OB_ADDR_MASK) {
1629  fatal("[ pvr: OB_ADDR: Fatal error: Unknown"
1630  " bits set: 0x%08" PRIx32" ]\n",
1631  (uint32_t)(idata & ~PVR_OB_ADDR_MASK));
1632  exit(1);
1633  }
1634  idata &= PVR_OB_ADDR_MASK;
1635  DEFAULT_WRITE;
1636  }
1637  break;
1638 
1639  case PVRREG_TILEBUF_ADDR:
1640  if (writeflag == MEM_WRITE) {
1641  debug("[ pvr: TILEBUF_ADDR set to 0x%08" PRIx32" ]\n",
1642  (uint32_t)(idata & PVR_TILEBUF_ADDR_MASK));
1643  if (idata & ~PVR_TILEBUF_ADDR_MASK) {
1644  fatal("[ pvr: TILEBUF_ADDR: Unknown"
1645  " bits set: 0x%08" PRIx32" ]\n",
1646  (uint32_t)(idata & ~PVR_TILEBUF_ADDR_MASK));
1647  exit(1);
1648  }
1649  idata &= PVR_TILEBUF_ADDR_MASK;
1650  DEFAULT_WRITE;
1651  pvr_tilebuf_debugdump(d);
1652  }
1653  break;
1654 
1655  case PVRREG_SPANSORT:
1656  if (writeflag == MEM_WRITE) {
1657  debug("[ pvr: SPANSORT: ");
1658  if (idata & PVR_SPANSORT_SPAN0)
1659  debug("SPAN0 ");
1660  if (idata & PVR_SPANSORT_SPAN1)
1661  debug("SPAN1 ");
1662  if (idata & PVR_SPANSORT_TSP_CACHE_ENABLE)
1663  debug("TSP_CACHE_ENABLE ");
1664  debug("]\n");
1665  DEFAULT_WRITE;
1666  }
1667  break;
1668 
1669  case PVRREG_BRDCOLR:
1670  if (writeflag == MEM_WRITE) {
1671  debug("[ pvr: BRDCOLR set to 0x%06" PRIx32" ]\n",
1672  (int)idata);
1673  DEFAULT_WRITE;
1674  d->border_updated = 1;
1675  }
1676  break;
1677 
1678  case PVRREG_DIWMODE:
1679  if (writeflag == MEM_WRITE) {
1680  d->clock_double = idata & DIWMODE_C_MASK? 1:0;
1681  d->strip_buffer_enabled = idata & DIWMODE_SE_MASK? 1:0;
1682  d->strip_length = (idata & DIWMODE_SL_MASK)
1683  >> DIWMODE_SL_SHIFT;
1684  d->argb8888_threshold = (idata & DIWMODE_TH_MASK)
1685  >> DIWMODE_TH_SHIFT;
1686  d->extend = (idata & DIWMODE_EX_MASK)
1687  >> DIWMODE_EX_SHIFT;
1688  d->pixelmode = (idata & DIWMODE_COL_MASK)
1689  >> DIWMODE_COL_SHIFT;
1690  d->line_double = idata & DIWMODE_SD_MASK? 1:0;
1691  d->display_enabled = idata & DIWMODE_DE_MASK? 1:0;
1692 
1693  debug("[ pvr: DIWMODE set to: ");
1694  debug("clock_double=%i, ", d->clock_double);
1695  debug("strip_buffer_enabled=%i, ",
1697  debug("strip_length=%i, ", d->strip_length);
1698  debug("argb8888_threshold=%i, ", d->argb8888_threshold);
1699  debug("extend=0x%x, ", d->extend);
1700  debug("pixelmode=");
1701  switch (d->pixelmode) {
1702  case 0: debug("RGB0555 (16-bit)"); break;
1703  case 1: debug("RGB565 (16-bit)"); break;
1704  case 2: debug("RGB888 (24-bit)"); break;
1705  case 3: debug("RGB0888 (32-bit)"); break;
1706  }
1707  debug(", line_double=%i, ", d->line_double);
1708  debug("display_enabled=%i", d->display_enabled);
1709  debug(" ]\n");
1710 
1711  DEFAULT_WRITE;
1713  pvr_fb_invalidate(d, -1, -1);
1714  }
1715  break;
1716 
1717  case PVRREG_DIWSIZE:
1718  if (writeflag == MEM_WRITE) {
1719  debug("[ pvr: DIWSIZE set to modulo=%i, "
1720  "width=%i, height=%i ]\n", (int)
1721  ((idata >> DIWSIZE_MODULO_SHIFT) & DIWSIZE_MASK),
1722  (int)((idata >> DIWSIZE_DPL_SHIFT) & DIWSIZE_MASK),
1723  (int)((idata >> DIWSIZE_LPF_SHIFT) & DIWSIZE_MASK));
1724  DEFAULT_WRITE;
1726  pvr_fb_invalidate(d, -1, -1);
1727  }
1728  break;
1729 
1731  if (writeflag == MEM_WRITE) {
1732  debug("[ pvr: FB_RENDER_ADDR1 set to 0x%08" PRIx32
1733  " ]\n", (int) idata);
1734  DEFAULT_WRITE;
1735  }
1736  break;
1737 
1739  if (writeflag == MEM_WRITE) {
1740  debug("[ pvr: FB_RENDER_ADDR2 set to 0x%08" PRIx32
1741  " ]\n", (int) idata);
1742  DEFAULT_WRITE;
1743  }
1744  break;
1745 
1746  case PVRREG_FB_CLIP_X:
1747  if (writeflag == MEM_WRITE) {
1748  debug("[ pvr: FB_CLIP_X set to min=%i, "
1749  "max=%i ]\n", (int) (idata & FB_CLIP_XY_MIN_MASK),
1750  (int) ((idata & FB_CLIP_XY_MAX_MASK)
1751  >> FB_CLIP_XY_MAX_SHIFT));
1752  DEFAULT_WRITE;
1754  pvr_fb_invalidate(d, -1, -1);
1755  }
1756  break;
1757 
1758  case PVRREG_FB_CLIP_Y:
1759  if (writeflag == MEM_WRITE) {
1760  debug("[ pvr: FB_CLIP_Y set to min=%i, "
1761  "max=%i ]\n", (int) (idata & FB_CLIP_XY_MIN_MASK),
1762  (int) ((idata & FB_CLIP_XY_MAX_MASK)
1763  >> FB_CLIP_XY_MAX_SHIFT));
1764  DEFAULT_WRITE;
1766  pvr_fb_invalidate(d, -1, -1);
1767  }
1768  break;
1769 
1770  case PVRREG_SHADOW:
1771  if (writeflag == MEM_WRITE) {
1772  debug("[ pvr: SHADOW set to enable=%i, "
1773  "intensity=%i ]\n",
1774  (int) (idata & SHADOW_ENABLE? 1 : 0),
1775  (int) (idata & SHADOW_INTENSITY_MASK));
1776  DEFAULT_WRITE;
1778  pvr_fb_invalidate(d, -1, -1);
1779  }
1780  break;
1781 
1782  case PVRREG_OBJECT_CLIP:
1783  if (writeflag == MEM_WRITE) {
1784  debug("[ pvr: OBJECT_CLIP 0x%08x ]\n", (int)idata);
1785  DEFAULT_WRITE;
1786  }
1787  break;
1788 
1789  case PVRREG_OB_CFG:
1790  if (writeflag == MEM_WRITE) {
1791  debug("[ pvr: OB_CFG 0x%08x ]\n", (int)idata);
1792  DEFAULT_WRITE;
1793  }
1794  break;
1795 
1796  case PVRREG_UNKNOWN_80:
1797  if (writeflag == MEM_WRITE) {
1798  debug("[ pvr: UNKNOWN_80 0x%08x ]\n", (int)idata);
1799  DEFAULT_WRITE;
1800  }
1801  break;
1802 
1803  case PVRREG_UNKNOWN_84:
1804  if (writeflag == MEM_WRITE) {
1805  debug("[ pvr: UNKNOWN_84 0x%08x ]\n", (int)idata);
1806  DEFAULT_WRITE;
1807  }
1808  break;
1809 
1810  case PVRREG_BGPLANE_Z:
1811  if (writeflag == MEM_WRITE) {
1812  debug("[ pvr: BGPLANE_Z 0x%08x ]\n", (int)idata);
1813  DEFAULT_WRITE;
1814  }
1815  break;
1816 
1817  case PVRREG_BGPLANE_CFG:
1818  if (writeflag == MEM_WRITE) {
1819  debug("[ pvr: BGPLANE_CFG 0x%08x ]\n", (int)idata);
1820  DEFAULT_WRITE;
1821  }
1822  break;
1823 
1824  case PVRREG_ISP_CFG:
1825  if (writeflag == MEM_WRITE) {
1826  debug("[ pvr: ISP_CFG 0x%08x ]\n", (int)idata);
1827  DEFAULT_WRITE;
1828  }
1829  break;
1830 
1831  case PVRREG_VRAM_CFG1:
1832  if (writeflag == MEM_WRITE) {
1833  debug("[ pvr: VRAM_CFG1 set to 0x%08" PRIx32,
1834  (int) idata);
1835  if (idata != VRAM_CFG1_GOOD_REFRESH_VALUE)
1836  fatal("{ VRAM_CFG1 = 0x%08" PRIx32" is not "
1837  "yet implemented! }", (int) idata);
1838  debug(" ]\n");
1839  DEFAULT_WRITE;
1840  }
1841  break;
1842 
1843  case PVRREG_VRAM_CFG2:
1844  if (writeflag == MEM_WRITE) {
1845  debug("[ pvr: VRAM_CFG2 set to 0x%08" PRIx32,
1846  (int) idata);
1847  if (idata != VRAM_CFG2_UNKNOWN_MAGIC)
1848  fatal("{ VRAM_CFG2 = 0x%08" PRIx32" is not "
1849  "yet implemented! }", (int) idata);
1850  debug(" ]\n");
1851  DEFAULT_WRITE;
1852  }
1853  break;
1854 
1855  case PVRREG_VRAM_CFG3:
1856  if (writeflag == MEM_WRITE) {
1857  debug("[ pvr: VRAM_CFG3 set to 0x%08" PRIx32,
1858  (int) idata);
1859  if (idata != VRAM_CFG3_UNKNOWN_MAGIC)
1860  fatal("{ VRAM_CFG3 = 0x%08" PRIx32" is not "
1861  "yet implemented! }", (int) idata);
1862  debug(" ]\n");
1863  DEFAULT_WRITE;
1864  }
1865  break;
1866 
1867  case PVRREG_FOG_TABLE_COL:
1868  // e.g. 0x007f7f7f
1869  if (writeflag == MEM_WRITE) {
1870  debug("[ pvr: FOG_TABLE_COL set to 0x%06" PRIx32" ]\n",
1871  (int) idata);
1872  DEFAULT_WRITE;
1873  }
1874  break;
1875 
1876  case PVRREG_FOG_VERTEX_COL:
1877  // e.g. 0x007f7f7f
1878  if (writeflag == MEM_WRITE) {
1879  debug("[ pvr: FOG_VERTEX_COL set to 0x%06" PRIx32" ]\n",
1880  (int) idata);
1881  DEFAULT_WRITE;
1882  }
1883  break;
1884 
1885  case PVRREG_FOG_DENSITY:
1886  // e.g. 0x0000ff07
1887  if (writeflag == MEM_WRITE) {
1888  debug("[ pvr: FOG_DENSITY set to 0x%08" PRIx32" ]\n",
1889  (int) idata);
1890  DEFAULT_WRITE;
1891  }
1892  break;
1893 
1894  case PVRREG_CLAMP_MAX:
1895  // e.g. 0xffffffff
1896  if (writeflag == MEM_WRITE) {
1897  debug("[ pvr: CLAMP_MAX set to 0x%06" PRIx32" ]\n",
1898  (int) idata);
1899  DEFAULT_WRITE;
1900  }
1901  break;
1902 
1903  case PVRREG_CLAMP_MIN:
1904  // e.g. 0x00000000
1905  if (writeflag == MEM_WRITE) {
1906  debug("[ pvr: CLAMP_MIN set to 0x%06" PRIx32" ]\n",
1907  (int) idata);
1908  DEFAULT_WRITE;
1909  }
1910  break;
1911 
1912  case PVRREG_FB_RENDER_CFG:
1913  if (writeflag == MEM_WRITE) {
1914  debug("[ pvr: PVRREG_FB_RENDER_CFG set to 0x%08x ]\n",
1915  (int) idata);
1916  /* TODO */
1917  DEFAULT_WRITE;
1918  }
1919  break;
1920 
1922  if (writeflag == MEM_WRITE) {
1923  debug("[ pvr: PVRREG_FB_RENDER_MODULO set to %i ]\n",
1924  (int) idata);
1925  /* TODO */
1926  DEFAULT_WRITE;
1927  }
1928  break;
1929 
1930  case PVRREG_DIWADDRL:
1931  if (writeflag == MEM_WRITE) {
1932  debug("[ pvr: DIWADDRL set to 0x%08" PRIx32" ]\n",
1933  (int) idata);
1934  pvr_fb_invalidate(d, -1, -1);
1935  DEFAULT_WRITE;
1936  }
1937  break;
1938 
1939  case PVRREG_DIWADDRS:
1940  if (writeflag == MEM_WRITE) {
1941  debug("[ pvr: DIWADDRS set to 0x%08" PRIx32" ]\n",
1942  (int) idata);
1943  pvr_fb_invalidate(d, -1, -1);
1944  DEFAULT_WRITE;
1945  }
1946  break;
1947 
1948  case PVRREG_HPOS_IRQ:
1949  DEFAULT_WRITE;
1950  break;
1951 
1952  case PVRREG_RASEVTPOS:
1953  if (writeflag == MEM_WRITE) {
1954  debug("[ pvr: RASEVTPOS pos1=%i pos2=%i ]\n",
1955  (int)((idata & RASEVTPOS_POS1_MASK)
1957  (int)(idata & RASEVTPOS_POS2_MASK));
1958  DEFAULT_WRITE;
1959  }
1960  break;
1961 
1962  case PVRREG_SYNCCONF:
1963  if (writeflag == MEM_WRITE) {
1964  d->video_enabled = idata & SYNCCONF_VO_MASK? 1:0;
1965  d->broadcast_standard = (idata & SYNCCONF_BC_MASK)
1966  >> SYNCCONF_BC_SHIFT;
1967  d->interlaced = idata & SYNCCONF_I_MASK? 1:0;
1968  d->h_sync_positive = idata & SYNCCONF_HP_MASK? 1:0;
1969  d->v_sync_positive = idata & SYNCCONF_VP_MASK? 1:0;
1970 
1971  debug("[ pvr: SYNCCONF set to: ");
1972  debug("video_enabled=%i, ", d->video_enabled);
1973  switch (d->broadcast_standard) {
1974  case SYNCCONF_BC_VGA: debug("VGA"); break;
1975  case SYNCCONF_BC_NTSC: debug("NTSC"); break;
1976  case SYNCCONF_BC_PAL: debug("PAL"); break;
1977  default: debug("*UNKNOWN*"); break;
1978  }
1979  debug(", interlaced=%i, ", d->interlaced);
1980  debug("hsync=%i, ", d->h_sync_positive);
1981  debug("vsync=%i ]\n", d->v_sync_positive);
1982 
1983  DEFAULT_WRITE;
1985  pvr_fb_invalidate(d, -1, -1);
1986  }
1987  break;
1988 
1989  case PVRREG_BRDHORZ:
1990  if (writeflag == MEM_WRITE) {
1991  debug("[ pvr: BRDHORZ start=%i stop=%i ]\n",
1992  (int)((idata & BRDHORZ_START_MASK)
1993  >> BRDHORZ_START_SHIFT),
1994  (int)(idata & BRDHORZ_STOP_MASK));
1995  DEFAULT_WRITE;
1996  }
1997  break;
1998 
1999  case PVRREG_SYNCSIZE:
2000  if (writeflag == MEM_WRITE) {
2001  debug("[ pvr: SYNCSIZE v=%i h=%i ]\n",
2002  (int)((idata & SYNCSIZE_V_MASK)
2003  >> SYNCSIZE_V_SHIFT),
2004  (int)(idata & SYNCSIZE_H_MASK));
2005  DEFAULT_WRITE;
2006  }
2007  break;
2008 
2009  case PVRREG_BRDVERT:
2010  if (writeflag == MEM_WRITE) {
2011  debug("[ pvr: BRDVERT start=%i stop=%i ]\n",
2012  (int)((idata & BRDVERT_START_MASK)
2013  >> BRDVERT_START_SHIFT),
2014  (int)(idata & BRDVERT_STOP_MASK));
2015  DEFAULT_WRITE;
2016  }
2017  break;
2018 
2019  case PVRREG_SYNCH_WIDTH:
2020  if (writeflag == MEM_WRITE) {
2021  debug("[ pvr: SYNCH_WIDTH 0x%08x ]\n", (int)idata);
2022  DEFAULT_WRITE;
2023  }
2024  break;
2025 
2026  case PVRREG_TSP_CFG:
2027  if (writeflag == MEM_WRITE) {
2028  debug("[ pvr: TSP_CFG 0x%08x ]\n", (int)idata);
2029  DEFAULT_WRITE;
2030  }
2031  break;
2032 
2033  case PVRREG_DIWCONF:
2034  if (writeflag == MEM_WRITE) {
2035  if ((idata & DIWCONF_MAGIC_MASK) !=
2036  DIWCONF_MAGIC && (idata & DIWCONF_MAGIC_MASK)
2037  != 0) {
2038  fatal("PVRREG_DIWCONF magic not set to "
2039  "Magic value. 0x%08x\n", (int)idata);
2040  exit(1);
2041  }
2042  if (idata & DIWCONF_BLANK)
2043  debug("[ pvr: PVRREG_DIWCONF: BLANK: TODO ]\n");
2044 
2045  DEFAULT_WRITE;
2047  }
2048  break;
2049 
2050  case PVRREG_DIWHSTRT:
2051  if (writeflag == MEM_WRITE) {
2052  int v = idata & DIWVSTRT_HPOS_MASK;
2053  debug("[ pvr: DIWHSTRT hpos=%i (%s) ]\n",
2054  v, v == 174? "PAL" :
2055  (v == 164? "NTSC" :
2056  (v == 144? "VGA" : "unknown!")));
2057  DEFAULT_WRITE;
2058  }
2059  break;
2060 
2061  case PVRREG_DIWVSTRT:
2062  if (writeflag == MEM_WRITE) {
2063  debug("[ pvr: DIWVSTRT v2=%i v1=%i ]\n",
2064  (int)((idata & DIWVSTRT_V2_MASK)
2065  >> DIWVSTRT_V2_SHIFT),
2066  (int)(idata & DIWVSTRT_V1_MASK));
2067  DEFAULT_WRITE;
2068  }
2069  break;
2070 
2071  case PVRREG_SCALER_CFG:
2072  if (writeflag == MEM_WRITE) {
2073  debug("[ pvr: SCALER_CFG 0x%08x ]\n", (int)idata);
2074  DEFAULT_WRITE;
2075  }
2076  break;
2077 
2078  case PVRREG_PALETTE_CFG:
2079  if (writeflag == MEM_WRITE) {
2080  debug("[ pvr: PALETTE_CFG 0x%08x ]\n", (int)idata);
2081  DEFAULT_WRITE;
2082  }
2083  break;
2084 
2085  case PVRREG_SYNC_STAT:
2086  /* TODO. Ugly hack, but it works: */
2087  odata = random();
2088  break;
2089 
2090  case PVRREG_MAGIC_110:
2091  if (writeflag == MEM_WRITE) {
2092  debug("[ pvr: MAGIC_110 set to 0x%08" PRIx32,
2093  (int) idata);
2094  if (idata != MAGIC_110_VALUE)
2095  fatal("{ MAGIC_110 = 0x%08" PRIx32" is not "
2096  "yet implemented! }", (int) idata);
2097  debug(" ]\n");
2098  DEFAULT_WRITE;
2099  }
2100  break;
2101 
2102  case PVRREG_TA_LUMINANCE:
2103  if (writeflag == MEM_WRITE) {
2104  debug("[ pvr: TA_LUMINANCE set to 0x%08" PRIx32" ]\n",
2105  (int) idata);
2106  DEFAULT_WRITE;
2107  }
2108  break;
2109 
2110  case PVRREG_TA_OPB_START:
2111  if (writeflag == MEM_WRITE) {
2112  if (idata & ~TA_OPB_START_MASK) {
2113  fatal("[ pvr: UNEXPECTED bits in "
2114  "TA_OPB_START: 0x%08x ]\n", (int)idata);
2115  exit(1);
2116  }
2117  idata &= TA_OPB_START_MASK;
2118  debug("[ pvr: TA_OPB_START set to 0x%x ]\n",
2119  (int) idata);
2120  DEFAULT_WRITE;
2121  }
2122  break;
2123 
2124  case PVRREG_TA_OB_START:
2125  if (writeflag == MEM_WRITE) {
2126  if (idata & ~TA_OB_START_MASK) {
2127  fatal("[ pvr: UNEXPECTED bits in "
2128  "TA_OB_START: 0x%08x ]\n", (int)idata);
2129  exit(1);
2130  }
2131  idata &= TA_OB_START_MASK;
2132  debug("[ pvr: TA_OB_START set to 0x%x ]\n",
2133  (int) idata);
2134  DEFAULT_WRITE;
2135  }
2136  break;
2137 
2138  case PVRREG_TA_OPB_END:
2139  if (writeflag == MEM_WRITE) {
2140  idata &= TA_OPB_END_MASK;
2141  debug("[ pvr: TA_OPB_END set to 0x%x ]\n",
2142  (int) idata);
2143  DEFAULT_WRITE;
2144  }
2145  break;
2146 
2147  case PVRREG_TA_OB_END:
2148  if (writeflag == MEM_WRITE) {
2149  idata &= TA_OB_END_MASK;
2150  debug("[ pvr: TA_OB_END set to 0x%x ]\n",
2151  (int) idata);
2152  DEFAULT_WRITE;
2153  }
2154  break;
2155 
2156  case PVRREG_TA_OPB_POS:
2157  if (writeflag == MEM_WRITE) {
2158  idata &= TA_OPB_POS_MASK;
2159  debug("[ pvr: TA_OPB_POS set to 0x%x ]\n",
2160  (int) idata);
2161  DEFAULT_WRITE;
2162  }
2163  break;
2164 
2165  case PVRREG_TA_OB_POS:
2166  if (writeflag == MEM_WRITE) {
2167  idata &= TA_OB_POS_MASK;
2168  debug("[ pvr: TA_OB_POS set to 0x%x ]\n",
2169  (int) idata);
2170  DEFAULT_WRITE;
2171  }
2172  break;
2173 
2174  case PVRREG_TA_OPL_INIT:
2175  if (writeflag == MEM_WRITE) {
2176  idata &= PVR_TA_OPL_INIT_MASK;
2177  debug("[ pvr: TA_OPL_INIT set to 0x%x ]\n",
2178  (int) idata);
2179  DEFAULT_WRITE;
2180  }
2181  break;
2182 
2183  case PVRREG_TILEBUF_SIZE:
2184  if (writeflag == MEM_WRITE) {
2188  d->tilebuf_xsize ++; d->tilebuf_ysize ++;
2189  debug("[ pvr: TILEBUF_SIZE set to %i x %i ]\n",
2190  d->tilebuf_xsize, d->tilebuf_ysize);
2191  DEFAULT_WRITE;
2192  }
2193  break;
2194 
2195  case PVRREG_TA_OPB_CFG:
2196  if (writeflag == MEM_WRITE) {
2197  debug("[ pvr: TA_OPB_CFG set to 0x%x ]\n",
2198  (int) idata);
2199  DEFAULT_WRITE;
2200  }
2201  break;
2202 
2203  case PVRREG_TA_INIT:
2204  if (writeflag == MEM_WRITE) {
2205  debug("[ pvr: TA_INIT ]\n");
2206 
2207  if (idata & PVR_TA_INIT)
2208  pvr_ta_init(cpu, d);
2209 
2210  if (idata != PVR_TA_INIT && idata != 0)
2211  fatal("{ TA_INIT = 0x%08" PRIx32" is not "
2212  "yet implemented! }", (int) idata);
2213 
2214  /* Always reset to 0. */
2215  idata = 0;
2216  DEFAULT_WRITE;
2217  }
2218  break;
2219 
2220  case PVRREG_YUV_STAT:
2221  // TODO. The "luftvarg" demo accesses this register.
2222  break;
2223 
2224  default:if (writeflag == MEM_READ) {
2225  fatal("[ pvr: read from UNIMPLEMENTED addr 0x%x ]\n",
2226  (int)relative_addr);
2227  } else {
2228  fatal("[ pvr: write to UNIMPLEMENTED addr 0x%x: 0x%x"
2229  " ]\n", (int)relative_addr, (int)idata);
2230  DEFAULT_WRITE;
2231  }
2232 
2233  exit(1);
2234  }
2235 
2236 return_ok:
2237  if (writeflag == MEM_READ)
2238  memory_writemax64(cpu, data, len, odata);
2239 
2240  return 1;
2241 }
2242 
2243 
2244 void pvr_extend_update_region(struct pvr_data *d, uint64_t low, uint64_t high)
2245 {
2246  int vram_ofs = REG(PVRREG_DIWADDRL);
2247  int bytes_per_line = d->xsize * d->bytes_per_pixel;
2248 
2249  low -= vram_ofs;
2250  high -= vram_ofs;
2251 
2252  /* Access inside visible part of VRAM? */
2253  if ((int64_t)high >= 0 && (int64_t)low <
2254  bytes_per_line * d->ysize) {
2255  int new_y1, new_y2;
2256 
2257  d->fb_update_x1 = 0;
2258  d->fb_update_x2 = d->xsize - 1;
2259 
2260  /* Calculate which line the low and high addresses
2261  correspond to: */
2262  new_y1 = low / bytes_per_line;
2263  new_y2 = high / bytes_per_line + 1;
2264 
2265  if (d->fb_update_y1 < 0 || new_y1 < d->fb_update_y1)
2266  d->fb_update_y1 = new_y1;
2267  if (d->fb_update_y2 < 0 || new_y2 > d->fb_update_y2)
2268  d->fb_update_y2 = new_y2;
2269 
2270  if (d->fb_update_y1 < 0)
2271  d->fb_update_y1 = 0;
2272  if (d->fb_update_y2 >= d->ysize)
2273  d->fb_update_y2 = d->ysize - 1;
2274  }
2275 }
2276 
2277 
2279 {
2280  struct pvr_data *d = (struct pvr_data *) extra;
2281  uint64_t high, low = (uint64_t)(int64_t) -1;
2282  int vram_ofs = REG(PVRREG_DIWADDRL), pixels_to_copy;
2283  int bytes_per_line = d->xsize * d->bytes_per_pixel;
2284  int fb_ofs, p;
2285  uint8_t *fb = (uint8_t *) d->fb->framebuffer;
2286  uint8_t *vram = (uint8_t *) d->vram;
2287 
2288 
2289  /*
2290  * Vertical retrace interrupts:
2291  *
2292  * TODO: Maybe it would be even more realistic to have the timer run
2293  * at, say, 60*4 = 240 Hz, and have the following events:
2294  *
2295  * (tick & 3) == 0 SYSASIC_EVENT_VBLINT
2296  * (tick & 3) == 1 SYSASIC_EVENT_PVR_SCANINT1
2297  * (tick & 3) == 2 nothing
2298  * (tick & 3) == 3 SYSASIC_EVENT_PVR_SCANINT2
2299  */
2300  if (d->vblank_interrupts_pending > 0) {
2302 
2305 
2306  // Is this needed?
2308 
2309  /* TODO: For now, I don't care about missed interrupts: */
2311  }
2312 
2313 
2314  /*
2315  * Framebuffer update:
2316  */
2317 
2318  /* Border changed? */
2319  if (d->border_updated) {
2320  /* Fill border with border color: */
2321  int rgb = REG(PVRREG_BRDCOLR), addr = 0;
2322  int x, y, b = rgb & 0xff, g = (rgb >> 8) & 0xff, r = rgb >> 16;
2323  int skiplen = (d->fb->xsize-2*PVR_MARGIN) * d->fb->bit_depth/8;
2324 
2325  for (y=0; y<d->fb->ysize; y++) {
2326  int xskip = y < PVR_MARGIN || y >=
2327  d->fb->ysize - PVR_MARGIN? -1 : PVR_MARGIN;
2328  for (x=0; x<d->fb->xsize; x++) {
2329  if (x == xskip) {
2330  x = d->fb->xsize - PVR_MARGIN;
2331  addr += skiplen;
2332  }
2333  fb[addr] = r;
2334  fb[addr+1] = g;
2335  fb[addr+2] = b;
2336  addr += 3;
2337  }
2338  }
2339 
2340  /* Full redraw of the framebuffer: */
2341  d->fb->update_x1 = 0; d->fb->update_x2 = d->fb->xsize - 1;
2342  d->fb->update_y1 = 0; d->fb->update_y2 = d->fb->ysize - 1;
2343  }
2344 
2345  memory_device_dyntrans_access(cpu, cpu->mem, extra, &low, &high);
2346  if ((int64_t)low != -1)
2347  pvr_extend_update_region(d, low, high);
2348 
2349  if (d->fb_update_x1 == -1)
2350  return;
2351 
2352  /* Copy (part of) the VRAM to the framebuffer: */
2353  if (d->fb_update_x2 >= d->xsize)
2354  d->fb_update_x2 = d->xsize - 1;
2355  if (d->fb_update_y2 >= d->ysize)
2356  d->fb_update_y2 = d->ysize - 1;
2357 
2358  vram_ofs += d->fb_update_y1 * bytes_per_line;
2359  vram_ofs += d->fb_update_x1 * d->bytes_per_pixel;
2360  pixels_to_copy = (d->fb_update_x2 - d->fb_update_x1 + 1);
2361  fb_ofs = (d->fb_update_y1 + PVR_MARGIN) * d->fb->bytes_per_line;
2362  fb_ofs += (d->fb_update_x1 + PVR_MARGIN) * d->fb->bit_depth / 8;
2363 
2364  /* Copy the actual pixels: (Four manually inlined, for speed.) */
2365 
2366  switch (d->pixelmode) {
2367  case 0: /* RGB0555 (16-bit) */
2368  {
2369  int y;
2370  for (y=d->fb_update_y1; y<=d->fb_update_y2; y++) {
2371  int fo = fb_ofs, vo = vram_ofs;
2372  for (p=0; p<pixels_to_copy; p++) {
2373  /* 0rrrrrgg(high) gggbbbbb(low) */
2374  fb[fo] = (vram[(vo+1)%VRAM_SIZE] << 1) & 0xf8;
2375  fb[fo+1] = ((vram[vo%VRAM_SIZE] >> 2) & 0x38) +
2376  (vram[(vo+1)%VRAM_SIZE] << 6);
2377  fb[fo+2] = (vram[vo%VRAM_SIZE] & 0x1f) << 3;
2378  fo += 3; vo += 2;
2379  }
2380 
2381  vram_ofs += bytes_per_line;
2382  fb_ofs += d->fb->bytes_per_line;
2383  }
2384  }
2385  break;
2386 
2387  case 1: /* RGB565 (16-bit) */
2388  {
2389  int y;
2390  for (y=d->fb_update_y1; y<=d->fb_update_y2; y++) {
2391  int fo = fb_ofs, vo = vram_ofs;
2392  for (p=0; p<pixels_to_copy; p++) {
2393  /* rrrrrggg(high) gggbbbbb(low) */
2394  fb[fo] = vram[(vo+1)%VRAM_SIZE] & 0xf8;
2395  fb[fo+1] = ((vram[vo%VRAM_SIZE] >> 3) & 0x1c) +
2396  (vram[(vo+1)%VRAM_SIZE] << 5);
2397  fb[fo+2] = (vram[vo%VRAM_SIZE] & 0x1f) << 3;
2398  fo += 3; vo += 2;
2399  }
2400 
2401  vram_ofs += bytes_per_line;
2402  fb_ofs += d->fb->bytes_per_line;
2403  }
2404  }
2405  break;
2406 
2407  case 2: /* RGB888 (24-bit) */
2408  {
2409  int y;
2410  for (y=d->fb_update_y1; y<=d->fb_update_y2; y++) {
2411  /* TODO: Reverse colors, like in the 32-bit case? */
2412  memcpy(fb+fb_ofs, vram+(vram_ofs%VRAM_SIZE), 3*pixels_to_copy);
2413  vram_ofs += bytes_per_line;
2414  fb_ofs += d->fb->bytes_per_line;
2415  }
2416  }
2417  break;
2418 
2419  case 3: /* RGB0888 (32-bit) */
2420  {
2421  int y;
2422  for (y=d->fb_update_y1; y<=d->fb_update_y2; y++) {
2423  int fo = fb_ofs, vo = vram_ofs;
2424  for (p=0; p<pixels_to_copy; p++) {
2425  fb[fo] = vram[(vo+2)%VRAM_SIZE];
2426  fb[fo+1] = vram[(vo+1)%VRAM_SIZE];
2427  fb[fo+2] = vram[(vo+0)%VRAM_SIZE];
2428  fo += 3; vo += 4;
2429  }
2430 
2431  vram_ofs += bytes_per_line;
2432  fb_ofs += d->fb->bytes_per_line;
2433  }
2434  }
2435  break;
2436  }
2437 
2438  /*
2439  * Extend the real framebuffer to encompass the area
2440  * just written to:
2441  */
2442 
2443  /* Offset to take the margin into account first... */
2446 
2447  if (d->fb_update_x1 < d->fb->update_x1 || d->fb->update_x1 < 0)
2448  d->fb->update_x1 = d->fb_update_x1;
2449  if (d->fb_update_x2 > d->fb->update_x2 || d->fb->update_x2 < 0)
2450  d->fb->update_x2 = d->fb_update_x2;
2451  if (d->fb_update_y1 < d->fb->update_y1 || d->fb->update_y1 < 0)
2452  d->fb->update_y1 = d->fb_update_y1;
2453  if (d->fb_update_y2 > d->fb->update_y2 || d->fb->update_y2 < 0)
2454  d->fb->update_y2 = d->fb_update_y2;
2455 
2456  /* Clear the PVR's update region: */
2457  d->fb_update_x1 = d->fb_update_x2 =
2458  d->fb_update_y1 = d->fb_update_y2 = -1;
2459 }
2460 
2461 
2462 DEVICE_ACCESS(pvr_vram_alt)
2463 {
2464  struct pvr_data_alt *d_alt = (struct pvr_data_alt *) extra;
2465  struct pvr_data *d = d_alt->d;
2466  size_t i;
2467 
2468  if (writeflag == MEM_READ) {
2469  /* Copy from real vram: */
2470  for (i=0; i<len; i++) {
2471  int addr = relative_addr + i;
2472  addr = ((addr & 4) << 20) | (addr & 3)
2473  | ((addr & 0x7ffff8) >> 1);
2474  data[i] = d->vram[addr % VRAM_SIZE];
2475  }
2476  return 1;
2477  }
2478 
2479  // Writes are only allowed as 16-bit access or higher.
2480  if (len < sizeof(uint16_t))
2481  fatal("pvr_vram_alt: write of less than 16 bits attempted?\n");
2482 
2483  /*
2484  * Convert writes to alternative VRAM, into normal writes:
2485  */
2486 
2487  for (i=0; i<len; i++) {
2488  int addr = relative_addr + i;
2489  addr = ((addr & 4) << 20) | (addr & 3) | ((addr & 0x7ffff8) >> 1);
2490  // printf(" %08x => alt addr %08x: %02x\n", (int)(relative_addr + i), (int)addr, data[i]);
2491  d->vram[addr % VRAM_SIZE] = data[i];
2492 
2493  // TODO: This is probably ultra-slow. (Should not be called
2494  // for every _byte_.)
2496  }
2497 
2498  return 1;
2499 }
2500 
2501 
2502 DEVICE_ACCESS(pvr_vram)
2503 {
2504  struct pvr_data *d = (struct pvr_data *) extra;
2505 
2506  // According to http://mc.pp.se/dc/pvr.html, reads of any size are
2507  // allowed.
2508  if (writeflag == MEM_READ) {
2509  memcpy(data, d->vram + relative_addr, len);
2510  return 1;
2511  }
2512 
2513  // However, writes are only allowed as 16-bit access or higher.
2514  if (len < sizeof(uint16_t))
2515  fatal("pvr_vram: write of less than 16 bits attempted?\n");
2516 
2517  /*
2518  * Write to VRAM:
2519  *
2520  * Calculate which part of the framebuffer this write corresponds to,
2521  * if any, and increase the update region to encompass the written
2522  * memory range.
2523  */
2524 
2525  memcpy(d->vram + relative_addr, data, len);
2526  pvr_extend_update_region(d, relative_addr, relative_addr + len - 1);
2527 
2528  return 1;
2529 }
2530 
2531 
2533 {
2534  struct machine *machine = devinit->machine;
2535  struct pvr_data *d;
2536  struct pvr_data_alt *d_alt;
2537 
2538  CHECK_ALLOCATION(d = (struct pvr_data *) malloc(sizeof(struct pvr_data)));
2539  memset(d, 0, sizeof(struct pvr_data));
2540 
2541  CHECK_ALLOCATION(d_alt = (struct pvr_data_alt *) malloc(sizeof(struct pvr_data_alt)));
2542  memset(d_alt, 0, sizeof(struct pvr_data_alt));
2543 
2544  d_alt->d = d;
2545 
2547  PVRREG_REGSTART, PVRREG_REGSIZE, dev_pvr_access, d,
2548  DM_DEFAULT, NULL);
2549 
2550  /* 8 MB video RAM: */
2551  d->vram = (uint8_t *) zeroed_alloc(VRAM_SIZE);
2552  memory_device_register(machine->memory, "pvr_vram", 0x05000000,
2553  VRAM_SIZE, dev_pvr_vram_access, (void *)d,
2556 
2557  /* 8 MB video RAM, when accessed at 0xa4000000: */
2558  memory_device_register(machine->memory, "pvr_alt_vram", 0x04000000,
2559  VRAM_SIZE, dev_pvr_vram_alt_access, (void *)d_alt,
2560  DM_DEFAULT, NULL);
2561 
2562  /* Tile Accelerator command area at 0x10000000: */
2564  0x10000000, 0x800000, dev_pvr_ta_access, d, DM_DEFAULT, NULL);
2565 
2566  /* PVR2 DMA registers at 0x5f6800: */
2567  memory_device_register(machine->memory, "pvr_dma", 0x005f6800,
2568  PVR_DMA_MEMLENGTH, dev_pvr_dma_access, d, DM_DEFAULT, NULL);
2569 
2570  /* More DMA registers at 0x5f7c00: */
2571  memory_device_register(machine->memory, "pvr_dma_more", 0x005f7c00,
2572  PVR_DMA_MEMLENGTH, dev_pvr_dma_more_access, d, DM_DEFAULT, NULL);
2573 
2574  d->xsize = 640;
2575  d->ysize = 480;
2576  d->pixelmode = 1; /* RGB565 */
2577  d->bytes_per_pixel = 2;
2578 
2581  d->xsize + PVR_MARGIN*2, d->ysize + PVR_MARGIN*2,
2582  24, "Dreamcast PVR");
2583 
2584  d->vblank_timer = timer_add(PVR_VBLANK_HZ, pvr_vblank_timer_tick, d);
2585 
2586  pvr_reset(d);
2587  pvr_reset_ta(d);
2588 
2589  machine_add_tickfunction(machine, dev_pvr_fb_tick, d,
2591 
2592  return 1;
2593 }
2594 
PVRREG_STARTRENDER
#define PVRREG_STARTRENDER
Definition: dreamcast_pvr.h:95
DIWMODE_DE_MASK
#define DIWMODE_DE_MASK
Definition: dreamcast_pvr.h:126
SYSASIC_EVENT_PVR_SCANINT1
#define SYSASIC_EVENT_PVR_SCANINT1
Definition: dreamcast_sysasicvar.h:53
TILEBUF_SIZE_HEIGHT_MASK
#define TILEBUF_SIZE_HEIGHT_MASK
Definition: dreamcast_pvr.h:324
DIWVSTRT_HPOS_MASK
#define DIWVSTRT_HPOS_MASK
Definition: dreamcast_pvr.h:276
data
u_short data
Definition: siireg.h:79
timer_add
struct timer * timer_add(double freq, void(*timer_tick)(struct timer *timer, void *extra), void *extra)
Definition: timer.cc:75
PVRREG_OBJECT_CLIP
#define PVRREG_OBJECT_CLIP
Definition: dreamcast_pvr.h:187
PVR_VBLANK_HZ
#define PVR_VBLANK_HZ
Definition: dev_pvr.cc:79
CHCR_SM_DECREMENTED
#define CHCR_SM_DECREMENTED
Definition: sh4_dmacreg.h:124
TA_OPB_CFG_TRANSMOD_MASK
#define TA_OPB_CFG_TRANSMOD_MASK
Definition: dreamcast_pvr.h:334
PVRREG_SYNC_STAT
#define PVRREG_SYNC_STAT
Definition: dreamcast_pvr.h:294
DIWMODE_COL_MASK
#define DIWMODE_COL_MASK
Definition: dreamcast_pvr.h:128
CHCR_SM
#define CHCR_SM
Definition: sh4_dmacreg.h:121
PVRREG_FB_RENDER_CFG
#define PVRREG_FB_RENDER_CFG
Definition: dreamcast_pvr.h:139
pvr_data::strip_buffer_enabled
int strip_buffer_enabled
Definition: dev_pvr.cc:116
PVR_PALETTE_CFG_MODE_ARGB4444
#define PVR_PALETTE_CFG_MODE_ARGB4444
Definition: dreamcast_pvr.h:291
PVRREG_FB_RENDER_MODULO
#define PVRREG_FB_RENDER_MODULO
Definition: dreamcast_pvr.h:156
DIWMODE_COL_SHIFT
#define DIWMODE_COL_SHIFT
Definition: dreamcast_pvr.h:129
PVRREG_TA_OB_START
#define PVRREG_TA_OB_START
Definition: dreamcast_pvr.h:308
dreamcast_sysasicvar.h
CHCR_TS
#define CHCR_TS
Definition: sh4_dmacreg.h:127
CHCR_TD
#define CHCR_TD
Definition: sh4_dmacreg.h:136
RASEVTPOS_POS1_SHIFT
#define RASEVTPOS_POS1_SHIFT
Definition: dreamcast_pvr.h:221
pvr_data::line_double
int line_double
Definition: dev_pvr.cc:121
BRDVERT_START_MASK
#define BRDVERT_START_MASK
Definition: dreamcast_pvr.h:257
TA_OB_POS_MASK
#define TA_OB_POS_MASK
Definition: dreamcast_pvr.h:321
CHCR_TS_4BYTE
#define CHCR_TS_4BYTE
Definition: sh4_dmacreg.h:131
VFB_GENERIC
#define VFB_GENERIC
Definition: devices.h:190
sh_cpu::dmac_chcr
uint32_t dmac_chcr[N_SH4_DMA_CHANNELS]
Definition: cpu_sh.h:167
DIWVSTRT_V2_SHIFT
#define DIWVSTRT_V2_SHIFT
Definition: dreamcast_pvr.h:281
PVRREG_TA_OPB_END
#define PVRREG_TA_OPB_END
Definition: dreamcast_pvr.h:311
pvr_dma_transfer
void pvr_dma_transfer(struct cpu *cpu, struct pvr_data *d)
Definition: dev_pvr.cc:166
DEVINIT
DEVINIT(pvr)
Definition: dev_pvr.cc:2532
timer
Definition: timer.cc:45
TA_OPB_END_MASK
#define TA_OPB_END_MASK
Definition: dreamcast_pvr.h:312
debug
#define debug
Definition: dev_adb.cc:57
PVRREG_CLAMP_MAX
#define PVRREG_CLAMP_MAX
Definition: dreamcast_pvr.h:213
TSP_CFG_MODULO_MASK
#define TSP_CFG_MODULO_MASK
Definition: dreamcast_pvr.h:267
pvr_extend_update_region
void pvr_extend_update_region(struct pvr_data *d, uint64_t low, uint64_t high)
Definition: dev_pvr.cc:2244
TA_OPB_POS_MASK
#define TA_OPB_POS_MASK
Definition: dreamcast_pvr.h:318
FB_CLIP_XY_MAX_MASK
#define FB_CLIP_XY_MAX_MASK
Definition: dreamcast_pvr.h:180
SYSASIC_EVENT_PVR_PTDONE
#define SYSASIC_EVENT_PVR_PTDONE
Definition: dreamcast_sysasicvar.h:66
DIWMODE_SD_MASK
#define DIWMODE_SD_MASK
Definition: dreamcast_pvr.h:127
SHADOW_ENABLE
#define SHADOW_ENABLE
Definition: dreamcast_pvr.h:185
SYSASIC_EVENT_PVR_SCANINT2
#define SYSASIC_EVENT_PVR_SCANINT2
Definition: dreamcast_sysasicvar.h:54
SYNCSIZE_H_MASK
#define SYNCSIZE_H_MASK
Definition: dreamcast_pvr.h:249
PVR_OB_ADDR_MASK
#define PVR_OB_ADDR_MASK
Definition: dreamcast_pvr.h:102
DIWCONF_MAGIC_MASK
#define DIWCONF_MAGIC_MASK
Definition: dreamcast_pvr.h:272
PVRREG_DIWHSTRT
#define PVRREG_DIWHSTRT
Definition: dreamcast_pvr.h:275
PVRREG_CLAMP_MIN
#define PVRREG_CLAMP_MIN
Definition: dreamcast_pvr.h:214
if
addr & if(addr >=0x24 &&page !=NULL)
Definition: tmp_arm_multi.cc:56
ieee_interpret_float_value
void ieee_interpret_float_value(uint64_t x, struct ieee_float_value *fvp, int fmt)
Definition: float_emul.cc:49
BRDVERT_START_SHIFT
#define BRDVERT_START_SHIFT
Definition: dreamcast_pvr.h:258
PVR_PALETTE_CFG_MODE_RGB565
#define PVR_PALETTE_CFG_MODE_RGB565
Definition: dreamcast_pvr.h:290
VRAM_CFG3_UNKNOWN_MAGIC
#define VRAM_CFG3_UNKNOWN_MAGIC
Definition: dreamcast_pvr.h:207
memory_device_register
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)
Definition: memory.cc:339
PVRREG_VRAM_CFG3
#define PVRREG_VRAM_CFG3
Definition: dreamcast_pvr.h:206
PVRREG_DIWADDRS
#define PVRREG_DIWADDRS
Definition: dreamcast_pvr.h:162
pvr_data::border_updated
int border_updated
Definition: dev_pvr.cc:124
pvr_data::extend
int extend
Definition: dev_pvr.cc:119
PVR_PALETTE_CFG_MODE_ARGB1555
#define PVR_PALETTE_CFG_MODE_ARGB1555
Definition: dreamcast_pvr.h:289
INTERNAL_FB_ADDR
#define INTERNAL_FB_ADDR
Definition: dev_pvr.cc:76
PVRREG_TILEBUF_SIZE
#define PVRREG_TILEBUF_SIZE
Definition: dreamcast_pvr.h:323
DEVICE_TICK
DEVICE_TICK(pvr_fb)
Definition: dev_pvr.cc:2278
vfb_data::update_x2
int update_x2
Definition: devices.h:220
MEM_READ
#define MEM_READ
Definition: memory.h:116
PVRREG_FB_CLIP_X
#define PVRREG_FB_CLIP_X
Definition: dreamcast_pvr.h:177
pvr_ta_init
void pvr_ta_init(struct cpu *cpu, struct pvr_data *d)
Definition: dev_pvr.cc:1406
vfb_data::xsize
int xsize
Definition: devices.h:204
DIWMODE_EX_SHIFT
#define DIWMODE_EX_SHIFT
Definition: dreamcast_pvr.h:131
t
vmrs t
Definition: armreg.h:750
FB_CLIP_XY_MIN_MASK
#define FB_CLIP_XY_MIN_MASK
Definition: dreamcast_pvr.h:179
DIWMODE_SL_MASK
#define DIWMODE_SL_MASK
Definition: dreamcast_pvr.h:134
PVRREG_PALETTE_CFG
#define PVRREG_PALETTE_CFG
Definition: dreamcast_pvr.h:287
DM_DEFAULT
#define DM_DEFAULT
Definition: memory.h:130
devinit::machine
struct machine * machine
Definition: device.h:41
SYSASIC_EVENT_TRANSDONE
#define SYSASIC_EVENT_TRANSDONE
Definition: dreamcast_sysasicvar.h:58
vfb_data::update_y1
int update_y1
Definition: devices.h:220
PVR_COUNT
#define PVR_COUNT
Definition: dev_pvr.cc:90
TA_OPB_CFG_TRANSPOLY_MASK
#define TA_OPB_CFG_TRANSPOLY_MASK
Definition: dreamcast_pvr.h:332
addr
uint32_t addr
Definition: tmp_arm_multi.cc:52
PVR_PALETTE_CFG_MODE_MASK
#define PVR_PALETTE_CFG_MODE_MASK
Definition: dreamcast_pvr.h:288
pvr_render
void pvr_render(struct cpu *cpu, struct pvr_data *d)
Definition: dev_pvr.cc:1043
PVRREG_REVISION
#define PVRREG_REVISION
Definition: dreamcast_pvr.h:85
RASEVTPOS_POS2_MASK
#define RASEVTPOS_POS2_MASK
Definition: dreamcast_pvr.h:219
PVRREG_FB_CLIP_Y
#define PVRREG_FB_CLIP_Y
Definition: dreamcast_pvr.h:178
CHCR_DM_DECREMENTED
#define CHCR_DM_DECREMENTED
Definition: sh4_dmacreg.h:120
sh_cpu::dmac_tcr
uint32_t dmac_tcr[N_SH4_DMA_CHANNELS]
Definition: cpu_sh.h:166
PVRREG_SHADOW
#define PVRREG_SHADOW
Definition: dreamcast_pvr.h:183
device.h
PVRREG_REGSTART
#define PVRREG_REGSTART
Definition: dreamcast_pvr.h:78
pvr_data::fb_update_x1
int fb_update_x1
Definition: dev_pvr.cc:98
CHCR_TS_8BYTE
#define CHCR_TS_8BYTE
Definition: sh4_dmacreg.h:128
PVR_FOG_TABLE_SIZE
#define PVR_FOG_TABLE_SIZE
Definition: dreamcast_pvr.h:361
DIWSIZE_MODULO_SHIFT
#define DIWSIZE_MODULO_SHIFT
Definition: dreamcast_pvr.h:171
VRAM_SIZE
#define VRAM_SIZE
Definition: dev_pvr.cc:83
N_PVR_DMA_REGS
#define N_PVR_DMA_REGS
Definition: dev_pvr.cc:87
pvr_data::vblank_interrupts_pending
int vblank_interrupts_pending
Definition: dev_pvr.cc:104
PVR_RESET_PVR
#define PVR_RESET_PVR
Definition: dreamcast_pvr.h:92
cmd
Definition: debugger_cmds.cc:1189
PVR_MODE
#define PVR_MODE
Definition: dev_pvr.cc:91
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
PVRREG_DIWMODE
#define PVRREG_DIWMODE
Definition: dreamcast_pvr.h:117
PVRREG_REGSIZE
#define PVRREG_REGSIZE
Definition: dreamcast_pvr.h:80
sh_cpu::dmac_dar
uint32_t dmac_dar[N_SH4_DMA_CHANNELS]
Definition: cpu_sh.h:165
SYSASIC_EVENT_OPAQUEDONE
#define SYSASIC_EVENT_OPAQUEDONE
Definition: dreamcast_sysasicvar.h:56
TA_OPB_CFG_OPAQUEPOLY_MASK
#define TA_OPB_CFG_OPAQUEPOLY_MASK
Definition: dreamcast_pvr.h:329
pvr_data::vram
uint8_t * vram
Definition: dev_pvr.cc:145
DIWSIZE_MASK
#define DIWSIZE_MASK
Definition: dreamcast_pvr.h:168
DIWMODE_TH_MASK
#define DIWMODE_TH_MASK
Definition: dreamcast_pvr.h:132
DM_DYNTRANS_WRITE_OK
#define DM_DYNTRANS_WRITE_OK
Definition: memory.h:132
SHADOW_INTENSITY_MASK
#define SHADOW_INTENSITY_MASK
Definition: dreamcast_pvr.h:184
machine_add_tickfunction
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
CHCR_SM_FIXED
#define CHCR_SM_FIXED
Definition: sh4_dmacreg.h:122
pvr_geometry_updated
void pvr_geometry_updated(struct pvr_data *d)
Definition: dev_pvr.cc:543
pvr_data::display_enabled
int display_enabled
Definition: dev_pvr.cc:122
SYSASIC_EVENT_OPAQUEMODDONE
#define SYSASIC_EVENT_OPAQUEMODDONE
Definition: dreamcast_sysasicvar.h:57
PVRREG_BGPLANE_Z
#define PVRREG_BGPLANE_Z
Definition: dreamcast_pvr.h:194
PVR_RESET_TA
#define PVR_RESET_TA
Definition: dreamcast_pvr.h:91
PVRREG_BRDCOLR
#define PVRREG_BRDCOLR
Definition: dreamcast_pvr.h:112
PVRREG_TA_OPB_START
#define PVRREG_TA_OPB_START
Definition: dreamcast_pvr.h:305
SYNCCONF_BC_VGA
#define SYNCCONF_BC_VGA
Definition: dreamcast_pvr.h:234
PVRREG_FB_RENDER_ADDR2
#define PVRREG_FB_RENDER_ADDR2
Definition: dreamcast_pvr.h:175
PHYSICAL
#define PHYSICAL
Definition: memory.h:126
SYNCSIZE_V_SHIFT
#define SYNCSIZE_V_SHIFT
Definition: dreamcast_pvr.h:251
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
PVRREG_UNKNOWN_84
#define PVRREG_UNKNOWN_84
Definition: dreamcast_pvr.h:192
FB_RENDER_CFG_RENDER_MODE_MASK
#define FB_RENDER_CFG_RENDER_MODE_MASK
Definition: dreamcast_pvr.h:140
CHCR_SM_INCREMENTED
#define CHCR_SM_INCREMENTED
Definition: sh4_dmacreg.h:123
CHCR_DM_INCREMENTED
#define CHCR_DM_INCREMENTED
Definition: sh4_dmacreg.h:119
CHCR_TS_2BYTE
#define CHCR_TS_2BYTE
Definition: sh4_dmacreg.h:130
TA_OPB_START_MASK
#define TA_OPB_START_MASK
Definition: dreamcast_pvr.h:306
PVRREG_OB_CFG
#define PVRREG_OB_CFG
Definition: dreamcast_pvr.h:189
pvr_data::fb_update_x2
int fb_update_x2
Definition: dev_pvr.cc:100
pvr_fb_invalidate
void pvr_fb_invalidate(struct pvr_data *d, int start, int stop)
Definition: dev_pvr.cc:516
TA_OB_START_MASK
#define TA_OB_START_MASK
Definition: dreamcast_pvr.h:309
misc.h
SYNCCONF_BC_PAL
#define SYNCCONF_BC_PAL
Definition: dreamcast_pvr.h:236
DIWMODE_SL_SHIFT
#define DIWMODE_SL_SHIFT
Definition: dreamcast_pvr.h:135
PVRREG_TA_OPB_CFG
#define PVRREG_TA_OPB_CFG
Definition: dreamcast_pvr.h:328
PVRREG_FOG_VERTEX_COL
#define PVRREG_FOG_VERTEX_COL
Definition: dreamcast_pvr.h:210
PVRREG_TA_LUMINANCE
#define PVRREG_TA_LUMINANCE
Definition: dreamcast_pvr.h:303
DIWMODE_TH_SHIFT
#define DIWMODE_TH_SHIFT
Definition: dreamcast_pvr.h:133
memory_readmax64
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
CHCR_RS
#define CHCR_RS
Definition: sh4_dmacreg.h:125
cpu::cd
union cpu::@1 cd
PVR_SPANSORT_SPAN1
#define PVR_SPANSORT_SPAN1
Definition: dreamcast_pvr.h:109
SYNCSIZE_V_MASK
#define SYNCSIZE_V_MASK
Definition: dreamcast_pvr.h:250
BRDHORZ_START_MASK
#define BRDHORZ_START_MASK
Definition: dreamcast_pvr.h:243
machine.h
TA_OPB_CFG_OPAQUEMOD_MASK
#define TA_OPB_CFG_OPAQUEMOD_MASK
Definition: dreamcast_pvr.h:330
PVRREG_TA_OB_POS
#define PVRREG_TA_OB_POS
Definition: dreamcast_pvr.h:320
PVRREG_SYNCSIZE
#define PVRREG_SYNCSIZE
Definition: dreamcast_pvr.h:248
machine
Definition: machine.h:97
pvr_data::broadcast_standard
int broadcast_standard
Definition: dev_pvr.cc:127
PVRREG_PALETTE
#define PVRREG_PALETTE
Definition: dreamcast_pvr.h:363
timer.h
CHCR_DM_FIXED
#define CHCR_DM_FIXED
Definition: sh4_dmacreg.h:118
PVRREG_YUV_STAT
#define PVRREG_YUV_STAT
Definition: dreamcast_pvr.h:349
pvr_data::tilebuf_ysize
int tilebuf_ysize
Definition: dev_pvr.cc:133
PVRREG_FOG_TABLE
#define PVRREG_FOG_TABLE
Definition: dreamcast_pvr.h:360
devinit::name
char * name
Definition: device.h:43
pvr_data::current_list_type
int current_list_type
Definition: dev_pvr.cc:139
ieee_float_value
Definition: float_emul.h:38
pvr_data::vram_z
double * vram_z
Definition: dev_pvr.cc:146
SYNCCONF_I_MASK
#define SYNCCONF_I_MASK
Definition: dreamcast_pvr.h:237
PVRREG_TA_OPB_POS
#define PVRREG_TA_OPB_POS
Definition: dreamcast_pvr.h:317
cpu::sh
struct sh_cpu sh
Definition: cpu.h:448
PVR_LMMODE0
#define PVR_LMMODE0
Definition: dev_pvr.cc:92
SYNCCONF_VP_MASK
#define SYNCCONF_VP_MASK
Definition: dreamcast_pvr.h:239
PVRREG_BRDVERT
#define PVRREG_BRDVERT
Definition: dreamcast_pvr.h:255
DIWCONF_MAGIC
#define DIWCONF_MAGIC
Definition: dreamcast_pvr.h:273
PVRREG_DIWCONF
#define PVRREG_DIWCONF
Definition: dreamcast_pvr.h:269
PVR_TA_INIT
#define PVR_TA_INIT
Definition: dreamcast_pvr.h:341
pvr_data::pixelmode
int pixelmode
Definition: dev_pvr.cc:120
PVRREG_RESET
#define PVRREG_RESET
Definition: dreamcast_pvr.h:90
pvr_data::fb_update_y2
int fb_update_y2
Definition: dev_pvr.cc:101
BRDHORZ_START_SHIFT
#define BRDHORZ_START_SHIFT
Definition: dreamcast_pvr.h:244
PVRREG_TA_OPL_INIT
#define PVRREG_TA_OPL_INIT
Definition: dreamcast_pvr.h:356
FB_CLIP_XY_MAX_SHIFT
#define FB_CLIP_XY_MAX_SHIFT
Definition: dreamcast_pvr.h:181
devinit
Definition: device.h:40
CHCR_TS_1BYTE
#define CHCR_TS_1BYTE
Definition: sh4_dmacreg.h:129
float_emul.h
PVRREG_SYNCH_WIDTH
#define PVRREG_SYNCH_WIDTH
Definition: dreamcast_pvr.h:262
pvr_data::fb_update_y1
int fb_update_y1
Definition: dev_pvr.cc:99
vfb_data::framebuffer
unsigned char * framebuffer
Definition: devices.h:231
PVRREG_UNKNOWN_80
#define PVRREG_UNKNOWN_80
Definition: dreamcast_pvr.h:191
memory_device_dyntrans_access
void memory_device_dyntrans_access(struct cpu *, struct memory *mem, void *extra, uint64_t *low, uint64_t *high)
Definition: memory.cc:264
cpu.h
DIWVSTRT_V2_MASK
#define DIWVSTRT_V2_MASK
Definition: dreamcast_pvr.h:280
CHCR_TE
#define CHCR_TE
Definition: sh4_dmacreg.h:135
pvr_data_alt
Definition: dev_pvr.cc:153
machine::memory
struct memory * memory
Definition: machine.h:126
cpu::mem
struct memory * mem
Definition: cpu.h:362
pvr_data::interlaced
int interlaced
Definition: dev_pvr.cc:128
pvr_data::argb8888_threshold
int argb8888_threshold
Definition: dev_pvr.cc:118
PVR_MARGIN
#define PVR_MARGIN
Definition: dev_pvr.cc:81
CHCR_DM
#define CHCR_DM
Definition: sh4_dmacreg.h:117
VRAM_CFG1_GOOD_REFRESH_VALUE
#define VRAM_CFG1_GOOD_REFRESH_VALUE
Definition: dreamcast_pvr.h:201
ieee_float_value::f
double f
Definition: float_emul.h:39
PVRREG_BRDHORZ
#define PVRREG_BRDHORZ
Definition: dreamcast_pvr.h:241
zeroed_alloc
void * zeroed_alloc(size_t s)
Definition: memory.cc:118
IEEE_FMT_S
#define IEEE_FMT_S
Definition: float_emul.h:43
pvr_data::dma_reg
uint32_t dma_reg[N_PVR_DMA_REGS]
Definition: dev_pvr.cc:149
SYNCCONF_VO_MASK
#define SYNCCONF_VO_MASK
Definition: dreamcast_pvr.h:231
BRDVERT_STOP_MASK
#define BRDVERT_STOP_MASK
Definition: dreamcast_pvr.h:256
PVRREG_FOG_TABLE_COL
#define PVRREG_FOG_TABLE_COL
Definition: dreamcast_pvr.h:209
PVRREG_TA_OB_END
#define PVRREG_TA_OB_END
Definition: dreamcast_pvr.h:314
sh_cpu::dmac_sar
uint32_t dmac_sar[N_SH4_DMA_CHANNELS]
Definition: cpu_sh.h:164
DIWCONF_BLANK
#define DIWCONF_BLANK
Definition: dreamcast_pvr.h:270
PVR_DMA_MEMLENGTH
#define PVR_DMA_MEMLENGTH
Definition: dev_pvr.cc:86
vfb_data::bytes_per_line
int bytes_per_line
Definition: devices.h:212
pvr_data::strip_length
int strip_length
Definition: dev_pvr.cc:117
pvr_data::xsize
int xsize
Definition: dev_pvr.cc:110
PVRREG_OB_ADDR
#define PVRREG_OB_ADDR
Definition: dreamcast_pvr.h:97
pvr_data::bytes_per_pixel
int bytes_per_pixel
Definition: dev_pvr.cc:111
PVRREG_SYNCCONF
#define PVRREG_SYNCCONF
Definition: dreamcast_pvr.h:225
PVR_ADDR
#define PVR_ADDR
Definition: dev_pvr.cc:89
vfb_data::update_x1
int update_x1
Definition: devices.h:220
NO_EXCEPTIONS
#define NO_EXCEPTIONS
Definition: memory.h:125
DM_READS_HAVE_NO_SIDE_EFFECTS
#define DM_READS_HAVE_NO_SIDE_EFFECTS
Definition: memory.h:133
pvr_data::reg
uint32_t reg[PVRREG_REGSIZE/sizeof(uint32_t)]
Definition: dev_pvr.cc:107
PVRREG_SPANSORT
#define PVRREG_SPANSORT
Definition: dreamcast_pvr.h:107
SYNCCONF_BC_MASK
#define SYNCCONF_BC_MASK
Definition: dreamcast_pvr.h:232
PVRREG_VRAM_CFG2
#define PVRREG_VRAM_CFG2
Definition: dreamcast_pvr.h:203
PVR_TILEBUF_ADDR_MASK
#define PVR_TILEBUF_ADDR_MASK
Definition: dreamcast_pvr.h:105
PVR_PALETTE_SIZE
#define PVR_PALETTE_SIZE
Definition: dreamcast_pvr.h:364
DIWMODE_C_MASK
#define DIWMODE_C_MASK
Definition: dreamcast_pvr.h:137
dreamcast_pvr.h
PVRREG_TSP_CFG
#define PVRREG_TSP_CFG
Definition: dreamcast_pvr.h:264
PVRREG_RASEVTPOS
#define PVRREG_RASEVTPOS
Definition: dreamcast_pvr.h:218
PVRREG_ID
#define PVRREG_ID
Definition: dreamcast_pvr.h:83
TILEBUF_SIZE_HEIGHT_SHIFT
#define TILEBUF_SIZE_HEIGHT_SHIFT
Definition: dreamcast_pvr.h:325
VRAM_CFG2_UNKNOWN_MAGIC
#define VRAM_CFG2_UNKNOWN_MAGIC
Definition: dreamcast_pvr.h:204
PVRREG_FB_RENDER_ADDR1
#define PVRREG_FB_RENDER_ADDR1
Definition: dreamcast_pvr.h:173
DIWSIZE_DPL_SHIFT
#define DIWSIZE_DPL_SHIFT
Definition: dreamcast_pvr.h:169
SYNCCONF_BC_SHIFT
#define SYNCCONF_BC_SHIFT
Definition: dreamcast_pvr.h:233
pvr_data::ta
uint32_t ta[64/sizeof(uint32_t)]
Definition: dev_pvr.cc:136
pvr_data_alt::d
struct pvr_data * d
Definition: dev_pvr.cc:154
PVRREG_DIWVSTRT
#define PVRREG_DIWVSTRT
Definition: dreamcast_pvr.h:278
SYSASIC_TRIGGER_EVENT
#define SYSASIC_TRIGGER_EVENT(e)
Definition: dreamcast_sysasicvar.h:77
pvr_data::n_ta_commands
size_t n_ta_commands
Definition: dev_pvr.cc:142
SYSASIC_EVENT_VBLINT
#define SYSASIC_EVENT_VBLINT
Definition: dreamcast_sysasicvar.h:55
DIWCONF_LR
#define DIWCONF_LR
Definition: dreamcast_pvr.h:271
REG
#define REG(x)
Definition: dev_pvr.cc:158
pvr_data::fb
struct vfb_data * fb
Definition: dev_pvr.cc:97
PVRREG_HPOS_IRQ
#define PVRREG_HPOS_IRQ
Definition: dreamcast_pvr.h:216
PVR_SPANSORT_TSP_CACHE_ENABLE
#define PVR_SPANSORT_TSP_CACHE_ENABLE
Definition: dreamcast_pvr.h:110
vfb_data::ysize
int ysize
Definition: devices.h:205
memory_writemax64
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
PVR_FB_TICK_SHIFT
#define PVR_FB_TICK_SHIFT
Definition: dev_pvr.cc:77
DIWSIZE_LPF_SHIFT
#define DIWSIZE_LPF_SHIFT
Definition: dreamcast_pvr.h:170
PVRREG_VRAM_CFG1
#define PVRREG_VRAM_CFG1
Definition: dreamcast_pvr.h:200
pvr_data::video_enabled
int video_enabled
Definition: dev_pvr.cc:126
RASEVTPOS_POS1_MASK
#define RASEVTPOS_POS1_MASK
Definition: dreamcast_pvr.h:220
PVR_SPANSORT_SPAN0
#define PVR_SPANSORT_SPAN0
Definition: dreamcast_pvr.h:108
devices.h
SYNCCONF_BC_NTSC
#define SYNCCONF_BC_NTSC
Definition: dreamcast_pvr.h:235
pvr_data::allocated_ta_commands
size_t allocated_ta_commands
Definition: dev_pvr.cc:141
cpu
Definition: cpu.h:326
DM_DYNTRANS_OK
#define DM_DYNTRANS_OK
Definition: memory.h:131
DEVICE_ACCESS
DEVICE_ACCESS(pvr_ta)
Definition: dev_pvr.cc:1515
pvr_data::tilebuf_xsize
int tilebuf_xsize
Definition: dev_pvr.cc:132
pvr_data::v_sync_positive
int v_sync_positive
Definition: dev_pvr.cc:130
PVRREG_ISP_CFG
#define PVRREG_ISP_CFG
Definition: dreamcast_pvr.h:198
pvr_data::h_sync_positive
int h_sync_positive
Definition: dev_pvr.cc:129
pvr_data::dma_more_reg
uint32_t dma_more_reg[N_PVR_DMA_REGS]
Definition: dev_pvr.cc:150
PVRREG_SCALER_CFG
#define PVRREG_SCALER_CFG
Definition: dreamcast_pvr.h:285
PVRREG_BGPLANE_CFG
#define PVRREG_BGPLANE_CFG
Definition: dreamcast_pvr.h:196
pvr_data::ysize
int ysize
Definition: dev_pvr.cc:110
DEFAULT_WRITE
#define DEFAULT_WRITE
Definition: dev_pvr.cc:159
PVRREG_MAGIC_110
#define PVRREG_MAGIC_110
Definition: dreamcast_pvr.h:300
cpu::memory_rw
int(* memory_rw)(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int cache_flags)
Definition: cpu.h:368
PVR_LMMODE1
#define PVR_LMMODE1
Definition: dev_pvr.cc:93
vfb_data
Definition: devices.h:198
SYSASIC_EVENT_RENDERDONE
#define SYSASIC_EVENT_RENDERDONE
Definition: dreamcast_sysasicvar.h:52
PVRREG_DIWSIZE
#define PVRREG_DIWSIZE
Definition: dreamcast_pvr.h:164
pvr_data::ta_commands
uint32_t * ta_commands
Definition: dev_pvr.cc:140
PVRREG_TA_INIT
#define PVRREG_TA_INIT
Definition: dreamcast_pvr.h:340
pvr_data::vblank_timer
struct timer * vblank_timer
Definition: dev_pvr.cc:103
PVR_PALETTE_CFG_MODE_ARGB8888
#define PVR_PALETTE_CFG_MODE_ARGB8888
Definition: dreamcast_pvr.h:292
PVRREG_DIWADDRL
#define PVRREG_DIWADDRL
Definition: dreamcast_pvr.h:160
DIWMODE_EX_MASK
#define DIWMODE_EX_MASK
Definition: dreamcast_pvr.h:130
TA_OPB_CFG_PUNCHTHROUGH_MASK
#define TA_OPB_CFG_PUNCHTHROUGH_MASK
Definition: dreamcast_pvr.h:336
pvr_data
Definition: dev_pvr.cc:96
SYNCCONF_HP_MASK
#define SYNCCONF_HP_MASK
Definition: dreamcast_pvr.h:238
SYSASIC_EVENT_TRANSMODDONE
#define SYSASIC_EVENT_TRANSMODDONE
Definition: dreamcast_sysasicvar.h:59
PVRREG_FOG_DENSITY
#define PVRREG_FOG_DENSITY
Definition: dreamcast_pvr.h:211
memory.h
pvr_data::clock_double
int clock_double
Definition: dev_pvr.cc:115
TILEBUF_SIZE_WIDTH_MASK
#define TILEBUF_SIZE_WIDTH_MASK
Definition: dreamcast_pvr.h:326
DIWMODE_SE_MASK
#define DIWMODE_SE_MASK
Definition: dreamcast_pvr.h:136
DIWVSTRT_V1_MASK
#define DIWVSTRT_V1_MASK
Definition: dreamcast_pvr.h:279
MAGIC_110_VALUE
#define MAGIC_110_VALUE
Definition: dreamcast_pvr.h:301
dev_fb_init
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)
Definition: dev_fb.cc:834
PVRREG_TILEBUF_ADDR
#define PVRREG_TILEBUF_ADDR
Definition: dreamcast_pvr.h:104
CHCR_TS_32BYTE
#define CHCR_TS_32BYTE
Definition: sh4_dmacreg.h:132
SYSASIC_EVENT_PVR_DMA
#define SYSASIC_EVENT_PVR_DMA
Definition: dreamcast_sysasicvar.h:65
vfb_data::update_y2
int update_y2
Definition: devices.h:220
vfb_data::bit_depth
int bit_depth
Definition: devices.h:206
TA_OB_END_MASK
#define TA_OB_END_MASK
Definition: dreamcast_pvr.h:315
BRDHORZ_STOP_MASK
#define BRDHORZ_STOP_MASK
Definition: dreamcast_pvr.h:242
CHCR_IE
#define CHCR_IE
Definition: sh4_dmacreg.h:134
PVR_TA_OPL_INIT_MASK
#define PVR_TA_OPL_INIT_MASK
Definition: dreamcast_pvr.h:358
CHECK_ALLOCATION
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18