filename | test/pvr.c |
changeset | 561:533f6b478071 |
prev | 320:660b15095115 |
next | 1151:e1848ca9b5b1 |
author | nkeynes |
date | Thu Dec 11 23:26:03 2008 +0000 (15 years ago) |
permissions | -rw-r--r-- |
last change | Disable the generational translation cache - I've got no evidence that it actually helps performance, and it simplifies things to get rid of it (in particular, translated code doesn't have to worry about being moved now). |
file | annotate | diff | log | raw |
nkeynes@185 | 1 | /** |
nkeynes@561 | 2 | * $Id$ |
nkeynes@185 | 3 | * |
nkeynes@185 | 4 | * PVR support code |
nkeynes@185 | 5 | * |
nkeynes@185 | 6 | * Copyright (c) 2006 Nathan Keynes. |
nkeynes@185 | 7 | * |
nkeynes@185 | 8 | * This program is free software; you can redistribute it and/or modify |
nkeynes@185 | 9 | * it under the terms of the GNU General Public License as published by |
nkeynes@185 | 10 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@185 | 11 | * (at your option) any later version. |
nkeynes@185 | 12 | * |
nkeynes@185 | 13 | * This program is distributed in the hope that it will be useful, |
nkeynes@185 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@185 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@185 | 16 | * GNU General Public License for more details. |
nkeynes@185 | 17 | */ |
nkeynes@185 | 18 | |
nkeynes@185 | 19 | #include "lib.h" |
nkeynes@185 | 20 | #include "pvr.h" |
nkeynes@185 | 21 | |
nkeynes@185 | 22 | #define PVR_BASE 0xA05F8000 |
nkeynes@185 | 23 | #define PVR_RESET (PVR_BASE+0x008) |
nkeynes@185 | 24 | #define TA_INIT (PVR_BASE+0x144) |
nkeynes@185 | 25 | #define TA_TILESTART (PVR_BASE+0x124) |
nkeynes@185 | 26 | #define TA_OBJSTART (PVR_BASE+0x128) |
nkeynes@185 | 27 | #define TA_TILEEND (PVR_BASE+0x12C) |
nkeynes@185 | 28 | #define TA_OBJEND (PVR_BASE+0x130) |
nkeynes@185 | 29 | #define TA_TILEPOSN (PVR_BASE+0x134) |
nkeynes@185 | 30 | #define TA_OBJPOSN (PVR_BASE+0x138) |
nkeynes@185 | 31 | #define TA_SIZE (PVR_BASE+0x13C) |
nkeynes@185 | 32 | #define TA_TILECFG (PVR_BASE+0x140) |
nkeynes@213 | 33 | #define TA_REINIT (PVR_BASE+0x160) |
nkeynes@185 | 34 | #define TA_PLISTSTART (PVR_BASE+0x164) |
nkeynes@185 | 35 | |
nkeynes@213 | 36 | #define RENDER_START (PVR_BASE+0x014) |
nkeynes@213 | 37 | #define RENDER_POLYBASE (PVR_BASE+0x020) |
nkeynes@213 | 38 | #define RENDER_TILEBASE (PVR_BASE+0x02C) |
nkeynes@213 | 39 | #define RENDER_MODE (PVR_BASE+0x048) |
nkeynes@213 | 40 | #define RENDER_SIZE (PVR_BASE+0x04C) |
nkeynes@213 | 41 | #define RENDER_ADDR1 (PVR_BASE+0x060) |
nkeynes@213 | 42 | #define RENDER_ADDR2 (PVR_BASE+0x064) |
nkeynes@213 | 43 | #define RENDER_HCLIP (PVR_BASE+0x068) |
nkeynes@213 | 44 | #define RENDER_VCLIP (PVR_BASE+0x06C) |
nkeynes@213 | 45 | #define RENDER_NEARCLIP (PVR_BASE+0x078) |
nkeynes@213 | 46 | #define RENDER_FARCLIP (PVR_BASE+0x088) |
nkeynes@213 | 47 | #define RENDER_BGPLANE (PVR_BASE+0x08C) |
nkeynes@213 | 48 | |
nkeynes@213 | 49 | #define DISPLAY_MODE (PVR_BASE+0x044) |
nkeynes@213 | 50 | #define DISPLAY_ADDR1 (PVR_BASE+0x050) |
nkeynes@213 | 51 | #define DISPLAY_ADDR2 (PVR_BASE+0x054) |
nkeynes@213 | 52 | #define DISPLAY_SIZE (PVR_BASE+0x05C |
nkeynes@185 | 53 | |
nkeynes@185 | 54 | void ta_dump_regs( FILE *f ) |
nkeynes@185 | 55 | { |
nkeynes@185 | 56 | fprintf( stderr, "TA Object start[128]: %08X posn[138]: %08X end[130]: %08X\n", |
nkeynes@185 | 57 | long_read(TA_OBJSTART), long_read(TA_OBJPOSN), long_read(TA_OBJEND) ); |
nkeynes@185 | 58 | fprintf( stderr, "TA OPB start[124]: %08X posn[134]: %08X end[12c]: %08X init: %08X\n", |
nkeynes@185 | 59 | long_read(TA_TILESTART), long_read(TA_TILEPOSN), long_read(TA_TILEEND), |
nkeynes@185 | 60 | long_read(TA_PLISTSTART) ); |
nkeynes@185 | 61 | fprintf( stderr, "TA Tilesize: %08X config: %08X\n", long_read(TA_SIZE), long_read(TA_TILECFG) ); |
nkeynes@185 | 62 | } |
nkeynes@185 | 63 | |
nkeynes@190 | 64 | |
nkeynes@190 | 65 | void ta_init( struct ta_config *config ) |
nkeynes@190 | 66 | { |
nkeynes@190 | 67 | long_write( PVR_RESET, 1 ); |
nkeynes@190 | 68 | long_write( PVR_RESET, 0 ); |
nkeynes@190 | 69 | |
nkeynes@190 | 70 | long_write( TA_SIZE, config->grid_size ); |
nkeynes@190 | 71 | long_write( TA_OBJSTART, config->obj_start & 0x00FFFFFF ); |
nkeynes@190 | 72 | long_write( TA_OBJEND, config->obj_end & 0x00FFFFFF ); |
nkeynes@190 | 73 | long_write( TA_TILESTART, config->tile_start & 0x00FFFFFF ); |
nkeynes@190 | 74 | long_write( TA_TILEEND, config->tile_end & 0x00FFFFFF ); |
nkeynes@190 | 75 | long_write( TA_PLISTSTART, config->plist_start & 0x00FFFFFF ); |
nkeynes@190 | 76 | long_write( TA_TILECFG, config->ta_cfg ); |
nkeynes@190 | 77 | long_write( TA_INIT, 0x80000000 ); |
nkeynes@190 | 78 | } |
nkeynes@190 | 79 | |
nkeynes@213 | 80 | void ta_reinit( ) |
nkeynes@213 | 81 | { |
nkeynes@213 | 82 | long_write( TA_REINIT, 0x80000000 ); |
nkeynes@213 | 83 | } |
nkeynes@213 | 84 | |
nkeynes@185 | 85 | int pvr_get_objbuf_size( ) |
nkeynes@185 | 86 | { |
nkeynes@185 | 87 | return long_read( TA_OBJPOSN ) - long_read( TA_OBJSTART ); |
nkeynes@185 | 88 | } |
nkeynes@185 | 89 | |
nkeynes@213 | 90 | int pvr_get_objbuf_posn( ) |
nkeynes@213 | 91 | { |
nkeynes@213 | 92 | return long_read( TA_OBJPOSN ); |
nkeynes@213 | 93 | } |
nkeynes@213 | 94 | |
nkeynes@190 | 95 | int pvr_get_plist_posn( ) |
nkeynes@190 | 96 | { |
nkeynes@190 | 97 | unsigned int addr = long_read( TA_TILEPOSN ) << 2; |
nkeynes@190 | 98 | return addr; |
nkeynes@190 | 99 | } |
nkeynes@190 | 100 | |
nkeynes@185 | 101 | void pvr_dump_objbuf( FILE *f ) |
nkeynes@185 | 102 | { |
nkeynes@185 | 103 | unsigned int start = long_read( TA_OBJSTART ); |
nkeynes@185 | 104 | unsigned int posn = long_read( TA_OBJPOSN ); |
nkeynes@185 | 105 | unsigned int end = long_read( TA_OBJEND ); |
nkeynes@185 | 106 | char *buf; |
nkeynes@185 | 107 | unsigned int length; |
nkeynes@185 | 108 | if( start < posn ) { |
nkeynes@185 | 109 | buf = (char *)(0xA5000000+start); |
nkeynes@185 | 110 | length = posn-start; |
nkeynes@185 | 111 | } else { |
nkeynes@185 | 112 | buf = (char *)(0xA5000000+end); |
nkeynes@185 | 113 | length = start-posn; |
nkeynes@185 | 114 | } |
nkeynes@185 | 115 | |
nkeynes@185 | 116 | fprintf( f, "Obj buffer: %08X - %08X - %08X\n", start, posn, end ); |
nkeynes@185 | 117 | fwrite_dump( f, buf, length ); |
nkeynes@185 | 118 | } |
nkeynes@185 | 119 | |
nkeynes@185 | 120 | void pvr_dump_tilebuf( FILE *f ) |
nkeynes@185 | 121 | { |
nkeynes@185 | 122 | unsigned int start = long_read( TA_TILESTART ); |
nkeynes@185 | 123 | unsigned int posn = long_read( TA_TILEPOSN ); |
nkeynes@185 | 124 | unsigned int end = long_read( TA_TILEEND ); |
nkeynes@185 | 125 | char *buf; |
nkeynes@185 | 126 | unsigned int length; |
nkeynes@185 | 127 | if( start < posn ) { |
nkeynes@185 | 128 | buf = (char *)(0xA5000000+start); |
nkeynes@185 | 129 | length = posn-start; |
nkeynes@185 | 130 | } else { |
nkeynes@185 | 131 | buf = (char *)(0xA5000000+end); |
nkeynes@185 | 132 | length = start-posn; |
nkeynes@185 | 133 | } |
nkeynes@185 | 134 | |
nkeynes@185 | 135 | fprintf( f, "Tile buffer: %08X - %08X - %08X\n", start, posn, end ); |
nkeynes@185 | 136 | fwrite_dump( f, buf, length ); |
nkeynes@185 | 137 | } |
nkeynes@185 | 138 | |
nkeynes@213 | 139 | static int ta_tile_sizes[4] = { 0, 32, 64, 128 }; |
nkeynes@213 | 140 | #define TILE_SIZE(cfg, tile) ta_tile_sizes[((((cfg->ta_cfg) >> (4*tile))&0x03))] |
nkeynes@213 | 141 | #define TILE_ENABLED(cfg, tile) ((((cfg->ta_cfg) >> (4*tile))&0x03) != 0) |
nkeynes@213 | 142 | void pvr_compute_tilematrix_addr( int *tile_ptrs, struct ta_config *config ) { |
nkeynes@213 | 143 | int tile_sizes[5], i; |
nkeynes@213 | 144 | int hsegs = (config->grid_size & 0xFFFF)+1; |
nkeynes@213 | 145 | int vsegs = (config->grid_size >> 16) + 1; |
nkeynes@213 | 146 | for( i=0; i<5; i++ ) { |
nkeynes@213 | 147 | tile_sizes[i] = TILE_SIZE(config,i); |
nkeynes@213 | 148 | } |
nkeynes@213 | 149 | tile_ptrs[0] = config->tile_start; |
nkeynes@213 | 150 | tile_ptrs[1] = tile_ptrs[0] + (hsegs*vsegs*tile_sizes[0]); |
nkeynes@213 | 151 | tile_ptrs[2] = tile_ptrs[1] + (hsegs*vsegs*tile_sizes[1]); |
nkeynes@213 | 152 | tile_ptrs[3] = tile_ptrs[2] + (hsegs*vsegs*tile_sizes[2]); |
nkeynes@213 | 153 | tile_ptrs[4] = tile_ptrs[3] + (hsegs*vsegs*tile_sizes[3]); |
nkeynes@213 | 154 | } |
nkeynes@213 | 155 | |
nkeynes@213 | 156 | static uint32_t *pvr_compute_tile_ptrs( uint32_t *target, struct ta_config *config, int x, int y ) |
nkeynes@213 | 157 | { |
nkeynes@213 | 158 | int i; |
nkeynes@213 | 159 | int cfg = config->ta_cfg; |
nkeynes@213 | 160 | int hsegs = (config->grid_size & 0xFFFF)+1; |
nkeynes@213 | 161 | int vsegs = (config->grid_size >> 16) + 1; |
nkeynes@213 | 162 | int tilematrix = config->tile_start; |
nkeynes@213 | 163 | for( i=0; i<5; i++ ) { |
nkeynes@213 | 164 | if( cfg & 0x03 ) { |
nkeynes@213 | 165 | int tile_size = ta_tile_sizes[cfg&0x03]; |
nkeynes@213 | 166 | *target++ = tilematrix + (((y*hsegs)+x)*tile_size); |
nkeynes@213 | 167 | tilematrix += hsegs*vsegs*tile_size; |
nkeynes@213 | 168 | } else { |
nkeynes@213 | 169 | *target++ = 0x80000000; |
nkeynes@213 | 170 | } |
nkeynes@213 | 171 | cfg = cfg >> 4; |
nkeynes@213 | 172 | } |
nkeynes@213 | 173 | return target; |
nkeynes@213 | 174 | } |
nkeynes@213 | 175 | |
nkeynes@213 | 176 | void pvr_build_tilemap1( uint32_t addr, struct ta_config *config, uint32_t control_word ) |
nkeynes@213 | 177 | { |
nkeynes@213 | 178 | uint32_t *dest = (uint32_t *)(PVR_VRAM_BASE+addr); |
nkeynes@213 | 179 | int w = (config->grid_size & 0x0000FFFF) + 1; |
nkeynes@213 | 180 | int h = (config->grid_size >> 16) + 1; |
nkeynes@213 | 181 | |
nkeynes@213 | 182 | int x,y; |
nkeynes@213 | 183 | memset( (char *)(dest-18), 0, 18*4 ); |
nkeynes@213 | 184 | *dest++ = 0x10000000; |
nkeynes@213 | 185 | *dest++ = 0x80000000; |
nkeynes@213 | 186 | *dest++ = 0x80000000; |
nkeynes@213 | 187 | *dest++ = 0x80000000; |
nkeynes@213 | 188 | *dest++ = 0x80000000; |
nkeynes@213 | 189 | *dest++ = 0x80000000; |
nkeynes@213 | 190 | for( x=0; x<w; x++ ) { |
nkeynes@213 | 191 | for( y=0; y<h; y++ ) { |
nkeynes@213 | 192 | *dest++ = control_word | (y << 8) | (x << 2); |
nkeynes@213 | 193 | dest = pvr_compute_tile_ptrs(dest, config, x, y); |
nkeynes@213 | 194 | } |
nkeynes@213 | 195 | } |
nkeynes@213 | 196 | dest[-6] |= 0x80000000; /* End-of-render */ |
nkeynes@213 | 197 | } |
nkeynes@213 | 198 | |
nkeynes@213 | 199 | void pvr_build_tilemap2( uint32_t addr, struct ta_config *config, uint32_t control_word ) |
nkeynes@213 | 200 | { |
nkeynes@213 | 201 | uint32_t *dest = (uint32_t *)(PVR_VRAM_BASE+addr); |
nkeynes@213 | 202 | int w = (config->grid_size & 0x0000FFFF) + 1; |
nkeynes@213 | 203 | int h = (config->grid_size >> 16) + 1; |
nkeynes@213 | 204 | |
nkeynes@213 | 205 | int x,y; |
nkeynes@213 | 206 | *dest++ = 0x10000000; |
nkeynes@213 | 207 | *dest++ = 0x80000000; |
nkeynes@213 | 208 | *dest++ = 0x80000000; |
nkeynes@213 | 209 | *dest++ = 0x80000000; |
nkeynes@213 | 210 | *dest++ = 0x80000000; |
nkeynes@213 | 211 | *dest++ = 0x80000000; |
nkeynes@213 | 212 | for( x=0; x<w; x++ ) { |
nkeynes@213 | 213 | for( y=0; y<h; y++ ) { |
nkeynes@213 | 214 | *dest++ = 0x40000000; |
nkeynes@213 | 215 | *dest++ = 0x80000000; |
nkeynes@213 | 216 | *dest++ = 0x80000000; |
nkeynes@213 | 217 | *dest++ = 0x80000000; |
nkeynes@213 | 218 | *dest++ = 0x80000000; |
nkeynes@213 | 219 | *dest++ = 0x80000000; |
nkeynes@213 | 220 | *dest++ = control_word | (y << 8) | (x << 2); |
nkeynes@213 | 221 | dest = pvr_compute_tile_ptrs(dest, config, x, y); |
nkeynes@213 | 222 | } |
nkeynes@213 | 223 | } |
nkeynes@213 | 224 | dest[-6] |= 0x80000000; /* End-of-render */ |
nkeynes@213 | 225 | } |
nkeynes@213 | 226 | |
nkeynes@213 | 227 | void render_set_backplane( uint32_t mode ) |
nkeynes@213 | 228 | { |
nkeynes@213 | 229 | long_write( RENDER_BGPLANE, mode ); |
nkeynes@213 | 230 | } |
nkeynes@213 | 231 | |
nkeynes@213 | 232 | int get_line_size( struct render_config *config ) |
nkeynes@213 | 233 | { |
nkeynes@213 | 234 | int modulo = config->width; |
nkeynes@213 | 235 | switch( config->mode & 0x07 ) { |
nkeynes@213 | 236 | case 4: |
nkeynes@213 | 237 | modulo *= 3; /* ??? */ |
nkeynes@213 | 238 | break; |
nkeynes@213 | 239 | case 5: |
nkeynes@213 | 240 | case 6: |
nkeynes@213 | 241 | modulo *= 4; |
nkeynes@213 | 242 | break; |
nkeynes@213 | 243 | default: |
nkeynes@213 | 244 | modulo *= 2; |
nkeynes@213 | 245 | } |
nkeynes@213 | 246 | return modulo; |
nkeynes@213 | 247 | } |
nkeynes@213 | 248 | |
nkeynes@213 | 249 | void render_start( struct render_config *config ) |
nkeynes@213 | 250 | { |
nkeynes@213 | 251 | int modulo = get_line_size( config ); |
nkeynes@213 | 252 | long_write( RENDER_POLYBASE, config->polybuf ); |
nkeynes@213 | 253 | long_write( RENDER_TILEBASE, config->tilemap ); |
nkeynes@213 | 254 | long_write( RENDER_ADDR1, config->render_addr ); |
nkeynes@213 | 255 | long_write( RENDER_SIZE, modulo >> 3 ); |
nkeynes@213 | 256 | long_write( RENDER_ADDR2, config->render_addr + modulo ); /* Not used? */ |
nkeynes@213 | 257 | long_write( RENDER_HCLIP, (config->width - 1) << 16 ); |
nkeynes@213 | 258 | long_write( RENDER_VCLIP, (config->height - 1) << 16 ); |
nkeynes@213 | 259 | long_write( RENDER_MODE, config->mode ); |
nkeynes@213 | 260 | float_write( RENDER_FARCLIP, config->farclip ); |
nkeynes@213 | 261 | float_write( RENDER_NEARCLIP, config->nearclip ); |
nkeynes@213 | 262 | long_write( RENDER_START, 0xFFFFFFFF ); |
nkeynes@213 | 263 | } |
nkeynes@213 | 264 | |
nkeynes@213 | 265 | void display_render( struct render_config *config ) |
nkeynes@213 | 266 | { |
nkeynes@213 | 267 | long_write( DISPLAY_ADDR1, config->render_addr ); |
nkeynes@213 | 268 | long_write( DISPLAY_ADDR2, config->render_addr + get_line_size(config) ); |
nkeynes@213 | 269 | } |
nkeynes@213 | 270 | |
nkeynes@185 | 271 | /************** Stolen from TATEST *************/ |
nkeynes@185 | 272 | |
nkeynes@185 | 273 | static unsigned int three_d_params[] = { |
nkeynes@185 | 274 | 0x80a8, 0x15d1c951, /* M (Unknown magic value) */ |
nkeynes@185 | 275 | 0x80a0, 0x00000020, /* M */ |
nkeynes@185 | 276 | 0x8008, 0x00000000, /* TA out of reset */ |
nkeynes@185 | 277 | 0x8048, 0x00000009, /* alpha config */ |
nkeynes@185 | 278 | 0x8068, 0x02800000, /* pixel clipping x */ |
nkeynes@185 | 279 | 0x806c, 0x01e00000, /* pixel clipping y */ |
nkeynes@185 | 280 | 0x8110, 0x00093f39, /* M */ |
nkeynes@185 | 281 | 0x8098, 0x00800408, /* M */ |
nkeynes@185 | 282 | 0x804c, 0x000000a0, /* display align (640*2)/8 */ |
nkeynes@185 | 283 | 0x8078, 0x3f800000, /* polygon culling (1.0f) */ |
nkeynes@185 | 284 | 0x8084, 0x00000000, /* M */ |
nkeynes@185 | 285 | 0x8030, 0x00000101, /* M */ |
nkeynes@185 | 286 | 0x80b0, 0x007f7f7f, /* Fog table color */ |
nkeynes@185 | 287 | 0x80b4, 0x007f7f7f, /* Fog vertex color */ |
nkeynes@185 | 288 | 0x80c0, 0x00000000, /* color clamp min */ |
nkeynes@185 | 289 | 0x80bc, 0xffffffff, /* color clamp max */ |
nkeynes@185 | 290 | 0x8080, 0x00000007, /* M */ |
nkeynes@185 | 291 | 0x8074, 0x00000001, /* cheap shadow */ |
nkeynes@185 | 292 | 0x807c, 0x0027df77, /* M */ |
nkeynes@185 | 293 | 0x8008, 0x00000001, /* TA reset */ |
nkeynes@185 | 294 | 0x8008, 0x00000000, /* TA out of reset */ |
nkeynes@185 | 295 | 0x80e4, 0x00000000, /* stride width */ |
nkeynes@185 | 296 | 0x6884, 0x00000000, /* Disable all interrupt events */ |
nkeynes@185 | 297 | 0x6930, 0x00000000, |
nkeynes@185 | 298 | 0x6938, 0x00000000, |
nkeynes@185 | 299 | 0x6900, 0xffffffff, /* Clear all pending int events */ |
nkeynes@185 | 300 | 0x6908, 0xffffffff, |
nkeynes@185 | 301 | 0x6930, 0x002807ec, /* Re-enable some events */ |
nkeynes@185 | 302 | 0x6938, 0x0000000e, |
nkeynes@185 | 303 | 0x80b8, 0x0000ff07, /* fog density */ |
nkeynes@185 | 304 | 0x80b4, 0x007f7f7f, /* fog vertex color */ |
nkeynes@185 | 305 | 0x80b0, 0x007f7f7f, /* fog table color */ |
nkeynes@185 | 306 | 0x8108, 0x00000003 /* 32bit palette */ |
nkeynes@185 | 307 | }; |
nkeynes@185 | 308 | |
nkeynes@185 | 309 | static unsigned int scrn_params[] = { |
nkeynes@185 | 310 | 0x80e8, 0x00160000, /* screen control */ |
nkeynes@185 | 311 | 0x8044, 0x00800000, /* pixel mode (vb+0x11) */ |
nkeynes@185 | 312 | 0x805c, 0x00000000, /* Size modulo and display lines (vb+0x17) */ |
nkeynes@185 | 313 | 0x80d0, 0x00000100, /* interlace flags */ |
nkeynes@185 | 314 | 0x80d8, 0x020c0359, /* M */ |
nkeynes@185 | 315 | 0x80cc, 0x001501fe, /* M */ |
nkeynes@185 | 316 | 0x80d4, 0x007e0345, /* horizontal border */ |
nkeynes@185 | 317 | 0x80dc, 0x00240204, /* vertical position */ |
nkeynes@185 | 318 | 0x80e0, 0x07d6c63f, /* sync control */ |
nkeynes@185 | 319 | 0x80ec, 0x000000a4, /* horizontal position */ |
nkeynes@185 | 320 | 0x80f0, 0x00120012, /* vertical border */ |
nkeynes@185 | 321 | 0x80c8, 0x03450000, /* set to same as border H in 80d4 */ |
nkeynes@185 | 322 | 0x8068, 0x027f0000, /* (X resolution - 1) << 16 */ |
nkeynes@185 | 323 | 0x806c, 0x01df0000, /* (Y resolution - 1) << 16 */ |
nkeynes@185 | 324 | 0x804c, 0x000000a0, /* display align */ |
nkeynes@185 | 325 | 0x8118, 0x00008040, /* M */ |
nkeynes@185 | 326 | 0x80f4, 0x00000401, /* anti-aliasing */ |
nkeynes@185 | 327 | 0x8048, 0x00000009, /* alpha config */ |
nkeynes@185 | 328 | 0x7814, 0x00000000, /* More interrupt control stuff (so it seems)*/ |
nkeynes@185 | 329 | 0x7834, 0x00000000, |
nkeynes@185 | 330 | 0x7854, 0x00000000, |
nkeynes@185 | 331 | 0x7874, 0x00000000, |
nkeynes@185 | 332 | 0x78bc, 0x4659404f, |
nkeynes@185 | 333 | 0x8040, 0x00000000 /* border color */ |
nkeynes@185 | 334 | }; |
nkeynes@185 | 335 | |
nkeynes@185 | 336 | static void set_regs(unsigned int *values, int cnt) |
nkeynes@185 | 337 | { |
nkeynes@185 | 338 | volatile unsigned char *regs = (volatile unsigned char *)(void *)0xa05f0000; |
nkeynes@185 | 339 | unsigned int r, v; |
nkeynes@185 | 340 | |
nkeynes@185 | 341 | while(cnt--) { |
nkeynes@185 | 342 | r = *values++; |
nkeynes@185 | 343 | v = *values++; |
nkeynes@185 | 344 | *(volatile unsigned int *)(regs+r) = v; |
nkeynes@185 | 345 | } |
nkeynes@185 | 346 | } |
nkeynes@185 | 347 | |
nkeynes@185 | 348 | int pvr_check_cable() |
nkeynes@185 | 349 | { |
nkeynes@185 | 350 | volatile unsigned int *porta = (unsigned int *)0xff80002c; |
nkeynes@185 | 351 | |
nkeynes@185 | 352 | /* PORT8 and PORT9 is input */ |
nkeynes@185 | 353 | *porta = (*porta & ~0xf0000) | 0xa0000; |
nkeynes@185 | 354 | |
nkeynes@185 | 355 | /* Return PORT8 and PORT9 */ |
nkeynes@185 | 356 | return ((*(volatile unsigned short *)(porta+1))>>8)&3; |
nkeynes@185 | 357 | } |
nkeynes@185 | 358 | void pvr_init_video(int cabletype, int mode, int res) |
nkeynes@185 | 359 | { |
nkeynes@185 | 360 | volatile unsigned int *videobase=(volatile unsigned int *)(void*)0xa05f8000; |
nkeynes@185 | 361 | static int bppshifttab[]= { 1,1,0,2 }; |
nkeynes@185 | 362 | int shift, lines, modulo, words_per_line, vpos; |
nkeynes@185 | 363 | int laceoffset=0, voffset=0; |
nkeynes@185 | 364 | unsigned int videoflags, attribs; |
nkeynes@185 | 365 | unsigned int hvcounter = (res<2? 0x01060359 : 0x020c0359); |
nkeynes@185 | 366 | |
nkeynes@185 | 367 | mode &= 3; |
nkeynes@185 | 368 | shift = bppshifttab[mode]; |
nkeynes@185 | 369 | |
nkeynes@185 | 370 | videobase[8/4]=0; |
nkeynes@185 | 371 | videobase[0x40/4]=0; |
nkeynes@185 | 372 | |
nkeynes@185 | 373 | /* Select pixel clock and colour mode */ |
nkeynes@185 | 374 | mode = (mode<<2)|1; |
nkeynes@185 | 375 | lines = 240; |
nkeynes@185 | 376 | if(!(cabletype&2)) { |
nkeynes@185 | 377 | |
nkeynes@185 | 378 | /* VGA mode */ |
nkeynes@185 | 379 | |
nkeynes@185 | 380 | if(res < 2) |
nkeynes@185 | 381 | mode |= 2; /* doublescan */ |
nkeynes@185 | 382 | |
nkeynes@185 | 383 | hvcounter = 0x020c0359; |
nkeynes@185 | 384 | |
nkeynes@185 | 385 | lines <<= 1; |
nkeynes@185 | 386 | mode |= 0x800000; /* fast pixel clock */ |
nkeynes@185 | 387 | } |
nkeynes@185 | 388 | videobase[0x44/4]=mode; |
nkeynes@185 | 389 | |
nkeynes@185 | 390 | /* Set video base address. Short fields will be offset by |
nkeynes@185 | 391 | 640 pixels, regardless of horizontal resolution. */ |
nkeynes@185 | 392 | videobase[0x50/4]=0; |
nkeynes@185 | 393 | videobase[0x54/4]=640<<shift; |
nkeynes@185 | 394 | |
nkeynes@185 | 395 | /* Set screen size, modulo, and interlace flag */ |
nkeynes@185 | 396 | videoflags = 1<<8; |
nkeynes@185 | 397 | if(res==0) |
nkeynes@185 | 398 | words_per_line=(320/4)<<shift; |
nkeynes@185 | 399 | else |
nkeynes@185 | 400 | words_per_line=(640/4)<<shift; |
nkeynes@185 | 401 | modulo = 1; |
nkeynes@185 | 402 | |
nkeynes@185 | 403 | if(!(cabletype&2)) |
nkeynes@185 | 404 | { |
nkeynes@185 | 405 | if(res==0) |
nkeynes@185 | 406 | /* VGA lores -> skip 320 pixels to keep modulo at 640 pixels */ |
nkeynes@185 | 407 | modulo += words_per_line; |
nkeynes@185 | 408 | } else { |
nkeynes@185 | 409 | if(res!=1) |
nkeynes@185 | 410 | /* NTSC lores -> skip 320 pixels to keep modulo at 640 pixels */ |
nkeynes@185 | 411 | /* _or_ NTSC hires -> skip every other line due to interlace */ |
nkeynes@185 | 412 | modulo += words_per_line; |
nkeynes@185 | 413 | |
nkeynes@185 | 414 | if(res==2) |
nkeynes@185 | 415 | /* interlace mode */ |
nkeynes@185 | 416 | videoflags |= 1<<4; |
nkeynes@185 | 417 | |
nkeynes@185 | 418 | /* enable NTSC */ |
nkeynes@185 | 419 | videoflags |= 1<<6; |
nkeynes@185 | 420 | } |
nkeynes@185 | 421 | |
nkeynes@185 | 422 | /* Write screen size and modulo */ |
nkeynes@185 | 423 | videobase[0x5c/4]=(((modulo<<10)+lines-1)<<10)+words_per_line-1; |
nkeynes@185 | 424 | |
nkeynes@185 | 425 | /* Enable video (lace, NTSC) */ |
nkeynes@185 | 426 | videobase[0xd0/4]=videoflags; |
nkeynes@185 | 427 | |
nkeynes@185 | 428 | /* Screen and border position */ |
nkeynes@185 | 429 | |
nkeynes@185 | 430 | if(!(cabletype&2)) |
nkeynes@185 | 431 | /* VGA */ |
nkeynes@185 | 432 | voffset += 36; |
nkeynes@185 | 433 | else |
nkeynes@185 | 434 | voffset += 18; |
nkeynes@185 | 435 | |
nkeynes@185 | 436 | vpos=(voffset<<16)|(voffset+laceoffset); |
nkeynes@185 | 437 | |
nkeynes@185 | 438 | videobase[0xf0/4]=vpos; /* V start */ |
nkeynes@185 | 439 | videobase[0xdc/4]=vpos+lines; /* start and end border */ |
nkeynes@185 | 440 | videobase[0xec/4]=0xa4; /* Horizontal pos */ |
nkeynes@185 | 441 | videobase[0xd8/4]=hvcounter; /* HV counter */ |
nkeynes@185 | 442 | videobase[0xd4/4]=0x007e0345; /* Horizontal border */ |
nkeynes@185 | 443 | |
nkeynes@185 | 444 | /* Select horizontal pixel doubling for lowres */ |
nkeynes@185 | 445 | if(res==0) |
nkeynes@185 | 446 | attribs=((22<<8)+1)<<8; |
nkeynes@185 | 447 | else |
nkeynes@185 | 448 | attribs=22<<16; |
nkeynes@185 | 449 | videobase[0xe8/4]=attribs; |
nkeynes@185 | 450 | |
nkeynes@185 | 451 | /* Set up vertical blank event */ |
nkeynes@185 | 452 | vpos = 260; |
nkeynes@185 | 453 | if(!(cabletype&2)) |
nkeynes@185 | 454 | vpos = 510; |
nkeynes@185 | 455 | videobase[0xcc/4]=(0x21<<16)|vpos; |
nkeynes@185 | 456 | |
nkeynes@185 | 457 | /* Select RGB/CVBS */ |
nkeynes@185 | 458 | if(cabletype&1) |
nkeynes@185 | 459 | mode = 3; |
nkeynes@185 | 460 | else |
nkeynes@185 | 461 | mode = 0; |
nkeynes@185 | 462 | *(volatile unsigned int *)(void*)0xa0702c00 = mode << 8; |
nkeynes@185 | 463 | |
nkeynes@185 | 464 | return; |
nkeynes@185 | 465 | } |
nkeynes@185 | 466 | |
nkeynes@185 | 467 | void pvr_init() |
nkeynes@185 | 468 | { |
nkeynes@185 | 469 | volatile unsigned int *vbl = (volatile unsigned int *)(void *)0xa05f810c; |
nkeynes@185 | 470 | |
nkeynes@185 | 471 | set_regs(three_d_params, sizeof(three_d_params)/sizeof(three_d_params[0])/2); |
nkeynes@185 | 472 | while (!(*vbl & 0x01ff)); |
nkeynes@185 | 473 | while (*vbl & 0x01ff); |
nkeynes@185 | 474 | set_regs(scrn_params, sizeof(scrn_params)/sizeof(scrn_params[0])/2); |
nkeynes@185 | 475 | pvr_init_video(pvr_check_cable(), 1, 2); |
nkeynes@185 | 476 | } |
nkeynes@185 | 477 | |
nkeynes@306 | 478 | void draw_grid( unsigned short *addr, unsigned short colour ) |
nkeynes@306 | 479 | { |
nkeynes@306 | 480 | int x,y; |
nkeynes@306 | 481 | unsigned int linesize = 640; |
nkeynes@306 | 482 | for( x=0; x<640; x+=32 ) { |
nkeynes@306 | 483 | for( y=0; y<480; y++ ) { |
nkeynes@306 | 484 | addr[(linesize*y) + x] = colour; |
nkeynes@306 | 485 | } |
nkeynes@306 | 486 | } |
nkeynes@306 | 487 | for( y=0; y<480; y+=32 ) { |
nkeynes@306 | 488 | for( x=0; x<640; x++ ) { |
nkeynes@306 | 489 | addr[(linesize*y) + x] = colour; |
nkeynes@306 | 490 | } |
nkeynes@306 | 491 | } |
nkeynes@320 | 492 | } |
nkeynes@306 | 493 | |
nkeynes@320 | 494 | void draw_grid_24( unsigned char *addr, unsigned int colour ) |
nkeynes@320 | 495 | { |
nkeynes@320 | 496 | int x,y; |
nkeynes@320 | 497 | char r = (colour >> 16) & 0xFF; |
nkeynes@320 | 498 | char g = (colour >> 8) & 0xFF; |
nkeynes@320 | 499 | char b = (colour & 0xFF); |
nkeynes@320 | 500 | unsigned int linesize = 640*3; |
nkeynes@320 | 501 | for( x=0; x<640; x+=32 ) { |
nkeynes@320 | 502 | for( y=0; y<480; y++ ) { |
nkeynes@320 | 503 | int a = (linesize*y)+x * 3; |
nkeynes@320 | 504 | addr[a++] = r; |
nkeynes@320 | 505 | addr[a++] = g; |
nkeynes@320 | 506 | addr[a++] = b; |
nkeynes@320 | 507 | } |
nkeynes@320 | 508 | } |
nkeynes@320 | 509 | for( y=0; y<480; y+=32 ) { |
nkeynes@320 | 510 | for( x=0; x<640; x++ ) { |
nkeynes@320 | 511 | int a = (linesize*y)+x * 3; |
nkeynes@320 | 512 | addr[a++] = r; |
nkeynes@320 | 513 | addr[a++] = g; |
nkeynes@320 | 514 | addr[a++] = b; |
nkeynes@320 | 515 | } |
nkeynes@320 | 516 | } |
nkeynes@306 | 517 | } |
.