Search
lxdream.org :: lxdream/src/pvr2/pvr2.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/pvr2.c
changeset 274:4e8f1e988d80
prev269:e41f9b1490d1
next282:01e53698ff38
author nkeynes
date Thu Jan 11 12:14:57 2007 +0000 (13 years ago)
permissions -rw-r--r--
last change Fix scheduling of scanlines between even and odd frames
view annotate diff log raw
     1 /**
     2  * $Id: pvr2.c,v 1.37 2007-01-11 12:14:57 nkeynes Exp $
     3  *
     4  * PVR2 (Video) Core module implementation and MMIO registers.
     5  *
     6  * Copyright (c) 2005 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    18 #define MODULE pvr2_module
    20 #include "dream.h"
    21 #include "eventq.h"
    22 #include "display.h"
    23 #include "mem.h"
    24 #include "asic.h"
    25 #include "clock.h"
    26 #include "pvr2/pvr2.h"
    27 #include "sh4/sh4core.h"
    28 #define MMIO_IMPL
    29 #include "pvr2/pvr2mmio.h"
    31 char *video_base;
    33 static void pvr2_init( void );
    34 static void pvr2_reset( void );
    35 static uint32_t pvr2_run_slice( uint32_t );
    36 static void pvr2_save_state( FILE *f );
    37 static int pvr2_load_state( FILE *f );
    38 static void pvr2_update_raster_posn( uint32_t nanosecs );
    39 static void pvr2_schedule_line_event( int eventid, int line );
    40 static void pvr2_schedule_scanline_event( int eventid, int line, int minimum_lines );
    41 uint32_t pvr2_get_sync_status();
    43 void pvr2_display_frame( void );
    45 int colour_format_bytes[] = { 2, 2, 2, 1, 3, 4, 1, 1 };
    47 struct dreamcast_module pvr2_module = { "PVR2", pvr2_init, pvr2_reset, NULL, 
    48 					pvr2_run_slice, NULL,
    49 					pvr2_save_state, pvr2_load_state };
    52 display_driver_t display_driver = NULL;
    54 struct video_timing {
    55     int fields_per_second;
    56     int total_lines;
    57     int retrace_lines;
    58     int line_time_ns;
    59 };
    61 struct video_timing pal_timing = { 50, 625, 65, 31945 };
    62 struct video_timing ntsc_timing= { 60, 525, 65, 31746 };
    64 struct pvr2_state {
    65     uint32_t frame_count;
    66     uint32_t line_count;
    67     uint32_t line_remainder;
    68     uint32_t cycles_run; /* Cycles already executed prior to main time slice */
    69     uint32_t irq_vpos1;
    70     uint32_t irq_vpos2;
    71     uint32_t odd_even_field; /* 1 = odd, 0 = even */
    73     /* timing */
    74     uint32_t dot_clock;
    75     uint32_t total_lines;
    76     uint32_t line_size;
    77     uint32_t line_time_ns;
    78     uint32_t vsync_lines;
    79     uint32_t hsync_width_ns;
    80     uint32_t front_porch_ns;
    81     uint32_t back_porch_ns;
    82     uint32_t retrace_start_line;
    83     uint32_t retrace_end_line;
    84     gboolean interlaced;
    85     struct video_timing timing;
    86 } pvr2_state;
    88 struct video_buffer video_buffer[2];
    89 int video_buffer_idx = 0;
    91 /**
    92  * Event handler for the retrace callback (fires on line 0 normally)
    93  */
    94 static void pvr2_retrace_callback( int eventid ) {
    95     asic_event( eventid );
    96     pvr2_update_raster_posn(sh4r.slice_cycle);
    97     pvr2_schedule_line_event( EVENT_RETRACE, 0 );
    98 }
   100 /**
   101  * Event handler for the scanline callbacks. Fires the corresponding
   102  * ASIC event, and resets the timer for the next field.
   103  */
   104 static void pvr2_scanline_callback( int eventid ) {
   105     asic_event( eventid );
   106     pvr2_update_raster_posn(sh4r.slice_cycle);
   107     if( eventid == EVENT_SCANLINE1 ) {
   108 	pvr2_schedule_scanline_event( eventid, pvr2_state.irq_vpos1, 1 );
   109     } else {
   110 	pvr2_schedule_scanline_event( eventid, pvr2_state.irq_vpos2, 1 );
   111     }
   112 }
   114 static void pvr2_init( void )
   115 {
   116     register_io_region( &mmio_region_PVR2 );
   117     register_io_region( &mmio_region_PVR2PAL );
   118     register_io_region( &mmio_region_PVR2TA );
   119     register_event_callback( EVENT_RETRACE, pvr2_retrace_callback );
   120     register_event_callback( EVENT_SCANLINE1, pvr2_scanline_callback );
   121     register_event_callback( EVENT_SCANLINE2, pvr2_scanline_callback );
   122     video_base = mem_get_region_by_name( MEM_REGION_VIDEO );
   123     texcache_init();
   124     pvr2_reset();
   125     pvr2_ta_reset();
   126 }
   128 static void pvr2_reset( void )
   129 {
   130     pvr2_state.line_count = 0;
   131     pvr2_state.line_remainder = 0;
   132     pvr2_state.cycles_run = 0;
   133     pvr2_state.irq_vpos1 = 0;
   134     pvr2_state.irq_vpos2 = 0;
   135     pvr2_state.timing = ntsc_timing;
   136     pvr2_state.dot_clock = PVR2_DOT_CLOCK;
   137     pvr2_state.back_porch_ns = 4000;
   138     mmio_region_PVR2_write( DISP_TOTAL, 0x0270035F );
   139     mmio_region_PVR2_write( DISP_SYNCTIME, 0x07D6A53F );
   140     video_buffer_idx = 0;
   142     pvr2_ta_init();
   143     pvr2_render_init();
   144     texcache_flush();
   145 }
   147 static void pvr2_save_state( FILE *f )
   148 {
   149     fwrite( &pvr2_state, sizeof(pvr2_state), 1, f );
   150     pvr2_ta_save_state( f );
   151 }
   153 static int pvr2_load_state( FILE *f )
   154 {
   155     if( fread( &pvr2_state, sizeof(pvr2_state), 1, f ) != 1 )
   156 	return 1;
   157     return pvr2_ta_load_state(f);
   158 }
   160 /**
   161  * Update the current raster position to the given number of nanoseconds,
   162  * relative to the last time slice. (ie the raster will be adjusted forward
   163  * by nanosecs - nanosecs_already_run_this_timeslice)
   164  */
   165 static void pvr2_update_raster_posn( uint32_t nanosecs )
   166 {
   167     uint32_t old_line_count = pvr2_state.line_count;
   168     if( pvr2_state.line_time_ns == 0 ) {
   169 	return; /* do nothing */
   170     }
   171     pvr2_state.line_remainder += (nanosecs - pvr2_state.cycles_run);
   172     pvr2_state.cycles_run = nanosecs;
   173     while( pvr2_state.line_remainder >= pvr2_state.line_time_ns ) {
   174 	pvr2_state.line_count ++;
   175 	pvr2_state.line_remainder -= pvr2_state.line_time_ns;
   176     }
   178     if( pvr2_state.line_count >= pvr2_state.total_lines ) {
   179 	pvr2_state.line_count -= pvr2_state.total_lines;
   180 	if( pvr2_state.interlaced ) {
   181 	    pvr2_state.odd_even_field = !pvr2_state.odd_even_field;
   182 	}
   183     }
   184     if( pvr2_state.line_count >= pvr2_state.retrace_end_line &&
   185 	(old_line_count < pvr2_state.retrace_end_line ||
   186 	 old_line_count > pvr2_state.line_count) ) {
   187 	pvr2_display_frame();
   188     }
   189 }
   191 static uint32_t pvr2_run_slice( uint32_t nanosecs ) 
   192 {
   193     pvr2_update_raster_posn( nanosecs );
   194     pvr2_state.cycles_run = 0;
   195     return nanosecs;
   196 }
   198 int pvr2_get_frame_count() 
   199 {
   200     return pvr2_state.frame_count;
   201 }
   203 /**
   204  * Display the next frame, copying the current contents of video ram to
   205  * the window. If the video configuration has changed, first recompute the
   206  * new frame size/depth.
   207  */
   208 void pvr2_display_frame( void )
   209 {
   210     uint32_t display_addr = MMIO_READ( PVR2, DISP_ADDR1 );
   212     int dispsize = MMIO_READ( PVR2, DISP_SIZE );
   213     int dispmode = MMIO_READ( PVR2, DISP_MODE );
   214     int vidcfg = MMIO_READ( PVR2, DISP_SYNCCFG );
   215     int vid_stride = ((dispsize & DISPSIZE_MODULO) >> 20) - 1;
   216     int vid_lpf = ((dispsize & DISPSIZE_LPF) >> 10) + 1;
   217     int vid_ppl = ((dispsize & DISPSIZE_PPL)) + 1;
   218     gboolean bEnabled = (dispmode & DISPMODE_DE) && (vidcfg & DISPCFG_VO ) ? TRUE : FALSE;
   219     gboolean interlaced = (vidcfg & DISPCFG_I ? TRUE : FALSE);
   220     video_buffer_t buffer = &video_buffer[video_buffer_idx];
   221     video_buffer_idx = !video_buffer_idx;
   222     video_buffer_t last = &video_buffer[video_buffer_idx];
   223     buffer->rowstride = (vid_ppl + vid_stride) << 2;
   224     buffer->data = video_base + MMIO_READ( PVR2, DISP_ADDR1 );
   225     buffer->vres = vid_lpf;
   226     if( interlaced ) buffer->vres <<= 1;
   227     switch( (dispmode & DISPMODE_COL) >> 2 ) {
   228     case 0: 
   229 	buffer->colour_format = COLFMT_ARGB1555;
   230 	buffer->hres = vid_ppl << 1; 
   231 	break;
   232     case 1: 
   233 	buffer->colour_format = COLFMT_RGB565;
   234 	buffer->hres = vid_ppl << 1; 
   235 	break;
   236     case 2:
   237 	buffer->colour_format = COLFMT_RGB888;
   238 	buffer->hres = (vid_ppl << 2) / 3; 
   239 	break;
   240     case 3: 
   241 	buffer->colour_format = COLFMT_ARGB8888;
   242 	buffer->hres = vid_ppl; 
   243 	break;
   244     }
   246     if( buffer->hres <=8 )
   247 	buffer->hres = 640;
   248     if( buffer->vres <=8 )
   249 	buffer->vres = 480;
   250     if( display_driver != NULL ) {
   251 	if( buffer->hres != last->hres ||
   252 	    buffer->vres != last->vres ||
   253 	    buffer->colour_format != last->colour_format) {
   254 	    display_driver->set_display_format( buffer->hres, buffer->vres,
   255 						buffer->colour_format );
   256 	}
   257 	if( !bEnabled ) {
   258 	    display_driver->display_blank_frame( 0 );
   259 	} else if( MMIO_READ( PVR2, DISP_CFG2 ) & 0x08 ) { /* Blanked */
   260 	    uint32_t colour = MMIO_READ( PVR2, DISP_BORDER );
   261 	    display_driver->display_blank_frame( colour );
   262 	} else if( !pvr2_render_display_frame( PVR2_RAM_BASE + display_addr ) ) {
   263 	    display_driver->display_frame( buffer );
   264 	}
   265     }
   266     pvr2_state.frame_count++;
   267 }
   269 /**
   270  * This has to handle every single register individually as they all get masked 
   271  * off differently (and its easier to do it at write time)
   272  */
   273 void mmio_region_PVR2_write( uint32_t reg, uint32_t val )
   274 {
   275     if( reg >= 0x200 && reg < 0x600 ) { /* Fog table */
   276         MMIO_WRITE( PVR2, reg, val );
   277         return;
   278     }
   280     switch(reg) {
   281     case PVRID:
   282     case PVRVER:
   283     case GUNPOS: /* Read only registers */
   284 	break;
   285     case PVRRESET:
   286 	val &= 0x00000007; /* Do stuff? */
   287 	MMIO_WRITE( PVR2, reg, val );
   288 	break;
   289     case RENDER_START:
   290 	if( val == 0xFFFFFFFF || val == 0x00000001 )
   291 	    pvr2_render_scene();
   292 	break;
   293     case RENDER_POLYBASE:
   294     	MMIO_WRITE( PVR2, reg, val&0x00F00000 );
   295     	break;
   296     case RENDER_TSPCFG:
   297     	MMIO_WRITE( PVR2, reg, val&0x00010101 );
   298     	break;
   299     case DISP_BORDER:
   300     	MMIO_WRITE( PVR2, reg, val&0x01FFFFFF );
   301     	break;
   302     case DISP_MODE:
   303     	MMIO_WRITE( PVR2, reg, val&0x00FFFF7F );
   304     	break;
   305     case RENDER_MODE:
   306     	MMIO_WRITE( PVR2, reg, val&0x00FFFF0F );
   307     	break;
   308     case RENDER_SIZE:
   309     	MMIO_WRITE( PVR2, reg, val&0x000001FF );
   310     	break;
   311     case DISP_ADDR1:
   312 	val &= 0x00FFFFFC;
   313 	MMIO_WRITE( PVR2, reg, val );
   314 	pvr2_update_raster_posn(sh4r.slice_cycle);
   315 	if( pvr2_state.line_count >= pvr2_state.retrace_start_line ||
   316 	    pvr2_state.line_count < pvr2_state.retrace_end_line ) {
   317 	    pvr2_display_frame();
   318 	}
   319 	break;
   320     case DISP_ADDR2:
   321     	MMIO_WRITE( PVR2, reg, val&0x00FFFFFC );
   322     	break;
   323     case DISP_SIZE:
   324     	MMIO_WRITE( PVR2, reg, val&0x3FFFFFFF );
   325     	break;
   326     case RENDER_ADDR1:
   327     case RENDER_ADDR2:
   328     	MMIO_WRITE( PVR2, reg, val&0x01FFFFFC );
   329     	break;
   330     case RENDER_HCLIP:
   331 	MMIO_WRITE( PVR2, reg, val&0x07FF07FF );
   332 	break;
   333     case RENDER_VCLIP:
   334 	MMIO_WRITE( PVR2, reg, val&0x03FF03FF );
   335 	break;
   336     case DISP_HPOSIRQ:
   337 	MMIO_WRITE( PVR2, reg, val&0x03FF33FF );
   338 	break;
   339     case DISP_VPOSIRQ:
   340 	val = val & 0x03FF03FF;
   341 	pvr2_state.irq_vpos1 = (val >> 16);
   342 	pvr2_state.irq_vpos2 = val & 0x03FF;
   343 	pvr2_update_raster_posn(sh4r.slice_cycle);
   344 	pvr2_schedule_scanline_event( EVENT_SCANLINE1, pvr2_state.irq_vpos1, 0 );
   345 	pvr2_schedule_scanline_event( EVENT_SCANLINE2, pvr2_state.irq_vpos2, 0 );
   346 	MMIO_WRITE( PVR2, reg, val );
   347 	break;
   348     case RENDER_NEARCLIP:
   349 	MMIO_WRITE( PVR2, reg, val & 0x7FFFFFFF );
   350 	break;
   351     case RENDER_SHADOW:
   352 	MMIO_WRITE( PVR2, reg, val&0x000001FF );
   353 	break;
   354     case RENDER_OBJCFG:
   355     	MMIO_WRITE( PVR2, reg, val&0x003FFFFF );
   356     	break;
   357     case RENDER_TSPCLIP:
   358     	MMIO_WRITE( PVR2, reg, val&0x7FFFFFFF );
   359     	break;
   360     case RENDER_FARCLIP:
   361 	MMIO_WRITE( PVR2, reg, val&0xFFFFFFF0 );
   362 	break;
   363     case RENDER_BGPLANE:
   364     	MMIO_WRITE( PVR2, reg, val&0x1FFFFFFF );
   365     	break;
   366     case RENDER_ISPCFG:
   367     	MMIO_WRITE( PVR2, reg, val&0x00FFFFF9 );
   368     	break;
   369     case VRAM_CFG1:
   370 	MMIO_WRITE( PVR2, reg, val&0x000000FF );
   371 	break;
   372     case VRAM_CFG2:
   373 	MMIO_WRITE( PVR2, reg, val&0x003FFFFF );
   374 	break;
   375     case VRAM_CFG3:
   376 	MMIO_WRITE( PVR2, reg, val&0x1FFFFFFF );
   377 	break;
   378     case RENDER_FOGTBLCOL:
   379     case RENDER_FOGVRTCOL:
   380 	MMIO_WRITE( PVR2, reg, val&0x00FFFFFF );
   381 	break;
   382     case RENDER_FOGCOEFF:
   383 	MMIO_WRITE( PVR2, reg, val&0x0000FFFF );
   384 	break;
   385     case RENDER_CLAMPHI:
   386     case RENDER_CLAMPLO:
   387 	MMIO_WRITE( PVR2, reg, val );
   388 	break;
   389     case RENDER_TEXSIZE:
   390 	MMIO_WRITE( PVR2, reg, val&0x00031F1F );
   391 	break;
   392     case RENDER_PALETTE:
   393 	MMIO_WRITE( PVR2, reg, val&0x00000003 );
   394 	break;
   396 	/********** CRTC registers *************/
   397     case DISP_HBORDER:
   398     case DISP_VBORDER:
   399 	MMIO_WRITE( PVR2, reg, val&0x03FF03FF );
   400 	break;
   401     case DISP_TOTAL:
   402 	val = val & 0x03FF03FF;
   403 	MMIO_WRITE( PVR2, reg, val );
   404 	pvr2_update_raster_posn(sh4r.slice_cycle);
   405 	pvr2_state.total_lines = (val >> 16) + 1;
   406 	pvr2_state.line_size = (val & 0x03FF) + 1;
   407 	pvr2_state.line_time_ns = 1000000 * pvr2_state.line_size / pvr2_state.dot_clock;
   408 	pvr2_state.retrace_end_line = 0x2A;
   409 	pvr2_state.retrace_start_line = pvr2_state.total_lines - 6;
   410 	pvr2_schedule_line_event( EVENT_RETRACE, 0 );
   411 	pvr2_schedule_scanline_event( EVENT_SCANLINE1, pvr2_state.irq_vpos1, 0 );
   412 	pvr2_schedule_scanline_event( EVENT_SCANLINE2, pvr2_state.irq_vpos2, 0 );
   413 	break;
   414     case DISP_SYNCCFG:
   415 	MMIO_WRITE( PVR2, reg, val&0x000003FF );
   416 	pvr2_state.interlaced = (val & 0x0010) ? TRUE : FALSE;
   417 	break;
   418     case DISP_SYNCTIME:
   419 	pvr2_state.vsync_lines = (val >> 8) & 0x0F;
   420 	pvr2_state.hsync_width_ns = ((val & 0x7F) + 1) * 2000000 / pvr2_state.dot_clock;
   421 	MMIO_WRITE( PVR2, reg, val&0xFFFFFF7F );
   422 	break;
   423     case DISP_CFG2:
   424 	MMIO_WRITE( PVR2, reg, val&0x003F01FF );
   425 	break;
   426     case DISP_HPOS:
   427 	val = val & 0x03FF;
   428 	pvr2_state.front_porch_ns = (val + 1) * 1000000 / pvr2_state.dot_clock;
   429 	MMIO_WRITE( PVR2, reg, val );
   430 	break;
   431     case DISP_VPOS:
   432 	MMIO_WRITE( PVR2, reg, val&0x03FF03FF );
   433 	break;
   435 	/*********** Tile accelerator registers ***********/
   436     case TA_POLYPOS:
   437     case TA_LISTPOS:
   438 	/* Readonly registers */
   439 	break;
   440     case TA_TILEBASE:
   441     case TA_LISTEND:
   442     case TA_LISTBASE:
   443 	MMIO_WRITE( PVR2, reg, val&0x00FFFFE0 );
   444 	break;
   445     case RENDER_TILEBASE:
   446     case TA_POLYBASE:
   447     case TA_POLYEND:
   448 	MMIO_WRITE( PVR2, reg, val&0x00FFFFFC );
   449 	break;
   450     case TA_TILESIZE:
   451 	MMIO_WRITE( PVR2, reg, val&0x000F003F );
   452 	break;
   453     case TA_TILECFG:
   454 	MMIO_WRITE( PVR2, reg, val&0x00133333 );
   455 	break;
   456     case TA_INIT:
   457 	if( val & 0x80000000 )
   458 	    pvr2_ta_init();
   459 	break;
   460     case TA_REINIT:
   461 	break;
   462 	/**************** Scaler registers? ****************/
   463     case SCALERCFG:
   464 	/* KOS suggests bits as follows:
   465 	 *   0: enable vertical scaling
   466 	 *  10: ???
   467 	 *  16: enable FSAA
   468 	 */
   469 	DEBUG( "Scaler config set to %08X", val );
   470 	MMIO_WRITE( PVR2, reg, val&0x0007FFFF );
   471 	break;
   473     case YUV_ADDR:
   474 	MMIO_WRITE( PVR2, reg, val&0x00FFFFF8 );
   475 	break;
   476     case YUV_CFG:
   477 	DEBUG( "YUV config set to %08X", val );
   478 	MMIO_WRITE( PVR2, reg, val&0x01013F3F );
   479 	break;
   482 	/**************** Unknowns ***************/
   483     case PVRUNK1:
   484     	MMIO_WRITE( PVR2, reg, val&0x000007FF );
   485     	break;
   486     case PVRUNK2:
   487 	MMIO_WRITE( PVR2, reg, val&0x00000007 );
   488 	break;
   489     case PVRUNK3:
   490 	MMIO_WRITE( PVR2, reg, val&0x000FFF3F );
   491 	break;
   492     case PVRUNK5:
   493 	MMIO_WRITE( PVR2, reg, val&0x0000FFFF );
   494 	break;
   495     case PVRUNK6:
   496 	MMIO_WRITE( PVR2, reg, val&0x000000FF );
   497 	break;
   498     case PVRUNK7:
   499 	MMIO_WRITE( PVR2, reg, val&0x00000001 );
   500 	break;
   501     }
   502 }
   504 /**
   505  * Calculate the current read value of the syncstat register, using
   506  * the current SH4 clock time as an offset from the last timeslice.
   507  * The register reads (LSB to MSB) as:
   508  *     0..9  Current scan line
   509  *     10    Odd/even field (1 = odd, 0 = even)
   510  *     11    Display active (including border and overscan)
   511  *     12    Horizontal sync off
   512  *     13    Vertical sync off
   513  * Note this method is probably incorrect for anything other than straight
   514  * interlaced PAL/NTSC, and needs further testing. 
   515  */
   516 uint32_t pvr2_get_sync_status()
   517 {
   518     pvr2_update_raster_posn(sh4r.slice_cycle);
   519     uint32_t result = pvr2_state.line_count;
   521     if( pvr2_state.odd_even_field ) {
   522 	result |= 0x0400;
   523     }
   524     if( (pvr2_state.line_count & 0x01) == pvr2_state.odd_even_field ) {
   525 	if( pvr2_state.line_remainder > pvr2_state.hsync_width_ns ) {
   526 	    result |= 0x1000; /* !HSYNC */
   527 	}
   528 	if( pvr2_state.line_count >= pvr2_state.vsync_lines ) {
   529 	    if( pvr2_state.line_remainder > pvr2_state.front_porch_ns ) {
   530 		result |= 0x2800; /* Display active */
   531 	    } else {
   532 		result |= 0x2000; /* Front porch */
   533 	    }
   534 	}
   535     } else {
   536 	if( pvr2_state.line_count >= pvr2_state.vsync_lines ) {
   537 	    if( pvr2_state.line_remainder < (pvr2_state.line_time_ns - pvr2_state.back_porch_ns)) {
   538 		result |= 0x3800; /* Display active */
   539 	    } else {
   540 		result |= 0x3000;
   541 	    }
   542 	} else {
   543 	    result |= 0x1000; /* Back porch */
   544 	}
   545     }
   546     return result;
   547 }
   549 /**
   550  * Schedule an event for the start of the given line. If the line is actually
   551  * the current line, schedules it for the next field. 
   552  * The raster position should be updated before calling this method.
   553  */
   554 static void pvr2_schedule_line_event( int eventid, int line )
   555 {
   556     uint32_t time;
   557     if( line <= pvr2_state.line_count ) {
   558 	time = (pvr2_state.total_lines - pvr2_state.line_count + line) * pvr2_state.line_time_ns
   559 	    - pvr2_state.line_remainder;
   560     } else {
   561 	time = (line - pvr2_state.line_count) * pvr2_state.line_time_ns - pvr2_state.line_remainder;
   562     }
   564     if( line < pvr2_state.total_lines ) {
   565 	event_schedule( eventid, time );
   566     } else {
   567 	event_cancel( eventid );
   568     }
   569 }
   571 /**
   572  * Schedule a "scanline" event. This actually goes off at
   573  * 2 * line in even fields and 2 * line + 1 in odd fields.
   574  * Otherwise this behaves as per pvr2_schedule_line_event().
   575  * The raster position should be updated before calling this
   576  * method.
   577  */
   578 static void pvr2_schedule_scanline_event( int eventid, int line, int minimum_lines )
   579 {
   580     uint32_t field = pvr2_state.odd_even_field;
   581     if( line <= pvr2_state.line_count && pvr2_state.interlaced ) {
   582 	field = !field;
   583     }
   585     line <<= 1;
   586     if( field ) {
   587 	line += 1;
   588     }
   590     if( line < pvr2_state.total_lines ) {
   591 	uint32_t lines;
   592 	uint32_t time;
   593 	if( line <= pvr2_state.line_count ) {
   594 	    lines = (pvr2_state.total_lines - pvr2_state.line_count + line);
   595 	} else {
   596 	    lines = (line - pvr2_state.line_count);
   597 	}
   598 	if( lines <= minimum_lines ) {
   599 	    lines += pvr2_state.total_lines;
   600 	}
   601 	time = (lines * pvr2_state.line_time_ns) - pvr2_state.line_remainder;
   602 	event_schedule( eventid, time );
   603     } else {
   604 	event_cancel( eventid );
   605     }
   606 }
   608 MMIO_REGION_READ_FN( PVR2, reg )
   609 {
   610     switch( reg ) {
   611         case DISP_SYNCSTAT:
   612             return pvr2_get_sync_status();
   613         default:
   614             return MMIO_READ( PVR2, reg );
   615     }
   616 }
   618 MMIO_REGION_DEFFNS( PVR2PAL )
   620 void pvr2_set_base_address( uint32_t base ) 
   621 {
   622     mmio_region_PVR2_write( DISP_ADDR1, base );
   623 }
   628 int32_t mmio_region_PVR2TA_read( uint32_t reg )
   629 {
   630     return 0xFFFFFFFF;
   631 }
   633 void mmio_region_PVR2TA_write( uint32_t reg, uint32_t val )
   634 {
   635     pvr2_ta_write( (char *)&val, sizeof(uint32_t) );
   636 }
   639 void pvr2_vram64_write( sh4addr_t destaddr, char *src, uint32_t length )
   640 {
   641     int bank_flag = (destaddr & 0x04) >> 2;
   642     uint32_t *banks[2];
   643     uint32_t *dwsrc;
   644     int i;
   646     destaddr = destaddr & 0x7FFFFF;
   647     if( destaddr + length > 0x800000 ) {
   648 	length = 0x800000 - destaddr;
   649     }
   651     for( i=destaddr & 0xFFFFF000; i < destaddr + length; i+= PAGE_SIZE ) {
   652 	texcache_invalidate_page( i );
   653     }
   655     banks[0] = ((uint32_t *)(video_base + ((destaddr & 0x007FFFF8) >>1)));
   656     banks[1] = banks[0] + 0x100000;
   657     if( bank_flag ) 
   658 	banks[0]++;
   660     /* Handle non-aligned start of source */
   661     if( destaddr & 0x03 ) {
   662 	char *dest = ((char *)banks[bank_flag]) + (destaddr & 0x03);
   663 	for( i= destaddr & 0x03; i < 4 && length > 0; i++, length-- ) {
   664 	    *dest++ = *src++;
   665 	}
   666 	bank_flag = !bank_flag;
   667     }
   669     dwsrc = (uint32_t *)src;
   670     while( length >= 4 ) {
   671 	*banks[bank_flag]++ = *dwsrc++;
   672 	bank_flag = !bank_flag;
   673 	length -= 4;
   674     }
   676     /* Handle non-aligned end of source */
   677     if( length ) {
   678 	src = (char *)dwsrc;
   679 	char *dest = (char *)banks[bank_flag];
   680 	while( length-- > 0 ) {
   681 	    *dest++ = *src++;
   682 	}
   683     }  
   684 }
   686 void pvr2_vram_write_invert( sh4addr_t destaddr, char *src, uint32_t length, uint32_t line_length )
   687 {
   688     char *dest = video_base + (destaddr & 0x007FFFFF);
   689     char *p = src + length - line_length;
   690     while( p >= src ) {
   691 	memcpy( dest, p, line_length );
   692 	p -= line_length;
   693 	dest += line_length;
   694     }
   695 }
   697 void pvr2_vram64_read( char *dest, sh4addr_t srcaddr, uint32_t length )
   698 {
   699     int bank_flag = (srcaddr & 0x04) >> 2;
   700     uint32_t *banks[2];
   701     uint32_t *dwdest;
   702     int i;
   704     srcaddr = srcaddr & 0x7FFFFF;
   705     if( srcaddr + length > 0x800000 )
   706 	length = 0x800000 - srcaddr;
   708     banks[0] = ((uint32_t *)(video_base + ((srcaddr&0x007FFFF8)>>1)));
   709     banks[1] = banks[0] + 0x100000;
   710     if( bank_flag )
   711 	banks[0]++;
   713     /* Handle non-aligned start of source */
   714     if( srcaddr & 0x03 ) {
   715 	char *src = ((char *)banks[bank_flag]) + (srcaddr & 0x03);
   716 	for( i= srcaddr & 0x03; i < 4 && length > 0; i++, length-- ) {
   717 	    *dest++ = *src++;
   718 	}
   719 	bank_flag = !bank_flag;
   720     }
   722     dwdest = (uint32_t *)dest;
   723     while( length >= 4 ) {
   724 	*dwdest++ = *banks[bank_flag]++;
   725 	bank_flag = !bank_flag;
   726 	length -= 4;
   727     }
   729     /* Handle non-aligned end of source */
   730     if( length ) {
   731 	dest = (char *)dwdest;
   732 	char *src = (char *)banks[bank_flag];
   733 	while( length-- > 0 ) {
   734 	    *dest++ = *src++;
   735 	}
   736     }
   737 }
   739 void pvr2_vram64_dump( sh4addr_t addr, uint32_t length, FILE *f ) 
   740 {
   741     char tmp[length];
   742     pvr2_vram64_read( tmp, addr, length );
   743     fwrite_dump( tmp, length, f );
   744 }
.