Search
lxdream.org :: lxdream/src/pvr2/pvr2mem.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/pvr2mem.c
changeset 1067:d3c00ffccfcd
prev953:f4a156508ad1
prev934:3acd3b3ee6d1
next1294:52be323fcab4
author nkeynes
date Wed Feb 15 17:54:51 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Use GL_TEXTURE_2D instead of GL_TEXTURE_RECTANGLE_ARB for frame buffers, for
systems that don't provide the latter (and there's not really much
difference anyway).
Add macro wrangling for GL_DEPTH24_STENCIL8 format
file annotate diff log raw
nkeynes@284
     1
/**
nkeynes@561
     2
 * $Id$
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@645
    18
#include <string.h>
nkeynes@645
    19
#include <stdio.h>
nkeynes@645
    20
#include <errno.h>
nkeynes@929
    21
#include "sh4/sh4core.h"
nkeynes@284
    22
#include "pvr2.h"
nkeynes@325
    23
#include "asic.h"
nkeynes@669
    24
#include "dream.h"
nkeynes@284
    25
nkeynes@934
    26
unsigned char pvr2_main_ram[8 MB];
nkeynes@284
    27
nkeynes@929
    28
/************************* VRAM32 address space ***************************/
nkeynes@929
    29
nkeynes@929
    30
static int32_t FASTCALL pvr2_vram32_read_long( sh4addr_t addr )
nkeynes@929
    31
{
nkeynes@929
    32
    pvr2_render_buffer_invalidate(addr, FALSE);
nkeynes@934
    33
    return *((int32_t *)(pvr2_main_ram+(addr&0x007FFFFF)));
nkeynes@929
    34
}
nkeynes@929
    35
static int32_t FASTCALL pvr2_vram32_read_word( sh4addr_t addr )
nkeynes@929
    36
{
nkeynes@929
    37
    pvr2_render_buffer_invalidate(addr, FALSE);
nkeynes@934
    38
    return SIGNEXT16(*((int16_t *)(pvr2_main_ram+(addr&0x007FFFFF))));
nkeynes@929
    39
}
nkeynes@929
    40
static int32_t FASTCALL pvr2_vram32_read_byte( sh4addr_t addr )
nkeynes@929
    41
{
nkeynes@929
    42
    pvr2_render_buffer_invalidate(addr, FALSE);
nkeynes@934
    43
    return SIGNEXT8(*((int8_t *)(pvr2_main_ram+(addr&0x007FFFFF))));
nkeynes@929
    44
}
nkeynes@929
    45
static void FASTCALL pvr2_vram32_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
    46
{
nkeynes@929
    47
    pvr2_render_buffer_invalidate(addr, TRUE);
nkeynes@934
    48
    *(uint32_t *)(pvr2_main_ram + (addr&0x007FFFFF)) = val;
nkeynes@929
    49
}
nkeynes@929
    50
static void FASTCALL pvr2_vram32_write_word( sh4addr_t addr, uint32_t val )
nkeynes@929
    51
{
nkeynes@929
    52
    pvr2_render_buffer_invalidate(addr, TRUE);
nkeynes@934
    53
    *(uint16_t *)(pvr2_main_ram + (addr&0x007FFFFF)) = (uint16_t)val;
nkeynes@929
    54
}
nkeynes@929
    55
static void FASTCALL pvr2_vram32_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@929
    56
{
nkeynes@929
    57
    pvr2_render_buffer_invalidate(addr, TRUE);
nkeynes@934
    58
    *(uint8_t *)(pvr2_main_ram + (addr&0x007FFFFF)) = (uint8_t)val;
nkeynes@929
    59
}
nkeynes@929
    60
static void FASTCALL pvr2_vram32_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@929
    61
{
nkeynes@929
    62
    // Render buffers pretty much have to be (at least) 32-byte aligned
nkeynes@929
    63
    pvr2_render_buffer_invalidate(addr, FALSE);
nkeynes@934
    64
    memcpy( dest, (pvr2_main_ram + (addr&0x007FFFFF)), 32 );
nkeynes@929
    65
}
nkeynes@929
    66
static void FASTCALL pvr2_vram32_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@929
    67
{
nkeynes@929
    68
    // Render buffers pretty much have to be (at least) 32-byte aligned
nkeynes@929
    69
    pvr2_render_buffer_invalidate(addr, TRUE);
nkeynes@934
    70
    memcpy( (pvr2_main_ram + (addr&0x007FFFFF)), src, 32 );    
nkeynes@929
    71
}
nkeynes@929
    72
nkeynes@929
    73
struct mem_region_fn mem_region_vram32 = { pvr2_vram32_read_long, pvr2_vram32_write_long, 
nkeynes@929
    74
        pvr2_vram32_read_word, pvr2_vram32_write_word, 
nkeynes@929
    75
        pvr2_vram32_read_byte, pvr2_vram32_write_byte, 
nkeynes@929
    76
        pvr2_vram32_read_burst, pvr2_vram32_write_burst }; 
nkeynes@929
    77
nkeynes@929
    78
/************************* VRAM64 address space ***************************/
nkeynes@929
    79
nkeynes@929
    80
#define TRANSLATE_VIDEO_64BIT_ADDRESS(a)  ( (((a)&0x00FFFFF8)>>1)|(((a)&0x00000004)<<20)|((a)&0x03) )
nkeynes@929
    81
nkeynes@929
    82
static int32_t FASTCALL pvr2_vram64_read_long( sh4addr_t addr )
nkeynes@929
    83
{
nkeynes@929
    84
    addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
nkeynes@929
    85
    pvr2_render_buffer_invalidate(addr, FALSE);
nkeynes@934
    86
    return *((int32_t *)(pvr2_main_ram+(addr&0x007FFFFF)));
nkeynes@929
    87
}
nkeynes@929
    88
static int32_t FASTCALL pvr2_vram64_read_word( sh4addr_t addr )
nkeynes@929
    89
{
nkeynes@929
    90
    addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
nkeynes@929
    91
    pvr2_render_buffer_invalidate(addr, FALSE);
nkeynes@934
    92
    return SIGNEXT16(*((int16_t *)(pvr2_main_ram+(addr&0x007FFFFF))));
nkeynes@929
    93
}
nkeynes@929
    94
