mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-05 19:45:05 +08:00
Compare commits
88 Commits
continuous
...
psp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8044646a2b | ||
|
|
cae351f7b1 | ||
|
|
9812a9104b | ||
|
|
d419921ca3 | ||
|
|
3ccb156554 | ||
|
|
15ea61ea34 | ||
|
|
e6a9724d7c | ||
|
|
28723b01a9 | ||
|
|
0dc1c13b83 | ||
|
|
1704712650 | ||
|
|
066d87f546 | ||
|
|
0b500168a7 | ||
|
|
e3e5fe8e18 | ||
|
|
da161103b1 | ||
|
|
d6d8ee3e57 | ||
|
|
89ee68d5d0 | ||
|
|
f5ca0175a5 | ||
|
|
5559f728b7 | ||
|
|
238687affa | ||
|
|
5832d017c7 | ||
|
|
4e78898c6f | ||
|
|
c6520b83b2 | ||
|
|
a440d1ff7a | ||
|
|
3889ed8c52 | ||
|
|
53d44f4c0e | ||
|
|
bdc2009683 | ||
|
|
a375adb9ea | ||
|
|
122a11005b | ||
|
|
f70938d2b0 | ||
|
|
40dca1ea1f | ||
|
|
f8452b8490 | ||
|
|
3b50fded8b | ||
|
|
5ad4f43a7e | ||
|
|
ef117ffbb3 | ||
|
|
8850d2ae52 | ||
|
|
e66400ca39 | ||
|
|
01affdcbbd | ||
|
|
ed2ba1f226 | ||
|
|
1abec2620a | ||
|
|
f4ae5cf8e0 | ||
|
|
57ddff5457 | ||
|
|
d98330adca | ||
|
|
21ed285da7 | ||
|
|
b517019750 | ||
|
|
b567531cdb | ||
|
|
9c61941e52 | ||
|
|
3afc7134ab | ||
|
|
bcf838c42f | ||
|
|
91d6fdd190 | ||
|
|
b8ff41eac9 | ||
|
|
0277700977 | ||
|
|
da68591f03 | ||
|
|
da695b75c4 | ||
|
|
1b4bc7f5ec | ||
|
|
cbfb43f05b | ||
|
|
db9e82cdec | ||
|
|
12889494e0 | ||
|
|
f2d59eb7f8 | ||
|
|
3a3b8e2c4a | ||
|
|
1e132bf29e | ||
|
|
d35330cd55 | ||
|
|
c07c1357e5 | ||
|
|
8071355d68 | ||
|
|
6073e35bfc | ||
|
|
8e8a0e4908 | ||
|
|
1d7176751c | ||
|
|
07e29771a1 | ||
|
|
89ec7122fe | ||
|
|
fe8fea742d | ||
|
|
2ab8bce924 | ||
|
|
90faeb231f | ||
|
|
2885d44593 | ||
|
|
4dfdbdd6aa | ||
|
|
5eb19c1478 | ||
|
|
13a9c41b0c | ||
|
|
2eef2cec49 | ||
|
|
7be87a913d | ||
|
|
dc22f5cbaf | ||
|
|
5c244b4140 | ||
|
|
e7e10ac8b9 | ||
|
|
a308ce2f48 | ||
|
|
eea17a4e32 | ||
|
|
cab187618d | ||
|
|
32e175311b | ||
|
|
190279c117 | ||
|
|
f5aaa58ff9 | ||
|
|
cd37d866c2 | ||
|
|
64020b2902 |
21
README.md
21
README.md
@@ -73,6 +73,10 @@ This repository contains our fork of HLSDK and restored source code for some of
|
|||||||
* Clone this repostory:
|
* Clone this repostory:
|
||||||
`$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`
|
`$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`
|
||||||
|
|
||||||
|
#### PSP
|
||||||
|
* Build pspsdk(GCC 9.3) from https://github.com/pspdev
|
||||||
|
* Clone this repository: `git clone --recursive https://github.com/Crow-bar/xash3d-fwgs`.
|
||||||
|
|
||||||
### Building
|
### Building
|
||||||
#### Windows (Visual Studio)
|
#### Windows (Visual Studio)
|
||||||
0) Open command line
|
0) Open command line
|
||||||
@@ -90,3 +94,20 @@ If compiling 32-bit on amd64, you may need to supply `export PKG_CONFIG_PATH=/us
|
|||||||
(You need to pass `-8` to compile 64-bit engine on 64-bit x86 processor)
|
(You need to pass `-8` to compile 64-bit engine on 64-bit x86 processor)
|
||||||
2) Compile: `./waf build`
|
2) Compile: `./waf build`
|
||||||
3) Install(optional): `./waf install --destdir=/path/to/any/output/directory`
|
3) Install(optional): `./waf install --destdir=/path/to/any/output/directory`
|
||||||
|
|
||||||
|
#### PSP
|
||||||
|
0) Navigate to `xash3d-fwgs` directory.
|
||||||
|
1) Examine which build options are available: `./waf --help`
|
||||||
|
2) Configure build:
|
||||||
|
Normal: `./waf configure -T fast --psp=prx,660,HW --prefix=/path/to/any/output/directory`
|
||||||
|
Profiling: `./waf configure -T debug --psp=elf,660,HW --enable-profiling --prefix=/path/to/any/output/directory`
|
||||||
|
3) Compile: `./waf build`
|
||||||
|
4) Install(optional): `./waf install`
|
||||||
|
|
||||||
|
|
||||||
|
## Running
|
||||||
|
0) Copy libraries and main executable somewhere, if you're skipped installation stage.
|
||||||
|
1) Copy game files to same directory
|
||||||
|
2) Run `xash3d.exe`/`xash3d.sh`/`xash3d` depending on which platform you're using.
|
||||||
|
|
||||||
|
For additional info, run Xash3D with `-help` command line key.
|
||||||
|
|||||||
@@ -20,16 +20,19 @@ GNU General Public License for more details.
|
|||||||
#define VIDEO_SDL 1
|
#define VIDEO_SDL 1
|
||||||
#define VIDEO_FBDEV 3
|
#define VIDEO_FBDEV 3
|
||||||
#define VIDEO_DOS 4
|
#define VIDEO_DOS 4
|
||||||
|
#define VIDEO_PSP 5
|
||||||
|
|
||||||
// audio backends (XASH_SOUND)
|
// audio backends (XASH_SOUND)
|
||||||
#define SOUND_NULL 0
|
#define SOUND_NULL 0
|
||||||
#define SOUND_SDL 1
|
#define SOUND_SDL 1
|
||||||
#define SOUND_ALSA 3
|
#define SOUND_ALSA 3
|
||||||
|
#define SOUND_PSP 4
|
||||||
|
|
||||||
// input (XASH_INPUT)
|
// input (XASH_INPUT)
|
||||||
#define INPUT_NULL 0
|
#define INPUT_NULL 0
|
||||||
#define INPUT_SDL 1
|
#define INPUT_SDL 1
|
||||||
#define INPUT_EVDEV 3
|
#define INPUT_EVDEV 3
|
||||||
|
#define INPUT_PSP 4
|
||||||
|
|
||||||
// timer (XASH_TIMER)
|
// timer (XASH_TIMER)
|
||||||
#define TIMER_NULL 0 // not used
|
#define TIMER_NULL 0 // not used
|
||||||
@@ -37,17 +40,20 @@ GNU General Public License for more details.
|
|||||||
#define TIMER_POSIX 2
|
#define TIMER_POSIX 2
|
||||||
#define TIMER_WIN32 3
|
#define TIMER_WIN32 3
|
||||||
#define TIMER_DOS 4
|
#define TIMER_DOS 4
|
||||||
|
#define TIMER_PSP 5
|
||||||
|
|
||||||
// messageboxes (XASH_MESSAGEBOX)
|
// messageboxes (XASH_MESSAGEBOX)
|
||||||
#define MSGBOX_STDERR 0
|
#define MSGBOX_STDERR 0
|
||||||
#define MSGBOX_SDL 1
|
#define MSGBOX_SDL 1
|
||||||
#define MSGBOX_WIN32 3
|
#define MSGBOX_WIN32 3
|
||||||
#define MSGBOX_NSWITCH 4
|
#define MSGBOX_NSWITCH 4
|
||||||
|
#define MSGBOX_PSP 5
|
||||||
|
|
||||||
// library loading (XASH_LIB)
|
// library loading (XASH_LIB)
|
||||||
#define LIB_NULL 0
|
#define LIB_NULL 0
|
||||||
#define LIB_POSIX 1
|
#define LIB_POSIX 1
|
||||||
#define LIB_WIN32 2
|
#define LIB_WIN32 2
|
||||||
#define LIB_STATIC 3
|
#define LIB_STATIC 3
|
||||||
|
#define LIB_PSP 4
|
||||||
|
|
||||||
#endif /* BACKENDS_H */
|
#endif /* BACKENDS_H */
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ NOTE: number at end of pixelformat name it's a total bitscount e.g. PF_RGB_24 ==
|
|||||||
|| type == PF_BC7_UNORM \
|
|| type == PF_BC7_UNORM \
|
||||||
|| type == PF_BC7_SRGB \
|
|| type == PF_BC7_SRGB \
|
||||||
|| type == PF_KTX2_RAW )
|
|| type == PF_KTX2_RAW )
|
||||||
|
#define ImageIND( type ) (type == PF_INDEXED_32 || type == PF_INDEXED_24)
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@@ -33,6 +34,10 @@ typedef enum
|
|||||||
PF_BGRA_32, // big endian RGBA (MacOS)
|
PF_BGRA_32, // big endian RGBA (MacOS)
|
||||||
PF_RGB_24, // uncompressed dds or another 24-bit image
|
PF_RGB_24, // uncompressed dds or another 24-bit image
|
||||||
PF_BGR_24, // big-endian RGB (MacOS)
|
PF_BGR_24, // big-endian RGB (MacOS)
|
||||||
|
PF_RGB_332, // 8-bit R3 G3 B2
|
||||||
|
PF_RGB_5650, // 16-bit R5 G6 B5
|
||||||
|
PF_RGBA_5551, // 16-bit R5 G5 B5 A1
|
||||||
|
PF_RGBA_4444, // 16-bit R4 G4 B4 A4
|
||||||
PF_LUMINANCE,
|
PF_LUMINANCE,
|
||||||
PF_DXT1, // s3tc DXT1/BC1 format
|
PF_DXT1, // s3tc DXT1/BC1 format
|
||||||
PF_DXT3, // s3tc DXT3/BC2 format
|
PF_DXT3, // s3tc DXT3/BC2 format
|
||||||
|
|||||||
@@ -127,6 +127,21 @@ typedef struct
|
|||||||
int flags; // sky or slime, no lightmap or 256 subdivision
|
int flags; // sky or slime, no lightmap or 256 subdivision
|
||||||
} mtexinfo_t;
|
} 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
|
typedef struct glpoly_s
|
||||||
{
|
{
|
||||||
struct glpoly_s *next;
|
struct glpoly_s *next;
|
||||||
@@ -135,7 +150,7 @@ typedef struct glpoly_s
|
|||||||
int flags; // for SURF_UNDERWATER
|
int flags; // for SURF_UNDERWATER
|
||||||
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
|
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
|
||||||
} glpoly_t;
|
} glpoly_t;
|
||||||
|
#endif
|
||||||
typedef struct mnode_s
|
typedef struct mnode_s
|
||||||
{
|
{
|
||||||
// common with leaf
|
// common with leaf
|
||||||
|
|||||||
@@ -77,6 +77,30 @@ SETUP BACKENDS DEFINITIONS
|
|||||||
|
|
||||||
// usually only 10-20 fds availiable
|
// usually only 10-20 fds availiable
|
||||||
#define XASH_REDUCE_FD
|
#define XASH_REDUCE_FD
|
||||||
|
#elif XASH_PSP
|
||||||
|
#ifndef XASH_VIDEO
|
||||||
|
#define XASH_VIDEO VIDEO_PSP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef XASH_TIMER
|
||||||
|
#define XASH_TIMER TIMER_PSP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef XASH_INPUT
|
||||||
|
#define XASH_INPUT INPUT_PSP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef XASH_SOUND
|
||||||
|
#define XASH_SOUND SOUND_PSP
|
||||||
|
#endif // XASH_SOUND
|
||||||
|
|
||||||
|
#ifndef XASH_MESSAGEBOX
|
||||||
|
#define XASH_MESSAGEBOX MSGBOX_PSP
|
||||||
|
#endif // XASH_MESSAGEBOX
|
||||||
|
|
||||||
|
#define XASH_REDUCE_FD
|
||||||
|
#define XASH_NO_TOUCH
|
||||||
|
#define XASH_NO_ZIP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // XASH_DEDICATED
|
#endif // XASH_DEDICATED
|
||||||
@@ -105,7 +129,7 @@ SETUP BACKENDS DEFINITIONS
|
|||||||
#endif // !XASH_WIN32
|
#endif // !XASH_WIN32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef XASH_STATIC_LIBS
|
#if defined(XASH_STATIC_LIBS) && !XASH_PSP
|
||||||
#define XASH_LIB LIB_STATIC
|
#define XASH_LIB LIB_STATIC
|
||||||
#define XASH_INTERNAL_GAMELIBS
|
#define XASH_INTERNAL_GAMELIBS
|
||||||
#define XASH_ALLOW_SAVERESTORE_OFFSETS
|
#define XASH_ALLOW_SAVERESTORE_OFFSETS
|
||||||
@@ -113,6 +137,8 @@ SETUP BACKENDS DEFINITIONS
|
|||||||
#define XASH_LIB LIB_WIN32
|
#define XASH_LIB LIB_WIN32
|
||||||
#elif XASH_POSIX
|
#elif XASH_POSIX
|
||||||
#define XASH_LIB LIB_POSIX
|
#define XASH_LIB LIB_POSIX
|
||||||
|
#elif XASH_PSP
|
||||||
|
#define XASH_LIB LIB_PSP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -193,4 +219,20 @@ Default build-depended cvar and constant values
|
|||||||
#define DEFAULT_MAX_EDICTS 1200 // was 900 before HL25
|
#define DEFAULT_MAX_EDICTS 1200 // was 900 before HL25
|
||||||
#endif // DEFAULT_MAX_EDICTS
|
#endif // DEFAULT_MAX_EDICTS
|
||||||
|
|
||||||
|
#ifndef DEFAULT_ACCELERATED_RENDERER
|
||||||
|
#ifdef XASH_PSP
|
||||||
|
#define DEFAULT_ACCELERATED_RENDERER "gu"
|
||||||
|
#else
|
||||||
|
#if XASH_MOBILE_PLATFORM
|
||||||
|
#define DEFAULT_ACCELERATED_RENDERER "gles1"
|
||||||
|
#else // !XASH_MOBILE_PLATFORM
|
||||||
|
#define DEFAULT_ACCELERATED_RENDERER "gl"
|
||||||
|
#endif // !XASH_MOBILE_PLATFORM
|
||||||
|
#endif
|
||||||
|
#endif // DEFAULT_ACCELERATED_RENDERER
|
||||||
|
|
||||||
|
#ifndef DEFAULT_SOFTWARE_RENDERER
|
||||||
|
#define DEFAULT_SOFTWARE_RENDERER "soft" // mittorn's ref_soft
|
||||||
|
#endif // DEFAULT_SOFTWARE_RENDERER
|
||||||
|
|
||||||
#endif // DEFAULTS_H
|
#endif // DEFAULTS_H
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ GNU General Public License for more details.
|
|||||||
#include <sys/syslimits.h>
|
#include <sys/syslimits.h>
|
||||||
#define OS_LIB_EXT "dylib"
|
#define OS_LIB_EXT "dylib"
|
||||||
#define OPEN_COMMAND "open"
|
#define OPEN_COMMAND "open"
|
||||||
#else
|
#elif XASH_PSP
|
||||||
|
#define OS_LIB_EXT "prx"
|
||||||
|
#else
|
||||||
#define OS_LIB_EXT "so"
|
#define OS_LIB_EXT "so"
|
||||||
#define OPEN_COMMAND "xdg-open"
|
#define OPEN_COMMAND "xdg-open"
|
||||||
#endif
|
#endif
|
||||||
@@ -55,6 +57,16 @@ GNU General Public License for more details.
|
|||||||
#define _mkdir( x ) mkdir( x, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH )
|
#define _mkdir( x ) mkdir( x, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if XASH_PSP
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pspiofilemgr.h>
|
||||||
|
|
||||||
|
#define O_BINARY 0
|
||||||
|
#define O_TEXT 0
|
||||||
|
|
||||||
|
#define _mkdir( x ) sceIoMkdir( x, FIO_S_IRWXU | FIO_S_IRWXG | FIO_S_IROTH | FIO_S_IXOTH )
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef void* HANDLE;
|
typedef void* HANDLE;
|
||||||
typedef void* HINSTANCE;
|
typedef void* HINSTANCE;
|
||||||
|
|
||||||
|
|||||||
@@ -101,8 +101,13 @@ typedef enum
|
|||||||
TF_TEXTURE_3D = (1<<20), // this is GL_TEXTURE_3D
|
TF_TEXTURE_3D = (1<<20), // this is GL_TEXTURE_3D
|
||||||
TF_ATLAS_PAGE = (1<<21), // bit who indicate lightmap page or deluxemap page
|
TF_ATLAS_PAGE = (1<<21), // bit who indicate lightmap page or deluxemap page
|
||||||
TF_ALPHACONTRAST = (1<<22), // special texture mode for A2C
|
TF_ALPHACONTRAST = (1<<22), // special texture mode for A2C
|
||||||
|
#if XASH_PSP
|
||||||
|
TF_IMG_SWIZZLED = (1<<23),
|
||||||
|
TF_IMG_INVRAM = (1<<24),
|
||||||
|
#else
|
||||||
// reserved
|
// reserved
|
||||||
// reserved
|
// reserved
|
||||||
|
#endif
|
||||||
TF_IMG_UPLOADED = (1<<25), // this is set for first time when called glTexImage, otherwise it will be call glTexSubImage
|
TF_IMG_UPLOADED = (1<<25), // this is set for first time when called glTexImage, otherwise it will be call glTexSubImage
|
||||||
TF_ARB_FLOAT = (1<<26), // float textures
|
TF_ARB_FLOAT = (1<<26), // float textures
|
||||||
TF_NOCOMPARE = (1<<27), // disable comparing for depth textures
|
TF_NOCOMPARE = (1<<27), // disable comparing for depth textures
|
||||||
|
|||||||
@@ -21,12 +21,22 @@ typedef int sound_t;
|
|||||||
typedef float vec_t;
|
typedef float vec_t;
|
||||||
typedef vec_t vec2_t[2];
|
typedef vec_t vec2_t[2];
|
||||||
typedef vec_t vec3_t[3];
|
typedef vec_t vec3_t[3];
|
||||||
|
#if XASH_PSP
|
||||||
|
typedef vec_t vec4_t[4] __attribute__( ( aligned( 16 ) ) );
|
||||||
|
typedef vec_t quat_t[4] __attribute__( ( aligned( 16 ) ) );
|
||||||
|
#else
|
||||||
typedef vec_t vec4_t[4];
|
typedef vec_t vec4_t[4];
|
||||||
typedef vec_t quat_t[4];
|
typedef vec_t quat_t[4];
|
||||||
|
#endif
|
||||||
typedef byte rgba_t[4]; // unsigned byte colorpack
|
typedef byte rgba_t[4]; // unsigned byte colorpack
|
||||||
typedef byte rgb_t[3]; // unsigned byte colorpack
|
typedef byte rgb_t[3]; // unsigned byte colorpack
|
||||||
|
#if XASH_PSP
|
||||||
|
typedef vec_t matrix3x4[3][4] __attribute__( ( aligned( 16 ) ) );
|
||||||
|
typedef vec_t matrix4x4[4][4] __attribute__( ( aligned( 16 ) ) );
|
||||||
|
#else
|
||||||
typedef vec_t matrix3x4[3][4];
|
typedef vec_t matrix3x4[3][4];
|
||||||
typedef vec_t matrix4x4[4][4];
|
typedef vec_t matrix4x4[4][4];
|
||||||
|
#endif
|
||||||
|
|
||||||
#if XASH_64BIT
|
#if XASH_64BIT
|
||||||
typedef uint32_t poolhandle_t;
|
typedef uint32_t poolhandle_t;
|
||||||
@@ -194,6 +204,9 @@ typedef void *(*pfnCreateInterface_t)( const char *, int * );
|
|||||||
// config strings are a general means of communication from
|
// config strings are a general means of communication from
|
||||||
// the server to all connected clients.
|
// the server to all connected clients.
|
||||||
// each config string can be at most CS_SIZE characters.
|
// each config string can be at most CS_SIZE characters.
|
||||||
|
#if XASH_PSP
|
||||||
|
#define MAX_QPATH 48
|
||||||
|
#else
|
||||||
#if XASH_LOW_MEMORY == 0
|
#if XASH_LOW_MEMORY == 0
|
||||||
#define MAX_QPATH 64 // max length of a game pathname
|
#define MAX_QPATH 64 // max length of a game pathname
|
||||||
#elif XASH_LOW_MEMORY == 2
|
#elif XASH_LOW_MEMORY == 2
|
||||||
@@ -201,6 +214,7 @@ typedef void *(*pfnCreateInterface_t)( const char *, int * );
|
|||||||
#elif XASH_LOW_MEMORY == 1
|
#elif XASH_LOW_MEMORY == 1
|
||||||
#define MAX_QPATH 48
|
#define MAX_QPATH 48
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#define MAX_OSPATH 260 // max length of a filesystem pathname
|
#define MAX_OSPATH 260 // max length of a filesystem pathname
|
||||||
#define CS_SIZE 64 // size of one config string
|
#define CS_SIZE 64 // size of one config string
|
||||||
#define CS_TIME 16 // size of time string
|
#define CS_TIME 16 // size of time string
|
||||||
|
|||||||
@@ -26,18 +26,6 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
// #define STUDIO_INTERPOLATION_FIX
|
// #define STUDIO_INTERPOLATION_FIX
|
||||||
|
|
||||||
/*
|
|
||||||
==================
|
|
||||||
CL_IsPlayerIndex
|
|
||||||
|
|
||||||
detect player entity
|
|
||||||
==================
|
|
||||||
*/
|
|
||||||
qboolean CL_IsPlayerIndex( int idx )
|
|
||||||
{
|
|
||||||
return ( idx >= 1 && idx <= cl.maxclients );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=========================================================================
|
=========================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -96,41 +96,6 @@ static dllfunc_t cdll_new_exports[] = // allowed only in SDK 2.3 and higher
|
|||||||
|
|
||||||
static void pfnSPR_DrawHoles( int frame, int x, int y, const wrect_t *prc );
|
static void pfnSPR_DrawHoles( int frame, int x, int y, const wrect_t *prc );
|
||||||
|
|
||||||
/*
|
|
||||||
====================
|
|
||||||
CL_GetEntityByIndex
|
|
||||||
|
|
||||||
Render callback for studio models
|
|
||||||
====================
|
|
||||||
*/
|
|
||||||
cl_entity_t *CL_GetEntityByIndex( int index )
|
|
||||||
{
|
|
||||||
if( !clgame.entities ) // not in game yet
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if( index < 0 || index >= clgame.maxEntities )
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if( index == 0 )
|
|
||||||
return clgame.entities;
|
|
||||||
|
|
||||||
return CL_EDICT_NUM( index );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
CL_ModelHandle
|
|
||||||
|
|
||||||
get model handle by index
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
model_t *CL_ModelHandle( int modelindex )
|
|
||||||
{
|
|
||||||
if( modelindex < 0 || modelindex >= MAX_MODELS )
|
|
||||||
return NULL;
|
|
||||||
return cl.models[modelindex];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
====================
|
====================
|
||||||
CL_IsThirdPerson
|
CL_IsThirdPerson
|
||||||
@@ -939,7 +904,7 @@ void CL_DrawCrosshair( void )
|
|||||||
VectorAdd( refState.viewangles, cl.crosshairangle, angles );
|
VectorAdd( refState.viewangles, cl.crosshairangle, angles );
|
||||||
AngleVectors( angles, forward, NULL, NULL );
|
AngleVectors( angles, forward, NULL, NULL );
|
||||||
VectorAdd( refState.vieworg, forward, point );
|
VectorAdd( refState.vieworg, forward, point );
|
||||||
ref.dllFuncs.WorldToScreen( point, screen );
|
gTriApi.WorldToScreen( point, screen );
|
||||||
|
|
||||||
x += ( clgame.viewport[2] >> 1 ) * screen[0] + 0.5f;
|
x += ( clgame.viewport[2] >> 1 ) * screen[0] + 0.5f;
|
||||||
y += ( clgame.viewport[3] >> 1 ) * screen[1] + 0.5f;
|
y += ( clgame.viewport[3] >> 1 ) * screen[1] + 0.5f;
|
||||||
@@ -1084,7 +1049,6 @@ void CL_ClearWorld( void )
|
|||||||
|
|
||||||
world.max_recursion = 0;
|
world.max_recursion = 0;
|
||||||
|
|
||||||
clgame.ds.cullMode = TRI_FRONT;
|
|
||||||
clgame.numStatics = 0;
|
clgame.numStatics = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,12 +81,12 @@ NetGraph_FillRGBA shortcut
|
|||||||
*/
|
*/
|
||||||
static void NetGraph_DrawRect( wrect_t *rect, byte colors[4] )
|
static void NetGraph_DrawRect( wrect_t *rect, byte colors[4] )
|
||||||
{
|
{
|
||||||
ref.dllFuncs.Color4ub( colors[0], colors[1], colors[2], colors[3] ); // color for this quad
|
gTriApi.Color4ub( colors[0], colors[1], colors[2], colors[3] ); // color for this quad
|
||||||
|
|
||||||
ref.dllFuncs.Vertex3f( rect->left, rect->top, 0 );
|
gTriApi.Vertex3f( rect->left, rect->top, 0 );
|
||||||
ref.dllFuncs.Vertex3f( rect->left + rect->right, rect->top, 0 );
|
gTriApi.Vertex3f( rect->left + rect->right, rect->top, 0 );
|
||||||
ref.dllFuncs.Vertex3f( rect->left + rect->right, rect->top + rect->bottom, 0 );
|
gTriApi.Vertex3f( rect->left + rect->right, rect->top + rect->bottom, 0 );
|
||||||
ref.dllFuncs.Vertex3f( rect->left, rect->top + rect->bottom, 0 );
|
gTriApi.Vertex3f( rect->left, rect->top + rect->bottom, 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -691,7 +691,7 @@ void SCR_DrawNetGraph( void )
|
|||||||
|
|
||||||
ref.dllFuncs.End();
|
ref.dllFuncs.End();
|
||||||
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
|
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
|
||||||
ref.dllFuncs.GL_SetRenderMode( kRenderNormal );
|
ref.dllFuncs.RenderMode( kRenderNormal );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -393,7 +393,7 @@ int CL_TempEntAddEntity( cl_entity_t *pEntity )
|
|||||||
VectorAdd( pEntity->origin, pEntity->model->maxs, maxs );
|
VectorAdd( pEntity->origin, pEntity->model->maxs, maxs );
|
||||||
|
|
||||||
// g-cont. just use PVS from previous frame
|
// g-cont. just use PVS from previous frame
|
||||||
if( TriBoxInPVS( mins, maxs ))
|
if( Mod_BoxVisible( mins, maxs, ref.dllFuncs.Mod_GetCurrentVis( )))
|
||||||
{
|
{
|
||||||
VectorCopy( pEntity->angles, pEntity->curstate.angles );
|
VectorCopy( pEntity->angles, pEntity->curstate.angles );
|
||||||
VectorCopy( pEntity->origin, pEntity->curstate.origin );
|
VectorCopy( pEntity->origin, pEntity->curstate.origin );
|
||||||
@@ -1023,8 +1023,12 @@ void GAME_EXPORT R_BreakModel( const vec3_t pos, const vec3_t size, const vec3_t
|
|||||||
count = (size[0] * size[1] + size[1] * size[2] + size[2] * size[0]) / (3 * SHARD_VOLUME * SHARD_VOLUME);
|
count = (size[0] * size[1] + size[1] * size[2] + size[2] * size[0]) / (3 * SHARD_VOLUME * SHARD_VOLUME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if XASH_PSP
|
||||||
|
if( count > 15 ) count = 15;
|
||||||
|
#else
|
||||||
// limit to 100 pieces
|
// limit to 100 pieces
|
||||||
if( count > 100 ) count = 100;
|
if( count > 100 ) count = 100;
|
||||||
|
#endif
|
||||||
|
|
||||||
for( i = 0; i < count; i++ )
|
for( i = 0; i < count; i++ )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -101,19 +101,6 @@ struct beam_s *R_BeamRing( int startEnt, int endEnt, int modelIndex, float life,
|
|||||||
struct beam_s *R_BeamFollow( int startEnt, int modelIndex, float life, float width, float r, float g, float b, float brightness );
|
struct beam_s *R_BeamFollow( int startEnt, int modelIndex, float life, float width, float r, float g, float b, float brightness );
|
||||||
void R_BeamKill( int deadEntity );
|
void R_BeamKill( int deadEntity );
|
||||||
|
|
||||||
|
|
||||||
// TriAPI
|
|
||||||
void TriRenderMode( int mode );
|
|
||||||
void TriColor4f( float r, float g, float b, float a );
|
|
||||||
void TriColor4ub( byte r, byte g, byte b, byte a );
|
|
||||||
void TriBrightness( float brightness );
|
|
||||||
void TriCullFace( TRICULLSTYLE mode );
|
|
||||||
int TriWorldToScreen( const float *world, float *screen );
|
|
||||||
int TriBoxInPVS( float *mins, float *maxs );
|
|
||||||
void TriLightAtPoint( float *pos, float *value );
|
|
||||||
void TriColor4fRendermode( float r, float g, float b, float a, int rendermode );
|
|
||||||
int TriSpriteTexture( model_t *pSpriteModel, int frame );
|
|
||||||
|
|
||||||
extern model_t *cl_sprite_dot;
|
extern model_t *cl_sprite_dot;
|
||||||
extern model_t *cl_sprite_shell;
|
extern model_t *cl_sprite_shell;
|
||||||
|
|
||||||
|
|||||||
@@ -417,10 +417,10 @@ void R_DrawLeafNode( float x, float y, float scale )
|
|||||||
|
|
||||||
void R_DrawNodeConnection( float x, float y, float x2, float y2 )
|
void R_DrawNodeConnection( float x, float y, float x2, float y2 )
|
||||||
{
|
{
|
||||||
ref.dllFuncs.Begin( TRI_LINES );
|
gTriApi.Begin( TRI_LINES );
|
||||||
ref.dllFuncs.Vertex3f( x, y, 0 );
|
gTriApi.Vertex3f( x, y, 0 );
|
||||||
ref.dllFuncs.Vertex3f( x2, y2, 0 );
|
gTriApi.Vertex3f( x2, y2, 0 );
|
||||||
ref.dllFuncs.End( );
|
gTriApi.End( );
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int shownodes, mleaf_t *viewleaf )
|
void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int shownodes, mleaf_t *viewleaf )
|
||||||
@@ -443,10 +443,10 @@ void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int shownodes,
|
|||||||
if( shownodes == 1 )
|
if( shownodes == 1 )
|
||||||
{
|
{
|
||||||
if( cl.worldmodel->leafs == leaf )
|
if( cl.worldmodel->leafs == leaf )
|
||||||
ref.dllFuncs.Color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
gTriApi.Color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||||
else if( viewleaf && viewleaf == leaf )
|
else if( viewleaf && viewleaf == leaf )
|
||||||
ref.dllFuncs.Color4f( 1.0f, 0.0f, 0.0f, 1.0f );
|
gTriApi.Color4f( 1.0f, 0.0f, 0.0f, 1.0f );
|
||||||
else ref.dllFuncs.Color4f( 0.0f, 1.0f, 0.0f, 1.0f );
|
else gTriApi.Color4f( 0.0f, 1.0f, 0.0f, 1.0f );
|
||||||
R_DrawLeafNode( x, y, scale );
|
R_DrawLeafNode( x, y, scale );
|
||||||
}
|
}
|
||||||
world.recursion_level--;
|
world.recursion_level--;
|
||||||
@@ -455,7 +455,7 @@ void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int shownodes,
|
|||||||
|
|
||||||
if( shownodes == 1 )
|
if( shownodes == 1 )
|
||||||
{
|
{
|
||||||
ref.dllFuncs.Color4f( 0.0f, 0.0f, 1.0f, 1.0f );
|
gTriApi.Color4f( 0.0f, 0.0f, 1.0f, 1.0f );
|
||||||
R_DrawLeafNode( x, y, scale );
|
R_DrawLeafNode( x, y, scale );
|
||||||
}
|
}
|
||||||
else if( shownodes == 2 )
|
else if( shownodes == 2 )
|
||||||
@@ -487,7 +487,7 @@ void R_ShowTree( void )
|
|||||||
//pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
//pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||||
|
|
||||||
//pglLineWidth( 2.0f );
|
//pglLineWidth( 2.0f );
|
||||||
ref.dllFuncs.Color4f( 1, 0.7f, 0, 1.0f );
|
gTriApi.Color4f( 1, 0.7f, 0, 1.0f );
|
||||||
//pglDisable( GL_TEXTURE_2D );
|
//pglDisable( GL_TEXTURE_2D );
|
||||||
R_ShowTree_r( cl.worldmodel->nodes, x, y, world.max_recursion * 3.5f, 2, viewleaf );
|
R_ShowTree_r( cl.worldmodel->nodes, x, y, world.max_recursion * 3.5f, 2, viewleaf );
|
||||||
//pglEnable( GL_TEXTURE_2D );
|
//pglEnable( GL_TEXTURE_2D );
|
||||||
|
|||||||
@@ -370,7 +370,6 @@ typedef struct
|
|||||||
// holds text color
|
// holds text color
|
||||||
rgba_t textColor;
|
rgba_t textColor;
|
||||||
rgba_t spriteColor;
|
rgba_t spriteColor;
|
||||||
vec4_t triRGBA;
|
|
||||||
|
|
||||||
// crosshair members
|
// crosshair members
|
||||||
const model_t *pCrosshair;
|
const model_t *pCrosshair;
|
||||||
@@ -839,7 +838,6 @@ void CL_ClearSpriteTextures( void );
|
|||||||
void CL_CenterPrint( const char *text, float y );
|
void CL_CenterPrint( const char *text, float y );
|
||||||
void CL_TextMessageParse( byte *pMemFile, int fileSize );
|
void CL_TextMessageParse( byte *pMemFile, int fileSize );
|
||||||
client_textmessage_t *CL_TextMessageGet( const char *pName );
|
client_textmessage_t *CL_TextMessageGet( const char *pName );
|
||||||
model_t *CL_ModelHandle( int modelindex );
|
|
||||||
void NetAPI_CancelAllRequests( void );
|
void NetAPI_CancelAllRequests( void );
|
||||||
cl_entity_t *CL_GetLocalPlayer( void );
|
cl_entity_t *CL_GetLocalPlayer( void );
|
||||||
model_t *CL_LoadClientSprite( const char *filename );
|
model_t *CL_LoadClientSprite( const char *filename );
|
||||||
@@ -861,19 +859,45 @@ void CL_EnableScissor( scissor_state_t *scissor, int x, int y, int width, int he
|
|||||||
void CL_DisableScissor( scissor_state_t *scissor );
|
void CL_DisableScissor( scissor_state_t *scissor );
|
||||||
qboolean CL_Scissor( const scissor_state_t *scissor, float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 );
|
qboolean CL_Scissor( const scissor_state_t *scissor, float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 );
|
||||||
|
|
||||||
_inline cl_entity_t *CL_EDICT_NUM( int n )
|
static inline cl_entity_t *CL_EDICT_NUM( int n )
|
||||||
{
|
{
|
||||||
if( !clgame.entities )
|
if( unlikely( !clgame.entities )) // not in game yet
|
||||||
{
|
{
|
||||||
Host_Error( "CL_EDICT_NUM: clgame.entities is NULL\n");
|
Host_Error( "CL_EDICT_NUM: clgame.entities is NULL\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(( n >= 0 ) && ( n < clgame.maxEntities ))
|
if( unlikely( n < 0 || n >= clgame.maxEntities ))
|
||||||
return clgame.entities + n;
|
{
|
||||||
|
Host_Error( "CL_EDICT_NUM: bad number %i\n", n );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
Host_Error( "CL_EDICT_NUM: bad number %i\n", n );
|
return &clgame.entities[n];
|
||||||
return NULL;
|
}
|
||||||
|
|
||||||
|
static inline cl_entity_t *CL_GetEntityByIndex( int n )
|
||||||
|
{
|
||||||
|
if( unlikely( !clgame.entities )) // not in game yet
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if( unlikely( n < 0 || n >= clgame.maxEntities ))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &clgame.entities[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline model_t *CL_ModelHandle( int modelindex )
|
||||||
|
{
|
||||||
|
if( unlikely( modelindex < 0 || modelindex >= MAX_MODELS ))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return cl.models[modelindex];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline qboolean CL_IsPlayerIndex( int idx )
|
||||||
|
{
|
||||||
|
return ( idx >= 1 && idx <= cl.maxclients );
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -995,7 +1019,6 @@ void CL_ProcessPlayerState( int playerindex, entity_state_t *state );
|
|||||||
void CL_ComputePlayerOrigin( cl_entity_t *clent );
|
void CL_ComputePlayerOrigin( cl_entity_t *clent );
|
||||||
void CL_ProcessPacket( frame_t *frame );
|
void CL_ProcessPacket( frame_t *frame );
|
||||||
void CL_MoveThirdpersonCamera( void );
|
void CL_MoveThirdpersonCamera( void );
|
||||||
qboolean CL_IsPlayerIndex( int idx );
|
|
||||||
void CL_SetIdealPitch( void );
|
void CL_SetIdealPitch( void );
|
||||||
void CL_EmitEntities( void );
|
void CL_EmitEntities( void );
|
||||||
|
|
||||||
@@ -1189,5 +1212,6 @@ int Key_ToUpper( int key );
|
|||||||
void OSK_Draw( void );
|
void OSK_Draw( void );
|
||||||
|
|
||||||
extern rgba_t g_color_table[8];
|
extern rgba_t g_color_table[8];
|
||||||
|
extern triangleapi_t gTriApi;
|
||||||
|
|
||||||
#endif//CLIENT_H
|
#endif//CLIENT_H
|
||||||
|
|||||||
@@ -2195,7 +2195,7 @@ void Con_VidInit( void )
|
|||||||
|
|
||||||
Con_LoadConchars();
|
Con_LoadConchars();
|
||||||
Con_CheckResize();
|
Con_CheckResize();
|
||||||
#if XASH_LOW_MEMORY
|
#if XASH_LOW_MEMORY && !XASH_PSP
|
||||||
con.background = R_GetBuiltinTexture( REF_BLACK_TEXTURE );
|
con.background = R_GetBuiltinTexture( REF_BLACK_TEXTURE );
|
||||||
#else
|
#else
|
||||||
// loading console image
|
// loading console image
|
||||||
|
|||||||
@@ -19,6 +19,24 @@ GNU General Public License for more details.
|
|||||||
#include "vgui_draw.h"
|
#include "vgui_draw.h"
|
||||||
#include "mobility_int.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
|
typedef enum
|
||||||
{
|
{
|
||||||
touch_command, // just tap a button
|
touch_command, // just tap a button
|
||||||
@@ -1529,7 +1547,6 @@ void Touch_Draw( void )
|
|||||||
ref.dllFuncs.R_DrawStretchPic( TO_SCRN_X( touch.move_start_x + touch.side * width - GRID_X * touch_move_indicator.value ),
|
ref.dllFuncs.R_DrawStretchPic( TO_SCRN_X( touch.move_start_x + touch.side * width - GRID_X * touch_move_indicator.value ),
|
||||||
TO_SCRN_Y( touch.move_start_y - touch.forward * height - GRID_Y * touch_move_indicator.value ),
|
TO_SCRN_Y( touch.move_start_y - touch.forward * height - GRID_Y * touch_move_indicator.value ),
|
||||||
TO_SCRN_X( GRID_X * 2 * touch_move_indicator.value ), TO_SCRN_Y( GRID_Y * 2 * touch_move_indicator.value ), 0, 0, 1, 1, touch.joytexture );
|
TO_SCRN_X( GRID_X * 2 * touch_move_indicator.value ), TO_SCRN_Y( GRID_Y * 2 * touch_move_indicator.value ), 0, 0, 1, 1, touch.joytexture );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2191,3 +2208,5 @@ void Touch_Shutdown( void )
|
|||||||
touch.initialized = false;
|
touch.initialized = false;
|
||||||
Mem_FreePool( &touch.mempool );
|
Mem_FreePool( &touch.mempool );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* XASH_NO_TOUCH */
|
||||||
|
|||||||
@@ -60,8 +60,10 @@ uint IN_CollectInputDevices( void )
|
|||||||
if( !m_ignore.value ) // no way to check is mouse connected, so use cvar only
|
if( !m_ignore.value ) // no way to check is mouse connected, so use cvar only
|
||||||
ret |= INPUT_DEVICE_MOUSE;
|
ret |= INPUT_DEVICE_MOUSE;
|
||||||
|
|
||||||
|
#ifndef XASH_NO_TOUCH
|
||||||
if( touch_enable.value )
|
if( touch_enable.value )
|
||||||
ret |= INPUT_DEVICE_TOUCH;
|
ret |= INPUT_DEVICE_TOUCH;
|
||||||
|
#endif
|
||||||
|
|
||||||
if( Joy_IsActive() ) // connected or enabled
|
if( Joy_IsActive() ) // connected or enabled
|
||||||
ret |= INPUT_DEVICE_JOYSTICK;
|
ret |= INPUT_DEVICE_JOYSTICK;
|
||||||
@@ -91,13 +93,17 @@ void IN_LockInputDevices( qboolean lock )
|
|||||||
{
|
{
|
||||||
SetBits( m_ignore.flags, FCVAR_READ_ONLY );
|
SetBits( m_ignore.flags, FCVAR_READ_ONLY );
|
||||||
SetBits( joy_enable.flags, FCVAR_READ_ONLY );
|
SetBits( joy_enable.flags, FCVAR_READ_ONLY );
|
||||||
|
#ifndef XASH_NO_TOUCH
|
||||||
SetBits( touch_enable.flags, FCVAR_READ_ONLY );
|
SetBits( touch_enable.flags, FCVAR_READ_ONLY );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ClearBits( m_ignore.flags, FCVAR_READ_ONLY );
|
ClearBits( m_ignore.flags, FCVAR_READ_ONLY );
|
||||||
ClearBits( joy_enable.flags, FCVAR_READ_ONLY );
|
ClearBits( joy_enable.flags, FCVAR_READ_ONLY );
|
||||||
|
#ifndef XASH_NO_TOUCH
|
||||||
ClearBits( touch_enable.flags, FCVAR_READ_ONLY );
|
ClearBits( touch_enable.flags, FCVAR_READ_ONLY );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,11 +357,14 @@ void IN_MouseEvent( int key, int down )
|
|||||||
else ClearBits( in_mstate, BIT( key ));
|
else ClearBits( in_mstate, BIT( key ));
|
||||||
|
|
||||||
// touch emulation overrides all input
|
// touch emulation overrides all input
|
||||||
|
#if XASH_NO_TOUCH
|
||||||
if( touch_emulate.value )
|
if( touch_emulate.value )
|
||||||
{
|
{
|
||||||
Touch_KeyEvent( K_MOUSE1 + key, down );
|
Touch_KeyEvent( K_MOUSE1 + key, down );
|
||||||
}
|
}
|
||||||
else if( cls.key_dest == key_game )
|
else
|
||||||
|
#endif
|
||||||
|
if( cls.key_dest == key_game )
|
||||||
{
|
{
|
||||||
// perform button actions
|
// perform button actions
|
||||||
VGui_MouseEvent( K_MOUSE1 + key, down );
|
VGui_MouseEvent( K_MOUSE1 + key, down );
|
||||||
@@ -364,8 +373,7 @@ void IN_MouseEvent( int key, int down )
|
|||||||
// client may override IN_MouseEvent
|
// client may override IN_MouseEvent
|
||||||
// but by default it calls back to Key_Event anyway
|
// but by default it calls back to Key_Event anyway
|
||||||
if( in_mouseactive )
|
if( in_mouseactive )
|
||||||
clgame.dllFuncs.IN_MouseEvent( in_mstate );
|
clgame.dllFuncs.IN_MouseEvent( in_mstate ); }
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// perform button actions
|
// perform button actions
|
||||||
|
|||||||
@@ -515,7 +515,6 @@ void Key_Init( void )
|
|||||||
|
|
||||||
Cvar_RegisterVariable( &osk_enable );
|
Cvar_RegisterVariable( &osk_enable );
|
||||||
Cvar_RegisterVariable( &key_rotate );
|
Cvar_RegisterVariable( &key_rotate );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -703,7 +702,11 @@ void GAME_EXPORT Key_Event( int key, int down )
|
|||||||
VGui_KeyEvent( key, down );
|
VGui_KeyEvent( key, down );
|
||||||
|
|
||||||
// console key is hardcoded, so the user can never unbind it
|
// console key is hardcoded, so the user can never unbind it
|
||||||
|
#if XASH_PSP
|
||||||
|
if( key == '`' || key == '~' || key == K_MODE_BUTTON )
|
||||||
|
#else
|
||||||
if( key == '`' || key == '~' )
|
if( key == '`' || key == '~' )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// we are in typing mode, so don't switch to console
|
// we are in typing mode, so don't switch to console
|
||||||
if( cls.key_dest == key_message || !down )
|
if( cls.key_dest == key_message || !down )
|
||||||
@@ -714,7 +717,11 @@ void GAME_EXPORT Key_Event( int key, int down )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// escape is always handled special
|
// escape is always handled special
|
||||||
|
#if XASH_PSP
|
||||||
|
if( ( key == K_ESCAPE || key == K_START_BUTTON ) && down )
|
||||||
|
#else
|
||||||
if( key == K_ESCAPE && down )
|
if( key == K_ESCAPE && down )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
switch( cls.key_dest )
|
switch( cls.key_dest )
|
||||||
{
|
{
|
||||||
@@ -881,7 +888,11 @@ Normal keyboard characters, already shifted / capslocked / etc
|
|||||||
void CL_CharEvent( int key )
|
void CL_CharEvent( int key )
|
||||||
{
|
{
|
||||||
// the console key should never be used as a char
|
// the console key should never be used as a char
|
||||||
|
#if XASH_PSP
|
||||||
|
if( key == '`' || key == '~' || key == K_MODE_BUTTON ) return;
|
||||||
|
#else
|
||||||
if( key == '`' || key == '~' ) return;
|
if( key == '`' || key == '~' ) return;
|
||||||
|
#endif
|
||||||
|
|
||||||
if( cls.key_dest == key_console && !Con_Visible( ))
|
if( cls.key_dest == key_console && !Con_Visible( ))
|
||||||
{
|
{
|
||||||
@@ -1006,7 +1017,11 @@ static qboolean OSK_KeyEvent( int key, int down )
|
|||||||
|
|
||||||
if( osk.curbutton.val == 0 )
|
if( osk.curbutton.val == 0 )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
if( key == K_ENTER || key == K_A_BUTTON )
|
||||||
|
#else
|
||||||
if( key == K_ENTER )
|
if( key == K_ENTER )
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
osk.curbutton.val = osk_keylayout[osk.curlayout][osk.curbutton.y][osk.curbutton.x];
|
osk.curbutton.val = osk_keylayout[osk.curlayout][osk.curbutton.y][osk.curbutton.x];
|
||||||
return true;
|
return true;
|
||||||
@@ -1017,6 +1032,9 @@ static qboolean OSK_KeyEvent( int key, int down )
|
|||||||
|
|
||||||
switch ( key )
|
switch ( key )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
case K_A_BUTTON:
|
||||||
|
#endif
|
||||||
case K_ENTER:
|
case K_ENTER:
|
||||||
switch( osk.curbutton.val )
|
switch( osk.curbutton.val )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -323,6 +323,10 @@ static ref_api_t gEngfuncs =
|
|||||||
&clgame.drawFuncs,
|
&clgame.drawFuncs,
|
||||||
|
|
||||||
&g_fsapi,
|
&g_fsapi,
|
||||||
|
#if XASH_PSP
|
||||||
|
P5Ram_Alloc,
|
||||||
|
P5Ram_Free,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static void R_UnloadProgs( void )
|
static void R_UnloadProgs( void )
|
||||||
@@ -344,33 +348,8 @@ static void R_UnloadProgs( void )
|
|||||||
memset( &ref.dllFuncs, 0, sizeof( ref.dllFuncs ));
|
memset( &ref.dllFuncs, 0, sizeof( ref.dllFuncs ));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CL_FillTriAPIFromRef( triangleapi_t *dst, const ref_interface_t *src )
|
|
||||||
{
|
|
||||||
dst->version = TRI_API_VERSION;
|
|
||||||
dst->Begin = src->Begin;
|
|
||||||
dst->RenderMode = TriRenderMode;
|
|
||||||
dst->End = src->End;
|
|
||||||
dst->Color4f = TriColor4f;
|
|
||||||
dst->Color4ub = TriColor4ub;
|
|
||||||
dst->TexCoord2f = src->TexCoord2f;
|
|
||||||
dst->Vertex3f = src->Vertex3f;
|
|
||||||
dst->Vertex3fv = src->Vertex3fv;
|
|
||||||
dst->Brightness = TriBrightness;
|
|
||||||
dst->CullFace = TriCullFace;
|
|
||||||
dst->SpriteTexture = TriSpriteTexture;
|
|
||||||
dst->WorldToScreen = TriWorldToScreen;
|
|
||||||
dst->Fog = src->Fog;
|
|
||||||
dst->ScreenToWorld = src->ScreenToWorld;
|
|
||||||
dst->GetMatrix = src->GetMatrix;
|
|
||||||
dst->BoxInPVS = TriBoxInPVS;
|
|
||||||
dst->LightAtPoint = TriLightAtPoint;
|
|
||||||
dst->Color4fRendermode = TriColor4fRendermode;
|
|
||||||
dst->FogParams = src->FogParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean R_LoadProgs( const char *name )
|
static qboolean R_LoadProgs( const char *name )
|
||||||
{
|
{
|
||||||
extern triangleapi_t gTriApi;
|
|
||||||
static ref_api_t gpEngfuncs;
|
static ref_api_t gpEngfuncs;
|
||||||
REFAPI GetRefAPI; // single export
|
REFAPI GetRefAPI; // single export
|
||||||
|
|
||||||
@@ -415,12 +394,18 @@ static qboolean R_LoadProgs( const char *name )
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize TriAPI callbacks
|
||||||
|
if( !ref.dllFuncs.getTriAPI( TRI_API_VERSION, &gTriApi ))
|
||||||
|
{
|
||||||
|
COM_FreeLibrary( ref.hInstance );
|
||||||
|
Con_Reportf( "R_LoadProgs: can't init TriAPI Interface: wrong version, %i must be %i\n", gTriApi.version, TRI_API_VERSION );
|
||||||
|
ref.hInstance = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Cvar_FullSet( "host_refloaded", "1", FCVAR_READ_ONLY );
|
Cvar_FullSet( "host_refloaded", "1", FCVAR_READ_ONLY );
|
||||||
ref.initialized = true;
|
ref.initialized = true;
|
||||||
|
|
||||||
// initialize TriAPI callbacks
|
|
||||||
CL_FillTriAPIFromRef( &gTriApi, &ref.dllFuncs );
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,11 @@ GNU General Public License for more details.
|
|||||||
// than could actually be referenced during gameplay,
|
// than could actually be referenced during gameplay,
|
||||||
// because we don't want to free anything until we are
|
// because we don't want to free anything until we are
|
||||||
// sure we won't need it.
|
// sure we won't need it.
|
||||||
|
#if XASH_PSP
|
||||||
|
#define MAX_SFX 2048
|
||||||
|
#else
|
||||||
#define MAX_SFX 8192
|
#define MAX_SFX 8192
|
||||||
|
#endif
|
||||||
#define MAX_SFX_HASH (MAX_SFX/4)
|
#define MAX_SFX_HASH (MAX_SFX/4)
|
||||||
|
|
||||||
static int s_numSfx = 0;
|
static int s_numSfx = 0;
|
||||||
|
|||||||
@@ -201,9 +201,15 @@ typedef struct
|
|||||||
|
|
||||||
//====================================================================
|
//====================================================================
|
||||||
|
|
||||||
|
#if XASH_PSP
|
||||||
|
#define MAX_DYNAMIC_CHANNELS (20 + NUM_AMBIENTS)
|
||||||
|
#define MAX_CHANNELS (128 + MAX_DYNAMIC_CHANNELS)
|
||||||
|
#define MAX_RAW_CHANNELS 16
|
||||||
|
#else
|
||||||
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
|
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
|
||||||
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
|
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
|
||||||
#define MAX_RAW_CHANNELS 48
|
#define MAX_RAW_CHANNELS 48
|
||||||
|
#endif
|
||||||
#define MAX_RAW_SAMPLES 8192
|
#define MAX_RAW_SAMPLES 8192
|
||||||
|
|
||||||
extern sound_t ambient_sfx[NUM_AMBIENTS];
|
extern sound_t ambient_sfx[NUM_AMBIENTS];
|
||||||
|
|||||||
175
engine/common/build.c
Normal file
175
engine/common/build.c
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
build.c - returns a engine build number
|
||||||
|
Copyright (C) 2010 Uncle Mike
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
static char *date = __DATE__ ;
|
||||||
|
static char *mon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||||
|
static char mond[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||||
|
|
||||||
|
// returns days since Apr 1 2015
|
||||||
|
int Q_buildnum( void )
|
||||||
|
{
|
||||||
|
int m = 0, d = 0, y = 0;
|
||||||
|
static int b = 0;
|
||||||
|
|
||||||
|
if( b != 0 ) return b;
|
||||||
|
|
||||||
|
for( m = 0; m < 11; m++ )
|
||||||
|
{
|
||||||
|
if( !Q_strnicmp( &date[0], mon[m], 3 ))
|
||||||
|
break;
|
||||||
|
d += mond[m];
|
||||||
|
}
|
||||||
|
|
||||||
|
d += Q_atoi( &date[4] ) - 1;
|
||||||
|
y = Q_atoi( &date[7] ) - 1900;
|
||||||
|
b = d + (int)((y - 1) * 365.25f );
|
||||||
|
|
||||||
|
if((( y % 4 ) == 0 ) && m > 1 )
|
||||||
|
{
|
||||||
|
b += 1;
|
||||||
|
}
|
||||||
|
b -= 41728; // Apr 1 2015
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
Q_buildnum_compat
|
||||||
|
|
||||||
|
Returns a Xash3D build number. This is left for compability with original Xash3D.
|
||||||
|
IMPORTANT: this value must be changed ONLY after updating to newer Xash3D
|
||||||
|
IMPORTANT: this value must be acquired through "build" cvar.
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
int Q_buildnum_compat( void )
|
||||||
|
{
|
||||||
|
// do not touch this! Only author of Xash3D can increase buildnumbers!
|
||||||
|
return 4529;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
============
|
||||||
|
Q_buildos
|
||||||
|
|
||||||
|
Returns current name of operating system. Without any spaces.
|
||||||
|
============
|
||||||
|
*/
|
||||||
|
const char *Q_buildos( void )
|
||||||
|
{
|
||||||
|
const char *osname;
|
||||||
|
|
||||||
|
#if XASH_MINGW
|
||||||
|
osname = "win32-mingw";
|
||||||
|
#elif XASH_WIN32
|
||||||
|
osname = "win32";
|
||||||
|
#elif XASH_ANDROID
|
||||||
|
osname = "android";
|
||||||
|
#elif XASH_LINUX
|
||||||
|
osname = "linux";
|
||||||
|
#elif XASH_APPLE
|
||||||
|
osname = "apple";
|
||||||
|
#elif XASH_FREEBSD
|
||||||
|
osname = "freebsd";
|
||||||
|
#elif XASH_NETBSD
|
||||||
|
osname = "netbsd";
|
||||||
|
#elif XASH_OPENBSD
|
||||||
|
osname = "openbsd";
|
||||||
|
#elif XASH_EMSCRIPTEN
|
||||||
|
osname = "emscripten";
|
||||||
|
#elif XASH_DOS4GW
|
||||||
|
osname = "DOS4GW";
|
||||||
|
#elif XASH_PSP
|
||||||
|
osname = "psp";
|
||||||
|
#else
|
||||||
|
#error "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return osname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
============
|
||||||
|
Q_buildos
|
||||||
|
|
||||||
|
Returns current name of operating system. Without any spaces.
|
||||||
|
============
|
||||||
|
*/
|
||||||
|
const char *Q_buildarch( void )
|
||||||
|
{
|
||||||
|
const char *archname;
|
||||||
|
|
||||||
|
#if XASH_AMD64
|
||||||
|
archname = "amd64";
|
||||||
|
#elif XASH_X86
|
||||||
|
archname = "i386";
|
||||||
|
#elif XASH_ARM && XASH_64BIT
|
||||||
|
archname = "arm64";
|
||||||
|
#elif XASH_ARM
|
||||||
|
archname = "armv"
|
||||||
|
#if XASH_ARM == 8
|
||||||
|
"8_32" // for those who (mis)using 32-bit OS on 64-bit CPU
|
||||||
|
#elif XASH_ARM == 7
|
||||||
|
"7"
|
||||||
|
#elif XASH_ARM == 6
|
||||||
|
"6"
|
||||||
|
#elif XASH_ARM == 5
|
||||||
|
"5"
|
||||||
|
#elif XASH_ARM == 4
|
||||||
|
"4"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if XASH_ARM_HARDFP
|
||||||
|
"hf";
|
||||||
|
#else
|
||||||
|
"l";
|
||||||
|
#endif
|
||||||
|
#elif XASH_MIPS && defined XASH_BIG_ENDIAN
|
||||||
|
archname = "mips";
|
||||||
|
#elif XASH_MIPS && defined XASH_LITTLE_ENDIAN
|
||||||
|
archname = "mipsel";
|
||||||
|
#elif XASH_JS
|
||||||
|
archname = "javascript";
|
||||||
|
#elif XASH_E2K
|
||||||
|
archname = "e2k";
|
||||||
|
#else
|
||||||
|
#error "Place your architecture name here! If this is a mistake, try to fix conditions above and report a bug"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return archname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
Q_buildcommit
|
||||||
|
|
||||||
|
Returns a short hash of current commit in VCS as string.
|
||||||
|
XASH_BUILD_COMMIT must be passed in quotes
|
||||||
|
|
||||||
|
if XASH_BUILD_COMMIT is not defined,
|
||||||
|
Q_buildcommit will identify this build as "notset"
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
const char *Q_buildcommit( void )
|
||||||
|
{
|
||||||
|
#ifdef XASH_BUILD_COMMIT
|
||||||
|
return XASH_BUILD_COMMIT;
|
||||||
|
#else
|
||||||
|
return "notset";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
@@ -141,6 +141,7 @@ typedef enum
|
|||||||
#define MAX_DECALS 256 // touching TE_DECAL messages, etc
|
#define MAX_DECALS 256 // touching TE_DECAL messages, etc
|
||||||
#define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn
|
#define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define GameState (&host.game)
|
#define GameState (&host.game)
|
||||||
|
|
||||||
@@ -723,7 +724,6 @@ int R_CreateDecalList( struct decallist_s *pList );
|
|||||||
void R_ClearAllDecals( void );
|
void R_ClearAllDecals( void );
|
||||||
void CL_ClearStaticEntities( void );
|
void CL_ClearStaticEntities( void );
|
||||||
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position );
|
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position );
|
||||||
struct cl_entity_s *CL_GetEntityByIndex( int index );
|
|
||||||
void CL_ServerCommand( qboolean reliable, const char *fmt, ... ) _format( 2 );
|
void CL_ServerCommand( qboolean reliable, const char *fmt, ... ) _format( 2 );
|
||||||
void CL_HudMessage( const char *pMessage );
|
void CL_HudMessage( const char *pMessage );
|
||||||
const char *CL_MsgInfo( int cmd );
|
const char *CL_MsgInfo( int cmd );
|
||||||
|
|||||||
4556
engine/common/filesystem.c
Normal file
4556
engine/common/filesystem.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1064,10 +1064,10 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
|
|||||||
|
|
||||||
// init host state machine
|
// init host state machine
|
||||||
COM_InitHostState();
|
COM_InitHostState();
|
||||||
|
#ifdef XASH_HASHED_VARS
|
||||||
// init hashed commands
|
// init hashed commands
|
||||||
BaseCmd_Init();
|
BaseCmd_Init();
|
||||||
|
#endif
|
||||||
// startup cmds and cvars subsystem
|
// startup cmds and cvars subsystem
|
||||||
Cmd_Init();
|
Cmd_Init();
|
||||||
Cvar_Init();
|
Cvar_Init();
|
||||||
@@ -1110,6 +1110,8 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
|
|||||||
Sys_Error( "couldn't find xash3d data directory" );
|
Sys_Error( "couldn't find xash3d data directory" );
|
||||||
host.rootdir[0] = 0;
|
host.rootdir[0] = 0;
|
||||||
}
|
}
|
||||||
|
#elif XASH_PSP
|
||||||
|
COM_ExtractFilePath( argv[0], host.rootdir );
|
||||||
#elif (XASH_SDL == 2) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
|
#elif (XASH_SDL == 2) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
|
||||||
char *szBasePath = SDL_GetBasePath();
|
char *szBasePath = SDL_GetBasePath();
|
||||||
if( szBasePath )
|
if( szBasePath )
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ Image_LoadTGA
|
|||||||
*/
|
*/
|
||||||
qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesize )
|
qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesize )
|
||||||
{
|
{
|
||||||
int i, columns, rows, row_inc, row, col;
|
int i, columns, rows, row_inc, row, col, bpp = 1;
|
||||||
byte *buf_p, *pixbuf, *targa_rgba;
|
byte *buf_p, *pixbuf, *targa_rgba;
|
||||||
rgba_t palette[256];
|
rgba_t palette[256];
|
||||||
byte red = 0, green = 0, blue = 0, alpha = 0;
|
byte red = 0, green = 0, blue = 0, alpha = 0;
|
||||||
@@ -32,6 +32,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
|||||||
int reflectivity[3] = { 0, 0, 0 };
|
int reflectivity[3] = { 0, 0, 0 };
|
||||||
qboolean compressed;
|
qboolean compressed;
|
||||||
tga_t targa_header;
|
tga_t targa_header;
|
||||||
|
int palIndex = 0;
|
||||||
|
|
||||||
if( filesize < sizeof( tga_t ))
|
if( filesize < sizeof( tga_t ))
|
||||||
return false;
|
return false;
|
||||||
@@ -55,8 +56,6 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
|||||||
// check for tga file
|
// check for tga file
|
||||||
if( !Image_ValidSize( name )) return false;
|
if( !Image_ValidSize( name )) return false;
|
||||||
|
|
||||||
image.type = PF_RGBA_32; // always exctracted to 32-bit buffer
|
|
||||||
|
|
||||||
if( targa_header.image_type == 1 || targa_header.image_type == 9 )
|
if( targa_header.image_type == 1 || targa_header.image_type == 9 )
|
||||||
{
|
{
|
||||||
// uncompressed colormapped image
|
// uncompressed colormapped image
|
||||||
@@ -119,11 +118,35 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) Type %i not supported\n", name, targa_header.image_type );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
columns = targa_header.width;
|
columns = targa_header.width;
|
||||||
rows = targa_header.height;
|
rows = targa_header.height;
|
||||||
|
|
||||||
image.size = image.width * image.height * 4;
|
if( Image_CheckFlag( IL_KEEP_8BIT ) && ( targa_header.image_type == 1 || targa_header.image_type == 9 ))
|
||||||
|
{
|
||||||
|
pixbuf = image.palette = Mem_Malloc( host.imagepool, 1024 );
|
||||||
|
for( i = 0; i < targa_header.colormap_length; i++ )
|
||||||
|
{
|
||||||
|
*pixbuf++ = palette[i][0];
|
||||||
|
*pixbuf++ = palette[i][1];
|
||||||
|
*pixbuf++ = palette[i][2];
|
||||||
|
*pixbuf++ = palette[i][3];
|
||||||
|
}
|
||||||
|
image.type = PF_INDEXED_32;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
image.palette = NULL;
|
||||||
|
image.type = PF_RGBA_32;
|
||||||
|
bpp = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
image.size = image.width * image.height * bpp;
|
||||||
targa_rgba = image.rgba = Mem_Malloc( host.imagepool, image.size );
|
targa_rgba = image.rgba = Mem_Malloc( host.imagepool, image.size );
|
||||||
|
|
||||||
// if bit 5 of attributes isn't set, the image has been stored from bottom to top
|
// if bit 5 of attributes isn't set, the image has been stored from bottom to top
|
||||||
@@ -134,8 +157,8 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pixbuf = targa_rgba + ( rows - 1 ) * columns * 4;
|
pixbuf = targa_rgba + ( rows - 1 ) * columns * bpp;
|
||||||
row_inc = -columns * 4 * 2;
|
row_inc = -columns * bpp * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
compressed = ( targa_header.image_type == 9 || targa_header.image_type == 10 || targa_header.image_type == 11 );
|
compressed = ( targa_header.image_type == 9 || targa_header.image_type == 10 || targa_header.image_type == 11 );
|
||||||
@@ -161,13 +184,13 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
|||||||
case 1:
|
case 1:
|
||||||
case 9:
|
case 9:
|
||||||
// colormapped image
|
// colormapped image
|
||||||
blue = *buf_p++;
|
palIndex = *buf_p++;
|
||||||
if( blue < targa_header.colormap_length )
|
if( palIndex < targa_header.colormap_length )
|
||||||
{
|
{
|
||||||
red = palette[blue][0];
|
red = palette[palIndex][0];
|
||||||
green = palette[blue][1];
|
green = palette[palIndex][1];
|
||||||
alpha = palette[blue][3];
|
blue = palette[palIndex][2];
|
||||||
blue = palette[blue][2];
|
alpha = palette[palIndex][3];
|
||||||
if( alpha != 255 ) image.flags |= IMAGE_HAS_ALPHA;
|
if( alpha != 255 ) image.flags |= IMAGE_HAS_ALPHA;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -208,10 +231,18 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
|||||||
reflectivity[1] += green;
|
reflectivity[1] += green;
|
||||||
reflectivity[2] += blue;
|
reflectivity[2] += blue;
|
||||||
|
|
||||||
*pixbuf++ = red;
|
if( image.type == PF_INDEXED_32 || image.type == PF_INDEXED_24 )
|
||||||
*pixbuf++ = green;
|
{
|
||||||
*pixbuf++ = blue;
|
*pixbuf++ = palIndex;
|
||||||
*pixbuf++ = alpha;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*pixbuf++ = red;
|
||||||
|
*pixbuf++ = green;
|
||||||
|
*pixbuf++ = blue;
|
||||||
|
*pixbuf++ = alpha;
|
||||||
|
}
|
||||||
|
|
||||||
if( ++col == columns )
|
if( ++col == columns )
|
||||||
{
|
{
|
||||||
// run spans across rows
|
// run spans across rows
|
||||||
@@ -223,6 +254,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
|||||||
}
|
}
|
||||||
|
|
||||||
VectorDivide( reflectivity, ( image.width * image.height ), image.fogParams );
|
VectorDivide( reflectivity, ( image.width * image.height ), image.fogParams );
|
||||||
|
if( image.palette ) Image_GetPaletteBMP( image.palette );
|
||||||
image.depth = 1;
|
image.depth = 1;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -93,6 +93,23 @@ static const loadpixformat_t load_null[] =
|
|||||||
{ NULL, NULL, NULL, IL_HINT_NO }
|
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// a1ba: that's weird, better debug
|
||||||
|
#if XASH_PSP
|
||||||
|
static const loadpixformat_t load_game[] =
|
||||||
|
{
|
||||||
|
{ "%s%s.%s", "mip", Image_LoadMIP, IL_HINT_NO }, // hl textures from wad or buffer
|
||||||
|
{ "%s%s.%s", "mdl", Image_LoadMDL, IL_HINT_HL }, // hl studio model skins
|
||||||
|
{ "%s%s.%s", "spr", Image_LoadSPR, IL_HINT_HL }, // hl sprite frames
|
||||||
|
{ "%s%s.%s", "lmp", Image_LoadLMP, IL_HINT_NO }, // hl menu images (cached.wad etc)
|
||||||
|
{ "%s%s.%s", "fnt", Image_LoadFNT, IL_HINT_HL }, // hl console font (fonts.wad etc)
|
||||||
|
{ "%s%s.%s", "pal", Image_LoadPAL, IL_HINT_NO }, // install studio\sprite palette
|
||||||
|
{ "%s%s.%s", "dds", Image_LoadDDS, IL_HINT_NO }, // dds for world and studio models
|
||||||
|
{ "%s%s.%s", "tga", Image_LoadTGA, IL_HINT_NO }, // hl vgui menus
|
||||||
|
{ "%s%s.%s", "bmp", Image_LoadBMP, IL_HINT_NO }, // WON menu images
|
||||||
|
{ "%s%s.%s", "png", Image_LoadPNG, IL_HINT_NO }, // NightFire 007 menus
|
||||||
|
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||||
|
};
|
||||||
|
#else
|
||||||
static const loadpixformat_t load_game[] =
|
static const loadpixformat_t load_game[] =
|
||||||
{
|
{
|
||||||
{ "%s%s.%s", "dds", Image_LoadDDS, IL_HINT_NO }, // dds for world and studio models
|
{ "%s%s.%s", "dds", Image_LoadDDS, IL_HINT_NO }, // dds for world and studio models
|
||||||
@@ -108,7 +125,7 @@ static const loadpixformat_t load_game[] =
|
|||||||
{ "%s%s.%s", "ktx2", Image_LoadKTX2, IL_HINT_NO }, // ktx2 for world and studio models
|
{ "%s%s.%s", "ktx2", Image_LoadKTX2, IL_HINT_NO }, // ktx2 for world and studio models
|
||||||
{ NULL, NULL, NULL, IL_HINT_NO }
|
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
=============================================================================
|
=============================================================================
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,13 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
static char szGameDir[128]; // safe place to keep gamedir
|
static char szGameDir[128]; // safe place to keep gamedir
|
||||||
static int szArgc;
|
static int szArgc;
|
||||||
|
|
||||||
|
#if XASH_PSP
|
||||||
|
#define MAX_NARGVS 50
|
||||||
|
static char *szArgv[MAX_NARGVS];
|
||||||
|
#else
|
||||||
static char **szArgv;
|
static char **szArgv;
|
||||||
|
#endif
|
||||||
|
|
||||||
static void Sys_ChangeGame( const char *progname )
|
static void Sys_ChangeGame( const char *progname )
|
||||||
{
|
{
|
||||||
@@ -71,20 +77,23 @@ static int Sys_Start( void )
|
|||||||
#endif
|
#endif
|
||||||
#elif XASH_IOS
|
#elif XASH_IOS
|
||||||
IOS_LaunchDialog();
|
IOS_LaunchDialog();
|
||||||
#endif
|
#elif XASH_PSP
|
||||||
|
|
||||||
return Host_Main( szArgc, szArgv, game, 0, Sys_ChangeGame );
|
return Host_Main( szArgc, szArgv, game, 0, Sys_ChangeGame );
|
||||||
}
|
}
|
||||||
|
|
||||||
int main( int argc, char **argv )
|
int main( int argc, char **argv )
|
||||||
{
|
{
|
||||||
#if XASH_PSVITA
|
#if XASH_PSP
|
||||||
|
Platform_ReadCmd( "start.cmd", &szArgc, szArgv );
|
||||||
|
#elif XASH_PSVITA
|
||||||
// inject -dev -console into args if required
|
// inject -dev -console into args if required
|
||||||
szArgc = PSVita_GetArgv( argc, argv, &szArgv );
|
szArgc = PSVita_GetArgv( argc, argv, &szArgv );
|
||||||
#else
|
#else
|
||||||
szArgc = argc;
|
szArgc = argc;
|
||||||
szArgv = argv;
|
szArgv = argv;
|
||||||
#endif // XASH_PSVITA
|
#endif // XASH_PSVITA
|
||||||
|
|
||||||
return Sys_Start();
|
return Sys_Start();
|
||||||
}
|
}
|
||||||
#endif // XASH_ENABLE_MAIN
|
#endif // XASH_ENABLE_MAIN
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ void COM_PushLibraryError( const char *error )
|
|||||||
Q_strncat( s_szLastError, error, sizeof( s_szLastError ) );
|
Q_strncat( s_szLastError, error, sizeof( s_szLastError ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !XASH_PSP
|
||||||
void *COM_FunctionFromName_SR( void *hInstance, const char *pName )
|
void *COM_FunctionFromName_SR( void *hInstance, const char *pName )
|
||||||
{
|
{
|
||||||
char **funcs = NULL;
|
char **funcs = NULL;
|
||||||
@@ -85,6 +86,7 @@ const char *COM_OffsetNameForFunction( void *function )
|
|||||||
Con_Reportf( "COM_OffsetNameForFunction %s\n", sname );
|
Con_Reportf( "COM_OffsetNameForFunction %s\n", sname );
|
||||||
return sname;
|
return sname;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
|
dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
|
||||||
{
|
{
|
||||||
@@ -128,7 +130,7 @@ dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
|
|||||||
|
|
||||||
static void COM_GenerateCommonLibraryName( const char *name, const char *ext, char *out, size_t size )
|
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 );
|
Q_snprintf( out, size, "%s.%s", name, ext );
|
||||||
#elif ( XASH_WIN32 || XASH_LINUX || XASH_APPLE )
|
#elif ( XASH_WIN32 || XASH_LINUX || XASH_APPLE )
|
||||||
Q_snprintf( out, size, "%s_%s.%s", name, Q_buildarch(), ext );
|
Q_snprintf( out, size, "%s_%s.%s", name, Q_buildarch(), ext );
|
||||||
@@ -191,6 +193,8 @@ static void COM_GenerateServerLibraryPath( char *out, size_t size )
|
|||||||
Q_strncpy( out, GI->game_dll, size );
|
Q_strncpy( out, GI->game_dll, size );
|
||||||
#elif XASH_APPLE
|
#elif XASH_APPLE
|
||||||
Q_strncpy( out, GI->game_dll_osx, size );
|
Q_strncpy( out, GI->game_dll_osx, size );
|
||||||
|
#elif XASH_PSP
|
||||||
|
Q_strncpy( out, GI->game_dll_psp, size );
|
||||||
#else // XASH_LINUX
|
#else // XASH_LINUX
|
||||||
Q_strncpy( out, GI->game_dll_linux, size );
|
Q_strncpy( out, GI->game_dll_linux, size );
|
||||||
#endif
|
#endif
|
||||||
@@ -203,6 +207,8 @@ static void COM_GenerateServerLibraryPath( char *out, size_t size )
|
|||||||
Q_strncpy( dllpath, GI->game_dll, sizeof( dllpath ) );
|
Q_strncpy( dllpath, GI->game_dll, sizeof( dllpath ) );
|
||||||
#elif XASH_APPLE
|
#elif XASH_APPLE
|
||||||
Q_strncpy( dllpath, GI->game_dll_osx, sizeof( dllpath ) );
|
Q_strncpy( dllpath, GI->game_dll_osx, sizeof( dllpath ) );
|
||||||
|
#elif XASH_PSP
|
||||||
|
Q_strncpy( dllpath, GI->game_dll_psp, sizeof( dllpath ) );
|
||||||
#else // XASH_APPLE
|
#else // XASH_APPLE
|
||||||
Q_strncpy( dllpath, GI->game_dll_linux, sizeof( dllpath ) );
|
Q_strncpy( dllpath, GI->game_dll_linux, sizeof( dllpath ) );
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1735,12 +1735,16 @@ static void Mod_LoadSubmodels( model_t *mod, dbspmodel_t *bmod )
|
|||||||
oldmaxfaces = Q_max( oldmaxfaces, out->numfaces );
|
oldmaxfaces = Q_max( oldmaxfaces, out->numfaces );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if XASH_PSP
|
||||||
|
refState.max_surfaces = 0; // sorting disabled
|
||||||
|
#else
|
||||||
// these array used to sort translucent faces in bmodels
|
// these array used to sort translucent faces in bmodels
|
||||||
if( oldmaxfaces > refState.max_surfaces )
|
if( oldmaxfaces > refState.max_surfaces )
|
||||||
{
|
{
|
||||||
refState.draw_surfaces = (sortedface_t *)Z_Realloc( refState.draw_surfaces, oldmaxfaces * sizeof( sortedface_t ));
|
refState.draw_surfaces = (sortedface_t *)Z_Realloc( refState.draw_surfaces, oldmaxfaces * sizeof( sortedface_t ));
|
||||||
refState.max_surfaces = oldmaxfaces;
|
refState.max_surfaces = oldmaxfaces;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -151,17 +151,6 @@ void MSG_Clear( sizebuf_t *sb )
|
|||||||
sb->bOverflow = false;
|
sb->bOverflow = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static qboolean MSG_Overflow( sizebuf_t *sb, int nBits )
|
|
||||||
{
|
|
||||||
if( sb->iCurBit + nBits > sb->nDataBits )
|
|
||||||
sb->bOverflow = true;
|
|
||||||
return sb->bOverflow;
|
|
||||||
}
|
|
||||||
|
|
||||||
qboolean MSG_CheckOverflow( sizebuf_t *sb )
|
|
||||||
{
|
|
||||||
return MSG_Overflow( sb, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
int MSG_SeekToBit( sizebuf_t *sb, int bitPos, int whence )
|
int MSG_SeekToBit( sizebuf_t *sb, int bitPos, int whence )
|
||||||
{
|
{
|
||||||
@@ -193,17 +182,6 @@ void MSG_SeekToByte( sizebuf_t *sb, int bytePos )
|
|||||||
sb->iCurBit = bytePos << 3;
|
sb->iCurBit = bytePos << 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MSG_WriteOneBit( sizebuf_t *sb, int nValue )
|
|
||||||
{
|
|
||||||
if( !MSG_Overflow( sb, 1 ))
|
|
||||||
{
|
|
||||||
if( nValue ) sb->pData[sb->iCurBit>>3] |= BIT( sb->iCurBit & 7 );
|
|
||||||
else sb->pData[sb->iCurBit>>3] &= ~BIT( sb->iCurBit & 7 );
|
|
||||||
|
|
||||||
sb->iCurBit++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits )
|
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits )
|
||||||
{
|
{
|
||||||
Assert( numbits >= 0 && numbits <= 32 );
|
Assert( numbits >= 0 && numbits <= 32 );
|
||||||
|
|||||||
@@ -64,6 +64,19 @@ _inline int MSG_TellBit( sizebuf_t *sb ) { return sb->iCurBit; }
|
|||||||
_inline const char *MSG_GetName( sizebuf_t *sb ) { return sb->pDebugName; }
|
_inline const char *MSG_GetName( sizebuf_t *sb ) { return sb->pDebugName; }
|
||||||
qboolean MSG_CheckOverflow( sizebuf_t *sb );
|
qboolean MSG_CheckOverflow( sizebuf_t *sb );
|
||||||
|
|
||||||
|
static inline qboolean MSG_Overflow( sizebuf_t *sb, int nBits )
|
||||||
|
{
|
||||||
|
if( sb->iCurBit + nBits > sb->nDataBits )
|
||||||
|
sb->bOverflow = true;
|
||||||
|
return sb->bOverflow;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline MSG_CheckOverflow( sizebuf_t *sb )
|
||||||
|
{
|
||||||
|
return MSG_Overflow( sb, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if XASH_BIG_ENDIAN
|
#if XASH_BIG_ENDIAN
|
||||||
#define MSG_BigShort( x ) ( x )
|
#define MSG_BigShort( x ) ( x )
|
||||||
#else
|
#else
|
||||||
@@ -78,7 +91,16 @@ void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, in
|
|||||||
void MSG_Clear( sizebuf_t *sb );
|
void MSG_Clear( sizebuf_t *sb );
|
||||||
|
|
||||||
// Bit-write functions
|
// Bit-write functions
|
||||||
void MSG_WriteOneBit( sizebuf_t *sb, int nValue );
|
static inline void MSG_WriteOneBit( sizebuf_t *sb, int nValue )
|
||||||
|
{
|
||||||
|
if( likely( !MSG_Overflow( sb, 1 )))
|
||||||
|
{
|
||||||
|
if( nValue ) sb->pData[sb->iCurBit>>3] |= BIT( sb->iCurBit & 7 );
|
||||||
|
else sb->pData[sb->iCurBit>>3] &= ~BIT( sb->iCurBit & 7 );
|
||||||
|
|
||||||
|
sb->iCurBit++;
|
||||||
|
}
|
||||||
|
}
|
||||||
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits );
|
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits );
|
||||||
void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits );
|
void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits );
|
||||||
void MSG_WriteBitLong( sizebuf_t *sb, uint data, int numbits, qboolean bSigned );
|
void MSG_WriteBitLong( sizebuf_t *sb, uint data, int numbits, qboolean bSigned );
|
||||||
|
|||||||
@@ -1095,7 +1095,6 @@ int Delta_TestBaseline( entity_state_t *from, entity_state_t *to, qboolean playe
|
|||||||
if( from == NULL ) return 0;
|
if( from == NULL ) return 0;
|
||||||
return countBits;
|
return countBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( FBitSet( to->entityType, ENTITY_BEAM ))
|
if( FBitSet( to->entityType, ENTITY_BEAM ))
|
||||||
dt = Delta_FindStructByIndex( DT_CUSTOM_ENTITY_STATE_T );
|
dt = Delta_FindStructByIndex( DT_CUSTOM_ENTITY_STATE_T );
|
||||||
else if( player )
|
else if( player )
|
||||||
@@ -1793,7 +1792,6 @@ void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *
|
|||||||
numChanges++;
|
numChanges++;
|
||||||
}
|
}
|
||||||
else MSG_WriteOneBit( msg, 0 );
|
else MSG_WriteOneBit( msg, 0 );
|
||||||
|
|
||||||
if( FBitSet( to->entityType, ENTITY_BEAM ))
|
if( FBitSet( to->entityType, ENTITY_BEAM ))
|
||||||
{
|
{
|
||||||
dt = Delta_FindStructByIndex( DT_CUSTOM_ENTITY_STATE_T );
|
dt = Delta_FindStructByIndex( DT_CUSTOM_ENTITY_STATE_T );
|
||||||
@@ -1806,7 +1804,6 @@ void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *
|
|||||||
{
|
{
|
||||||
dt = Delta_FindStructByIndex( DT_ENTITY_STATE_T );
|
dt = Delta_FindStructByIndex( DT_ENTITY_STATE_T );
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert( dt && dt->bInitialized );
|
Assert( dt && dt->bInitialized );
|
||||||
|
|
||||||
pField = dt->pFields;
|
pField = dt->pFields;
|
||||||
@@ -1924,7 +1921,6 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state
|
|||||||
{
|
{
|
||||||
dt = Delta_FindStructByIndex( DT_ENTITY_STATE_T );
|
dt = Delta_FindStructByIndex( DT_ENTITY_STATE_T );
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert( dt && dt->bInitialized );
|
Assert( dt && dt->bInitialized );
|
||||||
|
|
||||||
pField = dt->pFields;
|
pField = dt->pFields;
|
||||||
|
|||||||
@@ -356,7 +356,7 @@ qboolean NET_GetHostByName( const char *hostname, int family, struct sockaddr_st
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !XASH_EMSCRIPTEN && !XASH_DOS4GW && !defined XASH_NO_ASYNC_NS_RESOLVE
|
#if !XASH_EMSCRIPTEN && !XASH_DOS4GW && !XASH_PSP && !defined XASH_NO_ASYNC_NS_RESOLVE
|
||||||
#define CAN_ASYNC_NS_RESOLVE
|
#define CAN_ASYNC_NS_RESOLVE
|
||||||
#endif // !XASH_EMSCRIPTEN && !XASH_DOS4GW && !defined XASH_NO_ASYNC_NS_RESOLVE
|
#endif // !XASH_EMSCRIPTEN && !XASH_DOS4GW && !defined XASH_NO_ASYNC_NS_RESOLVE
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,18 @@ GNU General Public License for more details.
|
|||||||
#define NETSPLIT_BACKUP 8
|
#define NETSPLIT_BACKUP 8
|
||||||
#define NETSPLIT_BACKUP_MASK (NETSPLIT_BACKUP - 1)
|
#define NETSPLIT_BACKUP_MASK (NETSPLIT_BACKUP - 1)
|
||||||
#define NETSPLIT_HEADER_SIZE 18
|
#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
|
#if XASH_LOW_MEMORY == 2
|
||||||
#undef MULTIPLAYER_BACKUP
|
#undef MULTIPLAYER_BACKUP
|
||||||
#undef SINGLEPLAYER_BACKUP
|
#undef SINGLEPLAYER_BACKUP
|
||||||
@@ -108,7 +119,7 @@ GNU General Public License for more details.
|
|||||||
#define MAX_CUSTOM_BASELINES 8
|
#define MAX_CUSTOM_BASELINES 8
|
||||||
#define NET_MAX_FRAGMENT 32768
|
#define NET_MAX_FRAGMENT 32768
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* XASH_PSP */
|
||||||
typedef struct netsplit_chain_packet_s
|
typedef struct netsplit_chain_packet_s
|
||||||
{
|
{
|
||||||
// bool vector
|
// bool vector
|
||||||
|
|||||||
@@ -177,6 +177,29 @@ GNU General Public License for more details.
|
|||||||
#define FRAGMENT_MAX_SIZE 64000 // maximal fragment size
|
#define FRAGMENT_MAX_SIZE 64000 // maximal fragment size
|
||||||
#define FRAGMENT_LOCAL_SIZE FRAGMENT_MAX_SIZE // local connection
|
#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
|
#if XASH_LOW_MEMORY == 2
|
||||||
#undef MAX_VISIBLE_PACKET
|
#undef MAX_VISIBLE_PACKET
|
||||||
#undef MAX_VISIBLE_PACKET_VIS_BYTES
|
#undef MAX_VISIBLE_PACKET_VIS_BYTES
|
||||||
@@ -215,7 +238,7 @@ GNU General Public License for more details.
|
|||||||
#define MAX_RENDER_DECALS 128
|
#define MAX_RENDER_DECALS 128
|
||||||
#define MAX_RESOURCES 1024
|
#define MAX_RESOURCES 1024
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* XASH_PSP */
|
||||||
// Quake1 Protocol
|
// Quake1 Protocol
|
||||||
#define PROTOCOL_VERSION_QUAKE 15
|
#define PROTOCOL_VERSION_QUAKE 15
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size )
|
|||||||
fs_offset_t filesize = 0;
|
fs_offset_t filesize = 0;
|
||||||
const loadwavfmt_t *format;
|
const loadwavfmt_t *format;
|
||||||
byte *f;
|
byte *f;
|
||||||
|
|
||||||
Sound_Reset(); // clear old sounddata
|
Sound_Reset(); // clear old sounddata
|
||||||
Q_strncpy( loadname, filename, sizeof( loadname ));
|
Q_strncpy( loadname, filename, sizeof( loadname ));
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "soundlib.h"
|
#include "soundlib.h"
|
||||||
|
#if !XASH_PSP
|
||||||
#include "libmpg/libmpg.h"
|
#include "libmpg/libmpg.h"
|
||||||
|
|
||||||
#pragma pack( push, 1 )
|
#pragma pack( push, 1 )
|
||||||
@@ -455,3 +455,485 @@ void Stream_FreeMPG( stream_t *stream )
|
|||||||
|
|
||||||
Mem_Free( stream );
|
Mem_Free( stream );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else // XASH_PSP
|
||||||
|
#include "platform/psp/scemp3/pspmp3.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================================================================
|
||||||
|
|
||||||
|
PSP MPEG decoding
|
||||||
|
|
||||||
|
=================================================================
|
||||||
|
*/
|
||||||
|
#define MP3_ID3V1_ID "TAG"
|
||||||
|
#define MP3_ID3V1_ID_SZ 3
|
||||||
|
#define MP3_ID3V1_SZ 128
|
||||||
|
|
||||||
|
#define MP3_ID3V2_ID "ID3"
|
||||||
|
#define MP3_ID3V2_ID_SZ 3
|
||||||
|
#define MP3_ID3V2_SIZE_OFF 6
|
||||||
|
#define MP3_ID3V2_SIZE_SZ 4
|
||||||
|
#define MP3_ID3V2_HEADER_SZ 10
|
||||||
|
|
||||||
|
#define MP3_ERRORS_MAX 3
|
||||||
|
|
||||||
|
#define PCM_WIDTH 2 // always 16-bit PCM
|
||||||
|
#define PCM_CHANNELS 2 // always 2
|
||||||
|
|
||||||
|
#define MP3_BUFFER_SIZE ( 128 * 1024 )
|
||||||
|
#define PCM_BUFFER_SIZE (( 1152 * PCM_WIDTH * PCM_CHANNELS ) * 2 ) // framesample * width * channels * 2(double buffer)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int handle;
|
||||||
|
int cachePos;
|
||||||
|
int frameCount;
|
||||||
|
byte *pcmTempPtr;
|
||||||
|
} mp3_decoder_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
Sound_GetID3V2SizeMPG
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
__inline int Sound_GetID3V2SizeMPG( const byte *tagSize )
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
byte *sizePtr = (byte*)&size;
|
||||||
|
|
||||||
|
// 7 bit per byte, invert endian
|
||||||
|
sizePtr[0] = (( tagSize[3] >> 0 ) & 0x7F ) | (( tagSize[2] & 0x01 ) << 7 );
|
||||||
|
sizePtr[1] = (( tagSize[2] >> 1 ) & 0x3F ) | (( tagSize[1] & 0x03 ) << 6 );
|
||||||
|
sizePtr[2] = (( tagSize[1] >> 2 ) & 0x1F ) | (( tagSize[0] & 0x07 ) << 5 );
|
||||||
|
sizePtr[3] = (( tagSize[0] >> 3 ) & 0x0F );
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
Sound_FindHeadMPG
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
fs_offset_t Sound_FindHeadMPG( const byte *buffer, fs_offset_t filesize )
|
||||||
|
{
|
||||||
|
fs_offset_t result;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
if( filesize >= MP3_ID3V2_HEADER_SZ )
|
||||||
|
{
|
||||||
|
if( !memcmp( buffer, MP3_ID3V2_ID, MP3_ID3V2_ID_SZ ))
|
||||||
|
result = Sound_GetID3V2SizeMPG( &buffer[MP3_ID3V2_SIZE_OFF] ) + MP3_ID3V2_HEADER_SZ;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
Sound_FindTailMPG
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
fs_offset_t Sound_FindTailMPG( const byte *buffer, fs_offset_t filesize )
|
||||||
|
{
|
||||||
|
fs_offset_t result;
|
||||||
|
|
||||||
|
result = filesize;
|
||||||
|
if( filesize >= MP3_ID3V1_SZ )
|
||||||
|
{
|
||||||
|
if( !memcmp( &buffer[filesize - MP3_ID3V1_SZ], MP3_ID3V1_ID, MP3_ID3V1_ID_SZ ))
|
||||||
|
result -= MP3_ID3V1_SZ;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
qboolean Sound_LoadMPG( const char *name, const byte *buffer, fs_offset_t filesize )
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
int status;
|
||||||
|
int handle;
|
||||||
|
size_t bytesWrite = 0;
|
||||||
|
byte out[PCM_BUFFER_SIZE] __attribute__((aligned(64)));
|
||||||
|
fs_offset_t headOffset;
|
||||||
|
fs_offset_t tailOffset;
|
||||||
|
fs_offset_t contentSize;
|
||||||
|
int frameSample;
|
||||||
|
uint bps;
|
||||||
|
int frameLen;
|
||||||
|
int frameSize;
|
||||||
|
int frameCount;
|
||||||
|
|
||||||
|
headOffset = Sound_FindHeadMPG( buffer, filesize );
|
||||||
|
tailOffset = Sound_FindTailMPG( buffer, filesize );
|
||||||
|
contentSize = tailOffset - headOffset;
|
||||||
|
// TODO: read Xing header
|
||||||
|
|
||||||
|
handle = sceMp3ReserveMp3Handle( NULL );
|
||||||
|
if ( handle < 0 )
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "sceMp3ReserveMp3Handle returned 0x%08X\n", handle );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = sceMp3LowLevelInit( handle, &buffer[headOffset] );
|
||||||
|
if ( status < 0 )
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "sceMp3LowLevelInit returned 0x%08X\n", status );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
frameSample = sceMp3GetMaxOutputSample( handle );
|
||||||
|
frameSize = (( frameSample / 8 ) * sceMp3GetBitRate( handle ) * 1000 ) / sceMp3GetSamplingRate( handle );
|
||||||
|
frameCount = contentSize / frameSize;
|
||||||
|
|
||||||
|
sound.channels = sceMp3GetMp3ChannelNum( handle );
|
||||||
|
sound.rate = sceMp3GetSamplingRate( handle );
|
||||||
|
sound.width = PCM_WIDTH; // always 16-bit PCM
|
||||||
|
sound.loopstart = -1;
|
||||||
|
sound.size = (frameCount * frameSample) * sound.channels * sound.width; // invalid for VBR
|
||||||
|
/*
|
||||||
|
status = sceMp3LowLevelDecode(handle, &buffer[headOffset + mp3usedsize], &mp3usedsize, pcm, &pcmoutsize);
|
||||||
|
if(status < 0)
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "sceMp3LowLevelDecode returned 0x%08X\n", status);
|
||||||
|
}
|
||||||
|
sceMp3ReleaseMp3Handle( handle );
|
||||||
|
*/
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
Con_DPrintf( S_ERROR "Sound_LoadMPG unimplemented function!\n");
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
Stream_FindHeadMPG
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
SceOff Stream_FindHeadMPG( file_t *file )
|
||||||
|
{
|
||||||
|
SceOff result;
|
||||||
|
byte tagId[MP3_ID3V2_ID_SZ];
|
||||||
|
byte tagSize[MP3_ID3V2_SIZE_SZ];
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
FS_Seek( file, 0, SEEK_SET );
|
||||||
|
|
||||||
|
if( FS_Read( file, tagId, MP3_ID3V2_ID_SZ) < MP3_ID3V2_ID_SZ )
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "Sound_Mp3FindHead: ID3V2 ID read error\n");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !memcmp( tagId, MP3_ID3V2_ID, MP3_ID3V2_ID_SZ ))
|
||||||
|
{
|
||||||
|
FS_Seek( file, MP3_ID3V2_SIZE_OFF, SEEK_SET );
|
||||||
|
if( FS_Read( file, tagSize, MP3_ID3V2_SIZE_SZ ) < MP3_ID3V2_SIZE_SZ )
|
||||||
|
Con_DPrintf( S_ERROR "Sound_Mp3FindHead: ID3V2 SIZE read error\n");
|
||||||
|
else result = Sound_GetID3V2SizeMPG( tagSize ) + MP3_ID3V2_HEADER_SZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
Stream_FindTailMPG
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
SceOff Stream_FindTailMPG( file_t *file )
|
||||||
|
{
|
||||||
|
SceOff result;
|
||||||
|
byte tagId[MP3_ID3V1_ID_SZ];
|
||||||
|
|
||||||
|
result = FS_FileLength( file );
|
||||||
|
|
||||||
|
FS_Seek( file, result - MP3_ID3V1_SZ, SEEK_SET );
|
||||||
|
|
||||||
|
if( FS_Read( file, tagId, MP3_ID3V1_ID_SZ ) < MP3_ID3V1_ID_SZ )
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "Sound_Mp3FindTail: ID3V1 ID read error\n");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !memcmp( tagId, MP3_ID3V1_ID, MP3_ID3V1_ID_SZ ))
|
||||||
|
result -= MP3_ID3V1_SZ;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
Stream_FillBufferMPG
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
int Stream_FillBufferMPG( file_t *file, mp3_decoder_t *desc )
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
byte *dstPtr;
|
||||||
|
int dstSize;
|
||||||
|
int dstPos;
|
||||||
|
fs_offset_t readSize;
|
||||||
|
|
||||||
|
if( sceMp3CheckStreamDataNeeded( desc->handle ) <= 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// get Info on the stream (where to fill to, how much to fill, where to fill from)
|
||||||
|
status = sceMp3GetInfoToAddStreamData( desc->handle, &dstPtr, &dstSize, &dstPos );
|
||||||
|
if( status < 0 )
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "sceMp3GetInfoToAddStreamData returned 0x%08X\n", status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// seek file to position requested
|
||||||
|
if( desc->cachePos != dstPos )
|
||||||
|
{
|
||||||
|
FS_Seek( file, dstPos, SEEK_SET );
|
||||||
|
desc->cachePos = dstPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the amount of data
|
||||||
|
readSize = FS_Read( file, dstPtr, dstSize );
|
||||||
|
desc->cachePos += ( int )readSize;
|
||||||
|
|
||||||
|
// notify mp3 library about how much we really wrote to the stream buffer
|
||||||
|
status = sceMp3NotifyAddStreamData( desc->handle, ( int )readSize );
|
||||||
|
if ( status < 0 )
|
||||||
|
Con_DPrintf( S_ERROR "sceMp3NotifyAddStreamData returned 0x%08X\n", status);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
Stream_OpenMPG
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
stream_t *Stream_OpenMPG( const char *filename )
|
||||||
|
{
|
||||||
|
stream_t *stream;
|
||||||
|
mp3_decoder_t *desc;
|
||||||
|
file_t *file;
|
||||||
|
int status;
|
||||||
|
void *bufferBase;
|
||||||
|
|
||||||
|
file = FS_Open( filename, "rbh", false ); // hold mode
|
||||||
|
if( !file ) return NULL;
|
||||||
|
|
||||||
|
// at this point we have valid stream
|
||||||
|
stream = Mem_Calloc( host.soundpool, sizeof( stream_t ));
|
||||||
|
stream->file = file;
|
||||||
|
stream->pos = 0;
|
||||||
|
|
||||||
|
desc = Mem_Calloc( host.soundpool, sizeof( mp3_decoder_t ) + MP3_BUFFER_SIZE + PCM_BUFFER_SIZE + 63 );
|
||||||
|
bufferBase = (void *)(((( uintptr_t )desc + sizeof( mp3_decoder_t )) & (~( 64 - 1 ))) + 64 );
|
||||||
|
|
||||||
|
// reserve a mp3 handle
|
||||||
|
SceMp3InitArg mp3Init;
|
||||||
|
mp3Init.mp3StreamStart = Stream_FindHeadMPG( file );
|
||||||
|
mp3Init.mp3StreamEnd = Stream_FindTailMPG( file );
|
||||||
|
mp3Init.mp3Buf = bufferBase;
|
||||||
|
mp3Init.mp3BufSize = MP3_BUFFER_SIZE;
|
||||||
|
mp3Init.pcmBuf = (void *)(( uintptr_t )bufferBase + MP3_BUFFER_SIZE );
|
||||||
|
mp3Init.pcmBufSize = PCM_BUFFER_SIZE;
|
||||||
|
|
||||||
|
desc->cachePos = 0;
|
||||||
|
desc->pcmTempPtr = mp3Init.pcmBuf;
|
||||||
|
desc->handle = sceMp3ReserveMp3Handle( &mp3Init );
|
||||||
|
if ( desc->handle < 0 )
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "sceMp3ReserveMp3Handle returned 0x%08X\n", desc->handle );
|
||||||
|
Mem_Free( stream );
|
||||||
|
Mem_Free( desc );
|
||||||
|
FS_Close( file );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the stream buffer with some data so that sceMp3Init has something to work with
|
||||||
|
if( Stream_FillBufferMPG( file, desc ) != 0 )
|
||||||
|
{
|
||||||
|
Mem_Free( stream );
|
||||||
|
Mem_Free( desc );
|
||||||
|
FS_Close( file );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = sceMp3Init( desc->handle );
|
||||||
|
if ( status < 0 )
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "sceMp3Init returned 0x%08X\n", status );
|
||||||
|
Mem_Free( stream );
|
||||||
|
Mem_Free( desc );
|
||||||
|
FS_Close( file );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc->frameCount = sceMp3GetFrameNum( desc->handle );
|
||||||
|
|
||||||
|
stream->buffsize = 0; // how many samples left from previous frame
|
||||||
|
stream->channels = PCM_CHANNELS; // always 2 PCM channels
|
||||||
|
stream->rate = sceMp3GetSamplingRate( desc->handle );
|
||||||
|
stream->width = PCM_WIDTH; // always 16 bit PCM
|
||||||
|
stream->ptr = (void *)desc;
|
||||||
|
stream->type = WF_MPGDATA;
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
Stream_ReadMPG
|
||||||
|
|
||||||
|
assume stream is valid
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
int Stream_ReadMPG( stream_t *stream, int needBytes, void *buffer )
|
||||||
|
{
|
||||||
|
// buffer handling
|
||||||
|
int bytesWritten = 0;
|
||||||
|
mp3_decoder_t *desc;
|
||||||
|
int errdec;
|
||||||
|
|
||||||
|
desc = ( mp3_decoder_t* )stream->ptr;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
byte *data;
|
||||||
|
int outsize;
|
||||||
|
|
||||||
|
if( !stream->buffsize )
|
||||||
|
{
|
||||||
|
// Check if we need to fill our stream buffer
|
||||||
|
if( Stream_FillBufferMPG( stream->file, desc ) != 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for( errdec = 0; errdec < MP3_ERRORS_MAX; errdec++ )
|
||||||
|
{
|
||||||
|
stream->pos = sceMp3Decode( desc->handle, (SceShort16**)&desc->pcmTempPtr );
|
||||||
|
if(( int )stream->pos >= 0 ) // decoding successful
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if( stream->pos == 0x80671402 ) // next frame header
|
||||||
|
{
|
||||||
|
if( Stream_FillBufferMPG( stream->file, desc ) != 0 )
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(( int )stream->pos < 0 )
|
||||||
|
{
|
||||||
|
if( stream->pos != 0x80671402 )
|
||||||
|
Con_DPrintf( S_ERROR "sceMp3Decode returned 0x%08X\n", stream->pos );
|
||||||
|
return 0; // ???
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check remaining size
|
||||||
|
if( bytesWritten + stream->pos > needBytes )
|
||||||
|
outsize = ( needBytes - bytesWritten );
|
||||||
|
else outsize = stream->pos;
|
||||||
|
|
||||||
|
// copy raw sample to output buffer
|
||||||
|
data = (byte *)buffer + bytesWritten;
|
||||||
|
memcpy( data, &desc->pcmTempPtr[stream->buffsize], outsize );
|
||||||
|
bytesWritten += outsize;
|
||||||
|
stream->pos -= outsize;
|
||||||
|
stream->buffsize += outsize;
|
||||||
|
|
||||||
|
// continue from this sample on a next call
|
||||||
|
if( bytesWritten >= needBytes )
|
||||||
|
return bytesWritten;
|
||||||
|
|
||||||
|
stream->buffsize = 0; // no bytes remaining
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
Stream_SetPosMPG
|
||||||
|
|
||||||
|
assume stream is valid
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
int Stream_SetPosMPG( stream_t *stream, int newpos )
|
||||||
|
{
|
||||||
|
mp3_decoder_t *desc;
|
||||||
|
int frame;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
desc = ( mp3_decoder_t* )stream->ptr;
|
||||||
|
|
||||||
|
// get frame num
|
||||||
|
frame = newpos / sceMp3GetMaxOutputSample( desc->handle ); // VBR?
|
||||||
|
|
||||||
|
if( frame < 1 || frame >= desc->frameCount - 1 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
status = sceMp3ResetPlayPositionByFrame( desc->handle, frame );
|
||||||
|
if( status < 0 )
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "sceMp3ResetPlayPositionByFrame returned 0x%08X\n", status );
|
||||||
|
|
||||||
|
// failed to seek for some reasons
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// flush any previous data
|
||||||
|
stream->buffsize = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
Stream_GetPosMPG
|
||||||
|
|
||||||
|
assume stream is valid
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
int Stream_GetPosMPG( stream_t *stream )
|
||||||
|
{
|
||||||
|
mp3_decoder_t *desc;
|
||||||
|
|
||||||
|
desc = ( mp3_decoder_t * )stream->ptr;
|
||||||
|
|
||||||
|
return sceMp3GetSumDecodedSample( desc->handle );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
Stream_FreeMPG
|
||||||
|
|
||||||
|
assume stream is valid
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void Stream_FreeMPG( stream_t *stream )
|
||||||
|
{
|
||||||
|
mp3_decoder_t *desc;
|
||||||
|
|
||||||
|
desc = ( mp3_decoder_t * )stream->ptr;
|
||||||
|
if( desc )
|
||||||
|
{
|
||||||
|
sceMp3ReleaseMp3Handle( desc->handle );
|
||||||
|
Mem_Free( desc );
|
||||||
|
stream->ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( stream->file )
|
||||||
|
{
|
||||||
|
FS_Close( stream->file );
|
||||||
|
stream->file = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mem_Free( stream );
|
||||||
|
}
|
||||||
|
#endif // XASH_PSP
|
||||||
|
|||||||
@@ -331,7 +331,8 @@ stream_t *Stream_OpenWAV( const char *filename )
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// open
|
// open
|
||||||
file = FS_Open( filename, "rb", false );
|
// h - hold mode
|
||||||
|
file = FS_Open( filename, "rbh", false );
|
||||||
if( !file ) return NULL;
|
if( !file ) return NULL;
|
||||||
|
|
||||||
// find "RIFF" chunk
|
// find "RIFF" chunk
|
||||||
|
|||||||
@@ -74,7 +74,9 @@ struct stream_s
|
|||||||
|
|
||||||
// current stream state
|
// current stream state
|
||||||
void *ptr; // internal decoder state
|
void *ptr; // internal decoder state
|
||||||
|
#if !XASH_PSP
|
||||||
char temp[OUTBUF_SIZE]; // mpeg decoder stuff
|
char temp[OUTBUF_SIZE]; // mpeg decoder stuff
|
||||||
|
#endif
|
||||||
size_t pos; // actual track position (or actual buffer remains)
|
size_t pos; // actual track position (or actual buffer remains)
|
||||||
int buffsize; // cached buffer size
|
int buffsize; // cached buffer size
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ GNU General Public License for more details.
|
|||||||
#include <vitasdk.h>
|
#include <vitasdk.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if XASH_PSP
|
||||||
|
#include <pspkernel.h>
|
||||||
|
#include <psputility_sysparam.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "menu_int.h" // _UPDATE_PAGE macro
|
#include "menu_int.h" // _UPDATE_PAGE macro
|
||||||
|
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
@@ -144,6 +149,10 @@ const char *Sys_GetCurrentUser( void )
|
|||||||
|
|
||||||
if( pw )
|
if( pw )
|
||||||
return pw->pw_name;
|
return pw->pw_name;
|
||||||
|
#elif XASH_PSP
|
||||||
|
static string s_userName;
|
||||||
|
if( sceUtilityGetSystemParamString( PSP_SYSTEMPARAM_ID_STRING_NICKNAME, s_userName, sizeof( s_userName )) == 0 )
|
||||||
|
return s_userName;
|
||||||
#endif
|
#endif
|
||||||
return "Player";
|
return "Player";
|
||||||
}
|
}
|
||||||
@@ -485,7 +494,12 @@ Sys_Quit
|
|||||||
void Sys_Quit( void )
|
void Sys_Quit( void )
|
||||||
{
|
{
|
||||||
Host_Shutdown();
|
Host_Shutdown();
|
||||||
|
#if XASH_PSP
|
||||||
|
sceKernelDelayThread( 50 * 1000 );
|
||||||
|
sceKernelExitGame();
|
||||||
|
#else
|
||||||
exit( error_on_exit );
|
exit( error_on_exit );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -58,6 +58,15 @@ void SDLash_Init( void );
|
|||||||
void SDLash_Shutdown( void );
|
void SDLash_Shutdown( void );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if XASH_PSP
|
||||||
|
void Platform_ReadCmd( const char *fname, int *argc, char **argv );
|
||||||
|
SceUID Platform_LoadModule( const char *filename, int mpid, SceSize argsize, void *argp );
|
||||||
|
int Platform_UnloadModule( SceUID modid, int *sce_code );
|
||||||
|
|
||||||
|
#include "psp/p5ram_psp.h"
|
||||||
|
#include "psp/fsh_psp.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if XASH_ANDROID
|
#if XASH_ANDROID
|
||||||
const char *Android_GetAndroidID( void );
|
const char *Android_GetAndroidID( void );
|
||||||
const char *Android_LoadID( void );
|
const char *Android_LoadID( void );
|
||||||
|
|||||||
410
engine/platform/psp/fsh_psp.c
Normal file
410
engine/platform/psp/fsh_psp.c
Normal file
@@ -0,0 +1,410 @@
|
|||||||
|
/*
|
||||||
|
fsh_psp.c - PSP filesystem helper
|
||||||
|
Copyright (C) 2022 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#include <pspiofilemgr.h>
|
||||||
|
#include "common.h"
|
||||||
|
#include "fsh_psp.h"
|
||||||
|
|
||||||
|
#define FSH_MAX_PATH 64
|
||||||
|
#define FSH_EMPTY_STRING "*empty*"
|
||||||
|
|
||||||
|
typedef struct fsh_path_s
|
||||||
|
{
|
||||||
|
char path[FSH_MAX_PATH];
|
||||||
|
int fsize;
|
||||||
|
uint hashvalue;
|
||||||
|
struct fsh_path_s *nexthash;
|
||||||
|
}fsh_path_t;
|
||||||
|
|
||||||
|
typedef struct fsh_handle_s
|
||||||
|
{
|
||||||
|
qboolean ready;
|
||||||
|
int count;
|
||||||
|
char folderpath[PATH_MAX];
|
||||||
|
int folderpath_size;
|
||||||
|
uint empty_hash;
|
||||||
|
int pathlist_size;
|
||||||
|
int hashlist_size;
|
||||||
|
fsh_path_t *pathlist;
|
||||||
|
fsh_path_t **hashlist;
|
||||||
|
struct fsh_handle_s *next;
|
||||||
|
}fsh_handle_t;
|
||||||
|
|
||||||
|
static fsh_handle_t *fsh_poolchain = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
FSH_AddHash
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
_inline void FSH_AddHash( fsh_path_t **hashlist, uint hash, fsh_path_t *fptr )
|
||||||
|
{
|
||||||
|
fptr->hashvalue = hash;
|
||||||
|
fptr->nexthash = hashlist[hash];
|
||||||
|
hashlist[hash] = fptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
FSH_RemoveHash
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
_inline void FSH_RemoveHash( fsh_path_t **hashlist, uint hash, fsh_path_t *fptr )
|
||||||
|
{
|
||||||
|
fsh_path_t **fptr_prev;
|
||||||
|
|
||||||
|
for( fptr_prev = &hashlist[hash]; *fptr_prev != NULL; fptr_prev = &( *fptr_prev )->nexthash )
|
||||||
|
{
|
||||||
|
if( *fptr_prev == fptr )
|
||||||
|
{
|
||||||
|
*fptr_prev = fptr->nexthash;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
FSH_AddFilePath
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
int FSH_AddFilePathWs( fsh_handle_t *handle, const char *path, int size )
|
||||||
|
{
|
||||||
|
uint hash;
|
||||||
|
fsh_path_t *fptr;
|
||||||
|
const char *strip_path;
|
||||||
|
|
||||||
|
if( !handle )
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
if( Q_strnicmp( path, handle->folderpath, handle->folderpath_size ))
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
strip_path = path + handle->folderpath_size + 1; // + '/'
|
||||||
|
|
||||||
|
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||||
|
|
||||||
|
if( handle->ready && handle->count > 0 )
|
||||||
|
{
|
||||||
|
// see if already added
|
||||||
|
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||||
|
{
|
||||||
|
if( !Q_stricmp( fptr->path, strip_path ))
|
||||||
|
return fptr - handle->pathlist; // index
|
||||||
|
}
|
||||||
|
|
||||||
|
// find empty
|
||||||
|
for( fptr = handle->hashlist[handle->empty_hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||||
|
{
|
||||||
|
if( !Q_stricmp( fptr->path, FSH_EMPTY_STRING ))
|
||||||
|
{
|
||||||
|
Q_strncpy( fptr->path, strip_path, FSH_MAX_PATH - 1 );
|
||||||
|
|
||||||
|
// file size
|
||||||
|
fptr->fsize = size;
|
||||||
|
|
||||||
|
// remove empty from hash table
|
||||||
|
FSH_RemoveHash( handle->hashlist, handle->empty_hash, fptr );
|
||||||
|
|
||||||
|
// add to hash table
|
||||||
|
FSH_AddHash( handle->hashlist, hash, fptr );
|
||||||
|
|
||||||
|
return fptr - handle->pathlist; // index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create new
|
||||||
|
if( handle->count + 1 >= handle->pathlist_size )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
fptr = &handle->pathlist[handle->count];
|
||||||
|
Q_strncpy( fptr->path, strip_path, FSH_MAX_PATH - 1 );
|
||||||
|
|
||||||
|
// file size
|
||||||
|
fptr->fsize = size;
|
||||||
|
|
||||||
|
// add to hash table
|
||||||
|
FSH_AddHash( handle->hashlist, hash, fptr );
|
||||||
|
|
||||||
|
handle->count++;
|
||||||
|
|
||||||
|
return fptr - handle->pathlist; // index
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
FSH_RemoveFilePath
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
int FSH_RemoveFilePath( fsh_handle_t *handle, const char *path )
|
||||||
|
{
|
||||||
|
uint hash;
|
||||||
|
fsh_path_t *fptr, **fptr_prev;
|
||||||
|
const char *strip_path;
|
||||||
|
|
||||||
|
if( !handle )
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
if( Q_strnicmp( path, handle->folderpath, handle->folderpath_size ))
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
strip_path = path + handle->folderpath_size + 1; // + '/'
|
||||||
|
|
||||||
|
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||||
|
|
||||||
|
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||||
|
{
|
||||||
|
if( !Q_stricmp( fptr->path, strip_path ))
|
||||||
|
{
|
||||||
|
memset( fptr->path, 0, FSH_MAX_PATH );
|
||||||
|
Q_strncpy( fptr->path, FSH_EMPTY_STRING, FSH_MAX_PATH - 1 );
|
||||||
|
fptr->fsize = -3; // undefined
|
||||||
|
|
||||||
|
// remove from hash table
|
||||||
|
FSH_RemoveHash( handle->hashlist, hash, fptr );
|
||||||
|
|
||||||
|
// add empty to hash table
|
||||||
|
FSH_AddHash( handle->hashlist, handle->empty_hash, fptr );
|
||||||
|
|
||||||
|
return fptr - handle->pathlist; // index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
FSH_RenameFilePath
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
int FSH_RenameFilePath( fsh_handle_t *handle, const char *oldname, const char *newname )
|
||||||
|
{
|
||||||
|
uint hash;
|
||||||
|
fsh_path_t *fptr, **fptr_prev;
|
||||||
|
const char *strip_path;
|
||||||
|
|
||||||
|
if( !handle )
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
if( Q_strnicmp( oldname, handle->folderpath, handle->folderpath_size ))
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
strip_path = oldname + handle->folderpath_size + 1; // + '/'
|
||||||
|
|
||||||
|
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||||
|
|
||||||
|
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||||
|
{
|
||||||
|
if( !Q_stricmp( fptr->path, strip_path ))
|
||||||
|
{
|
||||||
|
strip_path = newname + handle->folderpath_size + 1; // + '/'
|
||||||
|
|
||||||
|
memset( fptr->path, 0, FSH_MAX_PATH );
|
||||||
|
Q_strncpy( fptr->path, strip_path, FSH_MAX_PATH - 1 );
|
||||||
|
|
||||||
|
// remove old from hash table
|
||||||
|
FSH_RemoveHash( handle->hashlist, hash, fptr );
|
||||||
|
|
||||||
|
// add new to hash table
|
||||||
|
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||||
|
FSH_AddHash( handle->hashlist, hash, fptr );
|
||||||
|
|
||||||
|
return fptr - handle->pathlist; // index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
FSH_FindSize
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
int FSH_FindSize( fsh_handle_t *handle, const char *path )
|
||||||
|
{
|
||||||
|
uint hash;
|
||||||
|
fsh_path_t *fptr;
|
||||||
|
const char *strip_path;
|
||||||
|
|
||||||
|
if( !handle )
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
if( !handle->ready || !handle->count || Q_strnicmp( path, handle->folderpath, handle->folderpath_size ))
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
strip_path = path + handle->folderpath_size + 1; // + '/'
|
||||||
|
|
||||||
|
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||||
|
|
||||||
|
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||||
|
{
|
||||||
|
if( !Q_stricmp( fptr->path, strip_path ))
|
||||||
|
return fptr->fsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
FSH_Find
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
int FSH_Find( fsh_handle_t *handle, const char *path )
|
||||||
|
{
|
||||||
|
uint hash;
|
||||||
|
fsh_path_t *fptr;
|
||||||
|
const char *strip_path;
|
||||||
|
|
||||||
|
if( !handle )
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
if( !handle->ready || !handle->count || Q_strnicmp( path, handle->folderpath, handle->folderpath_size ))
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
strip_path = path + handle->folderpath_size + 1; // + '/'
|
||||||
|
|
||||||
|
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||||
|
|
||||||
|
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||||
|
{
|
||||||
|
if( !Q_stricmp( fptr->path, strip_path ))
|
||||||
|
return fptr - handle->pathlist; // index
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
FSH_ScanDir
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
static int FSH_ScanDir( fsh_handle_t *handle, const char *path )
|
||||||
|
{
|
||||||
|
SceUID dir;
|
||||||
|
SceIoDirent entry;
|
||||||
|
char temp[FSH_MAX_PATH];
|
||||||
|
int result;
|
||||||
|
int fsize;
|
||||||
|
|
||||||
|
if(( dir = sceIoDopen( path )) < 0 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
// iterate through the directory
|
||||||
|
while( 1 )
|
||||||
|
{
|
||||||
|
// zero the dirent, to avoid possible problems with sceIoDread
|
||||||
|
memset( &entry, 0, sizeof( SceIoDirent ));
|
||||||
|
if( !sceIoDread( dir, &entry ))
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ignore the virtual directories
|
||||||
|
if( !Q_stricmp( entry.d_name, "." ) || !Q_stricmp( entry.d_name, ".." ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sprintf( temp, "%s/%s", path, entry.d_name );
|
||||||
|
|
||||||
|
if(FIO_S_ISDIR( entry.d_stat.st_mode ))
|
||||||
|
result = FSH_ScanDir( handle, temp );
|
||||||
|
else if(FIO_S_ISREG( entry.d_stat.st_mode ))
|
||||||
|
{
|
||||||
|
if( entry.d_stat.st_size <= __INT_MAX__ )
|
||||||
|
fsize = ( int )entry.d_stat.st_size;
|
||||||
|
else fsize = -3; // undefined
|
||||||
|
|
||||||
|
result = FSH_AddFilePathWs( handle, temp, fsize );
|
||||||
|
}
|
||||||
|
else continue;
|
||||||
|
if( result < 0 ) break;
|
||||||
|
}
|
||||||
|
sceIoDclose( dir );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
FSH_Create
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
fsh_handle_t *FSH_Create( const char *path, int maxfiles )
|
||||||
|
{
|
||||||
|
fsh_handle_t *handle;
|
||||||
|
|
||||||
|
handle = P5Ram_Alloc( sizeof( fsh_handle_t ), 1 );
|
||||||
|
if( !handle )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
handle->pathlist_size = maxfiles;
|
||||||
|
handle->pathlist = P5Ram_Alloc( handle->pathlist_size * sizeof( fsh_path_t ), 1 );
|
||||||
|
if( !handle->pathlist )
|
||||||
|
{
|
||||||
|
P5Ram_Free( handle );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->hashlist_size = maxfiles >> 2;
|
||||||
|
handle->hashlist = P5Ram_Alloc( handle->hashlist_size * sizeof( fsh_path_t* ), 1 );
|
||||||
|
if( !handle->hashlist )
|
||||||
|
{
|
||||||
|
P5Ram_Free( handle );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->empty_hash = COM_HashKey( FSH_EMPTY_STRING, handle->hashlist_size );
|
||||||
|
|
||||||
|
if( !Q_strnicmp( path, "./", 2 ))
|
||||||
|
path += 2;
|
||||||
|
|
||||||
|
Q_strncpy( handle->folderpath, path, FSH_MAX_PATH - 1 );
|
||||||
|
handle->folderpath_size = Q_strlen( handle->folderpath );
|
||||||
|
|
||||||
|
if( FSH_ScanDir( handle, handle->folderpath ) < 0 )
|
||||||
|
{
|
||||||
|
P5Ram_Free( handle );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->next = fsh_poolchain;
|
||||||
|
fsh_poolchain = handle;
|
||||||
|
|
||||||
|
handle->ready = true;
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
FSH_Shutdown
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void FSH_Free( fsh_handle_t *handle )
|
||||||
|
{
|
||||||
|
if( !handle )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( handle->pathlist )
|
||||||
|
P5Ram_Free( handle->pathlist );
|
||||||
|
|
||||||
|
if( handle->hashlist )
|
||||||
|
P5Ram_Free( handle->hashlist );
|
||||||
|
|
||||||
|
P5Ram_Free( handle );
|
||||||
|
}
|
||||||
37
engine/platform/psp/fsh_psp.h
Normal file
37
engine/platform/psp/fsh_psp.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
fsh_psp.h - PSP filesystem helper header
|
||||||
|
Copyright (C) 2022 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#ifndef FSH_PSP_H
|
||||||
|
#define FSH_PSP_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
typedef struct fsh_handle_s fsh_handle_t;
|
||||||
|
|
||||||
|
int FSH_AddFilePathWs( fsh_handle_t *handle, const char *path, int size );
|
||||||
|
#define FSH_AddFilePath( handle, path ) FSH_AddFilePathWs(handle, path, -2 )
|
||||||
|
int FSH_RemoveFilePath( fsh_handle_t *handle, const char *path );
|
||||||
|
int FSH_RenameFilePath( fsh_handle_t *handle, const char *oldname, const char *newname );
|
||||||
|
int FSH_FindSize( fsh_handle_t *handle, const char *path );
|
||||||
|
int FSH_Find( fsh_handle_t *handle, const char *path );
|
||||||
|
fsh_handle_t *FSH_Create( const char *path, int maxfiles );
|
||||||
|
void FSH_Free( fsh_handle_t *handle );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // P5RAM_PSP_H
|
||||||
239
engine/platform/psp/in_psp.c
Normal file
239
engine/platform/psp/in_psp.c
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
in_psp.c - PSP input component
|
||||||
|
Copyright (C) 2021 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#include "common.h"
|
||||||
|
#include "keydefs.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
#if XASH_INPUT == INPUT_PSP
|
||||||
|
#include <pspctrl.h>
|
||||||
|
|
||||||
|
#define PSP_MAX_KEYS sizeof(psp_keymap) / sizeof(struct psp_keymap_s)
|
||||||
|
#define PSP_EXT_KEY PSP_CTRL_HOME
|
||||||
|
|
||||||
|
convar_t *psp_joy_dz_min;
|
||||||
|
convar_t *psp_joy_dz_max;
|
||||||
|
convar_t *psp_joy_cv_power;
|
||||||
|
convar_t *psp_joy_cv_expo;
|
||||||
|
|
||||||
|
static struct psp_keymap_s
|
||||||
|
{
|
||||||
|
int srckey;
|
||||||
|
int dstkey;
|
||||||
|
qboolean stdpressed;
|
||||||
|
qboolean extpressed;
|
||||||
|
}psp_keymap[] =
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
{ PSP_CTRL_SELECT, '~' , false, false },
|
||||||
|
{ PSP_CTRL_START, K_ESCAPE , false, false },
|
||||||
|
{ PSP_CTRL_UP, K_UPARROW , false, false },
|
||||||
|
{ PSP_CTRL_RIGHT, K_RIGHTARROW, false, false },
|
||||||
|
{ PSP_CTRL_DOWN, K_DOWNARROW , false, false },
|
||||||
|
{ PSP_CTRL_LEFT, K_LEFTARROW , false, false },
|
||||||
|
{ PSP_CTRL_LTRIGGER, K_JOY1 , false, false },
|
||||||
|
{ PSP_CTRL_RTRIGGER, K_JOY2 , false, false },
|
||||||
|
{ PSP_CTRL_TRIANGLE, K_SHIFT , false, false },
|
||||||
|
{ PSP_CTRL_CIRCLE, K_SPACE , false, false },
|
||||||
|
{ PSP_CTRL_CROSS, K_ENTER , false, false },
|
||||||
|
{ PSP_CTRL_SQUARE, K_BACKSPACE , false, false },
|
||||||
|
#else
|
||||||
|
{ PSP_CTRL_SELECT , K_MODE_BUTTON , false, false },
|
||||||
|
{ PSP_CTRL_START , K_START_BUTTON, false, false },
|
||||||
|
{ PSP_CTRL_UP , K_UPARROW , false, false },
|
||||||
|
{ PSP_CTRL_RIGHT , K_RIGHTARROW , false, false },
|
||||||
|
{ PSP_CTRL_DOWN , K_DOWNARROW , false, false },
|
||||||
|
{ PSP_CTRL_LEFT , K_LEFTARROW , false, false },
|
||||||
|
{ PSP_CTRL_LTRIGGER, K_L1_BUTTON , false, false },
|
||||||
|
{ PSP_CTRL_RTRIGGER, K_R1_BUTTON , false, false },
|
||||||
|
{ PSP_CTRL_TRIANGLE, K_Y_BUTTON , false, false },
|
||||||
|
{ PSP_CTRL_CIRCLE , K_B_BUTTON , false, false },
|
||||||
|
{ PSP_CTRL_CROSS , K_A_BUTTON , false, false },
|
||||||
|
{ PSP_CTRL_SQUARE , K_X_BUTTON , false, false },
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
|
PSP_CTRL_HOME,
|
||||||
|
PSP_CTRL_HOLD,
|
||||||
|
PSP_CTRL_NOTE,
|
||||||
|
PSP_CTRL_SCREEN,
|
||||||
|
PSP_CTRL_VOLUP,
|
||||||
|
PSP_CTRL_VOLDOWN,
|
||||||
|
PSP_CTRL_WLAN_UP,
|
||||||
|
PSP_CTRL_REMOTE,
|
||||||
|
PSP_CTRL_DISC,
|
||||||
|
PSP_CTRL_MS,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
static signed short psp_joymap[256]; /* -32768 <> 32767 */
|
||||||
|
|
||||||
|
static float Platform_JoyAxisCompute( float axis, float deadzone_min, float deadzone_max, float power, float expo )
|
||||||
|
{
|
||||||
|
float abs_axis, fabs_axis, fcurve;
|
||||||
|
float scale, r_deadzone_max;
|
||||||
|
qboolean flip_axis = 0;
|
||||||
|
|
||||||
|
expo = bound( 0.0f, expo, 1.0f );
|
||||||
|
power = bound( 0.0f, power, 10.0f );
|
||||||
|
deadzone_min = bound( 0.0f, deadzone_min, 127.0f );
|
||||||
|
deadzone_max = bound( 0.0f, deadzone_max, 127.0f );
|
||||||
|
|
||||||
|
// (-127) - (0) - (+127)
|
||||||
|
abs_axis = axis - 128.0f;
|
||||||
|
if( abs_axis < 0.0f )
|
||||||
|
{
|
||||||
|
abs_axis = -abs_axis - 1.0f;
|
||||||
|
flip_axis = 1;
|
||||||
|
}
|
||||||
|
if( abs_axis <= deadzone_min ) return 0.0f;
|
||||||
|
r_deadzone_max = 127.0f - deadzone_max;
|
||||||
|
if( abs_axis >= r_deadzone_max ) return ( flip_axis ? -127.0f : 127.0f );
|
||||||
|
|
||||||
|
scale = 127.0f / ( r_deadzone_max - deadzone_min );
|
||||||
|
abs_axis -= deadzone_min;
|
||||||
|
abs_axis *= scale;
|
||||||
|
|
||||||
|
if( expo )
|
||||||
|
{
|
||||||
|
// x * ( x^power * expo + x * ( 1.0 - expo ))
|
||||||
|
fabs_axis = abs_axis / 127.0f; // 0.0f - 1.0f
|
||||||
|
fcurve = powf(fabs_axis, power) * expo + fabs_axis * (1.0f - expo);
|
||||||
|
abs_axis = fabs_axis * fcurve * 127.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( flip_axis ? -abs_axis : abs_axis );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_RunEvents( void )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
SceCtrlData buf;
|
||||||
|
signed short curr_X, curr_Y;
|
||||||
|
static unsigned int last_buttons;
|
||||||
|
static signed short last_X, last_Y;
|
||||||
|
|
||||||
|
sceCtrlPeekBufferPositive( &buf, 1 );
|
||||||
|
|
||||||
|
for( i = 0; i < PSP_MAX_KEYS; i++ )
|
||||||
|
{
|
||||||
|
if( buf.Buttons & PSP_EXT_KEY )
|
||||||
|
{
|
||||||
|
if(( last_buttons ^ buf.Buttons ) & psp_keymap[i].srckey )
|
||||||
|
{
|
||||||
|
if( psp_keymap[i].stdpressed )
|
||||||
|
{
|
||||||
|
psp_keymap[i].stdpressed = false;
|
||||||
|
Key_Event( psp_keymap[i].dstkey, psp_keymap[i].stdpressed );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
psp_keymap[i].extpressed = buf.Buttons & psp_keymap[i].srckey;
|
||||||
|
Key_Event( K_AUX16 + i, psp_keymap[i].extpressed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// release
|
||||||
|
if( psp_keymap[i].extpressed )
|
||||||
|
{
|
||||||
|
psp_keymap[i].extpressed = false;
|
||||||
|
Key_Event( K_AUX16 + i, psp_keymap[i].extpressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(( last_buttons ^ buf.Buttons ) & psp_keymap[i].srckey )
|
||||||
|
{
|
||||||
|
psp_keymap[i].stdpressed = buf.Buttons & psp_keymap[i].srckey;
|
||||||
|
Key_Event( psp_keymap[i].dstkey, psp_keymap[i].stdpressed );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
last_buttons = buf.Buttons;
|
||||||
|
|
||||||
|
if( FBitSet( psp_joy_dz_min->flags, FCVAR_CHANGED ) || FBitSet( psp_joy_dz_max->flags, FCVAR_CHANGED ) ||
|
||||||
|
FBitSet( psp_joy_cv_power->flags, FCVAR_CHANGED ) || FBitSet( psp_joy_cv_expo->flags, FCVAR_CHANGED ))
|
||||||
|
{
|
||||||
|
for ( i = 0; i < 256; i++ )
|
||||||
|
{
|
||||||
|
psp_joymap[i] = Platform_JoyAxisCompute( i, psp_joy_dz_min->value, psp_joy_dz_max->value, psp_joy_cv_power->value, psp_joy_cv_expo->value );
|
||||||
|
psp_joymap[i] *= 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearBits( psp_joy_dz_min->flags, FCVAR_CHANGED );
|
||||||
|
ClearBits( psp_joy_dz_max->flags, FCVAR_CHANGED );
|
||||||
|
ClearBits( psp_joy_cv_power->flags, FCVAR_CHANGED );
|
||||||
|
ClearBits( psp_joy_cv_expo->flags, FCVAR_CHANGED );
|
||||||
|
}
|
||||||
|
|
||||||
|
curr_X = psp_joymap[buf.Lx];
|
||||||
|
curr_Y = psp_joymap[buf.Ly];
|
||||||
|
|
||||||
|
if( last_X != curr_X )
|
||||||
|
Joy_AxisMotionEvent( 2, -curr_X );
|
||||||
|
|
||||||
|
if( last_Y != curr_Y )
|
||||||
|
Joy_AxisMotionEvent( 3, -curr_Y );
|
||||||
|
|
||||||
|
last_X = curr_X;
|
||||||
|
last_Y = curr_Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_GetMousePos( int *x, int *y )
|
||||||
|
{
|
||||||
|
*x = *y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_SetMousePos( int x, int y )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_EnableTextInput( qboolean enable )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int Platform_JoyInit( int numjoy )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// set up cvars
|
||||||
|
psp_joy_dz_min = Cvar_Get( "psp_joy_dz_min", "15", FCVAR_ARCHIVE, "joy deadzone min (0 - 127)" );
|
||||||
|
psp_joy_dz_max = Cvar_Get( "psp_joy_dz_max", "0", FCVAR_ARCHIVE, "joy deadzone max (0 - 127)" );
|
||||||
|
psp_joy_cv_power = Cvar_Get( "psp_joy_cv_power", "2", FCVAR_ARCHIVE, "joy curve power (0 - 10)" );
|
||||||
|
psp_joy_cv_expo = Cvar_Get( "psp_joy_cv_expo", "0.5", FCVAR_ARCHIVE, "joy curve expo (0 - 1.0)" );
|
||||||
|
|
||||||
|
// set up the controller.
|
||||||
|
sceCtrlSetSamplingCycle( 0 );
|
||||||
|
sceCtrlSetSamplingMode( PSP_CTRL_MODE_ANALOG );
|
||||||
|
|
||||||
|
// building a joystick map
|
||||||
|
for ( i = 0; i < 256; i++ )
|
||||||
|
{
|
||||||
|
psp_joymap[i] = Platform_JoyAxisCompute( i, psp_joy_dz_min->value, psp_joy_dz_max->value, psp_joy_cv_power->value, psp_joy_cv_expo->value );
|
||||||
|
psp_joymap[i] *= 256;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_MouseMove( float *x, float *y )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_PreCreateMove( void )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif /* XASH_INPUT */
|
||||||
8
engine/platform/psp/ka/KernelAccess.S
Normal file
8
engine/platform/psp/ka/KernelAccess.S
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
.set noreorder
|
||||||
|
|
||||||
|
#include "pspstub.s"
|
||||||
|
|
||||||
|
STUB_START "KernelAccess",0x40090000,0x00020005
|
||||||
|
STUB_FUNC 0x8A5C745F,kaGeEdramSetSize
|
||||||
|
STUB_FUNC 0x71570ECF,kaGeEdramGetHwSize
|
||||||
|
STUB_END
|
||||||
30
engine/platform/psp/ka/ka.h
Normal file
30
engine/platform/psp/ka/ka.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
kamod.h - kernel access module header
|
||||||
|
Copyright (C) 2022 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KAMOD_H
|
||||||
|
#define KAMOD_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
int kaGeEdramSetSize(int size);
|
||||||
|
int kaGeEdramGetHwSize(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // KAMOD_H
|
||||||
486
engine/platform/psp/lib_psp.c
Normal file
486
engine/platform/psp/lib_psp.c
Normal file
@@ -0,0 +1,486 @@
|
|||||||
|
/*
|
||||||
|
lib_psp.c - dynamic library code for Sony PSP system
|
||||||
|
Copyright (C) 2018 Flying With Gauss
|
||||||
|
Copyright (C) 2022 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/sor modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#include "platform/platform.h"
|
||||||
|
|
||||||
|
#if XASH_LIB == LIB_PSP
|
||||||
|
#include <pspmodulemgr.h>
|
||||||
|
#include "common.h"
|
||||||
|
#include "library.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
#include "server.h"
|
||||||
|
|
||||||
|
#define MOD_MAXNAMELEN 256
|
||||||
|
|
||||||
|
typedef struct table_s
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
void *pointer;
|
||||||
|
} table_t;
|
||||||
|
#include "generated_library_tables.h"
|
||||||
|
|
||||||
|
typedef struct mod_func_s
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
void *addr;
|
||||||
|
} mod_func_t;
|
||||||
|
|
||||||
|
typedef struct mod_handle_s
|
||||||
|
{
|
||||||
|
SceUID uid;
|
||||||
|
char name[MOD_MAXNAMELEN];
|
||||||
|
uint segAddr;
|
||||||
|
uint segSize;
|
||||||
|
mod_func_t *func;
|
||||||
|
struct mod_handle_s *next;
|
||||||
|
} mod_handle_t;
|
||||||
|
|
||||||
|
static mod_handle_t *modList = NULL;
|
||||||
|
static char *modErrorPtr = NULL;
|
||||||
|
static char modErrorBuf[1024];
|
||||||
|
|
||||||
|
#define Module_Error( fmt, ... ) Module_SetError( "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__ )
|
||||||
|
|
||||||
|
int Module_SetError( const char *fmt, ... )
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
va_start( args, fmt );
|
||||||
|
result = Q_vsnprintf( modErrorBuf, sizeof( modErrorBuf ), fmt, args );
|
||||||
|
va_end( args );
|
||||||
|
|
||||||
|
modErrorPtr = modErrorBuf;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *Module_GetError( void )
|
||||||
|
{
|
||||||
|
char *errPtr = modErrorPtr;
|
||||||
|
modErrorPtr = NULL;
|
||||||
|
return errPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mod_handle_t *Module_Find( const char *name )
|
||||||
|
{
|
||||||
|
mod_handle_t *modHandle;
|
||||||
|
|
||||||
|
if( !name )
|
||||||
|
{
|
||||||
|
Module_Error( "input mismatch" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( modHandle = modList; modHandle; modHandle = modHandle->next )
|
||||||
|
{
|
||||||
|
if( !Q_strcmp( modHandle->name, name ))
|
||||||
|
return modHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *Module_Name( void *handle )
|
||||||
|
{
|
||||||
|
mod_handle_t *modHandle;
|
||||||
|
|
||||||
|
if( !handle )
|
||||||
|
{
|
||||||
|
Module_Error( "input mismatch" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( modHandle = modList; modHandle; modHandle = modHandle->next )
|
||||||
|
{
|
||||||
|
if( modHandle == handle )
|
||||||
|
return modHandle->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mod_func_t *Module_LoadStatic( const char *name )
|
||||||
|
{
|
||||||
|
table_t *staticLib;
|
||||||
|
|
||||||
|
if( !name )
|
||||||
|
{
|
||||||
|
Module_Error( "input mismatch" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( staticLib = ( table_t* )libs; staticLib->pointer && staticLib->name; staticLib++ )
|
||||||
|
{
|
||||||
|
if( !Q_strcmp( staticLib->name, name ))
|
||||||
|
return staticLib->pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod_handle_t *Module_Load( const char *name )
|
||||||
|
{
|
||||||
|
mod_handle_t *modHandle;
|
||||||
|
mod_func_t *modFunc;
|
||||||
|
qboolean skipPrefix;
|
||||||
|
char modStaticName[32];
|
||||||
|
void *modArg[2];
|
||||||
|
SceUID modUid;
|
||||||
|
uint modSegAddr, modSegSize;
|
||||||
|
SceKernelModuleInfo info;
|
||||||
|
char engine_cwd[PATH_MAX];
|
||||||
|
|
||||||
|
if( !name )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
modHandle = Module_Find( name );
|
||||||
|
if( modHandle )
|
||||||
|
return modHandle;
|
||||||
|
|
||||||
|
skipPrefix = false;
|
||||||
|
modSegAddr = modSegSize = 0;
|
||||||
|
|
||||||
|
Q_sprintf( engine_cwd, "%s/", host.rootdir );
|
||||||
|
|
||||||
|
modArg[0] = &modFunc;
|
||||||
|
modArg[1] = engine_cwd;
|
||||||
|
modUid = Platform_LoadModule( name, 0, sizeof( modArg ), modArg );
|
||||||
|
if( modUid < 0 )
|
||||||
|
{
|
||||||
|
COM_FileBase( name, modStaticName );
|
||||||
|
|
||||||
|
if( !Q_strncmp( modStaticName, "lib", 3 ) )
|
||||||
|
skipPrefix = true;
|
||||||
|
|
||||||
|
modFunc = Module_LoadStatic( skipPrefix ? &modStaticName[3] : modStaticName );
|
||||||
|
if( !modFunc )
|
||||||
|
{
|
||||||
|
Module_Error( "module %s error ( %#010x )", name, modUid );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
modUid = -1;
|
||||||
|
|
||||||
|
Con_Reportf( "Module_Load( %s ): ( static ) success!\n", name );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info.size = sizeof( info );
|
||||||
|
if ( sceKernelQueryModuleInfo( modUid, &info ) >= 0 )
|
||||||
|
{
|
||||||
|
if( info.nsegment > 0 )
|
||||||
|
{
|
||||||
|
modSegAddr = info.segmentaddr[0];
|
||||||
|
modSegSize = info.segmentsize[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Con_Reportf( "Module_Load( %s ): ( dynamic ) success!\n", name );
|
||||||
|
}
|
||||||
|
|
||||||
|
modHandle = calloc( 1, sizeof( mod_handle_t ));
|
||||||
|
if( !modHandle )
|
||||||
|
{
|
||||||
|
Module_Error( "out of memory" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_strncpy( modHandle->name, name, MOD_MAXNAMELEN );
|
||||||
|
|
||||||
|
modHandle->uid = modUid;
|
||||||
|
modHandle->func = modFunc;
|
||||||
|
modHandle->segAddr = modSegAddr;
|
||||||
|
modHandle->segSize = modSegSize;
|
||||||
|
modHandle->next = modList;
|
||||||
|
|
||||||
|
modList = modHandle;
|
||||||
|
|
||||||
|
return modHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *Module_GetAddrByName( mod_handle_t *handle, const char *name )
|
||||||
|
{
|
||||||
|
mod_func_t *modFunc;
|
||||||
|
|
||||||
|
if( !handle || !name )
|
||||||
|
{
|
||||||
|
Module_Error( "input mismatch" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !Module_Name( handle ))
|
||||||
|
{
|
||||||
|
Module_SetError( "unknown handle" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !handle->func )
|
||||||
|
{
|
||||||
|
Module_SetError( "call Module_Load() first" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( modFunc = handle->func; modFunc->addr && modFunc->name; modFunc++ )
|
||||||
|
{
|
||||||
|
if( !Q_strcmp( modFunc->name, name ))
|
||||||
|
return modFunc->addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Module_Error( "func %s not found in %s", name, handle->name );
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *Module_GetNameByAddr( mod_handle_t *handle, const void *addr )
|
||||||
|
{
|
||||||
|
mod_func_t *modFunc;
|
||||||
|
|
||||||
|
if( !handle || !addr )
|
||||||
|
{
|
||||||
|
Module_Error( "input mismatch" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !Module_Name( handle ))
|
||||||
|
{
|
||||||
|
Module_SetError( "unknown handle" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !handle->func )
|
||||||
|
{
|
||||||
|
Module_SetError( "call Module_Load() first" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( modFunc = handle->func; modFunc->addr && modFunc->name; modFunc++ )
|
||||||
|
{
|
||||||
|
if( modFunc->addr == addr )
|
||||||
|
return modFunc->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Module_Error( "addr %#010x not found in %s", addr, handle->name );
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint Module_GetOffsetByAddr( mod_handle_t *handle, const void *addr )
|
||||||
|
{
|
||||||
|
uint addrUInt;
|
||||||
|
|
||||||
|
if( !handle || !addr )
|
||||||
|
{
|
||||||
|
Module_Error( "input mismatch" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !Module_Name( handle ))
|
||||||
|
{
|
||||||
|
Module_SetError( "unknown handle" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !handle->segAddr )
|
||||||
|
{
|
||||||
|
Module_SetError( "unknown segment" );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
addrUInt = ( uint )addr;
|
||||||
|
if( addrUInt < handle->segAddr || addrUInt >= ( handle->segAddr + handle->segSize ))
|
||||||
|
{
|
||||||
|
Module_SetError( "addr %#010x is out of range", addrUInt );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return addrUInt - handle->segAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *Module_GetAddrByOffset( mod_handle_t *handle, uint offset )
|
||||||
|
{
|
||||||
|
if( !handle || !offset )
|
||||||
|
{
|
||||||
|
Module_Error( "input mismatch" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !Module_Name( handle ))
|
||||||
|
{
|
||||||
|
Module_SetError( "unknown handle" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !handle->segAddr )
|
||||||
|
{
|
||||||
|
Module_SetError( "unknown segment" );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( offset >= handle->segSize )
|
||||||
|
{
|
||||||
|
Module_SetError( "offset %#010x is out of range", offset );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ( void* )( offset + handle->segAddr );
|
||||||
|
}
|
||||||
|
|
||||||
|
int Module_Unload( mod_handle_t *handle )
|
||||||
|
{
|
||||||
|
mod_handle_t *modHandle;
|
||||||
|
int result, sceCode;
|
||||||
|
|
||||||
|
if( !handle )
|
||||||
|
{
|
||||||
|
Module_Error( "input mismatch" );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !Module_Name( handle ))
|
||||||
|
{
|
||||||
|
Module_Error( "unknown handle" );
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( handle->uid != -1 )
|
||||||
|
{
|
||||||
|
result = Platform_UnloadModule( handle->uid, &sceCode );
|
||||||
|
if( result < 0 )
|
||||||
|
{
|
||||||
|
if( result == -1 )
|
||||||
|
Module_Error( "module %s doesn't want to stop", handle->name );
|
||||||
|
else
|
||||||
|
Module_Error( "module %s error ( %#010x )", handle->name, sceCode );
|
||||||
|
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( handle != modList )
|
||||||
|
{
|
||||||
|
for( modHandle = modList; modHandle; modHandle = modHandle->next )
|
||||||
|
{
|
||||||
|
if( modHandle->next == handle )
|
||||||
|
{
|
||||||
|
modHandle->next = handle->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else modList = handle->next;
|
||||||
|
|
||||||
|
free( handle );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean COM_CheckLibraryDirectDependency( const char *name, const char *depname, qboolean directpath )
|
||||||
|
{
|
||||||
|
// TODO: implement
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean directpath )
|
||||||
|
{
|
||||||
|
dll_user_t *hInst = NULL;
|
||||||
|
void *pHandle = NULL;
|
||||||
|
|
||||||
|
COM_ResetLibraryError();
|
||||||
|
|
||||||
|
// platforms where gameinfo mechanism is working goes here
|
||||||
|
// and use FS_FindLibrary
|
||||||
|
hInst = FS_FindLibrary( dllname, directpath );
|
||||||
|
if( !hInst )
|
||||||
|
{
|
||||||
|
// try to find by linker(LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, LD_32_LIBRARY_PATH and so on...)
|
||||||
|
if( !pHandle )
|
||||||
|
{
|
||||||
|
pHandle = Module_Load( dllname );
|
||||||
|
if( pHandle )
|
||||||
|
return pHandle;
|
||||||
|
|
||||||
|
COM_PushLibraryError( va( "Failed to find library %s", dllname ));
|
||||||
|
COM_PushLibraryError( Module_GetError() );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( hInst->custom_loader )
|
||||||
|
{
|
||||||
|
COM_PushLibraryError( va( "Custom library loader is not available. Extract library %s and fix gameinfo.txt!", hInst->fullPath ));
|
||||||
|
Mem_Free( hInst );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !( hInst->hInstance = Module_Load( hInst->fullPath )))
|
||||||
|
{
|
||||||
|
COM_PushLibraryError( Module_GetError() );
|
||||||
|
Mem_Free( hInst );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pHandle = hInst->hInstance;
|
||||||
|
|
||||||
|
Mem_Free( hInst );
|
||||||
|
|
||||||
|
return pHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void COM_FreeLibrary( void *hInstance )
|
||||||
|
{
|
||||||
|
Module_Unload( hInstance );
|
||||||
|
}
|
||||||
|
|
||||||
|
void *COM_GetProcAddress( void *hInstance, const char *name )
|
||||||
|
{
|
||||||
|
return Module_GetAddrByName( hInstance, name );
|
||||||
|
}
|
||||||
|
|
||||||
|
void *COM_FunctionFromName_SR( void *hInstance, const char *pName )
|
||||||
|
{
|
||||||
|
void *funcAddr;
|
||||||
|
|
||||||
|
if( !memcmp( pName, "ofs:", 4 ))
|
||||||
|
funcAddr = Module_GetAddrByOffset( hInstance, Q_atoi( &pName[4] ));
|
||||||
|
else
|
||||||
|
funcAddr = Module_GetAddrByName( hInstance, pName );
|
||||||
|
|
||||||
|
if( !funcAddr )
|
||||||
|
Con_Reportf( S_ERROR "FunctionFromName: Can't get symbol %s: %s\n", pName, Module_GetError() );
|
||||||
|
|
||||||
|
return funcAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *COM_NameForFunction( void *hInstance, void *function )
|
||||||
|
{
|
||||||
|
static char offsetName[16];
|
||||||
|
const char *funcName;
|
||||||
|
uint addrOffset;
|
||||||
|
|
||||||
|
funcName = Module_GetNameByAddr( hInstance, function );
|
||||||
|
if( funcName )
|
||||||
|
return funcName;
|
||||||
|
|
||||||
|
addrOffset = Module_GetOffsetByAddr( hInstance, function );
|
||||||
|
if( !addrOffset )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
Q_snprintf( offsetName, sizeof( offsetName ), "ofs:%u", addrOffset );
|
||||||
|
Con_Reportf( "COM_NameForFunction: %s\n", offsetName );
|
||||||
|
|
||||||
|
return offsetName;
|
||||||
|
}
|
||||||
|
#endif // XASH_LIB == LIB_PSP
|
||||||
165
engine/platform/psp/p5ram_psp.c
Normal file
165
engine/platform/psp/p5ram_psp.c
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
p5ram_psp.c - PSP P5 memory allocator
|
||||||
|
Copyright (C) 2022 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#include <pspkernel.h>
|
||||||
|
#include <psppower.h>
|
||||||
|
#include <pspsuspend.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "p5ram_psp.h"
|
||||||
|
|
||||||
|
#define P5RAM_ALIGN( x, a ) ((( x ) + (( typeof( x ))( a ) - 1 )) & ~( typeof( x )( a ) - 1 ))
|
||||||
|
|
||||||
|
#define P5RAM_CHECK( addr ) ((( unsigned int )addr >= ( unsigned int )p5ram_addr) && (( unsigned int )addr < ( unsigned int )p5ram_addr + p5ram_size))
|
||||||
|
|
||||||
|
#define P5RAM_FLAG_INIT 0x01
|
||||||
|
#define P5RAM_FLAG_SUSPENDED 0x02
|
||||||
|
|
||||||
|
typedef struct __attribute__(( aligned( 64 ))) p5ram_info_s
|
||||||
|
{
|
||||||
|
SceUID uid;
|
||||||
|
size_t size;
|
||||||
|
struct p5ram_info_s *next;
|
||||||
|
}p5ram_info_t;
|
||||||
|
|
||||||
|
static unsigned char p5ram_flags = 0x00;
|
||||||
|
static p5ram_info_t *p5ram_poolchain = NULL;
|
||||||
|
static void *p5ram_addr;
|
||||||
|
static unsigned int p5ram_size;
|
||||||
|
|
||||||
|
int P5Ram_Init( void )
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if( p5ram_flags & P5RAM_FLAG_INIT )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
result = sceKernelVolatileMemLock( 0, &p5ram_addr, &p5ram_size );
|
||||||
|
if( result == 0 )
|
||||||
|
p5ram_flags |= P5RAM_FLAG_INIT;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *P5Ram_Alloc( size_t size, int clear )
|
||||||
|
{
|
||||||
|
SceUID uid;
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
if(!( p5ram_flags & P5RAM_FLAG_INIT ))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
uid = sceKernelAllocPartitionMemory( 5, "USER P5", PSP_SMEM_Low, size + sizeof( p5ram_info_t ), NULL );
|
||||||
|
if( uid < 0 ) return NULL;
|
||||||
|
|
||||||
|
ptr = sceKernelGetBlockHeadAddr( uid );
|
||||||
|
(( p5ram_info_t* )ptr )->uid = uid;
|
||||||
|
(( p5ram_info_t* )ptr )->size = size;
|
||||||
|
(( p5ram_info_t* )ptr )->next = p5ram_poolchain;
|
||||||
|
if( clear ) memset(( unsigned char* )ptr + sizeof( p5ram_info_t ), 0, size );
|
||||||
|
|
||||||
|
p5ram_poolchain = ptr;
|
||||||
|
|
||||||
|
return ( void* )(( unsigned char* )ptr + sizeof( p5ram_info_t ));
|
||||||
|
}
|
||||||
|
|
||||||
|
void P5Ram_Free( void *ptr )
|
||||||
|
{
|
||||||
|
p5ram_info_t *info, *next_ptr;
|
||||||
|
|
||||||
|
if( !( p5ram_flags & P5RAM_FLAG_INIT ) || ptr == NULL ) return;
|
||||||
|
|
||||||
|
info = ( p5ram_info_t* )((unsigned char*)ptr - sizeof( p5ram_info_t ));
|
||||||
|
|
||||||
|
if( info == p5ram_poolchain )
|
||||||
|
{
|
||||||
|
p5ram_poolchain = p5ram_poolchain->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
next_ptr = p5ram_poolchain;
|
||||||
|
while( next_ptr )
|
||||||
|
{
|
||||||
|
if( next_ptr->next == info )
|
||||||
|
{
|
||||||
|
next_ptr->next = info->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next_ptr = next_ptr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sceKernelFreePartitionMemory( info->uid );
|
||||||
|
}
|
||||||
|
|
||||||
|
void P5Ram_FreeAll( void )
|
||||||
|
{
|
||||||
|
p5ram_info_t *next_ptr;
|
||||||
|
|
||||||
|
while( p5ram_poolchain )
|
||||||
|
{
|
||||||
|
next_ptr = p5ram_poolchain->next;
|
||||||
|
sceKernelFreePartitionMemory( p5ram_poolchain->uid );
|
||||||
|
p5ram_poolchain = next_ptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void P5Ram_Shutdown( void )
|
||||||
|
{
|
||||||
|
if( !( p5ram_flags & P5RAM_FLAG_INIT ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
P5Ram_FreeAll();
|
||||||
|
sceKernelVolatileMemUnlock( 0 );
|
||||||
|
|
||||||
|
p5ram_flags &= ~P5RAM_FLAG_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void P5Ram_PowerCallback( int count, int arg, void *common )
|
||||||
|
{
|
||||||
|
if( !( p5ram_flags & ( P5RAM_FLAG_INIT | P5RAM_FLAG_SUSPENDED )))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( arg & PSP_POWER_CB_POWER_SWITCH || arg & PSP_POWER_CB_SUSPENDING )
|
||||||
|
{
|
||||||
|
P5Ram_Shutdown();
|
||||||
|
p5ram_flags |= P5RAM_FLAG_SUSPENDED;
|
||||||
|
}
|
||||||
|
else if ( arg & PSP_POWER_CB_RESUMING )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if ( arg & PSP_POWER_CB_RESUME_COMPLETE )
|
||||||
|
{
|
||||||
|
P5Ram_Init();
|
||||||
|
p5ram_flags &= ~P5RAM_FLAG_SUSPENDED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef P5RAM_DEBUG
|
||||||
|
void P5Ram_Print( void )
|
||||||
|
{
|
||||||
|
p5ram_info_t *next_ptr;
|
||||||
|
|
||||||
|
printf("+++++++++++++++++++++++++++++\n");
|
||||||
|
next_ptr = p5ram_poolchain;
|
||||||
|
while( next_ptr )
|
||||||
|
{
|
||||||
|
printf("P5 ALLOC [ 0x%08X 0x%08X 0x%08X 0x%08X ]\n", next_ptr, next_ptr->uid, next_ptr->size, next_ptr->next );
|
||||||
|
next_ptr = next_ptr->next;
|
||||||
|
}
|
||||||
|
printf("+++++++++++++++++++++++++++++\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
38
engine/platform/psp/p5ram_psp.h
Normal file
38
engine/platform/psp/p5ram_psp.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
p5ram_psp.h - PSP P5 memory allocator header
|
||||||
|
Copyright (C) 2022 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#ifndef P5RAM_PSP_H
|
||||||
|
#define P5RAM_PSP_H
|
||||||
|
|
||||||
|
//#define P5RAM_DEBUG
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
int P5Ram_Init( void );
|
||||||
|
void *P5Ram_Alloc( size_t size, int clear );
|
||||||
|
void P5Ram_Free( void *ptr );
|
||||||
|
void P5Ram_FreeAll( void );
|
||||||
|
void P5Ram_Shutdown( void );
|
||||||
|
void P5Ram_PowerCallback( int count, int arg, void *common );
|
||||||
|
#ifdef P5RAM_DEBUG
|
||||||
|
void P5Ram_Print( void );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // P5RAM_PSP_H
|
||||||
248
engine/platform/psp/scemp3/pspmp3.h
Normal file
248
engine/platform/psp/scemp3/pspmp3.h
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
/*
|
||||||
|
* PSP Software Development Kit - https://github.com/pspdev
|
||||||
|
* -----------------------------------------------------------------------
|
||||||
|
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||||
|
*
|
||||||
|
* pspmp3.h - Prototypes for the sceMp3 library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 David Perry <tias_dp@hotmail.com>
|
||||||
|
* Copyright (c) 2008 Alexander Berl <raphael@fx-world.org>
|
||||||
|
* Copyright (c) 2022 Sergey Galushko
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SCELIBMP3_H__
|
||||||
|
#define __SCELIBMP3_H__
|
||||||
|
|
||||||
|
#include <psptypes.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct SceMp3InitArg {
|
||||||
|
/** Stream start position */
|
||||||
|
SceOff mp3StreamStart;
|
||||||
|
/** Stream end position */
|
||||||
|
SceOff mp3StreamEnd;
|
||||||
|
/** Pointer to a buffer to contain raw mp3 stream data (+1472 bytes workspace) */
|
||||||
|
SceUChar8* mp3Buf;
|
||||||
|
/** Size of mp3Buf buffer (must be >= 8192) */
|
||||||
|
SceInt32 mp3BufSize;
|
||||||
|
/** Pointer to decoded pcm samples buffer */
|
||||||
|
SceUChar8* pcmBuf;
|
||||||
|
/** Size of pcmBuf buffer (must be >= 9216) */
|
||||||
|
SceInt32 pcmBufSize;
|
||||||
|
} SceMp3InitArg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3ReserveMp3Handle
|
||||||
|
*
|
||||||
|
* @param args - Pointer to SceMp3InitArg structure
|
||||||
|
*
|
||||||
|
* @return sceMp3 handle on success, < 0 on error.
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3ReserveMp3Handle(SceMp3InitArg* args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3ReleaseMp3Handle
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
*
|
||||||
|
* @return 0 if success, < 0 on error.
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3ReleaseMp3Handle(SceInt32 handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3InitResource
|
||||||
|
*
|
||||||
|
* @return 0 if success, < 0 on error.
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3InitResource();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3TermResource
|
||||||
|
*
|
||||||
|
* @return 0 if success, < 0 on error.
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3TermResource();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3Init
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
*
|
||||||
|
* @return 0 if success, < 0 on error.
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3Init(SceInt32 handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3Decode
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
* @param dst - Pointer to destination pcm samples buffer
|
||||||
|
*
|
||||||
|
* @return number of bytes in decoded pcm buffer, < 0 on error.
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3Decode(SceInt32 handle, SceShort16** dst);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3GetInfoToAddStreamData
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
* @param dst - Pointer to stream data buffer
|
||||||
|
* @param towrite - Space remaining in stream data buffer
|
||||||
|
* @param srcpos - Position in source stream to start reading from
|
||||||
|
*
|
||||||
|
* @return 0 if success, < 0 on error.
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3GetInfoToAddStreamData(SceInt32 handle, SceUChar8** dst, SceInt32* towrite, SceInt32* srcpos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3NotifyAddStreamData
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
* @param size - number of bytes added to the stream data buffer
|
||||||
|
*
|
||||||
|
* @return 0 if success, < 0 on error.
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3NotifyAddStreamData(SceInt32 handle, SceInt32 size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3CheckStreamDataNeeded
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
*
|
||||||
|
* @return 1 if more stream data is needed, < 0 on error.
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3CheckStreamDataNeeded(SceInt32 handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3SetLoopNum
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
* @param loop - Number of loops
|
||||||
|
*
|
||||||
|
* @return 0 if success, < 0 on error.
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3SetLoopNum(SceInt32 handle, SceInt32 loop);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3GetLoopNum
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
*
|
||||||
|
* @return Number of loops
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3GetLoopNum(SceInt32 handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3GetSumDecodedSample
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
*
|
||||||
|
* @return Number of decoded samples
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3GetSumDecodedSample(SceInt32 handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3GetMaxOutputSample
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
*
|
||||||
|
* @return Number of max samples to output
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3GetMaxOutputSample(SceInt32 handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3GetSamplingRate
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
*
|
||||||
|
* @return Sampling rate of the mp3
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3GetSamplingRate(SceInt32 handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3GetBitRate
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
*
|
||||||
|
* @return Bitrate of the mp3
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3GetBitRate(SceInt32 handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3GetMp3ChannelNum
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
*
|
||||||
|
* @return Number of channels of the mp3
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3GetMp3ChannelNum(SceInt32 handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3ResetPlayPosition
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
*
|
||||||
|
* @return < 0 on error
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3ResetPlayPosition(SceInt32 handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3GetFrameNum
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
*
|
||||||
|
* @return < 0 on error
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3GetFrameNum(SceInt32 handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3ResetPlayPositionByFrame
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
* @param frame - frame
|
||||||
|
*
|
||||||
|
* @return < 0 on error
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3ResetPlayPositionByFrame(SceInt32 handle, SceUInt32 frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3GetMPEGVersion
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
*
|
||||||
|
* @return < 0 on error
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3GetMPEGVersion(SceInt32 handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3LowLevelInit
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
* @param src - Pointer to a buffer to contain raw mp3 stream data
|
||||||
|
*
|
||||||
|
* @return < 0 on error
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3LowLevelInit(SceInt32 handle, SceUChar8* src);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sceMp3LowLevelDecode
|
||||||
|
*
|
||||||
|
* @param handle - sceMp3 handle
|
||||||
|
* @param mp3src -
|
||||||
|
* @param mp3srcused -
|
||||||
|
* @param pcmdst -
|
||||||
|
* @param pcmdstoutsz -
|
||||||
|
*
|
||||||
|
* @return < 0 on error
|
||||||
|
*/
|
||||||
|
SceInt32 sceMp3LowLevelDecode(SceInt32 handle, SceUChar8* mp3src, SceUInt32* mp3srcused, SceShort16* pcmdst, SceUInt32* pcmdstoutsz);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
29
engine/platform/psp/scemp3/sceMp3.S
Normal file
29
engine/platform/psp/scemp3/sceMp3.S
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
.set noreorder
|
||||||
|
|
||||||
|
#include "pspimport.s"
|
||||||
|
|
||||||
|
IMPORT_START "sceMp3",0x00090011
|
||||||
|
IMPORT_FUNC "sceMp3",0x07EC321A,sceMp3ReserveMp3Handle
|
||||||
|
IMPORT_FUNC "sceMp3",0x0DB149F4,sceMp3NotifyAddStreamData
|
||||||
|
IMPORT_FUNC "sceMp3",0x2A368661,sceMp3ResetPlayPosition
|
||||||
|
IMPORT_FUNC "sceMp3",0x354D27EA,sceMp3GetSumDecodedSample
|
||||||
|
IMPORT_FUNC "sceMp3",0x35750070,sceMp3InitResource
|
||||||
|
IMPORT_FUNC "sceMp3",0x3C2FA058,sceMp3TermResource
|
||||||
|
IMPORT_FUNC "sceMp3",0x3CEF484F,sceMp3SetLoopNum
|
||||||
|
IMPORT_FUNC "sceMp3",0x44E07129,sceMp3Init
|
||||||
|
IMPORT_FUNC "sceMp3",0x732B042A,sceMp3EndEntry
|
||||||
|
IMPORT_FUNC "sceMp3",0x7F696782,sceMp3GetMp3ChannelNum
|
||||||
|
IMPORT_FUNC "sceMp3",0x87677E40,sceMp3GetBitRate
|
||||||
|
IMPORT_FUNC "sceMp3",0x87C263D1,sceMp3GetMaxOutputSample
|
||||||
|
IMPORT_FUNC "sceMp3",0x8AB81558,sceMp3StartEntry
|
||||||
|
IMPORT_FUNC "sceMp3",0x8F450998,sceMp3GetSamplingRate
|
||||||
|
IMPORT_FUNC "sceMp3",0xA703FE0F,sceMp3GetInfoToAddStreamData
|
||||||
|
IMPORT_FUNC "sceMp3",0xD021C0FB,sceMp3Decode
|
||||||
|
IMPORT_FUNC "sceMp3",0xD0A56296,sceMp3CheckStreamDataNeeded
|
||||||
|
IMPORT_FUNC "sceMp3",0xD8F54A51,sceMp3GetLoopNum
|
||||||
|
IMPORT_FUNC "sceMp3",0xF5478233,sceMp3ReleaseMp3Handle
|
||||||
|
IMPORT_FUNC "sceMp3",0xAE6D2027,sceMp3GetMPEGVersion
|
||||||
|
IMPORT_FUNC "sceMp3",0x3548AEC8,sceMp3GetFrameNum
|
||||||
|
IMPORT_FUNC "sceMp3",0x0840E808,sceMp3ResetPlayPositionByFrame
|
||||||
|
IMPORT_FUNC "sceMp3",0x1B839B83,sceMp3LowLevelInit
|
||||||
|
IMPORT_FUNC "sceMp3",0xE3EE2C81,sceMp3LowLevelDecode
|
||||||
275
engine/platform/psp/snd_psp.c
Normal file
275
engine/platform/psp/snd_psp.c
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
/*
|
||||||
|
snd_psp.c - psp sound hardware output
|
||||||
|
Copyright (C) 2022 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "platform/platform.h"
|
||||||
|
#if XASH_SOUND == SOUND_PSP
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
#include <pspaudio.h>
|
||||||
|
#include <pspkernel.h>
|
||||||
|
#include <pspdmac.h>
|
||||||
|
|
||||||
|
#include "sound.h"
|
||||||
|
|
||||||
|
#define PSP_NUM_AUDIO_SAMPLES 1024 // must be multiple of 64
|
||||||
|
#define PSP_OUTPUT_CHANNELS 2
|
||||||
|
#define PSP_OUTPUT_BUFFER_SIZE (( PSP_NUM_AUDIO_SAMPLES ) * ( PSP_OUTPUT_CHANNELS ))
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
SceUID threadUID;
|
||||||
|
SceUID semaUID;
|
||||||
|
int channel;
|
||||||
|
volatile int volL;
|
||||||
|
volatile int volR;
|
||||||
|
volatile int running;
|
||||||
|
} snd_psp = { -1, -1, -1, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, 1 };
|
||||||
|
|
||||||
|
static short snd_psp_buff[2][PSP_OUTPUT_BUFFER_SIZE] __attribute__(( aligned( 64 )));
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
SNDDMA_MainThread
|
||||||
|
|
||||||
|
Copy samples
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
static int SNDDMA_MainThread( SceSize args, void *argp )
|
||||||
|
{
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
while( snd_psp.running )
|
||||||
|
{
|
||||||
|
sceKernelWaitSema( snd_psp.semaUID, 1, NULL );
|
||||||
|
|
||||||
|
int len = PSP_OUTPUT_BUFFER_SIZE;
|
||||||
|
int size = dma.samples;
|
||||||
|
int pos = dma.samplepos;
|
||||||
|
int wrapped = pos + len - size;
|
||||||
|
|
||||||
|
if( wrapped < 0 )
|
||||||
|
{
|
||||||
|
sceDmacMemcpy( snd_psp_buff[index], dma.buffer + ( pos * 2 ), len * 2 );
|
||||||
|
dma.samplepos += len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int remaining = size - pos;
|
||||||
|
sceDmacMemcpy( snd_psp_buff[index], dma.buffer + ( pos * 2 ), remaining * 2 );
|
||||||
|
if( wrapped > 0 )
|
||||||
|
sceDmacMemcpy( snd_psp_buff[index] + ( remaining * 2 ), dma.buffer, wrapped * 2 );
|
||||||
|
dma.samplepos = wrapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
sceKernelSignalSema( snd_psp.semaUID, 1 );
|
||||||
|
|
||||||
|
sceAudioOutputPannedBlocking( snd_psp.channel, snd_psp.volL, snd_psp.volR, snd_psp_buff[index] );
|
||||||
|
index = !index;
|
||||||
|
}
|
||||||
|
|
||||||
|
sceKernelExitThread( 0 );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
SNDDMA_Init
|
||||||
|
|
||||||
|
Try to find a sound device to mix for.
|
||||||
|
Returns false if nothing is found.
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
qboolean SNDDMA_Init( void )
|
||||||
|
{
|
||||||
|
int samplecount;
|
||||||
|
|
||||||
|
dma.format.speed = SOUND_DMA_SPEED;
|
||||||
|
dma.format.channels = PSP_OUTPUT_CHANNELS;
|
||||||
|
dma.format.width = 2;
|
||||||
|
|
||||||
|
// must be multiple of 64
|
||||||
|
samplecount = s_samplecount->value;
|
||||||
|
if( !samplecount )
|
||||||
|
samplecount = 0x4000;
|
||||||
|
|
||||||
|
dma.samples = samplecount * PSP_OUTPUT_CHANNELS;
|
||||||
|
dma.samplepos = 0;
|
||||||
|
dma.buffer = memalign( 64, dma.samples * 2 ); // 16 bit
|
||||||
|
if( !dma.buffer )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// clearing buffers
|
||||||
|
memset( dma.buffer, 0, dma.samples * 2 );
|
||||||
|
memset( snd_psp_buff, 0, sizeof( snd_psp_buff ));
|
||||||
|
|
||||||
|
// allocate and initialize a hardware output channel
|
||||||
|
snd_psp.channel = sceAudioChReserve( PSP_AUDIO_NEXT_CHANNEL,
|
||||||
|
PSP_NUM_AUDIO_SAMPLES, PSP_AUDIO_FORMAT_STEREO );
|
||||||
|
if( snd_psp.channel < 0 )
|
||||||
|
{
|
||||||
|
SNDDMA_Shutdown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create semaphore
|
||||||
|
snd_psp.semaUID = sceKernelCreateSema( "sound_sema", 0, 1, 255, NULL );
|
||||||
|
if( snd_psp.semaUID <= 0 )
|
||||||
|
{
|
||||||
|
SNDDMA_Shutdown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create audio thread
|
||||||
|
snd_psp.threadUID = sceKernelCreateThread( "sound_thread", SNDDMA_MainThread, 0x12, 0x8000, 0, 0 );
|
||||||
|
if( snd_psp.threadUID < 0 )
|
||||||
|
{
|
||||||
|
SNDDMA_Shutdown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start audio thread
|
||||||
|
if( sceKernelStartThread( snd_psp.threadUID, 0, 0 ) < 0 )
|
||||||
|
{
|
||||||
|
SNDDMA_Shutdown();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Con_Printf( "Using PSP audio driver: %d Hz\n", dma.format.speed );
|
||||||
|
|
||||||
|
dma.initialized = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
SNDDMA_GetDMAPos
|
||||||
|
|
||||||
|
return the current sample position (in mono samples read)
|
||||||
|
inside the recirculating dma buffer, so the mixing code will know
|
||||||
|
how many sample are required to fill it up.
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
int SNDDMA_GetDMAPos( void )
|
||||||
|
{
|
||||||
|
return dma.samplepos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
SNDDMA_GetSoundtime
|
||||||
|
|
||||||
|
update global soundtime
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
int SNDDMA_GetSoundtime( void )
|
||||||
|
{
|
||||||
|
static int buffers, oldsamplepos;
|
||||||
|
int samplepos, fullsamples;
|
||||||
|
|
||||||
|
fullsamples = dma.samples / 2;
|
||||||
|
|
||||||
|
// it is possible to miscount buffers
|
||||||
|
// if it has wrapped twice between
|
||||||
|
// calls to S_Update. Oh well.
|
||||||
|
samplepos = SNDDMA_GetDMAPos();
|
||||||
|
|
||||||
|
if( samplepos < oldsamplepos )
|
||||||
|
{
|
||||||
|
buffers++; // buffer wrapped
|
||||||
|
|
||||||
|
if( paintedtime > 0x40000000 )
|
||||||
|
{
|
||||||
|
// time to chop things off to avoid 32 bit limits
|
||||||
|
buffers = 0;
|
||||||
|
paintedtime = fullsamples;
|
||||||
|
S_StopAllSounds( true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oldsamplepos = samplepos;
|
||||||
|
|
||||||
|
return ( buffers * fullsamples + samplepos / 2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
SNDDMA_BeginPainting
|
||||||
|
|
||||||
|
Makes sure dma.buffer is valid
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
void SNDDMA_BeginPainting( void )
|
||||||
|
{
|
||||||
|
if( snd_psp.semaUID > 0 )
|
||||||
|
sceKernelWaitSema( snd_psp.semaUID, 1, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
SNDDMA_Submit
|
||||||
|
|
||||||
|
Send sound to device if buffer isn't really the dma buffer
|
||||||
|
Also unlocks the dsound buffer
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
void SNDDMA_Submit( void )
|
||||||
|
{
|
||||||
|
if( snd_psp.semaUID > 0 )
|
||||||
|
sceKernelSignalSema( snd_psp.semaUID, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
SNDDMA_Shutdown
|
||||||
|
|
||||||
|
Reset the sound device for exiting
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
void SNDDMA_Shutdown( void )
|
||||||
|
{
|
||||||
|
Con_Printf("Shutting down audio.\n");
|
||||||
|
|
||||||
|
snd_psp.running = 0;
|
||||||
|
|
||||||
|
if( snd_psp.threadUID >= 0 )
|
||||||
|
{
|
||||||
|
sceKernelWaitThreadEnd( snd_psp.threadUID, NULL );
|
||||||
|
sceKernelDeleteThread( snd_psp.threadUID );
|
||||||
|
snd_psp.threadUID = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( snd_psp.semaUID > 0 )
|
||||||
|
{
|
||||||
|
sceKernelDeleteSema( snd_psp.semaUID );
|
||||||
|
snd_psp.semaUID = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( snd_psp.channel >= 0 )
|
||||||
|
{
|
||||||
|
sceAudioChRelease( snd_psp.channel );
|
||||||
|
snd_psp.channel = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( dma.buffer )
|
||||||
|
{
|
||||||
|
free( dma.buffer );
|
||||||
|
dma.buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dma.initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // XASH_SOUND == SOUND_PSP
|
||||||
353
engine/platform/psp/sys_psp.c
Normal file
353
engine/platform/psp/sys_psp.c
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
/*
|
||||||
|
sys_psp.c - PSP System utils
|
||||||
|
Copyright (C) 2021 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "platform/platform.h"
|
||||||
|
#include "platform/psp/ka/ka.h"
|
||||||
|
#include "platform/psp/scemp3/pspmp3.h"
|
||||||
|
#include <pspsdk.h>
|
||||||
|
#include <pspkernel.h>
|
||||||
|
#include <psppower.h>
|
||||||
|
#include <psprtc.h>
|
||||||
|
#include <pspprof.h>
|
||||||
|
#include <pspctrl.h>
|
||||||
|
#include <psputility.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
|
PSP_MODULE_INFO( "Xash3D", PSP_MODULE_USER, 1, 0 );
|
||||||
|
PSP_MAIN_THREAD_ATTR( PSP_THREAD_ATTR_USER | PSP_THREAD_ATTR_VFPU );
|
||||||
|
PSP_MAIN_THREAD_STACK_SIZE_KB( 512 );
|
||||||
|
PSP_HEAP_SIZE_KB( -3 * 1024 ); /* 3 MB for prx modules */
|
||||||
|
|
||||||
|
static qboolean psp_audiolib_init = false;
|
||||||
|
|
||||||
|
static int Platform_ExitCallback( int count, int arg, void *common )
|
||||||
|
{
|
||||||
|
host.crashed = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Platform_PowerCallback( int count, int arg, void *common )
|
||||||
|
{
|
||||||
|
P5Ram_PowerCallback( count, arg, common );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Platform_CallbackThread( SceSize args, void *argp )
|
||||||
|
{
|
||||||
|
int cbid;
|
||||||
|
|
||||||
|
//cbid = sceKernelCreateCallback( "Exit Callback", Platform_ExitCallback, NULL );
|
||||||
|
//sceKernelRegisterExitCallback( cbid );
|
||||||
|
|
||||||
|
cbid = sceKernelCreateCallback( "Power Callback", Platform_PowerCallback, NULL );
|
||||||
|
scePowerRegisterCallback( 0, cbid );
|
||||||
|
|
||||||
|
sceKernelSleepThreadCB();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sets up the callback thread and returns its thread id */
|
||||||
|
static int Platform_SetupCallbacks( void )
|
||||||
|
{
|
||||||
|
int thid = 0;
|
||||||
|
|
||||||
|
thid = sceKernelCreateThread("update_thread", Platform_CallbackThread, 0x11, 0xFA0, 0, 0);
|
||||||
|
if(thid >= 0)
|
||||||
|
{
|
||||||
|
sceKernelStartThread(thid, 0, 0);
|
||||||
|
}
|
||||||
|
return thid;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if XASH_TIMER == TIMER_PSP
|
||||||
|
double Platform_DoubleTime( void )
|
||||||
|
{
|
||||||
|
return ( double )sceKernelGetSystemTimeWide() * 0.000001; // microseconds to seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_Sleep( int msec )
|
||||||
|
{
|
||||||
|
sceKernelDelayThread( msec * 1000 );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *Platform_GetNativeObject( const char *name )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_Vibrate( float life, char flags )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_GetClipboardText( char *buffer, size_t size )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_SetClipboardText( const char *buffer, size_t size )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_ShellExecute( const char *path, const char *parms )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if XASH_MESSAGEBOX == MSGBOX_PSP
|
||||||
|
void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow )
|
||||||
|
{
|
||||||
|
static qboolean g_dbgscreen = false;
|
||||||
|
|
||||||
|
// Clear the sound buffer.
|
||||||
|
S_StopAllSounds( true );
|
||||||
|
|
||||||
|
// Print message to the debug screen.
|
||||||
|
if ( !g_dbgscreen )
|
||||||
|
{
|
||||||
|
pspDebugScreenInit();
|
||||||
|
g_dbgscreen = true;
|
||||||
|
}
|
||||||
|
pspDebugScreenSetTextColor( 0x0080ff );
|
||||||
|
pspDebugScreenPrintf( "\n\n\n\n%s:\n", title );
|
||||||
|
pspDebugScreenSetTextColor( 0x0000ff );
|
||||||
|
pspDebugScreenPrintData( message, Q_strlen( message ) );
|
||||||
|
pspDebugScreenSetTextColor( 0xffffff );
|
||||||
|
pspDebugScreenPrintf( "\n\nPress X to continue.\n" );
|
||||||
|
|
||||||
|
// Wait for a X button press.
|
||||||
|
SceCtrlData pad;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
sceCtrlReadBufferPositive( &pad, 1 );
|
||||||
|
}
|
||||||
|
while( !( pad.Buttons & PSP_CTRL_CROSS ) );
|
||||||
|
pspDebugScreenClear();
|
||||||
|
}
|
||||||
|
#endif // XASH_MESSAGEBOX == MSGBOX_PSP
|
||||||
|
|
||||||
|
void Platform_ReadCmd( const char *fname, int *argc, char **argv )
|
||||||
|
{
|
||||||
|
int cmd_fd;
|
||||||
|
size_t cmd_fsize;
|
||||||
|
byte *cmd_buff;
|
||||||
|
int i, j = 0;
|
||||||
|
|
||||||
|
cmd_fd = sceIoOpen( fname, PSP_O_RDONLY, 0777 );
|
||||||
|
if( cmd_fd > 0 )
|
||||||
|
{
|
||||||
|
cmd_fsize = sceIoLseek( cmd_fd, 0, PSP_SEEK_END );
|
||||||
|
sceIoLseek( cmd_fd, 0, PSP_SEEK_SET );
|
||||||
|
|
||||||
|
printf( "CMD FILE(%s) Size: %i\n", fname, cmd_fsize );
|
||||||
|
|
||||||
|
if( cmd_fsize == 0 ) return;
|
||||||
|
|
||||||
|
cmd_buff = malloc( cmd_fsize );
|
||||||
|
if( !cmd_buff )
|
||||||
|
{
|
||||||
|
printf( "CMD FILE(%s) Memory allocation error!\n", fname );
|
||||||
|
sceIoClose(cmd_fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sceIoRead(cmd_fd, cmd_buff, cmd_fsize) >= 0 )
|
||||||
|
{
|
||||||
|
for( i = 0; i < cmd_fsize; i++ )
|
||||||
|
{
|
||||||
|
if( isspace( cmd_buff[i] ) != 0 )
|
||||||
|
{
|
||||||
|
if( j == 0 ) continue;
|
||||||
|
|
||||||
|
argv[*argc] = malloc( j + 1 );
|
||||||
|
if( !argv[*argc] )
|
||||||
|
{
|
||||||
|
printf( "CMD FILE(%s) Memory allocation error!\n", fname );
|
||||||
|
free( cmd_buff );
|
||||||
|
sceIoClose( cmd_fd );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy( argv[*argc], &cmd_buff[i - j], j );
|
||||||
|
argv[*argc][j] = 0x00;
|
||||||
|
( int )( *argc )++;
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
else j++;
|
||||||
|
|
||||||
|
}
|
||||||
|
if( j != 0 )
|
||||||
|
{
|
||||||
|
argv[*argc] = malloc( j + 1 );
|
||||||
|
if( !argv[*argc] )
|
||||||
|
{
|
||||||
|
printf( "CMD FILE(%s) Memory allocation error!\n", fname );
|
||||||
|
free( cmd_buff );
|
||||||
|
sceIoClose( cmd_fd );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy( argv[*argc], &cmd_buff[i - j], j );
|
||||||
|
argv[*argc][j] = 0x00;
|
||||||
|
( int )( *argc )++;
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else printf( "CMD FILE(%s) Read error!\n", fname );
|
||||||
|
|
||||||
|
free( cmd_buff );
|
||||||
|
sceIoClose( cmd_fd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SceUID Platform_LoadModule( const char *filename, int mpid, SceSize argsize, void *argp )
|
||||||
|
{
|
||||||
|
SceKernelLMOption option;
|
||||||
|
SceUID modid = 0;
|
||||||
|
int retVal = 0, mresult;
|
||||||
|
|
||||||
|
memset( &option, 0, sizeof( option ) );
|
||||||
|
option.size = sizeof( option );
|
||||||
|
option.mpidtext = mpid;
|
||||||
|
option.mpiddata = mpid;
|
||||||
|
option.position = 0;
|
||||||
|
option.access = 1;
|
||||||
|
|
||||||
|
retVal = sceKernelLoadModule( filename, 0, &option );
|
||||||
|
if(retVal < 0)
|
||||||
|
return retVal;
|
||||||
|
|
||||||
|
modid = retVal;
|
||||||
|
|
||||||
|
retVal = sceKernelStartModule( modid, argsize, argp, &mresult, NULL );
|
||||||
|
if( retVal < 0 )
|
||||||
|
return retVal;
|
||||||
|
|
||||||
|
return modid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Platform_UnloadModule( SceUID modid, int *sce_code )
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
*sce_code = sceKernelStopModule( modid, 0, NULL, &status, NULL);
|
||||||
|
|
||||||
|
if( ( *sce_code ) < 0 )
|
||||||
|
return -2;
|
||||||
|
else if( status == SCE_KERNEL_ERROR_NOT_STOPPED )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*sce_code = sceKernelUnloadModule( modid );
|
||||||
|
return ( ( ( *sce_code ) < 0 ) ? -2 : 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
int Platform_InitAudioLibs( void )
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if( psp_audiolib_init )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
status = sceUtilityLoadModule( PSP_MODULE_AV_AVCODEC );
|
||||||
|
if ( status < 0 )
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "sceUtilityLoadModule(PSP_MODULE_AV_AVCODEC) returned 0x%08X\n", status );
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = sceUtilityLoadModule( PSP_MODULE_AV_MP3 );
|
||||||
|
if ( status < 0 )
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "sceUtilityLoadModule(PSP_MODULE_AV_MP3) returned 0x%08X\n", status );
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init mp3 resources
|
||||||
|
status = sceMp3InitResource();
|
||||||
|
if ( status < 0 )
|
||||||
|
{
|
||||||
|
Con_DPrintf( S_ERROR "sceMp3InitResource returned 0x%08X\n", status );
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
psp_audiolib_init = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Platform_ShutdownAudioLibs( void )
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if( !psp_audiolib_init )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
status = sceMp3TermResource();
|
||||||
|
if ( status < 0 )
|
||||||
|
Con_DPrintf( S_ERROR "sceMp3TermResource returned 0x%08X\n", status );
|
||||||
|
|
||||||
|
status = sceUtilityUnloadModule( PSP_MODULE_AV_MP3 );
|
||||||
|
if ( status < 0 )
|
||||||
|
Con_DPrintf( S_ERROR "sceUtilityUnloadModule(PSP_MODULE_AV_MP3) returned 0x%08X\n", status );
|
||||||
|
|
||||||
|
status = sceUtilityUnloadModule( PSP_MODULE_AV_AVCODEC );
|
||||||
|
if ( status < 0 )
|
||||||
|
Con_DPrintf( S_ERROR "sceUtilityUnloadModule(PSP_MODULE_AV_AVCODEC) returned 0x%08X\n", status );
|
||||||
|
|
||||||
|
psp_audiolib_init = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_Init( void )
|
||||||
|
{
|
||||||
|
SceUID kamID;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
// disable fpu exceptions (division by zero and etc...)
|
||||||
|
pspSdkDisableFPUExceptions();
|
||||||
|
|
||||||
|
// exit callback thread
|
||||||
|
Platform_SetupCallbacks();
|
||||||
|
|
||||||
|
// set max cpu/gpu frequency
|
||||||
|
scePowerSetClockFrequency( 333, 333, 166 );
|
||||||
|
|
||||||
|
// set max VRAM
|
||||||
|
kamID = Platform_LoadModule( "ka.prx", 1, 0, NULL );
|
||||||
|
if( kamID >= 0 )
|
||||||
|
{
|
||||||
|
result = kaGeEdramGetHwSize();
|
||||||
|
if( result > 0 )
|
||||||
|
result = kaGeEdramSetSize( result );
|
||||||
|
Platform_UnloadModule( kamID, &result );
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform_InitAudioLibs();
|
||||||
|
|
||||||
|
// P5 Ram init
|
||||||
|
P5Ram_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform_Shutdown( void )
|
||||||
|
{
|
||||||
|
P5Ram_Shutdown();
|
||||||
|
Platform_ShutdownAudioLibs();
|
||||||
|
#if XASH_PROFILING
|
||||||
|
gprof_cleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
384
engine/platform/psp/vid_psp.c
Normal file
384
engine/platform/psp/vid_psp.c
Normal file
@@ -0,0 +1,384 @@
|
|||||||
|
/*
|
||||||
|
vid_psp.c - PSP video component
|
||||||
|
Copyright (C) 2021 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#if XASH_VIDEO == VIDEO_PSP
|
||||||
|
|
||||||
|
#if !XASH_DEDICATED
|
||||||
|
#include <pspkernel.h>
|
||||||
|
#include <pspdisplay.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "client.h"
|
||||||
|
#include "mod_local.h"
|
||||||
|
#include "input.h"
|
||||||
|
#include "vid_common.h"
|
||||||
|
|
||||||
|
// Set frame buffer
|
||||||
|
#define PSP_FB_WIDTH 480
|
||||||
|
#define PSP_FB_HEIGHT 272
|
||||||
|
#define PSP_FB_BWIDTH 512
|
||||||
|
#define PSP_FB_FORMAT PSP_DISPLAY_PIXEL_FORMAT_565 //4444,5551,565,8888
|
||||||
|
|
||||||
|
#if PSP_FB_FORMAT == PSP_DISPLAY_PIXEL_FORMAT_4444
|
||||||
|
#define PSP_FB_BPP 2
|
||||||
|
#elif PSP_FB_FORMAT == PSP_DISPLAY_PIXEL_FORMAT_5551
|
||||||
|
#define PSP_FB_BPP 2
|
||||||
|
#elif PSP_FB_FORMAT == PSP_DISPLAY_PIXEL_FORMAT_565
|
||||||
|
#define PSP_FB_BPP 2
|
||||||
|
#elif PSP_FB_FORMAT == PSP_DISPLAY_PIXEL_FORMAT_8888
|
||||||
|
#define PSP_FB_BPP 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Set up screen scaling
|
||||||
|
#define PSP_WIDTH_AR 30
|
||||||
|
#define PSP_HEIGHT_AR 17
|
||||||
|
#define PSP_MIN_MAR 12
|
||||||
|
#define PSP_MAX_MAR 16
|
||||||
|
#define PSP_MIN_MAR_W (PSP_WIDTH_AR * PSP_MIN_MAR)
|
||||||
|
#define PSP_MIN_MAR_H (PSP_HEIGHT_AR * PSP_MIN_MAR)
|
||||||
|
#define PSP_MAX_MAR_W (PSP_WIDTH_AR * PSP_MAX_MAR)
|
||||||
|
#define PSP_MAX_MAR_H (PSP_HEIGHT_AR * PSP_MAX_MAR)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static qboolean vsync;
|
||||||
|
#if 1
|
||||||
|
static vidmode_t vidmodes[] = { "480x272", PSP_FB_WIDTH, PSP_FB_HEIGHT};
|
||||||
|
static int num_vidmodes = 1;
|
||||||
|
#else
|
||||||
|
static vidmode_t *vidmodes = NULL;
|
||||||
|
static int num_vidmodes = 0;
|
||||||
|
#endif
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
int in_width, in_height;
|
||||||
|
int out_width, out_height;
|
||||||
|
#endif
|
||||||
|
void *draw_buffer;
|
||||||
|
void *disp_buffer;
|
||||||
|
}vid_psp;
|
||||||
|
|
||||||
|
qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b )
|
||||||
|
{
|
||||||
|
*stride = PSP_FB_BWIDTH;
|
||||||
|
*r = 31;
|
||||||
|
*g = 63 << 5;
|
||||||
|
*b = 31 << 11;
|
||||||
|
*bpp = 2;
|
||||||
|
|
||||||
|
vid_psp.draw_buffer = (void*)malloc( PSP_FB_HEIGHT * PSP_FB_BWIDTH * PSP_FB_BPP );
|
||||||
|
if( !vid_psp.draw_buffer )
|
||||||
|
Host_Error( "Memory allocation failled! (vid_psp.draw_buffer)\n");
|
||||||
|
|
||||||
|
vid_psp.disp_buffer = (void*)malloc( PSP_FB_HEIGHT * PSP_FB_BWIDTH * PSP_FB_BPP );
|
||||||
|
if( !vid_psp.disp_buffer )
|
||||||
|
Host_Error( "Memory allocation failled! (vid_psp.disp_buffer)\n");
|
||||||
|
|
||||||
|
sceDisplaySetMode(0, PSP_FB_WIDTH, PSP_FB_HEIGHT);
|
||||||
|
sceDisplaySetFrameBuf(vid_psp.disp_buffer, PSP_FB_BWIDTH, PSP_FB_FORMAT, 1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *SW_LockBuffer( void )
|
||||||
|
{
|
||||||
|
return vid_psp.draw_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SW_UnlockBuffer( void )
|
||||||
|
{
|
||||||
|
void* p_swap = vid_psp.disp_buffer;
|
||||||
|
vid_psp.disp_buffer = vid_psp.draw_buffer;
|
||||||
|
vid_psp.draw_buffer = p_swap;
|
||||||
|
|
||||||
|
sceKernelDcacheWritebackInvalidateAll();
|
||||||
|
sceDisplaySetFrameBuf(vid_psp.disp_buffer, PSP_FB_BWIDTH, PSP_FB_FORMAT, PSP_DISPLAY_SETBUF_NEXTFRAME);
|
||||||
|
|
||||||
|
if ( vsync )
|
||||||
|
{
|
||||||
|
sceDisplayWaitVblankStart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int R_MaxVideoModes( void )
|
||||||
|
{
|
||||||
|
return num_vidmodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
vidmode_t *R_GetVideoMode( int num )
|
||||||
|
{
|
||||||
|
if( !vidmodes || num < 0 || num >= R_MaxVideoModes() )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vidmodes + num;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
static void R_InitVideoModes( void )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
vidmodes = Mem_Malloc( host.mempool, (PSP_MAX_MAR - PSP_MIN_MAR) * sizeof( vidmode_t ) );
|
||||||
|
|
||||||
|
// from smallest to largest
|
||||||
|
for(i = PSP_MIN_MAR ; i <= PSP_MAX_MAR; i++ )
|
||||||
|
{
|
||||||
|
vidmodes[num_vidmodes].width = PSP_WIDTH_AR * i;
|
||||||
|
vidmodes[num_vidmodes].height = PSP_HEIGHT_AR * i;
|
||||||
|
vidmodes[num_vidmodes].desc =
|
||||||
|
copystring( va( "%ix%i", vidmodes[num_vidmodes].width, vidmodes[num_vidmodes].height ));
|
||||||
|
|
||||||
|
num_vidmodes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void R_FreeVideoModes( void )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(!vidmodes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for( i = 0; i < num_vidmodes; i++ )
|
||||||
|
Mem_Free( (char*)vidmodes[i].desc );
|
||||||
|
Mem_Free( vidmodes );
|
||||||
|
|
||||||
|
vidmodes = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_GetProcAddress
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void *GL_GetProcAddress( const char *name )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
GL_UpdateSwapInterval
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
void GL_UpdateSwapInterval( void )
|
||||||
|
{
|
||||||
|
// disable VSync while level is loading
|
||||||
|
if( cls.state < ca_active )
|
||||||
|
{
|
||||||
|
// setup vsync here
|
||||||
|
vsync = false;
|
||||||
|
SetBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||||
|
}
|
||||||
|
else if( FBitSet( gl_vsync->flags, FCVAR_CHANGED ))
|
||||||
|
{
|
||||||
|
ClearBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||||
|
vsync = (gl_vsync->value > 0) ? true : false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static qboolean VID_SetScreenResolution( int width, int height )
|
||||||
|
{
|
||||||
|
int render_w = width, render_h = height;
|
||||||
|
uint rotate = vid_rotate->value;
|
||||||
|
|
||||||
|
if( ref.dllFuncs.R_SetDisplayTransform( rotate, 0, 0, vid_scale->value, vid_scale->value ) )
|
||||||
|
{
|
||||||
|
if( rotate & 1 )
|
||||||
|
{
|
||||||
|
int swap = render_w;
|
||||||
|
|
||||||
|
render_w = render_h;
|
||||||
|
render_h = swap;
|
||||||
|
}
|
||||||
|
|
||||||
|
render_h /= vid_scale->value;
|
||||||
|
render_w /= vid_scale->value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Con_Printf( S_WARN "failed to setup screen transform\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R_SaveVideoMode( width, height, render_w, render_h );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_SwapBuffers( void )
|
||||||
|
{
|
||||||
|
if ( vsync ) sceDisplayWaitVblankStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GL_SetAttribute( int attr, int val )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GL_GetAttribute( int attr, int *val )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
R_Init_Video
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
qboolean R_Init_Video( const int type )
|
||||||
|
{
|
||||||
|
string safe;
|
||||||
|
qboolean retval;
|
||||||
|
|
||||||
|
refState.desktopBitsPixel = ( PSP_FB_BPP * 8 );
|
||||||
|
|
||||||
|
VID_StartupGamma();
|
||||||
|
|
||||||
|
switch( type )
|
||||||
|
{
|
||||||
|
case REF_SOFTWARE:
|
||||||
|
glw_state.software = true;
|
||||||
|
break;
|
||||||
|
case REF_GL:
|
||||||
|
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", safe ) )
|
||||||
|
glw_state.safe = bound( SAFE_NO, Q_atoi( safe ), SAFE_DONTCARE );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Host_Error( "Can't initialize unknown context type %d!\n", type );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !(retval = VID_SetMode()) )
|
||||||
|
{
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( type )
|
||||||
|
{
|
||||||
|
case REF_GL:
|
||||||
|
// refdll also can check extensions
|
||||||
|
ref.dllFuncs.GL_InitExtensions();
|
||||||
|
break;
|
||||||
|
case REF_SOFTWARE:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
R_InitVideoModes();
|
||||||
|
#endif
|
||||||
|
host.renderinfo_changed = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
rserr_t R_ChangeDisplaySettings( int width, int height, qboolean fullscreen )
|
||||||
|
{
|
||||||
|
Con_Reportf( "R_ChangeDisplaySettings: Setting video mode to %dx%d %s\n", width, height, fullscreen ? "fullscreen" : "windowed" );
|
||||||
|
|
||||||
|
refState.fullScreen = fullscreen;
|
||||||
|
|
||||||
|
if( !VID_SetScreenResolution( width, height ) )
|
||||||
|
return rserr_invalid_fullscreen;
|
||||||
|
|
||||||
|
return rserr_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
VID_SetMode
|
||||||
|
|
||||||
|
Set the described video mode
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
qboolean VID_SetMode( void )
|
||||||
|
{
|
||||||
|
qboolean fullscreen = false;
|
||||||
|
int iScreenWidth, iScreenHeight;
|
||||||
|
rserr_t err;
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
iScreenWidth = PSP_FB_WIDTH;
|
||||||
|
iScreenHeight = PSP_FB_HEIGHT;
|
||||||
|
#else
|
||||||
|
vid_psp.out_width = PSP_FB_WIDTH;
|
||||||
|
vid_psp.out_height = PSP_FB_HEIGHT;
|
||||||
|
|
||||||
|
iScreenWidth = Cvar_VariableInteger( "width" );
|
||||||
|
iScreenHeight = Cvar_VariableInteger( "height" );
|
||||||
|
|
||||||
|
if( iScreenWidth < PSP_MIN_MAR_W ||
|
||||||
|
iScreenHeight < PSP_MIN_MAR_H ) // trying to get resolution automatically by default
|
||||||
|
{
|
||||||
|
iScreenWidth = PSP_MIN_MAR_W;
|
||||||
|
iScreenHeight = PSP_MIN_MAR_H;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( iScreenWidth > PSP_MAX_MAR_W ||
|
||||||
|
iScreenHeight > PSP_MAX_MAR_H ) // trying to get resolution automatically by default
|
||||||
|
{
|
||||||
|
iScreenWidth = PSP_MAX_MAR_W;
|
||||||
|
iScreenHeight = PSP_MAX_MAR_H;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if( !FBitSet( vid_fullscreen->flags, FCVAR_CHANGED ) )
|
||||||
|
Cvar_SetValue( "fullscreen", DEFAULT_FULLSCREEN );
|
||||||
|
else
|
||||||
|
ClearBits( vid_fullscreen->flags, FCVAR_CHANGED );
|
||||||
|
|
||||||
|
SetBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||||
|
fullscreen = true;//Cvar_VariableInteger("fullscreen") != 0;
|
||||||
|
|
||||||
|
if(( err = R_ChangeDisplaySettings( iScreenWidth, iScreenHeight, fullscreen )) == rserr_ok )
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
vid_psp.in_width = iScreenWidth;
|
||||||
|
vid_psp.in_height = iScreenHeight;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
R_Free_Video
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void R_Free_Video( void )
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
R_FreeVideoModes();
|
||||||
|
#endif
|
||||||
|
ref.dllFuncs.GL_ClearExtensions();
|
||||||
|
if( glw_state.software )
|
||||||
|
{
|
||||||
|
if( vid_psp.draw_buffer )
|
||||||
|
free( vid_psp.draw_buffer );
|
||||||
|
if( vid_psp.disp_buffer )
|
||||||
|
free( vid_psp.disp_buffer );
|
||||||
|
|
||||||
|
vid_psp.draw_buffer = NULL;
|
||||||
|
vid_psp.disp_buffer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // XASH_DEDICATED
|
||||||
|
#endif // XASH_VIDEO
|
||||||
@@ -446,6 +446,11 @@ typedef struct ref_api_s
|
|||||||
|
|
||||||
// filesystem exports
|
// filesystem exports
|
||||||
fs_api_t *fsapi;
|
fs_api_t *fsapi;
|
||||||
|
|
||||||
|
#if XASH_PSP
|
||||||
|
void *(*P5Ram_Alloc)( size_t size, int clear );
|
||||||
|
void (*P5Ram_Free)( void *ptr );
|
||||||
|
#endif
|
||||||
} ref_api_t;
|
} ref_api_t;
|
||||||
|
|
||||||
struct mip_s;
|
struct mip_s;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ extern int SV_UPDATE_BACKUP;
|
|||||||
#define GROUP_OP_AND 0
|
#define GROUP_OP_AND 0
|
||||||
#define GROUP_OP_NAND 1
|
#define GROUP_OP_NAND 1
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#if defined( NDEBUG )
|
||||||
#define SV_IsValidEdict( e ) ( e && !e->free )
|
#define SV_IsValidEdict( e ) ( e && !e->free )
|
||||||
#else
|
#else
|
||||||
#define SV_IsValidEdict( e ) SV_CheckEdict( e, __FILE__, __LINE__ )
|
#define SV_IsValidEdict( e ) SV_CheckEdict( e, __FILE__, __LINE__ )
|
||||||
@@ -509,7 +509,13 @@ qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multipla
|
|||||||
qboolean SV_InitGame( void );
|
qboolean SV_InitGame( void );
|
||||||
void SV_ActivateServer( int runPhysics );
|
void SV_ActivateServer( int runPhysics );
|
||||||
qboolean SV_SpawnServer( const char *server, const char *startspot, qboolean background );
|
qboolean SV_SpawnServer( const char *server, const char *startspot, qboolean background );
|
||||||
model_t *SV_ModelHandle( int modelindex );
|
static inline model_t *GAME_EXPORT SV_ModelHandle( int modelindex )
|
||||||
|
{
|
||||||
|
if( unlikely( modelindex < 0 || modelindex >= MAX_MODELS ))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return sv.models[modelindex];
|
||||||
|
}
|
||||||
void SV_DeactivateServer( void );
|
void SV_DeactivateServer( void );
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -648,10 +654,17 @@ void SV_RestartAmbientSounds( void );
|
|||||||
void SV_RestartDecals( void );
|
void SV_RestartDecals( void );
|
||||||
void SV_RestartStaticEnts( void );
|
void SV_RestartStaticEnts( void );
|
||||||
int pfnDropToFloor( edict_t* e );
|
int pfnDropToFloor( edict_t* e );
|
||||||
edict_t *SV_EdictNum( int n );
|
|
||||||
void SV_SetModel( edict_t *ent, const char *name );
|
void SV_SetModel( edict_t *ent, const char *name );
|
||||||
int pfnDecalIndex( const char *m );
|
int pfnDecalIndex( const char *m );
|
||||||
|
|
||||||
|
static inline edict_t *SV_EdictNum( int n )
|
||||||
|
{
|
||||||
|
if( unlikely( n < 0 || n >= GI->max_edicts ))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &svgame.edicts[n];
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// sv_log.c
|
// sv_log.c
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -39,13 +39,6 @@ static vec3_t viewPoint[MAX_CLIENTS];
|
|||||||
typedef void (__cdecl *LINK_ENTITY_FUNC)( entvars_t *pev );
|
typedef void (__cdecl *LINK_ENTITY_FUNC)( entvars_t *pev );
|
||||||
typedef void (__stdcall *GIVEFNPTRSTODLL)( enginefuncs_t* engfuncs, globalvars_t *pGlobals );
|
typedef void (__stdcall *GIVEFNPTRSTODLL)( enginefuncs_t* engfuncs, globalvars_t *pGlobals );
|
||||||
|
|
||||||
edict_t *SV_EdictNum( int n )
|
|
||||||
{
|
|
||||||
if(( n >= 0 ) && ( n < GI->max_edicts ))
|
|
||||||
return svgame.edicts + n;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
qboolean SV_CheckEdict( const edict_t *e, const char *file, const int line )
|
qboolean SV_CheckEdict( const edict_t *e, const char *file, const int line )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -262,20 +262,6 @@ int GAME_EXPORT SV_GenericIndex( const char *filename )
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
================
|
|
||||||
SV_ModelHandle
|
|
||||||
|
|
||||||
get model by handle
|
|
||||||
================
|
|
||||||
*/
|
|
||||||
model_t *GAME_EXPORT SV_ModelHandle( int modelindex )
|
|
||||||
{
|
|
||||||
if( modelindex < 0 || modelindex >= MAX_MODELS )
|
|
||||||
return NULL;
|
|
||||||
return sv.models[modelindex];
|
|
||||||
}
|
|
||||||
|
|
||||||
static resourcetype_t SV_DetermineResourceType( const char *filename )
|
static resourcetype_t SV_DetermineResourceType( const char *filename )
|
||||||
{
|
{
|
||||||
if( !Q_strncmp( filename, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 ) && Sound_SupportedFileFormat( COM_FileExtension( filename )))
|
if( !Q_strncmp( filename, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 ) && Sound_SupportedFileFormat( COM_FileExtension( filename )))
|
||||||
|
|||||||
@@ -945,12 +945,12 @@ static edict_t *SV_PushMove( edict_t *pusher, float movetime )
|
|||||||
// filter movetypes to collide with
|
// filter movetypes to collide with
|
||||||
if( !SV_CanPushed( check ))
|
if( !SV_CanPushed( check ))
|
||||||
continue;
|
continue;
|
||||||
|
#if !XASH_PSP
|
||||||
pusher->v.solid = SOLID_NOT;
|
pusher->v.solid = SOLID_NOT;
|
||||||
block = SV_TestEntityPosition( check, pusher );
|
block = SV_TestEntityPosition( check, pusher );
|
||||||
pusher->v.solid = oldsolid;
|
pusher->v.solid = oldsolid;
|
||||||
if( block ) continue;
|
if( block ) continue;
|
||||||
|
#endif
|
||||||
// if the entity is standing on the pusher, it will definately be moved
|
// if the entity is standing on the pusher, it will definately be moved
|
||||||
if( !( FBitSet( check->v.flags, FL_ONGROUND ) && check->v.groundentity == pusher ))
|
if( !( FBitSet( check->v.flags, FL_ONGROUND ) && check->v.groundentity == pusher ))
|
||||||
{
|
{
|
||||||
@@ -966,7 +966,12 @@ static edict_t *SV_PushMove( edict_t *pusher, float movetime )
|
|||||||
if( !SV_TestEntityPosition( check, NULL ))
|
if( !SV_TestEntityPosition( check, NULL ))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#if XASH_PSP
|
||||||
|
pusher->v.solid = SOLID_NOT;
|
||||||
|
block = SV_TestEntityPosition( check, pusher );
|
||||||
|
pusher->v.solid = oldsolid;
|
||||||
|
if( block ) continue;
|
||||||
|
#endif
|
||||||
// remove the onground flag for non-players
|
// remove the onground flag for non-players
|
||||||
if( check->v.movetype != MOVETYPE_WALK )
|
if( check->v.movetype != MOVETYPE_WALK )
|
||||||
check->v.flags &= ~FL_ONGROUND;
|
check->v.flags &= ~FL_ONGROUND;
|
||||||
@@ -1058,18 +1063,19 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
|||||||
for( e = 1; e < svgame.numEntities; e++ )
|
for( e = 1; e < svgame.numEntities; e++ )
|
||||||
{
|
{
|
||||||
check = EDICT_NUM( e );
|
check = EDICT_NUM( e );
|
||||||
|
|
||||||
if( !SV_IsValidEdict( check ))
|
if( !SV_IsValidEdict( check ))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// filter movetypes to collide with
|
// filter movetypes to collide with
|
||||||
if( !SV_CanPushed( check ))
|
if( !SV_CanPushed( check ))
|
||||||
continue;
|
continue;
|
||||||
|
#if !XASH_PSP
|
||||||
pusher->v.solid = SOLID_NOT;
|
pusher->v.solid = SOLID_NOT;
|
||||||
block = SV_TestEntityPosition( check, pusher );
|
block = SV_TestEntityPosition( check, pusher );
|
||||||
pusher->v.solid = oldsolid;
|
pusher->v.solid = oldsolid;
|
||||||
if( block ) continue;
|
if( block ) continue;
|
||||||
|
#endif
|
||||||
// if the entity is standing on the pusher, it will definately be moved
|
// if the entity is standing on the pusher, it will definately be moved
|
||||||
if( !(( check->v.flags & FL_ONGROUND ) && check->v.groundentity == pusher ))
|
if( !(( check->v.flags & FL_ONGROUND ) && check->v.groundentity == pusher ))
|
||||||
{
|
{
|
||||||
@@ -1085,7 +1091,12 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
|||||||
if( !SV_TestEntityPosition( check, NULL ))
|
if( !SV_TestEntityPosition( check, NULL ))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#if XASH_PSP
|
||||||
|
pusher->v.solid = SOLID_NOT;
|
||||||
|
block = SV_TestEntityPosition( check, pusher );
|
||||||
|
pusher->v.solid = oldsolid;
|
||||||
|
if( block ) continue;
|
||||||
|
#endif
|
||||||
// save original position of contacted entity
|
// save original position of contacted entity
|
||||||
pushed_p->ent = check;
|
pushed_p->ent = check;
|
||||||
VectorCopy( check->v.origin, pushed_p->origin );
|
VectorCopy( check->v.origin, pushed_p->origin );
|
||||||
@@ -1101,7 +1112,7 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
|||||||
Matrix4x4_VectorITransform( start_l, org, temp );
|
Matrix4x4_VectorITransform( start_l, org, temp );
|
||||||
Matrix4x4_VectorTransform( end_l, temp, org2 );
|
Matrix4x4_VectorTransform( end_l, temp, org2 );
|
||||||
VectorSubtract( org2, org, lmove );
|
VectorSubtract( org2, org, lmove );
|
||||||
|
|
||||||
// i can't clear FL_ONGROUND in all cases because many bad things may be happen
|
// i can't clear FL_ONGROUND in all cases because many bad things may be happen
|
||||||
if( check->v.movetype != MOVETYPE_WALK )
|
if( check->v.movetype != MOVETYPE_WALK )
|
||||||
{
|
{
|
||||||
@@ -1140,7 +1151,6 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
|||||||
return check;
|
return check;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,11 @@ half-life implementation of saverestore system
|
|||||||
#define SAVEGAME_HEADER (('V'<<24)+('A'<<16)+('S'<<8)+'J') // little-endian "JSAV"
|
#define SAVEGAME_HEADER (('V'<<24)+('A'<<16)+('S'<<8)+'J') // little-endian "JSAV"
|
||||||
#define SAVEGAME_VERSION 0x0071 // Version 0.71 GoldSrc compatible
|
#define SAVEGAME_VERSION 0x0071 // Version 0.71 GoldSrc compatible
|
||||||
#define CLIENT_SAVEGAME_VERSION 0x0067 // Version 0.67
|
#define CLIENT_SAVEGAME_VERSION 0x0067 // Version 0.67
|
||||||
|
#if XASH_PSP
|
||||||
|
#define SAVE_HEAPSIZE 0x200000 // reserve 2Mb for now
|
||||||
|
#else
|
||||||
#define SAVE_HEAPSIZE 0x400000 // reserve 4Mb for now
|
#define SAVE_HEAPSIZE 0x400000 // reserve 4Mb for now
|
||||||
|
#endif
|
||||||
#define SAVE_HASHSTRINGS 0xFFF // 4095 unique strings
|
#define SAVE_HASHSTRINGS 0xFFF // 4095 unique strings
|
||||||
|
|
||||||
// savedata headers
|
// savedata headers
|
||||||
@@ -384,7 +387,13 @@ static void InitEntityTable( SAVERESTOREDATA *pSaveData, int entityCount )
|
|||||||
ENTITYTABLE *pTable;
|
ENTITYTABLE *pTable;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
#if XASH_PSP
|
||||||
|
pSaveData->pTable = P5Ram_Alloc( sizeof( ENTITYTABLE ) * entityCount, 1 );
|
||||||
|
if( !pSaveData->pTable )
|
||||||
|
Host_Error( "%s: P5Ram_Alloc (pSaveData->pTable) failed!", __FUNCTION__ );
|
||||||
|
#else
|
||||||
pSaveData->pTable = Mem_Calloc( host.mempool, sizeof( ENTITYTABLE ) * entityCount );
|
pSaveData->pTable = Mem_Calloc( host.mempool, sizeof( ENTITYTABLE ) * entityCount );
|
||||||
|
#endif
|
||||||
pSaveData->tableCount = entityCount;
|
pSaveData->tableCount = entityCount;
|
||||||
|
|
||||||
// setup entitytable
|
// setup entitytable
|
||||||
@@ -700,8 +709,17 @@ static SAVERESTOREDATA *SaveInit( int size, int tokenCount )
|
|||||||
{
|
{
|
||||||
SAVERESTOREDATA *pSaveData;
|
SAVERESTOREDATA *pSaveData;
|
||||||
|
|
||||||
|
#if XASH_PSP
|
||||||
|
pSaveData = P5Ram_Alloc( sizeof( SAVERESTOREDATA ) + size, 1 );
|
||||||
|
if( !pSaveData )
|
||||||
|
Host_Error( "%s: P5Ram_Alloc (pSaveData) failed!", __FUNCTION__ );
|
||||||
|
pSaveData->pTokens = (char **)P5Ram_Alloc( tokenCount * sizeof( char* ), 1 );
|
||||||
|
if( !pSaveData->pTokens )
|
||||||
|
Host_Error( "%s: P5Ram_Alloc (pSaveData->pTokens) failed!", __FUNCTION__ );
|
||||||
|
#else
|
||||||
pSaveData = Mem_Calloc( host.mempool, sizeof( SAVERESTOREDATA ) + size );
|
pSaveData = Mem_Calloc( host.mempool, sizeof( SAVERESTOREDATA ) + size );
|
||||||
pSaveData->pTokens = (char **)Mem_Calloc( host.mempool, tokenCount * sizeof( char* ));
|
pSaveData->pTokens = (char **)Mem_Calloc( host.mempool, tokenCount * sizeof( char* ));
|
||||||
|
#endif
|
||||||
pSaveData->tokenCount = tokenCount;
|
pSaveData->tokenCount = tokenCount;
|
||||||
|
|
||||||
pSaveData->pBaseData = (char *)(pSaveData + 1); // skip the save structure);
|
pSaveData->pBaseData = (char *)(pSaveData + 1); // skip the save structure);
|
||||||
@@ -750,20 +768,32 @@ static void SaveFinish( SAVERESTOREDATA *pSaveData )
|
|||||||
|
|
||||||
if( pSaveData->pTokens )
|
if( pSaveData->pTokens )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
P5Ram_Free( pSaveData->pTokens );
|
||||||
|
#else
|
||||||
Mem_Free( pSaveData->pTokens );
|
Mem_Free( pSaveData->pTokens );
|
||||||
|
#endif
|
||||||
pSaveData->pTokens = NULL;
|
pSaveData->pTokens = NULL;
|
||||||
pSaveData->tokenCount = 0;
|
pSaveData->tokenCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( pSaveData->pTable )
|
if( pSaveData->pTable )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
P5Ram_Free( pSaveData->pTable );
|
||||||
|
#else
|
||||||
Mem_Free( pSaveData->pTable );
|
Mem_Free( pSaveData->pTable );
|
||||||
|
#endif
|
||||||
pSaveData->pTable = NULL;
|
pSaveData->pTable = NULL;
|
||||||
pSaveData->tableCount = 0;
|
pSaveData->tableCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
svgame.globals->pSaveData = NULL;
|
svgame.globals->pSaveData = NULL;
|
||||||
|
#if XASH_PSP
|
||||||
|
P5Ram_Free( pSaveData );
|
||||||
|
#else
|
||||||
Mem_Free( pSaveData );
|
Mem_Free( pSaveData );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2333,14 +2363,26 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if XASH_PSP
|
||||||
|
pSaveData = (char *)P5Ram_Alloc( size, 0 );
|
||||||
|
if( !pSaveData )
|
||||||
|
Host_Error( "%s: P5Ram_Alloc (pSaveData) failed!", __FUNCTION__ );
|
||||||
|
#else
|
||||||
pSaveData = (char *)Mem_Malloc( host.mempool, size );
|
pSaveData = (char *)Mem_Malloc( host.mempool, size );
|
||||||
|
#endif
|
||||||
FS_Read( f, pSaveData, size );
|
FS_Read( f, pSaveData, size );
|
||||||
pData = pSaveData;
|
pData = pSaveData;
|
||||||
|
|
||||||
// allocate a table for the strings, and parse the table
|
// allocate a table for the strings, and parse the table
|
||||||
if( tokenSize > 0 )
|
if( tokenSize > 0 )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
pTokenList = P5Ram_Alloc( tokenCount * sizeof( char* ), 1 );
|
||||||
|
if( !pTokenList )
|
||||||
|
Host_Error( "%s: P5Ram_Alloc (pTokenList) failed!", __FUNCTION__ );
|
||||||
|
#else
|
||||||
pTokenList = Mem_Calloc( host.mempool, tokenCount * sizeof( char* ));
|
pTokenList = Mem_Calloc( host.mempool, tokenCount * sizeof( char* ));
|
||||||
|
#endif
|
||||||
|
|
||||||
// make sure the token strings pointed to by the pToken hashtable.
|
// make sure the token strings pointed to by the pToken hashtable.
|
||||||
for( i = 0; i < tokenCount; i++ )
|
for( i = 0; i < tokenCount; i++ )
|
||||||
@@ -2352,22 +2394,40 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
|||||||
else pTokenList = NULL;
|
else pTokenList = NULL;
|
||||||
|
|
||||||
// short, short (size, index of field name)
|
// 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;
|
nFieldSize = *(short *)pData;
|
||||||
pData += sizeof( short );
|
pData += sizeof( short );
|
||||||
pFieldName = pTokenList[*(short *)pData];
|
pFieldName = pTokenList[*(short *)pData];
|
||||||
|
#endif
|
||||||
if( Q_stricmp( pFieldName, "GameHeader" ))
|
if( Q_stricmp( pFieldName, "GameHeader" ))
|
||||||
{
|
{
|
||||||
Q_strncpy( comment, "<missing GameHeader>", MAX_STRING );
|
Q_strncpy( comment, "<missing GameHeader>", MAX_STRING );
|
||||||
|
#if XASH_PSP
|
||||||
|
if( pTokenList ) P5Ram_Free( pTokenList );
|
||||||
|
if( pSaveData ) P5Ram_Free( pSaveData );
|
||||||
|
#else
|
||||||
if( pTokenList ) Mem_Free( pTokenList );
|
if( pTokenList ) Mem_Free( pTokenList );
|
||||||
if( pSaveData ) Mem_Free( pSaveData );
|
if( pSaveData ) Mem_Free( pSaveData );
|
||||||
|
#endif
|
||||||
FS_Close( f );
|
FS_Close( f );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int (fieldcount)
|
// int (fieldcount)
|
||||||
pData += sizeof( short );
|
pData += sizeof( short );
|
||||||
|
#if XASH_PSP /* FIX Unaligned access! */
|
||||||
|
memcpy(&nNumberOfFields, pData, sizeof(int));
|
||||||
|
#else
|
||||||
nNumberOfFields = (int)*pData;
|
nNumberOfFields = (int)*pData;
|
||||||
|
#endif
|
||||||
pData += nFieldSize;
|
pData += nFieldSize;
|
||||||
|
|
||||||
// each field is a short (size), short (index of name), binary string of "size" bytes (data)
|
// each field is a short (size), short (index of name), binary string of "size" bytes (data)
|
||||||
@@ -2378,11 +2438,23 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
|||||||
// Size
|
// Size
|
||||||
// szName
|
// szName
|
||||||
// Actual Data
|
// 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;
|
nFieldSize = *(short *)pData;
|
||||||
pData += sizeof( short );
|
pData += sizeof( short );
|
||||||
|
|
||||||
pFieldName = pTokenList[*(short *)pData];
|
pFieldName = pTokenList[*(short *)pData];
|
||||||
pData += sizeof( short );
|
pData += sizeof( short );
|
||||||
|
#endif
|
||||||
|
|
||||||
size = Q_min( nFieldSize, MAX_STRING );
|
size = Q_min( nFieldSize, MAX_STRING );
|
||||||
|
|
||||||
@@ -2400,8 +2472,13 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delete the string table we allocated
|
// delete the string table we allocated
|
||||||
|
#if XASH_PSP
|
||||||
|
if( pTokenList ) P5Ram_Free( pTokenList );
|
||||||
|
if( pSaveData ) P5Ram_Free( pSaveData );
|
||||||
|
#else
|
||||||
if( pTokenList ) Mem_Free( pTokenList );
|
if( pTokenList ) Mem_Free( pTokenList );
|
||||||
if( pSaveData ) Mem_Free( pSaveData );
|
if( pSaveData ) Mem_Free( pSaveData );
|
||||||
|
#endif
|
||||||
FS_Close( f );
|
FS_Close( f );
|
||||||
|
|
||||||
// at least mapname should be filled
|
// at least mapname should be filled
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ typedef enum
|
|||||||
SPR_CULL_NONE, // oriented sprite will be draw back face too
|
SPR_CULL_NONE, // oriented sprite will be draw back face too
|
||||||
} facetype_t;
|
} facetype_t;
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
// generic helper
|
// generic helper
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -133,4 +135,6 @@ typedef struct
|
|||||||
|
|
||||||
STATIC_ASSERT( sizeof( dframetype_t ) == 4, "invalid dframetype_t size" );
|
STATIC_ASSERT( sizeof( dframetype_t ) == 4, "invalid dframetype_t size" );
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
#endif//SPRITE_H
|
#endif//SPRITE_H
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ def configure(conf):
|
|||||||
# then remove them to avoid them getting linked to shared objects
|
# then remove them to avoid them getting linked to shared objects
|
||||||
for lib in extra_libs:
|
for lib in extra_libs:
|
||||||
conf.env.LDFLAGS.remove(lib)
|
conf.env.LDFLAGS.remove(lib)
|
||||||
|
elif conf.env.DEST_OS == 'psp':
|
||||||
|
conf.define('XASH_NO_NETWORK', 1)
|
||||||
elif conf.options.FBDEV_SW:
|
elif conf.options.FBDEV_SW:
|
||||||
# unused, XASH_LINUX without XASH_SDL gives fbdev & alsa support
|
# unused, XASH_LINUX without XASH_SDL gives fbdev & alsa support
|
||||||
# conf.define('XASH_FBDEV', 1)
|
# conf.define('XASH_FBDEV', 1)
|
||||||
@@ -87,7 +89,8 @@ def configure(conf):
|
|||||||
|
|
||||||
if conf.options.STATIC:
|
if conf.options.STATIC:
|
||||||
conf.env.STATIC = True
|
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:
|
if not conf.env.DEST_OS in ['win32', 'android'] and not conf.options.NO_ASYNC_RESOLVE:
|
||||||
conf.check_pthreads()
|
conf.check_pthreads()
|
||||||
@@ -132,16 +135,19 @@ def build(bld):
|
|||||||
'common/*.c',
|
'common/*.c',
|
||||||
'common/imagelib/*.c',
|
'common/imagelib/*.c',
|
||||||
'common/soundlib/*.c',
|
'common/soundlib/*.c',
|
||||||
'common/soundlib/libmpg/*.c',
|
|
||||||
'server/*.c'])
|
'server/*.c'])
|
||||||
|
|
||||||
|
# PSP uses hw MP3 decoder
|
||||||
|
if bld.env.DEST_OS != 'psp':
|
||||||
|
source += bld.path.ant_glob(['common/soundlib/libmpg/*.c'])
|
||||||
|
|
||||||
if bld.env.ENGINE_TESTS:
|
if bld.env.ENGINE_TESTS:
|
||||||
source += bld.path.ant_glob(['tests/*.c'])
|
source += bld.path.ant_glob(['tests/*.c'])
|
||||||
|
|
||||||
if bld.env.DEST_OS == 'win32':
|
if bld.env.DEST_OS == 'win32':
|
||||||
libs += ['USER32', 'SHELL32', 'GDI32', 'ADVAPI32', 'DBGHELP', 'PSAPI', 'WS2_32' ]
|
libs += ['USER32', 'SHELL32', 'GDI32', 'ADVAPI32', 'DBGHELP', 'PSAPI', 'WS2_32' ]
|
||||||
source += bld.path.ant_glob(['platform/win32/*.c'])
|
source += bld.path.ant_glob(['platform/win32/*.c'])
|
||||||
elif bld.env.DEST_OS not in ['dos', 'nswitch', 'psvita']: #posix
|
elif bld.env.DEST_OS not in ['dos', 'nswitch', 'psvita', 'psp']: #posix
|
||||||
libs += [ 'M', 'RT', 'PTHREAD', 'ASOUND']
|
libs += [ 'M', 'RT', 'PTHREAD', 'ASOUND']
|
||||||
if not bld.env.STATIC:
|
if not bld.env.STATIC:
|
||||||
libs += ['DL']
|
libs += ['DL']
|
||||||
@@ -211,6 +217,10 @@ def build(bld):
|
|||||||
'-lSceKernelDmacMgr_stub'
|
'-lSceKernelDmacMgr_stub'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if bld.env.DEST_OS == 'psp':
|
||||||
|
source += bld.path.ant_glob(['platform/psp/*.c'])
|
||||||
|
source += bld.path.ant_glob(['platform/psp/*/*.S'])
|
||||||
|
|
||||||
# add client files
|
# add client files
|
||||||
if not bld.env.DEDICATED:
|
if not bld.env.DEDICATED:
|
||||||
source += bld.path.ant_glob([
|
source += bld.path.ant_glob([
|
||||||
|
|||||||
@@ -121,6 +121,8 @@ const char *Q_PlatformStringByID( const int platform )
|
|||||||
return "nswitch";
|
return "nswitch";
|
||||||
case PLATFORM_PSVITA:
|
case PLATFORM_PSVITA:
|
||||||
return "psvita";
|
return "psvita";
|
||||||
|
case PLATFORM_PSP:
|
||||||
|
return "psp";
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( 0 );
|
assert( 0 );
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ Then you can use another oneliner to query all variables:
|
|||||||
#undef XASH_X86
|
#undef XASH_X86
|
||||||
#undef XASH_NSWITCH
|
#undef XASH_NSWITCH
|
||||||
#undef XASH_PSVITA
|
#undef XASH_PSVITA
|
||||||
|
#undef XASH_PSP
|
||||||
|
|
||||||
//================================================================
|
//================================================================
|
||||||
//
|
//
|
||||||
@@ -98,6 +99,8 @@ Then you can use another oneliner to query all variables:
|
|||||||
#define XASH_EMSCRIPTEN 1
|
#define XASH_EMSCRIPTEN 1
|
||||||
#elif defined __WATCOMC__ && defined __DOS__
|
#elif defined __WATCOMC__ && defined __DOS__
|
||||||
#define XASH_DOS4GW 1
|
#define XASH_DOS4GW 1
|
||||||
|
#elif defined __psp__
|
||||||
|
#define XASH_PSP 1
|
||||||
#else // POSIX compatible
|
#else // POSIX compatible
|
||||||
#define XASH_POSIX 1
|
#define XASH_POSIX 1
|
||||||
#if defined __linux__
|
#if defined __linux__
|
||||||
@@ -144,7 +147,7 @@ Then you can use another oneliner to query all variables:
|
|||||||
// but we still need XASH_MOBILE_PLATFORM for the engine.
|
// but we still need XASH_MOBILE_PLATFORM for the engine.
|
||||||
// So this macro is defined entirely in build-system: see main wscript
|
// So this macro is defined entirely in build-system: see main wscript
|
||||||
// HLSDK/PrimeXT/other SDKs users note: you may ignore this macro
|
// HLSDK/PrimeXT/other SDKs users note: you may ignore this macro
|
||||||
#if XASH_ANDROID || XASH_IOS || XASH_NSWITCH || XASH_PSVITA || XASH_SAILFISH
|
#if XASH_ANDROID || XASH_IOS || XASH_NSWITCH || XASH_PSVITA || XASH_SAILFISH || XASH_PSP
|
||||||
#define XASH_MOBILE_PLATFORM 1
|
#define XASH_MOBILE_PLATFORM 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ GNU General Public License for more details.
|
|||||||
#define PLATFORM_NSWITCH 13
|
#define PLATFORM_NSWITCH 13
|
||||||
#define PLATFORM_PSVITA 14
|
#define PLATFORM_PSVITA 14
|
||||||
#define PLATFORM_LINUX_UNKNOWN 15
|
#define PLATFORM_LINUX_UNKNOWN 15
|
||||||
|
#define PLATFORM_PSP 16
|
||||||
|
|
||||||
#if XASH_WIN32
|
#if XASH_WIN32
|
||||||
#define XASH_PLATFORM PLATFORM_WIN32
|
#define XASH_PLATFORM PLATFORM_WIN32
|
||||||
@@ -73,6 +74,8 @@ GNU General Public License for more details.
|
|||||||
#define XASH_PLATFORM PLATFORM_NSWITCH
|
#define XASH_PLATFORM PLATFORM_NSWITCH
|
||||||
#elif XASH_PSVITA
|
#elif XASH_PSVITA
|
||||||
#define XASH_PLATFORM PLATFORM_PSVITA
|
#define XASH_PLATFORM PLATFORM_PSVITA
|
||||||
|
#elif XASH_PSP
|
||||||
|
#define XASH_PLATFORM PLATFORM_PSP
|
||||||
#else
|
#else
|
||||||
#error
|
#error
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -35,13 +35,61 @@ const matrix3x4 m_matrix3x4_identity =
|
|||||||
*/
|
*/
|
||||||
void Matrix3x4_VectorTransform( const matrix3x4 in, const float v[3], float out[3] )
|
void Matrix3x4_VectorTransform( const matrix3x4 in, const float v[3], float out[3] )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||||
|
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||||
|
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||||
|
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||||
|
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||||
|
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||||
|
"vhdp.q S000, C130, C100\n" // S000 = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3]
|
||||||
|
"vhdp.q S001, C130, C110\n" // S001 = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2] + in[1][3]
|
||||||
|
"vhdp.q S002, C130, C120\n" // S002 = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2] + in[2][3]
|
||||||
|
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||||
|
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||||
|
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *in ), "m"( *v )
|
||||||
|
);
|
||||||
|
#else
|
||||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3];
|
out[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[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];
|
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] )
|
void Matrix3x4_VectorITransform( const matrix3x4 in, const float v[3], float out[3] )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||||
|
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||||
|
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||||
|
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||||
|
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||||
|
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||||
|
"vsub.t C130, C130, R103\n" // C130 = v - in[][3]
|
||||||
|
#if 1
|
||||||
|
"vtfm3.t C000, E100, C130\n" // C000 = E100 * C130
|
||||||
|
#else
|
||||||
|
"vdot.t S000, C130, R100\n" // S000 = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0]
|
||||||
|
"vdot.t S001, C130, R101\n" // S001 = dir[0] * in[0][1] + dir[1] * in[1][1] + dir[2] * in[2][1]
|
||||||
|
"vdot.t S002, C130, R102\n" // S002 = dir[0] * in[0][2] + dir[1] * in[1][2] + dir[2] * in[2][2]
|
||||||
|
#endif
|
||||||
|
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||||
|
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||||
|
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *in ), "m"( *v )
|
||||||
|
);
|
||||||
|
#else
|
||||||
vec3_t dir;
|
vec3_t dir;
|
||||||
|
|
||||||
dir[0] = v[0] - in[0][3];
|
dir[0] = v[0] - in[0][3];
|
||||||
@@ -51,24 +99,99 @@ void Matrix3x4_VectorITransform( const matrix3x4 in, const float v[3], float out
|
|||||||
out[0] = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0];
|
out[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[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];
|
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] )
|
void Matrix3x4_VectorRotate( const matrix3x4 in, const float v[3], float out[3] )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||||
|
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||||
|
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||||
|
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||||
|
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||||
|
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||||
|
#if 1
|
||||||
|
"vtfm3.t C000, M100, C130\n" // C000 = M100 * C130
|
||||||
|
#else
|
||||||
|
"vdot.t S000, C130, C100\n" // S000 = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2]
|
||||||
|
"vdot.t S001, C130, C110\n" // S001 = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2]
|
||||||
|
"vdot.t S002, C130, C120\n" // S002 = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2]
|
||||||
|
#endif
|
||||||
|
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||||
|
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||||
|
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *in ), "m"( *v )
|
||||||
|
);
|
||||||
|
|
||||||
|
#else
|
||||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2];
|
out[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[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];
|
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] )
|
void Matrix3x4_VectorIRotate( const matrix3x4 in, const float v[3], float out[3] )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||||
|
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||||
|
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||||
|
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||||
|
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||||
|
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||||
|
#if 1
|
||||||
|
"vtfm3.t C000, E100, C130\n" // C000 = E100 * C130
|
||||||
|
#else
|
||||||
|
"vdot.t S000, C130, R100\n" // S000 = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0]
|
||||||
|
"vdot.t S001, C130, R101\n" // S001 = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1]
|
||||||
|
"vdot.t S002, C130, R102\n" // S002 = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2]
|
||||||
|
#endif
|
||||||
|
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||||
|
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||||
|
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *in ), "m"( *v )
|
||||||
|
);
|
||||||
|
#else
|
||||||
out[0] = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0];
|
out[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[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];
|
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 )
|
void Matrix3x4_ConcatTransforms( matrix3x4 out, const matrix3x4 in1, const matrix3x4 in2 )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C100, 0 + %1\n" // C100 = in1[0]
|
||||||
|
"lv.q C110, 16 + %1\n" // C110 = in1[1]
|
||||||
|
"lv.q C120, 32 + %1\n" // C120 = in1[2]
|
||||||
|
"vzero.q C130\n" // C130 = [0, 0, 0, 0]
|
||||||
|
"lv.q C200, 0 + %2\n" // C100 = in2[0]
|
||||||
|
"lv.q C210, 16 + %2\n" // C110 = in2[1]
|
||||||
|
"lv.q C220, 32 + %2\n" // C120 = in2[2]
|
||||||
|
"vidt.q C230\n" // C230 = [0, 0, 0, 1]
|
||||||
|
"vmmul.q E000, E100, E200\n" // E000 = E100 * E200
|
||||||
|
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||||
|
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||||
|
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *in1 ), "m"( *in2 )
|
||||||
|
);
|
||||||
|
#else
|
||||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
|
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
|
||||||
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
|
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
|
||||||
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
|
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
|
||||||
@@ -81,6 +204,7 @@ void Matrix3x4_ConcatTransforms( matrix3x4 out, const matrix3x4 in1, const matri
|
|||||||
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
|
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
|
||||||
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
|
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
|
||||||
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
|
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out )
|
void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out )
|
||||||
@@ -105,6 +229,31 @@ void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out )
|
|||||||
|
|
||||||
void Matrix3x4_FromOriginQuat( matrix3x4 out, const vec4_t quaternion, const vec3_t origin )
|
void Matrix3x4_FromOriginQuat( matrix3x4 out, const vec4_t quaternion, const vec3_t origin )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C130, %1\n" // C130 = quaternion
|
||||||
|
"lv.s S300, 0 + %2\n" // S300 = origin[0]
|
||||||
|
"lv.s S301, 4 + %2\n" // S301 = origin[1]
|
||||||
|
"lv.s S302, 8 + %2\n" // S302 = origin[2]
|
||||||
|
"vmov.q C100, C130[ W, Z, -Y, -X]\n" // C100 = ( w, z, -y, -x)
|
||||||
|
"vmov.q C110, C130[-Z, W, X, -Y]\n" // C110 = (-z, w, x, -y)
|
||||||
|
"vmov.q C120, C130[ Y, -X, W, -Z]\n" // C120 = ( y, -x, w, -z)
|
||||||
|
"vmov.q C200, C130[ W, Z, -Y, X]\n" // C200 = ( w, z, -y, x)
|
||||||
|
"vmov.q C210, C130[-Z, W, X, Y]\n" // C210 = (-z, w, x, y)
|
||||||
|
"vmov.q C220, C130[ Y, -X, W, Z]\n" // C220 = ( y, -x, w, z)
|
||||||
|
"vmov.q C230, C130[-X, -Y, -Z, W]\n" // C230 = (-x, -y, -z, w)
|
||||||
|
"vmmul.q M000, E100, E200\n" // M000 = E100 * E200
|
||||||
|
"vmov.t R003, C300\n" // out[x][3] = origin[x]
|
||||||
|
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||||
|
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||||
|
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *quaternion ), "m"( *origin )
|
||||||
|
);
|
||||||
|
#else
|
||||||
out[0][0] = 1.0f - 2.0f * quaternion[1] * quaternion[1] - 2.0f * quaternion[2] * quaternion[2];
|
out[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[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];
|
out[2][0] = 2.0f * quaternion[0] * quaternion[2] - 2.0f * quaternion[3] * quaternion[1];
|
||||||
@@ -120,10 +269,166 @@ void Matrix3x4_FromOriginQuat( matrix3x4 out, const vec4_t quaternion, const vec
|
|||||||
out[0][3] = origin[0];
|
out[0][3] = origin[0];
|
||||||
out[1][3] = origin[1];
|
out[1][3] = origin[1];
|
||||||
out[2][3] = origin[2];
|
out[2][3] = origin[2];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix3x4_CreateFromEntity( matrix3x4 out, const vec3_t angles, const vec3_t origin, float scale )
|
void Matrix3x4_CreateFromEntity( matrix3x4 out, const vec3_t angles, const vec3_t origin, float scale )
|
||||||
{
|
{
|
||||||
|
#if 0/*XASH_PSP*/ /* performance not tested */ /* BUG */
|
||||||
|
if( angles[ROLL] )
|
||||||
|
{
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.s S100, 0 + %1\n" // S100 = angles[PITCH]
|
||||||
|
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||||
|
"lv.s S102, 8 + %1\n" // S102 = angles[ROLL]
|
||||||
|
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||||
|
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||||
|
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||||
|
"lv.s S130, %3\n" // S130 = scale
|
||||||
|
/**/
|
||||||
|
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||||
|
"vscl.t C100, C100, S120\n" // C100 = C100 * S120 = angles * ( 2 / 180 )
|
||||||
|
/**/
|
||||||
|
"vsin.t C110, C100\n" // C110 = sin( C100 ) P Y R
|
||||||
|
"vcos.t C120, C100\n" // C120 = cos( C100 ) P Y R
|
||||||
|
"vneg.t C100, C110\n" // C100 = -C110 = -sin( C100 )
|
||||||
|
/**/
|
||||||
|
"vmul.s S000, S120, S121\n" // S000 = S120 * S121 = out[0][0] = ( cp * cy )
|
||||||
|
"vmul.s S011, S112, S110\n" // S011 = S112 * S110 = ( sr * sp )
|
||||||
|
"vmul.s S001, S011, S121\n" // S001 = S011 * S121 = ( sr * sp * cy )
|
||||||
|
"vmul.s S103, S122, S101\n" // S001 = S122 * S101 = ( cr * -sy )
|
||||||
|
"vadd.s S001, S001, S103\n" // S001 = S001 + S103 = out[0][1] = ( sr * sp * cy + cr * -sy )
|
||||||
|
"vmul.s S012, S122, S110\n" // S002 = S122 * S110 = ( cr * sp )
|
||||||
|
"vmul.s S002, S012, S121\n" // S002 = S012 * S121 = ( cr * sp * cy )
|
||||||
|
"vmul.s S103, S102, S101\n" // S002 = S102 * S101 = ( -sr * -sy )
|
||||||
|
"vadd.s S002, S002, S103\n" // S002 = S002 + S103 = out[0][2] = ( cr * sp * cy + -sr * -sy )
|
||||||
|
/**/
|
||||||
|
"vmul.s S010, S120, S111\n" // S010 = S120 * S111 = out[1][0] = ( cp * sy )
|
||||||
|
"vmul.s S011, S011, S111\n" // S001 = S011 * S111 = ( sr * sp * sy )
|
||||||
|
"vmul.s S103, S122, S121\n" // S001 = S122 * S121 = ( cr * cy )
|
||||||
|
"vadd.s S011, S011, S103\n" // S011 = S011 + S103 = out[1][1] = ( sr * sp * sy + cr * cy )
|
||||||
|
"vmul.s S012, S012, S111\n" // S012 = S012 * S111 = ( cr * sp * sy )
|
||||||
|
"vmul.s S103, S102, S121\n" // S103 = S102 * S121 = ( -sr * cy )
|
||||||
|
"vadd.s S012, S012, S103\n" // S012 = S012 + S103 = out[1][2] = ( cr * sp * sy + -sr * cy )
|
||||||
|
/**/
|
||||||
|
"vmov.s S020, S101\n" // S020 = S101 = out[2][0] = ( -sp )
|
||||||
|
"vmul.s S021, S112, S120\n" // S021 = S112 * S120 = out[2][1] = ( sr * cp )
|
||||||
|
"vmul.s S022, S122, S120\n" // S021 = S122 * S120 = out[2][2] = ( cr * cp )
|
||||||
|
/**/
|
||||||
|
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||||
|
/**/
|
||||||
|
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||||
|
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||||
|
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if( angles[PITCH] )
|
||||||
|
{
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.s S100, 0 + %1\n" // S100 = angles[PITCH]
|
||||||
|
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||||
|
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||||
|
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||||
|
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||||
|
"lv.s S130, %3\n" // S130 = scale
|
||||||
|
/**/
|
||||||
|
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||||
|
"vscl.p C100, C100, S120\n" // C100 = C100 * S120 = angles * ( 2 / 180 )
|
||||||
|
/**/
|
||||||
|
"vsin.p C110, C100\n" // C110 = sin( C100 ) P Y
|
||||||
|
"vcos.p C120, C100\n" // C120 = cos( C100 ) P Y
|
||||||
|
"vneg.p C100, C110\n" // C100 = -C110 = -sin( C100 )
|
||||||
|
/**/
|
||||||
|
"vmul.s S000, S120, S121\n" // S000 = S120 * S121 = out[0][0] = ( cp * cy )
|
||||||
|
"vmov.s S001, S101\n" // S001 = S101 = out[0][1] = ( -sy )
|
||||||
|
"vmul.s S002, S110, S121\n" // S001 = S110 * S121 = out[0][2] = ( sp * cy )
|
||||||
|
/**/
|
||||||
|
"vmul.s S010, S120, S111\n" // S010 = S120 * S111 = out[1][0] = ( cp * sy )
|
||||||
|
"vmov.s S011, S121\n" // S011 = S121 = out[1][1] = ( cy )
|
||||||
|
"vmul.s S012, S110, S111\n" // S012 = S110 * S111 = out[1][2] = ( sp * sy )
|
||||||
|
/**/
|
||||||
|
"vmov.s S020, S100\n" // S020 = S100 = out[2][0] = ( -sp )
|
||||||
|
"vzero.s S021\n" // S021 = out[2][1] = 0.0f
|
||||||
|
"vmov.s S022, S120\n" // S022 = S120 = out[2][2] = ( cp )
|
||||||
|
/**/
|
||||||
|
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||||
|
/**/
|
||||||
|
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||||
|
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||||
|
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if( angles[YAW] )
|
||||||
|
{
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||||
|
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||||
|
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||||
|
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||||
|
"lv.s S130, %3\n" // S130 = scale
|
||||||
|
/**/
|
||||||
|
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||||
|
"vmul.s S101, S101, S120\n" // S101 = S101 * S120 = angles[YAW] * ( 2 / 180 )
|
||||||
|
/**/
|
||||||
|
"vsin.s S111, S101\n" // S111 = sin( S101 ) Y
|
||||||
|
"vcos.s S121, S101\n" // S121 = cos( S101 ) Y
|
||||||
|
/**/
|
||||||
|
"vzero.p R002\n" // S002 = 0.0f S012 = 0.0f
|
||||||
|
"vzero.p C020\n" // S020 = 0.0f S021 = 0.0f
|
||||||
|
"vmov.s S000, S121\n" // S000 = S121 = out[0][0] = ( cy )
|
||||||
|
"vneg.s S001, S111\n" // S001 = S111 = out[0][1] = ( -sy )
|
||||||
|
"vmov.s S010, S111\n" // S010 = S111 = out[1][0] = ( sy )
|
||||||
|
"vmov.s S011, S121\n" // S011 = S121 = out[1][1] = ( cy )
|
||||||
|
"vone.s S022\n" // S022 = out[2][2] = 1.0f
|
||||||
|
/**/
|
||||||
|
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||||
|
/**/
|
||||||
|
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||||
|
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||||
|
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.s S003, 0 + %1\n" // S003 = out[0][3] = origin[0]
|
||||||
|
"lv.s S013, 4 + %1\n" // S013 = out[1][3] = origin[1]
|
||||||
|
"lv.s S023, 8 + %1\n" // S023 = out[2][3] = origin[2]
|
||||||
|
"lv.s S130, %2\n" // S130 = scale
|
||||||
|
/**/
|
||||||
|
"vzero.t C000\n" // C000 = [0.0f, 0.0f, 0.0f]
|
||||||
|
"vzero.t C010\n" // C010 = [0.0f, 0.0f, 0.0f]
|
||||||
|
"vzero.t C020\n" // C020 = [0.0f, 0.0f, 0.0f]
|
||||||
|
"vmov.s S000, S130\n" // S000 = S130 = out[0][0] = scale
|
||||||
|
"vmov.s S011, S130\n" // S011 = S130 = out[1][1] = scale
|
||||||
|
"vmov.s S022, S130\n" // S022 = S130 = out[2][2] = scale
|
||||||
|
/**/
|
||||||
|
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||||
|
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||||
|
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *origin ), "m"( scale )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#else
|
||||||
float angle, sr, sp, sy, cr, cp, cy;
|
float angle, sr, sp, sy, cr, cp, cy;
|
||||||
|
|
||||||
if( angles[ROLL] )
|
if( angles[ROLL] )
|
||||||
@@ -201,6 +506,7 @@ void Matrix3x4_CreateFromEntity( matrix3x4 out, const vec3_t angles, const vec3_
|
|||||||
out[2][2] = scale;
|
out[2][2] = scale;
|
||||||
out[2][3] = origin[2];
|
out[2][3] = origin[2];
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -242,13 +548,61 @@ const matrix4x4 m_matrix4x4_identity =
|
|||||||
*/
|
*/
|
||||||
void Matrix4x4_VectorTransform( const matrix4x4 in, const float v[3], float out[3] )
|
void Matrix4x4_VectorTransform( const matrix4x4 in, const float v[3], float out[3] )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||||
|
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||||
|
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||||
|
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||||
|
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||||
|
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||||
|
"vhdp.q S000, C130, C100\n" // S000 = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3]
|
||||||
|
"vhdp.q S001, C130, C110\n" // S001 = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2] + in[1][3]
|
||||||
|
"vhdp.q S002, C130, C120\n" // S002 = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2] + in[2][3]
|
||||||
|
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||||
|
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||||
|
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *in ), "m"( *v )
|
||||||
|
);
|
||||||
|
#else
|
||||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3];
|
out[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[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];
|
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] )
|
void Matrix4x4_VectorITransform( const matrix4x4 in, const float v[3], float out[3] )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||||
|
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||||
|
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||||
|
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||||
|
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||||
|
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||||
|
"vsub.t C130, C130, R103\n" // C130 = v - in[][3]
|
||||||
|
#if 1
|
||||||
|
"vtfm3.t C000, E100, C130\n" // C000 = E100 * C130
|
||||||
|
#else
|
||||||
|
"vdot.t S000, C130, R100\n" // S000 = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0]
|
||||||
|
"vdot.t S001, C130, R101\n" // S001 = dir[0] * in[0][1] + dir[1] * in[1][1] + dir[2] * in[2][1]
|
||||||
|
"vdot.t S002, C130, R102\n" // S002 = dir[0] * in[0][2] + dir[1] * in[1][2] + dir[2] * in[2][2]
|
||||||
|
#endif
|
||||||
|
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||||
|
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||||
|
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *in ), "m"( *v )
|
||||||
|
);
|
||||||
|
#else
|
||||||
vec3_t dir;
|
vec3_t dir;
|
||||||
|
|
||||||
dir[0] = v[0] - in[0][3];
|
dir[0] = v[0] - in[0][3];
|
||||||
@@ -258,24 +612,99 @@ void Matrix4x4_VectorITransform( const matrix4x4 in, const float v[3], float out
|
|||||||
out[0] = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0];
|
out[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[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];
|
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] )
|
void Matrix4x4_VectorRotate( const matrix4x4 in, const float v[3], float out[3] )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||||
|
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||||
|
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||||
|
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||||
|
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||||
|
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||||
|
#if 1
|
||||||
|
"vtfm3.t C000, M100, C130\n" // C000 = M100 * C130
|
||||||
|
#else
|
||||||
|
"vdot.t S000, C130, C100\n" // S000 = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2]
|
||||||
|
"vdot.t S001, C130, C110\n" // S001 = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2]
|
||||||
|
"vdot.t S002, C130, C120\n" // S002 = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2]
|
||||||
|
#endif
|
||||||
|
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||||
|
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||||
|
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *in ), "m"( *v )
|
||||||
|
);
|
||||||
|
#else
|
||||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2];
|
out[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[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];
|
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] )
|
void Matrix4x4_VectorIRotate( const matrix4x4 in, const float v[3], float out[3] )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||||
|
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||||
|
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||||
|
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||||
|
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||||
|
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||||
|
#if 1
|
||||||
|
"vtfm3.t C000, E100, C130\n" // C000 = E100 * C130
|
||||||
|
#else
|
||||||
|
"vdot.t S000, C130, R100\n" // S000 = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0]
|
||||||
|
"vdot.t S001, C130, R101\n" // S001 = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1]
|
||||||
|
"vdot.t S002, C130, R102\n" // S002 = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2]
|
||||||
|
#endif
|
||||||
|
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||||
|
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||||
|
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *in ), "m"( *v )
|
||||||
|
);
|
||||||
|
#else
|
||||||
out[0] = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0];
|
out[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[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];
|
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 )
|
void Matrix4x4_ConcatTransforms( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C100, 0 + %1\n" // C100 = in1[0]
|
||||||
|
"lv.q C110, 16 + %1\n" // C110 = in1[1]
|
||||||
|
"lv.q C120, 32 + %1\n" // C120 = in1[2]
|
||||||
|
"vzero.q C130\n" // C130 = [0, 0, 0, 0]
|
||||||
|
"lv.q C200, 0 + %2\n" // C100 = in2[0]
|
||||||
|
"lv.q C210, 16 + %2\n" // C110 = in2[1]
|
||||||
|
"lv.q C220, 32 + %2\n" // C120 = in2[2]
|
||||||
|
"vidt.q C230\n" // C230 = [0, 0, 0, 1]
|
||||||
|
"vmmul.q E000, E100, E200\n" // E000 = E100 * E200
|
||||||
|
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||||
|
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||||
|
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *in1 ), "m"( *in2 )
|
||||||
|
);
|
||||||
|
#else
|
||||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
|
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
|
||||||
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
|
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
|
||||||
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
|
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
|
||||||
@@ -288,10 +717,174 @@ void Matrix4x4_ConcatTransforms( matrix4x4 out, const matrix4x4 in1, const matri
|
|||||||
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
|
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
|
||||||
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
|
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
|
||||||
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
|
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_t origin, float scale )
|
void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_t origin, float scale )
|
||||||
{
|
{
|
||||||
|
#if 0/*XASH_PSP*/ /* performance not tested */ /* BUG */
|
||||||
|
if( angles[ROLL] )
|
||||||
|
{
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.s S100, 0 + %1\n" // S100 = angles[PITCH]
|
||||||
|
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||||
|
"lv.s S102, 8 + %1\n" // S102 = angles[ROLL]
|
||||||
|
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||||
|
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||||
|
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||||
|
"lv.s S130, %3\n" // S130 = scale
|
||||||
|
/**/
|
||||||
|
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||||
|
"vscl.t C100, C100, S120\n" // C100 = C100 * S120 = angles * ( 2 / 180 )
|
||||||
|
/**/
|
||||||
|
"vsin.t C110, C100\n" // C110 = sin( C100 ) P Y R
|
||||||
|
"vcos.t C120, C100\n" // C120 = cos( C100 ) P Y R
|
||||||
|
"vneg.t C100, C110\n" // C100 = -C110 = -sin( C100 )
|
||||||
|
/**/
|
||||||
|
"vmul.s S000, S120, S121\n" // S000 = S120 * S121 = out[0][0] = ( cp * cy )
|
||||||
|
"vmul.s S011, S112, S110\n" // S011 = S112 * S110 = ( sr * sp )
|
||||||
|
"vmul.s S001, S011, S121\n" // S001 = S011 * S121 = ( sr * sp * cy )
|
||||||
|
"vmul.s S103, S122, S101\n" // S001 = S122 * S101 = ( cr * -sy )
|
||||||
|
"vadd.s S001, S001, S103\n" // S001 = S001 + S103 = out[0][1] = ( sr * sp * cy + cr * -sy )
|
||||||
|
"vmul.s S012, S122, S110\n" // S002 = S122 * S110 = ( cr * sp )
|
||||||
|
"vmul.s S002, S012, S121\n" // S002 = S012 * S121 = ( cr * sp * cy )
|
||||||
|
"vmul.s S103, S102, S101\n" // S002 = S102 * S101 = ( -sr * -sy )
|
||||||
|
"vadd.s S002, S002, S103\n" // S002 = S002 + S103 = out[0][2] = ( cr * sp * cy + -sr * -sy )
|
||||||
|
/**/
|
||||||
|
"vmul.s S010, S120, S111\n" // S010 = S120 * S111 = out[1][0] = ( cp * sy )
|
||||||
|
"vmul.s S011, S011, S111\n" // S001 = S011 * S111 = ( sr * sp * sy )
|
||||||
|
"vmul.s S103, S122, S121\n" // S001 = S122 * S121 = ( cr * cy )
|
||||||
|
"vadd.s S011, S011, S103\n" // S011 = S011 + S103 = out[1][1] = ( sr * sp * sy + cr * cy )
|
||||||
|
"vmul.s S012, S012, S111\n" // S012 = S012 * S111 = ( cr * sp * sy )
|
||||||
|
"vmul.s S103, S102, S121\n" // S103 = S102 * S121 = ( -sr * cy )
|
||||||
|
"vadd.s S012, S012, S103\n" // S012 = S012 + S103 = out[1][2] = ( cr * sp * sy + -sr * cy )
|
||||||
|
/**/
|
||||||
|
"vmov.s S020, S101\n" // S020 = S101 = out[2][0] = ( -sp )
|
||||||
|
"vmul.s S021, S112, S120\n" // S021 = S112 * S120 = out[2][1] = ( sr * cp )
|
||||||
|
"vmul.s S022, S122, S120\n" // S021 = S122 * S120 = out[2][2] = ( cr * cp )
|
||||||
|
/**/
|
||||||
|
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||||
|
"vidt.q C030\n" // C030 = [0.0f, 0.0f, 0.0f, 1.0f]
|
||||||
|
/**/
|
||||||
|
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||||
|
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||||
|
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||||
|
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if( angles[PITCH] )
|
||||||
|
{
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.s S100, 0 + %1\n" // S100 = angles[PITCH]
|
||||||
|
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||||
|
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||||
|
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||||
|
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||||
|
"lv.s S130, %3\n" // S130 = scale
|
||||||
|
/**/
|
||||||
|
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||||
|
"vscl.p C100, C100, S120\n" // C100 = C100 * S120 = angles * ( 2 / 180 )
|
||||||
|
/**/
|
||||||
|
"vsin.p C110, C100\n" // C110 = sin( C100 ) P Y
|
||||||
|
"vcos.p C120, C100\n" // C120 = cos( C100 ) P Y
|
||||||
|
"vneg.p C100, C110\n" // C100 = -C110 = -sin( C100 )
|
||||||
|
/**/
|
||||||
|
"vmul.s S000, S120, S121\n" // S000 = S120 * S121 = out[0][0] = ( cp * cy )
|
||||||
|
"vmov.s S001, S101\n" // S001 = S101 = out[0][1] = ( -sy )
|
||||||
|
"vmul.s S002, S110, S121\n" // S001 = S110 * S121 = out[0][2] = ( sp * cy )
|
||||||
|
/**/
|
||||||
|
"vmul.s S010, S120, S111\n" // S010 = S120 * S111 = out[1][0] = ( cp * sy )
|
||||||
|
"vmov.s S011, S121\n" // S011 = S121 = out[1][1] = ( cy )
|
||||||
|
"vmul.s S012, S110, S111\n" // S012 = S110 * S111 = out[1][2] = ( sp * sy )
|
||||||
|
/**/
|
||||||
|
"vmov.s S020, S100\n" // S020 = S100 = out[2][0] = ( -sp )
|
||||||
|
"vzero.s S021\n" // S021 = out[2][1] = 0.0f
|
||||||
|
"vmov.s S022, S120\n" // S022 = S120 = out[2][2] = ( cp )
|
||||||
|
/**/
|
||||||
|
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||||
|
"vidt.q C030\n" // C030 = [0.0f, 0.0f, 0.0f, 1.0f]
|
||||||
|
/**/
|
||||||
|
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||||
|
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||||
|
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||||
|
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if( angles[YAW] )
|
||||||
|
{
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||||
|
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||||
|
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||||
|
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||||
|
"lv.s S130, %3\n" // S130 = scale
|
||||||
|
/**/
|
||||||
|
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||||
|
"vmul.s S101, S101, S120\n" // S101 = S101 * S120 = angles[YAW] * ( 2 / 180 )
|
||||||
|
/**/
|
||||||
|
"vsin.s S111, S101\n" // S111 = sin( S101 ) Y
|
||||||
|
"vcos.s S121, S101\n" // S121 = cos( S101 ) Y
|
||||||
|
/**/
|
||||||
|
"vzero.p R002\n" // S002 = 0.0f S012 = 0.0f
|
||||||
|
"vzero.p C020\n" // S020 = 0.0f S021 = 0.0f
|
||||||
|
"vmov.s S000, S121\n" // S000 = S121 = out[0][0] = ( cy )
|
||||||
|
"vneg.s S001, S111\n" // S001 = S111 = out[0][1] = ( -sy )
|
||||||
|
"vmov.s S010, S111\n" // S010 = S111 = out[1][0] = ( sy )
|
||||||
|
"vmov.s S011, S121\n" // S011 = S121 = out[1][1] = ( cy )
|
||||||
|
"vone.s S022\n" // S022 = out[2][2] = 1.0f
|
||||||
|
/**/
|
||||||
|
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||||
|
"vidt.q C030\n" // C030 = [0.0f, 0.0f, 0.0f, 1.0f]
|
||||||
|
/**/
|
||||||
|
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||||
|
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||||
|
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||||
|
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.s S003, 0 + %1\n" // S003 = out[0][3] = origin[0]
|
||||||
|
"lv.s S013, 4 + %1\n" // S013 = out[1][3] = origin[1]
|
||||||
|
"lv.s S023, 8 + %1\n" // S023 = out[2][3] = origin[2]
|
||||||
|
"lv.s S130, %2\n" // S130 = scale
|
||||||
|
/**/
|
||||||
|
"vzero.t C000\n" // C000 = [0.0f, 0.0f, 0.0f]
|
||||||
|
"vzero.t C010\n" // C010 = [0.0f, 0.0f, 0.0f]
|
||||||
|
"vzero.t C020\n" // C020 = [0.0f, 0.0f, 0.0f]
|
||||||
|
"vidt.q C030\n" // C030 = [0.0f, 0.0f, 0.0f, 1.0f]
|
||||||
|
"vmov.s S000, S130\n" // S000 = S130 = out[0][0] = scale
|
||||||
|
"vmov.s S011, S130\n" // S011 = S130 = out[1][1] = scale
|
||||||
|
"vmov.s S022, S130\n" // S022 = S130 = out[2][2] = scale
|
||||||
|
/**/
|
||||||
|
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||||
|
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||||
|
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||||
|
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *origin ), "m"( scale )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#else
|
||||||
float angle, sr, sp, sy, cr, cp, cy;
|
float angle, sr, sp, sy, cr, cp, cy;
|
||||||
|
|
||||||
if( angles[ROLL] )
|
if( angles[ROLL] )
|
||||||
@@ -385,6 +978,7 @@ void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_
|
|||||||
out[3][2] = 0.0f;
|
out[3][2] = 0.0f;
|
||||||
out[3][3] = 1.0f;
|
out[3][3] = 1.0f;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Matrix4x4_ConvertToEntity( const matrix4x4 in, vec3_t angles, vec3_t origin )
|
void Matrix4x4_ConvertToEntity( const matrix4x4 in, vec3_t angles, vec3_t origin )
|
||||||
@@ -412,6 +1006,36 @@ void Matrix4x4_ConvertToEntity( const matrix4x4 in, vec3_t angles, vec3_t origin
|
|||||||
|
|
||||||
void Matrix4x4_TransformPositivePlane( const matrix4x4 in, const vec3_t normal, float d, vec3_t out, float *dist )
|
void Matrix4x4_TransformPositivePlane( const matrix4x4 in, const vec3_t normal, float d, vec3_t out, float *dist )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"mfc1 $8, %4\n" // FPU->CPU
|
||||||
|
"mtv $8, S210\n" // CPU->VFPU S210 = d
|
||||||
|
"lv.q C100, 0 + %2\n" // C100 = in[0]
|
||||||
|
"lv.q C110, 16 + %2\n" // C110 = in[1]
|
||||||
|
"lv.q C120, 32 + %2\n" // C120 = in[2]
|
||||||
|
"lv.s S200, 0 + %3\n" // S200 = normal[0]
|
||||||
|
"lv.s S201, 4 + %3\n" // S201 = normal[1]
|
||||||
|
"lv.s S202, 8 + %3\n" // S202 = normal[2]
|
||||||
|
"vdot.t S211, C100, C100\n" // S211 = C100 * C100
|
||||||
|
"vsqrt.s S211, S211\n" // S211 = sqrt( S211 )
|
||||||
|
"vrcp.s S212, S211\n" // S212 = 1 / S211
|
||||||
|
"vtfm3.t C000, M100, C200\n" // C000 = M100 * C200
|
||||||
|
"vscl.t C000, C000, S212\n" // C000 = C000 * S211
|
||||||
|
"vmul.s S003, S210, S211\n" // S003 = S210 * S211
|
||||||
|
"vdot.t S010, R103, C000\n" // S010 = R103 * C000
|
||||||
|
"vadd.s S003, S003, S010\n" // S003 = S003 + S010
|
||||||
|
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||||
|
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||||
|
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||||
|
"sv.s S003, %1\n" // dist = S003
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out ), "=m"( *dist )
|
||||||
|
: "m"( *in ), "m"( *normal ), "f"( d )
|
||||||
|
: "$8"
|
||||||
|
);
|
||||||
|
#else
|
||||||
float scale = sqrt( in[0][0] * in[0][0] + in[0][1] * in[0][1] + in[0][2] * in[0][2] );
|
float 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;
|
float iscale = 1.0f / scale;
|
||||||
|
|
||||||
@@ -419,6 +1043,7 @@ void Matrix4x4_TransformPositivePlane( const matrix4x4 in, const vec3_t normal,
|
|||||||
out[1] = (normal[0] * in[1][0] + normal[1] * in[1][1] + normal[2] * in[1][2]) * iscale;
|
out[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;
|
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] );
|
*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 )
|
void Matrix4x4_Invert_Simple( matrix4x4 out, const matrix4x4 in1 )
|
||||||
|
|||||||
0
public/rbtree.h
Normal file
0
public/rbtree.h
Normal file
@@ -16,7 +16,7 @@ def configure(conf):
|
|||||||
|
|
||||||
def build(bld):
|
def build(bld):
|
||||||
bld(name = 'sdk_includes', export_includes = '. ../common ../pm_shared ../engine')
|
bld(name = 'sdk_includes', export_includes = '. ../common ../pm_shared ../engine')
|
||||||
bld.stlib(source = bld.path.ant_glob('*.c'),
|
bld.stlib(source = bld.path.ant_glob('*.c') + bld.path.ant_glob('*.S'),
|
||||||
target = 'public',
|
target = 'public',
|
||||||
features = 'c',
|
features = 'c',
|
||||||
use = 'sdk_includes',
|
use = 'sdk_includes',
|
||||||
|
|||||||
@@ -209,6 +209,30 @@ rsqrt
|
|||||||
*/
|
*/
|
||||||
float rsqrt( float number )
|
float rsqrt( float number )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
#if 0 /* experimental */
|
||||||
|
if( number == 0.0f ) return 0.0f;
|
||||||
|
return ( 1.0 / __builtin_allegrex_sqrt_s( number ));
|
||||||
|
#else
|
||||||
|
float result;
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"mfc1 $8, %1\n" // FPU->CPU
|
||||||
|
"mtv $8, S000\n" // CPU->VFPU S000 = number
|
||||||
|
"vzero.s S001\n" // S100 = 0
|
||||||
|
"vcmp.s EZ, S000\n" // CC[0] = ( S000 == 0.0f )
|
||||||
|
"vrsq.s S000, S000\n" // S000 = 1.0 / sqrt( S000 )
|
||||||
|
"vcmovt.s S000, S001, 0\n" // if ( CC[0] ) S000 = S001
|
||||||
|
"sv.s S000, %0\n" // result = S000
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( result )
|
||||||
|
: "f"( number )
|
||||||
|
: "$8"
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
int i;
|
int i;
|
||||||
float x, y;
|
float x, y;
|
||||||
|
|
||||||
@@ -222,6 +246,7 @@ float rsqrt( float number )
|
|||||||
y = y * (1.5f - (x * y * y)); // first iteration
|
y = y * (1.5f - (x * y * y)); // first iteration
|
||||||
|
|
||||||
return y;
|
return y;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -384,6 +409,7 @@ void VectorsAngles( const vec3_t forward, const vec3_t right, const vec3_t up, v
|
|||||||
//
|
//
|
||||||
// bounds operations
|
// bounds operations
|
||||||
//
|
//
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
AddPointToBounds
|
AddPointToBounds
|
||||||
@@ -485,6 +511,46 @@ AngleQuaternion
|
|||||||
*/
|
*/
|
||||||
void AngleQuaternion( const vec3_t angles, vec4_t q, qboolean studio )
|
void AngleQuaternion( const vec3_t angles, vec4_t q, qboolean studio )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
vec4_t dst_angles;
|
||||||
|
if( studio )
|
||||||
|
{
|
||||||
|
dst_angles[0] = angles[PITCH];
|
||||||
|
dst_angles[1] = angles[YAW];
|
||||||
|
dst_angles[2] = angles[ROLL];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dst_angles[0] = DEG2RAD( angles[ROLL] );
|
||||||
|
dst_angles[1] = DEG2RAD( angles[PITCH] );
|
||||||
|
dst_angles[2] = DEG2RAD( angles[YAW] );
|
||||||
|
}
|
||||||
|
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C000, %1\n" // C000 = [PITCH, YAW, ROLL]
|
||||||
|
"vcst.s S010, VFPU_1_PI\n" // S010 = VFPU_1_PI = 1 / PI
|
||||||
|
"vscl.t C000, C000, S010\n" // C000 = C000 * S010 = C000 * 0.5f * ( 2 / PI )
|
||||||
|
"vcos.t C010, C000\n" // C010 = cos( C000 * 0.5f )
|
||||||
|
"vsin.t C000, C000\n" // C000 = sin( C000 * 0.5f )
|
||||||
|
"vcrs.t C020, C010, C010\n" // C020 = ( cp*cy, cy*cr, cr*cp )
|
||||||
|
"vcrs.t C030, C000, C000\n" // C030 = ( sp*sy, sy*sr, sr*sp )
|
||||||
|
"vmul.s S003, S020, S010\n" // S003 = S020 * S010 = cp*cy*cr
|
||||||
|
"vmul.s S013, S030, S000\n" // S013 = S030 * S000 = sp*sy*sr
|
||||||
|
"vmul.t C020, C020, C000\n" // C020 = C020 * C000 = ( cp*cy*sr, cy*cr*sp, cr*cp*sy )
|
||||||
|
"vmul.t C030, C030, C010\n" // C030 = C030 * C010 = ( sp*sy*cr, sy*sr*cp, sr*sp*cy )
|
||||||
|
"vadd.s S003, S003, S013\n" // S003 = S003 + S013 = cp*cy*cr + cp*cy*cr
|
||||||
|
"vadd.t C000, C020, C030[-X, Y, -Z]\n"
|
||||||
|
// S000 = S020 - C030 = cp*cy*sr - sp*sy*cr
|
||||||
|
// S001 = S021 + C031 = cy*cr*sp + sy*sr*cp
|
||||||
|
// S002 = S022 - C032 = cr*cp*sy - sr*sp*cy
|
||||||
|
"sv.q C000, %0\n" // *q = C000
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *q )
|
||||||
|
: "m"( dst_angles )
|
||||||
|
);
|
||||||
|
#else
|
||||||
float sr, sp, sy, cr, cp, cy;
|
float sr, sp, sy, cr, cp, cy;
|
||||||
|
|
||||||
if( studio )
|
if( studio )
|
||||||
@@ -504,6 +570,7 @@ void AngleQuaternion( const vec3_t angles, vec4_t q, qboolean studio )
|
|||||||
q[1] = cr * sp * cy + sr * cp * sy; // Y
|
q[1] = cr * sp * cy + sr * cp * sy; // Y
|
||||||
q[2] = cr * cp * sy - sr * sp * cy; // Z
|
q[2] = cr * cp * sy - sr * sp * cy; // Z
|
||||||
q[3] = cr * cp * cy + sr * sp * sy; // W
|
q[3] = cr * cp * cy + sr * sp * sy; // W
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -527,6 +594,7 @@ make sure quaternions are within 180 degrees of one another,
|
|||||||
if not, reverse q
|
if not, reverse q
|
||||||
====================
|
====================
|
||||||
*/
|
*/
|
||||||
|
#if !XASH_PSP
|
||||||
void QuaternionAlign( const vec4_t p, const vec4_t q, vec4_t qt )
|
void QuaternionAlign( const vec4_t p, const vec4_t q, vec4_t qt )
|
||||||
{
|
{
|
||||||
// decide if one of the quaternions is backwards
|
// decide if one of the quaternions is backwards
|
||||||
@@ -615,9 +683,9 @@ void QuaternionSlerp( const vec4_t p, const vec4_t q, float t, vec4_t qt )
|
|||||||
// 0.0 returns p, 1.0 return q.
|
// 0.0 returns p, 1.0 return q.
|
||||||
// decide if one of the quaternions is backwards
|
// decide if one of the quaternions is backwards
|
||||||
QuaternionAlign( p, q, q2 );
|
QuaternionAlign( p, q, q2 );
|
||||||
|
|
||||||
QuaternionSlerpNoAlign( p, q2, t, qt );
|
QuaternionSlerpNoAlign( p, q2, t, qt );
|
||||||
}
|
}
|
||||||
|
#endif // XASH_PSP
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==================
|
==================
|
||||||
@@ -626,10 +694,11 @@ BoxOnPlaneSide
|
|||||||
Returns 1, 2, or 1 + 2
|
Returns 1, 2, or 1 + 2
|
||||||
==================
|
==================
|
||||||
*/
|
*/
|
||||||
|
#if !XASH_PSP
|
||||||
int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p )
|
int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p )
|
||||||
{
|
{
|
||||||
float dist1, dist2;
|
|
||||||
int sides = 0;
|
int sides = 0;
|
||||||
|
float dist1, dist2;
|
||||||
|
|
||||||
// general case
|
// general case
|
||||||
switch( p->signbits )
|
switch( p->signbits )
|
||||||
@@ -679,6 +748,7 @@ int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p )
|
|||||||
|
|
||||||
return sides;
|
return sides;
|
||||||
}
|
}
|
||||||
|
#endif // !XASH_PSP
|
||||||
|
|
||||||
/*
|
/*
|
||||||
====================
|
====================
|
||||||
|
|||||||
@@ -175,8 +175,26 @@ static inline float UintAsFloat( uint32_t u )
|
|||||||
|
|
||||||
static inline void SinCos( float radians, float *sine, float *cosine )
|
static inline void SinCos( float radians, float *sine, float *cosine )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"mfc1 $8, %2\n" // FPU->CPU
|
||||||
|
"mtv $8, S000\n" // CPU->VFPU S000 = radians
|
||||||
|
"vcst.s S001, VFPU_2_PI\n" // S001 = VFPU_2_PI = 2 / PI
|
||||||
|
"vmul.s S000, S000, S001\n" // S000 = S000 * S001
|
||||||
|
"vrot.p C002, S000, [s, c]\n" // S002 = sin( radians ), S003 = cos( radians )
|
||||||
|
"sv.s S002, %0\n" // sine = S002
|
||||||
|
"sv.s S003, %1\n" // cosine = S003
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *sine), "=m"( *cosine )
|
||||||
|
: "f"( radians )
|
||||||
|
: "$8"
|
||||||
|
);
|
||||||
|
#else
|
||||||
*sine = sin(radians);
|
*sine = sin(radians);
|
||||||
*cosine = cos(radians);
|
*cosine = cos(radians);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
float rsqrt( float number );
|
float rsqrt( float number );
|
||||||
|
|||||||
218
public/xash3d_mathlib_asm.S
Normal file
218
public/xash3d_mathlib_asm.S
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
xash3d_mathlib_asm.S - internal mathlib ASM ver.
|
||||||
|
Copyright (C) 2022 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#include "build.h"
|
||||||
|
#if XASH_PSP
|
||||||
|
#include "as_reg_compat.h"
|
||||||
|
.set noreorder
|
||||||
|
.set noat
|
||||||
|
|
||||||
|
.text
|
||||||
|
.align 4
|
||||||
|
.global QuaternionSlerp
|
||||||
|
.global BoxOnPlaneSide
|
||||||
|
|
||||||
|
// void QuaternionSlerp( const vec4_t p, const vec4_t q, float t, vec4_t qt );
|
||||||
|
.ent QuaternionSlerp
|
||||||
|
QuaternionSlerp:
|
||||||
|
############################
|
||||||
|
# a0 - IN *p #
|
||||||
|
# a1 - IN *q #
|
||||||
|
# f12 - IN t #
|
||||||
|
# a2 - IN *qt #
|
||||||
|
############################
|
||||||
|
mfc1 $t0, $f12
|
||||||
|
mtv $t0, S031 // S031 = sclq = t
|
||||||
|
li $t0, 0x358637bd // t0 = EPSILON = 0.000001f
|
||||||
|
mtv $t0, S033 // S002 = t0 = EPSILON
|
||||||
|
lv.q C010, 0($a0) // C010 = p
|
||||||
|
lv.q C020, 0($a1) // C020 = q
|
||||||
|
|
||||||
|
// QuaternionAlign
|
||||||
|
vsub.q C100, C010, C020 // C100 = p[*] - q[*]
|
||||||
|
vadd.q C110, C010, C020 // C110 = p[*] + q[*]
|
||||||
|
vdot.q S000, C100, C100 // S000 = a += (p[*] - q[*]) * (p[*] - q[*])
|
||||||
|
vdot.q S001, C110, C110 // S001 = b += (p[*] + q[*]) * (p[*] + q[*])
|
||||||
|
vcmp.s GT, S000, S001 // CC[0] = a > b
|
||||||
|
vcmovt.q C020, C020[-X,-Y,-Z,-W], 0 // if CC[0] q = -q
|
||||||
|
// ***
|
||||||
|
|
||||||
|
// QuaternionSlerpNoAlign
|
||||||
|
vdot.q S000, C010, C020 // S000 = cosom += p[*] * q[*]
|
||||||
|
vadd.s S001, S000[1], S000 // S002 = 1.0f + cosom
|
||||||
|
vcmp.s LE, S001, S033 // CC[0] = ( 1.0f + cosom ) <= 0.000001f
|
||||||
|
bvt 0, Lqs2 // if CC[0] goto Lqs2
|
||||||
|
vocp.s S030, S031 // S030 = sclp = 1.0f - t (delay slot)
|
||||||
|
vsub.s S001, S000[1], S000 // S002 = 1.0f - cosom
|
||||||
|
vcmp.s LE, S001, S033 // CC[0] = ( 1.0f - cosom ) <= 0.000001f
|
||||||
|
bvt 0, Lqs1
|
||||||
|
nop
|
||||||
|
|
||||||
|
// acos
|
||||||
|
vcst.s S001, VFPU_SQRT1_2 // S001 = VFPU_SQRT1_2 = 1 / sqrt(2)
|
||||||
|
vcmp.s LT, S000[|x|], S001 // CC[0] = abs(cosom) < (1 / sqrt(2))
|
||||||
|
vasin.s S032, S000[|x|] // S032 = asin(abs(cosom))
|
||||||
|
bvtl 0, Lqs0 // if CC[0] goto Lqs0
|
||||||
|
vocp.s S032, S032 // S032 = 1 - S032 = acos(abs(cosom)) = omega (bvtl delay slot)
|
||||||
|
vmul.s S001, S000, S000 // S001 = cosom * cosom
|
||||||
|
vocp.s S001[0:1], S001 // S001 = 1 - S001[0:1]
|
||||||
|
vsqrt.s S001, S001 // S001 = sqrt(S001)
|
||||||
|
vasin.s S032, S001 // S032 = asin(S001) = acos(abs(cosom)) = omega
|
||||||
|
// ***
|
||||||
|
Lqs0:
|
||||||
|
vscl.p C030, C030, S032 // S030 = S030 * S032 = sclp * omega
|
||||||
|
// S031 = S031 * S032 = sclq * omega
|
||||||
|
vsin.t C030, C030 // S030 = sin(S030) = sin(sclp * omega) = sclp
|
||||||
|
// S031 = sin(S031) = sin(sclq * omega) = sclq
|
||||||
|
// S032 = sin(S032) = sin(omega)
|
||||||
|
vrcp.s S032, S032 // S032 = 1.0f / S032 = 1 / sin(omega) = sinom
|
||||||
|
vscl.p C030, C030, S032 // S030 = S030 * S032 = sin(sclp * omega) / sinom
|
||||||
|
// S031 = S031 * S032 = sin(sclq * omega) / sinom
|
||||||
|
Lqs1:
|
||||||
|
vscl.q C010, C010, S030 // C010 = p[*4] * sclp
|
||||||
|
vscl.q C020, C020, S031 // C020 = qt[*4] * sclq
|
||||||
|
b LqsEnd // goto LqsEnd
|
||||||
|
vadd.q C000, C010, C020 // S000 = qt[0] = sclp * p[0] + sclq * qt[0] (delay slot)
|
||||||
|
// S001 = qt[1] = sclp * p[1] + sclq * qt[1]
|
||||||
|
// S002 = qt[2] = sclp * p[2] + sclq * qt[2]
|
||||||
|
// S003 = qt[3] = sclp * p[3] + sclq * qt[3]
|
||||||
|
Lqs2:
|
||||||
|
vmov.q C000, C020[-Y,X,-W,Z] // S000 = qt[0] = -q[1];
|
||||||
|
// S001 = qt[1] = q[0];
|
||||||
|
// S002 = qt[2] = -q[3];
|
||||||
|
// S003 = qt[3] = q[2];
|
||||||
|
vsin.p C030, C030 // S030 = sclp = sin(( 1.0f - t ) * ( 0.5f * M_PI_F ))
|
||||||
|
// S031 = sclq = sin( t * ( 0.5f * M_PI_F ))
|
||||||
|
vscl.t C010, C010, S030 // C000 = p[*3] * sclp
|
||||||
|
vscl.t C020, C000, S031 // C030 = qt[*3] * sclq
|
||||||
|
vadd.t C000, C010, C020 // S000 = qt[0] = sclp * p[0] + sclq * qt[0]
|
||||||
|
// S001 = qt[1] = sclp * p[1] + sclq * qt[1]
|
||||||
|
// S002 = qt[2] = sclp * p[2] + sclq * qt[2]
|
||||||
|
// S003 = qt[3]
|
||||||
|
LqsEnd:
|
||||||
|
sv.q C000, 0($a2)
|
||||||
|
jr $ra
|
||||||
|
.end QuaternionSlerp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// int BoxOnPlaneSide( vec3_t emins, vec3_t emaxs, mplane_t *p );
|
||||||
|
.ent BoxOnPlaneSide
|
||||||
|
BoxOnPlaneSide:
|
||||||
|
############################
|
||||||
|
# a0 - IN *emins #
|
||||||
|
# a1 - IN *emaxs #
|
||||||
|
# a2 - IN *p #
|
||||||
|
# v0 - OUT sides #
|
||||||
|
############################
|
||||||
|
lbu $v0, 17($a2) // p->signbits
|
||||||
|
sltiu $v1, $v0, 8 // if(signbits > 8)
|
||||||
|
beq $v1, $zero, LSetSides // jump to LSetSides
|
||||||
|
vzero.p C030 // set zero vector
|
||||||
|
sll $v1, $v0, 2
|
||||||
|
la $v0, Ljmptab
|
||||||
|
addu $v0, $v0, $v1
|
||||||
|
lw $v0, 0($v0)
|
||||||
|
lv.s S000, 0($a2) // p->normal[0]
|
||||||
|
lv.s S001, 4($a2) // p->normal[1]
|
||||||
|
jr $v0
|
||||||
|
lv.s S002, 8($a2) // p->normal[2]
|
||||||
|
Lcase0:
|
||||||
|
lv.s S010, 0($a1) // emaxs[0]
|
||||||
|
lv.s S011, 4($a1) // emaxs[1]
|
||||||
|
lv.s S012, 8($a1) // emaxs[2]
|
||||||
|
lv.s S020, 0($a0) // emins[0]
|
||||||
|
lv.s S021, 4($a0) // emins[1]
|
||||||
|
b LDotProduct
|
||||||
|
lv.s S022, 8($a0) // emins[2]
|
||||||
|
Lcase1:
|
||||||
|
lv.s S010, 0($a0) // emins[0]
|
||||||
|
lv.s S011, 4($a1) // emaxs[1]
|
||||||
|
lv.s S012, 8($a1) // emaxs[2]
|
||||||
|
lv.s S020, 0($a1) // emaxs[0]
|
||||||
|
lv.s S021, 4($a0) // emins[1]
|
||||||
|
b LDotProduct
|
||||||
|
lv.s S022, 8($a0) // emins[2]
|
||||||
|
Lcase2:
|
||||||
|
lv.s S010, 0($a1) // emaxs[0]
|
||||||
|
lv.s S011, 4($a0) // emins[1]
|
||||||
|
lv.s S012, 8($a1) // emaxs[2]
|
||||||
|
lv.s S020, 0($a0) // emins[0]
|
||||||
|
lv.s S021, 4($a1) // emaxs[1]
|
||||||
|
b LDotProduct
|
||||||
|
lv.s S022, 8($a0) // emins[2]
|
||||||
|
Lcase3:
|
||||||
|
lv.s S010, 0($a0) // emins[0]
|
||||||
|
lv.s S011, 4($a0) // emins[1]
|
||||||
|
lv.s S012, 8($a1) // emaxs[2]
|
||||||
|
lv.s S020, 0($a1) // emaxs[0]
|
||||||
|
lv.s S021, 4($a1) // emaxs[1]
|
||||||
|
b LDotProduct
|
||||||
|
lv.s S022, 8($a0) // emins[2]
|
||||||
|
Lcase4:
|
||||||
|
lv.s S010, 0($a1) // emaxs[0]
|
||||||
|
lv.s S011, 4($a1) // emaxs[1]
|
||||||
|
lv.s S012, 8($a0) // emins[2]
|
||||||
|
lv.s S020, 0($a0) // emins[0]
|
||||||
|
lv.s S021, 4($a0) // emins[1]
|
||||||
|
b LDotProduct
|
||||||
|
lv.s S022, 8($a1) // emaxs[2]
|
||||||
|
Lcase5:
|
||||||
|
lv.s S010, 0($a0) // emins[0]
|
||||||
|
lv.s S011, 4($a1) // emaxs[1]
|
||||||
|
lv.s S012, 8($a0) // emins[2]
|
||||||
|
lv.s S020, 0($a1) // emaxs[0]
|
||||||
|
lv.s S021, 4($a0) // emins[1]
|
||||||
|
b LDotProduct
|
||||||
|
lv.s S022, 8($a1) // emaxs[2]
|
||||||
|
Lcase6:
|
||||||
|
lv.s S010, 0($a1) // emaxs[0]
|
||||||
|
lv.s S011, 4($a0) // emins[1]
|
||||||
|
lv.s S012, 8($a0) // emins[2]
|
||||||
|
lv.s S020, 0($a0) // emins[0]
|
||||||
|
lv.s S021, 4($a1) // emaxs[1]
|
||||||
|
b LDotProduct
|
||||||
|
lv.s S022, 8($a1) // emaxs[2]
|
||||||
|
Lcase7:
|
||||||
|
lv.s S010, 0($a0) // emins[0]
|
||||||
|
lv.s S011, 4($a0) // emins[1]
|
||||||
|
lv.s S012, 8($a0) // emins[2]
|
||||||
|
lv.s S020, 0($a1) // emaxs[0]
|
||||||
|
lv.s S021, 4($a1) // emaxs[1]
|
||||||
|
lv.s S022, 8($a1) // emaxs[2]
|
||||||
|
LDotProduct:
|
||||||
|
vdot.t S030, C000, C010 // S030 = C000 * C010
|
||||||
|
vdot.t S031, C000, C020 // S031 = C000 * C020
|
||||||
|
LSetSides:
|
||||||
|
lv.s S013, 12($a2) // p->dist
|
||||||
|
vcmp.s LT, S030, S013 // S030 < S013
|
||||||
|
bvt 0, LDist2 // if ( CC[0] == 1 ) jump to LDist2
|
||||||
|
li $v0, 0 // sides = 0
|
||||||
|
li $v0, 1 // sides = 1
|
||||||
|
LDist2:
|
||||||
|
vcmp.s GE, S031, S013 // S031 >= S013
|
||||||
|
bvt 0, LEnd // if ( CC[0] == 1 ) jump to LEnd
|
||||||
|
nop
|
||||||
|
ori $v0, $v0, 2
|
||||||
|
LEnd:
|
||||||
|
jr $ra
|
||||||
|
nop
|
||||||
|
.end BoxOnPlaneSide
|
||||||
|
|
||||||
|
.section .rodata
|
||||||
|
.align 4
|
||||||
|
Ljmptab:
|
||||||
|
.word Lcase0, Lcase1, Lcase2, Lcase3, Lcase4, Lcase5, Lcase6, Lcase7
|
||||||
|
#endif // XASH_PSP
|
||||||
@@ -142,7 +142,6 @@ void _TriColor4ub( byte r, byte g, byte b, byte a )
|
|||||||
pglColor4ub( r, g, b, a );
|
pglColor4ub( r, g, b, a );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=============
|
=============
|
||||||
TriColor4ub
|
TriColor4ub
|
||||||
@@ -365,4 +364,3 @@ void TriBrightness( float brightness )
|
|||||||
|
|
||||||
_TriColor4f( r, g, b, 1.0f );
|
_TriColor4f( r, g, b, 1.0f );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
ref/soft/exports.txt
Normal file
1
ref/soft/exports.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
GetRefAPI
|
||||||
@@ -201,6 +201,19 @@ void R_SetupDecalTextureSpaceBasis( decal_t *pDecal, msurface_t *surf, int textu
|
|||||||
// Build the initial list of vertices from the surface verts into the global array, 'verts'.
|
// Build the initial list of vertices from the surface verts into the global array, 'verts'.
|
||||||
void R_SetupDecalVertsForMSurface( decal_t *pDecal, msurface_t *surf, vec3_t textureSpaceBasis[3], float *verts )
|
void R_SetupDecalVertsForMSurface( decal_t *pDecal, msurface_t *surf, vec3_t textureSpaceBasis[3], float *verts )
|
||||||
{
|
{
|
||||||
|
#if XASH_PSP
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if( !surf->polys )
|
||||||
|
return;
|
||||||
|
for( i = 0; i < surf->polys->numverts; i++, verts += VERTEXSIZE )
|
||||||
|
{
|
||||||
|
VectorCopy( surf->polys->verts[i].xyz, verts ); // copy model space coordinates
|
||||||
|
verts[3] = DotProduct( verts, textureSpaceBasis[0] ) - pDecal->dx + 0.5f;
|
||||||
|
verts[4] = DotProduct( verts, textureSpaceBasis[1] ) - pDecal->dy + 0.5f;
|
||||||
|
verts[5] = verts[6] = 0.0f;
|
||||||
|
}
|
||||||
|
#else
|
||||||
float *v;
|
float *v;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -213,6 +226,7 @@ void R_SetupDecalVertsForMSurface( decal_t *pDecal, msurface_t *surf, vec3_t tex
|
|||||||
verts[4] = DotProduct( verts, textureSpaceBasis[1] ) - pDecal->dy + 0.5f;
|
verts[4] = DotProduct( verts, textureSpaceBasis[1] ) - pDecal->dy + 0.5f;
|
||||||
verts[5] = verts[6] = 0.0f;
|
verts[5] = verts[6] = 0.0f;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out where the decal maps onto the surface.
|
// Figure out where the decal maps onto the surface.
|
||||||
@@ -524,7 +538,26 @@ glpoly_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t
|
|||||||
|
|
||||||
v = R_DecalSetupVerts( pdecal, surf, pdecal->texture, &lnumverts );
|
v = R_DecalSetupVerts( pdecal, surf, pdecal->texture, &lnumverts );
|
||||||
if( !lnumverts ) return NULL; // probably this never happens
|
if( !lnumverts ) return NULL; // probably this never happens
|
||||||
|
#if XASH_PSP
|
||||||
|
// allocate glpoly
|
||||||
|
// REFTODO: com_studiocache pool!
|
||||||
|
poly = Mem_Calloc( r_temppool, sizeof( glpoly_t ) + ( lnumverts * 2 - 1 ) * sizeof( gu_vert_t ));
|
||||||
|
poly->next = pdecal->polys;
|
||||||
|
poly->flags = surf->flags;
|
||||||
|
pdecal->polys = poly;
|
||||||
|
poly->numverts = lnumverts;
|
||||||
|
|
||||||
|
for( i = 0; i < lnumverts; i++, v += VERTEXSIZE )
|
||||||
|
{
|
||||||
|
poly->verts[i].uv[0] = v[3];
|
||||||
|
poly->verts[i].uv[1] = v[4];
|
||||||
|
VectorCopy( v, poly->verts[i].xyz );
|
||||||
|
|
||||||
|
poly->verts[i + lnumverts].uv[0] = v[5];
|
||||||
|
poly->verts[i + lnumverts].uv[1] = v[6];
|
||||||
|
VectorCopy( v, poly->verts[i + lnumverts].xyz );
|
||||||
|
}
|
||||||
|
#else
|
||||||
// allocate glpoly
|
// allocate glpoly
|
||||||
// REFTODO: com_studiocache pool!
|
// REFTODO: com_studiocache pool!
|
||||||
poly = Mem_Calloc( r_temppool, sizeof( glpoly_t ) + ( lnumverts - 4 ) * VERTEXSIZE * sizeof( float ));
|
poly = Mem_Calloc( r_temppool, sizeof( glpoly_t ) + ( lnumverts - 4 ) * VERTEXSIZE * sizeof( float ));
|
||||||
@@ -541,7 +574,7 @@ glpoly_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t
|
|||||||
poly->verts[i][5] = v[5];
|
poly->verts[i][5] = v[5];
|
||||||
poly->verts[i][6] = v[6];
|
poly->verts[i][6] = v[6];
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return poly;
|
return poly;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -861,8 +894,18 @@ float * GAME_EXPORT R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int te
|
|||||||
{
|
{
|
||||||
v = g_DecalClipVerts[0];
|
v = g_DecalClipVerts[0];
|
||||||
count = p->numverts;
|
count = p->numverts;
|
||||||
|
#if XASH_PSP
|
||||||
|
// if we have mesh so skip clipping and just copy vertexes out (perf)
|
||||||
|
for( i = 0; i < count; i++, v += VERTEXSIZE )
|
||||||
|
{
|
||||||
|
VectorCopy( p->verts[i].xyz, v );
|
||||||
|
v[3] = p->verts[i].uv[0];
|
||||||
|
v[4] = p->verts[i].uv[1];
|
||||||
|
v[5] = p->verts[i + count].uv[0];
|
||||||
|
v[6] = p->verts[i + count].uv[1];
|
||||||
|
}
|
||||||
|
#else
|
||||||
v2 = p->verts[0];
|
v2 = p->verts[0];
|
||||||
|
|
||||||
// if we have mesh so skip clipping and just copy vertexes out (perf)
|
// if we have mesh so skip clipping and just copy vertexes out (perf)
|
||||||
for( i = 0; i < count; i++, v += VERTEXSIZE, v2 += VERTEXSIZE )
|
for( i = 0; i < count; i++, v += VERTEXSIZE, v2 += VERTEXSIZE )
|
||||||
{
|
{
|
||||||
@@ -872,7 +915,7 @@ float * GAME_EXPORT R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int te
|
|||||||
v[5] = v2[5];
|
v[5] = v2[5];
|
||||||
v[6] = v2[6];
|
v[6] = v2[6];
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
// restore pointer
|
// restore pointer
|
||||||
v = g_DecalClipVerts[0];
|
v = g_DecalClipVerts[0];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -492,4 +492,3 @@ void TriBrightness( float brightness )
|
|||||||
|
|
||||||
_TriColor4f( r, g, b, 1.0f );
|
_TriColor4f( r, g, b, 1.0f );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
ref_gu/exports.txt
Normal file
2
ref_gu/exports.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
GetRefAPI
|
||||||
|
GetRefHumanReadableName
|
||||||
1551
ref_gu/gu_alias.c
Normal file
1551
ref_gu/gu_alias.c
Normal file
File diff suppressed because it is too large
Load Diff
683
ref_gu/gu_backend.c
Normal file
683
ref_gu/gu_backend.c
Normal file
@@ -0,0 +1,683 @@
|
|||||||
|
/*
|
||||||
|
gl_backend.c - rendering backend
|
||||||
|
Copyright (C) 2010 Uncle Mike
|
||||||
|
Copyright (C) 2021 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "gu_local.h"
|
||||||
|
#include "xash3d_mathlib.h"
|
||||||
|
|
||||||
|
char r_speeds_msg[MAX_SYSPATH];
|
||||||
|
ref_speeds_t r_stats; // r_speeds counters
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
R_SpeedsMessage
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
qboolean R_SpeedsMessage( char *out, size_t size )
|
||||||
|
{
|
||||||
|
if( gEngfuncs.drawFuncs->R_SpeedsMessage != NULL )
|
||||||
|
{
|
||||||
|
if( gEngfuncs.drawFuncs->R_SpeedsMessage( out, size ))
|
||||||
|
return true;
|
||||||
|
// otherwise pass to default handler
|
||||||
|
}
|
||||||
|
|
||||||
|
if( r_speeds->value <= 0 ) return false;
|
||||||
|
if( !out || !size ) return false;
|
||||||
|
|
||||||
|
Q_strncpy( out, r_speeds_msg, size );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
R_Speeds_Printf
|
||||||
|
|
||||||
|
helper to print into r_speeds message
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
void R_Speeds_Printf( const char *msg, ... )
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
char text[2048];
|
||||||
|
|
||||||
|
va_start( argptr, msg );
|
||||||
|
Q_vsprintf( text, msg, argptr );
|
||||||
|
va_end( argptr );
|
||||||
|
|
||||||
|
Q_strncat( r_speeds_msg, text, sizeof( r_speeds_msg ));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
GL_BackendStartFrame
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
void GL_BackendStartFrame( void )
|
||||||
|
{
|
||||||
|
r_speeds_msg[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
GL_BackendEndFrame
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
void GL_BackendEndFrame( void )
|
||||||
|
{
|
||||||
|
mleaf_t *curleaf;
|
||||||
|
|
||||||
|
if( r_speeds->value <= 0 || !RI.drawWorld )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !RI.viewleaf )
|
||||||
|
curleaf = WORLDMODEL->leafs;
|
||||||
|
else curleaf = RI.viewleaf;
|
||||||
|
|
||||||
|
R_Speeds_Printf( "Renderer: ^1Engine^7\n\n" );
|
||||||
|
|
||||||
|
switch( (int)r_speeds->value )
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i wpoly, %3i apoly\n%3i epoly, %3i spoly",
|
||||||
|
r_stats.c_world_polys, r_stats.c_alias_polys, r_stats.c_studio_polys, r_stats.c_sprite_polys );
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
R_Speeds_Printf( "visible leafs:\n%3i leafs\ncurrent leaf %3i\n", r_stats.c_world_leafs, curleaf - WORLDMODEL->leafs );
|
||||||
|
R_Speeds_Printf( "ReciusiveWorldNode: %3lf secs\nDrawTextureChains %lf\n", r_stats.t_world_node, r_stats.t_world_draw );
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i alias models drawn\n%3i studio models drawn\n%3i sprites drawn",
|
||||||
|
r_stats.c_alias_models_drawn, r_stats.c_studio_models_drawn, r_stats.c_sprite_models_drawn );
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i static entities\n%3i normal entities\n%3i server entities",
|
||||||
|
r_numStatics, r_numEntities - r_numStatics, ENGINE_GET_PARM( PARM_NUMENTITIES ));
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i tempents\n%3i viewbeams\n%3i particles",
|
||||||
|
r_stats.c_active_tents_count, r_stats.c_view_beams_count, r_stats.c_particle_count );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset( &r_stats, 0, sizeof( r_stats ));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_LoadTexMatrix
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GL_LoadTexMatrix( const matrix4x4 m )
|
||||||
|
{
|
||||||
|
sceGumMatrixMode( GU_TEXTURE );
|
||||||
|
GL_LoadMatrix( m );
|
||||||
|
sceGumUpdateMatrix();
|
||||||
|
|
||||||
|
glState.texIdentityMatrix = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_LoadTexMatrixExt
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GL_LoadTexMatrixExt( const float *glmatrix )
|
||||||
|
{
|
||||||
|
Assert( glmatrix != NULL );
|
||||||
|
|
||||||
|
sceGumMatrixMode( GU_TEXTURE );
|
||||||
|
sceGumLoadMatrix( ( const ScePspFMatrix4 * ) glmatrix );
|
||||||
|
sceGumUpdateMatrix();
|
||||||
|
|
||||||
|
glState.texIdentityMatrix = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_LoadMatrix
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GL_LoadMatrix( const matrix4x4 source )
|
||||||
|
{
|
||||||
|
ScePspFMatrix4 dest;
|
||||||
|
|
||||||
|
Matrix4x4_ToFMatrix4( source, &dest );
|
||||||
|
sceGumLoadMatrix( &dest );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_LoadIdentityTexMatrix
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GL_LoadIdentityTexMatrix( void )
|
||||||
|
{
|
||||||
|
if( glState.texIdentityMatrix )
|
||||||
|
return;
|
||||||
|
|
||||||
|
sceGumMatrixMode( GU_TEXTURE );
|
||||||
|
sceGumLoadIdentity();
|
||||||
|
sceGumUpdateMatrix();
|
||||||
|
|
||||||
|
glState.texIdentityMatrix = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_SelectTexture
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GL_SelectTexture( GLint tmu )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
GL_DisableAllTexGens
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
void GL_DisableAllTexGens( void )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
GL_CleanUpTextureUnits
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
void GL_CleanUpTextureUnits( int last )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
GL_CleanupAllTextureUnits
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
void GL_CleanupAllTextureUnits( void )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_MultiTexCoord2f
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GL_MultiTexCoord2f( GLenum texture, GLfloat s, GLfloat t )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_TextureTarget
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GL_TextureTarget( uint target )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_TexGen
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GL_TexGen( GLenum coord, GLenum mode )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_SetTexCoordArrayMode
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GL_SetTexCoordArrayMode( GLenum mode )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_Cull
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GL_Cull( GLenum cull )
|
||||||
|
{
|
||||||
|
if( glState.faceCull == cull )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !cull )
|
||||||
|
{
|
||||||
|
sceGuDisable( GU_CULL_FACE );
|
||||||
|
glState.faceCull = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sceGuEnable( GU_CULL_FACE );
|
||||||
|
sceGuFrontFace( cull - 1 );
|
||||||
|
glState.faceCull = cull;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_SetRenderMode( int mode )
|
||||||
|
{
|
||||||
|
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
||||||
|
|
||||||
|
switch( mode )
|
||||||
|
{
|
||||||
|
case kRenderNormal:
|
||||||
|
default:
|
||||||
|
sceGuDisable( GU_BLEND );
|
||||||
|
sceGuDisable( GU_ALPHA_TEST );
|
||||||
|
break;
|
||||||
|
case kRenderTransColor:
|
||||||
|
case kRenderTransTexture:
|
||||||
|
sceGuEnable( GU_BLEND );
|
||||||
|
sceGuDisable( GU_ALPHA_TEST );
|
||||||
|
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
||||||
|
break;
|
||||||
|
case kRenderTransAlpha:
|
||||||
|
sceGuDisable( GU_BLEND );
|
||||||
|
sceGuEnable( GU_ALPHA_TEST );
|
||||||
|
break;
|
||||||
|
case kRenderGlow:
|
||||||
|
case kRenderTransAdd:
|
||||||
|
sceGuEnable( GU_BLEND );
|
||||||
|
sceGuDisable( GU_ALPHA_TEST );
|
||||||
|
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, GUBLEND1 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_SetColor4ub
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GL_SetColor4ub( byte r, byte g, byte b, byte a )
|
||||||
|
{
|
||||||
|
sceGuColor( GU_RGBA( r, g, b, a ));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
SCREEN SHOTS
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
// used for 'env' and 'sky' shots
|
||||||
|
typedef struct envmap_s
|
||||||
|
{
|
||||||
|
vec3_t angles;
|
||||||
|
int flags;
|
||||||
|
} envmap_t;
|
||||||
|
|
||||||
|
const envmap_t r_skyBoxInfo[6] =
|
||||||
|
{
|
||||||
|
{{ 0, 270, 180}, IMAGE_FLIP_X },
|
||||||
|
{{ 0, 90, 180}, IMAGE_FLIP_X },
|
||||||
|
{{ -90, 0, 180}, IMAGE_FLIP_X },
|
||||||
|
{{ 90, 0, 180}, IMAGE_FLIP_X },
|
||||||
|
{{ 0, 0, 180}, IMAGE_FLIP_X },
|
||||||
|
{{ 0, 180, 180}, IMAGE_FLIP_X },
|
||||||
|
};
|
||||||
|
|
||||||
|
const envmap_t r_envMapInfo[6] =
|
||||||
|
{
|
||||||
|
{{ 0, 0, 90}, 0 },
|
||||||
|
{{ 0, 180, -90}, 0 },
|
||||||
|
{{ 0, 90, 0}, 0 },
|
||||||
|
{{ 0, 270, 180}, 0 },
|
||||||
|
{{-90, 180, -90}, 0 },
|
||||||
|
{{ 90, 0, 90}, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
qboolean VID_ScreenShot( const char *filename, int shot_type )
|
||||||
|
{
|
||||||
|
rgbdata_t *r_shot;
|
||||||
|
uint flags = 0;
|
||||||
|
int width = 0, height = 0;
|
||||||
|
qboolean result;
|
||||||
|
int bpp;
|
||||||
|
|
||||||
|
r_shot = Mem_Calloc( r_temppool, sizeof( rgbdata_t ));
|
||||||
|
r_shot->width = (gpGlobals->width + 3) & ~3;
|
||||||
|
r_shot->height = (gpGlobals->height + 3) & ~3;
|
||||||
|
r_shot->flags = IMAGE_HAS_COLOR;
|
||||||
|
r_shot->type = PF_RGB_24;
|
||||||
|
bpp = gEngfuncs.Image_GetPFDesc( r_shot->type )->bpp;
|
||||||
|
r_shot->size = r_shot->width * r_shot->height * bpp;
|
||||||
|
r_shot->palette = NULL;
|
||||||
|
r_shot->buffer = Mem_Malloc( r_temppool, r_shot->size );
|
||||||
|
|
||||||
|
// get screen frame
|
||||||
|
byte *src = ( byte* )guRender.disp_buffer;
|
||||||
|
byte *dst = r_shot->buffer;
|
||||||
|
int cheight = r_shot->height;
|
||||||
|
|
||||||
|
// stride copy
|
||||||
|
while( cheight-- )
|
||||||
|
{
|
||||||
|
GL_PixelConverter( dst, src, r_shot->width, PC_HWF( guRender.buffer_format ), PC_SWF( r_shot->type ) );
|
||||||
|
dst += r_shot->width * bpp;
|
||||||
|
src += guRender.buffer_width * guRender.buffer_bpp;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( shot_type )
|
||||||
|
{
|
||||||
|
case VID_SCREENSHOT:
|
||||||
|
break;
|
||||||
|
case VID_SNAPSHOT:
|
||||||
|
gEngfuncs.FS_AllowDirectPaths( true );
|
||||||
|
break;
|
||||||
|
case VID_LEVELSHOT:
|
||||||
|
flags |= IMAGE_RESAMPLE;
|
||||||
|
if( gpGlobals->wideScreen )
|
||||||
|
{
|
||||||
|
height = 480;
|
||||||
|
width = 800;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
height = 480;
|
||||||
|
width = 640;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VID_MINISHOT:
|
||||||
|
flags |= IMAGE_RESAMPLE;
|
||||||
|
height = 200;
|
||||||
|
width = 320;
|
||||||
|
break;
|
||||||
|
case VID_MAPSHOT:
|
||||||
|
flags |= IMAGE_RESAMPLE|IMAGE_QUANTIZE; // GoldSrc request overviews in 8-bit format
|
||||||
|
height = 768;
|
||||||
|
width = 1024;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gEngfuncs.Image_Process( &r_shot, width, height, flags, 0.0f );
|
||||||
|
|
||||||
|
// write image
|
||||||
|
result = gEngfuncs.FS_SaveImage( filename, r_shot );
|
||||||
|
gEngfuncs.FS_AllowDirectPaths( false ); // always reset after store screenshot
|
||||||
|
gEngfuncs.FS_FreeImage( r_shot );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
VID_CubemapShot
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot )
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
rgbdata_t *r_shot, *r_side;
|
||||||
|
byte *temp = NULL;
|
||||||
|
byte *buffer = NULL;
|
||||||
|
string basename;
|
||||||
|
int i = 1, flags, result;
|
||||||
|
|
||||||
|
if( !RI.drawWorld || !WORLDMODEL )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// make sure the specified size is valid
|
||||||
|
while( i < size ) i<<=1;
|
||||||
|
|
||||||
|
if( i != size ) return false;
|
||||||
|
if( size > gpGlobals->width || size > gpGlobals->height )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// alloc space
|
||||||
|
temp = Mem_Malloc( r_temppool, size * size * 3 );
|
||||||
|
buffer = Mem_Malloc( r_temppool, size * size * 3 * 6 );
|
||||||
|
r_shot = Mem_Calloc( r_temppool, sizeof( rgbdata_t ));
|
||||||
|
r_side = Mem_Calloc( r_temppool, sizeof( rgbdata_t ));
|
||||||
|
|
||||||
|
// use client vieworg
|
||||||
|
if( !vieworg ) vieworg = RI.vieworg;
|
||||||
|
|
||||||
|
R_CheckGamma();
|
||||||
|
|
||||||
|
for( i = 0; i < 6; i++ )
|
||||||
|
{
|
||||||
|
// go into 3d mode
|
||||||
|
R_Set2DMode( false );
|
||||||
|
|
||||||
|
if( skyshot )
|
||||||
|
{
|
||||||
|
R_DrawCubemapView( vieworg, r_skyBoxInfo[i].angles, size );
|
||||||
|
flags = r_skyBoxInfo[i].flags;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
R_DrawCubemapView( vieworg, r_envMapInfo[i].angles, size );
|
||||||
|
flags = r_envMapInfo[i].flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
pglReadPixels( 0, 0, size, size, GL_RGB, GL_UNSIGNED_BYTE, temp );
|
||||||
|
r_side->flags = IMAGE_HAS_COLOR;
|
||||||
|
r_side->width = r_side->height = size;
|
||||||
|
r_side->type = PF_RGB_24;
|
||||||
|
r_side->size = r_side->width * r_side->height * 3;
|
||||||
|
r_side->buffer = temp;
|
||||||
|
|
||||||
|
if( flags ) gEngfuncs.Image_Process( &r_side, 0, 0, flags, 0.0f );
|
||||||
|
memcpy( buffer + (size * size * 3 * i), r_side->buffer, size * size * 3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
r_shot->flags = IMAGE_HAS_COLOR;
|
||||||
|
r_shot->flags |= (skyshot) ? IMAGE_SKYBOX : IMAGE_CUBEMAP;
|
||||||
|
r_shot->width = size;
|
||||||
|
r_shot->height = size;
|
||||||
|
r_shot->type = PF_RGB_24;
|
||||||
|
r_shot->size = r_shot->width * r_shot->height * 3 * 6;
|
||||||
|
r_shot->palette = NULL;
|
||||||
|
r_shot->buffer = buffer;
|
||||||
|
|
||||||
|
// make sure what we have right extension
|
||||||
|
Q_strncpy( basename, base, MAX_STRING );
|
||||||
|
COM_StripExtension( basename );
|
||||||
|
COM_DefaultExtension( basename, ".tga" );
|
||||||
|
|
||||||
|
// write image as 6 sides
|
||||||
|
result = gEngfuncs.FS_SaveImage( basename, r_shot );
|
||||||
|
gEngfuncs.FS_FreeImage( r_shot );
|
||||||
|
gEngfuncs.FS_FreeImage( r_side );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
R_ShowTextures
|
||||||
|
|
||||||
|
Draw all the images to the screen, on top of whatever
|
||||||
|
was there. This is used to test for texture thrashing.
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
void R_ShowTextures( void )
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
gl_texture_t *image;
|
||||||
|
float x, y, w, h;
|
||||||
|
int total, start, end;
|
||||||
|
int i, j, k, base_w, base_h;
|
||||||
|
rgba_t color = { 192, 192, 192, 255 };
|
||||||
|
int charHeight, numTries = 0;
|
||||||
|
static qboolean showHelp = true;
|
||||||
|
string shortname;
|
||||||
|
|
||||||
|
if( !CVAR_TO_BOOL( gl_showtextures ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( showHelp )
|
||||||
|
{
|
||||||
|
gEngfuncs.CL_CenterPrint( "use '<-' and '->' keys to change atlas page, ESC to quit", 0.25f );
|
||||||
|
showHelp = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GL_SetRenderMode( kRenderNormal );
|
||||||
|
pglClear( GL_COLOR_BUFFER_BIT );
|
||||||
|
pglFinish();
|
||||||
|
|
||||||
|
base_w = 8; // textures view by horizontal
|
||||||
|
base_h = 6; // textures view by vertical
|
||||||
|
|
||||||
|
rebuild_page:
|
||||||
|
total = base_w * base_h;
|
||||||
|
start = total * (gl_showtextures->value - 1);
|
||||||
|
end = total * gl_showtextures->value;
|
||||||
|
if( end > MAX_TEXTURES ) end = MAX_TEXTURES;
|
||||||
|
|
||||||
|
w = gpGlobals->width / base_w;
|
||||||
|
h = gpGlobals->height / base_h;
|
||||||
|
|
||||||
|
gEngfuncs.Con_DrawStringLen( NULL, NULL, &charHeight );
|
||||||
|
|
||||||
|
for( i = j = 0; i < MAX_TEXTURES; i++ )
|
||||||
|
{
|
||||||
|
image = R_GetTexture( i );
|
||||||
|
if( j == start ) break; // found start
|
||||||
|
if( pglIsTexture( image->texnum )) j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( i == MAX_TEXTURES && gl_showtextures->value != 1 )
|
||||||
|
{
|
||||||
|
// bad case, rewind to one and try again
|
||||||
|
gEngfuncs.Cvar_SetValue( "r_showtextures", max( 1, gl_showtextures->value - 1 ));
|
||||||
|
if( ++numTries < 2 ) goto rebuild_page; // to prevent infinite loop
|
||||||
|
}
|
||||||
|
|
||||||
|
for( k = 0; i < MAX_TEXTURES; i++ )
|
||||||
|
{
|
||||||
|
if( j == end ) break; // page is full
|
||||||
|
|
||||||
|
image = R_GetTexture( i );
|
||||||
|
if( !pglIsTexture( image->texnum ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
x = k % base_w * w;
|
||||||
|
y = k / base_w * h;
|
||||||
|
|
||||||
|
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||||
|
GL_Bind( XASH_TEXTURE0, i ); // NOTE: don't use image->texnum here, because skybox has a 'wrong' indexes
|
||||||
|
|
||||||
|
if( FBitSet( image->flags, TF_DEPTHMAP ) && !FBitSet( image->flags, TF_NOCOMPARE ))
|
||||||
|
pglTexParameteri( image->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE );
|
||||||
|
|
||||||
|
pglBegin( GL_QUADS );
|
||||||
|
pglTexCoord2f( 0, 0 );
|
||||||
|
pglVertex2f( x, y );
|
||||||
|
if( image->target == GL_TEXTURE_RECTANGLE_EXT )
|
||||||
|
pglTexCoord2f( image->width, 0 );
|
||||||
|
else pglTexCoord2f( 1, 0 );
|
||||||
|
pglVertex2f( x + w, y );
|
||||||
|
if( image->target == GL_TEXTURE_RECTANGLE_EXT )
|
||||||
|
pglTexCoord2f( image->width, image->height );
|
||||||
|
else pglTexCoord2f( 1, 1 );
|
||||||
|
pglVertex2f( x + w, y + h );
|
||||||
|
if( image->target == GL_TEXTURE_RECTANGLE_EXT )
|
||||||
|
pglTexCoord2f( 0, image->height );
|
||||||
|
else pglTexCoord2f( 0, 1 );
|
||||||
|
pglVertex2f( x, y + h );
|
||||||
|
pglEnd();
|
||||||
|
|
||||||
|
if( FBitSet( image->flags, TF_DEPTHMAP ) && !FBitSet( image->flags, TF_NOCOMPARE ))
|
||||||
|
pglTexParameteri( image->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB );
|
||||||
|
|
||||||
|
COM_FileBase( image->name, shortname );
|
||||||
|
if( Q_strlen( shortname ) > 18 )
|
||||||
|
{
|
||||||
|
// cutoff too long names, it looks ugly
|
||||||
|
shortname[16] = '.';
|
||||||
|
shortname[17] = '.';
|
||||||
|
shortname[18] = '\0';
|
||||||
|
}
|
||||||
|
gEngfuncs.Con_DrawString( x + 1, y + h - charHeight, shortname, color );
|
||||||
|
j++, k++;
|
||||||
|
}
|
||||||
|
|
||||||
|
gEngfuncs.CL_DrawCenterPrint ();
|
||||||
|
pglFinish();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
SCR_TimeRefresh_f
|
||||||
|
|
||||||
|
timerefresh [noflip]
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void SCR_TimeRefresh_f( void )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
double start, stop;
|
||||||
|
double time;
|
||||||
|
|
||||||
|
if( ENGINE_GET_PARM( PARM_CONNSTATE ) != ca_active )
|
||||||
|
return;
|
||||||
|
|
||||||
|
start = gEngfuncs.pfnTime();
|
||||||
|
|
||||||
|
// run without page flipping like GoldSrc
|
||||||
|
if( gEngfuncs.Cmd_Argc() == 1 )
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
pglDrawBuffer( GL_FRONT );
|
||||||
|
#endif
|
||||||
|
for( i = 0; i < 128; i++ )
|
||||||
|
{
|
||||||
|
gpGlobals->viewangles[1] = i / 128.0f * 360.0f;
|
||||||
|
R_RenderScene();
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
pglFinish();
|
||||||
|
#endif
|
||||||
|
R_EndFrame();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( i = 0; i < 128; i++ )
|
||||||
|
{
|
||||||
|
R_BeginFrame( true );
|
||||||
|
gpGlobals->viewangles[1] = i / 128.0f * 360.0f;
|
||||||
|
R_RenderScene();
|
||||||
|
R_EndFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stop = gEngfuncs.pfnTime ();
|
||||||
|
time = (stop - start);
|
||||||
|
gEngfuncs.Con_Printf( "%f seconds (%f fps)\n", time, 128 / time );
|
||||||
|
}
|
||||||
1410
ref_gu/gu_beams.c
Normal file
1410
ref_gu/gu_beams.c
Normal file
File diff suppressed because it is too large
Load Diff
337
ref_gu/gu_clipping.c
Normal file
337
ref_gu/gu_clipping.c
Normal file
@@ -0,0 +1,337 @@
|
|||||||
|
/*
|
||||||
|
gu_clipping.c - software clipping implimentation
|
||||||
|
Copyright (C) 2021 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Based on clipping system from PSP Quake by Peter Mackay and Chris Swindle.
|
||||||
|
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
VFPU REGS:
|
||||||
|
|
||||||
|
M700 - current frustum
|
||||||
|
M600 - world frustum
|
||||||
|
C010 - current plane ( GU_Clip2Plane )
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gu_local.h"
|
||||||
|
|
||||||
|
#define MAX_CLIPPED_VERTICES 32
|
||||||
|
|
||||||
|
// Cache
|
||||||
|
static ScePspFMatrix4 projection_view_matrix;
|
||||||
|
|
||||||
|
// The temporary working buffers.
|
||||||
|
static gu_vert_t work_buffer[2][MAX_CLIPPED_VERTICES] __attribute__(( aligned( 16 )));
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GU_ClipGetFrustum
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
_inline void GU_ClipGetAndStoreFrustum( const ScePspFMatrix4 *matrix )
|
||||||
|
{
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"vzero.q C210\n" // set zero vector
|
||||||
|
"lv.q C100, 0(%0)\n" // C000 = matrix->x
|
||||||
|
"lv.q C110, 16(%0)\n" // C010 = matrix->y
|
||||||
|
"lv.q C120, 32(%0)\n" // C020 = matrix->z
|
||||||
|
"lv.q C130, 48(%0)\n" // C030 = matrix->w
|
||||||
|
"vadd.q C000, R103, R101\n" // C000 = R103 + R101 ( BOTTOM )
|
||||||
|
"vadd.q C010, R103, R100\n" // C010 = R103 + R100 ( LEFT )
|
||||||
|
"vsub.q C020, R103, R100\n" // C020 = R103 - R100 ( RIGHT )
|
||||||
|
"vsub.q C030, R103, R101\n" // C030 = R103 - R101 ( TOP )
|
||||||
|
"vdot.q S200, C000, C000\n" // S110 = S100*S100 + S101*S101 + S102*S102 + S103*S103 ( BOTTOM )
|
||||||
|
"vdot.q S201, C010, C010\n" // S110 = S100*S100 + S101*S101 + S102*S102 + S103*S103 ( LEFT )
|
||||||
|
"vdot.q S202, C020, C020\n" // S110 = S100*S100 + S101*S101 + S102*S102 + S103*S103 ( RIGHT )
|
||||||
|
"vdot.q S203, C030, C030\n" // S110 = S100*S100 + S101*S101 + S102*S102 + S103*S103 ( TOP )
|
||||||
|
"vcmp.q EZ, C200\n" // CC[*] = ( C200 == 0.0f )
|
||||||
|
"vrsq.q C200, C200\n" // C200 = 1.0 / sqrt( C200 )
|
||||||
|
"vcmovt.q C200, C210, 6\n" // if ( CC[*] ) C200 = C210
|
||||||
|
"vscl.q C700, C000, S200\n" // C700 = C000 * S200 ( BOTTOM )
|
||||||
|
"vscl.q C710, C010, S201\n" // C710 = C010 * S201 ( LEFT )
|
||||||
|
"vscl.q C720, C020, S202\n" // C720 = C020 * S202 ( RIGHT )
|
||||||
|
"vscl.q C730, C030, S203\n" // C730 = C030 * S203 ( TOP )
|
||||||
|
".set pop\n" // Restore assembler option
|
||||||
|
:: "r"( matrix )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GU_ClipBeginFrame
|
||||||
|
|
||||||
|
Calculate the clipping frustum for static objects
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GU_ClipSetWorldFrustum( const matrix4x4 in )
|
||||||
|
{
|
||||||
|
// Get matrix.
|
||||||
|
Matrix4x4_ToFMatrix4( in, &projection_view_matrix );
|
||||||
|
|
||||||
|
// Calculate and cache the clipping frustum.
|
||||||
|
GU_ClipGetAndStoreFrustum( &projection_view_matrix );
|
||||||
|
|
||||||
|
// Save the clipping frustum.
|
||||||
|
__asm__ volatile(
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"vmmov.q M600, M700\n" // Save frustum
|
||||||
|
".set pop\n" // Restore assembler option
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GU_ClipRestoreWorldFrustum
|
||||||
|
|
||||||
|
Restore the clipping frustum
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GU_ClipRestoreWorldFrustum( void )
|
||||||
|
{
|
||||||
|
// Restore the clipping frustum.
|
||||||
|
__asm__ volatile(
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"vmmov.q M700, M600\n" // Restore frustum
|
||||||
|
".set pop\n" // Restore assembler option
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GU_ClipSetModelFrustum
|
||||||
|
|
||||||
|
Calculate the clipping frustum for dynamic objects
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GU_ClipSetModelFrustum( const matrix4x4 in )
|
||||||
|
{
|
||||||
|
ScePspFMatrix4 model_matrix;
|
||||||
|
ScePspFMatrix4 projection_view_model_matrix;
|
||||||
|
|
||||||
|
// Get matrix.
|
||||||
|
Matrix4x4_ToFMatrix4( in, &model_matrix );
|
||||||
|
|
||||||
|
// Combine the matrices (multiply projection-view by model).
|
||||||
|
gumMultMatrix( &projection_view_model_matrix, &projection_view_matrix, &model_matrix );
|
||||||
|
|
||||||
|
// Calculate and cache the clipping frustum.
|
||||||
|
GU_ClipGetAndStoreFrustum( &projection_view_model_matrix );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GU_ClipLoadFrustum
|
||||||
|
|
||||||
|
Load the clipping frustum ( native )
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
void GU_ClipLoadFrustum( const mplane_t *plane )
|
||||||
|
{
|
||||||
|
__asm__ volatile(
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"ulv.q C700, %0\n" // Load plane into register
|
||||||
|
"ulv.q C710, %1\n" // Load plane into register
|
||||||
|
"ulv.q C720, %2\n" // Load plane into register
|
||||||
|
"ulv.q C730, %3\n" // Load plane into register
|
||||||
|
"vneg.q R703, R703\n" // R703 = -R703 = -dist
|
||||||
|
".set pop\n" // Restore assembler option
|
||||||
|
:: "m"( plane[FRUSTUM_BOTTOM] ),
|
||||||
|
"m"( plane[FRUSTUM_LEFT] ),
|
||||||
|
"m"( plane[FRUSTUM_RIGHT] ),
|
||||||
|
"m"( plane[FRUSTUM_TOP] )
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GU_ClipIsRequired
|
||||||
|
|
||||||
|
Is clipping required?
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
int GU_ClipIsRequired( gu_vert_t* uv, int uvc )
|
||||||
|
{
|
||||||
|
int result = 1;
|
||||||
|
gu_vert_t *uv_end = uv + ( uvc - 1 );
|
||||||
|
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"vzero.q C000\n" // C000 = [0.0f, 0.0f, 0.0f. 0.0f]
|
||||||
|
"0:\n" // loop
|
||||||
|
"lv.s S010, 8(%1)\n" // S010 = v[i].xyz[0]
|
||||||
|
"lv.s S011, 12(%1)\n" // S011 = v[i].xyz[1]
|
||||||
|
"lv.s S012, 16(%1)\n" // S012 = v[i].xyz[2]
|
||||||
|
"vhtfm4.q C020, M700, C010\n" // C020 = frustrum * v[i].xyz
|
||||||
|
"vcmp.q LT, C020, C000\n" // S020 < 0.0f || S021 < 0.0f || S022 < 0.0f || S023 < 0.0f
|
||||||
|
"bvt 4, 1f\n" // if ( CC[4] == 1 ) jump to exit
|
||||||
|
"nop\n" // ( delay slot )
|
||||||
|
"bne %1, %2, 0b\n" // if ( $10 != $8 ) jump to loop
|
||||||
|
"addiu %1, %1, %3\n" // $8 = $8 + sizeof( gu_vert_t ) ( delay slot )
|
||||||
|
"move %0, $0\n" // res = 0
|
||||||
|
"1:\n" // exit
|
||||||
|
".set pop\n" // Restore assembler option
|
||||||
|
: "=r"( result ), "+r"( uv )
|
||||||
|
: "r"( uv_end ),
|
||||||
|
"n"(sizeof( gu_vert_t ))
|
||||||
|
: "$8"
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GU_Clip2Plane
|
||||||
|
|
||||||
|
Clips a polygon against a plane.
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
_inline void GU_Clip2Plane( gu_vert_t *uv, int uvc, gu_vert_t *cv, int *cvc )
|
||||||
|
{
|
||||||
|
gu_vert_t *uv_end = uv + ( uvc - 1 );
|
||||||
|
gu_vert_t *cv_start = cv;
|
||||||
|
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"vzero.q C000\n" // set zero vector
|
||||||
|
"lv.s S200, 8(%2)\n" // Load vertex P XYZ(4b) X into register
|
||||||
|
"lv.s S201, 12(%2)\n" // Load vertex P XYZ(4b) Y into register
|
||||||
|
"lv.s S202, 16(%2)\n" // Load vertex P XYZ(4b) Z into register
|
||||||
|
"lv.s S210, 0(%2)\n" // Load vertex P TEX(4b) U into register
|
||||||
|
"lv.s S211, 4(%2)\n" // Load vertex P TEX(4b) V into register
|
||||||
|
"vhdp.q S212, C200, C010\n" // distance P -> dP
|
||||||
|
"0:\n"
|
||||||
|
"lv.s S220, 8(%1)\n" // Load vertex S XYZ(4b) X into register
|
||||||
|
"lv.s S221, 12(%1)\n" // Load vertex S XYZ(4b) Y into register
|
||||||
|
"lv.s S222, 16(%1)\n" // Load vertex S XYZ(4b) Z into register
|
||||||
|
"lv.s S230, 0(%1)\n" // Load vertex S TEX(4b) U into register
|
||||||
|
"lv.s S231, 4(%1)\n" // Load vertex S TEX(4b) V into register
|
||||||
|
"vhdp.q S232, C220, C010\n" // distance S -> dS
|
||||||
|
"vcmp.s GT, S212, S000\n" // if (dP <= 0)
|
||||||
|
"bvf 0, 1f\n" // goto 1:
|
||||||
|
"nop\n"
|
||||||
|
"sv.s S210, 0(%0)\n" // cv->uv[0] = C020 U
|
||||||
|
"sv.s S211, 4(%0)\n" // cv->uv[1] = C021 V
|
||||||
|
"sv.s S200, 8(%0)\n" // cv->xyz[0] = C030 X
|
||||||
|
"sv.s S201, 12(%0)\n" // cv->xyz[1] = C031 Y
|
||||||
|
"sv.s S202, 16(%0)\n" // cv->xyz[2] = C032 Z
|
||||||
|
"addiu %0, %0, %3\n" // cv + sizeof(gu_vert_t)
|
||||||
|
"1:\n"
|
||||||
|
"vmul.s S020, S232, S212\n" // (dS * dP)
|
||||||
|
"vcmp.s LT, S020, S000\n" // if (dS * dP < 0)
|
||||||
|
"bvf 0, 2f\n" // goto 2:
|
||||||
|
"vsub.s S021, S232, S212\n" // (dS - dP)
|
||||||
|
"vrcp.s S021, S021\n"
|
||||||
|
"vmul.s S021, S021, S232\n" // R = dS / ( dS - dP )
|
||||||
|
#if 0
|
||||||
|
"vsub.t C200, C220, C200\n" // (S - P) XYZ
|
||||||
|
"vsub.p C210, C230, C210\n" // (S - P) UV
|
||||||
|
"vscl.t C200, C200, S021\n" // ((S - P) * R) XYZ
|
||||||
|
"vscl.p C210, C210, S021\n" // ((S - P) * R) UV
|
||||||
|
"vsub.t C200, C220, C200\n" // (S - (S - P) * R) XYZ
|
||||||
|
"vsub.p C210, C230, C210\n" // (S - (S - P) * R) UV
|
||||||
|
#else
|
||||||
|
"vsub.t C200, C200, C220\n" // (P - S) XYZ
|
||||||
|
"vsub.p C210, C210, C230\n" // (P - S) UV
|
||||||
|
"vscl.t C200, C200, S021\n" // ((P - S) * R) XYZ
|
||||||
|
"vscl.p C210, C210, S021\n" // ((P - S) * R) UV
|
||||||
|
"vadd.t C200, C220, C200\n" // (S + (P - S) * R) XYZ
|
||||||
|
"vadd.p C210, C230, C210\n" // (S + (P - S) * R) UV
|
||||||
|
#endif
|
||||||
|
"sv.s S210, 0(%0)\n" // cv->uv[0] = S210 U
|
||||||
|
"sv.s S211, 4(%0)\n" // cv->uv[1] = S211 V
|
||||||
|
"sv.s S200, 8(%0)\n" // cv->xyz[0] = S200 X
|
||||||
|
"sv.s S201, 12(%0)\n" // cv->xyz[1] = S201 Y
|
||||||
|
"sv.s S202, 16(%0)\n" // cv->xyz[2] = S202 Z
|
||||||
|
"addiu %0, %0, %3\n" // cv + sizeof(gu_vert_t)
|
||||||
|
"2:\n"
|
||||||
|
"vmov.t C200, C220\n" // P = S XYZ
|
||||||
|
"vmov.t C210, C230\n" // P = S UV and dS
|
||||||
|
"bne %1, %2, 0b\n" // if (uv != uv_end) goto 0:
|
||||||
|
"addiu %1, %1, %3\n" // uv + sizeof(gu_vert_t) ( delay slot )
|
||||||
|
".set pop\n" // suppress reordering
|
||||||
|
: "+r"( cv ), "+r"( uv )
|
||||||
|
: "r"( uv_end ),
|
||||||
|
"n"( sizeof( gu_vert_t ))
|
||||||
|
: "memory"
|
||||||
|
) ;
|
||||||
|
*cvc = ( cv - cv_start );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GU_Clip
|
||||||
|
|
||||||
|
Clips a polygon against the frustum
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GU_Clip( gu_vert_t *uv, int uvc, gu_vert_t **cv, int* cvc )
|
||||||
|
{
|
||||||
|
size_t vc;
|
||||||
|
|
||||||
|
if ( !uvc ) // no vertices to clip?
|
||||||
|
gEngfuncs.Host_Error( "GU_Clip: calling clip with zero vertices!" );
|
||||||
|
|
||||||
|
vc = uvc;
|
||||||
|
*cvc = 0;
|
||||||
|
|
||||||
|
__asm__ volatile(
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"vmov.q C010, C700\n" // CPLANE_BOTTOM
|
||||||
|
".set pop\n" // suppress reordering
|
||||||
|
);
|
||||||
|
GU_Clip2Plane( uv, vc, work_buffer[0], &vc );
|
||||||
|
if ( !vc ) return;
|
||||||
|
|
||||||
|
__asm__ volatile(
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"vmov.q C010, C710\n" // CPLANE_LEFT
|
||||||
|
".set pop\n" // suppress reordering
|
||||||
|
);
|
||||||
|
GU_Clip2Plane( work_buffer[0], vc, work_buffer[1], &vc );
|
||||||
|
if ( !vc ) return;
|
||||||
|
|
||||||
|
__asm__ volatile(
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"vmov.q C010, C720\n" // CPLANE_RIGHT
|
||||||
|
".set pop\n" // suppress reordering
|
||||||
|
);
|
||||||
|
GU_Clip2Plane( work_buffer[1], vc, work_buffer[0], &vc );
|
||||||
|
if ( !vc ) return;
|
||||||
|
|
||||||
|
__asm__ volatile(
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"vmov.q C010, C730\n" // CPLANE_TOP
|
||||||
|
".set pop\n" // suppress reordering
|
||||||
|
);
|
||||||
|
*cv = extGuBeginPacket( NULL ); // uncached
|
||||||
|
GU_Clip2Plane( work_buffer[0], vc, *cv, cvc );
|
||||||
|
if (!( *cvc )) return;
|
||||||
|
extGuEndPacket(( void * )( *cv + *cvc ));
|
||||||
|
}
|
||||||
503
ref_gu/gu_context.c
Normal file
503
ref_gu/gu_context.c
Normal file
@@ -0,0 +1,503 @@
|
|||||||
|
/*
|
||||||
|
vid_sdl.c - SDL vid component
|
||||||
|
Copyright (C) 2018 a1batross
|
||||||
|
Copyright (C) 2021 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// GL API function pointers, if any, reside in this translation unit
|
||||||
|
#define APIENTRY_LINKAGE
|
||||||
|
#include "gu_local.h"
|
||||||
|
|
||||||
|
ref_api_t gEngfuncs;
|
||||||
|
ref_globals_t *gpGlobals;
|
||||||
|
|
||||||
|
static void R_ClearScreen( void )
|
||||||
|
{
|
||||||
|
sceGuClearColor( 0x00000000 );
|
||||||
|
sceGuClear( GU_COLOR_BUFFER_BIT );
|
||||||
|
}
|
||||||
|
|
||||||
|
static const byte *R_GetTextureOriginalBuffer( unsigned int idx )
|
||||||
|
{
|
||||||
|
gl_texture_t *glt = R_GetTexture( idx );
|
||||||
|
|
||||||
|
if( !glt || !glt->original || !glt->original->buffer )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return glt->original->buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
CL_FillRGBA
|
||||||
|
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
static void CL_FillRGBA( float _x, float _y, float _w, float _h, int r, int g, int b, int a )
|
||||||
|
{
|
||||||
|
sceGuDisable( GU_TEXTURE_2D );
|
||||||
|
sceGuEnable( GU_BLEND );
|
||||||
|
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
||||||
|
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, GUBLEND1 );
|
||||||
|
sceGuColor( GUCOLOR4UB( r, g, b, a ) );
|
||||||
|
|
||||||
|
gu_vert_hv_t* const out = ( gu_vert_hv_t* )sceGuGetMemory( sizeof( gu_vert_hv_t ) * 2 );
|
||||||
|
out[0].x = _x;
|
||||||
|
out[0].y = _y;
|
||||||
|
out[0].z = 0;
|
||||||
|
out[1].x = _x + _w;
|
||||||
|
out[1].y = _y + _h;
|
||||||
|
out[1].z = 0;
|
||||||
|
sceGuDrawArray( GU_SPRITES, GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, out );
|
||||||
|
|
||||||
|
sceGuColor( 0xffffffff );
|
||||||
|
sceGuEnable( GU_TEXTURE_2D );
|
||||||
|
sceGuDisable( GU_BLEND );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
pfnFillRGBABlend
|
||||||
|
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
static void GAME_EXPORT CL_FillRGBABlend( float _x, float _y, float _w, float _h, int r, int g, int b, int a )
|
||||||
|
{
|
||||||
|
sceGuDisable( GU_TEXTURE_2D );
|
||||||
|
sceGuEnable( GU_BLEND );
|
||||||
|
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
||||||
|
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_DST_ALPHA, 0, 0 );
|
||||||
|
sceGuColor( GUCOLOR4UB( r, g, b, a ) );
|
||||||
|
|
||||||
|
gu_vert_hv_t* const out = ( gu_vert_hv_t* )sceGuGetMemory( sizeof( gu_vert_hv_t ) * 2 );
|
||||||
|
out[0].x = _x;
|
||||||
|
out[0].y = _y;
|
||||||
|
out[0].z = 0;
|
||||||
|
out[1].x = _x + _w;
|
||||||
|
out[1].y = _y + _h;
|
||||||
|
out[1].z = 0;
|
||||||
|
sceGuDrawArray( GU_SPRITES, GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, out );
|
||||||
|
|
||||||
|
sceGuColor( 0xffffffff );
|
||||||
|
sceGuEnable( GU_TEXTURE_2D );
|
||||||
|
sceGuDisable( GU_BLEND );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mod_BrushUnloadTextures( model_t *mod )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < mod->numtextures; i++ )
|
||||||
|
{
|
||||||
|
texture_t *tx = mod->textures[i];
|
||||||
|
if( !tx || tx->gl_texturenum == tr.defaultTexture )
|
||||||
|
continue; // free slot
|
||||||
|
|
||||||
|
GL_FreeTexture( tx->gl_texturenum ); // main texture
|
||||||
|
GL_FreeTexture( tx->fb_texturenum ); // luma texture
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mod_UnloadTextures( model_t *mod )
|
||||||
|
{
|
||||||
|
Assert( mod != NULL );
|
||||||
|
|
||||||
|
switch( mod->type )
|
||||||
|
{
|
||||||
|
case mod_studio:
|
||||||
|
Mod_StudioUnloadTextures( mod->cache.data );
|
||||||
|
break;
|
||||||
|
case mod_alias:
|
||||||
|
Mod_AliasUnloadTextures( mod->cache.data );
|
||||||
|
break;
|
||||||
|
case mod_brush:
|
||||||
|
Mod_BrushUnloadTextures( mod );
|
||||||
|
break;
|
||||||
|
case mod_sprite:
|
||||||
|
Mod_SpriteUnloadTextures( mod->cache.data );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ASSERT( 0 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf )
|
||||||
|
{
|
||||||
|
qboolean loaded = true;
|
||||||
|
|
||||||
|
if( create )
|
||||||
|
{
|
||||||
|
switch( mod->type )
|
||||||
|
{
|
||||||
|
case mod_studio:
|
||||||
|
// Mod_LoadStudioModel( mod, buf, loaded );
|
||||||
|
break;
|
||||||
|
case mod_sprite:
|
||||||
|
Mod_LoadSpriteModel( mod, buf, &loaded, mod->numtexinfo );
|
||||||
|
break;
|
||||||
|
case mod_alias:
|
||||||
|
Mod_LoadAliasModel( mod, buf, &loaded );
|
||||||
|
break;
|
||||||
|
case mod_brush:
|
||||||
|
// Mod_LoadBrushModel( mod, buf, loaded );
|
||||||
|
break;
|
||||||
|
default: gEngfuncs.Host_Error( "Mod_LoadModel: unsupported type %d\n", mod->type );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( loaded && gEngfuncs.drawFuncs->Mod_ProcessUserData )
|
||||||
|
gEngfuncs.drawFuncs->Mod_ProcessUserData( mod, create, buf );
|
||||||
|
|
||||||
|
if( !create )
|
||||||
|
Mod_UnloadTextures( mod );
|
||||||
|
|
||||||
|
return loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GL_RefGetParm( int parm, int arg )
|
||||||
|
{
|
||||||
|
gl_texture_t *glt;
|
||||||
|
|
||||||
|
switch( parm )
|
||||||
|
{
|
||||||
|
case PARM_TEX_WIDTH:
|
||||||
|
glt = R_GetTexture( arg );
|
||||||
|
return glt->width;
|
||||||
|
case PARM_TEX_HEIGHT:
|
||||||
|
glt = R_GetTexture( arg );
|
||||||
|
return glt->height;
|
||||||
|
case PARM_TEX_SRC_WIDTH:
|
||||||
|
glt = R_GetTexture( arg );
|
||||||
|
return glt->srcWidth;
|
||||||
|
case PARM_TEX_SRC_HEIGHT:
|
||||||
|
glt = R_GetTexture( arg );
|
||||||
|
return glt->srcHeight;
|
||||||
|
case PARM_TEX_GLFORMAT:
|
||||||
|
glt = R_GetTexture( arg );
|
||||||
|
return glt->format;
|
||||||
|
case PARM_TEX_ENCODE:
|
||||||
|
/*glt = R_GetTexture( arg );*/
|
||||||
|
return /*glt->encode*/0;
|
||||||
|
case PARM_TEX_MIPCOUNT:
|
||||||
|
glt = R_GetTexture( arg );
|
||||||
|
return glt->numMips;
|
||||||
|
case PARM_TEX_DEPTH:
|
||||||
|
/*glt = R_GetTexture( arg );*/
|
||||||
|
return /*glt->depth*/1;
|
||||||
|
case PARM_TEX_SKYBOX:
|
||||||
|
Assert( arg >= 0 && arg < 6 );
|
||||||
|
return tr.skyboxTextures[arg];
|
||||||
|
case PARM_TEX_SKYTEXNUM:
|
||||||
|
return tr.skytexturenum;
|
||||||
|
case PARM_TEX_LIGHTMAP:
|
||||||
|
arg = bound( 0, arg, MAX_LIGHTMAPS - 1 );
|
||||||
|
return tr.lightmapTextures[arg];
|
||||||
|
case PARM_WIDESCREEN:
|
||||||
|
return gpGlobals->wideScreen;
|
||||||
|
case PARM_FULLSCREEN:
|
||||||
|
return gpGlobals->fullScreen;
|
||||||
|
case PARM_SCREEN_WIDTH:
|
||||||
|
return gpGlobals->width;
|
||||||
|
case PARM_SCREEN_HEIGHT:
|
||||||
|
return gpGlobals->height;
|
||||||
|
case PARM_TEX_TARGET:
|
||||||
|
/*glt = R_GetTexture( arg );*/
|
||||||
|
return /*glt->target*/0;
|
||||||
|
case PARM_TEX_TEXNUM:
|
||||||
|
/*glt = R_GetTexture( arg );*/
|
||||||
|
return /*glt->texnum*/0;
|
||||||
|
case PARM_TEX_FLAGS:
|
||||||
|
glt = R_GetTexture( arg );
|
||||||
|
return glt->flags;
|
||||||
|
case PARM_ACTIVE_TMU:
|
||||||
|
return 0;
|
||||||
|
case PARM_LIGHTSTYLEVALUE:
|
||||||
|
arg = bound( 0, arg, MAX_LIGHTSTYLES - 1 );
|
||||||
|
return tr.lightstylevalue[arg];
|
||||||
|
case PARM_MAX_IMAGE_UNITS:
|
||||||
|
return 1;
|
||||||
|
case PARM_REBUILD_GAMMA:
|
||||||
|
return glConfig.softwareGammaUpdate;
|
||||||
|
case PARM_SURF_SAMPLESIZE:
|
||||||
|
if( arg >= 0 && arg < WORLDMODEL->numsurfaces )
|
||||||
|
return gEngfuncs.Mod_SampleSizeForFace( &WORLDMODEL->surfaces[arg] );
|
||||||
|
return LM_SAMPLE_SIZE;
|
||||||
|
case PARM_GL_CONTEXT_TYPE:
|
||||||
|
return CONTEXT_TYPE_GL;
|
||||||
|
case PARM_GLES_WRAPPER:
|
||||||
|
return GLES_WRAPPER_NONE;
|
||||||
|
case PARM_STENCIL_ACTIVE:
|
||||||
|
return glState.stencilEnabled;
|
||||||
|
case PARM_SKY_SPHERE:
|
||||||
|
return ENGINE_GET_PARM_( parm, arg ) && !tr.fCustomSkybox;
|
||||||
|
default:
|
||||||
|
return ENGINE_GET_PARM_( parm, arg );
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale )
|
||||||
|
{
|
||||||
|
gl_texture_t *glt = R_GetTexture( texture );
|
||||||
|
|
||||||
|
if( xScale ) *xScale = glt->xscale;
|
||||||
|
if( yScale ) *yScale = glt->yscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void R_GetExtraParmsForTexture( int texture, byte *red, byte *green, byte *blue, byte *density )
|
||||||
|
{
|
||||||
|
gl_texture_t *glt = R_GetTexture( texture );
|
||||||
|
|
||||||
|
if( red ) *red = glt->fogParams[0];
|
||||||
|
if( green ) *green = glt->fogParams[1];
|
||||||
|
if( blue ) *blue = glt->fogParams[2];
|
||||||
|
if( density ) *density = glt->fogParams[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void R_SetCurrentEntity( cl_entity_t *ent )
|
||||||
|
{
|
||||||
|
RI.currententity = ent;
|
||||||
|
|
||||||
|
// set model also
|
||||||
|
if( RI.currententity != NULL )
|
||||||
|
{
|
||||||
|
RI.currentmodel = RI.currententity->model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void R_SetCurrentModel( model_t *mod )
|
||||||
|
{
|
||||||
|
RI.currentmodel = mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float R_GetFrameTime( void )
|
||||||
|
{
|
||||||
|
return tr.frametime;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *GL_TextureName( unsigned int texnum )
|
||||||
|
{
|
||||||
|
return R_GetTexture( texnum )->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const byte *GL_TextureData( unsigned int texnum )
|
||||||
|
{
|
||||||
|
rgbdata_t *pic = R_GetTexture( texnum )->original;
|
||||||
|
|
||||||
|
if( pic != NULL )
|
||||||
|
return pic->buffer;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_ProcessEntData( qboolean allocate )
|
||||||
|
{
|
||||||
|
if( !allocate )
|
||||||
|
{
|
||||||
|
tr.draw_list->num_solid_entities = 0;
|
||||||
|
tr.draw_list->num_trans_entities = 0;
|
||||||
|
tr.draw_list->num_beam_entities = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( gEngfuncs.drawFuncs->R_ProcessEntData )
|
||||||
|
gEngfuncs.drawFuncs->R_ProcessEntData( allocate );
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean R_SetDisplayTransform( ref_screen_rotation_t rotate, int offset_x, int offset_y, float scale_x, float scale_y )
|
||||||
|
{
|
||||||
|
qboolean ret = true;
|
||||||
|
if( rotate > 0 )
|
||||||
|
{
|
||||||
|
gEngfuncs.Con_Printf("rotation transform not supported\n");
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( offset_x || offset_y )
|
||||||
|
{
|
||||||
|
gEngfuncs.Con_Printf("offset transform not supported\n");
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( scale_x != 1.0f || scale_y != 1.0f )
|
||||||
|
{
|
||||||
|
gEngfuncs.Con_Printf("scale transform not supported\n");
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* GAME_EXPORT R_GetProcAddress( const char *name )
|
||||||
|
{
|
||||||
|
return gEngfuncs.GL_GetProcAddress( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *R_GetConfigName( void )
|
||||||
|
{
|
||||||
|
return "ref_gu";
|
||||||
|
}
|
||||||
|
|
||||||
|
ref_interface_t gReffuncs =
|
||||||
|
{
|
||||||
|
R_Init,
|
||||||
|
R_Shutdown,
|
||||||
|
R_GetConfigName,
|
||||||
|
R_SetDisplayTransform,
|
||||||
|
|
||||||
|
GL_SetupAttributes,
|
||||||
|
GL_InitExtensions,
|
||||||
|
GL_ClearExtensions,
|
||||||
|
|
||||||
|
R_BeginFrame,
|
||||||
|
R_RenderScene,
|
||||||
|
R_EndFrame,
|
||||||
|
R_PushScene,
|
||||||
|
R_PopScene,
|
||||||
|
GL_BackendStartFrame,
|
||||||
|
GL_BackendEndFrame,
|
||||||
|
|
||||||
|
R_ClearScreen,
|
||||||
|
R_AllowFog,
|
||||||
|
GL_SetRenderMode,
|
||||||
|
GL_SetColor4ub,
|
||||||
|
|
||||||
|
R_AddEntity,
|
||||||
|
CL_AddCustomBeam,
|
||||||
|
R_ProcessEntData,
|
||||||
|
|
||||||
|
R_ShowTextures,
|
||||||
|
|
||||||
|
R_GetTextureOriginalBuffer,
|
||||||
|
GL_LoadTextureFromBuffer,
|
||||||
|
GL_ProcessTexture,
|
||||||
|
R_SetupSky,
|
||||||
|
|
||||||
|
R_Set2DMode,
|
||||||
|
R_DrawStretchRaw,
|
||||||
|
R_DrawStretchPic,
|
||||||
|
R_DrawTileClear,
|
||||||
|
CL_FillRGBA,
|
||||||
|
CL_FillRGBABlend,
|
||||||
|
|
||||||
|
VID_ScreenShot,
|
||||||
|
VID_CubemapShot,
|
||||||
|
|
||||||
|
R_LightPoint,
|
||||||
|
|
||||||
|
R_DecalShoot,
|
||||||
|
R_DecalRemoveAll,
|
||||||
|
R_CreateDecalList,
|
||||||
|
R_ClearAllDecals,
|
||||||
|
|
||||||
|
R_StudioEstimateFrame,
|
||||||
|
R_StudioLerpMovement,
|
||||||
|
CL_InitStudioAPI,
|
||||||
|
|
||||||
|
R_InitSkyClouds,
|
||||||
|
GL_SubdivideSurface,
|
||||||
|
CL_RunLightStyles,
|
||||||
|
|
||||||
|
R_GetSpriteParms,
|
||||||
|
R_GetSpriteTexture,
|
||||||
|
|
||||||
|
Mod_LoadMapSprite,
|
||||||
|
Mod_ProcessRenderData,
|
||||||
|
Mod_StudioLoadTextures,
|
||||||
|
|
||||||
|
CL_DrawParticles,
|
||||||
|
CL_DrawTracers,
|
||||||
|
CL_DrawBeams,
|
||||||
|
R_BeamCull,
|
||||||
|
|
||||||
|
GL_RefGetParm,
|
||||||
|
R_GetDetailScaleForTexture,
|
||||||
|
R_GetExtraParmsForTexture,
|
||||||
|
R_GetFrameTime,
|
||||||
|
|
||||||
|
R_SetCurrentEntity,
|
||||||
|
R_SetCurrentModel,
|
||||||
|
|
||||||
|
GL_FindTexture,
|
||||||
|
GL_TextureName,
|
||||||
|
GL_TextureData,
|
||||||
|
GL_LoadTexture,
|
||||||
|
GL_CreateTexture,
|
||||||
|
GL_LoadTextureArray,
|
||||||
|
GL_CreateTextureArray,
|
||||||
|
GL_FreeTexture,
|
||||||
|
|
||||||
|
DrawSingleDecal,
|
||||||
|
R_DecalSetupVerts,
|
||||||
|
R_EntityRemoveDecals,
|
||||||
|
|
||||||
|
R_UploadStretchRaw,
|
||||||
|
|
||||||
|
GL_Bind,
|
||||||
|
GL_SelectTexture,
|
||||||
|
GL_LoadTexMatrixExt,
|
||||||
|
GL_LoadIdentityTexMatrix,
|
||||||
|
GL_CleanUpTextureUnits,
|
||||||
|
GL_TexGen,
|
||||||
|
GL_TextureTarget,
|
||||||
|
GL_SetTexCoordArrayMode,
|
||||||
|
GL_UpdateTexSize,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
|
||||||
|
CL_DrawParticlesExternal,
|
||||||
|
R_LightVec,
|
||||||
|
R_StudioGetTexture,
|
||||||
|
|
||||||
|
R_RenderFrame,
|
||||||
|
Mod_SetOrthoBounds,
|
||||||
|
R_SpeedsMessage,
|
||||||
|
Mod_GetCurrentVis,
|
||||||
|
R_NewMap,
|
||||||
|
R_ClearScene,
|
||||||
|
R_GetProcAddress,
|
||||||
|
|
||||||
|
getTriAPI,
|
||||||
|
|
||||||
|
VGUI_DrawInit,
|
||||||
|
VGUI_DrawShutdown,
|
||||||
|
VGUI_SetupDrawingText,
|
||||||
|
VGUI_SetupDrawingRect,
|
||||||
|
VGUI_SetupDrawingImage,
|
||||||
|
VGUI_BindTexture,
|
||||||
|
VGUI_EnableTexture,
|
||||||
|
VGUI_CreateTexture,
|
||||||
|
VGUI_UploadTexture,
|
||||||
|
VGUI_UploadTextureBlock,
|
||||||
|
VGUI_DrawQuad,
|
||||||
|
VGUI_GetTextureSizes,
|
||||||
|
VGUI_GenerateTexture,
|
||||||
|
};
|
||||||
|
|
||||||
|
int EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs, ref_globals_t *globals )
|
||||||
|
{
|
||||||
|
if( version != REF_API_VERSION )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// fill in our callbacks
|
||||||
|
memcpy( funcs, &gReffuncs, sizeof( ref_interface_t ));
|
||||||
|
memcpy( &gEngfuncs, engfuncs, sizeof( ref_api_t ));
|
||||||
|
gpGlobals = globals;
|
||||||
|
|
||||||
|
return REF_API_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EXPORT GetRefHumanReadableName( char *out, size_t size )
|
||||||
|
{
|
||||||
|
Q_strncpy( out, "sceGu", size );
|
||||||
|
}
|
||||||
149
ref_gu/gu_cull.c
Normal file
149
ref_gu/gu_cull.c
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
gl_cull.c - render culling routines
|
||||||
|
Copyright (C) 2010 Uncle Mike
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gu_local.h"
|
||||||
|
#include "entity_types.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============================================================
|
||||||
|
|
||||||
|
FRUSTUM AND PVS CULLING
|
||||||
|
|
||||||
|
=============================================================
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_CullBox
|
||||||
|
|
||||||
|
Returns true if the box is completely outside the frustum
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
qboolean R_CullBox( const vec3_t mins, const vec3_t maxs )
|
||||||
|
{
|
||||||
|
return GL_FrustumCullBox( &RI.frustum, mins, maxs, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_CullSphere
|
||||||
|
|
||||||
|
Returns true if the sphere is completely outside the frustum
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
qboolean R_CullSphere( const vec3_t centre, const float radius )
|
||||||
|
{
|
||||||
|
return GL_FrustumCullSphere( &RI.frustum, centre, radius, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_CullModel
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
int R_CullModel( cl_entity_t *e, const vec3_t absmin, const vec3_t absmax )
|
||||||
|
{
|
||||||
|
if( e == gEngfuncs.GetViewModel() )
|
||||||
|
{
|
||||||
|
if( ENGINE_GET_PARM( PARM_DEV_OVERVIEW ))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if( RP_NORMALPASS() && !ENGINE_GET_PARM( PARM_THIRDPERSON ) && CL_IsViewEntityLocalPlayer())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// local client can't view himself if camera or thirdperson is not active
|
||||||
|
if( RP_LOCALCLIENT( e ) && !ENGINE_GET_PARM( PARM_THIRDPERSON ) && CL_IsViewEntityLocalPlayer())
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if( R_CullBox( absmin, absmax ))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_CullSurface
|
||||||
|
|
||||||
|
cull invisible surfaces
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
int R_CullSurface( msurface_t *surf, gl_frustum_t *frustum, uint clipflags )
|
||||||
|
{
|
||||||
|
cl_entity_t *e = RI.currententity;
|
||||||
|
|
||||||
|
if( !surf || !surf->texinfo || !surf->texinfo->texture )
|
||||||
|
return CULL_OTHER;
|
||||||
|
|
||||||
|
if( r_nocull->value )
|
||||||
|
return CULL_VISIBLE;
|
||||||
|
|
||||||
|
// world surfaces can be culled by vis frame too
|
||||||
|
if( RI.currententity == gEngfuncs.GetEntityByIndex( 0 ) && surf->visframe != tr.framecount )
|
||||||
|
return CULL_VISFRAME;
|
||||||
|
|
||||||
|
// only static ents can be culled by frustum
|
||||||
|
if( !R_StaticEntity( e )) frustum = NULL;
|
||||||
|
|
||||||
|
if( !VectorIsNull( surf->plane->normal ))
|
||||||
|
{
|
||||||
|
float dist;
|
||||||
|
|
||||||
|
// can use normal.z for world (optimisation)
|
||||||
|
if( RI.drawOrtho )
|
||||||
|
{
|
||||||
|
vec3_t orthonormal;
|
||||||
|
|
||||||
|
if( e == gEngfuncs.GetEntityByIndex( 0 ) ) orthonormal[2] = surf->plane->normal[2];
|
||||||
|
else Matrix4x4_VectorRotate( RI.objectMatrix, surf->plane->normal, orthonormal );
|
||||||
|
dist = orthonormal[2];
|
||||||
|
}
|
||||||
|
else dist = PlaneDiff( tr.modelorg, surf->plane );
|
||||||
|
|
||||||
|
if( glState.faceCull == GL_FRONT )
|
||||||
|
{
|
||||||
|
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||||
|
{
|
||||||
|
if( dist >= -BACKFACE_EPSILON )
|
||||||
|
return CULL_BACKSIDE; // wrong side
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( dist <= BACKFACE_EPSILON )
|
||||||
|
return CULL_BACKSIDE; // wrong side
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( glState.faceCull == GL_BACK )
|
||||||
|
{
|
||||||
|
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||||
|
{
|
||||||
|
if( dist <= BACKFACE_EPSILON )
|
||||||
|
return CULL_BACKSIDE; // wrong side
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( dist >= -BACKFACE_EPSILON )
|
||||||
|
return CULL_BACKSIDE; // wrong side
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( frustum && GL_FrustumCullBox( frustum, surf->info->mins, surf->info->maxs, clipflags ))
|
||||||
|
return CULL_FRUSTUM;
|
||||||
|
|
||||||
|
return CULL_VISIBLE;
|
||||||
|
}
|
||||||
124
ref_gu/gu_dbghulls.c
Normal file
124
ref_gu/gu_dbghulls.c
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
gl_dbghulls.c - loading & handling world and brushmodels
|
||||||
|
Copyright (C) 2016 Uncle Mike
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gu_local.h"
|
||||||
|
#include "mod_local.h"
|
||||||
|
|
||||||
|
#define list_entry( ptr, type, member ) \
|
||||||
|
((type *)((char *)(ptr) - (size_t)(&((type *)0)->member)))
|
||||||
|
|
||||||
|
// iterate over each entry in the list
|
||||||
|
#define list_for_each_entry( pos, head, member ) \
|
||||||
|
for( pos = list_entry( (head)->next, winding_t, member ); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = list_entry( pos->member.next, winding_t, member ))
|
||||||
|
|
||||||
|
// REFTODO: rewrite in triapi
|
||||||
|
void R_DrawWorldHull( void )
|
||||||
|
{
|
||||||
|
hull_model_t *hull = &WORLD->hull_models[0];
|
||||||
|
winding_t *poly;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if( FBitSet( r_showhull->flags, FCVAR_CHANGED ))
|
||||||
|
{
|
||||||
|
int val = bound( 0, (int)r_showhull->value, 3 );
|
||||||
|
if( val ) gEngfuncs.Mod_CreatePolygonsForHull( val );
|
||||||
|
ClearBits( r_showhull->flags, FCVAR_CHANGED );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !CVAR_TO_BOOL( r_showhull ))
|
||||||
|
return;
|
||||||
|
#if 1
|
||||||
|
sceGuDisable( GU_TEXTURE_2D );
|
||||||
|
list_for_each_entry( poly, &hull->polys, chain )
|
||||||
|
{
|
||||||
|
srand((unsigned int)poly);
|
||||||
|
sceGuColor( GU_RGBA(rand() % 256, rand() % 256, rand() % 256, rand() % 256) );
|
||||||
|
gu_vert_fv_t* const out = ( gu_vert_fv_t* )sceGuGetMemory( sizeof( gu_vert_fv_t ) * poly->numpoints );
|
||||||
|
for( i = 0; i < poly->numpoints; i++ )
|
||||||
|
{
|
||||||
|
out[i].x = poly->p[i][0];
|
||||||
|
out[i].y = poly->p[i][1];
|
||||||
|
out[i].z = poly->p[i][2];
|
||||||
|
}
|
||||||
|
sceGuDrawArray( GU_TRIANGLE_FAN, GU_VERTEX_32BITF, poly->numpoints, 0, out );
|
||||||
|
}
|
||||||
|
sceGuEnable( GU_TEXTURE_2D );
|
||||||
|
#else
|
||||||
|
pglDisable( GL_TEXTURE_2D );
|
||||||
|
list_for_each_entry( poly, &hull->polys, chain )
|
||||||
|
{
|
||||||
|
srand((unsigned int)poly);
|
||||||
|
pglColor3f( rand() % 256 / 255.0, rand() % 256 / 255.0, rand() % 256 / 255.0 );
|
||||||
|
pglBegin( GL_POLYGON );
|
||||||
|
for( i = 0; i < poly->numpoints; i++ )
|
||||||
|
pglVertex3fv( poly->p[i] );
|
||||||
|
pglEnd();
|
||||||
|
}
|
||||||
|
pglEnable( GL_TEXTURE_2D );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_DrawModelHull( void )
|
||||||
|
{
|
||||||
|
hull_model_t *hull;
|
||||||
|
winding_t *poly;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if( !CVAR_TO_BOOL( r_showhull ))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !RI.currentmodel || RI.currentmodel->name[0] != '*' )
|
||||||
|
return;
|
||||||
|
|
||||||
|
i = atoi( RI.currentmodel->name + 1 );
|
||||||
|
if( i < 1 || i >= WORLD->num_hull_models )
|
||||||
|
return;
|
||||||
|
|
||||||
|
hull = &WORLD->hull_models[i];
|
||||||
|
#if 1
|
||||||
|
sceGuDisable( GU_TEXTURE_2D );
|
||||||
|
list_for_each_entry( poly, &hull->polys, chain )
|
||||||
|
{
|
||||||
|
srand((unsigned int)poly);
|
||||||
|
sceGuColor( GU_RGBA(rand() % 256, rand() % 256, rand() % 256, rand() % 256) );
|
||||||
|
gu_vert_fv_t* const out = ( gu_vert_fv_t* )sceGuGetMemory( sizeof( gu_vert_fv_t ) * poly->numpoints );
|
||||||
|
for( i = 0; i < poly->numpoints; i++ )
|
||||||
|
{
|
||||||
|
out[i].x = poly->p[i][0];
|
||||||
|
out[i].y = poly->p[i][1];
|
||||||
|
out[i].z = poly->p[i][2];
|
||||||
|
}
|
||||||
|
sceGuDrawArray( GU_TRIANGLE_FAN, GU_VERTEX_32BITF, poly->numpoints, 0, out );
|
||||||
|
}
|
||||||
|
sceGuEnable( GU_TEXTURE_2D );
|
||||||
|
#else
|
||||||
|
pglPolygonOffset( 1.0f, 2.0 );
|
||||||
|
pglEnable( GL_POLYGON_OFFSET_FILL );
|
||||||
|
pglDisable( GL_TEXTURE_2D );
|
||||||
|
list_for_each_entry( poly, &hull->polys, chain )
|
||||||
|
{
|
||||||
|
srand((unsigned int)poly);
|
||||||
|
pglColor3f( rand() % 256 / 255.0, rand() % 256 / 255.0, rand() % 256 / 255.0 );
|
||||||
|
pglBegin( GL_POLYGON );
|
||||||
|
for( i = 0; i < poly->numpoints; i++ )
|
||||||
|
pglVertex3fv( poly->p[i] );
|
||||||
|
pglEnd();
|
||||||
|
}
|
||||||
|
pglEnable( GL_TEXTURE_2D );
|
||||||
|
pglDisable( GL_POLYGON_OFFSET_FILL );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
1268
ref_gu/gu_decals.c
Normal file
1268
ref_gu/gu_decals.c
Normal file
File diff suppressed because it is too large
Load Diff
308
ref_gu/gu_draw.c
Normal file
308
ref_gu/gu_draw.c
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
/*
|
||||||
|
gu_draw.c - orthogonal drawing stuff
|
||||||
|
Copyright (C) 2010 Uncle Mike
|
||||||
|
Copyright (C) 2021 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gu_local.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_GetImageParms
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void R_GetTextureParms( int *w, int *h, int texnum )
|
||||||
|
{
|
||||||
|
gl_texture_t *glt;
|
||||||
|
|
||||||
|
glt = R_GetTexture( texnum );
|
||||||
|
if( w ) *w = glt->srcWidth;
|
||||||
|
if( h ) *h = glt->srcHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_GetSpriteParms
|
||||||
|
|
||||||
|
same as GetImageParms but used
|
||||||
|
for sprite models
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int currentFrame, const model_t *pSprite )
|
||||||
|
{
|
||||||
|
mspriteframe_t *pFrame;
|
||||||
|
|
||||||
|
if( !pSprite || pSprite->type != mod_sprite ) return; // bad model ?
|
||||||
|
pFrame = R_GetSpriteFrame( pSprite, currentFrame, 0.0f );
|
||||||
|
|
||||||
|
if( frameWidth ) *frameWidth = pFrame->width;
|
||||||
|
if( frameHeight ) *frameHeight = pFrame->height;
|
||||||
|
if( numFrames ) *numFrames = pSprite->numframes;
|
||||||
|
}
|
||||||
|
|
||||||
|
int R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame )
|
||||||
|
{
|
||||||
|
if( !m_pSpriteModel || m_pSpriteModel->type != mod_sprite || !m_pSpriteModel->cache.data )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return R_GetSpriteFrame( m_pSpriteModel, frame, 0.0f )->gl_texturenum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_DrawStretchPic
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum )
|
||||||
|
{
|
||||||
|
float uw, uh;
|
||||||
|
gl_texture_t *glt;
|
||||||
|
|
||||||
|
GL_Bind( XASH_TEXTURE0, texnum );
|
||||||
|
|
||||||
|
glt = R_GetTexture( texnum );
|
||||||
|
|
||||||
|
gu_vert_htv_t* const out = ( gu_vert_htv_t* )sceGuGetMemory( sizeof( gu_vert_htv_t ) * 2 );
|
||||||
|
out[0].u = s1 * glt->width;
|
||||||
|
out[0].v = t1 * glt->height;
|
||||||
|
out[0].x = x;
|
||||||
|
out[0].y = y;
|
||||||
|
out[0].z = 0;
|
||||||
|
out[1].u = s2 * glt->width;
|
||||||
|
out[1].v = t2 * glt->height;
|
||||||
|
out[1].x = x + w;
|
||||||
|
out[1].y = y + h;
|
||||||
|
out[1].z = 0;
|
||||||
|
sceGuDrawArray( GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, out );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
Draw_TileClear
|
||||||
|
|
||||||
|
This repeats a 64*64 tile graphic to fill the screen around a sized down
|
||||||
|
refresh window.
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void R_DrawTileClear( int texnum, int x, int y, int w, int h )
|
||||||
|
{
|
||||||
|
float tw, th;
|
||||||
|
gl_texture_t *glt;
|
||||||
|
|
||||||
|
GL_SetRenderMode( kRenderNormal );
|
||||||
|
|
||||||
|
sceGuColor( 0xffffffff );
|
||||||
|
|
||||||
|
GL_Bind( XASH_TEXTURE0, texnum );
|
||||||
|
|
||||||
|
glt = R_GetTexture( texnum );
|
||||||
|
tw = glt->srcWidth;
|
||||||
|
th = glt->srcHeight;
|
||||||
|
|
||||||
|
gu_vert_htv_t* const out = ( gu_vert_htv_t* )sceGuGetMemory( sizeof( gu_vert_ftv_t ) * 2 );
|
||||||
|
out[0].u = x / tw * glt->width;
|
||||||
|
out[0].v = y / th * glt->height;
|
||||||
|
out[0].x = x;
|
||||||
|
out[0].y = y;
|
||||||
|
out[0].z = 0;
|
||||||
|
out[1].u = ( x + w ) / tw * glt->width;
|
||||||
|
out[1].v = ( y + h ) / th * glt->height;
|
||||||
|
out[1].x = x + w;
|
||||||
|
out[1].y = y + h;
|
||||||
|
out[1].z = 0;
|
||||||
|
sceGuDrawArray( GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, out );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_DrawStretchRaw
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty )
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
byte *raw = NULL;
|
||||||
|
gl_texture_t *tex;
|
||||||
|
|
||||||
|
if( !GL_Support( GL_ARB_TEXTURE_NPOT_EXT ))
|
||||||
|
{
|
||||||
|
int width = 1, height = 1;
|
||||||
|
|
||||||
|
// check the dimensions
|
||||||
|
width = NearestPOW( cols, true );
|
||||||
|
height = NearestPOW( rows, false );
|
||||||
|
|
||||||
|
if( cols != width || rows != height )
|
||||||
|
{
|
||||||
|
raw = GL_ResampleTexture( data, cols, rows, width, height, false );
|
||||||
|
cols = width;
|
||||||
|
rows = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
raw = (byte *)data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( cols > glConfig.max_2d_texture_size )
|
||||||
|
gEngfuncs.Host_Error( "R_DrawStretchRaw: size %i exceeds hardware limits\n", cols );
|
||||||
|
if( rows > glConfig.max_2d_texture_size )
|
||||||
|
gEngfuncs.Host_Error( "R_DrawStretchRaw: size %i exceeds hardware limits\n", rows );
|
||||||
|
|
||||||
|
pglDisable( GL_BLEND );
|
||||||
|
pglDisable( GL_ALPHA_TEST );
|
||||||
|
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||||
|
|
||||||
|
tex = R_GetTexture( tr.cinTexture );
|
||||||
|
GL_Bind( XASH_TEXTURE0, tr.cinTexture );
|
||||||
|
|
||||||
|
if( cols == tex->width && rows == tex->height )
|
||||||
|
{
|
||||||
|
if( dirty )
|
||||||
|
{
|
||||||
|
pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_BGRA, GL_UNSIGNED_BYTE, raw );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tex->size = cols * rows * 4;
|
||||||
|
tex->width = cols;
|
||||||
|
tex->height = rows;
|
||||||
|
if( dirty )
|
||||||
|
{
|
||||||
|
pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, raw );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pglBegin( GL_QUADS );
|
||||||
|
pglTexCoord2f( 0, 0 );
|
||||||
|
pglVertex2f( x, y );
|
||||||
|
pglTexCoord2f( 1, 0 );
|
||||||
|
pglVertex2f( x + w, y );
|
||||||
|
pglTexCoord2f( 1, 1 );
|
||||||
|
pglVertex2f( x + w, y + h );
|
||||||
|
pglTexCoord2f( 0, 1 );
|
||||||
|
pglVertex2f( x, y + h );
|
||||||
|
pglEnd();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_UploadStretchRaw
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, const byte *data )
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
byte *raw = NULL;
|
||||||
|
gl_texture_t *tex;
|
||||||
|
|
||||||
|
if( !GL_Support( GL_ARB_TEXTURE_NPOT_EXT ))
|
||||||
|
{
|
||||||
|
// check the dimensions
|
||||||
|
width = NearestPOW( width, true );
|
||||||
|
height = NearestPOW( height, false );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = bound( 128, width, glConfig.max_2d_texture_size );
|
||||||
|
height = bound( 128, height, glConfig.max_2d_texture_size );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( cols != width || rows != height )
|
||||||
|
{
|
||||||
|
raw = GL_ResampleTexture( data, cols, rows, width, height, false );
|
||||||
|
cols = width;
|
||||||
|
rows = height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
raw = (byte *)data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( cols > glConfig.max_2d_texture_size )
|
||||||
|
gEngfuncs.Host_Error( "R_UploadStretchRaw: size %i exceeds hardware limits\n", cols );
|
||||||
|
if( rows > glConfig.max_2d_texture_size )
|
||||||
|
gEngfuncs.Host_Error( "R_UploadStretchRaw: size %i exceeds hardware limits\n", rows );
|
||||||
|
|
||||||
|
tex = R_GetTexture( texture );
|
||||||
|
GL_Bind( GL_KEEP_UNIT, texture );
|
||||||
|
tex->width = cols;
|
||||||
|
tex->height = rows;
|
||||||
|
|
||||||
|
pglTexImage2D( GL_TEXTURE_2D, 0, tex->format, cols, rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, raw );
|
||||||
|
GL_ApplyTextureParams( tex );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
R_Set2DMode
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
void R_Set2DMode( qboolean enable )
|
||||||
|
{
|
||||||
|
if( enable )
|
||||||
|
{
|
||||||
|
if( glState.in2DMode )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// set 2D virtual screen size
|
||||||
|
#if 1 // through mode
|
||||||
|
sceGuViewport( 2048, 2048, gpGlobals->width, gpGlobals->height );
|
||||||
|
sceGuScissor( 0, 0, gpGlobals->width, gpGlobals->height );
|
||||||
|
#else
|
||||||
|
pglViewport( 0, 0, gpGlobals->width, gpGlobals->height );
|
||||||
|
pglMatrixMode( GL_PROJECTION );
|
||||||
|
pglLoadIdentity();
|
||||||
|
pglOrtho( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 );
|
||||||
|
pglMatrixMode( GL_MODELVIEW );
|
||||||
|
pglLoadIdentity();
|
||||||
|
#endif
|
||||||
|
GL_Cull( GL_NONE );
|
||||||
|
#if 1
|
||||||
|
sceGuDepthMask( GU_TRUE );
|
||||||
|
sceGuDisable( GU_DEPTH_TEST );
|
||||||
|
sceGuEnable( GU_ALPHA_TEST );
|
||||||
|
sceGuColor( 0xffffffff );
|
||||||
|
#else
|
||||||
|
pglDepthMask( GL_FALSE );
|
||||||
|
pglDisable( GL_DEPTH_TEST );
|
||||||
|
pglEnable( GL_ALPHA_TEST );
|
||||||
|
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||||
|
#endif
|
||||||
|
glState.in2DMode = true;
|
||||||
|
RI.currententity = NULL;
|
||||||
|
RI.currentmodel = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
sceGuDepthMask( GU_FALSE );
|
||||||
|
sceGuEnable( GU_DEPTH_TEST );
|
||||||
|
glState.in2DMode = false;
|
||||||
|
#else
|
||||||
|
pglDepthMask( GL_TRUE );
|
||||||
|
pglEnable( GL_DEPTH_TEST );
|
||||||
|
glState.in2DMode = false;
|
||||||
|
|
||||||
|
pglMatrixMode( GL_PROJECTION );
|
||||||
|
GL_LoadMatrix( RI.projectionMatrix );
|
||||||
|
|
||||||
|
pglMatrixMode( GL_MODELVIEW );
|
||||||
|
GL_LoadMatrix( RI.worldviewMatrix );
|
||||||
|
#endif
|
||||||
|
GL_Cull( GL_FRONT );
|
||||||
|
}
|
||||||
|
}
|
||||||
79
ref_gu/gu_extension.c
Normal file
79
ref_gu/gu_extension.c
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
gu_extension.c - PSP Graphic Unit extensions
|
||||||
|
Copyright (C) 2020 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pspkernel.h>
|
||||||
|
#include <pspge.h>
|
||||||
|
#include <pspgu.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "gu_extension.h"
|
||||||
|
|
||||||
|
/* from guInternal.h */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned int* start;
|
||||||
|
unsigned int* current;
|
||||||
|
int parent_context;
|
||||||
|
} GuDisplayList;
|
||||||
|
extern GuDisplayList* gu_list;
|
||||||
|
extern int gu_curr_context;
|
||||||
|
extern int ge_list_executed[];
|
||||||
|
|
||||||
|
static unsigned int gu_list_size;
|
||||||
|
|
||||||
|
|
||||||
|
void extGuStart(int cid, void* list, int size)
|
||||||
|
{
|
||||||
|
gu_list_size = size;
|
||||||
|
sceGuStart( cid, list );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Begin user packet */
|
||||||
|
void *extGuBeginPacket( unsigned int *maxsize )
|
||||||
|
{
|
||||||
|
unsigned int* current_ptr = gu_list->current;
|
||||||
|
if( maxsize != NULL )
|
||||||
|
{
|
||||||
|
unsigned int size = ( ( unsigned int )gu_list->current ) - ( ( unsigned int )gu_list->start );
|
||||||
|
*maxsize = ( ( unsigned int )gu_list_size ) - ( ( unsigned int )size );
|
||||||
|
}
|
||||||
|
return current_ptr + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* End user packet */
|
||||||
|
void extGuEndPacket( void *eaddr )
|
||||||
|
{
|
||||||
|
unsigned int* current_ptr = gu_list->current;
|
||||||
|
unsigned int size = ( ( unsigned int ) eaddr ) - ( ( unsigned int )current_ptr );
|
||||||
|
|
||||||
|
if( size > 0 )
|
||||||
|
{
|
||||||
|
size += 3;
|
||||||
|
size += ( ( unsigned int )( size >> 31 ) ) >> 30;
|
||||||
|
size = ( size >> 2 ) << 2;
|
||||||
|
|
||||||
|
unsigned int* new_ptr = ( unsigned int* )( ( ( unsigned int ) current_ptr ) + size + 8 );
|
||||||
|
|
||||||
|
int lo = ( 8 << 24 ) | ( ( ( unsigned int )new_ptr ) & 0xffffff );
|
||||||
|
int hi = ( 16 << 24 ) | ( ( ( ( unsigned int )new_ptr ) >> 8 ) & 0xf0000 );
|
||||||
|
|
||||||
|
current_ptr[0] = hi;
|
||||||
|
current_ptr[1] = lo;
|
||||||
|
|
||||||
|
gu_list->current = new_ptr;
|
||||||
|
|
||||||
|
if ( !gu_curr_context )
|
||||||
|
sceGeListUpdateStallAddr( ge_list_executed[0], new_ptr );
|
||||||
|
}
|
||||||
|
}
|
||||||
23
ref_gu/gu_extension.h
Normal file
23
ref_gu/gu_extension.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
gu_extension.h - PSP Graphic Unit extensions header
|
||||||
|
Copyright (C) 2020 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GU_EXTENSION_H
|
||||||
|
#define GU_EXTENSION_H
|
||||||
|
|
||||||
|
void extGuStart(int cid, void* list, int size);
|
||||||
|
void *extGuBeginPacket( unsigned int *maxsize );
|
||||||
|
void extGuEndPacket( void *eaddr );
|
||||||
|
|
||||||
|
#endif//GU_EXTENSION_H
|
||||||
356
ref_gu/gu_frustum.c
Normal file
356
ref_gu/gu_frustum.c
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
/*
|
||||||
|
gu_frustum.cpp - frustum test implementation
|
||||||
|
Copyright (C) 2016 Uncle Mike
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gu_local.h"
|
||||||
|
#include "xash3d_mathlib.h"
|
||||||
|
|
||||||
|
void GL_FrustumEnablePlane( gl_frustum_t *out, int side )
|
||||||
|
{
|
||||||
|
Assert( side >= 0 && side < FRUSTUM_PLANES );
|
||||||
|
|
||||||
|
// make sure what plane is ready
|
||||||
|
if( !VectorIsNull( out->planes[side].normal ))
|
||||||
|
SetBits( out->clipFlags, BIT( side ));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_FrustumDisablePlane( gl_frustum_t *out, int side )
|
||||||
|
{
|
||||||
|
Assert( side >= 0 && side < FRUSTUM_PLANES );
|
||||||
|
ClearBits( out->clipFlags, BIT( side ));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_FrustumSetPlane( gl_frustum_t *out, int side, const vec3_t vecNormal, float flDist )
|
||||||
|
{
|
||||||
|
Assert( side >= 0 && side < FRUSTUM_PLANES );
|
||||||
|
|
||||||
|
out->planes[side].type = PlaneTypeForNormal( vecNormal );
|
||||||
|
out->planes[side].signbits = SignbitsForPlane( vecNormal );
|
||||||
|
VectorCopy( vecNormal, out->planes[side].normal );
|
||||||
|
out->planes[side].dist = flDist;
|
||||||
|
|
||||||
|
SetBits( out->clipFlags, BIT( side ));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_FrustumNormalizePlane( gl_frustum_t *out, int side )
|
||||||
|
{
|
||||||
|
float length;
|
||||||
|
|
||||||
|
Assert( side >= 0 && side < FRUSTUM_PLANES );
|
||||||
|
|
||||||
|
// normalize
|
||||||
|
length = VectorLength( out->planes[side].normal );
|
||||||
|
|
||||||
|
if( length )
|
||||||
|
{
|
||||||
|
float ilength = (1.0f / length);
|
||||||
|
out->planes[side].normal[0] *= ilength;
|
||||||
|
out->planes[side].normal[1] *= ilength;
|
||||||
|
out->planes[side].normal[2] *= ilength;
|
||||||
|
out->planes[side].dist *= ilength;
|
||||||
|
}
|
||||||
|
|
||||||
|
out->planes[side].type = PlaneTypeForNormal( out->planes[side].normal );
|
||||||
|
out->planes[side].signbits = SignbitsForPlane( out->planes[side].normal );
|
||||||
|
|
||||||
|
SetBits( out->clipFlags, BIT( side ));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_FrustumInitProj( gl_frustum_t *out, float flZNear, float flZFar, float flFovX, float flFovY )
|
||||||
|
{
|
||||||
|
float xs, xc;
|
||||||
|
vec3_t farpoint, nearpoint;
|
||||||
|
vec3_t normal, iforward;
|
||||||
|
|
||||||
|
// horizontal fov used for left and right planes
|
||||||
|
SinCos( DEG2RAD( flFovX ) * 0.5f, &xs, &xc );
|
||||||
|
|
||||||
|
// setup left plane
|
||||||
|
VectorMAM( xs, RI.cull_vforward, -xc, RI.cull_vright, normal );
|
||||||
|
GL_FrustumSetPlane( out, FRUSTUM_LEFT, normal, DotProduct( RI.cullorigin, normal ));
|
||||||
|
|
||||||
|
// setup right plane
|
||||||
|
VectorMAM( xs, RI.cull_vforward, xc, RI.cull_vright, normal );
|
||||||
|
GL_FrustumSetPlane( out, FRUSTUM_RIGHT, normal, DotProduct( RI.cullorigin, normal ));
|
||||||
|
|
||||||
|
// vertical fov used for top and bottom planes
|
||||||
|
SinCos( DEG2RAD( flFovY ) * 0.5f, &xs, &xc );
|
||||||
|
VectorNegate( RI.cull_vforward, iforward );
|
||||||
|
|
||||||
|
// setup bottom plane
|
||||||
|
VectorMAM( xs, RI.cull_vforward, -xc, RI.cull_vup, normal );
|
||||||
|
GL_FrustumSetPlane( out, FRUSTUM_BOTTOM, normal, DotProduct( RI.cullorigin, normal ));
|
||||||
|
|
||||||
|
// setup top plane
|
||||||
|
VectorMAM( xs, RI.cull_vforward, xc, RI.cull_vup, normal );
|
||||||
|
GL_FrustumSetPlane( out, FRUSTUM_TOP, normal, DotProduct( RI.cullorigin, normal ));
|
||||||
|
|
||||||
|
// setup far plane
|
||||||
|
VectorMA( RI.cullorigin, flZFar, RI.cull_vforward, farpoint );
|
||||||
|
GL_FrustumSetPlane( out, FRUSTUM_FAR, iforward, DotProduct( iforward, farpoint ));
|
||||||
|
|
||||||
|
// no need to setup backplane for general view.
|
||||||
|
if( flZNear == 0.0f ) return;
|
||||||
|
|
||||||
|
// setup near plane
|
||||||
|
VectorMA( RI.cullorigin, flZNear, RI.cull_vforward, nearpoint );
|
||||||
|
GL_FrustumSetPlane( out, FRUSTUM_NEAR, RI.cull_vforward, DotProduct( RI.cull_vforward, nearpoint ));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_FrustumInitOrtho( gl_frustum_t *out, float xLeft, float xRight, float yTop, float yBottom, float flZNear, float flZFar )
|
||||||
|
{
|
||||||
|
vec3_t iforward, iright, iup;
|
||||||
|
|
||||||
|
// setup the near and far planes
|
||||||
|
float orgOffset = DotProduct( RI.cullorigin, RI.cull_vforward );
|
||||||
|
VectorNegate( RI.cull_vforward, iforward );
|
||||||
|
|
||||||
|
// because quake ortho is inverted and far and near should be swaped
|
||||||
|
GL_FrustumSetPlane( out, FRUSTUM_FAR, iforward, -flZNear - orgOffset );
|
||||||
|
GL_FrustumSetPlane( out, FRUSTUM_NEAR, RI.cull_vforward, flZFar + orgOffset );
|
||||||
|
|
||||||
|
// setup left and right planes
|
||||||
|
orgOffset = DotProduct( RI.cullorigin, RI.cull_vright );
|
||||||
|
VectorNegate( RI.cull_vright, iright );
|
||||||
|
|
||||||
|
GL_FrustumSetPlane( out, FRUSTUM_LEFT, RI.cull_vright, xLeft + orgOffset );
|
||||||
|
GL_FrustumSetPlane( out, FRUSTUM_RIGHT, iright, -xRight - orgOffset );
|
||||||
|
|
||||||
|
// setup top and buttom planes
|
||||||
|
orgOffset = DotProduct( RI.cullorigin, RI.cull_vup );
|
||||||
|
VectorNegate( RI.cull_vup, iup );
|
||||||
|
|
||||||
|
GL_FrustumSetPlane( out, FRUSTUM_TOP, RI.cull_vup, yTop + orgOffset );
|
||||||
|
GL_FrustumSetPlane( out, FRUSTUM_BOTTOM, iup, -yBottom - orgOffset );
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_FrustumInitBox( gl_frustum_t *out, const vec3_t org, float radius )
|
||||||
|
{
|
||||||
|
vec3_t normal;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for( i = 0; i < FRUSTUM_PLANES; i++ )
|
||||||
|
{
|
||||||
|
// setup normal for each direction
|
||||||
|
VectorClear( normal );
|
||||||
|
normal[((i >> 1) + 1) % 3] = (i & 1) ? 1.0f : -1.0f;
|
||||||
|
GL_FrustumSetPlane( out, i, normal, DotProduct( org, normal ) - radius );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_FrustumInitProjFromMatrix( gl_frustum_t *out, const matrix4x4 projection )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// left
|
||||||
|
out->planes[FRUSTUM_LEFT].normal[0] = projection[0][3] + projection[0][0];
|
||||||
|
out->planes[FRUSTUM_LEFT].normal[1] = projection[1][3] + projection[1][0];
|
||||||
|
out->planes[FRUSTUM_LEFT].normal[2] = projection[2][3] + projection[2][0];
|
||||||
|
out->planes[FRUSTUM_LEFT].dist = -(projection[3][3] + projection[3][0]);
|
||||||
|
|
||||||
|
// right
|
||||||
|
out->planes[FRUSTUM_RIGHT].normal[0] = projection[0][3] - projection[0][0];
|
||||||
|
out->planes[FRUSTUM_RIGHT].normal[1] = projection[1][3] - projection[1][0];
|
||||||
|
out->planes[FRUSTUM_RIGHT].normal[2] = projection[2][3] - projection[2][0];
|
||||||
|
out->planes[FRUSTUM_RIGHT].dist = -(projection[3][3] - projection[3][0]);
|
||||||
|
|
||||||
|
// bottom
|
||||||
|
out->planes[FRUSTUM_BOTTOM].normal[0] = projection[0][3] + projection[0][1];
|
||||||
|
out->planes[FRUSTUM_BOTTOM].normal[1] = projection[1][3] + projection[1][1];
|
||||||
|
out->planes[FRUSTUM_BOTTOM].normal[2] = projection[2][3] + projection[2][1];
|
||||||
|
out->planes[FRUSTUM_BOTTOM].dist = -(projection[3][3] + projection[3][1]);
|
||||||
|
|
||||||
|
// top
|
||||||
|
out->planes[FRUSTUM_TOP].normal[0] = projection[0][3] - projection[0][1];
|
||||||
|
out->planes[FRUSTUM_TOP].normal[1] = projection[1][3] - projection[1][1];
|
||||||
|
out->planes[FRUSTUM_TOP].normal[2] = projection[2][3] - projection[2][1];
|
||||||
|
out->planes[FRUSTUM_TOP].dist = -(projection[3][3] - projection[3][1]);
|
||||||
|
|
||||||
|
// near
|
||||||
|
out->planes[FRUSTUM_NEAR].normal[0] = projection[0][3] + projection[0][2];
|
||||||
|
out->planes[FRUSTUM_NEAR].normal[1] = projection[1][3] + projection[1][2];
|
||||||
|
out->planes[FRUSTUM_NEAR].normal[2] = projection[2][3] + projection[2][2];
|
||||||
|
out->planes[FRUSTUM_NEAR].dist = -(projection[3][3] + projection[3][2]);
|
||||||
|
|
||||||
|
// far
|
||||||
|
out->planes[FRUSTUM_FAR].normal[0] = projection[0][3] - projection[0][2];
|
||||||
|
out->planes[FRUSTUM_FAR].normal[1] = projection[1][3] - projection[1][2];
|
||||||
|
out->planes[FRUSTUM_FAR].normal[2] = projection[2][3] - projection[2][2];
|
||||||
|
out->planes[FRUSTUM_FAR].dist = -(projection[3][3] - projection[3][2]);
|
||||||
|
|
||||||
|
for( i = 0; i < FRUSTUM_PLANES; i++ )
|
||||||
|
{
|
||||||
|
GL_FrustumNormalizePlane( out, i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_FrustumComputeCorners( gl_frustum_t *out, vec3_t corners[8] )
|
||||||
|
{
|
||||||
|
memset( corners, 0, sizeof( vec3_t ) * 8 );
|
||||||
|
|
||||||
|
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_LEFT], &out->planes[FRUSTUM_TOP], &out->planes[FRUSTUM_FAR], corners[0] );
|
||||||
|
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_RIGHT], &out->planes[FRUSTUM_TOP], &out->planes[FRUSTUM_FAR], corners[1] );
|
||||||
|
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_LEFT], &out->planes[FRUSTUM_BOTTOM], &out->planes[FRUSTUM_FAR], corners[2] );
|
||||||
|
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_RIGHT], &out->planes[FRUSTUM_BOTTOM], &out->planes[FRUSTUM_FAR], corners[3] );
|
||||||
|
|
||||||
|
if( FBitSet( out->clipFlags, BIT( FRUSTUM_NEAR )))
|
||||||
|
{
|
||||||
|
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_LEFT], &out->planes[FRUSTUM_TOP], &out->planes[FRUSTUM_NEAR], corners[4] );
|
||||||
|
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_RIGHT], &out->planes[FRUSTUM_TOP], &out->planes[FRUSTUM_NEAR], corners[5] );
|
||||||
|
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_LEFT], &out->planes[FRUSTUM_BOTTOM], &out->planes[FRUSTUM_NEAR], corners[6] );
|
||||||
|
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_RIGHT], &out->planes[FRUSTUM_BOTTOM], &out->planes[FRUSTUM_NEAR], corners[7] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PlanesGetIntersectionPoint( &out->planes[FRUSTUM_LEFT], &out->planes[FRUSTUM_RIGHT], &out->planes[FRUSTUM_TOP], corners[4] );
|
||||||
|
VectorCopy( corners[4], corners[5] );
|
||||||
|
VectorCopy( corners[4], corners[6] );
|
||||||
|
VectorCopy( corners[4], corners[7] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_FrustumComputeBounds( gl_frustum_t *out, vec3_t mins, vec3_t maxs )
|
||||||
|
{
|
||||||
|
vec3_t corners[8];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
GL_FrustumComputeCorners( out, corners );
|
||||||
|
|
||||||
|
ClearBounds( mins, maxs );
|
||||||
|
|
||||||
|
for( i = 0; i < 8; i++ )
|
||||||
|
AddPointToBounds( corners[i], mins, maxs );
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_FrustumDrawDebug( gl_frustum_t *out )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
vec3_t bbox[8];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
GL_FrustumComputeCorners( out, bbox );
|
||||||
|
|
||||||
|
// g-cont. frustum must be yellow :-)
|
||||||
|
pglColor4f( 1.0f, 1.0f, 0.0f, 1.0f );
|
||||||
|
pglDisable( GL_TEXTURE_2D );
|
||||||
|
pglBegin( GL_LINES );
|
||||||
|
|
||||||
|
for( i = 0; i < 2; i += 1 )
|
||||||
|
{
|
||||||
|
pglVertex3fv( bbox[i+0] );
|
||||||
|
pglVertex3fv( bbox[i+2] );
|
||||||
|
pglVertex3fv( bbox[i+4] );
|
||||||
|
pglVertex3fv( bbox[i+6] );
|
||||||
|
pglVertex3fv( bbox[i+0] );
|
||||||
|
pglVertex3fv( bbox[i+4] );
|
||||||
|
pglVertex3fv( bbox[i+2] );
|
||||||
|
pglVertex3fv( bbox[i+6] );
|
||||||
|
pglVertex3fv( bbox[i*2+0] );
|
||||||
|
pglVertex3fv( bbox[i*2+1] );
|
||||||
|
pglVertex3fv( bbox[i*2+4] );
|
||||||
|
pglVertex3fv( bbox[i*2+5] );
|
||||||
|
}
|
||||||
|
|
||||||
|
pglEnd();
|
||||||
|
pglEnable( GL_TEXTURE_2D );
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// cull methods
|
||||||
|
qboolean GL_FrustumCullBox( gl_frustum_t *out, const vec3_t mins, const vec3_t maxs, int userClipFlags )
|
||||||
|
{
|
||||||
|
int iClipFlags;
|
||||||
|
int i, bit;
|
||||||
|
|
||||||
|
if( r_nocull->value )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( userClipFlags != 0 )
|
||||||
|
iClipFlags = userClipFlags;
|
||||||
|
else iClipFlags = out->clipFlags;
|
||||||
|
|
||||||
|
for( i = FRUSTUM_PLANES, bit = 1; i > 0; i--, bit <<= 1 )
|
||||||
|
{
|
||||||
|
const mplane_t *p = &out->planes[FRUSTUM_PLANES - i];
|
||||||
|
|
||||||
|
if( !FBitSet( iClipFlags, bit ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch( p->signbits )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if( p->normal[0] * maxs[0] + p->normal[1] * maxs[1] + p->normal[2] * maxs[2] < p->dist )
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if( p->normal[0] * mins[0] + p->normal[1] * maxs[1] + p->normal[2] * maxs[2] < p->dist )
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if( p->normal[0] * maxs[0] + p->normal[1] * mins[1] + p->normal[2] * maxs[2] < p->dist )
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if( p->normal[0] * mins[0] + p->normal[1] * mins[1] + p->normal[2] * maxs[2] < p->dist )
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if( p->normal[0] * maxs[0] + p->normal[1] * maxs[1] + p->normal[2] * mins[2] < p->dist )
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
if( p->normal[0] * mins[0] + p->normal[1] * maxs[1] + p->normal[2] * mins[2] < p->dist )
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
if( p->normal[0] * maxs[0] + p->normal[1] * mins[1] + p->normal[2] * mins[2] < p->dist )
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
if( p->normal[0] * mins[0] + p->normal[1] * mins[1] + p->normal[2] * mins[2] < p->dist )
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean GL_FrustumCullSphere( gl_frustum_t *out, const vec3_t center, float radius, int userClipFlags )
|
||||||
|
{
|
||||||
|
int iClipFlags;
|
||||||
|
int i, bit;
|
||||||
|
|
||||||
|
if( r_nocull->value )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( userClipFlags != 0 )
|
||||||
|
iClipFlags = userClipFlags;
|
||||||
|
else iClipFlags = out->clipFlags;
|
||||||
|
|
||||||
|
for( i = FRUSTUM_PLANES, bit = 1; i > 0; i--, bit <<= 1 )
|
||||||
|
{
|
||||||
|
const mplane_t *p = &out->planes[FRUSTUM_PLANES - i];
|
||||||
|
|
||||||
|
if( !FBitSet( iClipFlags, bit ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( DotProduct( center, p->normal ) - p->dist <= -radius )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
52
ref_gu/gu_frustum.h
Normal file
52
ref_gu/gu_frustum.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
gl_frustum.cpp - frustum test implementation
|
||||||
|
Copyright (C) 2016 Uncle Mike
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GL_FRUSTUM_H
|
||||||
|
#define GL_FRUSTUM_H
|
||||||
|
|
||||||
|
// don't change this order
|
||||||
|
#define FRUSTUM_LEFT 0
|
||||||
|
#define FRUSTUM_RIGHT 1
|
||||||
|
#define FRUSTUM_BOTTOM 2
|
||||||
|
#define FRUSTUM_TOP 3
|
||||||
|
#define FRUSTUM_FAR 4
|
||||||
|
#define FRUSTUM_NEAR 5
|
||||||
|
#define FRUSTUM_PLANES 6
|
||||||
|
|
||||||
|
typedef struct gl_frustum_s
|
||||||
|
{
|
||||||
|
mplane_t planes[FRUSTUM_PLANES];
|
||||||
|
unsigned int clipFlags;
|
||||||
|
} gl_frustum_t;
|
||||||
|
|
||||||
|
void GL_FrustumInitProj( gl_frustum_t *out, float flZNear, float flZFar, float flFovX, float flFovY );
|
||||||
|
void GL_FrustumInitOrtho( gl_frustum_t *out, float xLeft, float xRight, float yTop, float yBottom, float flZNear, float flZFar );
|
||||||
|
void GL_FrustumInitBox( gl_frustum_t *out, const vec3_t org, float radius ); // used for pointlights
|
||||||
|
void GL_FrustumInitProjFromMatrix( gl_frustum_t *out, const matrix4x4 projection );
|
||||||
|
void GL_FrustumSetPlane( gl_frustum_t *out, int side, const vec3_t vecNormal, float flDist );
|
||||||
|
void GL_FrustumNormalizePlane( gl_frustum_t *out, int side );
|
||||||
|
void GL_FrustumComputeBounds( gl_frustum_t *out, vec3_t mins, vec3_t maxs );
|
||||||
|
void GL_FrustumComputeCorners( gl_frustum_t *out, vec3_t bbox[8] );
|
||||||
|
void GL_FrustumDrawDebug( gl_frustum_t *out );
|
||||||
|
|
||||||
|
// cull methods
|
||||||
|
qboolean GL_FrustumCullBox( gl_frustum_t *out, const vec3_t mins, const vec3_t maxs, int userClipFlags );
|
||||||
|
qboolean GL_FrustumCullSphere( gl_frustum_t *out, const vec3_t centre, float radius, int userClipFlags );
|
||||||
|
|
||||||
|
// plane manipulating
|
||||||
|
void GL_FrustumEnablePlane( gl_frustum_t *out, int side );
|
||||||
|
void GL_FrustumDisablePlane( gl_frustum_t *out, int side );
|
||||||
|
|
||||||
|
#endif//GL_FRUSTUM_H
|
||||||
67
ref_gu/gu_helper.h
Normal file
67
ref_gu/gu_helper.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
gl_helper.h - gu helper
|
||||||
|
Copyright (C) 2021 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GU_HELPER_H
|
||||||
|
#define GU_HELPER_H
|
||||||
|
#ifndef APIENTRY
|
||||||
|
#define APIENTRY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef APIENTRY_LINKAGE
|
||||||
|
#define APIENTRY_LINKAGE extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// GL types wrapping
|
||||||
|
typedef uint GLenum;
|
||||||
|
typedef byte GLboolean;
|
||||||
|
typedef uint GLbitfield;
|
||||||
|
typedef void GLvoid;
|
||||||
|
typedef signed char GLbyte;
|
||||||
|
typedef short GLshort;
|
||||||
|
typedef int GLint;
|
||||||
|
typedef byte GLubyte;
|
||||||
|
typedef word GLushort;
|
||||||
|
typedef uint GLuint;
|
||||||
|
typedef int GLsizei;
|
||||||
|
typedef float GLfloat;
|
||||||
|
typedef float GLclampf;
|
||||||
|
typedef double GLdouble;
|
||||||
|
typedef double GLclampd;
|
||||||
|
typedef int GLintptrARB;
|
||||||
|
typedef int GLsizeiptrARB;
|
||||||
|
typedef char GLcharARB;
|
||||||
|
typedef uint GLhandleARB;
|
||||||
|
typedef float GLmatrix[16];
|
||||||
|
|
||||||
|
// GL_Cull wrapping
|
||||||
|
#define GL_NONE 0
|
||||||
|
#define GL_FRONT GU_CW + 1
|
||||||
|
#define GL_BACK GU_CCW + 1
|
||||||
|
|
||||||
|
// color functions wrapping
|
||||||
|
#define GUCOLOR4F( r, g, b, a ) GU_COLOR( ( r ), ( g ), ( b ), ( a ) )
|
||||||
|
#define GUCOLOR4FV( v ) GU_COLOR( ( v )[0], ( v )[1], ( v )[2], ( v )[3] )
|
||||||
|
#define GUCOLOR4UB( r, g, b, a ) GU_RGBA( ( r ), ( g ), ( b ), ( a ) )
|
||||||
|
#define GUCOLOR4UBV( v ) GU_RGBA( ( v )[0], ( v )[1], ( v )[2], ( v )[3] )
|
||||||
|
#define GUCOLOR3F( r, g, b ) GU_COLOR( ( r ), ( g ), ( b ), 1.0f )
|
||||||
|
#define GUCOLOR3FV( v ) GU_COLOR( ( v )[0], ( v )[1], ( v )[2], 1.0f )
|
||||||
|
#define GUCOLOR3UB( r, g, b ) GU_RGBA( ( r ), ( g ), ( b ), 255 )
|
||||||
|
#define GUCOLOR3UBV( v ) GU_RGBA( ( v )[0], ( v )[1], ( v )[2], 255 )
|
||||||
|
|
||||||
|
// blend function wrapping
|
||||||
|
#define GUBLEND1 0xffffffff
|
||||||
|
#define GUBLEND0 0x00000000
|
||||||
|
|
||||||
|
#endif // GU_HELPER_H
|
||||||
2063
ref_gu/gu_image.c
Normal file
2063
ref_gu/gu_image.c
Normal file
File diff suppressed because it is too large
Load Diff
829
ref_gu/gu_local.h
Normal file
829
ref_gu/gu_local.h
Normal file
@@ -0,0 +1,829 @@
|
|||||||
|
/*
|
||||||
|
gu_local.h - renderer local declarations
|
||||||
|
Copyright (C) 2010 Uncle Mike
|
||||||
|
Copyright (C) 2021 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GL_LOCAL_H
|
||||||
|
#define GL_LOCAL_H
|
||||||
|
|
||||||
|
#include <pspkernel.h>
|
||||||
|
#include <pspdisplay.h>
|
||||||
|
#include <pspgu.h>
|
||||||
|
#include <pspgum.h>
|
||||||
|
|
||||||
|
#include "port.h"
|
||||||
|
#include "xash3d_types.h"
|
||||||
|
#include "cvardef.h"
|
||||||
|
#include "const.h"
|
||||||
|
#include "com_model.h"
|
||||||
|
#include "cl_entity.h"
|
||||||
|
#include "render_api.h"
|
||||||
|
#include "protocol.h"
|
||||||
|
#include "dlight.h"
|
||||||
|
#include "gu_frustum.h"
|
||||||
|
#include "ref_api.h"
|
||||||
|
#include "xash3d_mathlib.h"
|
||||||
|
#include "ref_params.h"
|
||||||
|
#include "enginefeatures.h"
|
||||||
|
#include "com_strings.h"
|
||||||
|
#include "pm_movevars.h"
|
||||||
|
//#include "cvar.h"
|
||||||
|
#include "gu_helper.h"
|
||||||
|
#include "gu_extension.h"
|
||||||
|
#include "gu_vram.h"
|
||||||
|
#include "wadfile.h"
|
||||||
|
|
||||||
|
#ifndef offsetof
|
||||||
|
#define offsetof(s,m) (size_t)&(((s *)0)->m)
|
||||||
|
#endif // offsetof
|
||||||
|
|
||||||
|
#define ASSERT(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ )
|
||||||
|
#define Assert(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ )
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define CVAR_DEFINE( cv, cvname, cvstr, cvflags, cvdesc ) cvar_t cv = { cvname, cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, cvdesc }
|
||||||
|
#define CVAR_DEFINE_AUTO( cv, cvstr, cvflags, cvdesc ) cvar_t cv = { #cv, cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, cvdesc }
|
||||||
|
#define CVAR_TO_BOOL( x ) ((x) && ((x)->value != 0.0f) ? true : false )
|
||||||
|
|
||||||
|
#define WORLD (gEngfuncs.GetWorld())
|
||||||
|
#define WORLDMODEL (gEngfuncs.pfnGetModelByIndex( 1 ))
|
||||||
|
#define MOVEVARS (gEngfuncs.pfnGetMoveVars())
|
||||||
|
|
||||||
|
// make mod_ref.h?
|
||||||
|
#define LM_SAMPLE_SIZE 16
|
||||||
|
|
||||||
|
|
||||||
|
extern byte *r_temppool;
|
||||||
|
|
||||||
|
#define LIGHTMAP_BPP 1 //1 2 3 4
|
||||||
|
|
||||||
|
#if LIGHTMAP_BPP == 1
|
||||||
|
#define LIGHTMAP_FORMAT PF_RGB_332
|
||||||
|
#elif LIGHTMAP_BPP == 2
|
||||||
|
#define LIGHTMAP_FORMAT PF_RGB_5650
|
||||||
|
#elif LIGHTMAP_BPP == 3
|
||||||
|
#define LIGHTMAP_FORMAT PF_RGB_24
|
||||||
|
#elif LIGHTMAP_BPP == 4
|
||||||
|
#define LIGHTMAP_FORMAT PF_RGBA_32
|
||||||
|
#else
|
||||||
|
#error (1 > LIGHTMAP_BPP > 4)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
|
||||||
|
#define BLOCK_SIZE tr.block_size // lightmap blocksize
|
||||||
|
#define BLOCK_SIZE_DEFAULT 128 // for keep backward compatibility
|
||||||
|
#define BLOCK_SIZE_MAX 128
|
||||||
|
|
||||||
|
#define MAX_TEXTURES 1536
|
||||||
|
#define MAX_DETAIL_TEXTURES 64
|
||||||
|
#define MAX_LIGHTMAPS 64
|
||||||
|
#define SUBDIVIDE_SIZE 64
|
||||||
|
#define MAX_DECAL_SURFS 256
|
||||||
|
#define MAX_DRAW_STACK 2 // normal view and menu view
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define BLOCK_SIZE tr.block_size // lightmap blocksize
|
||||||
|
#define BLOCK_SIZE_DEFAULT 128 // for keep backward compatibility
|
||||||
|
#define BLOCK_SIZE_MAX 1024
|
||||||
|
|
||||||
|
#define MAX_TEXTURES 4096
|
||||||
|
#define MAX_DETAIL_TEXTURES 256
|
||||||
|
#define MAX_LIGHTMAPS 256
|
||||||
|
#define SUBDIVIDE_SIZE 64
|
||||||
|
#define MAX_DECAL_SURFS 4096
|
||||||
|
#define MAX_DRAW_STACK 2 // normal view and menu view
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SHADEDOT_QUANT 16 // precalculated dot products for quantized angles
|
||||||
|
#define SHADE_LAMBERT 1.495f
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
#define DEFAULT_ALPHATEST 0x00
|
||||||
|
#else
|
||||||
|
#define DEFAULT_ALPHATEST 0.0f
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// refparams
|
||||||
|
#define RP_NONE 0
|
||||||
|
#define RP_ENVVIEW BIT( 0 ) // used for cubemapshot
|
||||||
|
#define RP_OLDVIEWLEAF BIT( 1 )
|
||||||
|
#define RP_CLIPPLANE BIT( 2 )
|
||||||
|
|
||||||
|
#define RP_NONVIEWERREF (RP_ENVVIEW)
|
||||||
|
#define R_ModelOpaque( rm ) ( rm == kRenderNormal )
|
||||||
|
#define R_StaticEntity( ent ) ( VectorIsNull( ent->origin ) && VectorIsNull( ent->angles ))
|
||||||
|
#define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == ENGINE_GET_PARM( PARM_PLAYER_INDEX ) && e->player )
|
||||||
|
#define RP_NORMALPASS() ( FBitSet( RI.params, RP_NONVIEWERREF ) == 0 )
|
||||||
|
|
||||||
|
#define CL_IsViewEntityLocalPlayer() ( ENGINE_GET_PARM( PARM_VIEWENT_INDEX ) == ENGINE_GET_PARM( PARM_PLAYER_INDEX ) )
|
||||||
|
|
||||||
|
#define CULL_VISIBLE 0 // not culled
|
||||||
|
#define CULL_BACKSIDE 1 // backside of transparent wall
|
||||||
|
#define CULL_FRUSTUM 2 // culled by frustum
|
||||||
|
#define CULL_VISFRAME 3 // culled by PVS
|
||||||
|
#define CULL_OTHER 4 // culled by other reason
|
||||||
|
|
||||||
|
typedef struct gltexture_s
|
||||||
|
{
|
||||||
|
|
||||||
|
char name[128]; // game path, including extension (can be store image programs)
|
||||||
|
short srcWidth; // keep unscaled sizes
|
||||||
|
short srcHeight;
|
||||||
|
short width; // upload width\height
|
||||||
|
short height;
|
||||||
|
//short depth; // texture depth or count of layers for 2D_ARRAY
|
||||||
|
byte numMips; // mipmap count
|
||||||
|
byte *dstTexture; // texture pointer
|
||||||
|
byte *dstPalette;
|
||||||
|
byte bpp;
|
||||||
|
int format; // uploaded format
|
||||||
|
//GLint encode; // using GLSL decoder
|
||||||
|
texFlags_t flags;
|
||||||
|
|
||||||
|
rgba_t fogParams; // some water textures
|
||||||
|
// contain info about underwater fog
|
||||||
|
|
||||||
|
rgbdata_t *original; // keep original image
|
||||||
|
|
||||||
|
// debug info
|
||||||
|
size_t size; // upload size for debug targets
|
||||||
|
|
||||||
|
// detail textures stuff
|
||||||
|
float xscale;
|
||||||
|
float yscale;
|
||||||
|
#if 0
|
||||||
|
int servercount;
|
||||||
|
#endif
|
||||||
|
uint hashValue;
|
||||||
|
struct gltexture_s *nextHash;
|
||||||
|
} gl_texture_t;
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float x, y, z;
|
||||||
|
}gu_vert_fv_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned int c;
|
||||||
|
float x, y, z;
|
||||||
|
}gu_vert_fcv_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float u, v;
|
||||||
|
float x, y, z;
|
||||||
|
}gu_vert_ftv_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float u, v;
|
||||||
|
unsigned int c;
|
||||||
|
float x, y, z;
|
||||||
|
}gu_vert_ftcv_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float u, v;
|
||||||
|
unsigned int c;
|
||||||
|
float nx, ny, nz;
|
||||||
|
float x, y, z;
|
||||||
|
}gu_vert_ftcnv_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
short x, y, z;
|
||||||
|
}gu_vert_hv_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
short u, v;
|
||||||
|
short x, y, z;
|
||||||
|
}gu_vert_htv_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
short u, v;
|
||||||
|
unsigned int c;
|
||||||
|
short x, y, z;
|
||||||
|
}gu_vert_htcv_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int params; // rendering parameters
|
||||||
|
|
||||||
|
qboolean drawWorld; // ignore world for drawing PlayerModel
|
||||||
|
qboolean isSkyVisible; // sky is visible
|
||||||
|
qboolean onlyClientDraw; // disabled by client request
|
||||||
|
qboolean drawOrtho; // draw world as orthogonal projection
|
||||||
|
|
||||||
|
float fov_x, fov_y; // current view fov
|
||||||
|
|
||||||
|
cl_entity_t *currententity;
|
||||||
|
model_t *currentmodel;
|
||||||
|
cl_entity_t *currentbeam; // same as above but for beams
|
||||||
|
|
||||||
|
int viewport[4];
|
||||||
|
gl_frustum_t frustum;
|
||||||
|
|
||||||
|
mleaf_t *viewleaf;
|
||||||
|
mleaf_t *oldviewleaf;
|
||||||
|
vec3_t pvsorigin;
|
||||||
|
vec3_t vieworg; // locked vieworigin
|
||||||
|
vec3_t viewangles;
|
||||||
|
vec3_t vforward;
|
||||||
|
vec3_t vright;
|
||||||
|
vec3_t vup;
|
||||||
|
|
||||||
|
vec3_t cullorigin;
|
||||||
|
vec3_t cull_vforward;
|
||||||
|
vec3_t cull_vright;
|
||||||
|
vec3_t cull_vup;
|
||||||
|
|
||||||
|
float farClip;
|
||||||
|
|
||||||
|
qboolean fogCustom;
|
||||||
|
qboolean fogEnabled;
|
||||||
|
qboolean fogSkybox;
|
||||||
|
vec4_t fogColor;
|
||||||
|
float fogDensity;
|
||||||
|
float fogStart;
|
||||||
|
float fogEnd;
|
||||||
|
int cached_contents; // in water
|
||||||
|
int cached_waterlevel; // was in water
|
||||||
|
|
||||||
|
float skyMins[2][6];
|
||||||
|
float skyMaxs[2][6];
|
||||||
|
|
||||||
|
matrix4x4 objectMatrix; // currententity matrix
|
||||||
|
matrix4x4 worldviewMatrix; // modelview for world
|
||||||
|
matrix4x4 modelviewMatrix; // worldviewMatrix * objectMatrix
|
||||||
|
|
||||||
|
matrix4x4 projectionMatrix;
|
||||||
|
matrix4x4 worldviewProjectionMatrix; // worldviewMatrix * projectionMatrix
|
||||||
|
byte visbytes[(MAX_MAP_LEAFS+7)/8];// actual PVS for current frame
|
||||||
|
|
||||||
|
float viewplanedist;
|
||||||
|
mplane_t clipPlane;
|
||||||
|
} ref_instance_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
cl_entity_t *solid_entities[MAX_VISIBLE_PACKET]; // opaque moving or alpha brushes
|
||||||
|
cl_entity_t *trans_entities[MAX_VISIBLE_PACKET]; // translucent brushes
|
||||||
|
cl_entity_t *beam_entities[MAX_VISIBLE_PACKET];
|
||||||
|
uint num_solid_entities;
|
||||||
|
uint num_trans_entities;
|
||||||
|
uint num_beam_entities;
|
||||||
|
} draw_list_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int defaultTexture; // use for bad textures
|
||||||
|
int particleTexture;
|
||||||
|
int whiteTexture;
|
||||||
|
int grayTexture;
|
||||||
|
int blackTexture;
|
||||||
|
int solidskyTexture; // quake1 solid-sky layer
|
||||||
|
int alphaskyTexture; // quake1 alpha-sky layer
|
||||||
|
int lightmapTextures[MAX_LIGHTMAPS];
|
||||||
|
int dlightTexture; // custom dlight texture
|
||||||
|
int skyboxTextures[6]; // skybox sides
|
||||||
|
int cinTexture; // cinematic texture
|
||||||
|
|
||||||
|
int skytexturenum; // this not a gl_texturenum!
|
||||||
|
#if 0
|
||||||
|
int skyboxbasenum; // start with 5800
|
||||||
|
#endif
|
||||||
|
// entity lists
|
||||||
|
draw_list_t draw_stack[MAX_DRAW_STACK];
|
||||||
|
int draw_stack_pos;
|
||||||
|
draw_list_t *draw_list;
|
||||||
|
|
||||||
|
msurface_t *draw_decals[MAX_DECAL_SURFS];
|
||||||
|
int num_draw_decals;
|
||||||
|
|
||||||
|
// OpenGL matrix states
|
||||||
|
qboolean modelviewIdentity;
|
||||||
|
|
||||||
|
int visframecount; // PVS frame
|
||||||
|
int dlightframecount; // dynamic light frame
|
||||||
|
int realframecount; // not including viewpasses
|
||||||
|
int framecount;
|
||||||
|
|
||||||
|
qboolean ignore_lightgamma;
|
||||||
|
qboolean fCustomRendering;
|
||||||
|
qboolean fResetVis;
|
||||||
|
qboolean fFlipViewModel;
|
||||||
|
|
||||||
|
byte visbytes[(MAX_MAP_LEAFS+7)/8]; // member custom PVS
|
||||||
|
int lightstylevalue[MAX_LIGHTSTYLES]; // value 0 - 65536
|
||||||
|
int block_size; // lightmap blocksize
|
||||||
|
|
||||||
|
double frametime; // special frametime for multipass rendering (will set to 0 on a nextview)
|
||||||
|
float blend; // global blend value
|
||||||
|
|
||||||
|
// cull info
|
||||||
|
vec3_t modelorg; // relative to viewpoint
|
||||||
|
|
||||||
|
qboolean fCustomSkybox;
|
||||||
|
} gl_globals_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint c_world_polys;
|
||||||
|
uint c_studio_polys;
|
||||||
|
uint c_sprite_polys;
|
||||||
|
uint c_alias_polys;
|
||||||
|
uint c_world_leafs;
|
||||||
|
|
||||||
|
uint c_view_beams_count;
|
||||||
|
uint c_active_tents_count;
|
||||||
|
uint c_alias_models_drawn;
|
||||||
|
uint c_studio_models_drawn;
|
||||||
|
uint c_sprite_models_drawn;
|
||||||
|
uint c_particle_count;
|
||||||
|
|
||||||
|
uint c_client_ents; // entities that moved to client
|
||||||
|
double t_world_node;
|
||||||
|
double t_world_draw;
|
||||||
|
} ref_speeds_t;
|
||||||
|
|
||||||
|
extern ref_speeds_t r_stats;
|
||||||
|
extern ref_instance_t RI;
|
||||||
|
extern gl_globals_t tr;
|
||||||
|
|
||||||
|
extern float gldepthmin, gldepthmax;
|
||||||
|
#define r_numEntities (tr.draw_list->num_solid_entities + tr.draw_list->num_trans_entities)
|
||||||
|
#define r_numStatics (r_stats.c_client_ents)
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_backend.c
|
||||||
|
//
|
||||||
|
void GL_BackendStartFrame( void );
|
||||||
|
void GL_BackendEndFrame( void );
|
||||||
|
void GL_CleanUpTextureUnits( int last );
|
||||||
|
void GL_Bind( GLint tmu, GLenum texnum );
|
||||||
|
void GL_MultiTexCoord2f( GLenum texture, GLfloat s, GLfloat t );
|
||||||
|
void GL_SetTexCoordArrayMode( GLenum mode );
|
||||||
|
void GL_LoadTexMatrix( const matrix4x4 m );
|
||||||
|
void GL_LoadTexMatrixExt( const float *glmatrix );
|
||||||
|
void GL_LoadMatrix( const matrix4x4 source );
|
||||||
|
void GL_TexGen( GLenum coord, GLenum mode );
|
||||||
|
void GL_SelectTexture( GLint texture );
|
||||||
|
void GL_CleanupAllTextureUnits( void );
|
||||||
|
void GL_LoadIdentityTexMatrix( void );
|
||||||
|
void GL_DisableAllTexGens( void );
|
||||||
|
void GL_SetRenderMode( int mode );
|
||||||
|
void GL_TextureTarget( uint target );
|
||||||
|
void GL_Cull( GLenum cull );
|
||||||
|
void R_ShowTextures( void );
|
||||||
|
void SCR_TimeRefresh_f( void );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_beams.c
|
||||||
|
//
|
||||||
|
void CL_DrawBeams( int fTrans, BEAM *active_beams );
|
||||||
|
qboolean R_BeamCull( const vec3_t start, const vec3_t end, qboolean pvsOnly );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_cull.c
|
||||||
|
//
|
||||||
|
int R_CullModel( cl_entity_t *e, const vec3_t absmin, const vec3_t absmax );
|
||||||
|
qboolean R_CullBox( const vec3_t mins, const vec3_t maxs );
|
||||||
|
qboolean R_CullSphere( const vec3_t centre, const float radius );
|
||||||
|
int R_CullSurface( msurface_t *surf, gl_frustum_t *frustum, uint clipflags );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_decals.c
|
||||||
|
//
|
||||||
|
void DrawSurfaceDecals( msurface_t *fa, qboolean single, qboolean reverse );
|
||||||
|
float *R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int texture, int *outCount );
|
||||||
|
void DrawSingleDecal( decal_t *pDecal, msurface_t *fa );
|
||||||
|
void R_EntityRemoveDecals( model_t *mod );
|
||||||
|
void DrawDecalsBatch( void );
|
||||||
|
void R_ClearDecals( void );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_draw.c
|
||||||
|
//
|
||||||
|
void R_Set2DMode( qboolean enable );
|
||||||
|
void R_DrawTileClear( int texnum, int x, int y, int w, int h );
|
||||||
|
void R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, const byte *data );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_drawhulls.c
|
||||||
|
//
|
||||||
|
void R_DrawWorldHull( void );
|
||||||
|
void R_DrawModelHull( void );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_image.c
|
||||||
|
//
|
||||||
|
gl_texture_t *R_GetTexture( GLenum texnum );
|
||||||
|
#define GL_LoadTextureInternal( name, pic, flags ) GL_LoadTextureFromBuffer( name, pic, flags, false )
|
||||||
|
#define GL_UpdateTextureInternal( name, pic, flags ) GL_LoadTextureFromBuffer( name, pic, flags, true )
|
||||||
|
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags );
|
||||||
|
int GL_LoadTextureArray( const char **names, int flags );
|
||||||
|
int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update );
|
||||||
|
byte *GL_ResampleTexture( const byte *source, int in_w, int in_h, int out_w, int out_h, qboolean isNormalMap );
|
||||||
|
#define PC_SWF( X ) ( ( X ) | ( 1 << 15 ) )
|
||||||
|
#define PC_HWF( X ) ( X )
|
||||||
|
void GL_PixelConverter( byte *dst, const byte *src, int size, int inFormat, int outFormat );
|
||||||
|
int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags );
|
||||||
|
int GL_CreateTextureArray( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags );
|
||||||
|
void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor );
|
||||||
|
qboolean GL_UpdateTexture( int texnum, int xoff, int yoff, int width, int height, const void *buffer );
|
||||||
|
void GL_UpdateTexSize( int texnum, int width, int height, int depth );
|
||||||
|
int GL_FindTexture( const char *name );
|
||||||
|
void GL_FreeTexture( GLenum texnum );
|
||||||
|
const char *GL_Target( GLenum target );
|
||||||
|
void R_InitDlightTexture( void );
|
||||||
|
void R_TextureList_f( void );
|
||||||
|
void R_InitImages( void );
|
||||||
|
void R_ShutdownImages( void );
|
||||||
|
int GL_TexMemory( void );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_rlight.c
|
||||||
|
//
|
||||||
|
void CL_RunLightStyles( void );
|
||||||
|
void R_PushDlights( void );
|
||||||
|
void R_AnimateLight( void );
|
||||||
|
void R_GetLightSpot( vec3_t lightspot );
|
||||||
|
void R_MarkLights( dlight_t *light, int bit, mnode_t *node );
|
||||||
|
colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lightspot, vec3_t lightvec );
|
||||||
|
int R_CountSurfaceDlights( msurface_t *surf );
|
||||||
|
colorVec R_LightPoint( const vec3_t p0 );
|
||||||
|
int R_CountDlights( void );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_rmain.c
|
||||||
|
//
|
||||||
|
void R_ClearScene( void );
|
||||||
|
void R_LoadIdentity( void );
|
||||||
|
void R_RenderScene( void );
|
||||||
|
void R_DrawCubemapView( const vec3_t origin, const vec3_t angles, int size );
|
||||||
|
void R_SetupRefParams( const struct ref_viewpass_s *rvp );
|
||||||
|
void R_TranslateForEntity( cl_entity_t *e );
|
||||||
|
void R_RotateForEntity( cl_entity_t *e );
|
||||||
|
void R_SetupGL( qboolean set_gl_state );
|
||||||
|
void R_AllowFog( qboolean allowed );
|
||||||
|
void R_SetupFrustum( void );
|
||||||
|
void R_FindViewLeaf( void );
|
||||||
|
void R_CheckGamma( void );
|
||||||
|
void R_PushScene( void );
|
||||||
|
void R_PopScene( void );
|
||||||
|
void R_DrawFog( void );
|
||||||
|
int CL_FxBlend( cl_entity_t *e );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_rmath.c
|
||||||
|
//
|
||||||
|
void Matrix4x4_ToFMatrix4( const matrix4x4 in, ScePspFMatrix4 *out );
|
||||||
|
void Matrix4x4_FromFMatrix4( matrix4x4 out, ScePspFMatrix4 *in );
|
||||||
|
void Matrix4x4_Concat( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 );
|
||||||
|
void Matrix4x4_ConcatTranslate( matrix4x4 out, float x, float y, float z );
|
||||||
|
void Matrix4x4_ConcatRotate( matrix4x4 out, float angle, float x, float y, float z );
|
||||||
|
void Matrix4x4_ConcatScale( matrix4x4 out, float x );
|
||||||
|
void Matrix4x4_ConcatScale3( matrix4x4 out, float x, float y, float z );
|
||||||
|
void Matrix4x4_CreateTranslate( matrix4x4 out, float x, float y, float z );
|
||||||
|
void Matrix4x4_CreateRotate( matrix4x4 out, float angle, float x, float y, float z );
|
||||||
|
void Matrix4x4_CreateScale( matrix4x4 out, float x );
|
||||||
|
void Matrix4x4_CreateScale3( matrix4x4 out, float x, float y, float z );
|
||||||
|
void Matrix4x4_CreateProjection(matrix4x4 out, float xMax, float xMin, float yMax, float yMin, float zNear, float zFar);
|
||||||
|
void Matrix4x4_CreateOrtho(matrix4x4 m, float xLeft, float xRight, float yBottom, float yTop, float zNear, float zFar);
|
||||||
|
void Matrix4x4_CreateModelview( matrix4x4 out );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_rmisc.c
|
||||||
|
//
|
||||||
|
void R_ClearStaticEntities( void );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_rsurf.c
|
||||||
|
//
|
||||||
|
void R_MarkLeaves( void );
|
||||||
|
void R_DrawWorld( void );
|
||||||
|
void R_DrawWaterSurfaces( void );
|
||||||
|
void R_DrawBrushModel( cl_entity_t *e );
|
||||||
|
void GL_SubdivideSurface( msurface_t *fa );
|
||||||
|
void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa );
|
||||||
|
void DrawGLPoly( glpoly_t *p, float xScale, float yScale );
|
||||||
|
texture_t *R_TextureAnimation( msurface_t *s );
|
||||||
|
void GL_SetupFogColorForSurfaces( void );
|
||||||
|
void R_DrawAlphaTextureChains( void );
|
||||||
|
void GL_RebuildLightmaps( void );
|
||||||
|
void GL_InitRandomTable( void );
|
||||||
|
void GL_BuildLightmaps( void );
|
||||||
|
void GL_ResetFogColor( void );
|
||||||
|
void R_GenerateVBO( void );
|
||||||
|
void R_ClearVBO( void );
|
||||||
|
void R_AddDecalVBO( decal_t *pdecal, msurface_t *surf );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_rpart.c
|
||||||
|
//
|
||||||
|
void CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, float frametime );
|
||||||
|
void CL_DrawParticles( double frametime, particle_t *cl_active_particles, float partsize );
|
||||||
|
void CL_DrawTracers( double frametime, particle_t *cl_active_tracers );
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_sprite.c
|
||||||
|
//
|
||||||
|
void R_SpriteInit( void );
|
||||||
|
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags );
|
||||||
|
mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw );
|
||||||
|
void R_DrawSpriteModel( cl_entity_t *e );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_studio.c
|
||||||
|
//
|
||||||
|
void R_StudioInit( void );
|
||||||
|
void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded );
|
||||||
|
void R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t angles );
|
||||||
|
float CL_GetSequenceDuration( cl_entity_t *ent, int sequence );
|
||||||
|
struct mstudiotex_s *R_StudioGetTexture( cl_entity_t *e );
|
||||||
|
float CL_GetStudioEstimatedFrame( cl_entity_t *ent );
|
||||||
|
int R_GetEntityRenderMode( cl_entity_t *ent );
|
||||||
|
void R_DrawStudioModel( cl_entity_t *e );
|
||||||
|
player_info_t *pfnPlayerInfo( int index );
|
||||||
|
void R_GatherPlayerLight( void );
|
||||||
|
float R_StudioEstimateFrame( cl_entity_t *e, mstudioseqdesc_t *pseqdesc );
|
||||||
|
void R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t angles );
|
||||||
|
void R_StudioResetPlayerModels( void );
|
||||||
|
void CL_InitStudioAPI( void );
|
||||||
|
void Mod_StudioLoadTextures( model_t *mod, void *data );
|
||||||
|
void Mod_StudioUnloadTextures( void *data );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_alias.c
|
||||||
|
//
|
||||||
|
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded );
|
||||||
|
void R_DrawAliasModel( cl_entity_t *e );
|
||||||
|
void R_AliasInit( void );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_warp.c
|
||||||
|
//
|
||||||
|
void R_InitSkyClouds( mip_t *mt, struct texture_s *tx, qboolean custom_palette );
|
||||||
|
void R_AddSkyBoxSurface( msurface_t *fa );
|
||||||
|
void R_ClearSkyBox( void );
|
||||||
|
void R_DrawSkyBox( void );
|
||||||
|
void R_DrawClouds( void );
|
||||||
|
void EmitWaterPolys( msurface_t *warp, qboolean reverse );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_vgui.c
|
||||||
|
//
|
||||||
|
void VGUI_DrawInit( void );
|
||||||
|
void VGUI_DrawShutdown( void );
|
||||||
|
void VGUI_SetupDrawingText( int *pColor );
|
||||||
|
void VGUI_SetupDrawingRect( int *pColor );
|
||||||
|
void VGUI_SetupDrawingImage( int *pColor );
|
||||||
|
void VGUI_BindTexture( int id );
|
||||||
|
void VGUI_EnableTexture( qboolean enable );
|
||||||
|
void VGUI_CreateTexture( int id, int width, int height );
|
||||||
|
void VGUI_UploadTexture( int id, const char *buffer, int width, int height );
|
||||||
|
void VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight );
|
||||||
|
void VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr );
|
||||||
|
void VGUI_GetTextureSizes( int *width, int *height );
|
||||||
|
int VGUI_GenerateTexture( void );
|
||||||
|
|
||||||
|
//#include "vid_common.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// renderer exports
|
||||||
|
//
|
||||||
|
qboolean R_Init( void );
|
||||||
|
void R_Shutdown( void );
|
||||||
|
void GL_SetupAttributes( int safegl );
|
||||||
|
void GL_OnContextCreated( void );
|
||||||
|
void GL_InitExtensions( void );
|
||||||
|
void GL_ClearExtensions( void );
|
||||||
|
void VID_CheckChanges( void );
|
||||||
|
int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags );
|
||||||
|
void GL_FreeImage( const char *name );
|
||||||
|
qboolean VID_ScreenShot( const char *filename, int shot_type );
|
||||||
|
qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot );
|
||||||
|
void R_BeginFrame( qboolean clearScene );
|
||||||
|
void R_RenderFrame( const struct ref_viewpass_s *vp );
|
||||||
|
void R_EndFrame( void );
|
||||||
|
void R_ClearScene( void );
|
||||||
|
void R_GetTextureParms( int *w, int *h, int texnum );
|
||||||
|
void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int curFrame, const struct model_s *pSprite );
|
||||||
|
void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty );
|
||||||
|
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum );
|
||||||
|
qboolean R_SpeedsMessage( char *out, size_t size );
|
||||||
|
void R_SetupSky( const char *skyboxname );
|
||||||
|
qboolean R_CullBox( const vec3_t mins, const vec3_t maxs );
|
||||||
|
int R_WorldToScreen( const vec3_t point, vec3_t screen );
|
||||||
|
void R_ScreenToWorld( const vec3_t screen, vec3_t point );
|
||||||
|
qboolean R_AddEntity( struct cl_entity_s *pRefEntity, int entityType );
|
||||||
|
void Mod_LoadMapSprite( struct model_s *mod, const void *buffer, size_t size, qboolean *loaded );
|
||||||
|
void Mod_SpriteUnloadTextures( void *data );
|
||||||
|
void Mod_UnloadAliasModel( struct model_s *mod );
|
||||||
|
void Mod_AliasUnloadTextures( void *data );
|
||||||
|
void GL_SetRenderMode( int mode );
|
||||||
|
void GL_SetColor4ub( byte r, byte g, byte b, byte a );
|
||||||
|
void R_RunViewmodelEvents( void );
|
||||||
|
void R_DrawViewModel( void );
|
||||||
|
int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame );
|
||||||
|
void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale );
|
||||||
|
void R_RemoveEfrags( struct cl_entity_s *ent );
|
||||||
|
void R_AddEfrags( struct cl_entity_s *ent );
|
||||||
|
void R_DecalRemoveAll( int texture );
|
||||||
|
int R_CreateDecalList( decallist_t *pList );
|
||||||
|
void R_ClearAllDecals( void );
|
||||||
|
byte *Mod_GetCurrentVis( void );
|
||||||
|
void Mod_SetOrthoBounds( const float *mins, const float *maxs );
|
||||||
|
void R_NewMap( void );
|
||||||
|
void CL_AddCustomBeam( cl_entity_t *pEnvBeam );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_opengl.c
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_triapi.c
|
||||||
|
//
|
||||||
|
void TriRenderMode( int mode );
|
||||||
|
void TriBegin( int mode );
|
||||||
|
void TriEnd( void );
|
||||||
|
void TriTexCoord2f( float u, float v );
|
||||||
|
void TriVertex3fv( const float *v );
|
||||||
|
void TriVertex3f( float x, float y, float z );
|
||||||
|
void TriColor4f( float r, float g, float b, float a );
|
||||||
|
void TriColor4ub( byte r, byte g, byte b, byte a );
|
||||||
|
void TriBrightness( float brightness );
|
||||||
|
int TriWorldToScreen( const float *world, float *screen );
|
||||||
|
int TriSpriteTexture( model_t *pSpriteModel, int frame );
|
||||||
|
void TriFog( float flFogColor[3], float flStart, float flEnd, int bOn );
|
||||||
|
void TriGetMatrix( const int pname, float *matrix );
|
||||||
|
void TriFogParams( float flDensity, int iFogSkybox );
|
||||||
|
void TriCullFace( TRICULLSTYLE mode );
|
||||||
|
uint getTriBrightness( float brightness );
|
||||||
|
int TriBoxInPVS( float *mins, float *maxs );
|
||||||
|
void TriLightAtPoint( float *pos, float *value );
|
||||||
|
void TriColor4fRendermode( float r, float g, float b, float a, int rendermode );
|
||||||
|
int getTriAPI( int version, triangleapi_t *api );
|
||||||
|
|
||||||
|
//
|
||||||
|
// gu_clipping.c
|
||||||
|
//
|
||||||
|
#define CLIPPING_DEBUGGING 0
|
||||||
|
void GU_ClipSetWorldFrustum( const matrix4x4 in );
|
||||||
|
void GU_ClipRestoreWorldFrustum( void );
|
||||||
|
void GU_ClipSetModelFrustum( const matrix4x4 in );
|
||||||
|
void GU_ClipLoadFrustum( const mplane_t *plane ); // Experimental
|
||||||
|
int GU_ClipIsRequired( gu_vert_t* uv, int uvc );
|
||||||
|
void GU_Clip( gu_vert_t *uv, int uvc, gu_vert_t **cv, int* cvc );
|
||||||
|
|
||||||
|
/*
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
GL STATE MACHINE
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int max_texture_size;
|
||||||
|
qboolean softwareGammaUpdate;
|
||||||
|
} glconfig_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
|
||||||
|
int width, height;
|
||||||
|
int activeTMU;
|
||||||
|
GLint currentTexture;
|
||||||
|
GLboolean texIdentityMatrix;
|
||||||
|
GLint isFogEnabled;
|
||||||
|
|
||||||
|
int faceCull;
|
||||||
|
|
||||||
|
qboolean stencilEnabled;
|
||||||
|
qboolean in2DMode;
|
||||||
|
|
||||||
|
uint fogColor;
|
||||||
|
float fogDensity;
|
||||||
|
float fogStart;
|
||||||
|
float fogEnd;
|
||||||
|
} glstate_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
qboolean initialized; // OpenGL subsystem started
|
||||||
|
qboolean extended; // extended context allows to GL_Debug
|
||||||
|
} glwstate_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int screen_width;
|
||||||
|
int screen_height;
|
||||||
|
int buffer_width;
|
||||||
|
int buffer_format;
|
||||||
|
int buffer_bpp;
|
||||||
|
void *draw_buffer;
|
||||||
|
void *disp_buffer;
|
||||||
|
void *depth_buffer;
|
||||||
|
void *context_list;
|
||||||
|
size_t context_list_size;
|
||||||
|
}gurender_t;
|
||||||
|
|
||||||
|
extern glconfig_t glConfig;
|
||||||
|
extern glstate_t glState;
|
||||||
|
extern gurender_t guRender;
|
||||||
|
// move to engine
|
||||||
|
extern glwstate_t glw_state;
|
||||||
|
extern ref_api_t gEngfuncs;
|
||||||
|
extern ref_globals_t *gpGlobals;
|
||||||
|
|
||||||
|
#define ENGINE_GET_PARM_ (*gEngfuncs.EngineGetParm)
|
||||||
|
#define ENGINE_GET_PARM( parm ) ENGINE_GET_PARM_( ( parm ), 0 )
|
||||||
|
|
||||||
|
//
|
||||||
|
// renderer cvars
|
||||||
|
//
|
||||||
|
extern cvar_t *gl_texture_lodfunc;
|
||||||
|
extern cvar_t *gl_texture_lodbias;
|
||||||
|
extern cvar_t *gl_texture_lodslope;
|
||||||
|
extern cvar_t *gl_texture_nearest;
|
||||||
|
extern cvar_t *gl_lightmap_nearest;
|
||||||
|
extern cvar_t *gl_keeptjunctions;
|
||||||
|
extern cvar_t *gl_emboss_scale;
|
||||||
|
extern cvar_t *gl_round_down;
|
||||||
|
extern cvar_t *gl_detailscale;
|
||||||
|
extern cvar_t *gl_wireframe;
|
||||||
|
extern cvar_t *gl_depthoffset;
|
||||||
|
extern cvar_t *gl_clear;
|
||||||
|
extern cvar_t *gl_test; // cvar to testify new effects
|
||||||
|
extern cvar_t *gl_subdivide_size;
|
||||||
|
|
||||||
|
extern cvar_t *r_speeds;
|
||||||
|
extern cvar_t *r_fullbright;
|
||||||
|
extern cvar_t *r_norefresh;
|
||||||
|
extern cvar_t *r_lighting_extended;
|
||||||
|
extern cvar_t *r_lighting_modulate;
|
||||||
|
extern cvar_t *r_lighting_ambient;
|
||||||
|
extern cvar_t *r_studio_lambert;
|
||||||
|
extern cvar_t *r_detailtextures;
|
||||||
|
extern cvar_t *r_drawentities;
|
||||||
|
extern cvar_t *r_decals;
|
||||||
|
extern cvar_t *r_novis;
|
||||||
|
extern cvar_t *r_nocull;
|
||||||
|
extern cvar_t *r_lockpvs;
|
||||||
|
extern cvar_t *r_lockfrustum;
|
||||||
|
extern cvar_t *r_traceglow;
|
||||||
|
extern cvar_t *r_dynamic;
|
||||||
|
extern cvar_t *r_lightmap;
|
||||||
|
|
||||||
|
extern cvar_t *vid_brightness;
|
||||||
|
extern cvar_t *vid_gamma;
|
||||||
|
|
||||||
|
//
|
||||||
|
// engine shared convars
|
||||||
|
//
|
||||||
|
extern cvar_t *gl_showtextures;
|
||||||
|
extern cvar_t *tracerred;
|
||||||
|
extern cvar_t *tracergreen;
|
||||||
|
extern cvar_t *tracerblue;
|
||||||
|
extern cvar_t *traceralpha;
|
||||||
|
extern cvar_t *cl_lightstyle_lerping;
|
||||||
|
extern cvar_t *r_showhull;
|
||||||
|
extern cvar_t *r_fast_particles;
|
||||||
|
|
||||||
|
//
|
||||||
|
// engine callbacks
|
||||||
|
//
|
||||||
|
#include "crtlib.h"
|
||||||
|
|
||||||
|
#define Mem_Malloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, false, __FILE__, __LINE__ )
|
||||||
|
#define Mem_Calloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, true, __FILE__, __LINE__ )
|
||||||
|
#define Mem_Realloc( pool, ptr, size ) gEngfuncs._Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ )
|
||||||
|
#define Mem_Free( mem ) gEngfuncs._Mem_Free( mem, __FILE__, __LINE__ )
|
||||||
|
#define Mem_AllocPool( name ) gEngfuncs._Mem_AllocPool( name, __FILE__, __LINE__ )
|
||||||
|
#define Mem_FreePool( pool ) gEngfuncs._Mem_FreePool( pool, __FILE__, __LINE__ )
|
||||||
|
#define Mem_EmptyPool( pool ) gEngfuncs._Mem_EmptyPool( pool, __FILE__, __LINE__ )
|
||||||
|
|
||||||
|
#endif // GL_LOCAL_H
|
||||||
477
ref_gu/gu_render.c
Normal file
477
ref_gu/gu_render.c
Normal file
@@ -0,0 +1,477 @@
|
|||||||
|
/*
|
||||||
|
gu_render.c - render initialization
|
||||||
|
Copyright (C) 2010 Uncle Mike
|
||||||
|
Copyright (C) 2022 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
#include "gu_local.h"
|
||||||
|
|
||||||
|
cvar_t *gl_texture_lodfunc;
|
||||||
|
cvar_t *gl_texture_lodbias;
|
||||||
|
cvar_t *gl_texture_lodslope;
|
||||||
|
|
||||||
|
cvar_t *gl_texture_nearest;
|
||||||
|
cvar_t *gl_lightmap_nearest;
|
||||||
|
cvar_t *gl_keeptjunctions;
|
||||||
|
cvar_t *gl_emboss_scale;
|
||||||
|
cvar_t *gl_detailscale;
|
||||||
|
cvar_t *gl_depthoffset;
|
||||||
|
cvar_t *gl_wireframe;
|
||||||
|
cvar_t *gl_vsync;
|
||||||
|
cvar_t *gl_clear;
|
||||||
|
cvar_t *gl_test;
|
||||||
|
cvar_t *gl_subdivide_size;
|
||||||
|
cvar_t *r_speeds;
|
||||||
|
cvar_t *r_fullbright;
|
||||||
|
cvar_t *r_norefresh;
|
||||||
|
cvar_t *r_lighting_extended;
|
||||||
|
cvar_t *r_lighting_modulate;
|
||||||
|
cvar_t *r_lighting_ambient;
|
||||||
|
cvar_t *r_detailtextures;
|
||||||
|
cvar_t *r_drawentities;
|
||||||
|
cvar_t *r_adjust_fov;
|
||||||
|
cvar_t *r_decals;
|
||||||
|
cvar_t *r_novis;
|
||||||
|
cvar_t *r_nocull;
|
||||||
|
cvar_t *r_lockpvs;
|
||||||
|
cvar_t *r_lockfrustum;
|
||||||
|
cvar_t *r_traceglow;
|
||||||
|
cvar_t *r_dynamic;
|
||||||
|
cvar_t *r_lightmap;
|
||||||
|
cvar_t *r_showhull;
|
||||||
|
cvar_t *r_fast_particles;
|
||||||
|
cvar_t *gl_round_down;
|
||||||
|
cvar_t *gl_showtextures;
|
||||||
|
cvar_t *cl_lightstyle_lerping;
|
||||||
|
|
||||||
|
cvar_t *vid_brightness;
|
||||||
|
cvar_t *vid_gamma;
|
||||||
|
cvar_t *tracerred;
|
||||||
|
cvar_t *tracergreen;
|
||||||
|
cvar_t *tracerblue;
|
||||||
|
cvar_t *traceralpha;
|
||||||
|
|
||||||
|
byte *r_temppool;
|
||||||
|
|
||||||
|
gl_globals_t tr;
|
||||||
|
glconfig_t glConfig;
|
||||||
|
glstate_t glState;
|
||||||
|
glwstate_t glw_state;
|
||||||
|
gurender_t guRender;
|
||||||
|
|
||||||
|
// Set frame buffer
|
||||||
|
#define PSP_FB_WIDTH 480
|
||||||
|
#define PSP_FB_HEIGHT 272
|
||||||
|
#define PSP_FB_BWIDTH 512
|
||||||
|
#define PSP_FB_FORMAT GU_PSM_5650 //4444,5551,5650,8888
|
||||||
|
|
||||||
|
#if PSP_FB_FORMAT == GU_PSM_4444
|
||||||
|
#define PSP_FB_BPP 2
|
||||||
|
#elif PSP_FB_FORMAT == GU_PSM_5551
|
||||||
|
#define PSP_FB_BPP 2
|
||||||
|
#elif PSP_FB_FORMAT == GU_PSM_5650
|
||||||
|
#define PSP_FB_BPP 2
|
||||||
|
#elif PSP_FB_FORMAT == GU_PSM_8888
|
||||||
|
#define PSP_FB_BPP 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PSP_GU_LIST_SIZE 0x100000 // 1Mb
|
||||||
|
|
||||||
|
static byte context_list[PSP_GU_LIST_SIZE] __attribute__( ( aligned( 64 ) ) );
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
GU_Init
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static void GU_Init( void )
|
||||||
|
{
|
||||||
|
memset( &guRender, 0, sizeof( guRender ));
|
||||||
|
|
||||||
|
guRender.screen_width = PSP_FB_WIDTH;
|
||||||
|
guRender.screen_height = PSP_FB_HEIGHT;
|
||||||
|
guRender.buffer_width = PSP_FB_BWIDTH;
|
||||||
|
guRender.buffer_format = PSP_FB_FORMAT;
|
||||||
|
guRender.buffer_bpp = PSP_FB_BPP;
|
||||||
|
|
||||||
|
guRender.draw_buffer = ( void* )valloc( guRender.buffer_width * guRender.screen_height * guRender.buffer_bpp );
|
||||||
|
if( !guRender.draw_buffer )
|
||||||
|
gEngfuncs.Host_Error( "Memory allocation failled! (guRender.draw_buffer)\n" );
|
||||||
|
|
||||||
|
guRender.disp_buffer = ( void* )valloc( guRender.buffer_width * guRender.screen_height * guRender.buffer_bpp );
|
||||||
|
if( !guRender.disp_buffer )
|
||||||
|
gEngfuncs.Host_Error( "Memory allocation failled! (guRender.disp_buffer)\n" );
|
||||||
|
|
||||||
|
guRender.depth_buffer = ( void* )valloc( guRender.buffer_width * guRender.screen_height * guRender.buffer_bpp );
|
||||||
|
if( !guRender.depth_buffer )
|
||||||
|
gEngfuncs.Host_Error( "Memory allocation failled! (guRender.depth_buffer)\n" );
|
||||||
|
|
||||||
|
guRender.context_list = context_list;
|
||||||
|
guRender.context_list_size = sizeof( context_list );
|
||||||
|
|
||||||
|
// Initialise the GU.
|
||||||
|
sceGuInit();
|
||||||
|
|
||||||
|
// Set up the GU.
|
||||||
|
sceGuStart( GU_DIRECT, guRender.context_list );
|
||||||
|
|
||||||
|
sceGuDrawBuffer( guRender.buffer_format, vrelptr( guRender.draw_buffer ), guRender.buffer_width );
|
||||||
|
sceGuDispBuffer( guRender.screen_width, guRender.screen_height, vrelptr( guRender.disp_buffer ), guRender.buffer_width );
|
||||||
|
sceGuDepthBuffer( vrelptr( guRender.depth_buffer ), guRender.buffer_width );
|
||||||
|
|
||||||
|
// Set the rendering offset and viewport.
|
||||||
|
sceGuOffset( 2048 - ( guRender.screen_width / 2 ), 2048 - ( guRender.screen_height / 2 ) );
|
||||||
|
sceGuViewport( 2048, 2048, guRender.screen_width, guRender.screen_height );
|
||||||
|
|
||||||
|
// Set up scissoring.
|
||||||
|
sceGuEnable( GU_SCISSOR_TEST );
|
||||||
|
sceGuScissor( 0, 0, guRender.screen_width, guRender.screen_height );
|
||||||
|
|
||||||
|
// Xash default
|
||||||
|
sceGuClearColor( GU_COLOR( 0.5f, 0.5f, 0.5f, 1.0f ) );
|
||||||
|
|
||||||
|
sceGuEnable( GU_DEPTH_TEST );
|
||||||
|
sceGuDisable( GU_CULL_FACE );
|
||||||
|
sceGuEnable( GU_CLIP_PLANES );
|
||||||
|
sceGuDepthFunc( GU_LEQUAL );
|
||||||
|
sceGuColor( 0xffffffff );
|
||||||
|
|
||||||
|
// Set up stencil
|
||||||
|
if( glState.stencilEnabled )
|
||||||
|
{
|
||||||
|
sceGuDisable( GU_STENCIL_TEST );
|
||||||
|
/*pglStencilMask( ( GLuint ) ~0 );*/ // alpha color sceGuPixelMask
|
||||||
|
sceGuStencilFunc( GU_EQUAL, 0, ~0 );
|
||||||
|
sceGuStencilOp( GU_KEEP, GU_INCR, GU_INCR );
|
||||||
|
}
|
||||||
|
|
||||||
|
sceGuDepthRange( 0, 65535 );
|
||||||
|
sceGuDepthOffset( 0 );
|
||||||
|
|
||||||
|
sceGuDisable( GU_BLEND );
|
||||||
|
sceGuDisable( GU_ALPHA_TEST );
|
||||||
|
|
||||||
|
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
||||||
|
sceGuAlphaFunc( GU_GREATER, DEFAULT_ALPHATEST, 0xff );
|
||||||
|
sceGuEnable( GU_TEXTURE_2D );
|
||||||
|
sceGuShadeModel( GU_SMOOTH );
|
||||||
|
sceGuFrontFace( GU_CCW );
|
||||||
|
|
||||||
|
// Set the default matrices.
|
||||||
|
sceGumMatrixMode( GU_PROJECTION );
|
||||||
|
sceGumLoadIdentity();
|
||||||
|
sceGumMatrixMode( GU_VIEW );
|
||||||
|
sceGumLoadIdentity();
|
||||||
|
sceGumMatrixMode( GU_MODEL );
|
||||||
|
sceGumLoadIdentity();
|
||||||
|
sceGumMatrixMode( GU_TEXTURE );
|
||||||
|
sceGumLoadIdentity();
|
||||||
|
|
||||||
|
sceGumUpdateMatrix();
|
||||||
|
|
||||||
|
sceGuFinish();
|
||||||
|
sceGuSync( GU_SYNC_FINISH, GU_SYNC_WAIT );
|
||||||
|
|
||||||
|
// Turn on the display.
|
||||||
|
sceDisplayWaitVblankStart();
|
||||||
|
sceGuDisplay(GU_TRUE);
|
||||||
|
|
||||||
|
// Start a new render.
|
||||||
|
sceGuStart( GU_DIRECT, guRender.context_list );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
GU_Shutdown
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static void GU_Shutdown( void )
|
||||||
|
{
|
||||||
|
// Finish rendering.
|
||||||
|
sceGuFinish();
|
||||||
|
sceGuSync( GU_SYNC_FINISH, GU_SYNC_WAIT );
|
||||||
|
|
||||||
|
// Shut down the display.
|
||||||
|
sceGuTerm();
|
||||||
|
|
||||||
|
// Free the buffers.
|
||||||
|
if( guRender.draw_buffer )
|
||||||
|
vfree( guRender.draw_buffer );
|
||||||
|
if( guRender.disp_buffer )
|
||||||
|
vfree( guRender.disp_buffer );
|
||||||
|
if( guRender.depth_buffer )
|
||||||
|
vfree( guRender.depth_buffer );
|
||||||
|
|
||||||
|
guRender.draw_buffer = NULL;
|
||||||
|
guRender.disp_buffer = NULL;
|
||||||
|
guRender.depth_buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==============
|
||||||
|
GL_GetProcAddress
|
||||||
|
|
||||||
|
defined just for nanogl/glwes, so it don't link to SDL2 directly, nor use dlsym
|
||||||
|
==============
|
||||||
|
*/
|
||||||
|
void GAME_EXPORT *GL_GetProcAddress( const char *name )
|
||||||
|
{
|
||||||
|
return gEngfuncs.GL_GetProcAddress( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
GL_SetDefaultState
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static void GL_SetDefaultState( void )
|
||||||
|
{
|
||||||
|
memset( &glState, 0, sizeof( glState ));
|
||||||
|
|
||||||
|
// init draw stack
|
||||||
|
tr.draw_list = &tr.draw_stack[0];
|
||||||
|
tr.draw_stack_pos = 0;
|
||||||
|
|
||||||
|
// init glState struct
|
||||||
|
glState.currentTexture = -1;
|
||||||
|
glState.texIdentityMatrix = true;
|
||||||
|
glState.fogColor = 0;
|
||||||
|
glState.fogDensity = 0;
|
||||||
|
glState.fogStart = 100.0f;
|
||||||
|
glState.fogEnd = 1000.0f;
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
GL_SetDefaults
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static void GU_SetDefaults( void )
|
||||||
|
{
|
||||||
|
pglFinish();
|
||||||
|
|
||||||
|
pglClearColor( 0.5f, 0.5f, 0.5f, 1.0f );
|
||||||
|
|
||||||
|
pglDisable( GL_DEPTH_TEST );
|
||||||
|
pglDisable( GL_CULL_FACE );
|
||||||
|
pglDisable( GL_SCISSOR_TEST );
|
||||||
|
pglDepthFunc( GL_LEQUAL );
|
||||||
|
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||||
|
|
||||||
|
if( glState.stencilEnabled )
|
||||||
|
{
|
||||||
|
pglDisable( GL_STENCIL_TEST );
|
||||||
|
pglStencilMask( ( GLuint ) ~0 );
|
||||||
|
pglStencilFunc( GL_EQUAL, 0, ~0 );
|
||||||
|
pglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
|
||||||
|
}
|
||||||
|
|
||||||
|
pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
|
||||||
|
pglPolygonOffset( -1.0f, -2.0f );
|
||||||
|
|
||||||
|
GL_CleanupAllTextureUnits();
|
||||||
|
|
||||||
|
pglDisable( GL_BLEND );
|
||||||
|
pglDisable( GL_ALPHA_TEST );
|
||||||
|
pglDisable( GL_POLYGON_OFFSET_FILL );
|
||||||
|
pglAlphaFunc( GL_GREATER, DEFAULT_ALPHATEST );
|
||||||
|
pglEnable( GL_TEXTURE_2D );
|
||||||
|
pglShadeModel( GL_SMOOTH );
|
||||||
|
pglFrontFace( GL_CCW );
|
||||||
|
|
||||||
|
pglPointSize( 1.2f );
|
||||||
|
pglLineWidth( 1.2f );
|
||||||
|
|
||||||
|
GL_Cull( GL_NONE );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_RenderInfo_f
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void R_RenderInfo_f( void )
|
||||||
|
{
|
||||||
|
gEngfuncs.Con_Printf( "\n" );
|
||||||
|
gEngfuncs.Con_Printf( "HARDWARE RENDER\n");
|
||||||
|
gEngfuncs.Con_Printf( "MAX_TEXTURE_SIZE: %i\n", glConfig.max_texture_size );
|
||||||
|
gEngfuncs.Con_Printf( "MODE: %ix%i\n", gpGlobals->width, gpGlobals->height );
|
||||||
|
gEngfuncs.Con_Printf( "VERTICAL SYNC: %s\n", gl_vsync->value ? "enabled" : "disabled" );
|
||||||
|
gEngfuncs.Con_Printf( "VRAM AVAILABLE: %i\n", vmemavail() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_InitExtensions( void )
|
||||||
|
{
|
||||||
|
glState.stencilEnabled = true;
|
||||||
|
glConfig.max_texture_size = 256;
|
||||||
|
|
||||||
|
// get our various GL strings
|
||||||
|
gEngfuncs.Con_Reportf( "^3Video^7: PSP HW\n" );
|
||||||
|
|
||||||
|
gEngfuncs.Cvar_Get( "gl_max_size", va( "%i", glConfig.max_texture_size ), 0, "opengl texture max dims" );
|
||||||
|
/*
|
||||||
|
gEngfuncs.Image_AddCmdFlags( IL_DDS_HARDWARE );
|
||||||
|
*/
|
||||||
|
R_RenderInfo_f();
|
||||||
|
|
||||||
|
tr.framecount = tr.visframecount = 1;
|
||||||
|
glw_state.initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_ClearExtensions( void )
|
||||||
|
{
|
||||||
|
// now all extensions are disabled
|
||||||
|
glw_state.initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_InitCommands
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GL_InitCommands( void )
|
||||||
|
{
|
||||||
|
r_speeds = gEngfuncs.Cvar_Get( "r_speeds", "0", FCVAR_ARCHIVE, "shows renderer speeds" );
|
||||||
|
r_fullbright = gEngfuncs.Cvar_Get( "r_fullbright", "0", FCVAR_CHEAT, "disable lightmaps, get fullbright for entities" );
|
||||||
|
r_norefresh = gEngfuncs.Cvar_Get( "r_norefresh", "0", 0, "disable 3D rendering (use with caution)" );
|
||||||
|
r_lighting_extended = gEngfuncs.Cvar_Get( "r_lighting_extended", "0", FCVAR_ARCHIVE, "allow to get lighting from world and bmodels" ); // disabled
|
||||||
|
r_lighting_modulate = gEngfuncs.Cvar_Get( "r_lighting_modulate", "0.6", FCVAR_ARCHIVE, "lightstyles modulate scale" );
|
||||||
|
r_lighting_ambient = gEngfuncs.Cvar_Get( "r_lighting_ambient", "0.3", FCVAR_ARCHIVE, "map ambient lighting scale" );
|
||||||
|
r_novis = gEngfuncs.Cvar_Get( "r_novis", "0", 0, "ignore vis information (perfomance test)" );
|
||||||
|
r_nocull = gEngfuncs.Cvar_Get( "r_nocull", "0", 0, "ignore frustrum culling (perfomance test)" );
|
||||||
|
r_detailtextures = gEngfuncs.Cvar_Get( "r_detailtextures", "0", FCVAR_ARCHIVE, "enable detail textures support, use '2' for autogenerate detail.txt" ); // disabled
|
||||||
|
r_lockpvs = gEngfuncs.Cvar_Get( "r_lockpvs", "0", FCVAR_CHEAT, "lockpvs area at current point (pvs test)" );
|
||||||
|
r_lockfrustum = gEngfuncs.Cvar_Get( "r_lockfrustum", "0", FCVAR_CHEAT, "lock frustrum area at current point (cull test)" );
|
||||||
|
r_dynamic = gEngfuncs.Cvar_Get( "r_dynamic", "1", FCVAR_ARCHIVE, "allow dynamic lighting (dlights, lightstyles)" );
|
||||||
|
r_traceglow = gEngfuncs.Cvar_Get( "r_traceglow", "0", FCVAR_ARCHIVE, "cull flares behind models" ); // disabled
|
||||||
|
r_lightmap = gEngfuncs.Cvar_Get( "r_lightmap", "0", FCVAR_CHEAT, "lightmap debugging tool" );
|
||||||
|
r_drawentities = gEngfuncs.Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT, "render entities" );
|
||||||
|
r_decals = gEngfuncs.pfnGetCvarPointer( "r_decals", 0 );
|
||||||
|
r_showhull = gEngfuncs.pfnGetCvarPointer( "r_showhull", 0 );
|
||||||
|
r_fast_particles = gEngfuncs.Cvar_Get( "r_fast_particles", "1", FCVAR_ARCHIVE, "use GU_POINTS for particles" );
|
||||||
|
|
||||||
|
gl_texture_nearest = gEngfuncs.Cvar_Get( "gl_texture_nearest", "0", FCVAR_GLCONFIG, "disable texture filter" );
|
||||||
|
gl_lightmap_nearest = gEngfuncs.Cvar_Get( "gl_lightmap_nearest", "0", FCVAR_GLCONFIG, "disable lightmap filter" );
|
||||||
|
gl_vsync = gEngfuncs.pfnGetCvarPointer( "gl_vsync", 0 );
|
||||||
|
gl_detailscale = gEngfuncs.Cvar_Get( "gl_detailscale", "4.0", FCVAR_GLCONFIG, "default scale applies while auto-generate list of detail textures" );
|
||||||
|
gl_texture_lodfunc = gEngfuncs.Cvar_Get( "gl_texture_lodfunc", "2", FCVAR_GLCONFIG, "LOD func for mipmapped textures" );
|
||||||
|
gl_texture_lodbias = gEngfuncs.Cvar_Get( "gl_texture_lodbias", "-6.0", FCVAR_GLCONFIG, "LOD bias for mipmapped textures (perfomance|quality)" );
|
||||||
|
gl_texture_lodslope = gEngfuncs.Cvar_Get( "gl_texture_lodslope", "0.3", FCVAR_GLCONFIG, "LOD slope for mipmapped textures" );
|
||||||
|
gl_keeptjunctions = gEngfuncs.Cvar_Get( "gl_keeptjunctions", "1", FCVAR_GLCONFIG, "removing tjuncs causes blinking pixels" );
|
||||||
|
gl_emboss_scale = gEngfuncs.Cvar_Get( "gl_emboss_scale", "0", FCVAR_GLCONFIG|FCVAR_LATCH, "fake bumpmapping scale" );
|
||||||
|
gl_showtextures = gEngfuncs.pfnGetCvarPointer( "r_showtextures", 0 );
|
||||||
|
gl_clear = gEngfuncs.pfnGetCvarPointer( "gl_clear", 0 );
|
||||||
|
gl_test = gEngfuncs.Cvar_Get( "gl_test", "0", 0, "engine developer cvar for quick testing new features" );
|
||||||
|
gl_wireframe = gEngfuncs.Cvar_Get( "gl_wireframe", "0", FCVAR_GLCONFIG|FCVAR_SPONLY, "show wireframe overlay" );
|
||||||
|
gl_subdivide_size = gEngfuncs.Cvar_Get( "gl_subdivide_size", "256.0", FCVAR_GLCONFIG, "the division value for the sky brushes" );
|
||||||
|
gl_round_down = gEngfuncs.Cvar_Get( "gl_round_down", "1", FCVAR_GLCONFIG, "round texture sizes to nearest POT value" );
|
||||||
|
// these cvar not used by engine but some mods requires this
|
||||||
|
gl_depthoffset = gEngfuncs.Cvar_Get( "gl_depthoffset", "256.0", FCVAR_GLCONFIG, "depth offset for decals" );
|
||||||
|
|
||||||
|
// make sure gl_vsync is checked after vid_restart
|
||||||
|
SetBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||||
|
|
||||||
|
vid_gamma = gEngfuncs.pfnGetCvarPointer( "gamma", 0 );
|
||||||
|
vid_brightness = gEngfuncs.pfnGetCvarPointer( "brightness", 0 );
|
||||||
|
|
||||||
|
tracerred = gEngfuncs.Cvar_Get( "tracerred", "0.8", 0, "tracer red component weight ( 0 - 1.0 )" );
|
||||||
|
tracergreen = gEngfuncs.Cvar_Get( "tracergreen", "0.8", 0, "tracer green component weight ( 0 - 1.0 )" );
|
||||||
|
tracerblue = gEngfuncs.Cvar_Get( "tracerblue", "0.4", 0, "tracer blue component weight ( 0 - 1.0 )" );
|
||||||
|
traceralpha = gEngfuncs.Cvar_Get( "traceralpha", "0.5", 0, "tracer alpha amount ( 0 - 1.0 )" );
|
||||||
|
|
||||||
|
cl_lightstyle_lerping = gEngfuncs.pfnGetCvarPointer( "cl_lightstyle_lerping", 0 );
|
||||||
|
|
||||||
|
gEngfuncs.Cmd_AddCommand( "r_info", R_RenderInfo_f, "display renderer info" );
|
||||||
|
gEngfuncs.Cmd_AddCommand( "timerefresh", SCR_TimeRefresh_f, "turn quickly and print rendering statistcs" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
GL_RemoveCommands
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void GL_RemoveCommands( void )
|
||||||
|
{
|
||||||
|
gEngfuncs.Cmd_RemoveCommand( "r_info" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
R_Init
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
qboolean R_Init( void )
|
||||||
|
{
|
||||||
|
if( glw_state.initialized )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if( vinit() < 0 )
|
||||||
|
{
|
||||||
|
gEngfuncs.Host_Error( "Can't initialize video subsystem\nVRam unavailable" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GL_InitCommands();
|
||||||
|
GL_InitRandomTable();
|
||||||
|
|
||||||
|
GL_SetDefaultState();
|
||||||
|
|
||||||
|
// create the window and set up the context
|
||||||
|
if( !gEngfuncs.R_Init_Video( REF_GL )) // request GL context
|
||||||
|
{
|
||||||
|
GL_RemoveCommands();
|
||||||
|
gEngfuncs.R_Free_Video();
|
||||||
|
// Why? Host_Error again???
|
||||||
|
// gEngfuncs.Host_Error( "Can't initialize video subsystem\nProbably driver was not installed" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
r_temppool = Mem_AllocPool( "Render Zone" );
|
||||||
|
|
||||||
|
GU_Init();
|
||||||
|
R_InitImages();
|
||||||
|
R_SpriteInit();
|
||||||
|
R_StudioInit();
|
||||||
|
R_AliasInit();
|
||||||
|
R_ClearDecals();
|
||||||
|
R_ClearScene();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
R_Shutdown
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
void R_Shutdown( void )
|
||||||
|
{
|
||||||
|
if( !glw_state.initialized )
|
||||||
|
return;
|
||||||
|
|
||||||
|
GL_RemoveCommands();
|
||||||
|
R_ShutdownImages();
|
||||||
|
GU_Shutdown();
|
||||||
|
|
||||||
|
Mem_FreePool( &r_temppool );
|
||||||
|
|
||||||
|
// shut down OS specific OpenGL stuff like contexts, etc.
|
||||||
|
gEngfuncs.R_Free_Video();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL_SetupAttributes( int safegl )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
491
ref_gu/gu_rlight.c
Normal file
491
ref_gu/gu_rlight.c
Normal file
@@ -0,0 +1,491 @@
|
|||||||
|
/*
|
||||||
|
gl_rlight.c - dynamic and static lights
|
||||||
|
Copyright (C) 2010 Uncle Mike
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gu_local.h"
|
||||||
|
#include "pm_local.h"
|
||||||
|
#include "studio.h"
|
||||||
|
#include "xash3d_mathlib.h"
|
||||||
|
#include "ref_params.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============================================================================
|
||||||
|
|
||||||
|
DYNAMIC LIGHTS
|
||||||
|
|
||||||
|
=============================================================================
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
CL_RunLightStyles
|
||||||
|
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void CL_RunLightStyles( void )
|
||||||
|
{
|
||||||
|
int i, k, flight, clight;
|
||||||
|
float l, lerpfrac, backlerp;
|
||||||
|
float frametime = (gpGlobals->time - gpGlobals->oldtime);
|
||||||
|
float scale;
|
||||||
|
lightstyle_t *ls;
|
||||||
|
|
||||||
|
if( !WORLDMODEL ) return;
|
||||||
|
|
||||||
|
scale = r_lighting_modulate->value;
|
||||||
|
|
||||||
|
// light animations
|
||||||
|
// 'm' is normal light, 'a' is no light, 'z' is double bright
|
||||||
|
for( i = 0, ls = gEngfuncs.GetLightStyle( 0 ); i < MAX_LIGHTSTYLES; i++, ls++ )
|
||||||
|
{
|
||||||
|
if( !WORLDMODEL->lightdata )
|
||||||
|
{
|
||||||
|
tr.lightstylevalue[i] = 256 * 256;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !ENGINE_GET_PARM( PARAM_GAMEPAUSED ) && frametime <= 0.1f )
|
||||||
|
ls->time += frametime; // evaluate local time
|
||||||
|
|
||||||
|
flight = (int)Q_floor( ls->time * 10 );
|
||||||
|
clight = (int)Q_ceil( ls->time * 10 );
|
||||||
|
lerpfrac = ( ls->time * 10 ) - flight;
|
||||||
|
backlerp = 1.0f - lerpfrac;
|
||||||
|
|
||||||
|
if( !ls->length )
|
||||||
|
{
|
||||||
|
tr.lightstylevalue[i] = 256 * scale;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if( ls->length == 1 )
|
||||||
|
{
|
||||||
|
// single length style so don't bother interpolating
|
||||||
|
tr.lightstylevalue[i] = ls->map[0] * 22 * scale;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if( !ls->interp || !CVAR_TO_BOOL( cl_lightstyle_lerping ))
|
||||||
|
{
|
||||||
|
tr.lightstylevalue[i] = ls->map[flight%ls->length] * 22 * scale;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// interpolate animating light
|
||||||
|
// frame just gone
|
||||||
|
k = ls->map[flight % ls->length];
|
||||||
|
l = (float)( k * 22.0f ) * backlerp;
|
||||||
|
|
||||||
|
// upcoming frame
|
||||||
|
k = ls->map[clight % ls->length];
|
||||||
|
l += (float)( k * 22.0f ) * lerpfrac;
|
||||||
|
|
||||||
|
tr.lightstylevalue[i] = (int)l * scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_MarkLights
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
|
||||||
|
{
|
||||||
|
float dist;
|
||||||
|
msurface_t *surf;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if( !node || node->contents < 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
dist = PlaneDiff( light->origin, node->plane );
|
||||||
|
|
||||||
|
if( dist > light->radius )
|
||||||
|
{
|
||||||
|
R_MarkLights( light, bit, node->children[0] );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if( dist < -light->radius )
|
||||||
|
{
|
||||||
|
R_MarkLights( light, bit, node->children[1] );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark the polygons
|
||||||
|
surf = RI.currentmodel->surfaces + node->firstsurface;
|
||||||
|
|
||||||
|
for( i = 0; i < node->numsurfaces; i++, surf++ )
|
||||||
|
{
|
||||||
|
if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius ))
|
||||||
|
continue; // no intersection
|
||||||
|
|
||||||
|
if( surf->dlightframe != tr.dlightframecount )
|
||||||
|
{
|
||||||
|
surf->dlightbits = 0;
|
||||||
|
surf->dlightframe = tr.dlightframecount;
|
||||||
|
}
|
||||||
|
surf->dlightbits |= bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
R_MarkLights( light, bit, node->children[0] );
|
||||||
|
R_MarkLights( light, bit, node->children[1] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_PushDlights
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void R_PushDlights( void )
|
||||||
|
{
|
||||||
|
dlight_t *l;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
tr.dlightframecount = tr.framecount;
|
||||||
|
|
||||||
|
RI.currententity = gEngfuncs.GetEntityByIndex( 0 );
|
||||||
|
RI.currentmodel = RI.currententity->model;
|
||||||
|
|
||||||
|
for( i = 0, l = gEngfuncs.GetDynamicLight( 0 ); i < MAX_DLIGHTS; i++, l++ )
|
||||||
|
{
|
||||||
|
if( l->die < gpGlobals->time || !l->radius )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if( GL_FrustumCullSphere( &RI.frustum, l->origin, l->radius, 15 ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
R_MarkLights( l, 1<<i, RI.currentmodel->nodes );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_CountDlights
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
int R_CountDlights( void )
|
||||||
|
{
|
||||||
|
dlight_t *l;
|
||||||
|
int i, numDlights = 0;
|
||||||
|
|
||||||
|
for( i = 0, l = gEngfuncs.GetDynamicLight( 0 ); i < MAX_DLIGHTS; i++, l++ )
|
||||||
|
{
|
||||||
|
if( l->die < gpGlobals->time || !l->radius )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
numDlights++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return numDlights;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
R_CountSurfaceDlights
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
int R_CountSurfaceDlights( msurface_t *surf )
|
||||||
|
{
|
||||||
|
int i, numDlights = 0;
|
||||||
|
|
||||||
|
for( i = 0; i < MAX_DLIGHTS; i++ )
|
||||||
|
{
|
||||||
|
if(!( surf->dlightbits & BIT( i )))
|
||||||
|
continue; // not lit by this light
|
||||||
|
|
||||||
|
numDlights++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return numDlights;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
AMBIENT LIGHTING
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
*/
|
||||||
|
static vec3_t g_trace_lightspot;
|
||||||
|
static vec3_t g_trace_lightvec;
|
||||||
|
static float g_trace_fraction;
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_RecursiveLightPoint
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, float p2f, colorVec *cv, const vec3_t start, const vec3_t end )
|
||||||
|
{
|
||||||
|
float front, back, frac, midf;
|
||||||
|
int i, map, side, size;
|
||||||
|
float ds, dt, s, t;
|
||||||
|
int sample_size;
|
||||||
|
color24 *lm, *dm;
|
||||||
|
mextrasurf_t *info;
|
||||||
|
msurface_t *surf;
|
||||||
|
mtexinfo_t *tex;
|
||||||
|
matrix3x4 tbn;
|
||||||
|
vec3_t mid;
|
||||||
|
|
||||||
|
// didn't hit anything
|
||||||
|
if( !node || node->contents < 0 )
|
||||||
|
{
|
||||||
|
cv->r = cv->g = cv->b = cv->a = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate mid point
|
||||||
|
front = PlaneDiff( start, node->plane );
|
||||||
|
back = PlaneDiff( end, node->plane );
|
||||||
|
|
||||||
|
side = front < 0;
|
||||||
|
if(( back < 0 ) == side )
|
||||||
|
return R_RecursiveLightPoint( model, node->children[side], p1f, p2f, cv, start, end );
|
||||||
|
|
||||||
|
frac = front / ( front - back );
|
||||||
|
|
||||||
|
VectorLerp( start, frac, end, mid );
|
||||||
|
midf = p1f + ( p2f - p1f ) * frac;
|
||||||
|
|
||||||
|
// co down front side
|
||||||
|
if( R_RecursiveLightPoint( model, node->children[side], p1f, midf, cv, start, mid ))
|
||||||
|
return true; // hit something
|
||||||
|
|
||||||
|
if(( back < 0 ) == side )
|
||||||
|
{
|
||||||
|
cv->r = cv->g = cv->b = cv->a = 0;
|
||||||
|
return false; // didn't hit anything
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for impact on this node
|
||||||
|
surf = model->surfaces + node->firstsurface;
|
||||||
|
VectorCopy( mid, g_trace_lightspot );
|
||||||
|
|
||||||
|
for( i = 0; i < node->numsurfaces; i++, surf++ )
|
||||||
|
{
|
||||||
|
int smax, tmax;
|
||||||
|
|
||||||
|
tex = surf->texinfo;
|
||||||
|
info = surf->info;
|
||||||
|
|
||||||
|
if( FBitSet( surf->flags, SURF_DRAWTILED ))
|
||||||
|
continue; // no lightmaps
|
||||||
|
|
||||||
|
s = DotProduct( mid, info->lmvecs[0] ) + info->lmvecs[0][3];
|
||||||
|
t = DotProduct( mid, info->lmvecs[1] ) + info->lmvecs[1][3];
|
||||||
|
|
||||||
|
if( s < info->lightmapmins[0] || t < info->lightmapmins[1] )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ds = s - info->lightmapmins[0];
|
||||||
|
dt = t - info->lightmapmins[1];
|
||||||
|
|
||||||
|
if ( ds > info->lightextents[0] || dt > info->lightextents[1] )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cv->r = cv->g = cv->b = cv->a = 0;
|
||||||
|
|
||||||
|
if( !surf->samples )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
sample_size = gEngfuncs.Mod_SampleSizeForFace( surf );
|
||||||
|
smax = (info->lightextents[0] / sample_size) + 1;
|
||||||
|
tmax = (info->lightextents[1] / sample_size) + 1;
|
||||||
|
ds /= sample_size;
|
||||||
|
dt /= sample_size;
|
||||||
|
|
||||||
|
lm = surf->samples + Q_rint( dt ) * smax + Q_rint( ds );
|
||||||
|
g_trace_fraction = midf;
|
||||||
|
size = smax * tmax;
|
||||||
|
dm = NULL;
|
||||||
|
|
||||||
|
if( surf->info->deluxemap )
|
||||||
|
{
|
||||||
|
vec3_t faceNormal;
|
||||||
|
|
||||||
|
if( FBitSet( surf->flags, SURF_PLANEBACK ))
|
||||||
|
VectorNegate( surf->plane->normal, faceNormal );
|
||||||
|
else VectorCopy( surf->plane->normal, faceNormal );
|
||||||
|
|
||||||
|
// compute face TBN
|
||||||
|
#if 1
|
||||||
|
Vector4Set( tbn[0], surf->info->lmvecs[0][0], surf->info->lmvecs[0][1], surf->info->lmvecs[0][2], 0.0f );
|
||||||
|
Vector4Set( tbn[1], -surf->info->lmvecs[1][0], -surf->info->lmvecs[1][1], -surf->info->lmvecs[1][2], 0.0f );
|
||||||
|
Vector4Set( tbn[2], faceNormal[0], faceNormal[1], faceNormal[2], 0.0f );
|
||||||
|
#else
|
||||||
|
Vector4Set( tbn[0], surf->info->lmvecs[0][0], -surf->info->lmvecs[1][0], faceNormal[0], 0.0f );
|
||||||
|
Vector4Set( tbn[1], surf->info->lmvecs[0][1], -surf->info->lmvecs[1][1], faceNormal[1], 0.0f );
|
||||||
|
Vector4Set( tbn[2], surf->info->lmvecs[0][2], -surf->info->lmvecs[1][2], faceNormal[2], 0.0f );
|
||||||
|
#endif
|
||||||
|
VectorNormalize( tbn[0] );
|
||||||
|
VectorNormalize( tbn[1] );
|
||||||
|
VectorNormalize( tbn[2] );
|
||||||
|
dm = surf->info->deluxemap + Q_rint( dt ) * smax + Q_rint( ds );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ )
|
||||||
|
{
|
||||||
|
uint scale = tr.lightstylevalue[surf->styles[map]];
|
||||||
|
|
||||||
|
if( tr.ignore_lightgamma )
|
||||||
|
{
|
||||||
|
cv->r += lm->r * scale;
|
||||||
|
cv->g += lm->g * scale;
|
||||||
|
cv->b += lm->b * scale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cv->r += gEngfuncs.LightToTexGamma( lm->r ) * scale;
|
||||||
|
cv->g += gEngfuncs.LightToTexGamma( lm->g ) * scale;
|
||||||
|
cv->b += gEngfuncs.LightToTexGamma( lm->b ) * scale;
|
||||||
|
}
|
||||||
|
lm += size; // skip to next lightmap
|
||||||
|
|
||||||
|
if( dm != NULL )
|
||||||
|
{
|
||||||
|
vec3_t srcNormal, lightNormal;
|
||||||
|
float f = (1.0f / 128.0f);
|
||||||
|
|
||||||
|
VectorSet( srcNormal, ((float)dm->r - 128.0f) * f, ((float)dm->g - 128.0f) * f, ((float)dm->b - 128.0f) * f );
|
||||||
|
Matrix3x4_VectorIRotate( tbn, srcNormal, lightNormal ); // turn to world space
|
||||||
|
VectorScale( lightNormal, (float)scale * -1.0f, lightNormal ); // turn direction from light
|
||||||
|
VectorAdd( g_trace_lightvec, lightNormal, g_trace_lightvec );
|
||||||
|
dm += size; // skip to next deluxmap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// go down back side
|
||||||
|
return R_RecursiveLightPoint( model, node->children[!side], midf, p2f, cv, mid, end );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_LightVec
|
||||||
|
|
||||||
|
check bspmodels to get light from
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
colorVec R_LightVecInternal( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec )
|
||||||
|
{
|
||||||
|
float last_fraction;
|
||||||
|
int i, maxEnts = 1;
|
||||||
|
colorVec light, cv;
|
||||||
|
|
||||||
|
if( lspot ) VectorClear( lspot );
|
||||||
|
if( lvec ) VectorClear( lvec );
|
||||||
|
|
||||||
|
if( WORLDMODEL && WORLDMODEL->lightdata )
|
||||||
|
{
|
||||||
|
light.r = light.g = light.b = light.a = 0;
|
||||||
|
last_fraction = 1.0f;
|
||||||
|
|
||||||
|
// get light from bmodels too
|
||||||
|
if( CVAR_TO_BOOL( r_lighting_extended ))
|
||||||
|
maxEnts = MAX_PHYSENTS;
|
||||||
|
|
||||||
|
// check all the bsp-models
|
||||||
|
for( i = 0; i < maxEnts; i++ )
|
||||||
|
{
|
||||||
|
physent_t *pe = gEngfuncs.EV_GetPhysent( i );
|
||||||
|
vec3_t offset, start_l, end_l;
|
||||||
|
mnode_t *pnodes;
|
||||||
|
matrix4x4 matrix;
|
||||||
|
|
||||||
|
if( !pe )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if( !pe->model || pe->model->type != mod_brush )
|
||||||
|
continue; // skip non-bsp models
|
||||||
|
|
||||||
|
pnodes = &pe->model->nodes[pe->model->hulls[0].firstclipnode];
|
||||||
|
VectorSubtract( pe->model->hulls[0].clip_mins, vec3_origin, offset );
|
||||||
|
VectorAdd( offset, pe->origin, offset );
|
||||||
|
VectorSubtract( start, offset, start_l );
|
||||||
|
VectorSubtract( end, offset, end_l );
|
||||||
|
|
||||||
|
// rotate start and end into the models frame of reference
|
||||||
|
if( !VectorIsNull( pe->angles ))
|
||||||
|
{
|
||||||
|
Matrix4x4_CreateFromEntity( matrix, pe->angles, offset, 1.0f );
|
||||||
|
Matrix4x4_VectorITransform( matrix, start, start_l );
|
||||||
|
Matrix4x4_VectorITransform( matrix, end, end_l );
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorClear( g_trace_lightspot );
|
||||||
|
VectorClear( g_trace_lightvec );
|
||||||
|
g_trace_fraction = 1.0f;
|
||||||
|
|
||||||
|
if( !R_RecursiveLightPoint( pe->model, pnodes, 0.0f, 1.0f, &cv, start_l, end_l ))
|
||||||
|
continue; // didn't hit anything
|
||||||
|
|
||||||
|
if( g_trace_fraction < last_fraction )
|
||||||
|
{
|
||||||
|
if( lspot ) VectorCopy( g_trace_lightspot, lspot );
|
||||||
|
if( lvec ) VectorNormalize2( g_trace_lightvec, lvec );
|
||||||
|
light.r = Q_min(( cv.r >> 7 ), 255 );
|
||||||
|
light.g = Q_min(( cv.g >> 7 ), 255 );
|
||||||
|
light.b = Q_min(( cv.b >> 7 ), 255 );
|
||||||
|
last_fraction = g_trace_fraction;
|
||||||
|
|
||||||
|
if(( light.r + light.g + light.b ) != 0 )
|
||||||
|
break; // we get light now
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
light.r = light.g = light.b = 255;
|
||||||
|
light.a = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return light;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_LightVec
|
||||||
|
|
||||||
|
check bspmodels to get light from
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec )
|
||||||
|
{
|
||||||
|
colorVec light = R_LightVecInternal( start, end, lspot, lvec );
|
||||||
|
|
||||||
|
if( CVAR_TO_BOOL( r_lighting_extended ) && lspot != NULL && lvec != NULL )
|
||||||
|
{
|
||||||
|
// trying to get light from ceiling (but ignore gradient analyze)
|
||||||
|
if(( light.r + light.g + light.b ) == 0 )
|
||||||
|
return R_LightVecInternal( end, start, lspot, lvec );
|
||||||
|
}
|
||||||
|
|
||||||
|
return light;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
R_LightPoint
|
||||||
|
|
||||||
|
light from floor
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
colorVec R_LightPoint( const vec3_t p0 )
|
||||||
|
{
|
||||||
|
vec3_t p1;
|
||||||
|
|
||||||
|
VectorSet( p1, p0[0], p0[1], p0[2] - 2048.0f );
|
||||||
|
|
||||||
|
return R_LightVec( p0, p1, NULL, NULL );
|
||||||
|
}
|
||||||
1345
ref_gu/gu_rmain.c
Normal file
1345
ref_gu/gu_rmain.c
Normal file
File diff suppressed because it is too large
Load Diff
290
ref_gu/gu_rmath.c
Normal file
290
ref_gu/gu_rmath.c
Normal file
@@ -0,0 +1,290 @@
|
|||||||
|
/*
|
||||||
|
gl_rmath.c - renderer mathlib
|
||||||
|
Copyright (C) 2010 Uncle Mike
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gu_local.h"
|
||||||
|
#include "xash3d_mathlib.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================================================================
|
||||||
|
|
||||||
|
Matrix4x4 operations (private to renderer)
|
||||||
|
|
||||||
|
========================================================================
|
||||||
|
*/
|
||||||
|
void Matrix4x4_Concat( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 )
|
||||||
|
{
|
||||||
|
#if 1
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C100, 0 + %1\n" // C100 = in1[0]
|
||||||
|
"lv.q C110, 16 + %1\n" // C110 = in1[1]
|
||||||
|
"lv.q C120, 32 + %1\n" // C120 = in1[2]
|
||||||
|
"lv.q C130, 48 + %1\n" // C130 = in1[3]
|
||||||
|
"lv.q C200, 0 + %2\n" // C200 = in2[0]
|
||||||
|
"lv.q C210, 16 + %2\n" // C210 = in2[1]
|
||||||
|
"lv.q C220, 32 + %2\n" // C220 = in2[2]
|
||||||
|
"lv.q C230, 48 + %2\n" // C230 = in2[3]
|
||||||
|
"vmmul.q E000, E100, E200\n" // E000 = E100 * E200
|
||||||
|
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||||
|
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||||
|
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||||
|
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *in1 ), "m"( *in2 )
|
||||||
|
);
|
||||||
|
#else
|
||||||
|
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0] + in1[0][3] * in2[3][0];
|
||||||
|
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1] + in1[0][3] * in2[3][1];
|
||||||
|
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2] + in1[0][3] * in2[3][2];
|
||||||
|
out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3] * in2[3][3];
|
||||||
|
out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0] + in1[1][3] * in2[3][0];
|
||||||
|
out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1] + in1[1][3] * in2[3][1];
|
||||||
|
out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2] + in1[1][3] * in2[3][2];
|
||||||
|
out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3] * in2[3][3];
|
||||||
|
out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0] + in1[2][3] * in2[3][0];
|
||||||
|
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1] + in1[2][3] * in2[3][1];
|
||||||
|
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2] + in1[2][3] * in2[3][2];
|
||||||
|
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3] * in2[3][3];
|
||||||
|
out[3][0] = in1[3][0] * in2[0][0] + in1[3][1] * in2[1][0] + in1[3][2] * in2[2][0] + in1[3][3] * in2[3][0];
|
||||||
|
out[3][1] = in1[3][0] * in2[0][1] + in1[3][1] * in2[1][1] + in1[3][2] * in2[2][1] + in1[3][3] * in2[3][1];
|
||||||
|
out[3][2] = in1[3][0] * in2[0][2] + in1[3][1] * in2[1][2] + in1[3][2] * in2[2][2] + in1[3][3] * in2[3][2];
|
||||||
|
out[3][3] = in1[3][0] * in2[0][3] + in1[3][1] * in2[1][3] + in1[3][2] * in2[2][3] + in1[3][3] * in2[3][3];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
Matrix4x4_CreateProjection
|
||||||
|
|
||||||
|
NOTE: produce quake style world orientation
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void Matrix4x4_CreateProjection( matrix4x4 out, float xMax, float xMin, float yMax, float yMin, float zNear, float zFar )
|
||||||
|
{
|
||||||
|
out[0][0] = ( 2.0f * zNear ) / ( xMax - xMin );
|
||||||
|
out[1][1] = ( 2.0f * zNear ) / ( yMax - yMin );
|
||||||
|
out[2][2] = -( zFar + zNear ) / ( zFar - zNear );
|
||||||
|
out[3][3] = out[0][1] = out[1][0] = out[3][0] = out[0][3] = out[3][1] = out[1][3] = 0.0f;
|
||||||
|
|
||||||
|
out[2][0] = 0.0f;
|
||||||
|
out[2][1] = 0.0f;
|
||||||
|
out[0][2] = ( xMax + xMin ) / ( xMax - xMin );
|
||||||
|
out[1][2] = ( yMax + yMin ) / ( yMax - yMin );
|
||||||
|
out[3][2] = -1.0f;
|
||||||
|
out[2][3] = -( 2.0f * zFar * zNear ) / ( zFar - zNear );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Matrix4x4_CreateOrtho( matrix4x4 out, float xLeft, float xRight, float yBottom, float yTop, float zNear, float zFar )
|
||||||
|
{
|
||||||
|
out[0][0] = 2.0f / (xRight - xLeft);
|
||||||
|
out[1][1] = 2.0f / (yTop - yBottom);
|
||||||
|
out[2][2] = -2.0f / (zFar - zNear);
|
||||||
|
out[3][3] = 1.0f;
|
||||||
|
out[0][1] = out[0][2] = out[1][0] = out[1][2] = out[3][0] = out[3][1] = out[3][2] = 0.0f;
|
||||||
|
|
||||||
|
out[2][0] = 0.0f;
|
||||||
|
out[2][1] = 0.0f;
|
||||||
|
out[0][3] = -(xRight + xLeft) / (xRight - xLeft);
|
||||||
|
out[1][3] = -(yTop + yBottom) / (yTop - yBottom);
|
||||||
|
out[2][3] = -(zFar + zNear) / (zFar - zNear);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
Matrix4x4_CreateModelview
|
||||||
|
|
||||||
|
NOTE: produce quake style world orientation
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void Matrix4x4_CreateModelview( matrix4x4 out )
|
||||||
|
{
|
||||||
|
out[0][0] = out[1][1] = out[2][2] = 0.0f;
|
||||||
|
out[3][0] = out[0][3] = 0.0f;
|
||||||
|
out[3][1] = out[1][3] = 0.0f;
|
||||||
|
out[3][2] = out[2][3] = 0.0f;
|
||||||
|
out[3][3] = 1.0f;
|
||||||
|
out[1][0] = out[0][2] = out[2][1] = 0.0f;
|
||||||
|
out[2][0] = out[0][1] = -1.0f;
|
||||||
|
out[1][2] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Matrix4x4_ToFMatrix4( const matrix4x4 in, ScePspFMatrix4 *out )
|
||||||
|
{
|
||||||
|
// transpose matrix
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C000, 0 + %1\n" // C000 = in->x
|
||||||
|
"lv.q C010, 16 + %1\n" // C010 = in->y
|
||||||
|
"lv.q C020, 32 + %1\n" // C020 = in->z
|
||||||
|
"lv.q C030, 48 + %1\n" // C030 = in->w
|
||||||
|
"sv.q R000, 0 + %0\n" // out->x = R000
|
||||||
|
"sv.q R001, 16 + %0\n" // out->y = R010
|
||||||
|
"sv.q R002, 32 + %0\n" // out->z = R020
|
||||||
|
"sv.q R003, 48 + %0\n" // out->w = R030
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *in )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Matrix4x4_FromFMatrix4( matrix4x4 out, ScePspFMatrix4 *in )
|
||||||
|
{
|
||||||
|
// transpose matrix
|
||||||
|
__asm__ (
|
||||||
|
".set push\n" // save assembler option
|
||||||
|
".set noreorder\n" // suppress reordering
|
||||||
|
"lv.q C000, 0 + %1\n" // C000 = in->x
|
||||||
|
"lv.q C010, 16 + %1\n" // C010 = in->y
|
||||||
|
"lv.q C020, 32 + %1\n" // C020 = in->z
|
||||||
|
"lv.q C030, 48 + %1\n" // C030 = in->w
|
||||||
|
"sv.q R000, 0 + %0\n" // out->x = R000
|
||||||
|
"sv.q R001, 16 + %0\n" // out->y = R010
|
||||||
|
"sv.q R002, 32 + %0\n" // out->z = R020
|
||||||
|
"sv.q R003, 48 + %0\n" // out->w = R030
|
||||||
|
".set pop\n" // restore assembler option
|
||||||
|
: "=m"( *out )
|
||||||
|
: "m"( *in )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Matrix4x4_CreateTranslate( matrix4x4 out, float x, float y, float z )
|
||||||
|
{
|
||||||
|
out[0][0] = 1.0f;
|
||||||
|
out[0][1] = 0.0f;
|
||||||
|
out[0][2] = 0.0f;
|
||||||
|
out[0][3] = x;
|
||||||
|
out[1][0] = 0.0f;
|
||||||
|
out[1][1] = 1.0f;
|
||||||
|
out[1][2] = 0.0f;
|
||||||
|
out[1][3] = y;
|
||||||
|
out[2][0] = 0.0f;
|
||||||
|
out[2][1] = 0.0f;
|
||||||
|
out[2][2] = 1.0f;
|
||||||
|
out[2][3] = z;
|
||||||
|
out[3][0] = 0.0f;
|
||||||
|
out[3][1] = 0.0f;
|
||||||
|
out[3][2] = 0.0f;
|
||||||
|
out[3][3] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Matrix4x4_CreateRotate( matrix4x4 out, float angle, float x, float y, float z )
|
||||||
|
{
|
||||||
|
float len, c, s;
|
||||||
|
|
||||||
|
len = x * x + y * y + z * z;
|
||||||
|
if( len != 0.0f ) len = 1.0f / sqrt( len );
|
||||||
|
x *= len;
|
||||||
|
y *= len;
|
||||||
|
z *= len;
|
||||||
|
|
||||||
|
angle *= (-M_PI_F / 180.0f);
|
||||||
|
SinCos( angle, &s, &c );
|
||||||
|
|
||||||
|
out[0][0]=x * x + c * (1 - x * x);
|
||||||
|
out[0][1]=x * y * (1 - c) + z * s;
|
||||||
|
out[0][2]=z * x * (1 - c) - y * s;
|
||||||
|
out[0][3]=0.0f;
|
||||||
|
out[1][0]=x * y * (1 - c) - z * s;
|
||||||
|
out[1][1]=y * y + c * (1 - y * y);
|
||||||
|
out[1][2]=y * z * (1 - c) + x * s;
|
||||||
|
out[1][3]=0.0f;
|
||||||
|
out[2][0]=z * x * (1 - c) + y * s;
|
||||||
|
out[2][1]=y * z * (1 - c) - x * s;
|
||||||
|
out[2][2]=z * z + c * (1 - z * z);
|
||||||
|
out[2][3]=0.0f;
|
||||||
|
out[3][0]=0.0f;
|
||||||
|
out[3][1]=0.0f;
|
||||||
|
out[3][2]=0.0f;
|
||||||
|
out[3][3]=1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Matrix4x4_CreateScale( matrix4x4 out, float x )
|
||||||
|
{
|
||||||
|
out[0][0] = x;
|
||||||
|
out[0][1] = 0.0f;
|
||||||
|
out[0][2] = 0.0f;
|
||||||
|
out[0][3] = 0.0f;
|
||||||
|
out[1][0] = 0.0f;
|
||||||
|
out[1][1] = x;
|
||||||
|
out[1][2] = 0.0f;
|
||||||
|
out[1][3] = 0.0f;
|
||||||
|
out[2][0] = 0.0f;
|
||||||
|
out[2][1] = 0.0f;
|
||||||
|
out[2][2] = x;
|
||||||
|
out[2][3] = 0.0f;
|
||||||
|
out[3][0] = 0.0f;
|
||||||
|
out[3][1] = 0.0f;
|
||||||
|
out[3][2] = 0.0f;
|
||||||
|
out[3][3] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Matrix4x4_CreateScale3( matrix4x4 out, float x, float y, float z )
|
||||||
|
{
|
||||||
|
out[0][0] = x;
|
||||||
|
out[0][1] = 0.0f;
|
||||||
|
out[0][2] = 0.0f;
|
||||||
|
out[0][3] = 0.0f;
|
||||||
|
out[1][0] = 0.0f;
|
||||||
|
out[1][1] = y;
|
||||||
|
out[1][2] = 0.0f;
|
||||||
|
out[1][3] = 0.0f;
|
||||||
|
out[2][0] = 0.0f;
|
||||||
|
out[2][1] = 0.0f;
|
||||||
|
out[2][2] = z;
|
||||||
|
out[2][3] = 0.0f;
|
||||||
|
out[3][0] = 0.0f;
|
||||||
|
out[3][1] = 0.0f;
|
||||||
|
out[3][2] = 0.0f;
|
||||||
|
out[3][3] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Matrix4x4_ConcatTranslate( matrix4x4 out, float x, float y, float z )
|
||||||
|
{
|
||||||
|
matrix4x4 base, temp;
|
||||||
|
|
||||||
|
Matrix4x4_Copy( base, out );
|
||||||
|
Matrix4x4_CreateTranslate( temp, x, y, z );
|
||||||
|
Matrix4x4_Concat( out, base, temp );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Matrix4x4_ConcatRotate( matrix4x4 out, float angle, float x, float y, float z )
|
||||||
|
{
|
||||||
|
matrix4x4 base, temp;
|
||||||
|
|
||||||
|
Matrix4x4_Copy( base, out );
|
||||||
|
Matrix4x4_CreateRotate( temp, angle, x, y, z );
|
||||||
|
Matrix4x4_Concat( out, base, temp );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Matrix4x4_ConcatScale( matrix4x4 out, float x )
|
||||||
|
{
|
||||||
|
matrix4x4 base, temp;
|
||||||
|
|
||||||
|
Matrix4x4_Copy( base, out );
|
||||||
|
Matrix4x4_CreateScale( temp, x );
|
||||||
|
Matrix4x4_Concat( out, base, temp );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Matrix4x4_ConcatScale3( matrix4x4 out, float x, float y, float z )
|
||||||
|
{
|
||||||
|
matrix4x4 base, temp;
|
||||||
|
|
||||||
|
Matrix4x4_Copy( base, out );
|
||||||
|
Matrix4x4_CreateScale3( temp, x, y, z );
|
||||||
|
Matrix4x4_Concat( out, base, temp );
|
||||||
|
}
|
||||||
190
ref_gu/gu_rmisc.c
Normal file
190
ref_gu/gu_rmisc.c
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
gl_rmisc.c - renderer misceallaneous
|
||||||
|
Copyright (C) 2010 Uncle Mike
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gu_local.h"
|
||||||
|
#include "shake.h"
|
||||||
|
#include "screenfade.h"
|
||||||
|
#include "cdll_int.h"
|
||||||
|
|
||||||
|
static void R_ParseDetailTextures( const char *filename )
|
||||||
|
{
|
||||||
|
byte *afile;
|
||||||
|
char *pfile;
|
||||||
|
string token, texname;
|
||||||
|
string detail_texname;
|
||||||
|
string detail_path;
|
||||||
|
float xScale, yScale;
|
||||||
|
texture_t *tex;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
afile = gEngfuncs.COM_LoadFile( filename, NULL, false );
|
||||||
|
if( !afile ) return;
|
||||||
|
|
||||||
|
pfile = (char *)afile;
|
||||||
|
|
||||||
|
// format: 'texturename' 'detailtexture' 'xScale' 'yScale'
|
||||||
|
while(( pfile = gEngfuncs.COM_ParseFile( pfile, token )) != NULL )
|
||||||
|
{
|
||||||
|
texname[0] = '\0';
|
||||||
|
detail_texname[0] = '\0';
|
||||||
|
|
||||||
|
// read texname
|
||||||
|
if( token[0] == '{' )
|
||||||
|
{
|
||||||
|
// NOTE: COM_ParseFile handled some symbols seperately
|
||||||
|
// this code will be fix it
|
||||||
|
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
||||||
|
Q_strncat( texname, "{", sizeof( texname ));
|
||||||
|
Q_strncat( texname, token, sizeof( texname ));
|
||||||
|
}
|
||||||
|
else Q_strncpy( texname, token, sizeof( texname ));
|
||||||
|
|
||||||
|
// read detailtexture name
|
||||||
|
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
||||||
|
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
||||||
|
|
||||||
|
// trying the scales or '{'
|
||||||
|
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
||||||
|
|
||||||
|
// read second part of detailtexture name
|
||||||
|
if( token[0] == '{' )
|
||||||
|
{
|
||||||
|
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
||||||
|
pfile = gEngfuncs.COM_ParseFile( pfile, token ); // read scales
|
||||||
|
Q_strncat( detail_texname, token, sizeof( detail_texname ));
|
||||||
|
pfile = gEngfuncs.COM_ParseFile( pfile, token ); // parse scales
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_snprintf( detail_path, sizeof( detail_path ), "gfx/%s", detail_texname );
|
||||||
|
|
||||||
|
// read scales
|
||||||
|
xScale = Q_atof( token );
|
||||||
|
|
||||||
|
pfile = gEngfuncs.COM_ParseFile( pfile, token );
|
||||||
|
yScale = Q_atof( token );
|
||||||
|
|
||||||
|
if( xScale <= 0.0f || yScale <= 0.0f )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// search for existing texture and uploading detail texture
|
||||||
|
for( i = 0; i < WORLDMODEL->numtextures; i++ )
|
||||||
|
{
|
||||||
|
tex = WORLDMODEL->textures[i];
|
||||||
|
|
||||||
|
if( Q_stricmp( tex->name, texname ))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tex->dt_texturenum = GL_LoadTexture( detail_path, NULL, 0, TF_FORCE_COLOR );
|
||||||
|
|
||||||
|
// texture is loaded
|
||||||
|
if( tex->dt_texturenum )
|
||||||
|
{
|
||||||
|
gl_texture_t *glt;
|
||||||
|
|
||||||
|
glt = R_GetTexture( tex->gl_texturenum );
|
||||||
|
glt->xscale = xScale;
|
||||||
|
glt->yscale = yScale;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Mem_Free( afile );
|
||||||
|
}
|
||||||
|
|
||||||
|
void R_NewMap( void )
|
||||||
|
{
|
||||||
|
texture_t *tx;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
R_ClearDecals(); // clear all level decals
|
||||||
|
|
||||||
|
R_StudioResetPlayerModels();
|
||||||
|
|
||||||
|
// upload detailtextures
|
||||||
|
if( CVAR_TO_BOOL( r_detailtextures ))
|
||||||
|
{
|
||||||
|
string mapname, filepath;
|
||||||
|
|
||||||
|
Q_strncpy( mapname, WORLDMODEL->name, sizeof( mapname ));
|
||||||
|
COM_StripExtension( mapname );
|
||||||
|
Q_sprintf( filepath, "%s_detail.txt", mapname );
|
||||||
|
|
||||||
|
R_ParseDetailTextures( filepath );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( gEngfuncs.pfnGetCvarFloat( "v_dark" ))
|
||||||
|
{
|
||||||
|
screenfade_t *sf = gEngfuncs.GetScreenFade();
|
||||||
|
float fadetime = 5.0f;
|
||||||
|
client_textmessage_t *title;
|
||||||
|
|
||||||
|
title = gEngfuncs.pfnTextMessageGet( "GAMETITLE" );
|
||||||
|
if( ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ))
|
||||||
|
fadetime = 1.0f;
|
||||||
|
|
||||||
|
if( title )
|
||||||
|
{
|
||||||
|
// get settings from titles.txt
|
||||||
|
sf->fadeEnd = title->holdtime + title->fadeout;
|
||||||
|
sf->fadeReset = title->fadeout;
|
||||||
|
}
|
||||||
|
else sf->fadeEnd = sf->fadeReset = fadetime;
|
||||||
|
|
||||||
|
sf->fadeFlags = FFADE_IN;
|
||||||
|
sf->fader = sf->fadeg = sf->fadeb = 0;
|
||||||
|
sf->fadealpha = 255;
|
||||||
|
sf->fadeSpeed = (float)sf->fadealpha / sf->fadeReset;
|
||||||
|
sf->fadeReset += gpGlobals->time;
|
||||||
|
sf->fadeEnd += sf->fadeReset;
|
||||||
|
|
||||||
|
gEngfuncs.Cvar_SetValue( "v_dark", 0.0f );
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear out efrags in case the level hasn't been reloaded
|
||||||
|
for( i = 0; i < WORLDMODEL->numleafs; i++ )
|
||||||
|
WORLDMODEL->leafs[i+1].efrags = NULL;
|
||||||
|
|
||||||
|
glState.isFogEnabled = false;
|
||||||
|
tr.skytexturenum = -1;
|
||||||
|
#if 1
|
||||||
|
sceGuDisable( GU_FOG );
|
||||||
|
#else
|
||||||
|
pglDisable( GL_FOG );
|
||||||
|
#endif
|
||||||
|
// clearing texture chains
|
||||||
|
for( i = 0; i < WORLDMODEL->numtextures; i++ )
|
||||||
|
{
|
||||||
|
if( !WORLDMODEL->textures[i] )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tx = WORLDMODEL->textures[i];
|
||||||
|
|
||||||
|
if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == ( tx->height * 2 ))
|
||||||
|
tr.skytexturenum = i;
|
||||||
|
|
||||||
|
tx->texturechain = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SetupSky( MOVEVARS->skyName );
|
||||||
|
|
||||||
|
GL_BuildLightmaps ();
|
||||||
|
#if 0
|
||||||
|
R_GenerateVBO();
|
||||||
|
#endif
|
||||||
|
if( gEngfuncs.drawFuncs->R_NewMap != NULL )
|
||||||
|
gEngfuncs.drawFuncs->R_NewMap();
|
||||||
|
|
||||||
|
}
|
||||||
359
ref_gu/gu_rpart.c
Normal file
359
ref_gu/gu_rpart.c
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
/*
|
||||||
|
gu_rpart.c - particles and tracers
|
||||||
|
Copyright (C) 2010 Uncle Mike
|
||||||
|
Copyright (C) 2020 Sergey Galushko
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gu_local.h"
|
||||||
|
#include "r_efx.h"
|
||||||
|
#include "event_flags.h"
|
||||||
|
#include "entity_types.h"
|
||||||
|
#include "triangleapi.h"
|
||||||
|
#include "pm_local.h"
|
||||||
|
#include "cl_tent.h"
|
||||||
|
#include "studio.h"
|
||||||
|
|
||||||
|
static float gTracerSize[11] = { 1.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
static color24 gTracerColors[] =
|
||||||
|
{
|
||||||
|
{ 255, 255, 255 }, // White
|
||||||
|
{ 255, 0, 0 }, // Red
|
||||||
|
{ 0, 255, 0 }, // Green
|
||||||
|
{ 0, 0, 255 }, // Blue
|
||||||
|
{ 0, 0, 0 }, // Tracer default, filled in from cvars, etc.
|
||||||
|
{ 255, 167, 17 }, // Yellow-orange sparks
|
||||||
|
{ 255, 130, 90 }, // Yellowish streaks (garg)
|
||||||
|
{ 55, 60, 144 }, // Blue egon streak
|
||||||
|
{ 255, 130, 90 }, // More Yellowish streaks (garg)
|
||||||
|
{ 255, 140, 90 }, // More Yellowish streaks (garg)
|
||||||
|
{ 200, 130, 90 }, // More red streaks (garg)
|
||||||
|
{ 255, 120, 70 }, // Darker red streaks (garg)
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
CL_DrawParticles
|
||||||
|
|
||||||
|
update particle color, position, free expired and draw it
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void CL_DrawParticles( double frametime, particle_t *cl_active_particles, float partsize )
|
||||||
|
{
|
||||||
|
particle_t *p;
|
||||||
|
vec3_t right, up;
|
||||||
|
color24 *pColor;
|
||||||
|
int alpha;
|
||||||
|
float size;
|
||||||
|
uint vert_count;
|
||||||
|
uint vert_color;
|
||||||
|
|
||||||
|
if( !cl_active_particles )
|
||||||
|
return; // nothing to draw?
|
||||||
|
|
||||||
|
vert_count = 0;
|
||||||
|
vert_color = 0;
|
||||||
|
|
||||||
|
sceGuEnable( GU_BLEND );
|
||||||
|
sceGuDisable( GU_ALPHA_TEST );
|
||||||
|
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
|
||||||
|
|
||||||
|
sceGuDepthMask( GU_TRUE );
|
||||||
|
|
||||||
|
if( r_fast_particles->value )
|
||||||
|
{
|
||||||
|
gu_vert_fcv_t* const out = ( gu_vert_fcv_t* )extGuBeginPacket( NULL );
|
||||||
|
|
||||||
|
sceGuDisable( GU_TEXTURE_2D );
|
||||||
|
|
||||||
|
for( p = cl_active_particles; p; p = p->next )
|
||||||
|
{
|
||||||
|
if(( p->type != pt_blob ) || ( p->packedColor == 255 ))
|
||||||
|
{
|
||||||
|
p->color = bound( 0, p->color, 255 );
|
||||||
|
pColor = gEngfuncs.CL_GetPaletteColor( p->color );
|
||||||
|
|
||||||
|
alpha = 255 * (p->die - gpGlobals->time) * 16.0f;
|
||||||
|
if( alpha > 255 || p->type == pt_static )
|
||||||
|
alpha = 255;
|
||||||
|
|
||||||
|
out[vert_count].c = GUCOLOR4UB( gEngfuncs.LightToTexGamma( pColor->r ),
|
||||||
|
gEngfuncs.LightToTexGamma( pColor->g ),
|
||||||
|
gEngfuncs.LightToTexGamma( pColor->b ), alpha );
|
||||||
|
out[vert_count].x = p->org[0];
|
||||||
|
out[vert_count].y = p->org[1];
|
||||||
|
out[vert_count].z = p->org[2];
|
||||||
|
vert_count++;
|
||||||
|
|
||||||
|
r_stats.c_particle_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
gEngfuncs.CL_ThinkParticle( frametime, p );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( vert_count )
|
||||||
|
{
|
||||||
|
extGuEndPacket( ( void * )( out + vert_count ) );
|
||||||
|
sceGuDrawArray( GU_POINTS, GU_COLOR_8888 | GU_VERTEX_32BITF, vert_count, 0, out );
|
||||||
|
}
|
||||||
|
|
||||||
|
sceGuEnable( GU_TEXTURE_2D );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL_Bind( XASH_TEXTURE0, tr.particleTexture );
|
||||||
|
sceGuTexFunc( GU_TFX_MODULATE, GU_TCC_RGBA );
|
||||||
|
|
||||||
|
gu_vert_ftcv_t* const out = ( gu_vert_ftcv_t* )extGuBeginPacket( NULL );
|
||||||
|
|
||||||
|
for( p = cl_active_particles; p; p = p->next )
|
||||||
|
{
|
||||||
|
if(( p->type != pt_blob ) || ( p->packedColor == 255 ))
|
||||||
|
{
|
||||||
|
size = partsize; // get initial size of particle
|
||||||
|
|
||||||
|
// scale up to keep particles from disappearing
|
||||||
|
size += (p->org[0] - RI.vieworg[0]) * RI.cull_vforward[0];
|
||||||
|
size += (p->org[1] - RI.vieworg[1]) * RI.cull_vforward[1];
|
||||||
|
size += (p->org[2] - RI.vieworg[2]) * RI.cull_vforward[2];
|
||||||
|
|
||||||
|
if( size < 20.0f ) size = partsize;
|
||||||
|
else size = partsize + size * 0.002f;
|
||||||
|
|
||||||
|
// scale the axes by radius
|
||||||
|
VectorScale( RI.cull_vright, size, right );
|
||||||
|
VectorScale( RI.cull_vup, size, up );
|
||||||
|
|
||||||
|
p->color = bound( 0, p->color, 255 );
|
||||||
|
pColor = gEngfuncs.CL_GetPaletteColor( p->color );
|
||||||
|
|
||||||
|
alpha = 255 * (p->die - gpGlobals->time) * 16.0f;
|
||||||
|
if( alpha > 255 || p->type == pt_static )
|
||||||
|
alpha = 255;
|
||||||
|
vert_color = GUCOLOR4UB( gEngfuncs.LightToTexGamma( pColor->r ),
|
||||||
|
gEngfuncs.LightToTexGamma( pColor->g ),
|
||||||
|
gEngfuncs.LightToTexGamma( pColor->b ), alpha );
|
||||||
|
|
||||||
|
out[vert_count].u = 0.0f;
|
||||||
|
out[vert_count].v = 0.0f;
|
||||||
|
out[vert_count].c = vert_color;
|
||||||
|
out[vert_count].x = p->org[0] + right[0] + up[0];
|
||||||
|
out[vert_count].y = p->org[1] + right[1] + up[1];
|
||||||
|
out[vert_count].z = p->org[2] + right[2] + up[2];
|
||||||
|
vert_count++;
|
||||||
|
out[vert_count].u = 1.0f;
|
||||||
|
out[vert_count].v = 1.0f;
|
||||||
|
out[vert_count].c = vert_color;
|
||||||
|
out[vert_count].x = p->org[0] - right[0] - up[0];
|
||||||
|
out[vert_count].y = p->org[1] - right[1] - up[1];
|
||||||
|
out[vert_count].z = p->org[2] - right[2] - up[2];
|
||||||
|
vert_count++;
|
||||||
|
|
||||||
|
r_stats.c_particle_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
gEngfuncs.CL_ThinkParticle( frametime, p );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( vert_count )
|
||||||
|
{
|
||||||
|
extGuEndPacket(( void * )( out + vert_count ));
|
||||||
|
sceGuDrawArray( GU_SPRITES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF, vert_count, 0, out );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sceGuDepthMask( GU_FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
CL_CullTracer
|
||||||
|
|
||||||
|
check tracer bbox
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
static qboolean CL_CullTracer( particle_t *p, const vec3_t start, const vec3_t end )
|
||||||
|
{
|
||||||
|
vec3_t mins, maxs;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// compute the bounding box
|
||||||
|
for( i = 0; i < 3; i++ )
|
||||||
|
{
|
||||||
|
if( start[i] < end[i] )
|
||||||
|
{
|
||||||
|
mins[i] = start[i];
|
||||||
|
maxs[i] = end[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mins[i] = end[i];
|
||||||
|
maxs[i] = start[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't let it be zero sized
|
||||||
|
if( mins[i] == maxs[i] )
|
||||||
|
{
|
||||||
|
maxs[i] += gTracerSize[p->type] * 2.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check bbox
|
||||||
|
return R_CullBox( mins, maxs );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
CL_DrawTracers
|
||||||
|
|
||||||
|
update tracer color, position, free expired and draw it
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void CL_DrawTracers( double frametime, particle_t *cl_active_tracers )
|
||||||
|
{
|
||||||
|
float scale, atten, gravity;
|
||||||
|
vec3_t screenLast, screen;
|
||||||
|
vec3_t start, end, delta;
|
||||||
|
particle_t *p;
|
||||||
|
|
||||||
|
// update tracer color if this is changed
|
||||||
|
if( FBitSet( tracerred->flags|tracergreen->flags|tracerblue->flags|traceralpha->flags, FCVAR_CHANGED ))
|
||||||
|
{
|
||||||
|
color24 *customColors = &gTracerColors[4];
|
||||||
|
customColors->r = (byte)(tracerred->value * traceralpha->value * 255);
|
||||||
|
customColors->g = (byte)(tracergreen->value * traceralpha->value * 255);
|
||||||
|
customColors->b = (byte)(tracerblue->value * traceralpha->value * 255);
|
||||||
|
ClearBits( tracerred->flags, FCVAR_CHANGED );
|
||||||
|
ClearBits( tracergreen->flags, FCVAR_CHANGED );
|
||||||
|
ClearBits( tracerblue->flags, FCVAR_CHANGED );
|
||||||
|
ClearBits( traceralpha->flags, FCVAR_CHANGED );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !cl_active_tracers )
|
||||||
|
return; // nothing to draw?
|
||||||
|
|
||||||
|
sceGuEnable( GU_BLEND );
|
||||||
|
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_FIX, 0, GUBLEND1 );
|
||||||
|
sceGuDisable( GU_ALPHA_TEST );
|
||||||
|
sceGuDepthMask( GU_TRUE );
|
||||||
|
sceGuDisable( GU_TEXTURE_2D );
|
||||||
|
|
||||||
|
gravity = frametime * MOVEVARS->gravity;
|
||||||
|
scale = 1.0 - (frametime * 0.9);
|
||||||
|
if( scale < 0.0f ) scale = 0.0f;
|
||||||
|
|
||||||
|
for( p = cl_active_tracers; p; p = p->next )
|
||||||
|
{
|
||||||
|
atten = (p->die - gpGlobals->time);
|
||||||
|
if( atten > 0.1f ) atten = 0.1f;
|
||||||
|
|
||||||
|
VectorScale( p->vel, ( p->ramp * atten ), delta );
|
||||||
|
VectorAdd( p->org, delta, end );
|
||||||
|
VectorCopy( p->org, start );
|
||||||
|
|
||||||
|
if( !CL_CullTracer( p, start, end ))
|
||||||
|
{
|
||||||
|
vec3_t verts[4], tmp2;
|
||||||
|
vec3_t tmp, normal;
|
||||||
|
color24 *pColor;
|
||||||
|
|
||||||
|
// Transform point into screen space
|
||||||
|
TriWorldToScreen( start, screen );
|
||||||
|
TriWorldToScreen( end, screenLast );
|
||||||
|
|
||||||
|
// build world-space normal to screen-space direction vector
|
||||||
|
VectorSubtract( screen, screenLast, tmp );
|
||||||
|
|
||||||
|
// we don't need Z, we're in screen space
|
||||||
|
tmp[2] = 0;
|
||||||
|
VectorNormalize( tmp );
|
||||||
|
|
||||||
|
// build point along noraml line (normal is -y, x)
|
||||||
|
VectorScale( RI.cull_vup, tmp[0] * gTracerSize[p->type], normal );
|
||||||
|
VectorScale( RI.cull_vright, -tmp[1] * gTracerSize[p->type], tmp2 );
|
||||||
|
VectorSubtract( normal, tmp2, normal );
|
||||||
|
|
||||||
|
// compute four vertexes
|
||||||
|
VectorSubtract( start, normal, verts[0] );
|
||||||
|
VectorAdd( start, normal, verts[1] );
|
||||||
|
VectorAdd( verts[0], delta, verts[2] );
|
||||||
|
VectorAdd( verts[1], delta, verts[3] );
|
||||||
|
|
||||||
|
if( p->color > sizeof( gTracerColors ) / sizeof( color24 ) )
|
||||||
|
{
|
||||||
|
gEngfuncs.Con_Printf( S_ERROR "UserTracer with color > %d\n", sizeof( gTracerColors ) / sizeof( color24 ));
|
||||||
|
p->color = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pColor = &gTracerColors[p->color];
|
||||||
|
sceGuColor( GUCOLOR4UB( pColor->r, pColor->g, pColor->b, p->packedColor ));
|
||||||
|
|
||||||
|
gu_vert_fv_t* const out = ( gu_vert_fv_t* )sceGuGetMemory( sizeof( gu_vert_fv_t ) * 4 );
|
||||||
|
out[0].x = verts[2][0];
|
||||||
|
out[0].y = verts[2][1];
|
||||||
|
out[0].z = verts[2][2];
|
||||||
|
out[1].x = verts[3][0];
|
||||||
|
out[1].y = verts[3][1];
|
||||||
|
out[1].z = verts[3][2];
|
||||||
|
out[2].x = verts[1][0];
|
||||||
|
out[2].y = verts[1][1];
|
||||||
|
out[2].z = verts[1][2];
|
||||||
|
out[3].x = verts[0][0];
|
||||||
|
out[3].y = verts[0][1];
|
||||||
|
out[3].z = verts[0][2];
|
||||||
|
sceGuDrawArray( GU_TRIANGLE_FAN, GU_VERTEX_32BITF, 4, 0, out );
|
||||||
|
}
|
||||||
|
|
||||||
|
// evaluate position
|
||||||
|
VectorMA( p->org, frametime, p->vel, p->org );
|
||||||
|
|
||||||
|
if( p->type == pt_grav )
|
||||||
|
{
|
||||||
|
p->vel[0] *= scale;
|
||||||
|
p->vel[1] *= scale;
|
||||||
|
p->vel[2] -= gravity;
|
||||||
|
|
||||||
|
p->packedColor = 255 * (p->die - gpGlobals->time) * 2;
|
||||||
|
if( p->packedColor > 255 ) p->packedColor = 255;
|
||||||
|
}
|
||||||
|
else if( p->type == pt_slowgrav )
|
||||||
|
{
|
||||||
|
p->vel[2] = gravity * 0.05f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sceGuEnable( GU_TEXTURE_2D );
|
||||||
|
sceGuDepthMask( GU_FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
CL_DrawParticlesExternal
|
||||||
|
|
||||||
|
allow to draw effects from custom renderer
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
void CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, float frametime )
|
||||||
|
{
|
||||||
|
ref_instance_t oldRI = RI;
|
||||||
|
|
||||||
|
memcpy( &oldRI, &RI, sizeof( ref_instance_t ));
|
||||||
|
R_SetupRefParams( rvp );
|
||||||
|
R_SetupFrustum();
|
||||||
|
R_SetupGL( false ); // don't touch GL-states
|
||||||
|
tr.frametime = frametime;
|
||||||
|
|
||||||
|
gEngfuncs.CL_DrawEFX( frametime, trans_pass );
|
||||||
|
|
||||||
|
// restore internal state
|
||||||
|
memcpy( &RI, &oldRI, sizeof( ref_instance_t ));
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user