mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 03:24:56 +08:00
First merge attempt (many PSP tunings are missing, as they are outdated now)
This commit is contained in:
21
README.md
21
README.md
@@ -73,6 +73,10 @@ This repository contains our fork of HLSDK and restored source code for some of
|
||||
* Clone this repostory:
|
||||
`$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`
|
||||
|
||||
#### PSP
|
||||
* Build pspsdk(GCC 9.3) from https://github.com/pspdev
|
||||
* Clone this repository: `git clone --recursive https://github.com/Crow-bar/xash3d-fwgs`.
|
||||
|
||||
### Building
|
||||
#### Windows (Visual Studio)
|
||||
0) Open command line
|
||||
@@ -90,3 +94,20 @@ If compiling 32-bit on amd64, you may need to supply `export PKG_CONFIG_PATH=/us
|
||||
(You need to pass `-8` to compile 64-bit engine on 64-bit x86 processor)
|
||||
2) Compile: `./waf build`
|
||||
3) Install(optional): `./waf install --destdir=/path/to/any/output/directory`
|
||||
|
||||
#### PSP
|
||||
0) Navigate to `xash3d-fwgs` directory.
|
||||
1) Examine which build options are available: `./waf --help`
|
||||
2) Configure build:
|
||||
Normal: `./waf configure -T fast --psp=prx,660,HW --prefix=/path/to/any/output/directory`
|
||||
Profiling: `./waf configure -T debug --psp=elf,660,HW --enable-profiling --prefix=/path/to/any/output/directory`
|
||||
3) Compile: `./waf build`
|
||||
4) Install(optional): `./waf install`
|
||||
|
||||
|
||||
## Running
|
||||
0) Copy libraries and main executable somewhere, if you're skipped installation stage.
|
||||
1) Copy game files to same directory
|
||||
2) Run `xash3d.exe`/`xash3d.sh`/`xash3d` depending on which platform you're using.
|
||||
|
||||
For additional info, run Xash3D with `-help` command line key.
|
||||
|
||||
@@ -20,16 +20,19 @@ GNU General Public License for more details.
|
||||
#define VIDEO_SDL 1
|
||||
#define VIDEO_FBDEV 3
|
||||
#define VIDEO_DOS 4
|
||||
#define VIDEO_PSP 5
|
||||
|
||||
// audio backends (XASH_SOUND)
|
||||
#define SOUND_NULL 0
|
||||
#define SOUND_SDL 1
|
||||
#define SOUND_ALSA 3
|
||||
#define SOUND_PSP 4
|
||||
|
||||
// input (XASH_INPUT)
|
||||
#define INPUT_NULL 0
|
||||
#define INPUT_SDL 1
|
||||
#define INPUT_EVDEV 3
|
||||
#define INPUT_PSP 4
|
||||
|
||||
// timer (XASH_TIMER)
|
||||
#define TIMER_NULL 0 // not used
|
||||
@@ -37,17 +40,20 @@ GNU General Public License for more details.
|
||||
#define TIMER_POSIX 2
|
||||
#define TIMER_WIN32 3
|
||||
#define TIMER_DOS 4
|
||||
#define TIMER_PSP 5
|
||||
|
||||
// messageboxes (XASH_MESSAGEBOX)
|
||||
#define MSGBOX_STDERR 0
|
||||
#define MSGBOX_SDL 1
|
||||
#define MSGBOX_WIN32 3
|
||||
#define MSGBOX_NSWITCH 4
|
||||
#define MSGBOX_PSP 5
|
||||
|
||||
// library loading (XASH_LIB)
|
||||
#define LIB_NULL 0
|
||||
#define LIB_POSIX 1
|
||||
#define LIB_WIN32 2
|
||||
#define LIB_NULL 0
|
||||
#define LIB_POSIX 1
|
||||
#define LIB_WIN32 2
|
||||
#define LIB_STATIC 3
|
||||
#define LIB_PSP 4
|
||||
|
||||
#endif /* BACKENDS_H */
|
||||
|
||||
@@ -23,6 +23,7 @@ NOTE: number at end of pixelformat name it's a total bitscount e.g. PF_RGB_24 ==
|
||||
|| type == PF_BC7_UNORM \
|
||||
|| type == PF_BC7_SRGB \
|
||||
|| type == PF_KTX2_RAW )
|
||||
#define ImageIND( type ) (type == PF_INDEXED_32 || type == PF_INDEXED_24)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -33,6 +34,10 @@ typedef enum
|
||||
PF_BGRA_32, // big endian RGBA (MacOS)
|
||||
PF_RGB_24, // uncompressed dds or another 24-bit image
|
||||
PF_BGR_24, // big-endian RGB (MacOS)
|
||||
PF_RGB_332, // 8-bit R3 G3 B2
|
||||
PF_RGB_5650, // 16-bit R5 G6 B5
|
||||
PF_RGBA_5551, // 16-bit R5 G5 B5 A1
|
||||
PF_RGBA_4444, // 16-bit R4 G4 B4 A4
|
||||
PF_LUMINANCE,
|
||||
PF_DXT1, // s3tc DXT1/BC1 format
|
||||
PF_DXT3, // s3tc DXT3/BC2 format
|
||||
|
||||
@@ -127,6 +127,21 @@ typedef struct
|
||||
int flags; // sky or slime, no lightmap or 256 subdivision
|
||||
} mtexinfo_t;
|
||||
|
||||
#if XASH_PSP
|
||||
typedef struct
|
||||
{
|
||||
float uv[2];
|
||||
float xyz[3];
|
||||
}gu_vert_t;
|
||||
typedef struct glpoly_s
|
||||
{
|
||||
struct glpoly_s *next;
|
||||
struct glpoly_s *chain;
|
||||
int numverts;
|
||||
int flags; // for SURF_UNDERWATER
|
||||
gu_vert_t verts[1]; // variable sized (xyz s1t1 + lm(xyz s2t2))
|
||||
} glpoly_t;
|
||||
#else
|
||||
typedef struct glpoly_s
|
||||
{
|
||||
struct glpoly_s *next;
|
||||
@@ -135,7 +150,7 @@ typedef struct glpoly_s
|
||||
int flags; // for SURF_UNDERWATER
|
||||
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
|
||||
} glpoly_t;
|
||||
|
||||
#endif
|
||||
typedef struct mnode_s
|
||||
{
|
||||
// common with leaf
|
||||
|
||||
@@ -77,6 +77,30 @@ SETUP BACKENDS DEFINITIONS
|
||||
|
||||
// usually only 10-20 fds availiable
|
||||
#define XASH_REDUCE_FD
|
||||
#elif XASH_PSP
|
||||
#ifndef XASH_VIDEO
|
||||
#define XASH_VIDEO VIDEO_PSP
|
||||
#endif
|
||||
|
||||
#ifndef XASH_TIMER
|
||||
#define XASH_TIMER TIMER_PSP
|
||||
#endif
|
||||
|
||||
#ifndef XASH_INPUT
|
||||
#define XASH_INPUT INPUT_PSP
|
||||
#endif
|
||||
|
||||
#ifndef XASH_SOUND
|
||||
#define XASH_SOUND SOUND_PSP
|
||||
#endif // XASH_SOUND
|
||||
|
||||
#ifndef XASH_MESSAGEBOX
|
||||
#define XASH_MESSAGEBOX MSGBOX_PSP
|
||||
#endif // XASH_MESSAGEBOX
|
||||
|
||||
#define XASH_REDUCE_FD
|
||||
#define XASH_NO_TOUCH
|
||||
#define XASH_NO_ZIP
|
||||
#endif
|
||||
|
||||
#endif // XASH_DEDICATED
|
||||
@@ -105,7 +129,7 @@ SETUP BACKENDS DEFINITIONS
|
||||
#endif // !XASH_WIN32
|
||||
#endif
|
||||
|
||||
#ifdef XASH_STATIC_LIBS
|
||||
#if defined(XASH_STATIC_LIBS) && !XASH_PSP
|
||||
#define XASH_LIB LIB_STATIC
|
||||
#define XASH_INTERNAL_GAMELIBS
|
||||
#define XASH_ALLOW_SAVERESTORE_OFFSETS
|
||||
@@ -113,6 +137,8 @@ SETUP BACKENDS DEFINITIONS
|
||||
#define XASH_LIB LIB_WIN32
|
||||
#elif XASH_POSIX
|
||||
#define XASH_LIB LIB_POSIX
|
||||
#elif XASH_PSP
|
||||
#define XASH_LIB LIB_PSP
|
||||
#endif
|
||||
|
||||
//
|
||||
@@ -193,4 +219,20 @@ Default build-depended cvar and constant values
|
||||
#define DEFAULT_MAX_EDICTS 1200 // was 900 before HL25
|
||||
#endif // DEFAULT_MAX_EDICTS
|
||||
|
||||
#ifndef DEFAULT_ACCELERATED_RENDERER
|
||||
#ifdef XASH_PSP
|
||||
#define DEFAULT_ACCELERATED_RENDERER "gu"
|
||||
#else
|
||||
#if XASH_MOBILE_PLATFORM
|
||||
#define DEFAULT_ACCELERATED_RENDERER "gles1"
|
||||
#else // !XASH_MOBILE_PLATFORM
|
||||
#define DEFAULT_ACCELERATED_RENDERER "gl"
|
||||
#endif // !XASH_MOBILE_PLATFORM
|
||||
#endif
|
||||
#endif // DEFAULT_ACCELERATED_RENDERER
|
||||
|
||||
#ifndef DEFAULT_SOFTWARE_RENDERER
|
||||
#define DEFAULT_SOFTWARE_RENDERER "soft" // mittorn's ref_soft
|
||||
#endif // DEFAULT_SOFTWARE_RENDERER
|
||||
|
||||
#endif // DEFAULTS_H
|
||||
|
||||
@@ -24,7 +24,9 @@ GNU General Public License for more details.
|
||||
#include <sys/syslimits.h>
|
||||
#define OS_LIB_EXT "dylib"
|
||||
#define OPEN_COMMAND "open"
|
||||
#else
|
||||
#elif XASH_PSP
|
||||
#define OS_LIB_EXT "prx"
|
||||
#else
|
||||
#define OS_LIB_EXT "so"
|
||||
#define OPEN_COMMAND "xdg-open"
|
||||
#endif
|
||||
@@ -55,6 +57,16 @@ GNU General Public License for more details.
|
||||
#define _mkdir( x ) mkdir( x, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH )
|
||||
#endif
|
||||
|
||||
#if XASH_PSP
|
||||
#include <unistd.h>
|
||||
#include <pspiofilemgr.h>
|
||||
|
||||
#define O_BINARY 0
|
||||
#define O_TEXT 0
|
||||
|
||||
#define _mkdir( x ) sceIoMkdir( x, FIO_S_IRWXU | FIO_S_IRWXG | FIO_S_IROTH | FIO_S_IXOTH )
|
||||
#endif
|
||||
|
||||
typedef void* HANDLE;
|
||||
typedef void* HINSTANCE;
|
||||
|
||||
|
||||
@@ -101,8 +101,13 @@ typedef enum
|
||||
TF_TEXTURE_3D = (1<<20), // this is GL_TEXTURE_3D
|
||||
TF_ATLAS_PAGE = (1<<21), // bit who indicate lightmap page or deluxemap page
|
||||
TF_ALPHACONTRAST = (1<<22), // special texture mode for A2C
|
||||
#if XASH_PSP
|
||||
TF_IMG_SWIZZLED = (1<<23),
|
||||
TF_IMG_INVRAM = (1<<24),
|
||||
#else
|
||||
// reserved
|
||||
// reserved
|
||||
#endif
|
||||
TF_IMG_UPLOADED = (1<<25), // this is set for first time when called glTexImage, otherwise it will be call glTexSubImage
|
||||
TF_ARB_FLOAT = (1<<26), // float textures
|
||||
TF_NOCOMPARE = (1<<27), // disable comparing for depth textures
|
||||
|
||||
@@ -21,12 +21,22 @@ typedef int sound_t;
|
||||
typedef float vec_t;
|
||||
typedef vec_t vec2_t[2];
|
||||
typedef vec_t vec3_t[3];
|
||||
#if XASH_PSP
|
||||
typedef vec_t vec4_t[4] __attribute__( ( aligned( 16 ) ) );
|
||||
typedef vec_t quat_t[4] __attribute__( ( aligned( 16 ) ) );
|
||||
#else
|
||||
typedef vec_t vec4_t[4];
|
||||
typedef vec_t quat_t[4];
|
||||
#endif
|
||||
typedef byte rgba_t[4]; // unsigned byte colorpack
|
||||
typedef byte rgb_t[3]; // unsigned byte colorpack
|
||||
#if XASH_PSP
|
||||
typedef vec_t matrix3x4[3][4] __attribute__( ( aligned( 16 ) ) );
|
||||
typedef vec_t matrix4x4[4][4] __attribute__( ( aligned( 16 ) ) );
|
||||
#else
|
||||
typedef vec_t matrix3x4[3][4];
|
||||
typedef vec_t matrix4x4[4][4];
|
||||
#endif
|
||||
|
||||
#if XASH_64BIT
|
||||
typedef uint32_t poolhandle_t;
|
||||
@@ -194,6 +204,9 @@ typedef void *(*pfnCreateInterface_t)( const char *, int * );
|
||||
// config strings are a general means of communication from
|
||||
// the server to all connected clients.
|
||||
// each config string can be at most CS_SIZE characters.
|
||||
#if XASH_PSP
|
||||
#define MAX_QPATH 48
|
||||
#else
|
||||
#if XASH_LOW_MEMORY == 0
|
||||
#define MAX_QPATH 64 // max length of a game pathname
|
||||
#elif XASH_LOW_MEMORY == 2
|
||||
@@ -201,6 +214,7 @@ typedef void *(*pfnCreateInterface_t)( const char *, int * );
|
||||
#elif XASH_LOW_MEMORY == 1
|
||||
#define MAX_QPATH 48
|
||||
#endif
|
||||
#endif
|
||||
#define MAX_OSPATH 260 // max length of a filesystem pathname
|
||||
#define CS_SIZE 64 // size of one config string
|
||||
#define CS_TIME 16 // size of time string
|
||||
|
||||
@@ -26,18 +26,6 @@ GNU General Public License for more details.
|
||||
|
||||
// #define STUDIO_INTERPOLATION_FIX
|
||||
|
||||
/*
|
||||
==================
|
||||
CL_IsPlayerIndex
|
||||
|
||||
detect player entity
|
||||
==================
|
||||
*/
|
||||
qboolean CL_IsPlayerIndex( int idx )
|
||||
{
|
||||
return ( idx >= 1 && idx <= cl.maxclients );
|
||||
}
|
||||
|
||||
/*
|
||||
=========================================================================
|
||||
|
||||
|
||||
@@ -96,41 +96,6 @@ static dllfunc_t cdll_new_exports[] = // allowed only in SDK 2.3 and higher
|
||||
|
||||
static void pfnSPR_DrawHoles( int frame, int x, int y, const wrect_t *prc );
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_GetEntityByIndex
|
||||
|
||||
Render callback for studio models
|
||||
====================
|
||||
*/
|
||||
cl_entity_t *CL_GetEntityByIndex( int index )
|
||||
{
|
||||
if( !clgame.entities ) // not in game yet
|
||||
return NULL;
|
||||
|
||||
if( index < 0 || index >= clgame.maxEntities )
|
||||
return NULL;
|
||||
|
||||
if( index == 0 )
|
||||
return clgame.entities;
|
||||
|
||||
return CL_EDICT_NUM( index );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CL_ModelHandle
|
||||
|
||||
get model handle by index
|
||||
================
|
||||
*/
|
||||
model_t *CL_ModelHandle( int modelindex )
|
||||
{
|
||||
if( modelindex < 0 || modelindex >= MAX_MODELS )
|
||||
return NULL;
|
||||
return cl.models[modelindex];
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_IsThirdPerson
|
||||
@@ -939,7 +904,7 @@ void CL_DrawCrosshair( void )
|
||||
VectorAdd( refState.viewangles, cl.crosshairangle, angles );
|
||||
AngleVectors( angles, forward, NULL, NULL );
|
||||
VectorAdd( refState.vieworg, forward, point );
|
||||
ref.dllFuncs.WorldToScreen( point, screen );
|
||||
gTriApi.WorldToScreen( point, screen );
|
||||
|
||||
x += ( clgame.viewport[2] >> 1 ) * screen[0] + 0.5f;
|
||||
y += ( clgame.viewport[3] >> 1 ) * screen[1] + 0.5f;
|
||||
@@ -1084,7 +1049,6 @@ void CL_ClearWorld( void )
|
||||
|
||||
world.max_recursion = 0;
|
||||
|
||||
clgame.ds.cullMode = TRI_FRONT;
|
||||
clgame.numStatics = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,12 +81,12 @@ NetGraph_FillRGBA shortcut
|
||||
*/
|
||||
static void NetGraph_DrawRect( wrect_t *rect, byte colors[4] )
|
||||
{
|
||||
ref.dllFuncs.Color4ub( colors[0], colors[1], colors[2], colors[3] ); // color for this quad
|
||||
gTriApi.Color4ub( colors[0], colors[1], colors[2], colors[3] ); // color for this quad
|
||||
|
||||
ref.dllFuncs.Vertex3f( rect->left, rect->top, 0 );
|
||||
ref.dllFuncs.Vertex3f( rect->left + rect->right, rect->top, 0 );
|
||||
ref.dllFuncs.Vertex3f( rect->left + rect->right, rect->top + rect->bottom, 0 );
|
||||
ref.dllFuncs.Vertex3f( rect->left, rect->top + rect->bottom, 0 );
|
||||
gTriApi.Vertex3f( rect->left, rect->top, 0 );
|
||||
gTriApi.Vertex3f( rect->left + rect->right, rect->top, 0 );
|
||||
gTriApi.Vertex3f( rect->left + rect->right, rect->top + rect->bottom, 0 );
|
||||
gTriApi.Vertex3f( rect->left, rect->top + rect->bottom, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -691,7 +691,7 @@ void SCR_DrawNetGraph( void )
|
||||
|
||||
ref.dllFuncs.End();
|
||||
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderNormal );
|
||||
ref.dllFuncs.RenderMode( kRenderNormal );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -393,7 +393,7 @@ int CL_TempEntAddEntity( cl_entity_t *pEntity )
|
||||
VectorAdd( pEntity->origin, pEntity->model->maxs, maxs );
|
||||
|
||||
// g-cont. just use PVS from previous frame
|
||||
if( TriBoxInPVS( mins, maxs ))
|
||||
if( Mod_BoxVisible( mins, maxs, ref.dllFuncs.Mod_GetCurrentVis( )))
|
||||
{
|
||||
VectorCopy( pEntity->angles, pEntity->curstate.angles );
|
||||
VectorCopy( pEntity->origin, pEntity->curstate.origin );
|
||||
@@ -1023,8 +1023,12 @@ void GAME_EXPORT R_BreakModel( const vec3_t pos, const vec3_t size, const vec3_t
|
||||
count = (size[0] * size[1] + size[1] * size[2] + size[2] * size[0]) / (3 * SHARD_VOLUME * SHARD_VOLUME);
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
if( count > 15 ) count = 15;
|
||||
#else
|
||||
// limit to 100 pieces
|
||||
if( count > 100 ) count = 100;
|
||||
#endif
|
||||
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
|
||||
@@ -101,19 +101,6 @@ struct beam_s *R_BeamRing( int startEnt, int endEnt, int modelIndex, float life,
|
||||
struct beam_s *R_BeamFollow( int startEnt, int modelIndex, float life, float width, float r, float g, float b, float brightness );
|
||||
void R_BeamKill( int deadEntity );
|
||||
|
||||
|
||||
// TriAPI
|
||||
void TriRenderMode( int mode );
|
||||
void TriColor4f( float r, float g, float b, float a );
|
||||
void TriColor4ub( byte r, byte g, byte b, byte a );
|
||||
void TriBrightness( float brightness );
|
||||
void TriCullFace( TRICULLSTYLE mode );
|
||||
int TriWorldToScreen( const float *world, float *screen );
|
||||
int TriBoxInPVS( float *mins, float *maxs );
|
||||
void TriLightAtPoint( float *pos, float *value );
|
||||
void TriColor4fRendermode( float r, float g, float b, float a, int rendermode );
|
||||
int TriSpriteTexture( model_t *pSpriteModel, int frame );
|
||||
|
||||
extern model_t *cl_sprite_dot;
|
||||
extern model_t *cl_sprite_shell;
|
||||
|
||||
|
||||
@@ -417,10 +417,10 @@ void R_DrawLeafNode( float x, float y, float scale )
|
||||
|
||||
void R_DrawNodeConnection( float x, float y, float x2, float y2 )
|
||||
{
|
||||
ref.dllFuncs.Begin( TRI_LINES );
|
||||
ref.dllFuncs.Vertex3f( x, y, 0 );
|
||||
ref.dllFuncs.Vertex3f( x2, y2, 0 );
|
||||
ref.dllFuncs.End( );
|
||||
gTriApi.Begin( TRI_LINES );
|
||||
gTriApi.Vertex3f( x, y, 0 );
|
||||
gTriApi.Vertex3f( x2, y2, 0 );
|
||||
gTriApi.End( );
|
||||
}
|
||||
|
||||
void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int shownodes, mleaf_t *viewleaf )
|
||||
@@ -443,10 +443,10 @@ void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int shownodes,
|
||||
if( shownodes == 1 )
|
||||
{
|
||||
if( cl.worldmodel->leafs == leaf )
|
||||
ref.dllFuncs.Color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
gTriApi.Color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
else if( viewleaf && viewleaf == leaf )
|
||||
ref.dllFuncs.Color4f( 1.0f, 0.0f, 0.0f, 1.0f );
|
||||
else ref.dllFuncs.Color4f( 0.0f, 1.0f, 0.0f, 1.0f );
|
||||
gTriApi.Color4f( 1.0f, 0.0f, 0.0f, 1.0f );
|
||||
else gTriApi.Color4f( 0.0f, 1.0f, 0.0f, 1.0f );
|
||||
R_DrawLeafNode( x, y, scale );
|
||||
}
|
||||
world.recursion_level--;
|
||||
@@ -455,7 +455,7 @@ void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int shownodes,
|
||||
|
||||
if( shownodes == 1 )
|
||||
{
|
||||
ref.dllFuncs.Color4f( 0.0f, 0.0f, 1.0f, 1.0f );
|
||||
gTriApi.Color4f( 0.0f, 0.0f, 1.0f, 1.0f );
|
||||
R_DrawLeafNode( x, y, scale );
|
||||
}
|
||||
else if( shownodes == 2 )
|
||||
@@ -487,7 +487,7 @@ void R_ShowTree( void )
|
||||
//pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
|
||||
//pglLineWidth( 2.0f );
|
||||
ref.dllFuncs.Color4f( 1, 0.7f, 0, 1.0f );
|
||||
gTriApi.Color4f( 1, 0.7f, 0, 1.0f );
|
||||
//pglDisable( GL_TEXTURE_2D );
|
||||
R_ShowTree_r( cl.worldmodel->nodes, x, y, world.max_recursion * 3.5f, 2, viewleaf );
|
||||
//pglEnable( GL_TEXTURE_2D );
|
||||
|
||||
@@ -370,7 +370,6 @@ typedef struct
|
||||
// holds text color
|
||||
rgba_t textColor;
|
||||
rgba_t spriteColor;
|
||||
vec4_t triRGBA;
|
||||
|
||||
// crosshair members
|
||||
const model_t *pCrosshair;
|
||||
@@ -839,7 +838,6 @@ void CL_ClearSpriteTextures( void );
|
||||
void CL_CenterPrint( const char *text, float y );
|
||||
void CL_TextMessageParse( byte *pMemFile, int fileSize );
|
||||
client_textmessage_t *CL_TextMessageGet( const char *pName );
|
||||
model_t *CL_ModelHandle( int modelindex );
|
||||
void NetAPI_CancelAllRequests( void );
|
||||
cl_entity_t *CL_GetLocalPlayer( void );
|
||||
model_t *CL_LoadClientSprite( const char *filename );
|
||||
@@ -861,19 +859,45 @@ void CL_EnableScissor( scissor_state_t *scissor, int x, int y, int width, int he
|
||||
void CL_DisableScissor( scissor_state_t *scissor );
|
||||
qboolean CL_Scissor( const scissor_state_t *scissor, float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 );
|
||||
|
||||
_inline cl_entity_t *CL_EDICT_NUM( int n )
|
||||
static inline cl_entity_t *CL_EDICT_NUM( int n )
|
||||
{
|
||||
if( !clgame.entities )
|
||||
if( unlikely( !clgame.entities )) // not in game yet
|
||||
{
|
||||
Host_Error( "CL_EDICT_NUM: clgame.entities is NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(( n >= 0 ) && ( n < clgame.maxEntities ))
|
||||
return clgame.entities + n;
|
||||
if( unlikely( n < 0 || n >= clgame.maxEntities ))
|
||||
{
|
||||
Host_Error( "CL_EDICT_NUM: bad number %i\n", n );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Host_Error( "CL_EDICT_NUM: bad number %i\n", n );
|
||||
return NULL;
|
||||
return &clgame.entities[n];
|
||||
}
|
||||
|
||||
static inline cl_entity_t *CL_GetEntityByIndex( int n )
|
||||
{
|
||||
if( unlikely( !clgame.entities )) // not in game yet
|
||||
return NULL;
|
||||
|
||||
if( unlikely( n < 0 || n >= clgame.maxEntities ))
|
||||
return NULL;
|
||||
|
||||
return &clgame.entities[n];
|
||||
}
|
||||
|
||||
static inline model_t *CL_ModelHandle( int modelindex )
|
||||
{
|
||||
if( unlikely( modelindex < 0 || modelindex >= MAX_MODELS ))
|
||||
return NULL;
|
||||
|
||||
return cl.models[modelindex];
|
||||
}
|
||||
|
||||
static inline qboolean CL_IsPlayerIndex( int idx )
|
||||
{
|
||||
return ( idx >= 1 && idx <= cl.maxclients );
|
||||
}
|
||||
|
||||
//
|
||||
@@ -995,7 +1019,6 @@ void CL_ProcessPlayerState( int playerindex, entity_state_t *state );
|
||||
void CL_ComputePlayerOrigin( cl_entity_t *clent );
|
||||
void CL_ProcessPacket( frame_t *frame );
|
||||
void CL_MoveThirdpersonCamera( void );
|
||||
qboolean CL_IsPlayerIndex( int idx );
|
||||
void CL_SetIdealPitch( void );
|
||||
void CL_EmitEntities( void );
|
||||
|
||||
@@ -1189,5 +1212,6 @@ int Key_ToUpper( int key );
|
||||
void OSK_Draw( void );
|
||||
|
||||
extern rgba_t g_color_table[8];
|
||||
extern triangleapi_t gTriApi;
|
||||
|
||||
#endif//CLIENT_H
|
||||
|
||||
@@ -2195,7 +2195,7 @@ void Con_VidInit( void )
|
||||
|
||||
Con_LoadConchars();
|
||||
Con_CheckResize();
|
||||
#if XASH_LOW_MEMORY
|
||||
#if XASH_LOW_MEMORY && !XASH_PSP
|
||||
con.background = R_GetBuiltinTexture( REF_BLACK_TEXTURE );
|
||||
#else
|
||||
// loading console image
|
||||
|
||||
@@ -19,6 +19,24 @@ GNU General Public License for more details.
|
||||
#include "vgui_draw.h"
|
||||
#include "mobility_int.h"
|
||||
|
||||
#ifdef XASH_NO_TOUCH
|
||||
|
||||
void Touch_WriteConfig( void ) {}
|
||||
void Touch_SetClientOnly( qboolean state ) {}
|
||||
void Touch_RemoveButton( const char *name ) {}
|
||||
void Touch_HideButtons( const char *name, byte hide ) {}
|
||||
void Touch_AddClientButton( const char *name, const char *texture, const char *command, float x1, float y1, float x2, float y2, byte *color, int round, float aspect, int flags ) {}
|
||||
void Touch_AddDefaultButton( const char *name, const char *texturefile, const char *command, float x1, float y1, float x2, float y2, byte *color, int round, float aspect, int flags ) {}
|
||||
void Touch_ResetDefaultButtons( void ){}
|
||||
void Touch_Init( void ) {}
|
||||
void Touch_Draw( void ) {}
|
||||
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy ) { return 0; }
|
||||
void Touch_GetMove( float *forward, float *side, float *yaw, float *pitch ) {}
|
||||
void Touch_KeyEvent( int key, int down ) {}
|
||||
void Touch_Shutdown( void ) {}
|
||||
|
||||
#else /* XASH_NO_TOUCH */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
touch_command, // just tap a button
|
||||
@@ -1529,7 +1547,6 @@ void Touch_Draw( void )
|
||||
ref.dllFuncs.R_DrawStretchPic( TO_SCRN_X( touch.move_start_x + touch.side * width - GRID_X * touch_move_indicator.value ),
|
||||
TO_SCRN_Y( touch.move_start_y - touch.forward * height - GRID_Y * touch_move_indicator.value ),
|
||||
TO_SCRN_X( GRID_X * 2 * touch_move_indicator.value ), TO_SCRN_Y( GRID_Y * 2 * touch_move_indicator.value ), 0, 0, 1, 1, touch.joytexture );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2191,3 +2208,5 @@ void Touch_Shutdown( void )
|
||||
touch.initialized = false;
|
||||
Mem_FreePool( &touch.mempool );
|
||||
}
|
||||
|
||||
#endif /* XASH_NO_TOUCH */
|
||||
|
||||
@@ -60,8 +60,10 @@ uint IN_CollectInputDevices( void )
|
||||
if( !m_ignore.value ) // no way to check is mouse connected, so use cvar only
|
||||
ret |= INPUT_DEVICE_MOUSE;
|
||||
|
||||
#ifndef XASH_NO_TOUCH
|
||||
if( touch_enable.value )
|
||||
ret |= INPUT_DEVICE_TOUCH;
|
||||
#endif
|
||||
|
||||
if( Joy_IsActive() ) // connected or enabled
|
||||
ret |= INPUT_DEVICE_JOYSTICK;
|
||||
@@ -91,13 +93,17 @@ void IN_LockInputDevices( qboolean lock )
|
||||
{
|
||||
SetBits( m_ignore.flags, FCVAR_READ_ONLY );
|
||||
SetBits( joy_enable.flags, FCVAR_READ_ONLY );
|
||||
#ifndef XASH_NO_TOUCH
|
||||
SetBits( touch_enable.flags, FCVAR_READ_ONLY );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearBits( m_ignore.flags, FCVAR_READ_ONLY );
|
||||
ClearBits( joy_enable.flags, FCVAR_READ_ONLY );
|
||||
#ifndef XASH_NO_TOUCH
|
||||
ClearBits( touch_enable.flags, FCVAR_READ_ONLY );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,11 +357,14 @@ void IN_MouseEvent( int key, int down )
|
||||
else ClearBits( in_mstate, BIT( key ));
|
||||
|
||||
// touch emulation overrides all input
|
||||
#if XASH_NO_TOUCH
|
||||
if( touch_emulate.value )
|
||||
{
|
||||
Touch_KeyEvent( K_MOUSE1 + key, down );
|
||||
}
|
||||
else if( cls.key_dest == key_game )
|
||||
else
|
||||
#endif
|
||||
if( cls.key_dest == key_game )
|
||||
{
|
||||
// perform button actions
|
||||
VGui_MouseEvent( K_MOUSE1 + key, down );
|
||||
@@ -364,8 +373,7 @@ void IN_MouseEvent( int key, int down )
|
||||
// client may override IN_MouseEvent
|
||||
// but by default it calls back to Key_Event anyway
|
||||
if( in_mouseactive )
|
||||
clgame.dllFuncs.IN_MouseEvent( in_mstate );
|
||||
}
|
||||
clgame.dllFuncs.IN_MouseEvent( in_mstate ); }
|
||||
else
|
||||
{
|
||||
// perform button actions
|
||||
|
||||
@@ -515,7 +515,6 @@ void Key_Init( void )
|
||||
|
||||
Cvar_RegisterVariable( &osk_enable );
|
||||
Cvar_RegisterVariable( &key_rotate );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -703,7 +702,11 @@ void GAME_EXPORT Key_Event( int key, int down )
|
||||
VGui_KeyEvent( key, down );
|
||||
|
||||
// console key is hardcoded, so the user can never unbind it
|
||||
#if XASH_PSP
|
||||
if( key == '`' || key == '~' || key == K_MODE_BUTTON )
|
||||
#else
|
||||
if( key == '`' || key == '~' )
|
||||
#endif
|
||||
{
|
||||
// we are in typing mode, so don't switch to console
|
||||
if( cls.key_dest == key_message || !down )
|
||||
@@ -714,7 +717,11 @@ void GAME_EXPORT Key_Event( int key, int down )
|
||||
}
|
||||
|
||||
// escape is always handled special
|
||||
#if XASH_PSP
|
||||
if( ( key == K_ESCAPE || key == K_START_BUTTON ) && down )
|
||||
#else
|
||||
if( key == K_ESCAPE && down )
|
||||
#endif
|
||||
{
|
||||
switch( cls.key_dest )
|
||||
{
|
||||
@@ -881,7 +888,11 @@ Normal keyboard characters, already shifted / capslocked / etc
|
||||
void CL_CharEvent( int key )
|
||||
{
|
||||
// the console key should never be used as a char
|
||||
#if XASH_PSP
|
||||
if( key == '`' || key == '~' || key == K_MODE_BUTTON ) return;
|
||||
#else
|
||||
if( key == '`' || key == '~' ) return;
|
||||
#endif
|
||||
|
||||
if( cls.key_dest == key_console && !Con_Visible( ))
|
||||
{
|
||||
@@ -1006,7 +1017,11 @@ static qboolean OSK_KeyEvent( int key, int down )
|
||||
|
||||
if( osk.curbutton.val == 0 )
|
||||
{
|
||||
#if XASH_PSP
|
||||
if( key == K_ENTER || key == K_A_BUTTON )
|
||||
#else
|
||||
if( key == K_ENTER )
|
||||
#endif
|
||||
{
|
||||
osk.curbutton.val = osk_keylayout[osk.curlayout][osk.curbutton.y][osk.curbutton.x];
|
||||
return true;
|
||||
@@ -1017,6 +1032,9 @@ static qboolean OSK_KeyEvent( int key, int down )
|
||||
|
||||
switch ( key )
|
||||
{
|
||||
#if XASH_PSP
|
||||
case K_A_BUTTON:
|
||||
#endif
|
||||
case K_ENTER:
|
||||
switch( osk.curbutton.val )
|
||||
{
|
||||
|
||||
@@ -323,6 +323,10 @@ static ref_api_t gEngfuncs =
|
||||
&clgame.drawFuncs,
|
||||
|
||||
&g_fsapi,
|
||||
#if XASH_PSP
|
||||
P5Ram_Alloc,
|
||||
P5Ram_Free,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void R_UnloadProgs( void )
|
||||
@@ -344,33 +348,8 @@ static void R_UnloadProgs( void )
|
||||
memset( &ref.dllFuncs, 0, sizeof( ref.dllFuncs ));
|
||||
}
|
||||
|
||||
static void CL_FillTriAPIFromRef( triangleapi_t *dst, const ref_interface_t *src )
|
||||
{
|
||||
dst->version = TRI_API_VERSION;
|
||||
dst->Begin = src->Begin;
|
||||
dst->RenderMode = TriRenderMode;
|
||||
dst->End = src->End;
|
||||
dst->Color4f = TriColor4f;
|
||||
dst->Color4ub = TriColor4ub;
|
||||
dst->TexCoord2f = src->TexCoord2f;
|
||||
dst->Vertex3f = src->Vertex3f;
|
||||
dst->Vertex3fv = src->Vertex3fv;
|
||||
dst->Brightness = TriBrightness;
|
||||
dst->CullFace = TriCullFace;
|
||||
dst->SpriteTexture = TriSpriteTexture;
|
||||
dst->WorldToScreen = TriWorldToScreen;
|
||||
dst->Fog = src->Fog;
|
||||
dst->ScreenToWorld = src->ScreenToWorld;
|
||||
dst->GetMatrix = src->GetMatrix;
|
||||
dst->BoxInPVS = TriBoxInPVS;
|
||||
dst->LightAtPoint = TriLightAtPoint;
|
||||
dst->Color4fRendermode = TriColor4fRendermode;
|
||||
dst->FogParams = src->FogParams;
|
||||
}
|
||||
|
||||
static qboolean R_LoadProgs( const char *name )
|
||||
{
|
||||
extern triangleapi_t gTriApi;
|
||||
static ref_api_t gpEngfuncs;
|
||||
REFAPI GetRefAPI; // single export
|
||||
|
||||
@@ -415,12 +394,18 @@ static qboolean R_LoadProgs( const char *name )
|
||||
return false;
|
||||
}
|
||||
|
||||
// initialize TriAPI callbacks
|
||||
if( !ref.dllFuncs.getTriAPI( TRI_API_VERSION, &gTriApi ))
|
||||
{
|
||||
COM_FreeLibrary( ref.hInstance );
|
||||
Con_Reportf( "R_LoadProgs: can't init TriAPI Interface: wrong version, %i must be %i\n", gTriApi.version, TRI_API_VERSION );
|
||||
ref.hInstance = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
Cvar_FullSet( "host_refloaded", "1", FCVAR_READ_ONLY );
|
||||
ref.initialized = true;
|
||||
|
||||
// initialize TriAPI callbacks
|
||||
CL_FillTriAPIFromRef( &gTriApi, &ref.dllFuncs );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,11 @@ GNU General Public License for more details.
|
||||
// than could actually be referenced during gameplay,
|
||||
// because we don't want to free anything until we are
|
||||
// sure we won't need it.
|
||||
#if XASH_PSP
|
||||
#define MAX_SFX 2048
|
||||
#else
|
||||
#define MAX_SFX 8192
|
||||
#endif
|
||||
#define MAX_SFX_HASH (MAX_SFX/4)
|
||||
|
||||
static int s_numSfx = 0;
|
||||
|
||||
@@ -201,9 +201,15 @@ typedef struct
|
||||
|
||||
//====================================================================
|
||||
|
||||
#if XASH_PSP
|
||||
#define MAX_DYNAMIC_CHANNELS (20 + NUM_AMBIENTS)
|
||||
#define MAX_CHANNELS (128 + MAX_DYNAMIC_CHANNELS)
|
||||
#define MAX_RAW_CHANNELS 16
|
||||
#else
|
||||
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
|
||||
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
|
||||
#define MAX_RAW_CHANNELS 48
|
||||
#endif
|
||||
#define MAX_RAW_SAMPLES 8192
|
||||
|
||||
extern sound_t ambient_sfx[NUM_AMBIENTS];
|
||||
|
||||
175
engine/common/build.c
Normal file
175
engine/common/build.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
build.c - returns a engine build number
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static char *date = __DATE__ ;
|
||||
static char *mon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
static char mond[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
// returns days since Apr 1 2015
|
||||
int Q_buildnum( void )
|
||||
{
|
||||
int m = 0, d = 0, y = 0;
|
||||
static int b = 0;
|
||||
|
||||
if( b != 0 ) return b;
|
||||
|
||||
for( m = 0; m < 11; m++ )
|
||||
{
|
||||
if( !Q_strnicmp( &date[0], mon[m], 3 ))
|
||||
break;
|
||||
d += mond[m];
|
||||
}
|
||||
|
||||
d += Q_atoi( &date[4] ) - 1;
|
||||
y = Q_atoi( &date[7] ) - 1900;
|
||||
b = d + (int)((y - 1) * 365.25f );
|
||||
|
||||
if((( y % 4 ) == 0 ) && m > 1 )
|
||||
{
|
||||
b += 1;
|
||||
}
|
||||
b -= 41728; // Apr 1 2015
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Q_buildnum_compat
|
||||
|
||||
Returns a Xash3D build number. This is left for compability with original Xash3D.
|
||||
IMPORTANT: this value must be changed ONLY after updating to newer Xash3D
|
||||
IMPORTANT: this value must be acquired through "build" cvar.
|
||||
=============
|
||||
*/
|
||||
int Q_buildnum_compat( void )
|
||||
{
|
||||
// do not touch this! Only author of Xash3D can increase buildnumbers!
|
||||
return 4529;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Q_buildos
|
||||
|
||||
Returns current name of operating system. Without any spaces.
|
||||
============
|
||||
*/
|
||||
const char *Q_buildos( void )
|
||||
{
|
||||
const char *osname;
|
||||
|
||||
#if XASH_MINGW
|
||||
osname = "win32-mingw";
|
||||
#elif XASH_WIN32
|
||||
osname = "win32";
|
||||
#elif XASH_ANDROID
|
||||
osname = "android";
|
||||
#elif XASH_LINUX
|
||||
osname = "linux";
|
||||
#elif XASH_APPLE
|
||||
osname = "apple";
|
||||
#elif XASH_FREEBSD
|
||||
osname = "freebsd";
|
||||
#elif XASH_NETBSD
|
||||
osname = "netbsd";
|
||||
#elif XASH_OPENBSD
|
||||
osname = "openbsd";
|
||||
#elif XASH_EMSCRIPTEN
|
||||
osname = "emscripten";
|
||||
#elif XASH_DOS4GW
|
||||
osname = "DOS4GW";
|
||||
#elif XASH_PSP
|
||||
osname = "psp";
|
||||
#else
|
||||
#error "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug"
|
||||
#endif
|
||||
|
||||
return osname;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Q_buildos
|
||||
|
||||
Returns current name of operating system. Without any spaces.
|
||||
============
|
||||
*/
|
||||
const char *Q_buildarch( void )
|
||||
{
|
||||
const char *archname;
|
||||
|
||||
#if XASH_AMD64
|
||||
archname = "amd64";
|
||||
#elif XASH_X86
|
||||
archname = "i386";
|
||||
#elif XASH_ARM && XASH_64BIT
|
||||
archname = "arm64";
|
||||
#elif XASH_ARM
|
||||
archname = "armv"
|
||||
#if XASH_ARM == 8
|
||||
"8_32" // for those who (mis)using 32-bit OS on 64-bit CPU
|
||||
#elif XASH_ARM == 7
|
||||
"7"
|
||||
#elif XASH_ARM == 6
|
||||
"6"
|
||||
#elif XASH_ARM == 5
|
||||
"5"
|
||||
#elif XASH_ARM == 4
|
||||
"4"
|
||||
#endif
|
||||
|
||||
#if XASH_ARM_HARDFP
|
||||
"hf";
|
||||
#else
|
||||
"l";
|
||||
#endif
|
||||
#elif XASH_MIPS && defined XASH_BIG_ENDIAN
|
||||
archname = "mips";
|
||||
#elif XASH_MIPS && defined XASH_LITTLE_ENDIAN
|
||||
archname = "mipsel";
|
||||
#elif XASH_JS
|
||||
archname = "javascript";
|
||||
#elif XASH_E2K
|
||||
archname = "e2k";
|
||||
#else
|
||||
#error "Place your architecture name here! If this is a mistake, try to fix conditions above and report a bug"
|
||||
#endif
|
||||
|
||||
return archname;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Q_buildcommit
|
||||
|
||||
Returns a short hash of current commit in VCS as string.
|
||||
XASH_BUILD_COMMIT must be passed in quotes
|
||||
|
||||
if XASH_BUILD_COMMIT is not defined,
|
||||
Q_buildcommit will identify this build as "notset"
|
||||
=============
|
||||
*/
|
||||
const char *Q_buildcommit( void )
|
||||
{
|
||||
#ifdef XASH_BUILD_COMMIT
|
||||
return XASH_BUILD_COMMIT;
|
||||
#else
|
||||
return "notset";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ typedef enum
|
||||
#define MAX_DECALS 256 // touching TE_DECAL messages, etc
|
||||
#define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define GameState (&host.game)
|
||||
|
||||
@@ -723,7 +724,6 @@ int R_CreateDecalList( struct decallist_s *pList );
|
||||
void R_ClearAllDecals( void );
|
||||
void CL_ClearStaticEntities( void );
|
||||
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position );
|
||||
struct cl_entity_s *CL_GetEntityByIndex( int index );
|
||||
void CL_ServerCommand( qboolean reliable, const char *fmt, ... ) _format( 2 );
|
||||
void CL_HudMessage( const char *pMessage );
|
||||
const char *CL_MsgInfo( int cmd );
|
||||
|
||||
4556
engine/common/filesystem.c
Normal file
4556
engine/common/filesystem.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1064,10 +1064,10 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
|
||||
|
||||
// init host state machine
|
||||
COM_InitHostState();
|
||||
|
||||
#ifdef XASH_HASHED_VARS
|
||||
// init hashed commands
|
||||
BaseCmd_Init();
|
||||
|
||||
#endif
|
||||
// startup cmds and cvars subsystem
|
||||
Cmd_Init();
|
||||
Cvar_Init();
|
||||
@@ -1110,6 +1110,8 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
|
||||
Sys_Error( "couldn't find xash3d data directory" );
|
||||
host.rootdir[0] = 0;
|
||||
}
|
||||
#elif XASH_PSP
|
||||
COM_ExtractFilePath( argv[0], host.rootdir );
|
||||
#elif (XASH_SDL == 2) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
|
||||
char *szBasePath = SDL_GetBasePath();
|
||||
if( szBasePath )
|
||||
|
||||
@@ -24,7 +24,7 @@ Image_LoadTGA
|
||||
*/
|
||||
qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
int i, columns, rows, row_inc, row, col;
|
||||
int i, columns, rows, row_inc, row, col, bpp = 1;
|
||||
byte *buf_p, *pixbuf, *targa_rgba;
|
||||
rgba_t palette[256];
|
||||
byte red = 0, green = 0, blue = 0, alpha = 0;
|
||||
@@ -32,6 +32,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
int reflectivity[3] = { 0, 0, 0 };
|
||||
qboolean compressed;
|
||||
tga_t targa_header;
|
||||
int palIndex = 0;
|
||||
|
||||
if( filesize < sizeof( tga_t ))
|
||||
return false;
|
||||
@@ -55,8 +56,6 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
// check for tga file
|
||||
if( !Image_ValidSize( name )) return false;
|
||||
|
||||
image.type = PF_RGBA_32; // always exctracted to 32-bit buffer
|
||||
|
||||
if( targa_header.image_type == 1 || targa_header.image_type == 9 )
|
||||
{
|
||||
// uncompressed colormapped image
|
||||
@@ -119,11 +118,35 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) Type %i not supported\n", name, targa_header.image_type );
|
||||
return false;
|
||||
}
|
||||
|
||||
columns = targa_header.width;
|
||||
rows = targa_header.height;
|
||||
|
||||
image.size = image.width * image.height * 4;
|
||||
if( Image_CheckFlag( IL_KEEP_8BIT ) && ( targa_header.image_type == 1 || targa_header.image_type == 9 ))
|
||||
{
|
||||
pixbuf = image.palette = Mem_Malloc( host.imagepool, 1024 );
|
||||
for( i = 0; i < targa_header.colormap_length; i++ )
|
||||
{
|
||||
*pixbuf++ = palette[i][0];
|
||||
*pixbuf++ = palette[i][1];
|
||||
*pixbuf++ = palette[i][2];
|
||||
*pixbuf++ = palette[i][3];
|
||||
}
|
||||
image.type = PF_INDEXED_32;
|
||||
}
|
||||
else
|
||||
{
|
||||
image.palette = NULL;
|
||||
image.type = PF_RGBA_32;
|
||||
bpp = 4;
|
||||
}
|
||||
|
||||
image.size = image.width * image.height * bpp;
|
||||
targa_rgba = image.rgba = Mem_Malloc( host.imagepool, image.size );
|
||||
|
||||
// if bit 5 of attributes isn't set, the image has been stored from bottom to top
|
||||
@@ -134,8 +157,8 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
}
|
||||
else
|
||||
{
|
||||
pixbuf = targa_rgba + ( rows - 1 ) * columns * 4;
|
||||
row_inc = -columns * 4 * 2;
|
||||
pixbuf = targa_rgba + ( rows - 1 ) * columns * bpp;
|
||||
row_inc = -columns * bpp * 2;
|
||||
}
|
||||
|
||||
compressed = ( targa_header.image_type == 9 || targa_header.image_type == 10 || targa_header.image_type == 11 );
|
||||
@@ -161,13 +184,13 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
case 1:
|
||||
case 9:
|
||||
// colormapped image
|
||||
blue = *buf_p++;
|
||||
if( blue < targa_header.colormap_length )
|
||||
palIndex = *buf_p++;
|
||||
if( palIndex < targa_header.colormap_length )
|
||||
{
|
||||
red = palette[blue][0];
|
||||
green = palette[blue][1];
|
||||
alpha = palette[blue][3];
|
||||
blue = palette[blue][2];
|
||||
red = palette[palIndex][0];
|
||||
green = palette[palIndex][1];
|
||||
blue = palette[palIndex][2];
|
||||
alpha = palette[palIndex][3];
|
||||
if( alpha != 255 ) image.flags |= IMAGE_HAS_ALPHA;
|
||||
}
|
||||
break;
|
||||
@@ -208,10 +231,18 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
reflectivity[1] += green;
|
||||
reflectivity[2] += blue;
|
||||
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = alpha;
|
||||
if( image.type == PF_INDEXED_32 || image.type == PF_INDEXED_24 )
|
||||
{
|
||||
*pixbuf++ = palIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = alpha;
|
||||
}
|
||||
|
||||
if( ++col == columns )
|
||||
{
|
||||
// run spans across rows
|
||||
@@ -223,6 +254,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
}
|
||||
|
||||
VectorDivide( reflectivity, ( image.width * image.height ), image.fogParams );
|
||||
if( image.palette ) Image_GetPaletteBMP( image.palette );
|
||||
image.depth = 1;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -93,6 +93,23 @@ static const loadpixformat_t load_null[] =
|
||||
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||
};
|
||||
|
||||
// a1ba: that's weird, better debug
|
||||
#if XASH_PSP
|
||||
static const loadpixformat_t load_game[] =
|
||||
{
|
||||
{ "%s%s.%s", "mip", Image_LoadMIP, IL_HINT_NO }, // hl textures from wad or buffer
|
||||
{ "%s%s.%s", "mdl", Image_LoadMDL, IL_HINT_HL }, // hl studio model skins
|
||||
{ "%s%s.%s", "spr", Image_LoadSPR, IL_HINT_HL }, // hl sprite frames
|
||||
{ "%s%s.%s", "lmp", Image_LoadLMP, IL_HINT_NO }, // hl menu images (cached.wad etc)
|
||||
{ "%s%s.%s", "fnt", Image_LoadFNT, IL_HINT_HL }, // hl console font (fonts.wad etc)
|
||||
{ "%s%s.%s", "pal", Image_LoadPAL, IL_HINT_NO }, // install studio\sprite palette
|
||||
{ "%s%s.%s", "dds", Image_LoadDDS, IL_HINT_NO }, // dds for world and studio models
|
||||
{ "%s%s.%s", "tga", Image_LoadTGA, IL_HINT_NO }, // hl vgui menus
|
||||
{ "%s%s.%s", "bmp", Image_LoadBMP, IL_HINT_NO }, // WON menu images
|
||||
{ "%s%s.%s", "png", Image_LoadPNG, IL_HINT_NO }, // NightFire 007 menus
|
||||
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||
};
|
||||
#else
|
||||
static const loadpixformat_t load_game[] =
|
||||
{
|
||||
{ "%s%s.%s", "dds", Image_LoadDDS, IL_HINT_NO }, // dds for world and studio models
|
||||
@@ -108,7 +125,7 @@ static const loadpixformat_t load_game[] =
|
||||
{ "%s%s.%s", "ktx2", Image_LoadKTX2, IL_HINT_NO }, // ktx2 for world and studio models
|
||||
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||
};
|
||||
|
||||
#endif
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
|
||||
@@ -34,7 +34,13 @@ GNU General Public License for more details.
|
||||
|
||||
static char szGameDir[128]; // safe place to keep gamedir
|
||||
static int szArgc;
|
||||
|
||||
#if XASH_PSP
|
||||
#define MAX_NARGVS 50
|
||||
static char *szArgv[MAX_NARGVS];
|
||||
#else
|
||||
static char **szArgv;
|
||||
#endif
|
||||
|
||||
static void Sys_ChangeGame( const char *progname )
|
||||
{
|
||||
@@ -71,20 +77,23 @@ static int Sys_Start( void )
|
||||
#endif
|
||||
#elif XASH_IOS
|
||||
IOS_LaunchDialog();
|
||||
#endif
|
||||
#elif XASH_PSP
|
||||
|
||||
return Host_Main( szArgc, szArgv, game, 0, Sys_ChangeGame );
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
#if XASH_PSVITA
|
||||
#if XASH_PSP
|
||||
Platform_ReadCmd( "start.cmd", &szArgc, szArgv );
|
||||
#elif XASH_PSVITA
|
||||
// inject -dev -console into args if required
|
||||
szArgc = PSVita_GetArgv( argc, argv, &szArgv );
|
||||
#else
|
||||
szArgc = argc;
|
||||
szArgv = argv;
|
||||
#endif // XASH_PSVITA
|
||||
|
||||
return Sys_Start();
|
||||
}
|
||||
#endif // XASH_ENABLE_MAIN
|
||||
|
||||
@@ -38,6 +38,7 @@ void COM_PushLibraryError( const char *error )
|
||||
Q_strncat( s_szLastError, error, sizeof( s_szLastError ) );
|
||||
}
|
||||
|
||||
#if !XASH_PSP
|
||||
void *COM_FunctionFromName_SR( void *hInstance, const char *pName )
|
||||
{
|
||||
char **funcs = NULL;
|
||||
@@ -85,6 +86,7 @@ const char *COM_OffsetNameForFunction( void *function )
|
||||
Con_Reportf( "COM_OffsetNameForFunction %s\n", sname );
|
||||
return sname;
|
||||
}
|
||||
#endif
|
||||
|
||||
dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
|
||||
{
|
||||
@@ -128,7 +130,7 @@ dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
|
||||
|
||||
static void COM_GenerateCommonLibraryName( const char *name, const char *ext, char *out, size_t size )
|
||||
{
|
||||
#if ( XASH_WIN32 || XASH_LINUX || XASH_APPLE ) && XASH_X86
|
||||
#if (( XASH_WIN32 || XASH_LINUX || XASH_APPLE ) && XASH_X86) || XASH_PSP
|
||||
Q_snprintf( out, size, "%s.%s", name, ext );
|
||||
#elif ( XASH_WIN32 || XASH_LINUX || XASH_APPLE )
|
||||
Q_snprintf( out, size, "%s_%s.%s", name, Q_buildarch(), ext );
|
||||
@@ -191,6 +193,8 @@ static void COM_GenerateServerLibraryPath( char *out, size_t size )
|
||||
Q_strncpy( out, GI->game_dll, size );
|
||||
#elif XASH_APPLE
|
||||
Q_strncpy( out, GI->game_dll_osx, size );
|
||||
#elif XASH_PSP
|
||||
Q_strncpy( out, GI->game_dll_psp, size );
|
||||
#else // XASH_LINUX
|
||||
Q_strncpy( out, GI->game_dll_linux, size );
|
||||
#endif
|
||||
@@ -203,6 +207,8 @@ static void COM_GenerateServerLibraryPath( char *out, size_t size )
|
||||
Q_strncpy( dllpath, GI->game_dll, sizeof( dllpath ) );
|
||||
#elif XASH_APPLE
|
||||
Q_strncpy( dllpath, GI->game_dll_osx, sizeof( dllpath ) );
|
||||
#elif XASH_PSP
|
||||
Q_strncpy( dllpath, GI->game_dll_psp, sizeof( dllpath ) );
|
||||
#else // XASH_APPLE
|
||||
Q_strncpy( dllpath, GI->game_dll_linux, sizeof( dllpath ) );
|
||||
#endif
|
||||
|
||||
@@ -1735,12 +1735,16 @@ static void Mod_LoadSubmodels( model_t *mod, dbspmodel_t *bmod )
|
||||
oldmaxfaces = Q_max( oldmaxfaces, out->numfaces );
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
refState.max_surfaces = 0; // sorting disabled
|
||||
#else
|
||||
// these array used to sort translucent faces in bmodels
|
||||
if( oldmaxfaces > refState.max_surfaces )
|
||||
{
|
||||
refState.draw_surfaces = (sortedface_t *)Z_Realloc( refState.draw_surfaces, oldmaxfaces * sizeof( sortedface_t ));
|
||||
refState.max_surfaces = oldmaxfaces;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -151,17 +151,6 @@ void MSG_Clear( sizebuf_t *sb )
|
||||
sb->bOverflow = false;
|
||||
}
|
||||
|
||||
static qboolean MSG_Overflow( sizebuf_t *sb, int nBits )
|
||||
{
|
||||
if( sb->iCurBit + nBits > sb->nDataBits )
|
||||
sb->bOverflow = true;
|
||||
return sb->bOverflow;
|
||||
}
|
||||
|
||||
qboolean MSG_CheckOverflow( sizebuf_t *sb )
|
||||
{
|
||||
return MSG_Overflow( sb, 0 );
|
||||
}
|
||||
|
||||
int MSG_SeekToBit( sizebuf_t *sb, int bitPos, int whence )
|
||||
{
|
||||
@@ -193,17 +182,6 @@ void MSG_SeekToByte( sizebuf_t *sb, int bytePos )
|
||||
sb->iCurBit = bytePos << 3;
|
||||
}
|
||||
|
||||
void MSG_WriteOneBit( sizebuf_t *sb, int nValue )
|
||||
{
|
||||
if( !MSG_Overflow( sb, 1 ))
|
||||
{
|
||||
if( nValue ) sb->pData[sb->iCurBit>>3] |= BIT( sb->iCurBit & 7 );
|
||||
else sb->pData[sb->iCurBit>>3] &= ~BIT( sb->iCurBit & 7 );
|
||||
|
||||
sb->iCurBit++;
|
||||
}
|
||||
}
|
||||
|
||||
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits )
|
||||
{
|
||||
Assert( numbits >= 0 && numbits <= 32 );
|
||||
|
||||
@@ -64,6 +64,19 @@ _inline int MSG_TellBit( sizebuf_t *sb ) { return sb->iCurBit; }
|
||||
_inline const char *MSG_GetName( sizebuf_t *sb ) { return sb->pDebugName; }
|
||||
qboolean MSG_CheckOverflow( sizebuf_t *sb );
|
||||
|
||||
static inline qboolean MSG_Overflow( sizebuf_t *sb, int nBits )
|
||||
{
|
||||
if( sb->iCurBit + nBits > sb->nDataBits )
|
||||
sb->bOverflow = true;
|
||||
return sb->bOverflow;
|
||||
}
|
||||
|
||||
static inline MSG_CheckOverflow( sizebuf_t *sb )
|
||||
{
|
||||
return MSG_Overflow( sb, 0 );
|
||||
}
|
||||
|
||||
|
||||
#if XASH_BIG_ENDIAN
|
||||
#define MSG_BigShort( x ) ( x )
|
||||
#else
|
||||
@@ -78,7 +91,16 @@ void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, in
|
||||
void MSG_Clear( sizebuf_t *sb );
|
||||
|
||||
// Bit-write functions
|
||||
void MSG_WriteOneBit( sizebuf_t *sb, int nValue );
|
||||
static inline void MSG_WriteOneBit( sizebuf_t *sb, int nValue )
|
||||
{
|
||||
if( likely( !MSG_Overflow( sb, 1 )))
|
||||
{
|
||||
if( nValue ) sb->pData[sb->iCurBit>>3] |= BIT( sb->iCurBit & 7 );
|
||||
else sb->pData[sb->iCurBit>>3] &= ~BIT( sb->iCurBit & 7 );
|
||||
|
||||
sb->iCurBit++;
|
||||
}
|
||||
}
|
||||
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits );
|
||||
void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits );
|
||||
void MSG_WriteBitLong( sizebuf_t *sb, uint data, int numbits, qboolean bSigned );
|
||||
|
||||
@@ -1095,7 +1095,6 @@ int Delta_TestBaseline( entity_state_t *from, entity_state_t *to, qboolean playe
|
||||
if( from == NULL ) return 0;
|
||||
return countBits;
|
||||
}
|
||||
|
||||
if( FBitSet( to->entityType, ENTITY_BEAM ))
|
||||
dt = Delta_FindStructByIndex( DT_CUSTOM_ENTITY_STATE_T );
|
||||
else if( player )
|
||||
@@ -1793,7 +1792,6 @@ void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *
|
||||
numChanges++;
|
||||
}
|
||||
else MSG_WriteOneBit( msg, 0 );
|
||||
|
||||
if( FBitSet( to->entityType, ENTITY_BEAM ))
|
||||
{
|
||||
dt = Delta_FindStructByIndex( DT_CUSTOM_ENTITY_STATE_T );
|
||||
@@ -1806,7 +1804,6 @@ void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *
|
||||
{
|
||||
dt = Delta_FindStructByIndex( DT_ENTITY_STATE_T );
|
||||
}
|
||||
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
@@ -1924,7 +1921,6 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state
|
||||
{
|
||||
dt = Delta_FindStructByIndex( DT_ENTITY_STATE_T );
|
||||
}
|
||||
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
|
||||
@@ -356,7 +356,7 @@ qboolean NET_GetHostByName( const char *hostname, int family, struct sockaddr_st
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !XASH_EMSCRIPTEN && !XASH_DOS4GW && !defined XASH_NO_ASYNC_NS_RESOLVE
|
||||
#if !XASH_EMSCRIPTEN && !XASH_DOS4GW && !XASH_PSP && !defined XASH_NO_ASYNC_NS_RESOLVE
|
||||
#define CAN_ASYNC_NS_RESOLVE
|
||||
#endif // !XASH_EMSCRIPTEN && !XASH_DOS4GW && !defined XASH_NO_ASYNC_NS_RESOLVE
|
||||
|
||||
|
||||
@@ -86,7 +86,18 @@ GNU General Public License for more details.
|
||||
#define NETSPLIT_BACKUP 8
|
||||
#define NETSPLIT_BACKUP_MASK (NETSPLIT_BACKUP - 1)
|
||||
#define NETSPLIT_HEADER_SIZE 18
|
||||
|
||||
#if XASH_PSP
|
||||
#undef MULTIPLAYER_BACKUP
|
||||
#undef SINGLEPLAYER_BACKUP
|
||||
#undef NUM_PACKET_ENTITIES
|
||||
#undef MAX_CUSTOM_BASELINES
|
||||
#undef NET_MAX_FRAGMENT
|
||||
#define MULTIPLAYER_BACKUP 16
|
||||
#define SINGLEPLAYER_BACKUP 16
|
||||
#define NUM_PACKET_ENTITIES 32
|
||||
#define MAX_CUSTOM_BASELINES 8
|
||||
#define NET_MAX_FRAGMENT 32768
|
||||
#else
|
||||
#if XASH_LOW_MEMORY == 2
|
||||
#undef MULTIPLAYER_BACKUP
|
||||
#undef SINGLEPLAYER_BACKUP
|
||||
@@ -108,7 +119,7 @@ GNU General Public License for more details.
|
||||
#define MAX_CUSTOM_BASELINES 8
|
||||
#define NET_MAX_FRAGMENT 32768
|
||||
#endif
|
||||
|
||||
#endif /* XASH_PSP */
|
||||
typedef struct netsplit_chain_packet_s
|
||||
{
|
||||
// bool vector
|
||||
|
||||
@@ -177,6 +177,29 @@ GNU General Public License for more details.
|
||||
#define FRAGMENT_MAX_SIZE 64000 // maximal fragment size
|
||||
#define FRAGMENT_LOCAL_SIZE FRAGMENT_MAX_SIZE // local connection
|
||||
|
||||
#if XASH_PSP
|
||||
|
||||
#undef MAX_VISIBLE_PACKET
|
||||
#undef MAX_VISIBLE_PACKET_VIS_BYTES
|
||||
#undef MAX_EVENTS
|
||||
#undef MAX_SUPPORTED_MODELS
|
||||
#undef MAX_MODELS
|
||||
#undef MAX_SOUNDS
|
||||
#undef MAX_CUSTOM
|
||||
#undef MAX_RENDER_DECALS
|
||||
#undef MAX_RESOURCES
|
||||
|
||||
#define MAX_VISIBLE_PACKET 256
|
||||
#define MAX_VISIBLE_PACKET_VIS_BYTES ((MAX_VISIBLE_PACKET + 7) / 8)
|
||||
#define MAX_EVENTS 256
|
||||
#define MAX_SUPPORTED_MODELS 512
|
||||
#define MAX_MODELS MAX_SUPPORTED_MODELS
|
||||
#define MAX_SOUNDS 512
|
||||
#define MAX_CUSTOM 32
|
||||
#define MAX_RENDER_DECALS 256
|
||||
#define MAX_RESOURCES (MAX_MODELS+MAX_SOUNDS+MAX_CUSTOM+MAX_EVENTS)
|
||||
|
||||
#else
|
||||
#if XASH_LOW_MEMORY == 2
|
||||
#undef MAX_VISIBLE_PACKET
|
||||
#undef MAX_VISIBLE_PACKET_VIS_BYTES
|
||||
@@ -215,7 +238,7 @@ GNU General Public License for more details.
|
||||
#define MAX_RENDER_DECALS 128
|
||||
#define MAX_RESOURCES 1024
|
||||
#endif
|
||||
|
||||
#endif /* XASH_PSP */
|
||||
// Quake1 Protocol
|
||||
#define PROTOCOL_VERSION_QUAKE 15
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size )
|
||||
fs_offset_t filesize = 0;
|
||||
const loadwavfmt_t *format;
|
||||
byte *f;
|
||||
|
||||
|
||||
Sound_Reset(); // clear old sounddata
|
||||
Q_strncpy( loadname, filename, sizeof( loadname ));
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ 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.
|
||||
*/
|
||||
|
||||
#include "soundlib.h"
|
||||
#if !XASH_PSP
|
||||
#include "libmpg/libmpg.h"
|
||||
|
||||
#pragma pack( push, 1 )
|
||||
@@ -455,3 +455,485 @@ void Stream_FreeMPG( stream_t *stream )
|
||||
|
||||
Mem_Free( stream );
|
||||
}
|
||||
|
||||
#else // XASH_PSP
|
||||
#include "platform/psp/scemp3/pspmp3.h"
|
||||
|
||||
/*
|
||||
=================================================================
|
||||
|
||||
PSP MPEG decoding
|
||||
|
||||
=================================================================
|
||||
*/
|
||||
#define MP3_ID3V1_ID "TAG"
|
||||
#define MP3_ID3V1_ID_SZ 3
|
||||
#define MP3_ID3V1_SZ 128
|
||||
|
||||
#define MP3_ID3V2_ID "ID3"
|
||||
#define MP3_ID3V2_ID_SZ 3
|
||||
#define MP3_ID3V2_SIZE_OFF 6
|
||||
#define MP3_ID3V2_SIZE_SZ 4
|
||||
#define MP3_ID3V2_HEADER_SZ 10
|
||||
|
||||
#define MP3_ERRORS_MAX 3
|
||||
|
||||
#define PCM_WIDTH 2 // always 16-bit PCM
|
||||
#define PCM_CHANNELS 2 // always 2
|
||||
|
||||
#define MP3_BUFFER_SIZE ( 128 * 1024 )
|
||||
#define PCM_BUFFER_SIZE (( 1152 * PCM_WIDTH * PCM_CHANNELS ) * 2 ) // framesample * width * channels * 2(double buffer)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int handle;
|
||||
int cachePos;
|
||||
int frameCount;
|
||||
byte *pcmTempPtr;
|
||||
} mp3_decoder_t;
|
||||
|
||||
/*
|
||||
=================
|
||||
Sound_GetID3V2SizeMPG
|
||||
=================
|
||||
*/
|
||||
__inline int Sound_GetID3V2SizeMPG( const byte *tagSize )
|
||||
{
|
||||
int size;
|
||||
byte *sizePtr = (byte*)&size;
|
||||
|
||||
// 7 bit per byte, invert endian
|
||||
sizePtr[0] = (( tagSize[3] >> 0 ) & 0x7F ) | (( tagSize[2] & 0x01 ) << 7 );
|
||||
sizePtr[1] = (( tagSize[2] >> 1 ) & 0x3F ) | (( tagSize[1] & 0x03 ) << 6 );
|
||||
sizePtr[2] = (( tagSize[1] >> 2 ) & 0x1F ) | (( tagSize[0] & 0x07 ) << 5 );
|
||||
sizePtr[3] = (( tagSize[0] >> 3 ) & 0x0F );
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
=================
|
||||
Sound_FindHeadMPG
|
||||
=================
|
||||
*/
|
||||
fs_offset_t Sound_FindHeadMPG( const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
fs_offset_t result;
|
||||
|
||||
result = 0;
|
||||
if( filesize >= MP3_ID3V2_HEADER_SZ )
|
||||
{
|
||||
if( !memcmp( buffer, MP3_ID3V2_ID, MP3_ID3V2_ID_SZ ))
|
||||
result = Sound_GetID3V2SizeMPG( &buffer[MP3_ID3V2_SIZE_OFF] ) + MP3_ID3V2_HEADER_SZ;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sound_FindTailMPG
|
||||
=================
|
||||
*/
|
||||
fs_offset_t Sound_FindTailMPG( const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
fs_offset_t result;
|
||||
|
||||
result = filesize;
|
||||
if( filesize >= MP3_ID3V1_SZ )
|
||||
{
|
||||
if( !memcmp( &buffer[filesize - MP3_ID3V1_SZ], MP3_ID3V1_ID, MP3_ID3V1_ID_SZ ))
|
||||
result -= MP3_ID3V1_SZ;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
qboolean Sound_LoadMPG( const char *name, const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
#if 0
|
||||
int status;
|
||||
int handle;
|
||||
size_t bytesWrite = 0;
|
||||
byte out[PCM_BUFFER_SIZE] __attribute__((aligned(64)));
|
||||
fs_offset_t headOffset;
|
||||
fs_offset_t tailOffset;
|
||||
fs_offset_t contentSize;
|
||||
int frameSample;
|
||||
uint bps;
|
||||
int frameLen;
|
||||
int frameSize;
|
||||
int frameCount;
|
||||
|
||||
headOffset = Sound_FindHeadMPG( buffer, filesize );
|
||||
tailOffset = Sound_FindTailMPG( buffer, filesize );
|
||||
contentSize = tailOffset - headOffset;
|
||||
// TODO: read Xing header
|
||||
|
||||
handle = sceMp3ReserveMp3Handle( NULL );
|
||||
if ( handle < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3ReserveMp3Handle returned 0x%08X\n", handle );
|
||||
return false;
|
||||
}
|
||||
|
||||
status = sceMp3LowLevelInit( handle, &buffer[headOffset] );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3LowLevelInit returned 0x%08X\n", status );
|
||||
return false;
|
||||
}
|
||||
|
||||
frameSample = sceMp3GetMaxOutputSample( handle );
|
||||
frameSize = (( frameSample / 8 ) * sceMp3GetBitRate( handle ) * 1000 ) / sceMp3GetSamplingRate( handle );
|
||||
frameCount = contentSize / frameSize;
|
||||
|
||||
sound.channels = sceMp3GetMp3ChannelNum( handle );
|
||||
sound.rate = sceMp3GetSamplingRate( handle );
|
||||
sound.width = PCM_WIDTH; // always 16-bit PCM
|
||||
sound.loopstart = -1;
|
||||
sound.size = (frameCount * frameSample) * sound.channels * sound.width; // invalid for VBR
|
||||
/*
|
||||
status = sceMp3LowLevelDecode(handle, &buffer[headOffset + mp3usedsize], &mp3usedsize, pcm, &pcmoutsize);
|
||||
if(status < 0)
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3LowLevelDecode returned 0x%08X\n", status);
|
||||
}
|
||||
sceMp3ReleaseMp3Handle( handle );
|
||||
*/
|
||||
return true;
|
||||
#else
|
||||
Con_DPrintf( S_ERROR "Sound_LoadMPG unimplemented function!\n");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_FindHeadMPG
|
||||
=================
|
||||
*/
|
||||
SceOff Stream_FindHeadMPG( file_t *file )
|
||||
{
|
||||
SceOff result;
|
||||
byte tagId[MP3_ID3V2_ID_SZ];
|
||||
byte tagSize[MP3_ID3V2_SIZE_SZ];
|
||||
|
||||
result = 0;
|
||||
|
||||
FS_Seek( file, 0, SEEK_SET );
|
||||
|
||||
if( FS_Read( file, tagId, MP3_ID3V2_ID_SZ) < MP3_ID3V2_ID_SZ )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Sound_Mp3FindHead: ID3V2 ID read error\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
if( !memcmp( tagId, MP3_ID3V2_ID, MP3_ID3V2_ID_SZ ))
|
||||
{
|
||||
FS_Seek( file, MP3_ID3V2_SIZE_OFF, SEEK_SET );
|
||||
if( FS_Read( file, tagSize, MP3_ID3V2_SIZE_SZ ) < MP3_ID3V2_SIZE_SZ )
|
||||
Con_DPrintf( S_ERROR "Sound_Mp3FindHead: ID3V2 SIZE read error\n");
|
||||
else result = Sound_GetID3V2SizeMPG( tagSize ) + MP3_ID3V2_HEADER_SZ;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_FindTailMPG
|
||||
=================
|
||||
*/
|
||||
SceOff Stream_FindTailMPG( file_t *file )
|
||||
{
|
||||
SceOff result;
|
||||
byte tagId[MP3_ID3V1_ID_SZ];
|
||||
|
||||
result = FS_FileLength( file );
|
||||
|
||||
FS_Seek( file, result - MP3_ID3V1_SZ, SEEK_SET );
|
||||
|
||||
if( FS_Read( file, tagId, MP3_ID3V1_ID_SZ ) < MP3_ID3V1_ID_SZ )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Sound_Mp3FindTail: ID3V1 ID read error\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
if( !memcmp( tagId, MP3_ID3V1_ID, MP3_ID3V1_ID_SZ ))
|
||||
result -= MP3_ID3V1_SZ;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_FillBufferMPG
|
||||
=================
|
||||
*/
|
||||
int Stream_FillBufferMPG( file_t *file, mp3_decoder_t *desc )
|
||||
{
|
||||
int status;
|
||||
byte *dstPtr;
|
||||
int dstSize;
|
||||
int dstPos;
|
||||
fs_offset_t readSize;
|
||||
|
||||
if( sceMp3CheckStreamDataNeeded( desc->handle ) <= 0 )
|
||||
return 0;
|
||||
|
||||
// get Info on the stream (where to fill to, how much to fill, where to fill from)
|
||||
status = sceMp3GetInfoToAddStreamData( desc->handle, &dstPtr, &dstSize, &dstPos );
|
||||
if( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3GetInfoToAddStreamData returned 0x%08X\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
// seek file to position requested
|
||||
if( desc->cachePos != dstPos )
|
||||
{
|
||||
FS_Seek( file, dstPos, SEEK_SET );
|
||||
desc->cachePos = dstPos;
|
||||
}
|
||||
|
||||
// read the amount of data
|
||||
readSize = FS_Read( file, dstPtr, dstSize );
|
||||
desc->cachePos += ( int )readSize;
|
||||
|
||||
// notify mp3 library about how much we really wrote to the stream buffer
|
||||
status = sceMp3NotifyAddStreamData( desc->handle, ( int )readSize );
|
||||
if ( status < 0 )
|
||||
Con_DPrintf( S_ERROR "sceMp3NotifyAddStreamData returned 0x%08X\n", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_OpenMPG
|
||||
=================
|
||||
*/
|
||||
stream_t *Stream_OpenMPG( const char *filename )
|
||||
{
|
||||
stream_t *stream;
|
||||
mp3_decoder_t *desc;
|
||||
file_t *file;
|
||||
int status;
|
||||
void *bufferBase;
|
||||
|
||||
file = FS_Open( filename, "rbh", false ); // hold mode
|
||||
if( !file ) return NULL;
|
||||
|
||||
// at this point we have valid stream
|
||||
stream = Mem_Calloc( host.soundpool, sizeof( stream_t ));
|
||||
stream->file = file;
|
||||
stream->pos = 0;
|
||||
|
||||
desc = Mem_Calloc( host.soundpool, sizeof( mp3_decoder_t ) + MP3_BUFFER_SIZE + PCM_BUFFER_SIZE + 63 );
|
||||
bufferBase = (void *)(((( uintptr_t )desc + sizeof( mp3_decoder_t )) & (~( 64 - 1 ))) + 64 );
|
||||
|
||||
// reserve a mp3 handle
|
||||
SceMp3InitArg mp3Init;
|
||||
mp3Init.mp3StreamStart = Stream_FindHeadMPG( file );
|
||||
mp3Init.mp3StreamEnd = Stream_FindTailMPG( file );
|
||||
mp3Init.mp3Buf = bufferBase;
|
||||
mp3Init.mp3BufSize = MP3_BUFFER_SIZE;
|
||||
mp3Init.pcmBuf = (void *)(( uintptr_t )bufferBase + MP3_BUFFER_SIZE );
|
||||
mp3Init.pcmBufSize = PCM_BUFFER_SIZE;
|
||||
|
||||
desc->cachePos = 0;
|
||||
desc->pcmTempPtr = mp3Init.pcmBuf;
|
||||
desc->handle = sceMp3ReserveMp3Handle( &mp3Init );
|
||||
if ( desc->handle < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3ReserveMp3Handle returned 0x%08X\n", desc->handle );
|
||||
Mem_Free( stream );
|
||||
Mem_Free( desc );
|
||||
FS_Close( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Fill the stream buffer with some data so that sceMp3Init has something to work with
|
||||
if( Stream_FillBufferMPG( file, desc ) != 0 )
|
||||
{
|
||||
Mem_Free( stream );
|
||||
Mem_Free( desc );
|
||||
FS_Close( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = sceMp3Init( desc->handle );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3Init returned 0x%08X\n", status );
|
||||
Mem_Free( stream );
|
||||
Mem_Free( desc );
|
||||
FS_Close( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
desc->frameCount = sceMp3GetFrameNum( desc->handle );
|
||||
|
||||
stream->buffsize = 0; // how many samples left from previous frame
|
||||
stream->channels = PCM_CHANNELS; // always 2 PCM channels
|
||||
stream->rate = sceMp3GetSamplingRate( desc->handle );
|
||||
stream->width = PCM_WIDTH; // always 16 bit PCM
|
||||
stream->ptr = (void *)desc;
|
||||
stream->type = WF_MPGDATA;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_ReadMPG
|
||||
|
||||
assume stream is valid
|
||||
=================
|
||||
*/
|
||||
int Stream_ReadMPG( stream_t *stream, int needBytes, void *buffer )
|
||||
{
|
||||
// buffer handling
|
||||
int bytesWritten = 0;
|
||||
mp3_decoder_t *desc;
|
||||
int errdec;
|
||||
|
||||
desc = ( mp3_decoder_t* )stream->ptr;
|
||||
|
||||
while(1)
|
||||
{
|
||||
byte *data;
|
||||
int outsize;
|
||||
|
||||
if( !stream->buffsize )
|
||||
{
|
||||
// Check if we need to fill our stream buffer
|
||||
if( Stream_FillBufferMPG( stream->file, desc ) != 0 )
|
||||
return 0;
|
||||
|
||||
for( errdec = 0; errdec < MP3_ERRORS_MAX; errdec++ )
|
||||
{
|
||||
stream->pos = sceMp3Decode( desc->handle, (SceShort16**)&desc->pcmTempPtr );
|
||||
if(( int )stream->pos >= 0 ) // decoding successful
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if( stream->pos == 0x80671402 ) // next frame header
|
||||
{
|
||||
if( Stream_FillBufferMPG( stream->file, desc ) != 0 )
|
||||
return 0;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
if(( int )stream->pos < 0 )
|
||||
{
|
||||
if( stream->pos != 0x80671402 )
|
||||
Con_DPrintf( S_ERROR "sceMp3Decode returned 0x%08X\n", stream->pos );
|
||||
return 0; // ???
|
||||
}
|
||||
}
|
||||
|
||||
// check remaining size
|
||||
if( bytesWritten + stream->pos > needBytes )
|
||||
outsize = ( needBytes - bytesWritten );
|
||||
else outsize = stream->pos;
|
||||
|
||||
// copy raw sample to output buffer
|
||||
data = (byte *)buffer + bytesWritten;
|
||||
memcpy( data, &desc->pcmTempPtr[stream->buffsize], outsize );
|
||||
bytesWritten += outsize;
|
||||
stream->pos -= outsize;
|
||||
stream->buffsize += outsize;
|
||||
|
||||
// continue from this sample on a next call
|
||||
if( bytesWritten >= needBytes )
|
||||
return bytesWritten;
|
||||
|
||||
stream->buffsize = 0; // no bytes remaining
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_SetPosMPG
|
||||
|
||||
assume stream is valid
|
||||
=================
|
||||
*/
|
||||
int Stream_SetPosMPG( stream_t *stream, int newpos )
|
||||
{
|
||||
mp3_decoder_t *desc;
|
||||
int frame;
|
||||
int status;
|
||||
|
||||
desc = ( mp3_decoder_t* )stream->ptr;
|
||||
|
||||
// get frame num
|
||||
frame = newpos / sceMp3GetMaxOutputSample( desc->handle ); // VBR?
|
||||
|
||||
if( frame < 1 || frame >= desc->frameCount - 1 )
|
||||
return false;
|
||||
|
||||
status = sceMp3ResetPlayPositionByFrame( desc->handle, frame );
|
||||
if( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3ResetPlayPositionByFrame returned 0x%08X\n", status );
|
||||
|
||||
// failed to seek for some reasons
|
||||
return false;
|
||||
}
|
||||
|
||||
// flush any previous data
|
||||
stream->buffsize = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_GetPosMPG
|
||||
|
||||
assume stream is valid
|
||||
=================
|
||||
*/
|
||||
int Stream_GetPosMPG( stream_t *stream )
|
||||
{
|
||||
mp3_decoder_t *desc;
|
||||
|
||||
desc = ( mp3_decoder_t * )stream->ptr;
|
||||
|
||||
return sceMp3GetSumDecodedSample( desc->handle );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_FreeMPG
|
||||
|
||||
assume stream is valid
|
||||
=================
|
||||
*/
|
||||
void Stream_FreeMPG( stream_t *stream )
|
||||
{
|
||||
mp3_decoder_t *desc;
|
||||
|
||||
desc = ( mp3_decoder_t * )stream->ptr;
|
||||
if( desc )
|
||||
{
|
||||
sceMp3ReleaseMp3Handle( desc->handle );
|
||||
Mem_Free( desc );
|
||||
stream->ptr = NULL;
|
||||
}
|
||||
|
||||
if( stream->file )
|
||||
{
|
||||
FS_Close( stream->file );
|
||||
stream->file = NULL;
|
||||
}
|
||||
|
||||
Mem_Free( stream );
|
||||
}
|
||||
#endif // XASH_PSP
|
||||
|
||||
@@ -331,7 +331,8 @@ stream_t *Stream_OpenWAV( const char *filename )
|
||||
return NULL;
|
||||
|
||||
// open
|
||||
file = FS_Open( filename, "rb", false );
|
||||
// h - hold mode
|
||||
file = FS_Open( filename, "rbh", false );
|
||||
if( !file ) return NULL;
|
||||
|
||||
// find "RIFF" chunk
|
||||
|
||||
@@ -74,7 +74,9 @@ struct stream_s
|
||||
|
||||
// current stream state
|
||||
void *ptr; // internal decoder state
|
||||
#if !XASH_PSP
|
||||
char temp[OUTBUF_SIZE]; // mpeg decoder stuff
|
||||
#endif
|
||||
size_t pos; // actual track position (or actual buffer remains)
|
||||
int buffsize; // cached buffer size
|
||||
};
|
||||
|
||||
@@ -44,6 +44,11 @@ GNU General Public License for more details.
|
||||
#include <vitasdk.h>
|
||||
#endif
|
||||
|
||||
#if XASH_PSP
|
||||
#include <pspkernel.h>
|
||||
#include <psputility_sysparam.h>
|
||||
#endif
|
||||
|
||||
#include "menu_int.h" // _UPDATE_PAGE macro
|
||||
|
||||
#include "library.h"
|
||||
@@ -144,6 +149,10 @@ const char *Sys_GetCurrentUser( void )
|
||||
|
||||
if( pw )
|
||||
return pw->pw_name;
|
||||
#elif XASH_PSP
|
||||
static string s_userName;
|
||||
if( sceUtilityGetSystemParamString( PSP_SYSTEMPARAM_ID_STRING_NICKNAME, s_userName, sizeof( s_userName )) == 0 )
|
||||
return s_userName;
|
||||
#endif
|
||||
return "Player";
|
||||
}
|
||||
@@ -485,7 +494,12 @@ Sys_Quit
|
||||
void Sys_Quit( void )
|
||||
{
|
||||
Host_Shutdown();
|
||||
#if XASH_PSP
|
||||
sceKernelDelayThread( 50 * 1000 );
|
||||
sceKernelExitGame();
|
||||
#else
|
||||
exit( error_on_exit );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -58,6 +58,15 @@ void SDLash_Init( void );
|
||||
void SDLash_Shutdown( void );
|
||||
#endif
|
||||
|
||||
#if XASH_PSP
|
||||
void Platform_ReadCmd( const char *fname, int *argc, char **argv );
|
||||
SceUID Platform_LoadModule( const char *filename, int mpid, SceSize argsize, void *argp );
|
||||
int Platform_UnloadModule( SceUID modid, int *sce_code );
|
||||
|
||||
#include "psp/p5ram_psp.h"
|
||||
#include "psp/fsh_psp.h"
|
||||
#endif
|
||||
|
||||
#if XASH_ANDROID
|
||||
const char *Android_GetAndroidID( void );
|
||||
const char *Android_LoadID( void );
|
||||
|
||||
410
engine/platform/psp/fsh_psp.c
Normal file
410
engine/platform/psp/fsh_psp.c
Normal file
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
fsh_psp.c - PSP filesystem helper
|
||||
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.
|
||||
*/
|
||||
#include <pspiofilemgr.h>
|
||||
#include "common.h"
|
||||
#include "fsh_psp.h"
|
||||
|
||||
#define FSH_MAX_PATH 64
|
||||
#define FSH_EMPTY_STRING "*empty*"
|
||||
|
||||
typedef struct fsh_path_s
|
||||
{
|
||||
char path[FSH_MAX_PATH];
|
||||
int fsize;
|
||||
uint hashvalue;
|
||||
struct fsh_path_s *nexthash;
|
||||
}fsh_path_t;
|
||||
|
||||
typedef struct fsh_handle_s
|
||||
{
|
||||
qboolean ready;
|
||||
int count;
|
||||
char folderpath[PATH_MAX];
|
||||
int folderpath_size;
|
||||
uint empty_hash;
|
||||
int pathlist_size;
|
||||
int hashlist_size;
|
||||
fsh_path_t *pathlist;
|
||||
fsh_path_t **hashlist;
|
||||
struct fsh_handle_s *next;
|
||||
}fsh_handle_t;
|
||||
|
||||
static fsh_handle_t *fsh_poolchain = NULL;
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_AddHash
|
||||
================
|
||||
*/
|
||||
_inline void FSH_AddHash( fsh_path_t **hashlist, uint hash, fsh_path_t *fptr )
|
||||
{
|
||||
fptr->hashvalue = hash;
|
||||
fptr->nexthash = hashlist[hash];
|
||||
hashlist[hash] = fptr;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_RemoveHash
|
||||
================
|
||||
*/
|
||||
_inline void FSH_RemoveHash( fsh_path_t **hashlist, uint hash, fsh_path_t *fptr )
|
||||
{
|
||||
fsh_path_t **fptr_prev;
|
||||
|
||||
for( fptr_prev = &hashlist[hash]; *fptr_prev != NULL; fptr_prev = &( *fptr_prev )->nexthash )
|
||||
{
|
||||
if( *fptr_prev == fptr )
|
||||
{
|
||||
*fptr_prev = fptr->nexthash;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_AddFilePath
|
||||
================
|
||||
*/
|
||||
int FSH_AddFilePathWs( fsh_handle_t *handle, const char *path, int size )
|
||||
{
|
||||
uint hash;
|
||||
fsh_path_t *fptr;
|
||||
const char *strip_path;
|
||||
|
||||
if( !handle )
|
||||
return -2;
|
||||
|
||||
if( Q_strnicmp( path, handle->folderpath, handle->folderpath_size ))
|
||||
return -2;
|
||||
|
||||
strip_path = path + handle->folderpath_size + 1; // + '/'
|
||||
|
||||
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||
|
||||
if( handle->ready && handle->count > 0 )
|
||||
{
|
||||
// see if already added
|
||||
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||
{
|
||||
if( !Q_stricmp( fptr->path, strip_path ))
|
||||
return fptr - handle->pathlist; // index
|
||||
}
|
||||
|
||||
// find empty
|
||||
for( fptr = handle->hashlist[handle->empty_hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||
{
|
||||
if( !Q_stricmp( fptr->path, FSH_EMPTY_STRING ))
|
||||
{
|
||||
Q_strncpy( fptr->path, strip_path, FSH_MAX_PATH - 1 );
|
||||
|
||||
// file size
|
||||
fptr->fsize = size;
|
||||
|
||||
// remove empty from hash table
|
||||
FSH_RemoveHash( handle->hashlist, handle->empty_hash, fptr );
|
||||
|
||||
// add to hash table
|
||||
FSH_AddHash( handle->hashlist, hash, fptr );
|
||||
|
||||
return fptr - handle->pathlist; // index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create new
|
||||
if( handle->count + 1 >= handle->pathlist_size )
|
||||
return -1;
|
||||
|
||||
fptr = &handle->pathlist[handle->count];
|
||||
Q_strncpy( fptr->path, strip_path, FSH_MAX_PATH - 1 );
|
||||
|
||||
// file size
|
||||
fptr->fsize = size;
|
||||
|
||||
// add to hash table
|
||||
FSH_AddHash( handle->hashlist, hash, fptr );
|
||||
|
||||
handle->count++;
|
||||
|
||||
return fptr - handle->pathlist; // index
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_RemoveFilePath
|
||||
================
|
||||
*/
|
||||
int FSH_RemoveFilePath( fsh_handle_t *handle, const char *path )
|
||||
{
|
||||
uint hash;
|
||||
fsh_path_t *fptr, **fptr_prev;
|
||||
const char *strip_path;
|
||||
|
||||
if( !handle )
|
||||
return -2;
|
||||
|
||||
if( Q_strnicmp( path, handle->folderpath, handle->folderpath_size ))
|
||||
return -2;
|
||||
|
||||
strip_path = path + handle->folderpath_size + 1; // + '/'
|
||||
|
||||
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||
|
||||
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||
{
|
||||
if( !Q_stricmp( fptr->path, strip_path ))
|
||||
{
|
||||
memset( fptr->path, 0, FSH_MAX_PATH );
|
||||
Q_strncpy( fptr->path, FSH_EMPTY_STRING, FSH_MAX_PATH - 1 );
|
||||
fptr->fsize = -3; // undefined
|
||||
|
||||
// remove from hash table
|
||||
FSH_RemoveHash( handle->hashlist, hash, fptr );
|
||||
|
||||
// add empty to hash table
|
||||
FSH_AddHash( handle->hashlist, handle->empty_hash, fptr );
|
||||
|
||||
return fptr - handle->pathlist; // index
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_RenameFilePath
|
||||
================
|
||||
*/
|
||||
int FSH_RenameFilePath( fsh_handle_t *handle, const char *oldname, const char *newname )
|
||||
{
|
||||
uint hash;
|
||||
fsh_path_t *fptr, **fptr_prev;
|
||||
const char *strip_path;
|
||||
|
||||
if( !handle )
|
||||
return -2;
|
||||
|
||||
if( Q_strnicmp( oldname, handle->folderpath, handle->folderpath_size ))
|
||||
return -2;
|
||||
|
||||
strip_path = oldname + handle->folderpath_size + 1; // + '/'
|
||||
|
||||
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||
|
||||
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||
{
|
||||
if( !Q_stricmp( fptr->path, strip_path ))
|
||||
{
|
||||
strip_path = newname + handle->folderpath_size + 1; // + '/'
|
||||
|
||||
memset( fptr->path, 0, FSH_MAX_PATH );
|
||||
Q_strncpy( fptr->path, strip_path, FSH_MAX_PATH - 1 );
|
||||
|
||||
// remove old from hash table
|
||||
FSH_RemoveHash( handle->hashlist, hash, fptr );
|
||||
|
||||
// add new to hash table
|
||||
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||
FSH_AddHash( handle->hashlist, hash, fptr );
|
||||
|
||||
return fptr - handle->pathlist; // index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_FindSize
|
||||
================
|
||||
*/
|
||||
int FSH_FindSize( fsh_handle_t *handle, const char *path )
|
||||
{
|
||||
uint hash;
|
||||
fsh_path_t *fptr;
|
||||
const char *strip_path;
|
||||
|
||||
if( !handle )
|
||||
return -2;
|
||||
|
||||
if( !handle->ready || !handle->count || Q_strnicmp( path, handle->folderpath, handle->folderpath_size ))
|
||||
return -2;
|
||||
|
||||
strip_path = path + handle->folderpath_size + 1; // + '/'
|
||||
|
||||
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||
|
||||
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||
{
|
||||
if( !Q_stricmp( fptr->path, strip_path ))
|
||||
return fptr->fsize;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_Find
|
||||
================
|
||||
*/
|
||||
int FSH_Find( fsh_handle_t *handle, const char *path )
|
||||
{
|
||||
uint hash;
|
||||
fsh_path_t *fptr;
|
||||
const char *strip_path;
|
||||
|
||||
if( !handle )
|
||||
return -2;
|
||||
|
||||
if( !handle->ready || !handle->count || Q_strnicmp( path, handle->folderpath, handle->folderpath_size ))
|
||||
return -2;
|
||||
|
||||
strip_path = path + handle->folderpath_size + 1; // + '/'
|
||||
|
||||
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||
|
||||
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||
{
|
||||
if( !Q_stricmp( fptr->path, strip_path ))
|
||||
return fptr - handle->pathlist; // index
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_ScanDir
|
||||
================
|
||||
*/
|
||||
static int FSH_ScanDir( fsh_handle_t *handle, const char *path )
|
||||
{
|
||||
SceUID dir;
|
||||
SceIoDirent entry;
|
||||
char temp[FSH_MAX_PATH];
|
||||
int result;
|
||||
int fsize;
|
||||
|
||||
if(( dir = sceIoDopen( path )) < 0 )
|
||||
return -1;
|
||||
|
||||
result = 0;
|
||||
|
||||
// iterate through the directory
|
||||
while( 1 )
|
||||
{
|
||||
// zero the dirent, to avoid possible problems with sceIoDread
|
||||
memset( &entry, 0, sizeof( SceIoDirent ));
|
||||
if( !sceIoDread( dir, &entry ))
|
||||
break;
|
||||
|
||||
// ignore the virtual directories
|
||||
if( !Q_stricmp( entry.d_name, "." ) || !Q_stricmp( entry.d_name, ".." ))
|
||||
continue;
|
||||
|
||||
sprintf( temp, "%s/%s", path, entry.d_name );
|
||||
|
||||
if(FIO_S_ISDIR( entry.d_stat.st_mode ))
|
||||
result = FSH_ScanDir( handle, temp );
|
||||
else if(FIO_S_ISREG( entry.d_stat.st_mode ))
|
||||
{
|
||||
if( entry.d_stat.st_size <= __INT_MAX__ )
|
||||
fsize = ( int )entry.d_stat.st_size;
|
||||
else fsize = -3; // undefined
|
||||
|
||||
result = FSH_AddFilePathWs( handle, temp, fsize );
|
||||
}
|
||||
else continue;
|
||||
if( result < 0 ) break;
|
||||
}
|
||||
sceIoDclose( dir );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_Create
|
||||
================
|
||||
*/
|
||||
fsh_handle_t *FSH_Create( const char *path, int maxfiles )
|
||||
{
|
||||
fsh_handle_t *handle;
|
||||
|
||||
handle = P5Ram_Alloc( sizeof( fsh_handle_t ), 1 );
|
||||
if( !handle )
|
||||
return NULL;
|
||||
|
||||
handle->pathlist_size = maxfiles;
|
||||
handle->pathlist = P5Ram_Alloc( handle->pathlist_size * sizeof( fsh_path_t ), 1 );
|
||||
if( !handle->pathlist )
|
||||
{
|
||||
P5Ram_Free( handle );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handle->hashlist_size = maxfiles >> 2;
|
||||
handle->hashlist = P5Ram_Alloc( handle->hashlist_size * sizeof( fsh_path_t* ), 1 );
|
||||
if( !handle->hashlist )
|
||||
{
|
||||
P5Ram_Free( handle );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handle->empty_hash = COM_HashKey( FSH_EMPTY_STRING, handle->hashlist_size );
|
||||
|
||||
if( !Q_strnicmp( path, "./", 2 ))
|
||||
path += 2;
|
||||
|
||||
Q_strncpy( handle->folderpath, path, FSH_MAX_PATH - 1 );
|
||||
handle->folderpath_size = Q_strlen( handle->folderpath );
|
||||
|
||||
if( FSH_ScanDir( handle, handle->folderpath ) < 0 )
|
||||
{
|
||||
P5Ram_Free( handle );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handle->next = fsh_poolchain;
|
||||
fsh_poolchain = handle;
|
||||
|
||||
handle->ready = true;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_Shutdown
|
||||
================
|
||||
*/
|
||||
void FSH_Free( fsh_handle_t *handle )
|
||||
{
|
||||
if( !handle )
|
||||
return;
|
||||
|
||||
if( handle->pathlist )
|
||||
P5Ram_Free( handle->pathlist );
|
||||
|
||||
if( handle->hashlist )
|
||||
P5Ram_Free( handle->hashlist );
|
||||
|
||||
P5Ram_Free( handle );
|
||||
}
|
||||
37
engine/platform/psp/fsh_psp.h
Normal file
37
engine/platform/psp/fsh_psp.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
fsh_psp.h - PSP filesystem helper 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 FSH_PSP_H
|
||||
#define FSH_PSP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef struct fsh_handle_s fsh_handle_t;
|
||||
|
||||
int FSH_AddFilePathWs( fsh_handle_t *handle, const char *path, int size );
|
||||
#define FSH_AddFilePath( handle, path ) FSH_AddFilePathWs(handle, path, -2 )
|
||||
int FSH_RemoveFilePath( fsh_handle_t *handle, const char *path );
|
||||
int FSH_RenameFilePath( fsh_handle_t *handle, const char *oldname, const char *newname );
|
||||
int FSH_FindSize( fsh_handle_t *handle, const char *path );
|
||||
int FSH_Find( fsh_handle_t *handle, const char *path );
|
||||
fsh_handle_t *FSH_Create( const char *path, int maxfiles );
|
||||
void FSH_Free( fsh_handle_t *handle );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // P5RAM_PSP_H
|
||||
239
engine/platform/psp/in_psp.c
Normal file
239
engine/platform/psp/in_psp.c
Normal file
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
in_psp.c - PSP input component
|
||||
Copyright (C) 2021 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.
|
||||
*/
|
||||
#include "common.h"
|
||||
#include "keydefs.h"
|
||||
#include "input.h"
|
||||
#include "client.h"
|
||||
|
||||
#if XASH_INPUT == INPUT_PSP
|
||||
#include <pspctrl.h>
|
||||
|
||||
#define PSP_MAX_KEYS sizeof(psp_keymap) / sizeof(struct psp_keymap_s)
|
||||
#define PSP_EXT_KEY PSP_CTRL_HOME
|
||||
|
||||
convar_t *psp_joy_dz_min;
|
||||
convar_t *psp_joy_dz_max;
|
||||
convar_t *psp_joy_cv_power;
|
||||
convar_t *psp_joy_cv_expo;
|
||||
|
||||
static struct psp_keymap_s
|
||||
{
|
||||
int srckey;
|
||||
int dstkey;
|
||||
qboolean stdpressed;
|
||||
qboolean extpressed;
|
||||
}psp_keymap[] =
|
||||
{
|
||||
#if 0
|
||||
{ PSP_CTRL_SELECT, '~' , false, false },
|
||||
{ PSP_CTRL_START, K_ESCAPE , false, false },
|
||||
{ PSP_CTRL_UP, K_UPARROW , false, false },
|
||||
{ PSP_CTRL_RIGHT, K_RIGHTARROW, false, false },
|
||||
{ PSP_CTRL_DOWN, K_DOWNARROW , false, false },
|
||||
{ PSP_CTRL_LEFT, K_LEFTARROW , false, false },
|
||||
{ PSP_CTRL_LTRIGGER, K_JOY1 , false, false },
|
||||
{ PSP_CTRL_RTRIGGER, K_JOY2 , false, false },
|
||||
{ PSP_CTRL_TRIANGLE, K_SHIFT , false, false },
|
||||
{ PSP_CTRL_CIRCLE, K_SPACE , false, false },
|
||||
{ PSP_CTRL_CROSS, K_ENTER , false, false },
|
||||
{ PSP_CTRL_SQUARE, K_BACKSPACE , false, false },
|
||||
#else
|
||||
{ PSP_CTRL_SELECT , K_MODE_BUTTON , false, false },
|
||||
{ PSP_CTRL_START , K_START_BUTTON, false, false },
|
||||
{ PSP_CTRL_UP , K_UPARROW , false, false },
|
||||
{ PSP_CTRL_RIGHT , K_RIGHTARROW , false, false },
|
||||
{ PSP_CTRL_DOWN , K_DOWNARROW , false, false },
|
||||
{ PSP_CTRL_LEFT , K_LEFTARROW , false, false },
|
||||
{ PSP_CTRL_LTRIGGER, K_L1_BUTTON , false, false },
|
||||
{ PSP_CTRL_RTRIGGER, K_R1_BUTTON , false, false },
|
||||
{ PSP_CTRL_TRIANGLE, K_Y_BUTTON , false, false },
|
||||
{ PSP_CTRL_CIRCLE , K_B_BUTTON , false, false },
|
||||
{ PSP_CTRL_CROSS , K_A_BUTTON , false, false },
|
||||
{ PSP_CTRL_SQUARE , K_X_BUTTON , false, false },
|
||||
#endif
|
||||
#if 0
|
||||
PSP_CTRL_HOME,
|
||||
PSP_CTRL_HOLD,
|
||||
PSP_CTRL_NOTE,
|
||||
PSP_CTRL_SCREEN,
|
||||
PSP_CTRL_VOLUP,
|
||||
PSP_CTRL_VOLDOWN,
|
||||
PSP_CTRL_WLAN_UP,
|
||||
PSP_CTRL_REMOTE,
|
||||
PSP_CTRL_DISC,
|
||||
PSP_CTRL_MS,
|
||||
#endif
|
||||
};
|
||||
static signed short psp_joymap[256]; /* -32768 <> 32767 */
|
||||
|
||||
static float Platform_JoyAxisCompute( float axis, float deadzone_min, float deadzone_max, float power, float expo )
|
||||
{
|
||||
float abs_axis, fabs_axis, fcurve;
|
||||
float scale, r_deadzone_max;
|
||||
qboolean flip_axis = 0;
|
||||
|
||||
expo = bound( 0.0f, expo, 1.0f );
|
||||
power = bound( 0.0f, power, 10.0f );
|
||||
deadzone_min = bound( 0.0f, deadzone_min, 127.0f );
|
||||
deadzone_max = bound( 0.0f, deadzone_max, 127.0f );
|
||||
|
||||
// (-127) - (0) - (+127)
|
||||
abs_axis = axis - 128.0f;
|
||||
if( abs_axis < 0.0f )
|
||||
{
|
||||
abs_axis = -abs_axis - 1.0f;
|
||||
flip_axis = 1;
|
||||
}
|
||||
if( abs_axis <= deadzone_min ) return 0.0f;
|
||||
r_deadzone_max = 127.0f - deadzone_max;
|
||||
if( abs_axis >= r_deadzone_max ) return ( flip_axis ? -127.0f : 127.0f );
|
||||
|
||||
scale = 127.0f / ( r_deadzone_max - deadzone_min );
|
||||
abs_axis -= deadzone_min;
|
||||
abs_axis *= scale;
|
||||
|
||||
if( expo )
|
||||
{
|
||||
// x * ( x^power * expo + x * ( 1.0 - expo ))
|
||||
fabs_axis = abs_axis / 127.0f; // 0.0f - 1.0f
|
||||
fcurve = powf(fabs_axis, power) * expo + fabs_axis * (1.0f - expo);
|
||||
abs_axis = fabs_axis * fcurve * 127.0f;
|
||||
}
|
||||
|
||||
return ( flip_axis ? -abs_axis : abs_axis );
|
||||
}
|
||||
|
||||
void Platform_RunEvents( void )
|
||||
{
|
||||
int i;
|
||||
SceCtrlData buf;
|
||||
signed short curr_X, curr_Y;
|
||||
static unsigned int last_buttons;
|
||||
static signed short last_X, last_Y;
|
||||
|
||||
sceCtrlPeekBufferPositive( &buf, 1 );
|
||||
|
||||
for( i = 0; i < PSP_MAX_KEYS; i++ )
|
||||
{
|
||||
if( buf.Buttons & PSP_EXT_KEY )
|
||||
{
|
||||
if(( last_buttons ^ buf.Buttons ) & psp_keymap[i].srckey )
|
||||
{
|
||||
if( psp_keymap[i].stdpressed )
|
||||
{
|
||||
psp_keymap[i].stdpressed = false;
|
||||
Key_Event( psp_keymap[i].dstkey, psp_keymap[i].stdpressed );
|
||||
}
|
||||
else
|
||||
{
|
||||
psp_keymap[i].extpressed = buf.Buttons & psp_keymap[i].srckey;
|
||||
Key_Event( K_AUX16 + i, psp_keymap[i].extpressed);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// release
|
||||
if( psp_keymap[i].extpressed )
|
||||
{
|
||||
psp_keymap[i].extpressed = false;
|
||||
Key_Event( K_AUX16 + i, psp_keymap[i].extpressed);
|
||||
}
|
||||
|
||||
if(( last_buttons ^ buf.Buttons ) & psp_keymap[i].srckey )
|
||||
{
|
||||
psp_keymap[i].stdpressed = buf.Buttons & psp_keymap[i].srckey;
|
||||
Key_Event( psp_keymap[i].dstkey, psp_keymap[i].stdpressed );
|
||||
}
|
||||
}
|
||||
}
|
||||
last_buttons = buf.Buttons;
|
||||
|
||||
if( FBitSet( psp_joy_dz_min->flags, FCVAR_CHANGED ) || FBitSet( psp_joy_dz_max->flags, FCVAR_CHANGED ) ||
|
||||
FBitSet( psp_joy_cv_power->flags, FCVAR_CHANGED ) || FBitSet( psp_joy_cv_expo->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
for ( i = 0; i < 256; i++ )
|
||||
{
|
||||
psp_joymap[i] = Platform_JoyAxisCompute( i, psp_joy_dz_min->value, psp_joy_dz_max->value, psp_joy_cv_power->value, psp_joy_cv_expo->value );
|
||||
psp_joymap[i] *= 256;
|
||||
}
|
||||
|
||||
ClearBits( psp_joy_dz_min->flags, FCVAR_CHANGED );
|
||||
ClearBits( psp_joy_dz_max->flags, FCVAR_CHANGED );
|
||||
ClearBits( psp_joy_cv_power->flags, FCVAR_CHANGED );
|
||||
ClearBits( psp_joy_cv_expo->flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
curr_X = psp_joymap[buf.Lx];
|
||||
curr_Y = psp_joymap[buf.Ly];
|
||||
|
||||
if( last_X != curr_X )
|
||||
Joy_AxisMotionEvent( 2, -curr_X );
|
||||
|
||||
if( last_Y != curr_Y )
|
||||
Joy_AxisMotionEvent( 3, -curr_Y );
|
||||
|
||||
last_X = curr_X;
|
||||
last_Y = curr_Y;
|
||||
}
|
||||
|
||||
void Platform_GetMousePos( int *x, int *y )
|
||||
{
|
||||
*x = *y = 0;
|
||||
}
|
||||
|
||||
void Platform_SetMousePos( int x, int y )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Platform_EnableTextInput( qboolean enable )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Platform_JoyInit( int numjoy )
|
||||
{
|
||||
int i;
|
||||
|
||||
// set up cvars
|
||||
psp_joy_dz_min = Cvar_Get( "psp_joy_dz_min", "15", FCVAR_ARCHIVE, "joy deadzone min (0 - 127)" );
|
||||
psp_joy_dz_max = Cvar_Get( "psp_joy_dz_max", "0", FCVAR_ARCHIVE, "joy deadzone max (0 - 127)" );
|
||||
psp_joy_cv_power = Cvar_Get( "psp_joy_cv_power", "2", FCVAR_ARCHIVE, "joy curve power (0 - 10)" );
|
||||
psp_joy_cv_expo = Cvar_Get( "psp_joy_cv_expo", "0.5", FCVAR_ARCHIVE, "joy curve expo (0 - 1.0)" );
|
||||
|
||||
// set up the controller.
|
||||
sceCtrlSetSamplingCycle( 0 );
|
||||
sceCtrlSetSamplingMode( PSP_CTRL_MODE_ANALOG );
|
||||
|
||||
// building a joystick map
|
||||
for ( i = 0; i < 256; i++ )
|
||||
{
|
||||
psp_joymap[i] = Platform_JoyAxisCompute( i, psp_joy_dz_min->value, psp_joy_dz_max->value, psp_joy_cv_power->value, psp_joy_cv_expo->value );
|
||||
psp_joymap[i] *= 256;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Platform_MouseMove( float *x, float *y )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Platform_PreCreateMove( void )
|
||||
{
|
||||
|
||||
}
|
||||
#endif /* XASH_INPUT */
|
||||
8
engine/platform/psp/ka/KernelAccess.S
Normal file
8
engine/platform/psp/ka/KernelAccess.S
Normal file
@@ -0,0 +1,8 @@
|
||||
.set noreorder
|
||||
|
||||
#include "pspstub.s"
|
||||
|
||||
STUB_START "KernelAccess",0x40090000,0x00020005
|
||||
STUB_FUNC 0x8A5C745F,kaGeEdramSetSize
|
||||
STUB_FUNC 0x71570ECF,kaGeEdramGetHwSize
|
||||
STUB_END
|
||||
30
engine/platform/psp/ka/ka.h
Normal file
30
engine/platform/psp/ka/ka.h
Normal file
@@ -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
|
||||
486
engine/platform/psp/lib_psp.c
Normal file
486
engine/platform/psp/lib_psp.c
Normal file
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
lib_psp.c - dynamic library code for Sony PSP system
|
||||
Copyright (C) 2018 Flying With Gauss
|
||||
Copyright (C) 2022 Sergey Galushko
|
||||
|
||||
This program is free software: you can redistribute it and/sor 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.
|
||||
*/
|
||||
#include "platform/platform.h"
|
||||
|
||||
#if XASH_LIB == LIB_PSP
|
||||
#include <pspmodulemgr.h>
|
||||
#include "common.h"
|
||||
#include "library.h"
|
||||
#include "filesystem.h"
|
||||
#include "server.h"
|
||||
|
||||
#define MOD_MAXNAMELEN 256
|
||||
|
||||
typedef struct table_s
|
||||
{
|
||||
const char *name;
|
||||
void *pointer;
|
||||
} table_t;
|
||||
#include "generated_library_tables.h"
|
||||
|
||||
typedef struct mod_func_s
|
||||
{
|
||||
const char *name;
|
||||
void *addr;
|
||||
} mod_func_t;
|
||||
|
||||
typedef struct mod_handle_s
|
||||
{
|
||||
SceUID uid;
|
||||
char name[MOD_MAXNAMELEN];
|
||||
uint segAddr;
|
||||
uint segSize;
|
||||
mod_func_t *func;
|
||||
struct mod_handle_s *next;
|
||||
} mod_handle_t;
|
||||
|
||||
static mod_handle_t *modList = NULL;
|
||||
static char *modErrorPtr = NULL;
|
||||
static char modErrorBuf[1024];
|
||||
|
||||
#define Module_Error( fmt, ... ) Module_SetError( "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__ )
|
||||
|
||||
int Module_SetError( const char *fmt, ... )
|
||||
{
|
||||
va_list args;
|
||||
int result;
|
||||
|
||||
va_start( args, fmt );
|
||||
result = Q_vsnprintf( modErrorBuf, sizeof( modErrorBuf ), fmt, args );
|
||||
va_end( args );
|
||||
|
||||
modErrorPtr = modErrorBuf;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *Module_GetError( void )
|
||||
{
|
||||
char *errPtr = modErrorPtr;
|
||||
modErrorPtr = NULL;
|
||||
return errPtr;
|
||||
}
|
||||
|
||||
static mod_handle_t *Module_Find( const char *name )
|
||||
{
|
||||
mod_handle_t *modHandle;
|
||||
|
||||
if( !name )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( modHandle = modList; modHandle; modHandle = modHandle->next )
|
||||
{
|
||||
if( !Q_strcmp( modHandle->name, name ))
|
||||
return modHandle;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *Module_Name( void *handle )
|
||||
{
|
||||
mod_handle_t *modHandle;
|
||||
|
||||
if( !handle )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( modHandle = modList; modHandle; modHandle = modHandle->next )
|
||||
{
|
||||
if( modHandle == handle )
|
||||
return modHandle->name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static mod_func_t *Module_LoadStatic( const char *name )
|
||||
{
|
||||
table_t *staticLib;
|
||||
|
||||
if( !name )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( staticLib = ( table_t* )libs; staticLib->pointer && staticLib->name; staticLib++ )
|
||||
{
|
||||
if( !Q_strcmp( staticLib->name, name ))
|
||||
return staticLib->pointer;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mod_handle_t *Module_Load( const char *name )
|
||||
{
|
||||
mod_handle_t *modHandle;
|
||||
mod_func_t *modFunc;
|
||||
qboolean skipPrefix;
|
||||
char modStaticName[32];
|
||||
void *modArg[2];
|
||||
SceUID modUid;
|
||||
uint modSegAddr, modSegSize;
|
||||
SceKernelModuleInfo info;
|
||||
char engine_cwd[PATH_MAX];
|
||||
|
||||
if( !name )
|
||||
return NULL;
|
||||
|
||||
modHandle = Module_Find( name );
|
||||
if( modHandle )
|
||||
return modHandle;
|
||||
|
||||
skipPrefix = false;
|
||||
modSegAddr = modSegSize = 0;
|
||||
|
||||
Q_sprintf( engine_cwd, "%s/", host.rootdir );
|
||||
|
||||
modArg[0] = &modFunc;
|
||||
modArg[1] = engine_cwd;
|
||||
modUid = Platform_LoadModule( name, 0, sizeof( modArg ), modArg );
|
||||
if( modUid < 0 )
|
||||
{
|
||||
COM_FileBase( name, modStaticName );
|
||||
|
||||
if( !Q_strncmp( modStaticName, "lib", 3 ) )
|
||||
skipPrefix = true;
|
||||
|
||||
modFunc = Module_LoadStatic( skipPrefix ? &modStaticName[3] : modStaticName );
|
||||
if( !modFunc )
|
||||
{
|
||||
Module_Error( "module %s error ( %#010x )", name, modUid );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
modUid = -1;
|
||||
|
||||
Con_Reportf( "Module_Load( %s ): ( static ) success!\n", name );
|
||||
}
|
||||
else
|
||||
{
|
||||
info.size = sizeof( info );
|
||||
if ( sceKernelQueryModuleInfo( modUid, &info ) >= 0 )
|
||||
{
|
||||
if( info.nsegment > 0 )
|
||||
{
|
||||
modSegAddr = info.segmentaddr[0];
|
||||
modSegSize = info.segmentsize[0];
|
||||
}
|
||||
}
|
||||
|
||||
Con_Reportf( "Module_Load( %s ): ( dynamic ) success!\n", name );
|
||||
}
|
||||
|
||||
modHandle = calloc( 1, sizeof( mod_handle_t ));
|
||||
if( !modHandle )
|
||||
{
|
||||
Module_Error( "out of memory" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Q_strncpy( modHandle->name, name, MOD_MAXNAMELEN );
|
||||
|
||||
modHandle->uid = modUid;
|
||||
modHandle->func = modFunc;
|
||||
modHandle->segAddr = modSegAddr;
|
||||
modHandle->segSize = modSegSize;
|
||||
modHandle->next = modList;
|
||||
|
||||
modList = modHandle;
|
||||
|
||||
return modHandle;
|
||||
}
|
||||
|
||||
void *Module_GetAddrByName( mod_handle_t *handle, const char *name )
|
||||
{
|
||||
mod_func_t *modFunc;
|
||||
|
||||
if( !handle || !name )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !Module_Name( handle ))
|
||||
{
|
||||
Module_SetError( "unknown handle" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !handle->func )
|
||||
{
|
||||
Module_SetError( "call Module_Load() first" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( modFunc = handle->func; modFunc->addr && modFunc->name; modFunc++ )
|
||||
{
|
||||
if( !Q_strcmp( modFunc->name, name ))
|
||||
return modFunc->addr;
|
||||
}
|
||||
|
||||
Module_Error( "func %s not found in %s", name, handle->name );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *Module_GetNameByAddr( mod_handle_t *handle, const void *addr )
|
||||
{
|
||||
mod_func_t *modFunc;
|
||||
|
||||
if( !handle || !addr )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !Module_Name( handle ))
|
||||
{
|
||||
Module_SetError( "unknown handle" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !handle->func )
|
||||
{
|
||||
Module_SetError( "call Module_Load() first" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( modFunc = handle->func; modFunc->addr && modFunc->name; modFunc++ )
|
||||
{
|
||||
if( modFunc->addr == addr )
|
||||
return modFunc->name;
|
||||
}
|
||||
|
||||
Module_Error( "addr %#010x not found in %s", addr, handle->name );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint Module_GetOffsetByAddr( mod_handle_t *handle, const void *addr )
|
||||
{
|
||||
uint addrUInt;
|
||||
|
||||
if( !handle || !addr )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !Module_Name( handle ))
|
||||
{
|
||||
Module_SetError( "unknown handle" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !handle->segAddr )
|
||||
{
|
||||
Module_SetError( "unknown segment" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
addrUInt = ( uint )addr;
|
||||
if( addrUInt < handle->segAddr || addrUInt >= ( handle->segAddr + handle->segSize ))
|
||||
{
|
||||
Module_SetError( "addr %#010x is out of range", addrUInt );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return addrUInt - handle->segAddr;
|
||||
}
|
||||
|
||||
void *Module_GetAddrByOffset( mod_handle_t *handle, uint offset )
|
||||
{
|
||||
if( !handle || !offset )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !Module_Name( handle ))
|
||||
{
|
||||
Module_SetError( "unknown handle" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !handle->segAddr )
|
||||
{
|
||||
Module_SetError( "unknown segment" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( offset >= handle->segSize )
|
||||
{
|
||||
Module_SetError( "offset %#010x is out of range", offset );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ( void* )( offset + handle->segAddr );
|
||||
}
|
||||
|
||||
int Module_Unload( mod_handle_t *handle )
|
||||
{
|
||||
mod_handle_t *modHandle;
|
||||
int result, sceCode;
|
||||
|
||||
if( !handle )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( !Module_Name( handle ))
|
||||
{
|
||||
Module_Error( "unknown handle" );
|
||||
return -2;
|
||||
}
|
||||
|
||||
if( handle->uid != -1 )
|
||||
{
|
||||
result = Platform_UnloadModule( handle->uid, &sceCode );
|
||||
if( result < 0 )
|
||||
{
|
||||
if( result == -1 )
|
||||
Module_Error( "module %s doesn't want to stop", handle->name );
|
||||
else
|
||||
Module_Error( "module %s error ( %#010x )", handle->name, sceCode );
|
||||
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
|
||||
if( handle != modList )
|
||||
{
|
||||
for( modHandle = modList; modHandle; modHandle = modHandle->next )
|
||||
{
|
||||
if( modHandle->next == handle )
|
||||
{
|
||||
modHandle->next = handle->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else modList = handle->next;
|
||||
|
||||
free( handle );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
qboolean COM_CheckLibraryDirectDependency( const char *name, const char *depname, qboolean directpath )
|
||||
{
|
||||
// TODO: implement
|
||||
return true;
|
||||
}
|
||||
|
||||
void *COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean directpath )
|
||||
{
|
||||
dll_user_t *hInst = NULL;
|
||||
void *pHandle = NULL;
|
||||
|
||||
COM_ResetLibraryError();
|
||||
|
||||
// platforms where gameinfo mechanism is working goes here
|
||||
// and use FS_FindLibrary
|
||||
hInst = FS_FindLibrary( dllname, directpath );
|
||||
if( !hInst )
|
||||
{
|
||||
// try to find by linker(LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, LD_32_LIBRARY_PATH and so on...)
|
||||
if( !pHandle )
|
||||
{
|
||||
pHandle = Module_Load( dllname );
|
||||
if( pHandle )
|
||||
return pHandle;
|
||||
|
||||
COM_PushLibraryError( va( "Failed to find library %s", dllname ));
|
||||
COM_PushLibraryError( Module_GetError() );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( hInst->custom_loader )
|
||||
{
|
||||
COM_PushLibraryError( va( "Custom library loader is not available. Extract library %s and fix gameinfo.txt!", hInst->fullPath ));
|
||||
Mem_Free( hInst );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !( hInst->hInstance = Module_Load( hInst->fullPath )))
|
||||
{
|
||||
COM_PushLibraryError( Module_GetError() );
|
||||
Mem_Free( hInst );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pHandle = hInst->hInstance;
|
||||
|
||||
Mem_Free( hInst );
|
||||
|
||||
return pHandle;
|
||||
}
|
||||
|
||||
void COM_FreeLibrary( void *hInstance )
|
||||
{
|
||||
Module_Unload( hInstance );
|
||||
}
|
||||
|
||||
void *COM_GetProcAddress( void *hInstance, const char *name )
|
||||
{
|
||||
return Module_GetAddrByName( hInstance, name );
|
||||
}
|
||||
|
||||
void *COM_FunctionFromName_SR( void *hInstance, const char *pName )
|
||||
{
|
||||
void *funcAddr;
|
||||
|
||||
if( !memcmp( pName, "ofs:", 4 ))
|
||||
funcAddr = Module_GetAddrByOffset( hInstance, Q_atoi( &pName[4] ));
|
||||
else
|
||||
funcAddr = Module_GetAddrByName( hInstance, pName );
|
||||
|
||||
if( !funcAddr )
|
||||
Con_Reportf( S_ERROR "FunctionFromName: Can't get symbol %s: %s\n", pName, Module_GetError() );
|
||||
|
||||
return funcAddr;
|
||||
}
|
||||
|
||||
const char *COM_NameForFunction( void *hInstance, void *function )
|
||||
{
|
||||
static char offsetName[16];
|
||||
const char *funcName;
|
||||
uint addrOffset;
|
||||
|
||||
funcName = Module_GetNameByAddr( hInstance, function );
|
||||
if( funcName )
|
||||
return funcName;
|
||||
|
||||
addrOffset = Module_GetOffsetByAddr( hInstance, function );
|
||||
if( !addrOffset )
|
||||
return NULL;
|
||||
|
||||
Q_snprintf( offsetName, sizeof( offsetName ), "ofs:%u", addrOffset );
|
||||
Con_Reportf( "COM_NameForFunction: %s\n", offsetName );
|
||||
|
||||
return offsetName;
|
||||
}
|
||||
#endif // XASH_LIB == LIB_PSP
|
||||
165
engine/platform/psp/p5ram_psp.c
Normal file
165
engine/platform/psp/p5ram_psp.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
p5ram_psp.c - PSP P5 memory allocator
|
||||
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.
|
||||
*/
|
||||
#include <pspkernel.h>
|
||||
#include <psppower.h>
|
||||
#include <pspsuspend.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "p5ram_psp.h"
|
||||
|
||||
#define P5RAM_ALIGN( x, a ) ((( x ) + (( typeof( x ))( a ) - 1 )) & ~( typeof( x )( a ) - 1 ))
|
||||
|
||||
#define P5RAM_CHECK( addr ) ((( unsigned int )addr >= ( unsigned int )p5ram_addr) && (( unsigned int )addr < ( unsigned int )p5ram_addr + p5ram_size))
|
||||
|
||||
#define P5RAM_FLAG_INIT 0x01
|
||||
#define P5RAM_FLAG_SUSPENDED 0x02
|
||||
|
||||
typedef struct __attribute__(( aligned( 64 ))) p5ram_info_s
|
||||
{
|
||||
SceUID uid;
|
||||
size_t size;
|
||||
struct p5ram_info_s *next;
|
||||
}p5ram_info_t;
|
||||
|
||||
static unsigned char p5ram_flags = 0x00;
|
||||
static p5ram_info_t *p5ram_poolchain = NULL;
|
||||
static void *p5ram_addr;
|
||||
static unsigned int p5ram_size;
|
||||
|
||||
int P5Ram_Init( void )
|
||||
{
|
||||
int result;
|
||||
|
||||
if( p5ram_flags & P5RAM_FLAG_INIT )
|
||||
return -1;
|
||||
|
||||
result = sceKernelVolatileMemLock( 0, &p5ram_addr, &p5ram_size );
|
||||
if( result == 0 )
|
||||
p5ram_flags |= P5RAM_FLAG_INIT;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void *P5Ram_Alloc( size_t size, int clear )
|
||||
{
|
||||
SceUID uid;
|
||||
void *ptr;
|
||||
|
||||
if(!( p5ram_flags & P5RAM_FLAG_INIT ))
|
||||
return NULL;
|
||||
|
||||
uid = sceKernelAllocPartitionMemory( 5, "USER P5", PSP_SMEM_Low, size + sizeof( p5ram_info_t ), NULL );
|
||||
if( uid < 0 ) return NULL;
|
||||
|
||||
ptr = sceKernelGetBlockHeadAddr( uid );
|
||||
(( p5ram_info_t* )ptr )->uid = uid;
|
||||
(( p5ram_info_t* )ptr )->size = size;
|
||||
(( p5ram_info_t* )ptr )->next = p5ram_poolchain;
|
||||
if( clear ) memset(( unsigned char* )ptr + sizeof( p5ram_info_t ), 0, size );
|
||||
|
||||
p5ram_poolchain = ptr;
|
||||
|
||||
return ( void* )(( unsigned char* )ptr + sizeof( p5ram_info_t ));
|
||||
}
|
||||
|
||||
void P5Ram_Free( void *ptr )
|
||||
{
|
||||
p5ram_info_t *info, *next_ptr;
|
||||
|
||||
if( !( p5ram_flags & P5RAM_FLAG_INIT ) || ptr == NULL ) return;
|
||||
|
||||
info = ( p5ram_info_t* )((unsigned char*)ptr - sizeof( p5ram_info_t ));
|
||||
|
||||
if( info == p5ram_poolchain )
|
||||
{
|
||||
p5ram_poolchain = p5ram_poolchain->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_ptr = p5ram_poolchain;
|
||||
while( next_ptr )
|
||||
{
|
||||
if( next_ptr->next == info )
|
||||
{
|
||||
next_ptr->next = info->next;
|
||||
break;
|
||||
}
|
||||
next_ptr = next_ptr->next;
|
||||
}
|
||||
}
|
||||
|
||||
sceKernelFreePartitionMemory( info->uid );
|
||||
}
|
||||
|
||||
void P5Ram_FreeAll( void )
|
||||
{
|
||||
p5ram_info_t *next_ptr;
|
||||
|
||||
while( p5ram_poolchain )
|
||||
{
|
||||
next_ptr = p5ram_poolchain->next;
|
||||
sceKernelFreePartitionMemory( p5ram_poolchain->uid );
|
||||
p5ram_poolchain = next_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
void P5Ram_Shutdown( void )
|
||||
{
|
||||
if( !( p5ram_flags & P5RAM_FLAG_INIT ))
|
||||
return;
|
||||
|
||||
P5Ram_FreeAll();
|
||||
sceKernelVolatileMemUnlock( 0 );
|
||||
|
||||
p5ram_flags &= ~P5RAM_FLAG_INIT;
|
||||
}
|
||||
|
||||
void P5Ram_PowerCallback( int count, int arg, void *common )
|
||||
{
|
||||
if( !( p5ram_flags & ( P5RAM_FLAG_INIT | P5RAM_FLAG_SUSPENDED )))
|
||||
return;
|
||||
|
||||
if ( arg & PSP_POWER_CB_POWER_SWITCH || arg & PSP_POWER_CB_SUSPENDING )
|
||||
{
|
||||
P5Ram_Shutdown();
|
||||
p5ram_flags |= P5RAM_FLAG_SUSPENDED;
|
||||
}
|
||||
else if ( arg & PSP_POWER_CB_RESUMING )
|
||||
{
|
||||
}
|
||||
else if ( arg & PSP_POWER_CB_RESUME_COMPLETE )
|
||||
{
|
||||
P5Ram_Init();
|
||||
p5ram_flags &= ~P5RAM_FLAG_SUSPENDED;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef P5RAM_DEBUG
|
||||
void P5Ram_Print( void )
|
||||
{
|
||||
p5ram_info_t *next_ptr;
|
||||
|
||||
printf("+++++++++++++++++++++++++++++\n");
|
||||
next_ptr = p5ram_poolchain;
|
||||
while( next_ptr )
|
||||
{
|
||||
printf("P5 ALLOC [ 0x%08X 0x%08X 0x%08X 0x%08X ]\n", next_ptr, next_ptr->uid, next_ptr->size, next_ptr->next );
|
||||
next_ptr = next_ptr->next;
|
||||
}
|
||||
printf("+++++++++++++++++++++++++++++\n");
|
||||
}
|
||||
#endif
|
||||
38
engine/platform/psp/p5ram_psp.h
Normal file
38
engine/platform/psp/p5ram_psp.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
p5ram_psp.h - PSP P5 memory allocator 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 P5RAM_PSP_H
|
||||
#define P5RAM_PSP_H
|
||||
|
||||
//#define P5RAM_DEBUG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
int P5Ram_Init( void );
|
||||
void *P5Ram_Alloc( size_t size, int clear );
|
||||
void P5Ram_Free( void *ptr );
|
||||
void P5Ram_FreeAll( void );
|
||||
void P5Ram_Shutdown( void );
|
||||
void P5Ram_PowerCallback( int count, int arg, void *common );
|
||||
#ifdef P5RAM_DEBUG
|
||||
void P5Ram_Print( void );
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // P5RAM_PSP_H
|
||||
248
engine/platform/psp/scemp3/pspmp3.h
Normal file
248
engine/platform/psp/scemp3/pspmp3.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* pspmp3.h - Prototypes for the sceMp3 library
|
||||
*
|
||||
* Copyright (c) 2008 David Perry <tias_dp@hotmail.com>
|
||||
* Copyright (c) 2008 Alexander Berl <raphael@fx-world.org>
|
||||
* Copyright (c) 2022 Sergey Galushko
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SCELIBMP3_H__
|
||||
#define __SCELIBMP3_H__
|
||||
|
||||
#include <psptypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct SceMp3InitArg {
|
||||
/** Stream start position */
|
||||
SceOff mp3StreamStart;
|
||||
/** Stream end position */
|
||||
SceOff mp3StreamEnd;
|
||||
/** Pointer to a buffer to contain raw mp3 stream data (+1472 bytes workspace) */
|
||||
SceUChar8* mp3Buf;
|
||||
/** Size of mp3Buf buffer (must be >= 8192) */
|
||||
SceInt32 mp3BufSize;
|
||||
/** Pointer to decoded pcm samples buffer */
|
||||
SceUChar8* pcmBuf;
|
||||
/** Size of pcmBuf buffer (must be >= 9216) */
|
||||
SceInt32 pcmBufSize;
|
||||
} SceMp3InitArg;
|
||||
|
||||
/**
|
||||
* sceMp3ReserveMp3Handle
|
||||
*
|
||||
* @param args - Pointer to SceMp3InitArg structure
|
||||
*
|
||||
* @return sceMp3 handle on success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3ReserveMp3Handle(SceMp3InitArg* args);
|
||||
|
||||
/**
|
||||
* sceMp3ReleaseMp3Handle
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3ReleaseMp3Handle(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3InitResource
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3InitResource();
|
||||
|
||||
/**
|
||||
* sceMp3TermResource
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3TermResource();
|
||||
|
||||
/**
|
||||
* sceMp3Init
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3Init(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3Decode
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param dst - Pointer to destination pcm samples buffer
|
||||
*
|
||||
* @return number of bytes in decoded pcm buffer, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3Decode(SceInt32 handle, SceShort16** dst);
|
||||
|
||||
/**
|
||||
* sceMp3GetInfoToAddStreamData
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param dst - Pointer to stream data buffer
|
||||
* @param towrite - Space remaining in stream data buffer
|
||||
* @param srcpos - Position in source stream to start reading from
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3GetInfoToAddStreamData(SceInt32 handle, SceUChar8** dst, SceInt32* towrite, SceInt32* srcpos);
|
||||
|
||||
/**
|
||||
* sceMp3NotifyAddStreamData
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param size - number of bytes added to the stream data buffer
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3NotifyAddStreamData(SceInt32 handle, SceInt32 size);
|
||||
|
||||
/**
|
||||
* sceMp3CheckStreamDataNeeded
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return 1 if more stream data is needed, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3CheckStreamDataNeeded(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3SetLoopNum
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param loop - Number of loops
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3SetLoopNum(SceInt32 handle, SceInt32 loop);
|
||||
|
||||
/**
|
||||
* sceMp3GetLoopNum
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Number of loops
|
||||
*/
|
||||
SceInt32 sceMp3GetLoopNum(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetSumDecodedSample
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Number of decoded samples
|
||||
*/
|
||||
SceInt32 sceMp3GetSumDecodedSample(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetMaxOutputSample
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Number of max samples to output
|
||||
*/
|
||||
SceInt32 sceMp3GetMaxOutputSample(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetSamplingRate
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Sampling rate of the mp3
|
||||
*/
|
||||
SceInt32 sceMp3GetSamplingRate(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetBitRate
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Bitrate of the mp3
|
||||
*/
|
||||
SceInt32 sceMp3GetBitRate(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetMp3ChannelNum
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Number of channels of the mp3
|
||||
*/
|
||||
SceInt32 sceMp3GetMp3ChannelNum(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3ResetPlayPosition
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3ResetPlayPosition(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetFrameNum
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3GetFrameNum(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3ResetPlayPositionByFrame
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param frame - frame
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3ResetPlayPositionByFrame(SceInt32 handle, SceUInt32 frame);
|
||||
|
||||
/**
|
||||
* sceMp3GetMPEGVersion
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3GetMPEGVersion(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3LowLevelInit
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param src - Pointer to a buffer to contain raw mp3 stream data
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3LowLevelInit(SceInt32 handle, SceUChar8* src);
|
||||
|
||||
/**
|
||||
* sceMp3LowLevelDecode
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param mp3src -
|
||||
* @param mp3srcused -
|
||||
* @param pcmdst -
|
||||
* @param pcmdstoutsz -
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3LowLevelDecode(SceInt32 handle, SceUChar8* mp3src, SceUInt32* mp3srcused, SceShort16* pcmdst, SceUInt32* pcmdstoutsz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
29
engine/platform/psp/scemp3/sceMp3.S
Normal file
29
engine/platform/psp/scemp3/sceMp3.S
Normal file
@@ -0,0 +1,29 @@
|
||||
.set noreorder
|
||||
|
||||
#include "pspimport.s"
|
||||
|
||||
IMPORT_START "sceMp3",0x00090011
|
||||
IMPORT_FUNC "sceMp3",0x07EC321A,sceMp3ReserveMp3Handle
|
||||
IMPORT_FUNC "sceMp3",0x0DB149F4,sceMp3NotifyAddStreamData
|
||||
IMPORT_FUNC "sceMp3",0x2A368661,sceMp3ResetPlayPosition
|
||||
IMPORT_FUNC "sceMp3",0x354D27EA,sceMp3GetSumDecodedSample
|
||||
IMPORT_FUNC "sceMp3",0x35750070,sceMp3InitResource
|
||||
IMPORT_FUNC "sceMp3",0x3C2FA058,sceMp3TermResource
|
||||
IMPORT_FUNC "sceMp3",0x3CEF484F,sceMp3SetLoopNum
|
||||
IMPORT_FUNC "sceMp3",0x44E07129,sceMp3Init
|
||||
IMPORT_FUNC "sceMp3",0x732B042A,sceMp3EndEntry
|
||||
IMPORT_FUNC "sceMp3",0x7F696782,sceMp3GetMp3ChannelNum
|
||||
IMPORT_FUNC "sceMp3",0x87677E40,sceMp3GetBitRate
|
||||
IMPORT_FUNC "sceMp3",0x87C263D1,sceMp3GetMaxOutputSample
|
||||
IMPORT_FUNC "sceMp3",0x8AB81558,sceMp3StartEntry
|
||||
IMPORT_FUNC "sceMp3",0x8F450998,sceMp3GetSamplingRate
|
||||
IMPORT_FUNC "sceMp3",0xA703FE0F,sceMp3GetInfoToAddStreamData
|
||||
IMPORT_FUNC "sceMp3",0xD021C0FB,sceMp3Decode
|
||||
IMPORT_FUNC "sceMp3",0xD0A56296,sceMp3CheckStreamDataNeeded
|
||||
IMPORT_FUNC "sceMp3",0xD8F54A51,sceMp3GetLoopNum
|
||||
IMPORT_FUNC "sceMp3",0xF5478233,sceMp3ReleaseMp3Handle
|
||||
IMPORT_FUNC "sceMp3",0xAE6D2027,sceMp3GetMPEGVersion
|
||||
IMPORT_FUNC "sceMp3",0x3548AEC8,sceMp3GetFrameNum
|
||||
IMPORT_FUNC "sceMp3",0x0840E808,sceMp3ResetPlayPositionByFrame
|
||||
IMPORT_FUNC "sceMp3",0x1B839B83,sceMp3LowLevelInit
|
||||
IMPORT_FUNC "sceMp3",0xE3EE2C81,sceMp3LowLevelDecode
|
||||
275
engine/platform/psp/snd_psp.c
Normal file
275
engine/platform/psp/snd_psp.c
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
snd_psp.c - psp sound hardware output
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "platform/platform.h"
|
||||
#if XASH_SOUND == SOUND_PSP
|
||||
#include <malloc.h>
|
||||
|
||||
#include <pspaudio.h>
|
||||
#include <pspkernel.h>
|
||||
#include <pspdmac.h>
|
||||
|
||||
#include "sound.h"
|
||||
|
||||
#define PSP_NUM_AUDIO_SAMPLES 1024 // must be multiple of 64
|
||||
#define PSP_OUTPUT_CHANNELS 2
|
||||
#define PSP_OUTPUT_BUFFER_SIZE (( PSP_NUM_AUDIO_SAMPLES ) * ( PSP_OUTPUT_CHANNELS ))
|
||||
|
||||
static struct
|
||||
{
|
||||
SceUID threadUID;
|
||||
SceUID semaUID;
|
||||
int channel;
|
||||
volatile int volL;
|
||||
volatile int volR;
|
||||
volatile int running;
|
||||
} snd_psp = { -1, -1, -1, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, 1 };
|
||||
|
||||
static short snd_psp_buff[2][PSP_OUTPUT_BUFFER_SIZE] __attribute__(( aligned( 64 )));
|
||||
|
||||
/*
|
||||
==================
|
||||
SNDDMA_MainThread
|
||||
|
||||
Copy samples
|
||||
==================
|
||||
*/
|
||||
static int SNDDMA_MainThread( SceSize args, void *argp )
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
while( snd_psp.running )
|
||||
{
|
||||
sceKernelWaitSema( snd_psp.semaUID, 1, NULL );
|
||||
|
||||
int len = PSP_OUTPUT_BUFFER_SIZE;
|
||||
int size = dma.samples;
|
||||
int pos = dma.samplepos;
|
||||
int wrapped = pos + len - size;
|
||||
|
||||
if( wrapped < 0 )
|
||||
{
|
||||
sceDmacMemcpy( snd_psp_buff[index], dma.buffer + ( pos * 2 ), len * 2 );
|
||||
dma.samplepos += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
int remaining = size - pos;
|
||||
sceDmacMemcpy( snd_psp_buff[index], dma.buffer + ( pos * 2 ), remaining * 2 );
|
||||
if( wrapped > 0 )
|
||||
sceDmacMemcpy( snd_psp_buff[index] + ( remaining * 2 ), dma.buffer, wrapped * 2 );
|
||||
dma.samplepos = wrapped;
|
||||
}
|
||||
|
||||
sceKernelSignalSema( snd_psp.semaUID, 1 );
|
||||
|
||||
sceAudioOutputPannedBlocking( snd_psp.channel, snd_psp.volL, snd_psp.volR, snd_psp_buff[index] );
|
||||
index = !index;
|
||||
}
|
||||
|
||||
sceKernelExitThread( 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SNDDMA_Init
|
||||
|
||||
Try to find a sound device to mix for.
|
||||
Returns false if nothing is found.
|
||||
==================
|
||||
*/
|
||||
qboolean SNDDMA_Init( void )
|
||||
{
|
||||
int samplecount;
|
||||
|
||||
dma.format.speed = SOUND_DMA_SPEED;
|
||||
dma.format.channels = PSP_OUTPUT_CHANNELS;
|
||||
dma.format.width = 2;
|
||||
|
||||
// must be multiple of 64
|
||||
samplecount = s_samplecount->value;
|
||||
if( !samplecount )
|
||||
samplecount = 0x4000;
|
||||
|
||||
dma.samples = samplecount * PSP_OUTPUT_CHANNELS;
|
||||
dma.samplepos = 0;
|
||||
dma.buffer = memalign( 64, dma.samples * 2 ); // 16 bit
|
||||
if( !dma.buffer )
|
||||
return false;
|
||||
|
||||
// clearing buffers
|
||||
memset( dma.buffer, 0, dma.samples * 2 );
|
||||
memset( snd_psp_buff, 0, sizeof( snd_psp_buff ));
|
||||
|
||||
// allocate and initialize a hardware output channel
|
||||
snd_psp.channel = sceAudioChReserve( PSP_AUDIO_NEXT_CHANNEL,
|
||||
PSP_NUM_AUDIO_SAMPLES, PSP_AUDIO_FORMAT_STEREO );
|
||||
if( snd_psp.channel < 0 )
|
||||
{
|
||||
SNDDMA_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
// create semaphore
|
||||
snd_psp.semaUID = sceKernelCreateSema( "sound_sema", 0, 1, 255, NULL );
|
||||
if( snd_psp.semaUID <= 0 )
|
||||
{
|
||||
SNDDMA_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
// create audio thread
|
||||
snd_psp.threadUID = sceKernelCreateThread( "sound_thread", SNDDMA_MainThread, 0x12, 0x8000, 0, 0 );
|
||||
if( snd_psp.threadUID < 0 )
|
||||
{
|
||||
SNDDMA_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
// start audio thread
|
||||
if( sceKernelStartThread( snd_psp.threadUID, 0, 0 ) < 0 )
|
||||
{
|
||||
SNDDMA_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
Con_Printf( "Using PSP audio driver: %d Hz\n", dma.format.speed );
|
||||
|
||||
dma.initialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_GetDMAPos
|
||||
|
||||
return the current sample position (in mono samples read)
|
||||
inside the recirculating dma buffer, so the mixing code will know
|
||||
how many sample are required to fill it up.
|
||||
===============
|
||||
*/
|
||||
int SNDDMA_GetDMAPos( void )
|
||||
{
|
||||
return dma.samplepos;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_GetSoundtime
|
||||
|
||||
update global soundtime
|
||||
===============
|
||||
*/
|
||||
int SNDDMA_GetSoundtime( void )
|
||||
{
|
||||
static int buffers, oldsamplepos;
|
||||
int samplepos, fullsamples;
|
||||
|
||||
fullsamples = dma.samples / 2;
|
||||
|
||||
// it is possible to miscount buffers
|
||||
// if it has wrapped twice between
|
||||
// calls to S_Update. Oh well.
|
||||
samplepos = SNDDMA_GetDMAPos();
|
||||
|
||||
if( samplepos < oldsamplepos )
|
||||
{
|
||||
buffers++; // buffer wrapped
|
||||
|
||||
if( paintedtime > 0x40000000 )
|
||||
{
|
||||
// time to chop things off to avoid 32 bit limits
|
||||
buffers = 0;
|
||||
paintedtime = fullsamples;
|
||||
S_StopAllSounds( true );
|
||||
}
|
||||
}
|
||||
|
||||
oldsamplepos = samplepos;
|
||||
|
||||
return ( buffers * fullsamples + samplepos / 2 );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_BeginPainting
|
||||
|
||||
Makes sure dma.buffer is valid
|
||||
===============
|
||||
*/
|
||||
void SNDDMA_BeginPainting( void )
|
||||
{
|
||||
if( snd_psp.semaUID > 0 )
|
||||
sceKernelWaitSema( snd_psp.semaUID, 1, NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_Submit
|
||||
|
||||
Send sound to device if buffer isn't really the dma buffer
|
||||
Also unlocks the dsound buffer
|
||||
===============
|
||||
*/
|
||||
void SNDDMA_Submit( void )
|
||||
{
|
||||
if( snd_psp.semaUID > 0 )
|
||||
sceKernelSignalSema( snd_psp.semaUID, 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_Shutdown
|
||||
|
||||
Reset the sound device for exiting
|
||||
===============
|
||||
*/
|
||||
void SNDDMA_Shutdown( void )
|
||||
{
|
||||
Con_Printf("Shutting down audio.\n");
|
||||
|
||||
snd_psp.running = 0;
|
||||
|
||||
if( snd_psp.threadUID >= 0 )
|
||||
{
|
||||
sceKernelWaitThreadEnd( snd_psp.threadUID, NULL );
|
||||
sceKernelDeleteThread( snd_psp.threadUID );
|
||||
snd_psp.threadUID = -1;
|
||||
}
|
||||
|
||||
if( snd_psp.semaUID > 0 )
|
||||
{
|
||||
sceKernelDeleteSema( snd_psp.semaUID );
|
||||
snd_psp.semaUID = -1;
|
||||
}
|
||||
|
||||
if( snd_psp.channel >= 0 )
|
||||
{
|
||||
sceAudioChRelease( snd_psp.channel );
|
||||
snd_psp.channel = -1;
|
||||
}
|
||||
|
||||
if( dma.buffer )
|
||||
{
|
||||
free( dma.buffer );
|
||||
dma.buffer = NULL;
|
||||
}
|
||||
|
||||
dma.initialized = false;
|
||||
}
|
||||
|
||||
#endif // XASH_SOUND == SOUND_PSP
|
||||
353
engine/platform/psp/sys_psp.c
Normal file
353
engine/platform/psp/sys_psp.c
Normal file
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
sys_psp.c - PSP System utils
|
||||
Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "platform/psp/ka/ka.h"
|
||||
#include "platform/psp/scemp3/pspmp3.h"
|
||||
#include <pspsdk.h>
|
||||
#include <pspkernel.h>
|
||||
#include <psppower.h>
|
||||
#include <psprtc.h>
|
||||
#include <pspprof.h>
|
||||
#include <pspctrl.h>
|
||||
#include <psputility.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
PSP_MODULE_INFO( "Xash3D", PSP_MODULE_USER, 1, 0 );
|
||||
PSP_MAIN_THREAD_ATTR( PSP_THREAD_ATTR_USER | PSP_THREAD_ATTR_VFPU );
|
||||
PSP_MAIN_THREAD_STACK_SIZE_KB( 512 );
|
||||
PSP_HEAP_SIZE_KB( -3 * 1024 ); /* 3 MB for prx modules */
|
||||
|
||||
static qboolean psp_audiolib_init = false;
|
||||
|
||||
static int Platform_ExitCallback( int count, int arg, void *common )
|
||||
{
|
||||
host.crashed = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Platform_PowerCallback( int count, int arg, void *common )
|
||||
{
|
||||
P5Ram_PowerCallback( count, arg, common );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Platform_CallbackThread( SceSize args, void *argp )
|
||||
{
|
||||
int cbid;
|
||||
|
||||
//cbid = sceKernelCreateCallback( "Exit Callback", Platform_ExitCallback, NULL );
|
||||
//sceKernelRegisterExitCallback( cbid );
|
||||
|
||||
cbid = sceKernelCreateCallback( "Power Callback", Platform_PowerCallback, NULL );
|
||||
scePowerRegisterCallback( 0, cbid );
|
||||
|
||||
sceKernelSleepThreadCB();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sets up the callback thread and returns its thread id */
|
||||
static int Platform_SetupCallbacks( void )
|
||||
{
|
||||
int thid = 0;
|
||||
|
||||
thid = sceKernelCreateThread("update_thread", Platform_CallbackThread, 0x11, 0xFA0, 0, 0);
|
||||
if(thid >= 0)
|
||||
{
|
||||
sceKernelStartThread(thid, 0, 0);
|
||||
}
|
||||
return thid;
|
||||
}
|
||||
|
||||
#if XASH_TIMER == TIMER_PSP
|
||||
double Platform_DoubleTime( void )
|
||||
{
|
||||
return ( double )sceKernelGetSystemTimeWide() * 0.000001; // microseconds to seconds
|
||||
}
|
||||
|
||||
void Platform_Sleep( int msec )
|
||||
{
|
||||
sceKernelDelayThread( msec * 1000 );
|
||||
}
|
||||
#endif
|
||||
|
||||
void *Platform_GetNativeObject( const char *name )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Platform_Vibrate( float life, char flags )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Platform_GetClipboardText( char *buffer, size_t size )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Platform_SetClipboardText( const char *buffer, size_t size )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Platform_ShellExecute( const char *path, const char *parms )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#if XASH_MESSAGEBOX == MSGBOX_PSP
|
||||
void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow )
|
||||
{
|
||||
static qboolean g_dbgscreen = false;
|
||||
|
||||
// Clear the sound buffer.
|
||||
S_StopAllSounds( true );
|
||||
|
||||
// Print message to the debug screen.
|
||||
if ( !g_dbgscreen )
|
||||
{
|
||||
pspDebugScreenInit();
|
||||
g_dbgscreen = true;
|
||||
}
|
||||
pspDebugScreenSetTextColor( 0x0080ff );
|
||||
pspDebugScreenPrintf( "\n\n\n\n%s:\n", title );
|
||||
pspDebugScreenSetTextColor( 0x0000ff );
|
||||
pspDebugScreenPrintData( message, Q_strlen( message ) );
|
||||
pspDebugScreenSetTextColor( 0xffffff );
|
||||
pspDebugScreenPrintf( "\n\nPress X to continue.\n" );
|
||||
|
||||
// Wait for a X button press.
|
||||
SceCtrlData pad;
|
||||
do
|
||||
{
|
||||
sceCtrlReadBufferPositive( &pad, 1 );
|
||||
}
|
||||
while( !( pad.Buttons & PSP_CTRL_CROSS ) );
|
||||
pspDebugScreenClear();
|
||||
}
|
||||
#endif // XASH_MESSAGEBOX == MSGBOX_PSP
|
||||
|
||||
void Platform_ReadCmd( const char *fname, int *argc, char **argv )
|
||||
{
|
||||
int cmd_fd;
|
||||
size_t cmd_fsize;
|
||||
byte *cmd_buff;
|
||||
int i, j = 0;
|
||||
|
||||
cmd_fd = sceIoOpen( fname, PSP_O_RDONLY, 0777 );
|
||||
if( cmd_fd > 0 )
|
||||
{
|
||||
cmd_fsize = sceIoLseek( cmd_fd, 0, PSP_SEEK_END );
|
||||
sceIoLseek( cmd_fd, 0, PSP_SEEK_SET );
|
||||
|
||||
printf( "CMD FILE(%s) Size: %i\n", fname, cmd_fsize );
|
||||
|
||||
if( cmd_fsize == 0 ) return;
|
||||
|
||||
cmd_buff = malloc( cmd_fsize );
|
||||
if( !cmd_buff )
|
||||
{
|
||||
printf( "CMD FILE(%s) Memory allocation error!\n", fname );
|
||||
sceIoClose(cmd_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if( sceIoRead(cmd_fd, cmd_buff, cmd_fsize) >= 0 )
|
||||
{
|
||||
for( i = 0; i < cmd_fsize; i++ )
|
||||
{
|
||||
if( isspace( cmd_buff[i] ) != 0 )
|
||||
{
|
||||
if( j == 0 ) continue;
|
||||
|
||||
argv[*argc] = malloc( j + 1 );
|
||||
if( !argv[*argc] )
|
||||
{
|
||||
printf( "CMD FILE(%s) Memory allocation error!\n", fname );
|
||||
free( cmd_buff );
|
||||
sceIoClose( cmd_fd );
|
||||
return;
|
||||
}
|
||||
memcpy( argv[*argc], &cmd_buff[i - j], j );
|
||||
argv[*argc][j] = 0x00;
|
||||
( int )( *argc )++;
|
||||
j = 0;
|
||||
}
|
||||
else j++;
|
||||
|
||||
}
|
||||
if( j != 0 )
|
||||
{
|
||||
argv[*argc] = malloc( j + 1 );
|
||||
if( !argv[*argc] )
|
||||
{
|
||||
printf( "CMD FILE(%s) Memory allocation error!\n", fname );
|
||||
free( cmd_buff );
|
||||
sceIoClose( cmd_fd );
|
||||
return;
|
||||
}
|
||||
memcpy( argv[*argc], &cmd_buff[i - j], j );
|
||||
argv[*argc][j] = 0x00;
|
||||
( int )( *argc )++;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
else printf( "CMD FILE(%s) Read error!\n", fname );
|
||||
|
||||
free( cmd_buff );
|
||||
sceIoClose( cmd_fd );
|
||||
}
|
||||
}
|
||||
|
||||
SceUID Platform_LoadModule( const char *filename, int mpid, SceSize argsize, void *argp )
|
||||
{
|
||||
SceKernelLMOption option;
|
||||
SceUID modid = 0;
|
||||
int retVal = 0, mresult;
|
||||
|
||||
memset( &option, 0, sizeof( option ) );
|
||||
option.size = sizeof( option );
|
||||
option.mpidtext = mpid;
|
||||
option.mpiddata = mpid;
|
||||
option.position = 0;
|
||||
option.access = 1;
|
||||
|
||||
retVal = sceKernelLoadModule( filename, 0, &option );
|
||||
if(retVal < 0)
|
||||
return retVal;
|
||||
|
||||
modid = retVal;
|
||||
|
||||
retVal = sceKernelStartModule( modid, argsize, argp, &mresult, NULL );
|
||||
if( retVal < 0 )
|
||||
return retVal;
|
||||
|
||||
return modid;
|
||||
}
|
||||
|
||||
int Platform_UnloadModule( SceUID modid, int *sce_code )
|
||||
{
|
||||
int status;
|
||||
*sce_code = sceKernelStopModule( modid, 0, NULL, &status, NULL);
|
||||
|
||||
if( ( *sce_code ) < 0 )
|
||||
return -2;
|
||||
else if( status == SCE_KERNEL_ERROR_NOT_STOPPED )
|
||||
return -1;
|
||||
|
||||
*sce_code = sceKernelUnloadModule( modid );
|
||||
return ( ( ( *sce_code ) < 0 ) ? -2 : 0 );
|
||||
}
|
||||
|
||||
int Platform_InitAudioLibs( void )
|
||||
{
|
||||
int status;
|
||||
|
||||
if( psp_audiolib_init )
|
||||
return -1;
|
||||
|
||||
status = sceUtilityLoadModule( PSP_MODULE_AV_AVCODEC );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceUtilityLoadModule(PSP_MODULE_AV_AVCODEC) returned 0x%08X\n", status );
|
||||
return status;
|
||||
}
|
||||
|
||||
status = sceUtilityLoadModule( PSP_MODULE_AV_MP3 );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceUtilityLoadModule(PSP_MODULE_AV_MP3) returned 0x%08X\n", status );
|
||||
return status;
|
||||
}
|
||||
|
||||
// init mp3 resources
|
||||
status = sceMp3InitResource();
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3InitResource returned 0x%08X\n", status );
|
||||
return status;
|
||||
}
|
||||
|
||||
psp_audiolib_init = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Platform_ShutdownAudioLibs( void )
|
||||
{
|
||||
int status;
|
||||
|
||||
if( !psp_audiolib_init )
|
||||
return -1;
|
||||
|
||||
status = sceMp3TermResource();
|
||||
if ( status < 0 )
|
||||
Con_DPrintf( S_ERROR "sceMp3TermResource returned 0x%08X\n", status );
|
||||
|
||||
status = sceUtilityUnloadModule( PSP_MODULE_AV_MP3 );
|
||||
if ( status < 0 )
|
||||
Con_DPrintf( S_ERROR "sceUtilityUnloadModule(PSP_MODULE_AV_MP3) returned 0x%08X\n", status );
|
||||
|
||||
status = sceUtilityUnloadModule( PSP_MODULE_AV_AVCODEC );
|
||||
if ( status < 0 )
|
||||
Con_DPrintf( S_ERROR "sceUtilityUnloadModule(PSP_MODULE_AV_AVCODEC) returned 0x%08X\n", status );
|
||||
|
||||
psp_audiolib_init = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Platform_Init( void )
|
||||
{
|
||||
SceUID kamID;
|
||||
int result;
|
||||
|
||||
// disable fpu exceptions (division by zero and etc...)
|
||||
pspSdkDisableFPUExceptions();
|
||||
|
||||
// exit callback thread
|
||||
Platform_SetupCallbacks();
|
||||
|
||||
// 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 );
|
||||
}
|
||||
|
||||
Platform_InitAudioLibs();
|
||||
|
||||
// P5 Ram init
|
||||
P5Ram_Init();
|
||||
}
|
||||
|
||||
void Platform_Shutdown( void )
|
||||
{
|
||||
P5Ram_Shutdown();
|
||||
Platform_ShutdownAudioLibs();
|
||||
#if XASH_PROFILING
|
||||
gprof_cleanup();
|
||||
#endif
|
||||
}
|
||||
384
engine/platform/psp/vid_psp.c
Normal file
384
engine/platform/psp/vid_psp.c
Normal file
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
vid_psp.c - PSP video component
|
||||
Copyright (C) 2021 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.
|
||||
*/
|
||||
#if XASH_VIDEO == VIDEO_PSP
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
#include <pspkernel.h>
|
||||
#include <pspdisplay.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "mod_local.h"
|
||||
#include "input.h"
|
||||
#include "vid_common.h"
|
||||
|
||||
// Set frame buffer
|
||||
#define PSP_FB_WIDTH 480
|
||||
#define PSP_FB_HEIGHT 272
|
||||
#define PSP_FB_BWIDTH 512
|
||||
#define PSP_FB_FORMAT PSP_DISPLAY_PIXEL_FORMAT_565 //4444,5551,565,8888
|
||||
|
||||
#if PSP_FB_FORMAT == PSP_DISPLAY_PIXEL_FORMAT_4444
|
||||
#define PSP_FB_BPP 2
|
||||
#elif PSP_FB_FORMAT == PSP_DISPLAY_PIXEL_FORMAT_5551
|
||||
#define PSP_FB_BPP 2
|
||||
#elif PSP_FB_FORMAT == PSP_DISPLAY_PIXEL_FORMAT_565
|
||||
#define PSP_FB_BPP 2
|
||||
#elif PSP_FB_FORMAT == PSP_DISPLAY_PIXEL_FORMAT_8888
|
||||
#define PSP_FB_BPP 4
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// Set up screen scaling
|
||||
#define PSP_WIDTH_AR 30
|
||||
#define PSP_HEIGHT_AR 17
|
||||
#define PSP_MIN_MAR 12
|
||||
#define PSP_MAX_MAR 16
|
||||
#define PSP_MIN_MAR_W (PSP_WIDTH_AR * PSP_MIN_MAR)
|
||||
#define PSP_MIN_MAR_H (PSP_HEIGHT_AR * PSP_MIN_MAR)
|
||||
#define PSP_MAX_MAR_W (PSP_WIDTH_AR * PSP_MAX_MAR)
|
||||
#define PSP_MAX_MAR_H (PSP_HEIGHT_AR * PSP_MAX_MAR)
|
||||
#endif
|
||||
|
||||
|
||||
static qboolean vsync;
|
||||
#if 1
|
||||
static vidmode_t vidmodes[] = { "480x272", PSP_FB_WIDTH, PSP_FB_HEIGHT};
|
||||
static int num_vidmodes = 1;
|
||||
#else
|
||||
static vidmode_t *vidmodes = NULL;
|
||||
static int num_vidmodes = 0;
|
||||
#endif
|
||||
static struct
|
||||
{
|
||||
#if 0
|
||||
int in_width, in_height;
|
||||
int out_width, out_height;
|
||||
#endif
|
||||
void *draw_buffer;
|
||||
void *disp_buffer;
|
||||
}vid_psp;
|
||||
|
||||
qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b )
|
||||
{
|
||||
*stride = PSP_FB_BWIDTH;
|
||||
*r = 31;
|
||||
*g = 63 << 5;
|
||||
*b = 31 << 11;
|
||||
*bpp = 2;
|
||||
|
||||
vid_psp.draw_buffer = (void*)malloc( PSP_FB_HEIGHT * PSP_FB_BWIDTH * PSP_FB_BPP );
|
||||
if( !vid_psp.draw_buffer )
|
||||
Host_Error( "Memory allocation failled! (vid_psp.draw_buffer)\n");
|
||||
|
||||
vid_psp.disp_buffer = (void*)malloc( PSP_FB_HEIGHT * PSP_FB_BWIDTH * PSP_FB_BPP );
|
||||
if( !vid_psp.disp_buffer )
|
||||
Host_Error( "Memory allocation failled! (vid_psp.disp_buffer)\n");
|
||||
|
||||
sceDisplaySetMode(0, PSP_FB_WIDTH, PSP_FB_HEIGHT);
|
||||
sceDisplaySetFrameBuf(vid_psp.disp_buffer, PSP_FB_BWIDTH, PSP_FB_FORMAT, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void *SW_LockBuffer( void )
|
||||
{
|
||||
return vid_psp.draw_buffer;
|
||||
}
|
||||
|
||||
void SW_UnlockBuffer( void )
|
||||
{
|
||||
void* p_swap = vid_psp.disp_buffer;
|
||||
vid_psp.disp_buffer = vid_psp.draw_buffer;
|
||||
vid_psp.draw_buffer = p_swap;
|
||||
|
||||
sceKernelDcacheWritebackInvalidateAll();
|
||||
sceDisplaySetFrameBuf(vid_psp.disp_buffer, PSP_FB_BWIDTH, PSP_FB_FORMAT, PSP_DISPLAY_SETBUF_NEXTFRAME);
|
||||
|
||||
if ( vsync )
|
||||
{
|
||||
sceDisplayWaitVblankStart();
|
||||
}
|
||||
}
|
||||
|
||||
int R_MaxVideoModes( void )
|
||||
{
|
||||
return num_vidmodes;
|
||||
}
|
||||
|
||||
vidmode_t *R_GetVideoMode( int num )
|
||||
{
|
||||
if( !vidmodes || num < 0 || num >= R_MaxVideoModes() )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return vidmodes + num;
|
||||
}
|
||||
#if 0
|
||||
static void R_InitVideoModes( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
vidmodes = Mem_Malloc( host.mempool, (PSP_MAX_MAR - PSP_MIN_MAR) * sizeof( vidmode_t ) );
|
||||
|
||||
// from smallest to largest
|
||||
for(i = PSP_MIN_MAR ; i <= PSP_MAX_MAR; i++ )
|
||||
{
|
||||
vidmodes[num_vidmodes].width = PSP_WIDTH_AR * i;
|
||||
vidmodes[num_vidmodes].height = PSP_HEIGHT_AR * i;
|
||||
vidmodes[num_vidmodes].desc =
|
||||
copystring( va( "%ix%i", vidmodes[num_vidmodes].width, vidmodes[num_vidmodes].height ));
|
||||
|
||||
num_vidmodes++;
|
||||
}
|
||||
}
|
||||
|
||||
static void R_FreeVideoModes( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
if(!vidmodes)
|
||||
return;
|
||||
|
||||
for( i = 0; i < num_vidmodes; i++ )
|
||||
Mem_Free( (char*)vidmodes[i].desc );
|
||||
Mem_Free( vidmodes );
|
||||
|
||||
vidmodes = NULL;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
=================
|
||||
GL_GetProcAddress
|
||||
=================
|
||||
*/
|
||||
void *GL_GetProcAddress( const char *name )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
GL_UpdateSwapInterval
|
||||
===============
|
||||
*/
|
||||
void GL_UpdateSwapInterval( void )
|
||||
{
|
||||
// disable VSync while level is loading
|
||||
if( cls.state < ca_active )
|
||||
{
|
||||
// setup vsync here
|
||||
vsync = false;
|
||||
SetBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||
}
|
||||
else if( FBitSet( gl_vsync->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||
vsync = (gl_vsync->value > 0) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
static qboolean VID_SetScreenResolution( int width, int height )
|
||||
{
|
||||
int render_w = width, render_h = height;
|
||||
uint rotate = vid_rotate->value;
|
||||
|
||||
if( ref.dllFuncs.R_SetDisplayTransform( rotate, 0, 0, vid_scale->value, vid_scale->value ) )
|
||||
{
|
||||
if( rotate & 1 )
|
||||
{
|
||||
int swap = render_w;
|
||||
|
||||
render_w = render_h;
|
||||
render_h = swap;
|
||||
}
|
||||
|
||||
render_h /= vid_scale->value;
|
||||
render_w /= vid_scale->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf( S_WARN "failed to setup screen transform\n" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
R_SaveVideoMode( width, height, render_w, render_h );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GL_SwapBuffers( void )
|
||||
{
|
||||
if ( vsync ) sceDisplayWaitVblankStart();
|
||||
}
|
||||
|
||||
int GL_SetAttribute( int attr, int val )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GL_GetAttribute( int attr, int *val )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_Init_Video
|
||||
==================
|
||||
*/
|
||||
qboolean R_Init_Video( const int type )
|
||||
{
|
||||
string safe;
|
||||
qboolean retval;
|
||||
|
||||
refState.desktopBitsPixel = ( PSP_FB_BPP * 8 );
|
||||
|
||||
VID_StartupGamma();
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case REF_SOFTWARE:
|
||||
glw_state.software = true;
|
||||
break;
|
||||
case REF_GL:
|
||||
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", safe ) )
|
||||
glw_state.safe = bound( SAFE_NO, Q_atoi( safe ), SAFE_DONTCARE );
|
||||
break;
|
||||
default:
|
||||
Host_Error( "Can't initialize unknown context type %d!\n", type );
|
||||
break;
|
||||
}
|
||||
|
||||
if( !(retval = VID_SetMode()) )
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case REF_GL:
|
||||
// refdll also can check extensions
|
||||
ref.dllFuncs.GL_InitExtensions();
|
||||
break;
|
||||
case REF_SOFTWARE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
R_InitVideoModes();
|
||||
#endif
|
||||
host.renderinfo_changed = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
rserr_t R_ChangeDisplaySettings( int width, int height, qboolean fullscreen )
|
||||
{
|
||||
Con_Reportf( "R_ChangeDisplaySettings: Setting video mode to %dx%d %s\n", width, height, fullscreen ? "fullscreen" : "windowed" );
|
||||
|
||||
refState.fullScreen = fullscreen;
|
||||
|
||||
if( !VID_SetScreenResolution( width, height ) )
|
||||
return rserr_invalid_fullscreen;
|
||||
|
||||
return rserr_ok;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
VID_SetMode
|
||||
|
||||
Set the described video mode
|
||||
==================
|
||||
*/
|
||||
qboolean VID_SetMode( void )
|
||||
{
|
||||
qboolean fullscreen = false;
|
||||
int iScreenWidth, iScreenHeight;
|
||||
rserr_t err;
|
||||
|
||||
#if 1
|
||||
iScreenWidth = PSP_FB_WIDTH;
|
||||
iScreenHeight = PSP_FB_HEIGHT;
|
||||
#else
|
||||
vid_psp.out_width = PSP_FB_WIDTH;
|
||||
vid_psp.out_height = PSP_FB_HEIGHT;
|
||||
|
||||
iScreenWidth = Cvar_VariableInteger( "width" );
|
||||
iScreenHeight = Cvar_VariableInteger( "height" );
|
||||
|
||||
if( iScreenWidth < PSP_MIN_MAR_W ||
|
||||
iScreenHeight < PSP_MIN_MAR_H ) // trying to get resolution automatically by default
|
||||
{
|
||||
iScreenWidth = PSP_MIN_MAR_W;
|
||||
iScreenHeight = PSP_MIN_MAR_H;
|
||||
}
|
||||
|
||||
if( iScreenWidth > PSP_MAX_MAR_W ||
|
||||
iScreenHeight > PSP_MAX_MAR_H ) // trying to get resolution automatically by default
|
||||
{
|
||||
iScreenWidth = PSP_MAX_MAR_W;
|
||||
iScreenHeight = PSP_MAX_MAR_H;
|
||||
}
|
||||
#endif
|
||||
if( !FBitSet( vid_fullscreen->flags, FCVAR_CHANGED ) )
|
||||
Cvar_SetValue( "fullscreen", DEFAULT_FULLSCREEN );
|
||||
else
|
||||
ClearBits( vid_fullscreen->flags, FCVAR_CHANGED );
|
||||
|
||||
SetBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||
fullscreen = true;//Cvar_VariableInteger("fullscreen") != 0;
|
||||
|
||||
if(( err = R_ChangeDisplaySettings( iScreenWidth, iScreenHeight, fullscreen )) == rserr_ok )
|
||||
{
|
||||
#if 0
|
||||
vid_psp.in_width = iScreenWidth;
|
||||
vid_psp.in_height = iScreenHeight;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_Free_Video
|
||||
==================
|
||||
*/
|
||||
void R_Free_Video( void )
|
||||
{
|
||||
#if 0
|
||||
R_FreeVideoModes();
|
||||
#endif
|
||||
ref.dllFuncs.GL_ClearExtensions();
|
||||
if( glw_state.software )
|
||||
{
|
||||
if( vid_psp.draw_buffer )
|
||||
free( vid_psp.draw_buffer );
|
||||
if( vid_psp.disp_buffer )
|
||||
free( vid_psp.disp_buffer );
|
||||
|
||||
vid_psp.draw_buffer = NULL;
|
||||
vid_psp.disp_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // XASH_DEDICATED
|
||||
#endif // XASH_VIDEO
|
||||
@@ -446,6 +446,11 @@ typedef struct ref_api_s
|
||||
|
||||
// filesystem exports
|
||||
fs_api_t *fsapi;
|
||||
|
||||
#if XASH_PSP
|
||||
void *(*P5Ram_Alloc)( size_t size, int clear );
|
||||
void (*P5Ram_Free)( void *ptr );
|
||||
#endif
|
||||
} ref_api_t;
|
||||
|
||||
struct mip_s;
|
||||
|
||||
@@ -54,7 +54,7 @@ extern int SV_UPDATE_BACKUP;
|
||||
#define GROUP_OP_AND 0
|
||||
#define GROUP_OP_NAND 1
|
||||
|
||||
#ifdef NDEBUG
|
||||
#if defined( NDEBUG )
|
||||
#define SV_IsValidEdict( e ) ( e && !e->free )
|
||||
#else
|
||||
#define SV_IsValidEdict( e ) SV_CheckEdict( e, __FILE__, __LINE__ )
|
||||
@@ -509,7 +509,13 @@ qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multipla
|
||||
qboolean SV_InitGame( void );
|
||||
void SV_ActivateServer( int runPhysics );
|
||||
qboolean SV_SpawnServer( const char *server, const char *startspot, qboolean background );
|
||||
model_t *SV_ModelHandle( int modelindex );
|
||||
static inline model_t *GAME_EXPORT SV_ModelHandle( int modelindex )
|
||||
{
|
||||
if( unlikely( modelindex < 0 || modelindex >= MAX_MODELS ))
|
||||
return NULL;
|
||||
|
||||
return sv.models[modelindex];
|
||||
}
|
||||
void SV_DeactivateServer( void );
|
||||
|
||||
//
|
||||
@@ -648,10 +654,17 @@ void SV_RestartAmbientSounds( void );
|
||||
void SV_RestartDecals( void );
|
||||
void SV_RestartStaticEnts( void );
|
||||
int pfnDropToFloor( edict_t* e );
|
||||
edict_t *SV_EdictNum( int n );
|
||||
void SV_SetModel( edict_t *ent, const char *name );
|
||||
int pfnDecalIndex( const char *m );
|
||||
|
||||
static inline edict_t *SV_EdictNum( int n )
|
||||
{
|
||||
if( unlikely( n < 0 || n >= GI->max_edicts ))
|
||||
return NULL;
|
||||
|
||||
return &svgame.edicts[n];
|
||||
}
|
||||
|
||||
//
|
||||
// sv_log.c
|
||||
//
|
||||
|
||||
@@ -39,13 +39,6 @@ static vec3_t viewPoint[MAX_CLIENTS];
|
||||
typedef void (__cdecl *LINK_ENTITY_FUNC)( entvars_t *pev );
|
||||
typedef void (__stdcall *GIVEFNPTRSTODLL)( enginefuncs_t* engfuncs, globalvars_t *pGlobals );
|
||||
|
||||
edict_t *SV_EdictNum( int n )
|
||||
{
|
||||
if(( n >= 0 ) && ( n < GI->max_edicts ))
|
||||
return svgame.edicts + n;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
qboolean SV_CheckEdict( const edict_t *e, const char *file, const int line )
|
||||
{
|
||||
|
||||
@@ -262,20 +262,6 @@ int GAME_EXPORT SV_GenericIndex( const char *filename )
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_ModelHandle
|
||||
|
||||
get model by handle
|
||||
================
|
||||
*/
|
||||
model_t *GAME_EXPORT SV_ModelHandle( int modelindex )
|
||||
{
|
||||
if( modelindex < 0 || modelindex >= MAX_MODELS )
|
||||
return NULL;
|
||||
return sv.models[modelindex];
|
||||
}
|
||||
|
||||
static resourcetype_t SV_DetermineResourceType( const char *filename )
|
||||
{
|
||||
if( !Q_strncmp( filename, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 ) && Sound_SupportedFileFormat( COM_FileExtension( filename )))
|
||||
|
||||
@@ -945,12 +945,12 @@ static edict_t *SV_PushMove( edict_t *pusher, float movetime )
|
||||
// filter movetypes to collide with
|
||||
if( !SV_CanPushed( check ))
|
||||
continue;
|
||||
|
||||
#if !XASH_PSP
|
||||
pusher->v.solid = SOLID_NOT;
|
||||
block = SV_TestEntityPosition( check, pusher );
|
||||
pusher->v.solid = oldsolid;
|
||||
if( block ) continue;
|
||||
|
||||
#endif
|
||||
// if the entity is standing on the pusher, it will definately be moved
|
||||
if( !( FBitSet( check->v.flags, FL_ONGROUND ) && check->v.groundentity == pusher ))
|
||||
{
|
||||
@@ -966,7 +966,12 @@ static edict_t *SV_PushMove( edict_t *pusher, float movetime )
|
||||
if( !SV_TestEntityPosition( check, NULL ))
|
||||
continue;
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
pusher->v.solid = SOLID_NOT;
|
||||
block = SV_TestEntityPosition( check, pusher );
|
||||
pusher->v.solid = oldsolid;
|
||||
if( block ) continue;
|
||||
#endif
|
||||
// remove the onground flag for non-players
|
||||
if( check->v.movetype != MOVETYPE_WALK )
|
||||
check->v.flags &= ~FL_ONGROUND;
|
||||
@@ -1058,18 +1063,19 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
||||
for( e = 1; e < svgame.numEntities; e++ )
|
||||
{
|
||||
check = EDICT_NUM( e );
|
||||
|
||||
if( !SV_IsValidEdict( check ))
|
||||
continue;
|
||||
|
||||
// filter movetypes to collide with
|
||||
if( !SV_CanPushed( check ))
|
||||
continue;
|
||||
|
||||
#if !XASH_PSP
|
||||
pusher->v.solid = SOLID_NOT;
|
||||
block = SV_TestEntityPosition( check, pusher );
|
||||
pusher->v.solid = oldsolid;
|
||||
if( block ) continue;
|
||||
|
||||
#endif
|
||||
// if the entity is standing on the pusher, it will definately be moved
|
||||
if( !(( check->v.flags & FL_ONGROUND ) && check->v.groundentity == pusher ))
|
||||
{
|
||||
@@ -1085,7 +1091,12 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
||||
if( !SV_TestEntityPosition( check, NULL ))
|
||||
continue;
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
pusher->v.solid = SOLID_NOT;
|
||||
block = SV_TestEntityPosition( check, pusher );
|
||||
pusher->v.solid = oldsolid;
|
||||
if( block ) continue;
|
||||
#endif
|
||||
// save original position of contacted entity
|
||||
pushed_p->ent = check;
|
||||
VectorCopy( check->v.origin, pushed_p->origin );
|
||||
@@ -1101,7 +1112,7 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
||||
Matrix4x4_VectorITransform( start_l, org, temp );
|
||||
Matrix4x4_VectorTransform( end_l, temp, org2 );
|
||||
VectorSubtract( org2, org, lmove );
|
||||
|
||||
|
||||
// i can't clear FL_ONGROUND in all cases because many bad things may be happen
|
||||
if( check->v.movetype != MOVETYPE_WALK )
|
||||
{
|
||||
@@ -1140,7 +1151,6 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
||||
return check;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,11 @@ half-life implementation of saverestore system
|
||||
#define SAVEGAME_HEADER (('V'<<24)+('A'<<16)+('S'<<8)+'J') // little-endian "JSAV"
|
||||
#define SAVEGAME_VERSION 0x0071 // Version 0.71 GoldSrc compatible
|
||||
#define CLIENT_SAVEGAME_VERSION 0x0067 // Version 0.67
|
||||
|
||||
#if XASH_PSP
|
||||
#define SAVE_HEAPSIZE 0x200000 // reserve 2Mb for now
|
||||
#else
|
||||
#define SAVE_HEAPSIZE 0x400000 // reserve 4Mb for now
|
||||
#endif
|
||||
#define SAVE_HASHSTRINGS 0xFFF // 4095 unique strings
|
||||
|
||||
// savedata headers
|
||||
@@ -384,7 +387,13 @@ static void InitEntityTable( SAVERESTOREDATA *pSaveData, int entityCount )
|
||||
ENTITYTABLE *pTable;
|
||||
int i;
|
||||
|
||||
#if XASH_PSP
|
||||
pSaveData->pTable = P5Ram_Alloc( sizeof( ENTITYTABLE ) * entityCount, 1 );
|
||||
if( !pSaveData->pTable )
|
||||
Host_Error( "%s: P5Ram_Alloc (pSaveData->pTable) failed!", __FUNCTION__ );
|
||||
#else
|
||||
pSaveData->pTable = Mem_Calloc( host.mempool, sizeof( ENTITYTABLE ) * entityCount );
|
||||
#endif
|
||||
pSaveData->tableCount = entityCount;
|
||||
|
||||
// setup entitytable
|
||||
@@ -700,8 +709,17 @@ static SAVERESTOREDATA *SaveInit( int size, int tokenCount )
|
||||
{
|
||||
SAVERESTOREDATA *pSaveData;
|
||||
|
||||
#if XASH_PSP
|
||||
pSaveData = P5Ram_Alloc( sizeof( SAVERESTOREDATA ) + size, 1 );
|
||||
if( !pSaveData )
|
||||
Host_Error( "%s: P5Ram_Alloc (pSaveData) failed!", __FUNCTION__ );
|
||||
pSaveData->pTokens = (char **)P5Ram_Alloc( tokenCount * sizeof( char* ), 1 );
|
||||
if( !pSaveData->pTokens )
|
||||
Host_Error( "%s: P5Ram_Alloc (pSaveData->pTokens) failed!", __FUNCTION__ );
|
||||
#else
|
||||
pSaveData = Mem_Calloc( host.mempool, sizeof( SAVERESTOREDATA ) + size );
|
||||
pSaveData->pTokens = (char **)Mem_Calloc( host.mempool, tokenCount * sizeof( char* ));
|
||||
#endif
|
||||
pSaveData->tokenCount = tokenCount;
|
||||
|
||||
pSaveData->pBaseData = (char *)(pSaveData + 1); // skip the save structure);
|
||||
@@ -750,20 +768,32 @@ static void SaveFinish( SAVERESTOREDATA *pSaveData )
|
||||
|
||||
if( pSaveData->pTokens )
|
||||
{
|
||||
#if XASH_PSP
|
||||
P5Ram_Free( pSaveData->pTokens );
|
||||
#else
|
||||
Mem_Free( pSaveData->pTokens );
|
||||
#endif
|
||||
pSaveData->pTokens = NULL;
|
||||
pSaveData->tokenCount = 0;
|
||||
}
|
||||
|
||||
if( pSaveData->pTable )
|
||||
{
|
||||
#if XASH_PSP
|
||||
P5Ram_Free( pSaveData->pTable );
|
||||
#else
|
||||
Mem_Free( pSaveData->pTable );
|
||||
#endif
|
||||
pSaveData->pTable = NULL;
|
||||
pSaveData->tableCount = 0;
|
||||
}
|
||||
|
||||
svgame.globals->pSaveData = NULL;
|
||||
#if XASH_PSP
|
||||
P5Ram_Free( pSaveData );
|
||||
#else
|
||||
Mem_Free( pSaveData );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2333,14 +2363,26 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
pSaveData = (char *)P5Ram_Alloc( size, 0 );
|
||||
if( !pSaveData )
|
||||
Host_Error( "%s: P5Ram_Alloc (pSaveData) failed!", __FUNCTION__ );
|
||||
#else
|
||||
pSaveData = (char *)Mem_Malloc( host.mempool, size );
|
||||
#endif
|
||||
FS_Read( f, pSaveData, size );
|
||||
pData = pSaveData;
|
||||
|
||||
// allocate a table for the strings, and parse the table
|
||||
if( tokenSize > 0 )
|
||||
{
|
||||
#if XASH_PSP
|
||||
pTokenList = P5Ram_Alloc( tokenCount * sizeof( char* ), 1 );
|
||||
if( !pTokenList )
|
||||
Host_Error( "%s: P5Ram_Alloc (pTokenList) failed!", __FUNCTION__ );
|
||||
#else
|
||||
pTokenList = Mem_Calloc( host.mempool, tokenCount * sizeof( char* ));
|
||||
#endif
|
||||
|
||||
// make sure the token strings pointed to by the pToken hashtable.
|
||||
for( i = 0; i < tokenCount; i++ )
|
||||
@@ -2352,22 +2394,40 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
||||
else pTokenList = NULL;
|
||||
|
||||
// short, short (size, index of field name)
|
||||
#if XASH_PSP /* FIX Unaligned access! */
|
||||
short offpd;
|
||||
memcpy(&offpd, pData, sizeof( short ) );
|
||||
nFieldSize = offpd;
|
||||
pData += sizeof( short );
|
||||
|
||||
memcpy(&offpd, pData, sizeof( short ));
|
||||
pFieldName = pTokenList[offpd];
|
||||
#else
|
||||
nFieldSize = *(short *)pData;
|
||||
pData += sizeof( short );
|
||||
pFieldName = pTokenList[*(short *)pData];
|
||||
|
||||
#endif
|
||||
if( Q_stricmp( pFieldName, "GameHeader" ))
|
||||
{
|
||||
Q_strncpy( comment, "<missing GameHeader>", MAX_STRING );
|
||||
#if XASH_PSP
|
||||
if( pTokenList ) P5Ram_Free( pTokenList );
|
||||
if( pSaveData ) P5Ram_Free( pSaveData );
|
||||
#else
|
||||
if( pTokenList ) Mem_Free( pTokenList );
|
||||
if( pSaveData ) Mem_Free( pSaveData );
|
||||
#endif
|
||||
FS_Close( f );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// int (fieldcount)
|
||||
pData += sizeof( short );
|
||||
#if XASH_PSP /* FIX Unaligned access! */
|
||||
memcpy(&nNumberOfFields, pData, sizeof(int));
|
||||
#else
|
||||
nNumberOfFields = (int)*pData;
|
||||
#endif
|
||||
pData += nFieldSize;
|
||||
|
||||
// each field is a short (size), short (index of name), binary string of "size" bytes (data)
|
||||
@@ -2378,11 +2438,23 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
||||
// Size
|
||||
// szName
|
||||
// Actual Data
|
||||
|
||||
|
||||
#if XASH_PSP /* FIX Unaligned access! */
|
||||
memcpy(&offpd, pData, sizeof( short ) );
|
||||
nFieldSize = offpd;
|
||||
pData += sizeof( short );
|
||||
|
||||
memcpy(&offpd, pData, sizeof( short ));
|
||||
pFieldName = pTokenList[offpd];
|
||||
pData += sizeof( short );
|
||||
#else
|
||||
nFieldSize = *(short *)pData;
|
||||
pData += sizeof( short );
|
||||
|
||||
pFieldName = pTokenList[*(short *)pData];
|
||||
pData += sizeof( short );
|
||||
#endif
|
||||
|
||||
size = Q_min( nFieldSize, MAX_STRING );
|
||||
|
||||
@@ -2400,8 +2472,13 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
||||
}
|
||||
|
||||
// delete the string table we allocated
|
||||
#if XASH_PSP
|
||||
if( pTokenList ) P5Ram_Free( pTokenList );
|
||||
if( pSaveData ) P5Ram_Free( pSaveData );
|
||||
#else
|
||||
if( pTokenList ) Mem_Free( pTokenList );
|
||||
if( pSaveData ) Mem_Free( pSaveData );
|
||||
#endif
|
||||
FS_Close( f );
|
||||
|
||||
// at least mapname should be filled
|
||||
|
||||
@@ -65,6 +65,8 @@ typedef enum
|
||||
SPR_CULL_NONE, // oriented sprite will be draw back face too
|
||||
} facetype_t;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
// generic helper
|
||||
typedef struct
|
||||
{
|
||||
@@ -133,4 +135,6 @@ typedef struct
|
||||
|
||||
STATIC_ASSERT( sizeof( dframetype_t ) == 4, "invalid dframetype_t size" );
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif//SPRITE_H
|
||||
|
||||
@@ -67,6 +67,8 @@ def configure(conf):
|
||||
# then remove them to avoid them getting linked to shared objects
|
||||
for lib in extra_libs:
|
||||
conf.env.LDFLAGS.remove(lib)
|
||||
elif conf.env.DEST_OS == 'psp':
|
||||
conf.define('XASH_NO_NETWORK', 1)
|
||||
elif conf.options.FBDEV_SW:
|
||||
# unused, XASH_LINUX without XASH_SDL gives fbdev & alsa support
|
||||
# conf.define('XASH_FBDEV', 1)
|
||||
@@ -87,7 +89,8 @@ def configure(conf):
|
||||
|
||||
if conf.options.STATIC:
|
||||
conf.env.STATIC = True
|
||||
conf.define('XASH_NO_LIBDL',1)
|
||||
if conf.env.DEST_OS != 'psp':
|
||||
conf.define('XASH_NO_LIBDL',1)
|
||||
|
||||
if not conf.env.DEST_OS in ['win32', 'android'] and not conf.options.NO_ASYNC_RESOLVE:
|
||||
conf.check_pthreads()
|
||||
@@ -132,16 +135,19 @@ def build(bld):
|
||||
'common/*.c',
|
||||
'common/imagelib/*.c',
|
||||
'common/soundlib/*.c',
|
||||
'common/soundlib/libmpg/*.c',
|
||||
'server/*.c'])
|
||||
|
||||
# PSP uses hw MP3 decoder
|
||||
if bld.env.DEST_OS != 'psp':
|
||||
source += bld.path.ant_glob(['common/soundlib/libmpg/*.c'])
|
||||
|
||||
if bld.env.ENGINE_TESTS:
|
||||
source += bld.path.ant_glob(['tests/*.c'])
|
||||
|
||||
if bld.env.DEST_OS == 'win32':
|
||||
libs += ['USER32', 'SHELL32', 'GDI32', 'ADVAPI32', 'DBGHELP', 'PSAPI', 'WS2_32' ]
|
||||
source += bld.path.ant_glob(['platform/win32/*.c'])
|
||||
elif bld.env.DEST_OS not in ['dos', 'nswitch', 'psvita']: #posix
|
||||
elif bld.env.DEST_OS not in ['dos', 'nswitch', 'psvita', 'psp']: #posix
|
||||
libs += [ 'M', 'RT', 'PTHREAD', 'ASOUND']
|
||||
if not bld.env.STATIC:
|
||||
libs += ['DL']
|
||||
@@ -211,6 +217,10 @@ def build(bld):
|
||||
'-lSceKernelDmacMgr_stub'
|
||||
]
|
||||
|
||||
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:
|
||||
source += bld.path.ant_glob([
|
||||
|
||||
@@ -121,6 +121,8 @@ const char *Q_PlatformStringByID( const int platform )
|
||||
return "nswitch";
|
||||
case PLATFORM_PSVITA:
|
||||
return "psvita";
|
||||
case PLATFORM_PSP:
|
||||
return "psp";
|
||||
}
|
||||
|
||||
assert( 0 );
|
||||
|
||||
@@ -86,6 +86,7 @@ Then you can use another oneliner to query all variables:
|
||||
#undef XASH_X86
|
||||
#undef XASH_NSWITCH
|
||||
#undef XASH_PSVITA
|
||||
#undef XASH_PSP
|
||||
|
||||
//================================================================
|
||||
//
|
||||
@@ -98,6 +99,8 @@ Then you can use another oneliner to query all variables:
|
||||
#define XASH_EMSCRIPTEN 1
|
||||
#elif defined __WATCOMC__ && defined __DOS__
|
||||
#define XASH_DOS4GW 1
|
||||
#elif defined __psp__
|
||||
#define XASH_PSP 1
|
||||
#else // POSIX compatible
|
||||
#define XASH_POSIX 1
|
||||
#if defined __linux__
|
||||
@@ -144,7 +147,7 @@ Then you can use another oneliner to query all variables:
|
||||
// but we still need XASH_MOBILE_PLATFORM for the engine.
|
||||
// So this macro is defined entirely in build-system: see main wscript
|
||||
// HLSDK/PrimeXT/other SDKs users note: you may ignore this macro
|
||||
#if XASH_ANDROID || XASH_IOS || XASH_NSWITCH || XASH_PSVITA || XASH_SAILFISH
|
||||
#if XASH_ANDROID || XASH_IOS || XASH_NSWITCH || XASH_PSVITA || XASH_SAILFISH || XASH_PSP
|
||||
#define XASH_MOBILE_PLATFORM 1
|
||||
#endif
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ GNU General Public License for more details.
|
||||
#define PLATFORM_NSWITCH 13
|
||||
#define PLATFORM_PSVITA 14
|
||||
#define PLATFORM_LINUX_UNKNOWN 15
|
||||
#define PLATFORM_PSP 16
|
||||
|
||||
#if XASH_WIN32
|
||||
#define XASH_PLATFORM PLATFORM_WIN32
|
||||
@@ -73,6 +74,8 @@ GNU General Public License for more details.
|
||||
#define XASH_PLATFORM PLATFORM_NSWITCH
|
||||
#elif XASH_PSVITA
|
||||
#define XASH_PLATFORM PLATFORM_PSVITA
|
||||
#elif XASH_PSP
|
||||
#define XASH_PLATFORM PLATFORM_PSP
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
@@ -35,13 +35,61 @@ const matrix3x4 m_matrix3x4_identity =
|
||||
*/
|
||||
void Matrix3x4_VectorTransform( const matrix3x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
"vhdp.q S000, C130, C100\n" // S000 = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3]
|
||||
"vhdp.q S001, C130, C110\n" // S001 = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2] + in[1][3]
|
||||
"vhdp.q S002, C130, C120\n" // S002 = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2] + in[2][3]
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3];
|
||||
out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2] + in[1][3];
|
||||
out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2] + in[2][3];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix3x4_VectorITransform( const matrix3x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
"vsub.t C130, C130, R103\n" // C130 = v - in[][3]
|
||||
#if 1
|
||||
"vtfm3.t C000, E100, C130\n" // C000 = E100 * C130
|
||||
#else
|
||||
"vdot.t S000, C130, R100\n" // S000 = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0]
|
||||
"vdot.t S001, C130, R101\n" // S001 = dir[0] * in[0][1] + dir[1] * in[1][1] + dir[2] * in[2][1]
|
||||
"vdot.t S002, C130, R102\n" // S002 = dir[0] * in[0][2] + dir[1] * in[1][2] + dir[2] * in[2][2]
|
||||
#endif
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
vec3_t dir;
|
||||
|
||||
dir[0] = v[0] - in[0][3];
|
||||
@@ -51,24 +99,99 @@ void Matrix3x4_VectorITransform( const matrix3x4 in, const float v[3], float out
|
||||
out[0] = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0];
|
||||
out[1] = dir[0] * in[0][1] + dir[1] * in[1][1] + dir[2] * in[2][1];
|
||||
out[2] = dir[0] * in[0][2] + dir[1] * in[1][2] + dir[2] * in[2][2];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix3x4_VectorRotate( const matrix3x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
#if 1
|
||||
"vtfm3.t C000, M100, C130\n" // C000 = M100 * C130
|
||||
#else
|
||||
"vdot.t S000, C130, C100\n" // S000 = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2]
|
||||
"vdot.t S001, C130, C110\n" // S001 = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2]
|
||||
"vdot.t S002, C130, C120\n" // S002 = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2]
|
||||
#endif
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2];
|
||||
out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2];
|
||||
out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix3x4_VectorIRotate( const matrix3x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
#if 1
|
||||
"vtfm3.t C000, E100, C130\n" // C000 = E100 * C130
|
||||
#else
|
||||
"vdot.t S000, C130, R100\n" // S000 = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0]
|
||||
"vdot.t S001, C130, R101\n" // S001 = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1]
|
||||
"vdot.t S002, C130, R102\n" // S002 = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2]
|
||||
#endif
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0];
|
||||
out[1] = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1];
|
||||
out[2] = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix3x4_ConcatTransforms( matrix3x4 out, const matrix3x4 in1, const matrix3x4 in2 )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in1[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in1[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in1[2]
|
||||
"vzero.q C130\n" // C130 = [0, 0, 0, 0]
|
||||
"lv.q C200, 0 + %2\n" // C100 = in2[0]
|
||||
"lv.q C210, 16 + %2\n" // C110 = in2[1]
|
||||
"lv.q C220, 32 + %2\n" // C120 = in2[2]
|
||||
"vidt.q C230\n" // C230 = [0, 0, 0, 1]
|
||||
"vmmul.q E000, E100, E200\n" // E000 = E100 * E200
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in1 ), "m"( *in2 )
|
||||
);
|
||||
#else
|
||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
|
||||
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
|
||||
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
|
||||
@@ -81,6 +204,7 @@ void Matrix3x4_ConcatTransforms( matrix3x4 out, const matrix3x4 in1, const matri
|
||||
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
|
||||
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
|
||||
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out )
|
||||
@@ -105,6 +229,31 @@ void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out )
|
||||
|
||||
void Matrix3x4_FromOriginQuat( matrix3x4 out, const vec4_t quaternion, const vec3_t origin )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C130, %1\n" // C130 = quaternion
|
||||
"lv.s S300, 0 + %2\n" // S300 = origin[0]
|
||||
"lv.s S301, 4 + %2\n" // S301 = origin[1]
|
||||
"lv.s S302, 8 + %2\n" // S302 = origin[2]
|
||||
"vmov.q C100, C130[ W, Z, -Y, -X]\n" // C100 = ( w, z, -y, -x)
|
||||
"vmov.q C110, C130[-Z, W, X, -Y]\n" // C110 = (-z, w, x, -y)
|
||||
"vmov.q C120, C130[ Y, -X, W, -Z]\n" // C120 = ( y, -x, w, -z)
|
||||
"vmov.q C200, C130[ W, Z, -Y, X]\n" // C200 = ( w, z, -y, x)
|
||||
"vmov.q C210, C130[-Z, W, X, Y]\n" // C210 = (-z, w, x, y)
|
||||
"vmov.q C220, C130[ Y, -X, W, Z]\n" // C220 = ( y, -x, w, z)
|
||||
"vmov.q C230, C130[-X, -Y, -Z, W]\n" // C230 = (-x, -y, -z, w)
|
||||
"vmmul.q M000, E100, E200\n" // M000 = E100 * E200
|
||||
"vmov.t R003, C300\n" // out[x][3] = origin[x]
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *quaternion ), "m"( *origin )
|
||||
);
|
||||
#else
|
||||
out[0][0] = 1.0f - 2.0f * quaternion[1] * quaternion[1] - 2.0f * quaternion[2] * quaternion[2];
|
||||
out[1][0] = 2.0f * quaternion[0] * quaternion[1] + 2.0f * quaternion[3] * quaternion[2];
|
||||
out[2][0] = 2.0f * quaternion[0] * quaternion[2] - 2.0f * quaternion[3] * quaternion[1];
|
||||
@@ -120,10 +269,166 @@ void Matrix3x4_FromOriginQuat( matrix3x4 out, const vec4_t quaternion, const vec
|
||||
out[0][3] = origin[0];
|
||||
out[1][3] = origin[1];
|
||||
out[2][3] = origin[2];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix3x4_CreateFromEntity( matrix3x4 out, const vec3_t angles, const vec3_t origin, float scale )
|
||||
{
|
||||
#if 0/*XASH_PSP*/ /* performance not tested */ /* BUG */
|
||||
if( angles[ROLL] )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S100, 0 + %1\n" // S100 = angles[PITCH]
|
||||
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||
"lv.s S102, 8 + %1\n" // S102 = angles[ROLL]
|
||||
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %3\n" // S130 = scale
|
||||
/**/
|
||||
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||
"vscl.t C100, C100, S120\n" // C100 = C100 * S120 = angles * ( 2 / 180 )
|
||||
/**/
|
||||
"vsin.t C110, C100\n" // C110 = sin( C100 ) P Y R
|
||||
"vcos.t C120, C100\n" // C120 = cos( C100 ) P Y R
|
||||
"vneg.t C100, C110\n" // C100 = -C110 = -sin( C100 )
|
||||
/**/
|
||||
"vmul.s S000, S120, S121\n" // S000 = S120 * S121 = out[0][0] = ( cp * cy )
|
||||
"vmul.s S011, S112, S110\n" // S011 = S112 * S110 = ( sr * sp )
|
||||
"vmul.s S001, S011, S121\n" // S001 = S011 * S121 = ( sr * sp * cy )
|
||||
"vmul.s S103, S122, S101\n" // S001 = S122 * S101 = ( cr * -sy )
|
||||
"vadd.s S001, S001, S103\n" // S001 = S001 + S103 = out[0][1] = ( sr * sp * cy + cr * -sy )
|
||||
"vmul.s S012, S122, S110\n" // S002 = S122 * S110 = ( cr * sp )
|
||||
"vmul.s S002, S012, S121\n" // S002 = S012 * S121 = ( cr * sp * cy )
|
||||
"vmul.s S103, S102, S101\n" // S002 = S102 * S101 = ( -sr * -sy )
|
||||
"vadd.s S002, S002, S103\n" // S002 = S002 + S103 = out[0][2] = ( cr * sp * cy + -sr * -sy )
|
||||
/**/
|
||||
"vmul.s S010, S120, S111\n" // S010 = S120 * S111 = out[1][0] = ( cp * sy )
|
||||
"vmul.s S011, S011, S111\n" // S001 = S011 * S111 = ( sr * sp * sy )
|
||||
"vmul.s S103, S122, S121\n" // S001 = S122 * S121 = ( cr * cy )
|
||||
"vadd.s S011, S011, S103\n" // S011 = S011 + S103 = out[1][1] = ( sr * sp * sy + cr * cy )
|
||||
"vmul.s S012, S012, S111\n" // S012 = S012 * S111 = ( cr * sp * sy )
|
||||
"vmul.s S103, S102, S121\n" // S103 = S102 * S121 = ( -sr * cy )
|
||||
"vadd.s S012, S012, S103\n" // S012 = S012 + S103 = out[1][2] = ( cr * sp * sy + -sr * cy )
|
||||
/**/
|
||||
"vmov.s S020, S101\n" // S020 = S101 = out[2][0] = ( -sp )
|
||||
"vmul.s S021, S112, S120\n" // S021 = S112 * S120 = out[2][1] = ( sr * cp )
|
||||
"vmul.s S022, S122, S120\n" // S021 = S122 * S120 = out[2][2] = ( cr * cp )
|
||||
/**/
|
||||
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
else if( angles[PITCH] )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S100, 0 + %1\n" // S100 = angles[PITCH]
|
||||
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %3\n" // S130 = scale
|
||||
/**/
|
||||
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||
"vscl.p C100, C100, S120\n" // C100 = C100 * S120 = angles * ( 2 / 180 )
|
||||
/**/
|
||||
"vsin.p C110, C100\n" // C110 = sin( C100 ) P Y
|
||||
"vcos.p C120, C100\n" // C120 = cos( C100 ) P Y
|
||||
"vneg.p C100, C110\n" // C100 = -C110 = -sin( C100 )
|
||||
/**/
|
||||
"vmul.s S000, S120, S121\n" // S000 = S120 * S121 = out[0][0] = ( cp * cy )
|
||||
"vmov.s S001, S101\n" // S001 = S101 = out[0][1] = ( -sy )
|
||||
"vmul.s S002, S110, S121\n" // S001 = S110 * S121 = out[0][2] = ( sp * cy )
|
||||
/**/
|
||||
"vmul.s S010, S120, S111\n" // S010 = S120 * S111 = out[1][0] = ( cp * sy )
|
||||
"vmov.s S011, S121\n" // S011 = S121 = out[1][1] = ( cy )
|
||||
"vmul.s S012, S110, S111\n" // S012 = S110 * S111 = out[1][2] = ( sp * sy )
|
||||
/**/
|
||||
"vmov.s S020, S100\n" // S020 = S100 = out[2][0] = ( -sp )
|
||||
"vzero.s S021\n" // S021 = out[2][1] = 0.0f
|
||||
"vmov.s S022, S120\n" // S022 = S120 = out[2][2] = ( cp )
|
||||
/**/
|
||||
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
else if( angles[YAW] )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %3\n" // S130 = scale
|
||||
/**/
|
||||
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||
"vmul.s S101, S101, S120\n" // S101 = S101 * S120 = angles[YAW] * ( 2 / 180 )
|
||||
/**/
|
||||
"vsin.s S111, S101\n" // S111 = sin( S101 ) Y
|
||||
"vcos.s S121, S101\n" // S121 = cos( S101 ) Y
|
||||
/**/
|
||||
"vzero.p R002\n" // S002 = 0.0f S012 = 0.0f
|
||||
"vzero.p C020\n" // S020 = 0.0f S021 = 0.0f
|
||||
"vmov.s S000, S121\n" // S000 = S121 = out[0][0] = ( cy )
|
||||
"vneg.s S001, S111\n" // S001 = S111 = out[0][1] = ( -sy )
|
||||
"vmov.s S010, S111\n" // S010 = S111 = out[1][0] = ( sy )
|
||||
"vmov.s S011, S121\n" // S011 = S121 = out[1][1] = ( cy )
|
||||
"vone.s S022\n" // S022 = out[2][2] = 1.0f
|
||||
/**/
|
||||
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S003, 0 + %1\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %1\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %1\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %2\n" // S130 = scale
|
||||
/**/
|
||||
"vzero.t C000\n" // C000 = [0.0f, 0.0f, 0.0f]
|
||||
"vzero.t C010\n" // C010 = [0.0f, 0.0f, 0.0f]
|
||||
"vzero.t C020\n" // C020 = [0.0f, 0.0f, 0.0f]
|
||||
"vmov.s S000, S130\n" // S000 = S130 = out[0][0] = scale
|
||||
"vmov.s S011, S130\n" // S011 = S130 = out[1][1] = scale
|
||||
"vmov.s S022, S130\n" // S022 = S130 = out[2][2] = scale
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
#else
|
||||
float angle, sr, sp, sy, cr, cp, cy;
|
||||
|
||||
if( angles[ROLL] )
|
||||
@@ -201,6 +506,7 @@ void Matrix3x4_CreateFromEntity( matrix3x4 out, const vec3_t angles, const vec3_
|
||||
out[2][2] = scale;
|
||||
out[2][3] = origin[2];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -242,13 +548,61 @@ const matrix4x4 m_matrix4x4_identity =
|
||||
*/
|
||||
void Matrix4x4_VectorTransform( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
"vhdp.q S000, C130, C100\n" // S000 = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3]
|
||||
"vhdp.q S001, C130, C110\n" // S001 = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2] + in[1][3]
|
||||
"vhdp.q S002, C130, C120\n" // S002 = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2] + in[2][3]
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3];
|
||||
out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2] + in[1][3];
|
||||
out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2] + in[2][3];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix4x4_VectorITransform( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
"vsub.t C130, C130, R103\n" // C130 = v - in[][3]
|
||||
#if 1
|
||||
"vtfm3.t C000, E100, C130\n" // C000 = E100 * C130
|
||||
#else
|
||||
"vdot.t S000, C130, R100\n" // S000 = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0]
|
||||
"vdot.t S001, C130, R101\n" // S001 = dir[0] * in[0][1] + dir[1] * in[1][1] + dir[2] * in[2][1]
|
||||
"vdot.t S002, C130, R102\n" // S002 = dir[0] * in[0][2] + dir[1] * in[1][2] + dir[2] * in[2][2]
|
||||
#endif
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
vec3_t dir;
|
||||
|
||||
dir[0] = v[0] - in[0][3];
|
||||
@@ -258,24 +612,99 @@ void Matrix4x4_VectorITransform( const matrix4x4 in, const float v[3], float out
|
||||
out[0] = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0];
|
||||
out[1] = dir[0] * in[0][1] + dir[1] * in[1][1] + dir[2] * in[2][1];
|
||||
out[2] = dir[0] * in[0][2] + dir[1] * in[1][2] + dir[2] * in[2][2];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix4x4_VectorRotate( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
#if 1
|
||||
"vtfm3.t C000, M100, C130\n" // C000 = M100 * C130
|
||||
#else
|
||||
"vdot.t S000, C130, C100\n" // S000 = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2]
|
||||
"vdot.t S001, C130, C110\n" // S001 = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2]
|
||||
"vdot.t S002, C130, C120\n" // S002 = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2]
|
||||
#endif
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2];
|
||||
out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2];
|
||||
out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix4x4_VectorIRotate( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
#if 1
|
||||
"vtfm3.t C000, E100, C130\n" // C000 = E100 * C130
|
||||
#else
|
||||
"vdot.t S000, C130, R100\n" // S000 = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0]
|
||||
"vdot.t S001, C130, R101\n" // S001 = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1]
|
||||
"vdot.t S002, C130, R102\n" // S002 = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2]
|
||||
#endif
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0];
|
||||
out[1] = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1];
|
||||
out[2] = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2];
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void Matrix4x4_ConcatTransforms( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in1[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in1[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in1[2]
|
||||
"vzero.q C130\n" // C130 = [0, 0, 0, 0]
|
||||
"lv.q C200, 0 + %2\n" // C100 = in2[0]
|
||||
"lv.q C210, 16 + %2\n" // C110 = in2[1]
|
||||
"lv.q C220, 32 + %2\n" // C120 = in2[2]
|
||||
"vidt.q C230\n" // C230 = [0, 0, 0, 1]
|
||||
"vmmul.q E000, E100, E200\n" // E000 = E100 * E200
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in1 ), "m"( *in2 )
|
||||
);
|
||||
#else
|
||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
|
||||
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
|
||||
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
|
||||
@@ -288,10 +717,174 @@ void Matrix4x4_ConcatTransforms( matrix4x4 out, const matrix4x4 in1, const matri
|
||||
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
|
||||
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
|
||||
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_t origin, float scale )
|
||||
{
|
||||
#if 0/*XASH_PSP*/ /* performance not tested */ /* BUG */
|
||||
if( angles[ROLL] )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S100, 0 + %1\n" // S100 = angles[PITCH]
|
||||
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||
"lv.s S102, 8 + %1\n" // S102 = angles[ROLL]
|
||||
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %3\n" // S130 = scale
|
||||
/**/
|
||||
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||
"vscl.t C100, C100, S120\n" // C100 = C100 * S120 = angles * ( 2 / 180 )
|
||||
/**/
|
||||
"vsin.t C110, C100\n" // C110 = sin( C100 ) P Y R
|
||||
"vcos.t C120, C100\n" // C120 = cos( C100 ) P Y R
|
||||
"vneg.t C100, C110\n" // C100 = -C110 = -sin( C100 )
|
||||
/**/
|
||||
"vmul.s S000, S120, S121\n" // S000 = S120 * S121 = out[0][0] = ( cp * cy )
|
||||
"vmul.s S011, S112, S110\n" // S011 = S112 * S110 = ( sr * sp )
|
||||
"vmul.s S001, S011, S121\n" // S001 = S011 * S121 = ( sr * sp * cy )
|
||||
"vmul.s S103, S122, S101\n" // S001 = S122 * S101 = ( cr * -sy )
|
||||
"vadd.s S001, S001, S103\n" // S001 = S001 + S103 = out[0][1] = ( sr * sp * cy + cr * -sy )
|
||||
"vmul.s S012, S122, S110\n" // S002 = S122 * S110 = ( cr * sp )
|
||||
"vmul.s S002, S012, S121\n" // S002 = S012 * S121 = ( cr * sp * cy )
|
||||
"vmul.s S103, S102, S101\n" // S002 = S102 * S101 = ( -sr * -sy )
|
||||
"vadd.s S002, S002, S103\n" // S002 = S002 + S103 = out[0][2] = ( cr * sp * cy + -sr * -sy )
|
||||
/**/
|
||||
"vmul.s S010, S120, S111\n" // S010 = S120 * S111 = out[1][0] = ( cp * sy )
|
||||
"vmul.s S011, S011, S111\n" // S001 = S011 * S111 = ( sr * sp * sy )
|
||||
"vmul.s S103, S122, S121\n" // S001 = S122 * S121 = ( cr * cy )
|
||||
"vadd.s S011, S011, S103\n" // S011 = S011 + S103 = out[1][1] = ( sr * sp * sy + cr * cy )
|
||||
"vmul.s S012, S012, S111\n" // S012 = S012 * S111 = ( cr * sp * sy )
|
||||
"vmul.s S103, S102, S121\n" // S103 = S102 * S121 = ( -sr * cy )
|
||||
"vadd.s S012, S012, S103\n" // S012 = S012 + S103 = out[1][2] = ( cr * sp * sy + -sr * cy )
|
||||
/**/
|
||||
"vmov.s S020, S101\n" // S020 = S101 = out[2][0] = ( -sp )
|
||||
"vmul.s S021, S112, S120\n" // S021 = S112 * S120 = out[2][1] = ( sr * cp )
|
||||
"vmul.s S022, S122, S120\n" // S021 = S122 * S120 = out[2][2] = ( cr * cp )
|
||||
/**/
|
||||
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||
"vidt.q C030\n" // C030 = [0.0f, 0.0f, 0.0f, 1.0f]
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
else if( angles[PITCH] )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S100, 0 + %1\n" // S100 = angles[PITCH]
|
||||
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %3\n" // S130 = scale
|
||||
/**/
|
||||
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||
"vscl.p C100, C100, S120\n" // C100 = C100 * S120 = angles * ( 2 / 180 )
|
||||
/**/
|
||||
"vsin.p C110, C100\n" // C110 = sin( C100 ) P Y
|
||||
"vcos.p C120, C100\n" // C120 = cos( C100 ) P Y
|
||||
"vneg.p C100, C110\n" // C100 = -C110 = -sin( C100 )
|
||||
/**/
|
||||
"vmul.s S000, S120, S121\n" // S000 = S120 * S121 = out[0][0] = ( cp * cy )
|
||||
"vmov.s S001, S101\n" // S001 = S101 = out[0][1] = ( -sy )
|
||||
"vmul.s S002, S110, S121\n" // S001 = S110 * S121 = out[0][2] = ( sp * cy )
|
||||
/**/
|
||||
"vmul.s S010, S120, S111\n" // S010 = S120 * S111 = out[1][0] = ( cp * sy )
|
||||
"vmov.s S011, S121\n" // S011 = S121 = out[1][1] = ( cy )
|
||||
"vmul.s S012, S110, S111\n" // S012 = S110 * S111 = out[1][2] = ( sp * sy )
|
||||
/**/
|
||||
"vmov.s S020, S100\n" // S020 = S100 = out[2][0] = ( -sp )
|
||||
"vzero.s S021\n" // S021 = out[2][1] = 0.0f
|
||||
"vmov.s S022, S120\n" // S022 = S120 = out[2][2] = ( cp )
|
||||
/**/
|
||||
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||
"vidt.q C030\n" // C030 = [0.0f, 0.0f, 0.0f, 1.0f]
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
else if( angles[YAW] )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %3\n" // S130 = scale
|
||||
/**/
|
||||
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||
"vmul.s S101, S101, S120\n" // S101 = S101 * S120 = angles[YAW] * ( 2 / 180 )
|
||||
/**/
|
||||
"vsin.s S111, S101\n" // S111 = sin( S101 ) Y
|
||||
"vcos.s S121, S101\n" // S121 = cos( S101 ) Y
|
||||
/**/
|
||||
"vzero.p R002\n" // S002 = 0.0f S012 = 0.0f
|
||||
"vzero.p C020\n" // S020 = 0.0f S021 = 0.0f
|
||||
"vmov.s S000, S121\n" // S000 = S121 = out[0][0] = ( cy )
|
||||
"vneg.s S001, S111\n" // S001 = S111 = out[0][1] = ( -sy )
|
||||
"vmov.s S010, S111\n" // S010 = S111 = out[1][0] = ( sy )
|
||||
"vmov.s S011, S121\n" // S011 = S121 = out[1][1] = ( cy )
|
||||
"vone.s S022\n" // S022 = out[2][2] = 1.0f
|
||||
/**/
|
||||
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||
"vidt.q C030\n" // C030 = [0.0f, 0.0f, 0.0f, 1.0f]
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S003, 0 + %1\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %1\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %1\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %2\n" // S130 = scale
|
||||
/**/
|
||||
"vzero.t C000\n" // C000 = [0.0f, 0.0f, 0.0f]
|
||||
"vzero.t C010\n" // C010 = [0.0f, 0.0f, 0.0f]
|
||||
"vzero.t C020\n" // C020 = [0.0f, 0.0f, 0.0f]
|
||||
"vidt.q C030\n" // C030 = [0.0f, 0.0f, 0.0f, 1.0f]
|
||||
"vmov.s S000, S130\n" // S000 = S130 = out[0][0] = scale
|
||||
"vmov.s S011, S130\n" // S011 = S130 = out[1][1] = scale
|
||||
"vmov.s S022, S130\n" // S022 = S130 = out[2][2] = scale
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
#else
|
||||
float angle, sr, sp, sy, cr, cp, cy;
|
||||
|
||||
if( angles[ROLL] )
|
||||
@@ -385,6 +978,7 @@ void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_
|
||||
out[3][2] = 0.0f;
|
||||
out[3][3] = 1.0f;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix4x4_ConvertToEntity( const matrix4x4 in, vec3_t angles, vec3_t origin )
|
||||
@@ -412,6 +1006,36 @@ void Matrix4x4_ConvertToEntity( const matrix4x4 in, vec3_t angles, vec3_t origin
|
||||
|
||||
void Matrix4x4_TransformPositivePlane( const matrix4x4 in, const vec3_t normal, float d, vec3_t out, float *dist )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"mfc1 $8, %4\n" // FPU->CPU
|
||||
"mtv $8, S210\n" // CPU->VFPU S210 = d
|
||||
"lv.q C100, 0 + %2\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %2\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %2\n" // C120 = in[2]
|
||||
"lv.s S200, 0 + %3\n" // S200 = normal[0]
|
||||
"lv.s S201, 4 + %3\n" // S201 = normal[1]
|
||||
"lv.s S202, 8 + %3\n" // S202 = normal[2]
|
||||
"vdot.t S211, C100, C100\n" // S211 = C100 * C100
|
||||
"vsqrt.s S211, S211\n" // S211 = sqrt( S211 )
|
||||
"vrcp.s S212, S211\n" // S212 = 1 / S211
|
||||
"vtfm3.t C000, M100, C200\n" // C000 = M100 * C200
|
||||
"vscl.t C000, C000, S212\n" // C000 = C000 * S211
|
||||
"vmul.s S003, S210, S211\n" // S003 = S210 * S211
|
||||
"vdot.t S010, R103, C000\n" // S010 = R103 * C000
|
||||
"vadd.s S003, S003, S010\n" // S003 = S003 + S010
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
"sv.s S003, %1\n" // dist = S003
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out ), "=m"( *dist )
|
||||
: "m"( *in ), "m"( *normal ), "f"( d )
|
||||
: "$8"
|
||||
);
|
||||
#else
|
||||
float scale = sqrt( in[0][0] * in[0][0] + in[0][1] * in[0][1] + in[0][2] * in[0][2] );
|
||||
float iscale = 1.0f / scale;
|
||||
|
||||
@@ -419,6 +1043,7 @@ void Matrix4x4_TransformPositivePlane( const matrix4x4 in, const vec3_t normal,
|
||||
out[1] = (normal[0] * in[1][0] + normal[1] * in[1][1] + normal[2] * in[1][2]) * iscale;
|
||||
out[2] = (normal[0] * in[2][0] + normal[1] * in[2][1] + normal[2] * in[2][2]) * iscale;
|
||||
*dist = d * scale + ( out[0] * in[0][3] + out[1] * in[1][3] + out[2] * in[2][3] );
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix4x4_Invert_Simple( matrix4x4 out, const matrix4x4 in1 )
|
||||
|
||||
0
public/rbtree.h
Normal file
0
public/rbtree.h
Normal file
@@ -16,7 +16,7 @@ def configure(conf):
|
||||
|
||||
def build(bld):
|
||||
bld(name = 'sdk_includes', export_includes = '. ../common ../pm_shared ../engine')
|
||||
bld.stlib(source = bld.path.ant_glob('*.c'),
|
||||
bld.stlib(source = bld.path.ant_glob('*.c') + bld.path.ant_glob('*.S'),
|
||||
target = 'public',
|
||||
features = 'c',
|
||||
use = 'sdk_includes',
|
||||
|
||||
@@ -209,6 +209,30 @@ rsqrt
|
||||
*/
|
||||
float rsqrt( float number )
|
||||
{
|
||||
#if XASH_PSP
|
||||
#if 0 /* experimental */
|
||||
if( number == 0.0f ) return 0.0f;
|
||||
return ( 1.0 / __builtin_allegrex_sqrt_s( number ));
|
||||
#else
|
||||
float result;
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"mfc1 $8, %1\n" // FPU->CPU
|
||||
"mtv $8, S000\n" // CPU->VFPU S000 = number
|
||||
"vzero.s S001\n" // S100 = 0
|
||||
"vcmp.s EZ, S000\n" // CC[0] = ( S000 == 0.0f )
|
||||
"vrsq.s S000, S000\n" // S000 = 1.0 / sqrt( S000 )
|
||||
"vcmovt.s S000, S001, 0\n" // if ( CC[0] ) S000 = S001
|
||||
"sv.s S000, %0\n" // result = S000
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( result )
|
||||
: "f"( number )
|
||||
: "$8"
|
||||
);
|
||||
return result;
|
||||
#endif
|
||||
#else
|
||||
int i;
|
||||
float x, y;
|
||||
|
||||
@@ -222,6 +246,7 @@ float rsqrt( float number )
|
||||
y = y * (1.5f - (x * y * y)); // first iteration
|
||||
|
||||
return y;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -384,6 +409,7 @@ void VectorsAngles( const vec3_t forward, const vec3_t right, const vec3_t up, v
|
||||
//
|
||||
// bounds operations
|
||||
//
|
||||
|
||||
/*
|
||||
=================
|
||||
AddPointToBounds
|
||||
@@ -485,6 +511,46 @@ AngleQuaternion
|
||||
*/
|
||||
void AngleQuaternion( const vec3_t angles, vec4_t q, qboolean studio )
|
||||
{
|
||||
#if XASH_PSP
|
||||
vec4_t dst_angles;
|
||||
if( studio )
|
||||
{
|
||||
dst_angles[0] = angles[PITCH];
|
||||
dst_angles[1] = angles[YAW];
|
||||
dst_angles[2] = angles[ROLL];
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_angles[0] = DEG2RAD( angles[ROLL] );
|
||||
dst_angles[1] = DEG2RAD( angles[PITCH] );
|
||||
dst_angles[2] = DEG2RAD( angles[YAW] );
|
||||
}
|
||||
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C000, %1\n" // C000 = [PITCH, YAW, ROLL]
|
||||
"vcst.s S010, VFPU_1_PI\n" // S010 = VFPU_1_PI = 1 / PI
|
||||
"vscl.t C000, C000, S010\n" // C000 = C000 * S010 = C000 * 0.5f * ( 2 / PI )
|
||||
"vcos.t C010, C000\n" // C010 = cos( C000 * 0.5f )
|
||||
"vsin.t C000, C000\n" // C000 = sin( C000 * 0.5f )
|
||||
"vcrs.t C020, C010, C010\n" // C020 = ( cp*cy, cy*cr, cr*cp )
|
||||
"vcrs.t C030, C000, C000\n" // C030 = ( sp*sy, sy*sr, sr*sp )
|
||||
"vmul.s S003, S020, S010\n" // S003 = S020 * S010 = cp*cy*cr
|
||||
"vmul.s S013, S030, S000\n" // S013 = S030 * S000 = sp*sy*sr
|
||||
"vmul.t C020, C020, C000\n" // C020 = C020 * C000 = ( cp*cy*sr, cy*cr*sp, cr*cp*sy )
|
||||
"vmul.t C030, C030, C010\n" // C030 = C030 * C010 = ( sp*sy*cr, sy*sr*cp, sr*sp*cy )
|
||||
"vadd.s S003, S003, S013\n" // S003 = S003 + S013 = cp*cy*cr + cp*cy*cr
|
||||
"vadd.t C000, C020, C030[-X, Y, -Z]\n"
|
||||
// S000 = S020 - C030 = cp*cy*sr - sp*sy*cr
|
||||
// S001 = S021 + C031 = cy*cr*sp + sy*sr*cp
|
||||
// S002 = S022 - C032 = cr*cp*sy - sr*sp*cy
|
||||
"sv.q C000, %0\n" // *q = C000
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *q )
|
||||
: "m"( dst_angles )
|
||||
);
|
||||
#else
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
if( studio )
|
||||
@@ -504,6 +570,7 @@ void AngleQuaternion( const vec3_t angles, vec4_t q, qboolean studio )
|
||||
q[1] = cr * sp * cy + sr * cp * sy; // Y
|
||||
q[2] = cr * cp * sy - sr * sp * cy; // Z
|
||||
q[3] = cr * cp * cy + sr * sp * sy; // W
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -527,6 +594,7 @@ make sure quaternions are within 180 degrees of one another,
|
||||
if not, reverse q
|
||||
====================
|
||||
*/
|
||||
#if !XASH_PSP
|
||||
void QuaternionAlign( const vec4_t p, const vec4_t q, vec4_t qt )
|
||||
{
|
||||
// decide if one of the quaternions is backwards
|
||||
@@ -615,9 +683,9 @@ void QuaternionSlerp( const vec4_t p, const vec4_t q, float t, vec4_t qt )
|
||||
// 0.0 returns p, 1.0 return q.
|
||||
// decide if one of the quaternions is backwards
|
||||
QuaternionAlign( p, q, q2 );
|
||||
|
||||
QuaternionSlerpNoAlign( p, q2, t, qt );
|
||||
}
|
||||
#endif // XASH_PSP
|
||||
|
||||
/*
|
||||
==================
|
||||
@@ -626,10 +694,11 @@ BoxOnPlaneSide
|
||||
Returns 1, 2, or 1 + 2
|
||||
==================
|
||||
*/
|
||||
#if !XASH_PSP
|
||||
int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p )
|
||||
{
|
||||
float dist1, dist2;
|
||||
int sides = 0;
|
||||
float dist1, dist2;
|
||||
|
||||
// general case
|
||||
switch( p->signbits )
|
||||
@@ -679,6 +748,7 @@ int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p )
|
||||
|
||||
return sides;
|
||||
}
|
||||
#endif // !XASH_PSP
|
||||
|
||||
/*
|
||||
====================
|
||||
|
||||
@@ -175,8 +175,26 @@ static inline float UintAsFloat( uint32_t u )
|
||||
|
||||
static inline void SinCos( float radians, float *sine, float *cosine )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"mfc1 $8, %2\n" // FPU->CPU
|
||||
"mtv $8, S000\n" // CPU->VFPU S000 = radians
|
||||
"vcst.s S001, VFPU_2_PI\n" // S001 = VFPU_2_PI = 2 / PI
|
||||
"vmul.s S000, S000, S001\n" // S000 = S000 * S001
|
||||
"vrot.p C002, S000, [s, c]\n" // S002 = sin( radians ), S003 = cos( radians )
|
||||
"sv.s S002, %0\n" // sine = S002
|
||||
"sv.s S003, %1\n" // cosine = S003
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *sine), "=m"( *cosine )
|
||||
: "f"( radians )
|
||||
: "$8"
|
||||
);
|
||||
#else
|
||||
*sine = sin(radians);
|
||||
*cosine = cos(radians);
|
||||
#endif
|
||||
}
|
||||
|
||||
float rsqrt( float number );
|
||||
|
||||
218
public/xash3d_mathlib_asm.S
Normal file
218
public/xash3d_mathlib_asm.S
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
xash3d_mathlib_asm.S - internal mathlib ASM ver.
|
||||
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.
|
||||
*/
|
||||
#include "build.h"
|
||||
#if XASH_PSP
|
||||
#include "as_reg_compat.h"
|
||||
.set noreorder
|
||||
.set noat
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.global QuaternionSlerp
|
||||
.global BoxOnPlaneSide
|
||||
|
||||
// void QuaternionSlerp( const vec4_t p, const vec4_t q, float t, vec4_t qt );
|
||||
.ent QuaternionSlerp
|
||||
QuaternionSlerp:
|
||||
############################
|
||||
# a0 - IN *p #
|
||||
# a1 - IN *q #
|
||||
# f12 - IN t #
|
||||
# a2 - IN *qt #
|
||||
############################
|
||||
mfc1 $t0, $f12
|
||||
mtv $t0, S031 // S031 = sclq = t
|
||||
li $t0, 0x358637bd // t0 = EPSILON = 0.000001f
|
||||
mtv $t0, S033 // S002 = t0 = EPSILON
|
||||
lv.q C010, 0($a0) // C010 = p
|
||||
lv.q C020, 0($a1) // C020 = q
|
||||
|
||||
// QuaternionAlign
|
||||
vsub.q C100, C010, C020 // C100 = p[*] - q[*]
|
||||
vadd.q C110, C010, C020 // C110 = p[*] + q[*]
|
||||
vdot.q S000, C100, C100 // S000 = a += (p[*] - q[*]) * (p[*] - q[*])
|
||||
vdot.q S001, C110, C110 // S001 = b += (p[*] + q[*]) * (p[*] + q[*])
|
||||
vcmp.s GT, S000, S001 // CC[0] = a > b
|
||||
vcmovt.q C020, C020[-X,-Y,-Z,-W], 0 // if CC[0] q = -q
|
||||
// ***
|
||||
|
||||
// QuaternionSlerpNoAlign
|
||||
vdot.q S000, C010, C020 // S000 = cosom += p[*] * q[*]
|
||||
vadd.s S001, S000[1], S000 // S002 = 1.0f + cosom
|
||||
vcmp.s LE, S001, S033 // CC[0] = ( 1.0f + cosom ) <= 0.000001f
|
||||
bvt 0, Lqs2 // if CC[0] goto Lqs2
|
||||
vocp.s S030, S031 // S030 = sclp = 1.0f - t (delay slot)
|
||||
vsub.s S001, S000[1], S000 // S002 = 1.0f - cosom
|
||||
vcmp.s LE, S001, S033 // CC[0] = ( 1.0f - cosom ) <= 0.000001f
|
||||
bvt 0, Lqs1
|
||||
nop
|
||||
|
||||
// acos
|
||||
vcst.s S001, VFPU_SQRT1_2 // S001 = VFPU_SQRT1_2 = 1 / sqrt(2)
|
||||
vcmp.s LT, S000[|x|], S001 // CC[0] = abs(cosom) < (1 / sqrt(2))
|
||||
vasin.s S032, S000[|x|] // S032 = asin(abs(cosom))
|
||||
bvtl 0, Lqs0 // if CC[0] goto Lqs0
|
||||
vocp.s S032, S032 // S032 = 1 - S032 = acos(abs(cosom)) = omega (bvtl delay slot)
|
||||
vmul.s S001, S000, S000 // S001 = cosom * cosom
|
||||
vocp.s S001[0:1], S001 // S001 = 1 - S001[0:1]
|
||||
vsqrt.s S001, S001 // S001 = sqrt(S001)
|
||||
vasin.s S032, S001 // S032 = asin(S001) = acos(abs(cosom)) = omega
|
||||
// ***
|
||||
Lqs0:
|
||||
vscl.p C030, C030, S032 // S030 = S030 * S032 = sclp * omega
|
||||
// S031 = S031 * S032 = sclq * omega
|
||||
vsin.t C030, C030 // S030 = sin(S030) = sin(sclp * omega) = sclp
|
||||
// S031 = sin(S031) = sin(sclq * omega) = sclq
|
||||
// S032 = sin(S032) = sin(omega)
|
||||
vrcp.s S032, S032 // S032 = 1.0f / S032 = 1 / sin(omega) = sinom
|
||||
vscl.p C030, C030, S032 // S030 = S030 * S032 = sin(sclp * omega) / sinom
|
||||
// S031 = S031 * S032 = sin(sclq * omega) / sinom
|
||||
Lqs1:
|
||||
vscl.q C010, C010, S030 // C010 = p[*4] * sclp
|
||||
vscl.q C020, C020, S031 // C020 = qt[*4] * sclq
|
||||
b LqsEnd // goto LqsEnd
|
||||
vadd.q C000, C010, C020 // S000 = qt[0] = sclp * p[0] + sclq * qt[0] (delay slot)
|
||||
// S001 = qt[1] = sclp * p[1] + sclq * qt[1]
|
||||
// S002 = qt[2] = sclp * p[2] + sclq * qt[2]
|
||||
// S003 = qt[3] = sclp * p[3] + sclq * qt[3]
|
||||
Lqs2:
|
||||
vmov.q C000, C020[-Y,X,-W,Z] // S000 = qt[0] = -q[1];
|
||||
// S001 = qt[1] = q[0];
|
||||
// S002 = qt[2] = -q[3];
|
||||
// S003 = qt[3] = q[2];
|
||||
vsin.p C030, C030 // S030 = sclp = sin(( 1.0f - t ) * ( 0.5f * M_PI_F ))
|
||||
// S031 = sclq = sin( t * ( 0.5f * M_PI_F ))
|
||||
vscl.t C010, C010, S030 // C000 = p[*3] * sclp
|
||||
vscl.t C020, C000, S031 // C030 = qt[*3] * sclq
|
||||
vadd.t C000, C010, C020 // S000 = qt[0] = sclp * p[0] + sclq * qt[0]
|
||||
// S001 = qt[1] = sclp * p[1] + sclq * qt[1]
|
||||
// S002 = qt[2] = sclp * p[2] + sclq * qt[2]
|
||||
// S003 = qt[3]
|
||||
LqsEnd:
|
||||
sv.q C000, 0($a2)
|
||||
jr $ra
|
||||
.end QuaternionSlerp
|
||||
|
||||
|
||||
|
||||
|
||||
// int BoxOnPlaneSide( vec3_t emins, vec3_t emaxs, mplane_t *p );
|
||||
.ent BoxOnPlaneSide
|
||||
BoxOnPlaneSide:
|
||||
############################
|
||||
# a0 - IN *emins #
|
||||
# a1 - IN *emaxs #
|
||||
# a2 - IN *p #
|
||||
# v0 - OUT sides #
|
||||
############################
|
||||
lbu $v0, 17($a2) // p->signbits
|
||||
sltiu $v1, $v0, 8 // if(signbits > 8)
|
||||
beq $v1, $zero, LSetSides // jump to LSetSides
|
||||
vzero.p C030 // set zero vector
|
||||
sll $v1, $v0, 2
|
||||
la $v0, Ljmptab
|
||||
addu $v0, $v0, $v1
|
||||
lw $v0, 0($v0)
|
||||
lv.s S000, 0($a2) // p->normal[0]
|
||||
lv.s S001, 4($a2) // p->normal[1]
|
||||
jr $v0
|
||||
lv.s S002, 8($a2) // p->normal[2]
|
||||
Lcase0:
|
||||
lv.s S010, 0($a1) // emaxs[0]
|
||||
lv.s S011, 4($a1) // emaxs[1]
|
||||
lv.s S012, 8($a1) // emaxs[2]
|
||||
lv.s S020, 0($a0) // emins[0]
|
||||
lv.s S021, 4($a0) // emins[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a0) // emins[2]
|
||||
Lcase1:
|
||||
lv.s S010, 0($a0) // emins[0]
|
||||
lv.s S011, 4($a1) // emaxs[1]
|
||||
lv.s S012, 8($a1) // emaxs[2]
|
||||
lv.s S020, 0($a1) // emaxs[0]
|
||||
lv.s S021, 4($a0) // emins[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a0) // emins[2]
|
||||
Lcase2:
|
||||
lv.s S010, 0($a1) // emaxs[0]
|
||||
lv.s S011, 4($a0) // emins[1]
|
||||
lv.s S012, 8($a1) // emaxs[2]
|
||||
lv.s S020, 0($a0) // emins[0]
|
||||
lv.s S021, 4($a1) // emaxs[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a0) // emins[2]
|
||||
Lcase3:
|
||||
lv.s S010, 0($a0) // emins[0]
|
||||
lv.s S011, 4($a0) // emins[1]
|
||||
lv.s S012, 8($a1) // emaxs[2]
|
||||
lv.s S020, 0($a1) // emaxs[0]
|
||||
lv.s S021, 4($a1) // emaxs[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a0) // emins[2]
|
||||
Lcase4:
|
||||
lv.s S010, 0($a1) // emaxs[0]
|
||||
lv.s S011, 4($a1) // emaxs[1]
|
||||
lv.s S012, 8($a0) // emins[2]
|
||||
lv.s S020, 0($a0) // emins[0]
|
||||
lv.s S021, 4($a0) // emins[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a1) // emaxs[2]
|
||||
Lcase5:
|
||||
lv.s S010, 0($a0) // emins[0]
|
||||
lv.s S011, 4($a1) // emaxs[1]
|
||||
lv.s S012, 8($a0) // emins[2]
|
||||
lv.s S020, 0($a1) // emaxs[0]
|
||||
lv.s S021, 4($a0) // emins[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a1) // emaxs[2]
|
||||
Lcase6:
|
||||
lv.s S010, 0($a1) // emaxs[0]
|
||||
lv.s S011, 4($a0) // emins[1]
|
||||
lv.s S012, 8($a0) // emins[2]
|
||||
lv.s S020, 0($a0) // emins[0]
|
||||
lv.s S021, 4($a1) // emaxs[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a1) // emaxs[2]
|
||||
Lcase7:
|
||||
lv.s S010, 0($a0) // emins[0]
|
||||
lv.s S011, 4($a0) // emins[1]
|
||||
lv.s S012, 8($a0) // emins[2]
|
||||
lv.s S020, 0($a1) // emaxs[0]
|
||||
lv.s S021, 4($a1) // emaxs[1]
|
||||
lv.s S022, 8($a1) // emaxs[2]
|
||||
LDotProduct:
|
||||
vdot.t S030, C000, C010 // S030 = C000 * C010
|
||||
vdot.t S031, C000, C020 // S031 = C000 * C020
|
||||
LSetSides:
|
||||
lv.s S013, 12($a2) // p->dist
|
||||
vcmp.s LT, S030, S013 // S030 < S013
|
||||
bvt 0, LDist2 // if ( CC[0] == 1 ) jump to LDist2
|
||||
li $v0, 0 // sides = 0
|
||||
li $v0, 1 // sides = 1
|
||||
LDist2:
|
||||
vcmp.s GE, S031, S013 // S031 >= S013
|
||||
bvt 0, LEnd // if ( CC[0] == 1 ) jump to LEnd
|
||||
nop
|
||||
ori $v0, $v0, 2
|
||||
LEnd:
|
||||
jr $ra
|
||||
nop
|
||||
.end BoxOnPlaneSide
|
||||
|
||||
.section .rodata
|
||||
.align 4
|
||||
Ljmptab:
|
||||
.word Lcase0, Lcase1, Lcase2, Lcase3, Lcase4, Lcase5, Lcase6, Lcase7
|
||||
#endif // XASH_PSP
|
||||
@@ -142,7 +142,6 @@ void _TriColor4ub( byte r, byte g, byte b, byte a )
|
||||
pglColor4ub( r, g, b, a );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
TriColor4ub
|
||||
@@ -365,4 +364,3 @@ void TriBrightness( float brightness )
|
||||
|
||||
_TriColor4f( r, g, b, 1.0f );
|
||||
}
|
||||
|
||||
|
||||
1
ref/soft/exports.txt
Normal file
1
ref/soft/exports.txt
Normal file
@@ -0,0 +1 @@
|
||||
GetRefAPI
|
||||
@@ -201,6 +201,19 @@ void R_SetupDecalTextureSpaceBasis( decal_t *pDecal, msurface_t *surf, int textu
|
||||
// Build the initial list of vertices from the surface verts into the global array, 'verts'.
|
||||
void R_SetupDecalVertsForMSurface( decal_t *pDecal, msurface_t *surf, vec3_t textureSpaceBasis[3], float *verts )
|
||||
{
|
||||
#if XASH_PSP
|
||||
int i;
|
||||
|
||||
if( !surf->polys )
|
||||
return;
|
||||
for( i = 0; i < surf->polys->numverts; i++, verts += VERTEXSIZE )
|
||||
{
|
||||
VectorCopy( surf->polys->verts[i].xyz, verts ); // copy model space coordinates
|
||||
verts[3] = DotProduct( verts, textureSpaceBasis[0] ) - pDecal->dx + 0.5f;
|
||||
verts[4] = DotProduct( verts, textureSpaceBasis[1] ) - pDecal->dy + 0.5f;
|
||||
verts[5] = verts[6] = 0.0f;
|
||||
}
|
||||
#else
|
||||
float *v;
|
||||
int i;
|
||||
|
||||
@@ -213,6 +226,7 @@ void R_SetupDecalVertsForMSurface( decal_t *pDecal, msurface_t *surf, vec3_t tex
|
||||
verts[4] = DotProduct( verts, textureSpaceBasis[1] ) - pDecal->dy + 0.5f;
|
||||
verts[5] = verts[6] = 0.0f;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Figure out where the decal maps onto the surface.
|
||||
@@ -524,7 +538,26 @@ glpoly_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t
|
||||
|
||||
v = R_DecalSetupVerts( pdecal, surf, pdecal->texture, &lnumverts );
|
||||
if( !lnumverts ) return NULL; // probably this never happens
|
||||
#if XASH_PSP
|
||||
// allocate glpoly
|
||||
// REFTODO: com_studiocache pool!
|
||||
poly = Mem_Calloc( r_temppool, sizeof( glpoly_t ) + ( lnumverts * 2 - 1 ) * sizeof( gu_vert_t ));
|
||||
poly->next = pdecal->polys;
|
||||
poly->flags = surf->flags;
|
||||
pdecal->polys = poly;
|
||||
poly->numverts = lnumverts;
|
||||
|
||||
for( i = 0; i < lnumverts; i++, v += VERTEXSIZE )
|
||||
{
|
||||
poly->verts[i].uv[0] = v[3];
|
||||
poly->verts[i].uv[1] = v[4];
|
||||
VectorCopy( v, poly->verts[i].xyz );
|
||||
|
||||
poly->verts[i + lnumverts].uv[0] = v[5];
|
||||
poly->verts[i + lnumverts].uv[1] = v[6];
|
||||
VectorCopy( v, poly->verts[i + lnumverts].xyz );
|
||||
}
|
||||
#else
|
||||
// allocate glpoly
|
||||
// REFTODO: com_studiocache pool!
|
||||
poly = Mem_Calloc( r_temppool, sizeof( glpoly_t ) + ( lnumverts - 4 ) * VERTEXSIZE * sizeof( float ));
|
||||
@@ -541,7 +574,7 @@ glpoly_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t
|
||||
poly->verts[i][5] = v[5];
|
||||
poly->verts[i][6] = v[6];
|
||||
}
|
||||
|
||||
#endif
|
||||
return poly;
|
||||
}
|
||||
|
||||
@@ -861,8 +894,18 @@ float * GAME_EXPORT R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int te
|
||||
{
|
||||
v = g_DecalClipVerts[0];
|
||||
count = p->numverts;
|
||||
#if XASH_PSP
|
||||
// if we have mesh so skip clipping and just copy vertexes out (perf)
|
||||
for( i = 0; i < count; i++, v += VERTEXSIZE )
|
||||
{
|
||||
VectorCopy( p->verts[i].xyz, v );
|
||||
v[3] = p->verts[i].uv[0];
|
||||
v[4] = p->verts[i].uv[1];
|
||||
v[5] = p->verts[i + count].uv[0];
|
||||
v[6] = p->verts[i + count].uv[1];
|
||||
}
|
||||
#else
|
||||
v2 = p->verts[0];
|
||||
|
||||
// if we have mesh so skip clipping and just copy vertexes out (perf)
|
||||
for( i = 0; i < count; i++, v += VERTEXSIZE, v2 += VERTEXSIZE )
|
||||
{
|
||||
@@ -872,7 +915,7 @@ float * GAME_EXPORT R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int te
|
||||
v[5] = v2[5];
|
||||
v[6] = v2[6];
|
||||
}
|
||||
|
||||
#endif
|
||||
// restore pointer
|
||||
v = g_DecalClipVerts[0];
|
||||
}
|
||||
|
||||
@@ -492,4 +492,3 @@ void TriBrightness( float brightness )
|
||||
|
||||
_TriColor4f( r, g, b, 1.0f );
|
||||
}
|
||||
|
||||
|
||||
2
ref_gu/exports.txt
Normal file
2
ref_gu/exports.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
GetRefAPI
|
||||
GetRefHumanReadableName
|
||||
1551
ref_gu/gu_alias.c
Normal file
1551
ref_gu/gu_alias.c
Normal file
File diff suppressed because it is too large
Load Diff
683
ref_gu/gu_backend.c
Normal file
683
ref_gu/gu_backend.c
Normal file
@@ -0,0 +1,683 @@
|
||||
/*
|
||||
gl_backend.c - rendering backend
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
|
||||
#include "gu_local.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
char r_speeds_msg[MAX_SYSPATH];
|
||||
ref_speeds_t r_stats; // r_speeds counters
|
||||
|
||||
/*
|
||||
===============
|
||||
R_SpeedsMessage
|
||||
===============
|
||||
*/
|
||||
qboolean R_SpeedsMessage( char *out, size_t size )
|
||||
{
|
||||
if( gEngfuncs.drawFuncs->R_SpeedsMessage != NULL )
|
||||
{
|
||||
if( gEngfuncs.drawFuncs->R_SpeedsMessage( out, size ))
|
||||
return true;
|
||||
// otherwise pass to default handler
|
||||
}
|
||||
|
||||
if( r_speeds->value <= 0 ) return false;
|
||||
if( !out || !size ) return false;
|
||||
|
||||
Q_strncpy( out, r_speeds_msg, size );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
R_Speeds_Printf
|
||||
|
||||
helper to print into r_speeds message
|
||||
==============
|
||||
*/
|
||||
void R_Speeds_Printf( const char *msg, ... )
|
||||
{
|
||||
va_list argptr;
|
||||
char text[2048];
|
||||
|
||||
va_start( argptr, msg );
|
||||
Q_vsprintf( text, msg, argptr );
|
||||
va_end( argptr );
|
||||
|
||||
Q_strncat( r_speeds_msg, text, sizeof( r_speeds_msg ));
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
GL_BackendStartFrame
|
||||
==============
|
||||
*/
|
||||
void GL_BackendStartFrame( void )
|
||||
{
|
||||
r_speeds_msg[0] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
GL_BackendEndFrame
|
||||
==============
|
||||
*/
|
||||
void GL_BackendEndFrame( void )
|
||||
{
|
||||
mleaf_t *curleaf;
|
||||
|
||||
if( r_speeds->value <= 0 || !RI.drawWorld )
|
||||
return;
|
||||
|
||||
if( !RI.viewleaf )
|
||||
curleaf = WORLDMODEL->leafs;
|
||||
else curleaf = RI.viewleaf;
|
||||
|
||||
R_Speeds_Printf( "Renderer: ^1Engine^7\n\n" );
|
||||
|
||||
switch( (int)r_speeds->value )
|
||||
{
|
||||
case 1:
|
||||
Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i wpoly, %3i apoly\n%3i epoly, %3i spoly",
|
||||
r_stats.c_world_polys, r_stats.c_alias_polys, r_stats.c_studio_polys, r_stats.c_sprite_polys );
|
||||
break;
|
||||
case 2:
|
||||
R_Speeds_Printf( "visible leafs:\n%3i leafs\ncurrent leaf %3i\n", r_stats.c_world_leafs, curleaf - WORLDMODEL->leafs );
|
||||
R_Speeds_Printf( "ReciusiveWorldNode: %3lf secs\nDrawTextureChains %lf\n", r_stats.t_world_node, r_stats.t_world_draw );
|
||||
break;
|
||||
case 3:
|
||||
Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i alias models drawn\n%3i studio models drawn\n%3i sprites drawn",
|
||||
r_stats.c_alias_models_drawn, r_stats.c_studio_models_drawn, r_stats.c_sprite_models_drawn );
|
||||
break;
|
||||
case 4:
|
||||
Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i static entities\n%3i normal entities\n%3i server entities",
|
||||
r_numStatics, r_numEntities - r_numStatics, ENGINE_GET_PARM( PARM_NUMENTITIES ));
|
||||
break;
|
||||
case 5:
|
||||
Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i tempents\n%3i viewbeams\n%3i particles",
|
||||
r_stats.c_active_tents_count, r_stats.c_view_beams_count, r_stats.c_particle_count );
|
||||
break;
|
||||
}
|
||||
|
||||
memset( &r_stats, 0, sizeof( r_stats ));
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_LoadTexMatrix
|
||||
=================
|
||||
*/
|
||||
void GL_LoadTexMatrix( const matrix4x4 m )
|
||||
{
|
||||
sceGumMatrixMode( GU_TEXTURE );
|
||||
GL_LoadMatrix( m );
|
||||
sceGumUpdateMatrix();
|
||||
|
||||
glState.texIdentityMatrix = false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_LoadTexMatrixExt
|
||||
=================
|
||||
*/
|
||||
void GL_LoadTexMatrixExt( const float *glmatrix )
|
||||
{
|
||||
Assert( glmatrix != NULL );
|
||||
|
||||
sceGumMatrixMode( GU_TEXTURE );
|
||||
sceGumLoadMatrix( ( const ScePspFMatrix4 * ) glmatrix );
|
||||
sceGumUpdateMatrix();
|
||||
|
||||
glState.texIdentityMatrix = false;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_LoadMatrix
|
||||
=================
|
||||
*/
|
||||
void GL_LoadMatrix( const matrix4x4 source )
|
||||
{
|
||||
ScePspFMatrix4 dest;
|
||||
|
||||
Matrix4x4_ToFMatrix4( source, &dest );
|
||||
sceGumLoadMatrix( &dest );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_LoadIdentityTexMatrix
|
||||
=================
|
||||
*/
|
||||
void GL_LoadIdentityTexMatrix( void )
|
||||
{
|
||||
if( glState.texIdentityMatrix )
|
||||
return;
|
||||
|
||||
sceGumMatrixMode( GU_TEXTURE );
|
||||
sceGumLoadIdentity();
|
||||
sceGumUpdateMatrix();
|
||||
|
||||
glState.texIdentityMatrix = true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_SelectTexture
|
||||
=================
|
||||
*/
|
||||
void GL_SelectTexture( GLint tmu )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
GL_DisableAllTexGens
|
||||
==============
|
||||
*/
|
||||
void GL_DisableAllTexGens( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
GL_CleanUpTextureUnits
|
||||
==============
|
||||
*/
|
||||
void GL_CleanUpTextureUnits( int last )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
GL_CleanupAllTextureUnits
|
||||
==============
|
||||
*/
|
||||
void GL_CleanupAllTextureUnits( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_MultiTexCoord2f
|
||||
=================
|
||||
*/
|
||||
void GL_MultiTexCoord2f( GLenum texture, GLfloat s, GLfloat t )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_TextureTarget
|
||||
=================
|
||||
*/
|
||||
void GL_TextureTarget( uint target )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_TexGen
|
||||
=================
|
||||
*/
|
||||
void GL_TexGen( GLenum coord, GLenum mode )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_SetTexCoordArrayMode
|
||||
=================
|
||||
*/
|
||||
void GL_SetTexCoordArrayMode( GLenum mode )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_Cull
|
||||
=================
|
||||
*/
|
||||
void GL_Cull( GLenum cull )
|
||||
{
|
||||
if( glState.faceCull == cull )
|
||||
return;
|
||||
|
||||
if( !cull )
|
||||
{
|
||||
sceGuDisable( GU_CULL_FACE );
|
||||
glState.faceCull = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
sceGuEnable( GU_CULL_FACE );
|
||||
sceGuFrontFace( cull - 1 );
|
||||
glState.faceCull = cull;
|
||||
}
|
||||
|
||||
void GL_SetRenderMode( int mode )
|
||||
{
|
||||
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
||||
|
||||
switch( mode )
|
||||
{
|
||||
case kRenderNormal:
|
||||
default:
|
||||
sceGuDisable( GU_BLEND );
|
||||
sceGuDisable( GU_ALPHA_TEST );
|
||||
break;
|
||||
case kRenderTransColor:
|
||||
case kRenderTransTexture:
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuDisable( GU_ALPHA_TEST );
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
||||
break;
|
||||
case kRenderTransAlpha:
|
||||
sceGuDisable( GU_BLEND );
|
||||
sceGuEnable( GU_ALPHA_TEST );
|
||||
break;
|
||||
case kRenderGlow:
|
||||
case kRenderTransAdd:
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuDisable( GU_ALPHA_TEST );
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, GUBLEND1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_SetColor4ub
|
||||
=================
|
||||
*/
|
||||
void GL_SetColor4ub( byte r, byte g, byte b, byte a )
|
||||
{
|
||||
sceGuColor( GU_RGBA( r, g, b, a ));
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
SCREEN SHOTS
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
// used for 'env' and 'sky' shots
|
||||
typedef struct envmap_s
|
||||
{
|
||||
vec3_t angles;
|
||||
int flags;
|
||||
} envmap_t;
|
||||
|
||||
const envmap_t r_skyBoxInfo[6] =
|
||||
{
|
||||
{{ 0, 270, 180}, IMAGE_FLIP_X },
|
||||
{{ 0, 90, 180}, IMAGE_FLIP_X },
|
||||
{{ -90, 0, 180}, IMAGE_FLIP_X },
|
||||
{{ 90, 0, 180}, IMAGE_FLIP_X },
|
||||
{{ 0, 0, 180}, IMAGE_FLIP_X },
|
||||
{{ 0, 180, 180}, IMAGE_FLIP_X },
|
||||
};
|
||||
|
||||
const envmap_t r_envMapInfo[6] =
|
||||
{
|
||||
{{ 0, 0, 90}, 0 },
|
||||
{{ 0, 180, -90}, 0 },
|
||||
{{ 0, 90, 0}, 0 },
|
||||
{{ 0, 270, 180}, 0 },
|
||||
{{-90, 180, -90}, 0 },
|
||||
{{ 90, 0, 90}, 0 }
|
||||
};
|
||||
|
||||
|
||||
|
||||
qboolean VID_ScreenShot( const char *filename, int shot_type )
|
||||
{
|
||||
rgbdata_t *r_shot;
|
||||
uint flags = 0;
|
||||
int width = 0, height = 0;
|
||||
qboolean result;
|
||||
int bpp;
|
||||
|
||||
r_shot = Mem_Calloc( r_temppool, sizeof( rgbdata_t ));
|
||||
r_shot->width = (gpGlobals->width + 3) & ~3;
|
||||
r_shot->height = (gpGlobals->height + 3) & ~3;
|
||||
r_shot->flags = IMAGE_HAS_COLOR;
|
||||
r_shot->type = PF_RGB_24;
|
||||
bpp = gEngfuncs.Image_GetPFDesc( r_shot->type )->bpp;
|
||||
r_shot->size = r_shot->width * r_shot->height * bpp;
|
||||
r_shot->palette = NULL;
|
||||
r_shot->buffer = Mem_Malloc( r_temppool, r_shot->size );
|
||||
|
||||
// get screen frame
|
||||
byte *src = ( byte* )guRender.disp_buffer;
|
||||
byte *dst = r_shot->buffer;
|
||||
int cheight = r_shot->height;
|
||||
|
||||
// stride copy
|
||||
while( cheight-- )
|
||||
{
|
||||
GL_PixelConverter( dst, src, r_shot->width, PC_HWF( guRender.buffer_format ), PC_SWF( r_shot->type ) );
|
||||
dst += r_shot->width * bpp;
|
||||
src += guRender.buffer_width * guRender.buffer_bpp;
|
||||
}
|
||||
|
||||
switch( shot_type )
|
||||
{
|
||||
case VID_SCREENSHOT:
|
||||
break;
|
||||
case VID_SNAPSHOT:
|
||||
gEngfuncs.FS_AllowDirectPaths( true );
|
||||
break;
|
||||
case VID_LEVELSHOT:
|
||||
flags |= IMAGE_RESAMPLE;
|
||||
if( gpGlobals->wideScreen )
|
||||
{
|
||||
height = 480;
|
||||
width = 800;
|
||||
}
|
||||
else
|
||||
{
|
||||
height = 480;
|
||||
width = 640;
|
||||
}
|
||||
break;
|
||||
case VID_MINISHOT:
|
||||
flags |= IMAGE_RESAMPLE;
|
||||
height = 200;
|
||||
width = 320;
|
||||
break;
|
||||
case VID_MAPSHOT:
|
||||
flags |= IMAGE_RESAMPLE|IMAGE_QUANTIZE; // GoldSrc request overviews in 8-bit format
|
||||
height = 768;
|
||||
width = 1024;
|
||||
break;
|
||||
}
|
||||
|
||||
gEngfuncs.Image_Process( &r_shot, width, height, flags, 0.0f );
|
||||
|
||||
// write image
|
||||
result = gEngfuncs.FS_SaveImage( filename, r_shot );
|
||||
gEngfuncs.FS_AllowDirectPaths( false ); // always reset after store screenshot
|
||||
gEngfuncs.FS_FreeImage( r_shot );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
VID_CubemapShot
|
||||
=================
|
||||
*/
|
||||
qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot )
|
||||
{
|
||||
#if 0
|
||||
rgbdata_t *r_shot, *r_side;
|
||||
byte *temp = NULL;
|
||||
byte *buffer = NULL;
|
||||
string basename;
|
||||
int i = 1, flags, result;
|
||||
|
||||
if( !RI.drawWorld || !WORLDMODEL )
|
||||
return false;
|
||||
|
||||
// make sure the specified size is valid
|
||||
while( i < size ) i<<=1;
|
||||
|
||||
if( i != size ) return false;
|
||||
if( size > gpGlobals->width || size > gpGlobals->height )
|
||||
return false;
|
||||
|
||||
// alloc space
|
||||
temp = Mem_Malloc( r_temppool, size * size * 3 );
|
||||
buffer = Mem_Malloc( r_temppool, size * size * 3 * 6 );
|
||||
r_shot = Mem_Calloc( r_temppool, sizeof( rgbdata_t ));
|
||||
r_side = Mem_Calloc( r_temppool, sizeof( rgbdata_t ));
|
||||
|
||||
// use client vieworg
|
||||
if( !vieworg ) vieworg = RI.vieworg;
|
||||
|
||||
R_CheckGamma();
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
// go into 3d mode
|
||||
R_Set2DMode( false );
|
||||
|
||||
if( skyshot )
|
||||
{
|
||||
R_DrawCubemapView( vieworg, r_skyBoxInfo[i].angles, size );
|
||||
flags = r_skyBoxInfo[i].flags;
|
||||
}
|
||||
else
|
||||
{
|
||||
R_DrawCubemapView( vieworg, r_envMapInfo[i].angles, size );
|
||||
flags = r_envMapInfo[i].flags;
|
||||
}
|
||||
|
||||
pglReadPixels( 0, 0, size, size, GL_RGB, GL_UNSIGNED_BYTE, temp );
|
||||
r_side->flags = IMAGE_HAS_COLOR;
|
||||
r_side->width = r_side->height = size;
|
||||
r_side->type = PF_RGB_24;
|
||||
r_side->size = r_side->width * r_side->height * 3;
|
||||
r_side->buffer = temp;
|
||||
|
||||
if( flags ) gEngfuncs.Image_Process( &r_side, 0, 0, flags, 0.0f );
|
||||
memcpy( buffer + (size * size * 3 * i), r_side->buffer, size * size * 3 );
|
||||
}
|
||||
|
||||
r_shot->flags = IMAGE_HAS_COLOR;
|
||||
r_shot->flags |= (skyshot) ? IMAGE_SKYBOX : IMAGE_CUBEMAP;
|
||||
r_shot->width = size;
|
||||
r_shot->height = size;
|
||||
r_shot->type = PF_RGB_24;
|
||||
r_shot->size = r_shot->width * r_shot->height * 3 * 6;
|
||||
r_shot->palette = NULL;
|
||||
r_shot->buffer = buffer;
|
||||
|
||||
// make sure what we have right extension
|
||||
Q_strncpy( basename, base, MAX_STRING );
|
||||
COM_StripExtension( basename );
|
||||
COM_DefaultExtension( basename, ".tga" );
|
||||
|
||||
// write image as 6 sides
|
||||
result = gEngfuncs.FS_SaveImage( basename, r_shot );
|
||||
gEngfuncs.FS_FreeImage( r_shot );
|
||||
gEngfuncs.FS_FreeImage( r_side );
|
||||
|
||||
return result;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
//=======================================================
|
||||
|
||||
/*
|
||||
===============
|
||||
R_ShowTextures
|
||||
|
||||
Draw all the images to the screen, on top of whatever
|
||||
was there. This is used to test for texture thrashing.
|
||||
===============
|
||||
*/
|
||||
void R_ShowTextures( void )
|
||||
{
|
||||
#if 0
|
||||
gl_texture_t *image;
|
||||
float x, y, w, h;
|
||||
int total, start, end;
|
||||
int i, j, k, base_w, base_h;
|
||||
rgba_t color = { 192, 192, 192, 255 };
|
||||
int charHeight, numTries = 0;
|
||||
static qboolean showHelp = true;
|
||||
string shortname;
|
||||
|
||||
if( !CVAR_TO_BOOL( gl_showtextures ))
|
||||
return;
|
||||
|
||||
if( showHelp )
|
||||
{
|
||||
gEngfuncs.CL_CenterPrint( "use '<-' and '->' keys to change atlas page, ESC to quit", 0.25f );
|
||||
showHelp = false;
|
||||
}
|
||||
|
||||
GL_SetRenderMode( kRenderNormal );
|
||||
pglClear( GL_COLOR_BUFFER_BIT );
|
||||
pglFinish();
|
||||
|
||||
base_w = 8; // textures view by horizontal
|
||||
base_h = 6; // textures view by vertical
|
||||
|
||||
rebuild_page:
|
||||
total = base_w * base_h;
|
||||
start = total * (gl_showtextures->value - 1);
|
||||
end = total * gl_showtextures->value;
|
||||
if( end > MAX_TEXTURES ) end = MAX_TEXTURES;
|
||||
|
||||
w = gpGlobals->width / base_w;
|
||||
h = gpGlobals->height / base_h;
|
||||
|
||||
gEngfuncs.Con_DrawStringLen( NULL, NULL, &charHeight );
|
||||
|
||||
for( i = j = 0; i < MAX_TEXTURES; i++ )
|
||||
{
|
||||
image = R_GetTexture( i );
|
||||
if( j == start ) break; // found start
|
||||
if( pglIsTexture( image->texnum )) j++;
|
||||
}
|
||||
|
||||
if( i == MAX_TEXTURES && gl_showtextures->value != 1 )
|
||||
{
|
||||
// bad case, rewind to one and try again
|
||||
gEngfuncs.Cvar_SetValue( "r_showtextures", max( 1, gl_showtextures->value - 1 ));
|
||||
if( ++numTries < 2 ) goto rebuild_page; // to prevent infinite loop
|
||||
}
|
||||
|
||||
for( k = 0; i < MAX_TEXTURES; i++ )
|
||||
{
|
||||
if( j == end ) break; // page is full
|
||||
|
||||
image = R_GetTexture( i );
|
||||
if( !pglIsTexture( image->texnum ))
|
||||
continue;
|
||||
|
||||
x = k % base_w * w;
|
||||
y = k / base_w * h;
|
||||
|
||||
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
GL_Bind( XASH_TEXTURE0, i ); // NOTE: don't use image->texnum here, because skybox has a 'wrong' indexes
|
||||
|
||||
if( FBitSet( image->flags, TF_DEPTHMAP ) && !FBitSet( image->flags, TF_NOCOMPARE ))
|
||||
pglTexParameteri( image->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
pglTexCoord2f( 0, 0 );
|
||||
pglVertex2f( x, y );
|
||||
if( image->target == GL_TEXTURE_RECTANGLE_EXT )
|
||||
pglTexCoord2f( image->width, 0 );
|
||||
else pglTexCoord2f( 1, 0 );
|
||||
pglVertex2f( x + w, y );
|
||||
if( image->target == GL_TEXTURE_RECTANGLE_EXT )
|
||||
pglTexCoord2f( image->width, image->height );
|
||||
else pglTexCoord2f( 1, 1 );
|
||||
pglVertex2f( x + w, y + h );
|
||||
if( image->target == GL_TEXTURE_RECTANGLE_EXT )
|
||||
pglTexCoord2f( 0, image->height );
|
||||
else pglTexCoord2f( 0, 1 );
|
||||
pglVertex2f( x, y + h );
|
||||
pglEnd();
|
||||
|
||||
if( FBitSet( image->flags, TF_DEPTHMAP ) && !FBitSet( image->flags, TF_NOCOMPARE ))
|
||||
pglTexParameteri( image->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB );
|
||||
|
||||
COM_FileBase( image->name, shortname );
|
||||
if( Q_strlen( shortname ) > 18 )
|
||||
{
|
||||
// cutoff too long names, it looks ugly
|
||||
shortname[16] = '.';
|
||||
shortname[17] = '.';
|
||||
shortname[18] = '\0';
|
||||
}
|
||||
gEngfuncs.Con_DrawString( x + 1, y + h - charHeight, shortname, color );
|
||||
j++, k++;
|
||||
}
|
||||
|
||||
gEngfuncs.CL_DrawCenterPrint ();
|
||||
pglFinish();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SCR_TimeRefresh_f
|
||||
|
||||
timerefresh [noflip]
|
||||
================
|
||||
*/
|
||||
void SCR_TimeRefresh_f( void )
|
||||
{
|
||||
int i;
|
||||
double start, stop;
|
||||
double time;
|
||||
|
||||
if( ENGINE_GET_PARM( PARM_CONNSTATE ) != ca_active )
|
||||
return;
|
||||
|
||||
start = gEngfuncs.pfnTime();
|
||||
|
||||
// run without page flipping like GoldSrc
|
||||
if( gEngfuncs.Cmd_Argc() == 1 )
|
||||
{
|
||||
#if 0
|
||||
pglDrawBuffer( GL_FRONT );
|
||||
#endif
|
||||
for( i = 0; i < 128; i++ )
|
||||
{
|
||||
gpGlobals->viewangles[1] = i / 128.0f * 360.0f;
|
||||
R_RenderScene();
|
||||
}
|
||||
#if 0
|
||||
pglFinish();
|
||||
#endif
|
||||
R_EndFrame();
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < 128; i++ )
|
||||
{
|
||||
R_BeginFrame( true );
|
||||
gpGlobals->viewangles[1] = i / 128.0f * 360.0f;
|
||||
R_RenderScene();
|
||||
R_EndFrame();
|
||||
}
|
||||
}
|
||||
|
||||
stop = gEngfuncs.pfnTime ();
|
||||
time = (stop - start);
|
||||
gEngfuncs.Con_Printf( "%f seconds (%f fps)\n", time, 128 / time );
|
||||
}
|
||||
1410
ref_gu/gu_beams.c
Normal file
1410
ref_gu/gu_beams.c
Normal file
File diff suppressed because it is too large
Load Diff
337
ref_gu/gu_clipping.c
Normal file
337
ref_gu/gu_clipping.c
Normal file
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
gu_clipping.c - software clipping implimentation
|
||||
Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Based on clipping system from PSP Quake by Peter Mackay and Chris Swindle.
|
||||
|
||||
*/
|
||||
/*
|
||||
VFPU REGS:
|
||||
|
||||
M700 - current frustum
|
||||
M600 - world frustum
|
||||
C010 - current plane ( GU_Clip2Plane )
|
||||
*/
|
||||
|
||||
#include "gu_local.h"
|
||||
|
||||
#define MAX_CLIPPED_VERTICES 32
|
||||
|
||||
// Cache
|
||||
static ScePspFMatrix4 projection_view_matrix;
|
||||
|
||||
// The temporary working buffers.
|
||||
static gu_vert_t work_buffer[2][MAX_CLIPPED_VERTICES] __attribute__(( aligned( 16 )));
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_ClipGetFrustum
|
||||
=================
|
||||
*/
|
||||
_inline void GU_ClipGetAndStoreFrustum( const ScePspFMatrix4 *matrix )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"vzero.q C210\n" // set zero vector
|
||||
"lv.q C100, 0(%0)\n" // C000 = matrix->x
|
||||
"lv.q C110, 16(%0)\n" // C010 = matrix->y
|
||||
"lv.q C120, 32(%0)\n" // C020 = matrix->z
|
||||
"lv.q C130, 48(%0)\n" // C030 = matrix->w
|
||||
"vadd.q C000, R103, R101\n" // C000 = R103 + R101 ( BOTTOM )
|
||||
"vadd.q C010, R103, R100\n" // C010 = R103 + R100 ( LEFT )
|
||||
"vsub.q C020, R103, R100\n" // C020 = R103 - R100 ( RIGHT )
|
||||
"vsub.q C030, R103, R101\n" // C030 = R103 - R101 ( TOP )
|
||||
"vdot.q S200, C000, C000\n" // S110 = S100*S100 + S101*S101 + S102*S102 + S103*S103 ( BOTTOM )
|
||||
"vdot.q S201, C010, C010\n" // S110 = S100*S100 + S101*S101 + S102*S102 + S103*S103 ( LEFT )
|
||||
"vdot.q S202, C020, C020\n" // S110 = S100*S100 + S101*S101 + S102*S102 + S103*S103 ( RIGHT )
|
||||
"vdot.q S203, C030, C030\n" // S110 = S100*S100 + S101*S101 + S102*S102 + S103*S103 ( TOP )
|
||||
"vcmp.q EZ, C200\n" // CC[*] = ( C200 == 0.0f )
|
||||
"vrsq.q C200, C200\n" // C200 = 1.0 / sqrt( C200 )
|
||||
"vcmovt.q C200, C210, 6\n" // if ( CC[*] ) C200 = C210
|
||||
"vscl.q C700, C000, S200\n" // C700 = C000 * S200 ( BOTTOM )
|
||||
"vscl.q C710, C010, S201\n" // C710 = C010 * S201 ( LEFT )
|
||||
"vscl.q C720, C020, S202\n" // C720 = C020 * S202 ( RIGHT )
|
||||
"vscl.q C730, C030, S203\n" // C730 = C030 * S203 ( TOP )
|
||||
".set pop\n" // Restore assembler option
|
||||
:: "r"( matrix )
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_ClipBeginFrame
|
||||
|
||||
Calculate the clipping frustum for static objects
|
||||
=================
|
||||
*/
|
||||
void GU_ClipSetWorldFrustum( const matrix4x4 in )
|
||||
{
|
||||
// Get matrix.
|
||||
Matrix4x4_ToFMatrix4( in, &projection_view_matrix );
|
||||
|
||||
// Calculate and cache the clipping frustum.
|
||||
GU_ClipGetAndStoreFrustum( &projection_view_matrix );
|
||||
|
||||
// Save the clipping frustum.
|
||||
__asm__ volatile(
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"vmmov.q M600, M700\n" // Save frustum
|
||||
".set pop\n" // Restore assembler option
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_ClipRestoreWorldFrustum
|
||||
|
||||
Restore the clipping frustum
|
||||
=================
|
||||
*/
|
||||
void GU_ClipRestoreWorldFrustum( void )
|
||||
{
|
||||
// Restore the clipping frustum.
|
||||
__asm__ volatile(
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"vmmov.q M700, M600\n" // Restore frustum
|
||||
".set pop\n" // Restore assembler option
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_ClipSetModelFrustum
|
||||
|
||||
Calculate the clipping frustum for dynamic objects
|
||||
=================
|
||||
*/
|
||||
void GU_ClipSetModelFrustum( const matrix4x4 in )
|
||||
{
|
||||
ScePspFMatrix4 model_matrix;
|
||||
ScePspFMatrix4 projection_view_model_matrix;
|
||||
|
||||
// Get matrix.
|
||||
Matrix4x4_ToFMatrix4( in, &model_matrix );
|
||||
|
||||
// Combine the matrices (multiply projection-view by model).
|
||||
gumMultMatrix( &projection_view_model_matrix, &projection_view_matrix, &model_matrix );
|
||||
|
||||
// Calculate and cache the clipping frustum.
|
||||
GU_ClipGetAndStoreFrustum( &projection_view_model_matrix );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_ClipLoadFrustum
|
||||
|
||||
Load the clipping frustum ( native )
|
||||
=================
|
||||
*/
|
||||
#if 0
|
||||
void GU_ClipLoadFrustum( const mplane_t *plane )
|
||||
{
|
||||
__asm__ volatile(
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"ulv.q C700, %0\n" // Load plane into register
|
||||
"ulv.q C710, %1\n" // Load plane into register
|
||||
"ulv.q C720, %2\n" // Load plane into register
|
||||
"ulv.q C730, %3\n" // Load plane into register
|
||||
"vneg.q R703, R703\n" // R703 = -R703 = -dist
|
||||
".set pop\n" // Restore assembler option
|
||||
:: "m"( plane[FRUSTUM_BOTTOM] ),
|
||||
"m"( plane[FRUSTUM_LEFT] ),
|
||||
"m"( plane[FRUSTUM_RIGHT] ),
|
||||
"m"( plane[FRUSTUM_TOP] )
|
||||
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_ClipIsRequired
|
||||
|
||||
Is clipping required?
|
||||
=================
|
||||
*/
|
||||
int GU_ClipIsRequired( gu_vert_t* uv, int uvc )
|
||||
{
|
||||
int result = 1;
|
||||
gu_vert_t *uv_end = uv + ( uvc - 1 );
|
||||
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"vzero.q C000\n" // C000 = [0.0f, 0.0f, 0.0f. 0.0f]
|
||||
"0:\n" // loop
|
||||
"lv.s S010, 8(%1)\n" // S010 = v[i].xyz[0]
|
||||
"lv.s S011, 12(%1)\n" // S011 = v[i].xyz[1]
|
||||
"lv.s S012, 16(%1)\n" // S012 = v[i].xyz[2]
|
||||
"vhtfm4.q C020, M700, C010\n" // C020 = frustrum * v[i].xyz
|
||||
"vcmp.q LT, C020, C000\n" // S020 < 0.0f || S021 < 0.0f || S022 < 0.0f || S023 < 0.0f
|
||||
"bvt 4, 1f\n" // if ( CC[4] == 1 ) jump to exit
|
||||
"nop\n" // ( delay slot )
|
||||
"bne %1, %2, 0b\n" // if ( $10 != $8 ) jump to loop
|
||||
"addiu %1, %1, %3\n" // $8 = $8 + sizeof( gu_vert_t ) ( delay slot )
|
||||
"move %0, $0\n" // res = 0
|
||||
"1:\n" // exit
|
||||
".set pop\n" // Restore assembler option
|
||||
: "=r"( result ), "+r"( uv )
|
||||
: "r"( uv_end ),
|
||||
"n"(sizeof( gu_vert_t ))
|
||||
: "$8"
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_Clip2Plane
|
||||
|
||||
Clips a polygon against a plane.
|
||||
=================
|
||||
*/
|
||||
_inline void GU_Clip2Plane( gu_vert_t *uv, int uvc, gu_vert_t *cv, int *cvc )
|
||||
{
|
||||
gu_vert_t *uv_end = uv + ( uvc - 1 );
|
||||
gu_vert_t *cv_start = cv;
|
||||
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"vzero.q C000\n" // set zero vector
|
||||
"lv.s S200, 8(%2)\n" // Load vertex P XYZ(4b) X into register
|
||||
"lv.s S201, 12(%2)\n" // Load vertex P XYZ(4b) Y into register
|
||||
"lv.s S202, 16(%2)\n" // Load vertex P XYZ(4b) Z into register
|
||||
"lv.s S210, 0(%2)\n" // Load vertex P TEX(4b) U into register
|
||||
"lv.s S211, 4(%2)\n" // Load vertex P TEX(4b) V into register
|
||||
"vhdp.q S212, C200, C010\n" // distance P -> dP
|
||||
"0:\n"
|
||||
"lv.s S220, 8(%1)\n" // Load vertex S XYZ(4b) X into register
|
||||
"lv.s S221, 12(%1)\n" // Load vertex S XYZ(4b) Y into register
|
||||
"lv.s S222, 16(%1)\n" // Load vertex S XYZ(4b) Z into register
|
||||
"lv.s S230, 0(%1)\n" // Load vertex S TEX(4b) U into register
|
||||
"lv.s S231, 4(%1)\n" // Load vertex S TEX(4b) V into register
|
||||
"vhdp.q S232, C220, C010\n" // distance S -> dS
|
||||
"vcmp.s GT, S212, S000\n" // if (dP <= 0)
|
||||
"bvf 0, 1f\n" // goto 1:
|
||||
"nop\n"
|
||||
"sv.s S210, 0(%0)\n" // cv->uv[0] = C020 U
|
||||
"sv.s S211, 4(%0)\n" // cv->uv[1] = C021 V
|
||||
"sv.s S200, 8(%0)\n" // cv->xyz[0] = C030 X
|
||||
"sv.s S201, 12(%0)\n" // cv->xyz[1] = C031 Y
|
||||
"sv.s S202, 16(%0)\n" // cv->xyz[2] = C032 Z
|
||||
"addiu %0, %0, %3\n" // cv + sizeof(gu_vert_t)
|
||||
"1:\n"
|
||||
"vmul.s S020, S232, S212\n" // (dS * dP)
|
||||
"vcmp.s LT, S020, S000\n" // if (dS * dP < 0)
|
||||
"bvf 0, 2f\n" // goto 2:
|
||||
"vsub.s S021, S232, S212\n" // (dS - dP)
|
||||
"vrcp.s S021, S021\n"
|
||||
"vmul.s S021, S021, S232\n" // R = dS / ( dS - dP )
|
||||
#if 0
|
||||
"vsub.t C200, C220, C200\n" // (S - P) XYZ
|
||||
"vsub.p C210, C230, C210\n" // (S - P) UV
|
||||
"vscl.t C200, C200, S021\n" // ((S - P) * R) XYZ
|
||||
"vscl.p C210, C210, S021\n" // ((S - P) * R) UV
|
||||
"vsub.t C200, C220, C200\n" // (S - (S - P) * R) XYZ
|
||||
"vsub.p C210, C230, C210\n" // (S - (S - P) * R) UV
|
||||
#else
|
||||
"vsub.t C200, C200, C220\n" // (P - S) XYZ
|
||||
"vsub.p C210, C210, C230\n" // (P - S) UV
|
||||
"vscl.t C200, C200, S021\n" // ((P - S) * R) XYZ
|
||||
"vscl.p C210, C210, S021\n" // ((P - S) * R) UV
|
||||
"vadd.t C200, C220, C200\n" // (S + (P - S) * R) XYZ
|
||||
"vadd.p C210, C230, C210\n" // (S + (P - S) * R) UV
|
||||
#endif
|
||||
"sv.s S210, 0(%0)\n" // cv->uv[0] = S210 U
|
||||
"sv.s S211, 4(%0)\n" // cv->uv[1] = S211 V
|
||||
"sv.s S200, 8(%0)\n" // cv->xyz[0] = S200 X
|
||||
"sv.s S201, 12(%0)\n" // cv->xyz[1] = S201 Y
|
||||
"sv.s S202, 16(%0)\n" // cv->xyz[2] = S202 Z
|
||||
"addiu %0, %0, %3\n" // cv + sizeof(gu_vert_t)
|
||||
"2:\n"
|
||||
"vmov.t C200, C220\n" // P = S XYZ
|
||||
"vmov.t C210, C230\n" // P = S UV and dS
|
||||
"bne %1, %2, 0b\n" // if (uv != uv_end) goto 0:
|
||||
"addiu %1, %1, %3\n" // uv + sizeof(gu_vert_t) ( delay slot )
|
||||
".set pop\n" // suppress reordering
|
||||
: "+r"( cv ), "+r"( uv )
|
||||
: "r"( uv_end ),
|
||||
"n"( sizeof( gu_vert_t ))
|
||||
: "memory"
|
||||
) ;
|
||||
*cvc = ( cv - cv_start );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_Clip
|
||||
|
||||
Clips a polygon against the frustum
|
||||
=================
|
||||
*/
|
||||
void GU_Clip( gu_vert_t *uv, int uvc, gu_vert_t **cv, int* cvc )
|
||||
{
|
||||
size_t vc;
|
||||
|
||||
if ( !uvc ) // no vertices to clip?
|
||||
gEngfuncs.Host_Error( "GU_Clip: calling clip with zero vertices!" );
|
||||
|
||||
vc = uvc;
|
||||
*cvc = 0;
|
||||
|
||||
__asm__ volatile(
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"vmov.q C010, C700\n" // CPLANE_BOTTOM
|
||||
".set pop\n" // suppress reordering
|
||||
);
|
||||
GU_Clip2Plane( uv, vc, work_buffer[0], &vc );
|
||||
if ( !vc ) return;
|
||||
|
||||
__asm__ volatile(
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"vmov.q C010, C710\n" // CPLANE_LEFT
|
||||
".set pop\n" // suppress reordering
|
||||
);
|
||||
GU_Clip2Plane( work_buffer[0], vc, work_buffer[1], &vc );
|
||||
if ( !vc ) return;
|
||||
|
||||
__asm__ volatile(
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"vmov.q C010, C720\n" // CPLANE_RIGHT
|
||||
".set pop\n" // suppress reordering
|
||||
);
|
||||
GU_Clip2Plane( work_buffer[1], vc, work_buffer[0], &vc );
|
||||
if ( !vc ) return;
|
||||
|
||||
__asm__ volatile(
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"vmov.q C010, C730\n" // CPLANE_TOP
|
||||
".set pop\n" // suppress reordering
|
||||
);
|
||||
*cv = extGuBeginPacket( NULL ); // uncached
|
||||
GU_Clip2Plane( work_buffer[0], vc, *cv, cvc );
|
||||
if (!( *cvc )) return;
|
||||
extGuEndPacket(( void * )( *cv + *cvc ));
|
||||
}
|
||||
503
ref_gu/gu_context.c
Normal file
503
ref_gu/gu_context.c
Normal file
@@ -0,0 +1,503 @@
|
||||
/*
|
||||
vid_sdl.c - SDL vid component
|
||||
Copyright (C) 2018 a1batross
|
||||
Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
// GL API function pointers, if any, reside in this translation unit
|
||||
#define APIENTRY_LINKAGE
|
||||
#include "gu_local.h"
|
||||
|
||||
ref_api_t gEngfuncs;
|
||||
ref_globals_t *gpGlobals;
|
||||
|
||||
static void R_ClearScreen( void )
|
||||
{
|
||||
sceGuClearColor( 0x00000000 );
|
||||
sceGuClear( GU_COLOR_BUFFER_BIT );
|
||||
}
|
||||
|
||||
static const byte *R_GetTextureOriginalBuffer( unsigned int idx )
|
||||
{
|
||||
gl_texture_t *glt = R_GetTexture( idx );
|
||||
|
||||
if( !glt || !glt->original || !glt->original->buffer )
|
||||
return NULL;
|
||||
|
||||
return glt->original->buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
CL_FillRGBA
|
||||
|
||||
=============
|
||||
*/
|
||||
static void CL_FillRGBA( float _x, float _y, float _w, float _h, int r, int g, int b, int a )
|
||||
{
|
||||
sceGuDisable( GU_TEXTURE_2D );
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, GUBLEND1 );
|
||||
sceGuColor( GUCOLOR4UB( r, g, b, a ) );
|
||||
|
||||
gu_vert_hv_t* const out = ( gu_vert_hv_t* )sceGuGetMemory( sizeof( gu_vert_hv_t ) * 2 );
|
||||
out[0].x = _x;
|
||||
out[0].y = _y;
|
||||
out[0].z = 0;
|
||||
out[1].x = _x + _w;
|
||||
out[1].y = _y + _h;
|
||||
out[1].z = 0;
|
||||
sceGuDrawArray( GU_SPRITES, GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, out );
|
||||
|
||||
sceGuColor( 0xffffffff );
|
||||
sceGuEnable( GU_TEXTURE_2D );
|
||||
sceGuDisable( GU_BLEND );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
pfnFillRGBABlend
|
||||
|
||||
=============
|
||||
*/
|
||||
static void GAME_EXPORT CL_FillRGBABlend( float _x, float _y, float _w, float _h, int r, int g, int b, int a )
|
||||
{
|
||||
sceGuDisable( GU_TEXTURE_2D );
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_DST_ALPHA, 0, 0 );
|
||||
sceGuColor( GUCOLOR4UB( r, g, b, a ) );
|
||||
|
||||
gu_vert_hv_t* const out = ( gu_vert_hv_t* )sceGuGetMemory( sizeof( gu_vert_hv_t ) * 2 );
|
||||
out[0].x = _x;
|
||||
out[0].y = _y;
|
||||
out[0].z = 0;
|
||||
out[1].x = _x + _w;
|
||||
out[1].y = _y + _h;
|
||||
out[1].z = 0;
|
||||
sceGuDrawArray( GU_SPRITES, GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, out );
|
||||
|
||||
sceGuColor( 0xffffffff );
|
||||
sceGuEnable( GU_TEXTURE_2D );
|
||||
sceGuDisable( GU_BLEND );
|
||||
}
|
||||
|
||||
void Mod_BrushUnloadTextures( model_t *mod )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < mod->numtextures; i++ )
|
||||
{
|
||||
texture_t *tx = mod->textures[i];
|
||||
if( !tx || tx->gl_texturenum == tr.defaultTexture )
|
||||
continue; // free slot
|
||||
|
||||
GL_FreeTexture( tx->gl_texturenum ); // main texture
|
||||
GL_FreeTexture( tx->fb_texturenum ); // luma texture
|
||||
}
|
||||
}
|
||||
|
||||
void Mod_UnloadTextures( model_t *mod )
|
||||
{
|
||||
Assert( mod != NULL );
|
||||
|
||||
switch( mod->type )
|
||||
{
|
||||
case mod_studio:
|
||||
Mod_StudioUnloadTextures( mod->cache.data );
|
||||
break;
|
||||
case mod_alias:
|
||||
Mod_AliasUnloadTextures( mod->cache.data );
|
||||
break;
|
||||
case mod_brush:
|
||||
Mod_BrushUnloadTextures( mod );
|
||||
break;
|
||||
case mod_sprite:
|
||||
Mod_SpriteUnloadTextures( mod->cache.data );
|
||||
break;
|
||||
default:
|
||||
ASSERT( 0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf )
|
||||
{
|
||||
qboolean loaded = true;
|
||||
|
||||
if( create )
|
||||
{
|
||||
switch( mod->type )
|
||||
{
|
||||
case mod_studio:
|
||||
// Mod_LoadStudioModel( mod, buf, loaded );
|
||||
break;
|
||||
case mod_sprite:
|
||||
Mod_LoadSpriteModel( mod, buf, &loaded, mod->numtexinfo );
|
||||
break;
|
||||
case mod_alias:
|
||||
Mod_LoadAliasModel( mod, buf, &loaded );
|
||||
break;
|
||||
case mod_brush:
|
||||
// Mod_LoadBrushModel( mod, buf, loaded );
|
||||
break;
|
||||
default: gEngfuncs.Host_Error( "Mod_LoadModel: unsupported type %d\n", mod->type );
|
||||
}
|
||||
}
|
||||
|
||||
if( loaded && gEngfuncs.drawFuncs->Mod_ProcessUserData )
|
||||
gEngfuncs.drawFuncs->Mod_ProcessUserData( mod, create, buf );
|
||||
|
||||
if( !create )
|
||||
Mod_UnloadTextures( mod );
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
static int GL_RefGetParm( int parm, int arg )
|
||||
{
|
||||
gl_texture_t *glt;
|
||||
|
||||
switch( parm )
|
||||
{
|
||||
case PARM_TEX_WIDTH:
|
||||
glt = R_GetTexture( arg );
|
||||
return glt->width;
|
||||
case PARM_TEX_HEIGHT:
|
||||
glt = R_GetTexture( arg );
|
||||
return glt->height;
|
||||
case PARM_TEX_SRC_WIDTH:
|
||||
glt = R_GetTexture( arg );
|
||||
return glt->srcWidth;
|
||||
case PARM_TEX_SRC_HEIGHT:
|
||||
glt = R_GetTexture( arg );
|
||||
return glt->srcHeight;
|
||||
case PARM_TEX_GLFORMAT:
|
||||
glt = R_GetTexture( arg );
|
||||
return glt->format;
|
||||
case PARM_TEX_ENCODE:
|
||||
/*glt = R_GetTexture( arg );*/
|
||||
return /*glt->encode*/0;
|
||||
case PARM_TEX_MIPCOUNT:
|
||||
glt = R_GetTexture( arg );
|
||||
return glt->numMips;
|
||||
case PARM_TEX_DEPTH:
|
||||
/*glt = R_GetTexture( arg );*/
|
||||
return /*glt->depth*/1;
|
||||
case PARM_TEX_SKYBOX:
|
||||
Assert( arg >= 0 && arg < 6 );
|
||||
return tr.skyboxTextures[arg];
|
||||
case PARM_TEX_SKYTEXNUM:
|
||||
return tr.skytexturenum;
|
||||
case PARM_TEX_LIGHTMAP:
|
||||
arg = bound( 0, arg, MAX_LIGHTMAPS - 1 );
|
||||
return tr.lightmapTextures[arg];
|
||||
case PARM_WIDESCREEN:
|
||||
return gpGlobals->wideScreen;
|
||||
case PARM_FULLSCREEN:
|
||||
return gpGlobals->fullScreen;
|
||||
case PARM_SCREEN_WIDTH:
|
||||
return gpGlobals->width;
|
||||
case PARM_SCREEN_HEIGHT:
|
||||
return gpGlobals->height;
|
||||
case PARM_TEX_TARGET:
|
||||
/*glt = R_GetTexture( arg );*/
|
||||
return /*glt->target*/0;
|
||||
case PARM_TEX_TEXNUM:
|
||||
/*glt = R_GetTexture( arg );*/
|
||||
return /*glt->texnum*/0;
|
||||
case PARM_TEX_FLAGS:
|
||||
glt = R_GetTexture( arg );
|
||||
return glt->flags;
|
||||
case PARM_ACTIVE_TMU:
|
||||
return 0;
|
||||
case PARM_LIGHTSTYLEVALUE:
|
||||
arg = bound( 0, arg, MAX_LIGHTSTYLES - 1 );
|
||||
return tr.lightstylevalue[arg];
|
||||
case PARM_MAX_IMAGE_UNITS:
|
||||
return 1;
|
||||
case PARM_REBUILD_GAMMA:
|
||||
return glConfig.softwareGammaUpdate;
|
||||
case PARM_SURF_SAMPLESIZE:
|
||||
if( arg >= 0 && arg < WORLDMODEL->numsurfaces )
|
||||
return gEngfuncs.Mod_SampleSizeForFace( &WORLDMODEL->surfaces[arg] );
|
||||
return LM_SAMPLE_SIZE;
|
||||
case PARM_GL_CONTEXT_TYPE:
|
||||
return CONTEXT_TYPE_GL;
|
||||
case PARM_GLES_WRAPPER:
|
||||
return GLES_WRAPPER_NONE;
|
||||
case PARM_STENCIL_ACTIVE:
|
||||
return glState.stencilEnabled;
|
||||
case PARM_SKY_SPHERE:
|
||||
return ENGINE_GET_PARM_( parm, arg ) && !tr.fCustomSkybox;
|
||||
default:
|
||||
return ENGINE_GET_PARM_( parm, arg );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale )
|
||||
{
|
||||
gl_texture_t *glt = R_GetTexture( texture );
|
||||
|
||||
if( xScale ) *xScale = glt->xscale;
|
||||
if( yScale ) *yScale = glt->yscale;
|
||||
}
|
||||
|
||||
static void R_GetExtraParmsForTexture( int texture, byte *red, byte *green, byte *blue, byte *density )
|
||||
{
|
||||
gl_texture_t *glt = R_GetTexture( texture );
|
||||
|
||||
if( red ) *red = glt->fogParams[0];
|
||||
if( green ) *green = glt->fogParams[1];
|
||||
if( blue ) *blue = glt->fogParams[2];
|
||||
if( density ) *density = glt->fogParams[3];
|
||||
}
|
||||
|
||||
|
||||
static void R_SetCurrentEntity( cl_entity_t *ent )
|
||||
{
|
||||
RI.currententity = ent;
|
||||
|
||||
// set model also
|
||||
if( RI.currententity != NULL )
|
||||
{
|
||||
RI.currentmodel = RI.currententity->model;
|
||||
}
|
||||
}
|
||||
|
||||
static void R_SetCurrentModel( model_t *mod )
|
||||
{
|
||||
RI.currentmodel = mod;
|
||||
}
|
||||
|
||||
static float R_GetFrameTime( void )
|
||||
{
|
||||
return tr.frametime;
|
||||
}
|
||||
|
||||
static const char *GL_TextureName( unsigned int texnum )
|
||||
{
|
||||
return R_GetTexture( texnum )->name;
|
||||
}
|
||||
|
||||
const byte *GL_TextureData( unsigned int texnum )
|
||||
{
|
||||
rgbdata_t *pic = R_GetTexture( texnum )->original;
|
||||
|
||||
if( pic != NULL )
|
||||
return pic->buffer;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void R_ProcessEntData( qboolean allocate )
|
||||
{
|
||||
if( !allocate )
|
||||
{
|
||||
tr.draw_list->num_solid_entities = 0;
|
||||
tr.draw_list->num_trans_entities = 0;
|
||||
tr.draw_list->num_beam_entities = 0;
|
||||
}
|
||||
|
||||
if( gEngfuncs.drawFuncs->R_ProcessEntData )
|
||||
gEngfuncs.drawFuncs->R_ProcessEntData( allocate );
|
||||
}
|
||||
|
||||
qboolean R_SetDisplayTransform( ref_screen_rotation_t rotate, int offset_x, int offset_y, float scale_x, float scale_y )
|
||||
{
|
||||
qboolean ret = true;
|
||||
if( rotate > 0 )
|
||||
{
|
||||
gEngfuncs.Con_Printf("rotation transform not supported\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if( offset_x || offset_y )
|
||||
{
|
||||
gEngfuncs.Con_Printf("offset transform not supported\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if( scale_x != 1.0f || scale_y != 1.0f )
|
||||
{
|
||||
gEngfuncs.Con_Printf("scale transform not supported\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void* GAME_EXPORT R_GetProcAddress( const char *name )
|
||||
{
|
||||
return gEngfuncs.GL_GetProcAddress( name );
|
||||
}
|
||||
|
||||
static const char *R_GetConfigName( void )
|
||||
{
|
||||
return "ref_gu";
|
||||
}
|
||||
|
||||
ref_interface_t gReffuncs =
|
||||
{
|
||||
R_Init,
|
||||
R_Shutdown,
|
||||
R_GetConfigName,
|
||||
R_SetDisplayTransform,
|
||||
|
||||
GL_SetupAttributes,
|
||||
GL_InitExtensions,
|
||||
GL_ClearExtensions,
|
||||
|
||||
R_BeginFrame,
|
||||
R_RenderScene,
|
||||
R_EndFrame,
|
||||
R_PushScene,
|
||||
R_PopScene,
|
||||
GL_BackendStartFrame,
|
||||
GL_BackendEndFrame,
|
||||
|
||||
R_ClearScreen,
|
||||
R_AllowFog,
|
||||
GL_SetRenderMode,
|
||||
GL_SetColor4ub,
|
||||
|
||||
R_AddEntity,
|
||||
CL_AddCustomBeam,
|
||||
R_ProcessEntData,
|
||||
|
||||
R_ShowTextures,
|
||||
|
||||
R_GetTextureOriginalBuffer,
|
||||
GL_LoadTextureFromBuffer,
|
||||
GL_ProcessTexture,
|
||||
R_SetupSky,
|
||||
|
||||
R_Set2DMode,
|
||||
R_DrawStretchRaw,
|
||||
R_DrawStretchPic,
|
||||
R_DrawTileClear,
|
||||
CL_FillRGBA,
|
||||
CL_FillRGBABlend,
|
||||
|
||||
VID_ScreenShot,
|
||||
VID_CubemapShot,
|
||||
|
||||
R_LightPoint,
|
||||
|
||||
R_DecalShoot,
|
||||
R_DecalRemoveAll,
|
||||
R_CreateDecalList,
|
||||
R_ClearAllDecals,
|
||||
|
||||
R_StudioEstimateFrame,
|
||||
R_StudioLerpMovement,
|
||||
CL_InitStudioAPI,
|
||||
|
||||
R_InitSkyClouds,
|
||||
GL_SubdivideSurface,
|
||||
CL_RunLightStyles,
|
||||
|
||||
R_GetSpriteParms,
|
||||
R_GetSpriteTexture,
|
||||
|
||||
Mod_LoadMapSprite,
|
||||
Mod_ProcessRenderData,
|
||||
Mod_StudioLoadTextures,
|
||||
|
||||
CL_DrawParticles,
|
||||
CL_DrawTracers,
|
||||
CL_DrawBeams,
|
||||
R_BeamCull,
|
||||
|
||||
GL_RefGetParm,
|
||||
R_GetDetailScaleForTexture,
|
||||
R_GetExtraParmsForTexture,
|
||||
R_GetFrameTime,
|
||||
|
||||
R_SetCurrentEntity,
|
||||
R_SetCurrentModel,
|
||||
|
||||
GL_FindTexture,
|
||||
GL_TextureName,
|
||||
GL_TextureData,
|
||||
GL_LoadTexture,
|
||||
GL_CreateTexture,
|
||||
GL_LoadTextureArray,
|
||||
GL_CreateTextureArray,
|
||||
GL_FreeTexture,
|
||||
|
||||
DrawSingleDecal,
|
||||
R_DecalSetupVerts,
|
||||
R_EntityRemoveDecals,
|
||||
|
||||
R_UploadStretchRaw,
|
||||
|
||||
GL_Bind,
|
||||
GL_SelectTexture,
|
||||
GL_LoadTexMatrixExt,
|
||||
GL_LoadIdentityTexMatrix,
|
||||
GL_CleanUpTextureUnits,
|
||||
GL_TexGen,
|
||||
GL_TextureTarget,
|
||||
GL_SetTexCoordArrayMode,
|
||||
GL_UpdateTexSize,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
CL_DrawParticlesExternal,
|
||||
R_LightVec,
|
||||
R_StudioGetTexture,
|
||||
|
||||
R_RenderFrame,
|
||||
Mod_SetOrthoBounds,
|
||||
R_SpeedsMessage,
|
||||
Mod_GetCurrentVis,
|
||||
R_NewMap,
|
||||
R_ClearScene,
|
||||
R_GetProcAddress,
|
||||
|
||||
getTriAPI,
|
||||
|
||||
VGUI_DrawInit,
|
||||
VGUI_DrawShutdown,
|
||||
VGUI_SetupDrawingText,
|
||||
VGUI_SetupDrawingRect,
|
||||
VGUI_SetupDrawingImage,
|
||||
VGUI_BindTexture,
|
||||
VGUI_EnableTexture,
|
||||
VGUI_CreateTexture,
|
||||
VGUI_UploadTexture,
|
||||
VGUI_UploadTextureBlock,
|
||||
VGUI_DrawQuad,
|
||||
VGUI_GetTextureSizes,
|
||||
VGUI_GenerateTexture,
|
||||
};
|
||||
|
||||
int EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs, ref_globals_t *globals )
|
||||
{
|
||||
if( version != REF_API_VERSION )
|
||||
return 0;
|
||||
|
||||
// fill in our callbacks
|
||||
memcpy( funcs, &gReffuncs, sizeof( ref_interface_t ));
|
||||
memcpy( &gEngfuncs, engfuncs, sizeof( ref_api_t ));
|
||||
gpGlobals = globals;
|
||||
|
||||
return REF_API_VERSION;
|
||||
}
|
||||
|
||||
void EXPORT GetRefHumanReadableName( char *out, size_t size )
|
||||
{
|
||||
Q_strncpy( out, "sceGu", size );
|
||||
}
|
||||
149
ref_gu/gu_cull.c
Normal file
149
ref_gu/gu_cull.c
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
gl_cull.c - render culling routines
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "gu_local.h"
|
||||
#include "entity_types.h"
|
||||
|
||||
/*
|
||||
=============================================================
|
||||
|
||||
FRUSTUM AND PVS CULLING
|
||||
|
||||
=============================================================
|
||||
*/
|
||||
/*
|
||||
=================
|
||||
R_CullBox
|
||||
|
||||
Returns true if the box is completely outside the frustum
|
||||
=================
|
||||
*/
|
||||
qboolean R_CullBox( const vec3_t mins, const vec3_t maxs )
|
||||
{
|
||||
return GL_FrustumCullBox( &RI.frustum, mins, maxs, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_CullSphere
|
||||
|
||||
Returns true if the sphere is completely outside the frustum
|
||||
=================
|
||||
*/
|
||||
qboolean R_CullSphere( const vec3_t centre, const float radius )
|
||||
{
|
||||
return GL_FrustumCullSphere( &RI.frustum, centre, radius, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_CullModel
|
||||
=============
|
||||
*/
|
||||
int R_CullModel( cl_entity_t *e, const vec3_t absmin, const vec3_t absmax )
|
||||
{
|
||||
if( e == gEngfuncs.GetViewModel() )
|
||||
{
|
||||
if( ENGINE_GET_PARM( PARM_DEV_OVERVIEW ))
|
||||
return 1;
|
||||
|
||||
if( RP_NORMALPASS() && !ENGINE_GET_PARM( PARM_THIRDPERSON ) && CL_IsViewEntityLocalPlayer())
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// local client can't view himself if camera or thirdperson is not active
|
||||
if( RP_LOCALCLIENT( e ) && !ENGINE_GET_PARM( PARM_THIRDPERSON ) && CL_IsViewEntityLocalPlayer())
|
||||
return 1;
|
||||
|
||||
if( R_CullBox( absmin, absmax ))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_CullSurface
|
||||
|
||||
cull invisible surfaces
|
||||
=================
|
||||
*/
|
||||
int R_CullSurface( msurface_t *surf, gl_frustum_t *frustum, uint clipflags )
|
||||
{
|
||||
cl_entity_t *e = RI.currententity;
|
||||
|
||||
if( !surf || !surf->texinfo || !surf->texinfo->texture )
|
||||
return CULL_OTHER;
|
||||
|
||||
if( r_nocull->value )
|
||||
return CULL_VISIBLE;
|
||||
|
||||
// world surfaces can be culled by vis frame too
|
||||
if( RI.currententity == gEngfuncs.GetEntityByIndex( 0 ) && surf->visframe != tr.framecount )
|
||||
return CULL_VISFRAME;
|
||||
|
||||
// only static ents can be culled by frustum
|
||||
if( !R_StaticEntity( e )) frustum = NULL;
|
||||
|
||||
if( !VectorIsNull( surf->plane->normal ))
|
||||
{
|
||||
float dist;
|
||||
|
||||
// can use normal.z for world (optimisation)
|
||||
if( RI.drawOrtho )
|
||||
{
|
||||
vec3_t orthonormal;
|
||||
|
||||
if( e == gEngfuncs.GetEntityByIndex( 0 ) ) orthonormal[2] = surf->plane->normal[2];
|
||||
else Matrix4x4_VectorRotate( RI.objectMatrix, surf->plane->normal, orthonormal );
|
||||
dist = orthonormal[2];
|
||||
}
|
||||
else dist = PlaneDiff( tr.modelorg, surf->plane );
|
||||
|
||||
if( glState.faceCull == GL_FRONT )
|
||||
{
|
||||
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||
{
|
||||
if( dist >= -BACKFACE_EPSILON )
|
||||
return CULL_BACKSIDE; // wrong side
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dist <= BACKFACE_EPSILON )
|
||||
return CULL_BACKSIDE; // wrong side
|
||||
}
|
||||
}
|
||||
else if( glState.faceCull == GL_BACK )
|
||||
{
|
||||
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||
{
|
||||
if( dist <= BACKFACE_EPSILON )
|
||||
return CULL_BACKSIDE; // wrong side
|
||||
}
|
||||
else
|
||||
{
|
||||
if( dist >= -BACKFACE_EPSILON )
|
||||
return CULL_BACKSIDE; // wrong side
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( frustum && GL_FrustumCullBox( frustum, surf->info->mins, surf->info->maxs, clipflags ))
|
||||
return CULL_FRUSTUM;
|
||||
|
||||
return CULL_VISIBLE;
|
||||
}
|
||||
124
ref_gu/gu_dbghulls.c
Normal file
124
ref_gu/gu_dbghulls.c
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
gl_dbghulls.c - loading & handling world and brushmodels
|
||||
Copyright (C) 2016 Uncle Mike
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "gu_local.h"
|
||||
#include "mod_local.h"
|
||||
|
||||
#define list_entry( ptr, type, member ) \
|
||||
((type *)((char *)(ptr) - (size_t)(&((type *)0)->member)))
|
||||
|
||||
// iterate over each entry in the list
|
||||
#define list_for_each_entry( pos, head, member ) \
|
||||
for( pos = list_entry( (head)->next, winding_t, member ); \
|
||||
&pos->member != (head); \
|
||||
pos = list_entry( pos->member.next, winding_t, member ))
|
||||
|
||||
// REFTODO: rewrite in triapi
|
||||
void R_DrawWorldHull( void )
|
||||
{
|
||||
hull_model_t *hull = &WORLD->hull_models[0];
|
||||
winding_t *poly;
|
||||
int i;
|
||||
|
||||
if( FBitSet( r_showhull->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
int val = bound( 0, (int)r_showhull->value, 3 );
|
||||
if( val ) gEngfuncs.Mod_CreatePolygonsForHull( val );
|
||||
ClearBits( r_showhull->flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
if( !CVAR_TO_BOOL( r_showhull ))
|
||||
return;
|
||||
#if 1
|
||||
sceGuDisable( GU_TEXTURE_2D );
|
||||
list_for_each_entry( poly, &hull->polys, chain )
|
||||
{
|
||||
srand((unsigned int)poly);
|
||||
sceGuColor( GU_RGBA(rand() % 256, rand() % 256, rand() % 256, rand() % 256) );
|
||||
gu_vert_fv_t* const out = ( gu_vert_fv_t* )sceGuGetMemory( sizeof( gu_vert_fv_t ) * poly->numpoints );
|
||||
for( i = 0; i < poly->numpoints; i++ )
|
||||
{
|
||||
out[i].x = poly->p[i][0];
|
||||
out[i].y = poly->p[i][1];
|
||||
out[i].z = poly->p[i][2];
|
||||
}
|
||||
sceGuDrawArray( GU_TRIANGLE_FAN, GU_VERTEX_32BITF, poly->numpoints, 0, out );
|
||||
}
|
||||
sceGuEnable( GU_TEXTURE_2D );
|
||||
#else
|
||||
pglDisable( GL_TEXTURE_2D );
|
||||
list_for_each_entry( poly, &hull->polys, chain )
|
||||
{
|
||||
srand((unsigned int)poly);
|
||||
pglColor3f( rand() % 256 / 255.0, rand() % 256 / 255.0, rand() % 256 / 255.0 );
|
||||
pglBegin( GL_POLYGON );
|
||||
for( i = 0; i < poly->numpoints; i++ )
|
||||
pglVertex3fv( poly->p[i] );
|
||||
pglEnd();
|
||||
}
|
||||
pglEnable( GL_TEXTURE_2D );
|
||||
#endif
|
||||
}
|
||||
|
||||
void R_DrawModelHull( void )
|
||||
{
|
||||
hull_model_t *hull;
|
||||
winding_t *poly;
|
||||
int i;
|
||||
|
||||
if( !CVAR_TO_BOOL( r_showhull ))
|
||||
return;
|
||||
|
||||
if( !RI.currentmodel || RI.currentmodel->name[0] != '*' )
|
||||
return;
|
||||
|
||||
i = atoi( RI.currentmodel->name + 1 );
|
||||
if( i < 1 || i >= WORLD->num_hull_models )
|
||||
return;
|
||||
|
||||
hull = &WORLD->hull_models[i];
|
||||
#if 1
|
||||
sceGuDisable( GU_TEXTURE_2D );
|
||||
list_for_each_entry( poly, &hull->polys, chain )
|
||||
{
|
||||
srand((unsigned int)poly);
|
||||
sceGuColor( GU_RGBA(rand() % 256, rand() % 256, rand() % 256, rand() % 256) );
|
||||
gu_vert_fv_t* const out = ( gu_vert_fv_t* )sceGuGetMemory( sizeof( gu_vert_fv_t ) * poly->numpoints );
|
||||
for( i = 0; i < poly->numpoints; i++ )
|
||||
{
|
||||
out[i].x = poly->p[i][0];
|
||||
out[i].y = poly->p[i][1];
|
||||
out[i].z = poly->p[i][2];
|
||||
}
|
||||
sceGuDrawArray( GU_TRIANGLE_FAN, GU_VERTEX_32BITF, poly->numpoints, 0, out );
|
||||
}
|
||||
sceGuEnable( GU_TEXTURE_2D );
|
||||
#else
|
||||
pglPolygonOffset( 1.0f, 2.0 );
|
||||
pglEnable( GL_POLYGON_OFFSET_FILL );
|
||||
pglDisable( GL_TEXTURE_2D );
|
||||
list_for_each_entry( poly, &hull->polys, chain )
|
||||
{
|
||||
srand((unsigned int)poly);
|
||||
pglColor3f( rand() % 256 / 255.0, rand() % 256 / 255.0, rand() % 256 / 255.0 );
|
||||
pglBegin( GL_POLYGON );
|
||||
for( i = 0; i < poly->numpoints; i++ )
|
||||
pglVertex3fv( poly->p[i] );
|
||||
pglEnd();
|
||||
}
|
||||
pglEnable( GL_TEXTURE_2D );
|
||||
pglDisable( GL_POLYGON_OFFSET_FILL );
|
||||
#endif
|
||||
}
|
||||
1268
ref_gu/gu_decals.c
Normal file
1268
ref_gu/gu_decals.c
Normal file
File diff suppressed because it is too large
Load Diff
308
ref_gu/gu_draw.c
Normal file
308
ref_gu/gu_draw.c
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
gu_draw.c - orthogonal drawing stuff
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
Copyright (C) 2021 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.
|
||||
*/
|
||||
|
||||
#include "gu_local.h"
|
||||
|
||||
/*
|
||||
=============
|
||||
R_GetImageParms
|
||||
=============
|
||||
*/
|
||||
void R_GetTextureParms( int *w, int *h, int texnum )
|
||||
{
|
||||
gl_texture_t *glt;
|
||||
|
||||
glt = R_GetTexture( texnum );
|
||||
if( w ) *w = glt->srcWidth;
|
||||
if( h ) *h = glt->srcHeight;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_GetSpriteParms
|
||||
|
||||
same as GetImageParms but used
|
||||
for sprite models
|
||||
=============
|
||||
*/
|
||||
void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int currentFrame, const model_t *pSprite )
|
||||
{
|
||||
mspriteframe_t *pFrame;
|
||||
|
||||
if( !pSprite || pSprite->type != mod_sprite ) return; // bad model ?
|
||||
pFrame = R_GetSpriteFrame( pSprite, currentFrame, 0.0f );
|
||||
|
||||
if( frameWidth ) *frameWidth = pFrame->width;
|
||||
if( frameHeight ) *frameHeight = pFrame->height;
|
||||
if( numFrames ) *numFrames = pSprite->numframes;
|
||||
}
|
||||
|
||||
int R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame )
|
||||
{
|
||||
if( !m_pSpriteModel || m_pSpriteModel->type != mod_sprite || !m_pSpriteModel->cache.data )
|
||||
return 0;
|
||||
|
||||
return R_GetSpriteFrame( m_pSpriteModel, frame, 0.0f )->gl_texturenum;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_DrawStretchPic
|
||||
=============
|
||||
*/
|
||||
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum )
|
||||
{
|
||||
float uw, uh;
|
||||
gl_texture_t *glt;
|
||||
|
||||
GL_Bind( XASH_TEXTURE0, texnum );
|
||||
|
||||
glt = R_GetTexture( texnum );
|
||||
|
||||
gu_vert_htv_t* const out = ( gu_vert_htv_t* )sceGuGetMemory( sizeof( gu_vert_htv_t ) * 2 );
|
||||
out[0].u = s1 * glt->width;
|
||||
out[0].v = t1 * glt->height;
|
||||
out[0].x = x;
|
||||
out[0].y = y;
|
||||
out[0].z = 0;
|
||||
out[1].u = s2 * glt->width;
|
||||
out[1].v = t2 * glt->height;
|
||||
out[1].x = x + w;
|
||||
out[1].y = y + h;
|
||||
out[1].z = 0;
|
||||
sceGuDrawArray( GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, out );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Draw_TileClear
|
||||
|
||||
This repeats a 64*64 tile graphic to fill the screen around a sized down
|
||||
refresh window.
|
||||
=============
|
||||
*/
|
||||
void R_DrawTileClear( int texnum, int x, int y, int w, int h )
|
||||
{
|
||||
float tw, th;
|
||||
gl_texture_t *glt;
|
||||
|
||||
GL_SetRenderMode( kRenderNormal );
|
||||
|
||||
sceGuColor( 0xffffffff );
|
||||
|
||||
GL_Bind( XASH_TEXTURE0, texnum );
|
||||
|
||||
glt = R_GetTexture( texnum );
|
||||
tw = glt->srcWidth;
|
||||
th = glt->srcHeight;
|
||||
|
||||
gu_vert_htv_t* const out = ( gu_vert_htv_t* )sceGuGetMemory( sizeof( gu_vert_ftv_t ) * 2 );
|
||||
out[0].u = x / tw * glt->width;
|
||||
out[0].v = y / th * glt->height;
|
||||
out[0].x = x;
|
||||
out[0].y = y;
|
||||
out[0].z = 0;
|
||||
out[1].u = ( x + w ) / tw * glt->width;
|
||||
out[1].v = ( y + h ) / th * glt->height;
|
||||
out[1].x = x + w;
|
||||
out[1].y = y + h;
|
||||
out[1].z = 0;
|
||||
sceGuDrawArray( GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, out );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_DrawStretchRaw
|
||||
=============
|
||||
*/
|
||||
void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty )
|
||||
{
|
||||
#if 0
|
||||
byte *raw = NULL;
|
||||
gl_texture_t *tex;
|
||||
|
||||
if( !GL_Support( GL_ARB_TEXTURE_NPOT_EXT ))
|
||||
{
|
||||
int width = 1, height = 1;
|
||||
|
||||
// check the dimensions
|
||||
width = NearestPOW( cols, true );
|
||||
height = NearestPOW( rows, false );
|
||||
|
||||
if( cols != width || rows != height )
|
||||
{
|
||||
raw = GL_ResampleTexture( data, cols, rows, width, height, false );
|
||||
cols = width;
|
||||
rows = height;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
raw = (byte *)data;
|
||||
}
|
||||
|
||||
if( cols > glConfig.max_2d_texture_size )
|
||||
gEngfuncs.Host_Error( "R_DrawStretchRaw: size %i exceeds hardware limits\n", cols );
|
||||
if( rows > glConfig.max_2d_texture_size )
|
||||
gEngfuncs.Host_Error( "R_DrawStretchRaw: size %i exceeds hardware limits\n", rows );
|
||||
|
||||
pglDisable( GL_BLEND );
|
||||
pglDisable( GL_ALPHA_TEST );
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
|
||||
tex = R_GetTexture( tr.cinTexture );
|
||||
GL_Bind( XASH_TEXTURE0, tr.cinTexture );
|
||||
|
||||
if( cols == tex->width && rows == tex->height )
|
||||
{
|
||||
if( dirty )
|
||||
{
|
||||
pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_BGRA, GL_UNSIGNED_BYTE, raw );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tex->size = cols * rows * 4;
|
||||
tex->width = cols;
|
||||
tex->height = rows;
|
||||
if( dirty )
|
||||
{
|
||||
pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, raw );
|
||||
}
|
||||
}
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
pglTexCoord2f( 0, 0 );
|
||||
pglVertex2f( x, y );
|
||||
pglTexCoord2f( 1, 0 );
|
||||
pglVertex2f( x + w, y );
|
||||
pglTexCoord2f( 1, 1 );
|
||||
pglVertex2f( x + w, y + h );
|
||||
pglTexCoord2f( 0, 1 );
|
||||
pglVertex2f( x, y + h );
|
||||
pglEnd();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_UploadStretchRaw
|
||||
=============
|
||||
*/
|
||||
void R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, const byte *data )
|
||||
{
|
||||
#if 0
|
||||
byte *raw = NULL;
|
||||
gl_texture_t *tex;
|
||||
|
||||
if( !GL_Support( GL_ARB_TEXTURE_NPOT_EXT ))
|
||||
{
|
||||
// check the dimensions
|
||||
width = NearestPOW( width, true );
|
||||
height = NearestPOW( height, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
width = bound( 128, width, glConfig.max_2d_texture_size );
|
||||
height = bound( 128, height, glConfig.max_2d_texture_size );
|
||||
}
|
||||
|
||||
if( cols != width || rows != height )
|
||||
{
|
||||
raw = GL_ResampleTexture( data, cols, rows, width, height, false );
|
||||
cols = width;
|
||||
rows = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
raw = (byte *)data;
|
||||
}
|
||||
|
||||
if( cols > glConfig.max_2d_texture_size )
|
||||
gEngfuncs.Host_Error( "R_UploadStretchRaw: size %i exceeds hardware limits\n", cols );
|
||||
if( rows > glConfig.max_2d_texture_size )
|
||||
gEngfuncs.Host_Error( "R_UploadStretchRaw: size %i exceeds hardware limits\n", rows );
|
||||
|
||||
tex = R_GetTexture( texture );
|
||||
GL_Bind( GL_KEEP_UNIT, texture );
|
||||
tex->width = cols;
|
||||
tex->height = rows;
|
||||
|
||||
pglTexImage2D( GL_TEXTURE_2D, 0, tex->format, cols, rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, raw );
|
||||
GL_ApplyTextureParams( tex );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_Set2DMode
|
||||
===============
|
||||
*/
|
||||
void R_Set2DMode( qboolean enable )
|
||||
{
|
||||
if( enable )
|
||||
{
|
||||
if( glState.in2DMode )
|
||||
return;
|
||||
|
||||
// set 2D virtual screen size
|
||||
#if 1 // through mode
|
||||
sceGuViewport( 2048, 2048, gpGlobals->width, gpGlobals->height );
|
||||
sceGuScissor( 0, 0, gpGlobals->width, gpGlobals->height );
|
||||
#else
|
||||
pglViewport( 0, 0, gpGlobals->width, gpGlobals->height );
|
||||
pglMatrixMode( GL_PROJECTION );
|
||||
pglLoadIdentity();
|
||||
pglOrtho( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 );
|
||||
pglMatrixMode( GL_MODELVIEW );
|
||||
pglLoadIdentity();
|
||||
#endif
|
||||
GL_Cull( GL_NONE );
|
||||
#if 1
|
||||
sceGuDepthMask( GU_TRUE );
|
||||
sceGuDisable( GU_DEPTH_TEST );
|
||||
sceGuEnable( GU_ALPHA_TEST );
|
||||
sceGuColor( 0xffffffff );
|
||||
#else
|
||||
pglDepthMask( GL_FALSE );
|
||||
pglDisable( GL_DEPTH_TEST );
|
||||
pglEnable( GL_ALPHA_TEST );
|
||||
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
#endif
|
||||
glState.in2DMode = true;
|
||||
RI.currententity = NULL;
|
||||
RI.currentmodel = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 1
|
||||
sceGuDepthMask( GU_FALSE );
|
||||
sceGuEnable( GU_DEPTH_TEST );
|
||||
glState.in2DMode = false;
|
||||
#else
|
||||
pglDepthMask( GL_TRUE );
|
||||
pglEnable( GL_DEPTH_TEST );
|
||||
glState.in2DMode = false;
|
||||
|
||||
pglMatrixMode( GL_PROJECTION );
|
||||
GL_LoadMatrix( RI.projectionMatrix );
|
||||
|
||||
pglMatrixMode( GL_MODELVIEW );
|
||||
GL_LoadMatrix( RI.worldviewMatrix );
|
||||
#endif
|
||||
GL_Cull( GL_FRONT );
|
||||
}
|
||||
}
|
||||
79
ref_gu/gu_extension.c
Normal file
79
ref_gu/gu_extension.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
gu_extension.c - PSP Graphic Unit extensions
|
||||
Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#include <pspkernel.h>
|
||||
#include <pspge.h>
|
||||
#include <pspgu.h>
|
||||
#include <stdio.h>
|
||||
#include "gu_extension.h"
|
||||
|
||||
/* from guInternal.h */
|
||||
typedef struct
|
||||
{
|
||||
unsigned int* start;
|
||||
unsigned int* current;
|
||||
int parent_context;
|
||||
} GuDisplayList;
|
||||
extern GuDisplayList* gu_list;
|
||||
extern int gu_curr_context;
|
||||
extern int ge_list_executed[];
|
||||
|
||||
static unsigned int gu_list_size;
|
||||
|
||||
|
||||
void extGuStart(int cid, void* list, int size)
|
||||
{
|
||||
gu_list_size = size;
|
||||
sceGuStart( cid, list );
|
||||
}
|
||||
|
||||
/* Begin user packet */
|
||||
void *extGuBeginPacket( unsigned int *maxsize )
|
||||
{
|
||||
unsigned int* current_ptr = gu_list->current;
|
||||
if( maxsize != NULL )
|
||||
{
|
||||
unsigned int size = ( ( unsigned int )gu_list->current ) - ( ( unsigned int )gu_list->start );
|
||||
*maxsize = ( ( unsigned int )gu_list_size ) - ( ( unsigned int )size );
|
||||
}
|
||||
return current_ptr + 2;
|
||||
}
|
||||
|
||||
/* End user packet */
|
||||
void extGuEndPacket( void *eaddr )
|
||||
{
|
||||
unsigned int* current_ptr = gu_list->current;
|
||||
unsigned int size = ( ( unsigned int ) eaddr ) - ( ( unsigned int )current_ptr );
|
||||
|
||||
if( size > 0 )
|
||||
{
|
||||
size += 3;
|
||||
size += ( ( unsigned int )( size >> 31 ) ) >> 30;
|
||||
size = ( size >> 2 ) << 2;
|
||||
|
||||
unsigned int* new_ptr = ( unsigned int* )( ( ( unsigned int ) current_ptr ) + size + 8 );
|
||||
|
||||
int lo = ( 8 << 24 ) | ( ( ( unsigned int )new_ptr ) & 0xffffff );
|
||||
int hi = ( 16 << 24 ) | ( ( ( ( unsigned int )new_ptr ) >> 8 ) & 0xf0000 );
|
||||
|
||||
current_ptr[0] = hi;
|
||||
current_ptr[1] = lo;
|
||||
|
||||
gu_list->current = new_ptr;
|
||||
|
||||
if ( !gu_curr_context )
|
||||
sceGeListUpdateStallAddr( ge_list_executed[0], new_ptr );
|
||||
}
|
||||
}
|
||||
23
ref_gu/gu_extension.h
Normal file
23
ref_gu/gu_extension.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
gu_extension.h - PSP Graphic Unit extensions header
|
||||
Copyright (C) 2020 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 GU_EXTENSION_H
|
||||
#define GU_EXTENSION_H
|
||||
|
||||
void extGuStart(int cid, void* list, int size);
|
||||
void *extGuBeginPacket( unsigned int *maxsize );
|
||||
void extGuEndPacket( void *eaddr );
|
||||
|
||||
#endif//GU_EXTENSION_H
|
||||
356
ref_gu/gu_frustum.c
Normal file
356
ref_gu/gu_frustum.c
Normal file
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
gu_frustum.cpp - frustum test implementation
|
||||
Copyright (C) 2016 Uncle Mike
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "gu_local.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
void GL_FrustumEnablePlane( gl_frustum_t *out, int side )
|
||||
{
|
||||
Assert( side >= 0 && side < FRUSTUM_PLANES );
|
||||
|
||||
// make sure what plane is ready
|
||||
if( !VectorIsNull( out->planes[side].normal ))
|
||||
SetBits( out->clipFlags, BIT( side ));
|
||||
}
|
||||
|
||||
void GL_FrustumDisablePlane( gl_frustum_t *out, int side )
|
||||
{
|
||||
Assert( side >= 0 && side < FRUSTUM_PLANES );
|
||||
ClearBits( out->clipFlags, BIT( side ));
|
||||
}
|
||||
|
||||
void GL_FrustumSetPlane( gl_frustum_t *out, int side, const vec3_t vecNormal, float flDist )
|
||||
{
|
||||
Assert( side >= 0 && side < FRUSTUM_PLANES );
|
||||
|
||||
out->planes[side].type = PlaneTypeForNormal( vecNormal );
|
||||
out->planes[side].signbits = SignbitsForPlane( vecNormal );
|
||||
VectorCopy( vecNormal, out->planes[side].normal );
|
||||
out->planes[side].dist = flDist;
|
||||
|
||||
SetBits( out->clipFlags, BIT( side ));
|
||||
}
|
||||
|
||||
void GL_FrustumNormalizePlane( gl_frustum_t *out, int side )
|
||||
{
|
||||
float length;
|
||||
|
||||
Assert( side >= 0 && side < FRUSTUM_PLANES );
|
||||
|
||||
// normalize
|
||||
length = VectorLength( out->planes[side].normal );
|
||||
|
||||
if( length )
|
||||
{
|
||||
float ilength = (1.0f / length);
|
||||
out->planes[side].normal[0] *= ilength;
|
||||
out->planes[side].normal[1] *= ilength;
|
||||
out->planes[side].normal[2] *= ilength;
|
||||
out->planes[side].dist *= ilength;
|
||||
}
|
||||
|
||||
out->planes[side].type = PlaneTypeForNormal( out->planes[side].normal );
|
||||
out->planes[side].signbits = SignbitsForPlane( out->planes[side].normal );
|
||||
|
||||
SetBits( out->clipFlags, BIT( side ));
|
||||
}
|
||||
|
||||
void GL_FrustumInitProj( gl_frustum_t *out, float flZNear, float flZFar, float flFovX, float flFovY )
|
||||
{
|
||||
float xs, xc;
|
||||
vec3_t farpoint, nearpoint;
|
||||
vec3_t normal, iforward;
|
||||
|
||||
// horizontal fov used for left and right planes
|
||||
SinCos( DEG2RAD( flFovX ) * 0.5f, &xs, &xc );
|
||||
|
||||
// setup left plane
|
||||
VectorMAM( xs, RI.cull_vforward, -xc, RI.cull_vright, normal );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_LEFT, normal, DotProduct( RI.cullorigin, normal ));
|
||||
|
||||
// setup right plane
|
||||
VectorMAM( xs, RI.cull_vforward, xc, RI.cull_vright, normal );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_RIGHT, normal, DotProduct( RI.cullorigin, normal ));
|
||||
|
||||
// vertical fov used for top and bottom planes
|
||||
SinCos( DEG2RAD( flFovY ) * 0.5f, &xs, &xc );
|
||||
VectorNegate( RI.cull_vforward, iforward );
|
||||
|
||||
// setup bottom plane
|
||||
VectorMAM( xs, RI.cull_vforward, -xc, RI.cull_vup, normal );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_BOTTOM, normal, DotProduct( RI.cullorigin, normal ));
|
||||
|
||||
// setup top plane
|
||||
VectorMAM( xs, RI.cull_vforward, xc, RI.cull_vup, normal );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_TOP, normal, DotProduct( RI.cullorigin, normal ));
|
||||
|
||||
// setup far plane
|
||||
VectorMA( RI.cullorigin, flZFar, RI.cull_vforward, farpoint );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_FAR, iforward, DotProduct( iforward, farpoint ));
|
||||
|
||||
// no need to setup backplane for general view.
|
||||
if( flZNear == 0.0f ) return;
|
||||
|
||||
// setup near plane
|
||||
VectorMA( RI.cullorigin, flZNear, RI.cull_vforward, nearpoint );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_NEAR, RI.cull_vforward, DotProduct( RI.cull_vforward, nearpoint ));
|
||||
}
|
||||
|
||||
void GL_FrustumInitOrtho( gl_frustum_t *out, float xLeft, float xRight, float yTop, float yBottom, float flZNear, float flZFar )
|
||||
{
|
||||
vec3_t iforward, iright, iup;
|
||||
|
||||
// setup the near and far planes
|
||||
float orgOffset = DotProduct( RI.cullorigin, RI.cull_vforward );
|
||||
VectorNegate( RI.cull_vforward, iforward );
|
||||
|
||||
// because quake ortho is inverted and far and near should be swaped
|
||||
GL_FrustumSetPlane( out, FRUSTUM_FAR, iforward, -flZNear - orgOffset );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_NEAR, RI.cull_vforward, flZFar + orgOffset );
|
||||
|
||||
// setup left and right planes
|
||||
orgOffset = DotProduct( RI.cullorigin, RI.cull_vright );
|
||||
VectorNegate( RI.cull_vright, iright );
|
||||
|
||||
GL_FrustumSetPlane( out, FRUSTUM_LEFT, RI.cull_vright, xLeft + orgOffset );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_RIGHT, iright, -xRight - orgOffset );
|
||||
|
||||
// setup top and buttom planes
|
||||
orgOffset = DotProduct( RI.cullorigin, RI.cull_vup );
|
||||
VectorNegate( RI.cull_vup, iup );
|
||||
|
||||
GL_FrustumSetPlane( out, FRUSTUM_TOP, RI.cull_vup, yTop + orgOffset );
|
||||
GL_FrustumSetPlane( out, FRUSTUM_BOTTOM, iup, -yBottom - orgOffset );
|
||||
}
|
||||
|
||||
void GL_FrustumInitBox( gl_frustum_t *out, const vec3_t org, float radius )
|
||||
{
|
||||
vec3_t normal;
|
||||
int i;
|
||||
|
||||
for( i = 0; i < FRUSTUM_PLANES; i++ )
|
||||
{
|
||||
// setup normal for each direction
|
||||
VectorClear( normal );
|
||||
normal[((i >> 1) + 1) % 3] = (i & 1) ? 1.0f : -1.0f;
|
||||
GL_FrustumSetPlane( out, i, normal, DotProduct( org, normal ) - radius );
|
||||
}
|
||||
}
|
||||
|
||||
void GL_FrustumInitProjFromMatrix( gl_frustum_t *out, const matrix4x4 projection )
|
||||
{
|
||||
int i;
|
||||
|
||||
// left
|
||||
out->planes[FRUSTUM_LEFT].normal[0] = projection[0][3] + projection[0][0];
|
||||
out->planes[FRUSTUM_LEFT].normal[1] = projection[1][3] + projection[1][0];
|
||||
out->planes[FRUSTUM_LEFT].normal[2] = projection[2][3] + projection[2][0];
|
||||
out->planes[FRUSTUM_LEFT].dist = -(projection[3][3] + projection[3][0]);
|
||||
|
||||
// right
|
||||
out->planes[FRUSTUM_RIGHT].normal[0] = projection[0][3] - projection[0][0];
|
||||
out->planes[FRUSTUM_RIGHT].normal[1] = projection[1][3] - projection[1][0];
|
||||
out->planes[FRUSTUM_RIGHT].normal[2] = projection[2][3] - projection[2][0];
|
||||
out->planes[FRUSTUM_RIGHT].dist = -(projection[3][3] - projection[3][0]);
|
||||
|
||||
// bottom
|
||||
out->planes[FRUSTUM_BOTTOM].normal[0] = projection[0][3] + projection[0][1];
|
||||
out->planes[FRUSTUM_BOTTOM].normal[1] = projection[1][3] + projection[1][1];
|
||||
out->planes[FRUSTUM_BOTTOM].normal[2] = projection[2][3] + projection[2][1];
|
||||
out->planes[FRUSTUM_BOTTOM].dist = -(projection[3][3] + projection[3][1]);
|
||||
|
||||
// top
|
||||
out->planes[FRUSTUM_TOP].normal[0] = projection[0][3] - projection[0][1];
|
||||
out->planes[FRUSTUM_TOP].normal[1] = projection[1][3] - projection[1][1];
|
||||
out->planes[FRUSTUM_TOP].normal[2] = projection[2][3] - projection[2][1];
|
||||
out->planes[FRUSTUM_TOP].dist = -(projection[3][3] - projection[3][1]);
|
||||
|
||||
// near
|
||||
out->planes[FRUSTUM_NEAR].normal[0] = projection[0][3] + projection[0][2];
|
||||
out->planes[FRUSTUM_NEAR].normal[1] = projection[1][3] + projection[1][2];
|
||||
out->planes[FRUSTUM_NEAR].normal[2] = projection[2][3] + projection[2][2];
|
||||
out->planes[FRUSTUM_NEAR].dist = -(projection[3][3] + projection[3][2]);
|
||||
|
||||
// far
|
||||
out->planes[FRUSTUM_FAR].normal[0] = projection[0][3] - projection[0][2];
|
||||
out->planes[FRUSTUM_FAR].normal[1] = projection[1][3] - projection[1][2];
|
||||
out->planes[FRUSTUM_FAR].normal[2] = projection[2][3] - projection[2][2];
|
||||
out->planes[FRUSTUM_FAR].dist = -(projection[3][3] - projection[3][2]);
|
||||
|
||||
for( i = 0; i < FRUSTUM_PLANES; i++ )
|
||||
{
|
||||
GL_FrustumNormalizePlane( out, i );
|
||||
}
|
||||
}
|
||||
|
||||
void GL_FrustumComputeCorners( gl_frustum_t *out, vec3_t corners[8] )
|
||||
{
|
||||
memset( corners, 0, sizeof( vec3_t ) * 8 );
|
||||
|
||||
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_LEFT], &out->planes[FRUSTUM_TOP], &out->planes[FRUSTUM_FAR], corners[0] );
|
||||
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_RIGHT], &out->planes[FRUSTUM_TOP], &out->planes[FRUSTUM_FAR], corners[1] );
|
||||
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_LEFT], &out->planes[FRUSTUM_BOTTOM], &out->planes[FRUSTUM_FAR], corners[2] );
|
||||
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_RIGHT], &out->planes[FRUSTUM_BOTTOM], &out->planes[FRUSTUM_FAR], corners[3] );
|
||||
|
||||
if( FBitSet( out->clipFlags, BIT( FRUSTUM_NEAR )))
|
||||
{
|
||||
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_LEFT], &out->planes[FRUSTUM_TOP], &out->planes[FRUSTUM_NEAR], corners[4] );
|
||||
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_RIGHT], &out->planes[FRUSTUM_TOP], &out->planes[FRUSTUM_NEAR], corners[5] );
|
||||
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_LEFT], &out->planes[FRUSTUM_BOTTOM], &out->planes[FRUSTUM_NEAR], corners[6] );
|
||||
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_RIGHT], &out->planes[FRUSTUM_BOTTOM], &out->planes[FRUSTUM_NEAR], corners[7] );
|
||||
}
|
||||
else
|
||||
{
|
||||
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_LEFT], &out->planes[FRUSTUM_RIGHT], &out->planes[FRUSTUM_TOP], corners[4] );
|
||||
VectorCopy( corners[4], corners[5] );
|
||||
VectorCopy( corners[4], corners[6] );
|
||||
VectorCopy( corners[4], corners[7] );
|
||||
}
|
||||
}
|
||||
|
||||
void GL_FrustumComputeBounds( gl_frustum_t *out, vec3_t mins, vec3_t maxs )
|
||||
{
|
||||
vec3_t corners[8];
|
||||
int i;
|
||||
|
||||
GL_FrustumComputeCorners( out, corners );
|
||||
|
||||
ClearBounds( mins, maxs );
|
||||
|
||||
for( i = 0; i < 8; i++ )
|
||||
AddPointToBounds( corners[i], mins, maxs );
|
||||
}
|
||||
|
||||
void GL_FrustumDrawDebug( gl_frustum_t *out )
|
||||
{
|
||||
/*
|
||||
vec3_t bbox[8];
|
||||
int i;
|
||||
|
||||
GL_FrustumComputeCorners( out, bbox );
|
||||
|
||||
// g-cont. frustum must be yellow :-)
|
||||
pglColor4f( 1.0f, 1.0f, 0.0f, 1.0f );
|
||||
pglDisable( GL_TEXTURE_2D );
|
||||
pglBegin( GL_LINES );
|
||||
|
||||
for( i = 0; i < 2; i += 1 )
|
||||
{
|
||||
pglVertex3fv( bbox[i+0] );
|
||||
pglVertex3fv( bbox[i+2] );
|
||||
pglVertex3fv( bbox[i+4] );
|
||||
pglVertex3fv( bbox[i+6] );
|
||||
pglVertex3fv( bbox[i+0] );
|
||||
pglVertex3fv( bbox[i+4] );
|
||||
pglVertex3fv( bbox[i+2] );
|
||||
pglVertex3fv( bbox[i+6] );
|
||||
pglVertex3fv( bbox[i*2+0] );
|
||||
pglVertex3fv( bbox[i*2+1] );
|
||||
pglVertex3fv( bbox[i*2+4] );
|
||||
pglVertex3fv( bbox[i*2+5] );
|
||||
}
|
||||
|
||||
pglEnd();
|
||||
pglEnable( GL_TEXTURE_2D );
|
||||
*/
|
||||
}
|
||||
|
||||
// cull methods
|
||||
qboolean GL_FrustumCullBox( gl_frustum_t *out, const vec3_t mins, const vec3_t maxs, int userClipFlags )
|
||||
{
|
||||
int iClipFlags;
|
||||
int i, bit;
|
||||
|
||||
if( r_nocull->value )
|
||||
return false;
|
||||
|
||||
if( userClipFlags != 0 )
|
||||
iClipFlags = userClipFlags;
|
||||
else iClipFlags = out->clipFlags;
|
||||
|
||||
for( i = FRUSTUM_PLANES, bit = 1; i > 0; i--, bit <<= 1 )
|
||||
{
|
||||
const mplane_t *p = &out->planes[FRUSTUM_PLANES - i];
|
||||
|
||||
if( !FBitSet( iClipFlags, bit ))
|
||||
continue;
|
||||
|
||||
switch( p->signbits )
|
||||
{
|
||||
case 0:
|
||||
if( p->normal[0] * maxs[0] + p->normal[1] * maxs[1] + p->normal[2] * maxs[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 1:
|
||||
if( p->normal[0] * mins[0] + p->normal[1] * maxs[1] + p->normal[2] * maxs[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 2:
|
||||
if( p->normal[0] * maxs[0] + p->normal[1] * mins[1] + p->normal[2] * maxs[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 3:
|
||||
if( p->normal[0] * mins[0] + p->normal[1] * mins[1] + p->normal[2] * maxs[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 4:
|
||||
if( p->normal[0] * maxs[0] + p->normal[1] * maxs[1] + p->normal[2] * mins[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 5:
|
||||
if( p->normal[0] * mins[0] + p->normal[1] * maxs[1] + p->normal[2] * mins[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 6:
|
||||
if( p->normal[0] * maxs[0] + p->normal[1] * mins[1] + p->normal[2] * mins[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
case 7:
|
||||
if( p->normal[0] * mins[0] + p->normal[1] * mins[1] + p->normal[2] * mins[2] < p->dist )
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
qboolean GL_FrustumCullSphere( gl_frustum_t *out, const vec3_t center, float radius, int userClipFlags )
|
||||
{
|
||||
int iClipFlags;
|
||||
int i, bit;
|
||||
|
||||
if( r_nocull->value )
|
||||
return false;
|
||||
|
||||
if( userClipFlags != 0 )
|
||||
iClipFlags = userClipFlags;
|
||||
else iClipFlags = out->clipFlags;
|
||||
|
||||
for( i = FRUSTUM_PLANES, bit = 1; i > 0; i--, bit <<= 1 )
|
||||
{
|
||||
const mplane_t *p = &out->planes[FRUSTUM_PLANES - i];
|
||||
|
||||
if( !FBitSet( iClipFlags, bit ))
|
||||
continue;
|
||||
|
||||
if( DotProduct( center, p->normal ) - p->dist <= -radius )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
52
ref_gu/gu_frustum.h
Normal file
52
ref_gu/gu_frustum.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
gl_frustum.cpp - frustum test implementation
|
||||
Copyright (C) 2016 Uncle Mike
|
||||
|
||||
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 GL_FRUSTUM_H
|
||||
#define GL_FRUSTUM_H
|
||||
|
||||
// don't change this order
|
||||
#define FRUSTUM_LEFT 0
|
||||
#define FRUSTUM_RIGHT 1
|
||||
#define FRUSTUM_BOTTOM 2
|
||||
#define FRUSTUM_TOP 3
|
||||
#define FRUSTUM_FAR 4
|
||||
#define FRUSTUM_NEAR 5
|
||||
#define FRUSTUM_PLANES 6
|
||||
|
||||
typedef struct gl_frustum_s
|
||||
{
|
||||
mplane_t planes[FRUSTUM_PLANES];
|
||||
unsigned int clipFlags;
|
||||
} gl_frustum_t;
|
||||
|
||||
void GL_FrustumInitProj( gl_frustum_t *out, float flZNear, float flZFar, float flFovX, float flFovY );
|
||||
void GL_FrustumInitOrtho( gl_frustum_t *out, float xLeft, float xRight, float yTop, float yBottom, float flZNear, float flZFar );
|
||||
void GL_FrustumInitBox( gl_frustum_t *out, const vec3_t org, float radius ); // used for pointlights
|
||||
void GL_FrustumInitProjFromMatrix( gl_frustum_t *out, const matrix4x4 projection );
|
||||
void GL_FrustumSetPlane( gl_frustum_t *out, int side, const vec3_t vecNormal, float flDist );
|
||||
void GL_FrustumNormalizePlane( gl_frustum_t *out, int side );
|
||||
void GL_FrustumComputeBounds( gl_frustum_t *out, vec3_t mins, vec3_t maxs );
|
||||
void GL_FrustumComputeCorners( gl_frustum_t *out, vec3_t bbox[8] );
|
||||
void GL_FrustumDrawDebug( gl_frustum_t *out );
|
||||
|
||||
// cull methods
|
||||
qboolean GL_FrustumCullBox( gl_frustum_t *out, const vec3_t mins, const vec3_t maxs, int userClipFlags );
|
||||
qboolean GL_FrustumCullSphere( gl_frustum_t *out, const vec3_t centre, float radius, int userClipFlags );
|
||||
|
||||
// plane manipulating
|
||||
void GL_FrustumEnablePlane( gl_frustum_t *out, int side );
|
||||
void GL_FrustumDisablePlane( gl_frustum_t *out, int side );
|
||||
|
||||
#endif//GL_FRUSTUM_H
|
||||
67
ref_gu/gu_helper.h
Normal file
67
ref_gu/gu_helper.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
gl_helper.h - gu helper
|
||||
Copyright (C) 2021 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 GU_HELPER_H
|
||||
#define GU_HELPER_H
|
||||
#ifndef APIENTRY
|
||||
#define APIENTRY
|
||||
#endif
|
||||
|
||||
#ifndef APIENTRY_LINKAGE
|
||||
#define APIENTRY_LINKAGE extern
|
||||
#endif
|
||||
|
||||
// GL types wrapping
|
||||
typedef uint GLenum;
|
||||
typedef byte GLboolean;
|
||||
typedef uint GLbitfield;
|
||||
typedef void GLvoid;
|
||||
typedef signed char GLbyte;
|
||||
typedef short GLshort;
|
||||
typedef int GLint;
|
||||
typedef byte GLubyte;
|
||||
typedef word GLushort;
|
||||
typedef uint GLuint;
|
||||
typedef int GLsizei;
|
||||
typedef float GLfloat;
|
||||
typedef float GLclampf;
|
||||
typedef double GLdouble;
|
||||
typedef double GLclampd;
|
||||
typedef int GLintptrARB;
|
||||
typedef int GLsizeiptrARB;
|
||||
typedef char GLcharARB;
|
||||
typedef uint GLhandleARB;
|
||||
typedef float GLmatrix[16];
|
||||
|
||||
// GL_Cull wrapping
|
||||
#define GL_NONE 0
|
||||
#define GL_FRONT GU_CW + 1
|
||||
#define GL_BACK GU_CCW + 1
|
||||
|
||||
// color functions wrapping
|
||||
#define GUCOLOR4F( r, g, b, a ) GU_COLOR( ( r ), ( g ), ( b ), ( a ) )
|
||||
#define GUCOLOR4FV( v ) GU_COLOR( ( v )[0], ( v )[1], ( v )[2], ( v )[3] )
|
||||
#define GUCOLOR4UB( r, g, b, a ) GU_RGBA( ( r ), ( g ), ( b ), ( a ) )
|
||||
#define GUCOLOR4UBV( v ) GU_RGBA( ( v )[0], ( v )[1], ( v )[2], ( v )[3] )
|
||||
#define GUCOLOR3F( r, g, b ) GU_COLOR( ( r ), ( g ), ( b ), 1.0f )
|
||||
#define GUCOLOR3FV( v ) GU_COLOR( ( v )[0], ( v )[1], ( v )[2], 1.0f )
|
||||
#define GUCOLOR3UB( r, g, b ) GU_RGBA( ( r ), ( g ), ( b ), 255 )
|
||||
#define GUCOLOR3UBV( v ) GU_RGBA( ( v )[0], ( v )[1], ( v )[2], 255 )
|
||||
|
||||
// blend function wrapping
|
||||
#define GUBLEND1 0xffffffff
|
||||
#define GUBLEND0 0x00000000
|
||||
|
||||
#endif // GU_HELPER_H
|
||||
2063
ref_gu/gu_image.c
Normal file
2063
ref_gu/gu_image.c
Normal file
File diff suppressed because it is too large
Load Diff
829
ref_gu/gu_local.h
Normal file
829
ref_gu/gu_local.h
Normal file
@@ -0,0 +1,829 @@
|
||||
/*
|
||||
gu_local.h - renderer local declarations
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
Copyright (C) 2021 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 GL_LOCAL_H
|
||||
#define GL_LOCAL_H
|
||||
|
||||
#include <pspkernel.h>
|
||||
#include <pspdisplay.h>
|
||||
#include <pspgu.h>
|
||||
#include <pspgum.h>
|
||||
|
||||
#include "port.h"
|
||||
#include "xash3d_types.h"
|
||||
#include "cvardef.h"
|
||||
#include "const.h"
|
||||
#include "com_model.h"
|
||||
#include "cl_entity.h"
|
||||
#include "render_api.h"
|
||||
#include "protocol.h"
|
||||
#include "dlight.h"
|
||||
#include "gu_frustum.h"
|
||||
#include "ref_api.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "ref_params.h"
|
||||
#include "enginefeatures.h"
|
||||
#include "com_strings.h"
|
||||
#include "pm_movevars.h"
|
||||
//#include "cvar.h"
|
||||
#include "gu_helper.h"
|
||||
#include "gu_extension.h"
|
||||
#include "gu_vram.h"
|
||||
#include "wadfile.h"
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(s,m) (size_t)&(((s *)0)->m)
|
||||
#endif // offsetof
|
||||
|
||||
#define ASSERT(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ )
|
||||
#define Assert(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ )
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define CVAR_DEFINE( cv, cvname, cvstr, cvflags, cvdesc ) cvar_t cv = { cvname, cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, cvdesc }
|
||||
#define CVAR_DEFINE_AUTO( cv, cvstr, cvflags, cvdesc ) cvar_t cv = { #cv, cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, cvdesc }
|
||||
#define CVAR_TO_BOOL( x ) ((x) && ((x)->value != 0.0f) ? true : false )
|
||||
|
||||
#define WORLD (gEngfuncs.GetWorld())
|
||||
#define WORLDMODEL (gEngfuncs.pfnGetModelByIndex( 1 ))
|
||||
#define MOVEVARS (gEngfuncs.pfnGetMoveVars())
|
||||
|
||||
// make mod_ref.h?
|
||||
#define LM_SAMPLE_SIZE 16
|
||||
|
||||
|
||||
extern byte *r_temppool;
|
||||
|
||||
#define LIGHTMAP_BPP 1 //1 2 3 4
|
||||
|
||||
#if LIGHTMAP_BPP == 1
|
||||
#define LIGHTMAP_FORMAT PF_RGB_332
|
||||
#elif LIGHTMAP_BPP == 2
|
||||
#define LIGHTMAP_FORMAT PF_RGB_5650
|
||||
#elif LIGHTMAP_BPP == 3
|
||||
#define LIGHTMAP_FORMAT PF_RGB_24
|
||||
#elif LIGHTMAP_BPP == 4
|
||||
#define LIGHTMAP_FORMAT PF_RGBA_32
|
||||
#else
|
||||
#error (1 > LIGHTMAP_BPP > 4)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
|
||||
#define BLOCK_SIZE tr.block_size // lightmap blocksize
|
||||
#define BLOCK_SIZE_DEFAULT 128 // for keep backward compatibility
|
||||
#define BLOCK_SIZE_MAX 128
|
||||
|
||||
#define MAX_TEXTURES 1536
|
||||
#define MAX_DETAIL_TEXTURES 64
|
||||
#define MAX_LIGHTMAPS 64
|
||||
#define SUBDIVIDE_SIZE 64
|
||||
#define MAX_DECAL_SURFS 256
|
||||
#define MAX_DRAW_STACK 2 // normal view and menu view
|
||||
|
||||
#else
|
||||
|
||||
#define BLOCK_SIZE tr.block_size // lightmap blocksize
|
||||
#define BLOCK_SIZE_DEFAULT 128 // for keep backward compatibility
|
||||
#define BLOCK_SIZE_MAX 1024
|
||||
|
||||
#define MAX_TEXTURES 4096
|
||||
#define MAX_DETAIL_TEXTURES 256
|
||||
#define MAX_LIGHTMAPS 256
|
||||
#define SUBDIVIDE_SIZE 64
|
||||
#define MAX_DECAL_SURFS 4096
|
||||
#define MAX_DRAW_STACK 2 // normal view and menu view
|
||||
|
||||
#endif
|
||||
|
||||
#define SHADEDOT_QUANT 16 // precalculated dot products for quantized angles
|
||||
#define SHADE_LAMBERT 1.495f
|
||||
|
||||
#if 1
|
||||
#define DEFAULT_ALPHATEST 0x00
|
||||
#else
|
||||
#define DEFAULT_ALPHATEST 0.0f
|
||||
#endif
|
||||
|
||||
// refparams
|
||||
#define RP_NONE 0
|
||||
#define RP_ENVVIEW BIT( 0 ) // used for cubemapshot
|
||||
#define RP_OLDVIEWLEAF BIT( 1 )
|
||||
#define RP_CLIPPLANE BIT( 2 )
|
||||
|
||||
#define RP_NONVIEWERREF (RP_ENVVIEW)
|
||||
#define R_ModelOpaque( rm ) ( rm == kRenderNormal )
|
||||
#define R_StaticEntity( ent ) ( VectorIsNull( ent->origin ) && VectorIsNull( ent->angles ))
|
||||
#define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == ENGINE_GET_PARM( PARM_PLAYER_INDEX ) && e->player )
|
||||
#define RP_NORMALPASS() ( FBitSet( RI.params, RP_NONVIEWERREF ) == 0 )
|
||||
|
||||
#define CL_IsViewEntityLocalPlayer() ( ENGINE_GET_PARM( PARM_VIEWENT_INDEX ) == ENGINE_GET_PARM( PARM_PLAYER_INDEX ) )
|
||||
|
||||
#define CULL_VISIBLE 0 // not culled
|
||||
#define CULL_BACKSIDE 1 // backside of transparent wall
|
||||
#define CULL_FRUSTUM 2 // culled by frustum
|
||||
#define CULL_VISFRAME 3 // culled by PVS
|
||||
#define CULL_OTHER 4 // culled by other reason
|
||||
|
||||
typedef struct gltexture_s
|
||||
{
|
||||
|
||||
char name[128]; // game path, including extension (can be store image programs)
|
||||
short srcWidth; // keep unscaled sizes
|
||||
short srcHeight;
|
||||
short width; // upload width\height
|
||||
short height;
|
||||
//short depth; // texture depth or count of layers for 2D_ARRAY
|
||||
byte numMips; // mipmap count
|
||||
byte *dstTexture; // texture pointer
|
||||
byte *dstPalette;
|
||||
byte bpp;
|
||||
int format; // uploaded format
|
||||
//GLint encode; // using GLSL decoder
|
||||
texFlags_t flags;
|
||||
|
||||
rgba_t fogParams; // some water textures
|
||||
// contain info about underwater fog
|
||||
|
||||
rgbdata_t *original; // keep original image
|
||||
|
||||
// debug info
|
||||
size_t size; // upload size for debug targets
|
||||
|
||||
// detail textures stuff
|
||||
float xscale;
|
||||
float yscale;
|
||||
#if 0
|
||||
int servercount;
|
||||
#endif
|
||||
uint hashValue;
|
||||
struct gltexture_s *nextHash;
|
||||
} gl_texture_t;
|
||||
|
||||
#if 1
|
||||
typedef struct
|
||||
{
|
||||
float x, y, z;
|
||||
}gu_vert_fv_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int c;
|
||||
float x, y, z;
|
||||
}gu_vert_fcv_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float u, v;
|
||||
float x, y, z;
|
||||
}gu_vert_ftv_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float u, v;
|
||||
unsigned int c;
|
||||
float x, y, z;
|
||||
}gu_vert_ftcv_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float u, v;
|
||||
unsigned int c;
|
||||
float nx, ny, nz;
|
||||
float x, y, z;
|
||||
}gu_vert_ftcnv_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short x, y, z;
|
||||
}gu_vert_hv_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short u, v;
|
||||
short x, y, z;
|
||||
}gu_vert_htv_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short u, v;
|
||||
unsigned int c;
|
||||
short x, y, z;
|
||||
}gu_vert_htcv_t;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int params; // rendering parameters
|
||||
|
||||
qboolean drawWorld; // ignore world for drawing PlayerModel
|
||||
qboolean isSkyVisible; // sky is visible
|
||||
qboolean onlyClientDraw; // disabled by client request
|
||||
qboolean drawOrtho; // draw world as orthogonal projection
|
||||
|
||||
float fov_x, fov_y; // current view fov
|
||||
|
||||
cl_entity_t *currententity;
|
||||
model_t *currentmodel;
|
||||
cl_entity_t *currentbeam; // same as above but for beams
|
||||
|
||||
int viewport[4];
|
||||
gl_frustum_t frustum;
|
||||
|
||||
mleaf_t *viewleaf;
|
||||
mleaf_t *oldviewleaf;
|
||||
vec3_t pvsorigin;
|
||||
vec3_t vieworg; // locked vieworigin
|
||||
vec3_t viewangles;
|
||||
vec3_t vforward;
|
||||
vec3_t vright;
|
||||
vec3_t vup;
|
||||
|
||||
vec3_t cullorigin;
|
||||
vec3_t cull_vforward;
|
||||
vec3_t cull_vright;
|
||||
vec3_t cull_vup;
|
||||
|
||||
float farClip;
|
||||
|
||||
qboolean fogCustom;
|
||||
qboolean fogEnabled;
|
||||
qboolean fogSkybox;
|
||||
vec4_t fogColor;
|
||||
float fogDensity;
|
||||
float fogStart;
|
||||
float fogEnd;
|
||||
int cached_contents; // in water
|
||||
int cached_waterlevel; // was in water
|
||||
|
||||
float skyMins[2][6];
|
||||
float skyMaxs[2][6];
|
||||
|
||||
matrix4x4 objectMatrix; // currententity matrix
|
||||
matrix4x4 worldviewMatrix; // modelview for world
|
||||
matrix4x4 modelviewMatrix; // worldviewMatrix * objectMatrix
|
||||
|
||||
matrix4x4 projectionMatrix;
|
||||
matrix4x4 worldviewProjectionMatrix; // worldviewMatrix * projectionMatrix
|
||||
byte visbytes[(MAX_MAP_LEAFS+7)/8];// actual PVS for current frame
|
||||
|
||||
float viewplanedist;
|
||||
mplane_t clipPlane;
|
||||
} ref_instance_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cl_entity_t *solid_entities[MAX_VISIBLE_PACKET]; // opaque moving or alpha brushes
|
||||
cl_entity_t *trans_entities[MAX_VISIBLE_PACKET]; // translucent brushes
|
||||
cl_entity_t *beam_entities[MAX_VISIBLE_PACKET];
|
||||
uint num_solid_entities;
|
||||
uint num_trans_entities;
|
||||
uint num_beam_entities;
|
||||
} draw_list_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int defaultTexture; // use for bad textures
|
||||
int particleTexture;
|
||||
int whiteTexture;
|
||||
int grayTexture;
|
||||
int blackTexture;
|
||||
int solidskyTexture; // quake1 solid-sky layer
|
||||
int alphaskyTexture; // quake1 alpha-sky layer
|
||||
int lightmapTextures[MAX_LIGHTMAPS];
|
||||
int dlightTexture; // custom dlight texture
|
||||
int skyboxTextures[6]; // skybox sides
|
||||
int cinTexture; // cinematic texture
|
||||
|
||||
int skytexturenum; // this not a gl_texturenum!
|
||||
#if 0
|
||||
int skyboxbasenum; // start with 5800
|
||||
#endif
|
||||
// entity lists
|
||||
draw_list_t draw_stack[MAX_DRAW_STACK];
|
||||
int draw_stack_pos;
|
||||
draw_list_t *draw_list;
|
||||
|
||||
msurface_t *draw_decals[MAX_DECAL_SURFS];
|
||||
int num_draw_decals;
|
||||
|
||||
// OpenGL matrix states
|
||||
qboolean modelviewIdentity;
|
||||
|
||||
int visframecount; // PVS frame
|
||||
int dlightframecount; // dynamic light frame
|
||||
int realframecount; // not including viewpasses
|
||||
int framecount;
|
||||
|
||||
qboolean ignore_lightgamma;
|
||||
qboolean fCustomRendering;
|
||||
qboolean fResetVis;
|
||||
qboolean fFlipViewModel;
|
||||
|
||||
byte visbytes[(MAX_MAP_LEAFS+7)/8]; // member custom PVS
|
||||
int lightstylevalue[MAX_LIGHTSTYLES]; // value 0 - 65536
|
||||
int block_size; // lightmap blocksize
|
||||
|
||||
double frametime; // special frametime for multipass rendering (will set to 0 on a nextview)
|
||||
float blend; // global blend value
|
||||
|
||||
// cull info
|
||||
vec3_t modelorg; // relative to viewpoint
|
||||
|
||||
qboolean fCustomSkybox;
|
||||
} gl_globals_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint c_world_polys;
|
||||
uint c_studio_polys;
|
||||
uint c_sprite_polys;
|
||||
uint c_alias_polys;
|
||||
uint c_world_leafs;
|
||||
|
||||
uint c_view_beams_count;
|
||||
uint c_active_tents_count;
|
||||
uint c_alias_models_drawn;
|
||||
uint c_studio_models_drawn;
|
||||
uint c_sprite_models_drawn;
|
||||
uint c_particle_count;
|
||||
|
||||
uint c_client_ents; // entities that moved to client
|
||||
double t_world_node;
|
||||
double t_world_draw;
|
||||
} ref_speeds_t;
|
||||
|
||||
extern ref_speeds_t r_stats;
|
||||
extern ref_instance_t RI;
|
||||
extern gl_globals_t tr;
|
||||
|
||||
extern float gldepthmin, gldepthmax;
|
||||
#define r_numEntities (tr.draw_list->num_solid_entities + tr.draw_list->num_trans_entities)
|
||||
#define r_numStatics (r_stats.c_client_ents)
|
||||
|
||||
//
|
||||
// gu_backend.c
|
||||
//
|
||||
void GL_BackendStartFrame( void );
|
||||
void GL_BackendEndFrame( void );
|
||||
void GL_CleanUpTextureUnits( int last );
|
||||
void GL_Bind( GLint tmu, GLenum texnum );
|
||||
void GL_MultiTexCoord2f( GLenum texture, GLfloat s, GLfloat t );
|
||||
void GL_SetTexCoordArrayMode( GLenum mode );
|
||||
void GL_LoadTexMatrix( const matrix4x4 m );
|
||||
void GL_LoadTexMatrixExt( const float *glmatrix );
|
||||
void GL_LoadMatrix( const matrix4x4 source );
|
||||
void GL_TexGen( GLenum coord, GLenum mode );
|
||||
void GL_SelectTexture( GLint texture );
|
||||
void GL_CleanupAllTextureUnits( void );
|
||||
void GL_LoadIdentityTexMatrix( void );
|
||||
void GL_DisableAllTexGens( void );
|
||||
void GL_SetRenderMode( int mode );
|
||||
void GL_TextureTarget( uint target );
|
||||
void GL_Cull( GLenum cull );
|
||||
void R_ShowTextures( void );
|
||||
void SCR_TimeRefresh_f( void );
|
||||
|
||||
//
|
||||
// gu_beams.c
|
||||
//
|
||||
void CL_DrawBeams( int fTrans, BEAM *active_beams );
|
||||
qboolean R_BeamCull( const vec3_t start, const vec3_t end, qboolean pvsOnly );
|
||||
|
||||
//
|
||||
// gu_cull.c
|
||||
//
|
||||
int R_CullModel( cl_entity_t *e, const vec3_t absmin, const vec3_t absmax );
|
||||
qboolean R_CullBox( const vec3_t mins, const vec3_t maxs );
|
||||
qboolean R_CullSphere( const vec3_t centre, const float radius );
|
||||
int R_CullSurface( msurface_t *surf, gl_frustum_t *frustum, uint clipflags );
|
||||
|
||||
//
|
||||
// gu_decals.c
|
||||
//
|
||||
void DrawSurfaceDecals( msurface_t *fa, qboolean single, qboolean reverse );
|
||||
float *R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int texture, int *outCount );
|
||||
void DrawSingleDecal( decal_t *pDecal, msurface_t *fa );
|
||||
void R_EntityRemoveDecals( model_t *mod );
|
||||
void DrawDecalsBatch( void );
|
||||
void R_ClearDecals( void );
|
||||
|
||||
//
|
||||
// gu_draw.c
|
||||
//
|
||||
void R_Set2DMode( qboolean enable );
|
||||
void R_DrawTileClear( int texnum, int x, int y, int w, int h );
|
||||
void R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, const byte *data );
|
||||
|
||||
//
|
||||
// gu_drawhulls.c
|
||||
//
|
||||
void R_DrawWorldHull( void );
|
||||
void R_DrawModelHull( void );
|
||||
|
||||
//
|
||||
// gu_image.c
|
||||
//
|
||||
gl_texture_t *R_GetTexture( GLenum texnum );
|
||||
#define GL_LoadTextureInternal( name, pic, flags ) GL_LoadTextureFromBuffer( name, pic, flags, false )
|
||||
#define GL_UpdateTextureInternal( name, pic, flags ) GL_LoadTextureFromBuffer( name, pic, flags, true )
|
||||
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags );
|
||||
int GL_LoadTextureArray( const char **names, int flags );
|
||||
int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update );
|
||||
byte *GL_ResampleTexture( const byte *source, int in_w, int in_h, int out_w, int out_h, qboolean isNormalMap );
|
||||
#define PC_SWF( X ) ( ( X ) | ( 1 << 15 ) )
|
||||
#define PC_HWF( X ) ( X )
|
||||
void GL_PixelConverter( byte *dst, const byte *src, int size, int inFormat, int outFormat );
|
||||
int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags );
|
||||
int GL_CreateTextureArray( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags );
|
||||
void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor );
|
||||
qboolean GL_UpdateTexture( int texnum, int xoff, int yoff, int width, int height, const void *buffer );
|
||||
void GL_UpdateTexSize( int texnum, int width, int height, int depth );
|
||||
int GL_FindTexture( const char *name );
|
||||
void GL_FreeTexture( GLenum texnum );
|
||||
const char *GL_Target( GLenum target );
|
||||
void R_InitDlightTexture( void );
|
||||
void R_TextureList_f( void );
|
||||
void R_InitImages( void );
|
||||
void R_ShutdownImages( void );
|
||||
int GL_TexMemory( void );
|
||||
|
||||
//
|
||||
// gu_rlight.c
|
||||
//
|
||||
void CL_RunLightStyles( void );
|
||||
void R_PushDlights( void );
|
||||
void R_AnimateLight( void );
|
||||
void R_GetLightSpot( vec3_t lightspot );
|
||||
void R_MarkLights( dlight_t *light, int bit, mnode_t *node );
|
||||
colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lightspot, vec3_t lightvec );
|
||||
int R_CountSurfaceDlights( msurface_t *surf );
|
||||
colorVec R_LightPoint( const vec3_t p0 );
|
||||
int R_CountDlights( void );
|
||||
|
||||
//
|
||||
// gu_rmain.c
|
||||
//
|
||||
void R_ClearScene( void );
|
||||
void R_LoadIdentity( void );
|
||||
void R_RenderScene( void );
|
||||
void R_DrawCubemapView( const vec3_t origin, const vec3_t angles, int size );
|
||||
void R_SetupRefParams( const struct ref_viewpass_s *rvp );
|
||||
void R_TranslateForEntity( cl_entity_t *e );
|
||||
void R_RotateForEntity( cl_entity_t *e );
|
||||
void R_SetupGL( qboolean set_gl_state );
|
||||
void R_AllowFog( qboolean allowed );
|
||||
void R_SetupFrustum( void );
|
||||
void R_FindViewLeaf( void );
|
||||
void R_CheckGamma( void );
|
||||
void R_PushScene( void );
|
||||
void R_PopScene( void );
|
||||
void R_DrawFog( void );
|
||||
int CL_FxBlend( cl_entity_t *e );
|
||||
|
||||
//
|
||||
// gu_rmath.c
|
||||
//
|
||||
void Matrix4x4_ToFMatrix4( const matrix4x4 in, ScePspFMatrix4 *out );
|
||||
void Matrix4x4_FromFMatrix4( matrix4x4 out, ScePspFMatrix4 *in );
|
||||
void Matrix4x4_Concat( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 );
|
||||
void Matrix4x4_ConcatTranslate( matrix4x4 out, float x, float y, float z );
|
||||
void Matrix4x4_ConcatRotate( matrix4x4 out, float angle, float x, float y, float z );
|
||||
void Matrix4x4_ConcatScale( matrix4x4 out, float x );
|
||||
void Matrix4x4_ConcatScale3( matrix4x4 out, float x, float y, float z );
|
||||
void Matrix4x4_CreateTranslate( matrix4x4 out, float x, float y, float z );
|
||||
void Matrix4x4_CreateRotate( matrix4x4 out, float angle, float x, float y, float z );
|
||||
void Matrix4x4_CreateScale( matrix4x4 out, float x );
|
||||
void Matrix4x4_CreateScale3( matrix4x4 out, float x, float y, float z );
|
||||
void Matrix4x4_CreateProjection(matrix4x4 out, float xMax, float xMin, float yMax, float yMin, float zNear, float zFar);
|
||||
void Matrix4x4_CreateOrtho(matrix4x4 m, float xLeft, float xRight, float yBottom, float yTop, float zNear, float zFar);
|
||||
void Matrix4x4_CreateModelview( matrix4x4 out );
|
||||
|
||||
//
|
||||
// gu_rmisc.c
|
||||
//
|
||||
void R_ClearStaticEntities( void );
|
||||
|
||||
//
|
||||
// gu_rsurf.c
|
||||
//
|
||||
void R_MarkLeaves( void );
|
||||
void R_DrawWorld( void );
|
||||
void R_DrawWaterSurfaces( void );
|
||||
void R_DrawBrushModel( cl_entity_t *e );
|
||||
void GL_SubdivideSurface( msurface_t *fa );
|
||||
void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa );
|
||||
void DrawGLPoly( glpoly_t *p, float xScale, float yScale );
|
||||
texture_t *R_TextureAnimation( msurface_t *s );
|
||||
void GL_SetupFogColorForSurfaces( void );
|
||||
void R_DrawAlphaTextureChains( void );
|
||||
void GL_RebuildLightmaps( void );
|
||||
void GL_InitRandomTable( void );
|
||||
void GL_BuildLightmaps( void );
|
||||
void GL_ResetFogColor( void );
|
||||
void R_GenerateVBO( void );
|
||||
void R_ClearVBO( void );
|
||||
void R_AddDecalVBO( decal_t *pdecal, msurface_t *surf );
|
||||
|
||||
//
|
||||
// gu_rpart.c
|
||||
//
|
||||
void CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, float frametime );
|
||||
void CL_DrawParticles( double frametime, particle_t *cl_active_particles, float partsize );
|
||||
void CL_DrawTracers( double frametime, particle_t *cl_active_tracers );
|
||||
|
||||
|
||||
//
|
||||
// gu_sprite.c
|
||||
//
|
||||
void R_SpriteInit( void );
|
||||
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags );
|
||||
mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw );
|
||||
void R_DrawSpriteModel( cl_entity_t *e );
|
||||
|
||||
//
|
||||
// gu_studio.c
|
||||
//
|
||||
void R_StudioInit( void );
|
||||
void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded );
|
||||
void R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t angles );
|
||||
float CL_GetSequenceDuration( cl_entity_t *ent, int sequence );
|
||||
struct mstudiotex_s *R_StudioGetTexture( cl_entity_t *e );
|
||||
float CL_GetStudioEstimatedFrame( cl_entity_t *ent );
|
||||
int R_GetEntityRenderMode( cl_entity_t *ent );
|
||||
void R_DrawStudioModel( cl_entity_t *e );
|
||||
player_info_t *pfnPlayerInfo( int index );
|
||||
void R_GatherPlayerLight( void );
|
||||
float R_StudioEstimateFrame( cl_entity_t *e, mstudioseqdesc_t *pseqdesc );
|
||||
void R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t angles );
|
||||
void R_StudioResetPlayerModels( void );
|
||||
void CL_InitStudioAPI( void );
|
||||
void Mod_StudioLoadTextures( model_t *mod, void *data );
|
||||
void Mod_StudioUnloadTextures( void *data );
|
||||
|
||||
//
|
||||
// gu_alias.c
|
||||
//
|
||||
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded );
|
||||
void R_DrawAliasModel( cl_entity_t *e );
|
||||
void R_AliasInit( void );
|
||||
|
||||
//
|
||||
// gu_warp.c
|
||||
//
|
||||
void R_InitSkyClouds( mip_t *mt, struct texture_s *tx, qboolean custom_palette );
|
||||
void R_AddSkyBoxSurface( msurface_t *fa );
|
||||
void R_ClearSkyBox( void );
|
||||
void R_DrawSkyBox( void );
|
||||
void R_DrawClouds( void );
|
||||
void EmitWaterPolys( msurface_t *warp, qboolean reverse );
|
||||
|
||||
//
|
||||
// gu_vgui.c
|
||||
//
|
||||
void VGUI_DrawInit( void );
|
||||
void VGUI_DrawShutdown( void );
|
||||
void VGUI_SetupDrawingText( int *pColor );
|
||||
void VGUI_SetupDrawingRect( int *pColor );
|
||||
void VGUI_SetupDrawingImage( int *pColor );
|
||||
void VGUI_BindTexture( int id );
|
||||
void VGUI_EnableTexture( qboolean enable );
|
||||
void VGUI_CreateTexture( int id, int width, int height );
|
||||
void VGUI_UploadTexture( int id, const char *buffer, int width, int height );
|
||||
void VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight );
|
||||
void VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr );
|
||||
void VGUI_GetTextureSizes( int *width, int *height );
|
||||
int VGUI_GenerateTexture( void );
|
||||
|
||||
//#include "vid_common.h"
|
||||
|
||||
//
|
||||
// renderer exports
|
||||
//
|
||||
qboolean R_Init( void );
|
||||
void R_Shutdown( void );
|
||||
void GL_SetupAttributes( int safegl );
|
||||
void GL_OnContextCreated( void );
|
||||
void GL_InitExtensions( void );
|
||||
void GL_ClearExtensions( void );
|
||||
void VID_CheckChanges( void );
|
||||
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags );
|
||||
void GL_FreeImage( const char *name );
|
||||
qboolean VID_ScreenShot( const char *filename, int shot_type );
|
||||
qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot );
|
||||
void R_BeginFrame( qboolean clearScene );
|
||||
void R_RenderFrame( const struct ref_viewpass_s *vp );
|
||||
void R_EndFrame( void );
|
||||
void R_ClearScene( void );
|
||||
void R_GetTextureParms( int *w, int *h, int texnum );
|
||||
void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int curFrame, const struct model_s *pSprite );
|
||||
void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty );
|
||||
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum );
|
||||
qboolean R_SpeedsMessage( char *out, size_t size );
|
||||
void R_SetupSky( const char *skyboxname );
|
||||
qboolean R_CullBox( const vec3_t mins, const vec3_t maxs );
|
||||
int R_WorldToScreen( const vec3_t point, vec3_t screen );
|
||||
void R_ScreenToWorld( const vec3_t screen, vec3_t point );
|
||||
qboolean R_AddEntity( struct cl_entity_s *pRefEntity, int entityType );
|
||||
void Mod_LoadMapSprite( struct model_s *mod, const void *buffer, size_t size, qboolean *loaded );
|
||||
void Mod_SpriteUnloadTextures( void *data );
|
||||
void Mod_UnloadAliasModel( struct model_s *mod );
|
||||
void Mod_AliasUnloadTextures( void *data );
|
||||
void GL_SetRenderMode( int mode );
|
||||
void GL_SetColor4ub( byte r, byte g, byte b, byte a );
|
||||
void R_RunViewmodelEvents( void );
|
||||
void R_DrawViewModel( void );
|
||||
int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame );
|
||||
void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale );
|
||||
void R_RemoveEfrags( struct cl_entity_s *ent );
|
||||
void R_AddEfrags( struct cl_entity_s *ent );
|
||||
void R_DecalRemoveAll( int texture );
|
||||
int R_CreateDecalList( decallist_t *pList );
|
||||
void R_ClearAllDecals( void );
|
||||
byte *Mod_GetCurrentVis( void );
|
||||
void Mod_SetOrthoBounds( const float *mins, const float *maxs );
|
||||
void R_NewMap( void );
|
||||
void CL_AddCustomBeam( cl_entity_t *pEnvBeam );
|
||||
|
||||
//
|
||||
// gu_opengl.c
|
||||
//
|
||||
|
||||
//
|
||||
// gu_triapi.c
|
||||
//
|
||||
void TriRenderMode( int mode );
|
||||
void TriBegin( int mode );
|
||||
void TriEnd( void );
|
||||
void TriTexCoord2f( float u, float v );
|
||||
void TriVertex3fv( const float *v );
|
||||
void TriVertex3f( float x, float y, float z );
|
||||
void TriColor4f( float r, float g, float b, float a );
|
||||
void TriColor4ub( byte r, byte g, byte b, byte a );
|
||||
void TriBrightness( float brightness );
|
||||
int TriWorldToScreen( const float *world, float *screen );
|
||||
int TriSpriteTexture( model_t *pSpriteModel, int frame );
|
||||
void TriFog( float flFogColor[3], float flStart, float flEnd, int bOn );
|
||||
void TriGetMatrix( const int pname, float *matrix );
|
||||
void TriFogParams( float flDensity, int iFogSkybox );
|
||||
void TriCullFace( TRICULLSTYLE mode );
|
||||
uint getTriBrightness( float brightness );
|
||||
int TriBoxInPVS( float *mins, float *maxs );
|
||||
void TriLightAtPoint( float *pos, float *value );
|
||||
void TriColor4fRendermode( float r, float g, float b, float a, int rendermode );
|
||||
int getTriAPI( int version, triangleapi_t *api );
|
||||
|
||||
//
|
||||
// gu_clipping.c
|
||||
//
|
||||
#define CLIPPING_DEBUGGING 0
|
||||
void GU_ClipSetWorldFrustum( const matrix4x4 in );
|
||||
void GU_ClipRestoreWorldFrustum( void );
|
||||
void GU_ClipSetModelFrustum( const matrix4x4 in );
|
||||
void GU_ClipLoadFrustum( const mplane_t *plane ); // Experimental
|
||||
int GU_ClipIsRequired( gu_vert_t* uv, int uvc );
|
||||
void GU_Clip( gu_vert_t *uv, int uvc, gu_vert_t **cv, int* cvc );
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
GL STATE MACHINE
|
||||
|
||||
=======================================================================
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int max_texture_size;
|
||||
qboolean softwareGammaUpdate;
|
||||
} glconfig_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
int width, height;
|
||||
int activeTMU;
|
||||
GLint currentTexture;
|
||||
GLboolean texIdentityMatrix;
|
||||
GLint isFogEnabled;
|
||||
|
||||
int faceCull;
|
||||
|
||||
qboolean stencilEnabled;
|
||||
qboolean in2DMode;
|
||||
|
||||
uint fogColor;
|
||||
float fogDensity;
|
||||
float fogStart;
|
||||
float fogEnd;
|
||||
} glstate_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
qboolean initialized; // OpenGL subsystem started
|
||||
qboolean extended; // extended context allows to GL_Debug
|
||||
} glwstate_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int screen_width;
|
||||
int screen_height;
|
||||
int buffer_width;
|
||||
int buffer_format;
|
||||
int buffer_bpp;
|
||||
void *draw_buffer;
|
||||
void *disp_buffer;
|
||||
void *depth_buffer;
|
||||
void *context_list;
|
||||
size_t context_list_size;
|
||||
}gurender_t;
|
||||
|
||||
extern glconfig_t glConfig;
|
||||
extern glstate_t glState;
|
||||
extern gurender_t guRender;
|
||||
// move to engine
|
||||
extern glwstate_t glw_state;
|
||||
extern ref_api_t gEngfuncs;
|
||||
extern ref_globals_t *gpGlobals;
|
||||
|
||||
#define ENGINE_GET_PARM_ (*gEngfuncs.EngineGetParm)
|
||||
#define ENGINE_GET_PARM( parm ) ENGINE_GET_PARM_( ( parm ), 0 )
|
||||
|
||||
//
|
||||
// renderer cvars
|
||||
//
|
||||
extern cvar_t *gl_texture_lodfunc;
|
||||
extern cvar_t *gl_texture_lodbias;
|
||||
extern cvar_t *gl_texture_lodslope;
|
||||
extern cvar_t *gl_texture_nearest;
|
||||
extern cvar_t *gl_lightmap_nearest;
|
||||
extern cvar_t *gl_keeptjunctions;
|
||||
extern cvar_t *gl_emboss_scale;
|
||||
extern cvar_t *gl_round_down;
|
||||
extern cvar_t *gl_detailscale;
|
||||
extern cvar_t *gl_wireframe;
|
||||
extern cvar_t *gl_depthoffset;
|
||||
extern cvar_t *gl_clear;
|
||||
extern cvar_t *gl_test; // cvar to testify new effects
|
||||
extern cvar_t *gl_subdivide_size;
|
||||
|
||||
extern cvar_t *r_speeds;
|
||||
extern cvar_t *r_fullbright;
|
||||
extern cvar_t *r_norefresh;
|
||||
extern cvar_t *r_lighting_extended;
|
||||
extern cvar_t *r_lighting_modulate;
|
||||
extern cvar_t *r_lighting_ambient;
|
||||
extern cvar_t *r_studio_lambert;
|
||||
extern cvar_t *r_detailtextures;
|
||||
extern cvar_t *r_drawentities;
|
||||
extern cvar_t *r_decals;
|
||||
extern cvar_t *r_novis;
|
||||
extern cvar_t *r_nocull;
|
||||
extern cvar_t *r_lockpvs;
|
||||
extern cvar_t *r_lockfrustum;
|
||||
extern cvar_t *r_traceglow;
|
||||
extern cvar_t *r_dynamic;
|
||||
extern cvar_t *r_lightmap;
|
||||
|
||||
extern cvar_t *vid_brightness;
|
||||
extern cvar_t *vid_gamma;
|
||||
|
||||
//
|
||||
// engine shared convars
|
||||
//
|
||||
extern cvar_t *gl_showtextures;
|
||||
extern cvar_t *tracerred;
|
||||
extern cvar_t *tracergreen;
|
||||
extern cvar_t *tracerblue;
|
||||
extern cvar_t *traceralpha;
|
||||
extern cvar_t *cl_lightstyle_lerping;
|
||||
extern cvar_t *r_showhull;
|
||||
extern cvar_t *r_fast_particles;
|
||||
|
||||
//
|
||||
// engine callbacks
|
||||
//
|
||||
#include "crtlib.h"
|
||||
|
||||
#define Mem_Malloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||
#define Mem_Calloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Realloc( pool, ptr, size ) gEngfuncs._Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ )
|
||||
#define Mem_Free( mem ) gEngfuncs._Mem_Free( mem, __FILE__, __LINE__ )
|
||||
#define Mem_AllocPool( name ) gEngfuncs._Mem_AllocPool( name, __FILE__, __LINE__ )
|
||||
#define Mem_FreePool( pool ) gEngfuncs._Mem_FreePool( pool, __FILE__, __LINE__ )
|
||||
#define Mem_EmptyPool( pool ) gEngfuncs._Mem_EmptyPool( pool, __FILE__, __LINE__ )
|
||||
|
||||
#endif // GL_LOCAL_H
|
||||
477
ref_gu/gu_render.c
Normal file
477
ref_gu/gu_render.c
Normal file
@@ -0,0 +1,477 @@
|
||||
/*
|
||||
gu_render.c - render initialization
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
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.
|
||||
*/
|
||||
#include "gu_local.h"
|
||||
|
||||
cvar_t *gl_texture_lodfunc;
|
||||
cvar_t *gl_texture_lodbias;
|
||||
cvar_t *gl_texture_lodslope;
|
||||
|
||||
cvar_t *gl_texture_nearest;
|
||||
cvar_t *gl_lightmap_nearest;
|
||||
cvar_t *gl_keeptjunctions;
|
||||
cvar_t *gl_emboss_scale;
|
||||
cvar_t *gl_detailscale;
|
||||
cvar_t *gl_depthoffset;
|
||||
cvar_t *gl_wireframe;
|
||||
cvar_t *gl_vsync;
|
||||
cvar_t *gl_clear;
|
||||
cvar_t *gl_test;
|
||||
cvar_t *gl_subdivide_size;
|
||||
cvar_t *r_speeds;
|
||||
cvar_t *r_fullbright;
|
||||
cvar_t *r_norefresh;
|
||||
cvar_t *r_lighting_extended;
|
||||
cvar_t *r_lighting_modulate;
|
||||
cvar_t *r_lighting_ambient;
|
||||
cvar_t *r_detailtextures;
|
||||
cvar_t *r_drawentities;
|
||||
cvar_t *r_adjust_fov;
|
||||
cvar_t *r_decals;
|
||||
cvar_t *r_novis;
|
||||
cvar_t *r_nocull;
|
||||
cvar_t *r_lockpvs;
|
||||
cvar_t *r_lockfrustum;
|
||||
cvar_t *r_traceglow;
|
||||
cvar_t *r_dynamic;
|
||||
cvar_t *r_lightmap;
|
||||
cvar_t *r_showhull;
|
||||
cvar_t *r_fast_particles;
|
||||
cvar_t *gl_round_down;
|
||||
cvar_t *gl_showtextures;
|
||||
cvar_t *cl_lightstyle_lerping;
|
||||
|
||||
cvar_t *vid_brightness;
|
||||
cvar_t *vid_gamma;
|
||||
cvar_t *tracerred;
|
||||
cvar_t *tracergreen;
|
||||
cvar_t *tracerblue;
|
||||
cvar_t *traceralpha;
|
||||
|
||||
byte *r_temppool;
|
||||
|
||||
gl_globals_t tr;
|
||||
glconfig_t glConfig;
|
||||
glstate_t glState;
|
||||
glwstate_t glw_state;
|
||||
gurender_t guRender;
|
||||
|
||||
// Set frame buffer
|
||||
#define PSP_FB_WIDTH 480
|
||||
#define PSP_FB_HEIGHT 272
|
||||
#define PSP_FB_BWIDTH 512
|
||||
#define PSP_FB_FORMAT GU_PSM_5650 //4444,5551,5650,8888
|
||||
|
||||
#if PSP_FB_FORMAT == GU_PSM_4444
|
||||
#define PSP_FB_BPP 2
|
||||
#elif PSP_FB_FORMAT == GU_PSM_5551
|
||||
#define PSP_FB_BPP 2
|
||||
#elif PSP_FB_FORMAT == GU_PSM_5650
|
||||
#define PSP_FB_BPP 2
|
||||
#elif PSP_FB_FORMAT == GU_PSM_8888
|
||||
#define PSP_FB_BPP 4
|
||||
#endif
|
||||
|
||||
#define PSP_GU_LIST_SIZE 0x100000 // 1Mb
|
||||
|
||||
static byte context_list[PSP_GU_LIST_SIZE] __attribute__( ( aligned( 64 ) ) );
|
||||
|
||||
/*
|
||||
===============
|
||||
GU_Init
|
||||
===============
|
||||
*/
|
||||
static void GU_Init( void )
|
||||
{
|
||||
memset( &guRender, 0, sizeof( guRender ));
|
||||
|
||||
guRender.screen_width = PSP_FB_WIDTH;
|
||||
guRender.screen_height = PSP_FB_HEIGHT;
|
||||
guRender.buffer_width = PSP_FB_BWIDTH;
|
||||
guRender.buffer_format = PSP_FB_FORMAT;
|
||||
guRender.buffer_bpp = PSP_FB_BPP;
|
||||
|
||||
guRender.draw_buffer = ( void* )valloc( guRender.buffer_width * guRender.screen_height * guRender.buffer_bpp );
|
||||
if( !guRender.draw_buffer )
|
||||
gEngfuncs.Host_Error( "Memory allocation failled! (guRender.draw_buffer)\n" );
|
||||
|
||||
guRender.disp_buffer = ( void* )valloc( guRender.buffer_width * guRender.screen_height * guRender.buffer_bpp );
|
||||
if( !guRender.disp_buffer )
|
||||
gEngfuncs.Host_Error( "Memory allocation failled! (guRender.disp_buffer)\n" );
|
||||
|
||||
guRender.depth_buffer = ( void* )valloc( guRender.buffer_width * guRender.screen_height * guRender.buffer_bpp );
|
||||
if( !guRender.depth_buffer )
|
||||
gEngfuncs.Host_Error( "Memory allocation failled! (guRender.depth_buffer)\n" );
|
||||
|
||||
guRender.context_list = context_list;
|
||||
guRender.context_list_size = sizeof( context_list );
|
||||
|
||||
// Initialise the GU.
|
||||
sceGuInit();
|
||||
|
||||
// Set up the GU.
|
||||
sceGuStart( GU_DIRECT, guRender.context_list );
|
||||
|
||||
sceGuDrawBuffer( guRender.buffer_format, vrelptr( guRender.draw_buffer ), guRender.buffer_width );
|
||||
sceGuDispBuffer( guRender.screen_width, guRender.screen_height, vrelptr( guRender.disp_buffer ), guRender.buffer_width );
|
||||
sceGuDepthBuffer( vrelptr( guRender.depth_buffer ), guRender.buffer_width );
|
||||
|
||||
// Set the rendering offset and viewport.
|
||||
sceGuOffset( 2048 - ( guRender.screen_width / 2 ), 2048 - ( guRender.screen_height / 2 ) );
|
||||
sceGuViewport( 2048, 2048, guRender.screen_width, guRender.screen_height );
|
||||
|
||||
// Set up scissoring.
|
||||
sceGuEnable( GU_SCISSOR_TEST );
|
||||
sceGuScissor( 0, 0, guRender.screen_width, guRender.screen_height );
|
||||
|
||||
// Xash default
|
||||
sceGuClearColor( GU_COLOR( 0.5f, 0.5f, 0.5f, 1.0f ) );
|
||||
|
||||
sceGuEnable( GU_DEPTH_TEST );
|
||||
sceGuDisable( GU_CULL_FACE );
|
||||
sceGuEnable( GU_CLIP_PLANES );
|
||||
sceGuDepthFunc( GU_LEQUAL );
|
||||
sceGuColor( 0xffffffff );
|
||||
|
||||
// Set up stencil
|
||||
if( glState.stencilEnabled )
|
||||
{
|
||||
sceGuDisable( GU_STENCIL_TEST );
|
||||
/*pglStencilMask( ( GLuint ) ~0 );*/ // alpha color sceGuPixelMask
|
||||
sceGuStencilFunc( GU_EQUAL, 0, ~0 );
|
||||
sceGuStencilOp( GU_KEEP, GU_INCR, GU_INCR );
|
||||
}
|
||||
|
||||
sceGuDepthRange( 0, 65535 );
|
||||
sceGuDepthOffset( 0 );
|
||||
|
||||
sceGuDisable( GU_BLEND );
|
||||
sceGuDisable( GU_ALPHA_TEST );
|
||||
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
||||
sceGuAlphaFunc( GU_GREATER, DEFAULT_ALPHATEST, 0xff );
|
||||
sceGuEnable( GU_TEXTURE_2D );
|
||||
sceGuShadeModel( GU_SMOOTH );
|
||||
sceGuFrontFace( GU_CCW );
|
||||
|
||||
// Set the default matrices.
|
||||
sceGumMatrixMode( GU_PROJECTION );
|
||||
sceGumLoadIdentity();
|
||||
sceGumMatrixMode( GU_VIEW );
|
||||
sceGumLoadIdentity();
|
||||
sceGumMatrixMode( GU_MODEL );
|
||||
sceGumLoadIdentity();
|
||||
sceGumMatrixMode( GU_TEXTURE );
|
||||
sceGumLoadIdentity();
|
||||
|
||||
sceGumUpdateMatrix();
|
||||
|
||||
sceGuFinish();
|
||||
sceGuSync( GU_SYNC_FINISH, GU_SYNC_WAIT );
|
||||
|
||||
// Turn on the display.
|
||||
sceDisplayWaitVblankStart();
|
||||
sceGuDisplay(GU_TRUE);
|
||||
|
||||
// Start a new render.
|
||||
sceGuStart( GU_DIRECT, guRender.context_list );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
GU_Shutdown
|
||||
===============
|
||||
*/
|
||||
static void GU_Shutdown( void )
|
||||
{
|
||||
// Finish rendering.
|
||||
sceGuFinish();
|
||||
sceGuSync( GU_SYNC_FINISH, GU_SYNC_WAIT );
|
||||
|
||||
// Shut down the display.
|
||||
sceGuTerm();
|
||||
|
||||
// Free the buffers.
|
||||
if( guRender.draw_buffer )
|
||||
vfree( guRender.draw_buffer );
|
||||
if( guRender.disp_buffer )
|
||||
vfree( guRender.disp_buffer );
|
||||
if( guRender.depth_buffer )
|
||||
vfree( guRender.depth_buffer );
|
||||
|
||||
guRender.draw_buffer = NULL;
|
||||
guRender.disp_buffer = NULL;
|
||||
guRender.depth_buffer = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
GL_GetProcAddress
|
||||
|
||||
defined just for nanogl/glwes, so it don't link to SDL2 directly, nor use dlsym
|
||||
==============
|
||||
*/
|
||||
void GAME_EXPORT *GL_GetProcAddress( const char *name )
|
||||
{
|
||||
return gEngfuncs.GL_GetProcAddress( name );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
GL_SetDefaultState
|
||||
===============
|
||||
*/
|
||||
static void GL_SetDefaultState( void )
|
||||
{
|
||||
memset( &glState, 0, sizeof( glState ));
|
||||
|
||||
// init draw stack
|
||||
tr.draw_list = &tr.draw_stack[0];
|
||||
tr.draw_stack_pos = 0;
|
||||
|
||||
// init glState struct
|
||||
glState.currentTexture = -1;
|
||||
glState.texIdentityMatrix = true;
|
||||
glState.fogColor = 0;
|
||||
glState.fogDensity = 0;
|
||||
glState.fogStart = 100.0f;
|
||||
glState.fogEnd = 1000.0f;
|
||||
}
|
||||
#if 0
|
||||
/*
|
||||
===============
|
||||
GL_SetDefaults
|
||||
===============
|
||||
*/
|
||||
static void GU_SetDefaults( void )
|
||||
{
|
||||
pglFinish();
|
||||
|
||||
pglClearColor( 0.5f, 0.5f, 0.5f, 1.0f );
|
||||
|
||||
pglDisable( GL_DEPTH_TEST );
|
||||
pglDisable( GL_CULL_FACE );
|
||||
pglDisable( GL_SCISSOR_TEST );
|
||||
pglDepthFunc( GL_LEQUAL );
|
||||
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
|
||||
if( glState.stencilEnabled )
|
||||
{
|
||||
pglDisable( GL_STENCIL_TEST );
|
||||
pglStencilMask( ( GLuint ) ~0 );
|
||||
pglStencilFunc( GL_EQUAL, 0, ~0 );
|
||||
pglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
|
||||
}
|
||||
|
||||
pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||
pglPolygonOffset( -1.0f, -2.0f );
|
||||
|
||||
GL_CleanupAllTextureUnits();
|
||||
|
||||
pglDisable( GL_BLEND );
|
||||
pglDisable( GL_ALPHA_TEST );
|
||||
pglDisable( GL_POLYGON_OFFSET_FILL );
|
||||
pglAlphaFunc( GL_GREATER, DEFAULT_ALPHATEST );
|
||||
pglEnable( GL_TEXTURE_2D );
|
||||
pglShadeModel( GL_SMOOTH );
|
||||
pglFrontFace( GL_CCW );
|
||||
|
||||
pglPointSize( 1.2f );
|
||||
pglLineWidth( 1.2f );
|
||||
|
||||
GL_Cull( GL_NONE );
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
=================
|
||||
R_RenderInfo_f
|
||||
=================
|
||||
*/
|
||||
void R_RenderInfo_f( void )
|
||||
{
|
||||
gEngfuncs.Con_Printf( "\n" );
|
||||
gEngfuncs.Con_Printf( "HARDWARE RENDER\n");
|
||||
gEngfuncs.Con_Printf( "MAX_TEXTURE_SIZE: %i\n", glConfig.max_texture_size );
|
||||
gEngfuncs.Con_Printf( "MODE: %ix%i\n", gpGlobals->width, gpGlobals->height );
|
||||
gEngfuncs.Con_Printf( "VERTICAL SYNC: %s\n", gl_vsync->value ? "enabled" : "disabled" );
|
||||
gEngfuncs.Con_Printf( "VRAM AVAILABLE: %i\n", vmemavail() );
|
||||
}
|
||||
|
||||
void GL_InitExtensions( void )
|
||||
{
|
||||
glState.stencilEnabled = true;
|
||||
glConfig.max_texture_size = 256;
|
||||
|
||||
// get our various GL strings
|
||||
gEngfuncs.Con_Reportf( "^3Video^7: PSP HW\n" );
|
||||
|
||||
gEngfuncs.Cvar_Get( "gl_max_size", va( "%i", glConfig.max_texture_size ), 0, "opengl texture max dims" );
|
||||
/*
|
||||
gEngfuncs.Image_AddCmdFlags( IL_DDS_HARDWARE );
|
||||
*/
|
||||
R_RenderInfo_f();
|
||||
|
||||
tr.framecount = tr.visframecount = 1;
|
||||
glw_state.initialized = true;
|
||||
}
|
||||
|
||||
void GL_ClearExtensions( void )
|
||||
{
|
||||
// now all extensions are disabled
|
||||
glw_state.initialized = false;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_InitCommands
|
||||
=================
|
||||
*/
|
||||
void GL_InitCommands( void )
|
||||
{
|
||||
r_speeds = gEngfuncs.Cvar_Get( "r_speeds", "0", FCVAR_ARCHIVE, "shows renderer speeds" );
|
||||
r_fullbright = gEngfuncs.Cvar_Get( "r_fullbright", "0", FCVAR_CHEAT, "disable lightmaps, get fullbright for entities" );
|
||||
r_norefresh = gEngfuncs.Cvar_Get( "r_norefresh", "0", 0, "disable 3D rendering (use with caution)" );
|
||||
r_lighting_extended = gEngfuncs.Cvar_Get( "r_lighting_extended", "0", FCVAR_ARCHIVE, "allow to get lighting from world and bmodels" ); // disabled
|
||||
r_lighting_modulate = gEngfuncs.Cvar_Get( "r_lighting_modulate", "0.6", FCVAR_ARCHIVE, "lightstyles modulate scale" );
|
||||
r_lighting_ambient = gEngfuncs.Cvar_Get( "r_lighting_ambient", "0.3", FCVAR_ARCHIVE, "map ambient lighting scale" );
|
||||
r_novis = gEngfuncs.Cvar_Get( "r_novis", "0", 0, "ignore vis information (perfomance test)" );
|
||||
r_nocull = gEngfuncs.Cvar_Get( "r_nocull", "0", 0, "ignore frustrum culling (perfomance test)" );
|
||||
r_detailtextures = gEngfuncs.Cvar_Get( "r_detailtextures", "0", FCVAR_ARCHIVE, "enable detail textures support, use '2' for autogenerate detail.txt" ); // disabled
|
||||
r_lockpvs = gEngfuncs.Cvar_Get( "r_lockpvs", "0", FCVAR_CHEAT, "lockpvs area at current point (pvs test)" );
|
||||
r_lockfrustum = gEngfuncs.Cvar_Get( "r_lockfrustum", "0", FCVAR_CHEAT, "lock frustrum area at current point (cull test)" );
|
||||
r_dynamic = gEngfuncs.Cvar_Get( "r_dynamic", "1", FCVAR_ARCHIVE, "allow dynamic lighting (dlights, lightstyles)" );
|
||||
r_traceglow = gEngfuncs.Cvar_Get( "r_traceglow", "0", FCVAR_ARCHIVE, "cull flares behind models" ); // disabled
|
||||
r_lightmap = gEngfuncs.Cvar_Get( "r_lightmap", "0", FCVAR_CHEAT, "lightmap debugging tool" );
|
||||
r_drawentities = gEngfuncs.Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT, "render entities" );
|
||||
r_decals = gEngfuncs.pfnGetCvarPointer( "r_decals", 0 );
|
||||
r_showhull = gEngfuncs.pfnGetCvarPointer( "r_showhull", 0 );
|
||||
r_fast_particles = gEngfuncs.Cvar_Get( "r_fast_particles", "1", FCVAR_ARCHIVE, "use GU_POINTS for particles" );
|
||||
|
||||
gl_texture_nearest = gEngfuncs.Cvar_Get( "gl_texture_nearest", "0", FCVAR_GLCONFIG, "disable texture filter" );
|
||||
gl_lightmap_nearest = gEngfuncs.Cvar_Get( "gl_lightmap_nearest", "0", FCVAR_GLCONFIG, "disable lightmap filter" );
|
||||
gl_vsync = gEngfuncs.pfnGetCvarPointer( "gl_vsync", 0 );
|
||||
gl_detailscale = gEngfuncs.Cvar_Get( "gl_detailscale", "4.0", FCVAR_GLCONFIG, "default scale applies while auto-generate list of detail textures" );
|
||||
gl_texture_lodfunc = gEngfuncs.Cvar_Get( "gl_texture_lodfunc", "2", FCVAR_GLCONFIG, "LOD func for mipmapped textures" );
|
||||
gl_texture_lodbias = gEngfuncs.Cvar_Get( "gl_texture_lodbias", "-6.0", FCVAR_GLCONFIG, "LOD bias for mipmapped textures (perfomance|quality)" );
|
||||
gl_texture_lodslope = gEngfuncs.Cvar_Get( "gl_texture_lodslope", "0.3", FCVAR_GLCONFIG, "LOD slope for mipmapped textures" );
|
||||
gl_keeptjunctions = gEngfuncs.Cvar_Get( "gl_keeptjunctions", "1", FCVAR_GLCONFIG, "removing tjuncs causes blinking pixels" );
|
||||
gl_emboss_scale = gEngfuncs.Cvar_Get( "gl_emboss_scale", "0", FCVAR_GLCONFIG|FCVAR_LATCH, "fake bumpmapping scale" );
|
||||
gl_showtextures = gEngfuncs.pfnGetCvarPointer( "r_showtextures", 0 );
|
||||
gl_clear = gEngfuncs.pfnGetCvarPointer( "gl_clear", 0 );
|
||||
gl_test = gEngfuncs.Cvar_Get( "gl_test", "0", 0, "engine developer cvar for quick testing new features" );
|
||||
gl_wireframe = gEngfuncs.Cvar_Get( "gl_wireframe", "0", FCVAR_GLCONFIG|FCVAR_SPONLY, "show wireframe overlay" );
|
||||
gl_subdivide_size = gEngfuncs.Cvar_Get( "gl_subdivide_size", "256.0", FCVAR_GLCONFIG, "the division value for the sky brushes" );
|
||||
gl_round_down = gEngfuncs.Cvar_Get( "gl_round_down", "1", FCVAR_GLCONFIG, "round texture sizes to nearest POT value" );
|
||||
// these cvar not used by engine but some mods requires this
|
||||
gl_depthoffset = gEngfuncs.Cvar_Get( "gl_depthoffset", "256.0", FCVAR_GLCONFIG, "depth offset for decals" );
|
||||
|
||||
// make sure gl_vsync is checked after vid_restart
|
||||
SetBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||
|
||||
vid_gamma = gEngfuncs.pfnGetCvarPointer( "gamma", 0 );
|
||||
vid_brightness = gEngfuncs.pfnGetCvarPointer( "brightness", 0 );
|
||||
|
||||
tracerred = gEngfuncs.Cvar_Get( "tracerred", "0.8", 0, "tracer red component weight ( 0 - 1.0 )" );
|
||||
tracergreen = gEngfuncs.Cvar_Get( "tracergreen", "0.8", 0, "tracer green component weight ( 0 - 1.0 )" );
|
||||
tracerblue = gEngfuncs.Cvar_Get( "tracerblue", "0.4", 0, "tracer blue component weight ( 0 - 1.0 )" );
|
||||
traceralpha = gEngfuncs.Cvar_Get( "traceralpha", "0.5", 0, "tracer alpha amount ( 0 - 1.0 )" );
|
||||
|
||||
cl_lightstyle_lerping = gEngfuncs.pfnGetCvarPointer( "cl_lightstyle_lerping", 0 );
|
||||
|
||||
gEngfuncs.Cmd_AddCommand( "r_info", R_RenderInfo_f, "display renderer info" );
|
||||
gEngfuncs.Cmd_AddCommand( "timerefresh", SCR_TimeRefresh_f, "turn quickly and print rendering statistcs" );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GL_RemoveCommands
|
||||
=================
|
||||
*/
|
||||
void GL_RemoveCommands( void )
|
||||
{
|
||||
gEngfuncs.Cmd_RemoveCommand( "r_info" );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_Init
|
||||
===============
|
||||
*/
|
||||
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();
|
||||
|
||||
GL_SetDefaultState();
|
||||
|
||||
// create the window and set up the context
|
||||
if( !gEngfuncs.R_Init_Video( REF_GL )) // request GL context
|
||||
{
|
||||
GL_RemoveCommands();
|
||||
gEngfuncs.R_Free_Video();
|
||||
// Why? Host_Error again???
|
||||
// gEngfuncs.Host_Error( "Can't initialize video subsystem\nProbably driver was not installed" );
|
||||
return false;
|
||||
}
|
||||
|
||||
r_temppool = Mem_AllocPool( "Render Zone" );
|
||||
|
||||
GU_Init();
|
||||
R_InitImages();
|
||||
R_SpriteInit();
|
||||
R_StudioInit();
|
||||
R_AliasInit();
|
||||
R_ClearDecals();
|
||||
R_ClearScene();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_Shutdown
|
||||
===============
|
||||
*/
|
||||
void R_Shutdown( void )
|
||||
{
|
||||
if( !glw_state.initialized )
|
||||
return;
|
||||
|
||||
GL_RemoveCommands();
|
||||
R_ShutdownImages();
|
||||
GU_Shutdown();
|
||||
|
||||
Mem_FreePool( &r_temppool );
|
||||
|
||||
// shut down OS specific OpenGL stuff like contexts, etc.
|
||||
gEngfuncs.R_Free_Video();
|
||||
}
|
||||
|
||||
void GL_SetupAttributes( int safegl )
|
||||
{
|
||||
|
||||
}
|
||||
491
ref_gu/gu_rlight.c
Normal file
491
ref_gu/gu_rlight.c
Normal file
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
gl_rlight.c - dynamic and static lights
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "gu_local.h"
|
||||
#include "pm_local.h"
|
||||
#include "studio.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
#include "ref_params.h"
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
DYNAMIC LIGHTS
|
||||
|
||||
=============================================================================
|
||||
*/
|
||||
/*
|
||||
==================
|
||||
CL_RunLightStyles
|
||||
|
||||
==================
|
||||
*/
|
||||
void CL_RunLightStyles( void )
|
||||
{
|
||||
int i, k, flight, clight;
|
||||
float l, lerpfrac, backlerp;
|
||||
float frametime = (gpGlobals->time - gpGlobals->oldtime);
|
||||
float scale;
|
||||
lightstyle_t *ls;
|
||||
|
||||
if( !WORLDMODEL ) return;
|
||||
|
||||
scale = r_lighting_modulate->value;
|
||||
|
||||
// light animations
|
||||
// 'm' is normal light, 'a' is no light, 'z' is double bright
|
||||
for( i = 0, ls = gEngfuncs.GetLightStyle( 0 ); i < MAX_LIGHTSTYLES; i++, ls++ )
|
||||
{
|
||||
if( !WORLDMODEL->lightdata )
|
||||
{
|
||||
tr.lightstylevalue[i] = 256 * 256;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !ENGINE_GET_PARM( PARAM_GAMEPAUSED ) && frametime <= 0.1f )
|
||||
ls->time += frametime; // evaluate local time
|
||||
|
||||
flight = (int)Q_floor( ls->time * 10 );
|
||||
clight = (int)Q_ceil( ls->time * 10 );
|
||||
lerpfrac = ( ls->time * 10 ) - flight;
|
||||
backlerp = 1.0f - lerpfrac;
|
||||
|
||||
if( !ls->length )
|
||||
{
|
||||
tr.lightstylevalue[i] = 256 * scale;
|
||||
continue;
|
||||
}
|
||||
else if( ls->length == 1 )
|
||||
{
|
||||
// single length style so don't bother interpolating
|
||||
tr.lightstylevalue[i] = ls->map[0] * 22 * scale;
|
||||
continue;
|
||||
}
|
||||
else if( !ls->interp || !CVAR_TO_BOOL( cl_lightstyle_lerping ))
|
||||
{
|
||||
tr.lightstylevalue[i] = ls->map[flight%ls->length] * 22 * scale;
|
||||
continue;
|
||||
}
|
||||
|
||||
// interpolate animating light
|
||||
// frame just gone
|
||||
k = ls->map[flight % ls->length];
|
||||
l = (float)( k * 22.0f ) * backlerp;
|
||||
|
||||
// upcoming frame
|
||||
k = ls->map[clight % ls->length];
|
||||
l += (float)( k * 22.0f ) * lerpfrac;
|
||||
|
||||
tr.lightstylevalue[i] = (int)l * scale;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_MarkLights
|
||||
=============
|
||||
*/
|
||||
void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
|
||||
{
|
||||
float dist;
|
||||
msurface_t *surf;
|
||||
int i;
|
||||
|
||||
if( !node || node->contents < 0 )
|
||||
return;
|
||||
|
||||
dist = PlaneDiff( light->origin, node->plane );
|
||||
|
||||
if( dist > light->radius )
|
||||
{
|
||||
R_MarkLights( light, bit, node->children[0] );
|
||||
return;
|
||||
}
|
||||
if( dist < -light->radius )
|
||||
{
|
||||
R_MarkLights( light, bit, node->children[1] );
|
||||
return;
|
||||
}
|
||||
|
||||
// mark the polygons
|
||||
surf = RI.currentmodel->surfaces + node->firstsurface;
|
||||
|
||||
for( i = 0; i < node->numsurfaces; i++, surf++ )
|
||||
{
|
||||
if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius ))
|
||||
continue; // no intersection
|
||||
|
||||
if( surf->dlightframe != tr.dlightframecount )
|
||||
{
|
||||
surf->dlightbits = 0;
|
||||
surf->dlightframe = tr.dlightframecount;
|
||||
}
|
||||
surf->dlightbits |= bit;
|
||||
}
|
||||
|
||||
R_MarkLights( light, bit, node->children[0] );
|
||||
R_MarkLights( light, bit, node->children[1] );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_PushDlights
|
||||
=============
|
||||
*/
|
||||
void R_PushDlights( void )
|
||||
{
|
||||
dlight_t *l;
|
||||
int i;
|
||||
|
||||
tr.dlightframecount = tr.framecount;
|
||||
|
||||
RI.currententity = gEngfuncs.GetEntityByIndex( 0 );
|
||||
RI.currentmodel = RI.currententity->model;
|
||||
|
||||
for( i = 0, l = gEngfuncs.GetDynamicLight( 0 ); i < MAX_DLIGHTS; i++, l++ )
|
||||
{
|
||||
if( l->die < gpGlobals->time || !l->radius )
|
||||
continue;
|
||||
|
||||
if( GL_FrustumCullSphere( &RI.frustum, l->origin, l->radius, 15 ))
|
||||
continue;
|
||||
|
||||
R_MarkLights( l, 1<<i, RI.currentmodel->nodes );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_CountDlights
|
||||
=============
|
||||
*/
|
||||
int R_CountDlights( void )
|
||||
{
|
||||
dlight_t *l;
|
||||
int i, numDlights = 0;
|
||||
|
||||
for( i = 0, l = gEngfuncs.GetDynamicLight( 0 ); i < MAX_DLIGHTS; i++, l++ )
|
||||
{
|
||||
if( l->die < gpGlobals->time || !l->radius )
|
||||
continue;
|
||||
|
||||
numDlights++;
|
||||
}
|
||||
|
||||
return numDlights;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_CountSurfaceDlights
|
||||
=============
|
||||
*/
|
||||
int R_CountSurfaceDlights( msurface_t *surf )
|
||||
{
|
||||
int i, numDlights = 0;
|
||||
|
||||
for( i = 0; i < MAX_DLIGHTS; i++ )
|
||||
{
|
||||
if(!( surf->dlightbits & BIT( i )))
|
||||
continue; // not lit by this light
|
||||
|
||||
numDlights++;
|
||||
}
|
||||
|
||||
return numDlights;
|
||||
}
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
AMBIENT LIGHTING
|
||||
|
||||
=======================================================================
|
||||
*/
|
||||
static vec3_t g_trace_lightspot;
|
||||
static vec3_t g_trace_lightvec;
|
||||
static float g_trace_fraction;
|
||||
|
||||
/*
|
||||
=================
|
||||
R_RecursiveLightPoint
|
||||
=================
|
||||
*/
|
||||
static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, float p2f, colorVec *cv, const vec3_t start, const vec3_t end )
|
||||
{
|
||||
float front, back, frac, midf;
|
||||
int i, map, side, size;
|
||||
float ds, dt, s, t;
|
||||
int sample_size;
|
||||
color24 *lm, *dm;
|
||||
mextrasurf_t *info;
|
||||
msurface_t *surf;
|
||||
mtexinfo_t *tex;
|
||||
matrix3x4 tbn;
|
||||
vec3_t mid;
|
||||
|
||||
// didn't hit anything
|
||||
if( !node || node->contents < 0 )
|
||||
{
|
||||
cv->r = cv->g = cv->b = cv->a = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// calculate mid point
|
||||
front = PlaneDiff( start, node->plane );
|
||||
back = PlaneDiff( end, node->plane );
|
||||
|
||||
side = front < 0;
|
||||
if(( back < 0 ) == side )
|
||||
return R_RecursiveLightPoint( model, node->children[side], p1f, p2f, cv, start, end );
|
||||
|
||||
frac = front / ( front - back );
|
||||
|
||||
VectorLerp( start, frac, end, mid );
|
||||
midf = p1f + ( p2f - p1f ) * frac;
|
||||
|
||||
// co down front side
|
||||
if( R_RecursiveLightPoint( model, node->children[side], p1f, midf, cv, start, mid ))
|
||||
return true; // hit something
|
||||
|
||||
if(( back < 0 ) == side )
|
||||
{
|
||||
cv->r = cv->g = cv->b = cv->a = 0;
|
||||
return false; // didn't hit anything
|
||||
}
|
||||
|
||||
// check for impact on this node
|
||||
surf = model->surfaces + node->firstsurface;
|
||||
VectorCopy( mid, g_trace_lightspot );
|
||||
|
||||
for( i = 0; i < node->numsurfaces; i++, surf++ )
|
||||
{
|
||||
int smax, tmax;
|
||||
|
||||
tex = surf->texinfo;
|
||||
info = surf->info;
|
||||
|
||||
if( FBitSet( surf->flags, SURF_DRAWTILED ))
|
||||
continue; // no lightmaps
|
||||
|
||||
s = DotProduct( mid, info->lmvecs[0] ) + info->lmvecs[0][3];
|
||||
t = DotProduct( mid, info->lmvecs[1] ) + info->lmvecs[1][3];
|
||||
|
||||
if( s < info->lightmapmins[0] || t < info->lightmapmins[1] )
|
||||
continue;
|
||||
|
||||
ds = s - info->lightmapmins[0];
|
||||
dt = t - info->lightmapmins[1];
|
||||
|
||||
if ( ds > info->lightextents[0] || dt > info->lightextents[1] )
|
||||
continue;
|
||||
|
||||
cv->r = cv->g = cv->b = cv->a = 0;
|
||||
|
||||
if( !surf->samples )
|
||||
return true;
|
||||
|
||||
sample_size = gEngfuncs.Mod_SampleSizeForFace( surf );
|
||||
smax = (info->lightextents[0] / sample_size) + 1;
|
||||
tmax = (info->lightextents[1] / sample_size) + 1;
|
||||
ds /= sample_size;
|
||||
dt /= sample_size;
|
||||
|
||||
lm = surf->samples + Q_rint( dt ) * smax + Q_rint( ds );
|
||||
g_trace_fraction = midf;
|
||||
size = smax * tmax;
|
||||
dm = NULL;
|
||||
|
||||
if( surf->info->deluxemap )
|
||||
{
|
||||
vec3_t faceNormal;
|
||||
|
||||
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||
VectorNegate( surf->plane->normal, faceNormal );
|
||||
else VectorCopy( surf->plane->normal, faceNormal );
|
||||
|
||||
// compute face TBN
|
||||
#if 1
|
||||
Vector4Set( tbn[0], surf->info->lmvecs[0][0], surf->info->lmvecs[0][1], surf->info->lmvecs[0][2], 0.0f );
|
||||
Vector4Set( tbn[1], -surf->info->lmvecs[1][0], -surf->info->lmvecs[1][1], -surf->info->lmvecs[1][2], 0.0f );
|
||||
Vector4Set( tbn[2], faceNormal[0], faceNormal[1], faceNormal[2], 0.0f );
|
||||
#else
|
||||
Vector4Set( tbn[0], surf->info->lmvecs[0][0], -surf->info->lmvecs[1][0], faceNormal[0], 0.0f );
|
||||
Vector4Set( tbn[1], surf->info->lmvecs[0][1], -surf->info->lmvecs[1][1], faceNormal[1], 0.0f );
|
||||
Vector4Set( tbn[2], surf->info->lmvecs[0][2], -surf->info->lmvecs[1][2], faceNormal[2], 0.0f );
|
||||
#endif
|
||||
VectorNormalize( tbn[0] );
|
||||
VectorNormalize( tbn[1] );
|
||||
VectorNormalize( tbn[2] );
|
||||
dm = surf->info->deluxemap + Q_rint( dt ) * smax + Q_rint( ds );
|
||||
}
|
||||
|
||||
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ )
|
||||
{
|
||||
uint scale = tr.lightstylevalue[surf->styles[map]];
|
||||
|
||||
if( tr.ignore_lightgamma )
|
||||
{
|
||||
cv->r += lm->r * scale;
|
||||
cv->g += lm->g * scale;
|
||||
cv->b += lm->b * scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
cv->r += gEngfuncs.LightToTexGamma( lm->r ) * scale;
|
||||
cv->g += gEngfuncs.LightToTexGamma( lm->g ) * scale;
|
||||
cv->b += gEngfuncs.LightToTexGamma( lm->b ) * scale;
|
||||
}
|
||||
lm += size; // skip to next lightmap
|
||||
|
||||
if( dm != NULL )
|
||||
{
|
||||
vec3_t srcNormal, lightNormal;
|
||||
float f = (1.0f / 128.0f);
|
||||
|
||||
VectorSet( srcNormal, ((float)dm->r - 128.0f) * f, ((float)dm->g - 128.0f) * f, ((float)dm->b - 128.0f) * f );
|
||||
Matrix3x4_VectorIRotate( tbn, srcNormal, lightNormal ); // turn to world space
|
||||
VectorScale( lightNormal, (float)scale * -1.0f, lightNormal ); // turn direction from light
|
||||
VectorAdd( g_trace_lightvec, lightNormal, g_trace_lightvec );
|
||||
dm += size; // skip to next deluxmap
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// go down back side
|
||||
return R_RecursiveLightPoint( model, node->children[!side], midf, p2f, cv, mid, end );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightVec
|
||||
|
||||
check bspmodels to get light from
|
||||
=================
|
||||
*/
|
||||
colorVec R_LightVecInternal( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec )
|
||||
{
|
||||
float last_fraction;
|
||||
int i, maxEnts = 1;
|
||||
colorVec light, cv;
|
||||
|
||||
if( lspot ) VectorClear( lspot );
|
||||
if( lvec ) VectorClear( lvec );
|
||||
|
||||
if( WORLDMODEL && WORLDMODEL->lightdata )
|
||||
{
|
||||
light.r = light.g = light.b = light.a = 0;
|
||||
last_fraction = 1.0f;
|
||||
|
||||
// get light from bmodels too
|
||||
if( CVAR_TO_BOOL( r_lighting_extended ))
|
||||
maxEnts = MAX_PHYSENTS;
|
||||
|
||||
// check all the bsp-models
|
||||
for( i = 0; i < maxEnts; i++ )
|
||||
{
|
||||
physent_t *pe = gEngfuncs.EV_GetPhysent( i );
|
||||
vec3_t offset, start_l, end_l;
|
||||
mnode_t *pnodes;
|
||||
matrix4x4 matrix;
|
||||
|
||||
if( !pe )
|
||||
break;
|
||||
|
||||
if( !pe->model || pe->model->type != mod_brush )
|
||||
continue; // skip non-bsp models
|
||||
|
||||
pnodes = &pe->model->nodes[pe->model->hulls[0].firstclipnode];
|
||||
VectorSubtract( pe->model->hulls[0].clip_mins, vec3_origin, offset );
|
||||
VectorAdd( offset, pe->origin, offset );
|
||||
VectorSubtract( start, offset, start_l );
|
||||
VectorSubtract( end, offset, end_l );
|
||||
|
||||
// rotate start and end into the models frame of reference
|
||||
if( !VectorIsNull( pe->angles ))
|
||||
{
|
||||
Matrix4x4_CreateFromEntity( matrix, pe->angles, offset, 1.0f );
|
||||
Matrix4x4_VectorITransform( matrix, start, start_l );
|
||||
Matrix4x4_VectorITransform( matrix, end, end_l );
|
||||
}
|
||||
|
||||
VectorClear( g_trace_lightspot );
|
||||
VectorClear( g_trace_lightvec );
|
||||
g_trace_fraction = 1.0f;
|
||||
|
||||
if( !R_RecursiveLightPoint( pe->model, pnodes, 0.0f, 1.0f, &cv, start_l, end_l ))
|
||||
continue; // didn't hit anything
|
||||
|
||||
if( g_trace_fraction < last_fraction )
|
||||
{
|
||||
if( lspot ) VectorCopy( g_trace_lightspot, lspot );
|
||||
if( lvec ) VectorNormalize2( g_trace_lightvec, lvec );
|
||||
light.r = Q_min(( cv.r >> 7 ), 255 );
|
||||
light.g = Q_min(( cv.g >> 7 ), 255 );
|
||||
light.b = Q_min(( cv.b >> 7 ), 255 );
|
||||
last_fraction = g_trace_fraction;
|
||||
|
||||
if(( light.r + light.g + light.b ) != 0 )
|
||||
break; // we get light now
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
light.r = light.g = light.b = 255;
|
||||
light.a = 0;
|
||||
}
|
||||
|
||||
return light;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightVec
|
||||
|
||||
check bspmodels to get light from
|
||||
=================
|
||||
*/
|
||||
colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec )
|
||||
{
|
||||
colorVec light = R_LightVecInternal( start, end, lspot, lvec );
|
||||
|
||||
if( CVAR_TO_BOOL( r_lighting_extended ) && lspot != NULL && lvec != NULL )
|
||||
{
|
||||
// trying to get light from ceiling (but ignore gradient analyze)
|
||||
if(( light.r + light.g + light.b ) == 0 )
|
||||
return R_LightVecInternal( end, start, lspot, lvec );
|
||||
}
|
||||
|
||||
return light;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_LightPoint
|
||||
|
||||
light from floor
|
||||
=================
|
||||
*/
|
||||
colorVec R_LightPoint( const vec3_t p0 )
|
||||
{
|
||||
vec3_t p1;
|
||||
|
||||
VectorSet( p1, p0[0], p0[1], p0[2] - 2048.0f );
|
||||
|
||||
return R_LightVec( p0, p1, NULL, NULL );
|
||||
}
|
||||
1345
ref_gu/gu_rmain.c
Normal file
1345
ref_gu/gu_rmain.c
Normal file
File diff suppressed because it is too large
Load Diff
290
ref_gu/gu_rmath.c
Normal file
290
ref_gu/gu_rmath.c
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
gl_rmath.c - renderer mathlib
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "gu_local.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
/*
|
||||
========================================================================
|
||||
|
||||
Matrix4x4 operations (private to renderer)
|
||||
|
||||
========================================================================
|
||||
*/
|
||||
void Matrix4x4_Concat( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 )
|
||||
{
|
||||
#if 1
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in1[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in1[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in1[2]
|
||||
"lv.q C130, 48 + %1\n" // C130 = in1[3]
|
||||
"lv.q C200, 0 + %2\n" // C200 = in2[0]
|
||||
"lv.q C210, 16 + %2\n" // C210 = in2[1]
|
||||
"lv.q C220, 32 + %2\n" // C220 = in2[2]
|
||||
"lv.q C230, 48 + %2\n" // C230 = in2[3]
|
||||
"vmmul.q E000, E100, E200\n" // E000 = E100 * E200
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in1 ), "m"( *in2 )
|
||||
);
|
||||
#else
|
||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0] + in1[0][3] * in2[3][0];
|
||||
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1] + in1[0][3] * in2[3][1];
|
||||
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2] + in1[0][3] * in2[3][2];
|
||||
out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3] * in2[3][3];
|
||||
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0] + in1[1][3] * in2[3][0];
|
||||
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1] + in1[1][3] * in2[3][1];
|
||||
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2] + in1[1][3] * in2[3][2];
|
||||
out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3] * in2[3][3];
|
||||
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0] + in1[2][3] * in2[3][0];
|
||||
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1] + in1[2][3] * in2[3][1];
|
||||
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2] + in1[2][3] * in2[3][2];
|
||||
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3] * in2[3][3];
|
||||
out[3][0] = in1[3][0] * in2[0][0] + in1[3][1] * in2[1][0] + in1[3][2] * in2[2][0] + in1[3][3] * in2[3][0];
|
||||
out[3][1] = in1[3][0] * in2[0][1] + in1[3][1] * in2[1][1] + in1[3][2] * in2[2][1] + in1[3][3] * in2[3][1];
|
||||
out[3][2] = in1[3][0] * in2[0][2] + in1[3][1] * in2[1][2] + in1[3][2] * in2[2][2] + in1[3][3] * in2[3][2];
|
||||
out[3][3] = in1[3][0] * in2[0][3] + in1[3][1] * in2[1][3] + in1[3][2] * in2[2][3] + in1[3][3] * in2[3][3];
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Matrix4x4_CreateProjection
|
||||
|
||||
NOTE: produce quake style world orientation
|
||||
================
|
||||
*/
|
||||
void Matrix4x4_CreateProjection( matrix4x4 out, float xMax, float xMin, float yMax, float yMin, float zNear, float zFar )
|
||||
{
|
||||
out[0][0] = ( 2.0f * zNear ) / ( xMax - xMin );
|
||||
out[1][1] = ( 2.0f * zNear ) / ( yMax - yMin );
|
||||
out[2][2] = -( zFar + zNear ) / ( zFar - zNear );
|
||||
out[3][3] = out[0][1] = out[1][0] = out[3][0] = out[0][3] = out[3][1] = out[1][3] = 0.0f;
|
||||
|
||||
out[2][0] = 0.0f;
|
||||
out[2][1] = 0.0f;
|
||||
out[0][2] = ( xMax + xMin ) / ( xMax - xMin );
|
||||
out[1][2] = ( yMax + yMin ) / ( yMax - yMin );
|
||||
out[3][2] = -1.0f;
|
||||
out[2][3] = -( 2.0f * zFar * zNear ) / ( zFar - zNear );
|
||||
}
|
||||
|
||||
void Matrix4x4_CreateOrtho( matrix4x4 out, float xLeft, float xRight, float yBottom, float yTop, float zNear, float zFar )
|
||||
{
|
||||
out[0][0] = 2.0f / (xRight - xLeft);
|
||||
out[1][1] = 2.0f / (yTop - yBottom);
|
||||
out[2][2] = -2.0f / (zFar - zNear);
|
||||
out[3][3] = 1.0f;
|
||||
out[0][1] = out[0][2] = out[1][0] = out[1][2] = out[3][0] = out[3][1] = out[3][2] = 0.0f;
|
||||
|
||||
out[2][0] = 0.0f;
|
||||
out[2][1] = 0.0f;
|
||||
out[0][3] = -(xRight + xLeft) / (xRight - xLeft);
|
||||
out[1][3] = -(yTop + yBottom) / (yTop - yBottom);
|
||||
out[2][3] = -(zFar + zNear) / (zFar - zNear);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Matrix4x4_CreateModelview
|
||||
|
||||
NOTE: produce quake style world orientation
|
||||
================
|
||||
*/
|
||||
void Matrix4x4_CreateModelview( matrix4x4 out )
|
||||
{
|
||||
out[0][0] = out[1][1] = out[2][2] = 0.0f;
|
||||
out[3][0] = out[0][3] = 0.0f;
|
||||
out[3][1] = out[1][3] = 0.0f;
|
||||
out[3][2] = out[2][3] = 0.0f;
|
||||
out[3][3] = 1.0f;
|
||||
out[1][0] = out[0][2] = out[2][1] = 0.0f;
|
||||
out[2][0] = out[0][1] = -1.0f;
|
||||
out[1][2] = 1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4_ToFMatrix4( const matrix4x4 in, ScePspFMatrix4 *out )
|
||||
{
|
||||
// transpose matrix
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C000, 0 + %1\n" // C000 = in->x
|
||||
"lv.q C010, 16 + %1\n" // C010 = in->y
|
||||
"lv.q C020, 32 + %1\n" // C020 = in->z
|
||||
"lv.q C030, 48 + %1\n" // C030 = in->w
|
||||
"sv.q R000, 0 + %0\n" // out->x = R000
|
||||
"sv.q R001, 16 + %0\n" // out->y = R010
|
||||
"sv.q R002, 32 + %0\n" // out->z = R020
|
||||
"sv.q R003, 48 + %0\n" // out->w = R030
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in )
|
||||
);
|
||||
}
|
||||
|
||||
void Matrix4x4_FromFMatrix4( matrix4x4 out, ScePspFMatrix4 *in )
|
||||
{
|
||||
// transpose matrix
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C000, 0 + %1\n" // C000 = in->x
|
||||
"lv.q C010, 16 + %1\n" // C010 = in->y
|
||||
"lv.q C020, 32 + %1\n" // C020 = in->z
|
||||
"lv.q C030, 48 + %1\n" // C030 = in->w
|
||||
"sv.q R000, 0 + %0\n" // out->x = R000
|
||||
"sv.q R001, 16 + %0\n" // out->y = R010
|
||||
"sv.q R002, 32 + %0\n" // out->z = R020
|
||||
"sv.q R003, 48 + %0\n" // out->w = R030
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in )
|
||||
);
|
||||
}
|
||||
|
||||
void Matrix4x4_CreateTranslate( matrix4x4 out, float x, float y, float z )
|
||||
{
|
||||
out[0][0] = 1.0f;
|
||||
out[0][1] = 0.0f;
|
||||
out[0][2] = 0.0f;
|
||||
out[0][3] = x;
|
||||
out[1][0] = 0.0f;
|
||||
out[1][1] = 1.0f;
|
||||
out[1][2] = 0.0f;
|
||||
out[1][3] = y;
|
||||
out[2][0] = 0.0f;
|
||||
out[2][1] = 0.0f;
|
||||
out[2][2] = 1.0f;
|
||||
out[2][3] = z;
|
||||
out[3][0] = 0.0f;
|
||||
out[3][1] = 0.0f;
|
||||
out[3][2] = 0.0f;
|
||||
out[3][3] = 1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4_CreateRotate( matrix4x4 out, float angle, float x, float y, float z )
|
||||
{
|
||||
float len, c, s;
|
||||
|
||||
len = x * x + y * y + z * z;
|
||||
if( len != 0.0f ) len = 1.0f / sqrt( len );
|
||||
x *= len;
|
||||
y *= len;
|
||||
z *= len;
|
||||
|
||||
angle *= (-M_PI_F / 180.0f);
|
||||
SinCos( angle, &s, &c );
|
||||
|
||||
out[0][0]=x * x + c * (1 - x * x);
|
||||
out[0][1]=x * y * (1 - c) + z * s;
|
||||
out[0][2]=z * x * (1 - c) - y * s;
|
||||
out[0][3]=0.0f;
|
||||
out[1][0]=x * y * (1 - c) - z * s;
|
||||
out[1][1]=y * y + c * (1 - y * y);
|
||||
out[1][2]=y * z * (1 - c) + x * s;
|
||||
out[1][3]=0.0f;
|
||||
out[2][0]=z * x * (1 - c) + y * s;
|
||||
out[2][1]=y * z * (1 - c) - x * s;
|
||||
out[2][2]=z * z + c * (1 - z * z);
|
||||
out[2][3]=0.0f;
|
||||
out[3][0]=0.0f;
|
||||
out[3][1]=0.0f;
|
||||
out[3][2]=0.0f;
|
||||
out[3][3]=1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4_CreateScale( matrix4x4 out, float x )
|
||||
{
|
||||
out[0][0] = x;
|
||||
out[0][1] = 0.0f;
|
||||
out[0][2] = 0.0f;
|
||||
out[0][3] = 0.0f;
|
||||
out[1][0] = 0.0f;
|
||||
out[1][1] = x;
|
||||
out[1][2] = 0.0f;
|
||||
out[1][3] = 0.0f;
|
||||
out[2][0] = 0.0f;
|
||||
out[2][1] = 0.0f;
|
||||
out[2][2] = x;
|
||||
out[2][3] = 0.0f;
|
||||
out[3][0] = 0.0f;
|
||||
out[3][1] = 0.0f;
|
||||
out[3][2] = 0.0f;
|
||||
out[3][3] = 1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4_CreateScale3( matrix4x4 out, float x, float y, float z )
|
||||
{
|
||||
out[0][0] = x;
|
||||
out[0][1] = 0.0f;
|
||||
out[0][2] = 0.0f;
|
||||
out[0][3] = 0.0f;
|
||||
out[1][0] = 0.0f;
|
||||
out[1][1] = y;
|
||||
out[1][2] = 0.0f;
|
||||
out[1][3] = 0.0f;
|
||||
out[2][0] = 0.0f;
|
||||
out[2][1] = 0.0f;
|
||||
out[2][2] = z;
|
||||
out[2][3] = 0.0f;
|
||||
out[3][0] = 0.0f;
|
||||
out[3][1] = 0.0f;
|
||||
out[3][2] = 0.0f;
|
||||
out[3][3] = 1.0f;
|
||||
}
|
||||
|
||||
void Matrix4x4_ConcatTranslate( matrix4x4 out, float x, float y, float z )
|
||||
{
|
||||
matrix4x4 base, temp;
|
||||
|
||||
Matrix4x4_Copy( base, out );
|
||||
Matrix4x4_CreateTranslate( temp, x, y, z );
|
||||
Matrix4x4_Concat( out, base, temp );
|
||||
}
|
||||
|
||||
void Matrix4x4_ConcatRotate( matrix4x4 out, float angle, float x, float y, float z )
|
||||
{
|
||||
matrix4x4 base, temp;
|
||||
|
||||
Matrix4x4_Copy( base, out );
|
||||
Matrix4x4_CreateRotate( temp, angle, x, y, z );
|
||||
Matrix4x4_Concat( out, base, temp );
|
||||
}
|
||||
|
||||
void Matrix4x4_ConcatScale( matrix4x4 out, float x )
|
||||
{
|
||||
matrix4x4 base, temp;
|
||||
|
||||
Matrix4x4_Copy( base, out );
|
||||
Matrix4x4_CreateScale( temp, x );
|
||||
Matrix4x4_Concat( out, base, temp );
|
||||
}
|
||||
|
||||
void Matrix4x4_ConcatScale3( matrix4x4 out, float x, float y, float z )
|
||||
{
|
||||
matrix4x4 base, temp;
|
||||
|
||||
Matrix4x4_Copy( base, out );
|
||||
Matrix4x4_CreateScale3( temp, x, y, z );
|
||||
Matrix4x4_Concat( out, base, temp );
|
||||
}
|
||||
190
ref_gu/gu_rmisc.c
Normal file
190
ref_gu/gu_rmisc.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
gl_rmisc.c - renderer misceallaneous
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "gu_local.h"
|
||||
#include "shake.h"
|
||||
#include "screenfade.h"
|
||||
#include "cdll_int.h"
|
||||
|
||||
static void R_ParseDetailTextures( const char *filename )
|
||||
{
|
||||
byte *afile;
|
||||
char *pfile;
|
||||
string token, texname;
|
||||
string detail_texname;
|
||||
string detail_path;
|
||||
float xScale, yScale;
|
||||
texture_t *tex;
|
||||
int i;
|
||||
|
||||
afile = gEngfuncs.COM_LoadFile( filename, NULL, false );
|
||||
if( !afile ) return;
|
||||
|
||||
pfile = (char *)afile;
|
||||
|
||||
// format: 'texturename' 'detailtexture' 'xScale' 'yScale'
|
||||
while(( pfile = gEngfuncs.COM_ParseFile( pfile, token )) != NULL )
|
||||
{
|
||||
texname[0] = '\0';
|
||||
detail_texname[0] = '\0';
|
||||
|
||||
// read texname
|
||||
if( token[0] == '{' )
|
||||
{
|
||||
// NOTE: COM_ParseFile handled some symbols seperately
|
||||
// this code will be fix it
|
||||
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
||||
Q_strncat( texname, "{", sizeof( texname ));
|
||||
Q_strncat( texname, token, sizeof( texname ));
|
||||
}
|
||||
else Q_strncpy( texname, token, sizeof( texname ));
|
||||
|
||||
// read detailtexture name
|
||||
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
||||
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
||||
|
||||
// trying the scales or '{'
|
||||
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
||||
|
||||
// read second part of detailtexture name
|
||||
if( token[0] == '{' )
|
||||
{
|
||||
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
||||
pfile = gEngfuncs.COM_ParseFile( pfile, token ); // read scales
|
||||
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
||||
pfile = gEngfuncs.COM_ParseFile( pfile, token ); // parse scales
|
||||
}
|
||||
|
||||
Q_snprintf( detail_path, sizeof( detail_path ), "gfx/%s", detail_texname );
|
||||
|
||||
// read scales
|
||||
xScale = Q_atof( token );
|
||||
|
||||
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
||||
yScale = Q_atof( token );
|
||||
|
||||
if( xScale <= 0.0f || yScale <= 0.0f )
|
||||
continue;
|
||||
|
||||
// search for existing texture and uploading detail texture
|
||||
for( i = 0; i < WORLDMODEL->numtextures; i++ )
|
||||
{
|
||||
tex = WORLDMODEL->textures[i];
|
||||
|
||||
if( Q_stricmp( tex->name, texname ))
|
||||
continue;
|
||||
|
||||
tex->dt_texturenum = GL_LoadTexture( detail_path, NULL, 0, TF_FORCE_COLOR );
|
||||
|
||||
// texture is loaded
|
||||
if( tex->dt_texturenum )
|
||||
{
|
||||
gl_texture_t *glt;
|
||||
|
||||
glt = R_GetTexture( tex->gl_texturenum );
|
||||
glt->xscale = xScale;
|
||||
glt->yscale = yScale;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Mem_Free( afile );
|
||||
}
|
||||
|
||||
void R_NewMap( void )
|
||||
{
|
||||
texture_t *tx;
|
||||
int i;
|
||||
|
||||
R_ClearDecals(); // clear all level decals
|
||||
|
||||
R_StudioResetPlayerModels();
|
||||
|
||||
// upload detailtextures
|
||||
if( CVAR_TO_BOOL( r_detailtextures ))
|
||||
{
|
||||
string mapname, filepath;
|
||||
|
||||
Q_strncpy( mapname, WORLDMODEL->name, sizeof( mapname ));
|
||||
COM_StripExtension( mapname );
|
||||
Q_sprintf( filepath, "%s_detail.txt", mapname );
|
||||
|
||||
R_ParseDetailTextures( filepath );
|
||||
}
|
||||
|
||||
if( gEngfuncs.pfnGetCvarFloat( "v_dark" ))
|
||||
{
|
||||
screenfade_t *sf = gEngfuncs.GetScreenFade();
|
||||
float fadetime = 5.0f;
|
||||
client_textmessage_t *title;
|
||||
|
||||
title = gEngfuncs.pfnTextMessageGet( "GAMETITLE" );
|
||||
if( ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ))
|
||||
fadetime = 1.0f;
|
||||
|
||||
if( title )
|
||||
{
|
||||
// get settings from titles.txt
|
||||
sf->fadeEnd = title->holdtime + title->fadeout;
|
||||
sf->fadeReset = title->fadeout;
|
||||
}
|
||||
else sf->fadeEnd = sf->fadeReset = fadetime;
|
||||
|
||||
sf->fadeFlags = FFADE_IN;
|
||||
sf->fader = sf->fadeg = sf->fadeb = 0;
|
||||
sf->fadealpha = 255;
|
||||
sf->fadeSpeed = (float)sf->fadealpha / sf->fadeReset;
|
||||
sf->fadeReset += gpGlobals->time;
|
||||
sf->fadeEnd += sf->fadeReset;
|
||||
|
||||
gEngfuncs.Cvar_SetValue( "v_dark", 0.0f );
|
||||
}
|
||||
|
||||
// clear out efrags in case the level hasn't been reloaded
|
||||
for( i = 0; i < WORLDMODEL->numleafs; i++ )
|
||||
WORLDMODEL->leafs[i+1].efrags = NULL;
|
||||
|
||||
glState.isFogEnabled = false;
|
||||
tr.skytexturenum = -1;
|
||||
#if 1
|
||||
sceGuDisable( GU_FOG );
|
||||
#else
|
||||
pglDisable( GL_FOG );
|
||||
#endif
|
||||
// clearing texture chains
|
||||
for( i = 0; i < WORLDMODEL->numtextures; i++ )
|
||||
{
|
||||
if( !WORLDMODEL->textures[i] )
|
||||
continue;
|
||||
|
||||
tx = WORLDMODEL->textures[i];
|
||||
|
||||
if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == ( tx->height * 2 ))
|
||||
tr.skytexturenum = i;
|
||||
|
||||
tx->texturechain = NULL;
|
||||
}
|
||||
|
||||
R_SetupSky( MOVEVARS->skyName );
|
||||
|
||||
GL_BuildLightmaps ();
|
||||
#if 0
|
||||
R_GenerateVBO();
|
||||
#endif
|
||||
if( gEngfuncs.drawFuncs->R_NewMap != NULL )
|
||||
gEngfuncs.drawFuncs->R_NewMap();
|
||||
|
||||
}
|
||||
359
ref_gu/gu_rpart.c
Normal file
359
ref_gu/gu_rpart.c
Normal file
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
gu_rpart.c - particles and tracers
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#include "gu_local.h"
|
||||
#include "r_efx.h"
|
||||
#include "event_flags.h"
|
||||
#include "entity_types.h"
|
||||
#include "triangleapi.h"
|
||||
#include "pm_local.h"
|
||||
#include "cl_tent.h"
|
||||
#include "studio.h"
|
||||
|
||||
static float gTracerSize[11] = { 1.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
static color24 gTracerColors[] =
|
||||
{
|
||||
{ 255, 255, 255 }, // White
|
||||
{ 255, 0, 0 }, // Red
|
||||
{ 0, 255, 0 }, // Green
|
||||
{ 0, 0, 255 }, // Blue
|
||||
{ 0, 0, 0 }, // Tracer default, filled in from cvars, etc.
|
||||
{ 255, 167, 17 }, // Yellow-orange sparks
|
||||
{ 255, 130, 90 }, // Yellowish streaks (garg)
|
||||
{ 55, 60, 144 }, // Blue egon streak
|
||||
{ 255, 130, 90 }, // More Yellowish streaks (garg)
|
||||
{ 255, 140, 90 }, // More Yellowish streaks (garg)
|
||||
{ 200, 130, 90 }, // More red streaks (garg)
|
||||
{ 255, 120, 70 }, // Darker red streaks (garg)
|
||||
};
|
||||
|
||||
/*
|
||||
================
|
||||
CL_DrawParticles
|
||||
|
||||
update particle color, position, free expired and draw it
|
||||
================
|
||||
*/
|
||||
void CL_DrawParticles( double frametime, particle_t *cl_active_particles, float partsize )
|
||||
{
|
||||
particle_t *p;
|
||||
vec3_t right, up;
|
||||
color24 *pColor;
|
||||
int alpha;
|
||||
float size;
|
||||
uint vert_count;
|
||||
uint vert_color;
|
||||
|
||||
if( !cl_active_particles )
|
||||
return; // nothing to draw?
|
||||
|
||||
vert_count = 0;
|
||||
vert_color = 0;
|
||||
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuDisable( GU_ALPHA_TEST );
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
||||
|
||||
sceGuDepthMask( GU_TRUE );
|
||||
|
||||
if( r_fast_particles->value )
|
||||
{
|
||||
gu_vert_fcv_t* const out = ( gu_vert_fcv_t* )extGuBeginPacket( NULL );
|
||||
|
||||
sceGuDisable( GU_TEXTURE_2D );
|
||||
|
||||
for( p = cl_active_particles; p; p = p->next )
|
||||
{
|
||||
if(( p->type != pt_blob ) || ( p->packedColor == 255 ))
|
||||
{
|
||||
p->color = bound( 0, p->color, 255 );
|
||||
pColor = gEngfuncs.CL_GetPaletteColor( p->color );
|
||||
|
||||
alpha = 255 * (p->die - gpGlobals->time) * 16.0f;
|
||||
if( alpha > 255 || p->type == pt_static )
|
||||
alpha = 255;
|
||||
|
||||
out[vert_count].c = GUCOLOR4UB( gEngfuncs.LightToTexGamma( pColor->r ),
|
||||
gEngfuncs.LightToTexGamma( pColor->g ),
|
||||
gEngfuncs.LightToTexGamma( pColor->b ), alpha );
|
||||
out[vert_count].x = p->org[0];
|
||||
out[vert_count].y = p->org[1];
|
||||
out[vert_count].z = p->org[2];
|
||||
vert_count++;
|
||||
|
||||
r_stats.c_particle_count++;
|
||||
}
|
||||
|
||||
gEngfuncs.CL_ThinkParticle( frametime, p );
|
||||
}
|
||||
|
||||
if( vert_count )
|
||||
{
|
||||
extGuEndPacket( ( void * )( out + vert_count ) );
|
||||
sceGuDrawArray( GU_POINTS, GU_COLOR_8888 | GU_VERTEX_32BITF, vert_count, 0, out );
|
||||
}
|
||||
|
||||
sceGuEnable( GU_TEXTURE_2D );
|
||||
}
|
||||
else
|
||||
{
|
||||
GL_Bind( XASH_TEXTURE0, tr.particleTexture );
|
||||
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
||||
|
||||
gu_vert_ftcv_t* const out = ( gu_vert_ftcv_t* )extGuBeginPacket( NULL );
|
||||
|
||||
for( p = cl_active_particles; p; p = p->next )
|
||||
{
|
||||
if(( p->type != pt_blob ) || ( p->packedColor == 255 ))
|
||||
{
|
||||
size = partsize; // get initial size of particle
|
||||
|
||||
// scale up to keep particles from disappearing
|
||||
size += (p->org[0] - RI.vieworg[0]) * RI.cull_vforward[0];
|
||||
size += (p->org[1] - RI.vieworg[1]) * RI.cull_vforward[1];
|
||||
size += (p->org[2] - RI.vieworg[2]) * RI.cull_vforward[2];
|
||||
|
||||
if( size < 20.0f ) size = partsize;
|
||||
else size = partsize + size * 0.002f;
|
||||
|
||||
// scale the axes by radius
|
||||
VectorScale( RI.cull_vright, size, right );
|
||||
VectorScale( RI.cull_vup, size, up );
|
||||
|
||||
p->color = bound( 0, p->color, 255 );
|
||||
pColor = gEngfuncs.CL_GetPaletteColor( p->color );
|
||||
|
||||
alpha = 255 * (p->die - gpGlobals->time) * 16.0f;
|
||||
if( alpha > 255 || p->type == pt_static )
|
||||
alpha = 255;
|
||||
vert_color = GUCOLOR4UB( gEngfuncs.LightToTexGamma( pColor->r ),
|
||||
gEngfuncs.LightToTexGamma( pColor->g ),
|
||||
gEngfuncs.LightToTexGamma( pColor->b ), alpha );
|
||||
|
||||
out[vert_count].u = 0.0f;
|
||||
out[vert_count].v = 0.0f;
|
||||
out[vert_count].c = vert_color;
|
||||
out[vert_count].x = p->org[0] + right[0] + up[0];
|
||||
out[vert_count].y = p->org[1] + right[1] + up[1];
|
||||
out[vert_count].z = p->org[2] + right[2] + up[2];
|
||||
vert_count++;
|
||||
out[vert_count].u = 1.0f;
|
||||
out[vert_count].v = 1.0f;
|
||||
out[vert_count].c = vert_color;
|
||||
out[vert_count].x = p->org[0] - right[0] - up[0];
|
||||
out[vert_count].y = p->org[1] - right[1] - up[1];
|
||||
out[vert_count].z = p->org[2] - right[2] - up[2];
|
||||
vert_count++;
|
||||
|
||||
r_stats.c_particle_count++;
|
||||
}
|
||||
|
||||
gEngfuncs.CL_ThinkParticle( frametime, p );
|
||||
}
|
||||
|
||||
if( vert_count )
|
||||
{
|
||||
extGuEndPacket(( void * )( out + vert_count ));
|
||||
sceGuDrawArray( GU_SPRITES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF, vert_count, 0, out );
|
||||
}
|
||||
}
|
||||
|
||||
sceGuDepthMask( GU_FALSE );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CL_CullTracer
|
||||
|
||||
check tracer bbox
|
||||
================
|
||||
*/
|
||||
static qboolean CL_CullTracer( particle_t *p, const vec3_t start, const vec3_t end )
|
||||
{
|
||||
vec3_t mins, maxs;
|
||||
int i;
|
||||
|
||||
// compute the bounding box
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
if( start[i] < end[i] )
|
||||
{
|
||||
mins[i] = start[i];
|
||||
maxs[i] = end[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
mins[i] = end[i];
|
||||
maxs[i] = start[i];
|
||||
}
|
||||
|
||||
// don't let it be zero sized
|
||||
if( mins[i] == maxs[i] )
|
||||
{
|
||||
maxs[i] += gTracerSize[p->type] * 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// check bbox
|
||||
return R_CullBox( mins, maxs );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CL_DrawTracers
|
||||
|
||||
update tracer color, position, free expired and draw it
|
||||
================
|
||||
*/
|
||||
void CL_DrawTracers( double frametime, particle_t *cl_active_tracers )
|
||||
{
|
||||
float scale, atten, gravity;
|
||||
vec3_t screenLast, screen;
|
||||
vec3_t start, end, delta;
|
||||
particle_t *p;
|
||||
|
||||
// update tracer color if this is changed
|
||||
if( FBitSet( tracerred->flags|tracergreen->flags|tracerblue->flags|traceralpha->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
color24 *customColors = &gTracerColors[4];
|
||||
customColors->r = (byte)(tracerred->value * traceralpha->value * 255);
|
||||
customColors->g = (byte)(tracergreen->value * traceralpha->value * 255);
|
||||
customColors->b = (byte)(tracerblue->value * traceralpha->value * 255);
|
||||
ClearBits( tracerred->flags, FCVAR_CHANGED );
|
||||
ClearBits( tracergreen->flags, FCVAR_CHANGED );
|
||||
ClearBits( tracerblue->flags, FCVAR_CHANGED );
|
||||
ClearBits( traceralpha->flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
if( !cl_active_tracers )
|
||||
return; // nothing to draw?
|
||||
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, GUBLEND1 );
|
||||
sceGuDisable( GU_ALPHA_TEST );
|
||||
sceGuDepthMask( GU_TRUE );
|
||||
sceGuDisable( GU_TEXTURE_2D );
|
||||
|
||||
gravity = frametime * MOVEVARS->gravity;
|
||||
scale = 1.0 - (frametime * 0.9);
|
||||
if( scale < 0.0f ) scale = 0.0f;
|
||||
|
||||
for( p = cl_active_tracers; p; p = p->next )
|
||||
{
|
||||
atten = (p->die - gpGlobals->time);
|
||||
if( atten > 0.1f ) atten = 0.1f;
|
||||
|
||||
VectorScale( p->vel, ( p->ramp * atten ), delta );
|
||||
VectorAdd( p->org, delta, end );
|
||||
VectorCopy( p->org, start );
|
||||
|
||||
if( !CL_CullTracer( p, start, end ))
|
||||
{
|
||||
vec3_t verts[4], tmp2;
|
||||
vec3_t tmp, normal;
|
||||
color24 *pColor;
|
||||
|
||||
// Transform point into screen space
|
||||
TriWorldToScreen( start, screen );
|
||||
TriWorldToScreen( end, screenLast );
|
||||
|
||||
// build world-space normal to screen-space direction vector
|
||||
VectorSubtract( screen, screenLast, tmp );
|
||||
|
||||
// we don't need Z, we're in screen space
|
||||
tmp[2] = 0;
|
||||
VectorNormalize( tmp );
|
||||
|
||||
// build point along noraml line (normal is -y, x)
|
||||
VectorScale( RI.cull_vup, tmp[0] * gTracerSize[p->type], normal );
|
||||
VectorScale( RI.cull_vright, -tmp[1] * gTracerSize[p->type], tmp2 );
|
||||
VectorSubtract( normal, tmp2, normal );
|
||||
|
||||
// compute four vertexes
|
||||
VectorSubtract( start, normal, verts[0] );
|
||||
VectorAdd( start, normal, verts[1] );
|
||||
VectorAdd( verts[0], delta, verts[2] );
|
||||
VectorAdd( verts[1], delta, verts[3] );
|
||||
|
||||
if( p->color > sizeof( gTracerColors ) / sizeof( color24 ) )
|
||||
{
|
||||
gEngfuncs.Con_Printf( S_ERROR "UserTracer with color > %d\n", sizeof( gTracerColors ) / sizeof( color24 ));
|
||||
p->color = 0;
|
||||
}
|
||||
|
||||
pColor = &gTracerColors[p->color];
|
||||
sceGuColor( GUCOLOR4UB( pColor->r, pColor->g, pColor->b, p->packedColor ));
|
||||
|
||||
gu_vert_fv_t* const out = ( gu_vert_fv_t* )sceGuGetMemory( sizeof( gu_vert_fv_t ) * 4 );
|
||||
out[0].x = verts[2][0];
|
||||
out[0].y = verts[2][1];
|
||||
out[0].z = verts[2][2];
|
||||
out[1].x = verts[3][0];
|
||||
out[1].y = verts[3][1];
|
||||
out[1].z = verts[3][2];
|
||||
out[2].x = verts[1][0];
|
||||
out[2].y = verts[1][1];
|
||||
out[2].z = verts[1][2];
|
||||
out[3].x = verts[0][0];
|
||||
out[3].y = verts[0][1];
|
||||
out[3].z = verts[0][2];
|
||||
sceGuDrawArray( GU_TRIANGLE_FAN, GU_VERTEX_32BITF, 4, 0, out );
|
||||
}
|
||||
|
||||
// evaluate position
|
||||
VectorMA( p->org, frametime, p->vel, p->org );
|
||||
|
||||
if( p->type == pt_grav )
|
||||
{
|
||||
p->vel[0] *= scale;
|
||||
p->vel[1] *= scale;
|
||||
p->vel[2] -= gravity;
|
||||
|
||||
p->packedColor = 255 * (p->die - gpGlobals->time) * 2;
|
||||
if( p->packedColor > 255 ) p->packedColor = 255;
|
||||
}
|
||||
else if( p->type == pt_slowgrav )
|
||||
{
|
||||
p->vel[2] = gravity * 0.05f;
|
||||
}
|
||||
}
|
||||
|
||||
sceGuEnable( GU_TEXTURE_2D );
|
||||
sceGuDepthMask( GU_FALSE );
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
CL_DrawParticlesExternal
|
||||
|
||||
allow to draw effects from custom renderer
|
||||
===============
|
||||
*/
|
||||
void CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, float frametime )
|
||||
{
|
||||
ref_instance_t oldRI = RI;
|
||||
|
||||
memcpy( &oldRI, &RI, sizeof( ref_instance_t ));
|
||||
R_SetupRefParams( rvp );
|
||||
R_SetupFrustum();
|
||||
R_SetupGL( false ); // don't touch GL-states
|
||||
tr.frametime = frametime;
|
||||
|
||||
gEngfuncs.CL_DrawEFX( frametime, trans_pass );
|
||||
|
||||
// restore internal state
|
||||
memcpy( &RI, &oldRI, sizeof( ref_instance_t ));
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user