static int32_t FASTCALL pvr2_vram64_read_byte( sh4addr_t addr )
nkeynes@929
    95
{
nkeynes@929
    96
    addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
nkeynes@929
    97
    pvr2_render_buffer_invalidate(addr, FALSE);
nkeynes@934
    98
    return SIGNEXT8(*((int8_t *)(pvr2_main_ram+(addr&0x007FFFFF))));
nkeynes@929
    99
}
nkeynes@929
   100
static void FASTCALL pvr2_vram64_write_long( sh4addr_t addr, uint32_t val )
nkeynes@929
   101
{
nkeynes@929
   102
    texcache_invalidate_page(addr& 0x007FFFFF);
nkeynes@929
   103
    addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
nkeynes@929
   104
    pvr2_render_buffer_invalidate(addr, TRUE);
nkeynes@934
   105
    *(uint32_t *)(pvr2_main_ram + (addr&0x007FFFFF)) = val;
nkeynes@929
   106
}
nkeynes@929
   107
static void FASTCALL pvr2_vram64_write_word( sh4addr_t addr, uint32_t val )
nkeynes@929
   108
{
nkeynes@929
   109
    texcache_invalidate_page(addr& 0x007FFFFF);
nkeynes@929
   110
    addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
nkeynes@929
   111
    pvr2_render_buffer_invalidate(addr, TRUE);
nkeynes@934
   112
    *(uint16_t *)(pvr2_main_ram + (addr&0x007FFFFF)) = (uint16_t)val;
nkeynes@929
   113
}
nkeynes@929
   114
static void FASTCALL pvr2_vram64_write_byte( sh4addr_t addr, uint32_t val )
nkeynes@929
   115
{
nkeynes@929
   116
    texcache_invalidate_page(addr& 0x007FFFFF);
nkeynes@929
   117
    addr = TRANSLATE_VIDEO_64BIT_ADDRESS(addr);
nkeynes@929
   118
    pvr2_render_buffer_invalidate(addr, TRUE);
nkeynes@934
   119
    *(uint8_t *)(pvr2_main_ram + (addr&0x007FFFFF)) = (uint8_t)val;
nkeynes@929
   120
}
nkeynes@929
   121
static void FASTCALL pvr2_vram64_read_burst( unsigned char *dest, sh4addr_t addr )
nkeynes@929
   122
{
nkeynes@929
   123
    pvr2_vram64_read( dest, addr, 32 );
nkeynes@929
   124
}
nkeynes@929
   125
static void FASTCALL pvr2_vram64_write_burst( sh4addr_t addr, unsigned char *src )
nkeynes@929
   126
{
nkeynes@929
   127
    pvr2_vram64_write( addr, src, 32 );
nkeynes@929
   128
}
nkeynes@929
   129
nkeynes@929
   130
struct mem_region_fn mem_region_vram64 = { pvr2_vram64_read_long, pvr2_vram64_write_long, 
nkeynes@929
   131
        pvr2_vram64_read_word, pvr2_vram64_write_word, 
nkeynes@929
   132
        pvr2_vram64_read_byte, pvr2_vram64_write_byte, 
nkeynes@929
   133
        pvr2_vram64_read_burst, pvr2_vram64_write_burst }; 
nkeynes@929
   134
nkeynes@931
   135
/******************************* Burst areas ******************************/
nkeynes@931
   136
nkeynes@931
   137
static void FASTCALL pvr2_vramdma1_write_burst( sh4addr_t destaddr, unsigned char *src )
nkeynes@931
   138
{
nkeynes@931
   139
    int region = MMIO_READ( ASIC, PVRDMARGN1 );
nkeynes@931
   140
    if( region == 0 ) {
nkeynes@931
   141
        pvr2_vram64_write( destaddr, src, 32 );
nkeynes@931
   142
    } else {
nkeynes@931
   143
        destaddr &= PVR2_RAM_MASK;
nkeynes@934
   144
        unsigned char *dest = pvr2_main_ram + destaddr;
nkeynes@931
   145
        memcpy( dest, src, 32 );
nkeynes@931
   146
    }   
nkeynes@931
   147
}
nkeynes@931
   148
nkeynes@931
   149
static void FASTCALL pvr2_vramdma2_write_burst( sh4addr_t destaddr, unsigned char *src )
nkeynes@931
   150
{
nkeynes@931
   151
    int region = MMIO_READ( ASIC, PVRDMARGN2 );
nkeynes@931
   152
    if( region == 0 ) {
nkeynes@931
   153
        pvr2_vram64_write( destaddr, src, 32 );
nkeynes@931
   154
    } else {
nkeynes@931
   155
        destaddr &= PVR2_RAM_MASK;
nkeynes@934
   156
        unsigned char *dest = pvr2_main_ram + destaddr;
nkeynes@931
   157
        memcpy( dest, src, 32 );
nkeynes@931
   158
    }
nkeynes@931
   159
}
nkeynes@931
   160
nkeynes@931
   161
static void FASTCALL pvr2_yuv_write_burst( sh4addr_t destaddr, unsigned char *src )
nkeynes@931
   162
{
nkeynes@931
   163
    pvr2_yuv_write( src, 32 );
nkeynes@931
   164
}
nkeynes@931
   165
nkeynes@931
   166
struct mem_region_fn mem_region_pvr2ta = {
nkeynes@931
   167
        unmapped_read_long, unmapped_write_long,
nkeynes@931
   168
        unmapped_read_long, unmapped_write_long,
nkeynes@931
   169
        unmapped_read_long, unmapped_write_long,
nkeynes@931
   170
        unmapped_read_burst, pvr2_ta_write_burst };
nkeynes@931
   171
nkeynes@931
   172
struct mem_region_fn mem_region_pvr2yuv = {
nkeynes@931
   173
        unmapped_read_long, unmapped_write_long,
nkeynes@931
   174
        unmapped_read_long, unmapped_write_long,
nkeynes@931
   175
        unmapped_read_long, unmapped_write_long,
nkeynes@931
   176
        unmapped_read_burst, pvr2_yuv_write_burst };
nkeynes@931
   177
nkeynes@931
   178
struct mem_region_fn mem_region_pvr2vdma1 = {
nkeynes@931
   179
        unmapped_read_long, unmapped_write_long,
nkeynes@931
   180
        unmapped_read_long, unmapped_write_long,
nkeynes@931
   181
        unmapped_read_long, unmapped_write_long,
nkeynes@931
   182
        unmapped_read_burst, pvr2_vramdma1_write_burst };
nkeynes@931
   183
nkeynes@931
   184
