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,6 +24,8 @@ GNU General Public License for more details.
|
||||
#include <sys/syslimits.h>
|
||||
#define OS_LIB_EXT "dylib"
|
||||
#define OPEN_COMMAND "open"
|
||||
#elif XASH_PSP
|
||||
#define OS_LIB_EXT "prx"
|
||||
#else
|
||||
#define OS_LIB_EXT "so"
|
||||
#define OPEN_COMMAND "xdg-open"
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 );
|
||||
@@ -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 ));
|
||||
}
|
||||
2347
ref_gu/gu_rsurf.c
Normal file
2347
ref_gu/gu_rsurf.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user