Search
lxdream.org :: lxdream/src/pvr2/pvr2.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/pvr2.c
changeset 103:9b9cfc5855e0
prev100:995e42e96cc9
next106:9048bac046c3
author nkeynes
date Mon Mar 13 12:39:07 2006 +0000 (14 years ago)
permissions -rw-r--r--
last change More rendering work in progress. Almost there now...
file annotate diff log raw
1.1 --- a/src/pvr2/pvr2.c Wed Feb 15 13:11:50 2006 +0000
1.2 +++ b/src/pvr2/pvr2.c Mon Mar 13 12:39:07 2006 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: pvr2.c,v 1.16 2006-02-15 13:11:46 nkeynes Exp $
1.6 + * $Id: pvr2.c,v 1.17 2006-03-13 12:39:07 nkeynes Exp $
1.7 *
1.8 * PVR2 (Video) Core MMIO registers.
1.9 *
1.10 @@ -21,10 +21,10 @@
1.11 #include "video.h"
1.12 #include "mem.h"
1.13 #include "asic.h"
1.14 -#include "pvr2.h"
1.15 +#include "pvr2/pvr2.h"
1.16 #include "sh4/sh4core.h"
1.17 #define MMIO_IMPL
1.18 -#include "pvr2.h"
1.19 +#include "pvr2/pvr2mmio.h"
1.20
1.21 char *video_base;
1.22
1.23 @@ -32,10 +32,25 @@
1.24 uint32_t pvr2_run_slice( uint32_t );
1.25 void pvr2_display_frame( void );
1.26
1.27 +/**
1.28 + * Current PVR2 ram address of the data (if any) currently held in the
1.29 + * OpenGL buffers.
1.30 + */
1.31 +
1.32 video_driver_t video_driver = NULL;
1.33 struct video_buffer video_buffer[2];
1.34 int video_buffer_idx = 0;
1.35
1.36 +struct video_timing {
1.37 + int fields_per_second;
1.38 + int total_lines;
1.39 + int display_lines;
1.40 + int line_time_ns;
1.41 +};
1.42 +
1.43 +struct video_timing pal_timing = { 50, 625, 575, 32000 };
1.44 +struct video_timing ntsc_timing= { 60, 525, 480, 31746 };
1.45 +
1.46 struct dreamcast_module pvr2_module = { "PVR2", pvr2_init, NULL, NULL,
1.47 pvr2_run_slice, NULL,
1.48 NULL, NULL };
1.49 @@ -47,19 +62,36 @@
1.50 register_io_region( &mmio_region_PVR2TA );
1.51 video_base = mem_get_region_by_name( MEM_REGION_VIDEO );
1.52 video_driver = &video_gtk_driver;
1.53 - video_driver->set_output_format( 640, 480, COLFMT_RGB32 );
1.54 + video_driver->set_display_format( 640, 480, COLFMT_RGB32 );
1.55 }
1.56
1.57 +uint32_t pvr2_line_count = 0;
1.58 +uint32_t pvr2_line_remainder = 0;
1.59 +uint32_t pvr2_irq_vpos1 = 0;
1.60 +uint32_t pvr2_irq_vpos2 = 0;
1.61 +struct video_timing *pvr2_timing = &ntsc_timing;
1.62 uint32_t pvr2_time_counter = 0;
1.63 uint32_t pvr2_frame_counter = 0;
1.64 uint32_t pvr2_time_per_frame = 20000000;
1.65
1.66 uint32_t pvr2_run_slice( uint32_t nanosecs )
1.67 {
1.68 - pvr2_time_counter += nanosecs;
1.69 - while( pvr2_time_counter >= pvr2_time_per_frame ) {
1.70 - pvr2_display_frame();
1.71 - pvr2_time_counter -= pvr2_time_per_frame;
1.72 + pvr2_line_remainder += nanosecs;
1.73 + while( pvr2_line_remainder >= pvr2_timing->line_time_ns ) {
1.74 + pvr2_line_remainder -= pvr2_timing->line_time_ns;
1.75 + pvr2_line_count++;
1.76 + if( pvr2_line_count == pvr2_irq_vpos1 ) {
1.77 + asic_event( EVENT_SCANLINE1 );
1.78 + }
1.79 + if( pvr2_line_count == pvr2_irq_vpos2 ) {
1.80 + asic_event( EVENT_SCANLINE2 );
1.81 + }
1.82 + if( pvr2_line_count == pvr2_timing->display_lines ) {
1.83 + asic_event( EVENT_RETRACE );
1.84 + } else if( pvr2_line_count == pvr2_timing->total_lines ) {
1.85 + pvr2_display_frame();
1.86 + pvr2_line_count = 0;
1.87 + }
1.88 }
1.89 return nanosecs;
1.90 }
1.91 @@ -68,48 +100,61 @@
1.92 int interlaced, bChanged = 1, bEnabled = 0, vid_size = 0;
1.93 char *frame_start; /* current video start address (in real memory) */
1.94
1.95 -/*
1.96 +/**
1.97 * Display the next frame, copying the current contents of video ram to
1.98 * the window. If the video configuration has changed, first recompute the
1.99 * new frame size/depth.
1.100 */
1.101 void pvr2_display_frame( void )
1.102 {
1.103 + uint32_t display_addr = MMIO_READ( PVR2, DISPADDR1 );
1.104 +
1.105 int dispsize = MMIO_READ( PVR2, DISPSIZE );
1.106 int dispmode = MMIO_READ( PVR2, DISPMODE );
1.107 - int vidcfg = MMIO_READ( PVR2, VIDCFG );
1.108 + int vidcfg = MMIO_READ( PVR2, DISPCFG );
1.109 int vid_stride = ((dispsize & DISPSIZE_MODULO) >> 20) - 1;
1.110 int vid_lpf = ((dispsize & DISPSIZE_LPF) >> 10) + 1;
1.111 int vid_ppl = ((dispsize & DISPSIZE_PPL)) + 1;
1.112 - gboolean bEnabled = (dispmode & DISPMODE_DE) && (vidcfg & VIDCFG_VO ) ? TRUE : FALSE;
1.113 - gboolean interlaced = (vidcfg & VIDCFG_I ? TRUE : FALSE);
1.114 + gboolean bEnabled = (dispmode & DISPMODE_DE) && (vidcfg & DISPCFG_VO ) ? TRUE : FALSE;
1.115 + gboolean interlaced = (vidcfg & DISPCFG_I ? TRUE : FALSE);
1.116 if( bEnabled ) {
1.117 video_buffer_t buffer = &video_buffer[video_buffer_idx];
1.118 video_buffer_idx = !video_buffer_idx;
1.119 video_buffer_t last = &video_buffer[video_buffer_idx];
1.120 - buffer->colour_format = (dispmode & DISPMODE_COL);
1.121 buffer->rowstride = (vid_ppl + vid_stride) << 2;
1.122 buffer->data = frame_start = video_base + MMIO_READ( PVR2, DISPADDR1 );
1.123 buffer->vres = vid_lpf;
1.124 if( interlaced ) buffer->vres <<= 1;
1.125 - switch( buffer->colour_format ) {
1.126 - case COLFMT_RGB15:
1.127 - case COLFMT_RGB16: buffer->hres = vid_ppl << 1; break;
1.128 - case COLFMT_RGB24: buffer->hres = (vid_ppl << 2) / 3; break;
1.129 - case COLFMT_RGB32: buffer->hres = vid_ppl; break;
1.130 + switch( (dispmode & DISPMODE_COL) >> 2 ) {
1.131 + case 0:
1.132 + buffer->colour_format = COLFMT_ARGB1555;
1.133 + buffer->hres = vid_ppl << 1;
1.134 + break;
1.135 + case 1:
1.136 + buffer->colour_format = COLFMT_RGB565;
1.137 + buffer->hres = vid_ppl << 1;
1.138 + break;
1.139 + case 2:
1.140 + buffer->colour_format = COLFMT_RGB888;
1.141 + buffer->hres = (vid_ppl << 2) / 3;
1.142 + break;
1.143 + case 3:
1.144 + buffer->colour_format = COLFMT_ARGB8888;
1.145 + buffer->hres = vid_ppl;
1.146 + break;
1.147 }
1.148
1.149 if( video_driver != NULL ) {
1.150 if( buffer->hres != last->hres ||
1.151 buffer->vres != last->vres ||
1.152 buffer->colour_format != last->colour_format) {
1.153 - video_driver->set_output_format( buffer->hres, buffer->vres,
1.154 - buffer->colour_format );
1.155 + video_driver->set_display_format( buffer->hres, buffer->vres,
1.156 + buffer->colour_format );
1.157 }
1.158 - if( MMIO_READ( PVR2, VIDCFG2 ) & 0x08 ) { /* Blanked */
1.159 + if( MMIO_READ( PVR2, DISPCFG2 ) & 0x08 ) { /* Blanked */
1.160 uint32_t colour = MMIO_READ( PVR2, DISPBORDER );
1.161 video_driver->display_blank_frame( colour );
1.162 - } else {
1.163 + } else if( !pvr2_render_display_frame( PVR2_RAM_BASE + display_addr ) ) {
1.164 video_driver->display_frame( buffer );
1.165 }
1.166 }
1.167 @@ -135,6 +180,10 @@
1.168 MMIO_REGID(PVR2,reg), MMIO_REGDESC(PVR2,reg) );
1.169
1.170 switch(reg) {
1.171 + case VPOS_IRQ:
1.172 + pvr2_irq_vpos1 = (val >> 16) & 0x03FF;
1.173 + pvr2_irq_vpos2 = val & 0x03FF;
1.174 + break;
1.175 case TAINIT:
1.176 if( val & 0x80000000 )
1.177 pvr2_ta_init();
1.178 @@ -178,4 +227,88 @@
1.179 }
1.180
1.181
1.182 +void pvr2_vram64_write( sh4addr_t destaddr, char *src, uint32_t length )
1.183 +{
1.184 + int bank_flag = (destaddr & 0x04) >> 2;
1.185 + uint32_t *banks[2];
1.186 + uint32_t *dwsrc;
1.187 + int i;
1.188
1.189 + destaddr = destaddr & 0x7FFFFF;
1.190 + if( destaddr + length > 0x800000 ) {
1.191 + length = 0x800000 - destaddr;
1.192 + }
1.193 +
1.194 + for( i=destaddr & 0xFFFFF000; i < destaddr + length; i+= PAGE_SIZE ) {
1.195 + texcache_invalidate_page( i );
1.196 + }
1.197 +
1.198 + banks[0] = ((uint32_t *)(video_base + (destaddr>>3)));
1.199 + banks[1] = banks[0] + 0x100000;
1.200 +
1.201 + /* Handle non-aligned start of source */
1.202 + if( destaddr & 0x03 ) {
1.203 + char *dest = ((char *)banks[bank_flag]) + (destaddr & 0x03);
1.204 + for( i= destaddr & 0x03; i < 4 && length > 0; i++, length-- ) {
1.205 + *dest++ = *src++;
1.206 + }
1.207 + bank_flag = !bank_flag;
1.208 + }
1.209 +
1.210 + dwsrc = (uint32_t *)src;
1.211 + while( length >= 4 ) {
1.212 + *banks[bank_flag]++ = *dwsrc++;
1.213 + bank_flag = !bank_flag;
1.214 + length -= 4;
1.215 + }
1.216 +
1.217 + /* Handle non-aligned end of source */
1.218 + if( length ) {
1.219 + src = (char *)dwsrc;
1.220 + char *dest = (char *)banks[bank_flag];
1.221 + while( length-- > 0 ) {
1.222 + *dest++ = *src++;
1.223 + }
1.224 + }
1.225 +
1.226 +}
1.227 +
1.228 +void pvr2_vram64_read( char *dest, sh4addr_t srcaddr, uint32_t length )
1.229 +{
1.230 + int bank_flag = (srcaddr & 0x04) >> 2;
1.231 + uint32_t *banks[2];
1.232 + uint32_t *dwdest;
1.233 + int i;
1.234 +
1.235 + srcaddr = srcaddr & 0x7FFFFF;
1.236 + if( srcaddr + length > 0x800000 )
1.237 + length = 0x800000 - srcaddr;
1.238 +
1.239 + banks[0] = ((uint32_t *)(video_base + (srcaddr>>3)));
1.240 + banks[1] = banks[0] + 0x100000;
1.241 +
1.242 + /* Handle non-aligned start of source */
1.243 + if( srcaddr & 0x03 ) {
1.244 + char *src = ((char *)banks[bank_flag]) + (srcaddr & 0x03);
1.245 + for( i= srcaddr & 0x03; i < 4 && length > 0; i++, length-- ) {
1.246 + *dest++ = *src++;
1.247 + }
1.248 + bank_flag = !bank_flag;
1.249 + }
1.250 +
1.251 + dwdest = (uint32_t *)dest;
1.252 + while( length >= 4 ) {
1.253 + *dwdest++ = *banks[bank_flag]++;
1.254 + bank_flag = !bank_flag;
1.255 + length -= 4;
1.256 + }
1.257 +
1.258 + /* Handle non-aligned end of source */
1.259 + if( length ) {
1.260 + dest = (char *)dwdest;
1.261 + char *src = (char *)banks[bank_flag];
1.262 + while( length-- > 0 ) {
1.263 + *dest++ = *src++;
1.264 + }
1.265 + }
1.266 +}
.