struct mem_region_fn mem_region_pvr2vdma2 = {
nkeynes@931
   185
        unmapped_read_long, unmapped_write_long,
nkeynes@931
   186
        unmapped_read_long, unmapped_write_long,
nkeynes@931
   187
        unmapped_read_long, unmapped_write_long,
nkeynes@931
   188
        unmapped_read_burst, pvr2_vramdma2_write_burst };
nkeynes@929
   189
nkeynes@929
   190
nkeynes@429
   191
void pvr2_dma_write( sh4addr_t destaddr, unsigned char *src, uint32_t count )
nkeynes@325
   192
{
nkeynes@325
   193
    int region;
nkeynes@325
   194
nkeynes@325
   195
    switch( destaddr & 0x13800000 ) {
nkeynes@325
   196
    case 0x10000000:
nkeynes@325
   197
    case 0x12000000:
nkeynes@736
   198
        pvr2_ta_write( src, count );
nkeynes@736
   199
        break;
nkeynes@325
   200
    case 0x11000000:
nkeynes@325
   201
    case 0x11800000:
nkeynes@736
   202
        region = MMIO_READ( ASIC, PVRDMARGN1 );
nkeynes@736
   203
        if( region == 0 ) {
nkeynes@736
   204
            pvr2_vram64_write( destaddr, src, count );
nkeynes@736
   205
        } else {
nkeynes@834
   206
            destaddr &= PVR2_RAM_MASK;
nkeynes@934
   207
            unsigned char *dest = pvr2_main_ram + destaddr;
nkeynes@834
   208
            if( PVR2_RAM_SIZE - destaddr < count ) {
nkeynes@834
   209
                count = PVR2_RAM_SIZE - destaddr;
nkeynes@834
   210
            }
nkeynes@736
   211
            memcpy( dest, src, count );
nkeynes@736
   212
        }
nkeynes@736
   213
        break;
nkeynes@325
   214
    case 0x10800000:
nkeynes@325
   215
    case 0x12800000:
nkeynes@736
   216
        pvr2_yuv_write( src, count );
nkeynes@736
   217
        break;
nkeynes@325
   218
    case 0x13000000:
nkeynes@325
   219
    case 0x13800000:
nkeynes@736
   220
        region = MMIO_READ( ASIC, PVRDMARGN2 );
nkeynes@736
   221
        if( region == 0 ) {
nkeynes@736
   222
            pvr2_vram64_write( destaddr, src, count );
nkeynes@736
   223
        } else {
nkeynes@834
   224
            destaddr &= PVR2_RAM_MASK;
nkeynes@934
   225
            unsigned char *dest = pvr2_main_ram + destaddr;
nkeynes@834
   226
            if( PVR2_RAM_SIZE - destaddr < count ) {
nkeynes@834
   227
                count = PVR2_RAM_SIZE - destaddr;
nkeynes@834
   228
            }
nkeynes@736
   229
            memcpy( dest, src, count );
nkeynes@736
   230
        }
nkeynes@827
   231
    }
nkeynes@325
   232
}
nkeynes@325
   233
nkeynes@429
   234
void pvr2_vram64_write( sh4addr_t destaddr, unsigned char *src, uint32_t length )
nkeynes@284
   235
{
nkeynes@284
   236
    int bank_flag = (destaddr & 0x04) >> 2;
nkeynes@284
   237
    uint32_t *banks[2];
nkeynes@284
   238
    uint32_t *dwsrc;
nkeynes@284
   239
    int i;
nkeynes@284
   240
nkeynes@284
   241
    destaddr = destaddr & 0x7FFFFF;
nkeynes@284
   242
    if( destaddr + length > 0x800000 ) {
nkeynes@736
   243
        length = 0x800000 - destaddr;
nkeynes@284
   244
    }
nkeynes@284
   245
nkeynes@796
   246
    for( i=destaddr & 0xFFFFF000; i < destaddr + length; i+= LXDREAM_PAGE_SIZE ) {
nkeynes@736
   247
        texcache_invalidate_page( i );
nkeynes@284
   248
    }
nkeynes@284
   249
nkeynes@934
   250
    banks[0] = ((uint32_t *)(pvr2_main_ram + ((destaddr & 0x007FFFF8) >>1)));
nkeynes@284
   251
    banks[1] = banks[0] + 0x100000;
nkeynes@827
   252
    if( bank_flag )
nkeynes@736
   253
        banks[0]++;
nkeynes@736
   254
nkeynes@284
   255
    /* Handle non-aligned start of source */
nkeynes@284
   256
    if( destaddr & 0x03 ) {
nkeynes@736
   257
        unsigned char *dest = ((unsigned char *)banks[bank_flag]) + (destaddr & 0x03);
nkeynes@736
   258
        for( i= destaddr & 0x03; i < 4 && length > 0; i++, length-- ) {
nkeynes@736
   259
            *dest++ = *src++;
nkeynes@736
   260
        }
nkeynes@736
   261
        bank_flag = !bank_flag;
nkeynes@284
   262
    }
nkeynes@284
   263
nkeynes@284
   264
    dwsrc = (uint32_t *)src;
nkeynes@284
   265
    while( length >= 4 ) {
nkeynes@736
   266
        *banks[bank_flag]++ = *dwsrc++;
nkeynes@736
   267
        bank_flag = !bank_flag;
nkeynes@736
   268
        length -= 4;
nkeynes@284
   269
    }
nkeynes@736
   270
nkeynes@284
   271
    /* Handle non-aligned end of source */
nkeynes@284
   272
    if( length ) {
nkeynes@736
   273
        src = (unsigned char *)dwsrc;
nkeynes@736
   274
        unsigned char *dest = (unsigned char *)banks[bank_flag];
nkeynes@736
   275
        while( length-- > 0 ) {
nkeynes@736
   276
            *dest++ = *src++;
nkeynes@736
   277
        }
nkeynes@827
   278
    }
nkeynes@284
   279
}
nkeynes@284
   280
nkeynes@284
   281
/**
nkeynes@284
   282
 * Write an image to 64-bit vram, with a line-stride different from the line-size.
nkeynes@869
   283
 * The destaddr must be 64-bit aligned, and both line_bytes and line_stride_bytes
nkeynes@869
   284
 * must be multiples of 8.
nkeynes@284
   285
 */
nkeynes@827
   286
void pvr2_vram64_write_stride( sh4addr_t destaddr, unsigned char *src, uint32_t line_bytes,
nkeynes@736
   287
                               uint32_t line_stride_bytes, uint32_t line_count )
