nkeynes@284: /** nkeynes@561: * $Id$ 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@645: #include nkeynes@645: #include nkeynes@645: #include nkeynes@929: #include "sh4/sh4core.h" nkeynes@284: #include "pvr2.h" nkeynes@325: #include "asic.h" nkeynes@669: #include "dream.h" nkeynes@284: nkeynes@429: extern unsigned char *video_base; nkeynes@284: nkeynes@929: /************************* VRAM32 address space ***************************/ nkeynes@929: nkeynes@929: static int32_t FASTCALL pvr2_vram32_read_long( sh4addr_t addr ) nkeynes@929: { nkeynes@929: pvr2_render_buffer_invalidate(addr, FALSE); nkeynes@929: return *((int32_t *)(video_base+(addr&0x007FFFFF))); nkeynes@929: } nkeynes@929: static int32_t FASTCALL pvr2_vram32_read_word( sh4addr_t addr ) nkeynes@929: { nkeynes@929: pvr2_render_buffer_invalidate(addr, FALSE); nkeynes@929: return SIGNEXT16(*((int16_t *)(video_base+(addr&0x007FFFFF)))); nkeynes@929: } nkeynes@929: static int32_t FASTCALL pvr2_vram32_read_byte( sh4addr_t addr ) nkeynes@929: { nkeynes@929: pvr2_render_buffer_invalidate(addr, FALSE); nkeynes@929: return SIGNEXT8(*((int8_t *)(video_base+(addr&0x007FFFFF)))); nkeynes@929: } nkeynes@929: static void FASTCALL pvr2_vram32_write_long( sh4addr_t addr, uint32_t val ) nkeynes@929: { nkeynes@929: pvr2_render_buffer_invalidate(addr, TRUE); nkeynes@929: *(uint32_t *)(video_base + (addr&0x007FFFFF)) = val; nkeynes@929: } nkeynes@929: static void FASTCALL pvr2_vram32_write_word( sh4addr_t addr, uint32_t val ) nkeynes@929: { nkeynes@929: pvr2_render_buffer_invalidate(addr, TRUE); nkeynes@929: *(uint16_t *)(video_base + (addr&0x007FFFFF)) = (uint16_t)val; nkeynes@929: } nkeynes@929: static void FASTCALL pvr2_vram32_write_byte( sh4addr_t addr, uint32_t val ) nkeynes@929: { nkeynes@929: pvr2_render_buffer_invalidate(addr, TRUE); nkeynes@929: *(uint8_t *)(video_base + (addr&0x007FFFFF)) = (uint8_t)val; nkeynes@929: } nkeynes@929: static void FASTCALL pvr2_vram32_read_burst( unsigned char *dest, sh4addr_t addr ) nkeynes@929: { nkeynes@929: // Render buffers pretty much have to be (at least) 32-byte aligned nkeynes@929: pvr2_render_buffer_invalidate(addr, FALSE); nkeynes@929: memcpy( dest, (video_base + (addr&0x007FFFFF)), 32 ); nkeynes@929: } nkeynes@929: static void FASTCALL pvr2_vram32_write_burst( sh4addr_t addr, unsigned char *src ) nkeynes@929: { nkeynes@929: // Render buffers pretty much have to be (at least) 32-byte aligned nkeynes@929: pvr2_render_buffer_invalidate(addr, TRUE); nkeynes@929: memcpy( (video_base + (addr&0x007FFFFF)), src, 32 ); nkeynes@929: } nkeynes@929: nkeynes@929: struct mem_region_fn mem_region_vram32 = { pvr2_vram32_read_long, pvr2_vram32_write_long, nkeynes@929: pvr2_vram32_read_word, pvr2_vram32_write_word, nkeynes@929: pvr2_vram32_read_byte, pvr2_vram32_write_byte, nkeynes@929: pvr2_vram32_read_burst, pvr2_vram32_write_burst }; nkeynes@929: nkeynes@929: /************************* VRAM64 address space ***************************/ nkeynes@929: nkeynes@929: #define TRANSLATE_VIDEO_64BIT_ADDRESS(a) ( (((a)&0x00FFFFF8)>>1)|(((a)&0x00000004)<<20)|((a)&0x03) ) nkeynes@929: nkeynes@929: static int32_t FASTCALL pvr2_vram64_read_long( sh4addr_t addr ) nkeynes@929: { nkeynes@929: addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr); nkeynes@929: pvr2_render_buffer_invalidate(addr, FALSE); nkeynes@929: return *((int32_t *)(video_base+(addr&0x007FFFFF))); nkeynes@929: } nkeynes@929: static int32_t FASTCALL pvr2_vram64_read_word( sh4addr_t addr ) nkeynes@929: { nkeynes@929: addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr); nkeynes@929: pvr2_render_buffer_invalidate(addr, FALSE); nkeynes@929: return SIGNEXT16(*((int16_t *)(video_base+(addr&0x007FFFFF)))); nkeynes@929: } nkeynes@929: static int32_t FASTCALL pvr2_vram64_read_byte( sh4addr_t addr ) nkeynes@929: { nkeynes@929: addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr); nkeynes@929: pvr2_render_buffer_invalidate(addr, FALSE); nkeynes@929: return SIGNEXT8(*((int8_t *)(video_base+(addr&0x007FFFFF)))); nkeynes@929: } nkeynes@929: static void FASTCALL pvr2_vram64_write_long( sh4addr_t addr, uint32_t val ) nkeynes@929: { nkeynes@929: texcache_invalidate_page(addr& 0x007FFFFF); nkeynes@929: addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr); nkeynes@929: pvr2_render_buffer_invalidate(addr, TRUE); nkeynes@929: *(uint32_t *)(video_base + (addr&0x007FFFFF)) = val; nkeynes@929: } nkeynes@929: static void FASTCALL pvr2_vram64_write_word( sh4addr_t addr, uint32_t val ) nkeynes@929: { nkeynes@929: texcache_invalidate_page(addr& 0x007FFFFF); nkeynes@929: addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr); nkeynes@929: pvr2_render_buffer_invalidate(addr, TRUE); nkeynes@929: *(uint16_t *)(video_base + (addr&0x007FFFFF)) = (uint16_t)val; nkeynes@929: } nkeynes@929: static void FASTCALL pvr2_vram64_write_byte( sh4addr_t addr, uint32_t val ) nkeynes@929: { nkeynes@929: texcache_invalidate_page(addr& 0x007FFFFF); nkeynes@929: addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr); nkeynes@929: pvr2_render_buffer_invalidate(addr, TRUE); nkeynes@929: *(uint8_t *)(video_base + (addr&0x007FFFFF)) = (uint8_t)val; nkeynes@929: } nkeynes@929: static void FASTCALL pvr2_vram64_read_burst( unsigned char *dest, sh4addr_t addr ) nkeynes@929: { nkeynes@929: pvr2_vram64_read( dest, addr, 32 ); nkeynes@929: } nkeynes@929: static void FASTCALL pvr2_vram64_write_burst( sh4addr_t addr, unsigned char *src ) nkeynes@929: { nkeynes@929: pvr2_vram64_write( addr, src, 32 ); nkeynes@929: } nkeynes@929: nkeynes@929: struct mem_region_fn mem_region_vram64 = { pvr2_vram64_read_long, pvr2_vram64_write_long, nkeynes@929: pvr2_vram64_read_word, pvr2_vram64_write_word, nkeynes@929: pvr2_vram64_read_byte, pvr2_vram64_write_byte, nkeynes@929: pvr2_vram64_read_burst, pvr2_vram64_write_burst }; nkeynes@929: nkeynes@929: nkeynes@929: nkeynes@429: void pvr2_dma_write( sh4addr_t destaddr, unsigned char *src, uint32_t count ) nkeynes@325: { nkeynes@325: int region; nkeynes@325: nkeynes@325: switch( destaddr & 0x13800000 ) { nkeynes@325: case 0x10000000: nkeynes@325: case 0x12000000: nkeynes@736: pvr2_ta_write( src, count ); nkeynes@736: break; nkeynes@325: case 0x11000000: nkeynes@325: case 0x11800000: nkeynes@736: region = MMIO_READ( ASIC, PVRDMARGN1 ); nkeynes@736: if( region == 0 ) { nkeynes@736: pvr2_vram64_write( destaddr, src, count ); nkeynes@736: } else { nkeynes@834: destaddr &= PVR2_RAM_MASK; nkeynes@834: unsigned char *dest = video_base + destaddr; nkeynes@834: if( PVR2_RAM_SIZE - destaddr < count ) { nkeynes@834: count = PVR2_RAM_SIZE - destaddr; nkeynes@834: } nkeynes@736: memcpy( dest, src, count ); nkeynes@736: } nkeynes@736: break; nkeynes@325: case 0x10800000: nkeynes@325: case 0x12800000: nkeynes@736: pvr2_yuv_write( src, count ); nkeynes@736: break; nkeynes@325: case 0x13000000: nkeynes@325: case 0x13800000: nkeynes@736: region = MMIO_READ( ASIC, PVRDMARGN2 ); nkeynes@736: if( region == 0 ) { nkeynes@736: pvr2_vram64_write( destaddr, src, count ); nkeynes@736: } else { nkeynes@834: destaddr &= PVR2_RAM_MASK; nkeynes@834: unsigned char *dest = video_base + destaddr; nkeynes@834: if( PVR2_RAM_SIZE - destaddr < count ) { nkeynes@834: count = PVR2_RAM_SIZE - destaddr; nkeynes@834: } nkeynes@736: memcpy( dest, src, count ); nkeynes@736: } nkeynes@827: } nkeynes@325: } nkeynes@325: nkeynes@429: void pvr2_vram64_write( sh4addr_t destaddr, unsigned 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@736: length = 0x800000 - destaddr; nkeynes@284: } nkeynes@284: nkeynes@796: for( i=destaddr & 0xFFFFF000; i < destaddr + length; i+= LXDREAM_PAGE_SIZE ) { nkeynes@736: 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@827: if( bank_flag ) nkeynes@736: banks[0]++; nkeynes@736: nkeynes@284: /* Handle non-aligned start of source */ nkeynes@284: if( destaddr & 0x03 ) { nkeynes@736: unsigned char *dest = ((unsigned char *)banks[bank_flag]) + (destaddr & 0x03); nkeynes@736: for( i= destaddr & 0x03; i < 4 && length > 0; i++, length-- ) { nkeynes@736: *dest++ = *src++; nkeynes@736: } nkeynes@736: bank_flag = !bank_flag; nkeynes@284: } nkeynes@284: nkeynes@284: dwsrc = (uint32_t *)src; nkeynes@284: while( length >= 4 ) { nkeynes@736: *banks[bank_flag]++ = *dwsrc++; nkeynes@736: bank_flag = !bank_flag; nkeynes@736: length -= 4; nkeynes@284: } nkeynes@736: nkeynes@284: /* Handle non-aligned end of source */ nkeynes@284: if( length ) { nkeynes@736: src = (unsigned char *)dwsrc; nkeynes@736: unsigned char *dest = (unsigned char *)banks[bank_flag]; nkeynes@736: while( length-- > 0 ) { nkeynes@736: *dest++ = *src++; nkeynes@736: } nkeynes@827: } 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@869: * The destaddr must be 64-bit aligned, and both line_bytes and line_stride_bytes nkeynes@869: * must be multiples of 8. nkeynes@284: */ nkeynes@827: void pvr2_vram64_write_stride( sh4addr_t destaddr, unsigned char *src, uint32_t line_bytes, nkeynes@736: uint32_t line_stride_bytes, uint32_t line_count ) nkeynes@284: { nkeynes@869: int i,j; nkeynes@284: uint32_t *banks[2]; nkeynes@869: uint32_t *dwsrc = (uint32_t *)src; nkeynes@869: uint32_t line_gap = (line_stride_bytes - line_bytes) >> 3; nkeynes@284: nkeynes@284: destaddr = destaddr & 0x7FFFF8; nkeynes@869: line_bytes >>= 3; nkeynes@284: nkeynes@869: for( i=destaddr; i < destaddr + line_stride_bytes*line_count; i+= LXDREAM_PAGE_SIZE ) { nkeynes@736: 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@736: nkeynes@284: for( i=0; i= line_bytes. nkeynes@284: * This method is used to extract a "stride" texture from vram. nkeynes@284: */ nkeynes@429: void pvr2_vram64_read_stride( unsigned char *dest, uint32_t dest_line_bytes, sh4addr_t srcaddr, nkeynes@736: 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@429: uint32_t dest_line_gap = 0; nkeynes@429: uint32_t src_line_gap = 0; 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@736: dest_line_gap = (dest_line_bytes - src_line_bytes) >> 2; nkeynes@736: src_line_gap = 0; nkeynes@736: src_line_gap_flag = 0; nkeynes@736: line_bytes = src_line_bytes >> 2; nkeynes@284: } else { nkeynes@736: i = (src_line_bytes - dest_line_bytes); nkeynes@736: src_line_gap_flag = i & 0x04; nkeynes@736: src_line_gap = i >> 3; nkeynes@736: line_bytes = dest_line_bytes >> 2; nkeynes@284: } nkeynes@736: nkeynes@284: banks[0] = (uint32_t *)(video_base + (srcaddr>>1)); nkeynes@284: banks[1] = banks[0] + 0x100000; nkeynes@284: if( bank_flag ) nkeynes@736: banks[0]++; nkeynes@736: nkeynes@284: dwdest = (uint32_t *)dest; nkeynes@284: for( i=0; i> 1; nkeynes@736: uint8_t t1 = *banks[offset<4?0:1]++; nkeynes@736: uint8_t t2 = *banks[offset<3?0:1]++; nkeynes@736: dest[y1*stride + x1] = (t1 & 0x0F) | (t2<<4); nkeynes@736: dest[(y1+1)*stride + x1] = (t1>>4) | (t2&0xF0); nkeynes@315: } else if( width == 4 ) { nkeynes@736: pvr2_vram64_detwiddle_4( dest, banks, offset, x1, y1, 2, stride ); nkeynes@736: pvr2_vram64_detwiddle_4( dest, banks, offset+2, x1, y1+2, 2, stride ); nkeynes@736: pvr2_vram64_detwiddle_4( dest, banks, offset+4, x1+2, y1, 2, stride ); nkeynes@736: pvr2_vram64_detwiddle_4( dest, banks, offset+6, x1+2, y1+2, 2, stride ); nkeynes@736: nkeynes@315: } else { nkeynes@736: int subdivide = width >> 1; nkeynes@736: pvr2_vram64_detwiddle_4( dest, banks, offset, x1, y1, subdivide, stride ); nkeynes@736: pvr2_vram64_detwiddle_4( dest, banks, offset, x1, y1+subdivide, subdivide, stride ); nkeynes@736: pvr2_vram64_detwiddle_4( dest, banks, offset, x1+subdivide, y1, subdivide, stride ); nkeynes@736: pvr2_vram64_detwiddle_4( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, stride ); nkeynes@315: } nkeynes@315: } nkeynes@315: nkeynes@315: /** nkeynes@315: * @param dest Destination image buffer nkeynes@315: * @param banks Source data expressed as two bank pointers nkeynes@315: * @param offset Offset into banks[0] specifying where the next byte nkeynes@315: * to read is (0..3) nkeynes@315: * @param x1,y1 Destination coordinates nkeynes@315: * @param width Width of current destination block nkeynes@315: * @param stride Total width of image (ie stride) nkeynes@310: */ nkeynes@310: nkeynes@310: static void pvr2_vram64_detwiddle_8( uint8_t *dest, uint8_t *banks[2], int offset, nkeynes@736: int x1, int y1, int width, int stride ) nkeynes@310: { nkeynes@310: if( width == 2 ) { nkeynes@736: dest[y1*stride + x1] = *banks[0]++; nkeynes@736: dest[(y1+1)*stride + x1] = *banks[offset<3?0:1]++; nkeynes@736: dest[y1*stride + x1 + 1] = *banks[offset<2?0:1]++; nkeynes@736: dest[(y1+1)*stride + x1 + 1] = *banks[offset==0?0:1]++; nkeynes@736: uint8_t *tmp = banks[0]; /* swap banks */ nkeynes@736: banks[0] = banks[1]; nkeynes@736: banks[1] = tmp; nkeynes@310: } else { nkeynes@736: int subdivide = width >> 1; nkeynes@736: pvr2_vram64_detwiddle_8( dest, banks, offset, x1, y1, subdivide, stride ); nkeynes@736: pvr2_vram64_detwiddle_8( dest, banks, offset, x1, y1+subdivide, subdivide, stride ); nkeynes@736: pvr2_vram64_detwiddle_8( dest, banks, offset, x1+subdivide, y1, subdivide, stride ); nkeynes@736: pvr2_vram64_detwiddle_8( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, stride ); nkeynes@284: } nkeynes@310: } nkeynes@310: nkeynes@310: /** nkeynes@310: * @param dest Destination image buffer nkeynes@310: * @param banks Source data expressed as two bank pointers nkeynes@310: * @param offset Offset into banks[0] specifying where the next word nkeynes@310: * to read is (0 or 1) nkeynes@310: * @param x1,y1 Destination coordinates nkeynes@310: * @param width Width of current destination block nkeynes@315: * @param stride Total width of image (ie stride) nkeynes@310: */ nkeynes@310: nkeynes@310: static void pvr2_vram64_detwiddle_16( uint16_t *dest, uint16_t *banks[2], int offset, nkeynes@736: int x1, int y1, int width, int stride ) nkeynes@310: { nkeynes@310: if( width == 2 ) { nkeynes@736: dest[y1*stride + x1] = *banks[0]++; nkeynes@736: dest[(y1+1)*stride + x1] = *banks[offset]++; nkeynes@736: dest[y1*stride + x1 + 1] = *banks[1]++; nkeynes@736: dest[(y1+1)*stride + x1 + 1] = *banks[offset^1]++; nkeynes@310: } else { nkeynes@736: int subdivide = width >> 1; nkeynes@736: pvr2_vram64_detwiddle_16( dest, banks, offset, x1, y1, subdivide, stride ); nkeynes@736: pvr2_vram64_detwiddle_16( dest, banks, offset, x1, y1+subdivide, subdivide, stride ); nkeynes@736: pvr2_vram64_detwiddle_16( dest, banks, offset, x1+subdivide, y1, subdivide, stride ); nkeynes@736: pvr2_vram64_detwiddle_16( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, stride ); nkeynes@310: } nkeynes@310: } nkeynes@310: nkeynes@310: /** nkeynes@827: * Read an image from 64-bit vram stored as twiddled 4-bit pixels. The nkeynes@315: * image is written out to the destination in detwiddled form. nkeynes@315: * @param dest destination buffer, which must be at least width*height/2 in length nkeynes@315: * @param srcaddr source address in vram nkeynes@315: * @param width image width (must be a power of 2) nkeynes@315: * @param height image height (must be a power of 2) nkeynes@315: */ nkeynes@429: void pvr2_vram64_read_twiddled_4( unsigned char *dest, sh4addr_t srcaddr, uint32_t width, uint32_t height ) nkeynes@315: { nkeynes@315: int offset_flag = (srcaddr & 0x07); nkeynes@315: uint8_t *banks[2]; nkeynes@315: uint8_t *wdest = (uint8_t*)dest; nkeynes@315: uint32_t stride = width >> 1; nkeynes@429: int i; nkeynes@315: nkeynes@315: srcaddr = srcaddr & 0x7FFFF8; nkeynes@315: nkeynes@315: banks[0] = (uint8_t *)(video_base + (srcaddr>>1)); nkeynes@315: banks[1] = banks[0] + 0x400000; nkeynes@315: if( offset_flag & 0x04 ) { // If source is not 64-bit aligned, swap the banks nkeynes@736: uint8_t *tmp = banks[0]; nkeynes@736: banks[0] = banks[1]; nkeynes@736: banks[1] = tmp + 4; nkeynes@736: offset_flag &= 0x03; nkeynes@315: } nkeynes@315: banks[0] += offset_flag; nkeynes@315: nkeynes@315: if( width > height ) { nkeynes@736: for( i=0; i width ) { nkeynes@736: for( i=0; i>1)); nkeynes@310: banks[1] = banks[0] + 0x400000; nkeynes@310: if( offset_flag & 0x04 ) { // If source is not 64-bit aligned, swap the banks nkeynes@736: uint8_t *tmp = banks[0]; nkeynes@736: banks[0] = banks[1]; nkeynes@736: banks[1] = tmp + 4; nkeynes@736: offset_flag &= 0x03; nkeynes@310: } nkeynes@310: banks[0] += offset_flag; nkeynes@310: nkeynes@310: if( width > height ) { nkeynes@736: for( i=0; i width ) { nkeynes@736: for( i=0; i> 1; nkeynes@310: uint16_t *banks[2]; nkeynes@310: uint16_t *wdest = (uint16_t*)dest; nkeynes@429: int i; nkeynes@310: nkeynes@310: srcaddr = srcaddr & 0x7FFFF8; nkeynes@310: nkeynes@310: banks[0] = (uint16_t *)(video_base + (srcaddr>>1)); nkeynes@310: banks[1] = banks[0] + 0x200000; nkeynes@310: if( offset_flag & 0x02 ) { // If source is not 64-bit aligned, swap the banks nkeynes@736: uint16_t *tmp = banks[0]; nkeynes@736: banks[0] = banks[1]; nkeynes@736: banks[1] = tmp + 2; nkeynes@736: offset_flag &= 0x01; nkeynes@310: } nkeynes@310: banks[0] += offset_flag; nkeynes@736: nkeynes@310: nkeynes@310: if( width > height ) { nkeynes@736: for( i=0; i width ) { nkeynes@736: for( i=0; i= src ) { nkeynes@857: memcpy( dest, p, line_size ); nkeynes@736: p -= src_stride; nkeynes@857: dest += dest_stride; nkeynes@857: } nkeynes@857: } nkeynes@857: nkeynes@869: static void pvr2_vram64_write_invert( sh4addr_t destaddr, unsigned char *src, nkeynes@869: uint32_t src_size, uint32_t line_size, nkeynes@869: uint32_t dest_stride, uint32_t src_stride ) nkeynes@869: { nkeynes@869: int i,j; nkeynes@869: uint32_t *banks[2]; nkeynes@869: uint32_t *dwsrc = (uint32_t *)(src + src_size - src_stride); nkeynes@869: int32_t src_line_gap = ((int32_t)src_stride + line_size) >> 2; nkeynes@869: int32_t dest_line_gap = ((int32_t)dest_stride - (int32_t)line_size) >> 3; nkeynes@869: nkeynes@869: destaddr = destaddr & 0x7FFFF8; nkeynes@869: nkeynes@869: for( i=destaddr; i < destaddr + dest_stride*(src_size/src_stride); i+= LXDREAM_PAGE_SIZE ) { nkeynes@869: texcache_invalidate_page( i ); nkeynes@869: } nkeynes@869: nkeynes@869: banks[0] = (uint32_t *)(video_base + (destaddr >>1)); nkeynes@869: banks[1] = banks[0] + 0x100000; nkeynes@869: nkeynes@869: while( dwsrc >= (uint32_t *)src ) { nkeynes@869: for( j=0; j= src ) { nkeynes@857: unsigned char *s = p, *d = dest; nkeynes@857: int i; nkeynes@857: while( s < p+line_size ) { nkeynes@857: for( i=0; i> 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@736: 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@736: banks[0]++; nkeynes@736: nkeynes@284: /* Handle non-aligned start of source */ nkeynes@284: if( srcaddr & 0x03 ) { nkeynes@736: char *src = ((char *)banks[bank_flag]) + (srcaddr & 0x03); nkeynes@736: for( i= srcaddr & 0x03; i < 4 && length > 0; i++, length-- ) { nkeynes@736: *dest++ = *src++; nkeynes@736: } nkeynes@736: bank_flag = !bank_flag; nkeynes@284: } nkeynes@284: nkeynes@284: dwdest = (uint32_t *)dest; nkeynes@284: while( length >= 4 ) { nkeynes@736: *dwdest++ = *banks[bank_flag]++; nkeynes@736: bank_flag = !bank_flag; nkeynes@736: length -= 4; nkeynes@284: } nkeynes@736: nkeynes@284: /* Handle non-aligned end of source */ nkeynes@284: if( length ) { nkeynes@736: dest = (unsigned char *)dwdest; nkeynes@736: unsigned char *src = (unsigned char *)banks[bank_flag]; nkeynes@736: while( length-- > 0 ) { nkeynes@736: *dest++ = *src++; nkeynes@736: } nkeynes@284: } nkeynes@284: } nkeynes@284: nkeynes@309: void pvr2_vram64_dump_file( sh4addr_t addr, uint32_t length, gchar *filename ) nkeynes@309: { nkeynes@309: uint32_t tmp[length>>2]; nkeynes@309: FILE *f = fopen(filename, "wo"); nkeynes@309: unsigned int i, j; nkeynes@309: nkeynes@309: if( f == NULL ) { nkeynes@736: ERROR( "Unable to write to dump file '%s' (%s)", filename, strerror(errno) ); nkeynes@736: return; nkeynes@309: } nkeynes@429: pvr2_vram64_read( (unsigned char *)tmp, addr, length ); nkeynes@309: fprintf( f, "%08X\n", addr ); nkeynes@309: for( i =0; i>2; i+=8 ) { nkeynes@736: for( j=i; jwidth * colour_formats[buffer->colour_format].bpp; nkeynes@869: int src_stride = line_size; nkeynes@869: unsigned char target[buffer->size]; nkeynes@869: nkeynes@869: display_driver->read_render_buffer( target, buffer, line_size, buffer->colour_format ); nkeynes@869: nkeynes@869: if( (buffer->scale & 0xFFFF) == 0x0800 ) nkeynes@869: src_stride <<= 1; nkeynes@869: nkeynes@429: if( (buffer->address & 0xFF000000) == 0x04000000 ) { nkeynes@869: pvr2_vram64_write_invert( buffer->address, target, buffer->size, line_size, nkeynes@869: buffer->rowstride, src_stride ); nkeynes@315: } else { nkeynes@736: /* Regular buffer */ nkeynes@857: if( buffer->scale & SCALER_HSCALE ) { nkeynes@857: pvr2_vram_write_invert_hscale( buffer->address, target, buffer->size, line_size, buffer->rowstride, nkeynes@857: src_stride, colour_formats[buffer->colour_format].bpp ); nkeynes@352: } else { nkeynes@857: pvr2_vram_write_invert( buffer->address, target, buffer->size, line_size, buffer->rowstride, nkeynes@857: src_stride ); nkeynes@352: } nkeynes@315: } nkeynes@856: buffer->flushed = TRUE; nkeynes@315: } nkeynes@315: