Search
lxdream.org :: lxdream/src/pvr2/pvr2mem.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/pvr2mem.c
changeset 284:808617ee7135
next285:4fefedafebc6
author nkeynes
date Mon Jan 15 08:32:09 2007 +0000 (12 years ago)
permissions -rw-r--r--
last change Break vram routines out into pvr2mem.c
Initial (untested) implementation of stride textures
Hookup YUV converter code in pvr2.c
file annotate diff log raw
nkeynes@284
     1
/**
nkeynes@284
     2
 * $Id: pvr2mem.c,v 1.1 2007-01-15 08:32:09 nkeynes Exp $
nkeynes@284
     3
 *
nkeynes@284
     4
 * PVR2 (Video) VRAM handling routines (mainly for the 64-bit region)
nkeynes@284
     5
 *
nkeynes@284
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@284
     7
 *
nkeynes@284
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@284
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@284
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@284
    11
 * (at your option) any later version.
nkeynes@284
    12
 *
nkeynes@284
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@284
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@284
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@284
    16
 * GNU General Public License for more details.
nkeynes@284
    17
 */
nkeynes@284
    18
#include "pvr2.h"
nkeynes@284
    19
nkeynes@284
    20
extern char *video_base;
nkeynes@284
    21
nkeynes@284
    22
void pvr2_vram64_write( sh4addr_t destaddr, char *src, uint32_t length )
nkeynes@284
    23
{
nkeynes@284
    24
    int bank_flag = (destaddr & 0x04) >> 2;
nkeynes@284
    25
    uint32_t *banks[2];
nkeynes@284
    26
    uint32_t *dwsrc;
nkeynes@284
    27
    int i;
nkeynes@284
    28
nkeynes@284
    29
    destaddr = destaddr & 0x7FFFFF;
nkeynes@284
    30
    if( destaddr + length > 0x800000 ) {
nkeynes@284
    31
	length = 0x800000 - destaddr;
nkeynes@284
    32
    }
nkeynes@284
    33
nkeynes@284
    34
    for( i=destaddr & 0xFFFFF000; i < destaddr + length; i+= PAGE_SIZE ) {
nkeynes@284
    35
	texcache_invalidate_page( i );
nkeynes@284
    36
    }
nkeynes@284
    37
nkeynes@284
    38
    banks[0] = ((uint32_t *)(video_base + ((destaddr & 0x007FFFF8) >>1)));
nkeynes@284
    39
    banks[1] = banks[0] + 0x100000;
nkeynes@284
    40
    if( bank_flag ) 
nkeynes@284
    41
	banks[0]++;
nkeynes@284
    42
    
nkeynes@284
    43
    /* Handle non-aligned start of source */
nkeynes@284
    44
    if( destaddr & 0x03 ) {
nkeynes@284
    45
	char *dest = ((char *)banks[bank_flag]) + (destaddr & 0x03);
nkeynes@284
    46
	for( i= destaddr & 0x03; i < 4 && length > 0; i++, length-- ) {
nkeynes@284
    47
	    *dest++ = *src++;
nkeynes@284
    48
	}
nkeynes@284
    49
	bank_flag = !bank_flag;
nkeynes@284
    50
    }
nkeynes@284
    51
nkeynes@284
    52
    dwsrc = (uint32_t *)src;
nkeynes@284
    53
    while( length >= 4 ) {
nkeynes@284
    54
	*banks[bank_flag]++ = *dwsrc++;
nkeynes@284
    55
	bank_flag = !bank_flag;
nkeynes@284
    56
	length -= 4;
nkeynes@284
    57
    }
nkeynes@284
    58
    
nkeynes@284
    59
    /* Handle non-aligned end of source */
nkeynes@284
    60
    if( length ) {
nkeynes@284
    61
	src = (char *)dwsrc;
nkeynes@284
    62
	char *dest = (char *)banks[bank_flag];
nkeynes@284
    63
	while( length-- > 0 ) {
nkeynes@284
    64
	    *dest++ = *src++;
nkeynes@284
    65
	}
nkeynes@284
    66
    }  
nkeynes@284
    67
}
nkeynes@284
    68
nkeynes@284
    69
/**
nkeynes@284
    70
 * Write an image to 64-bit vram, with a line-stride different from the line-size.
nkeynes@284
    71
 * The destaddr must be 32-bit aligned, and both line_bytes and line_stride_bytes
nkeynes@284
    72
 * must be multiples of 4.
nkeynes@284
    73
 */
nkeynes@284
    74
void pvr2_vram64_write_stride( sh4addr_t destaddr, char *src, uint32_t line_bytes, 
nkeynes@284
    75
			       uint32_t line_stride_bytes, uint32_t line_count )