nkeynes@284
   288
{
nkeynes@869
   289
    int i,j;
nkeynes@284
   290
    uint32_t *banks[2];
nkeynes@869
   291
    uint32_t *dwsrc = (uint32_t *)src;
nkeynes@869
   292
    uint32_t line_gap = (line_stride_bytes - line_bytes) >> 3;
nkeynes@284
   293
nkeynes@284
   294
    destaddr = destaddr & 0x7FFFF8;
nkeynes@869
   295
    line_bytes >>= 3;
nkeynes@284
   296
nkeynes@869
   297
    for( i=destaddr; i < destaddr + line_stride_bytes*line_count; i+= LXDREAM_PAGE_SIZE ) {
nkeynes@736
   298
        texcache_invalidate_page( i );
nkeynes@284
   299
    }
nkeynes@284
   300
nkeynes@934
   301
    banks[0] = (uint32_t *)(pvr2_main_ram + (destaddr >>1));
nkeynes@284
   302
    banks[1] = banks[0] + 0x100000;
nkeynes@736
   303
nkeynes@284
   304
    for( i=0; i<line_count; i++ ) {
nkeynes@736
   305
        for( j=0; j<line_bytes; j++ ) {
nkeynes@869
   306
            *banks[0]++ = *dwsrc++;
nkeynes@869
   307
            *banks[1]++ = *dwsrc++;
nkeynes@736
   308
        }
nkeynes@736
   309
        banks[0] += line_gap;
nkeynes@736
   310
        banks[1] += line_gap;
nkeynes@827
   311
    }
nkeynes@284
   312
}
nkeynes@284
   313
nkeynes@284
   314
/**
nkeynes@284
   315
 * Read an image from 64-bit vram, with a destination line-stride different from the line-size.
nkeynes@284
   316
 * The srcaddr must be 32-bit aligned, and both line_bytes and line_stride_bytes
nkeynes@284
   317
 * must be multiples of 4. line_stride_bytes must be >= line_bytes.
nkeynes@284
   318
 * This method is used to extract a "stride" texture from vram.
nkeynes@284
   319
 */
nkeynes@429
   320
void pvr2_vram64_read_stride( unsigned char *dest, uint32_t dest_line_bytes, sh4addr_t srcaddr,
nkeynes@736
   321
                              uint32_t src_line_bytes, uint32_t line_count )
nkeynes@284
   322
{
nkeynes@284
   323
    int bank_flag = (srcaddr & 0x04) >> 2;
nkeynes@284
   324
    uint32_t *banks[2];
nkeynes@284
   325
    uint32_t *dwdest;
nkeynes@429
   326
    uint32_t dest_line_gap = 0;
nkeynes@429
   327
    uint32_t src_line_gap = 0;
nkeynes@284
   328
    uint32_t line_bytes;
nkeynes@284
   329
    int src_line_gap_flag;
nkeynes@284
   330
    int i,j;
nkeynes@284
   331
nkeynes@284
   332
    srcaddr = srcaddr & 0x7FFFF8;
nkeynes@284
   333
    if( src_line_bytes <= dest_line_bytes ) {
nkeynes@736
   334
        dest_line_gap = (dest_line_bytes - src_line_bytes) >> 2;
nkeynes@736
   335
        src_line_gap = 0;
nkeynes@736
   336
        src_line_gap_flag = 0;
nkeynes@736
   337
        line_bytes = src_line_bytes >> 2;
nkeynes@284
   338
    } else {
nkeynes@736
   339
        i = (src_line_bytes - dest_line_bytes);
nkeynes@736
   340
        src_line_gap_flag = i & 0x04;
nkeynes@736
   341
        src_line_gap = i >> 3;
nkeynes@736
   342
        line_bytes = dest_line_bytes >> 2;
nkeynes@284
   343
    }
nkeynes@736
   344
nkeynes@934
   345
    banks[0] = (uint32_t *)(pvr2_main_ram + (srcaddr>>1));
nkeynes@284
   346
    banks[1] = banks[0] + 0x100000;
nkeynes@284
   347
    if( bank_flag )
nkeynes@736
   348
        banks[0]++;
nkeynes@736
   349
nkeynes@284
   350
    dwdest = (uint32_t *)dest;
nkeynes@284
   351
    for( i=0; i<line_count; i++ ) {
nkeynes@736
   352
        for( j=0; j<line_bytes; j++ ) {
nkeynes@736
   353
            *dwdest++ = *banks[bank_flag]++;
nkeynes@736
   354
            bank_flag = !bank_flag;
nkeynes@736
   355
        }
nkeynes@736
   356
        dwdest += dest_line_gap;
nkeynes@736
   357
        banks[0] += src_line_gap;
nkeynes@736
   358
        banks[1] += src_line_gap;
nkeynes@736
   359
        if( src_line_gap_flag ) {
nkeynes@736
   360
            banks[bank_flag]++;
nkeynes@736
   361
            bank_flag = !bank_flag;
nkeynes@736
   362
        }
nkeynes@827
   363
    }
nkeynes@310
   364
}
nkeynes@310
   365
nkeynes@315
   366
nkeynes@310
   367
/**
nkeynes@310
   368
 * @param dest Destination image buffer
nkeynes@310
   369
 * @param banks Source data expressed as two bank pointers
nkeynes@310
   370
 * @param offset Offset into banks[0] specifying where the next byte
nkeynes@310
   371
 *  to read is (0..3)
nkeynes@310
   372
 * @param x1,y1 Destination coordinates
nkeynes@310
   373
 * @param width Width of current destination block
nkeynes@315
   374
 * @param stride Total width of image (ie stride) in bytes
nkeynes@315
   375
 */
nkeynes@315
   376
nkeynes@315
   377
static void pvr2_vram64_detwiddle_4( uint8_t *dest, uint8_t *banks[2], int offset,
nkeynes@736
   378
                                     int x1, int y1, int width, int stride )
nkeynes@315
   379
{
nkeynes@315
   380
    if( width == 2 ) {
nkeynes@736
   381
        x1 = x1 >> 1;
nkeynes@736
   382
        uint8_t t1 = *banks[offset<4?0:1]++;
nkeynes@736
   383
        uint8_t t2 = *banks[offset<3?0:1]++;
nkeynes@736
   384
        dest[y1*stride + x1] = (t1 & 0x0F) | (t2<<4);
nkeynes@736
   385
        dest[(y1+1)*stride + x1] = (t1>>4) | (t2&0xF0);
nkeynes@315
   386
    } else if( width == 4 ) {
nkeynes@736
   387
        pvr2_vram64_detwiddle_4( dest, banks, offset, x1, y1, 2, stride );
nkeynes@736
   388
        pvr2_vram64_detwiddle_4( dest, banks, offset+2, x1, y1+2, 2, stride );
nkeynes@736
   389
        pvr2_vram64_detwiddle_4( dest, banks, offset+4, x1+2, y1, 2, stride );
nkeynes@736
   390
        pvr2_vram64_detwiddle_4( dest, banks, offset+6, x1+2, y1+2, 2, stride );
nkeynes@736
   391
nkeynes@315
   392
    } else {
nkeynes@736
   393
        int subdivide = width >> 1;
nkeynes@736
   394
        pvr2_vram64_detwiddle_4( dest, banks, offset, x1, y1, subdivide, stride );
nkeynes@736
   395
        pvr2_vram64_detwiddle_4( dest, banks, offset, x1, y1+subdivide, subdivide, stride );
nkeynes@736
   396
        pvr2_vram64_detwiddle_4( dest, banks, offset, x1+subdivide, y1, subdivide, stride );
nkeynes@736
   397
        pvr2_vram64_detwiddle_4( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, stride );
nkeynes@315
   398
    }
nkeynes@315
   399
}
nkeynes@315
   400
nkeynes@315
   401
/**
nkeynes@315
   402
 * @param dest Destination image buffer
nkeynes@315
   403
 * @param banks Source data expressed as two bank pointers
nkeynes@315
   404
 * @param offset Offset into banks[0] specifying where the next byte
nkeynes@315
   405
 *  to read is (0..3)
nkeynes@315
   406
 * @param x1,y1 Destination coordinates
nkeynes@315
   407
 * @param width Width of current destination block
nkeynes@315
   408
 * @param stride Total width of image (ie stride)
nkeynes@310
   409
 */
nkeynes@310
   410
nkeynes@310
   411
static void pvr2_vram64_detwiddle_8( uint8_t *dest, uint8_t *banks[2], int offset,
nkeynes@736
   412
                                     int x1, int y1, int width, int stride )
nkeynes@310
   413
{
nkeynes@310
   414
    if( width == 2 ) {
nkeynes@736
   415
        dest[y1*stride + x1] = *banks[0]++;
nkeynes@736
   416
        dest[(y1+1)*stride + x1] = *banks[offset<3?0:1]++;
nkeynes@736
   417
        dest[y1*stride + x1 + 1] = *banks[offset<2?0:1]++;
nkeynes@736
   418
        dest[(y1+1)*stride + x1 + 1] = *banks[offset==0?0:1]++;
nkeynes@736
   419
        uint8_t *tmp = banks[0]; /* swap banks */
nkeynes@736
   420
        banks[0] = banks[1];
nkeynes@736
   421
        banks[1] = tmp;
nkeynes@310
   422
    } else {
nkeynes@736
   423
        int subdivide = width >> 1;
nkeynes@736
   424
        pvr2_vram64_detwiddle_8( dest, banks, offset, x1, y1, subdivide, stride );
nkeynes@736
   425
        pvr2_vram64_detwiddle_8( dest, banks, offset, x1, y1+subdivide, subdivide, stride );
nkeynes@736
   426
        pvr2_vram64_detwiddle_8( dest, banks, offset, x1+subdivide, y1, subdivide, stride );
nkeynes@736
   427
        pvr2_vram64_detwiddle_8( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, stride );
nkeynes@284
   428
    }
nkeynes@310
   429
}
nkeynes@310
   430
nkeynes@310
   431
/**
nkeynes@310
   432
 * @param dest Destination image buffer
nkeynes@310
   433
 * @param banks Source data expressed as two bank pointers
nkeynes@310
   434
 * @param offset Offset into banks[0] specifying where the next word
nkeynes@310
   435
 *  to read is (0 or 1)
nkeynes@310
   436
 * @param x1,y1 Destination coordinates
nkeynes@310
   437
 * @param width Width of current destination block
nkeynes@315
   438
 * @param stride Total width of image (ie stride)
nkeynes@310
   439
 */
nkeynes@310
   440
nkeynes@310
   441
static void pvr2_vram64_detwiddle_16( uint16_t *dest, uint16_t *banks[2], int offset,
nkeynes@736
   442
                                      int x1, int y1, int width, int stride )
nkeynes@310
   443
{
nkeynes@310
   444
    if( width == 2 ) {
nkeynes@736
   445
        dest[y1*stride + x1] = *banks[0]++;
nkeynes@736
   446
        dest[(y1+1)*stride + x1] = *banks[offset]++;
nkeynes@736
   447
        dest[y1*stride + x1 + 1] = *banks[1]++;
nkeynes@736
   448
        dest[(y1+1)*stride + x1 + 1] = *banks[offset^1]++;
nkeynes@310
   449
    } else {
nkeynes@736
   450
        int subdivide = width >> 1;
nkeynes@736
   451
        pvr2_vram64_detwiddle_16( dest, banks, offset, x1, y1, subdivide, stride );
nkeynes@736
   452
        pvr2_vram64_detwiddle_16( dest, banks, offset, x1, y1+subdivide, subdivide, stride );
nkeynes@736
   453
        pvr2_vram64_detwiddle_16( dest, banks, offset, x1+subdivide, y1, subdivide, stride );
nkeynes@736
   454
        pvr2_vram64_detwiddle_16( dest, banks, offset, x1+subdivide, y1+subdivide, subdivide, stride );
nkeynes@310
   455
    }
nkeynes@310
   456
}
nkeynes@310
   457
nkeynes@310
   458
/**
nkeynes@827
   459
 * Read an image from 64-bit vram stored as twiddled 4-bit pixels. The
nkeynes@315
   460
 * image is written out to the destination in detwiddled form.
nkeynes@315
   461
 * @param dest destination buffer, which must be at least width*height/2 in length
nkeynes@315
   462
 * @param srcaddr source address in vram
nkeynes@315
   463
 * @param width image width (must be a power of 2)
nkeynes@315
   464
 * @param height image height (must be a power of 2)
nkeynes@315
   465
 */
nkeynes@429
   466
