filename | src/pvr2/pvr2.c |
changeset | 85:71e239d20c5d |
prev | 65:9f124c245fc6 |
next | 94:8d80d9c7cc7d |
author | nkeynes |
date | Sun Jan 22 22:38:51 2006 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Fix colour mode definitions Add PVR2 palette region Fix ta end-of-command when it's not in the same buffer |
file | annotate | diff | log | raw |
nkeynes@31 | 1 | /** |
nkeynes@85 | 2 | * $Id: pvr2.c,v 1.13 2006-01-22 22:38:51 nkeynes Exp $ |
nkeynes@31 | 3 | * |
nkeynes@31 | 4 | * PVR2 (Video) MMIO and supporting functions. |
nkeynes@31 | 5 | * |
nkeynes@31 | 6 | * Copyright (c) 2005 Nathan Keynes. |
nkeynes@31 | 7 | * |
nkeynes@31 | 8 | * This program is free software; you can redistribute it and/or modify |
nkeynes@31 | 9 | * it under the terms of the GNU General Public License as published by |
nkeynes@31 | 10 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@31 | 11 | * (at your option) any later version. |
nkeynes@31 | 12 | * |
nkeynes@31 | 13 | * This program is distributed in the hope that it will be useful, |
nkeynes@31 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@31 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@31 | 16 | * GNU General Public License for more details. |
nkeynes@31 | 17 | */ |
nkeynes@35 | 18 | #define MODULE pvr2_module |
nkeynes@31 | 19 | |
nkeynes@1 | 20 | #include "dream.h" |
nkeynes@1 | 21 | #include "video.h" |
nkeynes@1 | 22 | #include "mem.h" |
nkeynes@1 | 23 | #include "asic.h" |
nkeynes@1 | 24 | #include "pvr2.h" |
nkeynes@56 | 25 | #include "sh4/sh4core.h" |
nkeynes@1 | 26 | #define MMIO_IMPL |
nkeynes@1 | 27 | #include "pvr2.h" |
nkeynes@1 | 28 | |
nkeynes@1 | 29 | char *video_base; |
nkeynes@1 | 30 | |
nkeynes@15 | 31 | void pvr2_init( void ); |
nkeynes@30 | 32 | uint32_t pvr2_run_slice( uint32_t ); |
nkeynes@23 | 33 | void pvr2_next_frame( void ); |
nkeynes@15 | 34 | |
nkeynes@23 | 35 | struct dreamcast_module pvr2_module = { "PVR2", pvr2_init, NULL, NULL, |
nkeynes@23 | 36 | pvr2_run_slice, NULL, |
nkeynes@15 | 37 | NULL, NULL }; |
nkeynes@15 | 38 | |
nkeynes@1 | 39 | void pvr2_init( void ) |
nkeynes@1 | 40 | { |
nkeynes@1 | 41 | register_io_region( &mmio_region_PVR2 ); |
nkeynes@85 | 42 | register_io_region( &mmio_region_PVR2PAL ); |
nkeynes@56 | 43 | register_io_region( &mmio_region_PVR2TA ); |
nkeynes@1 | 44 | video_base = mem_get_region_by_name( MEM_REGION_VIDEO ); |
nkeynes@1 | 45 | } |
nkeynes@1 | 46 | |
nkeynes@23 | 47 | uint32_t pvr2_time_counter = 0; |
nkeynes@30 | 48 | uint32_t pvr2_time_per_frame = 20000000; |
nkeynes@23 | 49 | |
nkeynes@30 | 50 | uint32_t pvr2_run_slice( uint32_t nanosecs ) |
nkeynes@23 | 51 | { |
nkeynes@30 | 52 | pvr2_time_counter += nanosecs; |
nkeynes@30 | 53 | while( pvr2_time_counter >= pvr2_time_per_frame ) { |
nkeynes@23 | 54 | pvr2_next_frame(); |
nkeynes@23 | 55 | pvr2_time_counter -= pvr2_time_per_frame; |
nkeynes@23 | 56 | } |
nkeynes@30 | 57 | return nanosecs; |
nkeynes@23 | 58 | } |
nkeynes@23 | 59 | |
nkeynes@1 | 60 | uint32_t vid_stride, vid_lpf, vid_ppl, vid_hres, vid_vres, vid_col; |
nkeynes@1 | 61 | int interlaced, bChanged = 1, bEnabled = 0, vid_size = 0; |
nkeynes@1 | 62 | char *frame_start; /* current video start address (in real memory) */ |
nkeynes@1 | 63 | |
nkeynes@1 | 64 | /* |
nkeynes@1 | 65 | * Display the next frame, copying the current contents of video ram to |
nkeynes@1 | 66 | * the window. If the video configuration has changed, first recompute the |
nkeynes@1 | 67 | * new frame size/depth. |
nkeynes@1 | 68 | */ |
nkeynes@1 | 69 | void pvr2_next_frame( void ) |
nkeynes@1 | 70 | { |
nkeynes@1 | 71 | if( bChanged ) { |
nkeynes@1 | 72 | int dispsize = MMIO_READ( PVR2, DISPSIZE ); |
nkeynes@1 | 73 | int dispmode = MMIO_READ( PVR2, DISPMODE ); |
nkeynes@1 | 74 | int vidcfg = MMIO_READ( PVR2, VIDCFG ); |
nkeynes@1 | 75 | vid_stride = ((dispsize & DISPSIZE_MODULO) >> 20) - 1; |
nkeynes@1 | 76 | vid_lpf = ((dispsize & DISPSIZE_LPF) >> 10) + 1; |
nkeynes@1 | 77 | vid_ppl = ((dispsize & DISPSIZE_PPL)) + 1; |
nkeynes@1 | 78 | vid_col = (dispmode & DISPMODE_COL); |
nkeynes@1 | 79 | frame_start = video_base + MMIO_READ( PVR2, DISPADDR1 ); |
nkeynes@1 | 80 | interlaced = (vidcfg & VIDCFG_I ? 1 : 0); |
nkeynes@1 | 81 | bEnabled = (dispmode & DISPMODE_DE) && (vidcfg & VIDCFG_VO ) ? 1 : 0; |
nkeynes@1 | 82 | vid_size = (vid_ppl * vid_lpf) << (interlaced ? 3 : 2); |
nkeynes@1 | 83 | vid_hres = vid_ppl; |
nkeynes@1 | 84 | vid_vres = vid_lpf; |
nkeynes@1 | 85 | if( interlaced ) vid_vres <<= 1; |
nkeynes@1 | 86 | switch( vid_col ) { |
nkeynes@1 | 87 | case MODE_RGB15: |
nkeynes@1 | 88 | case MODE_RGB16: vid_hres <<= 1; break; |
nkeynes@1 | 89 | case MODE_RGB24: vid_hres *= 3; break; |
nkeynes@1 | 90 | case MODE_RGB32: vid_hres <<= 2; break; |
nkeynes@1 | 91 | } |
nkeynes@1 | 92 | vid_hres >>= 2; |
nkeynes@1 | 93 | video_update_size( vid_hres, vid_vres, vid_col ); |
nkeynes@1 | 94 | bChanged = 0; |
nkeynes@1 | 95 | } |
nkeynes@1 | 96 | if( bEnabled ) { |
nkeynes@65 | 97 | if( MMIO_READ( PVR2, VIDCFG2 ) & 0x08 ) { |
nkeynes@65 | 98 | /* Blanked */ |
nkeynes@65 | 99 | uint32_t colour = MMIO_READ( PVR2, BORDERCOL ); |
nkeynes@65 | 100 | video_fill( colour ); |
nkeynes@65 | 101 | } else { |
nkeynes@65 | 102 | /* Assume bit depths match for now... */ |
nkeynes@65 | 103 | memcpy( video_data, frame_start, vid_size ); |
nkeynes@65 | 104 | } |
nkeynes@1 | 105 | } else { |
nkeynes@1 | 106 | memset( video_data, 0, vid_size ); |
nkeynes@1 | 107 | } |
nkeynes@1 | 108 | video_update_frame(); |
nkeynes@1 | 109 | asic_event( EVENT_SCANLINE1 ); |
nkeynes@1 | 110 | asic_event( EVENT_SCANLINE2 ); |
nkeynes@1 | 111 | asic_event( EVENT_RETRACE ); |
nkeynes@1 | 112 | } |
nkeynes@1 | 113 | |
nkeynes@1 | 114 | void mmio_region_PVR2_write( uint32_t reg, uint32_t val ) |
nkeynes@1 | 115 | { |
nkeynes@1 | 116 | if( reg >= 0x200 && reg < 0x600 ) { /* Fog table */ |
nkeynes@1 | 117 | MMIO_WRITE( PVR2, reg, val ); |
nkeynes@1 | 118 | /* I don't want to hear about these */ |
nkeynes@1 | 119 | return; |
nkeynes@1 | 120 | } |
nkeynes@1 | 121 | |
nkeynes@1 | 122 | INFO( "PVR2 write to %08X <= %08X [%s: %s]", reg, val, |
nkeynes@1 | 123 | MMIO_REGID(PVR2,reg), MMIO_REGDESC(PVR2,reg) ); |
nkeynes@1 | 124 | |
nkeynes@1 | 125 | switch(reg) { |
nkeynes@65 | 126 | case DISPSIZE: bChanged = 1; |
nkeynes@65 | 127 | case DISPMODE: bChanged = 1; |
nkeynes@65 | 128 | case DISPADDR1: bChanged = 1; |
nkeynes@65 | 129 | case DISPADDR2: bChanged = 1; |
nkeynes@65 | 130 | case VIDCFG: bChanged = 1; |
nkeynes@65 | 131 | break; |
nkeynes@65 | 132 | case RENDSTART: |
nkeynes@65 | 133 | if( val == 0xFFFFFFFF ) |
nkeynes@65 | 134 | pvr2_render_scene(); |
nkeynes@65 | 135 | break; |
nkeynes@1 | 136 | } |
nkeynes@1 | 137 | MMIO_WRITE( PVR2, reg, val ); |
nkeynes@1 | 138 | } |
nkeynes@1 | 139 | |
nkeynes@1 | 140 | MMIO_REGION_READ_FN( PVR2, reg ) |
nkeynes@1 | 141 | { |
nkeynes@1 | 142 | switch( reg ) { |
nkeynes@1 | 143 | case BEAMPOS: |
nkeynes@2 | 144 | return sh4r.icount&0x20 ? 0x2000 : 1; |
nkeynes@1 | 145 | default: |
nkeynes@1 | 146 | return MMIO_READ( PVR2, reg ); |
nkeynes@1 | 147 | } |
nkeynes@1 | 148 | } |
nkeynes@19 | 149 | |
nkeynes@85 | 150 | MMIO_REGION_DEFFNS( PVR2PAL ) |
nkeynes@85 | 151 | |
nkeynes@19 | 152 | void pvr2_set_base_address( uint32_t base ) |
nkeynes@19 | 153 | { |
nkeynes@19 | 154 | mmio_region_PVR2_write( DISPADDR1, base ); |
nkeynes@19 | 155 | } |
nkeynes@56 | 156 | |
nkeynes@56 | 157 | |
nkeynes@65 | 158 | void pvr2_render_scene( void ) |
nkeynes@65 | 159 | { |
nkeynes@65 | 160 | /* Actual rendering goes here :) */ |
nkeynes@65 | 161 | asic_event( EVENT_PVR_RENDER_DONE ); |
nkeynes@65 | 162 | DEBUG( "Rendered frame %d", video_frame_count ); |
nkeynes@65 | 163 | } |
nkeynes@65 | 164 | |
nkeynes@65 | 165 | /** Tile Accelerator */ |
nkeynes@65 | 166 | |
nkeynes@65 | 167 | struct tacmd { |
nkeynes@65 | 168 | uint32_t command; |
nkeynes@65 | 169 | uint32_t param1; |
nkeynes@65 | 170 | uint32_t param2; |
nkeynes@65 | 171 | uint32_t texture; |
nkeynes@65 | 172 | float alpha; |
nkeynes@65 | 173 | float red; |
nkeynes@65 | 174 | float green; |
nkeynes@65 | 175 | float blue; |
nkeynes@65 | 176 | }; |
nkeynes@65 | 177 | |
nkeynes@56 | 178 | int32_t mmio_region_PVR2TA_read( uint32_t reg ) |
nkeynes@56 | 179 | { |
nkeynes@56 | 180 | return 0xFFFFFFFF; |
nkeynes@56 | 181 | } |
nkeynes@56 | 182 | |
nkeynes@56 | 183 | char pvr2ta_remainder[8]; |
nkeynes@56 | 184 | |
nkeynes@56 | 185 | void mmio_region_PVR2TA_write( uint32_t reg, uint32_t val ) |
nkeynes@56 | 186 | { |
nkeynes@65 | 187 | DEBUG( "Direct write to TA %08X", val ); |
nkeynes@56 | 188 | } |
nkeynes@56 | 189 | |
nkeynes@85 | 190 | unsigned int pvr2_last_poly_type = 0; |
nkeynes@85 | 191 | |
nkeynes@56 | 192 | void pvr2ta_write( char *buf, uint32_t length ) |
nkeynes@56 | 193 | { |
nkeynes@65 | 194 | int i; |
nkeynes@65 | 195 | struct tacmd *cmd_list = (struct tacmd *)buf; |
nkeynes@65 | 196 | int count = length >> 5; |
nkeynes@65 | 197 | for( i=0; i<count; i++ ){ |
nkeynes@65 | 198 | unsigned int type = (cmd_list[i].command >> 24) & 0xFF; |
nkeynes@65 | 199 | DEBUG( "PVR2 cmd: %08X %08X %08X", cmd_list[i].command, cmd_list[i].param1, cmd_list[i].param2 ); |
nkeynes@65 | 200 | if( type == 0 ) { |
nkeynes@65 | 201 | /* End of list */ |
nkeynes@85 | 202 | switch( pvr2_last_poly_type ) { |
nkeynes@65 | 203 | case 0x80: /* Opaque polys */ |
nkeynes@65 | 204 | asic_event( EVENT_PVR_OPAQUE_DONE ); |
nkeynes@65 | 205 | break; |
nkeynes@65 | 206 | case 0x81: /* Opaque poly modifier */ |
nkeynes@65 | 207 | asic_event( EVENT_PVR_OPAQUEMOD_DONE ); |
nkeynes@65 | 208 | break; |
nkeynes@65 | 209 | case 0x82: /* Transparent polys */ |
nkeynes@65 | 210 | asic_event( EVENT_PVR_TRANS_DONE ); |
nkeynes@65 | 211 | break; |
nkeynes@65 | 212 | case 0x83: /* Transparent poly modifier */ |
nkeynes@65 | 213 | asic_event( EVENT_PVR_TRANSMOD_DONE ); |
nkeynes@65 | 214 | break; |
nkeynes@65 | 215 | case 0x84: /* Punchthrough */ |
nkeynes@65 | 216 | asic_event( EVENT_PVR_PUNCHOUT_DONE ); |
nkeynes@65 | 217 | break; |
nkeynes@65 | 218 | } |
nkeynes@85 | 219 | pvr2_last_poly_type = 0; |
nkeynes@85 | 220 | } else if( type >= 0x80 && type <= 0x84 ) { |
nkeynes@85 | 221 | pvr2_last_poly_type = type; |
nkeynes@65 | 222 | } |
nkeynes@65 | 223 | } |
nkeynes@56 | 224 | } |
nkeynes@65 | 225 |
.