nkeynes@284: /** nkeynes@285: * $Id: pvr2mem.c,v 1.2 2007-01-15 10:10:51 nkeynes Exp $ nkeynes@284: * nkeynes@284: * PVR2 (Video) VRAM handling routines (mainly for the 64-bit region) nkeynes@284: * nkeynes@284: * Copyright (c) 2005 Nathan Keynes. nkeynes@284: * nkeynes@284: * This program is free software; you can redistribute it and/or modify nkeynes@284: * it under the terms of the GNU General Public License as published by nkeynes@284: * the Free Software Foundation; either version 2 of the License, or nkeynes@284: * (at your option) any later version. nkeynes@284: * nkeynes@284: * This program is distributed in the hope that it will be useful, nkeynes@284: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@284: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@284: * GNU General Public License for more details. nkeynes@284: */ nkeynes@284: #include "pvr2.h" nkeynes@284: nkeynes@284: extern char *video_base; nkeynes@284: nkeynes@284: void pvr2_vram64_write( sh4addr_t destaddr, char *src, uint32_t length ) nkeynes@284: { nkeynes@284: int bank_flag = (destaddr & 0x04) >> 2; nkeynes@284: uint32_t *banks[2]; nkeynes@284: uint32_t *dwsrc; nkeynes@284: int i; nkeynes@284: nkeynes@284: destaddr = destaddr & 0x7FFFFF; nkeynes@284: if( destaddr + length > 0x800000 ) { nkeynes@284: length = 0x800000 - destaddr; nkeynes@284: } nkeynes@284: nkeynes@284: for( i=destaddr & 0xFFFFF000; i < destaddr + length; i+= PAGE_SIZE ) { nkeynes@284: texcache_invalidate_page( i ); nkeynes@284: } nkeynes@284: nkeynes@284: banks[0] = ((uint32_t *)(video_base + ((destaddr & 0x007FFFF8) >>1))); nkeynes@284: banks[1] = banks[0] + 0x100000; nkeynes@284: if( bank_flag ) nkeynes@284: banks[0]++; nkeynes@284: nkeynes@284: /* Handle non-aligned start of source */ nkeynes@284: if( destaddr & 0x03 ) { nkeynes@284: char *dest = ((char *)banks[bank_flag]) + (destaddr & 0x03); nkeynes@284: for( i= destaddr & 0x03; i < 4 && length > 0; i++, length-- ) { nkeynes@284: *dest++ = *src++; nkeynes@284: } nkeynes@284: bank_flag = !bank_flag; nkeynes@284: } nkeynes@284: nkeynes@284: dwsrc = (uint32_t *)src; nkeynes@284: while( length >= 4 ) { nkeynes@284: *banks[bank_flag]++ = *dwsrc++; nkeynes@284: bank_flag = !bank_flag; nkeynes@284: length -= 4; nkeynes@284: } nkeynes@284: nkeynes@284: /* Handle non-aligned end of source */ nkeynes@284: if( length ) { nkeynes@284: src = (char *)dwsrc; nkeynes@284: char *dest = (char *)banks[bank_flag]; nkeynes@284: while( length-- > 0 ) { nkeynes@284: *dest++ = *src++; nkeynes@284: } nkeynes@284: } nkeynes@284: } nkeynes@284: nkeynes@284: /** nkeynes@284: * Write an image to 64-bit vram, with a line-stride different from the line-size. nkeynes@284: * The destaddr must be 32-bit aligned, and both line_bytes and line_stride_bytes nkeynes@284: * must be multiples of 4. nkeynes@284: */ nkeynes@284: void pvr2_vram64_write_stride( sh4addr_t destaddr, char *src, uint32_t line_bytes, nkeynes@284: uint32_t line_stride_bytes, uint32_t line_count ) nkeynes@284: { nkeynes@284: int bank_flag = (destaddr & 0x04) >> 2; nkeynes@284: uint32_t *banks[2]; nkeynes@284: uint32_t *dwsrc; nkeynes@284: uint32_t line_gap; nkeynes@284: int line_gap_flag; nkeynes@284: int i,j; nkeynes@284: nkeynes@284: destaddr = destaddr & 0x7FFFF8; nkeynes@284: i = line_stride_bytes - line_bytes; nkeynes@284: line_gap_flag = i & 0x04; nkeynes@284: line_gap = i >> 3; nkeynes@284: line_bytes >>= 2; nkeynes@284: nkeynes@284: for( i=destaddr & 0xFFFFF000; i < destaddr + line_stride_bytes*line_count; i+= PAGE_SIZE ) { nkeynes@284: texcache_invalidate_page( i ); nkeynes@284: } nkeynes@284: nkeynes@284: banks[0] = (uint32_t *)(video_base + (destaddr >>1)); nkeynes@284: banks[1] = banks[0] + 0x100000; nkeynes@284: if( bank_flag ) nkeynes@284: banks[0]++; nkeynes@284: nkeynes@284: dwsrc = (uint32_t *)src; nkeynes@284: for( i=0; i= line_bytes. nkeynes@284: * This method is used to extract a "stride" texture from vram. nkeynes@284: */ nkeynes@284: void pvr2_vram64_read_stride( char *dest, uint32_t dest_line_bytes, sh4addr_t srcaddr, nkeynes@284: uint32_t src_line_bytes, uint32_t line_count ) nkeynes@284: { nkeynes@284: int bank_flag = (srcaddr & 0x04) >> 2; nkeynes@284: uint32_t *banks[2]; nkeynes@284: uint32_t *dwdest; nkeynes@284: uint32_t dest_line_gap; nkeynes@284: uint32_t src_line_gap; nkeynes@284: uint32_t line_bytes; nkeynes@284: int src_line_gap_flag; nkeynes@284: int i,j; nkeynes@284: nkeynes@284: srcaddr = srcaddr & 0x7FFFF8; nkeynes@284: if( src_line_bytes <= dest_line_bytes ) { nkeynes@284: dest_line_gap = (dest_line_bytes - src_line_bytes) >> 2; nkeynes@284: src_line_gap = 0; nkeynes@284: src_line_gap_flag = 0; nkeynes@284: line_bytes = src_line_bytes >> 2; nkeynes@284: } else { nkeynes@284: i = (src_line_bytes - dest_line_bytes); nkeynes@284: src_line_gap_flag = i & 0x04; nkeynes@284: src_line_gap = i >> 3; nkeynes@284: line_bytes = dest_line_bytes >> 2; nkeynes@284: } nkeynes@284: nkeynes@284: banks[0] = (uint32_t *)(video_base + (srcaddr>>1)); nkeynes@284: banks[1] = banks[0] + 0x100000; nkeynes@284: if( bank_flag ) nkeynes@284: banks[0]++; nkeynes@284: nkeynes@284: dwdest = (uint32_t *)dest; nkeynes@284: for( i=0; i= src ) { nkeynes@284: memcpy( dest, p, line_length ); nkeynes@284: p -= line_length; nkeynes@284: dest += line_length; nkeynes@284: } nkeynes@284: } nkeynes@284: nkeynes@284: void pvr2_vram64_read( char *dest, sh4addr_t srcaddr, uint32_t length ) nkeynes@284: { nkeynes@284: int bank_flag = (srcaddr & 0x04) >> 2; nkeynes@284: uint32_t *banks[2]; nkeynes@284: uint32_t *dwdest; nkeynes@284: int i; nkeynes@284: nkeynes@284: srcaddr = srcaddr & 0x7FFFFF; nkeynes@284: if( srcaddr + length > 0x800000 ) nkeynes@284: length = 0x800000 - srcaddr; nkeynes@284: nkeynes@284: banks[0] = ((uint32_t *)(video_base + ((srcaddr&0x007FFFF8)>>1))); nkeynes@284: banks[1] = banks[0] + 0x100000; nkeynes@284: if( bank_flag ) nkeynes@284: banks[0]++; nkeynes@284: nkeynes@284: /* Handle non-aligned start of source */ nkeynes@284: if( srcaddr & 0x03 ) { nkeynes@284: char *src = ((char *)banks[bank_flag]) + (srcaddr & 0x03); nkeynes@284: for( i= srcaddr & 0x03; i < 4 && length > 0; i++, length-- ) { nkeynes@284: *dest++ = *src++; nkeynes@284: } nkeynes@284: bank_flag = !bank_flag; nkeynes@284: } nkeynes@284: nkeynes@284: dwdest = (uint32_t *)dest; nkeynes@284: while( length >= 4 ) { nkeynes@284: *dwdest++ = *banks[bank_flag]++; nkeynes@284: bank_flag = !bank_flag; nkeynes@284: length -= 4; nkeynes@284: } nkeynes@284: nkeynes@284: /* Handle non-aligned end of source */ nkeynes@284: if( length ) { nkeynes@284: dest = (char *)dwdest; nkeynes@284: char *src = (char *)banks[bank_flag]; nkeynes@284: while( length-- > 0 ) { nkeynes@284: *dest++ = *src++; nkeynes@284: } nkeynes@284: } nkeynes@284: } nkeynes@284: nkeynes@284: void pvr2_vram64_dump( sh4addr_t addr, uint32_t length, FILE *f ) nkeynes@284: { nkeynes@284: char tmp[length]; nkeynes@284: pvr2_vram64_read( tmp, addr, length ); nkeynes@284: fwrite_dump( tmp, length, f ); nkeynes@284: }