void pvr2_vram64_read_twiddled_4( unsigned char *dest, sh4addr_t srcaddr, uint32_t width, uint32_t height )
nkeynes@315
   467
{
nkeynes@315
   468
    int offset_flag = (srcaddr & 0x07);
nkeynes@315
   469
    uint8_t *banks[2];
nkeynes@315
   470
    uint8_t *wdest = (uint8_t*)dest;
nkeynes@315
   471
    uint32_t stride = width >> 1;
nkeynes@429
   472
    int i;
nkeynes@315
   473
nkeynes@315
   474
    srcaddr = srcaddr & 0x7FFFF8;
nkeynes@315
   475
nkeynes@934
   476
    banks[0] = (uint8_t *)(pvr2_main_ram + (srcaddr>>1));
nkeynes@315
   477
    banks[1] = banks[0] + 0x400000;
nkeynes@315
   478
    if( offset_flag & 0x04 ) { // If source is not 64-bit aligned, swap the banks
nkeynes@736
   479
        uint8_t *tmp = banks[0];
nkeynes@736
   480
        banks[0] = banks[1];
nkeynes@736
   481
        banks[1] = tmp + 4;
nkeynes@736
   482
        offset_flag &= 0x03;
nkeynes@315
   483
    }
nkeynes@315
   484
    banks[0] += offset_flag;
nkeynes@315
   485
nkeynes@315
   486
    if( width > height ) {
nkeynes@736
   487
        for( i=0; i<width; i+=height ) {
nkeynes@736
   488
            pvr2_vram64_detwiddle_4( wdest, banks, offset_flag, i, 0, height, stride );
nkeynes@736
   489
        }
nkeynes@315
   490
    } else if( height > width ) {
nkeynes@736
   491
        for( i=0; i<height; i+=width ) {
nkeynes@736
   492
            pvr2_vram64_detwiddle_4( wdest, banks, offset_flag, 0, i, width, stride );
nkeynes@736
   493
        }
nkeynes@315
   494
    } else if( width == 1 ) {
nkeynes@736
   495
        *wdest = *banks[0];
nkeynes@315
   496
    } else {
nkeynes@736
   497
        pvr2_vram64_detwiddle_4( wdest, banks, offset_flag, 0, 0, width, stride );
nkeynes@827
   498
    }
nkeynes@315
   499
}
nkeynes@315
   500
nkeynes@315
   501
/**
nkeynes@827
   502
 * Read an image from 64-bit vram stored as twiddled 8-bit pixels. The
nkeynes@310
   503
 * image is written out to the destination in detwiddled form.
nkeynes@310
   504
 * @param dest destination buffer, which must be at least width*height in length
nkeynes@310
   505
 * @param srcaddr source address in vram
nkeynes@310
   506
 * @param width image width (must be a power of 2)
nkeynes@310
   507
 * @param height image height (must be a power of 2)
nkeynes@310
   508
 */
nkeynes@429
   509
void pvr2_vram64_read_twiddled_8( unsigned char *dest, sh4addr_t srcaddr, uint32_t width, uint32_t height )
nkeynes@310
   510
{
nkeynes@310
   511
    int offset_flag = (srcaddr & 0x07);
nkeynes@310
   512
    uint8_t *banks[2];
nkeynes@310
   513
    uint8_t *wdest = (uint8_t*)dest;
nkeynes@429
   514
    int i;
nkeynes@310
   515
nkeynes@310
   516
    srcaddr = srcaddr & 0x7FFFF8;
nkeynes@310
   517
nkeynes@934
   518
    banks[0] = (uint8_t *)(pvr2_main_ram + (srcaddr>>1));
nkeynes@310
   519
    banks[1] = banks[0] + 0x400000;
nkeynes@310
   520
    if( offset_flag & 0x04 ) { // If source is not 64-bit aligned, swap the banks
nkeynes@736
   521
        uint8_t *tmp = banks[0];
nkeynes@736
   522
        banks[0] = banks[1];
nkeynes@736
   523
        banks[1] = tmp + 4;
nkeynes@736
   524
        offset_flag &= 0x03;
nkeynes@310
   525
    }
nkeynes@310
   526
    banks[0] += offset_flag;
nkeynes@310
   527
nkeynes@310
   528
    if( width > height ) {
nkeynes@736
   529
        for( i=0; i<width; i+=height ) {
nkeynes@736
   530
            pvr2_vram64_detwiddle_8( wdest, banks, offset_flag, i, 0, height, width );
nkeynes@736
   531
        }
nkeynes@310
   532
    } else if( height > width ) {
nkeynes@736
   533
        for( i=0; i<height; i+=width ) {
nkeynes@736
   534
            pvr2_vram64_detwiddle_8( wdest, banks, offset_flag, 0, i, width, width );
nkeynes@736
   535
        }
nkeynes@310
   536
    } else if( width == 1 ) {
nkeynes@736
   537
        *wdest = *banks[0];
nkeynes@310
   538
    } else {
nkeynes@736
   539
        pvr2_vram64_detwiddle_8( wdest, banks, offset_flag, 0, 0, width, width );
nkeynes@827
   540
    }
nkeynes@310
   541
}
nkeynes@310
   542
nkeynes@310
   543
/**
nkeynes@827
   544
 * Read an image from 64-bit vram stored as twiddled 16-bit pixels. The
nkeynes@310
   545
 * image is written out to the destination in detwiddled form.
nkeynes@310
   546
 * @param dest destination buffer, which must be at least width*height*2 in length
nkeynes@310
   547
 * @param srcaddr source address in vram (must be 16-bit aligned)
nkeynes@310
   548
 * @param width image width (must be a power of 2)
nkeynes@310
   549
 * @param height image height (must be a power of 2)
nkeynes@310
   550
 */
nkeynes@429
   551
