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 Mon Nov 08 22:10:47 2010 +1000 (13 years ago)
permissions -rw-r--r--
last change Suggest to the compiler a little more firmly that it inline the x86op
functions (as these are nearly always called with constants, they can
usually be reduced down pretty dramatically)
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
}
.