mirror of
https://github.com/FWGS/xash3d-fwgs.git
synced 2026-08-06 20:30:36 +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 |
@@ -1,27 +0,0 @@
|
||||
image: alpine/latest
|
||||
packages:
|
||||
- build-base
|
||||
- sdl2-dev
|
||||
- freetype-dev
|
||||
- fontconfig-dev
|
||||
- opus-dev
|
||||
sources:
|
||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||
tasks:
|
||||
- client: |
|
||||
cd xash3d-fwgs
|
||||
./waf configure -8 --enable-tests --enable-engine-tests build install --destdir=bin
|
||||
- server: |
|
||||
cd xash3d-fwgs
|
||||
./waf configure --reconfigure --dedicated build install --destdir=bin
|
||||
- run-tests: |
|
||||
cd xash3d-fwgs/bin
|
||||
export SDL_VIDEODRIVER=wayland
|
||||
./xash3d -runtests
|
||||
./xash -runtests
|
||||
rm -rf valve/gameinfo.txt test_*
|
||||
- package: |
|
||||
cd xash3d-fwgs/bin
|
||||
tar -cjvf xash3d-fwgs-alpine-amd64.tar.bz2 *
|
||||
artifacts:
|
||||
- xash3d-fwgs/bin/xash3d-fwgs-alpine-amd64.tar.bz2
|
||||
@@ -1,30 +0,0 @@
|
||||
image: debian/sid
|
||||
arch: amd64
|
||||
packages:
|
||||
- build-essential
|
||||
- python-is-python3
|
||||
- libsdl2-dev
|
||||
- libfreetype-dev
|
||||
- libfontconfig-dev
|
||||
- libopus-dev
|
||||
sources:
|
||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||
tasks:
|
||||
- client: |
|
||||
cd xash3d-fwgs
|
||||
./waf configure -8 --enable-tests --enable-engine-tests build install --destdir=bin
|
||||
- server: |
|
||||
cd xash3d-fwgs
|
||||
./waf configure --reconfigure --dedicated build install --destdir=bin
|
||||
- run-tests: |
|
||||
cd xash3d-fwgs/bin
|
||||
export SDL_VIDEODRIVER=wayland
|
||||
./xash3d -runtests
|
||||
./xash -runtests
|
||||
rm -rf valve/gameinfo.txt test_*
|
||||
- package: |
|
||||
cd xash3d-fwgs/bin
|
||||
tar -cjvf xash3d-fwgs-debian-arm64.tar.bz2 *
|
||||
artifacts:
|
||||
- xash3d-fwgs/bin/xash3d-fwgs-debian-arm64.tar.bz2
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
image: debian/sid
|
||||
packages:
|
||||
- build-essential
|
||||
- python-is-python3
|
||||
- libsdl2-dev
|
||||
- libfreetype-dev
|
||||
- libfontconfig-dev
|
||||
- libopus-dev
|
||||
sources:
|
||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||
tasks:
|
||||
- client: |
|
||||
cd xash3d-fwgs
|
||||
./waf configure -8 --enable-tests --enable-engine-tests build install --destdir=bin
|
||||
- server: |
|
||||
cd xash3d-fwgs
|
||||
./waf configure --reconfigure --dedicated build install --destdir=bin
|
||||
- run-tests: |
|
||||
cd xash3d-fwgs/bin
|
||||
export SDL_VIDEODRIVER=wayland
|
||||
./xash3d -runtests
|
||||
./xash -runtests
|
||||
rm -rf valve/gameinfo.txt test_*
|
||||
- package: |
|
||||
cd xash3d-fwgs/bin
|
||||
tar -cjvf xash3d-fwgs-debian-amd64.tar.bz2 *
|
||||
artifacts:
|
||||
- xash3d-fwgs/bin/xash3d-fwgs-debian-amd64.tar.bz2
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
image: freebsd/latest
|
||||
packages:
|
||||
- lang/python
|
||||
- devel/pkgconf
|
||||
- devel/sdl20
|
||||
- print/freetype2
|
||||
- x11-fonts/fontconfig
|
||||
- audio/opus
|
||||
sources:
|
||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||
tasks:
|
||||
- client: |
|
||||
cd xash3d-fwgs
|
||||
./waf configure --enable-tests --enable-engine-tests build install --destdir=bin
|
||||
- server: |
|
||||
cd xash3d-fwgs
|
||||
./waf configure --reconfigure --dedicated build install --destdir=bin
|
||||
- run-tests: |
|
||||
cd xash3d-fwgs/bin
|
||||
export SDL_VIDEODRIVER=wayland
|
||||
./xash3d -runtests
|
||||
./xash -runtests
|
||||
rm -rf valve/gameinfo.txt test_*
|
||||
- package: |
|
||||
cd xash3d-fwgs/bin
|
||||
tar -cjvf xash3d-fwgs-freebsd-amd64.tar.bz2 *
|
||||
artifacts:
|
||||
- xash3d-fwgs/bin/xash3d-fwgs-freebsd-amd64.tar.bz2
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
image: netbsd/latest
|
||||
packages:
|
||||
- python311
|
||||
- SDL2
|
||||
- freetype2
|
||||
- fontconfig
|
||||
- libopus
|
||||
- pkgconf
|
||||
sources:
|
||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||
tasks:
|
||||
- client: |
|
||||
cd xash3d-fwgs
|
||||
python3.11 waf configure --enable-tests --enable-engine-tests build install --destdir=bin
|
||||
- server: |
|
||||
cd xash3d-fwgs
|
||||
python3.11 waf configure --reconfigure --dedicated build install --destdir=bin
|
||||
- run-tests: |
|
||||
cd xash3d-fwgs/bin
|
||||
export SDL_VIDEODRIVER=wayland
|
||||
./xash3d -runtests
|
||||
./xash -runtests
|
||||
rm -rf valve/gameinfo.txt test_*
|
||||
- package: |
|
||||
cd xash3d-fwgs/bin
|
||||
tar -cjvf xash3d-fwgs-netbsd-amd64.tar.bz2 *
|
||||
artifacts:
|
||||
- xash3d-fwgs/bin/xash3d-fwgs-netbsd-amd64.tar.bz2
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
image: openbsd/latest
|
||||
packages:
|
||||
- python3
|
||||
- sdl2
|
||||
- opus
|
||||
sources:
|
||||
- https://git.sr.ht/~a1batross/xash3d-fwgs
|
||||
tasks:
|
||||
- client: |
|
||||
cd xash3d-fwgs
|
||||
python3 waf configure --enable-tests --enable-engine-tests build install --destdir=bin
|
||||
- server: |
|
||||
cd xash3d-fwgs
|
||||
python3 waf configure --reconfigure --dedicated build install --destdir=bin
|
||||
- run-tests: |
|
||||
cd xash3d-fwgs/bin
|
||||
export SDL_VIDEODRIVER=wayland
|
||||
./xash3d -runtests
|
||||
./xash -runtests
|
||||
rm -rf valve/gameinfo.txt test_*
|
||||
- package: |
|
||||
cd xash3d-fwgs/bin
|
||||
tar -cjvf xash3d-fwgs-openbsd-amd64.tar.bz2 *
|
||||
artifacts:
|
||||
- xash3d-fwgs/bin/xash3d-fwgs-openbsd-amd64.tar.bz2
|
||||
|
||||
23
README.md
23
README.md
@@ -1,5 +1,5 @@
|
||||
# Xash3D FWGS Engine <img align="right" width="128" height="128" src="https://github.com/FWGS/xash3d-fwgs/raw/master/game_launch/icon-xash-material.png" alt="Xash3D FWGS icon" />
|
||||
[](https://builds.sr.ht/~a1batross/xash3d-fwgs?) [](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [](http://fwgsdiscord.mentality.rip/) \
|
||||
[](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [](http://fwgsdiscord.mentality.rip/) \
|
||||
[](https://github.com/FWGS/xash3d-fwgs/releases/latest) [](https://github.com/FWGS/xash3d-fwgs/releases/tag/continuous)
|
||||
|
||||
Xash3D FWGS is a game engine, aimed to provide compatibility with Half-Life Engine and extend it, as well as to give game developers well known workflow.
|
||||
@@ -73,6 +73,10 @@ This repository contains our fork of HLSDK and restored source code for some of
|
||||
* Clone this repostory:
|
||||
`$ git clone --recursive https://github.com/FWGS/xash3d-fwgs`
|
||||
|
||||
#### PSP
|
||||
* Build pspsdk(GCC 9.3) from https://github.com/pspdev
|
||||
* Clone this repository: `git clone --recursive https://github.com/Crow-bar/xash3d-fwgs`.
|
||||
|
||||
### Building
|
||||
#### Windows (Visual Studio)
|
||||
0) Open command line
|
||||
@@ -90,3 +94,20 @@ If compiling 32-bit on amd64, you may need to supply `export PKG_CONFIG_PATH=/us
|
||||
(You need to pass `-8` to compile 64-bit engine on 64-bit x86 processor)
|
||||
2) Compile: `./waf build`
|
||||
3) Install(optional): `./waf install --destdir=/path/to/any/output/directory`
|
||||
|
||||
#### PSP
|
||||
0) Navigate to `xash3d-fwgs` directory.
|
||||
1) Examine which build options are available: `./waf --help`
|
||||
2) Configure build:
|
||||
Normal: `./waf configure -T fast --psp=prx,660,HW --prefix=/path/to/any/output/directory`
|
||||
Profiling: `./waf configure -T debug --psp=elf,660,HW --enable-profiling --prefix=/path/to/any/output/directory`
|
||||
3) Compile: `./waf build`
|
||||
4) Install(optional): `./waf install`
|
||||
|
||||
|
||||
## Running
|
||||
0) Copy libraries and main executable somewhere, if you're skipped installation stage.
|
||||
1) Copy game files to same directory
|
||||
2) Run `xash3d.exe`/`xash3d.sh`/`xash3d` depending on which platform you're using.
|
||||
|
||||
For additional info, run Xash3D with `-help` command line key.
|
||||
|
||||
@@ -20,16 +20,19 @@ GNU General Public License for more details.
|
||||
#define VIDEO_SDL 1
|
||||
#define VIDEO_FBDEV 3
|
||||
#define VIDEO_DOS 4
|
||||
#define VIDEO_PSP 5
|
||||
|
||||
// audio backends (XASH_SOUND)
|
||||
#define SOUND_NULL 0
|
||||
#define SOUND_SDL 1
|
||||
#define SOUND_ALSA 3
|
||||
#define SOUND_PSP 4
|
||||
|
||||
// input (XASH_INPUT)
|
||||
#define INPUT_NULL 0
|
||||
#define INPUT_SDL 1
|
||||
#define INPUT_EVDEV 3
|
||||
#define INPUT_PSP 4
|
||||
|
||||
// timer (XASH_TIMER)
|
||||
#define TIMER_NULL 0 // not used
|
||||
@@ -37,17 +40,20 @@ GNU General Public License for more details.
|
||||
#define TIMER_POSIX 2
|
||||
#define TIMER_WIN32 3
|
||||
#define TIMER_DOS 4
|
||||
#define TIMER_PSP 5
|
||||
|
||||
// messageboxes (XASH_MESSAGEBOX)
|
||||
#define MSGBOX_STDERR 0
|
||||
#define MSGBOX_SDL 1
|
||||
#define MSGBOX_WIN32 3
|
||||
#define MSGBOX_NSWITCH 4
|
||||
#define MSGBOX_PSP 5
|
||||
|
||||
// library loading (XASH_LIB)
|
||||
#define LIB_NULL 0
|
||||
#define LIB_POSIX 1
|
||||
#define LIB_WIN32 2
|
||||
#define LIB_NULL 0
|
||||
#define LIB_POSIX 1
|
||||
#define LIB_WIN32 2
|
||||
#define LIB_STATIC 3
|
||||
#define LIB_PSP 4
|
||||
|
||||
#endif /* BACKENDS_H */
|
||||
|
||||
@@ -23,6 +23,7 @@ NOTE: number at end of pixelformat name it's a total bitscount e.g. PF_RGB_24 ==
|
||||
|| type == PF_BC7_UNORM \
|
||||
|| type == PF_BC7_SRGB \
|
||||
|| type == PF_KTX2_RAW )
|
||||
#define ImageIND( type ) (type == PF_INDEXED_32 || type == PF_INDEXED_24)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -33,6 +34,10 @@ typedef enum
|
||||
PF_BGRA_32, // big endian RGBA (MacOS)
|
||||
PF_RGB_24, // uncompressed dds or another 24-bit image
|
||||
PF_BGR_24, // big-endian RGB (MacOS)
|
||||
PF_RGB_332, // 8-bit R3 G3 B2
|
||||
PF_RGB_5650, // 16-bit R5 G6 B5
|
||||
PF_RGBA_5551, // 16-bit R5 G5 B5 A1
|
||||
PF_RGBA_4444, // 16-bit R4 G4 B4 A4
|
||||
PF_LUMINANCE,
|
||||
PF_DXT1, // s3tc DXT1/BC1 format
|
||||
PF_DXT3, // s3tc DXT3/BC2 format
|
||||
|
||||
@@ -127,6 +127,21 @@ typedef struct
|
||||
int flags; // sky or slime, no lightmap or 256 subdivision
|
||||
} mtexinfo_t;
|
||||
|
||||
#if XASH_PSP
|
||||
typedef struct
|
||||
{
|
||||
float uv[2];
|
||||
float xyz[3];
|
||||
}gu_vert_t;
|
||||
typedef struct glpoly_s
|
||||
{
|
||||
struct glpoly_s *next;
|
||||
struct glpoly_s *chain;
|
||||
int numverts;
|
||||
int flags; // for SURF_UNDERWATER
|
||||
gu_vert_t verts[1]; // variable sized (xyz s1t1 + lm(xyz s2t2))
|
||||
} glpoly_t;
|
||||
#else
|
||||
typedef struct glpoly_s
|
||||
{
|
||||
struct glpoly_s *next;
|
||||
@@ -135,7 +150,7 @@ typedef struct glpoly_s
|
||||
int flags; // for SURF_UNDERWATER
|
||||
float verts[4][VERTEXSIZE]; // variable sized (xyz s1t1 s2t2)
|
||||
} glpoly_t;
|
||||
|
||||
#endif
|
||||
typedef struct mnode_s
|
||||
{
|
||||
// common with leaf
|
||||
|
||||
@@ -77,6 +77,30 @@ SETUP BACKENDS DEFINITIONS
|
||||
|
||||
// usually only 10-20 fds availiable
|
||||
#define XASH_REDUCE_FD
|
||||
#elif XASH_PSP
|
||||
#ifndef XASH_VIDEO
|
||||
#define XASH_VIDEO VIDEO_PSP
|
||||
#endif
|
||||
|
||||
#ifndef XASH_TIMER
|
||||
#define XASH_TIMER TIMER_PSP
|
||||
#endif
|
||||
|
||||
#ifndef XASH_INPUT
|
||||
#define XASH_INPUT INPUT_PSP
|
||||
#endif
|
||||
|
||||
#ifndef XASH_SOUND
|
||||
#define XASH_SOUND SOUND_PSP
|
||||
#endif // XASH_SOUND
|
||||
|
||||
#ifndef XASH_MESSAGEBOX
|
||||
#define XASH_MESSAGEBOX MSGBOX_PSP
|
||||
#endif // XASH_MESSAGEBOX
|
||||
|
||||
#define XASH_REDUCE_FD
|
||||
#define XASH_NO_TOUCH
|
||||
#define XASH_NO_ZIP
|
||||
#endif
|
||||
|
||||
#endif // XASH_DEDICATED
|
||||
@@ -105,7 +129,7 @@ SETUP BACKENDS DEFINITIONS
|
||||
#endif // !XASH_WIN32
|
||||
#endif
|
||||
|
||||
#ifdef XASH_STATIC_LIBS
|
||||
#if defined(XASH_STATIC_LIBS) && !XASH_PSP
|
||||
#define XASH_LIB LIB_STATIC
|
||||
#define XASH_INTERNAL_GAMELIBS
|
||||
#define XASH_ALLOW_SAVERESTORE_OFFSETS
|
||||
@@ -113,6 +137,8 @@ SETUP BACKENDS DEFINITIONS
|
||||
#define XASH_LIB LIB_WIN32
|
||||
#elif XASH_POSIX
|
||||
#define XASH_LIB LIB_POSIX
|
||||
#elif XASH_PSP
|
||||
#define XASH_LIB LIB_PSP
|
||||
#endif
|
||||
|
||||
//
|
||||
@@ -193,4 +219,20 @@ Default build-depended cvar and constant values
|
||||
#define DEFAULT_MAX_EDICTS 1200 // was 900 before HL25
|
||||
#endif // DEFAULT_MAX_EDICTS
|
||||
|
||||
#ifndef DEFAULT_ACCELERATED_RENDERER
|
||||
#ifdef XASH_PSP
|
||||
#define DEFAULT_ACCELERATED_RENDERER "gu"
|
||||
#else
|
||||
#if XASH_MOBILE_PLATFORM
|
||||
#define DEFAULT_ACCELERATED_RENDERER "gles1"
|
||||
#else // !XASH_MOBILE_PLATFORM
|
||||
#define DEFAULT_ACCELERATED_RENDERER "gl"
|
||||
#endif // !XASH_MOBILE_PLATFORM
|
||||
#endif
|
||||
#endif // DEFAULT_ACCELERATED_RENDERER
|
||||
|
||||
#ifndef DEFAULT_SOFTWARE_RENDERER
|
||||
#define DEFAULT_SOFTWARE_RENDERER "soft" // mittorn's ref_soft
|
||||
#endif // DEFAULT_SOFTWARE_RENDERER
|
||||
|
||||
#endif // DEFAULTS_H
|
||||
|
||||
@@ -24,7 +24,9 @@ GNU General Public License for more details.
|
||||
#include <sys/syslimits.h>
|
||||
#define OS_LIB_EXT "dylib"
|
||||
#define OPEN_COMMAND "open"
|
||||
#else
|
||||
#elif XASH_PSP
|
||||
#define OS_LIB_EXT "prx"
|
||||
#else
|
||||
#define OS_LIB_EXT "so"
|
||||
#define OPEN_COMMAND "xdg-open"
|
||||
#endif
|
||||
@@ -35,6 +37,7 @@ GNU General Public License for more details.
|
||||
#define __cdecl
|
||||
#define __stdcall
|
||||
#define _inline static inline
|
||||
#define FORCEINLINE inline __attribute__((always_inline))
|
||||
|
||||
#if XASH_POSIX
|
||||
#include <unistd.h>
|
||||
@@ -54,6 +57,16 @@ GNU General Public License for more details.
|
||||
#define _mkdir( x ) mkdir( x, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH )
|
||||
#endif
|
||||
|
||||
#if XASH_PSP
|
||||
#include <unistd.h>
|
||||
#include <pspiofilemgr.h>
|
||||
|
||||
#define O_BINARY 0
|
||||
#define O_TEXT 0
|
||||
|
||||
#define _mkdir( x ) sceIoMkdir( x, FIO_S_IRWXU | FIO_S_IRWXG | FIO_S_IROTH | FIO_S_IXOTH )
|
||||
#endif
|
||||
|
||||
typedef void* HANDLE;
|
||||
typedef void* HINSTANCE;
|
||||
|
||||
@@ -62,6 +75,13 @@ GNU General Public License for more details.
|
||||
int x, y;
|
||||
} POINT;
|
||||
#else // WIN32
|
||||
#ifdef __MINGW32__
|
||||
#define _inline static inline
|
||||
#define FORCEINLINE inline __attribute__((always_inline))
|
||||
#else
|
||||
#define FORCEINLINE __forceinline
|
||||
#endif
|
||||
|
||||
#define open _open
|
||||
#define read _read
|
||||
#define alloca _alloca
|
||||
|
||||
@@ -101,8 +101,13 @@ typedef enum
|
||||
TF_TEXTURE_3D = (1<<20), // this is GL_TEXTURE_3D
|
||||
TF_ATLAS_PAGE = (1<<21), // bit who indicate lightmap page or deluxemap page
|
||||
TF_ALPHACONTRAST = (1<<22), // special texture mode for A2C
|
||||
#if XASH_PSP
|
||||
TF_IMG_SWIZZLED = (1<<23),
|
||||
TF_IMG_INVRAM = (1<<24),
|
||||
#else
|
||||
// reserved
|
||||
// reserved
|
||||
#endif
|
||||
TF_IMG_UPLOADED = (1<<25), // this is set for first time when called glTexImage, otherwise it will be call glTexSubImage
|
||||
TF_ARB_FLOAT = (1<<26), // float textures
|
||||
TF_NOCOMPARE = (1<<27), // disable comparing for depth textures
|
||||
|
||||
@@ -21,12 +21,22 @@ typedef int sound_t;
|
||||
typedef float vec_t;
|
||||
typedef vec_t vec2_t[2];
|
||||
typedef vec_t vec3_t[3];
|
||||
#if XASH_PSP
|
||||
typedef vec_t vec4_t[4] __attribute__( ( aligned( 16 ) ) );
|
||||
typedef vec_t quat_t[4] __attribute__( ( aligned( 16 ) ) );
|
||||
#else
|
||||
typedef vec_t vec4_t[4];
|
||||
typedef vec_t quat_t[4];
|
||||
#endif
|
||||
typedef byte rgba_t[4]; // unsigned byte colorpack
|
||||
typedef byte rgb_t[3]; // unsigned byte colorpack
|
||||
#if XASH_PSP
|
||||
typedef vec_t matrix3x4[3][4] __attribute__( ( aligned( 16 ) ) );
|
||||
typedef vec_t matrix4x4[4][4] __attribute__( ( aligned( 16 ) ) );
|
||||
#else
|
||||
typedef vec_t matrix3x4[3][4];
|
||||
typedef vec_t matrix4x4[4][4];
|
||||
#endif
|
||||
|
||||
#if XASH_64BIT
|
||||
typedef uint32_t poolhandle_t;
|
||||
@@ -86,8 +96,6 @@ typedef uint64_t longtime_t;
|
||||
#define NORETURN __attribute__((noreturn))
|
||||
#define NONNULL __attribute__((nonnull))
|
||||
#define ALLOC_CHECK(x) __attribute__((alloc_size(x)))
|
||||
#define FORCEINLINE inline __attribute__((always_inline))
|
||||
#define NOINLINE __attribute__((noinline))
|
||||
#elif defined(_MSC_VER)
|
||||
#define EXPORT __declspec( dllexport )
|
||||
#define GAME_EXPORT
|
||||
@@ -95,8 +103,6 @@ typedef uint64_t longtime_t;
|
||||
#define NORETURN
|
||||
#define NONNULL
|
||||
#define ALLOC_CHECK(x)
|
||||
#define FORCEINLINE __forceinline
|
||||
#define NOINLINE __declspec( noinline )
|
||||
#else
|
||||
#define EXPORT
|
||||
#define GAME_EXPORT
|
||||
@@ -104,8 +110,6 @@ typedef uint64_t longtime_t;
|
||||
#define NORETURN
|
||||
#define NONNULL
|
||||
#define ALLOC_CHECK(x)
|
||||
#define FORCEINLINE
|
||||
#define NOINLINE
|
||||
#endif
|
||||
|
||||
#if ( __GNUC__ >= 3 )
|
||||
@@ -200,6 +204,9 @@ typedef void *(*pfnCreateInterface_t)( const char *, int * );
|
||||
// config strings are a general means of communication from
|
||||
// the server to all connected clients.
|
||||
// each config string can be at most CS_SIZE characters.
|
||||
#if XASH_PSP
|
||||
#define MAX_QPATH 48
|
||||
#else
|
||||
#if XASH_LOW_MEMORY == 0
|
||||
#define MAX_QPATH 64 // max length of a game pathname
|
||||
#elif XASH_LOW_MEMORY == 2
|
||||
@@ -207,6 +214,7 @@ typedef void *(*pfnCreateInterface_t)( const char *, int * );
|
||||
#elif XASH_LOW_MEMORY == 1
|
||||
#define MAX_QPATH 48
|
||||
#endif
|
||||
#endif
|
||||
#define MAX_OSPATH 260 // max length of a filesystem pathname
|
||||
#define CS_SIZE 64 // size of one config string
|
||||
#define CS_TIME 16 // size of time string
|
||||
|
||||
@@ -26,18 +26,6 @@ GNU General Public License for more details.
|
||||
|
||||
// #define STUDIO_INTERPOLATION_FIX
|
||||
|
||||
/*
|
||||
==================
|
||||
CL_IsPlayerIndex
|
||||
|
||||
detect player entity
|
||||
==================
|
||||
*/
|
||||
qboolean CL_IsPlayerIndex( int idx )
|
||||
{
|
||||
return ( idx >= 1 && idx <= cl.maxclients );
|
||||
}
|
||||
|
||||
/*
|
||||
=========================================================================
|
||||
|
||||
|
||||
@@ -96,41 +96,6 @@ static dllfunc_t cdll_new_exports[] = // allowed only in SDK 2.3 and higher
|
||||
|
||||
static void pfnSPR_DrawHoles( int frame, int x, int y, const wrect_t *prc );
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_GetEntityByIndex
|
||||
|
||||
Render callback for studio models
|
||||
====================
|
||||
*/
|
||||
cl_entity_t *CL_GetEntityByIndex( int index )
|
||||
{
|
||||
if( !clgame.entities ) // not in game yet
|
||||
return NULL;
|
||||
|
||||
if( index < 0 || index >= clgame.maxEntities )
|
||||
return NULL;
|
||||
|
||||
if( index == 0 )
|
||||
return clgame.entities;
|
||||
|
||||
return CL_EDICT_NUM( index );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
CL_ModelHandle
|
||||
|
||||
get model handle by index
|
||||
================
|
||||
*/
|
||||
model_t *CL_ModelHandle( int modelindex )
|
||||
{
|
||||
if( modelindex < 0 || modelindex >= MAX_MODELS )
|
||||
return NULL;
|
||||
return cl.models[modelindex];
|
||||
}
|
||||
|
||||
/*
|
||||
====================
|
||||
CL_IsThirdPerson
|
||||
@@ -357,23 +322,20 @@ void SPR_AdjustSize( float *x, float *y, float *w, float *h )
|
||||
*h *= yscale;
|
||||
}
|
||||
|
||||
static void SPR_AdjustTexCoords( int texnum, float width, float height, float *s1, float *t1, float *s2, float *t2 )
|
||||
void SPR_AdjustTexCoords( float width, float height, float *s1, float *t1, float *s2, float *t2 )
|
||||
{
|
||||
if( REF_GET_PARM( PARM_TEX_FILTERING, texnum ))
|
||||
if( refState.width != clgame.scrInfo.iWidth )
|
||||
{
|
||||
if( refState.width != clgame.scrInfo.iWidth )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*s1 += 0.5f;
|
||||
*s2 -= 0.5f;
|
||||
}
|
||||
// align to texel if scaling
|
||||
*s1 += 0.5f;
|
||||
*s2 -= 0.5f;
|
||||
}
|
||||
|
||||
if( refState.height != clgame.scrInfo.iHeight )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*t1 += 0.5f;
|
||||
*t2 -= 0.5f;
|
||||
}
|
||||
if( refState.height != clgame.scrInfo.iHeight )
|
||||
{
|
||||
// align to texel if scaling
|
||||
*t1 += 0.5f;
|
||||
*t2 -= 0.5f;
|
||||
}
|
||||
|
||||
*s1 /= width;
|
||||
@@ -405,8 +367,6 @@ static void SPR_DrawGeneric( int frame, float x, float y, float width, float hei
|
||||
height = h;
|
||||
}
|
||||
|
||||
texnum = ref.dllFuncs.R_GetSpriteTexture( clgame.ds.pSprite, frame );
|
||||
|
||||
if( prc )
|
||||
{
|
||||
wrect_t rc = *prc;
|
||||
@@ -423,7 +383,7 @@ static void SPR_DrawGeneric( int frame, float x, float y, float width, float hei
|
||||
t2 = rc.bottom;
|
||||
|
||||
// calc user-defined rectangle
|
||||
SPR_AdjustTexCoords( texnum, width, height, &s1, &t1, &s2, &t2 );
|
||||
SPR_AdjustTexCoords( width, height, &s1, &t1, &s2, &t2 );
|
||||
width = rc.right - rc.left;
|
||||
height = rc.bottom - rc.top;
|
||||
}
|
||||
@@ -439,6 +399,7 @@ static void SPR_DrawGeneric( int frame, float x, float y, float width, float hei
|
||||
|
||||
// scale for screen sizes
|
||||
SPR_AdjustSize( &x, &y, &width, &height );
|
||||
texnum = ref.dllFuncs.R_GetSpriteTexture( clgame.ds.pSprite, frame );
|
||||
ref.dllFuncs.Color4ub( clgame.ds.spriteColor[0], clgame.ds.spriteColor[1], clgame.ds.spriteColor[2], clgame.ds.spriteColor[3] );
|
||||
ref.dllFuncs.R_DrawStretchPic( x, y, width, height, s1, t1, s2, t2, texnum );
|
||||
}
|
||||
@@ -943,7 +904,7 @@ void CL_DrawCrosshair( void )
|
||||
VectorAdd( refState.viewangles, cl.crosshairangle, angles );
|
||||
AngleVectors( angles, forward, NULL, NULL );
|
||||
VectorAdd( refState.vieworg, forward, point );
|
||||
ref.dllFuncs.WorldToScreen( point, screen );
|
||||
gTriApi.WorldToScreen( point, screen );
|
||||
|
||||
x += ( clgame.viewport[2] >> 1 ) * screen[0] + 0.5f;
|
||||
y += ( clgame.viewport[3] >> 1 ) * screen[1] + 0.5f;
|
||||
@@ -1088,7 +1049,6 @@ void CL_ClearWorld( void )
|
||||
|
||||
world.max_recursion = 0;
|
||||
|
||||
clgame.ds.cullMode = TRI_FRONT;
|
||||
clgame.numStatics = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1092,11 +1092,6 @@ static int pfnDelete( const char *path )
|
||||
return FS_Delete( path );
|
||||
}
|
||||
|
||||
static void GAME_EXPORT pfnCon_DefaultColor( int r, int g, int b )
|
||||
{
|
||||
Con_DefaultColor( r, g, b, true );
|
||||
}
|
||||
|
||||
// engine callbacks
|
||||
static ui_enginefuncs_t gEngfuncs =
|
||||
{
|
||||
@@ -1136,7 +1131,7 @@ static ui_enginefuncs_t gEngfuncs =
|
||||
UI_DrawConsoleString,
|
||||
UI_DrawSetTextColor,
|
||||
Con_DrawStringLen,
|
||||
pfnCon_DefaultColor,
|
||||
Con_DefaultColor,
|
||||
pfnGetPlayerModel,
|
||||
pfnSetPlayerModel,
|
||||
pfnClearScene,
|
||||
|
||||
@@ -3139,7 +3139,7 @@ void CL_Init( void )
|
||||
|
||||
VID_Init(); // init video
|
||||
S_Init(); // init sound
|
||||
Voice_Init( VOICE_DEFAULT_CODEC, 3, true ); // init voice (do not open the device)
|
||||
Voice_Init( VOICE_DEFAULT_CODEC, 3 ); // init voice
|
||||
|
||||
// unreliable buffer. unsed for unreliable commands and voice stream
|
||||
MSG_Init( &cls.datagram, "cls.datagram", cls.datagram_buf, sizeof( cls.datagram_buf ));
|
||||
|
||||
@@ -81,12 +81,12 @@ NetGraph_FillRGBA shortcut
|
||||
*/
|
||||
static void NetGraph_DrawRect( wrect_t *rect, byte colors[4] )
|
||||
{
|
||||
ref.dllFuncs.Color4ub( colors[0], colors[1], colors[2], colors[3] ); // color for this quad
|
||||
gTriApi.Color4ub( colors[0], colors[1], colors[2], colors[3] ); // color for this quad
|
||||
|
||||
ref.dllFuncs.Vertex3f( rect->left, rect->top, 0 );
|
||||
ref.dllFuncs.Vertex3f( rect->left + rect->right, rect->top, 0 );
|
||||
ref.dllFuncs.Vertex3f( rect->left + rect->right, rect->top + rect->bottom, 0 );
|
||||
ref.dllFuncs.Vertex3f( rect->left, rect->top + rect->bottom, 0 );
|
||||
gTriApi.Vertex3f( rect->left, rect->top, 0 );
|
||||
gTriApi.Vertex3f( rect->left + rect->right, rect->top, 0 );
|
||||
gTriApi.Vertex3f( rect->left + rect->right, rect->top + rect->bottom, 0 );
|
||||
gTriApi.Vertex3f( rect->left, rect->top + rect->bottom, 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -691,7 +691,7 @@ void SCR_DrawNetGraph( void )
|
||||
|
||||
ref.dllFuncs.End();
|
||||
ref.dllFuncs.Color4ub( 255, 255, 255, 255 );
|
||||
ref.dllFuncs.GL_SetRenderMode( kRenderNormal );
|
||||
ref.dllFuncs.RenderMode( kRenderNormal );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1778,7 +1778,7 @@ void CL_ParseVoiceInit( sizebuf_t *msg )
|
||||
char *pszCodec = MSG_ReadString( msg );
|
||||
int quality = MSG_ReadByte( msg );
|
||||
|
||||
Voice_Init( pszCodec, quality, false ); // init requested codec and the device
|
||||
Voice_Init( pszCodec, quality );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -393,7 +393,7 @@ int CL_TempEntAddEntity( cl_entity_t *pEntity )
|
||||
VectorAdd( pEntity->origin, pEntity->model->maxs, maxs );
|
||||
|
||||
// g-cont. just use PVS from previous frame
|
||||
if( TriBoxInPVS( mins, maxs ))
|
||||
if( Mod_BoxVisible( mins, maxs, ref.dllFuncs.Mod_GetCurrentVis( )))
|
||||
{
|
||||
VectorCopy( pEntity->angles, pEntity->curstate.angles );
|
||||
VectorCopy( pEntity->origin, pEntity->curstate.origin );
|
||||
@@ -1023,8 +1023,12 @@ void GAME_EXPORT R_BreakModel( const vec3_t pos, const vec3_t size, const vec3_t
|
||||
count = (size[0] * size[1] + size[1] * size[2] + size[2] * size[0]) / (3 * SHARD_VOLUME * SHARD_VOLUME);
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
if( count > 15 ) count = 15;
|
||||
#else
|
||||
// limit to 100 pieces
|
||||
if( count > 100 ) count = 100;
|
||||
#endif
|
||||
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
|
||||
@@ -101,19 +101,6 @@ struct beam_s *R_BeamRing( int startEnt, int endEnt, int modelIndex, float life,
|
||||
struct beam_s *R_BeamFollow( int startEnt, int modelIndex, float life, float width, float r, float g, float b, float brightness );
|
||||
void R_BeamKill( int deadEntity );
|
||||
|
||||
|
||||
// TriAPI
|
||||
void TriRenderMode( int mode );
|
||||
void TriColor4f( float r, float g, float b, float a );
|
||||
void TriColor4ub( byte r, byte g, byte b, byte a );
|
||||
void TriBrightness( float brightness );
|
||||
void TriCullFace( TRICULLSTYLE mode );
|
||||
int TriWorldToScreen( const float *world, float *screen );
|
||||
int TriBoxInPVS( float *mins, float *maxs );
|
||||
void TriLightAtPoint( float *pos, float *value );
|
||||
void TriColor4fRendermode( float r, float g, float b, float a, int rendermode );
|
||||
int TriSpriteTexture( model_t *pSpriteModel, int frame );
|
||||
|
||||
extern model_t *cl_sprite_dot;
|
||||
extern model_t *cl_sprite_shell;
|
||||
|
||||
|
||||
@@ -417,10 +417,10 @@ void R_DrawLeafNode( float x, float y, float scale )
|
||||
|
||||
void R_DrawNodeConnection( float x, float y, float x2, float y2 )
|
||||
{
|
||||
ref.dllFuncs.Begin( TRI_LINES );
|
||||
ref.dllFuncs.Vertex3f( x, y, 0 );
|
||||
ref.dllFuncs.Vertex3f( x2, y2, 0 );
|
||||
ref.dllFuncs.End( );
|
||||
gTriApi.Begin( TRI_LINES );
|
||||
gTriApi.Vertex3f( x, y, 0 );
|
||||
gTriApi.Vertex3f( x2, y2, 0 );
|
||||
gTriApi.End( );
|
||||
}
|
||||
|
||||
void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int shownodes, mleaf_t *viewleaf )
|
||||
@@ -443,10 +443,10 @@ void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int shownodes,
|
||||
if( shownodes == 1 )
|
||||
{
|
||||
if( cl.worldmodel->leafs == leaf )
|
||||
ref.dllFuncs.Color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
gTriApi.Color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
else if( viewleaf && viewleaf == leaf )
|
||||
ref.dllFuncs.Color4f( 1.0f, 0.0f, 0.0f, 1.0f );
|
||||
else ref.dllFuncs.Color4f( 0.0f, 1.0f, 0.0f, 1.0f );
|
||||
gTriApi.Color4f( 1.0f, 0.0f, 0.0f, 1.0f );
|
||||
else gTriApi.Color4f( 0.0f, 1.0f, 0.0f, 1.0f );
|
||||
R_DrawLeafNode( x, y, scale );
|
||||
}
|
||||
world.recursion_level--;
|
||||
@@ -455,7 +455,7 @@ void R_ShowTree_r( mnode_t *node, float x, float y, float scale, int shownodes,
|
||||
|
||||
if( shownodes == 1 )
|
||||
{
|
||||
ref.dllFuncs.Color4f( 0.0f, 0.0f, 1.0f, 1.0f );
|
||||
gTriApi.Color4f( 0.0f, 0.0f, 1.0f, 1.0f );
|
||||
R_DrawLeafNode( x, y, scale );
|
||||
}
|
||||
else if( shownodes == 2 )
|
||||
@@ -487,7 +487,7 @@ void R_ShowTree( void )
|
||||
//pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
|
||||
//pglLineWidth( 2.0f );
|
||||
ref.dllFuncs.Color4f( 1, 0.7f, 0, 1.0f );
|
||||
gTriApi.Color4f( 1, 0.7f, 0, 1.0f );
|
||||
//pglDisable( GL_TEXTURE_2D );
|
||||
R_ShowTree_r( cl.worldmodel->nodes, x, y, world.max_recursion * 3.5f, 2, viewleaf );
|
||||
//pglEnable( GL_TEXTURE_2D );
|
||||
|
||||
@@ -370,7 +370,6 @@ typedef struct
|
||||
// holds text color
|
||||
rgba_t textColor;
|
||||
rgba_t spriteColor;
|
||||
vec4_t triRGBA;
|
||||
|
||||
// crosshair members
|
||||
const model_t *pCrosshair;
|
||||
@@ -839,13 +838,13 @@ void CL_ClearSpriteTextures( void );
|
||||
void CL_CenterPrint( const char *text, float y );
|
||||
void CL_TextMessageParse( byte *pMemFile, int fileSize );
|
||||
client_textmessage_t *CL_TextMessageGet( const char *pName );
|
||||
model_t *CL_ModelHandle( int modelindex );
|
||||
void NetAPI_CancelAllRequests( void );
|
||||
cl_entity_t *CL_GetLocalPlayer( void );
|
||||
model_t *CL_LoadClientSprite( const char *filename );
|
||||
model_t *CL_LoadModel( const char *modelname, int *index );
|
||||
HSPRITE pfnSPR_LoadExt( const char *szPicName, uint texFlags );
|
||||
void SPR_AdjustSize( float *x, float *y, float *w, float *h );
|
||||
void SPR_AdjustTexCoords( float width, float height, float *s1, float *t1, float *s2, float *t2 );
|
||||
int CL_GetScreenInfo( SCREENINFO *pscrinfo );
|
||||
void CL_FillRGBA( int x, int y, int width, int height, int r, int g, int b, int a );
|
||||
pmtrace_t *PM_CL_TraceLine( float *start, float *end, int flags, int usehull, int ignore_pe );
|
||||
@@ -860,19 +859,45 @@ void CL_EnableScissor( scissor_state_t *scissor, int x, int y, int width, int he
|
||||
void CL_DisableScissor( scissor_state_t *scissor );
|
||||
qboolean CL_Scissor( const scissor_state_t *scissor, float *x, float *y, float *width, float *height, float *u0, float *v0, float *u1, float *v1 );
|
||||
|
||||
_inline cl_entity_t *CL_EDICT_NUM( int n )
|
||||
static inline cl_entity_t *CL_EDICT_NUM( int n )
|
||||
{
|
||||
if( !clgame.entities )
|
||||
if( unlikely( !clgame.entities )) // not in game yet
|
||||
{
|
||||
Host_Error( "CL_EDICT_NUM: clgame.entities is NULL\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(( n >= 0 ) && ( n < clgame.maxEntities ))
|
||||
return clgame.entities + n;
|
||||
if( unlikely( n < 0 || n >= clgame.maxEntities ))
|
||||
{
|
||||
Host_Error( "CL_EDICT_NUM: bad number %i\n", n );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Host_Error( "CL_EDICT_NUM: bad number %i\n", n );
|
||||
return NULL;
|
||||
return &clgame.entities[n];
|
||||
}
|
||||
|
||||
static inline cl_entity_t *CL_GetEntityByIndex( int n )
|
||||
{
|
||||
if( unlikely( !clgame.entities )) // not in game yet
|
||||
return NULL;
|
||||
|
||||
if( unlikely( n < 0 || n >= clgame.maxEntities ))
|
||||
return NULL;
|
||||
|
||||
return &clgame.entities[n];
|
||||
}
|
||||
|
||||
static inline model_t *CL_ModelHandle( int modelindex )
|
||||
{
|
||||
if( unlikely( modelindex < 0 || modelindex >= MAX_MODELS ))
|
||||
return NULL;
|
||||
|
||||
return cl.models[modelindex];
|
||||
}
|
||||
|
||||
static inline qboolean CL_IsPlayerIndex( int idx )
|
||||
{
|
||||
return ( idx >= 1 && idx <= cl.maxclients );
|
||||
}
|
||||
|
||||
//
|
||||
@@ -994,7 +1019,6 @@ void CL_ProcessPlayerState( int playerindex, entity_state_t *state );
|
||||
void CL_ComputePlayerOrigin( cl_entity_t *clent );
|
||||
void CL_ProcessPacket( frame_t *frame );
|
||||
void CL_MoveThirdpersonCamera( void );
|
||||
qboolean CL_IsPlayerIndex( int idx );
|
||||
void CL_SetIdealPitch( void );
|
||||
void CL_EmitEntities( void );
|
||||
|
||||
@@ -1071,7 +1095,7 @@ int Con_UtfProcessChar( int in );
|
||||
int Con_UtfProcessCharForce( int in );
|
||||
int Con_UtfMoveLeft( char *str, int pos );
|
||||
int Con_UtfMoveRight( char *str, int pos, int length );
|
||||
void Con_DefaultColor( int r, int g, int b, qboolean gameui );
|
||||
void Con_DefaultColor( int r, int g, int b );
|
||||
void Con_InvalidateFonts( void );
|
||||
cl_font_t *Con_GetCurFont( void );
|
||||
cl_font_t *Con_GetFont( int num );
|
||||
@@ -1188,5 +1212,6 @@ int Key_ToUpper( int key );
|
||||
void OSK_Draw( void );
|
||||
|
||||
extern rgba_t g_color_table[8];
|
||||
extern triangleapi_t gTriApi;
|
||||
|
||||
#endif//CLIENT_H
|
||||
|
||||
@@ -175,10 +175,10 @@ static void Con_SetColor( void )
|
||||
switch( num )
|
||||
{
|
||||
case 1:
|
||||
Con_DefaultColor( r, r, r, false );
|
||||
Con_DefaultColor( r, r, r );
|
||||
break;
|
||||
case 3:
|
||||
Con_DefaultColor( r, g, b, false );
|
||||
Con_DefaultColor( r, g, b );
|
||||
break;
|
||||
default:
|
||||
Cvar_DirectSet( &con_color, con_color.def_string );
|
||||
@@ -2195,7 +2195,7 @@ void Con_VidInit( void )
|
||||
|
||||
Con_LoadConchars();
|
||||
Con_CheckResize();
|
||||
#if XASH_LOW_MEMORY
|
||||
#if XASH_LOW_MEMORY && !XASH_PSP
|
||||
con.background = R_GetBuiltinTexture( REF_BLACK_TEXTURE );
|
||||
#else
|
||||
// loading console image
|
||||
@@ -2310,20 +2310,11 @@ Con_DefaultColor
|
||||
called from MainUI
|
||||
=========
|
||||
*/
|
||||
void Con_DefaultColor( int r, int g, int b, qboolean gameui )
|
||||
void GAME_EXPORT Con_DefaultColor( int r, int g, int b )
|
||||
{
|
||||
r = bound( 0, r, 255 );
|
||||
g = bound( 0, g, 255 );
|
||||
b = bound( 0, b, 255 );
|
||||
|
||||
// gameui wants to override console color... check if it's not default
|
||||
if( gameui && ( g_color_table[7][0] != r || g_color_table[7][1] != g || g_color_table[7][2] != b ))
|
||||
{
|
||||
// yes, different from default orange, disable con_color
|
||||
SetBits( con_color.flags, FCVAR_READ_ONLY );
|
||||
ClearBits( con_color.flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
MakeRGBA( g_color_table[7], r, g, b, 255 );
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,24 @@ GNU General Public License for more details.
|
||||
#include "vgui_draw.h"
|
||||
#include "mobility_int.h"
|
||||
|
||||
#ifdef XASH_NO_TOUCH
|
||||
|
||||
void Touch_WriteConfig( void ) {}
|
||||
void Touch_SetClientOnly( qboolean state ) {}
|
||||
void Touch_RemoveButton( const char *name ) {}
|
||||
void Touch_HideButtons( const char *name, byte hide ) {}
|
||||
void Touch_AddClientButton( const char *name, const char *texture, const char *command, float x1, float y1, float x2, float y2, byte *color, int round, float aspect, int flags ) {}
|
||||
void Touch_AddDefaultButton( const char *name, const char *texturefile, const char *command, float x1, float y1, float x2, float y2, byte *color, int round, float aspect, int flags ) {}
|
||||
void Touch_ResetDefaultButtons( void ){}
|
||||
void Touch_Init( void ) {}
|
||||
void Touch_Draw( void ) {}
|
||||
int IN_TouchEvent( touchEventType type, int fingerID, float x, float y, float dx, float dy ) { return 0; }
|
||||
void Touch_GetMove( float *forward, float *side, float *yaw, float *pitch ) {}
|
||||
void Touch_KeyEvent( int key, int down ) {}
|
||||
void Touch_Shutdown( void ) {}
|
||||
|
||||
#else /* XASH_NO_TOUCH */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
touch_command, // just tap a button
|
||||
@@ -1529,7 +1547,6 @@ void Touch_Draw( void )
|
||||
ref.dllFuncs.R_DrawStretchPic( TO_SCRN_X( touch.move_start_x + touch.side * width - GRID_X * touch_move_indicator.value ),
|
||||
TO_SCRN_Y( touch.move_start_y - touch.forward * height - GRID_Y * touch_move_indicator.value ),
|
||||
TO_SCRN_X( GRID_X * 2 * touch_move_indicator.value ), TO_SCRN_Y( GRID_Y * 2 * touch_move_indicator.value ), 0, 0, 1, 1, touch.joytexture );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2191,3 +2208,5 @@ void Touch_Shutdown( void )
|
||||
touch.initialized = false;
|
||||
Mem_FreePool( &touch.mempool );
|
||||
}
|
||||
|
||||
#endif /* XASH_NO_TOUCH */
|
||||
|
||||
@@ -60,8 +60,10 @@ uint IN_CollectInputDevices( void )
|
||||
if( !m_ignore.value ) // no way to check is mouse connected, so use cvar only
|
||||
ret |= INPUT_DEVICE_MOUSE;
|
||||
|
||||
#ifndef XASH_NO_TOUCH
|
||||
if( touch_enable.value )
|
||||
ret |= INPUT_DEVICE_TOUCH;
|
||||
#endif
|
||||
|
||||
if( Joy_IsActive() ) // connected or enabled
|
||||
ret |= INPUT_DEVICE_JOYSTICK;
|
||||
@@ -91,13 +93,17 @@ void IN_LockInputDevices( qboolean lock )
|
||||
{
|
||||
SetBits( m_ignore.flags, FCVAR_READ_ONLY );
|
||||
SetBits( joy_enable.flags, FCVAR_READ_ONLY );
|
||||
#ifndef XASH_NO_TOUCH
|
||||
SetBits( touch_enable.flags, FCVAR_READ_ONLY );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearBits( m_ignore.flags, FCVAR_READ_ONLY );
|
||||
ClearBits( joy_enable.flags, FCVAR_READ_ONLY );
|
||||
#ifndef XASH_NO_TOUCH
|
||||
ClearBits( touch_enable.flags, FCVAR_READ_ONLY );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,11 +357,14 @@ void IN_MouseEvent( int key, int down )
|
||||
else ClearBits( in_mstate, BIT( key ));
|
||||
|
||||
// touch emulation overrides all input
|
||||
#if XASH_NO_TOUCH
|
||||
if( touch_emulate.value )
|
||||
{
|
||||
Touch_KeyEvent( K_MOUSE1 + key, down );
|
||||
}
|
||||
else if( cls.key_dest == key_game )
|
||||
else
|
||||
#endif
|
||||
if( cls.key_dest == key_game )
|
||||
{
|
||||
// perform button actions
|
||||
VGui_MouseEvent( K_MOUSE1 + key, down );
|
||||
@@ -364,8 +373,7 @@ void IN_MouseEvent( int key, int down )
|
||||
// client may override IN_MouseEvent
|
||||
// but by default it calls back to Key_Event anyway
|
||||
if( in_mouseactive )
|
||||
clgame.dllFuncs.IN_MouseEvent( in_mstate );
|
||||
}
|
||||
clgame.dllFuncs.IN_MouseEvent( in_mstate ); }
|
||||
else
|
||||
{
|
||||
// perform button actions
|
||||
|
||||
@@ -515,7 +515,6 @@ void Key_Init( void )
|
||||
|
||||
Cvar_RegisterVariable( &osk_enable );
|
||||
Cvar_RegisterVariable( &key_rotate );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -703,7 +702,11 @@ void GAME_EXPORT Key_Event( int key, int down )
|
||||
VGui_KeyEvent( key, down );
|
||||
|
||||
// console key is hardcoded, so the user can never unbind it
|
||||
#if XASH_PSP
|
||||
if( key == '`' || key == '~' || key == K_MODE_BUTTON )
|
||||
#else
|
||||
if( key == '`' || key == '~' )
|
||||
#endif
|
||||
{
|
||||
// we are in typing mode, so don't switch to console
|
||||
if( cls.key_dest == key_message || !down )
|
||||
@@ -714,7 +717,11 @@ void GAME_EXPORT Key_Event( int key, int down )
|
||||
}
|
||||
|
||||
// escape is always handled special
|
||||
#if XASH_PSP
|
||||
if( ( key == K_ESCAPE || key == K_START_BUTTON ) && down )
|
||||
#else
|
||||
if( key == K_ESCAPE && down )
|
||||
#endif
|
||||
{
|
||||
switch( cls.key_dest )
|
||||
{
|
||||
@@ -881,7 +888,11 @@ Normal keyboard characters, already shifted / capslocked / etc
|
||||
void CL_CharEvent( int key )
|
||||
{
|
||||
// the console key should never be used as a char
|
||||
#if XASH_PSP
|
||||
if( key == '`' || key == '~' || key == K_MODE_BUTTON ) return;
|
||||
#else
|
||||
if( key == '`' || key == '~' ) return;
|
||||
#endif
|
||||
|
||||
if( cls.key_dest == key_console && !Con_Visible( ))
|
||||
{
|
||||
@@ -1006,7 +1017,11 @@ static qboolean OSK_KeyEvent( int key, int down )
|
||||
|
||||
if( osk.curbutton.val == 0 )
|
||||
{
|
||||
#if XASH_PSP
|
||||
if( key == K_ENTER || key == K_A_BUTTON )
|
||||
#else
|
||||
if( key == K_ENTER )
|
||||
#endif
|
||||
{
|
||||
osk.curbutton.val = osk_keylayout[osk.curlayout][osk.curbutton.y][osk.curbutton.x];
|
||||
return true;
|
||||
@@ -1017,6 +1032,9 @@ static qboolean OSK_KeyEvent( int key, int down )
|
||||
|
||||
switch ( key )
|
||||
{
|
||||
#if XASH_PSP
|
||||
case K_A_BUTTON:
|
||||
#endif
|
||||
case K_ENTER:
|
||||
switch( osk.curbutton.val )
|
||||
{
|
||||
|
||||
@@ -323,6 +323,10 @@ static ref_api_t gEngfuncs =
|
||||
&clgame.drawFuncs,
|
||||
|
||||
&g_fsapi,
|
||||
#if XASH_PSP
|
||||
P5Ram_Alloc,
|
||||
P5Ram_Free,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void R_UnloadProgs( void )
|
||||
@@ -344,33 +348,8 @@ static void R_UnloadProgs( void )
|
||||
memset( &ref.dllFuncs, 0, sizeof( ref.dllFuncs ));
|
||||
}
|
||||
|
||||
static void CL_FillTriAPIFromRef( triangleapi_t *dst, const ref_interface_t *src )
|
||||
{
|
||||
dst->version = TRI_API_VERSION;
|
||||
dst->Begin = src->Begin;
|
||||
dst->RenderMode = TriRenderMode;
|
||||
dst->End = src->End;
|
||||
dst->Color4f = TriColor4f;
|
||||
dst->Color4ub = TriColor4ub;
|
||||
dst->TexCoord2f = src->TexCoord2f;
|
||||
dst->Vertex3f = src->Vertex3f;
|
||||
dst->Vertex3fv = src->Vertex3fv;
|
||||
dst->Brightness = TriBrightness;
|
||||
dst->CullFace = TriCullFace;
|
||||
dst->SpriteTexture = TriSpriteTexture;
|
||||
dst->WorldToScreen = TriWorldToScreen;
|
||||
dst->Fog = src->Fog;
|
||||
dst->ScreenToWorld = src->ScreenToWorld;
|
||||
dst->GetMatrix = src->GetMatrix;
|
||||
dst->BoxInPVS = TriBoxInPVS;
|
||||
dst->LightAtPoint = TriLightAtPoint;
|
||||
dst->Color4fRendermode = TriColor4fRendermode;
|
||||
dst->FogParams = src->FogParams;
|
||||
}
|
||||
|
||||
static qboolean R_LoadProgs( const char *name )
|
||||
{
|
||||
extern triangleapi_t gTriApi;
|
||||
static ref_api_t gpEngfuncs;
|
||||
REFAPI GetRefAPI; // single export
|
||||
|
||||
@@ -415,12 +394,18 @@ static qboolean R_LoadProgs( const char *name )
|
||||
return false;
|
||||
}
|
||||
|
||||
// initialize TriAPI callbacks
|
||||
if( !ref.dllFuncs.getTriAPI( TRI_API_VERSION, &gTriApi ))
|
||||
{
|
||||
COM_FreeLibrary( ref.hInstance );
|
||||
Con_Reportf( "R_LoadProgs: can't init TriAPI Interface: wrong version, %i must be %i\n", gTriApi.version, TRI_API_VERSION );
|
||||
ref.hInstance = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
Cvar_FullSet( "host_refloaded", "1", FCVAR_READ_ONLY );
|
||||
ref.initialized = true;
|
||||
|
||||
// initialize TriAPI callbacks
|
||||
CL_FillTriAPIFromRef( &gTriApi, &ref.dllFuncs );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,11 @@ GNU General Public License for more details.
|
||||
// than could actually be referenced during gameplay,
|
||||
// because we don't want to free anything until we are
|
||||
// sure we won't need it.
|
||||
#if XASH_PSP
|
||||
#define MAX_SFX 2048
|
||||
#else
|
||||
#define MAX_SFX 8192
|
||||
#endif
|
||||
#define MAX_SFX_HASH (MAX_SFX/4)
|
||||
|
||||
static int s_numSfx = 0;
|
||||
|
||||
@@ -201,9 +201,15 @@ typedef struct
|
||||
|
||||
//====================================================================
|
||||
|
||||
#if XASH_PSP
|
||||
#define MAX_DYNAMIC_CHANNELS (20 + NUM_AMBIENTS)
|
||||
#define MAX_CHANNELS (128 + MAX_DYNAMIC_CHANNELS)
|
||||
#define MAX_RAW_CHANNELS 16
|
||||
#else
|
||||
#define MAX_DYNAMIC_CHANNELS (60 + NUM_AMBIENTS)
|
||||
#define MAX_CHANNELS (256 + MAX_DYNAMIC_CHANNELS) // Scourge Of Armagon has too many static sounds on hip2m4.bsp
|
||||
#define MAX_RAW_CHANNELS 48
|
||||
#endif
|
||||
#define MAX_RAW_SAMPLES 8192
|
||||
|
||||
extern sound_t ambient_sfx[NUM_AMBIENTS];
|
||||
|
||||
@@ -428,9 +428,6 @@ void Voice_Disconnect( void )
|
||||
voice.players_status[i].talking_ack = false;
|
||||
}
|
||||
}
|
||||
|
||||
VoiceCapture_Shutdown();
|
||||
voice.device_opened = false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -591,53 +588,48 @@ Voice_Init
|
||||
Initialize the voice subsystem
|
||||
=========================
|
||||
*/
|
||||
qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit )
|
||||
qboolean Voice_Init( const char *pszCodecName, int quality )
|
||||
{
|
||||
if( !voice_enable.value )
|
||||
return false;
|
||||
|
||||
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
|
||||
{
|
||||
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
|
||||
return false;
|
||||
}
|
||||
|
||||
// reinitialize only if codec parameters are different
|
||||
if( Q_strcmp( pszCodecName, voice.codec ) || voice.quality != quality )
|
||||
if( !Q_strcmp( voice.codec, pszCodecName ) && voice.quality == quality )
|
||||
return true;
|
||||
|
||||
Voice_Shutdown();
|
||||
|
||||
voice.autogain.block_size = 128;
|
||||
|
||||
if( !Voice_InitOpusDecoder( ))
|
||||
{
|
||||
// no reason to init encoder and open audio device
|
||||
// if we can't hear other players
|
||||
Con_Printf( S_ERROR "Voice chat disabled.\n" );
|
||||
Voice_Shutdown();
|
||||
|
||||
if( Q_strcmp( pszCodecName, VOICE_OPUS_CUSTOM_CODEC ))
|
||||
{
|
||||
Con_Printf( S_ERROR "Server requested unsupported codec: %s\n", pszCodecName );
|
||||
return false;
|
||||
}
|
||||
|
||||
voice.autogain.block_size = 128;
|
||||
|
||||
if( !Voice_InitOpusDecoder( ))
|
||||
{
|
||||
// no reason to init encoder and open audio device
|
||||
// if we can't hear other players
|
||||
Con_Printf( S_ERROR "Voice chat disabled.\n" );
|
||||
Voice_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
// we can hear others players, so it's fine to fail now
|
||||
voice.initialized = true;
|
||||
Q_strncpy( voice.codec, pszCodecName, sizeof( voice.codec ));
|
||||
|
||||
if( !Voice_InitOpusEncoder( quality ))
|
||||
{
|
||||
Con_Printf( S_WARN "Other players will not be able to hear you.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
voice.quality = quality;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !preinit )
|
||||
// we can hear others players, so it's fine to fail now
|
||||
voice.initialized = true;
|
||||
Q_strncpy( voice.codec, pszCodecName, sizeof( voice.codec ));
|
||||
|
||||
if( !Voice_InitOpusEncoder( quality ))
|
||||
{
|
||||
voice.device_opened = VoiceCapture_Init();
|
||||
|
||||
if( !voice.device_opened )
|
||||
Con_Printf( S_WARN "No microphone is available.\n" );
|
||||
Con_Printf( S_WARN "Other players will not be able to hear you.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
voice.quality = quality;
|
||||
|
||||
if( !VoiceCapture_Init( ))
|
||||
Con_Printf( S_WARN "No microphone is available.\n" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ typedef struct voice_state_s
|
||||
|
||||
qboolean initialized;
|
||||
qboolean is_recording;
|
||||
qboolean device_opened;
|
||||
double start_time;
|
||||
|
||||
voice_status_t local;
|
||||
@@ -93,7 +92,7 @@ extern voice_state_t voice;
|
||||
void CL_AddVoiceToDatagram( void );
|
||||
|
||||
void Voice_RegisterCvars( void );
|
||||
qboolean Voice_Init( const char *pszCodecName, int quality, qboolean preinit );
|
||||
qboolean Voice_Init( const char *pszCodecName, int quality );
|
||||
void Voice_Idle( double frametime );
|
||||
qboolean Voice_IsRecording( void );
|
||||
void Voice_RecordStop( void );
|
||||
|
||||
175
engine/common/build.c
Normal file
175
engine/common/build.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
build.c - returns a engine build number
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static char *date = __DATE__ ;
|
||||
static char *mon[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
static char mond[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
// returns days since Apr 1 2015
|
||||
int Q_buildnum( void )
|
||||
{
|
||||
int m = 0, d = 0, y = 0;
|
||||
static int b = 0;
|
||||
|
||||
if( b != 0 ) return b;
|
||||
|
||||
for( m = 0; m < 11; m++ )
|
||||
{
|
||||
if( !Q_strnicmp( &date[0], mon[m], 3 ))
|
||||
break;
|
||||
d += mond[m];
|
||||
}
|
||||
|
||||
d += Q_atoi( &date[4] ) - 1;
|
||||
y = Q_atoi( &date[7] ) - 1900;
|
||||
b = d + (int)((y - 1) * 365.25f );
|
||||
|
||||
if((( y % 4 ) == 0 ) && m > 1 )
|
||||
{
|
||||
b += 1;
|
||||
}
|
||||
b -= 41728; // Apr 1 2015
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Q_buildnum_compat
|
||||
|
||||
Returns a Xash3D build number. This is left for compability with original Xash3D.
|
||||
IMPORTANT: this value must be changed ONLY after updating to newer Xash3D
|
||||
IMPORTANT: this value must be acquired through "build" cvar.
|
||||
=============
|
||||
*/
|
||||
int Q_buildnum_compat( void )
|
||||
{
|
||||
// do not touch this! Only author of Xash3D can increase buildnumbers!
|
||||
return 4529;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Q_buildos
|
||||
|
||||
Returns current name of operating system. Without any spaces.
|
||||
============
|
||||
*/
|
||||
const char *Q_buildos( void )
|
||||
{
|
||||
const char *osname;
|
||||
|
||||
#if XASH_MINGW
|
||||
osname = "win32-mingw";
|
||||
#elif XASH_WIN32
|
||||
osname = "win32";
|
||||
#elif XASH_ANDROID
|
||||
osname = "android";
|
||||
#elif XASH_LINUX
|
||||
osname = "linux";
|
||||
#elif XASH_APPLE
|
||||
osname = "apple";
|
||||
#elif XASH_FREEBSD
|
||||
osname = "freebsd";
|
||||
#elif XASH_NETBSD
|
||||
osname = "netbsd";
|
||||
#elif XASH_OPENBSD
|
||||
osname = "openbsd";
|
||||
#elif XASH_EMSCRIPTEN
|
||||
osname = "emscripten";
|
||||
#elif XASH_DOS4GW
|
||||
osname = "DOS4GW";
|
||||
#elif XASH_PSP
|
||||
osname = "psp";
|
||||
#else
|
||||
#error "Place your operating system name here! If this is a mistake, try to fix conditions above and report a bug"
|
||||
#endif
|
||||
|
||||
return osname;
|
||||
}
|
||||
|
||||
/*
|
||||
============
|
||||
Q_buildos
|
||||
|
||||
Returns current name of operating system. Without any spaces.
|
||||
============
|
||||
*/
|
||||
const char *Q_buildarch( void )
|
||||
{
|
||||
const char *archname;
|
||||
|
||||
#if XASH_AMD64
|
||||
archname = "amd64";
|
||||
#elif XASH_X86
|
||||
archname = "i386";
|
||||
#elif XASH_ARM && XASH_64BIT
|
||||
archname = "arm64";
|
||||
#elif XASH_ARM
|
||||
archname = "armv"
|
||||
#if XASH_ARM == 8
|
||||
"8_32" // for those who (mis)using 32-bit OS on 64-bit CPU
|
||||
#elif XASH_ARM == 7
|
||||
"7"
|
||||
#elif XASH_ARM == 6
|
||||
"6"
|
||||
#elif XASH_ARM == 5
|
||||
"5"
|
||||
#elif XASH_ARM == 4
|
||||
"4"
|
||||
#endif
|
||||
|
||||
#if XASH_ARM_HARDFP
|
||||
"hf";
|
||||
#else
|
||||
"l";
|
||||
#endif
|
||||
#elif XASH_MIPS && defined XASH_BIG_ENDIAN
|
||||
archname = "mips";
|
||||
#elif XASH_MIPS && defined XASH_LITTLE_ENDIAN
|
||||
archname = "mipsel";
|
||||
#elif XASH_JS
|
||||
archname = "javascript";
|
||||
#elif XASH_E2K
|
||||
archname = "e2k";
|
||||
#else
|
||||
#error "Place your architecture name here! If this is a mistake, try to fix conditions above and report a bug"
|
||||
#endif
|
||||
|
||||
return archname;
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
Q_buildcommit
|
||||
|
||||
Returns a short hash of current commit in VCS as string.
|
||||
XASH_BUILD_COMMIT must be passed in quotes
|
||||
|
||||
if XASH_BUILD_COMMIT is not defined,
|
||||
Q_buildcommit will identify this build as "notset"
|
||||
=============
|
||||
*/
|
||||
const char *Q_buildcommit( void )
|
||||
{
|
||||
#ifdef XASH_BUILD_COMMIT
|
||||
return XASH_BUILD_COMMIT;
|
||||
#else
|
||||
return "notset";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ typedef enum
|
||||
#define MAX_DECALS 256 // touching TE_DECAL messages, etc
|
||||
#define MAX_STATIC_ENTITIES 32 // static entities that moved on the client when level is spawn
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define GameState (&host.game)
|
||||
|
||||
@@ -723,7 +724,6 @@ int R_CreateDecalList( struct decallist_s *pList );
|
||||
void R_ClearAllDecals( void );
|
||||
void CL_ClearStaticEntities( void );
|
||||
qboolean S_StreamGetCurrentState( char *currentTrack, char *loopTrack, int *position );
|
||||
struct cl_entity_s *CL_GetEntityByIndex( int index );
|
||||
void CL_ServerCommand( qboolean reliable, const char *fmt, ... ) _format( 2 );
|
||||
void CL_HudMessage( const char *pMessage );
|
||||
const char *CL_MsgInfo( int cmd );
|
||||
|
||||
@@ -372,9 +372,9 @@ static void Sys_Crash( int signal, siginfo_t *si, void *context)
|
||||
bp = (void**)ucontext->uc_mcontext.mc_rbp;
|
||||
sp = (void**)ucontext->uc_mcontext.mc_rsp;
|
||||
#elif XASH_NETBSD
|
||||
pc = (void*)ucontext->uc_mcontext.__gregs[_REG_RIP];
|
||||
bp = (void**)ucontext->uc_mcontext.__gregs[_REG_RBP];
|
||||
sp = (void**)ucontext->uc_mcontext.__gregs[_REG_RSP];
|
||||
pc = (void*)ucontext->uc_mcontext.__gregs[REG_RIP];
|
||||
bp = (void**)ucontext->uc_mcontext.__gregs[REG_RBP];
|
||||
sp = (void**)ucontext->uc_mcontext.__gregs[REG_RSP];
|
||||
#elif XASH_OPENBSD
|
||||
pc = (void*)ucontext->sc_rip;
|
||||
bp = (void**)ucontext->sc_rbp;
|
||||
|
||||
4556
engine/common/filesystem.c
Normal file
4556
engine/common/filesystem.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1064,10 +1064,10 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
|
||||
|
||||
// init host state machine
|
||||
COM_InitHostState();
|
||||
|
||||
#ifdef XASH_HASHED_VARS
|
||||
// init hashed commands
|
||||
BaseCmd_Init();
|
||||
|
||||
#endif
|
||||
// startup cmds and cvars subsystem
|
||||
Cmd_Init();
|
||||
Cvar_Init();
|
||||
@@ -1110,6 +1110,8 @@ void Host_InitCommon( int argc, char **argv, const char *progname, qboolean bCha
|
||||
Sys_Error( "couldn't find xash3d data directory" );
|
||||
host.rootdir[0] = 0;
|
||||
}
|
||||
#elif XASH_PSP
|
||||
COM_ExtractFilePath( argv[0], host.rootdir );
|
||||
#elif (XASH_SDL == 2) && !XASH_NSWITCH // GetBasePath not impl'd in switch-sdl2
|
||||
char *szBasePath = SDL_GetBasePath();
|
||||
if( szBasePath )
|
||||
|
||||
@@ -24,7 +24,7 @@ Image_LoadTGA
|
||||
*/
|
||||
qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
int i, columns, rows, row_inc, row, col;
|
||||
int i, columns, rows, row_inc, row, col, bpp = 1;
|
||||
byte *buf_p, *pixbuf, *targa_rgba;
|
||||
rgba_t palette[256];
|
||||
byte red = 0, green = 0, blue = 0, alpha = 0;
|
||||
@@ -32,6 +32,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
int reflectivity[3] = { 0, 0, 0 };
|
||||
qboolean compressed;
|
||||
tga_t targa_header;
|
||||
int palIndex = 0;
|
||||
|
||||
if( filesize < sizeof( tga_t ))
|
||||
return false;
|
||||
@@ -55,8 +56,6 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
// check for tga file
|
||||
if( !Image_ValidSize( name )) return false;
|
||||
|
||||
image.type = PF_RGBA_32; // always exctracted to 32-bit buffer
|
||||
|
||||
if( targa_header.image_type == 1 || targa_header.image_type == 9 )
|
||||
{
|
||||
// uncompressed colormapped image
|
||||
@@ -119,11 +118,35 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Image_LoadTGA: (%s) Type %i not supported\n", name, targa_header.image_type );
|
||||
return false;
|
||||
}
|
||||
|
||||
columns = targa_header.width;
|
||||
rows = targa_header.height;
|
||||
|
||||
image.size = image.width * image.height * 4;
|
||||
if( Image_CheckFlag( IL_KEEP_8BIT ) && ( targa_header.image_type == 1 || targa_header.image_type == 9 ))
|
||||
{
|
||||
pixbuf = image.palette = Mem_Malloc( host.imagepool, 1024 );
|
||||
for( i = 0; i < targa_header.colormap_length; i++ )
|
||||
{
|
||||
*pixbuf++ = palette[i][0];
|
||||
*pixbuf++ = palette[i][1];
|
||||
*pixbuf++ = palette[i][2];
|
||||
*pixbuf++ = palette[i][3];
|
||||
}
|
||||
image.type = PF_INDEXED_32;
|
||||
}
|
||||
else
|
||||
{
|
||||
image.palette = NULL;
|
||||
image.type = PF_RGBA_32;
|
||||
bpp = 4;
|
||||
}
|
||||
|
||||
image.size = image.width * image.height * bpp;
|
||||
targa_rgba = image.rgba = Mem_Malloc( host.imagepool, image.size );
|
||||
|
||||
// if bit 5 of attributes isn't set, the image has been stored from bottom to top
|
||||
@@ -134,8 +157,8 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
}
|
||||
else
|
||||
{
|
||||
pixbuf = targa_rgba + ( rows - 1 ) * columns * 4;
|
||||
row_inc = -columns * 4 * 2;
|
||||
pixbuf = targa_rgba + ( rows - 1 ) * columns * bpp;
|
||||
row_inc = -columns * bpp * 2;
|
||||
}
|
||||
|
||||
compressed = ( targa_header.image_type == 9 || targa_header.image_type == 10 || targa_header.image_type == 11 );
|
||||
@@ -161,13 +184,13 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
case 1:
|
||||
case 9:
|
||||
// colormapped image
|
||||
blue = *buf_p++;
|
||||
if( blue < targa_header.colormap_length )
|
||||
palIndex = *buf_p++;
|
||||
if( palIndex < targa_header.colormap_length )
|
||||
{
|
||||
red = palette[blue][0];
|
||||
green = palette[blue][1];
|
||||
alpha = palette[blue][3];
|
||||
blue = palette[blue][2];
|
||||
red = palette[palIndex][0];
|
||||
green = palette[palIndex][1];
|
||||
blue = palette[palIndex][2];
|
||||
alpha = palette[palIndex][3];
|
||||
if( alpha != 255 ) image.flags |= IMAGE_HAS_ALPHA;
|
||||
}
|
||||
break;
|
||||
@@ -208,10 +231,18 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
reflectivity[1] += green;
|
||||
reflectivity[2] += blue;
|
||||
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = alpha;
|
||||
if( image.type == PF_INDEXED_32 || image.type == PF_INDEXED_24 )
|
||||
{
|
||||
*pixbuf++ = palIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pixbuf++ = red;
|
||||
*pixbuf++ = green;
|
||||
*pixbuf++ = blue;
|
||||
*pixbuf++ = alpha;
|
||||
}
|
||||
|
||||
if( ++col == columns )
|
||||
{
|
||||
// run spans across rows
|
||||
@@ -223,6 +254,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, fs_offset_t filesi
|
||||
}
|
||||
|
||||
VectorDivide( reflectivity, ( image.width * image.height ), image.fogParams );
|
||||
if( image.palette ) Image_GetPaletteBMP( image.palette );
|
||||
image.depth = 1;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -93,6 +93,23 @@ static const loadpixformat_t load_null[] =
|
||||
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||
};
|
||||
|
||||
// a1ba: that's weird, better debug
|
||||
#if XASH_PSP
|
||||
static const loadpixformat_t load_game[] =
|
||||
{
|
||||
{ "%s%s.%s", "mip", Image_LoadMIP, IL_HINT_NO }, // hl textures from wad or buffer
|
||||
{ "%s%s.%s", "mdl", Image_LoadMDL, IL_HINT_HL }, // hl studio model skins
|
||||
{ "%s%s.%s", "spr", Image_LoadSPR, IL_HINT_HL }, // hl sprite frames
|
||||
{ "%s%s.%s", "lmp", Image_LoadLMP, IL_HINT_NO }, // hl menu images (cached.wad etc)
|
||||
{ "%s%s.%s", "fnt", Image_LoadFNT, IL_HINT_HL }, // hl console font (fonts.wad etc)
|
||||
{ "%s%s.%s", "pal", Image_LoadPAL, IL_HINT_NO }, // install studio\sprite palette
|
||||
{ "%s%s.%s", "dds", Image_LoadDDS, IL_HINT_NO }, // dds for world and studio models
|
||||
{ "%s%s.%s", "tga", Image_LoadTGA, IL_HINT_NO }, // hl vgui menus
|
||||
{ "%s%s.%s", "bmp", Image_LoadBMP, IL_HINT_NO }, // WON menu images
|
||||
{ "%s%s.%s", "png", Image_LoadPNG, IL_HINT_NO }, // NightFire 007 menus
|
||||
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||
};
|
||||
#else
|
||||
static const loadpixformat_t load_game[] =
|
||||
{
|
||||
{ "%s%s.%s", "dds", Image_LoadDDS, IL_HINT_NO }, // dds for world and studio models
|
||||
@@ -108,7 +125,7 @@ static const loadpixformat_t load_game[] =
|
||||
{ "%s%s.%s", "ktx2", Image_LoadKTX2, IL_HINT_NO }, // ktx2 for world and studio models
|
||||
{ NULL, NULL, NULL, IL_HINT_NO }
|
||||
};
|
||||
|
||||
#endif
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
|
||||
@@ -34,7 +34,13 @@ GNU General Public License for more details.
|
||||
|
||||
static char szGameDir[128]; // safe place to keep gamedir
|
||||
static int szArgc;
|
||||
|
||||
#if XASH_PSP
|
||||
#define MAX_NARGVS 50
|
||||
static char *szArgv[MAX_NARGVS];
|
||||
#else
|
||||
static char **szArgv;
|
||||
#endif
|
||||
|
||||
static void Sys_ChangeGame( const char *progname )
|
||||
{
|
||||
@@ -71,20 +77,23 @@ static int Sys_Start( void )
|
||||
#endif
|
||||
#elif XASH_IOS
|
||||
IOS_LaunchDialog();
|
||||
#endif
|
||||
#elif XASH_PSP
|
||||
|
||||
return Host_Main( szArgc, szArgv, game, 0, Sys_ChangeGame );
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
#if XASH_PSVITA
|
||||
#if XASH_PSP
|
||||
Platform_ReadCmd( "start.cmd", &szArgc, szArgv );
|
||||
#elif XASH_PSVITA
|
||||
// inject -dev -console into args if required
|
||||
szArgc = PSVita_GetArgv( argc, argv, &szArgv );
|
||||
#else
|
||||
szArgc = argc;
|
||||
szArgv = argv;
|
||||
#endif // XASH_PSVITA
|
||||
|
||||
return Sys_Start();
|
||||
}
|
||||
#endif // XASH_ENABLE_MAIN
|
||||
|
||||
@@ -38,6 +38,7 @@ void COM_PushLibraryError( const char *error )
|
||||
Q_strncat( s_szLastError, error, sizeof( s_szLastError ) );
|
||||
}
|
||||
|
||||
#if !XASH_PSP
|
||||
void *COM_FunctionFromName_SR( void *hInstance, const char *pName )
|
||||
{
|
||||
char **funcs = NULL;
|
||||
@@ -85,6 +86,7 @@ const char *COM_OffsetNameForFunction( void *function )
|
||||
Con_Reportf( "COM_OffsetNameForFunction %s\n", sname );
|
||||
return sname;
|
||||
}
|
||||
#endif
|
||||
|
||||
dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
|
||||
{
|
||||
@@ -128,7 +130,7 @@ dll_user_t *FS_FindLibrary( const char *dllname, qboolean directpath )
|
||||
|
||||
static void COM_GenerateCommonLibraryName( const char *name, const char *ext, char *out, size_t size )
|
||||
{
|
||||
#if ( XASH_WIN32 || XASH_LINUX || XASH_APPLE ) && XASH_X86
|
||||
#if (( XASH_WIN32 || XASH_LINUX || XASH_APPLE ) && XASH_X86) || XASH_PSP
|
||||
Q_snprintf( out, size, "%s.%s", name, ext );
|
||||
#elif ( XASH_WIN32 || XASH_LINUX || XASH_APPLE )
|
||||
Q_snprintf( out, size, "%s_%s.%s", name, Q_buildarch(), ext );
|
||||
@@ -191,6 +193,8 @@ static void COM_GenerateServerLibraryPath( char *out, size_t size )
|
||||
Q_strncpy( out, GI->game_dll, size );
|
||||
#elif XASH_APPLE
|
||||
Q_strncpy( out, GI->game_dll_osx, size );
|
||||
#elif XASH_PSP
|
||||
Q_strncpy( out, GI->game_dll_psp, size );
|
||||
#else // XASH_LINUX
|
||||
Q_strncpy( out, GI->game_dll_linux, size );
|
||||
#endif
|
||||
@@ -203,6 +207,8 @@ static void COM_GenerateServerLibraryPath( char *out, size_t size )
|
||||
Q_strncpy( dllpath, GI->game_dll, sizeof( dllpath ) );
|
||||
#elif XASH_APPLE
|
||||
Q_strncpy( dllpath, GI->game_dll_osx, sizeof( dllpath ) );
|
||||
#elif XASH_PSP
|
||||
Q_strncpy( dllpath, GI->game_dll_psp, sizeof( dllpath ) );
|
||||
#else // XASH_APPLE
|
||||
Q_strncpy( dllpath, GI->game_dll_linux, sizeof( dllpath ) );
|
||||
#endif
|
||||
|
||||
@@ -1735,12 +1735,16 @@ static void Mod_LoadSubmodels( model_t *mod, dbspmodel_t *bmod )
|
||||
oldmaxfaces = Q_max( oldmaxfaces, out->numfaces );
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
refState.max_surfaces = 0; // sorting disabled
|
||||
#else
|
||||
// these array used to sort translucent faces in bmodels
|
||||
if( oldmaxfaces > refState.max_surfaces )
|
||||
{
|
||||
refState.draw_surfaces = (sortedface_t *)Z_Realloc( refState.draw_surfaces, oldmaxfaces * sizeof( sortedface_t ));
|
||||
refState.max_surfaces = oldmaxfaces;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -151,17 +151,6 @@ void MSG_Clear( sizebuf_t *sb )
|
||||
sb->bOverflow = false;
|
||||
}
|
||||
|
||||
static qboolean MSG_Overflow( sizebuf_t *sb, int nBits )
|
||||
{
|
||||
if( sb->iCurBit + nBits > sb->nDataBits )
|
||||
sb->bOverflow = true;
|
||||
return sb->bOverflow;
|
||||
}
|
||||
|
||||
qboolean MSG_CheckOverflow( sizebuf_t *sb )
|
||||
{
|
||||
return MSG_Overflow( sb, 0 );
|
||||
}
|
||||
|
||||
int MSG_SeekToBit( sizebuf_t *sb, int bitPos, int whence )
|
||||
{
|
||||
@@ -193,17 +182,6 @@ void MSG_SeekToByte( sizebuf_t *sb, int bytePos )
|
||||
sb->iCurBit = bytePos << 3;
|
||||
}
|
||||
|
||||
void MSG_WriteOneBit( sizebuf_t *sb, int nValue )
|
||||
{
|
||||
if( !MSG_Overflow( sb, 1 ))
|
||||
{
|
||||
if( nValue ) sb->pData[sb->iCurBit>>3] |= BIT( sb->iCurBit & 7 );
|
||||
else sb->pData[sb->iCurBit>>3] &= ~BIT( sb->iCurBit & 7 );
|
||||
|
||||
sb->iCurBit++;
|
||||
}
|
||||
}
|
||||
|
||||
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits )
|
||||
{
|
||||
Assert( numbits >= 0 && numbits <= 32 );
|
||||
|
||||
@@ -64,6 +64,19 @@ _inline int MSG_TellBit( sizebuf_t *sb ) { return sb->iCurBit; }
|
||||
_inline const char *MSG_GetName( sizebuf_t *sb ) { return sb->pDebugName; }
|
||||
qboolean MSG_CheckOverflow( sizebuf_t *sb );
|
||||
|
||||
static inline qboolean MSG_Overflow( sizebuf_t *sb, int nBits )
|
||||
{
|
||||
if( sb->iCurBit + nBits > sb->nDataBits )
|
||||
sb->bOverflow = true;
|
||||
return sb->bOverflow;
|
||||
}
|
||||
|
||||
static inline MSG_CheckOverflow( sizebuf_t *sb )
|
||||
{
|
||||
return MSG_Overflow( sb, 0 );
|
||||
}
|
||||
|
||||
|
||||
#if XASH_BIG_ENDIAN
|
||||
#define MSG_BigShort( x ) ( x )
|
||||
#else
|
||||
@@ -78,7 +91,16 @@ void MSG_StartWriting( sizebuf_t *sb, void *pData, int nBytes, int iStartBit, in
|
||||
void MSG_Clear( sizebuf_t *sb );
|
||||
|
||||
// Bit-write functions
|
||||
void MSG_WriteOneBit( sizebuf_t *sb, int nValue );
|
||||
static inline void MSG_WriteOneBit( sizebuf_t *sb, int nValue )
|
||||
{
|
||||
if( likely( !MSG_Overflow( sb, 1 )))
|
||||
{
|
||||
if( nValue ) sb->pData[sb->iCurBit>>3] |= BIT( sb->iCurBit & 7 );
|
||||
else sb->pData[sb->iCurBit>>3] &= ~BIT( sb->iCurBit & 7 );
|
||||
|
||||
sb->iCurBit++;
|
||||
}
|
||||
}
|
||||
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits );
|
||||
void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits );
|
||||
void MSG_WriteBitLong( sizebuf_t *sb, uint data, int numbits, qboolean bSigned );
|
||||
|
||||
@@ -1095,7 +1095,6 @@ int Delta_TestBaseline( entity_state_t *from, entity_state_t *to, qboolean playe
|
||||
if( from == NULL ) return 0;
|
||||
return countBits;
|
||||
}
|
||||
|
||||
if( FBitSet( to->entityType, ENTITY_BEAM ))
|
||||
dt = Delta_FindStructByIndex( DT_CUSTOM_ENTITY_STATE_T );
|
||||
else if( player )
|
||||
@@ -1793,7 +1792,6 @@ void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *
|
||||
numChanges++;
|
||||
}
|
||||
else MSG_WriteOneBit( msg, 0 );
|
||||
|
||||
if( FBitSet( to->entityType, ENTITY_BEAM ))
|
||||
{
|
||||
dt = Delta_FindStructByIndex( DT_CUSTOM_ENTITY_STATE_T );
|
||||
@@ -1806,7 +1804,6 @@ void MSG_WriteDeltaEntity( entity_state_t *from, entity_state_t *to, sizebuf_t *
|
||||
{
|
||||
dt = Delta_FindStructByIndex( DT_ENTITY_STATE_T );
|
||||
}
|
||||
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
@@ -1924,7 +1921,6 @@ qboolean MSG_ReadDeltaEntity( sizebuf_t *msg, entity_state_t *from, entity_state
|
||||
{
|
||||
dt = Delta_FindStructByIndex( DT_ENTITY_STATE_T );
|
||||
}
|
||||
|
||||
Assert( dt && dt->bInitialized );
|
||||
|
||||
pField = dt->pFields;
|
||||
|
||||
@@ -356,7 +356,7 @@ qboolean NET_GetHostByName( const char *hostname, int family, struct sockaddr_st
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !XASH_EMSCRIPTEN && !XASH_DOS4GW && !defined XASH_NO_ASYNC_NS_RESOLVE
|
||||
#if !XASH_EMSCRIPTEN && !XASH_DOS4GW && !XASH_PSP && !defined XASH_NO_ASYNC_NS_RESOLVE
|
||||
#define CAN_ASYNC_NS_RESOLVE
|
||||
#endif // !XASH_EMSCRIPTEN && !XASH_DOS4GW && !defined XASH_NO_ASYNC_NS_RESOLVE
|
||||
|
||||
|
||||
@@ -86,7 +86,18 @@ GNU General Public License for more details.
|
||||
#define NETSPLIT_BACKUP 8
|
||||
#define NETSPLIT_BACKUP_MASK (NETSPLIT_BACKUP - 1)
|
||||
#define NETSPLIT_HEADER_SIZE 18
|
||||
|
||||
#if XASH_PSP
|
||||
#undef MULTIPLAYER_BACKUP
|
||||
#undef SINGLEPLAYER_BACKUP
|
||||
#undef NUM_PACKET_ENTITIES
|
||||
#undef MAX_CUSTOM_BASELINES
|
||||
#undef NET_MAX_FRAGMENT
|
||||
#define MULTIPLAYER_BACKUP 16
|
||||
#define SINGLEPLAYER_BACKUP 16
|
||||
#define NUM_PACKET_ENTITIES 32
|
||||
#define MAX_CUSTOM_BASELINES 8
|
||||
#define NET_MAX_FRAGMENT 32768
|
||||
#else
|
||||
#if XASH_LOW_MEMORY == 2
|
||||
#undef MULTIPLAYER_BACKUP
|
||||
#undef SINGLEPLAYER_BACKUP
|
||||
@@ -108,7 +119,7 @@ GNU General Public License for more details.
|
||||
#define MAX_CUSTOM_BASELINES 8
|
||||
#define NET_MAX_FRAGMENT 32768
|
||||
#endif
|
||||
|
||||
#endif /* XASH_PSP */
|
||||
typedef struct netsplit_chain_packet_s
|
||||
{
|
||||
// bool vector
|
||||
|
||||
@@ -177,6 +177,29 @@ GNU General Public License for more details.
|
||||
#define FRAGMENT_MAX_SIZE 64000 // maximal fragment size
|
||||
#define FRAGMENT_LOCAL_SIZE FRAGMENT_MAX_SIZE // local connection
|
||||
|
||||
#if XASH_PSP
|
||||
|
||||
#undef MAX_VISIBLE_PACKET
|
||||
#undef MAX_VISIBLE_PACKET_VIS_BYTES
|
||||
#undef MAX_EVENTS
|
||||
#undef MAX_SUPPORTED_MODELS
|
||||
#undef MAX_MODELS
|
||||
#undef MAX_SOUNDS
|
||||
#undef MAX_CUSTOM
|
||||
#undef MAX_RENDER_DECALS
|
||||
#undef MAX_RESOURCES
|
||||
|
||||
#define MAX_VISIBLE_PACKET 256
|
||||
#define MAX_VISIBLE_PACKET_VIS_BYTES ((MAX_VISIBLE_PACKET + 7) / 8)
|
||||
#define MAX_EVENTS 256
|
||||
#define MAX_SUPPORTED_MODELS 512
|
||||
#define MAX_MODELS MAX_SUPPORTED_MODELS
|
||||
#define MAX_SOUNDS 512
|
||||
#define MAX_CUSTOM 32
|
||||
#define MAX_RENDER_DECALS 256
|
||||
#define MAX_RESOURCES (MAX_MODELS+MAX_SOUNDS+MAX_CUSTOM+MAX_EVENTS)
|
||||
|
||||
#else
|
||||
#if XASH_LOW_MEMORY == 2
|
||||
#undef MAX_VISIBLE_PACKET
|
||||
#undef MAX_VISIBLE_PACKET_VIS_BYTES
|
||||
@@ -215,7 +238,7 @@ GNU General Public License for more details.
|
||||
#define MAX_RENDER_DECALS 128
|
||||
#define MAX_RESOURCES 1024
|
||||
#endif
|
||||
|
||||
#endif /* XASH_PSP */
|
||||
// Quake1 Protocol
|
||||
#define PROTOCOL_VERSION_QUAKE 15
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ wavdata_t *FS_LoadSound( const char *filename, const byte *buffer, size_t size )
|
||||
fs_offset_t filesize = 0;
|
||||
const loadwavfmt_t *format;
|
||||
byte *f;
|
||||
|
||||
|
||||
Sound_Reset(); // clear old sounddata
|
||||
Q_strncpy( loadname, filename, sizeof( loadname ));
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "soundlib.h"
|
||||
#if !XASH_PSP
|
||||
#include "libmpg/libmpg.h"
|
||||
|
||||
#pragma pack( push, 1 )
|
||||
@@ -455,3 +455,485 @@ void Stream_FreeMPG( stream_t *stream )
|
||||
|
||||
Mem_Free( stream );
|
||||
}
|
||||
|
||||
#else // XASH_PSP
|
||||
#include "platform/psp/scemp3/pspmp3.h"
|
||||
|
||||
/*
|
||||
=================================================================
|
||||
|
||||
PSP MPEG decoding
|
||||
|
||||
=================================================================
|
||||
*/
|
||||
#define MP3_ID3V1_ID "TAG"
|
||||
#define MP3_ID3V1_ID_SZ 3
|
||||
#define MP3_ID3V1_SZ 128
|
||||
|
||||
#define MP3_ID3V2_ID "ID3"
|
||||
#define MP3_ID3V2_ID_SZ 3
|
||||
#define MP3_ID3V2_SIZE_OFF 6
|
||||
#define MP3_ID3V2_SIZE_SZ 4
|
||||
#define MP3_ID3V2_HEADER_SZ 10
|
||||
|
||||
#define MP3_ERRORS_MAX 3
|
||||
|
||||
#define PCM_WIDTH 2 // always 16-bit PCM
|
||||
#define PCM_CHANNELS 2 // always 2
|
||||
|
||||
#define MP3_BUFFER_SIZE ( 128 * 1024 )
|
||||
#define PCM_BUFFER_SIZE (( 1152 * PCM_WIDTH * PCM_CHANNELS ) * 2 ) // framesample * width * channels * 2(double buffer)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int handle;
|
||||
int cachePos;
|
||||
int frameCount;
|
||||
byte *pcmTempPtr;
|
||||
} mp3_decoder_t;
|
||||
|
||||
/*
|
||||
=================
|
||||
Sound_GetID3V2SizeMPG
|
||||
=================
|
||||
*/
|
||||
__inline int Sound_GetID3V2SizeMPG( const byte *tagSize )
|
||||
{
|
||||
int size;
|
||||
byte *sizePtr = (byte*)&size;
|
||||
|
||||
// 7 bit per byte, invert endian
|
||||
sizePtr[0] = (( tagSize[3] >> 0 ) & 0x7F ) | (( tagSize[2] & 0x01 ) << 7 );
|
||||
sizePtr[1] = (( tagSize[2] >> 1 ) & 0x3F ) | (( tagSize[1] & 0x03 ) << 6 );
|
||||
sizePtr[2] = (( tagSize[1] >> 2 ) & 0x1F ) | (( tagSize[0] & 0x07 ) << 5 );
|
||||
sizePtr[3] = (( tagSize[0] >> 3 ) & 0x0F );
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
=================
|
||||
Sound_FindHeadMPG
|
||||
=================
|
||||
*/
|
||||
fs_offset_t Sound_FindHeadMPG( const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
fs_offset_t result;
|
||||
|
||||
result = 0;
|
||||
if( filesize >= MP3_ID3V2_HEADER_SZ )
|
||||
{
|
||||
if( !memcmp( buffer, MP3_ID3V2_ID, MP3_ID3V2_ID_SZ ))
|
||||
result = Sound_GetID3V2SizeMPG( &buffer[MP3_ID3V2_SIZE_OFF] ) + MP3_ID3V2_HEADER_SZ;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sound_FindTailMPG
|
||||
=================
|
||||
*/
|
||||
fs_offset_t Sound_FindTailMPG( const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
fs_offset_t result;
|
||||
|
||||
result = filesize;
|
||||
if( filesize >= MP3_ID3V1_SZ )
|
||||
{
|
||||
if( !memcmp( &buffer[filesize - MP3_ID3V1_SZ], MP3_ID3V1_ID, MP3_ID3V1_ID_SZ ))
|
||||
result -= MP3_ID3V1_SZ;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
qboolean Sound_LoadMPG( const char *name, const byte *buffer, fs_offset_t filesize )
|
||||
{
|
||||
#if 0
|
||||
int status;
|
||||
int handle;
|
||||
size_t bytesWrite = 0;
|
||||
byte out[PCM_BUFFER_SIZE] __attribute__((aligned(64)));
|
||||
fs_offset_t headOffset;
|
||||
fs_offset_t tailOffset;
|
||||
fs_offset_t contentSize;
|
||||
int frameSample;
|
||||
uint bps;
|
||||
int frameLen;
|
||||
int frameSize;
|
||||
int frameCount;
|
||||
|
||||
headOffset = Sound_FindHeadMPG( buffer, filesize );
|
||||
tailOffset = Sound_FindTailMPG( buffer, filesize );
|
||||
contentSize = tailOffset - headOffset;
|
||||
// TODO: read Xing header
|
||||
|
||||
handle = sceMp3ReserveMp3Handle( NULL );
|
||||
if ( handle < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3ReserveMp3Handle returned 0x%08X\n", handle );
|
||||
return false;
|
||||
}
|
||||
|
||||
status = sceMp3LowLevelInit( handle, &buffer[headOffset] );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3LowLevelInit returned 0x%08X\n", status );
|
||||
return false;
|
||||
}
|
||||
|
||||
frameSample = sceMp3GetMaxOutputSample( handle );
|
||||
frameSize = (( frameSample / 8 ) * sceMp3GetBitRate( handle ) * 1000 ) / sceMp3GetSamplingRate( handle );
|
||||
frameCount = contentSize / frameSize;
|
||||
|
||||
sound.channels = sceMp3GetMp3ChannelNum( handle );
|
||||
sound.rate = sceMp3GetSamplingRate( handle );
|
||||
sound.width = PCM_WIDTH; // always 16-bit PCM
|
||||
sound.loopstart = -1;
|
||||
sound.size = (frameCount * frameSample) * sound.channels * sound.width; // invalid for VBR
|
||||
/*
|
||||
status = sceMp3LowLevelDecode(handle, &buffer[headOffset + mp3usedsize], &mp3usedsize, pcm, &pcmoutsize);
|
||||
if(status < 0)
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3LowLevelDecode returned 0x%08X\n", status);
|
||||
}
|
||||
sceMp3ReleaseMp3Handle( handle );
|
||||
*/
|
||||
return true;
|
||||
#else
|
||||
Con_DPrintf( S_ERROR "Sound_LoadMPG unimplemented function!\n");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_FindHeadMPG
|
||||
=================
|
||||
*/
|
||||
SceOff Stream_FindHeadMPG( file_t *file )
|
||||
{
|
||||
SceOff result;
|
||||
byte tagId[MP3_ID3V2_ID_SZ];
|
||||
byte tagSize[MP3_ID3V2_SIZE_SZ];
|
||||
|
||||
result = 0;
|
||||
|
||||
FS_Seek( file, 0, SEEK_SET );
|
||||
|
||||
if( FS_Read( file, tagId, MP3_ID3V2_ID_SZ) < MP3_ID3V2_ID_SZ )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Sound_Mp3FindHead: ID3V2 ID read error\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
if( !memcmp( tagId, MP3_ID3V2_ID, MP3_ID3V2_ID_SZ ))
|
||||
{
|
||||
FS_Seek( file, MP3_ID3V2_SIZE_OFF, SEEK_SET );
|
||||
if( FS_Read( file, tagSize, MP3_ID3V2_SIZE_SZ ) < MP3_ID3V2_SIZE_SZ )
|
||||
Con_DPrintf( S_ERROR "Sound_Mp3FindHead: ID3V2 SIZE read error\n");
|
||||
else result = Sound_GetID3V2SizeMPG( tagSize ) + MP3_ID3V2_HEADER_SZ;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_FindTailMPG
|
||||
=================
|
||||
*/
|
||||
SceOff Stream_FindTailMPG( file_t *file )
|
||||
{
|
||||
SceOff result;
|
||||
byte tagId[MP3_ID3V1_ID_SZ];
|
||||
|
||||
result = FS_FileLength( file );
|
||||
|
||||
FS_Seek( file, result - MP3_ID3V1_SZ, SEEK_SET );
|
||||
|
||||
if( FS_Read( file, tagId, MP3_ID3V1_ID_SZ ) < MP3_ID3V1_ID_SZ )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "Sound_Mp3FindTail: ID3V1 ID read error\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
if( !memcmp( tagId, MP3_ID3V1_ID, MP3_ID3V1_ID_SZ ))
|
||||
result -= MP3_ID3V1_SZ;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_FillBufferMPG
|
||||
=================
|
||||
*/
|
||||
int Stream_FillBufferMPG( file_t *file, mp3_decoder_t *desc )
|
||||
{
|
||||
int status;
|
||||
byte *dstPtr;
|
||||
int dstSize;
|
||||
int dstPos;
|
||||
fs_offset_t readSize;
|
||||
|
||||
if( sceMp3CheckStreamDataNeeded( desc->handle ) <= 0 )
|
||||
return 0;
|
||||
|
||||
// get Info on the stream (where to fill to, how much to fill, where to fill from)
|
||||
status = sceMp3GetInfoToAddStreamData( desc->handle, &dstPtr, &dstSize, &dstPos );
|
||||
if( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3GetInfoToAddStreamData returned 0x%08X\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
// seek file to position requested
|
||||
if( desc->cachePos != dstPos )
|
||||
{
|
||||
FS_Seek( file, dstPos, SEEK_SET );
|
||||
desc->cachePos = dstPos;
|
||||
}
|
||||
|
||||
// read the amount of data
|
||||
readSize = FS_Read( file, dstPtr, dstSize );
|
||||
desc->cachePos += ( int )readSize;
|
||||
|
||||
// notify mp3 library about how much we really wrote to the stream buffer
|
||||
status = sceMp3NotifyAddStreamData( desc->handle, ( int )readSize );
|
||||
if ( status < 0 )
|
||||
Con_DPrintf( S_ERROR "sceMp3NotifyAddStreamData returned 0x%08X\n", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_OpenMPG
|
||||
=================
|
||||
*/
|
||||
stream_t *Stream_OpenMPG( const char *filename )
|
||||
{
|
||||
stream_t *stream;
|
||||
mp3_decoder_t *desc;
|
||||
file_t *file;
|
||||
int status;
|
||||
void *bufferBase;
|
||||
|
||||
file = FS_Open( filename, "rbh", false ); // hold mode
|
||||
if( !file ) return NULL;
|
||||
|
||||
// at this point we have valid stream
|
||||
stream = Mem_Calloc( host.soundpool, sizeof( stream_t ));
|
||||
stream->file = file;
|
||||
stream->pos = 0;
|
||||
|
||||
desc = Mem_Calloc( host.soundpool, sizeof( mp3_decoder_t ) + MP3_BUFFER_SIZE + PCM_BUFFER_SIZE + 63 );
|
||||
bufferBase = (void *)(((( uintptr_t )desc + sizeof( mp3_decoder_t )) & (~( 64 - 1 ))) + 64 );
|
||||
|
||||
// reserve a mp3 handle
|
||||
SceMp3InitArg mp3Init;
|
||||
mp3Init.mp3StreamStart = Stream_FindHeadMPG( file );
|
||||
mp3Init.mp3StreamEnd = Stream_FindTailMPG( file );
|
||||
mp3Init.mp3Buf = bufferBase;
|
||||
mp3Init.mp3BufSize = MP3_BUFFER_SIZE;
|
||||
mp3Init.pcmBuf = (void *)(( uintptr_t )bufferBase + MP3_BUFFER_SIZE );
|
||||
mp3Init.pcmBufSize = PCM_BUFFER_SIZE;
|
||||
|
||||
desc->cachePos = 0;
|
||||
desc->pcmTempPtr = mp3Init.pcmBuf;
|
||||
desc->handle = sceMp3ReserveMp3Handle( &mp3Init );
|
||||
if ( desc->handle < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3ReserveMp3Handle returned 0x%08X\n", desc->handle );
|
||||
Mem_Free( stream );
|
||||
Mem_Free( desc );
|
||||
FS_Close( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Fill the stream buffer with some data so that sceMp3Init has something to work with
|
||||
if( Stream_FillBufferMPG( file, desc ) != 0 )
|
||||
{
|
||||
Mem_Free( stream );
|
||||
Mem_Free( desc );
|
||||
FS_Close( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = sceMp3Init( desc->handle );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3Init returned 0x%08X\n", status );
|
||||
Mem_Free( stream );
|
||||
Mem_Free( desc );
|
||||
FS_Close( file );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
desc->frameCount = sceMp3GetFrameNum( desc->handle );
|
||||
|
||||
stream->buffsize = 0; // how many samples left from previous frame
|
||||
stream->channels = PCM_CHANNELS; // always 2 PCM channels
|
||||
stream->rate = sceMp3GetSamplingRate( desc->handle );
|
||||
stream->width = PCM_WIDTH; // always 16 bit PCM
|
||||
stream->ptr = (void *)desc;
|
||||
stream->type = WF_MPGDATA;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_ReadMPG
|
||||
|
||||
assume stream is valid
|
||||
=================
|
||||
*/
|
||||
int Stream_ReadMPG( stream_t *stream, int needBytes, void *buffer )
|
||||
{
|
||||
// buffer handling
|
||||
int bytesWritten = 0;
|
||||
mp3_decoder_t *desc;
|
||||
int errdec;
|
||||
|
||||
desc = ( mp3_decoder_t* )stream->ptr;
|
||||
|
||||
while(1)
|
||||
{
|
||||
byte *data;
|
||||
int outsize;
|
||||
|
||||
if( !stream->buffsize )
|
||||
{
|
||||
// Check if we need to fill our stream buffer
|
||||
if( Stream_FillBufferMPG( stream->file, desc ) != 0 )
|
||||
return 0;
|
||||
|
||||
for( errdec = 0; errdec < MP3_ERRORS_MAX; errdec++ )
|
||||
{
|
||||
stream->pos = sceMp3Decode( desc->handle, (SceShort16**)&desc->pcmTempPtr );
|
||||
if(( int )stream->pos >= 0 ) // decoding successful
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if( stream->pos == 0x80671402 ) // next frame header
|
||||
{
|
||||
if( Stream_FillBufferMPG( stream->file, desc ) != 0 )
|
||||
return 0;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
if(( int )stream->pos < 0 )
|
||||
{
|
||||
if( stream->pos != 0x80671402 )
|
||||
Con_DPrintf( S_ERROR "sceMp3Decode returned 0x%08X\n", stream->pos );
|
||||
return 0; // ???
|
||||
}
|
||||
}
|
||||
|
||||
// check remaining size
|
||||
if( bytesWritten + stream->pos > needBytes )
|
||||
outsize = ( needBytes - bytesWritten );
|
||||
else outsize = stream->pos;
|
||||
|
||||
// copy raw sample to output buffer
|
||||
data = (byte *)buffer + bytesWritten;
|
||||
memcpy( data, &desc->pcmTempPtr[stream->buffsize], outsize );
|
||||
bytesWritten += outsize;
|
||||
stream->pos -= outsize;
|
||||
stream->buffsize += outsize;
|
||||
|
||||
// continue from this sample on a next call
|
||||
if( bytesWritten >= needBytes )
|
||||
return bytesWritten;
|
||||
|
||||
stream->buffsize = 0; // no bytes remaining
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_SetPosMPG
|
||||
|
||||
assume stream is valid
|
||||
=================
|
||||
*/
|
||||
int Stream_SetPosMPG( stream_t *stream, int newpos )
|
||||
{
|
||||
mp3_decoder_t *desc;
|
||||
int frame;
|
||||
int status;
|
||||
|
||||
desc = ( mp3_decoder_t* )stream->ptr;
|
||||
|
||||
// get frame num
|
||||
frame = newpos / sceMp3GetMaxOutputSample( desc->handle ); // VBR?
|
||||
|
||||
if( frame < 1 || frame >= desc->frameCount - 1 )
|
||||
return false;
|
||||
|
||||
status = sceMp3ResetPlayPositionByFrame( desc->handle, frame );
|
||||
if( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3ResetPlayPositionByFrame returned 0x%08X\n", status );
|
||||
|
||||
// failed to seek for some reasons
|
||||
return false;
|
||||
}
|
||||
|
||||
// flush any previous data
|
||||
stream->buffsize = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_GetPosMPG
|
||||
|
||||
assume stream is valid
|
||||
=================
|
||||
*/
|
||||
int Stream_GetPosMPG( stream_t *stream )
|
||||
{
|
||||
mp3_decoder_t *desc;
|
||||
|
||||
desc = ( mp3_decoder_t * )stream->ptr;
|
||||
|
||||
return sceMp3GetSumDecodedSample( desc->handle );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Stream_FreeMPG
|
||||
|
||||
assume stream is valid
|
||||
=================
|
||||
*/
|
||||
void Stream_FreeMPG( stream_t *stream )
|
||||
{
|
||||
mp3_decoder_t *desc;
|
||||
|
||||
desc = ( mp3_decoder_t * )stream->ptr;
|
||||
if( desc )
|
||||
{
|
||||
sceMp3ReleaseMp3Handle( desc->handle );
|
||||
Mem_Free( desc );
|
||||
stream->ptr = NULL;
|
||||
}
|
||||
|
||||
if( stream->file )
|
||||
{
|
||||
FS_Close( stream->file );
|
||||
stream->file = NULL;
|
||||
}
|
||||
|
||||
Mem_Free( stream );
|
||||
}
|
||||
#endif // XASH_PSP
|
||||
|
||||
@@ -331,7 +331,8 @@ stream_t *Stream_OpenWAV( const char *filename )
|
||||
return NULL;
|
||||
|
||||
// open
|
||||
file = FS_Open( filename, "rb", false );
|
||||
// h - hold mode
|
||||
file = FS_Open( filename, "rbh", false );
|
||||
if( !file ) return NULL;
|
||||
|
||||
// find "RIFF" chunk
|
||||
|
||||
@@ -74,7 +74,9 @@ struct stream_s
|
||||
|
||||
// current stream state
|
||||
void *ptr; // internal decoder state
|
||||
#if !XASH_PSP
|
||||
char temp[OUTBUF_SIZE]; // mpeg decoder stuff
|
||||
#endif
|
||||
size_t pos; // actual track position (or actual buffer remains)
|
||||
int buffsize; // cached buffer size
|
||||
};
|
||||
|
||||
@@ -44,6 +44,11 @@ GNU General Public License for more details.
|
||||
#include <vitasdk.h>
|
||||
#endif
|
||||
|
||||
#if XASH_PSP
|
||||
#include <pspkernel.h>
|
||||
#include <psputility_sysparam.h>
|
||||
#endif
|
||||
|
||||
#include "menu_int.h" // _UPDATE_PAGE macro
|
||||
|
||||
#include "library.h"
|
||||
@@ -144,6 +149,10 @@ const char *Sys_GetCurrentUser( void )
|
||||
|
||||
if( pw )
|
||||
return pw->pw_name;
|
||||
#elif XASH_PSP
|
||||
static string s_userName;
|
||||
if( sceUtilityGetSystemParamString( PSP_SYSTEMPARAM_ID_STRING_NICKNAME, s_userName, sizeof( s_userName )) == 0 )
|
||||
return s_userName;
|
||||
#endif
|
||||
return "Player";
|
||||
}
|
||||
@@ -485,7 +494,12 @@ Sys_Quit
|
||||
void Sys_Quit( void )
|
||||
{
|
||||
Host_Shutdown();
|
||||
#if XASH_PSP
|
||||
sceKernelDelayThread( 50 * 1000 );
|
||||
sceKernelExitGame();
|
||||
#else
|
||||
exit( error_on_exit );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -29,8 +29,7 @@ GNU General Public License for more details.
|
||||
#include "platform/platform.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined( __GLIBC__ )
|
||||
#if ( __GLIBC__ <= 2 ) && ( __GLIBC_MINOR__ <= 30 )
|
||||
#if defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 30)
|
||||
// Library support was added in glibc 2.30.
|
||||
// Earlier glibc versions did not provide a wrapper for this system call,
|
||||
// necessitating the use of syscall(2).
|
||||
@@ -40,14 +39,7 @@ static pid_t gettid( void )
|
||||
{
|
||||
return syscall( SYS_gettid );
|
||||
}
|
||||
#endif // ( __GLIBC__ <= 2 ) && ( __GLIBC_MINOR__ <= 30 )
|
||||
|
||||
// Glibc misses this macro in POSIX headers (bits/types/sigevent_t.h)
|
||||
// but it does present in Linux headers (asm-generic/siginfo.h) and musl
|
||||
#if !defined( sigev_notify_thread_id )
|
||||
#define sigev_notify_thread_id _sigev_un._tid
|
||||
#endif // !defined( sigev_notify_thread_id )
|
||||
#endif // defined(__GLIBC__)
|
||||
#endif
|
||||
|
||||
static void *g_hsystemd;
|
||||
static int (*g_pfn_sd_notify)( int unset_environment, const char *state );
|
||||
@@ -158,7 +150,7 @@ void Linux_SetTimer( float tm )
|
||||
// this path availiable in POSIX, but may signal wrong thread...
|
||||
// sev.sigev_notify = SIGEV_SIGNAL;
|
||||
sev.sigev_notify = SIGEV_THREAD_ID;
|
||||
sev.sigev_notify_thread_id = gettid();
|
||||
sev._sigev_un._tid = gettid();
|
||||
sev.sigev_signo = DEBUG_TIMER_SIGNAL;
|
||||
sev.sigev_value.sival_ptr = &timerid;
|
||||
timer_create( CLOCK_REALTIME, &sev, &timerid );
|
||||
|
||||
@@ -58,6 +58,15 @@ void SDLash_Init( void );
|
||||
void SDLash_Shutdown( void );
|
||||
#endif
|
||||
|
||||
#if XASH_PSP
|
||||
void Platform_ReadCmd( const char *fname, int *argc, char **argv );
|
||||
SceUID Platform_LoadModule( const char *filename, int mpid, SceSize argsize, void *argp );
|
||||
int Platform_UnloadModule( SceUID modid, int *sce_code );
|
||||
|
||||
#include "psp/p5ram_psp.h"
|
||||
#include "psp/fsh_psp.h"
|
||||
#endif
|
||||
|
||||
#if XASH_ANDROID
|
||||
const char *Android_GetAndroidID( void );
|
||||
const char *Android_LoadID( void );
|
||||
|
||||
410
engine/platform/psp/fsh_psp.c
Normal file
410
engine/platform/psp/fsh_psp.c
Normal file
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
fsh_psp.c - PSP filesystem helper
|
||||
Copyright (C) 2022 Sergey Galushko
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
#include <pspiofilemgr.h>
|
||||
#include "common.h"
|
||||
#include "fsh_psp.h"
|
||||
|
||||
#define FSH_MAX_PATH 64
|
||||
#define FSH_EMPTY_STRING "*empty*"
|
||||
|
||||
typedef struct fsh_path_s
|
||||
{
|
||||
char path[FSH_MAX_PATH];
|
||||
int fsize;
|
||||
uint hashvalue;
|
||||
struct fsh_path_s *nexthash;
|
||||
}fsh_path_t;
|
||||
|
||||
typedef struct fsh_handle_s
|
||||
{
|
||||
qboolean ready;
|
||||
int count;
|
||||
char folderpath[PATH_MAX];
|
||||
int folderpath_size;
|
||||
uint empty_hash;
|
||||
int pathlist_size;
|
||||
int hashlist_size;
|
||||
fsh_path_t *pathlist;
|
||||
fsh_path_t **hashlist;
|
||||
struct fsh_handle_s *next;
|
||||
}fsh_handle_t;
|
||||
|
||||
static fsh_handle_t *fsh_poolchain = NULL;
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_AddHash
|
||||
================
|
||||
*/
|
||||
_inline void FSH_AddHash( fsh_path_t **hashlist, uint hash, fsh_path_t *fptr )
|
||||
{
|
||||
fptr->hashvalue = hash;
|
||||
fptr->nexthash = hashlist[hash];
|
||||
hashlist[hash] = fptr;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_RemoveHash
|
||||
================
|
||||
*/
|
||||
_inline void FSH_RemoveHash( fsh_path_t **hashlist, uint hash, fsh_path_t *fptr )
|
||||
{
|
||||
fsh_path_t **fptr_prev;
|
||||
|
||||
for( fptr_prev = &hashlist[hash]; *fptr_prev != NULL; fptr_prev = &( *fptr_prev )->nexthash )
|
||||
{
|
||||
if( *fptr_prev == fptr )
|
||||
{
|
||||
*fptr_prev = fptr->nexthash;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_AddFilePath
|
||||
================
|
||||
*/
|
||||
int FSH_AddFilePathWs( fsh_handle_t *handle, const char *path, int size )
|
||||
{
|
||||
uint hash;
|
||||
fsh_path_t *fptr;
|
||||
const char *strip_path;
|
||||
|
||||
if( !handle )
|
||||
return -2;
|
||||
|
||||
if( Q_strnicmp( path, handle->folderpath, handle->folderpath_size ))
|
||||
return -2;
|
||||
|
||||
strip_path = path + handle->folderpath_size + 1; // + '/'
|
||||
|
||||
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||
|
||||
if( handle->ready && handle->count > 0 )
|
||||
{
|
||||
// see if already added
|
||||
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||
{
|
||||
if( !Q_stricmp( fptr->path, strip_path ))
|
||||
return fptr - handle->pathlist; // index
|
||||
}
|
||||
|
||||
// find empty
|
||||
for( fptr = handle->hashlist[handle->empty_hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||
{
|
||||
if( !Q_stricmp( fptr->path, FSH_EMPTY_STRING ))
|
||||
{
|
||||
Q_strncpy( fptr->path, strip_path, FSH_MAX_PATH - 1 );
|
||||
|
||||
// file size
|
||||
fptr->fsize = size;
|
||||
|
||||
// remove empty from hash table
|
||||
FSH_RemoveHash( handle->hashlist, handle->empty_hash, fptr );
|
||||
|
||||
// add to hash table
|
||||
FSH_AddHash( handle->hashlist, hash, fptr );
|
||||
|
||||
return fptr - handle->pathlist; // index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create new
|
||||
if( handle->count + 1 >= handle->pathlist_size )
|
||||
return -1;
|
||||
|
||||
fptr = &handle->pathlist[handle->count];
|
||||
Q_strncpy( fptr->path, strip_path, FSH_MAX_PATH - 1 );
|
||||
|
||||
// file size
|
||||
fptr->fsize = size;
|
||||
|
||||
// add to hash table
|
||||
FSH_AddHash( handle->hashlist, hash, fptr );
|
||||
|
||||
handle->count++;
|
||||
|
||||
return fptr - handle->pathlist; // index
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_RemoveFilePath
|
||||
================
|
||||
*/
|
||||
int FSH_RemoveFilePath( fsh_handle_t *handle, const char *path )
|
||||
{
|
||||
uint hash;
|
||||
fsh_path_t *fptr, **fptr_prev;
|
||||
const char *strip_path;
|
||||
|
||||
if( !handle )
|
||||
return -2;
|
||||
|
||||
if( Q_strnicmp( path, handle->folderpath, handle->folderpath_size ))
|
||||
return -2;
|
||||
|
||||
strip_path = path + handle->folderpath_size + 1; // + '/'
|
||||
|
||||
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||
|
||||
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||
{
|
||||
if( !Q_stricmp( fptr->path, strip_path ))
|
||||
{
|
||||
memset( fptr->path, 0, FSH_MAX_PATH );
|
||||
Q_strncpy( fptr->path, FSH_EMPTY_STRING, FSH_MAX_PATH - 1 );
|
||||
fptr->fsize = -3; // undefined
|
||||
|
||||
// remove from hash table
|
||||
FSH_RemoveHash( handle->hashlist, hash, fptr );
|
||||
|
||||
// add empty to hash table
|
||||
FSH_AddHash( handle->hashlist, handle->empty_hash, fptr );
|
||||
|
||||
return fptr - handle->pathlist; // index
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_RenameFilePath
|
||||
================
|
||||
*/
|
||||
int FSH_RenameFilePath( fsh_handle_t *handle, const char *oldname, const char *newname )
|
||||
{
|
||||
uint hash;
|
||||
fsh_path_t *fptr, **fptr_prev;
|
||||
const char *strip_path;
|
||||
|
||||
if( !handle )
|
||||
return -2;
|
||||
|
||||
if( Q_strnicmp( oldname, handle->folderpath, handle->folderpath_size ))
|
||||
return -2;
|
||||
|
||||
strip_path = oldname + handle->folderpath_size + 1; // + '/'
|
||||
|
||||
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||
|
||||
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||
{
|
||||
if( !Q_stricmp( fptr->path, strip_path ))
|
||||
{
|
||||
strip_path = newname + handle->folderpath_size + 1; // + '/'
|
||||
|
||||
memset( fptr->path, 0, FSH_MAX_PATH );
|
||||
Q_strncpy( fptr->path, strip_path, FSH_MAX_PATH - 1 );
|
||||
|
||||
// remove old from hash table
|
||||
FSH_RemoveHash( handle->hashlist, hash, fptr );
|
||||
|
||||
// add new to hash table
|
||||
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||
FSH_AddHash( handle->hashlist, hash, fptr );
|
||||
|
||||
return fptr - handle->pathlist; // index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_FindSize
|
||||
================
|
||||
*/
|
||||
int FSH_FindSize( fsh_handle_t *handle, const char *path )
|
||||
{
|
||||
uint hash;
|
||||
fsh_path_t *fptr;
|
||||
const char *strip_path;
|
||||
|
||||
if( !handle )
|
||||
return -2;
|
||||
|
||||
if( !handle->ready || !handle->count || Q_strnicmp( path, handle->folderpath, handle->folderpath_size ))
|
||||
return -2;
|
||||
|
||||
strip_path = path + handle->folderpath_size + 1; // + '/'
|
||||
|
||||
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||
|
||||
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||
{
|
||||
if( !Q_stricmp( fptr->path, strip_path ))
|
||||
return fptr->fsize;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_Find
|
||||
================
|
||||
*/
|
||||
int FSH_Find( fsh_handle_t *handle, const char *path )
|
||||
{
|
||||
uint hash;
|
||||
fsh_path_t *fptr;
|
||||
const char *strip_path;
|
||||
|
||||
if( !handle )
|
||||
return -2;
|
||||
|
||||
if( !handle->ready || !handle->count || Q_strnicmp( path, handle->folderpath, handle->folderpath_size ))
|
||||
return -2;
|
||||
|
||||
strip_path = path + handle->folderpath_size + 1; // + '/'
|
||||
|
||||
hash = COM_HashKey( strip_path, handle->hashlist_size );
|
||||
|
||||
for( fptr = handle->hashlist[hash]; fptr != NULL; fptr = fptr->nexthash )
|
||||
{
|
||||
if( !Q_stricmp( fptr->path, strip_path ))
|
||||
return fptr - handle->pathlist; // index
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_ScanDir
|
||||
================
|
||||
*/
|
||||
static int FSH_ScanDir( fsh_handle_t *handle, const char *path )
|
||||
{
|
||||
SceUID dir;
|
||||
SceIoDirent entry;
|
||||
char temp[FSH_MAX_PATH];
|
||||
int result;
|
||||
int fsize;
|
||||
|
||||
if(( dir = sceIoDopen( path )) < 0 )
|
||||
return -1;
|
||||
|
||||
result = 0;
|
||||
|
||||
// iterate through the directory
|
||||
while( 1 )
|
||||
{
|
||||
// zero the dirent, to avoid possible problems with sceIoDread
|
||||
memset( &entry, 0, sizeof( SceIoDirent ));
|
||||
if( !sceIoDread( dir, &entry ))
|
||||
break;
|
||||
|
||||
// ignore the virtual directories
|
||||
if( !Q_stricmp( entry.d_name, "." ) || !Q_stricmp( entry.d_name, ".." ))
|
||||
continue;
|
||||
|
||||
sprintf( temp, "%s/%s", path, entry.d_name );
|
||||
|
||||
if(FIO_S_ISDIR( entry.d_stat.st_mode ))
|
||||
result = FSH_ScanDir( handle, temp );
|
||||
else if(FIO_S_ISREG( entry.d_stat.st_mode ))
|
||||
{
|
||||
if( entry.d_stat.st_size <= __INT_MAX__ )
|
||||
fsize = ( int )entry.d_stat.st_size;
|
||||
else fsize = -3; // undefined
|
||||
|
||||
result = FSH_AddFilePathWs( handle, temp, fsize );
|
||||
}
|
||||
else continue;
|
||||
if( result < 0 ) break;
|
||||
}
|
||||
sceIoDclose( dir );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_Create
|
||||
================
|
||||
*/
|
||||
fsh_handle_t *FSH_Create( const char *path, int maxfiles )
|
||||
{
|
||||
fsh_handle_t *handle;
|
||||
|
||||
handle = P5Ram_Alloc( sizeof( fsh_handle_t ), 1 );
|
||||
if( !handle )
|
||||
return NULL;
|
||||
|
||||
handle->pathlist_size = maxfiles;
|
||||
handle->pathlist = P5Ram_Alloc( handle->pathlist_size * sizeof( fsh_path_t ), 1 );
|
||||
if( !handle->pathlist )
|
||||
{
|
||||
P5Ram_Free( handle );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handle->hashlist_size = maxfiles >> 2;
|
||||
handle->hashlist = P5Ram_Alloc( handle->hashlist_size * sizeof( fsh_path_t* ), 1 );
|
||||
if( !handle->hashlist )
|
||||
{
|
||||
P5Ram_Free( handle );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handle->empty_hash = COM_HashKey( FSH_EMPTY_STRING, handle->hashlist_size );
|
||||
|
||||
if( !Q_strnicmp( path, "./", 2 ))
|
||||
path += 2;
|
||||
|
||||
Q_strncpy( handle->folderpath, path, FSH_MAX_PATH - 1 );
|
||||
handle->folderpath_size = Q_strlen( handle->folderpath );
|
||||
|
||||
if( FSH_ScanDir( handle, handle->folderpath ) < 0 )
|
||||
{
|
||||
P5Ram_Free( handle );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handle->next = fsh_poolchain;
|
||||
fsh_poolchain = handle;
|
||||
|
||||
handle->ready = true;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
FSH_Shutdown
|
||||
================
|
||||
*/
|
||||
void FSH_Free( fsh_handle_t *handle )
|
||||
{
|
||||
if( !handle )
|
||||
return;
|
||||
|
||||
if( handle->pathlist )
|
||||
P5Ram_Free( handle->pathlist );
|
||||
|
||||
if( handle->hashlist )
|
||||
P5Ram_Free( handle->hashlist );
|
||||
|
||||
P5Ram_Free( handle );
|
||||
}
|
||||
37
engine/platform/psp/fsh_psp.h
Normal file
37
engine/platform/psp/fsh_psp.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
fsh_psp.h - PSP filesystem helper header
|
||||
Copyright (C) 2022 Sergey Galushko
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
#ifndef FSH_PSP_H
|
||||
#define FSH_PSP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef struct fsh_handle_s fsh_handle_t;
|
||||
|
||||
int FSH_AddFilePathWs( fsh_handle_t *handle, const char *path, int size );
|
||||
#define FSH_AddFilePath( handle, path ) FSH_AddFilePathWs(handle, path, -2 )
|
||||
int FSH_RemoveFilePath( fsh_handle_t *handle, const char *path );
|
||||
int FSH_RenameFilePath( fsh_handle_t *handle, const char *oldname, const char *newname );
|
||||
int FSH_FindSize( fsh_handle_t *handle, const char *path );
|
||||
int FSH_Find( fsh_handle_t *handle, const char *path );
|
||||
fsh_handle_t *FSH_Create( const char *path, int maxfiles );
|
||||
void FSH_Free( fsh_handle_t *handle );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // P5RAM_PSP_H
|
||||
239
engine/platform/psp/in_psp.c
Normal file
239
engine/platform/psp/in_psp.c
Normal file
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
in_psp.c - PSP input component
|
||||
Copyright (C) 2021 Sergey Galushko
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
#include "common.h"
|
||||
#include "keydefs.h"
|
||||
#include "input.h"
|
||||
#include "client.h"
|
||||
|
||||
#if XASH_INPUT == INPUT_PSP
|
||||
#include <pspctrl.h>
|
||||
|
||||
#define PSP_MAX_KEYS sizeof(psp_keymap) / sizeof(struct psp_keymap_s)
|
||||
#define PSP_EXT_KEY PSP_CTRL_HOME
|
||||
|
||||
convar_t *psp_joy_dz_min;
|
||||
convar_t *psp_joy_dz_max;
|
||||
convar_t *psp_joy_cv_power;
|
||||
convar_t *psp_joy_cv_expo;
|
||||
|
||||
static struct psp_keymap_s
|
||||
{
|
||||
int srckey;
|
||||
int dstkey;
|
||||
qboolean stdpressed;
|
||||
qboolean extpressed;
|
||||
}psp_keymap[] =
|
||||
{
|
||||
#if 0
|
||||
{ PSP_CTRL_SELECT, '~' , false, false },
|
||||
{ PSP_CTRL_START, K_ESCAPE , false, false },
|
||||
{ PSP_CTRL_UP, K_UPARROW , false, false },
|
||||
{ PSP_CTRL_RIGHT, K_RIGHTARROW, false, false },
|
||||
{ PSP_CTRL_DOWN, K_DOWNARROW , false, false },
|
||||
{ PSP_CTRL_LEFT, K_LEFTARROW , false, false },
|
||||
{ PSP_CTRL_LTRIGGER, K_JOY1 , false, false },
|
||||
{ PSP_CTRL_RTRIGGER, K_JOY2 , false, false },
|
||||
{ PSP_CTRL_TRIANGLE, K_SHIFT , false, false },
|
||||
{ PSP_CTRL_CIRCLE, K_SPACE , false, false },
|
||||
{ PSP_CTRL_CROSS, K_ENTER , false, false },
|
||||
{ PSP_CTRL_SQUARE, K_BACKSPACE , false, false },
|
||||
#else
|
||||
{ PSP_CTRL_SELECT , K_MODE_BUTTON , false, false },
|
||||
{ PSP_CTRL_START , K_START_BUTTON, false, false },
|
||||
{ PSP_CTRL_UP , K_UPARROW , false, false },
|
||||
{ PSP_CTRL_RIGHT , K_RIGHTARROW , false, false },
|
||||
{ PSP_CTRL_DOWN , K_DOWNARROW , false, false },
|
||||
{ PSP_CTRL_LEFT , K_LEFTARROW , false, false },
|
||||
{ PSP_CTRL_LTRIGGER, K_L1_BUTTON , false, false },
|
||||
{ PSP_CTRL_RTRIGGER, K_R1_BUTTON , false, false },
|
||||
{ PSP_CTRL_TRIANGLE, K_Y_BUTTON , false, false },
|
||||
{ PSP_CTRL_CIRCLE , K_B_BUTTON , false, false },
|
||||
{ PSP_CTRL_CROSS , K_A_BUTTON , false, false },
|
||||
{ PSP_CTRL_SQUARE , K_X_BUTTON , false, false },
|
||||
#endif
|
||||
#if 0
|
||||
PSP_CTRL_HOME,
|
||||
PSP_CTRL_HOLD,
|
||||
PSP_CTRL_NOTE,
|
||||
PSP_CTRL_SCREEN,
|
||||
PSP_CTRL_VOLUP,
|
||||
PSP_CTRL_VOLDOWN,
|
||||
PSP_CTRL_WLAN_UP,
|
||||
PSP_CTRL_REMOTE,
|
||||
PSP_CTRL_DISC,
|
||||
PSP_CTRL_MS,
|
||||
#endif
|
||||
};
|
||||
static signed short psp_joymap[256]; /* -32768 <> 32767 */
|
||||
|
||||
static float Platform_JoyAxisCompute( float axis, float deadzone_min, float deadzone_max, float power, float expo )
|
||||
{
|
||||
float abs_axis, fabs_axis, fcurve;
|
||||
float scale, r_deadzone_max;
|
||||
qboolean flip_axis = 0;
|
||||
|
||||
expo = bound( 0.0f, expo, 1.0f );
|
||||
power = bound( 0.0f, power, 10.0f );
|
||||
deadzone_min = bound( 0.0f, deadzone_min, 127.0f );
|
||||
deadzone_max = bound( 0.0f, deadzone_max, 127.0f );
|
||||
|
||||
// (-127) - (0) - (+127)
|
||||
abs_axis = axis - 128.0f;
|
||||
if( abs_axis < 0.0f )
|
||||
{
|
||||
abs_axis = -abs_axis - 1.0f;
|
||||
flip_axis = 1;
|
||||
}
|
||||
if( abs_axis <= deadzone_min ) return 0.0f;
|
||||
r_deadzone_max = 127.0f - deadzone_max;
|
||||
if( abs_axis >= r_deadzone_max ) return ( flip_axis ? -127.0f : 127.0f );
|
||||
|
||||
scale = 127.0f / ( r_deadzone_max - deadzone_min );
|
||||
abs_axis -= deadzone_min;
|
||||
abs_axis *= scale;
|
||||
|
||||
if( expo )
|
||||
{
|
||||
// x * ( x^power * expo + x * ( 1.0 - expo ))
|
||||
fabs_axis = abs_axis / 127.0f; // 0.0f - 1.0f
|
||||
fcurve = powf(fabs_axis, power) * expo + fabs_axis * (1.0f - expo);
|
||||
abs_axis = fabs_axis * fcurve * 127.0f;
|
||||
}
|
||||
|
||||
return ( flip_axis ? -abs_axis : abs_axis );
|
||||
}
|
||||
|
||||
void Platform_RunEvents( void )
|
||||
{
|
||||
int i;
|
||||
SceCtrlData buf;
|
||||
signed short curr_X, curr_Y;
|
||||
static unsigned int last_buttons;
|
||||
static signed short last_X, last_Y;
|
||||
|
||||
sceCtrlPeekBufferPositive( &buf, 1 );
|
||||
|
||||
for( i = 0; i < PSP_MAX_KEYS; i++ )
|
||||
{
|
||||
if( buf.Buttons & PSP_EXT_KEY )
|
||||
{
|
||||
if(( last_buttons ^ buf.Buttons ) & psp_keymap[i].srckey )
|
||||
{
|
||||
if( psp_keymap[i].stdpressed )
|
||||
{
|
||||
psp_keymap[i].stdpressed = false;
|
||||
Key_Event( psp_keymap[i].dstkey, psp_keymap[i].stdpressed );
|
||||
}
|
||||
else
|
||||
{
|
||||
psp_keymap[i].extpressed = buf.Buttons & psp_keymap[i].srckey;
|
||||
Key_Event( K_AUX16 + i, psp_keymap[i].extpressed);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// release
|
||||
if( psp_keymap[i].extpressed )
|
||||
{
|
||||
psp_keymap[i].extpressed = false;
|
||||
Key_Event( K_AUX16 + i, psp_keymap[i].extpressed);
|
||||
}
|
||||
|
||||
if(( last_buttons ^ buf.Buttons ) & psp_keymap[i].srckey )
|
||||
{
|
||||
psp_keymap[i].stdpressed = buf.Buttons & psp_keymap[i].srckey;
|
||||
Key_Event( psp_keymap[i].dstkey, psp_keymap[i].stdpressed );
|
||||
}
|
||||
}
|
||||
}
|
||||
last_buttons = buf.Buttons;
|
||||
|
||||
if( FBitSet( psp_joy_dz_min->flags, FCVAR_CHANGED ) || FBitSet( psp_joy_dz_max->flags, FCVAR_CHANGED ) ||
|
||||
FBitSet( psp_joy_cv_power->flags, FCVAR_CHANGED ) || FBitSet( psp_joy_cv_expo->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
for ( i = 0; i < 256; i++ )
|
||||
{
|
||||
psp_joymap[i] = Platform_JoyAxisCompute( i, psp_joy_dz_min->value, psp_joy_dz_max->value, psp_joy_cv_power->value, psp_joy_cv_expo->value );
|
||||
psp_joymap[i] *= 256;
|
||||
}
|
||||
|
||||
ClearBits( psp_joy_dz_min->flags, FCVAR_CHANGED );
|
||||
ClearBits( psp_joy_dz_max->flags, FCVAR_CHANGED );
|
||||
ClearBits( psp_joy_cv_power->flags, FCVAR_CHANGED );
|
||||
ClearBits( psp_joy_cv_expo->flags, FCVAR_CHANGED );
|
||||
}
|
||||
|
||||
curr_X = psp_joymap[buf.Lx];
|
||||
curr_Y = psp_joymap[buf.Ly];
|
||||
|
||||
if( last_X != curr_X )
|
||||
Joy_AxisMotionEvent( 2, -curr_X );
|
||||
|
||||
if( last_Y != curr_Y )
|
||||
Joy_AxisMotionEvent( 3, -curr_Y );
|
||||
|
||||
last_X = curr_X;
|
||||
last_Y = curr_Y;
|
||||
}
|
||||
|
||||
void Platform_GetMousePos( int *x, int *y )
|
||||
{
|
||||
*x = *y = 0;
|
||||
}
|
||||
|
||||
void Platform_SetMousePos( int x, int y )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Platform_EnableTextInput( qboolean enable )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int Platform_JoyInit( int numjoy )
|
||||
{
|
||||
int i;
|
||||
|
||||
// set up cvars
|
||||
psp_joy_dz_min = Cvar_Get( "psp_joy_dz_min", "15", FCVAR_ARCHIVE, "joy deadzone min (0 - 127)" );
|
||||
psp_joy_dz_max = Cvar_Get( "psp_joy_dz_max", "0", FCVAR_ARCHIVE, "joy deadzone max (0 - 127)" );
|
||||
psp_joy_cv_power = Cvar_Get( "psp_joy_cv_power", "2", FCVAR_ARCHIVE, "joy curve power (0 - 10)" );
|
||||
psp_joy_cv_expo = Cvar_Get( "psp_joy_cv_expo", "0.5", FCVAR_ARCHIVE, "joy curve expo (0 - 1.0)" );
|
||||
|
||||
// set up the controller.
|
||||
sceCtrlSetSamplingCycle( 0 );
|
||||
sceCtrlSetSamplingMode( PSP_CTRL_MODE_ANALOG );
|
||||
|
||||
// building a joystick map
|
||||
for ( i = 0; i < 256; i++ )
|
||||
{
|
||||
psp_joymap[i] = Platform_JoyAxisCompute( i, psp_joy_dz_min->value, psp_joy_dz_max->value, psp_joy_cv_power->value, psp_joy_cv_expo->value );
|
||||
psp_joymap[i] *= 256;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Platform_MouseMove( float *x, float *y )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Platform_PreCreateMove( void )
|
||||
{
|
||||
|
||||
}
|
||||
#endif /* XASH_INPUT */
|
||||
8
engine/platform/psp/ka/KernelAccess.S
Normal file
8
engine/platform/psp/ka/KernelAccess.S
Normal file
@@ -0,0 +1,8 @@
|
||||
.set noreorder
|
||||
|
||||
#include "pspstub.s"
|
||||
|
||||
STUB_START "KernelAccess",0x40090000,0x00020005
|
||||
STUB_FUNC 0x8A5C745F,kaGeEdramSetSize
|
||||
STUB_FUNC 0x71570ECF,kaGeEdramGetHwSize
|
||||
STUB_END
|
||||
30
engine/platform/psp/ka/ka.h
Normal file
30
engine/platform/psp/ka/ka.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
kamod.h - kernel access module header
|
||||
Copyright (C) 2022 Sergey Galushko
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef KAMOD_H
|
||||
#define KAMOD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
int kaGeEdramSetSize(int size);
|
||||
int kaGeEdramGetHwSize(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // KAMOD_H
|
||||
486
engine/platform/psp/lib_psp.c
Normal file
486
engine/platform/psp/lib_psp.c
Normal file
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
lib_psp.c - dynamic library code for Sony PSP system
|
||||
Copyright (C) 2018 Flying With Gauss
|
||||
Copyright (C) 2022 Sergey Galushko
|
||||
|
||||
This program is free software: you can redistribute it and/sor modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
#include "platform/platform.h"
|
||||
|
||||
#if XASH_LIB == LIB_PSP
|
||||
#include <pspmodulemgr.h>
|
||||
#include "common.h"
|
||||
#include "library.h"
|
||||
#include "filesystem.h"
|
||||
#include "server.h"
|
||||
|
||||
#define MOD_MAXNAMELEN 256
|
||||
|
||||
typedef struct table_s
|
||||
{
|
||||
const char *name;
|
||||
void *pointer;
|
||||
} table_t;
|
||||
#include "generated_library_tables.h"
|
||||
|
||||
typedef struct mod_func_s
|
||||
{
|
||||
const char *name;
|
||||
void *addr;
|
||||
} mod_func_t;
|
||||
|
||||
typedef struct mod_handle_s
|
||||
{
|
||||
SceUID uid;
|
||||
char name[MOD_MAXNAMELEN];
|
||||
uint segAddr;
|
||||
uint segSize;
|
||||
mod_func_t *func;
|
||||
struct mod_handle_s *next;
|
||||
} mod_handle_t;
|
||||
|
||||
static mod_handle_t *modList = NULL;
|
||||
static char *modErrorPtr = NULL;
|
||||
static char modErrorBuf[1024];
|
||||
|
||||
#define Module_Error( fmt, ... ) Module_SetError( "%s: " fmt "\n", __FUNCTION__, ##__VA_ARGS__ )
|
||||
|
||||
int Module_SetError( const char *fmt, ... )
|
||||
{
|
||||
va_list args;
|
||||
int result;
|
||||
|
||||
va_start( args, fmt );
|
||||
result = Q_vsnprintf( modErrorBuf, sizeof( modErrorBuf ), fmt, args );
|
||||
va_end( args );
|
||||
|
||||
modErrorPtr = modErrorBuf;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *Module_GetError( void )
|
||||
{
|
||||
char *errPtr = modErrorPtr;
|
||||
modErrorPtr = NULL;
|
||||
return errPtr;
|
||||
}
|
||||
|
||||
static mod_handle_t *Module_Find( const char *name )
|
||||
{
|
||||
mod_handle_t *modHandle;
|
||||
|
||||
if( !name )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( modHandle = modList; modHandle; modHandle = modHandle->next )
|
||||
{
|
||||
if( !Q_strcmp( modHandle->name, name ))
|
||||
return modHandle;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *Module_Name( void *handle )
|
||||
{
|
||||
mod_handle_t *modHandle;
|
||||
|
||||
if( !handle )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( modHandle = modList; modHandle; modHandle = modHandle->next )
|
||||
{
|
||||
if( modHandle == handle )
|
||||
return modHandle->name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static mod_func_t *Module_LoadStatic( const char *name )
|
||||
{
|
||||
table_t *staticLib;
|
||||
|
||||
if( !name )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( staticLib = ( table_t* )libs; staticLib->pointer && staticLib->name; staticLib++ )
|
||||
{
|
||||
if( !Q_strcmp( staticLib->name, name ))
|
||||
return staticLib->pointer;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mod_handle_t *Module_Load( const char *name )
|
||||
{
|
||||
mod_handle_t *modHandle;
|
||||
mod_func_t *modFunc;
|
||||
qboolean skipPrefix;
|
||||
char modStaticName[32];
|
||||
void *modArg[2];
|
||||
SceUID modUid;
|
||||
uint modSegAddr, modSegSize;
|
||||
SceKernelModuleInfo info;
|
||||
char engine_cwd[PATH_MAX];
|
||||
|
||||
if( !name )
|
||||
return NULL;
|
||||
|
||||
modHandle = Module_Find( name );
|
||||
if( modHandle )
|
||||
return modHandle;
|
||||
|
||||
skipPrefix = false;
|
||||
modSegAddr = modSegSize = 0;
|
||||
|
||||
Q_sprintf( engine_cwd, "%s/", host.rootdir );
|
||||
|
||||
modArg[0] = &modFunc;
|
||||
modArg[1] = engine_cwd;
|
||||
modUid = Platform_LoadModule( name, 0, sizeof( modArg ), modArg );
|
||||
if( modUid < 0 )
|
||||
{
|
||||
COM_FileBase( name, modStaticName );
|
||||
|
||||
if( !Q_strncmp( modStaticName, "lib", 3 ) )
|
||||
skipPrefix = true;
|
||||
|
||||
modFunc = Module_LoadStatic( skipPrefix ? &modStaticName[3] : modStaticName );
|
||||
if( !modFunc )
|
||||
{
|
||||
Module_Error( "module %s error ( %#010x )", name, modUid );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
modUid = -1;
|
||||
|
||||
Con_Reportf( "Module_Load( %s ): ( static ) success!\n", name );
|
||||
}
|
||||
else
|
||||
{
|
||||
info.size = sizeof( info );
|
||||
if ( sceKernelQueryModuleInfo( modUid, &info ) >= 0 )
|
||||
{
|
||||
if( info.nsegment > 0 )
|
||||
{
|
||||
modSegAddr = info.segmentaddr[0];
|
||||
modSegSize = info.segmentsize[0];
|
||||
}
|
||||
}
|
||||
|
||||
Con_Reportf( "Module_Load( %s ): ( dynamic ) success!\n", name );
|
||||
}
|
||||
|
||||
modHandle = calloc( 1, sizeof( mod_handle_t ));
|
||||
if( !modHandle )
|
||||
{
|
||||
Module_Error( "out of memory" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Q_strncpy( modHandle->name, name, MOD_MAXNAMELEN );
|
||||
|
||||
modHandle->uid = modUid;
|
||||
modHandle->func = modFunc;
|
||||
modHandle->segAddr = modSegAddr;
|
||||
modHandle->segSize = modSegSize;
|
||||
modHandle->next = modList;
|
||||
|
||||
modList = modHandle;
|
||||
|
||||
return modHandle;
|
||||
}
|
||||
|
||||
void *Module_GetAddrByName( mod_handle_t *handle, const char *name )
|
||||
{
|
||||
mod_func_t *modFunc;
|
||||
|
||||
if( !handle || !name )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !Module_Name( handle ))
|
||||
{
|
||||
Module_SetError( "unknown handle" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !handle->func )
|
||||
{
|
||||
Module_SetError( "call Module_Load() first" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( modFunc = handle->func; modFunc->addr && modFunc->name; modFunc++ )
|
||||
{
|
||||
if( !Q_strcmp( modFunc->name, name ))
|
||||
return modFunc->addr;
|
||||
}
|
||||
|
||||
Module_Error( "func %s not found in %s", name, handle->name );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *Module_GetNameByAddr( mod_handle_t *handle, const void *addr )
|
||||
{
|
||||
mod_func_t *modFunc;
|
||||
|
||||
if( !handle || !addr )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !Module_Name( handle ))
|
||||
{
|
||||
Module_SetError( "unknown handle" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !handle->func )
|
||||
{
|
||||
Module_SetError( "call Module_Load() first" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for( modFunc = handle->func; modFunc->addr && modFunc->name; modFunc++ )
|
||||
{
|
||||
if( modFunc->addr == addr )
|
||||
return modFunc->name;
|
||||
}
|
||||
|
||||
Module_Error( "addr %#010x not found in %s", addr, handle->name );
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint Module_GetOffsetByAddr( mod_handle_t *handle, const void *addr )
|
||||
{
|
||||
uint addrUInt;
|
||||
|
||||
if( !handle || !addr )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !Module_Name( handle ))
|
||||
{
|
||||
Module_SetError( "unknown handle" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !handle->segAddr )
|
||||
{
|
||||
Module_SetError( "unknown segment" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
addrUInt = ( uint )addr;
|
||||
if( addrUInt < handle->segAddr || addrUInt >= ( handle->segAddr + handle->segSize ))
|
||||
{
|
||||
Module_SetError( "addr %#010x is out of range", addrUInt );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return addrUInt - handle->segAddr;
|
||||
}
|
||||
|
||||
void *Module_GetAddrByOffset( mod_handle_t *handle, uint offset )
|
||||
{
|
||||
if( !handle || !offset )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !Module_Name( handle ))
|
||||
{
|
||||
Module_SetError( "unknown handle" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !handle->segAddr )
|
||||
{
|
||||
Module_SetError( "unknown segment" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( offset >= handle->segSize )
|
||||
{
|
||||
Module_SetError( "offset %#010x is out of range", offset );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ( void* )( offset + handle->segAddr );
|
||||
}
|
||||
|
||||
int Module_Unload( mod_handle_t *handle )
|
||||
{
|
||||
mod_handle_t *modHandle;
|
||||
int result, sceCode;
|
||||
|
||||
if( !handle )
|
||||
{
|
||||
Module_Error( "input mismatch" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( !Module_Name( handle ))
|
||||
{
|
||||
Module_Error( "unknown handle" );
|
||||
return -2;
|
||||
}
|
||||
|
||||
if( handle->uid != -1 )
|
||||
{
|
||||
result = Platform_UnloadModule( handle->uid, &sceCode );
|
||||
if( result < 0 )
|
||||
{
|
||||
if( result == -1 )
|
||||
Module_Error( "module %s doesn't want to stop", handle->name );
|
||||
else
|
||||
Module_Error( "module %s error ( %#010x )", handle->name, sceCode );
|
||||
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
|
||||
if( handle != modList )
|
||||
{
|
||||
for( modHandle = modList; modHandle; modHandle = modHandle->next )
|
||||
{
|
||||
if( modHandle->next == handle )
|
||||
{
|
||||
modHandle->next = handle->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else modList = handle->next;
|
||||
|
||||
free( handle );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
qboolean COM_CheckLibraryDirectDependency( const char *name, const char *depname, qboolean directpath )
|
||||
{
|
||||
// TODO: implement
|
||||
return true;
|
||||
}
|
||||
|
||||
void *COM_LoadLibrary( const char *dllname, int build_ordinals_table, qboolean directpath )
|
||||
{
|
||||
dll_user_t *hInst = NULL;
|
||||
void *pHandle = NULL;
|
||||
|
||||
COM_ResetLibraryError();
|
||||
|
||||
// platforms where gameinfo mechanism is working goes here
|
||||
// and use FS_FindLibrary
|
||||
hInst = FS_FindLibrary( dllname, directpath );
|
||||
if( !hInst )
|
||||
{
|
||||
// try to find by linker(LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, LD_32_LIBRARY_PATH and so on...)
|
||||
if( !pHandle )
|
||||
{
|
||||
pHandle = Module_Load( dllname );
|
||||
if( pHandle )
|
||||
return pHandle;
|
||||
|
||||
COM_PushLibraryError( va( "Failed to find library %s", dllname ));
|
||||
COM_PushLibraryError( Module_GetError() );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if( hInst->custom_loader )
|
||||
{
|
||||
COM_PushLibraryError( va( "Custom library loader is not available. Extract library %s and fix gameinfo.txt!", hInst->fullPath ));
|
||||
Mem_Free( hInst );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( !( hInst->hInstance = Module_Load( hInst->fullPath )))
|
||||
{
|
||||
COM_PushLibraryError( Module_GetError() );
|
||||
Mem_Free( hInst );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pHandle = hInst->hInstance;
|
||||
|
||||
Mem_Free( hInst );
|
||||
|
||||
return pHandle;
|
||||
}
|
||||
|
||||
void COM_FreeLibrary( void *hInstance )
|
||||
{
|
||||
Module_Unload( hInstance );
|
||||
}
|
||||
|
||||
void *COM_GetProcAddress( void *hInstance, const char *name )
|
||||
{
|
||||
return Module_GetAddrByName( hInstance, name );
|
||||
}
|
||||
|
||||
void *COM_FunctionFromName_SR( void *hInstance, const char *pName )
|
||||
{
|
||||
void *funcAddr;
|
||||
|
||||
if( !memcmp( pName, "ofs:", 4 ))
|
||||
funcAddr = Module_GetAddrByOffset( hInstance, Q_atoi( &pName[4] ));
|
||||
else
|
||||
funcAddr = Module_GetAddrByName( hInstance, pName );
|
||||
|
||||
if( !funcAddr )
|
||||
Con_Reportf( S_ERROR "FunctionFromName: Can't get symbol %s: %s\n", pName, Module_GetError() );
|
||||
|
||||
return funcAddr;
|
||||
}
|
||||
|
||||
const char *COM_NameForFunction( void *hInstance, void *function )
|
||||
{
|
||||
static char offsetName[16];
|
||||
const char *funcName;
|
||||
uint addrOffset;
|
||||
|
||||
funcName = Module_GetNameByAddr( hInstance, function );
|
||||
if( funcName )
|
||||
return funcName;
|
||||
|
||||
addrOffset = Module_GetOffsetByAddr( hInstance, function );
|
||||
if( !addrOffset )
|
||||
return NULL;
|
||||
|
||||
Q_snprintf( offsetName, sizeof( offsetName ), "ofs:%u", addrOffset );
|
||||
Con_Reportf( "COM_NameForFunction: %s\n", offsetName );
|
||||
|
||||
return offsetName;
|
||||
}
|
||||
#endif // XASH_LIB == LIB_PSP
|
||||
165
engine/platform/psp/p5ram_psp.c
Normal file
165
engine/platform/psp/p5ram_psp.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
p5ram_psp.c - PSP P5 memory allocator
|
||||
Copyright (C) 2022 Sergey Galushko
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
#include <pspkernel.h>
|
||||
#include <psppower.h>
|
||||
#include <pspsuspend.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "p5ram_psp.h"
|
||||
|
||||
#define P5RAM_ALIGN( x, a ) ((( x ) + (( typeof( x ))( a ) - 1 )) & ~( typeof( x )( a ) - 1 ))
|
||||
|
||||
#define P5RAM_CHECK( addr ) ((( unsigned int )addr >= ( unsigned int )p5ram_addr) && (( unsigned int )addr < ( unsigned int )p5ram_addr + p5ram_size))
|
||||
|
||||
#define P5RAM_FLAG_INIT 0x01
|
||||
#define P5RAM_FLAG_SUSPENDED 0x02
|
||||
|
||||
typedef struct __attribute__(( aligned( 64 ))) p5ram_info_s
|
||||
{
|
||||
SceUID uid;
|
||||
size_t size;
|
||||
struct p5ram_info_s *next;
|
||||
}p5ram_info_t;
|
||||
|
||||
static unsigned char p5ram_flags = 0x00;
|
||||
static p5ram_info_t *p5ram_poolchain = NULL;
|
||||
static void *p5ram_addr;
|
||||
static unsigned int p5ram_size;
|
||||
|
||||
int P5Ram_Init( void )
|
||||
{
|
||||
int result;
|
||||
|
||||
if( p5ram_flags & P5RAM_FLAG_INIT )
|
||||
return -1;
|
||||
|
||||
result = sceKernelVolatileMemLock( 0, &p5ram_addr, &p5ram_size );
|
||||
if( result == 0 )
|
||||
p5ram_flags |= P5RAM_FLAG_INIT;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void *P5Ram_Alloc( size_t size, int clear )
|
||||
{
|
||||
SceUID uid;
|
||||
void *ptr;
|
||||
|
||||
if(!( p5ram_flags & P5RAM_FLAG_INIT ))
|
||||
return NULL;
|
||||
|
||||
uid = sceKernelAllocPartitionMemory( 5, "USER P5", PSP_SMEM_Low, size + sizeof( p5ram_info_t ), NULL );
|
||||
if( uid < 0 ) return NULL;
|
||||
|
||||
ptr = sceKernelGetBlockHeadAddr( uid );
|
||||
(( p5ram_info_t* )ptr )->uid = uid;
|
||||
(( p5ram_info_t* )ptr )->size = size;
|
||||
(( p5ram_info_t* )ptr )->next = p5ram_poolchain;
|
||||
if( clear ) memset(( unsigned char* )ptr + sizeof( p5ram_info_t ), 0, size );
|
||||
|
||||
p5ram_poolchain = ptr;
|
||||
|
||||
return ( void* )(( unsigned char* )ptr + sizeof( p5ram_info_t ));
|
||||
}
|
||||
|
||||
void P5Ram_Free( void *ptr )
|
||||
{
|
||||
p5ram_info_t *info, *next_ptr;
|
||||
|
||||
if( !( p5ram_flags & P5RAM_FLAG_INIT ) || ptr == NULL ) return;
|
||||
|
||||
info = ( p5ram_info_t* )((unsigned char*)ptr - sizeof( p5ram_info_t ));
|
||||
|
||||
if( info == p5ram_poolchain )
|
||||
{
|
||||
p5ram_poolchain = p5ram_poolchain->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_ptr = p5ram_poolchain;
|
||||
while( next_ptr )
|
||||
{
|
||||
if( next_ptr->next == info )
|
||||
{
|
||||
next_ptr->next = info->next;
|
||||
break;
|
||||
}
|
||||
next_ptr = next_ptr->next;
|
||||
}
|
||||
}
|
||||
|
||||
sceKernelFreePartitionMemory( info->uid );
|
||||
}
|
||||
|
||||
void P5Ram_FreeAll( void )
|
||||
{
|
||||
p5ram_info_t *next_ptr;
|
||||
|
||||
while( p5ram_poolchain )
|
||||
{
|
||||
next_ptr = p5ram_poolchain->next;
|
||||
sceKernelFreePartitionMemory( p5ram_poolchain->uid );
|
||||
p5ram_poolchain = next_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
void P5Ram_Shutdown( void )
|
||||
{
|
||||
if( !( p5ram_flags & P5RAM_FLAG_INIT ))
|
||||
return;
|
||||
|
||||
P5Ram_FreeAll();
|
||||
sceKernelVolatileMemUnlock( 0 );
|
||||
|
||||
p5ram_flags &= ~P5RAM_FLAG_INIT;
|
||||
}
|
||||
|
||||
void P5Ram_PowerCallback( int count, int arg, void *common )
|
||||
{
|
||||
if( !( p5ram_flags & ( P5RAM_FLAG_INIT | P5RAM_FLAG_SUSPENDED )))
|
||||
return;
|
||||
|
||||
if ( arg & PSP_POWER_CB_POWER_SWITCH || arg & PSP_POWER_CB_SUSPENDING )
|
||||
{
|
||||
P5Ram_Shutdown();
|
||||
p5ram_flags |= P5RAM_FLAG_SUSPENDED;
|
||||
}
|
||||
else if ( arg & PSP_POWER_CB_RESUMING )
|
||||
{
|
||||
}
|
||||
else if ( arg & PSP_POWER_CB_RESUME_COMPLETE )
|
||||
{
|
||||
P5Ram_Init();
|
||||
p5ram_flags &= ~P5RAM_FLAG_SUSPENDED;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef P5RAM_DEBUG
|
||||
void P5Ram_Print( void )
|
||||
{
|
||||
p5ram_info_t *next_ptr;
|
||||
|
||||
printf("+++++++++++++++++++++++++++++\n");
|
||||
next_ptr = p5ram_poolchain;
|
||||
while( next_ptr )
|
||||
{
|
||||
printf("P5 ALLOC [ 0x%08X 0x%08X 0x%08X 0x%08X ]\n", next_ptr, next_ptr->uid, next_ptr->size, next_ptr->next );
|
||||
next_ptr = next_ptr->next;
|
||||
}
|
||||
printf("+++++++++++++++++++++++++++++\n");
|
||||
}
|
||||
#endif
|
||||
38
engine/platform/psp/p5ram_psp.h
Normal file
38
engine/platform/psp/p5ram_psp.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
p5ram_psp.h - PSP P5 memory allocator header
|
||||
Copyright (C) 2022 Sergey Galushko
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
#ifndef P5RAM_PSP_H
|
||||
#define P5RAM_PSP_H
|
||||
|
||||
//#define P5RAM_DEBUG
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
int P5Ram_Init( void );
|
||||
void *P5Ram_Alloc( size_t size, int clear );
|
||||
void P5Ram_Free( void *ptr );
|
||||
void P5Ram_FreeAll( void );
|
||||
void P5Ram_Shutdown( void );
|
||||
void P5Ram_PowerCallback( int count, int arg, void *common );
|
||||
#ifdef P5RAM_DEBUG
|
||||
void P5Ram_Print( void );
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // P5RAM_PSP_H
|
||||
248
engine/platform/psp/scemp3/pspmp3.h
Normal file
248
engine/platform/psp/scemp3/pspmp3.h
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* PSP Software Development Kit - https://github.com/pspdev
|
||||
* -----------------------------------------------------------------------
|
||||
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
|
||||
*
|
||||
* pspmp3.h - Prototypes for the sceMp3 library
|
||||
*
|
||||
* Copyright (c) 2008 David Perry <tias_dp@hotmail.com>
|
||||
* Copyright (c) 2008 Alexander Berl <raphael@fx-world.org>
|
||||
* Copyright (c) 2022 Sergey Galushko
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SCELIBMP3_H__
|
||||
#define __SCELIBMP3_H__
|
||||
|
||||
#include <psptypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct SceMp3InitArg {
|
||||
/** Stream start position */
|
||||
SceOff mp3StreamStart;
|
||||
/** Stream end position */
|
||||
SceOff mp3StreamEnd;
|
||||
/** Pointer to a buffer to contain raw mp3 stream data (+1472 bytes workspace) */
|
||||
SceUChar8* mp3Buf;
|
||||
/** Size of mp3Buf buffer (must be >= 8192) */
|
||||
SceInt32 mp3BufSize;
|
||||
/** Pointer to decoded pcm samples buffer */
|
||||
SceUChar8* pcmBuf;
|
||||
/** Size of pcmBuf buffer (must be >= 9216) */
|
||||
SceInt32 pcmBufSize;
|
||||
} SceMp3InitArg;
|
||||
|
||||
/**
|
||||
* sceMp3ReserveMp3Handle
|
||||
*
|
||||
* @param args - Pointer to SceMp3InitArg structure
|
||||
*
|
||||
* @return sceMp3 handle on success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3ReserveMp3Handle(SceMp3InitArg* args);
|
||||
|
||||
/**
|
||||
* sceMp3ReleaseMp3Handle
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3ReleaseMp3Handle(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3InitResource
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3InitResource();
|
||||
|
||||
/**
|
||||
* sceMp3TermResource
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3TermResource();
|
||||
|
||||
/**
|
||||
* sceMp3Init
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3Init(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3Decode
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param dst - Pointer to destination pcm samples buffer
|
||||
*
|
||||
* @return number of bytes in decoded pcm buffer, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3Decode(SceInt32 handle, SceShort16** dst);
|
||||
|
||||
/**
|
||||
* sceMp3GetInfoToAddStreamData
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param dst - Pointer to stream data buffer
|
||||
* @param towrite - Space remaining in stream data buffer
|
||||
* @param srcpos - Position in source stream to start reading from
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3GetInfoToAddStreamData(SceInt32 handle, SceUChar8** dst, SceInt32* towrite, SceInt32* srcpos);
|
||||
|
||||
/**
|
||||
* sceMp3NotifyAddStreamData
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param size - number of bytes added to the stream data buffer
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3NotifyAddStreamData(SceInt32 handle, SceInt32 size);
|
||||
|
||||
/**
|
||||
* sceMp3CheckStreamDataNeeded
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return 1 if more stream data is needed, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3CheckStreamDataNeeded(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3SetLoopNum
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param loop - Number of loops
|
||||
*
|
||||
* @return 0 if success, < 0 on error.
|
||||
*/
|
||||
SceInt32 sceMp3SetLoopNum(SceInt32 handle, SceInt32 loop);
|
||||
|
||||
/**
|
||||
* sceMp3GetLoopNum
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Number of loops
|
||||
*/
|
||||
SceInt32 sceMp3GetLoopNum(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetSumDecodedSample
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Number of decoded samples
|
||||
*/
|
||||
SceInt32 sceMp3GetSumDecodedSample(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetMaxOutputSample
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Number of max samples to output
|
||||
*/
|
||||
SceInt32 sceMp3GetMaxOutputSample(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetSamplingRate
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Sampling rate of the mp3
|
||||
*/
|
||||
SceInt32 sceMp3GetSamplingRate(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetBitRate
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Bitrate of the mp3
|
||||
*/
|
||||
SceInt32 sceMp3GetBitRate(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetMp3ChannelNum
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return Number of channels of the mp3
|
||||
*/
|
||||
SceInt32 sceMp3GetMp3ChannelNum(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3ResetPlayPosition
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3ResetPlayPosition(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3GetFrameNum
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3GetFrameNum(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3ResetPlayPositionByFrame
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param frame - frame
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3ResetPlayPositionByFrame(SceInt32 handle, SceUInt32 frame);
|
||||
|
||||
/**
|
||||
* sceMp3GetMPEGVersion
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3GetMPEGVersion(SceInt32 handle);
|
||||
|
||||
/**
|
||||
* sceMp3LowLevelInit
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param src - Pointer to a buffer to contain raw mp3 stream data
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3LowLevelInit(SceInt32 handle, SceUChar8* src);
|
||||
|
||||
/**
|
||||
* sceMp3LowLevelDecode
|
||||
*
|
||||
* @param handle - sceMp3 handle
|
||||
* @param mp3src -
|
||||
* @param mp3srcused -
|
||||
* @param pcmdst -
|
||||
* @param pcmdstoutsz -
|
||||
*
|
||||
* @return < 0 on error
|
||||
*/
|
||||
SceInt32 sceMp3LowLevelDecode(SceInt32 handle, SceUChar8* mp3src, SceUInt32* mp3srcused, SceShort16* pcmdst, SceUInt32* pcmdstoutsz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
29
engine/platform/psp/scemp3/sceMp3.S
Normal file
29
engine/platform/psp/scemp3/sceMp3.S
Normal file
@@ -0,0 +1,29 @@
|
||||
.set noreorder
|
||||
|
||||
#include "pspimport.s"
|
||||
|
||||
IMPORT_START "sceMp3",0x00090011
|
||||
IMPORT_FUNC "sceMp3",0x07EC321A,sceMp3ReserveMp3Handle
|
||||
IMPORT_FUNC "sceMp3",0x0DB149F4,sceMp3NotifyAddStreamData
|
||||
IMPORT_FUNC "sceMp3",0x2A368661,sceMp3ResetPlayPosition
|
||||
IMPORT_FUNC "sceMp3",0x354D27EA,sceMp3GetSumDecodedSample
|
||||
IMPORT_FUNC "sceMp3",0x35750070,sceMp3InitResource
|
||||
IMPORT_FUNC "sceMp3",0x3C2FA058,sceMp3TermResource
|
||||
IMPORT_FUNC "sceMp3",0x3CEF484F,sceMp3SetLoopNum
|
||||
IMPORT_FUNC "sceMp3",0x44E07129,sceMp3Init
|
||||
IMPORT_FUNC "sceMp3",0x732B042A,sceMp3EndEntry
|
||||
IMPORT_FUNC "sceMp3",0x7F696782,sceMp3GetMp3ChannelNum
|
||||
IMPORT_FUNC "sceMp3",0x87677E40,sceMp3GetBitRate
|
||||
IMPORT_FUNC "sceMp3",0x87C263D1,sceMp3GetMaxOutputSample
|
||||
IMPORT_FUNC "sceMp3",0x8AB81558,sceMp3StartEntry
|
||||
IMPORT_FUNC "sceMp3",0x8F450998,sceMp3GetSamplingRate
|
||||
IMPORT_FUNC "sceMp3",0xA703FE0F,sceMp3GetInfoToAddStreamData
|
||||
IMPORT_FUNC "sceMp3",0xD021C0FB,sceMp3Decode
|
||||
IMPORT_FUNC "sceMp3",0xD0A56296,sceMp3CheckStreamDataNeeded
|
||||
IMPORT_FUNC "sceMp3",0xD8F54A51,sceMp3GetLoopNum
|
||||
IMPORT_FUNC "sceMp3",0xF5478233,sceMp3ReleaseMp3Handle
|
||||
IMPORT_FUNC "sceMp3",0xAE6D2027,sceMp3GetMPEGVersion
|
||||
IMPORT_FUNC "sceMp3",0x3548AEC8,sceMp3GetFrameNum
|
||||
IMPORT_FUNC "sceMp3",0x0840E808,sceMp3ResetPlayPositionByFrame
|
||||
IMPORT_FUNC "sceMp3",0x1B839B83,sceMp3LowLevelInit
|
||||
IMPORT_FUNC "sceMp3",0xE3EE2C81,sceMp3LowLevelDecode
|
||||
275
engine/platform/psp/snd_psp.c
Normal file
275
engine/platform/psp/snd_psp.c
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
snd_psp.c - psp sound hardware output
|
||||
Copyright (C) 2022 Sergey Galushko
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "platform/platform.h"
|
||||
#if XASH_SOUND == SOUND_PSP
|
||||
#include <malloc.h>
|
||||
|
||||
#include <pspaudio.h>
|
||||
#include <pspkernel.h>
|
||||
#include <pspdmac.h>
|
||||
|
||||
#include "sound.h"
|
||||
|
||||
#define PSP_NUM_AUDIO_SAMPLES 1024 // must be multiple of 64
|
||||
#define PSP_OUTPUT_CHANNELS 2
|
||||
#define PSP_OUTPUT_BUFFER_SIZE (( PSP_NUM_AUDIO_SAMPLES ) * ( PSP_OUTPUT_CHANNELS ))
|
||||
|
||||
static struct
|
||||
{
|
||||
SceUID threadUID;
|
||||
SceUID semaUID;
|
||||
int channel;
|
||||
volatile int volL;
|
||||
volatile int volR;
|
||||
volatile int running;
|
||||
} snd_psp = { -1, -1, -1, PSP_AUDIO_VOLUME_MAX, PSP_AUDIO_VOLUME_MAX, 1 };
|
||||
|
||||
static short snd_psp_buff[2][PSP_OUTPUT_BUFFER_SIZE] __attribute__(( aligned( 64 )));
|
||||
|
||||
/*
|
||||
==================
|
||||
SNDDMA_MainThread
|
||||
|
||||
Copy samples
|
||||
==================
|
||||
*/
|
||||
static int SNDDMA_MainThread( SceSize args, void *argp )
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
while( snd_psp.running )
|
||||
{
|
||||
sceKernelWaitSema( snd_psp.semaUID, 1, NULL );
|
||||
|
||||
int len = PSP_OUTPUT_BUFFER_SIZE;
|
||||
int size = dma.samples;
|
||||
int pos = dma.samplepos;
|
||||
int wrapped = pos + len - size;
|
||||
|
||||
if( wrapped < 0 )
|
||||
{
|
||||
sceDmacMemcpy( snd_psp_buff[index], dma.buffer + ( pos * 2 ), len * 2 );
|
||||
dma.samplepos += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
int remaining = size - pos;
|
||||
sceDmacMemcpy( snd_psp_buff[index], dma.buffer + ( pos * 2 ), remaining * 2 );
|
||||
if( wrapped > 0 )
|
||||
sceDmacMemcpy( snd_psp_buff[index] + ( remaining * 2 ), dma.buffer, wrapped * 2 );
|
||||
dma.samplepos = wrapped;
|
||||
}
|
||||
|
||||
sceKernelSignalSema( snd_psp.semaUID, 1 );
|
||||
|
||||
sceAudioOutputPannedBlocking( snd_psp.channel, snd_psp.volL, snd_psp.volR, snd_psp_buff[index] );
|
||||
index = !index;
|
||||
}
|
||||
|
||||
sceKernelExitThread( 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SNDDMA_Init
|
||||
|
||||
Try to find a sound device to mix for.
|
||||
Returns false if nothing is found.
|
||||
==================
|
||||
*/
|
||||
qboolean SNDDMA_Init( void )
|
||||
{
|
||||
int samplecount;
|
||||
|
||||
dma.format.speed = SOUND_DMA_SPEED;
|
||||
dma.format.channels = PSP_OUTPUT_CHANNELS;
|
||||
dma.format.width = 2;
|
||||
|
||||
// must be multiple of 64
|
||||
samplecount = s_samplecount->value;
|
||||
if( !samplecount )
|
||||
samplecount = 0x4000;
|
||||
|
||||
dma.samples = samplecount * PSP_OUTPUT_CHANNELS;
|
||||
dma.samplepos = 0;
|
||||
dma.buffer = memalign( 64, dma.samples * 2 ); // 16 bit
|
||||
if( !dma.buffer )
|
||||
return false;
|
||||
|
||||
// clearing buffers
|
||||
memset( dma.buffer, 0, dma.samples * 2 );
|
||||
memset( snd_psp_buff, 0, sizeof( snd_psp_buff ));
|
||||
|
||||
// allocate and initialize a hardware output channel
|
||||
snd_psp.channel = sceAudioChReserve( PSP_AUDIO_NEXT_CHANNEL,
|
||||
PSP_NUM_AUDIO_SAMPLES, PSP_AUDIO_FORMAT_STEREO );
|
||||
if( snd_psp.channel < 0 )
|
||||
{
|
||||
SNDDMA_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
// create semaphore
|
||||
snd_psp.semaUID = sceKernelCreateSema( "sound_sema", 0, 1, 255, NULL );
|
||||
if( snd_psp.semaUID <= 0 )
|
||||
{
|
||||
SNDDMA_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
// create audio thread
|
||||
snd_psp.threadUID = sceKernelCreateThread( "sound_thread", SNDDMA_MainThread, 0x12, 0x8000, 0, 0 );
|
||||
if( snd_psp.threadUID < 0 )
|
||||
{
|
||||
SNDDMA_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
// start audio thread
|
||||
if( sceKernelStartThread( snd_psp.threadUID, 0, 0 ) < 0 )
|
||||
{
|
||||
SNDDMA_Shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
Con_Printf( "Using PSP audio driver: %d Hz\n", dma.format.speed );
|
||||
|
||||
dma.initialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_GetDMAPos
|
||||
|
||||
return the current sample position (in mono samples read)
|
||||
inside the recirculating dma buffer, so the mixing code will know
|
||||
how many sample are required to fill it up.
|
||||
===============
|
||||
*/
|
||||
int SNDDMA_GetDMAPos( void )
|
||||
{
|
||||
return dma.samplepos;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_GetSoundtime
|
||||
|
||||
update global soundtime
|
||||
===============
|
||||
*/
|
||||
int SNDDMA_GetSoundtime( void )
|
||||
{
|
||||
static int buffers, oldsamplepos;
|
||||
int samplepos, fullsamples;
|
||||
|
||||
fullsamples = dma.samples / 2;
|
||||
|
||||
// it is possible to miscount buffers
|
||||
// if it has wrapped twice between
|
||||
// calls to S_Update. Oh well.
|
||||
samplepos = SNDDMA_GetDMAPos();
|
||||
|
||||
if( samplepos < oldsamplepos )
|
||||
{
|
||||
buffers++; // buffer wrapped
|
||||
|
||||
if( paintedtime > 0x40000000 )
|
||||
{
|
||||
// time to chop things off to avoid 32 bit limits
|
||||
buffers = 0;
|
||||
paintedtime = fullsamples;
|
||||
S_StopAllSounds( true );
|
||||
}
|
||||
}
|
||||
|
||||
oldsamplepos = samplepos;
|
||||
|
||||
return ( buffers * fullsamples + samplepos / 2 );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_BeginPainting
|
||||
|
||||
Makes sure dma.buffer is valid
|
||||
===============
|
||||
*/
|
||||
void SNDDMA_BeginPainting( void )
|
||||
{
|
||||
if( snd_psp.semaUID > 0 )
|
||||
sceKernelWaitSema( snd_psp.semaUID, 1, NULL );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_Submit
|
||||
|
||||
Send sound to device if buffer isn't really the dma buffer
|
||||
Also unlocks the dsound buffer
|
||||
===============
|
||||
*/
|
||||
void SNDDMA_Submit( void )
|
||||
{
|
||||
if( snd_psp.semaUID > 0 )
|
||||
sceKernelSignalSema( snd_psp.semaUID, 1 );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
SNDDMA_Shutdown
|
||||
|
||||
Reset the sound device for exiting
|
||||
===============
|
||||
*/
|
||||
void SNDDMA_Shutdown( void )
|
||||
{
|
||||
Con_Printf("Shutting down audio.\n");
|
||||
|
||||
snd_psp.running = 0;
|
||||
|
||||
if( snd_psp.threadUID >= 0 )
|
||||
{
|
||||
sceKernelWaitThreadEnd( snd_psp.threadUID, NULL );
|
||||
sceKernelDeleteThread( snd_psp.threadUID );
|
||||
snd_psp.threadUID = -1;
|
||||
}
|
||||
|
||||
if( snd_psp.semaUID > 0 )
|
||||
{
|
||||
sceKernelDeleteSema( snd_psp.semaUID );
|
||||
snd_psp.semaUID = -1;
|
||||
}
|
||||
|
||||
if( snd_psp.channel >= 0 )
|
||||
{
|
||||
sceAudioChRelease( snd_psp.channel );
|
||||
snd_psp.channel = -1;
|
||||
}
|
||||
|
||||
if( dma.buffer )
|
||||
{
|
||||
free( dma.buffer );
|
||||
dma.buffer = NULL;
|
||||
}
|
||||
|
||||
dma.initialized = false;
|
||||
}
|
||||
|
||||
#endif // XASH_SOUND == SOUND_PSP
|
||||
353
engine/platform/psp/sys_psp.c
Normal file
353
engine/platform/psp/sys_psp.c
Normal file
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
sys_psp.c - PSP System utils
|
||||
Copyright (C) 2021 Sergey Galushko
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "platform/platform.h"
|
||||
#include "platform/psp/ka/ka.h"
|
||||
#include "platform/psp/scemp3/pspmp3.h"
|
||||
#include <pspsdk.h>
|
||||
#include <pspkernel.h>
|
||||
#include <psppower.h>
|
||||
#include <psprtc.h>
|
||||
#include <pspprof.h>
|
||||
#include <pspctrl.h>
|
||||
#include <psputility.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
PSP_MODULE_INFO( "Xash3D", PSP_MODULE_USER, 1, 0 );
|
||||
PSP_MAIN_THREAD_ATTR( PSP_THREAD_ATTR_USER | PSP_THREAD_ATTR_VFPU );
|
||||
PSP_MAIN_THREAD_STACK_SIZE_KB( 512 );
|
||||
PSP_HEAP_SIZE_KB( -3 * 1024 ); /* 3 MB for prx modules */
|
||||
|
||||
static qboolean psp_audiolib_init = false;
|
||||
|
||||
static int Platform_ExitCallback( int count, int arg, void *common )
|
||||
{
|
||||
host.crashed = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Platform_PowerCallback( int count, int arg, void *common )
|
||||
{
|
||||
P5Ram_PowerCallback( count, arg, common );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Platform_CallbackThread( SceSize args, void *argp )
|
||||
{
|
||||
int cbid;
|
||||
|
||||
//cbid = sceKernelCreateCallback( "Exit Callback", Platform_ExitCallback, NULL );
|
||||
//sceKernelRegisterExitCallback( cbid );
|
||||
|
||||
cbid = sceKernelCreateCallback( "Power Callback", Platform_PowerCallback, NULL );
|
||||
scePowerRegisterCallback( 0, cbid );
|
||||
|
||||
sceKernelSleepThreadCB();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sets up the callback thread and returns its thread id */
|
||||
static int Platform_SetupCallbacks( void )
|
||||
{
|
||||
int thid = 0;
|
||||
|
||||
thid = sceKernelCreateThread("update_thread", Platform_CallbackThread, 0x11, 0xFA0, 0, 0);
|
||||
if(thid >= 0)
|
||||
{
|
||||
sceKernelStartThread(thid, 0, 0);
|
||||
}
|
||||
return thid;
|
||||
}
|
||||
|
||||
#if XASH_TIMER == TIMER_PSP
|
||||
double Platform_DoubleTime( void )
|
||||
{
|
||||
return ( double )sceKernelGetSystemTimeWide() * 0.000001; // microseconds to seconds
|
||||
}
|
||||
|
||||
void Platform_Sleep( int msec )
|
||||
{
|
||||
sceKernelDelayThread( msec * 1000 );
|
||||
}
|
||||
#endif
|
||||
|
||||
void *Platform_GetNativeObject( const char *name )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Platform_Vibrate( float life, char flags )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Platform_GetClipboardText( char *buffer, size_t size )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Platform_SetClipboardText( const char *buffer, size_t size )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Platform_ShellExecute( const char *path, const char *parms )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#if XASH_MESSAGEBOX == MSGBOX_PSP
|
||||
void Platform_MessageBox( const char *title, const char *message, qboolean parentMainWindow )
|
||||
{
|
||||
static qboolean g_dbgscreen = false;
|
||||
|
||||
// Clear the sound buffer.
|
||||
S_StopAllSounds( true );
|
||||
|
||||
// Print message to the debug screen.
|
||||
if ( !g_dbgscreen )
|
||||
{
|
||||
pspDebugScreenInit();
|
||||
g_dbgscreen = true;
|
||||
}
|
||||
pspDebugScreenSetTextColor( 0x0080ff );
|
||||
pspDebugScreenPrintf( "\n\n\n\n%s:\n", title );
|
||||
pspDebugScreenSetTextColor( 0x0000ff );
|
||||
pspDebugScreenPrintData( message, Q_strlen( message ) );
|
||||
pspDebugScreenSetTextColor( 0xffffff );
|
||||
pspDebugScreenPrintf( "\n\nPress X to continue.\n" );
|
||||
|
||||
// Wait for a X button press.
|
||||
SceCtrlData pad;
|
||||
do
|
||||
{
|
||||
sceCtrlReadBufferPositive( &pad, 1 );
|
||||
}
|
||||
while( !( pad.Buttons & PSP_CTRL_CROSS ) );
|
||||
pspDebugScreenClear();
|
||||
}
|
||||
#endif // XASH_MESSAGEBOX == MSGBOX_PSP
|
||||
|
||||
void Platform_ReadCmd( const char *fname, int *argc, char **argv )
|
||||
{
|
||||
int cmd_fd;
|
||||
size_t cmd_fsize;
|
||||
byte *cmd_buff;
|
||||
int i, j = 0;
|
||||
|
||||
cmd_fd = sceIoOpen( fname, PSP_O_RDONLY, 0777 );
|
||||
if( cmd_fd > 0 )
|
||||
{
|
||||
cmd_fsize = sceIoLseek( cmd_fd, 0, PSP_SEEK_END );
|
||||
sceIoLseek( cmd_fd, 0, PSP_SEEK_SET );
|
||||
|
||||
printf( "CMD FILE(%s) Size: %i\n", fname, cmd_fsize );
|
||||
|
||||
if( cmd_fsize == 0 ) return;
|
||||
|
||||
cmd_buff = malloc( cmd_fsize );
|
||||
if( !cmd_buff )
|
||||
{
|
||||
printf( "CMD FILE(%s) Memory allocation error!\n", fname );
|
||||
sceIoClose(cmd_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if( sceIoRead(cmd_fd, cmd_buff, cmd_fsize) >= 0 )
|
||||
{
|
||||
for( i = 0; i < cmd_fsize; i++ )
|
||||
{
|
||||
if( isspace( cmd_buff[i] ) != 0 )
|
||||
{
|
||||
if( j == 0 ) continue;
|
||||
|
||||
argv[*argc] = malloc( j + 1 );
|
||||
if( !argv[*argc] )
|
||||
{
|
||||
printf( "CMD FILE(%s) Memory allocation error!\n", fname );
|
||||
free( cmd_buff );
|
||||
sceIoClose( cmd_fd );
|
||||
return;
|
||||
}
|
||||
memcpy( argv[*argc], &cmd_buff[i - j], j );
|
||||
argv[*argc][j] = 0x00;
|
||||
( int )( *argc )++;
|
||||
j = 0;
|
||||
}
|
||||
else j++;
|
||||
|
||||
}
|
||||
if( j != 0 )
|
||||
{
|
||||
argv[*argc] = malloc( j + 1 );
|
||||
if( !argv[*argc] )
|
||||
{
|
||||
printf( "CMD FILE(%s) Memory allocation error!\n", fname );
|
||||
free( cmd_buff );
|
||||
sceIoClose( cmd_fd );
|
||||
return;
|
||||
}
|
||||
memcpy( argv[*argc], &cmd_buff[i - j], j );
|
||||
argv[*argc][j] = 0x00;
|
||||
( int )( *argc )++;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
else printf( "CMD FILE(%s) Read error!\n", fname );
|
||||
|
||||
free( cmd_buff );
|
||||
sceIoClose( cmd_fd );
|
||||
}
|
||||
}
|
||||
|
||||
SceUID Platform_LoadModule( const char *filename, int mpid, SceSize argsize, void *argp )
|
||||
{
|
||||
SceKernelLMOption option;
|
||||
SceUID modid = 0;
|
||||
int retVal = 0, mresult;
|
||||
|
||||
memset( &option, 0, sizeof( option ) );
|
||||
option.size = sizeof( option );
|
||||
option.mpidtext = mpid;
|
||||
option.mpiddata = mpid;
|
||||
option.position = 0;
|
||||
option.access = 1;
|
||||
|
||||
retVal = sceKernelLoadModule( filename, 0, &option );
|
||||
if(retVal < 0)
|
||||
return retVal;
|
||||
|
||||
modid = retVal;
|
||||
|
||||
retVal = sceKernelStartModule( modid, argsize, argp, &mresult, NULL );
|
||||
if( retVal < 0 )
|
||||
return retVal;
|
||||
|
||||
return modid;
|
||||
}
|
||||
|
||||
int Platform_UnloadModule( SceUID modid, int *sce_code )
|
||||
{
|
||||
int status;
|
||||
*sce_code = sceKernelStopModule( modid, 0, NULL, &status, NULL);
|
||||
|
||||
if( ( *sce_code ) < 0 )
|
||||
return -2;
|
||||
else if( status == SCE_KERNEL_ERROR_NOT_STOPPED )
|
||||
return -1;
|
||||
|
||||
*sce_code = sceKernelUnloadModule( modid );
|
||||
return ( ( ( *sce_code ) < 0 ) ? -2 : 0 );
|
||||
}
|
||||
|
||||
int Platform_InitAudioLibs( void )
|
||||
{
|
||||
int status;
|
||||
|
||||
if( psp_audiolib_init )
|
||||
return -1;
|
||||
|
||||
status = sceUtilityLoadModule( PSP_MODULE_AV_AVCODEC );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceUtilityLoadModule(PSP_MODULE_AV_AVCODEC) returned 0x%08X\n", status );
|
||||
return status;
|
||||
}
|
||||
|
||||
status = sceUtilityLoadModule( PSP_MODULE_AV_MP3 );
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceUtilityLoadModule(PSP_MODULE_AV_MP3) returned 0x%08X\n", status );
|
||||
return status;
|
||||
}
|
||||
|
||||
// init mp3 resources
|
||||
status = sceMp3InitResource();
|
||||
if ( status < 0 )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "sceMp3InitResource returned 0x%08X\n", status );
|
||||
return status;
|
||||
}
|
||||
|
||||
psp_audiolib_init = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Platform_ShutdownAudioLibs( void )
|
||||
{
|
||||
int status;
|
||||
|
||||
if( !psp_audiolib_init )
|
||||
return -1;
|
||||
|
||||
status = sceMp3TermResource();
|
||||
if ( status < 0 )
|
||||
Con_DPrintf( S_ERROR "sceMp3TermResource returned 0x%08X\n", status );
|
||||
|
||||
status = sceUtilityUnloadModule( PSP_MODULE_AV_MP3 );
|
||||
if ( status < 0 )
|
||||
Con_DPrintf( S_ERROR "sceUtilityUnloadModule(PSP_MODULE_AV_MP3) returned 0x%08X\n", status );
|
||||
|
||||
status = sceUtilityUnloadModule( PSP_MODULE_AV_AVCODEC );
|
||||
if ( status < 0 )
|
||||
Con_DPrintf( S_ERROR "sceUtilityUnloadModule(PSP_MODULE_AV_AVCODEC) returned 0x%08X\n", status );
|
||||
|
||||
psp_audiolib_init = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Platform_Init( void )
|
||||
{
|
||||
SceUID kamID;
|
||||
int result;
|
||||
|
||||
// disable fpu exceptions (division by zero and etc...)
|
||||
pspSdkDisableFPUExceptions();
|
||||
|
||||
// exit callback thread
|
||||
Platform_SetupCallbacks();
|
||||
|
||||
// set max cpu/gpu frequency
|
||||
scePowerSetClockFrequency( 333, 333, 166 );
|
||||
|
||||
// set max VRAM
|
||||
kamID = Platform_LoadModule( "ka.prx", 1, 0, NULL );
|
||||
if( kamID >= 0 )
|
||||
{
|
||||
result = kaGeEdramGetHwSize();
|
||||
if( result > 0 )
|
||||
result = kaGeEdramSetSize( result );
|
||||
Platform_UnloadModule( kamID, &result );
|
||||
}
|
||||
|
||||
Platform_InitAudioLibs();
|
||||
|
||||
// P5 Ram init
|
||||
P5Ram_Init();
|
||||
}
|
||||
|
||||
void Platform_Shutdown( void )
|
||||
{
|
||||
P5Ram_Shutdown();
|
||||
Platform_ShutdownAudioLibs();
|
||||
#if XASH_PROFILING
|
||||
gprof_cleanup();
|
||||
#endif
|
||||
}
|
||||
384
engine/platform/psp/vid_psp.c
Normal file
384
engine/platform/psp/vid_psp.c
Normal file
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
vid_psp.c - PSP video component
|
||||
Copyright (C) 2021 Sergey Galushko
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
#if XASH_VIDEO == VIDEO_PSP
|
||||
|
||||
#if !XASH_DEDICATED
|
||||
#include <pspkernel.h>
|
||||
#include <pspdisplay.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "client.h"
|
||||
#include "mod_local.h"
|
||||
#include "input.h"
|
||||
#include "vid_common.h"
|
||||
|
||||
// Set frame buffer
|
||||
#define PSP_FB_WIDTH 480
|
||||
#define PSP_FB_HEIGHT 272
|
||||
#define PSP_FB_BWIDTH 512
|
||||
#define PSP_FB_FORMAT PSP_DISPLAY_PIXEL_FORMAT_565 //4444,5551,565,8888
|
||||
|
||||
#if PSP_FB_FORMAT == PSP_DISPLAY_PIXEL_FORMAT_4444
|
||||
#define PSP_FB_BPP 2
|
||||
#elif PSP_FB_FORMAT == PSP_DISPLAY_PIXEL_FORMAT_5551
|
||||
#define PSP_FB_BPP 2
|
||||
#elif PSP_FB_FORMAT == PSP_DISPLAY_PIXEL_FORMAT_565
|
||||
#define PSP_FB_BPP 2
|
||||
#elif PSP_FB_FORMAT == PSP_DISPLAY_PIXEL_FORMAT_8888
|
||||
#define PSP_FB_BPP 4
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// Set up screen scaling
|
||||
#define PSP_WIDTH_AR 30
|
||||
#define PSP_HEIGHT_AR 17
|
||||
#define PSP_MIN_MAR 12
|
||||
#define PSP_MAX_MAR 16
|
||||
#define PSP_MIN_MAR_W (PSP_WIDTH_AR * PSP_MIN_MAR)
|
||||
#define PSP_MIN_MAR_H (PSP_HEIGHT_AR * PSP_MIN_MAR)
|
||||
#define PSP_MAX_MAR_W (PSP_WIDTH_AR * PSP_MAX_MAR)
|
||||
#define PSP_MAX_MAR_H (PSP_HEIGHT_AR * PSP_MAX_MAR)
|
||||
#endif
|
||||
|
||||
|
||||
static qboolean vsync;
|
||||
#if 1
|
||||
static vidmode_t vidmodes[] = { "480x272", PSP_FB_WIDTH, PSP_FB_HEIGHT};
|
||||
static int num_vidmodes = 1;
|
||||
#else
|
||||
static vidmode_t *vidmodes = NULL;
|
||||
static int num_vidmodes = 0;
|
||||
#endif
|
||||
static struct
|
||||
{
|
||||
#if 0
|
||||
int in_width, in_height;
|
||||
int out_width, out_height;
|
||||
#endif
|
||||
void *draw_buffer;
|
||||
void *disp_buffer;
|
||||
}vid_psp;
|
||||
|
||||
qboolean SW_CreateBuffer( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b )
|
||||
{
|
||||
*stride = PSP_FB_BWIDTH;
|
||||
*r = 31;
|
||||
*g = 63 << 5;
|
||||
*b = 31 << 11;
|
||||
*bpp = 2;
|
||||
|
||||
vid_psp.draw_buffer = (void*)malloc( PSP_FB_HEIGHT * PSP_FB_BWIDTH * PSP_FB_BPP );
|
||||
if( !vid_psp.draw_buffer )
|
||||
Host_Error( "Memory allocation failled! (vid_psp.draw_buffer)\n");
|
||||
|
||||
vid_psp.disp_buffer = (void*)malloc( PSP_FB_HEIGHT * PSP_FB_BWIDTH * PSP_FB_BPP );
|
||||
if( !vid_psp.disp_buffer )
|
||||
Host_Error( "Memory allocation failled! (vid_psp.disp_buffer)\n");
|
||||
|
||||
sceDisplaySetMode(0, PSP_FB_WIDTH, PSP_FB_HEIGHT);
|
||||
sceDisplaySetFrameBuf(vid_psp.disp_buffer, PSP_FB_BWIDTH, PSP_FB_FORMAT, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void *SW_LockBuffer( void )
|
||||
{
|
||||
return vid_psp.draw_buffer;
|
||||
}
|
||||
|
||||
void SW_UnlockBuffer( void )
|
||||
{
|
||||
void* p_swap = vid_psp.disp_buffer;
|
||||
vid_psp.disp_buffer = vid_psp.draw_buffer;
|
||||
vid_psp.draw_buffer = p_swap;
|
||||
|
||||
sceKernelDcacheWritebackInvalidateAll();
|
||||
sceDisplaySetFrameBuf(vid_psp.disp_buffer, PSP_FB_BWIDTH, PSP_FB_FORMAT, PSP_DISPLAY_SETBUF_NEXTFRAME);
|
||||
|
||||
if ( vsync )
|
||||
{
|
||||
sceDisplayWaitVblankStart();
|
||||
}
|
||||
}
|
||||
|
||||
int R_MaxVideoModes( void )
|
||||
{
|
||||
return num_vidmodes;
|
||||
}
|
||||
|
||||
vidmode_t *R_GetVideoMode( int num )
|
||||
{
|
||||
if( !vidmodes || num < 0 || num >= R_MaxVideoModes() )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return vidmodes + num;
|
||||
}
|
||||
#if 0
|
||||
static void R_InitVideoModes( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
vidmodes = Mem_Malloc( host.mempool, (PSP_MAX_MAR - PSP_MIN_MAR) * sizeof( vidmode_t ) );
|
||||
|
||||
// from smallest to largest
|
||||
for(i = PSP_MIN_MAR ; i <= PSP_MAX_MAR; i++ )
|
||||
{
|
||||
vidmodes[num_vidmodes].width = PSP_WIDTH_AR * i;
|
||||
vidmodes[num_vidmodes].height = PSP_HEIGHT_AR * i;
|
||||
vidmodes[num_vidmodes].desc =
|
||||
copystring( va( "%ix%i", vidmodes[num_vidmodes].width, vidmodes[num_vidmodes].height ));
|
||||
|
||||
num_vidmodes++;
|
||||
}
|
||||
}
|
||||
|
||||
static void R_FreeVideoModes( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
if(!vidmodes)
|
||||
return;
|
||||
|
||||
for( i = 0; i < num_vidmodes; i++ )
|
||||
Mem_Free( (char*)vidmodes[i].desc );
|
||||
Mem_Free( vidmodes );
|
||||
|
||||
vidmodes = NULL;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
=================
|
||||
GL_GetProcAddress
|
||||
=================
|
||||
*/
|
||||
void *GL_GetProcAddress( const char *name )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
GL_UpdateSwapInterval
|
||||
===============
|
||||
*/
|
||||
void GL_UpdateSwapInterval( void )
|
||||
{
|
||||
// disable VSync while level is loading
|
||||
if( cls.state < ca_active )
|
||||
{
|
||||
// setup vsync here
|
||||
vsync = false;
|
||||
SetBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||
}
|
||||
else if( FBitSet( gl_vsync->flags, FCVAR_CHANGED ))
|
||||
{
|
||||
ClearBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||
vsync = (gl_vsync->value > 0) ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
static qboolean VID_SetScreenResolution( int width, int height )
|
||||
{
|
||||
int render_w = width, render_h = height;
|
||||
uint rotate = vid_rotate->value;
|
||||
|
||||
if( ref.dllFuncs.R_SetDisplayTransform( rotate, 0, 0, vid_scale->value, vid_scale->value ) )
|
||||
{
|
||||
if( rotate & 1 )
|
||||
{
|
||||
int swap = render_w;
|
||||
|
||||
render_w = render_h;
|
||||
render_h = swap;
|
||||
}
|
||||
|
||||
render_h /= vid_scale->value;
|
||||
render_w /= vid_scale->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_Printf( S_WARN "failed to setup screen transform\n" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
R_SaveVideoMode( width, height, render_w, render_h );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GL_SwapBuffers( void )
|
||||
{
|
||||
if ( vsync ) sceDisplayWaitVblankStart();
|
||||
}
|
||||
|
||||
int GL_SetAttribute( int attr, int val )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GL_GetAttribute( int attr, int *val )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_Init_Video
|
||||
==================
|
||||
*/
|
||||
qboolean R_Init_Video( const int type )
|
||||
{
|
||||
string safe;
|
||||
qboolean retval;
|
||||
|
||||
refState.desktopBitsPixel = ( PSP_FB_BPP * 8 );
|
||||
|
||||
VID_StartupGamma();
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case REF_SOFTWARE:
|
||||
glw_state.software = true;
|
||||
break;
|
||||
case REF_GL:
|
||||
if( !glw_state.safe && Sys_GetParmFromCmdLine( "-safegl", safe ) )
|
||||
glw_state.safe = bound( SAFE_NO, Q_atoi( safe ), SAFE_DONTCARE );
|
||||
break;
|
||||
default:
|
||||
Host_Error( "Can't initialize unknown context type %d!\n", type );
|
||||
break;
|
||||
}
|
||||
|
||||
if( !(retval = VID_SetMode()) )
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case REF_GL:
|
||||
// refdll also can check extensions
|
||||
ref.dllFuncs.GL_InitExtensions();
|
||||
break;
|
||||
case REF_SOFTWARE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
R_InitVideoModes();
|
||||
#endif
|
||||
host.renderinfo_changed = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
rserr_t R_ChangeDisplaySettings( int width, int height, qboolean fullscreen )
|
||||
{
|
||||
Con_Reportf( "R_ChangeDisplaySettings: Setting video mode to %dx%d %s\n", width, height, fullscreen ? "fullscreen" : "windowed" );
|
||||
|
||||
refState.fullScreen = fullscreen;
|
||||
|
||||
if( !VID_SetScreenResolution( width, height ) )
|
||||
return rserr_invalid_fullscreen;
|
||||
|
||||
return rserr_ok;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
VID_SetMode
|
||||
|
||||
Set the described video mode
|
||||
==================
|
||||
*/
|
||||
qboolean VID_SetMode( void )
|
||||
{
|
||||
qboolean fullscreen = false;
|
||||
int iScreenWidth, iScreenHeight;
|
||||
rserr_t err;
|
||||
|
||||
#if 1
|
||||
iScreenWidth = PSP_FB_WIDTH;
|
||||
iScreenHeight = PSP_FB_HEIGHT;
|
||||
#else
|
||||
vid_psp.out_width = PSP_FB_WIDTH;
|
||||
vid_psp.out_height = PSP_FB_HEIGHT;
|
||||
|
||||
iScreenWidth = Cvar_VariableInteger( "width" );
|
||||
iScreenHeight = Cvar_VariableInteger( "height" );
|
||||
|
||||
if( iScreenWidth < PSP_MIN_MAR_W ||
|
||||
iScreenHeight < PSP_MIN_MAR_H ) // trying to get resolution automatically by default
|
||||
{
|
||||
iScreenWidth = PSP_MIN_MAR_W;
|
||||
iScreenHeight = PSP_MIN_MAR_H;
|
||||
}
|
||||
|
||||
if( iScreenWidth > PSP_MAX_MAR_W ||
|
||||
iScreenHeight > PSP_MAX_MAR_H ) // trying to get resolution automatically by default
|
||||
{
|
||||
iScreenWidth = PSP_MAX_MAR_W;
|
||||
iScreenHeight = PSP_MAX_MAR_H;
|
||||
}
|
||||
#endif
|
||||
if( !FBitSet( vid_fullscreen->flags, FCVAR_CHANGED ) )
|
||||
Cvar_SetValue( "fullscreen", DEFAULT_FULLSCREEN );
|
||||
else
|
||||
ClearBits( vid_fullscreen->flags, FCVAR_CHANGED );
|
||||
|
||||
SetBits( gl_vsync->flags, FCVAR_CHANGED );
|
||||
fullscreen = true;//Cvar_VariableInteger("fullscreen") != 0;
|
||||
|
||||
if(( err = R_ChangeDisplaySettings( iScreenWidth, iScreenHeight, fullscreen )) == rserr_ok )
|
||||
{
|
||||
#if 0
|
||||
vid_psp.in_width = iScreenWidth;
|
||||
vid_psp.in_height = iScreenHeight;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
R_Free_Video
|
||||
==================
|
||||
*/
|
||||
void R_Free_Video( void )
|
||||
{
|
||||
#if 0
|
||||
R_FreeVideoModes();
|
||||
#endif
|
||||
ref.dllFuncs.GL_ClearExtensions();
|
||||
if( glw_state.software )
|
||||
{
|
||||
if( vid_psp.draw_buffer )
|
||||
free( vid_psp.draw_buffer );
|
||||
if( vid_psp.disp_buffer )
|
||||
free( vid_psp.disp_buffer );
|
||||
|
||||
vid_psp.draw_buffer = NULL;
|
||||
vid_psp.disp_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // XASH_DEDICATED
|
||||
#endif // XASH_VIDEO
|
||||
@@ -283,12 +283,6 @@ typedef enum
|
||||
PARM_GET_MOVEVARS_PTR = -13, // clgame.movevars
|
||||
PARM_GET_PALETTE_PTR = -14, // clgame.palette
|
||||
PARM_GET_VIEWENT_PTR = -15, // clgame.viewent
|
||||
|
||||
// implemented by ref_dll
|
||||
|
||||
// returns non-null integer if filtering is enabled for texture
|
||||
// pass -1 to query global filtering settings
|
||||
PARM_TEX_FILTERING = -65536,
|
||||
} ref_parm_e;
|
||||
|
||||
typedef struct ref_api_s
|
||||
@@ -452,6 +446,11 @@ typedef struct ref_api_s
|
||||
|
||||
// filesystem exports
|
||||
fs_api_t *fsapi;
|
||||
|
||||
#if XASH_PSP
|
||||
void *(*P5Ram_Alloc)( size_t size, int clear );
|
||||
void (*P5Ram_Free)( void *ptr );
|
||||
#endif
|
||||
} ref_api_t;
|
||||
|
||||
struct mip_s;
|
||||
|
||||
@@ -54,7 +54,7 @@ extern int SV_UPDATE_BACKUP;
|
||||
#define GROUP_OP_AND 0
|
||||
#define GROUP_OP_NAND 1
|
||||
|
||||
#ifdef NDEBUG
|
||||
#if defined( NDEBUG )
|
||||
#define SV_IsValidEdict( e ) ( e && !e->free )
|
||||
#else
|
||||
#define SV_IsValidEdict( e ) SV_CheckEdict( e, __FILE__, __LINE__ )
|
||||
@@ -509,7 +509,13 @@ qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multipla
|
||||
qboolean SV_InitGame( void );
|
||||
void SV_ActivateServer( int runPhysics );
|
||||
qboolean SV_SpawnServer( const char *server, const char *startspot, qboolean background );
|
||||
model_t *SV_ModelHandle( int modelindex );
|
||||
static inline model_t *GAME_EXPORT SV_ModelHandle( int modelindex )
|
||||
{
|
||||
if( unlikely( modelindex < 0 || modelindex >= MAX_MODELS ))
|
||||
return NULL;
|
||||
|
||||
return sv.models[modelindex];
|
||||
}
|
||||
void SV_DeactivateServer( void );
|
||||
|
||||
//
|
||||
@@ -648,10 +654,17 @@ void SV_RestartAmbientSounds( void );
|
||||
void SV_RestartDecals( void );
|
||||
void SV_RestartStaticEnts( void );
|
||||
int pfnDropToFloor( edict_t* e );
|
||||
edict_t *SV_EdictNum( int n );
|
||||
void SV_SetModel( edict_t *ent, const char *name );
|
||||
int pfnDecalIndex( const char *m );
|
||||
|
||||
static inline edict_t *SV_EdictNum( int n )
|
||||
{
|
||||
if( unlikely( n < 0 || n >= GI->max_edicts ))
|
||||
return NULL;
|
||||
|
||||
return &svgame.edicts[n];
|
||||
}
|
||||
|
||||
//
|
||||
// sv_log.c
|
||||
//
|
||||
|
||||
@@ -39,13 +39,6 @@ static vec3_t viewPoint[MAX_CLIENTS];
|
||||
typedef void (__cdecl *LINK_ENTITY_FUNC)( entvars_t *pev );
|
||||
typedef void (__stdcall *GIVEFNPTRSTODLL)( enginefuncs_t* engfuncs, globalvars_t *pGlobals );
|
||||
|
||||
edict_t *SV_EdictNum( int n )
|
||||
{
|
||||
if(( n >= 0 ) && ( n < GI->max_edicts ))
|
||||
return svgame.edicts + n;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
qboolean SV_CheckEdict( const edict_t *e, const char *file, const int line )
|
||||
{
|
||||
|
||||
@@ -262,20 +262,6 @@ int GAME_EXPORT SV_GenericIndex( const char *filename )
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
SV_ModelHandle
|
||||
|
||||
get model by handle
|
||||
================
|
||||
*/
|
||||
model_t *GAME_EXPORT SV_ModelHandle( int modelindex )
|
||||
{
|
||||
if( modelindex < 0 || modelindex >= MAX_MODELS )
|
||||
return NULL;
|
||||
return sv.models[modelindex];
|
||||
}
|
||||
|
||||
static resourcetype_t SV_DetermineResourceType( const char *filename )
|
||||
{
|
||||
if( !Q_strncmp( filename, DEFAULT_SOUNDPATH, sizeof( DEFAULT_SOUNDPATH ) - 1 ) && Sound_SupportedFileFormat( COM_FileExtension( filename )))
|
||||
@@ -545,7 +531,7 @@ void SV_FreeOldEntities( void )
|
||||
}
|
||||
|
||||
// decrement svgame.numEntities if the highest number entities died
|
||||
for( ; ( ent = EDICT_NUM( svgame.numEntities - 1 )) && ent->free; svgame.numEntities-- );
|
||||
for( ; EDICT_NUM( svgame.numEntities - 1 )->free; svgame.numEntities-- );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -945,12 +945,12 @@ static edict_t *SV_PushMove( edict_t *pusher, float movetime )
|
||||
// filter movetypes to collide with
|
||||
if( !SV_CanPushed( check ))
|
||||
continue;
|
||||
|
||||
#if !XASH_PSP
|
||||
pusher->v.solid = SOLID_NOT;
|
||||
block = SV_TestEntityPosition( check, pusher );
|
||||
pusher->v.solid = oldsolid;
|
||||
if( block ) continue;
|
||||
|
||||
#endif
|
||||
// if the entity is standing on the pusher, it will definately be moved
|
||||
if( !( FBitSet( check->v.flags, FL_ONGROUND ) && check->v.groundentity == pusher ))
|
||||
{
|
||||
@@ -966,7 +966,12 @@ static edict_t *SV_PushMove( edict_t *pusher, float movetime )
|
||||
if( !SV_TestEntityPosition( check, NULL ))
|
||||
continue;
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
pusher->v.solid = SOLID_NOT;
|
||||
block = SV_TestEntityPosition( check, pusher );
|
||||
pusher->v.solid = oldsolid;
|
||||
if( block ) continue;
|
||||
#endif
|
||||
// remove the onground flag for non-players
|
||||
if( check->v.movetype != MOVETYPE_WALK )
|
||||
check->v.flags &= ~FL_ONGROUND;
|
||||
@@ -1058,18 +1063,19 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
||||
for( e = 1; e < svgame.numEntities; e++ )
|
||||
{
|
||||
check = EDICT_NUM( e );
|
||||
|
||||
if( !SV_IsValidEdict( check ))
|
||||
continue;
|
||||
|
||||
// filter movetypes to collide with
|
||||
if( !SV_CanPushed( check ))
|
||||
continue;
|
||||
|
||||
#if !XASH_PSP
|
||||
pusher->v.solid = SOLID_NOT;
|
||||
block = SV_TestEntityPosition( check, pusher );
|
||||
pusher->v.solid = oldsolid;
|
||||
if( block ) continue;
|
||||
|
||||
#endif
|
||||
// if the entity is standing on the pusher, it will definately be moved
|
||||
if( !(( check->v.flags & FL_ONGROUND ) && check->v.groundentity == pusher ))
|
||||
{
|
||||
@@ -1085,7 +1091,12 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
||||
if( !SV_TestEntityPosition( check, NULL ))
|
||||
continue;
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
pusher->v.solid = SOLID_NOT;
|
||||
block = SV_TestEntityPosition( check, pusher );
|
||||
pusher->v.solid = oldsolid;
|
||||
if( block ) continue;
|
||||
#endif
|
||||
// save original position of contacted entity
|
||||
pushed_p->ent = check;
|
||||
VectorCopy( check->v.origin, pushed_p->origin );
|
||||
@@ -1101,7 +1112,7 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
||||
Matrix4x4_VectorITransform( start_l, org, temp );
|
||||
Matrix4x4_VectorTransform( end_l, temp, org2 );
|
||||
VectorSubtract( org2, org, lmove );
|
||||
|
||||
|
||||
// i can't clear FL_ONGROUND in all cases because many bad things may be happen
|
||||
if( check->v.movetype != MOVETYPE_WALK )
|
||||
{
|
||||
@@ -1140,7 +1151,6 @@ static edict_t *SV_PushRotate( edict_t *pusher, float movetime )
|
||||
return check;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1842,10 +1852,8 @@ void SV_Physics( void )
|
||||
// increase framecount
|
||||
sv.framecount++;
|
||||
|
||||
#if 0 // figure out why this causes memory corruption
|
||||
// decrement svgame.numEntities if the highest number entities died
|
||||
for( ; ( ent = EDICT_NUM( svgame.numEntities - 1 )) && ent->free; svgame.numEntities-- );
|
||||
#endif
|
||||
for( ; EDICT_NUM( svgame.numEntities - 1 )->free; svgame.numEntities-- );
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -32,8 +32,11 @@ half-life implementation of saverestore system
|
||||
#define SAVEGAME_HEADER (('V'<<24)+('A'<<16)+('S'<<8)+'J') // little-endian "JSAV"
|
||||
#define SAVEGAME_VERSION 0x0071 // Version 0.71 GoldSrc compatible
|
||||
#define CLIENT_SAVEGAME_VERSION 0x0067 // Version 0.67
|
||||
|
||||
#if XASH_PSP
|
||||
#define SAVE_HEAPSIZE 0x200000 // reserve 2Mb for now
|
||||
#else
|
||||
#define SAVE_HEAPSIZE 0x400000 // reserve 4Mb for now
|
||||
#endif
|
||||
#define SAVE_HASHSTRINGS 0xFFF // 4095 unique strings
|
||||
|
||||
// savedata headers
|
||||
@@ -384,7 +387,13 @@ static void InitEntityTable( SAVERESTOREDATA *pSaveData, int entityCount )
|
||||
ENTITYTABLE *pTable;
|
||||
int i;
|
||||
|
||||
#if XASH_PSP
|
||||
pSaveData->pTable = P5Ram_Alloc( sizeof( ENTITYTABLE ) * entityCount, 1 );
|
||||
if( !pSaveData->pTable )
|
||||
Host_Error( "%s: P5Ram_Alloc (pSaveData->pTable) failed!", __FUNCTION__ );
|
||||
#else
|
||||
pSaveData->pTable = Mem_Calloc( host.mempool, sizeof( ENTITYTABLE ) * entityCount );
|
||||
#endif
|
||||
pSaveData->tableCount = entityCount;
|
||||
|
||||
// setup entitytable
|
||||
@@ -700,8 +709,17 @@ static SAVERESTOREDATA *SaveInit( int size, int tokenCount )
|
||||
{
|
||||
SAVERESTOREDATA *pSaveData;
|
||||
|
||||
#if XASH_PSP
|
||||
pSaveData = P5Ram_Alloc( sizeof( SAVERESTOREDATA ) + size, 1 );
|
||||
if( !pSaveData )
|
||||
Host_Error( "%s: P5Ram_Alloc (pSaveData) failed!", __FUNCTION__ );
|
||||
pSaveData->pTokens = (char **)P5Ram_Alloc( tokenCount * sizeof( char* ), 1 );
|
||||
if( !pSaveData->pTokens )
|
||||
Host_Error( "%s: P5Ram_Alloc (pSaveData->pTokens) failed!", __FUNCTION__ );
|
||||
#else
|
||||
pSaveData = Mem_Calloc( host.mempool, sizeof( SAVERESTOREDATA ) + size );
|
||||
pSaveData->pTokens = (char **)Mem_Calloc( host.mempool, tokenCount * sizeof( char* ));
|
||||
#endif
|
||||
pSaveData->tokenCount = tokenCount;
|
||||
|
||||
pSaveData->pBaseData = (char *)(pSaveData + 1); // skip the save structure);
|
||||
@@ -750,20 +768,32 @@ static void SaveFinish( SAVERESTOREDATA *pSaveData )
|
||||
|
||||
if( pSaveData->pTokens )
|
||||
{
|
||||
#if XASH_PSP
|
||||
P5Ram_Free( pSaveData->pTokens );
|
||||
#else
|
||||
Mem_Free( pSaveData->pTokens );
|
||||
#endif
|
||||
pSaveData->pTokens = NULL;
|
||||
pSaveData->tokenCount = 0;
|
||||
}
|
||||
|
||||
if( pSaveData->pTable )
|
||||
{
|
||||
#if XASH_PSP
|
||||
P5Ram_Free( pSaveData->pTable );
|
||||
#else
|
||||
Mem_Free( pSaveData->pTable );
|
||||
#endif
|
||||
pSaveData->pTable = NULL;
|
||||
pSaveData->tableCount = 0;
|
||||
}
|
||||
|
||||
svgame.globals->pSaveData = NULL;
|
||||
#if XASH_PSP
|
||||
P5Ram_Free( pSaveData );
|
||||
#else
|
||||
Mem_Free( pSaveData );
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2333,14 +2363,26 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if XASH_PSP
|
||||
pSaveData = (char *)P5Ram_Alloc( size, 0 );
|
||||
if( !pSaveData )
|
||||
Host_Error( "%s: P5Ram_Alloc (pSaveData) failed!", __FUNCTION__ );
|
||||
#else
|
||||
pSaveData = (char *)Mem_Malloc( host.mempool, size );
|
||||
#endif
|
||||
FS_Read( f, pSaveData, size );
|
||||
pData = pSaveData;
|
||||
|
||||
// allocate a table for the strings, and parse the table
|
||||
if( tokenSize > 0 )
|
||||
{
|
||||
#if XASH_PSP
|
||||
pTokenList = P5Ram_Alloc( tokenCount * sizeof( char* ), 1 );
|
||||
if( !pTokenList )
|
||||
Host_Error( "%s: P5Ram_Alloc (pTokenList) failed!", __FUNCTION__ );
|
||||
#else
|
||||
pTokenList = Mem_Calloc( host.mempool, tokenCount * sizeof( char* ));
|
||||
#endif
|
||||
|
||||
// make sure the token strings pointed to by the pToken hashtable.
|
||||
for( i = 0; i < tokenCount; i++ )
|
||||
@@ -2352,22 +2394,40 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
||||
else pTokenList = NULL;
|
||||
|
||||
// short, short (size, index of field name)
|
||||
#if XASH_PSP /* FIX Unaligned access! */
|
||||
short offpd;
|
||||
memcpy(&offpd, pData, sizeof( short ) );
|
||||
nFieldSize = offpd;
|
||||
pData += sizeof( short );
|
||||
|
||||
memcpy(&offpd, pData, sizeof( short ));
|
||||
pFieldName = pTokenList[offpd];
|
||||
#else
|
||||
nFieldSize = *(short *)pData;
|
||||
pData += sizeof( short );
|
||||
pFieldName = pTokenList[*(short *)pData];
|
||||
|
||||
#endif
|
||||
if( Q_stricmp( pFieldName, "GameHeader" ))
|
||||
{
|
||||
Q_strncpy( comment, "<missing GameHeader>", MAX_STRING );
|
||||
#if XASH_PSP
|
||||
if( pTokenList ) P5Ram_Free( pTokenList );
|
||||
if( pSaveData ) P5Ram_Free( pSaveData );
|
||||
#else
|
||||
if( pTokenList ) Mem_Free( pTokenList );
|
||||
if( pSaveData ) Mem_Free( pSaveData );
|
||||
#endif
|
||||
FS_Close( f );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// int (fieldcount)
|
||||
pData += sizeof( short );
|
||||
#if XASH_PSP /* FIX Unaligned access! */
|
||||
memcpy(&nNumberOfFields, pData, sizeof(int));
|
||||
#else
|
||||
nNumberOfFields = (int)*pData;
|
||||
#endif
|
||||
pData += nFieldSize;
|
||||
|
||||
// each field is a short (size), short (index of name), binary string of "size" bytes (data)
|
||||
@@ -2378,11 +2438,23 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
||||
// Size
|
||||
// szName
|
||||
// Actual Data
|
||||
|
||||
|
||||
#if XASH_PSP /* FIX Unaligned access! */
|
||||
memcpy(&offpd, pData, sizeof( short ) );
|
||||
nFieldSize = offpd;
|
||||
pData += sizeof( short );
|
||||
|
||||
memcpy(&offpd, pData, sizeof( short ));
|
||||
pFieldName = pTokenList[offpd];
|
||||
pData += sizeof( short );
|
||||
#else
|
||||
nFieldSize = *(short *)pData;
|
||||
pData += sizeof( short );
|
||||
|
||||
pFieldName = pTokenList[*(short *)pData];
|
||||
pData += sizeof( short );
|
||||
#endif
|
||||
|
||||
size = Q_min( nFieldSize, MAX_STRING );
|
||||
|
||||
@@ -2400,8 +2472,13 @@ int GAME_EXPORT SV_GetSaveComment( const char *savename, char *comment )
|
||||
}
|
||||
|
||||
// delete the string table we allocated
|
||||
#if XASH_PSP
|
||||
if( pTokenList ) P5Ram_Free( pTokenList );
|
||||
if( pSaveData ) P5Ram_Free( pSaveData );
|
||||
#else
|
||||
if( pTokenList ) Mem_Free( pTokenList );
|
||||
if( pSaveData ) Mem_Free( pSaveData );
|
||||
#endif
|
||||
FS_Close( f );
|
||||
|
||||
// at least mapname should be filled
|
||||
|
||||
@@ -65,6 +65,8 @@ typedef enum
|
||||
SPR_CULL_NONE, // oriented sprite will be draw back face too
|
||||
} facetype_t;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
// generic helper
|
||||
typedef struct
|
||||
{
|
||||
@@ -133,4 +135,6 @@ typedef struct
|
||||
|
||||
STATIC_ASSERT( sizeof( dframetype_t ) == 4, "invalid dframetype_t size" );
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif//SPRITE_H
|
||||
|
||||
@@ -67,6 +67,8 @@ def configure(conf):
|
||||
# then remove them to avoid them getting linked to shared objects
|
||||
for lib in extra_libs:
|
||||
conf.env.LDFLAGS.remove(lib)
|
||||
elif conf.env.DEST_OS == 'psp':
|
||||
conf.define('XASH_NO_NETWORK', 1)
|
||||
elif conf.options.FBDEV_SW:
|
||||
# unused, XASH_LINUX without XASH_SDL gives fbdev & alsa support
|
||||
# conf.define('XASH_FBDEV', 1)
|
||||
@@ -87,10 +89,11 @@ def configure(conf):
|
||||
|
||||
if conf.options.STATIC:
|
||||
conf.env.STATIC = True
|
||||
conf.define('XASH_NO_LIBDL',1)
|
||||
if conf.env.DEST_OS != 'psp':
|
||||
conf.define('XASH_NO_LIBDL',1)
|
||||
|
||||
if not conf.env.DEST_OS in ['win32', 'android'] and not conf.options.NO_ASYNC_RESOLVE:
|
||||
conf.check_pthreads(mode='c')
|
||||
conf.check_pthreads()
|
||||
|
||||
if conf.env.DEST_OS == 'linux':
|
||||
conf.check_cc(lib='rt')
|
||||
@@ -132,16 +135,19 @@ def build(bld):
|
||||
'common/*.c',
|
||||
'common/imagelib/*.c',
|
||||
'common/soundlib/*.c',
|
||||
'common/soundlib/libmpg/*.c',
|
||||
'server/*.c'])
|
||||
|
||||
# PSP uses hw MP3 decoder
|
||||
if bld.env.DEST_OS != 'psp':
|
||||
source += bld.path.ant_glob(['common/soundlib/libmpg/*.c'])
|
||||
|
||||
if bld.env.ENGINE_TESTS:
|
||||
source += bld.path.ant_glob(['tests/*.c'])
|
||||
|
||||
if bld.env.DEST_OS == 'win32':
|
||||
libs += ['USER32', 'SHELL32', 'GDI32', 'ADVAPI32', 'DBGHELP', 'PSAPI', 'WS2_32' ]
|
||||
source += bld.path.ant_glob(['platform/win32/*.c'])
|
||||
elif bld.env.DEST_OS not in ['dos', 'nswitch', 'psvita']: #posix
|
||||
elif bld.env.DEST_OS not in ['dos', 'nswitch', 'psvita', 'psp']: #posix
|
||||
libs += [ 'M', 'RT', 'PTHREAD', 'ASOUND']
|
||||
if not bld.env.STATIC:
|
||||
libs += ['DL']
|
||||
@@ -211,6 +217,10 @@ def build(bld):
|
||||
'-lSceKernelDmacMgr_stub'
|
||||
]
|
||||
|
||||
if bld.env.DEST_OS == 'psp':
|
||||
source += bld.path.ant_glob(['platform/psp/*.c'])
|
||||
source += bld.path.ant_glob(['platform/psp/*/*.S'])
|
||||
|
||||
# add client files
|
||||
if not bld.env.DEDICATED:
|
||||
source += bld.path.ant_glob([
|
||||
|
||||
@@ -121,6 +121,8 @@ const char *Q_PlatformStringByID( const int platform )
|
||||
return "nswitch";
|
||||
case PLATFORM_PSVITA:
|
||||
return "psvita";
|
||||
case PLATFORM_PSP:
|
||||
return "psp";
|
||||
}
|
||||
|
||||
assert( 0 );
|
||||
|
||||
@@ -86,6 +86,7 @@ Then you can use another oneliner to query all variables:
|
||||
#undef XASH_X86
|
||||
#undef XASH_NSWITCH
|
||||
#undef XASH_PSVITA
|
||||
#undef XASH_PSP
|
||||
|
||||
//================================================================
|
||||
//
|
||||
@@ -98,6 +99,8 @@ Then you can use another oneliner to query all variables:
|
||||
#define XASH_EMSCRIPTEN 1
|
||||
#elif defined __WATCOMC__ && defined __DOS__
|
||||
#define XASH_DOS4GW 1
|
||||
#elif defined __psp__
|
||||
#define XASH_PSP 1
|
||||
#else // POSIX compatible
|
||||
#define XASH_POSIX 1
|
||||
#if defined __linux__
|
||||
@@ -144,7 +147,7 @@ Then you can use another oneliner to query all variables:
|
||||
// but we still need XASH_MOBILE_PLATFORM for the engine.
|
||||
// So this macro is defined entirely in build-system: see main wscript
|
||||
// HLSDK/PrimeXT/other SDKs users note: you may ignore this macro
|
||||
#if XASH_ANDROID || XASH_IOS || XASH_NSWITCH || XASH_PSVITA || XASH_SAILFISH
|
||||
#if XASH_ANDROID || XASH_IOS || XASH_NSWITCH || XASH_PSVITA || XASH_SAILFISH || XASH_PSP
|
||||
#define XASH_MOBILE_PLATFORM 1
|
||||
#endif
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ GNU General Public License for more details.
|
||||
#define PLATFORM_NSWITCH 13
|
||||
#define PLATFORM_PSVITA 14
|
||||
#define PLATFORM_LINUX_UNKNOWN 15
|
||||
#define PLATFORM_PSP 16
|
||||
|
||||
#if XASH_WIN32
|
||||
#define XASH_PLATFORM PLATFORM_WIN32
|
||||
@@ -73,6 +74,8 @@ GNU General Public License for more details.
|
||||
#define XASH_PLATFORM PLATFORM_NSWITCH
|
||||
#elif XASH_PSVITA
|
||||
#define XASH_PLATFORM PLATFORM_PSVITA
|
||||
#elif XASH_PSP
|
||||
#define XASH_PLATFORM PLATFORM_PSP
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
|
||||
@@ -35,13 +35,61 @@ const matrix3x4 m_matrix3x4_identity =
|
||||
*/
|
||||
void Matrix3x4_VectorTransform( const matrix3x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
"vhdp.q S000, C130, C100\n" // S000 = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3]
|
||||
"vhdp.q S001, C130, C110\n" // S001 = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2] + in[1][3]
|
||||
"vhdp.q S002, C130, C120\n" // S002 = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2] + in[2][3]
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3];
|
||||
out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2] + in[1][3];
|
||||
out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2] + in[2][3];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix3x4_VectorITransform( const matrix3x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
"vsub.t C130, C130, R103\n" // C130 = v - in[][3]
|
||||
#if 1
|
||||
"vtfm3.t C000, E100, C130\n" // C000 = E100 * C130
|
||||
#else
|
||||
"vdot.t S000, C130, R100\n" // S000 = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0]
|
||||
"vdot.t S001, C130, R101\n" // S001 = dir[0] * in[0][1] + dir[1] * in[1][1] + dir[2] * in[2][1]
|
||||
"vdot.t S002, C130, R102\n" // S002 = dir[0] * in[0][2] + dir[1] * in[1][2] + dir[2] * in[2][2]
|
||||
#endif
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
vec3_t dir;
|
||||
|
||||
dir[0] = v[0] - in[0][3];
|
||||
@@ -51,24 +99,99 @@ void Matrix3x4_VectorITransform( const matrix3x4 in, const float v[3], float out
|
||||
out[0] = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0];
|
||||
out[1] = dir[0] * in[0][1] + dir[1] * in[1][1] + dir[2] * in[2][1];
|
||||
out[2] = dir[0] * in[0][2] + dir[1] * in[1][2] + dir[2] * in[2][2];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix3x4_VectorRotate( const matrix3x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
#if 1
|
||||
"vtfm3.t C000, M100, C130\n" // C000 = M100 * C130
|
||||
#else
|
||||
"vdot.t S000, C130, C100\n" // S000 = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2]
|
||||
"vdot.t S001, C130, C110\n" // S001 = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2]
|
||||
"vdot.t S002, C130, C120\n" // S002 = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2]
|
||||
#endif
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2];
|
||||
out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2];
|
||||
out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix3x4_VectorIRotate( const matrix3x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
#if 1
|
||||
"vtfm3.t C000, E100, C130\n" // C000 = E100 * C130
|
||||
#else
|
||||
"vdot.t S000, C130, R100\n" // S000 = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0]
|
||||
"vdot.t S001, C130, R101\n" // S001 = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1]
|
||||
"vdot.t S002, C130, R102\n" // S002 = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2]
|
||||
#endif
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0];
|
||||
out[1] = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1];
|
||||
out[2] = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix3x4_ConcatTransforms( matrix3x4 out, const matrix3x4 in1, const matrix3x4 in2 )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in1[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in1[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in1[2]
|
||||
"vzero.q C130\n" // C130 = [0, 0, 0, 0]
|
||||
"lv.q C200, 0 + %2\n" // C100 = in2[0]
|
||||
"lv.q C210, 16 + %2\n" // C110 = in2[1]
|
||||
"lv.q C220, 32 + %2\n" // C120 = in2[2]
|
||||
"vidt.q C230\n" // C230 = [0, 0, 0, 1]
|
||||
"vmmul.q E000, E100, E200\n" // E000 = E100 * E200
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in1 ), "m"( *in2 )
|
||||
);
|
||||
#else
|
||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
|
||||
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
|
||||
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
|
||||
@@ -81,6 +204,7 @@ void Matrix3x4_ConcatTransforms( matrix3x4 out, const matrix3x4 in1, const matri
|
||||
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
|
||||
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
|
||||
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out )
|
||||
@@ -105,6 +229,31 @@ void Matrix3x4_AnglesFromMatrix( const matrix3x4 in, vec3_t out )
|
||||
|
||||
void Matrix3x4_FromOriginQuat( matrix3x4 out, const vec4_t quaternion, const vec3_t origin )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C130, %1\n" // C130 = quaternion
|
||||
"lv.s S300, 0 + %2\n" // S300 = origin[0]
|
||||
"lv.s S301, 4 + %2\n" // S301 = origin[1]
|
||||
"lv.s S302, 8 + %2\n" // S302 = origin[2]
|
||||
"vmov.q C100, C130[ W, Z, -Y, -X]\n" // C100 = ( w, z, -y, -x)
|
||||
"vmov.q C110, C130[-Z, W, X, -Y]\n" // C110 = (-z, w, x, -y)
|
||||
"vmov.q C120, C130[ Y, -X, W, -Z]\n" // C120 = ( y, -x, w, -z)
|
||||
"vmov.q C200, C130[ W, Z, -Y, X]\n" // C200 = ( w, z, -y, x)
|
||||
"vmov.q C210, C130[-Z, W, X, Y]\n" // C210 = (-z, w, x, y)
|
||||
"vmov.q C220, C130[ Y, -X, W, Z]\n" // C220 = ( y, -x, w, z)
|
||||
"vmov.q C230, C130[-X, -Y, -Z, W]\n" // C230 = (-x, -y, -z, w)
|
||||
"vmmul.q M000, E100, E200\n" // M000 = E100 * E200
|
||||
"vmov.t R003, C300\n" // out[x][3] = origin[x]
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *quaternion ), "m"( *origin )
|
||||
);
|
||||
#else
|
||||
out[0][0] = 1.0f - 2.0f * quaternion[1] * quaternion[1] - 2.0f * quaternion[2] * quaternion[2];
|
||||
out[1][0] = 2.0f * quaternion[0] * quaternion[1] + 2.0f * quaternion[3] * quaternion[2];
|
||||
out[2][0] = 2.0f * quaternion[0] * quaternion[2] - 2.0f * quaternion[3] * quaternion[1];
|
||||
@@ -120,10 +269,166 @@ void Matrix3x4_FromOriginQuat( matrix3x4 out, const vec4_t quaternion, const vec
|
||||
out[0][3] = origin[0];
|
||||
out[1][3] = origin[1];
|
||||
out[2][3] = origin[2];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix3x4_CreateFromEntity( matrix3x4 out, const vec3_t angles, const vec3_t origin, float scale )
|
||||
{
|
||||
#if 0/*XASH_PSP*/ /* performance not tested */ /* BUG */
|
||||
if( angles[ROLL] )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S100, 0 + %1\n" // S100 = angles[PITCH]
|
||||
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||
"lv.s S102, 8 + %1\n" // S102 = angles[ROLL]
|
||||
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %3\n" // S130 = scale
|
||||
/**/
|
||||
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||
"vscl.t C100, C100, S120\n" // C100 = C100 * S120 = angles * ( 2 / 180 )
|
||||
/**/
|
||||
"vsin.t C110, C100\n" // C110 = sin( C100 ) P Y R
|
||||
"vcos.t C120, C100\n" // C120 = cos( C100 ) P Y R
|
||||
"vneg.t C100, C110\n" // C100 = -C110 = -sin( C100 )
|
||||
/**/
|
||||
"vmul.s S000, S120, S121\n" // S000 = S120 * S121 = out[0][0] = ( cp * cy )
|
||||
"vmul.s S011, S112, S110\n" // S011 = S112 * S110 = ( sr * sp )
|
||||
"vmul.s S001, S011, S121\n" // S001 = S011 * S121 = ( sr * sp * cy )
|
||||
"vmul.s S103, S122, S101\n" // S001 = S122 * S101 = ( cr * -sy )
|
||||
"vadd.s S001, S001, S103\n" // S001 = S001 + S103 = out[0][1] = ( sr * sp * cy + cr * -sy )
|
||||
"vmul.s S012, S122, S110\n" // S002 = S122 * S110 = ( cr * sp )
|
||||
"vmul.s S002, S012, S121\n" // S002 = S012 * S121 = ( cr * sp * cy )
|
||||
"vmul.s S103, S102, S101\n" // S002 = S102 * S101 = ( -sr * -sy )
|
||||
"vadd.s S002, S002, S103\n" // S002 = S002 + S103 = out[0][2] = ( cr * sp * cy + -sr * -sy )
|
||||
/**/
|
||||
"vmul.s S010, S120, S111\n" // S010 = S120 * S111 = out[1][0] = ( cp * sy )
|
||||
"vmul.s S011, S011, S111\n" // S001 = S011 * S111 = ( sr * sp * sy )
|
||||
"vmul.s S103, S122, S121\n" // S001 = S122 * S121 = ( cr * cy )
|
||||
"vadd.s S011, S011, S103\n" // S011 = S011 + S103 = out[1][1] = ( sr * sp * sy + cr * cy )
|
||||
"vmul.s S012, S012, S111\n" // S012 = S012 * S111 = ( cr * sp * sy )
|
||||
"vmul.s S103, S102, S121\n" // S103 = S102 * S121 = ( -sr * cy )
|
||||
"vadd.s S012, S012, S103\n" // S012 = S012 + S103 = out[1][2] = ( cr * sp * sy + -sr * cy )
|
||||
/**/
|
||||
"vmov.s S020, S101\n" // S020 = S101 = out[2][0] = ( -sp )
|
||||
"vmul.s S021, S112, S120\n" // S021 = S112 * S120 = out[2][1] = ( sr * cp )
|
||||
"vmul.s S022, S122, S120\n" // S021 = S122 * S120 = out[2][2] = ( cr * cp )
|
||||
/**/
|
||||
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
else if( angles[PITCH] )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S100, 0 + %1\n" // S100 = angles[PITCH]
|
||||
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %3\n" // S130 = scale
|
||||
/**/
|
||||
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||
"vscl.p C100, C100, S120\n" // C100 = C100 * S120 = angles * ( 2 / 180 )
|
||||
/**/
|
||||
"vsin.p C110, C100\n" // C110 = sin( C100 ) P Y
|
||||
"vcos.p C120, C100\n" // C120 = cos( C100 ) P Y
|
||||
"vneg.p C100, C110\n" // C100 = -C110 = -sin( C100 )
|
||||
/**/
|
||||
"vmul.s S000, S120, S121\n" // S000 = S120 * S121 = out[0][0] = ( cp * cy )
|
||||
"vmov.s S001, S101\n" // S001 = S101 = out[0][1] = ( -sy )
|
||||
"vmul.s S002, S110, S121\n" // S001 = S110 * S121 = out[0][2] = ( sp * cy )
|
||||
/**/
|
||||
"vmul.s S010, S120, S111\n" // S010 = S120 * S111 = out[1][0] = ( cp * sy )
|
||||
"vmov.s S011, S121\n" // S011 = S121 = out[1][1] = ( cy )
|
||||
"vmul.s S012, S110, S111\n" // S012 = S110 * S111 = out[1][2] = ( sp * sy )
|
||||
/**/
|
||||
"vmov.s S020, S100\n" // S020 = S100 = out[2][0] = ( -sp )
|
||||
"vzero.s S021\n" // S021 = out[2][1] = 0.0f
|
||||
"vmov.s S022, S120\n" // S022 = S120 = out[2][2] = ( cp )
|
||||
/**/
|
||||
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
else if( angles[YAW] )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %3\n" // S130 = scale
|
||||
/**/
|
||||
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||
"vmul.s S101, S101, S120\n" // S101 = S101 * S120 = angles[YAW] * ( 2 / 180 )
|
||||
/**/
|
||||
"vsin.s S111, S101\n" // S111 = sin( S101 ) Y
|
||||
"vcos.s S121, S101\n" // S121 = cos( S101 ) Y
|
||||
/**/
|
||||
"vzero.p R002\n" // S002 = 0.0f S012 = 0.0f
|
||||
"vzero.p C020\n" // S020 = 0.0f S021 = 0.0f
|
||||
"vmov.s S000, S121\n" // S000 = S121 = out[0][0] = ( cy )
|
||||
"vneg.s S001, S111\n" // S001 = S111 = out[0][1] = ( -sy )
|
||||
"vmov.s S010, S111\n" // S010 = S111 = out[1][0] = ( sy )
|
||||
"vmov.s S011, S121\n" // S011 = S121 = out[1][1] = ( cy )
|
||||
"vone.s S022\n" // S022 = out[2][2] = 1.0f
|
||||
/**/
|
||||
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S003, 0 + %1\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %1\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %1\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %2\n" // S130 = scale
|
||||
/**/
|
||||
"vzero.t C000\n" // C000 = [0.0f, 0.0f, 0.0f]
|
||||
"vzero.t C010\n" // C010 = [0.0f, 0.0f, 0.0f]
|
||||
"vzero.t C020\n" // C020 = [0.0f, 0.0f, 0.0f]
|
||||
"vmov.s S000, S130\n" // S000 = S130 = out[0][0] = scale
|
||||
"vmov.s S011, S130\n" // S011 = S130 = out[1][1] = scale
|
||||
"vmov.s S022, S130\n" // S022 = S130 = out[2][2] = scale
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
#else
|
||||
float angle, sr, sp, sy, cr, cp, cy;
|
||||
|
||||
if( angles[ROLL] )
|
||||
@@ -201,6 +506,7 @@ void Matrix3x4_CreateFromEntity( matrix3x4 out, const vec3_t angles, const vec3_
|
||||
out[2][2] = scale;
|
||||
out[2][3] = origin[2];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -242,13 +548,61 @@ const matrix4x4 m_matrix4x4_identity =
|
||||
*/
|
||||
void Matrix4x4_VectorTransform( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
"vhdp.q S000, C130, C100\n" // S000 = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3]
|
||||
"vhdp.q S001, C130, C110\n" // S001 = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2] + in[1][3]
|
||||
"vhdp.q S002, C130, C120\n" // S002 = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2] + in[2][3]
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2] + in[0][3];
|
||||
out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2] + in[1][3];
|
||||
out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2] + in[2][3];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix4x4_VectorITransform( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
"vsub.t C130, C130, R103\n" // C130 = v - in[][3]
|
||||
#if 1
|
||||
"vtfm3.t C000, E100, C130\n" // C000 = E100 * C130
|
||||
#else
|
||||
"vdot.t S000, C130, R100\n" // S000 = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0]
|
||||
"vdot.t S001, C130, R101\n" // S001 = dir[0] * in[0][1] + dir[1] * in[1][1] + dir[2] * in[2][1]
|
||||
"vdot.t S002, C130, R102\n" // S002 = dir[0] * in[0][2] + dir[1] * in[1][2] + dir[2] * in[2][2]
|
||||
#endif
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
vec3_t dir;
|
||||
|
||||
dir[0] = v[0] - in[0][3];
|
||||
@@ -258,24 +612,99 @@ void Matrix4x4_VectorITransform( const matrix4x4 in, const float v[3], float out
|
||||
out[0] = dir[0] * in[0][0] + dir[1] * in[1][0] + dir[2] * in[2][0];
|
||||
out[1] = dir[0] * in[0][1] + dir[1] * in[1][1] + dir[2] * in[2][1];
|
||||
out[2] = dir[0] * in[0][2] + dir[1] * in[1][2] + dir[2] * in[2][2];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix4x4_VectorRotate( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
#if 1
|
||||
"vtfm3.t C000, M100, C130\n" // C000 = M100 * C130
|
||||
#else
|
||||
"vdot.t S000, C130, C100\n" // S000 = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2]
|
||||
"vdot.t S001, C130, C110\n" // S001 = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2]
|
||||
"vdot.t S002, C130, C120\n" // S002 = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2]
|
||||
#endif
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[0][1] + v[2] * in[0][2];
|
||||
out[1] = v[0] * in[1][0] + v[1] * in[1][1] + v[2] * in[1][2];
|
||||
out[2] = v[0] * in[2][0] + v[1] * in[2][1] + v[2] * in[2][2];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix4x4_VectorIRotate( const matrix4x4 in, const float v[3], float out[3] )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in[2]
|
||||
"lv.s S130, 0 + %2\n" // S130 = v[0]
|
||||
"lv.s S131, 4 + %2\n" // S131 = v[1]
|
||||
"lv.s S132, 8 + %2\n" // S132 = v[2]
|
||||
#if 1
|
||||
"vtfm3.t C000, E100, C130\n" // C000 = E100 * C130
|
||||
#else
|
||||
"vdot.t S000, C130, R100\n" // S000 = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0]
|
||||
"vdot.t S001, C130, R101\n" // S001 = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1]
|
||||
"vdot.t S002, C130, R102\n" // S002 = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2]
|
||||
#endif
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in ), "m"( *v )
|
||||
);
|
||||
#else
|
||||
out[0] = v[0] * in[0][0] + v[1] * in[1][0] + v[2] * in[2][0];
|
||||
out[1] = v[0] * in[0][1] + v[1] * in[1][1] + v[2] * in[2][1];
|
||||
out[2] = v[0] * in[0][2] + v[1] * in[1][2] + v[2] * in[2][2];
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void Matrix4x4_ConcatTransforms( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C100, 0 + %1\n" // C100 = in1[0]
|
||||
"lv.q C110, 16 + %1\n" // C110 = in1[1]
|
||||
"lv.q C120, 32 + %1\n" // C120 = in1[2]
|
||||
"vzero.q C130\n" // C130 = [0, 0, 0, 0]
|
||||
"lv.q C200, 0 + %2\n" // C100 = in2[0]
|
||||
"lv.q C210, 16 + %2\n" // C110 = in2[1]
|
||||
"lv.q C220, 32 + %2\n" // C120 = in2[2]
|
||||
"vidt.q C230\n" // C230 = [0, 0, 0, 1]
|
||||
"vmmul.q E000, E100, E200\n" // E000 = E100 * E200
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *in1 ), "m"( *in2 )
|
||||
);
|
||||
#else
|
||||
out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
|
||||
out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
|
||||
out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
|
||||
@@ -288,10 +717,174 @@ void Matrix4x4_ConcatTransforms( matrix4x4 out, const matrix4x4 in1, const matri
|
||||
out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
|
||||
out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
|
||||
out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_t origin, float scale )
|
||||
{
|
||||
#if 0/*XASH_PSP*/ /* performance not tested */ /* BUG */
|
||||
if( angles[ROLL] )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S100, 0 + %1\n" // S100 = angles[PITCH]
|
||||
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||
"lv.s S102, 8 + %1\n" // S102 = angles[ROLL]
|
||||
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %3\n" // S130 = scale
|
||||
/**/
|
||||
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||
"vscl.t C100, C100, S120\n" // C100 = C100 * S120 = angles * ( 2 / 180 )
|
||||
/**/
|
||||
"vsin.t C110, C100\n" // C110 = sin( C100 ) P Y R
|
||||
"vcos.t C120, C100\n" // C120 = cos( C100 ) P Y R
|
||||
"vneg.t C100, C110\n" // C100 = -C110 = -sin( C100 )
|
||||
/**/
|
||||
"vmul.s S000, S120, S121\n" // S000 = S120 * S121 = out[0][0] = ( cp * cy )
|
||||
"vmul.s S011, S112, S110\n" // S011 = S112 * S110 = ( sr * sp )
|
||||
"vmul.s S001, S011, S121\n" // S001 = S011 * S121 = ( sr * sp * cy )
|
||||
"vmul.s S103, S122, S101\n" // S001 = S122 * S101 = ( cr * -sy )
|
||||
"vadd.s S001, S001, S103\n" // S001 = S001 + S103 = out[0][1] = ( sr * sp * cy + cr * -sy )
|
||||
"vmul.s S012, S122, S110\n" // S002 = S122 * S110 = ( cr * sp )
|
||||
"vmul.s S002, S012, S121\n" // S002 = S012 * S121 = ( cr * sp * cy )
|
||||
"vmul.s S103, S102, S101\n" // S002 = S102 * S101 = ( -sr * -sy )
|
||||
"vadd.s S002, S002, S103\n" // S002 = S002 + S103 = out[0][2] = ( cr * sp * cy + -sr * -sy )
|
||||
/**/
|
||||
"vmul.s S010, S120, S111\n" // S010 = S120 * S111 = out[1][0] = ( cp * sy )
|
||||
"vmul.s S011, S011, S111\n" // S001 = S011 * S111 = ( sr * sp * sy )
|
||||
"vmul.s S103, S122, S121\n" // S001 = S122 * S121 = ( cr * cy )
|
||||
"vadd.s S011, S011, S103\n" // S011 = S011 + S103 = out[1][1] = ( sr * sp * sy + cr * cy )
|
||||
"vmul.s S012, S012, S111\n" // S012 = S012 * S111 = ( cr * sp * sy )
|
||||
"vmul.s S103, S102, S121\n" // S103 = S102 * S121 = ( -sr * cy )
|
||||
"vadd.s S012, S012, S103\n" // S012 = S012 + S103 = out[1][2] = ( cr * sp * sy + -sr * cy )
|
||||
/**/
|
||||
"vmov.s S020, S101\n" // S020 = S101 = out[2][0] = ( -sp )
|
||||
"vmul.s S021, S112, S120\n" // S021 = S112 * S120 = out[2][1] = ( sr * cp )
|
||||
"vmul.s S022, S122, S120\n" // S021 = S122 * S120 = out[2][2] = ( cr * cp )
|
||||
/**/
|
||||
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||
"vidt.q C030\n" // C030 = [0.0f, 0.0f, 0.0f, 1.0f]
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
else if( angles[PITCH] )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S100, 0 + %1\n" // S100 = angles[PITCH]
|
||||
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %3\n" // S130 = scale
|
||||
/**/
|
||||
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||
"vscl.p C100, C100, S120\n" // C100 = C100 * S120 = angles * ( 2 / 180 )
|
||||
/**/
|
||||
"vsin.p C110, C100\n" // C110 = sin( C100 ) P Y
|
||||
"vcos.p C120, C100\n" // C120 = cos( C100 ) P Y
|
||||
"vneg.p C100, C110\n" // C100 = -C110 = -sin( C100 )
|
||||
/**/
|
||||
"vmul.s S000, S120, S121\n" // S000 = S120 * S121 = out[0][0] = ( cp * cy )
|
||||
"vmov.s S001, S101\n" // S001 = S101 = out[0][1] = ( -sy )
|
||||
"vmul.s S002, S110, S121\n" // S001 = S110 * S121 = out[0][2] = ( sp * cy )
|
||||
/**/
|
||||
"vmul.s S010, S120, S111\n" // S010 = S120 * S111 = out[1][0] = ( cp * sy )
|
||||
"vmov.s S011, S121\n" // S011 = S121 = out[1][1] = ( cy )
|
||||
"vmul.s S012, S110, S111\n" // S012 = S110 * S111 = out[1][2] = ( sp * sy )
|
||||
/**/
|
||||
"vmov.s S020, S100\n" // S020 = S100 = out[2][0] = ( -sp )
|
||||
"vzero.s S021\n" // S021 = out[2][1] = 0.0f
|
||||
"vmov.s S022, S120\n" // S022 = S120 = out[2][2] = ( cp )
|
||||
/**/
|
||||
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||
"vidt.q C030\n" // C030 = [0.0f, 0.0f, 0.0f, 1.0f]
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
else if( angles[YAW] )
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S101, 4 + %1\n" // S101 = angles[YAW]
|
||||
"lv.s S003, 0 + %2\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %2\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %2\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %3\n" // S130 = scale
|
||||
/**/
|
||||
"vfim.s S120, 0.0111111111111111\n" // S121 = 0.0111111111111111 const ( 2 / 180 )
|
||||
"vmul.s S101, S101, S120\n" // S101 = S101 * S120 = angles[YAW] * ( 2 / 180 )
|
||||
/**/
|
||||
"vsin.s S111, S101\n" // S111 = sin( S101 ) Y
|
||||
"vcos.s S121, S101\n" // S121 = cos( S101 ) Y
|
||||
/**/
|
||||
"vzero.p R002\n" // S002 = 0.0f S012 = 0.0f
|
||||
"vzero.p C020\n" // S020 = 0.0f S021 = 0.0f
|
||||
"vmov.s S000, S121\n" // S000 = S121 = out[0][0] = ( cy )
|
||||
"vneg.s S001, S111\n" // S001 = S111 = out[0][1] = ( -sy )
|
||||
"vmov.s S010, S111\n" // S010 = S111 = out[1][0] = ( sy )
|
||||
"vmov.s S011, S121\n" // S011 = S121 = out[1][1] = ( cy )
|
||||
"vone.s S022\n" // S022 = out[2][2] = 1.0f
|
||||
/**/
|
||||
"vmscl.t E000, E000, S130\n" // E000 = E000 * S103 = out(3) * scale
|
||||
"vidt.q C030\n" // C030 = [0.0f, 0.0f, 0.0f, 1.0f]
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *angles ), "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.s S003, 0 + %1\n" // S003 = out[0][3] = origin[0]
|
||||
"lv.s S013, 4 + %1\n" // S013 = out[1][3] = origin[1]
|
||||
"lv.s S023, 8 + %1\n" // S023 = out[2][3] = origin[2]
|
||||
"lv.s S130, %2\n" // S130 = scale
|
||||
/**/
|
||||
"vzero.t C000\n" // C000 = [0.0f, 0.0f, 0.0f]
|
||||
"vzero.t C010\n" // C010 = [0.0f, 0.0f, 0.0f]
|
||||
"vzero.t C020\n" // C020 = [0.0f, 0.0f, 0.0f]
|
||||
"vidt.q C030\n" // C030 = [0.0f, 0.0f, 0.0f, 1.0f]
|
||||
"vmov.s S000, S130\n" // S000 = S130 = out[0][0] = scale
|
||||
"vmov.s S011, S130\n" // S011 = S130 = out[1][1] = scale
|
||||
"vmov.s S022, S130\n" // S022 = S130 = out[2][2] = scale
|
||||
/**/
|
||||
"sv.q C000, 0 + %0\n" // out[0] = C000
|
||||
"sv.q C010, 16 + %0\n" // out[1] = C010
|
||||
"sv.q C020, 32 + %0\n" // out[2] = C020
|
||||
"sv.q C030, 48 + %0\n" // out[3] = C030
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out )
|
||||
: "m"( *origin ), "m"( scale )
|
||||
);
|
||||
}
|
||||
#else
|
||||
float angle, sr, sp, sy, cr, cp, cy;
|
||||
|
||||
if( angles[ROLL] )
|
||||
@@ -385,6 +978,7 @@ void Matrix4x4_CreateFromEntity( matrix4x4 out, const vec3_t angles, const vec3_
|
||||
out[3][2] = 0.0f;
|
||||
out[3][3] = 1.0f;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix4x4_ConvertToEntity( const matrix4x4 in, vec3_t angles, vec3_t origin )
|
||||
@@ -412,6 +1006,36 @@ void Matrix4x4_ConvertToEntity( const matrix4x4 in, vec3_t angles, vec3_t origin
|
||||
|
||||
void Matrix4x4_TransformPositivePlane( const matrix4x4 in, const vec3_t normal, float d, vec3_t out, float *dist )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"mfc1 $8, %4\n" // FPU->CPU
|
||||
"mtv $8, S210\n" // CPU->VFPU S210 = d
|
||||
"lv.q C100, 0 + %2\n" // C100 = in[0]
|
||||
"lv.q C110, 16 + %2\n" // C110 = in[1]
|
||||
"lv.q C120, 32 + %2\n" // C120 = in[2]
|
||||
"lv.s S200, 0 + %3\n" // S200 = normal[0]
|
||||
"lv.s S201, 4 + %3\n" // S201 = normal[1]
|
||||
"lv.s S202, 8 + %3\n" // S202 = normal[2]
|
||||
"vdot.t S211, C100, C100\n" // S211 = C100 * C100
|
||||
"vsqrt.s S211, S211\n" // S211 = sqrt( S211 )
|
||||
"vrcp.s S212, S211\n" // S212 = 1 / S211
|
||||
"vtfm3.t C000, M100, C200\n" // C000 = M100 * C200
|
||||
"vscl.t C000, C000, S212\n" // C000 = C000 * S211
|
||||
"vmul.s S003, S210, S211\n" // S003 = S210 * S211
|
||||
"vdot.t S010, R103, C000\n" // S010 = R103 * C000
|
||||
"vadd.s S003, S003, S010\n" // S003 = S003 + S010
|
||||
"sv.s S000, 0 + %0\n" // out[0] = S000
|
||||
"sv.s S001, 4 + %0\n" // out[1] = S001
|
||||
"sv.s S002, 8 + %0\n" // out[2] = S002
|
||||
"sv.s S003, %1\n" // dist = S003
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *out ), "=m"( *dist )
|
||||
: "m"( *in ), "m"( *normal ), "f"( d )
|
||||
: "$8"
|
||||
);
|
||||
#else
|
||||
float scale = sqrt( in[0][0] * in[0][0] + in[0][1] * in[0][1] + in[0][2] * in[0][2] );
|
||||
float iscale = 1.0f / scale;
|
||||
|
||||
@@ -419,6 +1043,7 @@ void Matrix4x4_TransformPositivePlane( const matrix4x4 in, const vec3_t normal,
|
||||
out[1] = (normal[0] * in[1][0] + normal[1] * in[1][1] + normal[2] * in[1][2]) * iscale;
|
||||
out[2] = (normal[0] * in[2][0] + normal[1] * in[2][1] + normal[2] * in[2][2]) * iscale;
|
||||
*dist = d * scale + ( out[0] * in[0][3] + out[1] * in[1][3] + out[2] * in[2][3] );
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix4x4_Invert_Simple( matrix4x4 out, const matrix4x4 in1 )
|
||||
|
||||
0
public/rbtree.h
Normal file
0
public/rbtree.h
Normal file
@@ -16,7 +16,7 @@ def configure(conf):
|
||||
|
||||
def build(bld):
|
||||
bld(name = 'sdk_includes', export_includes = '. ../common ../pm_shared ../engine')
|
||||
bld.stlib(source = bld.path.ant_glob('*.c'),
|
||||
bld.stlib(source = bld.path.ant_glob('*.c') + bld.path.ant_glob('*.S'),
|
||||
target = 'public',
|
||||
features = 'c',
|
||||
use = 'sdk_includes',
|
||||
|
||||
@@ -209,6 +209,30 @@ rsqrt
|
||||
*/
|
||||
float rsqrt( float number )
|
||||
{
|
||||
#if XASH_PSP
|
||||
#if 0 /* experimental */
|
||||
if( number == 0.0f ) return 0.0f;
|
||||
return ( 1.0 / __builtin_allegrex_sqrt_s( number ));
|
||||
#else
|
||||
float result;
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"mfc1 $8, %1\n" // FPU->CPU
|
||||
"mtv $8, S000\n" // CPU->VFPU S000 = number
|
||||
"vzero.s S001\n" // S100 = 0
|
||||
"vcmp.s EZ, S000\n" // CC[0] = ( S000 == 0.0f )
|
||||
"vrsq.s S000, S000\n" // S000 = 1.0 / sqrt( S000 )
|
||||
"vcmovt.s S000, S001, 0\n" // if ( CC[0] ) S000 = S001
|
||||
"sv.s S000, %0\n" // result = S000
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( result )
|
||||
: "f"( number )
|
||||
: "$8"
|
||||
);
|
||||
return result;
|
||||
#endif
|
||||
#else
|
||||
int i;
|
||||
float x, y;
|
||||
|
||||
@@ -222,6 +246,7 @@ float rsqrt( float number )
|
||||
y = y * (1.5f - (x * y * y)); // first iteration
|
||||
|
||||
return y;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -384,6 +409,7 @@ void VectorsAngles( const vec3_t forward, const vec3_t right, const vec3_t up, v
|
||||
//
|
||||
// bounds operations
|
||||
//
|
||||
|
||||
/*
|
||||
=================
|
||||
AddPointToBounds
|
||||
@@ -485,6 +511,46 @@ AngleQuaternion
|
||||
*/
|
||||
void AngleQuaternion( const vec3_t angles, vec4_t q, qboolean studio )
|
||||
{
|
||||
#if XASH_PSP
|
||||
vec4_t dst_angles;
|
||||
if( studio )
|
||||
{
|
||||
dst_angles[0] = angles[PITCH];
|
||||
dst_angles[1] = angles[YAW];
|
||||
dst_angles[2] = angles[ROLL];
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_angles[0] = DEG2RAD( angles[ROLL] );
|
||||
dst_angles[1] = DEG2RAD( angles[PITCH] );
|
||||
dst_angles[2] = DEG2RAD( angles[YAW] );
|
||||
}
|
||||
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"lv.q C000, %1\n" // C000 = [PITCH, YAW, ROLL]
|
||||
"vcst.s S010, VFPU_1_PI\n" // S010 = VFPU_1_PI = 1 / PI
|
||||
"vscl.t C000, C000, S010\n" // C000 = C000 * S010 = C000 * 0.5f * ( 2 / PI )
|
||||
"vcos.t C010, C000\n" // C010 = cos( C000 * 0.5f )
|
||||
"vsin.t C000, C000\n" // C000 = sin( C000 * 0.5f )
|
||||
"vcrs.t C020, C010, C010\n" // C020 = ( cp*cy, cy*cr, cr*cp )
|
||||
"vcrs.t C030, C000, C000\n" // C030 = ( sp*sy, sy*sr, sr*sp )
|
||||
"vmul.s S003, S020, S010\n" // S003 = S020 * S010 = cp*cy*cr
|
||||
"vmul.s S013, S030, S000\n" // S013 = S030 * S000 = sp*sy*sr
|
||||
"vmul.t C020, C020, C000\n" // C020 = C020 * C000 = ( cp*cy*sr, cy*cr*sp, cr*cp*sy )
|
||||
"vmul.t C030, C030, C010\n" // C030 = C030 * C010 = ( sp*sy*cr, sy*sr*cp, sr*sp*cy )
|
||||
"vadd.s S003, S003, S013\n" // S003 = S003 + S013 = cp*cy*cr + cp*cy*cr
|
||||
"vadd.t C000, C020, C030[-X, Y, -Z]\n"
|
||||
// S000 = S020 - C030 = cp*cy*sr - sp*sy*cr
|
||||
// S001 = S021 + C031 = cy*cr*sp + sy*sr*cp
|
||||
// S002 = S022 - C032 = cr*cp*sy - sr*sp*cy
|
||||
"sv.q C000, %0\n" // *q = C000
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *q )
|
||||
: "m"( dst_angles )
|
||||
);
|
||||
#else
|
||||
float sr, sp, sy, cr, cp, cy;
|
||||
|
||||
if( studio )
|
||||
@@ -504,6 +570,7 @@ void AngleQuaternion( const vec3_t angles, vec4_t q, qboolean studio )
|
||||
q[1] = cr * sp * cy + sr * cp * sy; // Y
|
||||
q[2] = cr * cp * sy - sr * sp * cy; // Z
|
||||
q[3] = cr * cp * cy + sr * sp * sy; // W
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -527,6 +594,7 @@ make sure quaternions are within 180 degrees of one another,
|
||||
if not, reverse q
|
||||
====================
|
||||
*/
|
||||
#if !XASH_PSP
|
||||
void QuaternionAlign( const vec4_t p, const vec4_t q, vec4_t qt )
|
||||
{
|
||||
// decide if one of the quaternions is backwards
|
||||
@@ -615,9 +683,9 @@ void QuaternionSlerp( const vec4_t p, const vec4_t q, float t, vec4_t qt )
|
||||
// 0.0 returns p, 1.0 return q.
|
||||
// decide if one of the quaternions is backwards
|
||||
QuaternionAlign( p, q, q2 );
|
||||
|
||||
QuaternionSlerpNoAlign( p, q2, t, qt );
|
||||
}
|
||||
#endif // XASH_PSP
|
||||
|
||||
/*
|
||||
==================
|
||||
@@ -626,10 +694,11 @@ BoxOnPlaneSide
|
||||
Returns 1, 2, or 1 + 2
|
||||
==================
|
||||
*/
|
||||
#if !XASH_PSP
|
||||
int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p )
|
||||
{
|
||||
float dist1, dist2;
|
||||
int sides = 0;
|
||||
float dist1, dist2;
|
||||
|
||||
// general case
|
||||
switch( p->signbits )
|
||||
@@ -679,6 +748,7 @@ int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p )
|
||||
|
||||
return sides;
|
||||
}
|
||||
#endif // !XASH_PSP
|
||||
|
||||
/*
|
||||
====================
|
||||
|
||||
@@ -175,8 +175,26 @@ static inline float UintAsFloat( uint32_t u )
|
||||
|
||||
static inline void SinCos( float radians, float *sine, float *cosine )
|
||||
{
|
||||
#if XASH_PSP
|
||||
__asm__ (
|
||||
".set push\n" // save assembler option
|
||||
".set noreorder\n" // suppress reordering
|
||||
"mfc1 $8, %2\n" // FPU->CPU
|
||||
"mtv $8, S000\n" // CPU->VFPU S000 = radians
|
||||
"vcst.s S001, VFPU_2_PI\n" // S001 = VFPU_2_PI = 2 / PI
|
||||
"vmul.s S000, S000, S001\n" // S000 = S000 * S001
|
||||
"vrot.p C002, S000, [s, c]\n" // S002 = sin( radians ), S003 = cos( radians )
|
||||
"sv.s S002, %0\n" // sine = S002
|
||||
"sv.s S003, %1\n" // cosine = S003
|
||||
".set pop\n" // restore assembler option
|
||||
: "=m"( *sine), "=m"( *cosine )
|
||||
: "f"( radians )
|
||||
: "$8"
|
||||
);
|
||||
#else
|
||||
*sine = sin(radians);
|
||||
*cosine = cos(radians);
|
||||
#endif
|
||||
}
|
||||
|
||||
float rsqrt( float number );
|
||||
|
||||
218
public/xash3d_mathlib_asm.S
Normal file
218
public/xash3d_mathlib_asm.S
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
xash3d_mathlib_asm.S - internal mathlib ASM ver.
|
||||
Copyright (C) 2022 Sergey Galushko
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
#include "build.h"
|
||||
#if XASH_PSP
|
||||
#include "as_reg_compat.h"
|
||||
.set noreorder
|
||||
.set noat
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.global QuaternionSlerp
|
||||
.global BoxOnPlaneSide
|
||||
|
||||
// void QuaternionSlerp( const vec4_t p, const vec4_t q, float t, vec4_t qt );
|
||||
.ent QuaternionSlerp
|
||||
QuaternionSlerp:
|
||||
############################
|
||||
# a0 - IN *p #
|
||||
# a1 - IN *q #
|
||||
# f12 - IN t #
|
||||
# a2 - IN *qt #
|
||||
############################
|
||||
mfc1 $t0, $f12
|
||||
mtv $t0, S031 // S031 = sclq = t
|
||||
li $t0, 0x358637bd // t0 = EPSILON = 0.000001f
|
||||
mtv $t0, S033 // S002 = t0 = EPSILON
|
||||
lv.q C010, 0($a0) // C010 = p
|
||||
lv.q C020, 0($a1) // C020 = q
|
||||
|
||||
// QuaternionAlign
|
||||
vsub.q C100, C010, C020 // C100 = p[*] - q[*]
|
||||
vadd.q C110, C010, C020 // C110 = p[*] + q[*]
|
||||
vdot.q S000, C100, C100 // S000 = a += (p[*] - q[*]) * (p[*] - q[*])
|
||||
vdot.q S001, C110, C110 // S001 = b += (p[*] + q[*]) * (p[*] + q[*])
|
||||
vcmp.s GT, S000, S001 // CC[0] = a > b
|
||||
vcmovt.q C020, C020[-X,-Y,-Z,-W], 0 // if CC[0] q = -q
|
||||
// ***
|
||||
|
||||
// QuaternionSlerpNoAlign
|
||||
vdot.q S000, C010, C020 // S000 = cosom += p[*] * q[*]
|
||||
vadd.s S001, S000[1], S000 // S002 = 1.0f + cosom
|
||||
vcmp.s LE, S001, S033 // CC[0] = ( 1.0f + cosom ) <= 0.000001f
|
||||
bvt 0, Lqs2 // if CC[0] goto Lqs2
|
||||
vocp.s S030, S031 // S030 = sclp = 1.0f - t (delay slot)
|
||||
vsub.s S001, S000[1], S000 // S002 = 1.0f - cosom
|
||||
vcmp.s LE, S001, S033 // CC[0] = ( 1.0f - cosom ) <= 0.000001f
|
||||
bvt 0, Lqs1
|
||||
nop
|
||||
|
||||
// acos
|
||||
vcst.s S001, VFPU_SQRT1_2 // S001 = VFPU_SQRT1_2 = 1 / sqrt(2)
|
||||
vcmp.s LT, S000[|x|], S001 // CC[0] = abs(cosom) < (1 / sqrt(2))
|
||||
vasin.s S032, S000[|x|] // S032 = asin(abs(cosom))
|
||||
bvtl 0, Lqs0 // if CC[0] goto Lqs0
|
||||
vocp.s S032, S032 // S032 = 1 - S032 = acos(abs(cosom)) = omega (bvtl delay slot)
|
||||
vmul.s S001, S000, S000 // S001 = cosom * cosom
|
||||
vocp.s S001[0:1], S001 // S001 = 1 - S001[0:1]
|
||||
vsqrt.s S001, S001 // S001 = sqrt(S001)
|
||||
vasin.s S032, S001 // S032 = asin(S001) = acos(abs(cosom)) = omega
|
||||
// ***
|
||||
Lqs0:
|
||||
vscl.p C030, C030, S032 // S030 = S030 * S032 = sclp * omega
|
||||
// S031 = S031 * S032 = sclq * omega
|
||||
vsin.t C030, C030 // S030 = sin(S030) = sin(sclp * omega) = sclp
|
||||
// S031 = sin(S031) = sin(sclq * omega) = sclq
|
||||
// S032 = sin(S032) = sin(omega)
|
||||
vrcp.s S032, S032 // S032 = 1.0f / S032 = 1 / sin(omega) = sinom
|
||||
vscl.p C030, C030, S032 // S030 = S030 * S032 = sin(sclp * omega) / sinom
|
||||
// S031 = S031 * S032 = sin(sclq * omega) / sinom
|
||||
Lqs1:
|
||||
vscl.q C010, C010, S030 // C010 = p[*4] * sclp
|
||||
vscl.q C020, C020, S031 // C020 = qt[*4] * sclq
|
||||
b LqsEnd // goto LqsEnd
|
||||
vadd.q C000, C010, C020 // S000 = qt[0] = sclp * p[0] + sclq * qt[0] (delay slot)
|
||||
// S001 = qt[1] = sclp * p[1] + sclq * qt[1]
|
||||
// S002 = qt[2] = sclp * p[2] + sclq * qt[2]
|
||||
// S003 = qt[3] = sclp * p[3] + sclq * qt[3]
|
||||
Lqs2:
|
||||
vmov.q C000, C020[-Y,X,-W,Z] // S000 = qt[0] = -q[1];
|
||||
// S001 = qt[1] = q[0];
|
||||
// S002 = qt[2] = -q[3];
|
||||
// S003 = qt[3] = q[2];
|
||||
vsin.p C030, C030 // S030 = sclp = sin(( 1.0f - t ) * ( 0.5f * M_PI_F ))
|
||||
// S031 = sclq = sin( t * ( 0.5f * M_PI_F ))
|
||||
vscl.t C010, C010, S030 // C000 = p[*3] * sclp
|
||||
vscl.t C020, C000, S031 // C030 = qt[*3] * sclq
|
||||
vadd.t C000, C010, C020 // S000 = qt[0] = sclp * p[0] + sclq * qt[0]
|
||||
// S001 = qt[1] = sclp * p[1] + sclq * qt[1]
|
||||
// S002 = qt[2] = sclp * p[2] + sclq * qt[2]
|
||||
// S003 = qt[3]
|
||||
LqsEnd:
|
||||
sv.q C000, 0($a2)
|
||||
jr $ra
|
||||
.end QuaternionSlerp
|
||||
|
||||
|
||||
|
||||
|
||||
// int BoxOnPlaneSide( vec3_t emins, vec3_t emaxs, mplane_t *p );
|
||||
.ent BoxOnPlaneSide
|
||||
BoxOnPlaneSide:
|
||||
############################
|
||||
# a0 - IN *emins #
|
||||
# a1 - IN *emaxs #
|
||||
# a2 - IN *p #
|
||||
# v0 - OUT sides #
|
||||
############################
|
||||
lbu $v0, 17($a2) // p->signbits
|
||||
sltiu $v1, $v0, 8 // if(signbits > 8)
|
||||
beq $v1, $zero, LSetSides // jump to LSetSides
|
||||
vzero.p C030 // set zero vector
|
||||
sll $v1, $v0, 2
|
||||
la $v0, Ljmptab
|
||||
addu $v0, $v0, $v1
|
||||
lw $v0, 0($v0)
|
||||
lv.s S000, 0($a2) // p->normal[0]
|
||||
lv.s S001, 4($a2) // p->normal[1]
|
||||
jr $v0
|
||||
lv.s S002, 8($a2) // p->normal[2]
|
||||
Lcase0:
|
||||
lv.s S010, 0($a1) // emaxs[0]
|
||||
lv.s S011, 4($a1) // emaxs[1]
|
||||
lv.s S012, 8($a1) // emaxs[2]
|
||||
lv.s S020, 0($a0) // emins[0]
|
||||
lv.s S021, 4($a0) // emins[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a0) // emins[2]
|
||||
Lcase1:
|
||||
lv.s S010, 0($a0) // emins[0]
|
||||
lv.s S011, 4($a1) // emaxs[1]
|
||||
lv.s S012, 8($a1) // emaxs[2]
|
||||
lv.s S020, 0($a1) // emaxs[0]
|
||||
lv.s S021, 4($a0) // emins[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a0) // emins[2]
|
||||
Lcase2:
|
||||
lv.s S010, 0($a1) // emaxs[0]
|
||||
lv.s S011, 4($a0) // emins[1]
|
||||
lv.s S012, 8($a1) // emaxs[2]
|
||||
lv.s S020, 0($a0) // emins[0]
|
||||
lv.s S021, 4($a1) // emaxs[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a0) // emins[2]
|
||||
Lcase3:
|
||||
lv.s S010, 0($a0) // emins[0]
|
||||
lv.s S011, 4($a0) // emins[1]
|
||||
lv.s S012, 8($a1) // emaxs[2]
|
||||
lv.s S020, 0($a1) // emaxs[0]
|
||||
lv.s S021, 4($a1) // emaxs[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a0) // emins[2]
|
||||
Lcase4:
|
||||
lv.s S010, 0($a1) // emaxs[0]
|
||||
lv.s S011, 4($a1) // emaxs[1]
|
||||
lv.s S012, 8($a0) // emins[2]
|
||||
lv.s S020, 0($a0) // emins[0]
|
||||
lv.s S021, 4($a0) // emins[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a1) // emaxs[2]
|
||||
Lcase5:
|
||||
lv.s S010, 0($a0) // emins[0]
|
||||
lv.s S011, 4($a1) // emaxs[1]
|
||||
lv.s S012, 8($a0) // emins[2]
|
||||
lv.s S020, 0($a1) // emaxs[0]
|
||||
lv.s S021, 4($a0) // emins[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a1) // emaxs[2]
|
||||
Lcase6:
|
||||
lv.s S010, 0($a1) // emaxs[0]
|
||||
lv.s S011, 4($a0) // emins[1]
|
||||
lv.s S012, 8($a0) // emins[2]
|
||||
lv.s S020, 0($a0) // emins[0]
|
||||
lv.s S021, 4($a1) // emaxs[1]
|
||||
b LDotProduct
|
||||
lv.s S022, 8($a1) // emaxs[2]
|
||||
Lcase7:
|
||||
lv.s S010, 0($a0) // emins[0]
|
||||
lv.s S011, 4($a0) // emins[1]
|
||||
lv.s S012, 8($a0) // emins[2]
|
||||
lv.s S020, 0($a1) // emaxs[0]
|
||||
lv.s S021, 4($a1) // emaxs[1]
|
||||
lv.s S022, 8($a1) // emaxs[2]
|
||||
LDotProduct:
|
||||
vdot.t S030, C000, C010 // S030 = C000 * C010
|
||||
vdot.t S031, C000, C020 // S031 = C000 * C020
|
||||
LSetSides:
|
||||
lv.s S013, 12($a2) // p->dist
|
||||
vcmp.s LT, S030, S013 // S030 < S013
|
||||
bvt 0, LDist2 // if ( CC[0] == 1 ) jump to LDist2
|
||||
li $v0, 0 // sides = 0
|
||||
li $v0, 1 // sides = 1
|
||||
LDist2:
|
||||
vcmp.s GE, S031, S013 // S031 >= S013
|
||||
bvt 0, LEnd // if ( CC[0] == 1 ) jump to LEnd
|
||||
nop
|
||||
ori $v0, $v0, 2
|
||||
LEnd:
|
||||
jr $ra
|
||||
nop
|
||||
.end BoxOnPlaneSide
|
||||
|
||||
.section .rodata
|
||||
.align 4
|
||||
Ljmptab:
|
||||
.word Lcase0, Lcase1, Lcase2, Lcase3, Lcase4, Lcase5, Lcase6, Lcase7
|
||||
#endif // XASH_PSP
|
||||
@@ -167,25 +167,6 @@ qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf )
|
||||
return loaded;
|
||||
}
|
||||
|
||||
static qboolean R_TextureFilteringEnabled( int arg )
|
||||
{
|
||||
gl_texture_t *glt;
|
||||
|
||||
if( arg < 0 )
|
||||
return gl_texture_nearest.value == 0.0f;
|
||||
|
||||
glt = R_GetTexture( arg );
|
||||
|
||||
if( FBitSet( glt->flags, TF_NEAREST ))
|
||||
return false;
|
||||
|
||||
// lightmaps have special cvar
|
||||
if( FBitSet( glt->flags, TF_ATLAS_PAGE ))
|
||||
return gl_lightmap_nearest.value == 0.0f;
|
||||
|
||||
return gl_texture_nearest.value == 0.0f;
|
||||
}
|
||||
|
||||
static int GL_RefGetParm( int parm, int arg )
|
||||
{
|
||||
gl_texture_t *glt;
|
||||
@@ -256,8 +237,6 @@ static int GL_RefGetParm( int parm, int arg )
|
||||
return glState.stencilEnabled;
|
||||
case PARM_SKY_SPHERE:
|
||||
return FBitSet( tr.world->flags, FWORLD_SKYSPHERE ) && !FBitSet( tr.world->flags, FWORLD_CUSTOM_SKYBOX );
|
||||
case PARM_TEX_FILTERING:
|
||||
return R_TextureFilteringEnabled( arg );
|
||||
default:
|
||||
return ENGINE_GET_PARM_( parm, arg );
|
||||
}
|
||||
|
||||
@@ -383,6 +383,7 @@ 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 );
|
||||
|
||||
//
|
||||
|
||||
@@ -153,12 +153,8 @@ void R_PushDlights( void )
|
||||
tr.dlightframecount = tr.framecount;
|
||||
|
||||
RI.currententity = CL_GetEntityByIndex( 0 );
|
||||
|
||||
// no world -- no dlights
|
||||
if( !RI.currententity )
|
||||
return;
|
||||
|
||||
RI.currentmodel = RI.currententity->model;
|
||||
if( RI.currententity )
|
||||
RI.currentmodel = RI.currententity->model;
|
||||
|
||||
for( i = 0; i < MAX_DLIGHTS; i++, l++ )
|
||||
{
|
||||
@@ -170,10 +166,31 @@ void R_PushDlights( void )
|
||||
if( GL_FrustumCullSphere( &RI.frustum, l->origin, l->radius, 15 ))
|
||||
continue;
|
||||
|
||||
R_MarkLights( l, 1<<i, RI.currentmodel->nodes );
|
||||
if( RI.currententity )
|
||||
R_MarkLights( l, 1<<i, RI.currentmodel->nodes );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
|
||||
@@ -224,9 +224,10 @@ every render pass applies new fog layer, resulting in wrong fog color
|
||||
recalculate fog color for current pass count
|
||||
===============================
|
||||
*/
|
||||
void GL_SetupFogColorForSurfacesEx( int passes, float density, qboolean blend_lightmaps )
|
||||
|
||||
void GL_SetupFogColorForSurfacesEx( int passes, float density )
|
||||
{
|
||||
vec4_t fogColor;
|
||||
vec3_t fogColor;
|
||||
float factor, div;
|
||||
|
||||
if( !glState.isFogEnabled )
|
||||
@@ -243,13 +244,6 @@ void GL_SetupFogColorForSurfacesEx( int passes, float density, qboolean blend_li
|
||||
fogColor[0] = pow( RI.fogColor[0] / div, ( 1.0f / factor ));
|
||||
fogColor[1] = pow( RI.fogColor[1] / div, ( 1.0f / factor ));
|
||||
fogColor[2] = pow( RI.fogColor[2] / div, ( 1.0f / factor ));
|
||||
fogColor[3] = 1.0f; // ignored but GL_FOG_COLOR requires vec4_t
|
||||
|
||||
// because of enabled blending in R_BlendLightmaps, need to scale down fog color
|
||||
// but only during lightmap blending & without VBO (it takes another route)
|
||||
if( blend_lightmaps && gl_overbright.value )
|
||||
VectorScale( fogColor, 0.5f, fogColor );
|
||||
|
||||
pglFogfv( GL_FOG_COLOR, fogColor );
|
||||
pglFogf( GL_FOG_DENSITY, RI.fogDensity * density );
|
||||
}
|
||||
@@ -257,7 +251,7 @@ void GL_SetupFogColorForSurfacesEx( int passes, float density, qboolean blend_li
|
||||
|
||||
void GL_SetupFogColorForSurfaces( void )
|
||||
{
|
||||
GL_SetupFogColorForSurfacesEx( r_detailtextures.value ? 3 : 2, 1.0f, false );
|
||||
GL_SetupFogColorForSurfacesEx( r_detailtextures.value ? 3 : 2, 1.0f );
|
||||
}
|
||||
|
||||
void GL_ResetFogColor( void )
|
||||
@@ -527,7 +521,7 @@ texture_t *R_TextureAnimation( msurface_t *s )
|
||||
R_AddDynamicLights
|
||||
===============
|
||||
*/
|
||||
static void R_AddDynamicLights( msurface_t *surf )
|
||||
void R_AddDynamicLights( msurface_t *surf )
|
||||
{
|
||||
float dist, rad, minlight;
|
||||
int lnum, s, t, sd, td, smax, tmax;
|
||||
@@ -541,7 +535,7 @@ static void R_AddDynamicLights( msurface_t *surf )
|
||||
uint *bl;
|
||||
|
||||
// no dlighted surfaces here
|
||||
if( !surf->dlightbits ) return;
|
||||
if( !R_CountSurfaceDlights( surf )) return;
|
||||
|
||||
sample_size = gEngfuncs.Mod_SampleSizeForFace( surf );
|
||||
smax = (info->lightextents[0] / sample_size) + 1;
|
||||
@@ -950,7 +944,7 @@ void R_BlendLightmaps( void )
|
||||
if( !R_HasLightmap() )
|
||||
return;
|
||||
|
||||
GL_SetupFogColorForSurfacesEx( r_detailtextures.value ? 3 : 2, 1.0f, true );
|
||||
GL_SetupFogColorForSurfaces ();
|
||||
|
||||
if( !r_lightmap->value )
|
||||
pglEnable( GL_BLEND );
|
||||
@@ -1128,7 +1122,7 @@ void R_RenderDetails( int passes )
|
||||
if( !draw_details )
|
||||
return;
|
||||
|
||||
GL_SetupFogColorForSurfacesEx( passes, passes == 2 ? 0.5f : 1.0f, false );
|
||||
GL_SetupFogColorForSurfacesEx( passes, passes == 2 ? 0.5f : 1.0f );
|
||||
|
||||
pglEnable( GL_BLEND );
|
||||
pglBlendFunc( GL_DST_COLOR, GL_SRC_COLOR );
|
||||
@@ -1947,10 +1941,9 @@ void R_GenerateVBO( void )
|
||||
|
||||
if( vbo->array_len + surf->polys->numverts > VBOINDEX_MAX )
|
||||
{
|
||||
vbotex->vboarray = vbo;
|
||||
// generate new array and new vbotexture node
|
||||
vbo->array = Mem_Calloc( vbos.mempool, sizeof( vbovertex_t ) * vbo->array_len );
|
||||
gEngfuncs.Con_Printf( "R_GenerateVBOs: allocated array of %d verts, texture %d, lm %d\n", vbo->array_len, j, k );
|
||||
gEngfuncs.Con_Printf( "R_GenerateVBOs: allocated array of %d verts, texture %d\n", vbo->array_len, j );
|
||||
vbo->next = Mem_Calloc( vbos.mempool, sizeof( vboarray_t ) );
|
||||
vbo = vbo->next;
|
||||
vbotex->next = Mem_Calloc( vbos.mempool, sizeof( vbotexture_t ) );
|
||||
@@ -2994,7 +2987,7 @@ void R_ClearVBOState( qboolean drawlightmap, qboolean drawtextures )
|
||||
if( drawlightmap )
|
||||
{
|
||||
// reset states
|
||||
GL_Bind( XASH_TEXTURE1, tr.defaultTexture ); // force reset tmu in case we have only one lightmap
|
||||
GL_SelectTexture( XASH_TEXTURE1 );
|
||||
pglDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
pglDisable( GL_TEXTURE_2D );
|
||||
if( drawtextures )
|
||||
@@ -3036,7 +3029,7 @@ void R_DrawVBO( qboolean drawlightmap, qboolean drawtextures )
|
||||
if( !r_vbo.value )
|
||||
return;
|
||||
|
||||
GL_SetupFogColorForSurfacesEx( 1, 0.5f, false );
|
||||
GL_SetupFogColorForSurfacesEx( 1, 0.5f );
|
||||
|
||||
R_SetupVBOArrayStatic( vbo, drawlightmap, drawtextures );
|
||||
mtst.skiptexture = !drawtextures;
|
||||
|
||||
@@ -142,7 +142,6 @@ void _TriColor4ub( byte r, byte g, byte b, byte a )
|
||||
pglColor4ub( r, g, b, a );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
TriColor4ub
|
||||
@@ -365,4 +364,3 @@ void TriBrightness( float brightness )
|
||||
|
||||
_TriColor4f( r, g, b, 1.0f );
|
||||
}
|
||||
|
||||
|
||||
1
ref/soft/exports.txt
Normal file
1
ref/soft/exports.txt
Normal file
@@ -0,0 +1 @@
|
||||
GetRefAPI
|
||||
@@ -101,6 +101,7 @@ qboolean GAME_EXPORT Mod_ProcessRenderData( model_t *mod, qboolean create, const
|
||||
return loaded;
|
||||
}
|
||||
|
||||
|
||||
static int GL_RefGetParm( int parm, int arg )
|
||||
{
|
||||
image_t *glt;
|
||||
@@ -171,8 +172,6 @@ static int GL_RefGetParm( int parm, int arg )
|
||||
return 0; //glState.stencilEnabled;
|
||||
case PARM_SKY_SPHERE:
|
||||
return 0; // ref_soft doesn't support sky sphere
|
||||
case PARM_TEX_FILTERING:
|
||||
return 0; // ref_soft doesn't do filtering in general
|
||||
default:
|
||||
return ENGINE_GET_PARM_( parm, arg );
|
||||
}
|
||||
|
||||
@@ -201,6 +201,19 @@ void R_SetupDecalTextureSpaceBasis( decal_t *pDecal, msurface_t *surf, int textu
|
||||
// Build the initial list of vertices from the surface verts into the global array, 'verts'.
|
||||
void R_SetupDecalVertsForMSurface( decal_t *pDecal, msurface_t *surf, vec3_t textureSpaceBasis[3], float *verts )
|
||||
{
|
||||
#if XASH_PSP
|
||||
int i;
|
||||
|
||||
if( !surf->polys )
|
||||
return;
|
||||
for( i = 0; i < surf->polys->numverts; i++, verts += VERTEXSIZE )
|
||||
{
|
||||
VectorCopy( surf->polys->verts[i].xyz, verts ); // copy model space coordinates
|
||||
verts[3] = DotProduct( verts, textureSpaceBasis[0] ) - pDecal->dx + 0.5f;
|
||||
verts[4] = DotProduct( verts, textureSpaceBasis[1] ) - pDecal->dy + 0.5f;
|
||||
verts[5] = verts[6] = 0.0f;
|
||||
}
|
||||
#else
|
||||
float *v;
|
||||
int i;
|
||||
|
||||
@@ -213,6 +226,7 @@ void R_SetupDecalVertsForMSurface( decal_t *pDecal, msurface_t *surf, vec3_t tex
|
||||
verts[4] = DotProduct( verts, textureSpaceBasis[1] ) - pDecal->dy + 0.5f;
|
||||
verts[5] = verts[6] = 0.0f;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Figure out where the decal maps onto the surface.
|
||||
@@ -524,7 +538,26 @@ glpoly_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t
|
||||
|
||||
v = R_DecalSetupVerts( pdecal, surf, pdecal->texture, &lnumverts );
|
||||
if( !lnumverts ) return NULL; // probably this never happens
|
||||
#if XASH_PSP
|
||||
// allocate glpoly
|
||||
// REFTODO: com_studiocache pool!
|
||||
poly = Mem_Calloc( r_temppool, sizeof( glpoly_t ) + ( lnumverts * 2 - 1 ) * sizeof( gu_vert_t ));
|
||||
poly->next = pdecal->polys;
|
||||
poly->flags = surf->flags;
|
||||
pdecal->polys = poly;
|
||||
poly->numverts = lnumverts;
|
||||
|
||||
for( i = 0; i < lnumverts; i++, v += VERTEXSIZE )
|
||||
{
|
||||
poly->verts[i].uv[0] = v[3];
|
||||
poly->verts[i].uv[1] = v[4];
|
||||
VectorCopy( v, poly->verts[i].xyz );
|
||||
|
||||
poly->verts[i + lnumverts].uv[0] = v[5];
|
||||
poly->verts[i + lnumverts].uv[1] = v[6];
|
||||
VectorCopy( v, poly->verts[i + lnumverts].xyz );
|
||||
}
|
||||
#else
|
||||
// allocate glpoly
|
||||
// REFTODO: com_studiocache pool!
|
||||
poly = Mem_Calloc( r_temppool, sizeof( glpoly_t ) + ( lnumverts - 4 ) * VERTEXSIZE * sizeof( float ));
|
||||
@@ -541,7 +574,7 @@ glpoly_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t
|
||||
poly->verts[i][5] = v[5];
|
||||
poly->verts[i][6] = v[6];
|
||||
}
|
||||
|
||||
#endif
|
||||
return poly;
|
||||
}
|
||||
|
||||
@@ -861,8 +894,18 @@ float * GAME_EXPORT R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int te
|
||||
{
|
||||
v = g_DecalClipVerts[0];
|
||||
count = p->numverts;
|
||||
#if XASH_PSP
|
||||
// if we have mesh so skip clipping and just copy vertexes out (perf)
|
||||
for( i = 0; i < count; i++, v += VERTEXSIZE )
|
||||
{
|
||||
VectorCopy( p->verts[i].xyz, v );
|
||||
v[3] = p->verts[i].uv[0];
|
||||
v[4] = p->verts[i].uv[1];
|
||||
v[5] = p->verts[i + count].uv[0];
|
||||
v[6] = p->verts[i + count].uv[1];
|
||||
}
|
||||
#else
|
||||
v2 = p->verts[0];
|
||||
|
||||
// if we have mesh so skip clipping and just copy vertexes out (perf)
|
||||
for( i = 0; i < count; i++, v += VERTEXSIZE, v2 += VERTEXSIZE )
|
||||
{
|
||||
@@ -872,7 +915,7 @@ float * GAME_EXPORT R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int te
|
||||
v[5] = v2[5];
|
||||
v[6] = v2[6];
|
||||
}
|
||||
|
||||
#endif
|
||||
// restore pointer
|
||||
v = g_DecalClipVerts[0];
|
||||
}
|
||||
|
||||
@@ -156,12 +156,8 @@ void R_PushDlights( void )
|
||||
tr.dlightframecount = tr.framecount;
|
||||
|
||||
RI.currententity = CL_GetEntityByIndex( 0 );
|
||||
|
||||
// no world -- no dlights
|
||||
if( !RI.currententity )
|
||||
return;
|
||||
|
||||
RI.currentmodel = RI.currententity->model;
|
||||
if( RI.currententity )
|
||||
RI.currentmodel = RI.currententity->model;
|
||||
|
||||
for( i = 0; i < MAX_DLIGHTS; i++, l++ )
|
||||
{
|
||||
@@ -173,10 +169,31 @@ void R_PushDlights( void )
|
||||
//if( GL_FrustumCullSphere( &RI.frustum, l->origin, l->radius, 15 ))
|
||||
//continue;
|
||||
|
||||
R_MarkLights( l, 1<<i, RI.currentmodel->nodes );
|
||||
if( RI.currententity )
|
||||
R_MarkLights( l, 1<<i, RI.currentmodel->nodes );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
=======================================================================
|
||||
|
||||
|
||||
@@ -461,6 +461,7 @@ 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 );
|
||||
#endif
|
||||
//
|
||||
|
||||
@@ -72,7 +72,7 @@ static void R_BuildLightMap( void );
|
||||
R_AddDynamicLights
|
||||
===============
|
||||
*/
|
||||
static void R_AddDynamicLights( msurface_t *surf )
|
||||
void R_AddDynamicLights( msurface_t *surf )
|
||||
{
|
||||
float dist, rad, minlight;
|
||||
int lnum, s, t, sd, td, smax, tmax;
|
||||
@@ -86,7 +86,7 @@ static void R_AddDynamicLights( msurface_t *surf )
|
||||
uint *bl;
|
||||
|
||||
// no dlighted surfaces here
|
||||
if( !surf->dlightbits ) return;
|
||||
//if( !R_CountSurfaceDlights( surf )) return;
|
||||
|
||||
sample_size = gEngfuncs.Mod_SampleSizeForFace( surf );
|
||||
smax = (info->lightextents[0] / sample_size) + 1;
|
||||
|
||||
@@ -492,4 +492,3 @@ void TriBrightness( float brightness )
|
||||
|
||||
_TriColor4f( r, g, b, 1.0f );
|
||||
}
|
||||
|
||||
|
||||
2
ref_gu/exports.txt
Normal file
2
ref_gu/exports.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
GetRefAPI
|
||||
GetRefHumanReadableName
|
||||
1551
ref_gu/gu_alias.c
Normal file
1551
ref_gu/gu_alias.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user