void pvr2_vram64_read_twiddled_16( unsigned char *dest, sh4addr_t srcaddr, uint32_t width, uint32_t height ) {
nkeynes@310
   552
    int offset_flag = (srcaddr & 0x06) >> 1;
nkeynes@310
   553
    uint16_t *banks[2];
nkeynes@310
   554
    uint16_t *wdest = (uint16_t*)dest;
nkeynes@429
   555
    int i;
nkeynes@310
   556
nkeynes@310
   557
    srcaddr = srcaddr & 0x7FFFF8;
nkeynes@310
   558
nkeynes@934
   559
    banks[0] = (uint16_t *)(pvr2_main_ram + (srcaddr>>1));
nkeynes@310
   560
    banks[1] = banks[0] + 0x200000;
nkeynes@310
   561
    if( offset_flag & 0x02 ) { // If source is not 64-bit aligned, swap the banks
nkeynes@736
   562
        uint16_t *tmp = banks[0];
nkeynes@736
   563
        banks[0] = banks[1];
nkeynes@736
   564
        banks[1] = tmp + 2;
nkeynes@736
   565
        offset_flag &= 0x01;
nkeynes@310
   566
    }
nkeynes@310
   567
    banks[0] += offset_flag;
nkeynes@736
   568
nkeynes@310
   569
nkeynes@310
   570
    if( width > height ) {
nkeynes@736
   571
        for( i=0; i<width; i+=height ) {
nkeynes@736
   572
            pvr2_vram64_detwiddle_16( wdest, banks, offset_flag, i, 0, height, width );
nkeynes@736
   573
        }
nkeynes@310
   574
    } else if( height > width ) {
nkeynes@736
   575
        for( i=0; i<height; i+=width ) {
nkeynes@736
   576
            pvr2_vram64_detwiddle_16( wdest, banks, offset_flag, 0, i, width, width );
nkeynes@736
   577
        }
nkeynes@310
   578
    } else if( width == 1 ) {
nkeynes@736
   579
        *wdest = *banks[0];
nkeynes@310
   580
    } else {
nkeynes@736
   581
        pvr2_vram64_detwiddle_16( wdest, banks, offset_flag, 0, 0, width, width );
nkeynes@827
   582
    }
nkeynes@284
   583
}
nkeynes@284
   584
nkeynes@857
   585
static void pvr2_vram_write_invert( sh4addr_t destaddr, unsigned char *src, uint32_t src_size, 
nkeynes@857
   586
                             uint32_t line_size, uint32_t dest_stride,
nkeynes@736
   587
                             uint32_t src_stride )
nkeynes@284
   588
{
nkeynes@934
   589
    unsigned char *dest = pvr2_main_ram + (destaddr & 0x007FFFFF);
nkeynes@857
   590
    unsigned char *p = src + src_size - src_stride;
nkeynes@284
   591
    while( p >= src ) {
nkeynes@857
   592
        memcpy( dest, p, line_size );
nkeynes@736
   593
        p -= src_stride;
nkeynes@857
   594
        dest += dest_stride;
nkeynes@857
   595
    }
nkeynes@857
   596
}
nkeynes@857
   597
nkeynes@869
   598
static void pvr2_vram64_write_invert( sh4addr_t destaddr, unsigned char *src, 
nkeynes@869
   599
                                      uint32_t src_size, uint32_t line_size, 
nkeynes@869
   600
                                      uint32_t dest_stride, uint32_t src_stride )
nkeynes@869
   601
{
nkeynes@869
   602
    int i,j;
nkeynes@869
   603
    uint32_t *banks[2];
nkeynes@869
   604
    uint32_t *dwsrc = (uint32_t *)(src + src_size - src_stride);
nkeynes@869
   605
    int32_t src_line_gap = ((int32_t)src_stride + line_size) >> 2; 
nkeynes@869
   606
    int32_t dest_line_gap = ((int32_t)dest_stride - (int32_t)line_size) >> 3;
nkeynes@869
   607
nkeynes@869
   608
    destaddr = destaddr & 0x7FFFF8;
nkeynes@869
   609
nkeynes@869
   610
    for( i=destaddr; i < destaddr + dest_stride*(src_size/src_stride); i+= LXDREAM_PAGE_SIZE ) {
nkeynes@869
   611
        texcache_invalidate_page( i );
nkeynes@869
   612
    }
nkeynes@869
   613
nkeynes@934
   614
    banks[0] = (uint32_t *)(pvr2_main_ram + (destaddr >>1));
nkeynes@869
   615
    banks[1] = banks[0] + 0x100000;
nkeynes@869
   616
nkeynes@869
   617
    while( dwsrc >= (uint32_t *)src ) { 
nkeynes@869
   618
        for( j=0; j<line_size; j+=8 ) {
nkeynes@869
   619
            *banks[0]++ = *dwsrc++;
nkeynes@869
   620
            *banks[1]++ = *dwsrc++;
nkeynes@869
   621
        }
nkeynes@869
   622
        banks[0] += dest_line_gap;
nkeynes@869
   623
        banks[1] += dest_line_gap;
nkeynes@869
   624
        dwsrc -= src_line_gap;
nkeynes@869
   625
    }    
nkeynes@869
   626
}
nkeynes@869
   627
nkeynes@857
   628
/**
nkeynes@857
   629
 * Copy a pixel buffer to vram, flipping and scaling at the same time. This
nkeynes@857
   630
 * is not massively efficient, but it's used pretty rarely.
nkeynes@857
   631
 */
nkeynes@857
   632
static void pvr2_vram_write_invert_hscale( sh4addr_t destaddr, unsigned char *src, uint32_t src_size, 
nkeynes@857
   633
                             uint32_t line_size, uint32_t dest_stride,
nkeynes@857
   634
                             uint32_t src_stride, int bpp )
nkeynes@857
   635
{
nkeynes@934
   636
    unsigned char *dest = pvr2_main_ram + (destaddr & 0x007FFFFF);
nkeynes@857
   637
    unsigned char *p = src + src_size - src_stride;
nkeynes@857
   638
    while( p >= src ) {
nkeynes@857
   639
        unsigned char *s = p, *d = dest;
nkeynes@857
   640
        int i;
nkeynes@857
   641
        while( s < p+line_size ) {
nkeynes@857
   642
            for( i=0; i<bpp; i++ ) {
nkeynes@857
   643
                *d++ = *s++;
nkeynes@857
   644
            }
nkeynes@857
   645
            s+= bpp;
nkeynes@857
   646
        }
nkeynes@857
   647
        p -= src_stride;
nkeynes@857
   648
        dest += dest_stride;
nkeynes@284
   649
    }
nkeynes@284
   650
}
nkeynes@284
   651
nkeynes@429
   652
