Compare commits

..

88 Commits

Author SHA1 Message Date
Alibek Omarov
8044646a2b First merge attempt (many PSP tunings are missing, as they are outdated now) 2024-01-18 06:51:13 +03:00
Crow-bar
cae351f7b1 engine: psp math optimization, QuaternionSlerp, BoundsIntersect, Mod_SetStudioHullPlane 2022-12-20 11:10:04 +03:00
Crow-bar
9812a9104b ref_gu: clipping code update 2022-12-07 17:03:11 +03:00
Crow-bar
d419921ca3 engine: psp filesystem fix 2022-12-06 11:46:31 +03:00
Crow-bar
3ccb156554 platform: using hw psp mp3 decoder for streams 2022-11-21 11:14:22 +03:00
Crow-bar
15ea61ea34 psp: mainui update 2022-11-11 10:10:47 +03:00
Crow-bar
e6a9724d7c platform: psp joystick curve support 2022-11-02 16:40:39 +03:00
Crow-bar
28723b01a9 platform: psp PATH_MAX fix 2022-11-02 16:38:33 +03:00
Crow-bar
0dc1c13b83 engine: psp Adrenaline bug 2022-11-02 16:36:23 +03:00
Crow-bar
1704712650 platform: psp fixed issues with libc 2022-11-02 09:52:42 +03:00
Crow-bar
066d87f546 ref_gu: depth mask returned 2022-10-31 09:34:16 +03:00
Crow-bar
0b500168a7 ref_gu: gl_nosort cvar removed 2022-10-31 09:32:22 +03:00
Crow-bar
e3e5fe8e18 platform: psp filesystem helper strip_path 2022-10-31 09:21:37 +03:00
Crow-bar
da161103b1 ref_gu: correct ONE/ZERO modifier for sceGuBlendFunc 2022-10-20 16:57:48 +03:00
Crow-bar
d6d8ee3e57 ref_gu: updated initial GU settings 2022-10-20 16:54:06 +03:00
Crow-bar
89ee68d5d0 ref_gu: depth bug fixed, sort code removed 2022-10-20 16:50:48 +03:00
Crow-bar
f5ca0175a5 engine: DSP optimization 2022-10-20 16:45:05 +03:00
Crow-bar
5559f728b7 waf: psp profiling flags for c++ 2022-10-19 10:57:21 +03:00
Crow-bar
238687affa Merge branch 'psp-tgapal' into psp 2022-10-18 09:51:35 +03:00
Crow-bar
5832d017c7 Merge branch 'psp-triapi' into psp 2022-10-18 09:51:22 +03:00
Crow-bar
4e78898c6f Merge branch 'psp-cachedfs' into psp 2022-10-18 09:51:06 +03:00
Crow-bar
c6520b83b2 server: sv_save.c: checking P5Ram_Alloc results; memory leak fix 2022-10-18 09:31:03 +03:00
Crow-bar
a440d1ff7a paltform: psp filesystem helper update 2022-10-18 09:19:57 +03:00
Crow-bar
3889ed8c52 engine: using sceIoRemove() instead of remove() for psp 2022-10-14 15:37:24 +03:00
Crow-bar
53d44f4c0e paltform: psp filesystem helper 2022-10-13 14:40:02 +03:00
Crow-bar
bdc2009683 server: minor fix for inline functions 2022-10-12 11:04:35 +03:00
Crow-bar
a375adb9ea ref_gu: skybox_ext reordering 2022-10-10 16:54:11 +03:00
Crow-bar
122a11005b imagelib: hardware palette support for tga 2022-10-10 16:49:01 +03:00
Crow-bar
f70938d2b0 ref_gl: ref_soft: ref_gu: engine: TriAPI update 2022-10-10 16:44:48 +03:00
Crow-bar
40dca1ea1f ref_gu: vsync fix 2022-10-06 16:58:33 +03:00
Crow-bar
f8452b8490 ref_gu: R_TextureList_f total size fix 2022-10-06 16:45:15 +03:00
Crow-bar
3b50fded8b ref_gu: menu freeze fix 2022-10-06 15:25:07 +03:00
Crow-bar
5ad4f43a7e waf: self.onlypsp fixed 2022-10-05 10:42:11 +03:00
Crow-bar
ef117ffbb3 readme: psp profiling 2022-10-05 10:36:39 +03:00
Crow-bar
8850d2ae52 waf: updated build rules for psp 2022-10-05 10:26:13 +03:00
Crow-bar
e66400ca39 engine: net_encode.c, net_buffer.c inline functions optimization 2022-10-04 10:31:33 +03:00
Crow-bar
01affdcbbd psp: lower sound thread priority 2022-10-04 10:27:31 +03:00
Crow-bar
ed2ba1f226 psp: additional buttons, when pressed HOME 2022-10-04 10:27:01 +03:00
Crow-bar
1abec2620a psp: fixed bug in asm code, returned vsqrt+vrcp in TransformPositivePlane and TransformStandartPlane 2022-10-04 09:00:49 +03:00
Crow-bar
f4ae5cf8e0 platform: using sceKernelGetSystemTimeWide instead of sceRtcGetCurrentTick 2022-10-03 08:19:49 +03:00
Crow-bar
57ddff5457 engine: R_BreakModel limit reduction for psp 2022-10-02 21:36:41 +03:00
Crow-bar
d98330adca psp: asm code optimization 2022-10-02 12:38:12 +03:00
Crow-bar
21ed285da7 engine: psp filetime fix 2022-09-21 17:01:14 +03:00
Crow-bar
b517019750 platform: p5 allocator fix; ref_gu: using vram for palettes 2022-09-21 15:31:26 +03:00
Crow-bar
b567531cdb platform: PSP volatile(P5) memory allocator 2022-09-21 08:58:02 +03:00
Crow-bar
9c61941e52 ref_gu: code cleanup, fix spaces and tabs, asm Matrix_FromOriginQuat 2022-09-09 10:18:29 +03:00
Crow-bar
3afc7134ab ref_gu: efx optimization 2022-09-05 11:58:33 +03:00
Crow-bar
bcf838c42f engine: .bss size reduction for PSP 2022-08-30 16:47:03 +03:00
Crow-bar
91d6fdd190 psp: using the maximum amount of VRAM 2022-08-10 16:58:20 +03:00
Crow-bar
b8ff41eac9 psp: removed dll_psp.h 2022-08-10 16:49:49 +03:00
Alibek Omarov
0277700977 gitignore: fix waf ignores 2022-08-10 16:44:09 +03:00
Crow-bar
da68591f03 ref_gu: .bss size reduction 2022-06-16 14:14:55 +03:00
Crow-bar
da695b75c4 engine: using MSGBOX in developer mode (Sys_Error) 2022-06-16 14:08:01 +03:00
Crow-bar
1b4bc7f5ec platform: module loader refactoring 2022-06-16 09:59:01 +03:00
Crow-bar
cbfb43f05b engine: NORETURN macro disabled for PSP 2022-06-10 13:32:03 +03:00
Crow-bar
db9e82cdec engine: CL_IsPlayerIndex macro 2022-06-10 11:19:16 +03:00
Crow-bar
12889494e0 ref_gu: reducing the number of calls to CL_GetEntityLight and CL_GetDynamicLight 2022-06-10 10:49:07 +03:00
Crow-bar
f2d59eb7f8 ref_gu: studio model optimization 2022-06-09 11:13:29 +03:00
Crow-bar
3a3b8e2c4a ref_gu: triapi update 2022-06-08 16:15:38 +03:00
Crow-bar
1e132bf29e ref_gu: added rgb 332 format; changeable output format in R_BuildLightMap 2022-06-01 16:16:51 +03:00
Crow-bar
d35330cd55 psp: enabled console background image 2022-06-01 14:55:43 +03:00
Crow-bar
c07c1357e5 platform: buttons layout update 2022-05-27 15:11:38 +03:00
Crow-bar
8071355d68 ref_soft: framebuffer width fix 2022-05-27 15:00:30 +03:00
Crow-bar
6073e35bfc vid_psp.c: CRLF -> LF 2022-05-27 14:58:47 +03:00
Crow-bar
8e8a0e4908 ref_gu: optimized sprites and particles 2022-05-26 15:53:31 +03:00
Crow-bar
1d7176751c ref_gu: pixel converter update 2022-05-25 16:56:53 +03:00
Crow-bar
07e29771a1 ref_gu: refactoring 2022-05-24 08:35:13 +03:00
Crow-bar
89ec7122fe ref_gu: cleanup, added texture wrap mode in GL_Bind 2022-05-17 11:50:04 +03:00
Crow-bar
fe8fea742d filesystem: added XASH_NO_ZIP define, 64 byte alignment for file buffer 2022-05-13 09:59:00 +03:00
Crow-bar
2ab8bce924 ref_gu: texture min size fixed 2022-05-05 21:54:18 +03:00
Crow-bar
90faeb231f optimization: aligned memory access, vfpu math 2022-05-05 21:50:14 +03:00
Crow-bar
2885d44593 platform: 60 fps cap fix 2022-05-04 10:49:07 +03:00
Crow-bar
4dfdbdd6aa ref_gu: unnecessary operations 2022-04-25 16:44:01 +03:00
Crow-bar
5eb19c1478 ref_gu: viewport bug fixed 2022-04-24 23:34:39 +03:00
Crow-bar
13a9c41b0c added .vscode/ to .gitignore 2022-04-16 18:38:11 +03:00
Crow-bar
2eef2cec49 sound: psp sound output rewritten 2022-04-16 12:39:02 +03:00
Crow-bar
7be87a913d filesystem: small changes 2022-04-14 14:54:52 +03:00
Crow-bar
dc22f5cbaf vox: MAX_SENTENCES changed to 2048 2022-04-14 10:17:28 +03:00
Crow-bar
5c244b4140 filesystem: Stream_OpenWAV hold mode fix 2022-04-11 14:53:01 +03:00
Crow-bar
e7e10ac8b9 filesystem: hold mode fix 2022-04-10 21:34:43 +03:00
Crow-bar
a308ce2f48 ref_gu: texture loader update 2022-04-09 17:34:42 +03:00
Crow-bar
eea17a4e32 Matrix_CreateFromEntity ASM BUG 2022-04-09 17:28:09 +03:00
Crow-bar
cab187618d FCVAR_GLCONFIG permission update 2022-04-09 17:26:42 +03:00
Crow-bar
32e175311b mainui update 2022-04-07 11:24:55 +03:00
Crow-bar
190279c117 system user name 2022-04-05 22:35:13 +03:00
Crow-bar
f5aaa58ff9 readme: update 2022-04-03 18:10:58 +03:00
Crow-bar
cd37d866c2 code cleanup 2022-04-03 18:00:12 +03:00
Sergey Galushko
64020b2902 PSP Port initial 2022-03-30 21:36:08 +03:00
134 changed files with 32368 additions and 588 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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" />
[![builds.sr.ht status](https://builds.sr.ht/~a1batross/xash3d-fwgs.svg)](https://builds.sr.ht/~a1batross/xash3d-fwgs?) [![GitHub Actions Status](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [![FreeBSD Build Status](https://img.shields.io/cirrus/github/FWGS/xash3d-fwgs?label=freebsd%20build)](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [![Discord Server](https://img.shields.io/discord/355697768582610945.svg)](http://fwgsdiscord.mentality.rip/) \
[![GitHub Actions Status](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml/badge.svg)](https://github.com/FWGS/xash3d-fwgs/actions/workflows/c-cpp.yml) [![FreeBSD Build Status](https://img.shields.io/cirrus/github/FWGS/xash3d-fwgs?label=freebsd%20build)](https://cirrus-ci.com/github/FWGS/xash3d-fwgs) [![Discord Server](https://img.shields.io/discord/355697768582610945.svg)](http://fwgsdiscord.mentality.rip/) \
[![Download Stable](https://img.shields.io/badge/download-stable-yellow)](https://github.com/FWGS/xash3d-fwgs/releases/latest) [![Download Testing](https://img.shields.io/badge/downloads-testing-orange)](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.

View File

@@ -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 */

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 );
}
/*
=========================================================================

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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 ));

View File

@@ -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 );
}
}

View File

@@ -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 );
}
/*

View File

@@ -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++ )
{

View File

@@ -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;

View File

@@ -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 );

View File

@@ -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

View File

@@ -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 );
}

View File

@@ -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 */

View File

@@ -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

View File

@@ -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 )
{

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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];

View File

@@ -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;
}

View File

@@ -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
View 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
}