nkeynes@284
    76
{
nkeynes@284
    77
    int bank_flag = (destaddr & 0x04) >> 2;
nkeynes@284
    78
    uint32_t *banks[2];
nkeynes@284
    79
    uint32_t *dwsrc;
nkeynes@284
    80
    uint32_t line_gap;
nkeynes@284
    81
    int line_gap_flag;
nkeynes@284
    82
    int i,j;
nkeynes@284
    83
nkeynes@284
    84
    destaddr = destaddr & 0x7FFFF8;
nkeynes@284
    85
    i = line_stride_bytes - line_bytes;
nkeynes@284
    86
    line_gap_flag = i & 0x04;
nkeynes@284
    87
    line_gap = i >> 3;
nkeynes@284
    88
    line_bytes >>= 2;
nkeynes@284
    89
nkeynes@284
    90
    for( i=destaddr & 0xFFFFF000; i < destaddr + line_stride_bytes*line_count; i+= PAGE_SIZE ) {
nkeynes@284
    91
	texcache_invalidate_page( i );
nkeynes@284
    92
    }
nkeynes@284
    93
nkeynes@284
    94
    banks[0] = (uint32_t *)(video_base + (destaddr >>1));
nkeynes@284
    95
    banks[1] = banks[0] + 0x100000;
nkeynes@284
    96
    if( bank_flag ) 
nkeynes@284
    97
	banks[0]++;
nkeynes@284
    98
    
nkeynes@284
    99
    dwsrc = (uint32_t *)src;
nkeynes@284
   100
    for( i=0; i<line_count; i++ ) {
nkeynes@284
   101
	for( j=0; j<line_bytes; j++ ) {
nkeynes@284
   102
	    *banks[bank_flag]++ = *dwsrc++;
nkeynes@284
   103
	    bank_flag = !bank_flag;
nkeynes@284
   104
	}
nkeynes@284
   105
	*banks[0] += line_gap;
nkeynes@284
   106
	*banks[1] += line_gap;
nkeynes@284
   107
	if( line_gap_flag ) {
nkeynes@284
   108
	    *banks[bank_flag]++;
nkeynes@284
   109
	    bank_flag = !bank_flag;
nkeynes@284
   110
	}
nkeynes@284
   111
    }    
nkeynes@284
   112
}
nkeynes@284
   113
nkeynes@284
   114
/**
nkeynes@284
   115
 * Read an image from 64-bit vram, with a destination line-stride different from the line-size.
nkeynes@284
   116
 * The srcaddr must be 32-bit aligned, and both line_bytes and line_stride_bytes
nkeynes@284
   117
 * must be multiples of 4. line_stride_bytes must be >= line_bytes.
nkeynes@284
   118
 * This method is used to extract a "stride" texture from vram.
nkeynes@284
   119
 */
nkeynes@284
   120
void pvr2_vram64_read_stride( char *dest, uint32_t dest_line_bytes, sh4addr_t srcaddr,
nkeynes@284
   121
				   uint32_t src_line_bytes, uint32_t line_count )
nkeynes@284
   122
{
nkeynes@284
   123
    int bank_flag = (srcaddr & 0x04) >> 2;
nkeynes@284
   124
    uint32_t *banks[2];
nkeynes@284
   125
    uint32_t *dwdest;
nkeynes@284
   126
    uint32_t dest_line_gap;
nkeynes@284
   127
    uint32_t src_line_gap;
nkeynes@284
   128
    uint32_t line_bytes;
nkeynes@284
   129
    int src_line_gap_flag;
nkeynes@284
   130
    int i,j;
nkeynes@284
   131
nkeynes@284
   132
    srcaddr = srcaddr & 0x7FFFF8;
nkeynes@284
   133
    if( src_line_bytes <= dest_line_bytes ) {
nkeynes@284
   134
	dest_line_gap = (dest_line_bytes - src_line_bytes) >> 2;
nkeynes@284
   135
	src_line_gap = 0;
nkeynes@284
   136
	src_line_gap_flag = 0;
nkeynes@284
   137
	line_bytes = src_line_bytes >> 2;
nkeynes@284
   138
    } else {
nkeynes@284
   139
	i = (src_line_bytes - dest_line_bytes);
nkeynes@284
   140
	src_line_gap_flag = i & 0x04;
nkeynes@284
   141
	src_line_gap = i >> 3;
nkeynes@284
   142
	line_bytes = dest_line_bytes >> 2;
nkeynes@284
   143
    }
nkeynes@284
   144
	
nkeynes@284
   145
    banks[0] = (uint32_t *)(video_base + (srcaddr>>1));
nkeynes@284
   146
    banks[1] = banks[0] + 0x100000;
nkeynes@284
   147
    if( bank_flag )
nkeynes@284
   148
	banks[0]++;
nkeynes@284
   149
    
nkeynes@284
   150
    dwdest = (uint32_t *)dest;
nkeynes@284
   151
    for( i=0; i<line_count; i++ ) {
nkeynes@284
   152
	for( j=0; j<line_bytes; j++ ) {
nkeynes@284
   153
	    *dwdest++ = *banks[bank_flag]++;
nkeynes@284
   154
	    bank_flag = !bank_flag;
nkeynes@284
   155
	}
nkeynes@284
   156
	dwdest += dest_line_gap;
nkeynes@284
   157
	banks[0] += src_line_gap;
nkeynes@284
   158
	banks[1] += src_line_gap;
nkeynes@284
   159
	if( src_line_gap_flag ) {
nkeynes@284
   160
	    banks[bank_flag]++;
nkeynes@284
   161
	    bank_flag = !bank_flag;
nkeynes@284
   162
	}
nkeynes@284
   163
    }
nkeynes@284
   164
    
nkeynes@284
   165
}
nkeynes@284
   166
