From 91d6fdd190bfbbccbc17ecedda6d124fda5095c9 Mon Sep 17 00:00:00 2001 From: Crow-bar Date: Wed, 10 Aug 2022 16:58:20 +0300 Subject: [PATCH] psp: using the maximum amount of VRAM --- engine/platform/psp/ka/KernelAccess.S | 8 + engine/platform/psp/ka/ka.h | 30 +++ engine/platform/psp/sys_psp.c | 16 +- engine/wscript | 1 + ref_gu/gu_render.c | 6 + ref_gu/gu_vram.c | 255 +++++++++++++++----------- ref_gu/gu_vram.h | 2 + scripts/waifulib/xcompile.py | 1 + 8 files changed, 208 insertions(+), 111 deletions(-) create mode 100644 engine/platform/psp/ka/KernelAccess.S create mode 100644 engine/platform/psp/ka/ka.h diff --git a/engine/platform/psp/ka/KernelAccess.S b/engine/platform/psp/ka/KernelAccess.S new file mode 100644 index 00000000..44023056 --- /dev/null +++ b/engine/platform/psp/ka/KernelAccess.S @@ -0,0 +1,8 @@ + .set noreorder + +#include "pspstub.s" + + STUB_START "KernelAccess",0x40090000,0x00020005 + STUB_FUNC 0x8A5C745F,kaGeEdramSetSize + STUB_FUNC 0x71570ECF,kaGeEdramGetHwSize + STUB_END diff --git a/engine/platform/psp/ka/ka.h b/engine/platform/psp/ka/ka.h new file mode 100644 index 00000000..2e2238f9 --- /dev/null +++ b/engine/platform/psp/ka/ka.h @@ -0,0 +1,30 @@ +/* +kamod.h - kernel access module header +Copyright (C) 2022 Sergey Galushko + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +*/ + +#ifndef KAMOD_H +#define KAMOD_H + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +int kaGeEdramSetSize(int size); +int kaGeEdramGetHwSize(void); + +#ifdef __cplusplus +} +#endif + +#endif // KAMOD_H diff --git a/engine/platform/psp/sys_psp.c b/engine/platform/psp/sys_psp.c index 561fb739..9c56ecc4 100644 --- a/engine/platform/psp/sys_psp.c +++ b/engine/platform/psp/sys_psp.c @@ -14,6 +14,7 @@ GNU General Public License for more details. */ #include "platform/platform.h" +#include "platform/psp/ka/ka.h" #include #include #include @@ -256,11 +257,14 @@ int Platform_UnloadModule( SceUID modid, int *sce_code ) return -1; *sce_code = sceKernelUnloadModule( modid ); - return ( ( ( *sce_code ) < 0 ) ? -2 : 0 ); + return ( ( ( *sce_code ) < 0 ) ? -2 : 0 ); } void Platform_Init( void ) { + SceUID kamID; + int result; + // disable fpu exceptions (division by zero and etc...) pspSdkDisableFPUExceptions(); @@ -269,6 +273,16 @@ void Platform_Init( void ) // set max cpu/gpu frequency scePowerSetClockFrequency( 333, 333, 166 ); + + // set max VRAM + kamID = Platform_LoadModule( "ka.prx", 1, 0, NULL ); + if( kamID >= 0 ) + { + result = kaGeEdramGetHwSize(); + if( result > 0 ) + result = kaGeEdramSetSize( result ); + Platform_UnloadModule( kamID, &result ); + } } void Platform_Shutdown( void ) diff --git a/engine/wscript b/engine/wscript index c230a68b..18e26531 100644 --- a/engine/wscript +++ b/engine/wscript @@ -137,6 +137,7 @@ def build(bld): if bld.env.DEST_OS == 'psp': source += bld.path.ant_glob(['platform/psp/*.c']) + source += bld.path.ant_glob(['platform/psp/*/*.S']) # add client files if not bld.env.DEDICATED: diff --git a/ref_gu/gu_render.c b/ref_gu/gu_render.c index 57312499..3727fcd1 100644 --- a/ref_gu/gu_render.c +++ b/ref_gu/gu_render.c @@ -417,6 +417,12 @@ qboolean R_Init( void ) if( glw_state.initialized ) return true; + if( vinit() < 0 ) + { + gEngfuncs.Host_Error( "Can't initialize video subsystem\nVRam unavailable" ); + return false; + } + GL_InitCommands(); GL_InitRandomTable(); diff --git a/ref_gu/gu_vram.c b/ref_gu/gu_vram.c index ee8ac5e8..d589eef4 100644 --- a/ref_gu/gu_vram.c +++ b/ref_gu/gu_vram.c @@ -10,20 +10,31 @@ */ #include "gu_vram.h" #include +#include +#include + +#define _MBEINVRAM +//#define _DEBUG // Configure the memory to be managed -#define __MEM_SIZE 0x00200000 -#define __MEM_START 0x04000000 +static unsigned int __mem_size = 0; +static unsigned int __mem_start = 0; +static int __mem_num_blocks = 0; + +static unsigned int *__mem_blocks; + +static int __largest_update = 0; +static int __largest_block = 0; +static int __mem_free = 0; // Configure the block size the memory gets subdivided into (page size) -// __MEM_SIZE/__BLOCK_SIZE may not exceed 2^16-1 = 65535 +// __mem_size/__BLOCK_SIZE may not exceed 2^16-1 = 65535 // The block size also defines the alignment of allocations // Larger block sizes perform better, because the blocktable is smaller and therefore fits better into cache // however the overhead is also bigger and more memory is wasted -#define __BLOCK_SIZE 512 -#define __MEM_BLOCKS (__MEM_SIZE/__BLOCK_SIZE) -#define __BLOCKS(x) ((x+__BLOCK_SIZE-1)/__BLOCK_SIZE) -#define __BLOCKSIZE(x) ((x+__BLOCK_SIZE-1)&~(__BLOCK_SIZE-1)) +#define __BLOCK_SIZE 512 +#define __BLOCKS(x) (( x + __BLOCK_SIZE - 1 ) / __BLOCK_SIZE ) +#define __BLOCKSIZE(x) (( x + __BLOCK_SIZE - 1 ) & ~( __BLOCK_SIZE - 1 )) // A MEMORY BLOCK ENTRY IS MADE UP LIKE THAT: @@ -37,36 +48,56 @@ // // This management can handle a max amount of 2^16-1 = 65535 blocks, which resolves to 64MB at blocksize of 1024 bytes // -#define __BLOCK_GET_SIZE(x) ((x & 0x7FFF)) -#define __BLOCK_GET_PREV(x) ((x >> 15) & 0x7FFF) -#define __BLOCK_GET_FREE(x) ((x >> 31)) -#define __BLOCK_GET_BLOCK(x) ((x >> 30) & 0x1) -#define __BLOCK_SET_SIZE(x,y) x=((x & ~0x7FFF) | ((y) & 0x7FFF)) -#define __BLOCK_ADD_SIZE(x,y) x=((x & ~0x7FFF) | (((x & 0x7FFF)+((y) & 0x7FFF)) & 0x7FFF)) -#define __BLOCK_SET_PREV(x,y) x=((x & ~0x3FFF8000) | (((y) & 0x7FFF)<<15)) -#define __BLOCK_SET_FREE(x,y) x=((x & 0x7FFFFFFF) | (((y) & 0x1)<<31)) -#define __BLOCK_SET_BLOCK(x,y) x=((x & 0xBFFFFFFF) | (((y) & 0x1)<<30)) -#define __BLOCK_MAKE(s,p,f,n) (((f & 0x1)<<31) | ((n & 0x1)<<30) | (((p) & 0x7FFF)<<15) | ((s) & 0x7FFF)) -#define __BLOCK_GET_FREEBLOCK(x) ((x>>30) & 0x3) // returns 11b if block is a starting block and free, 10b if block is a starting block and allocated, 0xb if it is a non-starting block (don't change) -#define __BLOCK0 ((__MEM_BLOCKS) | (1<<31) | (1<<30)) +#define __BLOCK_GET_SIZE( x ) (( x & 0x7FFF )) +#define __BLOCK_GET_PREV( x ) (( x >> 15 ) & 0x7FFF ) +#define __BLOCK_GET_FREE( x ) (( x >> 31 )) +#define __BLOCK_GET_BLOCK( x ) (( x >> 30) & 0x1 ) +#define __BLOCK_SET_SIZE( x, y ) x = (( x & ~0x7FFF ) | (( y ) & 0x7FFF )) +#define __BLOCK_ADD_SIZE( x, y ) x = (( x & ~0x7FFF ) | ((( x & 0x7FFF ) + (( y ) & 0x7FFF )) & 0x7FFF )) +#define __BLOCK_SET_PREV( x, y ) x = (( x & ~0x3FFF8000 ) | ((( y ) & 0x7FFF ) << 15 )) +#define __BLOCK_SET_FREE( x, y ) x = (( x & 0x7FFFFFFF ) | ((( y ) & 0x1 ) << 31 )) +#define __BLOCK_SET_BLOCK( x, y ) x = (( x & 0xBFFFFFFF ) | ((( y ) & 0x1 ) << 30 )) +#define __BLOCK_MAKE( s, p, f, n ) ((( f & 0x1 ) << 31 ) | (( n & 0x1 ) << 30 ) | ((( p ) & 0x7FFF ) << 15 ) | (( s ) & 0x7FFF )) +#define __BLOCK_GET_FREEBLOCK( x ) (( x >> 30 ) & 0x3 ) // returns 11b if block is a starting block and free, 10b if block is a starting block and allocated, 0xb if it is a non-starting block (don't change) +#define __BLOCK0 (( __mem_num_blocks ) | ( 1 << 31 ) | ( 1 << 30 )) +int vinit( void ) +{ + if( __mem_start ) return 0; -unsigned int __mem_blocks[__MEM_BLOCKS] = { 0 }; + __mem_size = sceGeEdramGetSize(); + __mem_start = ( unsigned int )sceGeEdramGetAddr(); +#ifdef _MBEINVRAM + __mem_num_blocks = __mem_size / ( __BLOCK_SIZE + sizeof( unsigned int )); + __mem_size = __mem_num_blocks * __BLOCK_SIZE; + __mem_blocks = ( unsigned int* )( __mem_start + __mem_size ); // to end +#else + __mem_num_blocks = __mem_size / __BLOCK_SIZE; + __mem_blocks = ( unsigned int* )calloc( __mem_num_blocks, sizeof( unsigned int )); + if( !__mem_blocks ) + { + __mem_size = 0; + __mem_start = 0; + return -1; + } +#endif + __largest_block = __mem_num_blocks; + __mem_free = __mem_num_blocks; - -static int __largest_update = 0; -static int __largest_block = __MEM_BLOCKS; -static int __mem_free = __MEM_BLOCKS; + return 0; +} inline void* vrelptr( void *ptr ) { - return (void*)((unsigned int)ptr & ~__MEM_START); + if( !__mem_start ) return NULL; + return ( void* )(( unsigned int )ptr & ~__mem_start ); } inline void* vabsptr( void *ptr ) { - return (void*)((unsigned int)ptr | __MEM_START); + if( !__mem_start ) return NULL; + return ( void* )(( unsigned int )ptr | __mem_start ); } @@ -74,10 +105,10 @@ static void __find_largest_block( void ) { int i = 0; __largest_block = 0; - while (i<__MEM_BLOCKS) + while( i < __mem_num_blocks ) { - int csize = __BLOCK_GET_SIZE(__mem_blocks[i]); - if (__BLOCK_GET_FREEBLOCK(__mem_blocks[i])==3 && csize>__largest_block) + int csize = __BLOCK_GET_SIZE( __mem_blocks[i] ); + if( __BLOCK_GET_FREEBLOCK( __mem_blocks[i] ) == 3 && csize > __largest_block ) __largest_block = csize; i += csize; } @@ -88,158 +119,161 @@ static void __find_largest_block( void ) void __memwalk( void ) { int i = 0; - if (__mem_blocks[0]==0) __mem_blocks[0] = __BLOCK0; - while (i<__MEM_BLOCKS) + if( !__mem_start ) return; + if( __mem_blocks[0] == 0 ) __mem_blocks[0] = __BLOCK0; + while( i < __mem_num_blocks ) { - printf("BLOCK %i:\n", i); - printf(" free: %i\n", __BLOCK_GET_FREEBLOCK(__mem_blocks[i])); - printf(" size: %i\n", __BLOCK_GET_SIZE(__mem_blocks[i])); - printf(" prev: %i\n", __BLOCK_GET_PREV(__mem_blocks[i])); - i+=__BLOCK_GET_SIZE(__mem_blocks[i]); + printf( "BLOCK %i:\n", i ); + printf( " free: %i\n", __BLOCK_GET_FREEBLOCK( __mem_blocks[i] )); + printf( " size: %i\n", __BLOCK_GET_SIZE( __mem_blocks[i] )); + printf( " prev: %i\n", __BLOCK_GET_PREV( __mem_blocks[i] )); + i += __BLOCK_GET_SIZE( __mem_blocks[i] ); } } #endif void* valloc( size_t size ) { + if( !__mem_start ) return NULL; + // Initialize memory block, if not yet done - if (__mem_blocks[0]==0) __mem_blocks[0] = __BLOCK0; - + if( __mem_blocks[0] == 0 ) __mem_blocks[0] = __BLOCK0; + int i = 0; int j = 0; - int bsize = __BLOCKS(size); - - if (__largest_update==0 && __largest_block=bsize) + int csize = __BLOCK_GET_SIZE( __mem_blocks[i] ); + if( __BLOCK_GET_FREEBLOCK( __mem_blocks[i] ) == 3 && csize >= bsize ) { - if (csizebsize && next<__MEM_BLOCKS) + __mem_blocks[i] = __BLOCK_MAKE( bsize, j, 0, 1 ); + + int next = i + bsize; + if( csize > bsize && next < __mem_num_blocks ) { - __mem_blocks[next] = __BLOCK_MAKE(csize-bsize,i,1,1); - int nextnext = i+csize; - if (nextnext<__MEM_BLOCKS) + __mem_blocks[next] = __BLOCK_MAKE( csize - bsize, i, 1, 1 ); + int nextnext = i + csize; + if ( nextnext < __mem_num_blocks ) { - __BLOCK_SET_PREV(__mem_blocks[nextnext], next); + __BLOCK_SET_PREV( __mem_blocks[nextnext], next ); } } __mem_free -= bsize; - if (__largest_block==csize) // if we just allocated from one of the largest blocks + if( __largest_block == csize ) // if we just allocated from one of the largest blocks { - if ((csize-bsize)>(__mem_free/2)) - __largest_block = (csize-bsize); // there can't be another largest block + if(( csize - bsize ) > ( __mem_free / 2 )) + __largest_block = ( csize - bsize ); // there can't be another largest block else __largest_update = 1; } - return ((void*)(__MEM_START + (i*__BLOCK_SIZE))); + return (( void* )( __mem_start + ( i * __BLOCK_SIZE ))); } void vfree( void* ptr ) { - if (ptr==0) return; + if( ptr == 0 ) return; - int block = ((unsigned int)ptr - __MEM_START)/__BLOCK_SIZE; - if (block<0 || block>__MEM_BLOCKS) + int block = (( unsigned int )ptr - __mem_start ) / __BLOCK_SIZE; + if( block < 0 || block > __mem_num_blocks ) { - #ifdef _DEBUG - printf("Block is out of range: %i (0x%x)\n", block, (int)ptr); - #endif +#ifdef _DEBUG + printf( "Block is out of range: %i (0x%x)\n", block, (int)ptr ); +#endif return; } - int csize = __BLOCK_GET_SIZE(__mem_blocks[block]); - #ifdef _DEBUG + int csize = __BLOCK_GET_SIZE( __mem_blocks[block] ); +#ifdef _DEBUG printf("freeing block %i (0x%x), size: %i\n", block, (int)ptr, csize); - #endif +#endif - if (__BLOCK_GET_FREEBLOCK(__mem_blocks[block])!=1 || csize==0) + if( __BLOCK_GET_FREEBLOCK( __mem_blocks[block] ) != 1 || csize == 0 ) { - #ifdef _DEBUG - printf("Block was not allocated!\n"); - #endif +#ifdef _DEBUG + printf( "Block was not allocated!\n" ); +#endif return; } - + // Mark block as free - __BLOCK_SET_FREE(__mem_blocks[block],1); + __BLOCK_SET_FREE( __mem_blocks[block], 1 ); __mem_free += csize; - - int next = block+csize; + + int next = block + csize; // Merge with previous block if possible - int prev = __BLOCK_GET_PREV(__mem_blocks[block]); - if (prev