View File

@@ -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 );

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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 )

View File

@@ -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;

View File

@@ -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
/*
=============================================================================

View File

@@ -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

View File

@@ -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

View File

@@ -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
}
/*

View File

@@ -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 );

View File

@@ -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 );

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 ));

View File

@@ -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

View File

@@ -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

View File

@@ -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
};

View File

@@ -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
}
/*

View File

@@ -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 );

View File

@@ -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 );

View 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 );
}

View 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

View 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 */

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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
}

View 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

View File

@@ -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;

View File

@@ -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
//

View File

@@ -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 )
{

View File

@@ -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-- );
}
/*

View File

@@ -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-- );
}
/*

View File

@@ -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

View File

@@ -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

View File

@@ -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([

View File

@@ -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 );

View File

@@ -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

View File

@@ -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

View File

@@ -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
View File

View 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',

View File

@@ -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
/*
====================

View File

@@ -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
View 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

View File

@@ -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 );
}

View File

@@ -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 );
//

View File

@@ -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;
}
/*
=======================================================================

View File

@@ -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;

View File

@@ -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
View File

@@ -0,0 +1 @@
GetRefAPI

View File

@@ -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 );
}

View File

@@ -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];
}

View File

@@ -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;
}
/*
=======================================================================

View File

@@ -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
//

View File

@@ -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;

View File

@@ -492,4 +492,3 @@ void TriBrightness( float brightness )
_TriColor4f( r, g, b, 1.0f );
}

2
ref_gu/exports.txt Normal file
View File

@@ -0,0 +1,2 @@
GetRefAPI
GetRefHumanReadableName

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