void pvr2_vram64_read( unsigned char *dest, sh4addr_t srcaddr, uint32_t length )
nkeynes@284
   653
{
nkeynes@284
   654
    int bank_flag = (srcaddr & 0x04) >> 2;
nkeynes@284
   655
    uint32_t *banks[2];
nkeynes@284
   656
    uint32_t *dwdest;
nkeynes@284
   657
    int i;
nkeynes@284
   658
nkeynes@284
   659
    srcaddr = srcaddr & 0x7FFFFF;
nkeynes@284
   660
    if( srcaddr + length > 0x800000 )
nkeynes@736
   661
        length = 0x800000 - srcaddr;
nkeynes@284
   662
nkeynes@934
   663
    banks[0] = ((uint32_t *)(pvr2_main_ram + ((srcaddr&0x007FFFF8)>>1)));
nkeynes@284
   664
    banks[1] = banks[0] + 0x100000;
nkeynes@284
   665
    if( bank_flag )
nkeynes@736
   666
        banks[0]++;
nkeynes@736
   667
nkeynes@284
   668
    /* Handle non-aligned start of source */
nkeynes@284
   669
    if( srcaddr & 0x03 ) {
nkeynes@736
   670
        char *src = ((char *)banks[bank_flag]) + (srcaddr & 0x03);
nkeynes@736
   671
        for( i= srcaddr & 0x03; i < 4 && length > 0; i++, length-- ) {
nkeynes@736
   672
            *dest++ = *src++;
nkeynes@736
   673
        }
nkeynes@736
   674
        bank_flag = !bank_flag;
nkeynes@284
   675
    }
nkeynes@284
   676
nkeynes@284
   677
    dwdest = (uint32_t *)dest;
nkeynes@284
   678
    while( length >= 4 ) {
nkeynes@736
   679
        *dwdest++ = *banks[bank_flag]++;
nkeynes@736
   680
        bank_flag = !bank_flag;
nkeynes@736
   681
        length -= 4;
nkeynes@284
   682
    }
nkeynes@736
   683
nkeynes@284
   684
    /* Handle non-aligned end of source */
nkeynes@284
   685
    if( length ) {
nkeynes@736
   686
        dest = (unsigned char *)dwdest;
nkeynes@736
   687
        unsigned char *src = (unsigned char *)banks[bank_flag];
nkeynes@736
   688
        while( length-- > 0 ) {
nkeynes@736
   689
            *dest++ = *src++;
nkeynes@736
   690
        }
nkeynes@284
   691
    }
nkeynes@284
   692
}
nkeynes@284
   693
nkeynes@309
   694
void pvr2_vram64_dump_file( sh4addr_t addr, uint32_t length, gchar *filename )
nkeynes@309
   695
{
nkeynes@309
   696
    uint32_t tmp[length>>2];
nkeynes@309
   697
    FILE *f = fopen(filename, "wo");
nkeynes@309
   698
    unsigned int i, j;
nkeynes@309
   699
nkeynes@309
   700
    if( f == NULL ) {
nkeynes@736
   701
        ERROR( "Unable to write to dump file '%s' (%s)", filename, strerror(errno) );
nkeynes@736
   702
        return;
nkeynes@309
   703
    }
nkeynes@429
   704
    pvr2_vram64_read( (unsigned char *)tmp, addr, length );
nkeynes@309
   705
    fprintf( f, "%08X\n", addr );
nkeynes@309
   706
    for( i =0; i<length>>2; i+=8 ) {
nkeynes@736
   707
        for( j=i; j<i+8; j++ ) {
nkeynes@736
   708
            if( j < length )
nkeynes@736
   709
                fprintf( f, " %08X", tmp[j] );
nkeynes@736
   710
            else
nkeynes@736
   711
                fprintf( f, "         " );
nkeynes@736
   712
        }
nkeynes@736
   713
        fprintf( f, "\n" );
nkeynes@309
   714
    }
nkeynes@309
   715
    fclose(f);
nkeynes@309
   716
}
nkeynes@309
   717
nkeynes@827
   718
void pvr2_vram64_dump( sh4addr_t addr, uint32_t length, FILE *f )
nkeynes@284
   719
{
nkeynes@429
   720
    unsigned char tmp[length];
nkeynes@284
   721
    pvr2_vram64_read( tmp, addr, length );
nkeynes@284
   722
    fwrite_dump( tmp, length, f );
nkeynes@284
   723
}
nkeynes@315
   724
nkeynes@315
   725
nkeynes@315
   726
nkeynes@315
   727
/**
nkeynes@315
   728
 * Flush the indicated render buffer back to PVR. Caller is responsible for
nkeynes@315
   729
 * tracking whether there is actually anything in the buffer.
nkeynes@315
   730
 *
nkeynes@869
   731
 * FIXME: Handle horizontal scaler 
nkeynes@827
   732
 *
nkeynes@315
   733
 * @param buffer A render buffer indicating the address to store to, and the
nkeynes@315
   734
 * format the data needs to be in.
nkeynes@315
   735
 */
nkeynes@352
   736
void pvr2_render_buffer_copy_to_sh4( render_buffer_t buffer )
nkeynes@315
   737
{
nkeynes@869
   738
    int line_size = buffer->width * colour_formats[buffer->colour_format].bpp;
nkeynes@869
   739
    int src_stride = line_size;
nkeynes@869
   740
    unsigned char target[buffer->size];
nkeynes@869
   741
nkeynes@869
   742
    display_driver->read_render_buffer( target, buffer, line_size, buffer->colour_format );
nkeynes@869
   743
nkeynes@869
   744
    if( (buffer->scale & 0xFFFF) == 0x0800 )
nkeynes@869
   745
        src_stride <<= 1;
nkeynes@869
   746
nkeynes@429
   747
    if( (buffer->address & 0xFF000000) == 0x04000000 ) {
nkeynes@869
   748
        pvr2_vram64_write_invert( buffer->address, target, buffer->size, line_size, 
nkeynes@869
   749
                                  buffer->rowstride, src_stride );
nkeynes@315
   750
    } else {
nkeynes@736
   751
        /* Regular buffer */
nkeynes@857
   752
        if( buffer->scale & SCALER_HSCALE ) {
nkeynes@857
   753
            pvr2_vram_write_invert_hscale( buffer->address, target, buffer->size, line_size, buffer->rowstride,
nkeynes@857
   754
                                           src_stride, colour_formats[buffer->colour_format].bpp );
nkeynes@352
   755
        } else {
nkeynes@857
   756
            pvr2_vram_write_invert( buffer->address, target, buffer->size, line_size, buffer->rowstride,
nkeynes@857
   757
                                    src_stride );
nkeynes@352
   758
        }
nkeynes@315
   759
    }
nkeynes@856
   760
    buffer->flushed = TRUE;
nkeynes@315
   761
}
nkeynes@315
   762
.