Search
lxdream.org :: lxdream/test/pvr.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/pvr.c
changeset 561:533f6b478071
prev320:660b15095115
next1151:e1848ca9b5b1
author nkeynes
date Thu Jul 24 07:27:48 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Halt emulation after reporting an error
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
}
.