mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-08 05:11:51 +08:00
PSP Port initial
This commit is contained in:
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -1,6 +1,6 @@
|
||||
[submodule "mainui"]
|
||||
path = mainui
|
||||
url = https://github.com/FWGS/mainui_cpp
|
||||
url = https://github.com/Crow-bar/mainui_cpp
|
||||
[submodule "ref_gl/nanogl"]
|
||||
path = ref_gl/nanogl
|
||||
url = https://github.com/FWGS/nanogl
|
||||
|
||||
@@ -21,6 +21,7 @@ GNU General Public License for more details.
|
||||
#define VIDEO_ANDROID 2
|
||||
#define VIDEO_FBDEV 3
|
||||
#define VIDEO_DOS 4
|
||||
#define VIDEO_PSP 5
|
||||
|
||||
|
||||
// audio backends (XASH_SOUND)
|
||||
@@ -28,6 +29,7 @@ GNU General Public License for more details.
|
||||
#define SOUND_SDL 1
|
||||
#define SOUND_OPENSLES 2
|
||||
#define SOUND_ALSA 3
|
||||
#define SOUND_PSP 4
|
||||
|
||||
// crash handler (XASH_CRASHHANDLER)
|
||||
#define CRASHHANDLER_NULL 0
|
||||
@@ -40,6 +42,7 @@ GNU General Public License for more details.
|
||||
#define INPUT_SDL 1
|
||||
#define INPUT_ANDROID 2
|
||||
#define INPUT_EVDEV 3
|
||||
#define INPUT_PSP 4
|
||||
|
||||
// timer (XASH_TIMER)
|
||||
#define TIMER_NULL 0 // not used
|
||||
@@ -47,19 +50,21 @@ GNU General Public License for more details.
|
||||
#define TIMER_LINUX 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_ANDROID 2
|
||||
#define MSGBOX_WIN32 3
|
||||
|
||||
#define MSGBOX_PSP 4
|
||||
|
||||
// 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 */
|
||||
|
||||
@@ -126,6 +126,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;
|
||||
@@ -134,7 +149,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
|
||||
|
||||
@@ -95,6 +95,29 @@ 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
|
||||
#endif
|
||||
|
||||
#endif // XASH_DEDICATED
|
||||
@@ -132,7 +155,7 @@ SETUP BACKENDS DEFINITIONS
|
||||
#endif // !XASH_WIN32
|
||||
#endif
|
||||
|
||||
#ifdef XASH_STATIC_LIBS
|
||||
#if defined(XASH_STATIC_LIBS) && !defined(XASH_PSP)
|
||||
#define XASH_LIB LIB_STATIC
|
||||
#define XASH_INTERNAL_GAMELIBS
|
||||
#define XASH_ALLOW_SAVERESTORE_OFFSETS
|
||||
@@ -140,6 +163,9 @@ SETUP BACKENDS DEFINITIONS
|
||||
#define XASH_LIB LIB_WIN32
|
||||
#elif XASH_POSIX
|
||||
#define XASH_LIB LIB_POSIX
|
||||
#elif XASH_PSP
|
||||
#define XASH_ALLOW_SAVERESTORE_OFFSETS
|
||||
#define XASH_LIB LIB_PSP
|
||||
#endif
|
||||
|
||||
//
|
||||
@@ -193,11 +219,15 @@ Default build-depended cvar and constant values
|
||||
#endif // DEFAULT_FULLSCREEN
|
||||
|
||||
#ifndef DEFAULT_ACCELERATED_RENDERER
|
||||
#if XASH_MOBILE_PLATFORM
|
||||
#define DEFAULT_ACCELERATED_RENDERER "gles1"
|
||||
#else // !XASH_MOBILE_PLATFORM
|
||||
#define DEFAULT_ACCELERATED_RENDERER "gl"
|
||||
#endif // !XASH_MOBILE_PLATFORM
|
||||
#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
|
||||
|
||||
@@ -26,7 +26,9 @@ GNU General Public License for more details.
|
||||
#include <sys/syslimits.h>
|
||||
#define OS_LIB_EXT "dylib"
|
||||
#define OPEN_COMMAND "open"
|
||||
#else
|
||||
#elif XASH_PSP
|
||||
#define OS_LIB_EXT "prx"
|
||||
#else
|
||||
#define OS_LIB_EXT "so"
|
||||
#define OPEN_COMMAND "xdg-open"
|
||||
#endif
|
||||
@@ -74,6 +76,25 @@ GNU General Public License for more details.
|
||||
#define FreeLibrary( x ) (0)
|
||||
#define SetCurrentDirectory( x ) (!chdir( x ))
|
||||
#endif
|
||||
|
||||
#if XASH_PSP
|
||||
#include <unistd.h>
|
||||
#include <pspiofilemgr.h>
|
||||
#include "../engine/platform/psp/dll_psp.h"
|
||||
#define PATH_MAX 1024
|
||||
#define PATH_SPLITTER "/"
|
||||
#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 )
|
||||
#define SetCurrentDirectory( x ) ( !sceIoChdir( x ) )
|
||||
#define LoadLibrary( x ) ( 0 )
|
||||
#define GetProcAddress( x, y ) ( 0 )
|
||||
#define FreeLibrary( x ) ( 0 )
|
||||
// #define LoadLibrary( x ) dlopen( x, RTLD_NOW )
|
||||
// #define GetProcAddress( x, y ) dlsym( x, y )
|
||||
// #define FreeLibrary( x ) dlclose( x )
|
||||
#endif
|
||||
|
||||
//#define MAKEWORD( a, b ) ((short int)(((unsigned char)(a))|(((short int)((unsigned char)(b)))<<8)))
|
||||
#define max( a, b ) (((a) > (b)) ? (a) : (b))
|
||||
#define min( a, b ) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
@@ -136,6 +136,9 @@ typedef void (*setpair_t)( const char *key, const void *value, void *buffer, voi
|
||||
// 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
|
||||
@@ -143,6 +146,7 @@ typedef void (*setpair_t)( const char *key, const void *value, void *buffer, voi
|
||||
#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
|
||||
|
||||
@@ -103,6 +103,12 @@ CL_GetEntityByIndex
|
||||
Render callback for studio models
|
||||
====================
|
||||
*/
|
||||
#if XASH_OPT
|
||||
cl_entity_t *pfnCL_GetEntityByIndex( int index )
|
||||
{
|
||||
return CL_GetEntityByIndex( index );
|
||||
}
|
||||
#else
|
||||
cl_entity_t *CL_GetEntityByIndex( int index )
|
||||
{
|
||||
if( !clgame.entities ) // not in game yet
|
||||
@@ -116,7 +122,7 @@ cl_entity_t *CL_GetEntityByIndex( int index )
|
||||
|
||||
return CL_EDICT_NUM( index );
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
================
|
||||
CL_ModelHandle
|
||||
@@ -124,13 +130,19 @@ CL_ModelHandle
|
||||
get model handle by index
|
||||
================
|
||||
*/
|
||||
#if XASH_OPT
|
||||
model_t *pfnCL_ModelHandle( int modelindex )
|
||||
{
|
||||
return CL_ModelHandle( modelindex );
|
||||
}
|
||||
#else
|
||||
model_t *CL_ModelHandle( int modelindex )
|
||||
{
|
||||
if( modelindex < 0 || modelindex >= MAX_MODELS )
|
||||
return NULL;
|
||||
return cl.models[modelindex];
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
====================
|
||||
CL_IsThirdPerson
|
||||
@@ -3807,7 +3819,11 @@ static cl_enginefunc_t gEngfuncs =
|
||||
pfnIsNoClipping,
|
||||
CL_GetLocalPlayer,
|
||||
CL_GetViewModel,
|
||||
#if XASH_OPT
|
||||
pfnCL_GetEntityByIndex,
|
||||
#else
|
||||
CL_GetEntityByIndex,
|
||||
#endif
|
||||
pfnGetClientTime,
|
||||
pfnCalcShake,
|
||||
pfnApplyShake,
|
||||
|
||||
@@ -16,9 +16,11 @@ GNU General Public License for more details.
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
|
||||
#if XASH_LOW_MEMORY
|
||||
#if XASH_LOW_MEMORY == 0
|
||||
#define NET_TIMINGS 1024
|
||||
#else
|
||||
#elif XASH_LOW_MEMORY == 1
|
||||
#define NET_TIMINGS 256
|
||||
#elif XASH_LOW_MEMORY == 2
|
||||
#define NET_TIMINGS 64
|
||||
#endif
|
||||
#define NET_TIMINGS_MASK (NET_TIMINGS - 1)
|
||||
|
||||
@@ -271,7 +271,11 @@ static render_api_t gRenderAPI =
|
||||
pfnFileBufferCRC32,
|
||||
COM_CompareFileTime,
|
||||
Host_Error,
|
||||
#if XASH_OPT
|
||||
(void*)pfnCL_ModelHandle,
|
||||
#else
|
||||
(void*)CL_ModelHandle,
|
||||
#endif
|
||||
pfnTime,
|
||||
Cvar_Set,
|
||||
S_FadeMusicVolume,
|
||||
|
||||
@@ -709,7 +709,11 @@ dlight_t *CL_GetEntityLight( int number );
|
||||
//
|
||||
// cl_cmds.c
|
||||
//
|
||||
#ifdef XASH_PSP
|
||||
void CL_Quit_f( void );
|
||||
#else
|
||||
void CL_Quit_f( void ) NORETURN;
|
||||
#endif
|
||||
void CL_ScreenShot_f( void );
|
||||
void CL_SnapShot_f( void );
|
||||
void CL_PlayCDTrack_f( void );
|
||||
@@ -821,7 +825,12 @@ void CL_TextMessageParse( byte *pMemFile, int fileSize );
|
||||
client_textmessage_t *CL_TextMessageGet( const char *pName );
|
||||
int pfnDecalIndexFromName( const char *szDecalName );
|
||||
int pfnIndexFromTrace( struct pmtrace_s *pTrace );
|
||||
#if XASH_OPT
|
||||
#define CL_ModelHandle( modelindex ) ( ( ( modelindex ) < 0 || ( modelindex ) >= MAX_MODELS ) ? NULL : cl.models[( modelindex )] )
|
||||
model_t *pfnCL_ModelHandle( int modelindex );
|
||||
#else
|
||||
model_t *CL_ModelHandle( int modelindex );
|
||||
#endif
|
||||
void NetAPI_CancelAllRequests( void );
|
||||
int CL_FindModelIndex( const char *m );
|
||||
cl_entity_t *CL_GetLocalPlayer( void );
|
||||
|
||||
@@ -1788,13 +1788,20 @@ void Key_Console( int key )
|
||||
}
|
||||
|
||||
// console scrolling
|
||||
#if XASH_PSP
|
||||
if( key == K_JOY2 )
|
||||
#else
|
||||
if( key == K_PGUP )
|
||||
#endif
|
||||
{
|
||||
Con_PageUp( 1 );
|
||||
return;
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
if( key == K_JOY1 )
|
||||
#else
|
||||
if( key == K_PGDN )
|
||||
#endif
|
||||
{
|
||||
Con_PageDown( 1 );
|
||||
return;
|
||||
|
||||
@@ -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
|
||||
@@ -1973,3 +1991,5 @@ void Touch_Shutdown( void )
|
||||
touch.initialized = false;
|
||||
Mem_FreePool( &touch.mempool );
|
||||
}
|
||||
|
||||
#endif /* XASH_NO_TOUCH */
|
||||
|
||||
@@ -61,10 +61,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( CVAR_TO_BOOL(touch_enable) )
|
||||
ret |= INPUT_DEVICE_TOUCH;
|
||||
|
||||
#endif
|
||||
if( Joy_IsActive() ) // connected or enabled
|
||||
ret |= INPUT_DEVICE_JOYSTICK;
|
||||
|
||||
@@ -93,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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +200,7 @@ void IN_ToggleClientMouse( int newstate, int oldstate )
|
||||
else if( newstate == key_game )
|
||||
{
|
||||
// reset mouse pos, so cancel effect in game
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 )
|
||||
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) && !defined( XASH_NO_TOUCH )
|
||||
if( CVAR_TO_BOOL( touch_enable ) )
|
||||
{
|
||||
SDL_SetRelativeMouseMode( SDL_FALSE );
|
||||
@@ -277,7 +281,7 @@ void IN_ActivateMouse( qboolean force )
|
||||
{
|
||||
if( in_mouse_suspended )
|
||||
{
|
||||
#ifdef XASH_SDL
|
||||
#if defined( XASH_SDL ) && !defined( XASH_NO_TOUCH )
|
||||
/// TODO: Platform_ShowCursor
|
||||
if( !touch_emulate )
|
||||
SDL_ShowCursor( SDL_FALSE );
|
||||
@@ -372,6 +376,7 @@ void IN_MouseEvent( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifndef XASH_NO_TOUCH
|
||||
// touch emu: handle motion
|
||||
if( CVAR_TO_BOOL( touch_emulate ))
|
||||
{
|
||||
@@ -380,7 +385,7 @@ void IN_MouseEvent( void )
|
||||
else
|
||||
Touch_KeyEvent( K_MOUSE1, 2 );
|
||||
}
|
||||
|
||||
#endif
|
||||
if( !in_mouseinitialized || !in_mouseactive )
|
||||
return;
|
||||
|
||||
@@ -396,9 +401,10 @@ void IN_MouseEvent( void )
|
||||
Platform_GetMousePos(&x, &y);
|
||||
if( host.mouse_visible )
|
||||
SDL_ShowCursor( SDL_TRUE );
|
||||
#ifndef XASH_NO_TOUCH
|
||||
else if( !CVAR_TO_BOOL( touch_emulate ) )
|
||||
SDL_ShowCursor( SDL_FALSE );
|
||||
|
||||
#endif
|
||||
if( x < host.window_center_x / 2 ||
|
||||
y < host.window_center_y / 2 ||
|
||||
x > host.window_center_x + host.window_center_x / 2 ||
|
||||
|
||||
@@ -519,8 +519,11 @@ void Key_Init( void )
|
||||
|
||||
// setup default binding. "unbindall" from config.cfg will be reset it
|
||||
for( kn = keynames; kn->name; kn++ ) Key_SetBinding( kn->keynum, kn->binding );
|
||||
|
||||
#if XASH_PSP
|
||||
osk_enable = Cvar_Get( "osk_enable", "1", FCVAR_ARCHIVE, "enable built-in on-screen keyboard" );
|
||||
#else
|
||||
osk_enable = Cvar_Get( "osk_enable", "0", FCVAR_ARCHIVE, "enable built-in on-screen keyboard" );
|
||||
#endif
|
||||
key_rotate = Cvar_Get( "key_rotate", "0", FCVAR_ARCHIVE, "rotate arrow keys (0-3)" );
|
||||
|
||||
}
|
||||
|
||||
@@ -268,7 +268,11 @@ static ref_api_t gEngfuncs =
|
||||
|
||||
CL_GetLocalPlayer,
|
||||
CL_GetViewModel,
|
||||
#if XASH_OPT
|
||||
pfnCL_GetEntityByIndex,
|
||||
#else
|
||||
CL_GetEntityByIndex,
|
||||
#endif
|
||||
R_BeamGetEntity,
|
||||
CL_GetWaterEntity,
|
||||
CL_AddVisibleEntity,
|
||||
@@ -295,7 +299,11 @@ static ref_api_t gEngfuncs =
|
||||
|
||||
Mod_ForName,
|
||||
pfnMod_Extradata,
|
||||
#if XASH_OPT
|
||||
pfnCL_ModelHandle,
|
||||
#else
|
||||
CL_ModelHandle,
|
||||
#endif
|
||||
pfnMod_GetCurrentLoadingModel,
|
||||
pfnMod_SetCurrentLoadingModel,
|
||||
|
||||
|
||||
@@ -466,8 +466,14 @@ void VOX_LoadSound( channel_t *pchan, const char *pszin )
|
||||
|
||||
// lookup actual string in g_Sentences,
|
||||
// set pointer to string data
|
||||
#ifdef XASH_PSP
|
||||
if( pszin[0] == '#' )
|
||||
psz = VOX_LookupString( pszin + 1, NULL );
|
||||
else
|
||||
psz = VOX_LookupString( pszin, NULL );
|
||||
#else
|
||||
psz = VOX_LookupString( pszin, NULL );
|
||||
|
||||
#endif
|
||||
if( !psz )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "VOX_LoadSound: no such sentence %s\n", pszin );
|
||||
|
||||
@@ -17,6 +17,7 @@ GNU General Public License for more details.
|
||||
#include "base_cmd.h"
|
||||
#include "cdll_int.h"
|
||||
|
||||
#ifdef XASH_HASHED_VARS
|
||||
// TODO: use another hash function, as COM_HashKey depends on string length
|
||||
#define HASH_SIZE 128 // 128 * 4 * 4 == 2048 bytes
|
||||
static base_command_hashmap_t *hashed_cmds[HASH_SIZE];
|
||||
@@ -285,3 +286,5 @@ void BaseCmd_Test_f( void )
|
||||
Con_Printf( "BaseCmd is valid\n" );
|
||||
}
|
||||
}
|
||||
|
||||
#endif // XASH_HASHED_VARS
|
||||
|
||||
@@ -93,6 +93,8 @@ const char *Q_buildos( void )
|
||||
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
|
||||
@@ -136,9 +138,9 @@ const char *Q_buildarch( void )
|
||||
#else
|
||||
"l";
|
||||
#endif
|
||||
#elif XASH_MIPS && XASH_BIG_ENDIAN
|
||||
#elif XASH_MIPS && defined XASH_BIG_ENDIAN
|
||||
archname = "mips";
|
||||
#elif XASH_MIPS && XASH_LITTLE_ENDIAN
|
||||
#elif XASH_MIPS && defined XASH_LITTLE_ENDIAN
|
||||
archname = "mipsel";
|
||||
#elif XASH_JS
|
||||
archname = "javascript";
|
||||
|
||||
@@ -138,10 +138,13 @@ typedef enum
|
||||
|
||||
#define CIN_MAIN 0
|
||||
#define CIN_LOGO 1
|
||||
#if XASH_PSP
|
||||
#define MAX_DECALS 256 // touching TE_DECAL messages, etc
|
||||
#define MAX_STATIC_ENTITIES 256 // static entities that moved on the client when level is spawn
|
||||
#else
|
||||
#if XASH_LOW_MEMORY == 0
|
||||
#define MAX_DECALS 512 // touching TE_DECAL messages, etc
|
||||
#define MAX_STATIC_ENTITIES 3096 // static entities that moved on the client when level is spawn
|
||||
|
||||
#elif XASH_LOW_MEMORY == 2
|
||||
#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
|
||||
@@ -149,6 +152,7 @@ typedef enum
|
||||
#define MAX_DECALS 512 // touching TE_DECAL messages, etc
|
||||
#define MAX_STATIC_ENTITIES 128 // static entities that moved on the client when level is spawn
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// filesystem flags
|
||||
#define FS_STATIC_PATH ( 1U << 0 ) // FS_ClearSearchPath will be ignore this path
|
||||
@@ -240,7 +244,9 @@ typedef struct gameinfo_s
|
||||
int max_tents; // min temp ents is 300, max is 2048
|
||||
int max_beams; // min beams is 64, max beams is 512
|
||||
int max_particles; // min particles is 4096, max particles is 32768
|
||||
|
||||
#ifdef XASH_PSP
|
||||
char game_dll_psp[64];
|
||||
#endif
|
||||
char game_dll_linux[64]; // custom path for game.dll
|
||||
char game_dll_osx[64]; // custom path for game.dll
|
||||
|
||||
@@ -871,7 +877,12 @@ int R_CreateDecalList( struct decallist_s *pList );
|
||||
void R_ClearAllDecals( void );
|
||||
void CL_ClearStaticEntities( void );
|
||||
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position );
|
||||
#if XASH_OPT
|
||||
#define CL_GetEntityByIndex( index ) ( ( !clgame.entities ) ? NULL : ( ( ( index ) < 0 || ( index ) >= clgame.maxEntities ) ? NULL : ( ( ( index ) == 0 ) ? clgame.entities : ( clgame.entities + ( index ) ) ) ) )
|
||||
struct cl_entity_s *pfnCL_GetEntityByIndex( int index );
|
||||
#else
|
||||
struct cl_entity_s *CL_GetEntityByIndex( int index );
|
||||
#endif
|
||||
struct player_info_s *CL_GetPlayerInfo( int playerIndex );
|
||||
void CL_ServerCommand( qboolean reliable, char *fmt, ... ) _format( 2 );
|
||||
void CL_HudMessage( const char *pMessage );
|
||||
|
||||
@@ -23,6 +23,10 @@ GNU General Public License for more details.
|
||||
#elif XASH_DOS4GW
|
||||
#include <direct.h>
|
||||
#include <errno.h>
|
||||
#elif XASH_PSP
|
||||
#include <pspiofilemgr.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
@@ -80,16 +84,25 @@ typedef struct wadtype_s
|
||||
|
||||
struct file_s
|
||||
{
|
||||
#if XASH_PSP
|
||||
SceUID handle; // psp file descriptor
|
||||
#else
|
||||
int handle; // file descriptor
|
||||
#endif
|
||||
fs_offset_t real_length; // uncompressed file size (for files opened in "read" mode)
|
||||
fs_offset_t position; // current position in the file
|
||||
fs_offset_t offset; // offset into the package (0 if external file)
|
||||
int ungetc; // single stored character from ungetc, cleared to EOF when read
|
||||
#if !XASH_PSP /* unused */
|
||||
time_t filetime; // pak, wad or real filetime
|
||||
#endif
|
||||
// contents buffer
|
||||
fs_offset_t buff_ind, buff_len; // buffer current index and length
|
||||
byte buff[FILE_BUFF_SIZE]; // intermediate buffer
|
||||
#ifdef XASH_REDUCE_FD
|
||||
#if XASH_PSP
|
||||
qboolean backup_hold;
|
||||
#endif
|
||||
const char *backup_path;
|
||||
fs_offset_t backup_position;
|
||||
uint backup_options;
|
||||
@@ -110,7 +123,11 @@ struct wfile_s
|
||||
typedef struct pack_s
|
||||
{
|
||||
string filename;
|
||||
#if XASH_PSP
|
||||
SceUID handle;
|
||||
#else
|
||||
int handle;
|
||||
#endif
|
||||
int numfiles;
|
||||
time_t filetime; // common for all packed files
|
||||
dpackfile_t *files;
|
||||
@@ -128,7 +145,11 @@ typedef struct zipfile_s
|
||||
typedef struct zip_s
|
||||
{
|
||||
string filename;
|
||||
#if XASH_PSP
|
||||
SceUID handle;
|
||||
#else
|
||||
int handle;
|
||||
#endif
|
||||
int numfiles;
|
||||
time_t filetime;
|
||||
zipfile_t *files;
|
||||
@@ -168,7 +189,20 @@ static void FS_EnsureOpenFile( file_t *file )
|
||||
|
||||
if( file && !file->backup_path )
|
||||
return;
|
||||
|
||||
#if XASH_PSP
|
||||
if( fs_last_readfile && (fs_last_readfile->handle != -1) && (fs_last_readfile->backup_hold == false) )
|
||||
{
|
||||
fs_last_readfile->backup_position = sceIoLseek( fs_last_readfile->handle, 0, PSP_SEEK_CUR );
|
||||
sceIoClose( fs_last_readfile->handle );
|
||||
fs_last_readfile->handle = -1;
|
||||
}
|
||||
fs_last_readfile = file;
|
||||
if( file && (file->handle == -1) )
|
||||
{
|
||||
file->handle = sceIoOpen( file->backup_path, file->backup_options, 0666 );
|
||||
sceIoLseek( file->handle, file->backup_position, PSP_SEEK_SET );
|
||||
}
|
||||
#else
|
||||
if( fs_last_readfile && (fs_last_readfile->handle != -1) )
|
||||
{
|
||||
fs_last_readfile->backup_position = lseek( fs_last_readfile->handle, 0, SEEK_CUR );
|
||||
@@ -181,13 +215,23 @@ static void FS_EnsureOpenFile( file_t *file )
|
||||
file->handle = open( file->backup_path, file->backup_options );
|
||||
lseek( file->handle, file->backup_position, SEEK_SET );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void FS_EnsureOpenZip( zip_t *zip )
|
||||
{
|
||||
if( fs_last_zip == zip )
|
||||
return;
|
||||
|
||||
#if XASH_PSP
|
||||
if( fs_last_zip && (fs_last_zip->handle != -1) )
|
||||
{
|
||||
sceIoClose( fs_last_zip->handle );
|
||||
fs_last_zip->handle = -1;
|
||||
}
|
||||
fs_last_zip = zip;
|
||||
if( zip && (zip->handle == -1) )
|
||||
zip->handle = sceIoOpen( zip->filename, PSP_O_RDONLY, 0666 );
|
||||
#else
|
||||
if( fs_last_zip && (fs_last_zip->handle != -1) )
|
||||
{
|
||||
close( fs_last_zip->handle );
|
||||
@@ -196,6 +240,7 @@ static void FS_EnsureOpenZip( zip_t *zip )
|
||||
fs_last_zip = zip;
|
||||
if( zip && (zip->handle == -1) )
|
||||
zip->handle = open( zip->filename, O_RDONLY|O_BINARY );
|
||||
#endif
|
||||
}
|
||||
|
||||
static void FS_BackupFileName( file_t *file, const char *path, uint options )
|
||||
@@ -207,7 +252,11 @@ static void FS_BackupFileName( file_t *file, const char *path, uint options )
|
||||
if( file == fs_last_readfile )
|
||||
FS_EnsureOpenFile( NULL );
|
||||
}
|
||||
#if XASH_PSP
|
||||
else if( options == PSP_O_RDONLY )
|
||||
#else
|
||||
else if( options == O_RDONLY || options == (O_RDONLY|O_BINARY) )
|
||||
#endif
|
||||
{
|
||||
file->backup_path = copystring( path );
|
||||
file->backup_options = options;
|
||||
@@ -325,6 +374,9 @@ static void listdirectory( stringlist_t *list, const char *path, qboolean lowerc
|
||||
char pattern[4096];
|
||||
struct _finddata_t n_file;
|
||||
int hFile;
|
||||
#elif XASH_PSP
|
||||
SceUID dir;
|
||||
SceIoDirent entry;
|
||||
#else
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
@@ -343,6 +395,20 @@ static void listdirectory( stringlist_t *list, const char *path, qboolean lowerc
|
||||
while( _findnext( hFile, &n_file ) == 0 )
|
||||
stringlistappend( list, n_file.name );
|
||||
_findclose( hFile );
|
||||
#elif XASH_PSP
|
||||
if( ( dir = sceIoDopen( path ) ) < 0 )
|
||||
return;
|
||||
|
||||
// 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;
|
||||
stringlistappend( list, entry.d_name );
|
||||
}
|
||||
sceIoDclose( dir );
|
||||
#else
|
||||
if( !( dir = opendir( path ) ) )
|
||||
return;
|
||||
@@ -405,7 +471,7 @@ static const char *FS_FixFileCase( const char *path )
|
||||
|
||||
out[i] = 0;
|
||||
return out;
|
||||
#elif !XASH_WIN32 && !XASH_IOS // assume case insensitive
|
||||
#elif !XASH_WIN32 && !XASH_IOS && !XASH_PSP // assume case insensitive
|
||||
DIR *dir; struct dirent *entry;
|
||||
char path2[PATH_MAX], *fname;
|
||||
|
||||
@@ -524,7 +590,11 @@ void FS_CreatePath( char *path )
|
||||
// create the directory
|
||||
save = *ofs;
|
||||
*ofs = 0;
|
||||
#if XASH_PSP
|
||||
sceIoMkdir( path, 0777 );
|
||||
#else
|
||||
_mkdir( path );
|
||||
#endif
|
||||
*ofs = save;
|
||||
}
|
||||
}
|
||||
@@ -585,14 +655,20 @@ of the list so they override previous pack files.
|
||||
pack_t *FS_LoadPackPAK( const char *packfile, int *error )
|
||||
{
|
||||
dpackheader_t header;
|
||||
#if XASH_PSP
|
||||
SceUID packhandle;
|
||||
#else
|
||||
int packhandle;
|
||||
#endif
|
||||
int i, numpackfiles;
|
||||
pack_t *pack;
|
||||
dpackfile_t *info;
|
||||
|
||||
#if XASH_PSP
|
||||
packhandle = sceIoOpen( packfile, PSP_O_RDONLY, 0666 );
|
||||
#else
|
||||
packhandle = open( packfile, O_RDONLY|O_BINARY );
|
||||
|
||||
#if !XASH_WIN32
|
||||
#endif
|
||||
#if !XASH_WIN32 && !XASH_PSP
|
||||
if( packhandle < 0 )
|
||||
{
|
||||
const char *fpackfile = FS_FixFileCase( packfile );
|
||||
@@ -607,14 +683,20 @@ pack_t *FS_LoadPackPAK( const char *packfile, int *error )
|
||||
if( error ) *error = PAK_LOAD_COULDNT_OPEN;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
sceIoRead( packhandle, (void *)&header, sizeof( header ));
|
||||
#else
|
||||
read( packhandle, (void *)&header, sizeof( header ));
|
||||
|
||||
#endif
|
||||
if( header.ident != IDPACKV1HEADER )
|
||||
{
|
||||
Con_Reportf( "%s is not a packfile. Ignored.\n", packfile );
|
||||
if( error ) *error = PAK_LOAD_BAD_HEADER;
|
||||
#if XASH_PSP
|
||||
sceIoClose( packhandle );
|
||||
#else
|
||||
close( packhandle );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -622,7 +704,11 @@ pack_t *FS_LoadPackPAK( const char *packfile, int *error )
|
||||
{
|
||||
Con_Reportf( S_ERROR "%s has an invalid directory size. Ignored.\n", packfile );
|
||||
if( error ) *error = PAK_LOAD_BAD_FOLDERS;
|
||||
#if XASH_PSP
|
||||
sceIoClose( packhandle );
|
||||
#else
|
||||
close( packhandle );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -632,7 +718,11 @@ pack_t *FS_LoadPackPAK( const char *packfile, int *error )
|
||||
{
|
||||
Con_Reportf( S_ERROR "%s has too many files ( %i ). Ignored.\n", packfile, numpackfiles );
|
||||
if( error ) *error = PAK_LOAD_TOO_MANY_FILES;
|
||||
#if XASH_PSP
|
||||
sceIoClose( packhandle );
|
||||
#else
|
||||
close( packhandle );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -640,18 +730,33 @@ pack_t *FS_LoadPackPAK( const char *packfile, int *error )
|
||||
{
|
||||
Con_Reportf( "%s has no files. Ignored.\n", packfile );
|
||||
if( error ) *error = PAK_LOAD_NO_FILES;
|
||||
#if XASH_PSP
|
||||
sceIoClose( packhandle );
|
||||
#else
|
||||
close( packhandle );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info = (dpackfile_t *)Mem_Malloc( fs_mempool, sizeof( *info ) * numpackfiles );
|
||||
#if XASH_PSP
|
||||
sceIoLseek( packhandle, header.dirofs, PSP_SEEK_SET );
|
||||
#else
|
||||
lseek( packhandle, header.dirofs, SEEK_SET );
|
||||
|
||||
#endif
|
||||
#if XASH_PSP
|
||||
if( header.dirlen != sceIoRead( packhandle, (void *)info, header.dirlen ) )
|
||||
#else
|
||||
if( header.dirlen != read( packhandle, (void *)info, header.dirlen ))
|
||||
#endif
|
||||
{
|
||||
Con_Reportf( "%s is an incomplete PAK, not loading\n", packfile );
|
||||
if( error ) *error = PAK_LOAD_CORRUPTED;
|
||||
#if XASH_PSP
|
||||
sceIoClose( packhandle );
|
||||
#else
|
||||
close( packhandle );
|
||||
#endif
|
||||
Mem_Free( info );
|
||||
return NULL;
|
||||
}
|
||||
@@ -669,7 +774,11 @@ pack_t *FS_LoadPackPAK( const char *packfile, int *error )
|
||||
|
||||
#ifdef XASH_REDUCE_FD
|
||||
// will reopen when needed
|
||||
close(pack->handle);
|
||||
#if XASH_PSP
|
||||
sceIoClose( packhandle );
|
||||
#else
|
||||
close( packhandle );
|
||||
#endif
|
||||
pack->handle = -1;
|
||||
#endif
|
||||
|
||||
@@ -689,10 +798,12 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
|
||||
zipfile_t *info = NULL;
|
||||
char filename_buffer[MAX_SYSPATH];
|
||||
zip_t *zip = (zip_t *)Mem_Calloc( fs_mempool, sizeof( zip_t ) );
|
||||
|
||||
#if XASH_PSP
|
||||
zip->handle = sceIoOpen( zipfile, PSP_O_RDONLY, 0666 );
|
||||
#else
|
||||
zip->handle = open( zipfile, O_RDONLY|O_BINARY );
|
||||
|
||||
#if !XASH_WIN32
|
||||
#endif
|
||||
#if !XASH_WIN32 && !XASH_PSP
|
||||
if( zip->handle < 0 )
|
||||
{
|
||||
const char *fzipfile = FS_FixFileCase( zipfile );
|
||||
@@ -711,9 +822,11 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
|
||||
Zip_Close( zip );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
length = sceIoLseek( zip->handle, 0, PSP_SEEK_END );
|
||||
#else
|
||||
length = lseek( zip->handle, 0, SEEK_END );
|
||||
|
||||
#endif
|
||||
if( length > UINT_MAX )
|
||||
{
|
||||
Con_Reportf( S_ERROR "%s bigger than 4GB.\n", zipfile );
|
||||
@@ -724,11 +837,13 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
|
||||
Zip_Close( zip );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
sceIoLseek( zip->handle, 0, PSP_SEEK_SET );
|
||||
sceIoRead( zip->handle, &signature, sizeof( signature ) );
|
||||
#else
|
||||
lseek( zip->handle, 0, SEEK_SET );
|
||||
|
||||
read( zip->handle, &signature, sizeof( signature ) );
|
||||
|
||||
#endif
|
||||
if( signature == ZIP_HEADER_EOCD )
|
||||
{
|
||||
Con_Reportf( S_WARN "%s has no files. Ignored.\n", zipfile );
|
||||
@@ -752,14 +867,22 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
|
||||
}
|
||||
|
||||
// Find oecd
|
||||
#if XASH_PSP
|
||||
sceIoLseek( zip->handle, 0, PSP_SEEK_SET );
|
||||
#else
|
||||
lseek( zip->handle, 0, SEEK_SET );
|
||||
#endif
|
||||
filepos = length;
|
||||
|
||||
while ( filepos > 0 )
|
||||
{
|
||||
#if XASH_PSP
|
||||
sceIoLseek( zip->handle, filepos, PSP_SEEK_SET );
|
||||
sceIoRead( zip->handle, &signature, sizeof( signature ) );
|
||||
#else
|
||||
lseek( zip->handle, filepos, SEEK_SET );
|
||||
read( zip->handle, &signature, sizeof( signature ) );
|
||||
|
||||
#endif
|
||||
if( signature == ZIP_HEADER_EOCD )
|
||||
break;
|
||||
|
||||
@@ -776,19 +899,27 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
|
||||
Zip_Close( zip );
|
||||
return NULL;
|
||||
}
|
||||
#if XASH_PSP
|
||||
sceIoRead( zip->handle, &header_eocd, sizeof( zip_header_eocd_t ) );
|
||||
|
||||
// Move to CDF start
|
||||
sceIoLseek( zip->handle, header_eocd.central_directory_offset, PSP_SEEK_SET );
|
||||
#else
|
||||
read( zip->handle, &header_eocd, sizeof( zip_header_eocd_t ) );
|
||||
|
||||
// Move to CDF start
|
||||
lseek( zip->handle, header_eocd.central_directory_offset, SEEK_SET );
|
||||
|
||||
#endif
|
||||
// Calc count of files in archive
|
||||
info = (zipfile_t *)Mem_Calloc( fs_mempool, sizeof( zipfile_t ) * header_eocd.total_central_directory_record );
|
||||
|
||||
for( i = 0; i < header_eocd.total_central_directory_record; i++ )
|
||||
{
|
||||
#if XASH_PSP
|
||||
sceIoRead( zip->handle, &header_cdf, sizeof( header_cdf ) );
|
||||
#else
|
||||
read( zip->handle, &header_cdf, sizeof( header_cdf ) );
|
||||
|
||||
#endif
|
||||
if( header_cdf.signature != ZIP_HEADER_CDF )
|
||||
{
|
||||
Con_Reportf( S_ERROR "CDF signature mismatch in %s. Zip file corrupted.\n", zipfile );
|
||||
@@ -804,7 +935,11 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
|
||||
if( header_cdf.uncompressed_size && header_cdf.filename_len && ( header_cdf.filename_len < MAX_SYSPATH ) )
|
||||
{
|
||||
memset( &filename_buffer, '\0', MAX_SYSPATH );
|
||||
#if XASH_PSP
|
||||
sceIoRead( zip->handle, &filename_buffer, header_cdf.filename_len );
|
||||
#else
|
||||
read( zip->handle, &filename_buffer, header_cdf.filename_len );
|
||||
#endif
|
||||
Q_strncpy( info[numpackfiles].name, filename_buffer, MAX_SYSPATH );
|
||||
|
||||
info[numpackfiles].size = header_cdf.uncompressed_size;
|
||||
@@ -813,6 +948,15 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
|
||||
numpackfiles++;
|
||||
}
|
||||
else
|
||||
#if XASH_PSP
|
||||
sceIoLseek( zip->handle, header_cdf.filename_len, PSP_SEEK_CUR );
|
||||
|
||||
if( header_cdf.extrafield_len )
|
||||
sceIoLseek( zip->handle, header_cdf.extrafield_len, PSP_SEEK_CUR );
|
||||
|
||||
if( header_cdf.file_commentary_len )
|
||||
sceIoLseek( zip->handle, header_cdf.file_commentary_len, PSP_SEEK_CUR );
|
||||
#else
|
||||
lseek( zip->handle, header_cdf.filename_len, SEEK_CUR );
|
||||
|
||||
if( header_cdf.extrafield_len )
|
||||
@@ -820,15 +964,20 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
|
||||
|
||||
if( header_cdf.file_commentary_len )
|
||||
lseek( zip->handle, header_cdf.file_commentary_len, SEEK_CUR );
|
||||
#endif
|
||||
}
|
||||
|
||||
// recalculate offsets
|
||||
for( i = 0; i < numpackfiles; i++ )
|
||||
{
|
||||
zip_header_t header;
|
||||
|
||||
#if XASH_PSP
|
||||
sceIoLseek( zip->handle, info[i].offset, PSP_SEEK_SET );
|
||||
sceIoRead( zip->handle, &header, sizeof( header ) );
|
||||
#else
|
||||
lseek( zip->handle, info[i].offset, SEEK_SET );
|
||||
read( zip->handle, &header, sizeof( header ) );
|
||||
#endif
|
||||
info[i].flags = header.compression_flags;
|
||||
info[i].offset = info[i].offset + header.filename_len + header.extrafield_len + sizeof( header );
|
||||
}
|
||||
@@ -840,8 +989,13 @@ static zip_t *FS_LoadZip( const char *zipfile, int *error )
|
||||
|
||||
#ifdef XASH_REDUCE_FD
|
||||
// will reopen when needed
|
||||
close(zip->handle);
|
||||
#if XASH_PSP
|
||||
sceIoClose( zip->handle );
|
||||
zip->handle = -1;
|
||||
#else
|
||||
close( zip->handle );
|
||||
zip->handle = -1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if( error )
|
||||
@@ -858,10 +1012,13 @@ void Zip_Close( zip_t *zip )
|
||||
Mem_Free( zip->files );
|
||||
|
||||
FS_EnsureOpenZip( NULL );
|
||||
|
||||
#if XASH_PSP
|
||||
if( zip->handle >= 0 )
|
||||
sceIoClose( zip->handle );
|
||||
#else
|
||||
if( zip->handle >= 0 )
|
||||
close( zip->handle );
|
||||
|
||||
#endif
|
||||
Mem_Free( zip );
|
||||
}
|
||||
|
||||
@@ -885,10 +1042,13 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game
|
||||
file = &search->zip->files[index];
|
||||
|
||||
FS_EnsureOpenZip( search->zip );
|
||||
|
||||
#if XASH_PSP
|
||||
if( sceIoLseek( search->zip->handle, file->offset, PSP_SEEK_SET ) == -1 )
|
||||
return NULL;
|
||||
#else
|
||||
if( lseek( search->zip->handle, file->offset, SEEK_SET ) == -1 )
|
||||
return NULL;
|
||||
|
||||
#endif
|
||||
/*if( read( search->zip->handle, &header, sizeof( header ) ) < 0 )
|
||||
return NULL;
|
||||
|
||||
@@ -902,8 +1062,11 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game
|
||||
{
|
||||
decompressed_buffer = Mem_Malloc( fs_mempool, file->size + 1 );
|
||||
decompressed_buffer[file->size] = '\0';
|
||||
|
||||
#if XASH_PSP
|
||||
sceIoRead( search->zip->handle, decompressed_buffer, file->size );
|
||||
#else
|
||||
read( search->zip->handle, decompressed_buffer, file->size );
|
||||
#endif
|
||||
#if 0
|
||||
CRC32_Init( &test_crc );
|
||||
CRC32_ProcessBuffer( &test_crc, decompressed_buffer, file->size );
|
||||
@@ -927,9 +1090,11 @@ static byte *Zip_LoadFile( const char *path, fs_offset_t *sizeptr, qboolean game
|
||||
compressed_buffer = Mem_Malloc( fs_mempool, file->compressed_size + 1 );
|
||||
decompressed_buffer = Mem_Malloc( fs_mempool, file->size + 1 );
|
||||
decompressed_buffer[file->size] = '\0';
|
||||
|
||||
#if XASH_PSP
|
||||
sceIoRead( search->zip->handle, compressed_buffer, file->compressed_size );
|
||||
#else
|
||||
read( search->zip->handle, compressed_buffer, file->compressed_size );
|
||||
|
||||
#endif
|
||||
memset( &decompress_stream, 0, sizeof( decompress_stream ) );
|
||||
|
||||
decompress_stream.total_in = decompress_stream.avail_in = file->compressed_size;
|
||||
@@ -1268,12 +1433,15 @@ void FS_AddGameHierarchy( const char *dir, uint flags )
|
||||
FS_AddGameDirectory( va( "%s/%s/", host.rodir, dir ), newFlags );
|
||||
FS_AllowDirectPaths( false );
|
||||
}
|
||||
|
||||
#if !XASH_PSP
|
||||
if( isGameDir )
|
||||
FS_AddGameDirectory( va( "%s/downloaded/", dir ), FS_NOWRITE_PATH | FS_CUSTOM_PATH );
|
||||
#endif
|
||||
FS_AddGameDirectory( va( "%s/", dir ), flags );
|
||||
#if !XASH_PSP
|
||||
if( isGameDir )
|
||||
FS_AddGameDirectory( va( "%s/custom/", dir ), FS_NOWRITE_PATH | FS_CUSTOM_PATH );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1302,8 +1470,13 @@ void FS_ClearSearchPath( void )
|
||||
{
|
||||
if( search->pack->files )
|
||||
Mem_Free( search->pack->files );
|
||||
#if XASH_PSP
|
||||
if( search->pack->handle >= 0 )
|
||||
sceIoClose( search->pack->handle );
|
||||
#else
|
||||
if( search->pack->handle >= 0 )
|
||||
close( search->pack->handle );
|
||||
#endif
|
||||
Mem_Free( search->pack );
|
||||
}
|
||||
|
||||
@@ -1477,8 +1650,10 @@ static void FS_WriteGameInfo( const char *filepath, gameinfo_t *GameInfo )
|
||||
|
||||
if( Q_strlen( GameInfo->game_dll_osx ))
|
||||
FS_Printf( f, "gamedll_osx\t\t\"%s\"\n", GameInfo->game_dll_osx );
|
||||
|
||||
|
||||
#if XASH_PSP
|
||||
if( Q_strlen( GameInfo->game_dll_psp ))
|
||||
FS_Printf( f, "gamedll_psp\t\t\"%s\"\n", GameInfo->game_dll_psp );
|
||||
#endif
|
||||
if( Q_strlen( GameInfo->iconpath ))
|
||||
FS_Printf( f, "icon\t\t\"%s\"\n", GameInfo->iconpath );
|
||||
|
||||
@@ -1545,7 +1720,9 @@ void FS_InitGameInfo( gameinfo_t *GameInfo, const char *gamedir )
|
||||
Q_strncpy( GameInfo->game_dll, "dlls/hl.dll", sizeof( GameInfo->game_dll ));
|
||||
Q_strncpy( GameInfo->game_dll_linux, "dlls/hl.so", sizeof( GameInfo->game_dll_linux ));
|
||||
Q_strncpy( GameInfo->game_dll_osx, "dlls/hl.dylib", sizeof( GameInfo->game_dll_osx ));
|
||||
|
||||
#if XASH_PSP
|
||||
Q_strncpy( GameInfo->game_dll_psp, "dlls/server.prx", sizeof( GameInfo->game_dll_psp ));
|
||||
#endif
|
||||
// .ico path
|
||||
Q_strncpy( GameInfo->iconpath, "game.ico", sizeof( GameInfo->iconpath ));
|
||||
|
||||
@@ -1562,6 +1739,9 @@ void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qbool
|
||||
{
|
||||
char *pfile = (char*) buf;
|
||||
qboolean found_linux = false, found_osx = false;
|
||||
#if XASH_PSP
|
||||
qboolean found_psp = false;
|
||||
#endif
|
||||
string token;
|
||||
|
||||
while(( pfile = COM_ParseFile( pfile, token )) != NULL )
|
||||
@@ -1617,6 +1797,14 @@ void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qbool
|
||||
pfile = COM_ParseFile( pfile, GameInfo->game_dll_osx );
|
||||
found_osx = true;
|
||||
}
|
||||
#if XASH_PSP
|
||||
// valid for both
|
||||
else if( !Q_stricmp( token, "gamedll_psp" ))
|
||||
{
|
||||
pfile = COM_ParseFile( pfile, GameInfo->game_dll_psp );
|
||||
found_psp = true;
|
||||
}
|
||||
#endif
|
||||
// valid for both
|
||||
else if( !Q_stricmp( token, "icon" ))
|
||||
{
|
||||
@@ -1759,7 +1947,8 @@ void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qbool
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if XASH_PSP
|
||||
if( !found_linux || !found_osx )
|
||||
{
|
||||
// just replace extension from dll to so/dylib
|
||||
@@ -1773,7 +1962,10 @@ void FS_ParseGenericGameInfo( gameinfo_t *GameInfo, const char *buf, const qbool
|
||||
if( !found_osx )
|
||||
Q_snprintf( GameInfo->game_dll_osx, sizeof( GameInfo->game_dll_osx ), "%s.dylib", gamedll );
|
||||
}
|
||||
|
||||
#else
|
||||
if( !found_psp )
|
||||
Q_snprintf( GameInfo->game_dll_psp, sizeof( GameInfo->game_dll_psp ), "dlls/server.prx" ); // force set
|
||||
#endif
|
||||
// make sure what gamedir is really exist
|
||||
if( !FS_SysFolderExists( va( "%s"PATH_SPLITTER"%s", host.rootdir, GameInfo->falldir )))
|
||||
GameInfo->falldir[0] = '\0';
|
||||
@@ -2027,7 +2219,7 @@ void FS_Init( void )
|
||||
Cmd_AddCommand( "fs_path", FS_Path_f, "show filesystem search pathes" );
|
||||
Cmd_AddCommand( "fs_clearpaths", FS_ClearPaths_f, "clear filesystem search pathes" );
|
||||
|
||||
#if !XASH_WIN32
|
||||
#if !XASH_WIN32 && !XASH_PSP
|
||||
if( Sys_CheckParm( "-casesensitive" ) )
|
||||
fs_caseinsensitive = false;
|
||||
|
||||
@@ -2156,12 +2348,30 @@ Internal function used to determine filetime
|
||||
*/
|
||||
static int FS_SysFileTime( const char *filename )
|
||||
{
|
||||
#if XASH_PSP
|
||||
SceIoStat buf;
|
||||
struct tm libc_tm;
|
||||
|
||||
if ( sceIoGetstat( filename, &buf ) < 0 )
|
||||
return -1;
|
||||
|
||||
libc_tm.tm_year = buf.st_mtime.year;
|
||||
libc_tm.tm_mon = buf.st_mtime.month;
|
||||
libc_tm.tm_mday = buf.st_mtime.day;
|
||||
libc_tm.tm_hour = buf.st_mtime.hour;
|
||||
libc_tm.tm_min = buf.st_mtime.minute;
|
||||
libc_tm.tm_sec = buf.st_mtime.second;
|
||||
libc_tm.tm_isdst = -1;
|
||||
|
||||
return mktime( &libc_tm );
|
||||
#else
|
||||
struct stat buf;
|
||||
|
||||
if( stat( filename, &buf ) == -1 )
|
||||
return -1;
|
||||
|
||||
return buf.st_mtime;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2176,7 +2386,53 @@ static file_t *FS_SysOpen( const char *filepath, const char *mode )
|
||||
file_t *file;
|
||||
int mod, opt;
|
||||
uint ind;
|
||||
#if XASH_PSP
|
||||
qboolean backup_hold = false;
|
||||
|
||||
// Hold file in open state
|
||||
if( mode[0] == '*' )
|
||||
{
|
||||
backup_hold = true;
|
||||
mode++;
|
||||
}
|
||||
|
||||
// Parse the mode string
|
||||
switch( mode[0] )
|
||||
{
|
||||
case 'r': // read
|
||||
mod = PSP_O_RDONLY;
|
||||
opt = 0;
|
||||
break;
|
||||
case 'w': // write
|
||||
mod = PSP_O_WRONLY;
|
||||
opt = PSP_O_CREAT | PSP_O_TRUNC;
|
||||
break;
|
||||
case 'a': // append
|
||||
mod = PSP_O_WRONLY;
|
||||
opt = PSP_O_CREAT | PSP_O_APPEND;
|
||||
break;
|
||||
case 'e': // edit
|
||||
mod = PSP_O_WRONLY;
|
||||
opt = PSP_O_CREAT;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( ind = 1; mode[ind] != '\0'; ind++ )
|
||||
{
|
||||
switch( mode[ind] )
|
||||
{
|
||||
case '+':
|
||||
mod = PSP_O_RDWR;
|
||||
break;
|
||||
case 'b': // not used
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Parse the mode string
|
||||
switch( mode[0] )
|
||||
{
|
||||
@@ -2214,14 +2470,23 @@ static file_t *FS_SysOpen( const char *filepath, const char *mode )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
file = (file_t *)Mem_Calloc( fs_mempool, sizeof( *file ));
|
||||
#if !XASH_PSP
|
||||
file->filetime = FS_SysFileTime( filepath );
|
||||
#endif
|
||||
file->ungetc = EOF;
|
||||
|
||||
#if XASH_PSP
|
||||
file->handle = sceIoOpen( filepath, mod|opt, 0666 );
|
||||
#else
|
||||
file->handle = open( filepath, mod|opt, 0666 );
|
||||
#endif
|
||||
|
||||
#if !XASH_WIN32
|
||||
#if XASH_PSP
|
||||
file->backup_hold = backup_hold;
|
||||
if( file->handle >= 0 )
|
||||
FS_BackupFileName( file, filepath, mod|opt );
|
||||
#elif !XASH_WIN32
|
||||
if( file->handle < 0 )
|
||||
{
|
||||
const char *ffilepath = FS_FixFileCase( filepath );
|
||||
@@ -2234,22 +2499,29 @@ static file_t *FS_SysOpen( const char *filepath, const char *mode )
|
||||
FS_BackupFileName( file, filepath, mod|opt );
|
||||
#endif
|
||||
|
||||
|
||||
if( file->handle < 0 )
|
||||
{
|
||||
Mem_Free( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#if XASH_PSP
|
||||
file->real_length = sceIoLseek( file->handle, 0, PSP_SEEK_END );
|
||||
#else
|
||||
file->real_length = lseek( file->handle, 0, SEEK_END );
|
||||
|
||||
#endif
|
||||
// uncomment do disable write
|
||||
//if( opt & O_CREAT )
|
||||
// return NULL;
|
||||
|
||||
// For files opened in append mode, we start at the end of the file
|
||||
if( opt & O_APPEND ) file->position = file->real_length;
|
||||
#if XASH_PSP
|
||||
else sceIoLseek( file->handle, 0, PSP_SEEK_SET );
|
||||
#else
|
||||
else lseek( file->handle, 0, SEEK_SET );
|
||||
#endif
|
||||
|
||||
return file;
|
||||
}
|
||||
@@ -2270,6 +2542,15 @@ static file_t *FS_OpenHandle( const char *syspath, int handle, fs_offset_t offse
|
||||
{
|
||||
file_t *file = (file_t *)Mem_Calloc( fs_mempool, sizeof( file_t ));
|
||||
#ifndef XASH_REDUCE_FD
|
||||
#if XASH_PSP
|
||||
file->handle = sceIoOpen( syspath, PSP_O_RDONLY, 0666 );
|
||||
|
||||
if( sceIoLseek( file->handle, offset, SEEK_SET ) == -1 )
|
||||
{
|
||||
Mem_Free( file );
|
||||
return NULL;
|
||||
}
|
||||
#else /* XASH_PSP */
|
||||
#ifdef HAVE_DUP
|
||||
file->handle = dup( handle );
|
||||
#else
|
||||
@@ -2281,13 +2562,18 @@ static file_t *FS_OpenHandle( const char *syspath, int handle, fs_offset_t offse
|
||||
Mem_Free( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
#endif /* XASH_PSP */
|
||||
#else /* XASH_REDUCE_FD */
|
||||
file->backup_position = offset;
|
||||
file->backup_path = copystring( syspath );
|
||||
#if XASH_PSP
|
||||
file->backup_hold = false;
|
||||
file->backup_options = PSP_O_RDONLY;
|
||||
#else
|
||||
file->backup_options = O_RDONLY|O_BINARY;
|
||||
file->handle = -1;
|
||||
#endif
|
||||
file->handle = -1;
|
||||
#endif /* XASH_REDUCE_FD */
|
||||
|
||||
file->real_length = len;
|
||||
file->offset = offset;
|
||||
@@ -2349,6 +2635,11 @@ qboolean FS_SysFileExists( const char *path, qboolean caseinsensitive )
|
||||
|
||||
close( desc );
|
||||
return true;
|
||||
#elif XASH_PSP
|
||||
SceIoStat buf;
|
||||
if ( sceIoGetstat( path, &buf ) < 0 )
|
||||
return false;
|
||||
return FIO_S_ISREG( buf.st_mode );
|
||||
#else
|
||||
int ret;
|
||||
struct stat buf;
|
||||
@@ -2383,6 +2674,23 @@ qboolean FS_SysFolderExists( const char *path )
|
||||
DWORD dwFlags = GetFileAttributes( path );
|
||||
|
||||
return ( dwFlags != -1 ) && ( dwFlags & FILE_ATTRIBUTE_DIRECTORY );
|
||||
#elif XASH_PSP
|
||||
SceUID dir = sceIoDopen( path );
|
||||
|
||||
if( dir >= 0 )
|
||||
{
|
||||
sceIoDclose( dir );
|
||||
return true;
|
||||
}
|
||||
else if( ( dir == 0x80010002 ) || ( dir == 0x80010014 ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Reportf( S_ERROR "FS_SysFolderExists: problem while opening dir: %#010x\n", dir );
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
DIR *dir = opendir( path );
|
||||
|
||||
@@ -2640,7 +2948,11 @@ file_t *FS_Open( const char *filepath, const char *mode, qboolean gamedironly )
|
||||
char real_path[MAX_SYSPATH];
|
||||
|
||||
// open the file on disk directly
|
||||
#if XASH_PSP /* Fixed double slashes */
|
||||
Q_sprintf( real_path, "%s%s", fs_writedir, filepath );
|
||||
#else
|
||||
Q_sprintf( real_path, "%s/%s", fs_writedir, filepath );
|
||||
#endif
|
||||
FS_CreatePath( real_path );// Create directories up to the file
|
||||
return FS_SysOpen( real_path, mode );
|
||||
}
|
||||
@@ -2663,7 +2975,11 @@ int FS_Close( file_t *file )
|
||||
FS_BackupFileName( file, NULL, 0 );
|
||||
|
||||
if( file->handle >= 0 )
|
||||
#if XASH_PSP
|
||||
if( sceIoClose( file->handle ) )
|
||||
#else
|
||||
if( close( file->handle ))
|
||||
#endif
|
||||
return EOF;
|
||||
|
||||
Mem_Free( file );
|
||||
@@ -2685,15 +3001,22 @@ fs_offset_t FS_Write( file_t *file, const void *data, size_t datasize )
|
||||
|
||||
// if necessary, seek to the exact file position we're supposed to be
|
||||
if( file->buff_ind != file->buff_len )
|
||||
#if XASH_PSP
|
||||
sceIoLseek( file->handle, file->buff_ind - file->buff_len, PSP_SEEK_CUR );
|
||||
#else
|
||||
lseek( file->handle, file->buff_ind - file->buff_len, SEEK_CUR );
|
||||
|
||||
#endif
|
||||
// purge cached data
|
||||
FS_Purge( file );
|
||||
|
||||
#if XASH_PSP
|
||||
// write the buffer and update the position
|
||||
result = sceIoWrite( file->handle, data, (fs_offset_t)datasize );
|
||||
file->position = sceIoLseek( file->handle, 0, PSP_SEEK_CUR );
|
||||
#else
|
||||
// write the buffer and update the position
|
||||
result = write( file->handle, data, (fs_offset_t)datasize );
|
||||
file->position = lseek( file->handle, 0, SEEK_CUR );
|
||||
|
||||
#endif
|
||||
if( file->real_length < file->position )
|
||||
file->real_length = file->position;
|
||||
|
||||
@@ -2752,9 +3075,13 @@ fs_offset_t FS_Read( file_t *file, void *buffer, size_t buffersize )
|
||||
{
|
||||
if( count > (fs_offset_t)buffersize )
|
||||
count = (fs_offset_t)buffersize;
|
||||
#if XASH_PSP
|
||||
sceIoLseek( file->handle, file->offset + file->position, PSP_SEEK_SET );
|
||||
nb = sceIoRead (file->handle, &((byte *)buffer)[done], count );
|
||||
#else
|
||||
lseek( file->handle, file->offset + file->position, SEEK_SET );
|
||||
nb = read (file->handle, &((byte *)buffer)[done], count );
|
||||
|
||||
#endif
|
||||
if( nb > 0 )
|
||||
{
|
||||
done += nb;
|
||||
@@ -2767,9 +3094,13 @@ fs_offset_t FS_Read( file_t *file, void *buffer, size_t buffersize )
|
||||
{
|
||||
if( count > (fs_offset_t)sizeof( file->buff ))
|
||||
count = (fs_offset_t)sizeof( file->buff );
|
||||
#if XASH_PSP
|
||||
sceIoLseek( file->handle, file->offset + file->position, PSP_SEEK_SET );
|
||||
nb = sceIoRead( file->handle, file->buff, count );
|
||||
#else
|
||||
lseek( file->handle, file->offset + file->position, SEEK_SET );
|
||||
nb = read( file->handle, file->buff, count );
|
||||
|
||||
#endif
|
||||
if( nb > 0 )
|
||||
{
|
||||
file->buff_len = nb;
|
||||
@@ -2843,8 +3174,11 @@ int FS_VPrintf( file_t *file, const char *format, va_list ap )
|
||||
Mem_Free( tempbuff );
|
||||
buff_size *= 2;
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
len = sceIoWrite( file->handle, tempbuff, len );
|
||||
#else
|
||||
len = write( file->handle, tempbuff, len );
|
||||
#endif
|
||||
Mem_Free( tempbuff );
|
||||
|
||||
return len;
|
||||
@@ -2956,9 +3290,13 @@ int FS_Seek( file_t *file, fs_offset_t offset, int whence )
|
||||
FS_EnsureOpenFile( file );
|
||||
// Purge cached data
|
||||
FS_Purge( file );
|
||||
|
||||
#if XASH_PSP
|
||||
if( sceIoLseek( file->handle, file->offset + offset, PSP_SEEK_SET ) == -1 )
|
||||
return -1;
|
||||
#else
|
||||
if( lseek( file->handle, file->offset + offset, SEEK_SET ) == -1 )
|
||||
return -1;
|
||||
#endif
|
||||
file->position = offset;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -874,10 +874,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();
|
||||
@@ -908,6 +908,8 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
|
||||
#if TARGET_OS_IOS
|
||||
const char *IOS_GetDocsDir();
|
||||
Q_strncpy( host.rootdir, IOS_GetDocsDir(), sizeof(host.rootdir) );
|
||||
#elif XASH_PSP
|
||||
COM_ExtractFilePath( argv[0], host.rootdir );
|
||||
#elif XASH_SDL == 2
|
||||
char *szBasePath;
|
||||
|
||||
@@ -1009,7 +1011,11 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
|
||||
host_serverstate = Cvar_Get( "host_serverstate", "0", FCVAR_READ_ONLY, "displays current server state" );
|
||||
host_maxfps = Cvar_Get( "fps_max", "72", FCVAR_ARCHIVE, "host fps upper limit" );
|
||||
host_framerate = Cvar_Get( "host_framerate", "0", 0, "locks frame timing to this value in seconds" );
|
||||
#if XASH_PSP
|
||||
host_sleeptime = Cvar_Get( "sleeptime", "0", FCVAR_ARCHIVE, "milliseconds to sleep for each frame. higher values reduce fps accuracy" );
|
||||
#else
|
||||
host_sleeptime = Cvar_Get( "sleeptime", "1", FCVAR_ARCHIVE, "milliseconds to sleep for each frame. higher values reduce fps accuracy" );
|
||||
#endif
|
||||
host_gameloaded = Cvar_Get( "host_gameloaded", "0", FCVAR_READ_ONLY, "inidcates a loaded game.dll" );
|
||||
host_clientloaded = Cvar_Get( "host_clientloaded", "0", FCVAR_READ_ONLY, "inidcates a loaded client.dll" );
|
||||
host_limitlocal = Cvar_Get( "host_limitlocal", "0", 0, "apply cl_cmdrate and rate to loopback connection" );
|
||||
|
||||
@@ -101,7 +101,22 @@ static const loadpixformat_t load_null[] =
|
||||
{
|
||||
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||
};
|
||||
|
||||
#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", "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
|
||||
{ "%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
|
||||
{ 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
|
||||
@@ -116,7 +131,7 @@ static const loadpixformat_t load_game[] =
|
||||
{ "%s%s.%s", "pal", Image_LoadPAL, IL_HINT_NO }, // install studio\sprite palette
|
||||
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||
};
|
||||
|
||||
#endif
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
|
||||
@@ -34,6 +34,11 @@ GNU General Public License for more details.
|
||||
static char szGameDir[128]; // safe place to keep gamedir
|
||||
static int g_iArgc;
|
||||
static char **g_pszArgv;
|
||||
#if XASH_PSP
|
||||
#define MAX_NARGVS 50
|
||||
static int g_fArgc;
|
||||
static char *g_fArgv[MAX_NARGVS];
|
||||
#endif
|
||||
|
||||
void Launcher_ChangeGame( const char *progname )
|
||||
{
|
||||
@@ -70,6 +75,7 @@ int __stdcall WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int n
|
||||
free( szArgv );
|
||||
}
|
||||
#endif
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
char gamedir_buf[32] = "";
|
||||
@@ -102,15 +108,38 @@ int main( int argc, char** argv )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if XASH_PSP
|
||||
g_iArgc = argc;
|
||||
g_pszArgv = argv;
|
||||
if(argc <= 1)
|
||||
{
|
||||
g_fArgc = 0;
|
||||
g_fArgv[g_fArgc++] = argv[0]; // for get root directory path
|
||||
Platform_ReadCmd( "start.cmd", &g_fArgc, g_fArgv );
|
||||
if(g_fArgc > 1)
|
||||
{
|
||||
g_iArgc = g_fArgc;
|
||||
g_pszArgv = g_fArgv;
|
||||
}
|
||||
}
|
||||
#else
|
||||
g_iArgc = argc;
|
||||
g_pszArgv = argv;
|
||||
#endif
|
||||
#if XASH_IOS
|
||||
{
|
||||
void IOS_LaunchDialog( void );
|
||||
IOS_LaunchDialog();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if XASH_PSP
|
||||
Host_Main( g_iArgc, g_pszArgv, gamedir, 0, &Launcher_ChangeGame );
|
||||
Sys_Quit( );
|
||||
return 0;
|
||||
#else
|
||||
return Host_Main( g_iArgc, g_pszArgv, gamedir, 0, &Launcher_ChangeGame );
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -63,7 +63,7 @@ const char *COM_OffsetNameForFunction( void *function )
|
||||
|
||||
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 );
|
||||
@@ -110,6 +110,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
|
||||
@@ -122,6 +124,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
|
||||
|
||||
@@ -94,13 +94,14 @@ void MSG_Clear( sizebuf_t *sb )
|
||||
sb->bOverflow = false;
|
||||
}
|
||||
|
||||
#if !XASH_PSP
|
||||
static qboolean MSG_Overflow( sizebuf_t *sb, int nBits )
|
||||
{
|
||||
if( sb->iCurBit + nBits > sb->nDataBits )
|
||||
sb->bOverflow = true;
|
||||
return sb->bOverflow;
|
||||
}
|
||||
|
||||
#endif
|
||||
qboolean MSG_CheckOverflow( sizebuf_t *sb )
|
||||
{
|
||||
return MSG_Overflow( sb, 0 );
|
||||
@@ -135,7 +136,7 @@ void MSG_SeekToByte( sizebuf_t *sb, int bytePos )
|
||||
{
|
||||
sb->iCurBit = bytePos << 3;
|
||||
}
|
||||
|
||||
#if !XASH_PSP
|
||||
void MSG_WriteOneBit( sizebuf_t *sb, int nValue )
|
||||
{
|
||||
if( !MSG_Overflow( sb, 1 ))
|
||||
@@ -146,7 +147,7 @@ void MSG_WriteOneBit( sizebuf_t *sb, int nValue )
|
||||
sb->iCurBit++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits )
|
||||
{
|
||||
Assert( numbits >= 0 && numbits <= 32 );
|
||||
|
||||
@@ -70,7 +70,26 @@ void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, in
|
||||
void MSG_Clear( sizebuf_t *sb );
|
||||
|
||||
// Bit-write functions
|
||||
#if XASH_PSP
|
||||
_inline qboolean MSG_Overflow( sizebuf_t *sb, int nBits )
|
||||
{
|
||||
if( sb->iCurBit + nBits > sb->nDataBits )
|
||||
sb->bOverflow = true;
|
||||
return sb->bOverflow;
|
||||
}
|
||||
_inline 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++;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void MSG_WriteOneBit( sizebuf_t *sb, int nValue );
|
||||
#endif
|
||||
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, int data, int numbits, qboolean bSigned );
|
||||
|
||||
@@ -295,6 +295,17 @@ static const delta_field_t ent_fields[] =
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
#if XASH_OPT /* Direct access */
|
||||
#define D_event_t 0
|
||||
#define D_movevars_t 1
|
||||
#define D_usercmd_t 2
|
||||
#define D_clientdata_t 3
|
||||
#define D_weapon_data_t 4
|
||||
#define D_entity_state_t 5
|
||||
#define D_entity_state_player_t 6
|
||||
#define D_custom_entity_state_t 7
|
||||
#endif
|
||||
|
||||
static delta_info_t dt_info[] =
|
||||
{
|
||||
{ "event_t", ev_fields, NUM_FIELDS( ev_fields ) },
|
||||
@@ -799,9 +810,11 @@ void Delta_Init( void )
|
||||
|
||||
Delta_InitFields (); // initialize fields
|
||||
delta_init = true;
|
||||
|
||||
#if XASH_OPT
|
||||
dt = &dt_info[D_movevars_t];
|
||||
#else
|
||||
dt = Delta_FindStruct( "movevars_t" );
|
||||
|
||||
#endif
|
||||
Assert( dt != NULL );
|
||||
if( dt->bInitialized ) return; // "movevars_t" already specified by user
|
||||
|
||||
@@ -894,7 +907,11 @@ Delta_ClampIntegerField
|
||||
prevent data to out of range
|
||||
=====================
|
||||
*/
|
||||
#if XASH_OPT
|
||||
_inline int Delta_ClampIntegerField( delta_t *pField, int iValue, qboolean bSigned, int numbits )
|
||||
#else
|
||||
int Delta_ClampIntegerField( delta_t *pField, int iValue, qboolean bSigned, int numbits )
|
||||
#endif
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
if( numbits < 32 && abs( iValue ) >= (uint)BIT( numbits ))
|
||||
@@ -989,7 +1006,6 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba
|
||||
#if defined __GNUC__ && __GNUC_MAJOR < 9 && !defined __clang__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits );
|
||||
toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits );
|
||||
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
|
||||
@@ -1065,13 +1081,20 @@ int Delta_TestBaseline( entity_state_t *from, entity_state_t *to, qboolean playe
|
||||
if( from == NULL ) return 0;
|
||||
return countBits;
|
||||
}
|
||||
|
||||
#if XASH_OPT
|
||||
dt = &dt_info[D_weapon_data_t];
|
||||
if( FBitSet( to->entityType, ENTITY_BEAM ))
|
||||
dt = &dt_info[D_custom_entity_state_t];
|
||||
else if( player )
|
||||
dt = &dt_info[D_entity_state_player_t];
|
||||
else dt = &dt_info[D_entity_state_t];
|
||||
#else
|
||||
if( FBitSet( to->entityType, ENTITY_BEAM ))
|
||||
dt = Delta_FindStruct( "custom_entity_state_t" );
|
||||
else if( player )
|
||||
dt = Delta_FindStruct( "entity_state_player_t" );
|
||||
else dt = Delta_FindStruct( "entity_state_t" );
|
||||
|
||||
#endif
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
countBits++; // entityType flag
|
||||
@@ -1109,7 +1132,11 @@ write fields by offsets
|
||||
assume from and to is valid
|
||||
=====================
|
||||
*/
|
||||
#if XASH_OPT
|
||||
_inline qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to, float timebase )
|
||||
#else
|
||||
qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to, float timebase )
|
||||
#endif
|
||||
{
|
||||
qboolean bSigned = ( pField->flags & DT_SIGNED ) ? true : false;
|
||||
float flValue, flAngle, flTime;
|
||||
@@ -1332,8 +1359,11 @@ void MSG_WriteDeltaUsercmd( sizebuf_t *msg, usercmd_t *from, usercmd_t *to )
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
int i;
|
||||
|
||||
#if XASH_OPT
|
||||
dt = &dt_info[D_usercmd_t];
|
||||
#else
|
||||
dt = Delta_FindStruct( "usercmd_t" );
|
||||
#endif
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
@@ -1359,8 +1389,11 @@ void MSG_ReadDeltaUsercmd( sizebuf_t *msg, usercmd_t *from, usercmd_t *to )
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
int i;
|
||||
|
||||
#if XASH_OPT
|
||||
dt = &dt_info[D_usercmd_t];
|
||||
#else
|
||||
dt = Delta_FindStruct( "usercmd_t" );
|
||||
#endif
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
@@ -1394,8 +1427,11 @@ void MSG_WriteDeltaEvent( sizebuf_t *msg, event_args_t *from, event_args_t *to )
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
int i;
|
||||
|
||||
#if XASH_OPT
|
||||
dt = &dt_info[D_event_t];
|
||||
#else
|
||||
dt = Delta_FindStruct( "event_t" );
|
||||
#endif
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
@@ -1421,8 +1457,11 @@ void MSG_ReadDeltaEvent( sizebuf_t *msg, event_args_t *from, event_args_t *to )
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
int i;
|
||||
|
||||
#if XASH_OPT
|
||||
dt = &dt_info[D_event_t];
|
||||
#else
|
||||
dt = Delta_FindStruct( "event_t" );
|
||||
#endif
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
@@ -1450,8 +1489,11 @@ qboolean MSG_WriteDeltaMovevars( sizebuf_t *msg, movevars_t *from, movevars_t *t
|
||||
delta_info_t *dt;
|
||||
int i, startBit;
|
||||
int numChanges = 0;
|
||||
|
||||
#if XASH_OPT
|
||||
dt = &dt_info[D_movevars_t];
|
||||
#else
|
||||
dt = Delta_FindStruct( "movevars_t" );
|
||||
#endif
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
@@ -1485,8 +1527,11 @@ void MSG_ReadDeltaMovevars( sizebuf_t *msg, movevars_t *from, movevars_t *to )
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
int i;
|
||||
|
||||
#if XASH_OPT
|
||||
dt = &dt_info[D_movevars_t];
|
||||
#else
|
||||
dt = Delta_FindStruct( "movevars_t" );
|
||||
#endif
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
@@ -1522,8 +1567,11 @@ void MSG_WriteClientData( sizebuf_t *msg, clientdata_t *from, clientdata_t *to,
|
||||
delta_info_t *dt;
|
||||
int i, startBit;
|
||||
int numChanges = 0;
|
||||
|
||||
#if XASH_OPT
|
||||
dt = &dt_info[D_clientdata_t];
|
||||
#else
|
||||
dt = Delta_FindStruct( "clientdata_t" );
|
||||
#endif
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
@@ -1562,8 +1610,11 @@ void MSG_ReadClientData( sizebuf_t *msg, clientdata_t *from, clientdata_t *to, f
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
int i;
|
||||
|
||||
#if XASH_OPT
|
||||
dt = &dt_info[D_clientdata_t];
|
||||
#else
|
||||
dt = Delta_FindStruct( "clientdata_t" );
|
||||
#endif
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
@@ -1603,8 +1654,11 @@ void MSG_WriteWeaponData( sizebuf_t *msg, weapon_data_t *from, weapon_data_t *to
|
||||
delta_info_t *dt;
|
||||
int i, startBit;
|
||||
int numChanges = 0;
|
||||
|
||||
#if XASH_OPT
|
||||
dt = &dt_info[D_weapon_data_t];
|
||||
#else
|
||||
dt = Delta_FindStruct( "weapon_data_t" );
|
||||
#endif
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
@@ -1641,8 +1695,11 @@ void MSG_ReadWeaponData( sizebuf_t *msg, weapon_data_t *from, weapon_data_t *to,
|
||||
delta_t *pField;
|
||||
delta_info_t *dt;
|
||||
int i;
|
||||
|
||||
#if XASH_OPT
|
||||
dt = &dt_info[D_weapon_data_t];
|
||||
#else
|
||||
dt = Delta_FindStruct( "weapon_data_t" );
|
||||
#endif
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
@@ -1724,7 +1781,20 @@ void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *
|
||||
numChanges++;
|
||||
}
|
||||
else MSG_WriteOneBit( msg, 0 );
|
||||
|
||||
#if XASH_OPT
|
||||
if( FBitSet( to->entityType, ENTITY_BEAM ))
|
||||
{
|
||||
dt = &dt_info[D_custom_entity_state_t];
|
||||
}
|
||||
else if( delta_type == DELTA_PLAYER )
|
||||
{
|
||||
dt = &dt_info[D_entity_state_player_t];
|
||||
}
|
||||
else
|
||||
{
|
||||
dt = &dt_info[D_entity_state_t];
|
||||
}
|
||||
#else
|
||||
if( FBitSet( to->entityType, ENTITY_BEAM ))
|
||||
{
|
||||
dt = Delta_FindStruct( "custom_entity_state_t" );
|
||||
@@ -1737,7 +1807,7 @@ void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *
|
||||
{
|
||||
dt = Delta_FindStruct( "entity_state_t" );
|
||||
}
|
||||
|
||||
#endif
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
@@ -1843,6 +1913,20 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state
|
||||
to->entityType = MSG_ReadUBitLong( msg, 2 );
|
||||
to->number = number;
|
||||
|
||||
#if XASH_OPT
|
||||
if( cls.legacymode ? ( to->entityType == ENTITY_BEAM ) : FBitSet( to->entityType, ENTITY_BEAM ))
|
||||
{
|
||||
dt = &dt_info[D_custom_entity_state_t];
|
||||
}
|
||||
else if( delta_type == DELTA_PLAYER )
|
||||
{
|
||||
dt = &dt_info[D_entity_state_player_t];
|
||||
}
|
||||
else
|
||||
{
|
||||
dt = &dt_info[D_entity_state_t];
|
||||
}
|
||||
#else
|
||||
if( cls.legacymode ? ( to->entityType == ENTITY_BEAM ) : FBitSet( to->entityType, ENTITY_BEAM ))
|
||||
{
|
||||
dt = Delta_FindStruct( "custom_entity_state_t" );
|
||||
@@ -1855,7 +1939,7 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state
|
||||
{
|
||||
dt = Delta_FindStruct( "entity_state_t" );
|
||||
}
|
||||
|
||||
#endif
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
|
||||
@@ -93,6 +93,7 @@ static int ioctl_stub( int d, unsigned long r, ... )
|
||||
#define SOCKET int
|
||||
typedef int WSAsize_t;
|
||||
#else
|
||||
#include <errno.h> //GSA
|
||||
#include "platform/stub/net_stub.h"
|
||||
#endif
|
||||
|
||||
@@ -340,7 +341,7 @@ int NET_GetHostByName( const char *hostname )
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined XASH_NO_ASYNC_NS_RESOLVE && ( XASH_WIN32 || !(XASH_EMSCRIPTEN || XASH_DOS4GW) )
|
||||
#if !defined XASH_NO_ASYNC_NS_RESOLVE && ( XASH_WIN32 || !(XASH_EMSCRIPTEN || XASH_DOS4GW || XASH_PSP) )
|
||||
#define CAN_ASYNC_NS_RESOLVE
|
||||
#endif
|
||||
|
||||
|
||||
@@ -87,7 +87,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
|
||||
@@ -109,7 +120,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
|
||||
|
||||
@@ -182,6 +182,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
|
||||
@@ -234,7 +257,7 @@ GNU General Public License for more details.
|
||||
#define MAX_RENDER_DECALS 128
|
||||
#define MAX_RESOURCES 1024
|
||||
#endif
|
||||
|
||||
#endif /* XASH_PSP */
|
||||
// Quake1 Protocol
|
||||
#define PROTOCOL_VERSION_QUAKE 15
|
||||
|
||||
|
||||
@@ -62,10 +62,10 @@ wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size )
|
||||
fs_offset_t filesize = 0;
|
||||
const loadwavfmt_t *format;
|
||||
byte *f;
|
||||
|
||||
|
||||
Sound_Reset(); // clear old sounddata
|
||||
Q_strncpy( loadname, filename, sizeof( loadname ));
|
||||
|
||||
|
||||
if( Q_stricmp( ext, "" ))
|
||||
{
|
||||
// we needs to compare file extension with list of supported formats
|
||||
|
||||
@@ -117,8 +117,11 @@ stream_t *Stream_OpenMPG( const char *filename )
|
||||
file_t *file;
|
||||
int ret;
|
||||
wavinfo_t sc;
|
||||
|
||||
#if XASH_PSP // hold mode
|
||||
file = FS_Open( filename, "*rb", false );
|
||||
#else
|
||||
file = FS_Open( filename, "rb", false );
|
||||
#endif
|
||||
if( !file ) return NULL;
|
||||
|
||||
// at this point we have valid stream
|
||||
|
||||
@@ -320,7 +320,11 @@ stream_t *Stream_OpenWAV( const char *filename )
|
||||
return NULL;
|
||||
|
||||
// open
|
||||
#if XASH_PSP // hold mode
|
||||
file = FS_Open( filename, "*rb", false );
|
||||
#else
|
||||
file = FS_Open( filename, "rb", false );
|
||||
#endif
|
||||
if( !file ) return NULL;
|
||||
|
||||
// find "RIFF" chunk
|
||||
|
||||
@@ -32,6 +32,10 @@ GNU General Public License for more details.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if XASH_PSP
|
||||
#include <pspkernel.h>
|
||||
#endif
|
||||
|
||||
#include "menu_int.h" // _UPDATE_PAGE macro
|
||||
|
||||
qboolean error_on_exit = false; // arg for exit();
|
||||
@@ -472,7 +476,12 @@ Sys_Quit
|
||||
void Sys_Quit( void )
|
||||
{
|
||||
Host_Shutdown();
|
||||
#if XASH_PSP
|
||||
sceKernelDelayThread( 50 * 1000 );
|
||||
sceKernelExitGame();
|
||||
#else
|
||||
exit( error_on_exit );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -68,7 +68,11 @@ void Sys_Print( const char *pMsg );
|
||||
void Sys_PrintLog( const char *pMsg );
|
||||
void Sys_InitLog( void );
|
||||
void Sys_CloseLog( void );
|
||||
#ifdef XASH_PSP
|
||||
void Sys_Quit( void );
|
||||
#else
|
||||
void Sys_Quit( void ) NORETURN;
|
||||
#endif
|
||||
|
||||
//
|
||||
// sys_con.c
|
||||
|
||||
@@ -38,7 +38,11 @@ void Platform_MessageBox( const char *title, const char *message, qboolean paren
|
||||
// commented out, as this is an optional feature or maybe implemented in system API directly
|
||||
// see system.c
|
||||
// qboolean Sys_DebuggerPresent( void );
|
||||
|
||||
#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 );
|
||||
#endif
|
||||
#if XASH_ANDROID
|
||||
const char *Android_GetAndroidID( void );
|
||||
const char *Android_LoadID( void );
|
||||
|
||||
259
engine/platform/psp/dll_psp.c
Normal file
259
engine/platform/psp/dll_psp.c
Normal file
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
From the vitaXash3D by fgsfdsfgs.
|
||||
*/
|
||||
#include "common.h"
|
||||
#include "dll_psp.h"
|
||||
#include <pspsdk.h>
|
||||
#include <pspkernel.h>
|
||||
#include <pspuser.h>
|
||||
|
||||
#define MAX_DLNAMELEN 256
|
||||
|
||||
#if 1
|
||||
typedef struct table_s
|
||||
{
|
||||
const char *name;
|
||||
void *pointer;
|
||||
} table_t;
|
||||
|
||||
#include "generated_library_tables.h"
|
||||
#endif
|
||||
|
||||
typedef struct dll_s
|
||||
{
|
||||
SceUID handle;
|
||||
char name[MAX_DLNAMELEN];
|
||||
int refcnt;
|
||||
dllexport_t *exp;
|
||||
struct dll_s *next;
|
||||
} dll_t;
|
||||
|
||||
static dll_t *dll_list;
|
||||
static char *dll_err = NULL;
|
||||
static char dll_err_buf[1024];
|
||||
|
||||
static void *dlfind( const char *name )
|
||||
{
|
||||
dll_t *d = NULL;
|
||||
for( d = dll_list; d; d = d->next )
|
||||
if( !Q_strcmp( d->name, name ) )
|
||||
break;
|
||||
return d;
|
||||
}
|
||||
|
||||
static const char *dlname( void *handle )
|
||||
{
|
||||
dll_t *d = NULL;
|
||||
// iterate through all dll_ts to check if the handle is actually in the list
|
||||
// and not some bogus pointer from god knows where
|
||||
for( d = dll_list; d; d = d->next ) if( d == handle ) break;
|
||||
return d ? d->name : NULL;
|
||||
}
|
||||
|
||||
void *dlopen( const char *name, int flag )
|
||||
{
|
||||
dll_t *old, *new;
|
||||
char fullpath[MAX_SYSPATH];
|
||||
char static_name[16];
|
||||
void *static_exp;
|
||||
void *dynamic_exp;
|
||||
void *exp_p;
|
||||
SceUID h;
|
||||
|
||||
if( !name )
|
||||
return NULL;
|
||||
|
||||
old = dlfind( name );
|
||||
if( old )
|
||||
{
|
||||
old->refcnt++;
|
||||
return old;
|
||||
}
|
||||
|
||||
Q_snprintf( fullpath, sizeof( fullpath ), "%s", name );
|
||||
|
||||
exp_p = &dynamic_exp;
|
||||
static_exp = NULL;
|
||||
memset( static_name, 0x00, sizeof( static_name ) );
|
||||
|
||||
h = Platform_LoadModule( fullpath, 0, sizeof( exp_p ), &exp_p );
|
||||
if( h < 0 )
|
||||
{
|
||||
snprintf( dll_err_buf, sizeof( dll_err_buf ), "dlopen( %s ): error %#010x\n", name, h );
|
||||
dll_err = dll_err_buf;
|
||||
|
||||
COM_FileBase( name, static_name );
|
||||
|
||||
if( !Q_strncmp( static_name, "lib", 3 ) )
|
||||
Q_sprintf( static_name, "%s", &static_name[3] );
|
||||
|
||||
table_t* tbl = ( table_t* )libs;
|
||||
while( tbl->name )
|
||||
{
|
||||
if( !Q_strcmp( tbl->name, static_name) )
|
||||
{
|
||||
static_exp = tbl->pointer;
|
||||
break;
|
||||
}
|
||||
tbl++;
|
||||
}
|
||||
|
||||
if( static_exp == NULL )
|
||||
return NULL;
|
||||
|
||||
Con_Printf ( "dlopen( %s ): ( static ) success!\n", fullpath );
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf ( "dlopen( %s ): ( dynamic ) success!\n", fullpath );
|
||||
}
|
||||
|
||||
new = calloc( 1, sizeof( dll_t ) );
|
||||
if( !new )
|
||||
{
|
||||
dll_err = "dlopen(): out of memory";
|
||||
return NULL;
|
||||
}
|
||||
snprintf( new->name, MAX_DLNAMELEN, name );
|
||||
|
||||
if( static_exp != NULL )
|
||||
{
|
||||
new->handle = -1;
|
||||
new->exp = static_exp;
|
||||
}
|
||||
else
|
||||
{
|
||||
new->handle = h;
|
||||
new->exp = dynamic_exp;
|
||||
}
|
||||
|
||||
new->refcnt = 1;
|
||||
|
||||
new->next = dll_list;
|
||||
dll_list = new;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
void *dlsym( void *handle, const char *symbol )
|
||||
{
|
||||
if( !handle || !symbol )
|
||||
{
|
||||
dll_err = "dlsym(): NULL args";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !dlname( handle ) )
|
||||
{
|
||||
dll_err = "dlsym(): unknown handle";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dll_t *d = handle;
|
||||
if( !d->refcnt )
|
||||
{
|
||||
dll_err = "dlsym(): call dlopen() first";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dllexport_t *f = NULL;
|
||||
for( f = d->exp; f && f->func; f++ )
|
||||
{
|
||||
if( !Q_strcmp( f->name, symbol ) )
|
||||
break;
|
||||
}
|
||||
|
||||
if( f && f->func )
|
||||
{
|
||||
return f->func;
|
||||
}
|
||||
else
|
||||
{
|
||||
dll_err = "dlsym(): symbol not found in dll";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int dlclose( void *handle )
|
||||
{
|
||||
int result, sce_code;
|
||||
dll_t *d;
|
||||
|
||||
if( !handle )
|
||||
{
|
||||
dll_err = "dlclose(): NULL arg";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( !dlname( handle ) )
|
||||
{
|
||||
dll_err = "dlclose(): unknown handle";
|
||||
return -2;
|
||||
}
|
||||
|
||||
d = handle;
|
||||
d->refcnt--;
|
||||
if( d->refcnt <= 0 )
|
||||
{
|
||||
if( d->handle != -1 )
|
||||
{
|
||||
result = Platform_UnloadModule( d->handle, &sce_code );
|
||||
if( result < 0 )
|
||||
{
|
||||
if( result == -1 )
|
||||
{
|
||||
dll_err = "dlclose(): module doesn't want to stop";
|
||||
return -3;
|
||||
}
|
||||
|
||||
snprintf( dll_err_buf, sizeof( dll_err_buf ), "dlclose( %s ): error %#010x", d->name, sce_code );
|
||||
dll_err = dll_err_buf;
|
||||
}
|
||||
}
|
||||
|
||||
if( d == dll_list )
|
||||
dll_list = NULL;
|
||||
else
|
||||
{
|
||||
dll_t *pd;
|
||||
for( pd = dll_list; pd; pd = pd->next )
|
||||
{
|
||||
if( pd->next == d )
|
||||
{
|
||||
pd->next = d->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
free( d );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *dlerror( void )
|
||||
{
|
||||
char *err = dll_err;
|
||||
dll_err = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
int dladdr( const void *addr, Dl_info *info )
|
||||
{
|
||||
dll_t *d = NULL;
|
||||
dllexport_t *f = NULL;
|
||||
for( d = dll_list; d; d = d->next )
|
||||
for( f = d->exp; f && f->func; f++ )
|
||||
if( f->func == addr ) goto for_end;
|
||||
for_end:
|
||||
if( d && f && f->func )
|
||||
{
|
||||
if( info )
|
||||
{
|
||||
info->dli_fhandle = d;
|
||||
info->dli_sname = f->name;
|
||||
info->dli_saddr = addr;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
38
engine/platform/psp/dll_psp.h
Normal file
38
engine/platform/psp/dll_psp.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef DLL_PSP_H
|
||||
#define DLL_PSP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define RTLD_LAZY 0x0001
|
||||
#define RTLD_NOW 0x0002
|
||||
|
||||
typedef struct dllexport_s
|
||||
{
|
||||
const char *name;
|
||||
void *func;
|
||||
} dllexport_t;
|
||||
|
||||
typedef struct Dl_info_s
|
||||
{
|
||||
void *dli_fhandle;
|
||||
const char *dli_sname;
|
||||
const void *dli_saddr;
|
||||
} Dl_info;
|
||||
|
||||
void *dlsym(void *handle, const char *symbol );
|
||||
void *dlopen(const char *name, int flag );
|
||||
int dlclose(void *handle);
|
||||
char *dlerror( void );
|
||||
int dladdr( const void *addr, Dl_info *info );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
182
engine/platform/psp/in_psp.c
Normal file
182
engine/platform/psp/in_psp.c
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
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 12
|
||||
|
||||
extern convar_t *psp_deadzone_min;
|
||||
extern convar_t *psp_deadzone_max;
|
||||
|
||||
static struct psp_keymap_s
|
||||
{
|
||||
unsigned int srckey;
|
||||
int dstkey;
|
||||
}psp_keymap[] =
|
||||
{
|
||||
#if 1
|
||||
{ PSP_CTRL_SELECT, '~' },
|
||||
{ PSP_CTRL_START, K_ESCAPE },
|
||||
{ PSP_CTRL_UP, K_UPARROW },
|
||||
{ PSP_CTRL_RIGHT, K_RIGHTARROW },
|
||||
{ PSP_CTRL_DOWN, K_DOWNARROW },
|
||||
{ PSP_CTRL_LEFT, K_LEFTARROW },
|
||||
{ PSP_CTRL_LTRIGGER, K_JOY1 },
|
||||
{ PSP_CTRL_RTRIGGER, K_JOY2 },
|
||||
{ PSP_CTRL_TRIANGLE, K_SHIFT },
|
||||
{ PSP_CTRL_CIRCLE, K_SPACE },
|
||||
{ PSP_CTRL_CROSS, K_ENTER },
|
||||
{ PSP_CTRL_SQUARE, K_BACKSPACE },
|
||||
#else
|
||||
{ PSP_CTRL_SELECT, K_MODE_BUTTON },
|
||||
{ PSP_CTRL_START, K_START_BUTTON },
|
||||
{ PSP_CTRL_UP, K_UPARROW },
|
||||
{ PSP_CTRL_RIGHT, K_RIGHTARROW },
|
||||
{ PSP_CTRL_DOWN, K_DOWNARROW },
|
||||
{ PSP_CTRL_LEFT, K_LEFTARROW },
|
||||
{ PSP_CTRL_LTRIGGER, K_L1_BUTTON },
|
||||
{ PSP_CTRL_RTRIGGER, K_R1_BUTTON },
|
||||
{ PSP_CTRL_TRIANGLE, K_Y_BUTTON },
|
||||
{ PSP_CTRL_CIRCLE, K_B_BUTTON },
|
||||
{ PSP_CTRL_CROSS, K_A_BUTTON },
|
||||
{ PSP_CTRL_SQUARE, K_X_BUTTON },
|
||||
#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_JoyRescale( float axis, float deadzone_min, float deadzone_max )
|
||||
{
|
||||
float abs_axis, scale, r_deadzone_max;
|
||||
int flip_axis = 0;
|
||||
|
||||
// (-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;
|
||||
|
||||
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;
|
||||
|
||||
sceCtrlReadBufferPositive( &buf, 1 );
|
||||
|
||||
for( i = 0; i < PSP_MAX_KEYS; i++ )
|
||||
{
|
||||
if( ( last_buttons ^ buf.Buttons ) & psp_keymap[i].srckey )
|
||||
Key_Event( psp_keymap[i].dstkey, buf.Buttons & psp_keymap[i].srckey );
|
||||
}
|
||||
last_buttons = buf.Buttons;
|
||||
|
||||
if( FBitSet( psp_deadzone_min->flags, FCVAR_CHANGED ) || FBitSet( psp_deadzone_max->flags, FCVAR_CHANGED ) )
|
||||
{
|
||||
for ( i = 0; i < 256; i++ )
|
||||
{
|
||||
psp_joymap[i] = Platform_JoyRescale( i, psp_deadzone_min->value, psp_deadzone_max->value );
|
||||
psp_joymap[i] *= 256;
|
||||
}
|
||||
|
||||
ClearBits( psp_deadzone_min->flags, FCVAR_CHANGED );
|
||||
ClearBits( psp_deadzone_max->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 the controller.
|
||||
sceCtrlSetSamplingCycle( 0 );
|
||||
sceCtrlSetSamplingMode( PSP_CTRL_MODE_ANALOG );
|
||||
|
||||
// building a joystick map
|
||||
for ( i = 0; i < 256; i++ )
|
||||
{
|
||||
psp_joymap[i] = Platform_JoyRescale( i, psp_deadzone_min->value, psp_deadzone_max->value );
|
||||
psp_joymap[i] *= 256;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Platform_MouseMove( float *x, float *y )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Platform_PreCreateMove( void )
|
||||
{
|
||||
|
||||
}
|
||||
#endif /* XASH_INPUT */
|
||||
145
engine/platform/psp/lib_psp.c
Normal file
145
engine/platform/psp/lib_psp.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
lib_psp.c - dynamic library code for Sony PSP system
|
||||
Copyright (C) 2018 Flying With Gauss
|
||||
|
||||
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 "common.h"
|
||||
#include "library.h"
|
||||
#include "filesystem.h"
|
||||
#include "server.h"
|
||||
#include "platform/psp/lib_psp.h"
|
||||
|
||||
#ifdef XASH_NO_LIBDL
|
||||
#ifndef XASH_DLL_LOADER
|
||||
#error Enable at least one dll backend!!!
|
||||
#endif // XASH_DLL_LOADER
|
||||
|
||||
void *dlsym(void *handle, const char *symbol )
|
||||
{
|
||||
Con_DPrintf( "dlsym( %p, \"%s\" ): stub\n", handle, symbol );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *dlopen(const char *name, int flag )
|
||||
{
|
||||
Con_DPrintf( "dlopen( \"%s\", %d ): stub\n", name, flag );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int dlclose(void *handle)
|
||||
{
|
||||
Con_DPrintf( "dlsym( %p ): stub\n", handle );
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *dlerror( void )
|
||||
{
|
||||
return "Loading ELF libraries not supported in this build!\n";
|
||||
}
|
||||
|
||||
int dladdr( const void *addr, Dl_info *info )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif // XASH_NO_LIBDL
|
||||
|
||||
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 = dlopen( dllname, RTLD_LAZY );
|
||||
if( pHandle )
|
||||
return pHandle;
|
||||
|
||||
COM_PushLibraryError( va( "Failed to find library %s", dllname ));
|
||||
COM_PushLibraryError( dlerror() );
|
||||
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 = dlopen( hInst->fullPath, RTLD_LAZY ) ) )
|
||||
{
|
||||
COM_PushLibraryError( dlerror() );
|
||||
Mem_Free( hInst );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pHandle = hInst->hInstance;
|
||||
|
||||
Mem_Free( hInst );
|
||||
|
||||
return pHandle;
|
||||
}
|
||||
|
||||
void COM_FreeLibrary( void *hInstance )
|
||||
{
|
||||
dlclose( hInstance );
|
||||
}
|
||||
|
||||
void *COM_GetProcAddress( void *hInstance, const char *name )
|
||||
{
|
||||
return dlsym( hInstance, name );
|
||||
}
|
||||
|
||||
void *COM_FunctionFromName( void *hInstance, const char *pName )
|
||||
{
|
||||
void *function;
|
||||
if( !( function = COM_GetProcAddress( hInstance, pName ) ) )
|
||||
{
|
||||
Con_Reportf( S_ERROR "FunctionFromName: Can't get symbol %s: %s\n", pName, dlerror());
|
||||
}
|
||||
return function;
|
||||
}
|
||||
|
||||
const char *COM_NameForFunction( void *hInstance, void *function )
|
||||
{
|
||||
// NOTE: dladdr() is a glibc extension
|
||||
Dl_info info = {0};
|
||||
dladdr((void*)function, &info);
|
||||
if(info.dli_sname)
|
||||
return info.dli_sname;
|
||||
#ifdef XASH_ALLOW_SAVERESTORE_OFFSETS
|
||||
return COM_OffsetNameForFunction( function );
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
0
engine/platform/psp/lib_psp.h
Normal file
0
engine/platform/psp/lib_psp.h
Normal file
252
engine/platform/psp/s_psp.c
Normal file
252
engine/platform/psp/s_psp.c
Normal file
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
s_psp.c - sound hardware output
|
||||
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 XASH_DEDICATED
|
||||
#include "common.h"
|
||||
#if XASH_SOUND == SOUND_PSP
|
||||
|
||||
#include <pspaudiolib.h>
|
||||
#include <pspkernel.h>
|
||||
#include <psputility.h>
|
||||
|
||||
#include "sound.h"
|
||||
|
||||
#define SAMPLE_16BIT_SHIFT 1
|
||||
#define SECONDARY_BUFFER_SIZE 0x10000
|
||||
|
||||
#define SND_CHANELS 2
|
||||
#define SND_FREQ 44100
|
||||
#define SND_BUF_SIZE 16384
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short left;
|
||||
short right;
|
||||
}sample_t;
|
||||
|
||||
static sample_t snd_buffer[SND_BUF_SIZE] __attribute__( ( aligned( 64 ) ) );
|
||||
static volatile unsigned int snd_sampleread;
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
Global variables. Must be visible to window-procedure function
|
||||
so it can unlock and free the data block after it has been played.
|
||||
=======================================================================
|
||||
*/
|
||||
|
||||
dma_t dma;
|
||||
|
||||
void S_Activate( qboolean active )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* From PSP Quake */
|
||||
static void PSP_SoundCallback( void* buffer, unsigned int samplesToWrite, void* userData )
|
||||
{
|
||||
// Where are we writing to?
|
||||
sample_t* const dest = ( sample_t* )buffer;
|
||||
|
||||
// Where are we reading from?
|
||||
const sample_t* const src = &snd_buffer[snd_sampleread];
|
||||
|
||||
// How many samples to read?
|
||||
const unsigned int samplesToRead = samplesToWrite; // 44100
|
||||
|
||||
// Going to wrap past the end of the input buffer?
|
||||
const unsigned int samplesBeforeEndOfInput = SND_BUF_SIZE - snd_sampleread;
|
||||
if ( samplesToRead > samplesBeforeEndOfInput )
|
||||
{
|
||||
// Yes, so write the first chunk from the end of the input buffer.
|
||||
memcpy( dest, src, samplesBeforeEndOfInput * sizeof( sample_t ) );
|
||||
|
||||
// Write the second chunk from the start of the input buffer.
|
||||
const unsigned int samplesToReadFromBeginning = samplesToRead - samplesBeforeEndOfInput;
|
||||
|
||||
memcpy( &dest[samplesBeforeEndOfInput], src, samplesToReadFromBeginning * sizeof( sample_t ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// No wrapping, just copy.
|
||||
memcpy( &dest[0], src, samplesToRead * sizeof( sample_t ) );
|
||||
}
|
||||
|
||||
// Update the read offset.
|
||||
snd_sampleread = ( snd_sampleread + samplesToRead ) % SND_BUF_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SNDDMA_Init
|
||||
|
||||
Try to find a sound device to mix for.
|
||||
Returns false if nothing is found.
|
||||
==================
|
||||
*/
|
||||
qboolean SNDDMA_Init( void )
|
||||
{
|
||||
dma.format.speed = SND_FREQ;
|
||||
dma.format.channels = SND_CHANELS;
|
||||
dma.format.width = 2;
|
||||
dma.samples = SND_BUF_SIZE * SND_CHANELS;
|
||||
dma.buffer = ( unsigned char * )snd_buffer;
|
||||
dma.samplepos = 0;
|
||||
|
||||
// Initialise the audio system. This initialises it for the CD audio module
|
||||
// too.
|
||||
pspAudioInit();
|
||||
|
||||
// Set the channel callback.
|
||||
// Sound effects use channel 0, CD audio uses channel 1.
|
||||
pspAudioSetChannelCallback( 0, PSP_SoundCallback, 0 );
|
||||
|
||||
Con_Printf( "Using PSP audio driver: %d Hz\n", dma.format.speed );
|
||||
|
||||
//SNDDMA_Activate( true );
|
||||
|
||||
dma.initialized = true;
|
||||
#if 0 /* libmp3 */
|
||||
// load modules
|
||||
int status = sceUtilityLoadModule( PSP_MODULE_AV_AVCODEC );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_Printf( "Error - PSP_MODULE_AV_AVCODEC returned 0x%08X\n", status );
|
||||
}else printf("PSP_MODULE_AV_AVCODEC - OK\n");
|
||||
|
||||
status = sceUtilityLoadModule( PSP_MODULE_AV_MP3 );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_Printf( "Error - PSP_MODULE_AV_MP3 returned 0x%08X\n", status );
|
||||
}else printf("PSP_MODULE_AV_MP3 - OK\n");
|
||||
|
||||
// init mp3 resources
|
||||
status = sceMp3InitResource();
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_Printf("Error - sceMp3InitResource returned 0x%08X\n", status);
|
||||
}else printf("sceMp3InitResource - OK\n");
|
||||
#endif
|
||||
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 )
|
||||
{
|
||||
dma.samplepos = snd_sampleread * SND_CHANELS;
|
||||
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 )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_Submit
|
||||
|
||||
Send sound to device if buffer isn't really the dma buffer
|
||||
Also unlocks the dsound buffer
|
||||
===============
|
||||
*/
|
||||
void SNDDMA_Submit( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_Shutdown
|
||||
|
||||
Reset the sound device for exiting
|
||||
===============
|
||||
*/
|
||||
void SNDDMA_Shutdown( void )
|
||||
{
|
||||
Con_Printf("Shutting down audio.\n");
|
||||
|
||||
// Clear the mixing buffer so we don't get any noise during cleanup.
|
||||
memset(snd_buffer, 0, sizeof(snd_buffer));
|
||||
|
||||
// Clear the channel callback.
|
||||
pspAudioSetChannelCallback(0, 0, 0);
|
||||
|
||||
// Stop the audio system?
|
||||
pspAudioEndPre();
|
||||
|
||||
// Insert a false delay so the thread can be cleaned up.
|
||||
sceKernelDelayThread(50 * 1000);
|
||||
|
||||
// Shut down the audio system.
|
||||
pspAudioEnd();
|
||||
|
||||
dma.initialized = false;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
281
engine/platform/psp/sys_psp.c
Normal file
281
engine/platform/psp/sys_psp.c
Normal file
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
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 <pspsdk.h>
|
||||
#include <pspkernel.h>
|
||||
#include <psppower.h>
|
||||
#include <psprtc.h>
|
||||
#include <pspprof.h>
|
||||
#include <pspctrl.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 */
|
||||
|
||||
convar_t *psp_deadzone_min;
|
||||
convar_t *psp_deadzone_max;
|
||||
|
||||
/* Exit callback */
|
||||
static int exit_callback( int arg1, int arg2, void *common )
|
||||
{
|
||||
host.crashed = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Callback thread */
|
||||
static int CallbackThread( SceSize args, void *argp )
|
||||
{
|
||||
int cbid;
|
||||
|
||||
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
|
||||
sceKernelRegisterExitCallback(cbid);
|
||||
sceKernelSleepThreadCB();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sets up the callback thread and returns its thread id */
|
||||
static int SetupCallbacks( void )
|
||||
{
|
||||
int thid = 0;
|
||||
|
||||
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
|
||||
if(thid >= 0)
|
||||
{
|
||||
sceKernelStartThread(thid, 0, 0);
|
||||
}
|
||||
return thid;
|
||||
}
|
||||
|
||||
#if XASH_TIMER == TIMER_PSP
|
||||
double Platform_DoubleTime( void )
|
||||
{
|
||||
/*
|
||||
static u64 start_ticks;
|
||||
static qboolean timer_init = false;
|
||||
u64 current_ticks;
|
||||
|
||||
if ( !timer_init )
|
||||
{
|
||||
sceRtcGetCurrentTick( &start_ticks );
|
||||
timer_init = true;
|
||||
}
|
||||
sceRtcGetCurrentTick( ¤t_ticks );
|
||||
|
||||
return ( current_ticks - start_ticks ) * 0.000001;
|
||||
*/
|
||||
u64 current_ticks;
|
||||
sceRtcGetCurrentTick( ¤t_ticks );
|
||||
|
||||
return ( double )current_ticks * 0.000001;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
void Platform_Init( void )
|
||||
{
|
||||
pspSdkDisableFPUExceptions();
|
||||
|
||||
SetupCallbacks();
|
||||
scePowerSetClockFrequency( 333, 333, 166 );
|
||||
|
||||
psp_deadzone_min = Cvar_Get( "psp_deadzone_min", "20", FCVAR_ARCHIVE, "Joy deadzone min (0 - 127)" );
|
||||
psp_deadzone_max = Cvar_Get( "psp_deadzone_max", "0", FCVAR_ARCHIVE, "Joy deadzone max (0 - 127)" );
|
||||
}
|
||||
|
||||
void Platform_Shutdown( void )
|
||||
{
|
||||
#if XASH_PROFILING
|
||||
gprof_cleanup();
|
||||
#endif
|
||||
}
|
||||
538
engine/platform/psp/vid_psp.c
Normal file
538
engine/platform/psp/vid_psp.c
Normal file
@@ -0,0 +1,538 @@
|
||||
/*
|
||||
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 <pspgu.h>
|
||||
#include <pspgum.h>
|
||||
#include "vram_psp.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "mod_local.h"
|
||||
#include "input.h"
|
||||
#include "vid_common.h"
|
||||
|
||||
// Set gu list
|
||||
#define PSP_GU_STATIC_LIST 1
|
||||
#define PSP_GU_LIST_SIZE 0x40000
|
||||
|
||||
// Set frame buffer
|
||||
#define PSP_FB_WIDTH 480
|
||||
#define PSP_FB_HEIGHT 272
|
||||
#define PSP_FB_BWIDTH 512
|
||||
#define PSP_FB_FORMAT 5650 //4444,5551,5650,8888
|
||||
|
||||
#if PSP_FB_FORMAT == 4444
|
||||
#define PSP_FB_HW_FORMAT GU_PSM_4444
|
||||
#define PSP_FB_SW_FORMAT PSP_DISPLAY_PIXEL_FORMAT_4444
|
||||
#define PSP_FB_BPP 2
|
||||
#elif PSP_FB_FORMAT == 5551
|
||||
#define PSP_FB_HW_FORMAT GU_PSM_5551
|
||||
#define PSP_FB_SW_FORMAT PSP_DISPLAY_PIXEL_FORMAT_5551
|
||||
#define PSP_FB_BPP 2
|
||||
#elif PSP_FB_FORMAT == 5650
|
||||
#define PSP_FB_HW_FORMAT GU_PSM_5650
|
||||
#define PSP_FB_SW_FORMAT PSP_DISPLAY_PIXEL_FORMAT_565
|
||||
#define PSP_FB_BPP 2
|
||||
#elif PSP_FB_FORMAT == 8888
|
||||
#define PSP_FB_HW_FORMAT GU_PSM_8888
|
||||
#define PSP_FB_SW_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;
|
||||
void *depth_buffer;
|
||||
#if PSP_GU_STATIC_LIST
|
||||
unsigned int gu_list[PSP_GU_LIST_SIZE] __attribute__( ( aligned( 64 ) ) );
|
||||
#else
|
||||
unsigned int *gu_list;
|
||||
#endif
|
||||
}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*)valloc( 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*)valloc( 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_WIDTH, PSP_FB_SW_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_SW_FORMAT, PSP_DISPLAY_SETBUF_NEXTFRAME);
|
||||
|
||||
if ( vsync )
|
||||
{
|
||||
sceDisplayWaitVblankStart();
|
||||
}
|
||||
}
|
||||
|
||||
_inline void GU_Init( void )
|
||||
{
|
||||
vid_psp.draw_buffer = ( void* )valloc( 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* )valloc( PSP_FB_HEIGHT * PSP_FB_BWIDTH * PSP_FB_BPP );
|
||||
if( !vid_psp.disp_buffer )
|
||||
Host_Error( "Memory allocation failled! (vid_psp.disp_buffer)\n");
|
||||
|
||||
vid_psp.depth_buffer = ( void* )valloc( PSP_FB_HEIGHT * PSP_FB_BWIDTH * PSP_FB_BPP );
|
||||
if( !vid_psp.depth_buffer )
|
||||
Host_Error( "Memory allocation failled! (vid_psp.depth_buffer)\n");
|
||||
|
||||
#if !PSP_GU_STATIC_LIST
|
||||
vid_psp.gu_list = ( unsigned int* )valloc( PSP_GU_LIST_SIZE * sizeof ( unsigned int ) );
|
||||
if( !vid_psp.gu_list )
|
||||
Host_Error( "Memory allocation failled! (vid_psp.gu_list)\n");
|
||||
#endif
|
||||
|
||||
// Initialise the GU.
|
||||
sceGuInit();
|
||||
|
||||
// Set up the GU.
|
||||
sceGuStart( GU_DIRECT, vid_psp.gu_list );
|
||||
|
||||
sceGuDrawBuffer( PSP_FB_HW_FORMAT, vrelptr( vid_psp.draw_buffer ), PSP_FB_BWIDTH);
|
||||
sceGuDispBuffer( PSP_FB_WIDTH, PSP_FB_HEIGHT, vrelptr( vid_psp.disp_buffer ), PSP_FB_BWIDTH);
|
||||
sceGuDepthBuffer( vrelptr( vid_psp.depth_buffer ), PSP_FB_BWIDTH);
|
||||
|
||||
// Set the rendering offset and viewport.
|
||||
sceGuOffset( 2048 - ( PSP_FB_WIDTH / 2 ), 2048 - ( PSP_FB_HEIGHT / 2 ) );
|
||||
sceGuViewport( 2048, 2048, PSP_FB_WIDTH, PSP_FB_HEIGHT );
|
||||
|
||||
// Set up scissoring.
|
||||
sceGuEnable( GU_SCISSOR_TEST );
|
||||
sceGuScissor( 0, 0, PSP_FB_WIDTH, PSP_FB_HEIGHT );
|
||||
|
||||
// Set up texturing.
|
||||
sceGuEnable( GU_TEXTURE_2D );
|
||||
|
||||
// Set up clearing.
|
||||
sceGuClearDepth( 65535 );
|
||||
sceGuClearColor( GU_RGBA( 0x10, 0x20, 0x40, 0xff ) );
|
||||
|
||||
// Set up depth.
|
||||
sceGuDepthOffset( 0 );
|
||||
sceGuDepthRange( 0, 65535 );
|
||||
sceGuDepthFunc( GU_LEQUAL );
|
||||
sceGuEnable( GU_DEPTH_TEST );
|
||||
|
||||
// Set up fog
|
||||
// sceGuFog( 100.0f, 500.0f, 0xffffffff );
|
||||
// sceGuDisable( GU_FOG );
|
||||
|
||||
// Set the default matrices.
|
||||
sceGumMatrixMode( GU_PROJECTION );
|
||||
sceGumLoadIdentity();
|
||||
sceGumMatrixMode( GU_VIEW );
|
||||
sceGumLoadIdentity();
|
||||
sceGumMatrixMode( GU_MODEL );
|
||||
sceGumLoadIdentity();
|
||||
sceGumMatrixMode( GU_TEXTURE );
|
||||
sceGumLoadIdentity();
|
||||
|
||||
sceGumUpdateMatrix();
|
||||
|
||||
// Set up culling.
|
||||
sceGuFrontFace( GU_CW );
|
||||
sceGuEnable( GU_CULL_FACE );
|
||||
sceGuEnable( GU_CLIP_PLANES );
|
||||
|
||||
// Set up blending.
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
||||
|
||||
sceGuFinish();
|
||||
sceGuSync( GU_SYNC_FINISH, GU_SYNC_WHAT_DONE );
|
||||
|
||||
// Turn on the display.
|
||||
sceDisplayWaitVblankStart();
|
||||
sceGuDisplay(GU_TRUE);
|
||||
|
||||
// Start a new render.
|
||||
sceGuStart( GU_DIRECT, vid_psp.gu_list );
|
||||
|
||||
Con_Printf( "Vram available: %i\n", vmemavail() );
|
||||
}
|
||||
|
||||
_inline void GU_Shutdown( void )
|
||||
{
|
||||
// Finish rendering.
|
||||
sceGuFinish();
|
||||
sceGuSync( GU_SYNC_FINISH, GU_SYNC_WHAT_DONE );
|
||||
|
||||
// Shut down the display.
|
||||
sceGuTerm();
|
||||
|
||||
// Free the buffers.
|
||||
vfree( vid_psp.draw_buffer );
|
||||
vid_psp.draw_buffer = NULL;
|
||||
vfree( vid_psp.disp_buffer );
|
||||
vid_psp.disp_buffer = NULL;
|
||||
vfree( vid_psp.depth_buffer );
|
||||
vid_psp.depth_buffer = NULL;
|
||||
#if !PSP_GU_STATIC_LIST
|
||||
vfree( vid_psp.gu_list );
|
||||
vid_psp.gu_list = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
_inline void GU_SwapBuffers( void )
|
||||
{
|
||||
/*
|
||||
// Don't forget writeback the cache
|
||||
sceKernelDcacheWritebackAll();
|
||||
*/
|
||||
// Finish rendering.
|
||||
size_t list_size = sceGuFinish();
|
||||
/*
|
||||
if( list_size > sizeof( gu_list ) - 1000 )
|
||||
printf( "Display list size (%i) %i!\n", list_size, sizeof( gu_list ) );
|
||||
*/
|
||||
sceGuSync( GU_SYNC_FINISH, GU_SYNC_WHAT_DONE );
|
||||
|
||||
if ( vsync )
|
||||
{
|
||||
sceDisplayWaitVblankStart();
|
||||
}
|
||||
|
||||
// Swap the buffers.
|
||||
sceGuSwapBuffers();
|
||||
|
||||
void* p_swap = vid_psp.disp_buffer;
|
||||
vid_psp.disp_buffer = vid_psp.draw_buffer;
|
||||
vid_psp.draw_buffer = p_swap;
|
||||
|
||||
// Start a new render.
|
||||
sceGuStart( GU_DIRECT, vid_psp.gu_list );
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
GU_SwapBuffers();
|
||||
}
|
||||
|
||||
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();
|
||||
GU_Init();
|
||||
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 )
|
||||
GU_Shutdown();
|
||||
}
|
||||
|
||||
#endif // XASH_DEDICATED
|
||||
#endif // XASH_VIDEO
|
||||
259
engine/platform/psp/vram_psp.c
Normal file
259
engine/platform/psp/vram_psp.c
Normal file
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Helper for use with the PSP Software Development Kit - http://www.pspdev.org
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed as 'free to use and modify as long as credited appropriately'
|
||||
*
|
||||
* vram.c - Standard C high performance VRAM allocation routines.
|
||||
*
|
||||
* Copyright (c) 2007 Alexander Berl 'Raphael' <raphael@fx-world.org>
|
||||
* http://wordpress.fx-world.org
|
||||
*/
|
||||
#include "vram.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// Configure the memory to be managed
|
||||
#define __MEM_SIZE 0x00200000
|
||||
#define __MEM_START 0x04000000
|
||||
|
||||
// Configure the block size the memory gets subdivided into (page size)
|
||||
// __MEM_SIZE/__BLOCK_SIZE may not exceed 2^16-1 = 65535
|
||||
// The block size also defines the alignment of allocations
|
||||
// Larger block sizes perform better, because the blocktable is smaller and therefore fits better into cache
|
||||
// however the overhead is also bigger and more memory is wasted
|
||||
#define __BLOCK_SIZE 512
|
||||
#define __MEM_BLOCKS (__MEM_SIZE/__BLOCK_SIZE)
|
||||
#define __BLOCKS(x) ((x+__BLOCK_SIZE-1)/__BLOCK_SIZE)
|
||||
#define __BLOCKSIZE(x) ((x+__BLOCK_SIZE-1)&~(__BLOCK_SIZE-1))
|
||||
|
||||
|
||||
// A MEMORY BLOCK ENTRY IS MADE UP LIKE THAT:
|
||||
// bit: 31 30 29 - 15 14-0
|
||||
// free block prev size
|
||||
//
|
||||
// bit 31: free bit, indicating if block is allocated or not
|
||||
// bit 30: blocked bit, indicating if block is part of a larger block (0) - used for error resilience
|
||||
// bit 29-15: block index of previous block
|
||||
// bit 14- 0: size of current block
|
||||
//
|
||||
// This management can handle a max amount of 2^16-1 = 65535 blocks, which resolves to 64MB at blocksize of 1024 bytes
|
||||
//
|
||||
#define __BLOCK_GET_SIZE(x) ((x & 0x7FFF))
|
||||
#define __BLOCK_GET_PREV(x) ((x >> 15) & 0x7FFF)
|
||||
#define __BLOCK_GET_FREE(x) ((x >> 31))
|
||||
#define __BLOCK_GET_BLOCK(x) ((x >> 30) & 0x1)
|
||||
#define __BLOCK_SET_SIZE(x,y) x=((x & ~0x7FFF) | ((y) & 0x7FFF))
|
||||
#define __BLOCK_ADD_SIZE(x,y) x=((x & ~0x7FFF) | (((x & 0x7FFF)+((y) & 0x7FFF)) & 0x7FFF))
|
||||
#define __BLOCK_SET_PREV(x,y) x=((x & ~0x3FFF8000) | (((y) & 0x7FFF)<<15))
|
||||
#define __BLOCK_SET_FREE(x,y) x=((x & 0x7FFFFFFF) | (((y) & 0x1)<<31))
|
||||
#define __BLOCK_SET_BLOCK(x,y) x=((x & 0xBFFFFFFF) | (((y) & 0x1)<<30))
|
||||
#define __BLOCK_MAKE(s,p,f,n) (((f & 0x1)<<31) | ((n & 0x1)<<30) | (((p) & 0x7FFF)<<15) | ((s) & 0x7FFF))
|
||||
#define __BLOCK_GET_FREEBLOCK(x) ((x>>30) & 0x3) // returns 11b if block is a starting block and free, 10b if block is a starting block and allocated, 0xb if it is a non-starting block (don't change)
|
||||
#define __BLOCK0 ((__MEM_BLOCKS) | (1<<31) | (1<<30))
|
||||
|
||||
|
||||
unsigned int __mem_blocks[__MEM_BLOCKS] = { 0 };
|
||||
|
||||
|
||||
static int __largest_update = 0;
|
||||
static int __largest_block = __MEM_BLOCKS;
|
||||
static int __mem_free = __MEM_BLOCKS;
|
||||
|
||||
|
||||
inline void* vrelptr( void *ptr )
|
||||
{
|
||||
return (void*)((unsigned int)ptr & ~__MEM_START);
|
||||
}
|
||||
|
||||
inline void* vabsptr( void *ptr )
|
||||
{
|
||||
return (void*)((unsigned int)ptr | __MEM_START);
|
||||
}
|
||||
|
||||
|
||||
static void __find_largest_block( void )
|
||||
{
|
||||
int i = 0;
|
||||
__largest_block = 0;
|
||||
while (i<__MEM_BLOCKS)
|
||||
{
|
||||
int csize = __BLOCK_GET_SIZE(__mem_blocks[i]);
|
||||
if (__BLOCK_GET_FREEBLOCK(__mem_blocks[i])==3 && csize>__largest_block)
|
||||
__largest_block = csize;
|
||||
i += csize;
|
||||
}
|
||||
__largest_update = 0;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
void __memwalk( void )
|
||||
{
|
||||
int i = 0;
|
||||
if (__mem_blocks[0]==0) __mem_blocks[0] = __BLOCK0;
|
||||
while (i<__MEM_BLOCKS)
|
||||
{
|
||||
printf("BLOCK %i:\n", i);
|
||||
printf(" free: %i\n", __BLOCK_GET_FREEBLOCK(__mem_blocks[i]));
|
||||
printf(" size: %i\n", __BLOCK_GET_SIZE(__mem_blocks[i]));
|
||||
printf(" prev: %i\n", __BLOCK_GET_PREV(__mem_blocks[i]));
|
||||
i+=__BLOCK_GET_SIZE(__mem_blocks[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void* valloc( size_t size )
|
||||
{
|
||||
// Initialize memory block, if not yet done
|
||||
if (__mem_blocks[0]==0) __mem_blocks[0] = __BLOCK0;
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int bsize = __BLOCKS(size);
|
||||
|
||||
if (__largest_update==0 && __largest_block<bsize)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
printf("Not enough memory to allocate %i bytes (largest: %i)!\n",size,vlargestblock());
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
printf("allocating %i bytes, in %i blocks\n", size, bsize);
|
||||
#endif
|
||||
// Find smallest block that still fits the requested size
|
||||
int bestblock = -1;
|
||||
int bestblock_prev = 0;
|
||||
int bestblock_size = __MEM_BLOCKS+1;
|
||||
while (i<__MEM_BLOCKS)
|
||||
{
|
||||
int csize = __BLOCK_GET_SIZE(__mem_blocks[i]);
|
||||
if (__BLOCK_GET_FREEBLOCK(__mem_blocks[i])==3 && csize>=bsize)
|
||||
{
|
||||
if (csize<bestblock_size)
|
||||
{
|
||||
bestblock = i;
|
||||
bestblock_prev = j;
|
||||
bestblock_size = csize;
|
||||
}
|
||||
|
||||
if (csize==bsize)
|
||||
break;
|
||||
}
|
||||
j = i;
|
||||
i += csize;
|
||||
}
|
||||
|
||||
if (bestblock<0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
printf("Not enough memory to allocate %i bytes (largest: %i)!\n",size,vlargestblock());
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
i = bestblock;
|
||||
j = bestblock_prev;
|
||||
int csize = bestblock_size;
|
||||
__mem_blocks[i] = __BLOCK_MAKE(bsize,j,0,1);
|
||||
|
||||
int next = i+bsize;
|
||||
if (csize>bsize && next<__MEM_BLOCKS)
|
||||
{
|
||||
__mem_blocks[next] = __BLOCK_MAKE(csize-bsize,i,1,1);
|
||||
int nextnext = i+csize;
|
||||
if (nextnext<__MEM_BLOCKS)
|
||||
{
|
||||
__BLOCK_SET_PREV(__mem_blocks[nextnext], next);
|
||||
}
|
||||
}
|
||||
|
||||
__mem_free -= bsize;
|
||||
if (__largest_block==csize) // if we just allocated from one of the largest blocks
|
||||
{
|
||||
if ((csize-bsize)>(__mem_free/2))
|
||||
__largest_block = (csize-bsize); // there can't be another largest block
|
||||
else
|
||||
__largest_update = 1;
|
||||
}
|
||||
return ((void*)(__MEM_START + (i*__BLOCK_SIZE)));
|
||||
}
|
||||
|
||||
|
||||
void vfree( void* ptr )
|
||||
{
|
||||
if (ptr==0) return;
|
||||
|
||||
int block = ((unsigned int)ptr - __MEM_START)/__BLOCK_SIZE;
|
||||
if (block<0 || block>__MEM_BLOCKS)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
printf("Block is out of range: %i (0x%x)\n", block, (int)ptr);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
int csize = __BLOCK_GET_SIZE(__mem_blocks[block]);
|
||||
#ifdef _DEBUG
|
||||
printf("freeing block %i (0x%x), size: %i\n", block, (int)ptr, csize);
|
||||
#endif
|
||||
|
||||
if (__BLOCK_GET_FREEBLOCK(__mem_blocks[block])!=1 || csize==0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
printf("Block was not allocated!\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark block as free
|
||||
__BLOCK_SET_FREE(__mem_blocks[block],1);
|
||||
__mem_free += csize;
|
||||
|
||||
int next = block+csize;
|
||||
// Merge with previous block if possible
|
||||
int prev = __BLOCK_GET_PREV(__mem_blocks[block]);
|
||||
if (prev<block)
|
||||
{
|
||||
if (__BLOCK_GET_FREEBLOCK(__mem_blocks[prev])==3)
|
||||
{
|
||||
__BLOCK_ADD_SIZE(__mem_blocks[prev], csize);
|
||||
__BLOCK_SET_BLOCK(__mem_blocks[block],0); // mark current block as inter block
|
||||
if (next<__MEM_BLOCKS)
|
||||
__BLOCK_SET_PREV(__mem_blocks[next], prev);
|
||||
block = prev;
|
||||
}
|
||||
}
|
||||
|
||||
// Merge with next block if possible
|
||||
if (next<__MEM_BLOCKS)
|
||||
{
|
||||
if (__BLOCK_GET_FREEBLOCK(__mem_blocks[next])==3)
|
||||
{
|
||||
__BLOCK_ADD_SIZE(__mem_blocks[block], __BLOCK_GET_SIZE(__mem_blocks[next]));
|
||||
__BLOCK_SET_BLOCK(__mem_blocks[next],0); // mark next block as inter block
|
||||
int nextnext = next + __BLOCK_GET_SIZE(__mem_blocks[next]);
|
||||
if (nextnext<__MEM_BLOCKS)
|
||||
__BLOCK_SET_PREV(__mem_blocks[nextnext], block);
|
||||
}
|
||||
}
|
||||
|
||||
// Update if a new largest block emerged
|
||||
if (__largest_block<__BLOCK_GET_SIZE(__mem_blocks[block]))
|
||||
{
|
||||
__largest_block = __BLOCK_GET_SIZE(__mem_blocks[block]);
|
||||
__largest_update = 0; // No update necessary any more, because update only necessary when largest has shrinked at most
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t vmemavail( void )
|
||||
{
|
||||
return __mem_free * __BLOCK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
size_t vlargestblock( void )
|
||||
{
|
||||
if (__largest_update) __find_largest_block();
|
||||
return __largest_block * __BLOCK_SIZE;
|
||||
}
|
||||
|
||||
39
engine/platform/psp/vram_psp.h
Normal file
39
engine/platform/psp/vram_psp.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Helper for use with the PSP Software Development Kit - http://www.pspdev.org
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed as 'free to use and modify as long as credited appropriately'
|
||||
*
|
||||
* vram.h - Standard C high performance VRAM allocation routines.
|
||||
*
|
||||
* Copyright (c) 2007 Alexander Berl 'Raphael' <raphael@fx-world.org>
|
||||
* http://wordpress.fx-world.org
|
||||
*/
|
||||
#ifndef vram_h__
|
||||
#define vram_h__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void* vrelptr( void *ptr ); // make a pointer relative to memory base address (ATTENTION: A NULL rel ptr is not illegal/invalid!)
|
||||
void* vabsptr( void *ptr ); // make a pointer absolute (default return type of valloc)
|
||||
|
||||
void* valloc( size_t size );
|
||||
void vfree( void* ptr );
|
||||
size_t vmemavail();
|
||||
size_t vlargestblock();
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
// Debug printf (to stdout) a trace of the current Memblocks
|
||||
void __memwalk();
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ifdef vram_h__
|
||||
@@ -54,13 +54,17 @@ extern int SV_UPDATE_BACKUP;
|
||||
#define GROUP_OP_AND 0
|
||||
#define GROUP_OP_NAND 1
|
||||
|
||||
#ifdef NDEBUG
|
||||
#if defined( NDEBUG ) || XASH_OPT
|
||||
#define SV_IsValidEdict( e ) ( e && !e->free )
|
||||
#else
|
||||
#define SV_IsValidEdict( e ) SV_CheckEdict( e, __FILE__, __LINE__ )
|
||||
#endif
|
||||
#define NUM_FOR_EDICT(e) ((int)((edict_t *)(e) - svgame.edicts))
|
||||
#if XASH_OPT
|
||||
#define EDICT_NUM( num ) ( ( ( ( num ) >= 0 ) && ( ( num ) < GI->max_edicts) ) ? svgame.edicts + ( num ) : NULL )
|
||||
#else
|
||||
#define EDICT_NUM( num ) SV_EdictNum( num )
|
||||
#endif
|
||||
#define STRING( offset ) SV_GetString( offset )
|
||||
#define ALLOC_STRING(str) SV_AllocString( str )
|
||||
#define MAKE_STRING(str) SV_MakeString( str )
|
||||
@@ -476,7 +480,12 @@ void Master_Packet( void );
|
||||
//
|
||||
void SV_ActivateServer( int runPhysics );
|
||||
qboolean SV_SpawnServer( const char *server, const char *startspot, qboolean background );
|
||||
#if XASH_OPT
|
||||
#define SV_ModelHandle( modelindex ) ( ( modelindex < 0 || modelindex >= MAX_MODELS ) ? NULL : sv.models[( modelindex )] )
|
||||
model_t *pfnSV_ModelHandle( int modelindex );
|
||||
#else
|
||||
model_t *SV_ModelHandle( int modelindex );
|
||||
#endif
|
||||
void SV_DeactivateServer( void );
|
||||
|
||||
//
|
||||
@@ -490,7 +499,17 @@ qboolean SV_RunThink( edict_t *ent );
|
||||
qboolean SV_PlayerRunThink( edict_t *ent, float frametime, double time );
|
||||
qboolean SV_TestEntityPosition( edict_t *ent, edict_t *blocker );
|
||||
void SV_Impact( edict_t *e1, edict_t *e2, trace_t *trace );
|
||||
#if XASH_OPT
|
||||
// filter movetypes to collide with
|
||||
#define SV_CanPushed( ent ) ( ( ent )->v.movetype == MOVETYPE_NONE || \
|
||||
( ent )->v.movetype == MOVETYPE_PUSH || \
|
||||
( ent )->v.movetype == MOVETYPE_FOLLOW || \
|
||||
( ent )->v.movetype == MOVETYPE_NOCLIP || \
|
||||
( ent )->v.movetype == MOVETYPE_COMPOUND ) ? false : true
|
||||
qboolean pfnSV_CanPushed( edict_t *ent );
|
||||
#else
|
||||
qboolean SV_CanPushed( edict_t *ent );
|
||||
#endif
|
||||
void SV_FreeOldEntities( void );
|
||||
void SV_CheckAllEnts( void );
|
||||
|
||||
@@ -633,7 +652,9 @@ void SV_RestartAmbientSounds( void );
|
||||
void SV_RestartDecals( void );
|
||||
void SV_RestartStaticEnts( void );
|
||||
int pfnGetCurrentPlayer( void );
|
||||
#if !XASH_OPT
|
||||
edict_t *SV_EdictNum( int n );
|
||||
#endif
|
||||
char *SV_Localinfo( void );
|
||||
//
|
||||
// sv_log.c
|
||||
|
||||
@@ -35,7 +35,7 @@ static vec3_t viewPoint[MAX_CLIENTS];
|
||||
// exports
|
||||
typedef void (__cdecl *LINK_ENTITY_FUNC)( entvars_t *pev );
|
||||
typedef void (__stdcall *GIVEFNPTRSTODLL)( enginefuncs_t* engfuncs, globalvars_t *pGlobals );
|
||||
|
||||
#if !XASH_OPT
|
||||
edict_t *SV_EdictNum( int n )
|
||||
{
|
||||
if(( n >= 0 ) && ( n < GI->max_edicts ))
|
||||
@@ -59,7 +59,7 @@ qboolean SV_CheckEdict( const edict_t *e, const char *file, const int line )
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*
|
||||
=============
|
||||
EntvarsDescription
|
||||
@@ -2679,7 +2679,8 @@ void GAME_EXPORT pfnMessageEnd( void )
|
||||
return;
|
||||
}
|
||||
|
||||
*(word *)&sv.multicast.pData[svgame.msg_size_index] = svgame.msg_realsize;
|
||||
/**(word *)&*/ // GSA
|
||||
sv.multicast.pData[svgame.msg_size_index] = svgame.msg_realsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -266,12 +266,19 @@ SV_ModelHandle
|
||||
get model by handle
|
||||
================
|
||||
*/
|
||||
#if XASH_OPT
|
||||
model_t *pfnSV_ModelHandle( int modelindex )
|
||||
{
|
||||
return SV_ModelHandle( modelindex );
|
||||
}
|
||||
#else
|
||||
model_t *SV_ModelHandle( int modelindex )
|
||||
{
|
||||
if( modelindex < 0 || modelindex >= MAX_MODELS )
|
||||
return NULL;
|
||||
return sv.models[modelindex];
|
||||
}
|
||||
#endif
|
||||
|
||||
void SV_ReadResourceList( const char *filename )
|
||||
{
|
||||
|
||||
@@ -842,6 +842,12 @@ SV_CanPushed
|
||||
filter entities for push
|
||||
============
|
||||
*/
|
||||
#if XASH_OPT
|
||||
qboolean pfnSV_CanPushed( edict_t *ent )
|
||||
{
|
||||
return SV_CanPushed( ent );
|
||||
}
|
||||
#else
|
||||
qboolean SV_CanPushed( edict_t *ent )
|
||||
{
|
||||
// filter movetypes to collide with
|
||||
@@ -856,6 +862,7 @@ qboolean SV_CanPushed( edict_t *ent )
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
============
|
||||
@@ -864,7 +871,11 @@ SV_CanBlock
|
||||
allow entity to block pusher?
|
||||
============
|
||||
*/
|
||||
#if XASH_PSP
|
||||
static inline qboolean SV_CanBlock( edict_t *ent )
|
||||
#else
|
||||
static qboolean SV_CanBlock( edict_t *ent )
|
||||
#endif
|
||||
{
|
||||
if( ent->v.mins[0] == ent->v.maxs[0] )
|
||||
return false;
|
||||
@@ -936,12 +947,12 @@ static edict_t *SV_PushMove( edict_t *pusher, float movetime )
|
||||
// filter movetypes to collide with
|
||||
if( !SV_CanPushed( check ))
|
||||
continue;
|
||||
|
||||
#if !XASH_OPT
|
||||
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 ))
|
||||
{
|
||||
@@ -957,7 +968,12 @@ static edict_t *SV_PushMove( edict_t *pusher, float movetime )
|
||||
if( !SV_TestEntityPosition( check, NULL ))
|
||||
continue;
|
||||
}
|
||||
|
||||
#if XASH_OPT
|
||||
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;
|
||||
@@ -1049,18 +1065,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_OPT
|
||||
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 ))
|
||||
{
|
||||
@@ -1076,7 +1093,12 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
||||
if( !SV_TestEntityPosition( check, NULL ))
|
||||
continue;
|
||||
}
|
||||
|
||||
#if XASH_OPT
|
||||
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 );
|
||||
@@ -1092,7 +1114,7 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
||||
Matrix4x4_VectorITransform( start_l, org, temp );
|
||||
Matrix4x4_VectorTransform( end_l, temp, org2 );
|
||||
VectorSubtract( org2, org, lmove );
|
||||
|
||||
|
||||
// i can't clear FL_ONGROUND in all cases because many bad things may be happen
|
||||
if( check->v.movetype != MOVETYPE_WALK )
|
||||
{
|
||||
@@ -1131,7 +1153,6 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
||||
return check;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2018,7 +2039,11 @@ static server_physics_api_t gPhysicsAPI =
|
||||
SV_LinkEdict,
|
||||
SV_GetServerTime,
|
||||
SV_GetFrameTime,
|
||||
#if XASH_OPT
|
||||
(void*)pfnSV_ModelHandle,
|
||||
#else
|
||||
(void*)SV_ModelHandle,
|
||||
#endif
|
||||
SV_GetHeadNode,
|
||||
SV_ServerState,
|
||||
Host_Error,
|
||||
|
||||
@@ -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
|
||||
|
||||
#ifdef 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
|
||||
#define SAVE_AGED_COUNT 2
|
||||
|
||||
@@ -2255,10 +2258,19 @@ 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 );
|
||||
@@ -2270,7 +2282,11 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
||||
|
||||
// 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)
|
||||
@@ -2280,12 +2296,21 @@ 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
|
||||
if( !Q_stricmp( pFieldName, "comment" ))
|
||||
{
|
||||
Q_strncpy( description, pData, nFieldSize );
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
|
||||
#ifndef SPRITE_H
|
||||
#define SPRITE_H
|
||||
#ifdef __psp__ // GSA
|
||||
#pragma pack(push, 1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
@@ -125,4 +128,7 @@ typedef struct
|
||||
frametype_t type;
|
||||
} dframetype_t;
|
||||
|
||||
#ifdef __psp__ // GSA
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
#endif//SPRITE_H
|
||||
|
||||
@@ -44,6 +44,8 @@ def configure(conf):
|
||||
elif conf.env.DEST_OS == 'android': # Android doesn't need SDL2
|
||||
for i in ['log']:
|
||||
conf.check_cc(lib = i)
|
||||
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)
|
||||
@@ -66,7 +68,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.load('pthreads')
|
||||
@@ -99,7 +102,7 @@ def build(bld):
|
||||
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 != 'dos': #posix
|
||||
elif bld.env.DEST_OS not in ['dos', 'psp']: #posix
|
||||
libs += [ 'M', 'RT', 'PTHREAD', 'ASOUND']
|
||||
if not bld.env.STATIC:
|
||||
libs += ['DL']
|
||||
@@ -112,7 +115,6 @@ def build(bld):
|
||||
source += bld.path.ant_glob(['platform/dos/*.c'])
|
||||
source += bld.path.ant_glob(['platform/stub/s_stub.c'])
|
||||
|
||||
|
||||
if bld.get_define('XASH_CUSTOM_SWAP'):
|
||||
source += bld.path.ant_glob(['platform/misc/kmalloc.c', 'platform/misc/sbrk.c'])
|
||||
|
||||
@@ -133,6 +135,9 @@ def build(bld):
|
||||
libs += ['LOG']
|
||||
source += bld.path.ant_glob(['platform/android/*.cpp', 'platform/android/*.c', 'platform/linux/*.c'])
|
||||
|
||||
if bld.env.DEST_OS == 'psp':
|
||||
source += bld.path.ant_glob(['platform/psp/*.c'])
|
||||
|
||||
# add client files
|
||||
if not bld.env.DEDICATED:
|
||||
source += bld.path.ant_glob([
|
||||
|
||||
2
mainui
2
mainui
Submodule mainui updated: 6e9135516a...d3c61e2e14
@@ -70,6 +70,8 @@ For more information, please refer to <http://unlicense.org/>
|
||||
#undef XASH_WIN32
|
||||
#undef XASH_WIN64
|
||||
#undef XASH_X86
|
||||
#undef XASH_PSP
|
||||
#undef XASH_OPT
|
||||
|
||||
//================================================================
|
||||
//
|
||||
@@ -115,11 +117,15 @@ For more information, please refer to <http://unlicense.org/>
|
||||
#elif defined __WATCOMC__ && defined __DOS__
|
||||
#define XASH_DOS4GW 1
|
||||
#define XASH_LITTLE_ENDIAN
|
||||
#elif defined __psp__
|
||||
#define XASH_PSP 1
|
||||
#define XASH_LITTLE_ENDIAN
|
||||
#define XASH_OPT 1
|
||||
#else
|
||||
#error "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug"
|
||||
#endif
|
||||
|
||||
#if defined XASH_ANDROID || defined XASH_IOS
|
||||
#if defined XASH_ANDROID || defined XASH_IOS || defined XASH_PSP
|
||||
#define XASH_MOBILE_PLATFORM 1
|
||||
#endif
|
||||
|
||||
|
||||
@@ -35,13 +35,57 @@ const matrix3x4 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
|
||||
"ulv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"ulv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"ulv.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
|
||||
"ulv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"ulv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"ulv.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]
|
||||
"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]
|
||||
"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,20 +95,74 @@ 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
|
||||
"ulv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"ulv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"ulv.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 0
|
||||
"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
|
||||
"ulv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"ulv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"ulv.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 0
|
||||
"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 )
|
||||
@@ -119,6 +217,30 @@ void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out )
|
||||
|
||||
void Matrix3x4_FromOriginQuat( matrix3x4 out, const vec4_t quaternion, const vec3_t origin )
|
||||
{
|
||||
#if 0//XASH_PSP /* not tested */
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"ulv.q C130, %1\n" // C130 = quaternion
|
||||
"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]
|
||||
"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 E000, E100, E200\n" // E000 = E100 * E200
|
||||
"usv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"usv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"usv.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];
|
||||
@@ -134,10 +256,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 XASH_PSP /* performance not tested */
|
||||
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
|
||||
/**/
|
||||
"usv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"usv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"usv.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
|
||||
/**/
|
||||
"usv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"usv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"usv.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
|
||||
/**/
|
||||
"usv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"usv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"usv.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
|
||||
/**/
|
||||
"usv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"usv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"usv.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] )
|
||||
@@ -215,10 +493,39 @@ void Matrix3x4_CreateFromEntity( matrix3x4 out, const vec3_t angles, const vec3_
|
||||
out[2][2] = scale;
|
||||
out[2][3] = origin[2];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix3x4_TransformPositivePlane( const matrix3x4 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
|
||||
"ulv.q C100, 0 + %2\n" // C100 = in[0]
|
||||
"ulv.q C110, 16 + %2\n" // C110 = in[1]
|
||||
"ulv.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]
|
||||
"lv.s S210, %4\n" // S210 = d
|
||||
"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 ), "m"( d )
|
||||
);
|
||||
#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;
|
||||
|
||||
@@ -226,6 +533,7 @@ void Matrix3x4_TransformPositivePlane( const matrix3x4 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 Matrix3x4_Invert_Simple( matrix3x4 out, const matrix3x4 in1 )
|
||||
@@ -312,13 +620,57 @@ const matrix4x4 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
|
||||
"ulv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"ulv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"ulv.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
|
||||
"ulv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"ulv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"ulv.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 C200, C130, R103\n" // C130 = v - in[][3]
|
||||
"vdot.t S000, C200, R100\n" // S000 = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0]
|
||||
"vdot.t S001, C200, R101\n" // S001 = dir[0] * in[0][1] + dir[1] * in[1][1] + dir[2] * in[2][1]
|
||||
"vdot.t S002, C200, R102\n" // S002 = dir[0] * in[0][2] + dir[1] * in[1][2] + dir[2] * in[2][2]
|
||||
"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];
|
||||
@@ -328,20 +680,74 @@ 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
|
||||
"ulv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"ulv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"ulv.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 0
|
||||
"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
|
||||
"ulv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"ulv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"ulv.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 0
|
||||
"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 )
|
||||
@@ -384,6 +790,7 @@ void Matrix4x4_FromOriginQuat( matrix4x4 out, const vec4_t quaternion, const vec
|
||||
out[1][1] = 1.0f - 2.0f * quaternion[0] * quaternion[0] - 2.0f * quaternion[2] * quaternion[2];
|
||||
out[2][1] = 2.0f * quaternion[1] * quaternion[2] + 2.0f * quaternion[3] * quaternion[0];
|
||||
out[1][3] = origin[1];
|
||||
|
||||
out[0][2] = 2.0f * quaternion[0] * quaternion[2] + 2.0f * quaternion[3] * quaternion[1];
|
||||
out[1][2] = 2.0f * quaternion[1] * quaternion[2] - 2.0f * quaternion[3] * quaternion[0];
|
||||
out[2][2] = 1.0f - 2.0f * quaternion[0] * quaternion[0] - 2.0f * quaternion[1] * quaternion[1];
|
||||
@@ -396,6 +803,169 @@ void Matrix4x4_FromOriginQuat( matrix4x4 out, const vec4_t quaternion, const vec
|
||||
|
||||
void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_t origin, float scale )
|
||||
{
|
||||
#if XASH_PSP /* performance not tested */
|
||||
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]
|
||||
/**/
|
||||
"usv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"usv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"usv.q C020, 32 + %0\n" // out[2] = C020
|
||||
"usv.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]
|
||||
/**/
|
||||
"usv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"usv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"usv.q C020, 32 + %0\n" // out[2] = C020
|
||||
"usv.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]
|
||||
/**/
|
||||
"usv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"usv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"usv.q C020, 32 + %0\n" // out[2] = C020
|
||||
"usv.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
|
||||
/**/
|
||||
"usv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"usv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"usv.q C020, 32 + %0\n" // out[2] = C020
|
||||
"usv.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] )
|
||||
@@ -489,6 +1059,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 )
|
||||
@@ -516,6 +1087,34 @@ 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
|
||||
"ulv.q C100, 0 + %2\n" // C100 = in[0]
|
||||
"ulv.q C110, 16 + %2\n" // C110 = in[1]
|
||||
"ulv.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]
|
||||
"lv.s S210, %4\n" // S210 = d
|
||||
"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 ), "m"( d )
|
||||
);
|
||||
#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;
|
||||
|
||||
@@ -523,10 +1122,39 @@ 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_TransformStandardPlane( 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
|
||||
"ulv.q C100, 0 + %2\n" // C100 = in[0]
|
||||
"ulv.q C110, 16 + %2\n" // C110 = in[1]
|
||||
"ulv.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]
|
||||
"lv.s S210, %4\n" // S210 = d
|
||||
"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
|
||||
"vsub.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 ), "m"( d )
|
||||
);
|
||||
#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;
|
||||
|
||||
@@ -534,6 +1162,7 @@ void Matrix4x4_TransformStandardPlane( 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 )
|
||||
@@ -635,7 +1264,7 @@ qboolean Matrix4x4_Invert_Full( matrix4x4 out, const matrix4x4 in1 )
|
||||
r[3][4] = 0.0f;
|
||||
r[3][5] = 0.0f;
|
||||
r[3][6] = 0.0f;
|
||||
r[3][7] = 1.0f;
|
||||
r[3][7] = 1.0f;
|
||||
|
||||
if( fabs( r[3][0] ) > fabs( r[2][0] ))
|
||||
{
|
||||
|
||||
@@ -34,7 +34,7 @@ int boxpnt[6][4] =
|
||||
{ 7, 5, 1, 3 }, // -X
|
||||
{ 7, 3, 2, 6 }, // -Y
|
||||
{ 7, 6, 4, 5 }, // -Z
|
||||
};
|
||||
};
|
||||
|
||||
// pre-quantized table normals from Quake1
|
||||
const float m_bytenormals[NUMVERTEXNORMALS][3] =
|
||||
@@ -128,7 +128,7 @@ round the hullsize to nearest 'right' value
|
||||
void RoundUpHullSize( vec3_t size )
|
||||
{
|
||||
int i, j;
|
||||
|
||||
|
||||
for( i = 0; i < 3; i++)
|
||||
{
|
||||
qboolean negative = false;
|
||||
@@ -149,7 +149,7 @@ void RoundUpHullSize( vec3_t size )
|
||||
{
|
||||
result = ( value - hull_table[j] );
|
||||
if( result <= HULL_PRECISION )
|
||||
{
|
||||
{
|
||||
result = -hull_table[j];
|
||||
break;
|
||||
}
|
||||
@@ -158,7 +158,7 @@ void RoundUpHullSize( vec3_t size )
|
||||
{
|
||||
result = ( value - hull_table[j] );
|
||||
if( result <= HULL_PRECISION )
|
||||
{
|
||||
{
|
||||
result = hull_table[j];
|
||||
break;
|
||||
}
|
||||
@@ -244,6 +244,23 @@ qboolean PlanesGetIntersectionPoint( const mplane_t *plane1, const mplane_t *pla
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
PlaneIntersect
|
||||
|
||||
find point where ray
|
||||
was intersect with plane
|
||||
=================
|
||||
*/
|
||||
void PlaneIntersect( const mplane_t *plane, const vec3_t p0, const vec3_t p1, vec3_t out )
|
||||
{
|
||||
float distToPlane = PlaneDiff( p0, plane );
|
||||
float planeDotRay = DotProduct( plane->normal, p1 );
|
||||
float sect = -(distToPlane) / planeDotRay;
|
||||
|
||||
VectorMA( p0, sect, p1, out );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
NearestPOW
|
||||
@@ -289,6 +306,23 @@ rsqrt
|
||||
*/
|
||||
float rsqrt( float number )
|
||||
{
|
||||
#if XASH_PSP
|
||||
float result;
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S000, %1\n" // S000 = number
|
||||
"vzero.s S001\n" // S111 = 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 = S001
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( result )
|
||||
: "m"( number )
|
||||
);
|
||||
return result;
|
||||
#else
|
||||
int i;
|
||||
float x, y;
|
||||
|
||||
@@ -302,6 +336,7 @@ float rsqrt( float number )
|
||||
y = y * (1.5f - (x * y * y)); // first iteration
|
||||
|
||||
return y;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -311,6 +346,21 @@ SinCos
|
||||
*/
|
||||
void SinCos( float radians, float *sine, float *cosine )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S000, %2\n" // 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 )
|
||||
: "m"( radians )
|
||||
);
|
||||
#else
|
||||
#if _MSC_VER == 1200
|
||||
_asm
|
||||
{
|
||||
@@ -327,6 +377,7 @@ void SinCos( float radians, float *sine, float *cosine )
|
||||
*sine = sin(radians);
|
||||
*cosine = cos(radians);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -451,7 +502,7 @@ void GAME_EXPORT VectorAngles( const float *forward, float *angles )
|
||||
if( pitch < 0 ) pitch += 360;
|
||||
}
|
||||
|
||||
VectorSet( angles, pitch, yaw, 0 );
|
||||
VectorSet( angles, pitch, yaw, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -489,6 +540,7 @@ void VectorsAngles( const vec3_t forward, const vec3_t right, const vec3_t up, v
|
||||
//
|
||||
// bounds operations
|
||||
//
|
||||
|
||||
/*
|
||||
=================
|
||||
ClearBounds
|
||||
@@ -585,23 +637,6 @@ qboolean SphereIntersect( const vec3_t vSphereCenter, float fSphereRadiusSquared
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
PlaneIntersect
|
||||
|
||||
find point where ray
|
||||
was intersect with plane
|
||||
=================
|
||||
*/
|
||||
void PlaneIntersect( const mplane_t *plane, const vec3_t p0, const vec3_t p1, vec3_t out )
|
||||
{
|
||||
float distToPlane = PlaneDiff( p0, plane );
|
||||
float planeDotRay = DotProduct( plane->normal, p1 );
|
||||
float sect = -(distToPlane) / planeDotRay;
|
||||
|
||||
VectorMA( p0, sect, p1, out );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
RadiusFromBounds
|
||||
@@ -630,6 +665,42 @@ AngleQuaternion
|
||||
*/
|
||||
void AngleQuaternion( const vec3_t angles, vec4_t q, qboolean studio )
|
||||
{
|
||||
#if 0//XASH_PSP /* performance not tested */
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
|
||||
|
||||
|
||||
/**/
|
||||
"lv.s S000, 8 + %1\n" // S000 = angles[ROLL]
|
||||
"lv.s S001, 0 + %1\n" // S000 = angles[PITCH]
|
||||
"lv.s S002, 4 + %1\n" // S000 = angles[YAW]
|
||||
/**/
|
||||
"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( *angles * 0.5f )
|
||||
"vsin.t C000, C000\n" // C000 = sin( *angles * 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 = cr*cp*cy + sr*sp*sy
|
||||
"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
|
||||
"usv.q C000, %0\n" // *q = C000
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *q )
|
||||
: "m"( *angles ), "r"( studio )
|
||||
);
|
||||
|
||||
printf("ASM [%f %f %f %f]\n", q[0], q[1], q[2], q[3] );
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
if( studio )
|
||||
@@ -649,6 +720,28 @@ 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
|
||||
printf("C [%f %f %f %f]\n", q[0], q[1], q[2], q[3] );
|
||||
#else
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
if( studio )
|
||||
{
|
||||
SinCos( angles[ROLL] * 0.5f, &sy, &cy );
|
||||
SinCos( angles[YAW] * 0.5f, &sp, &cp );
|
||||
SinCos( angles[PITCH] * 0.5f, &sr, &cr );
|
||||
}
|
||||
else
|
||||
{
|
||||
SinCos( DEG2RAD( angles[YAW] ) * 0.5f, &sy, &cy );
|
||||
SinCos( DEG2RAD( angles[PITCH] ) * 0.5f, &sp, &cp );
|
||||
SinCos( DEG2RAD( angles[ROLL] ) * 0.5f, &sr, &cr );
|
||||
}
|
||||
|
||||
q[0] = sr * cp * cy - cr * sp * sy; // X
|
||||
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
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -679,20 +772,20 @@ void QuaternionAlign( const vec4_t p, const vec4_t q, vec4_t qt )
|
||||
float b = 0.0f;
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 4; i++ )
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
a += (p[i] - q[i]) * (p[i] - q[i]);
|
||||
b += (p[i] + q[i]) * (p[i] + q[i]);
|
||||
}
|
||||
|
||||
if( a > b )
|
||||
if( a > b )
|
||||
{
|
||||
for( i = 0; i < 4; i++ )
|
||||
for( i = 0; i < 4; i++ )
|
||||
qt[i] = -q[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < 4; i++ )
|
||||
for( i = 0; i < 4; i++ )
|
||||
qt[i] = q[i];
|
||||
}
|
||||
}
|
||||
@@ -820,8 +913,184 @@ Returns 1, 2, or 1 + 2
|
||||
*/
|
||||
int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p )
|
||||
{
|
||||
float dist1, dist2;
|
||||
#if XASH_PSP
|
||||
int sides;
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S000, 0 + %[normal]\n" // S000 = p->normal[0]
|
||||
"lv.s S001, 4 + %[normal]\n" // S001 = p->normal[1]
|
||||
"lv.s S002, 8 + %[normal]\n" // S002 = p->normal[2]
|
||||
"vzero.p C030\n" // C030 = [0.0f, 0.0f]
|
||||
"lv.s S032, %[dist]\n" // S032 = p->dist
|
||||
"move $8, $0\n" // $8 = 0
|
||||
"beq %[signbits], $8, 0f\n" // jump to 0
|
||||
"addiu $8, $8, 1\n" // $8 = $8 + 1 ( delay slot )
|
||||
"beq %[signbits], $8, 1f\n" // jump to 1
|
||||
"addiu $8, $8, 1\n" // $8 = $8 + 1 ( delay slot )
|
||||
"beq %[signbits], $8, 2f\n" // jump to 2
|
||||
"addiu $8, $8, 1\n" // $8 = $8 + 1 ( delay slot )
|
||||
"beq %[signbits], $8, 3f\n" // jump to 3
|
||||
"addiu $8, $8, 1\n" // $8 = $8 + 1 ( delay slot )
|
||||
"beq %[signbits], $8, 4f\n" // jump to 4
|
||||
"addiu $8, $8, 1\n" // $8 = $8 + 1 ( delay slot )
|
||||
"beq %[signbits], $8, 5f\n" // jump to 5
|
||||
"addiu $8, $8, 1\n" // $8 = $8 + 1 ( delay slot )
|
||||
"beq %[signbits], $8, 6f\n" // jump to 6
|
||||
"addiu $8, $8, 1\n" // $8 = $8 + 1 ( delay slot )
|
||||
"beq %[signbits], $8, 7f\n" // jump to 7
|
||||
"nop\n" // ( delay slot )
|
||||
"j 8f\n" // jump to SetSides
|
||||
"nop\n" // ( delay slot )
|
||||
"0:\n"
|
||||
/*
|
||||
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
|
||||
dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
|
||||
*/
|
||||
"lv.s S010, 0 + %[emaxs]\n" // S010 = emaxs[0]
|
||||
"lv.s S011, 4 + %[emaxs]\n" // S011 = emaxs[1]
|
||||
"lv.s S012, 8 + %[emaxs]\n" // S012 = emaxs[2]
|
||||
"lv.s S020, 0 + %[emins]\n" // S020 = emins[0]
|
||||
"lv.s S021, 4 + %[emins]\n" // S021 = emins[1]
|
||||
"lv.s S022, 8 + %[emins]\n" // S022 = emins[2]
|
||||
"vdot.t S030, C000, C010\n" // S030 = C000 * C010
|
||||
"vdot.t S031, C000, C020\n" // S030 = C000 * C020
|
||||
"j 8f\n" // jump to SetSides
|
||||
"nop\n" // ( delay slot )
|
||||
"1:\n"
|
||||
/*
|
||||
dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
|
||||
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
|
||||
*/
|
||||
"lv.s S010, 0 + %[emins]\n" // S010 = emins[0]
|
||||
"lv.s S011, 4 + %[emaxs]\n" // S011 = emaxs[1]
|
||||
"lv.s S012, 8 + %[emaxs]\n" // S012 = emaxs[2]
|
||||
"lv.s S020, 0 + %[emaxs]\n" // S020 = emaxs[0]
|
||||
"lv.s S021, 4 + %[emins]\n" // S021 = emins[1]
|
||||
"lv.s S022, 8 + %[emins]\n" // S022 = emins[2]
|
||||
"vdot.t S030, C000, C010\n" // S030 = C000 * C010
|
||||
"vdot.t S031, C000, C020\n" // S030 = C000 * C020
|
||||
"j 8f\n" // jump to SetSides
|
||||
"nop\n" // ( delay slot )
|
||||
"2:\n"
|
||||
/*
|
||||
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
|
||||
dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
|
||||
*/
|
||||
"lv.s S010, 0 + %[emaxs]\n" // S010 = emaxs[0]
|
||||
"lv.s S011, 4 + %[emins]\n" // S011 = emins[1]
|
||||
"lv.s S012, 8 + %[emaxs]\n" // S012 = emaxs[2]
|
||||
"lv.s S020, 0 + %[emins]\n" // S020 = emins[0]
|
||||
"lv.s S021, 4 + %[emaxs]\n" // S021 = emaxs[1]
|
||||
"lv.s S022, 8 + %[emins]\n" // S022 = emins[2]
|
||||
"vdot.t S030, C000, C010\n" // S030 = C000 * C010
|
||||
"vdot.t S031, C000, C020\n" // S030 = C000 * C020
|
||||
"j 8f\n" // jump to SetSides
|
||||
"nop\n" // ( delay slot )
|
||||
"3:\n"
|
||||
/*
|
||||
dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
|
||||
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
|
||||
*/
|
||||
"lv.s S010, 0 + %[emins]\n" // S010 = emins[0]
|
||||
"lv.s S011, 4 + %[emins]\n" // S011 = emins[1]
|
||||
"lv.s S012, 8 + %[emaxs]\n" // S012 = emaxs[2]
|
||||
"lv.s S020, 0 + %[emaxs]\n" // S020 = emaxs[0]
|
||||
"lv.s S021, 4 + %[emaxs]\n" // S021 = emaxs[1]
|
||||
"lv.s S022, 8 + %[emins]\n" // S022 = emins[2]
|
||||
"vdot.t S030, C000, C010\n" // S030 = C000 * C010
|
||||
"vdot.t S031, C000, C020\n" // S030 = C000 * C020
|
||||
"j 8f\n" // jump to SetSides
|
||||
"nop\n" // ( delay slot )
|
||||
"4:\n"
|
||||
/*
|
||||
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
|
||||
dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
|
||||
*/
|
||||
"lv.s S010, 0 + %[emaxs]\n" // S010 = emaxs[0]
|
||||
"lv.s S011, 4 + %[emaxs]\n" // S011 = emaxs[1]
|
||||
"lv.s S012, 8 + %[emins]\n" // S012 = emins[2]
|
||||
"lv.s S020, 0 + %[emins]\n" // S020 = emins[0]
|
||||
"lv.s S021, 4 + %[emins]\n" // S021 = emins[1]
|
||||
"lv.s S022, 8 + %[emaxs]\n" // S022 = emaxs[2]
|
||||
"vdot.t S030, C000, C010\n" // S030 = C000 * C010
|
||||
"vdot.t S031, C000, C020\n" // S030 = C000 * C020
|
||||
"j 8f\n" // jump to SetSides
|
||||
"nop\n" // ( delay slot )
|
||||
"5:\n"
|
||||
/*
|
||||
dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
|
||||
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
|
||||
*/
|
||||
"lv.s S010, 0 + %[emins]\n" // S010 = emins[0]
|
||||
"lv.s S011, 4 + %[emaxs]\n" // S011 = emaxs[1]
|
||||
"lv.s S012, 8 + %[emins]\n" // S012 = emins[2]
|
||||
"lv.s S020, 0 + %[emaxs]\n" // S020 = emaxs[0]
|
||||
"lv.s S021, 4 + %[emins]\n" // S021 = emins[1]
|
||||
"lv.s S022, 8 + %[emaxs]\n" // S022 = emaxs[2]
|
||||
"vdot.t S030, C000, C010\n" // S030 = C000 * C010
|
||||
"vdot.t S031, C000, C020\n" // S030 = C000 * C020
|
||||
"j 8f\n" // jump to SetSides
|
||||
"nop\n" // ( delay slot )
|
||||
"6:\n"
|
||||
/*
|
||||
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
|
||||
dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
|
||||
*/
|
||||
"lv.s S010, 0 + %[emaxs]\n" // S010 = emaxs[0]
|
||||
"lv.s S011, 4 + %[emins]\n" // S011 = emins[1]
|
||||
"lv.s S012, 8 + %[emins]\n" // S012 = emins[2]
|
||||
"lv.s S020, 0 + %[emins]\n" // S020 = emins[0]
|
||||
"lv.s S021, 4 + %[emaxs]\n" // S021 = emaxs[1]
|
||||
"lv.s S022, 8 + %[emaxs]\n" // S022 = emaxs[2]
|
||||
"vdot.t S030, C000, C010\n" // S030 = C000 * C010
|
||||
"vdot.t S031, C000, C020\n" // S030 = C000 * C020
|
||||
"j 8f\n" // jump to SetSides
|
||||
"nop\n" // ( delay slot )
|
||||
"7:\n"
|
||||
/*
|
||||
dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
|
||||
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
|
||||
*/
|
||||
"lv.s S010, 0 + %[emins]\n" // S010 = emins[0]
|
||||
"lv.s S011, 4 + %[emins]\n" // S011 = emins[1]
|
||||
"lv.s S012, 8 + %[emins]\n" // S012 = emins[2]
|
||||
"lv.s S020, 0 + %[emaxs]\n" // S020 = emaxs[0]
|
||||
"lv.s S021, 4 + %[emaxs]\n" // S021 = emaxs[1]
|
||||
"lv.s S022, 8 + %[emaxs]\n" // S022 = emaxs[2]
|
||||
"vdot.t S030, C000, C010\n" // S030 = C000 * C010
|
||||
"vdot.t S031, C000, C020\n" // S030 = C000 * C020
|
||||
"8:\n" // SetSides
|
||||
/*
|
||||
if( dist1 >= p->dist )
|
||||
sides = 1;
|
||||
if( dist2 < p->dist )
|
||||
sides |= 2;
|
||||
*/
|
||||
"addiu %[sides], $0, 0\n" // sides = 0
|
||||
"vcmp.s LT, S030, S032\n" // S030 < S032
|
||||
"bvt 0, 9f\n" // if ( CC[0] == 1 ) jump to 9
|
||||
"nop\n" // ( delay slot )
|
||||
"addiu %[sides], %[sides], 1\n"// sides = 1
|
||||
"9:\n"
|
||||
"vcmp.s GE, S031, S032\n" // S031 >= S032
|
||||
"bvt 0, 10f\n" // if ( CC[0] == 1 ) jump to 10
|
||||
"nop\n" // ( delay slot )
|
||||
"addiu %[sides], %[sides], 2\n"// sides = sides + 2
|
||||
"10:\n"
|
||||
".set pop\n" // restore assembler option
|
||||
: [sides] "=r" ( sides )
|
||||
: [normal] "m" ( p->normal ),
|
||||
[emaxs] "m" ( *emaxs ),
|
||||
[emins] "m" ( *emins ),
|
||||
[signbits] "r" ( p->signbits ),
|
||||
[dist] "m" ( p->dist )
|
||||
: "$8"
|
||||
);
|
||||
return sides;
|
||||
#else
|
||||
int sides = 0;
|
||||
float dist1, dist2;
|
||||
|
||||
// general case
|
||||
switch( p->signbits )
|
||||
@@ -870,5 +1139,6 @@ int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p )
|
||||
sides |= 2;
|
||||
|
||||
return sides;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
2
ref_gu/exports.txt
Normal file
2
ref_gu/exports.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
GetRefAPI
|
||||
GetRefHumanReadableName
|
||||
1545
ref_gu/gu_alias.c
Normal file
1545
ref_gu/gu_alias.c
Normal file
File diff suppressed because it is too large
Load Diff
663
ref_gu/gu_backend.c
Normal file
663
ref_gu/gu_backend.c
Normal file
@@ -0,0 +1,663 @@
|
||||
/*
|
||||
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 )
|
||||
{
|
||||
float dest[16];
|
||||
|
||||
Matrix4x4_ToArrayFloatGL( source, dest );
|
||||
sceGumLoadMatrix( ( const ScePspFMatrix4 * ) 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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
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 )
|
||||
{
|
||||
#if 0
|
||||
rgbdata_t *r_shot;
|
||||
uint flags = IMAGE_FLIP_Y;
|
||||
int width = 0, height = 0;
|
||||
qboolean result;
|
||||
|
||||
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;
|
||||
r_shot->size = r_shot->width * r_shot->height * gEngfuncs.Image_GetPFDesc( r_shot->type )->bpp;
|
||||
r_shot->palette = NULL;
|
||||
r_shot->buffer = Mem_Malloc( r_temppool, r_shot->size );
|
||||
|
||||
// get screen frame
|
||||
pglReadPixels( 0, 0, r_shot->width, r_shot->height, GL_RGB, GL_UNSIGNED_BYTE, r_shot->buffer );
|
||||
|
||||
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;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
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 );
|
||||
}
|
||||
1544
ref_gu/gu_beams.c
Normal file
1544
ref_gu/gu_beams.c
Normal file
File diff suppressed because it is too large
Load Diff
416
ref_gu/gu_clipping.c
Normal file
416
ref_gu/gu_clipping.c
Normal file
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include "gu_local.h"
|
||||
|
||||
#define MAX_CLIPPED_VERTICES 32
|
||||
|
||||
#define CPLANE_BOTTOM 0
|
||||
#define CPLANE_LEFT 1
|
||||
#define CPLANE_RIGHT 2
|
||||
#define CPLANE_TOP 3
|
||||
#define MAX_CPLANES 4
|
||||
|
||||
// Types.
|
||||
typedef ScePspFVector4 plane_type;
|
||||
typedef plane_type frustum_t[MAX_CPLANES];
|
||||
|
||||
// Transformed frustum.
|
||||
static ScePspFMatrix4 projection_view_matrix __attribute__( ( aligned( 16 ) ) );
|
||||
static frustum_t projection_view_frustum __attribute__( ( aligned( 16 ) ) );
|
||||
static frustum_t clipping_frustum __attribute__( ( aligned( 16 ) ) );
|
||||
|
||||
// The temporary working buffers.
|
||||
static gu_vert_t work_buffer[2][MAX_CLIPPED_VERTICES] __attribute__( ( aligned( 16 ) ) );
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_ClipGetFrustum
|
||||
=================
|
||||
*/
|
||||
_inline void GU_ClipGetFrustum(const ScePspFMatrix4 *matrix, frustum_t* frustum)
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0(%4)\n" // C000 = matrix->x
|
||||
"lv.q C110, 16(%4)\n" // C010 = matrix->y
|
||||
"lv.q C120, 32(%4)\n" // C020 = matrix->z
|
||||
"lv.q C130, 48(%4)\n" // C030 = matrix->w
|
||||
"vzero.q C210\n" // C000 = 0
|
||||
"vadd.q C000, R103, R101\n" // C000 = R103 + R101 ( BOTTOM )
|
||||
"vdot.q S200, C000, C000\n" // S110 = S100*S100 + S101*S101 + S102*S102 + S103*S103 ( BOTTOM )
|
||||
"vadd.q C010, R103, R100\n" // C010 = R103 + R100 ( LEFT )
|
||||
"vdot.q S201, C010, C010\n" // S110 = S100*S100 + S101*S101 + S102*S102 + S103*S103 ( LEFT )
|
||||
"vsub.q C020, R103, R100\n" // C020 = R103 - R100 ( RIGHT )
|
||||
"vdot.q S202, C020, C020\n" // S110 = S100*S100 + S101*S101 + S102*S102 + S103*S103 ( RIGHT )
|
||||
"vsub.q C030, R103, R101\n" // C030 = R103 - R101 ( TOP )
|
||||
"vdot.q S203, C030, C030\n" // S110 = S100*S100 + S101*S101 + S102*S102 + S103*S103 ( TOP )
|
||||
"vcmp.q EZ, C200\n" // CC[0] = ( C200 == 0.0f )
|
||||
"vrsq.q C200, C200\n" // C200 = 1.0 / sqrt( C200 )
|
||||
"vcmovt.q C200, C210, 0\n" // if ( CC[*] ) C200 = C210
|
||||
"vscl.q C000, C000, S200\n" // C000 = C000 * S200 ( BOTTOM )
|
||||
"vscl.q C010, C010, S201\n" // C010 = C010 * S201 ( LEFT )
|
||||
"vscl.q C020, C020, S202\n" // C020 = C020 * S202 ( RIGHT )
|
||||
"vscl.q C030, C030, S203\n" // C030 = C030 * S203 ( TOP )
|
||||
"sv.q C000, %0\n" // Store plane from register
|
||||
"sv.q C010, %1\n" // Store plane from register
|
||||
"sv.q C020, %2\n" // Store plane from register
|
||||
"sv.q C030, %3\n" // Store plane from register
|
||||
".set pop\n" // Restore assembler option
|
||||
: "=m"( ( *frustum )[CPLANE_BOTTOM] ),
|
||||
"=m"( ( *frustum )[CPLANE_LEFT] ),
|
||||
"=m"( ( *frustum )[CPLANE_RIGHT] ),
|
||||
"=m"( ( *frustum )[CPLANE_TOP] )
|
||||
: "r"( matrix ) /* addr */
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_ClipBeginFrame
|
||||
|
||||
Calculate the clipping frustum for static objects
|
||||
=================
|
||||
*/
|
||||
void GU_ClipBeginFrame( void )
|
||||
{
|
||||
// Get the projection matrix.
|
||||
sceGumMatrixMode( GU_PROJECTION );
|
||||
ScePspFMatrix4 proj;
|
||||
sceGumStoreMatrix( &proj );
|
||||
|
||||
// Get the view matrix.
|
||||
sceGumMatrixMode( GU_VIEW );
|
||||
ScePspFMatrix4 view;
|
||||
sceGumStoreMatrix( &view );
|
||||
|
||||
// Restore matrix mode.
|
||||
sceGumMatrixMode( GU_MODEL );
|
||||
|
||||
// Combine the two matrices (multiply projection by view).
|
||||
gumMultMatrix( &projection_view_matrix, &proj, &view );
|
||||
|
||||
// Calculate and cache the clipping frustum.
|
||||
GU_ClipGetFrustum( &projection_view_matrix, &projection_view_frustum );
|
||||
|
||||
__asm__ volatile(
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C700, %4\n" // Load plane into register
|
||||
"lv.q C710, %5\n" // Load plane into register
|
||||
"lv.q C720, %6\n" // Load plane into register
|
||||
"lv.q C730, %7\n" // Load plane into register
|
||||
"sv.q C700, %0\n" // Store plane from register
|
||||
"sv.q C710, %1\n" // Store plane from register
|
||||
"sv.q C720, %2\n" // Store plane from register
|
||||
"sv.q C730, %3\n" // Store plane from register
|
||||
".set pop\n" // Restore assembler option
|
||||
: "=m"( clipping_frustum[CPLANE_BOTTOM] ),
|
||||
"=m"( clipping_frustum[CPLANE_LEFT] ),
|
||||
"=m"( clipping_frustum[CPLANE_RIGHT] ),
|
||||
"=m"( clipping_frustum[CPLANE_TOP] )
|
||||
: "m"( projection_view_frustum[CPLANE_BOTTOM] ),
|
||||
"m"( projection_view_frustum[CPLANE_LEFT] ),
|
||||
"m"( projection_view_frustum[CPLANE_RIGHT] ),
|
||||
"m"( projection_view_frustum[CPLANE_TOP] )
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_ClipBeginBrush
|
||||
|
||||
Calculate the clipping frustum for dynamic objects
|
||||
=================
|
||||
*/
|
||||
void GU_ClipBeginBrush( void )
|
||||
{
|
||||
// Get the model matrix.
|
||||
ScePspFMatrix4 model_matrix;
|
||||
sceGumStoreMatrix( &model_matrix );
|
||||
|
||||
// Combine the matrices (multiply projection-view by model).
|
||||
ScePspFMatrix4 projection_view_model_matrix;
|
||||
gumMultMatrix( &projection_view_model_matrix, &projection_view_matrix, &model_matrix );
|
||||
|
||||
// Calculate the clipping frustum.
|
||||
GU_ClipGetFrustum( &projection_view_model_matrix, &clipping_frustum );
|
||||
|
||||
__asm__ volatile(
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C700, %0\n" // Load plane into register
|
||||
"lv.q C710, %1\n" // Load plane into register
|
||||
"lv.q C720, %2\n" // Load plane into register
|
||||
"lv.q C730, %3\n" // Load plane into register
|
||||
".set pop\n" // Restore assembler option
|
||||
:: "m"( clipping_frustum[CPLANE_BOTTOM] ),
|
||||
"m"( clipping_frustum[CPLANE_LEFT] ),
|
||||
"m"( clipping_frustum[CPLANE_RIGHT] ),
|
||||
"m"( clipping_frustum[CPLANE_TOP] )
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_ClipEndBrush
|
||||
|
||||
Restore the clipping frustum
|
||||
=================
|
||||
*/
|
||||
void GU_ClipEndBrush( void )
|
||||
{
|
||||
__asm__ volatile(
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C700, %4\n" // Load plane into register
|
||||
"lv.q C710, %5\n" // Load plane into register
|
||||
"lv.q C720, %6\n" // Load plane into register
|
||||
"lv.q C730, %7\n" // Load plane into register
|
||||
"sv.q C700, %0\n" // Store plane from register
|
||||
"sv.q C710, %1\n" // Store plane from register
|
||||
"sv.q C720, %2\n" // Store plane from register
|
||||
"sv.q C730, %3\n" // Store plane from register
|
||||
".set pop\n" // Restore assembler option
|
||||
: "=m"( clipping_frustum[CPLANE_BOTTOM] ),
|
||||
"=m"( clipping_frustum[CPLANE_LEFT] ),
|
||||
"=m"( clipping_frustum[CPLANE_RIGHT] ),
|
||||
"=m"( clipping_frustum[CPLANE_TOP] )
|
||||
: "m"( projection_view_frustum[CPLANE_BOTTOM] ),
|
||||
"m"( projection_view_frustum[CPLANE_LEFT] ),
|
||||
"m"( projection_view_frustum[CPLANE_RIGHT] ),
|
||||
"m"( projection_view_frustum[CPLANE_TOP] )
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
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, %4\n" // Load plane into register
|
||||
"ulv.q C710, %5\n" // Load plane into register
|
||||
"ulv.q C720, %6\n" // Load plane into register
|
||||
"ulv.q C730, %7\n" // Load plane into register
|
||||
"vneg.q R703, R703\n" // R703 = -R703 = -dist
|
||||
"sv.q C700, %0\n" // Store plane from register
|
||||
"sv.q C710, %1\n" // Store plane from register
|
||||
"sv.q C720, %2\n" // Store plane from register
|
||||
"sv.q C730, %3\n" // Store plane from register
|
||||
".set pop\n" // Restore assembler option
|
||||
: "=m"( clipping_frustum[CPLANE_BOTTOM] ),
|
||||
"=m"( clipping_frustum[CPLANE_LEFT] ),
|
||||
"=m"( clipping_frustum[CPLANE_RIGHT] ),
|
||||
"=m"( clipping_frustum[CPLANE_TOP] )
|
||||
: "m"( plane[FRUSTUM_BOTTOM] ),
|
||||
"m"( plane[FRUSTUM_LEFT] ),
|
||||
"m"( plane[FRUSTUM_RIGHT] ),
|
||||
"m"( plane[FRUSTUM_TOP] )
|
||||
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_ClipIsRequired
|
||||
|
||||
Is clipping required?
|
||||
=================
|
||||
*/
|
||||
qboolean GU_ClipIsRequired( const gu_vert_t* v, size_t vc )
|
||||
{
|
||||
int res;
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"move $8, %1\n" // $8 = &v[0]
|
||||
"move $9, %2\n" // $9 = vc
|
||||
"li $10, 20\n" // $10 = 20( sizeof( gu_vert_t ) )
|
||||
"mul $10, $10, $9\n" // $10 = $10 * $9
|
||||
"addu $10, $10, $8\n" // $10 = $10 + $8
|
||||
"addiu %0, $0, 1\n" // res = 1
|
||||
"vzero.q C600\n" // C600 = [0.0f, 0.0f, 0.0f. 0.0f]
|
||||
"0:\n" // loop
|
||||
"lv.s S610, 8($8)\n" // S610 = v[i].xyz[0]
|
||||
"lv.s S611, 12($8)\n" // S611 = v[i].xyz[1]
|
||||
"lv.s S612, 16($8)\n" // S612 = v[i].xyz[2]
|
||||
"vhtfm4.q C620, M700, C610\n" // C620 = frustrum * v[i].xyz
|
||||
"vcmp.q LT, C620, C600\n" // S620 < 0.0f || S621 < 0.0f || S622 < 0.0f || S623 < 0.0f
|
||||
"bvt 4, 1f\n" // if ( CC[4] == 1 ) jump to exit
|
||||
"addiu $8, $8, 20\n" // $8 = $8 + 20( sizeof( gu_vert_t ) ) ( delay slot )
|
||||
"bne $10, $8, 0b\n" // if ( $10 != $8 ) jump to loop
|
||||
"nop\n" // ( delay slot )
|
||||
"move %0, $0\n" // res = 0
|
||||
"1:\n" // exit
|
||||
".set pop\n" // Restore assembler option
|
||||
: "=r"( res )
|
||||
: "r"( v ), "r"( vc )
|
||||
: "$8", "$9", "$10"
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_Clip2Plane
|
||||
|
||||
Clips a polygon against a plane.
|
||||
=================
|
||||
*/
|
||||
_inline void GU_Clip2Plane( plane_type *plane, gu_vert_t *uv, size_t uvc, gu_vert_t *cv, size_t *cvc )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"move $8, %1\n" // $8 = uv[0] is S
|
||||
"addiu $9, $8, 20\n" // $9 = uv[1] is P
|
||||
"move $10, %2\n" // $10 = uvc
|
||||
"li $11, 20\n" // $11 = 20( sizeof( gu_vert_t ) )
|
||||
"mul $11, $11, $10\n" // $11 = $11 * $10
|
||||
"addu $11, $11, $8\n" // $11 = $11 + $8
|
||||
"move $12, %3\n" // $12 = &cv[0]
|
||||
"move %0, $0\n" // cvc = 0
|
||||
"ulv.q C100, %4\n" // Load plane into register
|
||||
"vzero.s S110\n" // Set zero for cmp
|
||||
"0:\n" // loop
|
||||
"lv.s S000, 0($8)\n" // Load vertex S TEX(4b) U into register
|
||||
"lv.s S001, 4($8)\n" // Load vertex S TEX(4b) V into register
|
||||
"lv.s S010, 8($8)\n" // Load vertex S XYZ(4b) X into register
|
||||
"lv.s S011, 12($8)\n" // Load vertex S XYZ(4b) Y into register
|
||||
"lv.s S012, 16($8)\n" // Load vertex S XYZ(4b) Z into register
|
||||
"lv.s S020, 0($9)\n" // Load vertex P TEX(4b) U into register
|
||||
"lv.s S021, 4($9)\n" // Load vertex P TEX(4b) V into register
|
||||
"lv.s S030, 8($9)\n" // Load vertex P XYZ(4b) X into register
|
||||
"lv.s S031, 12($9)\n" // Load vertex P XYZ(4b) Y into register
|
||||
"lv.s S032, 16($9)\n" // Load vertex P XYZ(4b) Z into register
|
||||
"vhdp.q S111, C010, C100\n" // S111 = plane * S (S DIST)
|
||||
"vhdp.q S112, C030, C100\n" // S112 = plane * P (P DIST)
|
||||
"vcmp.s LE, S111, S110\n" // (S dist <= 0.0f)
|
||||
"bvt 0, 2f\n" // if ( CC[0] == 1 ) jump to 2f
|
||||
"nop\n" // ( delay slot )
|
||||
"vcmp.s LE, S112, S110\n" // (P dist <= 0.0f)
|
||||
"bvt 0, 1f\n" // if ( CC[0] == 1 ) jump to 1f
|
||||
"nop\n" // ( delay slot )
|
||||
"sv.s S020, 0($12)\n" // cv->uv[0] = C020 TEX U
|
||||
"sv.s S021, 4($12)\n" // cv->uv[1] = C021 TEX V
|
||||
"sv.s S030, 8($12)\n" // cv->xyz[0] = C030 XYZ X
|
||||
"sv.s S031, 12($12)\n" // cv->xyz[1] = C031 XYZ Y
|
||||
"sv.s S032, 16($12)\n" // cv->xyz[2] = C032 XYZ Z
|
||||
"addiu $12, $12, 20\n" // $12 = $12 + 20( sizeof( gu_vert_t ) )
|
||||
"j 3f\n" // jump to next
|
||||
"addiu %0, %0, 1\n" // cvc += 1 ( delay slot )
|
||||
"1:\n"
|
||||
"vsub.s S112, S111, S112\n" // S112 = ( S dist - P dist )
|
||||
"vdiv.s S112, S111, S112\n" // S112 = S111 / S112
|
||||
"vsub.p C120, C020, C000\n" // C120 = C020(P TEX) - C000(S TEX)
|
||||
"vsub.t C130, C030, C010\n" // C130 = C030(P XYZ) - C010(S XYZ)
|
||||
"vscl.p C120, C120, S112\n" // C120 = C020 * S112
|
||||
"vscl.t C130, C130, S112\n" // C130 = C030 * S112
|
||||
"vadd.p C120, C120, C000\n" // C120 = C120 + C000(S TEX)
|
||||
"vadd.t C130, C130, C010\n" // C130 = C130 + C010(S XYZ)
|
||||
"sv.s S120, 0($12)\n" // cv->uv[0] = S120 TEX U
|
||||
"sv.s S121, 4($12)\n" // cv->uv[1] = S121 TEX V
|
||||
"sv.s S130, 8($12)\n" // cv->xyz[0] = S130 XYZ X
|
||||
"sv.s S131, 12($12)\n" // cv->xyz[1] = S131 XYZ Y
|
||||
"sv.s S132, 16($12)\n" // cv->xyz[2] = S132 XYZ Z
|
||||
"addiu $12, $12, 20\n" // $12 = $12 + 20( sizeof( gu_vert_t ) )
|
||||
"j 3f\n" // jump to next
|
||||
"addiu %0, %0, 1\n" // cvc += 1 ( delay slot )
|
||||
"2:\n"
|
||||
"vcmp.s LE, S112, S110\n" // (P dist <= 0.0f)
|
||||
"bvt 0, 3f\n" // if ( CC[0] == 1 ) jump to next
|
||||
"nop\n" // ( delay slot )
|
||||
"vsub.s S112, S111, S112\n" // S112 = ( S dist - P dist )
|
||||
"vdiv.s S112, S111, S112\n" // S112 = S111 / S112
|
||||
"vsub.p C120, C020, C000\n" // C120 = C020(P TEX) - C000(S TEX)
|
||||
"vsub.t C130, C030, C010\n" // C130 = C030(P XYZ) - C010(S XYZ)
|
||||
"vscl.p C120, C120, S112\n" // C120 = C020 * S112
|
||||
"vscl.t C130, C130, S112\n" // C130 = C030 * S112
|
||||
"vadd.p C120, C120, C000\n" // C120 = C120 + C000(S TEX)
|
||||
"vadd.t C130, C130, C010\n" // C130 = C130 + C010(S XYZ)
|
||||
"sv.s S120, 0($12)\n" // cv->uv[0] = S120 TEX U
|
||||
"sv.s S121, 4($12)\n" // cv->uv[1] = S121 TEX V
|
||||
"sv.s S130, 8($12)\n" // cv->xyz[0] = S130 XYZ X
|
||||
"sv.s S131, 12($12)\n" // cv->xyz[1] = S131 XYZ Y
|
||||
"sv.s S132, 16($12)\n" // cv->xyz[2] = S132 XYZ Z
|
||||
"addiu $12, $12, 20\n" // $12 = $12 + 20( sizeof( gu_vert_t ) )
|
||||
"addiu %0, %0, 1\n" // cvc += 1
|
||||
"sv.s S020, 0($12)\n" // cv->uv[0] = S020 TEX U
|
||||
"sv.s S021, 4($12)\n" // cv->uv[1] = S021 TEX V
|
||||
"sv.s S030, 8($12)\n" // cv->xyz[0] = S030 XYZ X
|
||||
"sv.s S031, 12($12)\n" // cv->xyz[1] = S031 XYZ Y
|
||||
"sv.s S032, 16($12)\n" // cv->xyz[2] = S032 XYZ Z
|
||||
"addiu $12, $12, 20\n" // $12 = $12 + 20( sizeof( gu_vert_t ) )
|
||||
"addiu %0, %0, 1\n" // cvc += 1
|
||||
"3:\n" // next
|
||||
"addiu $8, $8, 20\n" // $8 = $8 + 20( sizeof( gu_vert_t ) )
|
||||
"addiu $9, $8, 20\n" // $9 = $8 + 20( sizeof( gu_vert_t ) )
|
||||
"bne $9, $11, 4f\n" // if ( $11 != $9 ) jump to next
|
||||
"nop\n"
|
||||
"move $9, %1\n" // $9 = &uv[0] set P
|
||||
"4:\n"
|
||||
"bne $11, $8, 0b\n" // if ( $11 != $8 ) jump to loop
|
||||
"nop\n" // ( delay slot )
|
||||
".set pop\n" // Restore assembler option
|
||||
: "+r"( *cvc )
|
||||
: "r"( uv ), "r"( uvc ), "r"( cv ), "m"( *plane )
|
||||
: "$8", "$9", "$10", "$11", "$12"
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
GU_Clip
|
||||
|
||||
Clips a polygon against the frustum
|
||||
=================
|
||||
*/
|
||||
void GU_Clip( gu_vert_t *uv, size_t uvc, gu_vert_t **cv, size_t* cvc )
|
||||
{
|
||||
size_t vc;
|
||||
|
||||
if ( !uvc ) // no vertices to clip?
|
||||
gEngfuncs.Host_Error( "GU_Clip: calling clip with zero vertices!" );
|
||||
|
||||
vc = uvc;
|
||||
*cvc = 0;
|
||||
|
||||
GU_Clip2Plane( &clipping_frustum[CPLANE_BOTTOM], uv, vc, work_buffer[0], &vc );
|
||||
if ( !vc ) return;
|
||||
GU_Clip2Plane( &clipping_frustum[CPLANE_LEFT], work_buffer[0], vc, work_buffer[1], &vc );
|
||||
if ( !vc ) return;
|
||||
GU_Clip2Plane( &clipping_frustum[CPLANE_RIGHT], work_buffer[1], vc, work_buffer[0], &vc );
|
||||
if ( !vc ) return;
|
||||
*cv = extGuBeginPacket( NULL ); // uncached
|
||||
GU_Clip2Plane( &clipping_frustum[CPLANE_TOP], work_buffer[0], vc, *cv, cvc );
|
||||
if ( !cvc ) return;
|
||||
extGuEndPacket( ( void * )( *cv + *cvc ) );
|
||||
}
|
||||
515
ref_gu/gu_context.c
Normal file
515
ref_gu/gu_context.c
Normal file
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
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;
|
||||
case PARM_TEX_MIPCOUNT:
|
||||
glt = R_GetTexture( arg );
|
||||
return glt->numMips;
|
||||
case PARM_TEX_DEPTH:
|
||||
glt = R_GetTexture( arg );
|
||||
return glt->depth;
|
||||
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,
|
||||
|
||||
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,
|
||||
|
||||
TriRenderMode,
|
||||
TriBegin,
|
||||
TriEnd,
|
||||
_TriColor4f,
|
||||
_TriColor4ub,
|
||||
TriTexCoord2f,
|
||||
TriVertex3fv,
|
||||
TriVertex3f,
|
||||
TriWorldToScreen,
|
||||
TriFog,
|
||||
R_ScreenToWorld,
|
||||
TriGetMatrix,
|
||||
TriFogParams,
|
||||
TriCullFace,
|
||||
|
||||
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->width );
|
||||
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
|
||||
355
ref_gu/gu_frustum.c
Normal file
355
ref_gu/gu_frustum.c
Normal file
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
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
|
||||
74
ref_gu/gu_helper.h
Normal file
74
ref_gu/gu_helper.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
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 0xffffff
|
||||
#define GUBLEND0 0x000000
|
||||
|
||||
// texture flags
|
||||
#define GUFLAGTEXNONE 0x00
|
||||
#define GUFLAGTEXUSED 0x01
|
||||
#define GUFLAGTEXSWIZZLED 0x02
|
||||
#define GUFLAGTEXINVRAM 0x04
|
||||
/*#define GUFLAGMIP 0x08*/
|
||||
|
||||
#endif // GU_HELPER_H
|
||||
2499
ref_gu/gu_image.c
Normal file
2499
ref_gu/gu_image.c
Normal file
File diff suppressed because it is too large
Load Diff
349
ref_gu/gu_init.c
Normal file
349
ref_gu/gu_init.c
Normal file
@@ -0,0 +1,349 @@
|
||||
|
||||
#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_finish;
|
||||
cvar_t *gl_nosort;
|
||||
cvar_t *gl_vsync;
|
||||
cvar_t *gl_clear;
|
||||
cvar_t *gl_test;
|
||||
cvar_t *gl_stencilbits;
|
||||
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 *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;
|
||||
|
||||
/*
|
||||
==============
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
GL_SetDefaults
|
||||
===============
|
||||
*/
|
||||
static void GL_SetDefaults( void )
|
||||
{
|
||||
#if 1
|
||||
/*
|
||||
sceGuFinish();
|
||||
sceGuSync(0,0);
|
||||
*/
|
||||
sceGuClearColor( GU_COLOR( 0.5f, 0.5f, 0.5f, 1.0f ) );
|
||||
|
||||
sceGuDisable( GU_DEPTH_TEST );
|
||||
sceGuDisable( GU_CULL_FACE );
|
||||
//sceGuDisable( GU_SCISSOR_TEST );
|
||||
sceGuDepthFunc( GU_LEQUAL );
|
||||
sceGuColor( 0xffffffff );
|
||||
|
||||
if( glState.stencilEnabled )
|
||||
{
|
||||
sceGuDisable( GU_STENCIL_TEST );
|
||||
/*pglStencilMask( ( GLuint ) ~0 );*/
|
||||
sceGuStencilFunc( GU_EQUAL, 0, ~0 );
|
||||
sceGuStencilOp( GU_KEEP, GU_INCR, GU_INCR );
|
||||
}
|
||||
sceGuDepthOffset( 0 );
|
||||
|
||||
GL_CleanupAllTextureUnits();
|
||||
|
||||
sceGuDisable( GU_BLEND );
|
||||
sceGuDisable( GU_ALPHA_TEST );
|
||||
|
||||
sceGuAlphaFunc( GU_GREATER, DEFAULT_ALPHATEST, 0xff );
|
||||
sceGuEnable( GU_TEXTURE_2D );
|
||||
sceGuShadeModel( GU_SMOOTH );
|
||||
sceGuFrontFace( GU_CCW );
|
||||
#else
|
||||
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 );
|
||||
#endif
|
||||
GL_Cull( GL_NONE );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
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( "Color %d bits, Alpha %d bits, Depth %d bits, Stencil %d bits\n", glConfig.color_bits,
|
||||
glConfig.alpha_bits, glConfig.depth_bits, glConfig.stencil_bits );
|
||||
}
|
||||
|
||||
void GL_InitExtensions( void )
|
||||
{
|
||||
// int colorBits[3];
|
||||
|
||||
glConfig.color_bits = 5 + 5 + 5;
|
||||
glConfig.alpha_bits = 1;
|
||||
glConfig.stencil_bits = ( int )gl_stencilbits->value;
|
||||
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 );
|
||||
|
||||
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", "-5.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_finish = gEngfuncs.Cvar_Get( "gl_finish", "0", FCVAR_GLCONFIG, "use glFinish instead of glFlush" );
|
||||
gl_nosort = gEngfuncs.Cvar_Get( "gl_nosort", "1", FCVAR_GLCONFIG, "disable sorting of translucent surfaces" );
|
||||
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_stencilbits = gEngfuncs.Cvar_Get( "gl_stencilbits", "8", FCVAR_GLCONFIG, "pixelformat stencil bits (0 - auto)" );
|
||||
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", "2", 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;
|
||||
|
||||
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" );
|
||||
|
||||
GL_SetDefaults();
|
||||
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();
|
||||
|
||||
Mem_FreePool( &r_temppool );
|
||||
|
||||
// shut down OS specific OpenGL stuff like contexts, etc.
|
||||
gEngfuncs.R_Free_Video();
|
||||
}
|
||||
|
||||
void GL_SetupAttributes( int safegl )
|
||||
{
|
||||
|
||||
}
|
||||
809
ref_gu/gu_local.h
Normal file
809
ref_gu/gu_local.h
Normal file
@@ -0,0 +1,809 @@
|
||||
/*
|
||||
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
|
||||
#if 1
|
||||
#include <pspkernel.h>
|
||||
#include <pspgu.h>
|
||||
#include <pspgum.h>
|
||||
#endif
|
||||
#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 "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;
|
||||
#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 guFlags;
|
||||
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
|
||||
//
|
||||
void R_SetTextureParameters( void );
|
||||
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 );
|
||||
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_UpdateDlightTexture( int texnum, int xoff, int yoff, int width, int height, const void *buffer );
|
||||
void GL_UpdateTexSize( int texnum, int width, int height, int depth );
|
||||
void GL_ApplyTextureParams( gl_texture_t *tex );
|
||||
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_ToArrayFloatGL( const matrix4x4 in, float out[16] );
|
||||
void Matrix4x4_FromArrayFloatGL( matrix4x4 out, const float in[16] );
|
||||
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 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 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 );
|
||||
#if 1
|
||||
/* Needs for psp */
|
||||
unsigned int getTriBrightness( float brightness );
|
||||
#endif
|
||||
|
||||
//
|
||||
// gu_clipping.c
|
||||
//
|
||||
#define CLIPPING_DEBUGGING 0
|
||||
void GU_ClipBeginFrame( void );
|
||||
void GU_ClipBeginBrush( void );
|
||||
void GU_ClipEndBrush( void );
|
||||
void GU_ClipLoadFrustum( const mplane_t *plane ); // Experimental
|
||||
qboolean GU_ClipIsRequired( const gu_vert_t* v, size_t vc );
|
||||
void GU_Clip( gu_vert_t *uv, size_t uvc, gu_vert_t **cv, size_t* cvc );
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
GL STATE MACHINE
|
||||
|
||||
=======================================================================
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int max_texture_size;
|
||||
int color_bits;
|
||||
int alpha_bits;
|
||||
int depth_bits;
|
||||
int stencil_bits;
|
||||
|
||||
gl_context_type_t context;
|
||||
gles_wrapper_t wrapper;
|
||||
|
||||
qboolean softwareGammaUpdate;
|
||||
qboolean fCustomRenderer;
|
||||
int prev_width;
|
||||
int prev_height;
|
||||
} 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;
|
||||
|
||||
extern glconfig_t glConfig;
|
||||
extern glstate_t glState;
|
||||
// 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_finish;
|
||||
extern cvar_t *gl_nosort;
|
||||
extern cvar_t *gl_clear;
|
||||
extern cvar_t *gl_test; // cvar to testify new effects
|
||||
extern cvar_t *gl_stencilbits;
|
||||
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;
|
||||
|
||||
//
|
||||
// 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
|
||||
496
ref_gu/gu_rlight.c
Normal file
496
ref_gu/gu_rlight.c
Normal file
@@ -0,0 +1,496 @@
|
||||
/*
|
||||
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; i < MAX_LIGHTSTYLES; i++ )
|
||||
{
|
||||
ls = gEngfuncs.GetLightStyle( i );
|
||||
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; i < MAX_DLIGHTS; i++, l++ )
|
||||
{
|
||||
l = gEngfuncs.GetDynamicLight( i );
|
||||
|
||||
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; i < MAX_DLIGHTS; i++ )
|
||||
{
|
||||
l = gEngfuncs.GetDynamicLight( i );
|
||||
|
||||
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 );
|
||||
}
|
||||
1361
ref_gu/gu_rmain.c
Normal file
1361
ref_gu/gu_rmain.c
Normal file
File diff suppressed because it is too large
Load Diff
267
ref_gu/gu_rmath.c
Normal file
267
ref_gu/gu_rmath.c
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
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 )
|
||||
{
|
||||
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];
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
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_ToArrayFloatGL( const matrix4x4 in, float out[16] )
|
||||
{
|
||||
out[ 0] = in[0][0];
|
||||
out[ 1] = in[1][0];
|
||||
out[ 2] = in[2][0];
|
||||
out[ 3] = in[3][0];
|
||||
out[ 4] = in[0][1];
|
||||
out[ 5] = in[1][1];
|
||||
out[ 6] = in[2][1];
|
||||
out[ 7] = in[3][1];
|
||||
out[ 8] = in[0][2];
|
||||
out[ 9] = in[1][2];
|
||||
out[10] = in[2][2];
|
||||
out[11] = in[3][2];
|
||||
out[12] = in[0][3];
|
||||
out[13] = in[1][3];
|
||||
out[14] = in[2][3];
|
||||
out[15] = in[3][3];
|
||||
}
|
||||
|
||||
void Matrix4x4_FromArrayFloatGL( matrix4x4 out, const float in[16] )
|
||||
{
|
||||
out[0][0] = in[0];
|
||||
out[1][0] = in[1];
|
||||
out[2][0] = in[2];
|
||||
out[3][0] = in[3];
|
||||
out[0][1] = in[4];
|
||||
out[1][1] = in[5];
|
||||
out[2][1] = in[6];
|
||||
out[3][1] = in[7];
|
||||
out[0][2] = in[8];
|
||||
out[1][2] = in[9];
|
||||
out[2][2] = in[10];
|
||||
out[3][2] = in[11];
|
||||
out[0][3] = in[12];
|
||||
out[1][3] = in[13];
|
||||
out[2][3] = in[14];
|
||||
out[3][3] = in[15];
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
405
ref_gu/gu_rpart.c
Normal file
405
ref_gu/gu_rpart.c
Normal file
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
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;
|
||||
|
||||
if( !cl_active_particles )
|
||||
return; // nothing to draw?
|
||||
#if 1
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuDisable( GU_ALPHA_TEST );
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
||||
|
||||
GL_Bind( XASH_TEXTURE0, tr.particleTexture );
|
||||
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
||||
sceGuDepthMask( GU_TRUE );
|
||||
|
||||
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;
|
||||
|
||||
sceGuColor( GUCOLOR4UB( gEngfuncs.LightToTexGamma( pColor->r ),
|
||||
gEngfuncs.LightToTexGamma( pColor->g ),
|
||||
gEngfuncs.LightToTexGamma( pColor->b ), alpha ) );
|
||||
|
||||
gu_vert_ftv_t* const out = ( gu_vert_ftv_t* )sceGuGetMemory( sizeof( gu_vert_ftv_t ) * 4 );
|
||||
|
||||
out[0].u = 0.0f;
|
||||
out[0].v = 1.0f;
|
||||
out[0].x = p->org[0] - right[0] + up[0];
|
||||
out[0].y = p->org[1] - right[1] + up[1];
|
||||
out[0].z = p->org[2] - right[2] + up[2];
|
||||
out[1].u = 0.0f;
|
||||
out[1].v = 0.0f;
|
||||
out[1].x = p->org[0] + right[0] + up[0];
|
||||
out[1].y = p->org[1] + right[1] + up[1];
|
||||
out[1].z = p->org[2] + right[2] + up[2];
|
||||
out[2].u = 1.0f;
|
||||
out[2].v = 0.0f;
|
||||
out[2].x = p->org[0] + right[0] - up[0];
|
||||
out[2].y = p->org[1] + right[1] - up[1];
|
||||
out[2].z = p->org[2] + right[2] - up[2];
|
||||
out[3].u = 1.0f;
|
||||
out[3].v = 1.0f;
|
||||
out[3].x = p->org[0] - right[0] - up[0];
|
||||
out[3].y = p->org[1] - right[1] - up[1];
|
||||
out[3].z = p->org[2] - right[2] - up[2];
|
||||
|
||||
sceGuDrawArray( GU_TRIANGLE_FAN, GU_TEXTURE_32BITF | GU_VERTEX_32BITF, 4, 0, out );
|
||||
|
||||
r_stats.c_particle_count++;
|
||||
}
|
||||
|
||||
gEngfuncs.CL_ThinkParticle( frametime, p );
|
||||
}
|
||||
|
||||
sceGuDepthMask( GU_FALSE );
|
||||
#else
|
||||
pglEnable( GL_BLEND );
|
||||
pglDisable( GL_ALPHA_TEST );
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
GL_Bind( XASH_TEXTURE0, tr.particleTexture );
|
||||
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglDepthMask( GL_FALSE );
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
|
||||
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;
|
||||
|
||||
pglColor4ub( gEngfuncs.LightToTexGamma( pColor->r ),
|
||||
gEngfuncs.LightToTexGamma( pColor->g ),
|
||||
gEngfuncs.LightToTexGamma( pColor->b ), alpha );
|
||||
|
||||
pglTexCoord2f( 0.0f, 1.0f );
|
||||
pglVertex3f( p->org[0] - right[0] + up[0], p->org[1] - right[1] + up[1], p->org[2] - right[2] + up[2] );
|
||||
pglTexCoord2f( 0.0f, 0.0f );
|
||||
pglVertex3f( p->org[0] + right[0] + up[0], p->org[1] + right[1] + up[1], p->org[2] + right[2] + up[2] );
|
||||
pglTexCoord2f( 1.0f, 0.0f );
|
||||
pglVertex3f( p->org[0] + right[0] - up[0], p->org[1] + right[1] - up[1], p->org[2] + right[2] - up[2] );
|
||||
pglTexCoord2f( 1.0f, 1.0f );
|
||||
pglVertex3f( p->org[0] - right[0] - up[0], p->org[1] - right[1] - up[1], p->org[2] - right[2] - up[2] );
|
||||
r_stats.c_particle_count++;
|
||||
}
|
||||
|
||||
gEngfuncs.CL_ThinkParticle( frametime, p );
|
||||
}
|
||||
|
||||
pglEnd();
|
||||
pglDepthMask( GL_TRUE );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
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?
|
||||
|
||||
if( !TriSpriteTexture( gEngfuncs.GetDefaultSprite( REF_DOT_SPRITE ), 0 ))
|
||||
return;
|
||||
#if 1
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, GUBLEND1 );
|
||||
sceGuDisable( GU_ALPHA_TEST );
|
||||
sceGuDepthMask( GU_TRUE );
|
||||
#else
|
||||
pglEnable( GL_BLEND );
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
||||
pglDisable( GL_ALPHA_TEST );
|
||||
pglDepthMask( GL_FALSE );
|
||||
#endif
|
||||
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];
|
||||
#if 1
|
||||
sceGuColor( GUCOLOR4UB( pColor->r, pColor->g, pColor->b, p->packedColor ) );
|
||||
|
||||
gu_vert_ftv_t* const out = ( gu_vert_ftv_t* )sceGuGetMemory( sizeof( gu_vert_ftv_t ) * 4 );
|
||||
|
||||
out[0].u = 0.0f;
|
||||
out[0].v = 0.8f;
|
||||
out[0].x = verts[2][0];
|
||||
out[0].y = verts[2][1];
|
||||
out[0].z = verts[2][2];
|
||||
out[1].u = 1.0f;
|
||||
out[1].v = 0.8f;
|
||||
out[1].x = verts[3][0];
|
||||
out[1].y = verts[3][1];
|
||||
out[1].z = verts[3][2];
|
||||
out[2].u = 1.0f;
|
||||
out[2].v = 0.0f;
|
||||
out[2].x = verts[1][0];
|
||||
out[2].y = verts[1][1];
|
||||
out[2].z = verts[1][2];
|
||||
out[3].u = 0.0f;
|
||||
out[3].v = 0.0f;
|
||||
out[3].x = verts[0][0];
|
||||
out[3].y = verts[0][1];
|
||||
out[3].z = verts[0][2];
|
||||
|
||||
sceGuDrawArray( GU_TRIANGLE_FAN, GU_TEXTURE_32BITF | GU_VERTEX_32BITF, 4, 0, out );
|
||||
#else
|
||||
pglColor4ub( pColor->r, pColor->g, pColor->b, p->packedColor );
|
||||
|
||||
pglBegin( GL_QUADS );
|
||||
pglTexCoord2f( 0.0f, 0.8f );
|
||||
pglVertex3fv( verts[2] );
|
||||
pglTexCoord2f( 1.0f, 0.8f );
|
||||
pglVertex3fv( verts[3] );
|
||||
pglTexCoord2f( 1.0f, 0.0f );
|
||||
pglVertex3fv( verts[1] );
|
||||
pglTexCoord2f( 0.0f, 0.0f );
|
||||
pglVertex3fv( verts[0] );
|
||||
pglEnd();
|
||||
#endif
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
#if 1
|
||||
sceGuDepthMask( GU_FALSE );
|
||||
#else
|
||||
pglDepthMask( GL_TRUE );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
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 ));
|
||||
}
|
||||
2352
ref_gu/gu_rsurf.c
Normal file
2352
ref_gu/gu_rsurf.c
Normal file
File diff suppressed because it is too large
Load Diff
1026
ref_gu/gu_sprite.c
Normal file
1026
ref_gu/gu_sprite.c
Normal file
File diff suppressed because it is too large
Load Diff
4142
ref_gu/gu_studio.c
Normal file
4142
ref_gu/gu_studio.c
Normal file
File diff suppressed because it is too large
Load Diff
577
ref_gu/gu_triapi.c
Normal file
577
ref_gu/gu_triapi.c
Normal file
@@ -0,0 +1,577 @@
|
||||
/*
|
||||
gu_triapi.c - TriAPI draw methods
|
||||
Copyright (C) 2011 Uncle Mike
|
||||
Copyright (C) 2019 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.
|
||||
*/
|
||||
|
||||
#include "gu_local.h"
|
||||
#include "const.h"
|
||||
|
||||
static struct
|
||||
{
|
||||
int renderMode; // override kRenderMode from TriAPI
|
||||
vec4_t triRGBA;
|
||||
} ds;
|
||||
|
||||
/*
|
||||
===============================================================
|
||||
|
||||
TRIAPI IMPLEMENTATION
|
||||
|
||||
===============================================================
|
||||
*/
|
||||
#if 1
|
||||
static struct
|
||||
{
|
||||
void *start;
|
||||
gu_vert_ftcv_t *list;
|
||||
qboolean begin;
|
||||
int count;
|
||||
int prim;
|
||||
unsigned int flags;
|
||||
}tri_gucontext =
|
||||
{
|
||||
.start = NULL,
|
||||
.list = NULL,
|
||||
.begin = false,
|
||||
.count = 0,
|
||||
.prim = 0,
|
||||
.flags = 0
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
=============
|
||||
TriRenderMode
|
||||
|
||||
set rendermode
|
||||
=============
|
||||
*/
|
||||
void TriRenderMode( int mode )
|
||||
{
|
||||
#if 1
|
||||
ds.renderMode = mode;
|
||||
switch( mode )
|
||||
{
|
||||
case kRenderNormal:
|
||||
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
||||
sceGuDisable( GU_BLEND );
|
||||
sceGuDepthMask( GU_FALSE );
|
||||
break;
|
||||
case kRenderTransAlpha:
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
||||
sceGuDepthMask( GU_TRUE );
|
||||
break;
|
||||
case kRenderTransColor:
|
||||
case kRenderTransTexture:
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
||||
break;
|
||||
case kRenderGlow:
|
||||
case kRenderTransAdd:
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, GUBLEND1 );
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuDepthMask( GU_TRUE );
|
||||
break;
|
||||
}
|
||||
#else
|
||||
ds.renderMode = mode;
|
||||
switch( mode )
|
||||
{
|
||||
case kRenderNormal:
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglDisable( GL_BLEND );
|
||||
pglDepthMask( GL_TRUE );
|
||||
break;
|
||||
case kRenderTransAlpha:
|
||||
pglEnable( GL_BLEND );
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
pglDepthMask( GL_FALSE );
|
||||
break;
|
||||
case kRenderTransColor:
|
||||
case kRenderTransTexture:
|
||||
pglEnable( GL_BLEND );
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
break;
|
||||
case kRenderGlow:
|
||||
case kRenderTransAdd:
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
||||
pglEnable( GL_BLEND );
|
||||
pglDepthMask( GL_FALSE );
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
TriBegin
|
||||
|
||||
begin triangle sequence
|
||||
=============
|
||||
*/
|
||||
void TriBegin( int mode )
|
||||
{
|
||||
#if 1
|
||||
switch( mode )
|
||||
{
|
||||
case TRI_POINTS:
|
||||
tri_gucontext.prim = GU_POINTS;
|
||||
break;
|
||||
case TRI_TRIANGLES:
|
||||
tri_gucontext.prim = GU_TRIANGLES;
|
||||
break;
|
||||
case TRI_TRIANGLE_FAN:
|
||||
tri_gucontext.prim = GU_TRIANGLE_FAN;
|
||||
break;
|
||||
case TRI_QUADS:
|
||||
tri_gucontext.prim = GU_TRIANGLE_FAN;
|
||||
break;
|
||||
case TRI_LINES:
|
||||
tri_gucontext.prim = GU_LINES;
|
||||
break;
|
||||
case TRI_TRIANGLE_STRIP:
|
||||
tri_gucontext.prim = GU_TRIANGLE_STRIP;
|
||||
break;
|
||||
case TRI_QUAD_STRIP:
|
||||
tri_gucontext.prim = GU_TRIANGLE_STRIP;
|
||||
break;
|
||||
case TRI_POLYGON:
|
||||
default:
|
||||
tri_gucontext.prim = GU_TRIANGLE_FAN;
|
||||
break;
|
||||
}
|
||||
tri_gucontext.start = extGuBeginPacket( NULL );
|
||||
tri_gucontext.list = ( gu_vert_ftcv_t* )tri_gucontext.start;
|
||||
tri_gucontext.begin = true;
|
||||
tri_gucontext.count = 0;
|
||||
tri_gucontext.flags = 0;
|
||||
#else
|
||||
switch( mode )
|
||||
{
|
||||
case TRI_POINTS:
|
||||
mode = GL_POINTS;
|
||||
break;
|
||||
case TRI_TRIANGLES:
|
||||
mode = GL_TRIANGLES;
|
||||
break;
|
||||
case TRI_TRIANGLE_FAN:
|
||||
mode = GL_TRIANGLE_FAN;
|
||||
break;
|
||||
case TRI_QUADS:
|
||||
mode = GL_QUADS;
|
||||
break;
|
||||
case TRI_LINES:
|
||||
mode = GL_LINES;
|
||||
break;
|
||||
case TRI_TRIANGLE_STRIP:
|
||||
mode = GL_TRIANGLE_STRIP;
|
||||
break;
|
||||
case TRI_QUAD_STRIP:
|
||||
mode = GL_QUAD_STRIP;
|
||||
break;
|
||||
case TRI_POLYGON:
|
||||
default:
|
||||
mode = GL_POLYGON;
|
||||
break;
|
||||
}
|
||||
|
||||
pglBegin( mode );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
TriEnd
|
||||
|
||||
draw triangle sequence
|
||||
=============
|
||||
*/
|
||||
void TriEnd( void )
|
||||
{
|
||||
#if 1
|
||||
unsigned int vert_size;
|
||||
|
||||
if( !tri_gucontext.begin )
|
||||
return;
|
||||
|
||||
extGuEndPacket( ( void* )tri_gucontext.list );
|
||||
sceGuDrawArray( tri_gucontext.prim, tri_gucontext.flags, tri_gucontext.count, 0, tri_gucontext.start );
|
||||
|
||||
tri_gucontext.begin = false;
|
||||
#else
|
||||
pglEnd( );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
_TriColor4f
|
||||
|
||||
=============
|
||||
*/
|
||||
void _TriColor4f( float r, float g, float b, float a )
|
||||
{
|
||||
#if 1
|
||||
if( tri_gucontext.begin )
|
||||
{
|
||||
tri_gucontext.flags |= GU_COLOR_8888;
|
||||
tri_gucontext.list->c = GUCOLOR4F( r, g, b, a );
|
||||
}
|
||||
else
|
||||
{
|
||||
sceGuColor( GUCOLOR4F( r, g, b, a ) );
|
||||
}
|
||||
#else
|
||||
pglColor4f( r, g, b, a );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
_TriColor4ub
|
||||
|
||||
=============
|
||||
*/
|
||||
void _TriColor4ub( byte r, byte g, byte b, byte a )
|
||||
{
|
||||
#if 1
|
||||
if( tri_gucontext.begin )
|
||||
{
|
||||
tri_gucontext.flags |= GU_COLOR_8888;
|
||||
tri_gucontext.list->c = GUCOLOR4UB( r, g, b, a );
|
||||
}
|
||||
else
|
||||
{
|
||||
sceGuColor( GUCOLOR4UB( r, g, b, a ) );
|
||||
}
|
||||
#else
|
||||
pglColor4ub( r, g, b, a );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
TriColor4ub
|
||||
|
||||
=============
|
||||
*/
|
||||
void TriColor4ub( byte r, byte g, byte b, byte a )
|
||||
{
|
||||
ds.triRGBA[0] = r * (1.0f / 255.0f);
|
||||
ds.triRGBA[1] = g * (1.0f / 255.0f);
|
||||
ds.triRGBA[2] = b * (1.0f / 255.0f);
|
||||
ds.triRGBA[3] = a * (1.0f / 255.0f);
|
||||
|
||||
_TriColor4f( ds.triRGBA[0], ds.triRGBA[1], ds.triRGBA[2], 1.0f );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
TriColor4f
|
||||
=================
|
||||
*/
|
||||
void TriColor4f( float r, float g, float b, float a )
|
||||
{
|
||||
if( ds.renderMode == kRenderTransAlpha )
|
||||
TriColor4ub( r * 255.0f, g * 255.0f, b * 255.0f, a * 255.0f );
|
||||
else _TriColor4f( r * a, g * a, b * a, 1.0 );
|
||||
|
||||
ds.triRGBA[0] = r;
|
||||
ds.triRGBA[1] = g;
|
||||
ds.triRGBA[2] = b;
|
||||
ds.triRGBA[3] = a;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
TriTexCoord2f
|
||||
|
||||
=============
|
||||
*/
|
||||
void TriTexCoord2f( float u, float v )
|
||||
{
|
||||
#if 1
|
||||
if( !tri_gucontext.begin )
|
||||
return;
|
||||
|
||||
tri_gucontext.flags |= GU_TEXTURE_32BITF;
|
||||
tri_gucontext.list->u = u;
|
||||
tri_gucontext.list->v = v;
|
||||
#else
|
||||
pglTexCoord2f( u, v );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
TriVertex3fv
|
||||
|
||||
=============
|
||||
*/
|
||||
void TriVertex3fv( const float *v )
|
||||
{
|
||||
#if 1
|
||||
if( !tri_gucontext.begin )
|
||||
return;
|
||||
|
||||
if( !(tri_gucontext.flags & GU_TEXTURE_32BITF) )
|
||||
{
|
||||
tri_gucontext.list->u = 0;
|
||||
tri_gucontext.list->v = 0;
|
||||
}
|
||||
|
||||
if( !(tri_gucontext.flags & GU_COLOR_8888) )
|
||||
{
|
||||
tri_gucontext.list->c = 0xffffffff;
|
||||
}
|
||||
|
||||
tri_gucontext.flags |= GU_VERTEX_32BITF;
|
||||
tri_gucontext.list->x = v[0];
|
||||
tri_gucontext.list->y = v[1];
|
||||
tri_gucontext.list->z = v[2];
|
||||
tri_gucontext.list++;
|
||||
|
||||
tri_gucontext.count++;
|
||||
#else
|
||||
pglVertex3fv( v );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
TriVertex3f
|
||||
|
||||
=============
|
||||
*/
|
||||
void TriVertex3f( float x, float y, float z )
|
||||
{
|
||||
#if 1
|
||||
if( !tri_gucontext.begin )
|
||||
return;
|
||||
|
||||
if( !(tri_gucontext.flags & GU_TEXTURE_32BITF) )
|
||||
{
|
||||
tri_gucontext.list->u = 0;
|
||||
tri_gucontext.list->v = 0;
|
||||
}
|
||||
|
||||
if( !(tri_gucontext.flags & GU_COLOR_8888) )
|
||||
{
|
||||
tri_gucontext.list->c = 0xffffffff;
|
||||
}
|
||||
|
||||
tri_gucontext.flags |= GU_VERTEX_32BITF;
|
||||
tri_gucontext.list->x = x;
|
||||
tri_gucontext.list->y = y;
|
||||
tri_gucontext.list->z = z;
|
||||
tri_gucontext.list++;
|
||||
|
||||
tri_gucontext.count++;
|
||||
#else
|
||||
pglVertex3f( x, y, z );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
TriWorldToScreen
|
||||
|
||||
convert world coordinates (x,y,z) into screen (x, y)
|
||||
=============
|
||||
*/
|
||||
int TriWorldToScreen( const float *world, float *screen )
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = R_WorldToScreen( world, screen );
|
||||
|
||||
screen[0] = 0.5f * screen[0] * (float)RI.viewport[2];
|
||||
screen[1] = -0.5f * screen[1] * (float)RI.viewport[3];
|
||||
screen[0] += 0.5f * (float)RI.viewport[2];
|
||||
screen[1] += 0.5f * (float)RI.viewport[3];
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
TriSpriteTexture
|
||||
|
||||
bind current texture
|
||||
=============
|
||||
*/
|
||||
int TriSpriteTexture( model_t *pSpriteModel, int frame )
|
||||
{
|
||||
int gl_texturenum;
|
||||
|
||||
if(( gl_texturenum = R_GetSpriteTexture( pSpriteModel, frame )) == 0 )
|
||||
return 0;
|
||||
|
||||
if( gl_texturenum <= 0 || gl_texturenum > MAX_TEXTURES )
|
||||
gl_texturenum = tr.defaultTexture;
|
||||
|
||||
GL_Bind( XASH_TEXTURE0, gl_texturenum );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
TriFog
|
||||
|
||||
enables global fog on the level
|
||||
=============
|
||||
*/
|
||||
void TriFog( float flFogColor[3], float flStart, float flEnd, int bOn )
|
||||
{
|
||||
// overrided by internal fog
|
||||
if( RI.fogEnabled ) return;
|
||||
RI.fogCustom = bOn;
|
||||
|
||||
// check for invalid parms
|
||||
if( flEnd <= flStart )
|
||||
{
|
||||
glState.isFogEnabled = RI.fogCustom = false;
|
||||
#if 1
|
||||
sceGuDisable( GU_FOG );
|
||||
#else
|
||||
pglDisable( GL_FOG );
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#if 1
|
||||
if( RI.fogCustom )
|
||||
sceGuEnable( GU_FOG );
|
||||
else sceGuDisable( GU_FOG );
|
||||
#else
|
||||
if( RI.fogCustom )
|
||||
pglEnable( GL_FOG );
|
||||
else pglDisable( GL_FOG );
|
||||
#endif
|
||||
// copy fog params
|
||||
RI.fogColor[0] = flFogColor[0] / 255.0f;
|
||||
RI.fogColor[1] = flFogColor[1] / 255.0f;
|
||||
RI.fogColor[2] = flFogColor[2] / 255.0f;
|
||||
RI.fogStart = flStart;
|
||||
RI.fogColor[3] = 1.0f;
|
||||
RI.fogDensity = 0.0f;
|
||||
RI.fogSkybox = true;
|
||||
RI.fogEnd = flEnd;
|
||||
|
||||
#if 1
|
||||
printf("TRI FOG: s %f e %f c %f %f %f %f \n", RI.fogStart, RI.fogEnd,
|
||||
RI.fogColor[0], RI.fogColor[1], RI.fogColor[2], RI.fogColor[3] );
|
||||
|
||||
//glState.fogDensity = RI.fogDensity
|
||||
glState.fogColor = GUCOLOR4F( RI.fogColor[0], RI.fogColor[1], RI.fogColor[2], glState.fogDensity );
|
||||
glState.fogStart = RI.fogStart;
|
||||
glState.fogEnd = RI.fogEnd;
|
||||
|
||||
sceGuFog( glState.fogStart, glState.fogEnd, glState.fogColor );
|
||||
#else
|
||||
pglFogi( GL_FOG_MODE, GL_LINEAR );
|
||||
pglFogfv( GL_FOG_COLOR, RI.fogColor );
|
||||
pglFogf( GL_FOG_START, RI.fogStart );
|
||||
pglFogf( GL_FOG_END, RI.fogEnd );
|
||||
pglHint( GL_FOG_HINT, GL_NICEST );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
TriGetMatrix
|
||||
|
||||
very strange export
|
||||
=============
|
||||
*/
|
||||
void TriGetMatrix( const int pname, float *matrix )
|
||||
{
|
||||
#if 1
|
||||
printf("%s:%i:%s - Not implemented\n", __FILE__, __LINE__, __FUNCTION__ );
|
||||
#else
|
||||
pglGetFloatv( pname, matrix );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
TriForParams
|
||||
|
||||
=============
|
||||
*/
|
||||
void TriFogParams( float flDensity, int iFogSkybox )
|
||||
{
|
||||
RI.fogDensity = flDensity;
|
||||
RI.fogSkybox = iFogSkybox;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
TriCullFace
|
||||
|
||||
=============
|
||||
*/
|
||||
void TriCullFace( TRICULLSTYLE mode )
|
||||
{
|
||||
int glMode;
|
||||
|
||||
switch( mode )
|
||||
{
|
||||
case TRI_FRONT:
|
||||
glMode = GL_FRONT;
|
||||
break;
|
||||
default:
|
||||
glMode = GL_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
GL_Cull( mode );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
TriBrightness
|
||||
=============
|
||||
*/
|
||||
void TriBrightness( float brightness )
|
||||
{
|
||||
float r, g, b;
|
||||
|
||||
r = ds.triRGBA[0] * ds.triRGBA[3] * brightness;
|
||||
g = ds.triRGBA[1] * ds.triRGBA[3] * brightness;
|
||||
b = ds.triRGBA[2] * ds.triRGBA[3] * brightness;
|
||||
|
||||
_TriColor4f( r, g, b, 1.0f );
|
||||
}
|
||||
|
||||
unsigned int getTriBrightness( float brightness )
|
||||
{
|
||||
vec3_t color;
|
||||
|
||||
if(brightness < 0.0f) return 0;
|
||||
|
||||
color[0] = ds.triRGBA[0] * ds.triRGBA[3] * brightness;
|
||||
color[1] = ds.triRGBA[1] * ds.triRGBA[3] * brightness;
|
||||
color[2] = ds.triRGBA[2] * ds.triRGBA[3] * brightness;
|
||||
|
||||
VectorNormalizeFast( color );
|
||||
|
||||
return GUCOLOR3FV( color );
|
||||
}
|
||||
|
||||
309
ref_gu/gu_vgui.c
Normal file
309
ref_gu/gu_vgui.c
Normal file
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
gl_vgui.c - OpenGL vgui draw methods
|
||||
Copyright (C) 2011 Uncle Mike
|
||||
Copyright (C) 2019 a1batross
|
||||
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"
|
||||
|
||||
#define VGUI_MAX_TEXTURES ( MAX_TEXTURES / 2 ) // a half of total textures count
|
||||
#if 1
|
||||
static short g_textures[VGUI_MAX_TEXTURES];
|
||||
#else
|
||||
static int g_textures[VGUI_MAX_TEXTURES];
|
||||
#endif
|
||||
static int g_textureId = 0;
|
||||
static int g_iBoundTexture;
|
||||
|
||||
/*
|
||||
================
|
||||
VGUI_DrawInit
|
||||
|
||||
Startup VGUI backend
|
||||
================
|
||||
*/
|
||||
void GAME_EXPORT VGUI_DrawInit( void )
|
||||
{
|
||||
memset( g_textures, 0, sizeof( g_textures ));
|
||||
g_textureId = g_iBoundTexture = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
VGUI_DrawShutdown
|
||||
|
||||
Release all textures
|
||||
================
|
||||
*/
|
||||
void GAME_EXPORT VGUI_DrawShutdown( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 1; i < g_textureId; i++ )
|
||||
{
|
||||
GL_FreeTexture( g_textures[i] );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
VGUI_GenerateTexture
|
||||
|
||||
generate unique texture number
|
||||
================
|
||||
*/
|
||||
int GAME_EXPORT VGUI_GenerateTexture( void )
|
||||
{
|
||||
if( ++g_textureId >= VGUI_MAX_TEXTURES )
|
||||
gEngfuncs.Host_Error( "VGUI_GenerateTexture: VGUI_MAX_TEXTURES limit exceeded\n" );
|
||||
return g_textureId;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
VGUI_UploadTexture
|
||||
|
||||
Upload texture into video memory
|
||||
================
|
||||
*/
|
||||
void GAME_EXPORT VGUI_UploadTexture( int id, const char *buffer, int width, int height )
|
||||
{
|
||||
rgbdata_t r_image;
|
||||
char texName[32];
|
||||
|
||||
if( id <= 0 || id >= VGUI_MAX_TEXTURES )
|
||||
{
|
||||
gEngfuncs.Con_DPrintf( S_ERROR "VGUI_UploadTexture: bad texture %i. Ignored\n", id );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_snprintf( texName, sizeof( texName ), "*vgui%i", id );
|
||||
memset( &r_image, 0, sizeof( r_image ));
|
||||
|
||||
r_image.width = width;
|
||||
r_image.height = height;
|
||||
r_image.type = PF_RGBA_32;
|
||||
r_image.size = r_image.width * r_image.height * 4;
|
||||
r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA;
|
||||
r_image.buffer = (byte *)buffer;
|
||||
|
||||
g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
VGUI_CreateTexture
|
||||
|
||||
Create empty rgba texture and upload them into video memory
|
||||
================
|
||||
*/
|
||||
void GAME_EXPORT VGUI_CreateTexture( int id, int width, int height )
|
||||
{
|
||||
rgbdata_t r_image;
|
||||
char texName[32];
|
||||
|
||||
if( id <= 0 || id >= VGUI_MAX_TEXTURES )
|
||||
{
|
||||
gEngfuncs.Con_Reportf( S_ERROR "VGUI_CreateTexture: bad texture %i. Ignored\n", id );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_snprintf( texName, sizeof( texName ), "*vgui%i", id );
|
||||
memset( &r_image, 0, sizeof( r_image ));
|
||||
|
||||
r_image.width = width;
|
||||
r_image.height = height;
|
||||
r_image.type = PF_RGBA_32;
|
||||
r_image.size = r_image.width * r_image.height * 4;
|
||||
r_image.flags = IMAGE_HAS_ALPHA;
|
||||
r_image.buffer = NULL;
|
||||
|
||||
g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE|TF_NEAREST );
|
||||
g_iBoundTexture = id;
|
||||
}
|
||||
|
||||
void GAME_EXPORT VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight )
|
||||
{
|
||||
if( id <= 0 || id >= VGUI_MAX_TEXTURES || g_textures[id] == 0 || g_textures[id] == tr.whiteTexture )
|
||||
{
|
||||
gEngfuncs.Con_Reportf( S_ERROR "VGUI_UploadTextureBlock: bad texture %i. Ignored\n", id );
|
||||
return;
|
||||
}
|
||||
#if 1
|
||||
|
||||
#else
|
||||
pglTexSubImage2D( GL_TEXTURE_2D, 0, drawX, drawY, blockWidth, blockHeight, GL_RGBA, GL_UNSIGNED_BYTE, rgba );
|
||||
#endif
|
||||
g_iBoundTexture = id;
|
||||
}
|
||||
|
||||
void GAME_EXPORT VGUI_SetupDrawingRect( int *pColor )
|
||||
{
|
||||
#if 1
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuDisable( GU_ALPHA_TEST );
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
||||
sceGuColor( GUCOLOR4UB( pColor[0], pColor[1], pColor[2], 255 - pColor[3] ) );
|
||||
#else
|
||||
pglEnable( GL_BLEND );
|
||||
pglDisable( GL_ALPHA_TEST );
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
pglColor4ub( pColor[0], pColor[1], pColor[2], 255 - pColor[3] );
|
||||
#endif
|
||||
}
|
||||
|
||||
void GAME_EXPORT VGUI_SetupDrawingText( int *pColor )
|
||||
{
|
||||
#if 1
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuEnable( GU_ALPHA_TEST );
|
||||
sceGuAlphaFunc( GU_GREATER, 0x00, 0xff );
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
||||
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
||||
sceGuColor( GUCOLOR4UB( pColor[0], pColor[1], pColor[2], 255 - pColor[3] ) );
|
||||
#else
|
||||
pglEnable( GL_BLEND );
|
||||
pglEnable( GL_ALPHA_TEST );
|
||||
pglAlphaFunc( GL_GREATER, 0.0f );
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglColor4ub( pColor[0], pColor[1], pColor[2], 255 - pColor[3] );
|
||||
#endif
|
||||
}
|
||||
|
||||
void GAME_EXPORT VGUI_SetupDrawingImage( int *pColor )
|
||||
{
|
||||
#if 1
|
||||
sceGuEnable( GU_BLEND );
|
||||
sceGuEnable( GU_ALPHA_TEST );
|
||||
sceGuAlphaFunc( GU_GREATER, 0x00, 0xff );
|
||||
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
||||
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
||||
sceGuColor( GUCOLOR4UB( pColor[0], pColor[1], pColor[2], 255 - pColor[3] ) );
|
||||
#else
|
||||
pglEnable( GL_BLEND );
|
||||
pglEnable( GL_ALPHA_TEST );
|
||||
pglAlphaFunc( GL_GREATER, 0.0f );
|
||||
pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
pglColor4ub( pColor[0], pColor[1], pColor[2], 255 - pColor[3] );
|
||||
#endif
|
||||
}
|
||||
|
||||
void GAME_EXPORT VGUI_BindTexture( int id )
|
||||
{
|
||||
if( id > 0 && id < VGUI_MAX_TEXTURES && g_textures[id] )
|
||||
{
|
||||
GL_Bind( XASH_TEXTURE0, g_textures[id] );
|
||||
g_iBoundTexture = id;
|
||||
}
|
||||
else
|
||||
{
|
||||
// NOTE: same as bogus index 2700 in GoldSrc
|
||||
id = g_iBoundTexture = 1;
|
||||
GL_Bind( XASH_TEXTURE0, g_textures[id] );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
VGUI_GetTextureSizes
|
||||
|
||||
returns wide and tall for currently binded texture
|
||||
================
|
||||
*/
|
||||
void GAME_EXPORT VGUI_GetTextureSizes( int *width, int *height )
|
||||
{
|
||||
gl_texture_t *glt;
|
||||
int texnum;
|
||||
|
||||
if( g_iBoundTexture )
|
||||
texnum = g_textures[g_iBoundTexture];
|
||||
else texnum = tr.defaultTexture;
|
||||
|
||||
glt = R_GetTexture( texnum );
|
||||
if( width ) *width = glt->srcWidth;
|
||||
if( height ) *height = glt->srcHeight;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
VGUI_EnableTexture
|
||||
|
||||
disable texturemode for fill rectangle
|
||||
================
|
||||
*/
|
||||
void GAME_EXPORT VGUI_EnableTexture( qboolean enable )
|
||||
{
|
||||
#if 1
|
||||
if( enable ) sceGuEnable( GU_TEXTURE_2D );
|
||||
else sceGuDisable( GU_TEXTURE_2D );
|
||||
#else
|
||||
if( enable ) pglEnable( GL_TEXTURE_2D );
|
||||
else pglDisable( GL_TEXTURE_2D );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
VGUI_DrawQuad
|
||||
|
||||
generic method to fill rectangle
|
||||
================
|
||||
*/
|
||||
void GAME_EXPORT VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr )
|
||||
{
|
||||
int width, height;
|
||||
float xscale, yscale;
|
||||
#if 1
|
||||
gl_texture_t *glt;
|
||||
float twidth, theight;
|
||||
#endif
|
||||
gEngfuncs.CL_GetScreenInfo( &width, &height );
|
||||
|
||||
xscale = gpGlobals->width / (float)width;
|
||||
yscale = gpGlobals->height / (float)height;
|
||||
|
||||
ASSERT( ul != NULL && lr != NULL );
|
||||
#if 1
|
||||
glt = R_GetTexture( g_iBoundTexture ? g_textures[g_iBoundTexture] : tr.defaultTexture );
|
||||
|
||||
gu_vert_htv_t* const out = ( gu_vert_htv_t* )sceGuGetMemory( sizeof( gu_vert_htv_t ) * 2 );
|
||||
out[0].u = ul->coord[0] * glt->width;
|
||||
out[0].v = ul->coord[1] * glt->height;
|
||||
out[0].x = ul->point[0] * xscale;
|
||||
out[0].y = ul->point[1] * yscale;
|
||||
out[0].z = 0;
|
||||
out[1].u = lr->coord[0] * glt->width;
|
||||
out[1].v = lr->coord[1] * glt->height;
|
||||
out[1].x = lr->point[0] * xscale;
|
||||
out[1].y = lr->point[1] * yscale;
|
||||
out[1].z = 0;
|
||||
sceGuDrawArray( GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, out );
|
||||
#else
|
||||
pglBegin( GL_QUADS );
|
||||
pglTexCoord2f( ul->coord[0], ul->coord[1] );
|
||||
pglVertex2f( ul->point[0] * xscale, ul->point[1] * yscale );
|
||||
|
||||
pglTexCoord2f( lr->coord[0], ul->coord[1] );
|
||||
pglVertex2f( lr->point[0] * xscale, ul->point[1] * yscale );
|
||||
|
||||
pglTexCoord2f( lr->coord[0], lr->coord[1] );
|
||||
pglVertex2f( lr->point[0] * xscale, lr->point[1] * yscale );
|
||||
|
||||
pglTexCoord2f( ul->coord[0], lr->coord[1] );
|
||||
pglVertex2f( ul->point[0] * xscale, lr->point[1] * yscale );
|
||||
pglEnd();
|
||||
#endif
|
||||
}
|
||||
871
ref_gu/gu_warp.c
Normal file
871
ref_gu/gu_warp.c
Normal file
@@ -0,0 +1,871 @@
|
||||
/*
|
||||
gl_warp.c - sky and water polygons
|
||||
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 "wadfile.h"
|
||||
#define SKYCLOUDS_QUALITY 12
|
||||
#define MAX_CLIP_VERTS 128 // skybox clip vertices
|
||||
#define TURBSCALE ( 256.0f / ( M_PI2 ))
|
||||
const char* r_skyBoxSuffix[6] = { "rt", "bk", "lf", "ft", "up", "dn" };
|
||||
static const int r_skyTexOrder[6] = { 0, 2, 1, 3, 4, 5 };
|
||||
|
||||
static const vec3_t skyclip[6] =
|
||||
{
|
||||
{ 1, 1, 0 },
|
||||
{ 1, -1, 0 },
|
||||
{ 0, -1, 1 },
|
||||
{ 0, 1, 1 },
|
||||
{ 1, 0, 1 },
|
||||
{ -1, 0, 1 }
|
||||
};
|
||||
|
||||
// 1 = s, 2 = t, 3 = 2048
|
||||
static const int st_to_vec[6][3] =
|
||||
{
|
||||
{ 3, -1, 2 },
|
||||
{ -3, 1, 2 },
|
||||
{ 1, 3, 2 },
|
||||
{ -1, -3, 2 },
|
||||
{ -2, -1, 3 }, // 0 degrees yaw, look straight up
|
||||
{ 2, -1, -3 } // look straight down
|
||||
};
|
||||
|
||||
// s = [0]/[2], t = [1]/[2]
|
||||
static const int vec_to_st[6][3] =
|
||||
{
|
||||
{ -2, 3, 1 },
|
||||
{ 2, 3, -1 },
|
||||
{ 1, 3, 2 },
|
||||
{ -1, 3, -2 },
|
||||
{ -2, -1, 3 },
|
||||
{ -2, 1, -3 }
|
||||
};
|
||||
|
||||
// speed up sin calculations
|
||||
float r_turbsin[] =
|
||||
{
|
||||
#include "warpsin.h"
|
||||
};
|
||||
|
||||
#define SKYBOX_MISSED 0
|
||||
#define SKYBOX_HLSTYLE 1
|
||||
#define SKYBOX_Q1STYLE 2
|
||||
|
||||
static int CheckSkybox( const char *name )
|
||||
{
|
||||
const char *skybox_ext[3] = { "dds", "tga", "bmp" };
|
||||
int i, j, num_checked_sides;
|
||||
const char *sidename;
|
||||
|
||||
// search for skybox images
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
num_checked_sides = 0;
|
||||
for( j = 0; j < 6; j++ )
|
||||
{
|
||||
// build side name
|
||||
sidename = va( "%s%s.%s", name, r_skyBoxSuffix[j], skybox_ext[i] );
|
||||
if( gEngfuncs.FS_FileExists( sidename, false ))
|
||||
num_checked_sides++;
|
||||
|
||||
}
|
||||
|
||||
if( num_checked_sides == 6 )
|
||||
return SKYBOX_HLSTYLE; // image exists
|
||||
|
||||
for( j = 0; j < 6; j++ )
|
||||
{
|
||||
// build side name
|
||||
sidename = va( "%s_%s.%s", name, r_skyBoxSuffix[j], skybox_ext[i] );
|
||||
if( gEngfuncs.FS_FileExists( sidename, false ))
|
||||
num_checked_sides++;
|
||||
}
|
||||
|
||||
if( num_checked_sides == 6 )
|
||||
return SKYBOX_Q1STYLE; // images exists
|
||||
}
|
||||
|
||||
return SKYBOX_MISSED;
|
||||
}
|
||||
|
||||
void DrawSkyPolygon( int nump, vec3_t vecs )
|
||||
{
|
||||
int i, j, axis;
|
||||
float s, t, dv, *vp;
|
||||
vec3_t v, av;
|
||||
|
||||
// decide which face it maps to
|
||||
VectorClear( v );
|
||||
|
||||
for( i = 0, vp = vecs; i < nump; i++, vp += 3 )
|
||||
VectorAdd( vp, v, v );
|
||||
|
||||
av[0] = fabs( v[0] );
|
||||
av[1] = fabs( v[1] );
|
||||
av[2] = fabs( v[2] );
|
||||
|
||||
if( av[0] > av[1] && av[0] > av[2] )
|
||||
axis = (v[0] < 0) ? 1 : 0;
|
||||
else if( av[1] > av[2] && av[1] > av[0] )
|
||||
axis = (v[1] < 0) ? 3 : 2;
|
||||
else axis = (v[2] < 0) ? 5 : 4;
|
||||
|
||||
// project new texture coords
|
||||
for( i = 0; i < nump; i++, vecs += 3 )
|
||||
{
|
||||
j = vec_to_st[axis][2];
|
||||
dv = (j > 0) ? vecs[j-1] : -vecs[-j-1];
|
||||
|
||||
if( dv == 0.0f ) continue;
|
||||
|
||||
j = vec_to_st[axis][0];
|
||||
s = (j < 0) ? -vecs[-j-1] / dv : vecs[j-1] / dv;
|
||||
|
||||
j = vec_to_st[axis][1];
|
||||
t = (j < 0) ? -vecs[-j-1] / dv : vecs[j-1] / dv;
|
||||
|
||||
if( s < RI.skyMins[0][axis] ) RI.skyMins[0][axis] = s;
|
||||
if( t < RI.skyMins[1][axis] ) RI.skyMins[1][axis] = t;
|
||||
if( s > RI.skyMaxs[0][axis] ) RI.skyMaxs[0][axis] = s;
|
||||
if( t > RI.skyMaxs[1][axis] ) RI.skyMaxs[1][axis] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
ClipSkyPolygon
|
||||
==============
|
||||
*/
|
||||
void ClipSkyPolygon( int nump, vec3_t vecs, int stage )
|
||||
{
|
||||
const float *norm;
|
||||
float *v, d, e;
|
||||
qboolean front, back;
|
||||
float dists[MAX_CLIP_VERTS + 1];
|
||||
int sides[MAX_CLIP_VERTS + 1];
|
||||
vec3_t newv[2][MAX_CLIP_VERTS + 1];
|
||||
int newc[2];
|
||||
int i, j;
|
||||
|
||||
if( nump > MAX_CLIP_VERTS )
|
||||
gEngfuncs.Host_Error( "ClipSkyPolygon: MAX_CLIP_VERTS\n" );
|
||||
loc1:
|
||||
if( stage == 6 )
|
||||
{
|
||||
// fully clipped, so draw it
|
||||
DrawSkyPolygon( nump, vecs );
|
||||
return;
|
||||
}
|
||||
|
||||
front = back = false;
|
||||
norm = skyclip[stage];
|
||||
for( i = 0, v = vecs; i < nump; i++, v += 3 )
|
||||
{
|
||||
d = DotProduct( v, norm );
|
||||
if( d > ON_EPSILON )
|
||||
{
|
||||
front = true;
|
||||
sides[i] = SIDE_FRONT;
|
||||
}
|
||||
else if( d < -ON_EPSILON )
|
||||
{
|
||||
back = true;
|
||||
sides[i] = SIDE_BACK;
|
||||
}
|
||||
else
|
||||
{
|
||||
sides[i] = SIDE_ON;
|
||||
}
|
||||
dists[i] = d;
|
||||
}
|
||||
|
||||
if( !front || !back )
|
||||
{
|
||||
// not clipped
|
||||
stage++;
|
||||
goto loc1;
|
||||
}
|
||||
|
||||
// clip it
|
||||
sides[i] = sides[0];
|
||||
dists[i] = dists[0];
|
||||
VectorCopy( vecs, ( vecs + ( i * 3 )));
|
||||
newc[0] = newc[1] = 0;
|
||||
|
||||
for( i = 0, v = vecs; i < nump; i++, v += 3 )
|
||||
{
|
||||
switch( sides[i] )
|
||||
{
|
||||
case SIDE_FRONT:
|
||||
VectorCopy( v, newv[0][newc[0]] );
|
||||
newc[0]++;
|
||||
break;
|
||||
case SIDE_BACK:
|
||||
VectorCopy( v, newv[1][newc[1]] );
|
||||
newc[1]++;
|
||||
break;
|
||||
case SIDE_ON:
|
||||
VectorCopy( v, newv[0][newc[0]] );
|
||||
newc[0]++;
|
||||
VectorCopy( v, newv[1][newc[1]] );
|
||||
newc[1]++;
|
||||
break;
|
||||
}
|
||||
|
||||
if( sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i] )
|
||||
continue;
|
||||
|
||||
d = dists[i] / ( dists[i] - dists[i+1] );
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
e = v[j] + d * ( v[j+3] - v[j] );
|
||||
newv[0][newc[0]][j] = e;
|
||||
newv[1][newc[1]][j] = e;
|
||||
}
|
||||
newc[0]++;
|
||||
newc[1]++;
|
||||
}
|
||||
|
||||
// continue
|
||||
ClipSkyPolygon( newc[0], newv[0][0], stage + 1 );
|
||||
ClipSkyPolygon( newc[1], newv[1][0], stage + 1 );
|
||||
}
|
||||
#if 1
|
||||
_inline void MakeSkyVec( float s, float t, int axis, gu_vert_t *out )
|
||||
{
|
||||
int j, k, farclip;
|
||||
vec3_t v, b;
|
||||
|
||||
farclip = RI.farClip;
|
||||
|
||||
b[0] = s * (farclip >> 1);
|
||||
b[1] = t * (farclip >> 1);
|
||||
b[2] = (farclip >> 1);
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
k = st_to_vec[axis][j];
|
||||
v[j] = (k < 0) ? -b[-k-1] : b[k-1];
|
||||
v[j] += RI.cullorigin[j];
|
||||
}
|
||||
|
||||
// avoid bilerp seam
|
||||
s = (s + 1.0f) * 0.5f;
|
||||
t = (t + 1.0f) * 0.5f;
|
||||
|
||||
if( s < 1.0f / 512.0f )
|
||||
s = 1.0f / 512.0f;
|
||||
else if( s > 511.0f / 512.0f )
|
||||
s = 511.0f / 512.0f;
|
||||
if( t < 1.0f / 512.0f )
|
||||
t = 1.0f / 512.0f;
|
||||
else if( t > 511.0f / 512.0f )
|
||||
t = 511.0f / 512.0f;
|
||||
|
||||
t = 1.0f - t;
|
||||
|
||||
out->uv[0] = s;
|
||||
out->uv[1] = t;
|
||||
VectorCopy( v, out->xyz );
|
||||
}
|
||||
#else
|
||||
void MakeSkyVec( float s, float t, int axis )
|
||||
{
|
||||
int j, k, farclip;
|
||||
vec3_t v, b;
|
||||
|
||||
farclip = RI.farClip;
|
||||
|
||||
b[0] = s * (farclip >> 1);
|
||||
b[1] = t * (farclip >> 1);
|
||||
b[2] = (farclip >> 1);
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
k = st_to_vec[axis][j];
|
||||
v[j] = (k < 0) ? -b[-k-1] : b[k-1];
|
||||
v[j] += RI.cullorigin[j];
|
||||
}
|
||||
|
||||
// avoid bilerp seam
|
||||
s = (s + 1.0f) * 0.5f;
|
||||
t = (t + 1.0f) * 0.5f;
|
||||
|
||||
if( s < 1.0f / 512.0f )
|
||||
s = 1.0f / 512.0f;
|
||||
else if( s > 511.0f / 512.0f )
|
||||
s = 511.0f / 512.0f;
|
||||
if( t < 1.0f / 512.0f )
|
||||
t = 1.0f / 512.0f;
|
||||
else if( t > 511.0f / 512.0f )
|
||||
t = 511.0f / 512.0f;
|
||||
|
||||
t = 1.0f - t;
|
||||
|
||||
pglTexCoord2f( s, t );
|
||||
pglVertex3fv( v );
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
==============
|
||||
R_ClearSkyBox
|
||||
==============
|
||||
*/
|
||||
void R_ClearSkyBox( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
RI.skyMins[0][i] = RI.skyMins[1][i] = 9999999.0f;
|
||||
RI.skyMaxs[0][i] = RI.skyMaxs[1][i] = -9999999.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
R_AddSkyBoxSurface
|
||||
=================
|
||||
*/
|
||||
void R_AddSkyBoxSurface( msurface_t *fa )
|
||||
{
|
||||
vec3_t verts[MAX_CLIP_VERTS];
|
||||
glpoly_t *p;
|
||||
float *v;
|
||||
int i;
|
||||
|
||||
if( ENGINE_GET_PARM( PARM_SKY_SPHERE ) && fa->polys && !tr.fCustomSkybox )
|
||||
{
|
||||
glpoly_t *p = fa->polys;
|
||||
|
||||
// draw the sky poly
|
||||
sceGuDrawArray( GU_TRIANGLE_FAN, GU_TEXTURE_32BITF | GU_VERTEX_32BITF, p->numverts, 0, p->verts );
|
||||
}
|
||||
|
||||
// calculate vertex values for sky box
|
||||
for( p = fa->polys; p; p = p->next )
|
||||
{
|
||||
for( i = 0; i < p->numverts; i++ )
|
||||
VectorSubtract( p->verts[i].xyz, RI.cullorigin, verts[i] );
|
||||
ClipSkyPolygon( p->numverts, verts[0], 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
R_UnloadSkybox
|
||||
|
||||
Unload previous skybox
|
||||
==============
|
||||
*/
|
||||
void R_UnloadSkybox( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
// release old skybox
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
if( !tr.skyboxTextures[i] ) continue;
|
||||
GL_FreeTexture( tr.skyboxTextures[i] );
|
||||
}
|
||||
#if 0
|
||||
tr.skyboxbasenum = 5800; // set skybox base (to let some mods load hi-res skyboxes)
|
||||
#endif
|
||||
memset( tr.skyboxTextures, 0, sizeof( tr.skyboxTextures ));
|
||||
tr.fCustomSkybox = false;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
R_DrawSkybox
|
||||
==============
|
||||
*/
|
||||
void R_DrawSkyBox( void )
|
||||
{
|
||||
int i;
|
||||
RI.isSkyVisible = true;
|
||||
|
||||
// don't fogging skybox (this fix old Half-Life bug)
|
||||
if( !RI.fogSkybox ) R_AllowFog( false );
|
||||
|
||||
/*
|
||||
if( RI.fogEnabled )
|
||||
pglFogf( GL_FOG_DENSITY, RI.fogDensity * 0.5f );
|
||||
*/
|
||||
sceGuDisable( GU_BLEND );
|
||||
sceGuDisable( GU_ALPHA_TEST );
|
||||
sceGuTexFunc( GU_TFX_REPLACE, GU_TCC_RGBA );
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
if( RI.skyMins[0][i] >= RI.skyMaxs[0][i] || RI.skyMins[1][i] >= RI.skyMaxs[1][i] )
|
||||
continue;
|
||||
|
||||
if( tr.skyboxTextures[r_skyTexOrder[i]] )
|
||||
GL_Bind( XASH_TEXTURE0, tr.skyboxTextures[r_skyTexOrder[i]] );
|
||||
else GL_Bind( XASH_TEXTURE0, tr.grayTexture ); // stub
|
||||
|
||||
//gu_vert_t uv[4] __attribute__( ( aligned( 16 ) ) ); // dcache writeback required!
|
||||
gu_vert_t* const uv = ( gu_vert_t* )sceGuGetMemory( sizeof( gu_vert_t ) * 4 );
|
||||
MakeSkyVec( RI.skyMins[0][i], RI.skyMins[1][i], i, &uv[0] );
|
||||
MakeSkyVec( RI.skyMins[0][i], RI.skyMaxs[1][i], i, &uv[1] );
|
||||
MakeSkyVec( RI.skyMaxs[0][i], RI.skyMaxs[1][i], i, &uv[2] );
|
||||
MakeSkyVec( RI.skyMaxs[0][i], RI.skyMins[1][i], i, &uv[3] );
|
||||
|
||||
if ( GU_ClipIsRequired( uv, 4 ) )
|
||||
{
|
||||
gu_vert_t* cv;
|
||||
size_t cvc;
|
||||
|
||||
GU_Clip( uv, 4, &cv, &cvc );
|
||||
if( cvc ) sceGuDrawArray( GU_TRIANGLE_FAN, GU_TEXTURE_32BITF | GU_VERTEX_32BITF, cvc, 0, cv );
|
||||
}
|
||||
else sceGuDrawArray( GU_TRIANGLE_FAN, GU_TEXTURE_32BITF | GU_VERTEX_32BITF, 4, 0, uv );
|
||||
}
|
||||
|
||||
if( !RI.fogSkybox )
|
||||
R_AllowFog( true );
|
||||
/*
|
||||
if( RI.fogEnabled )
|
||||
pglFogf( GL_FOG_DENSITY, RI.fogDensity );
|
||||
*/
|
||||
R_LoadIdentity();
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_SetupSky
|
||||
===============
|
||||
*/
|
||||
void R_SetupSky( const char *skyboxname )
|
||||
{
|
||||
char loadname[MAX_STRING];
|
||||
char sidename[MAX_STRING];
|
||||
int i, result;
|
||||
|
||||
if( !COM_CheckString( skyboxname ))
|
||||
{
|
||||
R_UnloadSkybox();
|
||||
return; // clear old skybox
|
||||
}
|
||||
|
||||
Q_snprintf( loadname, sizeof( loadname ), "gfx/env/%s", skyboxname );
|
||||
COM_StripExtension( loadname );
|
||||
|
||||
// kill the underline suffix to find them manually later
|
||||
if( loadname[Q_strlen( loadname ) - 1] == '_' )
|
||||
loadname[Q_strlen( loadname ) - 1] = '\0';
|
||||
result = CheckSkybox( loadname );
|
||||
|
||||
// to prevent infinite recursion if default skybox was missed
|
||||
if( result == SKYBOX_MISSED && Q_stricmp( loadname, DEFAULT_SKYBOX_PATH ))
|
||||
{
|
||||
gEngfuncs.Con_Reportf( S_WARN "missed or incomplete skybox '%s'\n", skyboxname );
|
||||
R_SetupSky( "desert" ); // force to default
|
||||
return;
|
||||
}
|
||||
|
||||
// release old skybox
|
||||
R_UnloadSkybox();
|
||||
gEngfuncs.Con_DPrintf( "SKY: " );
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
if( result == SKYBOX_HLSTYLE )
|
||||
Q_snprintf( sidename, sizeof( sidename ), "%s%s", loadname, r_skyBoxSuffix[i] );
|
||||
else Q_snprintf( sidename, sizeof( sidename ), "%s_%s", loadname, r_skyBoxSuffix[i] );
|
||||
|
||||
tr.skyboxTextures[i] = GL_LoadTexture( sidename, NULL, 0, TF_CLAMP|TF_SKY );
|
||||
if( !tr.skyboxTextures[i] ) break;
|
||||
gEngfuncs.Con_DPrintf( "%s%s%s", skyboxname, r_skyBoxSuffix[i], i != 5 ? ", " : ". " );
|
||||
}
|
||||
|
||||
if( i == 6 )
|
||||
{
|
||||
tr.fCustomSkybox = true;
|
||||
gEngfuncs.Con_DPrintf( "done\n" );
|
||||
return; // loaded
|
||||
}
|
||||
|
||||
gEngfuncs.Con_DPrintf( "^2failed\n" );
|
||||
R_UnloadSkybox();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//
|
||||
// RENDER CLOUDS
|
||||
//
|
||||
//==============================================================================
|
||||
/*
|
||||
==============
|
||||
R_CloudVertex
|
||||
==============
|
||||
*/
|
||||
void R_CloudVertex( float s, float t, int axis, vec3_t v )
|
||||
{
|
||||
int j, k, farclip;
|
||||
vec3_t b;
|
||||
|
||||
farclip = RI.farClip;
|
||||
|
||||
b[0] = s * (farclip >> 1);
|
||||
b[1] = t * (farclip >> 1);
|
||||
b[2] = (farclip >> 1);
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
{
|
||||
k = st_to_vec[axis][j];
|
||||
v[j] = (k < 0) ? -b[-k-1] : b[k-1];
|
||||
v[j] += RI.cullorigin[j];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_CloudTexCoord
|
||||
=============
|
||||
*/
|
||||
#if 1
|
||||
_inline void R_CloudTexCoord( vec3_t v, float speed, float *s, float *t )
|
||||
#else
|
||||
void R_CloudTexCoord( vec3_t v, float speed, float *s, float *t )
|
||||
#endif
|
||||
{
|
||||
float length, speedscale;
|
||||
vec3_t dir;
|
||||
|
||||
speedscale = gpGlobals->time * speed;
|
||||
speedscale -= (int)speedscale & ~127;
|
||||
|
||||
VectorSubtract( v, RI.vieworg, dir );
|
||||
dir[2] *= 3.0f; // flatten the sphere
|
||||
|
||||
length = VectorLength( dir );
|
||||
length = 6.0f * 63.0f / length;
|
||||
|
||||
*s = ( speedscale + dir[0] * length ) * (1.0f / 128.0f);
|
||||
*t = ( speedscale + dir[1] * length ) * (1.0f / 128.0f);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
R_CloudDrawPoly
|
||||
===============
|
||||
*/
|
||||
void R_CloudDrawPoly( glpoly_t *p )
|
||||
{
|
||||
float *v;
|
||||
int i;
|
||||
|
||||
GL_SetRenderMode( kRenderNormal );
|
||||
GL_Bind( XASH_TEXTURE0, tr.solidskyTexture );
|
||||
|
||||
gu_vert_t* out = ( gu_vert_t* )sceGuGetMemory( sizeof( gu_vert_t ) * 4 );
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
R_CloudTexCoord( p->verts[i].xyz, 8.0f, &out[i].uv[0], &out[i].uv[1] );
|
||||
VectorCopy( p->verts[i].xyz, out[i].xyz );
|
||||
}
|
||||
sceGuDrawArray( GU_TRIANGLE_FAN, GU_TEXTURE_32BITF | GU_VERTEX_32BITF, 4, 0, out );
|
||||
|
||||
GL_SetRenderMode( kRenderTransTexture );
|
||||
GL_Bind( XASH_TEXTURE0, tr.alphaskyTexture );
|
||||
|
||||
out = ( gu_vert_t* )sceGuGetMemory( sizeof( gu_vert_t ) * 4 );
|
||||
for( i = 0; i < 4; i++ )
|
||||
{
|
||||
R_CloudTexCoord( p->verts[i].xyz, 16.0f, &out[i].uv[0], &out[i].uv[1] );
|
||||
VectorCopy( p->verts[i].xyz, out[i].xyz );
|
||||
}
|
||||
sceGuDrawArray( GU_TRIANGLE_FAN, GU_TEXTURE_32BITF | GU_VERTEX_32BITF, 4, 0, out );
|
||||
|
||||
sceGuDisable( GU_BLEND );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
R_CloudRenderSide
|
||||
==============
|
||||
*/
|
||||
void R_CloudRenderSide( int axis )
|
||||
{
|
||||
vec3_t verts[4];
|
||||
float di, qi, dj, qj;
|
||||
vec3_t vup, vright;
|
||||
vec3_t temp, temp2;
|
||||
glpoly_t p[1];
|
||||
int i, j;
|
||||
|
||||
R_CloudVertex( -1.0f, -1.0f, axis, verts[0] );
|
||||
R_CloudVertex( -1.0f, 1.0f, axis, verts[1] );
|
||||
R_CloudVertex( 1.0f, 1.0f, axis, verts[2] );
|
||||
R_CloudVertex( 1.0f, -1.0f, axis, verts[3] );
|
||||
|
||||
VectorSubtract( verts[2], verts[3], vup );
|
||||
VectorSubtract( verts[2], verts[1], vright );
|
||||
|
||||
p->numverts = 4;
|
||||
di = SKYCLOUDS_QUALITY;
|
||||
qi = 1.0f / di;
|
||||
dj = (axis < 4) ? di * 2 : di; //subdivide vertically more than horizontally on skybox sides
|
||||
qj = 1.0f / dj;
|
||||
|
||||
for( i = 0; i < di; i++ )
|
||||
{
|
||||
for( j = 0; j < dj; j++ )
|
||||
{
|
||||
if( i * qi < RI.skyMins[0][axis] / 2 + 0.5f - qi
|
||||
|| i * qi > RI.skyMaxs[0][axis] / 2 + 0.5f
|
||||
|| j * qj < RI.skyMins[1][axis] / 2 + 0.5f - qj
|
||||
|| j * qj > RI.skyMaxs[1][axis] / 2 + 0.5f )
|
||||
continue;
|
||||
|
||||
VectorScale( vright, qi * i, temp );
|
||||
VectorScale( vup, qj * j, temp2 );
|
||||
VectorAdd( temp, temp2, temp );
|
||||
VectorAdd( verts[0], temp, p->verts[0].xyz );
|
||||
|
||||
VectorScale( vup, qj, temp );
|
||||
VectorAdd( p->verts[0].xyz, temp, p->verts[1].xyz );
|
||||
|
||||
VectorScale( vright, qi, temp );
|
||||
VectorAdd( p->verts[1].xyz, temp, p->verts[2].xyz );
|
||||
|
||||
VectorAdd( p->verts[0].xyz, temp, p->verts[3].xyz );
|
||||
|
||||
R_CloudDrawPoly( p );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
R_DrawClouds
|
||||
|
||||
Quake-style clouds
|
||||
==============
|
||||
*/
|
||||
void R_DrawClouds( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
RI.isSkyVisible = true;
|
||||
|
||||
/*
|
||||
if( RI.fogEnabled )
|
||||
pglFogf( GL_FOG_DENSITY, RI.fogDensity * 0.25f );
|
||||
*/
|
||||
sceGuDepthFunc( GU_GEQUAL );
|
||||
sceGuDepthMask( GU_TRUE );
|
||||
|
||||
for( i = 0; i < 6; i++ )
|
||||
{
|
||||
if( RI.skyMins[0][i] >= RI.skyMaxs[0][i] || RI.skyMins[1][i] >= RI.skyMaxs[1][i] )
|
||||
continue;
|
||||
R_CloudRenderSide( i );
|
||||
}
|
||||
|
||||
sceGuDepthFunc( GU_LEQUAL );
|
||||
sceGuDepthMask( GU_FALSE );
|
||||
/*
|
||||
if( RI.fogEnabled )
|
||||
pglFogf( GL_FOG_DENSITY, RI.fogDensity );
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
R_InitSkyClouds
|
||||
|
||||
A sky texture is 256*128, with the right side being a masked overlay
|
||||
==============
|
||||
*/
|
||||
void R_InitSkyClouds( mip_t *mt, texture_t *tx, qboolean custom_palette )
|
||||
{
|
||||
rgbdata_t r_temp, *r_sky;
|
||||
uint *trans, *rgba;
|
||||
uint transpix;
|
||||
int r, g, b;
|
||||
int i, j, p;
|
||||
char texname[32];
|
||||
|
||||
if( !glw_state.initialized )
|
||||
return;
|
||||
|
||||
Q_snprintf( texname, sizeof( texname ), "%s%s.mip", ( mt->offsets[0] > 0 ) ? "#" : "", tx->name );
|
||||
|
||||
if( mt->offsets[0] > 0 )
|
||||
{
|
||||
int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6);
|
||||
|
||||
if( custom_palette ) size += sizeof( short ) + 768;
|
||||
r_sky = gEngfuncs.FS_LoadImage( texname, (byte *)mt, size );
|
||||
}
|
||||
else
|
||||
{
|
||||
// okay, loading it from wad
|
||||
r_sky = gEngfuncs.FS_LoadImage( texname, NULL, 0 );
|
||||
}
|
||||
|
||||
// make sure what sky image is valid
|
||||
if( !r_sky || !r_sky->palette || r_sky->type != PF_INDEXED_32 || r_sky->height == 0 )
|
||||
{
|
||||
gEngfuncs.Con_Reportf( S_ERROR "R_InitSky: unable to load sky texture %s\n", tx->name );
|
||||
if( r_sky ) gEngfuncs.FS_FreeImage( r_sky );
|
||||
return;
|
||||
}
|
||||
|
||||
// make an average value for the back to avoid
|
||||
// a fringe on the top level
|
||||
trans = Mem_Malloc( r_temppool, r_sky->height * r_sky->height * sizeof( *trans ));
|
||||
r = g = b = 0;
|
||||
|
||||
for( i = 0; i < r_sky->width >> 1; i++ )
|
||||
{
|
||||
for( j = 0; j < r_sky->height; j++ )
|
||||
{
|
||||
p = r_sky->buffer[i * r_sky->width + j + r_sky->height];
|
||||
rgba = (uint *)r_sky->palette + p;
|
||||
trans[(i * r_sky->height) + j] = *rgba;
|
||||
r += ((byte *)rgba)[0];
|
||||
g += ((byte *)rgba)[1];
|
||||
b += ((byte *)rgba)[2];
|
||||
}
|
||||
}
|
||||
|
||||
((byte *)&transpix)[0] = r / ( r_sky->height * r_sky->height );
|
||||
((byte *)&transpix)[1] = g / ( r_sky->height * r_sky->height );
|
||||
((byte *)&transpix)[2] = b / ( r_sky->height * r_sky->height );
|
||||
((byte *)&transpix)[3] = 0;
|
||||
|
||||
// build a temporary image
|
||||
r_temp = *r_sky;
|
||||
r_temp.width = r_sky->width >> 1;
|
||||
r_temp.height = r_sky->height;
|
||||
r_temp.type = PF_RGBA_32;
|
||||
r_temp.flags = IMAGE_HAS_COLOR;
|
||||
r_temp.size = r_temp.width * r_temp.height * 4;
|
||||
r_temp.buffer = (byte *)trans;
|
||||
r_temp.palette = NULL;
|
||||
|
||||
// load it in
|
||||
tr.solidskyTexture = GL_LoadTextureInternal( REF_SOLIDSKY_TEXTURE, &r_temp, TF_NOMIPMAP );
|
||||
|
||||
for( i = 0; i < r_sky->width >> 1; i++ )
|
||||
{
|
||||
for( j = 0; j < r_sky->height; j++ )
|
||||
{
|
||||
p = r_sky->buffer[i * r_sky->width + j];
|
||||
|
||||
if( p == 0 )
|
||||
{
|
||||
trans[(i * r_sky->height) + j] = transpix;
|
||||
}
|
||||
else
|
||||
{
|
||||
rgba = (uint *)r_sky->palette + p;
|
||||
trans[(i * r_sky->height) + j] = *rgba;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r_temp.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA;
|
||||
|
||||
// load it in
|
||||
tr.alphaskyTexture = GL_LoadTextureInternal( REF_ALPHASKY_TEXTURE, &r_temp, TF_NOMIPMAP );
|
||||
|
||||
// clean up
|
||||
gEngfuncs.FS_FreeImage( r_sky );
|
||||
Mem_Free( trans );
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
EmitWaterPolys
|
||||
|
||||
Does a water warp on the pre-fragmented glpoly_t chain
|
||||
=============
|
||||
*/
|
||||
void EmitWaterPolys( msurface_t *warp, qboolean reverse )
|
||||
{
|
||||
gu_vert_t *verts;
|
||||
float *v, nv, waveHeight;
|
||||
float s, t, os, ot;
|
||||
glpoly_t *p;
|
||||
int i;
|
||||
|
||||
if( !warp->polys ) return;
|
||||
|
||||
// set the current waveheight
|
||||
if( warp->polys->verts[0].xyz[2] >= RI.vieworg[2] )
|
||||
waveHeight = -RI.currententity->curstate.scale;
|
||||
else waveHeight = RI.currententity->curstate.scale;
|
||||
|
||||
// reset fog color for nonlightmapped water
|
||||
GL_ResetFogColor();
|
||||
|
||||
for( p = warp->polys; p; p = p->next )
|
||||
{
|
||||
if( reverse )
|
||||
verts = &p->verts[p->numverts - 1];
|
||||
else verts = &p->verts[0];
|
||||
|
||||
gu_vert_t* const out = ( gu_vert_t* )sceGuGetMemory( sizeof( gu_vert_t ) * p->numverts );
|
||||
for( i = 0; i < p->numverts; i++ )
|
||||
{
|
||||
if( waveHeight )
|
||||
{
|
||||
nv = r_turbsin[( int )( gpGlobals->time * 160.0f + verts->xyz[1] + verts->xyz[0]) & 255] + 8.0f;
|
||||
nv = (r_turbsin[( int )( verts->xyz[0] * 5.0f + gpGlobals->time * 171.0f - verts->xyz[1]) & 255] + 8.0f ) * 0.8f + nv;
|
||||
nv = nv * waveHeight + verts->xyz[2];
|
||||
}
|
||||
else nv = verts->xyz[2];
|
||||
|
||||
os = verts->uv[0];
|
||||
ot = verts->uv[1];
|
||||
|
||||
s = os + r_turbsin[(int)((ot * 0.125f + gpGlobals->time) * TURBSCALE) & 255];
|
||||
s *= ( 1.0f / SUBDIVIDE_SIZE );
|
||||
|
||||
t = ot + r_turbsin[(int)((os * 0.125f + gpGlobals->time) * TURBSCALE) & 255];
|
||||
t *= ( 1.0f / SUBDIVIDE_SIZE );
|
||||
|
||||
out[i].uv[0] = s;
|
||||
out[i].uv[1] = t;
|
||||
out[i].xyz[0] = verts->xyz[0];
|
||||
out[i].xyz[1] = verts->xyz[1];
|
||||
out[i].xyz[2] = nv;
|
||||
|
||||
if( reverse )
|
||||
verts -= 1;
|
||||
else verts += 1;
|
||||
}
|
||||
if ( GU_ClipIsRequired( out, p->numverts ) )
|
||||
{
|
||||
// Clip the polygon.
|
||||
gu_vert_t* cv;
|
||||
size_t cvc;
|
||||
|
||||
GU_Clip( out, p->numverts, &cv, &cvc );
|
||||
if( cvc )
|
||||
sceGuDrawArray( GU_TRIANGLE_FAN, GU_TEXTURE_32BITF | GU_VERTEX_32BITF, cvc, 0, cv );
|
||||
}
|
||||
else
|
||||
sceGuDrawArray( GU_TRIANGLE_FAN, GU_TEXTURE_32BITF | GU_VERTEX_32BITF, p->numverts, 0, out );
|
||||
}
|
||||
GL_SetupFogColorForSurfaces();
|
||||
}
|
||||
39
ref_gu/vram_psp.h
Normal file
39
ref_gu/vram_psp.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Helper for use with the PSP Software Development Kit - http://www.pspdev.org
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed as 'free to use and modify as long as credited appropriately'
|
||||
*
|
||||
* vram.h - Standard C high performance VRAM allocation routines.
|
||||
*
|
||||
* Copyright (c) 2007 Alexander Berl 'Raphael' <raphael@fx-world.org>
|
||||
* http://wordpress.fx-world.org
|
||||
*/
|
||||
#ifndef vram_h__
|
||||
#define vram_h__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void* vrelptr( void *ptr ); // make a pointer relative to memory base address (ATTENTION: A NULL rel ptr is not illegal/invalid!)
|
||||
void* vabsptr( void *ptr ); // make a pointer absolute (default return type of valloc)
|
||||
|
||||
void* valloc( size_t size );
|
||||
void vfree( void* ptr );
|
||||
size_t vmemavail();
|
||||
size_t vlargestblock();
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
// Debug printf (to stdout) a trace of the current Memblocks
|
||||
void __memwalk();
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ifdef vram_h__
|
||||
58
ref_gu/wscript
Normal file
58
ref_gu/wscript
Normal file
@@ -0,0 +1,58 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# mittorn, 2018
|
||||
|
||||
from waflib import Logs
|
||||
import os
|
||||
|
||||
top = '.'
|
||||
|
||||
def options(opt):
|
||||
grp = opt.add_option_group('ref_gu options')
|
||||
|
||||
grp.add_option('--enable-static-gl', action='store_true', dest='GL_STATIC', default=False,
|
||||
help = 'enable direct linking to opengl [default: %default]')
|
||||
|
||||
grp.add_option('--disable-gl', action='store_false', dest='GL', default=True,
|
||||
help = 'disable opengl [default: %default]')
|
||||
|
||||
# stub
|
||||
return
|
||||
|
||||
def configure(conf):
|
||||
# check for dedicated server build
|
||||
if conf.options.DEDICATED:
|
||||
return
|
||||
|
||||
conf.define_cond('SUPPORT_BSP2_FORMAT', conf.options.SUPPORT_BSP2_FORMAT)
|
||||
|
||||
conf.env.GL = conf.options.GL
|
||||
conf.env.GL_STATIC = conf.options.GL_STATIC
|
||||
|
||||
conf.define('REF_DLL', 1)
|
||||
|
||||
def build(bld):
|
||||
libs = [ 'public', 'M' ]
|
||||
|
||||
source = bld.path.ant_glob(['*.c'])
|
||||
|
||||
includes = ['.',
|
||||
'../engine',
|
||||
'../engine/common',
|
||||
'../engine/server',
|
||||
'../engine/client',
|
||||
'../public',
|
||||
'../common',
|
||||
'../pm_shared' ]
|
||||
|
||||
if bld.env.GL:
|
||||
bld.shlib(
|
||||
source = source,
|
||||
target = 'ref_gu',
|
||||
features = 'c',
|
||||
includes = includes,
|
||||
use = libs + (['GL'] if bld.env.GL_STATIC else []),
|
||||
defines = ['XASH_GL_STATIC'] if bld.env.GL_STATIC else [],
|
||||
install_path = bld.env.LIBDIR,
|
||||
subsystem = bld.env.MSVC_SUBSYSTEM
|
||||
)
|
||||
2
ref_soft/exports.txt
Normal file
2
ref_soft/exports.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
GetRefAPI
|
||||
GetRefHumanReadableName
|
||||
@@ -28,6 +28,8 @@ ANDROID_NDK_SYSROOT_FLAG_MAX = 19 # latest NDK that need --sysroot flag
|
||||
ANDROID_NDK_API_MIN = { 10: 3, 19: 16, 20: 16 } # minimal API level ndk revision supports
|
||||
ANDROID_64BIT_API_MIN = 21 # minimal API level that supports 64-bit targets
|
||||
|
||||
PSP_SDK_ENVVARS = ['PSPDEV', 'PSPSDK', 'PSPTOOLCHAIN']
|
||||
|
||||
# This class does support ONLY r10e and r19c/r20 NDK
|
||||
class Android:
|
||||
ctx = None # waf context
|
||||
@@ -320,11 +322,80 @@ class Android:
|
||||
ldflags += ['-march=armv5te']
|
||||
return ldflags
|
||||
|
||||
|
||||
|
||||
class PSP:
|
||||
ctx = None # waf context
|
||||
sdk_home = None
|
||||
psptoolchain_path = None
|
||||
pspsdk_path = None
|
||||
binutils_path = None
|
||||
module_type = None
|
||||
fw_version = None
|
||||
render_type = None
|
||||
|
||||
def __init__(self, ctx, moduletype, fwversion, rendertype):
|
||||
self.ctx = ctx
|
||||
self.module_type = moduletype
|
||||
self.fw_version = fwversion
|
||||
self.render_type = rendertype
|
||||
|
||||
for i in PSP_SDK_ENVVARS:
|
||||
self.sdk_home = os.getenv(i)
|
||||
if self.sdk_home != None:
|
||||
break
|
||||
else:
|
||||
ctx.fatal('Set %s environment variable pointing to the root of PSP SDK!' %
|
||||
' or '.join(PSP_SDK_ENVVARS))
|
||||
|
||||
self.psptoolchain_path = os.path.join(self.sdk_home, 'psp')
|
||||
self.pspsdk_path = os.path.join(self.psptoolchain_path, 'sdk')
|
||||
self.binutils_path = os.path.join(self.sdk_home, 'bin')
|
||||
|
||||
def cflags(self, cxx = False):
|
||||
cflags = []
|
||||
cflags += ['-I%s' % (os.path.join(self.pspsdk_path, 'include'))]
|
||||
# cflags += ['-I%s' % (os.path.join(self.psptoolchain_path, 'include'))]
|
||||
cflags += ['-I.']
|
||||
cflags += ['-D_PSP_FW_VERSION=%s' % self.fw_version, '-G0']
|
||||
return cflags
|
||||
# they go before object list
|
||||
def linkflags(self):
|
||||
linkflags = []
|
||||
# if self.module_type == 'prx':
|
||||
# linkflags += ['-specs=%s' % os.path.join(self.pspsdk_path, 'lib/prxspecs')]
|
||||
# linkflags += ['-Wl,-q,-T%s' % os.path.join(self.pspsdk_path, 'lib/linkfile.prx')]
|
||||
# linkflags += ['-Wl,--hash-style=sysv', '-Wl,--no-undefined', '-no-canonical-prefixes']
|
||||
return linkflags
|
||||
|
||||
def ldflags(self):
|
||||
ldflags = []
|
||||
if self.module_type == 'prx':
|
||||
ldflags += ['-specs=%s' % os.path.join(self.pspsdk_path, 'lib/prxspecs')]
|
||||
ldflags += ['-Wl,-q,-T%s' % os.path.join(self.pspsdk_path, 'lib/linkfile.prx')]
|
||||
ldflags += ['-L%s' % os.path.join(self.pspsdk_path, 'lib')]
|
||||
# ldflags += ['-L%s' % os.path.join(self.psptoolchain_path, 'lib')]
|
||||
ldflags += ['-L.']
|
||||
# ldflags += ['-lgcc', '-no-canonical-prefixes']
|
||||
return ldflags
|
||||
|
||||
def stdlibs(self):
|
||||
stdlibs = []
|
||||
stdlibs += ['-lpspdisplay', '-lpspgum_vfpu', '-lpspgu','-lpspge', '-lpspvfpu']
|
||||
stdlibs += ['-lpspaudiolib', '-lpspaudio']
|
||||
stdlibs += ['-lstdc++', '-lc', '-lm', '-lpspdebug', '-lpspctrl', '-lpspsdk', '-lpsprtc']
|
||||
stdlibs += ['-lpspnet', '-lpspnet_inet', '-lpspnet_apctl', '-lpspnet_resolver', '-lpsputility', '-lpspuser', '-lpspkernel', '-lpsppower']
|
||||
return stdlibs
|
||||
|
||||
def options(opt):
|
||||
android = opt.add_option_group('Android options')
|
||||
android.add_option('--android', action='store', dest='ANDROID_OPTS', default=None,
|
||||
help='enable building for android, format: --android=<arch>,<toolchain>,<api>, example: --android=armeabi-v7a-hard,4.9,9')
|
||||
|
||||
psp = opt.add_option_group('Sony PSP options')
|
||||
psp.add_option('--psp', action='store', dest='PSP_OPTS', default=None,
|
||||
help='enable building for Sony PSP, format: --psp=<module type>,<fw version>,<render type> example: --psp=prx,660,HW')
|
||||
|
||||
def configure(conf):
|
||||
if conf.options.ANDROID_OPTS:
|
||||
values = conf.options.ANDROID_OPTS.split(',')
|
||||
@@ -361,11 +432,98 @@ def configure(conf):
|
||||
# conf.env.ANDROID_OPTS = android
|
||||
conf.env.DEST_OS2 = 'android'
|
||||
|
||||
MACRO_TO_DESTOS = OrderedDict({ '__ANDROID__' : 'android' })
|
||||
if conf.options.PSP_OPTS:
|
||||
values = conf.options.PSP_OPTS.split(',')
|
||||
if len(values) != 3:
|
||||
conf.fatal('Invalid --psp paramater value!')
|
||||
|
||||
valid_module_type = ['elf', 'prx']
|
||||
valid_render_type = ['SW', 'HW', 'ALL']
|
||||
|
||||
if values[0] not in valid_module_type:
|
||||
conf.fatal('Unknown module type: %s. Supported: %r' % (values[0], ', '.join(valid_module_type)))
|
||||
if values[2] not in valid_render_type:
|
||||
conf.fatal('Unknown render type: %s. Supported: %r' % (values[2], ', '.join(valid_render_type)))
|
||||
|
||||
conf.psp = psp = PSP(conf, values[0], values[1], values[2])
|
||||
conf.environ['CC'] = os.path.join(psp.binutils_path, 'psp-gcc')
|
||||
conf.environ['CXX'] = os.path.join(psp.binutils_path, 'psp-gcc')
|
||||
conf.environ['AS'] = os.path.join(psp.binutils_path, 'psp-gcc')
|
||||
conf.environ['STRIP'] = os.path.join(psp.binutils_path, 'psp-strip')
|
||||
conf.environ['LD'] = os.path.join(psp.binutils_path, 'psp-gcc')
|
||||
conf.environ['AR'] = os.path.join(psp.binutils_path, 'psp-ar')
|
||||
conf.environ['RANLIB'] = os.path.join(psp.binutils_path, 'psp-ranlib')
|
||||
conf.environ['OBJCOPY'] = os.path.join(psp.binutils_path, 'psp-objcopy')
|
||||
|
||||
# conf.environ['PRXGEN'] = os.path.join(psp.binutils_path, 'prxgen')
|
||||
# conf.environ['MKSFO'] = os.path.join(psp.binutils_path, 'mksfoex')
|
||||
# conf.environ['PACK_PBP'] = os.path.join(psp.binutils_path, 'pack-pbp')
|
||||
# conf.environ['FIXUP'] = os.path.join(psp.binutils_path, 'psp-fixup-imports')
|
||||
|
||||
conf.env.PRXGEN = conf.find_program('psp-prxgen', path_list = psp.binutils_path)
|
||||
conf.env.MKSFO = conf.find_program('mksfoex', path_list = psp.binutils_path)
|
||||
conf.env.PACK_PBP = conf.find_program('pack-pbp', path_list = psp.binutils_path)
|
||||
conf.env.FIXUP = conf.find_program('psp-fixup-imports', path_list = psp.binutils_path)
|
||||
|
||||
conf.env.CFLAGS += psp.cflags()
|
||||
conf.env.CXXFLAGS += psp.cflags()
|
||||
conf.env.LINKFLAGS += psp.linkflags()
|
||||
conf.env.LDFLAGS += psp.ldflags()
|
||||
|
||||
conf.env.PREFIX = '/lib'
|
||||
|
||||
conf.msg('Selected PSPSDK', '%s' % (psp.sdk_home))
|
||||
# no need to print C/C++ compiler, as it would be printed by compiler_c/cxx
|
||||
conf.msg('... C/C++ flags', ' '.join(psp.cflags()).replace(psp.sdk_home, '$PSPSDK'))
|
||||
conf.msg('... link flags', ' '.join(psp.linkflags()).replace(psp.sdk_home, '$PSPSDK'))
|
||||
conf.msg('... ld flags', ' '.join(psp.ldflags()).replace(psp.sdk_home, '$PSPSDK'))
|
||||
|
||||
if conf.options.PROFILING:
|
||||
conf.env.LDFLAGS += ['-lpspprof']
|
||||
conf.env.CFLAGS += ['-pg']
|
||||
conf.env.LDFLAGS += psp.stdlibs()
|
||||
|
||||
conf.env.DEST_OS2 = 'psp'
|
||||
conf.env.PSP_RENDER_TYPE = psp.render_type
|
||||
conf.env.PSP_PATTERN_program = '%s'
|
||||
conf.env.PSP_PATTERN_stlib = 'lib%s.a'
|
||||
conf.env.PSP_PATTERN_shlib = '%s.elf'
|
||||
|
||||
if psp.module_type == 'prx':
|
||||
conf.env.PSP_BUILD_PRX = True
|
||||
|
||||
MACRO_TO_DESTOS = OrderedDict({ '__ANDROID__' : 'android', '__psp__' : 'psp'})
|
||||
for k in c_config.MACRO_TO_DESTOS:
|
||||
MACRO_TO_DESTOS[k] = c_config.MACRO_TO_DESTOS[k] # ordering is important
|
||||
c_config.MACRO_TO_DESTOS = MACRO_TO_DESTOS
|
||||
|
||||
def build(bld):
|
||||
if bld.env.DEST_OS == 'psp':
|
||||
bld(rule='${FIXUP} -o ${TGT} ${SRC}', source='engine/xash', target='xash.elf')
|
||||
if bld.env.PSP_BUILD_PRX:
|
||||
bld(rule='${PRXGEN} ${SRC} ${TGT}', source='xash.elf', target='xash.prx')
|
||||
bld(rule='${MKSFO} -d MEMSIZE=1 Xash3D ${TGT}', source='xash.prx', target='PARAM.SFO')
|
||||
bld(rule='${PACK_PBP} ${TGT} ${SRC[1]} ${PSP_EBOOT_ICON} ${PSP_EBOOT_ICON1} ${PSP_EBOOT_UNKPNG} ${PSP_EBOOT_PIC1} ${PSP_EBOOT_SND0} ${SRC[0]} ${PSP_EBOOT_PSAR}', source='xash.prx PARAM.SFO', target='EBOOT.PBP')
|
||||
else:
|
||||
bld(rule='${STRIP} -o ${TGT} ${SRC}', source='xash.elf', target='xash_strip.elf')
|
||||
bld(rule='${MKSFO} -d MEMSIZE=1 Xash3D ${TGT}', source='xash_strip.elf', target='PARAM.SFO')
|
||||
bld(rule='${PACK_PBP} ${TGT} ${SRC[1]} ${PSP_EBOOT_ICON} ${PSP_EBOOT_ICON1} ${PSP_EBOOT_UNKPNG} ${PSP_EBOOT_PIC1} ${PSP_EBOOT_SND0} ${SRC[0]} ${PSP_EBOOT_PSAR}', source='xash_strip.elf PARAM.SFO', target='EBOOT.PBP')
|
||||
# source_target = os.path.join('engine', bld.env.PSP_BUILD_TARGET)
|
||||
# Logs.info(source_target)
|
||||
# Logs.info(bld.env.PSP_BUILD_TARGET)
|
||||
# bld(rule='${FIXUP} -o ${PSP_BUILD_TARGET}.elf ${SRC}', source=source_target, always=True)
|
||||
# if bld.env.PSP_BUILD_PRX:
|
||||
# bld(rule='${PRXGEN} ${PSP_BUILD_TARGET}.elf ${PSP_BUILD_TARGET}.prx', always=True)
|
||||
# if bld.env.PSP_BUILD_EBOOT:
|
||||
# bld(rule='${MKSFO} -d MEMSIZE=1 ${PSP_EBOOT_TITLE} ${PSP_EBOOT_SFO}', always=True)
|
||||
# bld(rule='${PACK_PBP} ${PSP_EBOOT} ${PSP_EBOOT_SFO} ${PSP_EBOOT_ICON} ${PSP_EBOOT_ICON1} ${PSP_EBOOT_UNKPNG} ${PSP_EBOOT_PIC1} ${PSP_EBOOT_SND0} ${PSP_BUILD_TARGET}.prx ${PSP_EBOOT_PSAR}', always=True)
|
||||
# else:
|
||||
# if bld.env.PSP_BUILD_EBOOT:
|
||||
# bld(rule='${STRIP} -o ${PSP_BUILD_TARGET}.elf ${PSP_BUILD_TARGET}_strip.elf', always=True)
|
||||
# bld(rule='${MKSFO} -d MEMSIZE=1 ${PSP_EBOOT_TITLE} ${PSP_EBOOT_SFO}', always=True)
|
||||
# bld(rule='${PACK_PBP} ${PSP_EBOOT} ${PSP_EBOOT_SFO} ${PSP_EBOOT_ICON} ${PSP_EBOOT_ICON1} ${PSP_EBOOT_UNKPNG} ${PSP_EBOOT_PIC1} ${PSP_EBOOT_SND0} ${PSP_BUILD_TARGET}_strip.elf ${PSP_EBOOT_PSAR}', always=True)
|
||||
# bld(rule='rm -f ${PSP_BUILD_TARGET}_strip.elf', always=True)
|
||||
|
||||
def post_compiler_cxx_configure(conf):
|
||||
conf.msg('Target OS', conf.env.DEST_OS)
|
||||
conf.msg('Target CPU', conf.env.DEST_CPU)
|
||||
|
||||
93
wscript
93
wscript
@@ -49,11 +49,12 @@ SUBDIRS = [
|
||||
Subproject('public', dedicated=False, mandatory = True),
|
||||
Subproject('game_launch', singlebin=True),
|
||||
Subproject('ref_gl',),
|
||||
Subproject('ref_gu',),
|
||||
Subproject('ref_soft'),
|
||||
Subproject('mainui'),
|
||||
Subproject('vgui_support'),
|
||||
Subproject('stub/server', dedicated=False),
|
||||
Subproject('stub/client'),
|
||||
Subproject('stubserver/server', dedicated=False),
|
||||
Subproject('stubserver/client'),
|
||||
Subproject('dllemu'),
|
||||
Subproject('engine', dedicated=False),
|
||||
]
|
||||
@@ -92,7 +93,10 @@ def options(opt):
|
||||
help = 'enable low memory mode (only for devices have <128 ram)')
|
||||
|
||||
grp.add_option('--enable-magx', action = 'store_true', dest = 'MAGX', default = False,
|
||||
help = 'enable targetting for MotoMAGX phones [default: %default]')
|
||||
help = 'enable targeting for MotoMAGX phones [default: %default]')
|
||||
|
||||
grp.add_option('--enable-profiling', action = 'store_true', dest = 'PROFILING', default = False,
|
||||
help = 'enable building with GNU profiling tools')
|
||||
|
||||
grp.add_option('--ignore-projects', action = 'store', dest = 'IGNORE_PROJECTS', default = None,
|
||||
help = 'disable selected projects from build [default: %default]')
|
||||
@@ -116,6 +120,7 @@ def configure(conf):
|
||||
enforce_pic = True # modern defaults
|
||||
valid_build_types = ['fastnative', 'fast', 'release', 'debug', 'nooptimize', 'sanitize', 'none']
|
||||
conf.load('fwgslib reconfigure')
|
||||
|
||||
if conf.options.IGNORE_PROJECTS:
|
||||
conf.env.IGNORE_PROJECTS = conf.options.IGNORE_PROJECTS.split(',')
|
||||
|
||||
@@ -139,7 +144,7 @@ def configure(conf):
|
||||
conf.env.MSVC_TARGETS = ['x86'] # explicitly request x86 target for MSVC
|
||||
if sys.platform == 'win32':
|
||||
conf.load('msvc msvc_pdb msdev msvs')
|
||||
conf.load('xshlib subproject xcompile compiler_c compiler_cxx gitversion clang_compilation_database strip_on_install waf_unit_test')
|
||||
conf.load('xshlib subproject xcompile gas compiler_c compiler_cxx gitversion clang_compilation_database strip_on_install waf_unit_test')
|
||||
|
||||
try:
|
||||
conf.env.CC_VERSION[0]
|
||||
@@ -153,6 +158,58 @@ def configure(conf):
|
||||
conf.options.GLWES = True
|
||||
conf.options.GL = False
|
||||
|
||||
if conf.env.DEST_OS == 'psp':
|
||||
conf.options.NO_VGUI= True # skip vgui
|
||||
conf.options.SINGLE_BINARY = True
|
||||
conf.options.NO_ASYNC_RESOLVE = True
|
||||
conf.options.LOW_MEMORY = 2
|
||||
conf.options.GL = True
|
||||
conf.options.GL_STATIC = True
|
||||
conf.options.STATIC = True
|
||||
enforce_pic = False
|
||||
|
||||
# rewrite compile patterns
|
||||
conf.env.cprogram_PATTERN = conf.env.PSP_PATTERN_program
|
||||
conf.env.cxxprogram_PATTERN = conf.env.PSP_PATTERN_program
|
||||
conf.env.cshlib_PATTERN = conf.env.PSP_PATTERN_shlib
|
||||
conf.env.cxxshlib_PATTERN = conf.env.PSP_PATTERN_shlib
|
||||
conf.env.cstlib_PATTERN = conf.env.PSP_PATTERN_stlib
|
||||
conf.env.cxxstlib_PATTERN = conf.env.PSP_PATTERN_stlib
|
||||
|
||||
# set EBOOT.PBP generation parameters
|
||||
conf.env.PSP_EBOOT_TITLE = 'Xash3D'
|
||||
conf.env.PSP_EBOOT_SFO = 'PARAM.SFO'
|
||||
conf.env.PSP_EBOOT_ICON = 'NULL'
|
||||
conf.env.PSP_EBOOT_ICON1 = 'NULL'
|
||||
conf.env.PSP_EBOOT_UNKPNG = 'NULL'
|
||||
conf.env.PSP_EBOOT_PIC1 = 'NULL'
|
||||
conf.env.PSP_EBOOT_SND0 = 'NULL'
|
||||
conf.env.PSP_EBOOT_PSAR = 'NULL'
|
||||
conf.env.PSP_EBOOT = 'EBOOT.PBP'
|
||||
|
||||
# set target parameters
|
||||
conf.env.PSP_BUILD_TARGET = 'xash'
|
||||
conf.env.PSP_BUILD_EBOOT = True
|
||||
|
||||
if conf.options.SINGLE_BINARY:
|
||||
conf.options.IGNORE_PROJECTS = 'ref_gl,stub/server,stub/client'
|
||||
conf.options.STATIC_LINKING = 'menu'
|
||||
if conf.env.PSP_RENDER_TYPE == 'SW':
|
||||
conf.options.STATIC_LINKING += ',ref_soft'
|
||||
else:
|
||||
conf.options.IGNORE_PROJECTS += ',ref_soft'
|
||||
|
||||
if conf.env.PSP_RENDER_TYPE == 'HW':
|
||||
conf.options.STATIC_LINKING += ',ref_gu'
|
||||
else:
|
||||
conf.options.IGNORE_PROJECTS += ',ref_gu'
|
||||
|
||||
if conf.env.PSP_RENDER_TYPE == 'ALL':
|
||||
conf.options.STATIC_LINKING += 'ref_soft,ref_gu'
|
||||
|
||||
conf.env.IGNORE_PROJECTS = conf.options.IGNORE_PROJECTS.split(',')
|
||||
conf.load('xshlib') # for set linking
|
||||
|
||||
if conf.env.STATIC_LINKING:
|
||||
enforce_pic = False # PIC may break static linking
|
||||
|
||||
@@ -244,7 +301,7 @@ def configure(conf):
|
||||
},
|
||||
'debug': {
|
||||
'msvc': ['/O1'],
|
||||
'gcc': ['-Og'],
|
||||
'gcc': ['-Og', '-fno-omit-frame-pointer', '-funwind-tables'],
|
||||
'owcc': ['-O0', '-fno-omit-frame-pointer', '-funwind-tables', '-fno-omit-leaf-frame-pointer'],
|
||||
'default': ['-O1']
|
||||
},
|
||||
@@ -268,12 +325,12 @@ def configure(conf):
|
||||
'-Werror=vla',
|
||||
'-Werror=tautological-compare',
|
||||
'-Werror=duplicated-cond',
|
||||
'-Werror=duplicated-branches', # BEWARE: buggy
|
||||
# '-Werror=duplicated-branches', # BEWARE: buggy
|
||||
'-Werror=bool-compare',
|
||||
'-Werror=bool-operation',
|
||||
'-Werror=cast-align',
|
||||
# '-Werror=cast-align',
|
||||
'-Werror=cast-align=strict', # =strict is for GCC >=8
|
||||
'-Werror=packed',
|
||||
# '-Werror=packed',
|
||||
'-Werror=packed-not-aligned',
|
||||
'-Wuninitialized', # older GCC versions have -Wmaybe-uninitialized enabled by this switch, which is not accurate
|
||||
# so just warn, not error
|
||||
@@ -288,10 +345,10 @@ def configure(conf):
|
||||
'-Werror=implicit-function-declaration',
|
||||
'-Werror=int-conversion',
|
||||
'-Werror=implicit-int',
|
||||
'-Werror=strict-prototypes',
|
||||
# '-Werror=strict-prototypes',
|
||||
'-Werror=old-style-declaration',
|
||||
'-Werror=old-style-definition',
|
||||
'-Werror=declaration-after-statement',
|
||||
# '-Werror=declaration-after-statement',
|
||||
'-Werror=enum-conversion',
|
||||
'-fnonconst-initializers' # owcc
|
||||
]
|
||||
@@ -299,6 +356,13 @@ def configure(conf):
|
||||
linkflags = conf.get_flags_by_type(linker_flags, conf.options.BUILD_TYPE, conf.env.COMPILER_CC, conf.env.CC_VERSION[0])
|
||||
cflags = conf.get_flags_by_type(compiler_c_cxx_flags, conf.options.BUILD_TYPE, conf.env.COMPILER_CC, conf.env.CC_VERSION[0])
|
||||
|
||||
# Profiling
|
||||
# if conf.options.PROFILING:
|
||||
# prof_cflags = {
|
||||
# 'gcc': ['-pg']
|
||||
# }
|
||||
# cflags += conf.get_flags_by_compiler(prof_cflags, conf.env.COMPILER_CC)
|
||||
|
||||
# Here we don't differentiate C or C++ flags
|
||||
if conf.options.LTO:
|
||||
lto_cflags = {
|
||||
@@ -323,7 +387,7 @@ def configure(conf):
|
||||
}
|
||||
|
||||
cflags += conf.get_flags_by_compiler(polly_cflags, conf.env.COMPILER_CC)
|
||||
|
||||
|
||||
# And here C++ flags starts to be treated separately
|
||||
cxxflags = list(cflags)
|
||||
if conf.env.COMPILER_CC != 'msvc':
|
||||
@@ -359,7 +423,8 @@ def configure(conf):
|
||||
else:
|
||||
# include portable stdint by Paul Hsich
|
||||
conf.define('STDINT_H', 'pstdint.h')
|
||||
|
||||
|
||||
conf.env.PROFILING = conf.options.PROFILING
|
||||
conf.env.DEDICATED = conf.options.DEDICATED
|
||||
conf.env.SINGLE_BINARY = conf.options.SINGLE_BINARY or conf.env.DEDICATED
|
||||
if conf.env.DEST_OS == 'dos':
|
||||
@@ -407,6 +472,9 @@ def configure(conf):
|
||||
if conf.options.LOW_MEMORY:
|
||||
conf.define('XASH_LOW_MEMORY', conf.options.LOW_MEMORY)
|
||||
|
||||
if conf.options.PROFILING:
|
||||
conf.define('XASH_PROFILING', 1)
|
||||
|
||||
for i in SUBDIRS:
|
||||
if not i.is_enabled(conf):
|
||||
continue
|
||||
@@ -420,3 +488,4 @@ def build(bld):
|
||||
continue
|
||||
|
||||
bld.add_subproject(i.name)
|
||||
bld.load('xcompile')
|
||||
|
||||
Reference in New Issue
Block a user