nkeynes@1: #include "dream.h" nkeynes@1: #include "video.h" nkeynes@1: #include "mem.h" nkeynes@1: #include "asic.h" nkeynes@1: #include "pvr2.h" nkeynes@1: #define MMIO_IMPL nkeynes@1: #include "pvr2.h" nkeynes@1: nkeynes@1: char *video_base; nkeynes@1: nkeynes@1: void pvr2_init( void ) nkeynes@1: { nkeynes@1: register_io_region( &mmio_region_PVR2 ); nkeynes@1: video_base = mem_get_region_by_name( MEM_REGION_VIDEO ); nkeynes@1: } nkeynes@1: nkeynes@1: uint32_t vid_stride, vid_lpf, vid_ppl, vid_hres, vid_vres, vid_col; nkeynes@1: int interlaced, bChanged = 1, bEnabled = 0, vid_size = 0; nkeynes@1: char *frame_start; /* current video start address (in real memory) */ nkeynes@1: nkeynes@1: /* nkeynes@1: * Display the next frame, copying the current contents of video ram to nkeynes@1: * the window. If the video configuration has changed, first recompute the nkeynes@1: * new frame size/depth. nkeynes@1: */ nkeynes@1: void pvr2_next_frame( void ) nkeynes@1: { nkeynes@1: if( bChanged ) { nkeynes@1: int dispsize = MMIO_READ( PVR2, DISPSIZE ); nkeynes@1: int dispmode = MMIO_READ( PVR2, DISPMODE ); nkeynes@1: int vidcfg = MMIO_READ( PVR2, VIDCFG ); nkeynes@1: vid_stride = ((dispsize & DISPSIZE_MODULO) >> 20) - 1; nkeynes@1: vid_lpf = ((dispsize & DISPSIZE_LPF) >> 10) + 1; nkeynes@1: vid_ppl = ((dispsize & DISPSIZE_PPL)) + 1; nkeynes@1: vid_col = (dispmode & DISPMODE_COL); nkeynes@1: frame_start = video_base + MMIO_READ( PVR2, DISPADDR1 ); nkeynes@1: interlaced = (vidcfg & VIDCFG_I ? 1 : 0); nkeynes@1: bEnabled = (dispmode & DISPMODE_DE) && (vidcfg & VIDCFG_VO ) ? 1 : 0; nkeynes@1: vid_size = (vid_ppl * vid_lpf) << (interlaced ? 3 : 2); nkeynes@1: vid_hres = vid_ppl; nkeynes@1: vid_vres = vid_lpf; nkeynes@1: if( interlaced ) vid_vres <<= 1; nkeynes@1: switch( vid_col ) { nkeynes@1: case MODE_RGB15: nkeynes@1: case MODE_RGB16: vid_hres <<= 1; break; nkeynes@1: case MODE_RGB24: vid_hres *= 3; break; nkeynes@1: case MODE_RGB32: vid_hres <<= 2; break; nkeynes@1: } nkeynes@1: vid_hres >>= 2; nkeynes@1: video_update_size( vid_hres, vid_vres, vid_col ); nkeynes@1: bChanged = 0; nkeynes@1: } nkeynes@1: if( bEnabled ) { nkeynes@1: /* Assume bit depths match for now... */ nkeynes@1: memcpy( video_data, frame_start, vid_size ); nkeynes@1: } else { nkeynes@1: memset( video_data, 0, vid_size ); nkeynes@1: } nkeynes@1: video_update_frame(); nkeynes@1: asic_event( EVENT_SCANLINE1 ); nkeynes@1: asic_event( EVENT_SCANLINE2 ); nkeynes@1: asic_event( EVENT_RETRACE ); nkeynes@1: } nkeynes@1: nkeynes@1: void mmio_region_PVR2_write( uint32_t reg, uint32_t val ) nkeynes@1: { nkeynes@1: if( reg >= 0x200 && reg < 0x600 ) { /* Fog table */ nkeynes@1: MMIO_WRITE( PVR2, reg, val ); nkeynes@1: /* I don't want to hear about these */ nkeynes@1: return; nkeynes@1: } nkeynes@1: nkeynes@1: INFO( "PVR2 write to %08X <= %08X [%s: %s]", reg, val, nkeynes@1: MMIO_REGID(PVR2,reg), MMIO_REGDESC(PVR2,reg) ); nkeynes@1: nkeynes@1: switch(reg) { nkeynes@1: case DISPSIZE: bChanged = 1; nkeynes@1: case DISPMODE: bChanged = 1; nkeynes@1: case DISPADDR1: bChanged = 1; nkeynes@1: case DISPADDR2: bChanged = 1; nkeynes@1: case VIDCFG: bChanged = 1; nkeynes@1: break; nkeynes@1: nkeynes@1: } nkeynes@1: MMIO_WRITE( PVR2, reg, val ); nkeynes@1: } nkeynes@1: nkeynes@1: MMIO_REGION_READ_FN( PVR2, reg ) nkeynes@1: { nkeynes@1: switch( reg ) { nkeynes@1: case BEAMPOS: nkeynes@2: return sh4r.icount&0x20 ? 0x2000 : 1; nkeynes@1: default: nkeynes@1: return MMIO_READ( PVR2, reg ); nkeynes@1: } nkeynes@1: }