nkeynes@284
   167
void pvr2_vram_write_invert( sh4addr_t destaddr, char *src, uint32_t length, uint32_t line_length )
nkeynes@284
   168
{
nkeynes@284
   169
    char *dest = video_base + (destaddr & 0x007FFFFF);
nkeynes@284
   170
    char *p = src + length - line_length;
nkeynes@284
   171
    while( p >= src ) {
nkeynes@284
   172
	memcpy( dest, p, line_length );
nkeynes@284
   173
	p -= line_length;
nkeynes@284
   174
	dest += line_length;
nkeynes@284
   175
    }
nkeynes@284
   176
}
nkeynes@284
   177
nkeynes@284
   178
void pvr2_vram64_read( char *dest, sh4addr_t srcaddr, uint32_t length )
nkeynes@284
   179
{
nkeynes@284
   180
    int bank_flag = (srcaddr & 0x04) >> 2;
nkeynes@284
   181
    uint32_t *banks[2];
nkeynes@284
   182
    uint32_t *dwdest;
nkeynes@284
   183
    int i;
nkeynes@284
   184
nkeynes@284
   185
    srcaddr = srcaddr & 0x7FFFFF;
nkeynes@284
   186
    if( srcaddr + length > 0x800000 )
nkeynes@284
   187
	length = 0x800000 - srcaddr;
nkeynes@284
   188
nkeynes@284
   189
    banks[0] = ((uint32_t *)(video_base + ((srcaddr&0x007FFFF8)>>1)));
nkeynes@284
   190
    banks[1] = banks[0] + 0x100000;
nkeynes@284
   191
    if( bank_flag )
nkeynes@284
   192
	banks[0]++;
nkeynes@284
   193
    
nkeynes@284
   194
    /* Handle non-aligned start of source */
nkeynes@284
   195
    if( srcaddr & 0x03 ) {
nkeynes@284
   196
	char *src = ((char *)banks[bank_flag]) + (srcaddr & 0x03);
nkeynes@284
   197
	for( i= srcaddr & 0x03; i < 4 && length > 0; i++, length-- ) {
nkeynes@284
   198
	    *dest++ = *src++;
nkeynes@284
   199
	}
nkeynes@284
   200
	bank_flag = !bank_flag;
nkeynes@284
   201
    }
nkeynes@284
   202
nkeynes@284
   203
    dwdest = (uint32_t *)dest;
nkeynes@284
   204
    while( length >= 4 ) {
nkeynes@284
   205
	*dwdest++ = *banks[bank_flag]++;
nkeynes@284
   206
	bank_flag = !bank_flag;
nkeynes@284
   207
	length -= 4;
nkeynes@284
   208
    }
nkeynes@284
   209
    
nkeynes@284
   210
    /* Handle non-aligned end of source */
nkeynes@284
   211
    if( length ) {
nkeynes@284
   212
	dest = (char *)dwdest;
nkeynes@284
   213
	char *src = (char *)banks[bank_flag];
nkeynes@284
   214
	while( length-- > 0 ) {
nkeynes@284
   215
	    *dest++ = *src++;
nkeynes@284
   216
	}
nkeynes@284
   217
    }
nkeynes@284
   218
}
nkeynes@284
   219
nkeynes@284
   220
void pvr2_vram64_dump( sh4addr_t addr, uint32_t length, FILE *f ) 
nkeynes@284
   221
{
nkeynes@284
   222
    char tmp[length];
nkeynes@284
   223
    pvr2_vram64_read( tmp, addr, length );
nkeynes@284
   224
    fwrite_dump( tmp, length, f );
nkeynes@284
   225
}
.