Adds PSP2 platform.

This commit is contained in:
Dima353
2026-07-23 02:56:35 +03:00
parent bcab2bf55f
commit dea91bd448
57 changed files with 2010 additions and 71 deletions
+70
View File
@@ -0,0 +1,70 @@
TITLE := "Grand Theft Auto III"
TITLE_ID := GTA3RT000
TARGET := GTA3
SOURCES := src src/animation src/audio src/audio/oal src/audio/eax src/buildings src/control src/collision src/core src/entities src/math src/modelinfo src/objects src/peds src/renderer src/rw src/save src/skel src/skel/glfw src/text src/vehicles src/weapons src/extras src/fakerw
INCLUDES := src src/animation src/audio src/audio/oal src/audio/eax src/buildings src/control src/collision src/core src/entities src/math src/modelinfo src/objects src/peds src/renderer src/rw src/save src/skel src/skel/glfw src/text src/vehicles src/weapons src/extras src/fakerw librw
CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c))
CPPFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.cpp))
BINFILES := $(foreach dir,$(DATA), $(wildcard $(dir)/*.bin))
OBJS := $(addsuffix .o,$(BINFILES)) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o)
INCLUDE := $(foreach dir,$(INCLUDES),-I$(dir))
PREFIX = arm-vita-eabi
CC = $(PREFIX)-gcc
CXX = $(PREFIX)-g++
ARCH := -mtune=cortex-a9 -march=armv7-a -mfpu=neon
CFLAGS := -g -Wl,-q,--no-enum-size-warning -fno-short-enums -fno-optimize-sibling-calls -O2 -ftree-vectorize -mfloat-abi=hard -fno-builtin-memcpy $(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -DPSP2 -DNDEBUG -DMASTER -DLIBRW -DRW_GL3 -DAUDIO_OAL -DLIBRW_GLAD
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
ASFLAGS := -g $(ARCH)
LDFLAGS = -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lrw -lopenal -lSDL2 -lvita2d -lvitaGL -lSceAppMgr_stub -lSceDisplay_stub -lSceCommonDialog_stub -lSceLibKernel_stub \
-lSceSysmodule_stub -lvitashark -lSceShaccCg_stub -lSceShaccCgExt -lvitaGL -lmathneon -lSceGxm_stub -lScePower_stub \
-lSceCtrl_stub -lSceHid_stub -lSceAudio_stub -lSceAudioIn_stub -lSceTouch_stub -lm -lpthread -lmpg123 -lSceMotion_stub \
-lSceSysmodule_stub -lSceAvPlayer_stub -lSceKernelDmacMgr_stub -ltaihen_stub
all: $(TARGET).vpk
%.vpk: eboot.bin
vita-mksfoex -s APP_VER=01.50 -s TITLE_ID=$(TITLE_ID) -d ATTRIBUTE2=12 $(TITLE) param.sfo
vita-pack-vpk -s param.sfo -b eboot.bin \
--add sce_sys/icon0.png=sce_sys/icon0.png \
--add sce_sys/livearea/contents/bg.png=sce_sys/livearea/contents/bg.png \
--add sce_sys/livearea/contents/startup.png=sce_sys/livearea/contents/startup.png \
--add sce_sys/livearea/contents/template.xml=sce_sys/livearea/contents/template.xml \
--add sce_sys/manual/001.png=sce_sys/manual/001.png \
--add sce_sys/manual/002.png=sce_sys/manual/002.png \
--add sce_sys/manual/003.png=sce_sys/manual/003.png \
--add sce_sys/manual/004.png=sce_sys/manual/004.png \
--add sce_sys/manual/005.png=sce_sys/manual/005.png \
--add sce_sys/manual/006.png=sce_sys/manual/006.png \
--add sce_sys/manual/007.png=sce_sys/manual/007.png \
--add sce_sys/manual/008.png=sce_sys/manual/008.png \
--add sce_sys/manual/009.png=sce_sys/manual/009.png \
--add sce_sys/manual/010.png=sce_sys/manual/010.png \
--add sce_sys/manual/011.png=sce_sys/manual/011.png \
--add sce_sys/manual/012.png=sce_sys/manual/012.png \
--add sce_sys/manual/013.png=sce_sys/manual/013.png \
--add sce_sys/manual/014.png=sce_sys/manual/014.png \
--add sce_sys/manual/015.png=sce_sys/manual/015.png \
--add sce_sys/manual/016.png=sce_sys/manual/016.png \
--add sce_sys/manual/017.png=sce_sys/manual/017.png \
--add sce_sys/manual/018.png=sce_sys/manual/018.png \
--add sce_sys/manual/019.png=sce_sys/manual/019.png \
--add sce_sys/manual/020.png=sce_sys/manual/020.png \
$(TARGET).vpk
eboot.bin: $(TARGET).velf
vita-make-fself -c -s $< $@
%.velf: %.elf
vita-elf-create $< $@
$(TARGET).elf: $(OBJS)
$(CXX) $(CXXFLAGS) $^ $(LIBS) -o $@
clean:
@rm -rf $(TARGET).vpk $(TARGET).velf $(TARGET).elf $(OBJS) eboot.bin param.sfo
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<livearea style="psmobile" format-ver="01.00" content-rev="1">
<livearea-background>
<image>bg.png</image>
</livearea-background>
<gate>
<startup-image>startup.png</startup-image>
</gate>
</livearea>
Binary file not shown.

After

Width:  |  Height:  |  Size: 435 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 638 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 621 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 623 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 413 KiB

+2
View File
@@ -51,6 +51,7 @@ using namespace re3_openal;
void EFXInit() void EFXInit()
{ {
#ifndef PSP2
/* Define a macro to help load the function pointers. */ /* Define a macro to help load the function pointers. */
#define LOAD_PROC(T, x) ((x) = (T)alGetProcAddress(#x)) #define LOAD_PROC(T, x) ((x) = (T)alGetProcAddress(#x))
LOAD_PROC(LPALGENEFFECTS, alGenEffects); LOAD_PROC(LPALGENEFFECTS, alGenEffects);
@@ -89,6 +90,7 @@ void EFXInit()
LOAD_PROC(LPALGETAUXILIARYEFFECTSLOTF, alGetAuxiliaryEffectSlotf); LOAD_PROC(LPALGETAUXILIARYEFFECTSLOTF, alGetAuxiliaryEffectSlotf);
LOAD_PROC(LPALGETAUXILIARYEFFECTSLOTFV, alGetAuxiliaryEffectSlotfv); LOAD_PROC(LPALGETAUXILIARYEFFECTSLOTFV, alGetAuxiliaryEffectSlotfv);
#undef LOAD_PROC #undef LOAD_PROC
#endif
} }
void SetEffectsLevel(ALuint uiFilter, float level) void SetEffectsLevel(ALuint uiFilter, float level)
+15 -5
View File
@@ -18,7 +18,7 @@
#include <direct.h> #include <direct.h>
#include <shlobj.h> #include <shlobj.h>
#include <shlguid.h> #include <shlguid.h>
#else #elif !defined(PSP2)
#define _getcwd getcwd #define _getcwd getcwd
#endif #endif
@@ -255,7 +255,8 @@ set_new_provider(int index)
usingEAX3 = 0; usingEAX3 = 0;
_usingEFX = false; _usingEFX = false;
if ( !strcmp(&providers[index].name[strlen(providers[index].name) - strlen(" EAX3")], " EAX3") #if !defined(PSP2)
if ( !strcmp(&providers[index].name[strlen(providers[index].name) - strlen(" EAX3")], " EAX3")
&& alcIsExtensionPresent(ALDevice, (ALCchar*)ALC_EXT_EFX_NAME) ) && alcIsExtensionPresent(ALDevice, (ALCchar*)ALC_EXT_EFX_NAME) )
{ {
@@ -282,7 +283,8 @@ set_new_provider(int index)
alAuxiliaryEffectSloti(ALEffectSlot, AL_EFFECTSLOT_EFFECT, ALEffect); alAuxiliaryEffectSloti(ALEffectSlot, AL_EFFECTSLOT_EFFECT, ALEffect);
EAX_SetAll(&EAX30_ORIGINAL_PRESETS[EAX_ENVIRONMENT_CAVE]); EAX_SetAll(&EAX30_ORIGINAL_PRESETS[EAX_ENVIRONMENT_CAVE]);
} }
#endif
//SampleManager.SetSpeakerConfig(speaker_type); //SampleManager.SetSpeakerConfig(speaker_type);
if ( IsFXSupported() ) if ( IsFXSupported() )
@@ -420,7 +422,7 @@ _ResolveLink(char const *path, char *out)
#else #else
struct stat sb; struct stat sb;
if (lstat(path, &sb) == -1) { if (_lstat(path, &sb) == -1) {
perror("lstat: "); perror("lstat: ");
return FALSE; return FALSE;
} }
@@ -457,7 +459,8 @@ _FindMP3s(void)
WIN32_FIND_DATA fd; WIN32_FIND_DATA fd;
char filepath[MAX_PATH + sizeof(fd.cFileName)]; char filepath[MAX_PATH + sizeof(fd.cFileName)];
if (getcwd(_mp3DirectoryPath, MAX_PATH) == NULL) { // _getcwd on PSP2 returns the data directory; elsewhere it is the real one.
if (_getcwd(_mp3DirectoryPath, MAX_PATH) == NULL) {
perror("getcwd: "); perror("getcwd: ");
return; return;
} }
@@ -509,6 +512,8 @@ _FindMP3s(void)
{ {
if (filepathlen > 0) if (filepathlen > 0)
{ {
// No symlinks on this filesystem, and readlink is a stub here.
#ifndef PSP2
if (_ResolveLink(filepath, filepath)) if (_ResolveLink(filepath, filepath))
{ {
OutputDebugString("Resolving Link"); OutputDebugString("Resolving Link");
@@ -516,6 +521,7 @@ _FindMP3s(void)
bShortcut = TRUE; bShortcut = TRUE;
} }
else else
#endif
{ {
bShortcut = FALSE; bShortcut = FALSE;
if (filepathlen > MAX_PATH) { if (filepathlen > MAX_PATH) {
@@ -568,6 +574,7 @@ _FindMP3s(void)
{ {
if ( filepathlen > 0 ) if ( filepathlen > 0 )
{ {
#ifndef PSP2
if ( _ResolveLink(filepath, filepath) ) if ( _ResolveLink(filepath, filepath) )
{ {
OutputDebugString("Resolving Link"); OutputDebugString("Resolving Link");
@@ -575,6 +582,7 @@ _FindMP3s(void)
bShortcut = TRUE; bShortcut = TRUE;
} }
else else
#endif
bShortcut = FALSE; bShortcut = FALSE;
if (aStream[0] && aStream[0]->Open(filepath)) if (aStream[0] && aStream[0]->Open(filepath))
@@ -839,12 +847,14 @@ cSampleManager::Initialise(void)
alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED);
#ifndef PSP2
if ( alcIsExtensionPresent(ALDevice, (ALCchar*)ALC_EXT_EFX_NAME) ) if ( alcIsExtensionPresent(ALDevice, (ALCchar*)ALC_EXT_EFX_NAME) )
{ {
_effectsSupported = providers[index].bSupportsFx; _effectsSupported = providers[index].bSupportsFx;
alGenAuxiliaryEffectSlots(1, &ALEffectSlot); alGenAuxiliaryEffectSlots(1, &ALEffectSlot);
alGenEffects(1, &ALEffect); alGenEffects(1, &ALEffect);
} }
#endif
alGenSources(MAX_STREAMS*2, ALStreamSources[0]); alGenSources(MAX_STREAMS*2, ALStreamSources[0]);
for ( int32 i = 0; i < MAX_STREAMS; i++ ) for ( int32 i = 0; i < MAX_STREAMS; i++ )
+4
View File
@@ -30,7 +30,11 @@ bool PrintDebugCode = false;
int16 DebugCamMode; int16 DebugCamMode;
#ifdef FREE_CAM #ifdef FREE_CAM
#ifdef GTA_HANDHELD
bool CCamera::bFreeCam = true; // handhelds default the free camera on
#else
bool CCamera::bFreeCam = false; bool CCamera::bFreeCam = false;
#endif
int nPreviousMode = -1; int nPreviousMode = -1;
#endif #endif
+17 -2
View File
@@ -7,7 +7,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
#ifndef PSP2
#include <sys/statvfs.h> #include <sys/statvfs.h>
#endif
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
@@ -26,6 +28,12 @@
#define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__) #define CDDEBUG(f, ...) debug ("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
#define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__) #define CDTRACE(f, ...) printf("%s: " f "\n", "cdvd_stream", ## __VA_ARGS__)
#ifdef PSP2
// Named semaphores do not exist here, and newlib does not declare SEM_FAILED.
#define USE_UNNAMED_SEM
#define SEM_FAILED ((sem_t *) 0)
#endif
#ifdef FLUSHABLE_STREAMING #ifdef FLUSHABLE_STREAMING
bool flushStream[MAX_CDCHANNELS]; bool flushStream[MAX_CDCHANNELS];
#endif #endif
@@ -198,6 +206,7 @@ CdStreamInitThread(void)
void void
CdStreamInit(int32 numChannels) CdStreamInit(int32 numChannels)
{ {
#ifndef PSP2
struct statvfs fsInfo; struct statvfs fsInfo;
if((statvfs("models/gta3.img", &fsInfo)) < 0) if((statvfs("models/gta3.img", &fsInfo)) < 0)
@@ -206,6 +215,7 @@ CdStreamInit(int32 numChannels)
ASSERT(0); ASSERT(0);
return; return;
} }
#endif
#ifdef __linux__ #ifdef __linux__
_gdwCdStreamFlags = O_RDONLY | O_NOATIME; _gdwCdStreamFlags = O_RDONLY | O_NOATIME;
#else #else
@@ -219,7 +229,11 @@ CdStreamInit(int32 numChannels)
debug("Using no buffered loading for streaming\n"); debug("Using no buffered loading for streaming\n");
} }
*/ */
#ifndef PSP2
void *pBuffer = (void *)RwMallocAlign(CDSTREAM_SECTOR_SIZE, (RwUInt32)fsInfo.f_bsize); void *pBuffer = (void *)RwMallocAlign(CDSTREAM_SECTOR_SIZE, (RwUInt32)fsInfo.f_bsize);
#else
void *pBuffer = (void *)RwMallocAlign(CDSTREAM_SECTOR_SIZE, CDSTREAM_SECTOR_SIZE);
#endif
ASSERT( pBuffer != nil ); ASSERT( pBuffer != nil );
gNumImages = 0; gNumImages = 0;
@@ -245,13 +259,14 @@ GetGTA3ImgSize(void)
struct stat statbuf; struct stat statbuf;
char path[PATH_MAX]; char path[PATH_MAX];
realpath(gImgNames[0], path); // _realpath is the Vita shim, plain realpath everywhere else - see crossplatform.h
_realpath(gImgNames[0], path);
if (stat(path, &statbuf) == -1) { if (stat(path, &statbuf) == -1) {
// Try case-insensitivity // Try case-insensitivity
char* real = casepath(gImgNames[0], false); char* real = casepath(gImgNames[0], false);
if (real) if (real)
{ {
realpath(real, path); _realpath(real, path);
free(real); free(real);
if (stat(path, &statbuf) != -1) if (stat(path, &statbuf) != -1)
goto ok; goto ok;
+3 -1
View File
@@ -32,14 +32,16 @@ static myFILE myfiles[NUMFILES];
#include <dirent.h> #include <dirent.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#if !defined(PSP2)
#define _getcwd getcwd #define _getcwd getcwd
#endif
// Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen) // Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen)
void mychdir(char const *path) void mychdir(char const *path)
{ {
char* r = casepath(path, false); char* r = casepath(path, false);
if (r) { if (r) {
chdir(r); _chdir(r);
free(r); free(r);
} else { } else {
errno = ENOENT; errno = ENOENT;
+355 -15
View File
@@ -35,6 +35,10 @@
#include "FileLoader.h" #include "FileLoader.h"
#include "frontendoption.h" #include "frontendoption.h"
#ifdef PSP2
extern bool useRearpad; // touch input: front panel or rear, see crossplatform.cpp
#endif
// Game has colors inlined in code. // Game has colors inlined in code.
// For easier modification we collect them here: // For easier modification we collect them here:
const CRGBA LABEL_COLOR(235, 170, 50, 255); const CRGBA LABEL_COLOR(235, 170, 50, 255);
@@ -145,11 +149,7 @@ int8 CMenuManager::m_PrefsIslandLoading = ISLAND_LOADING_LOW;
#endif #endif
#ifdef GAMEPAD_MENU #ifdef GAMEPAD_MENU
#ifdef __SWITCH__ int8 CMenuManager::m_PrefsControllerType = DEFAULT_CONTROLLER_TYPE;
int8 CMenuManager::m_PrefsControllerType = CONTROLLER_NINTENDO_SWITCH;
#else
int8 CMenuManager::m_PrefsControllerType = CONTROLLER_XBOXONE;
#endif
#endif #endif
int32 CMenuManager::OS_Language = LANG_ENGLISH; int32 CMenuManager::OS_Language = LANG_ENGLISH;
@@ -160,7 +160,11 @@ int8 CMenuManager::m_PrefsVsyncDisp = 1;
int8 CMenuManager::m_PrefsFrameLimiter = 1; int8 CMenuManager::m_PrefsFrameLimiter = 1;
int8 CMenuManager::m_PrefsShowSubtitles = 1; int8 CMenuManager::m_PrefsShowSubtitles = 1;
int8 CMenuManager::m_PrefsSpeakers; int8 CMenuManager::m_PrefsSpeakers;
#ifdef GTA_HANDHELD
int32 CMenuManager::m_ControlMethod = CONTROL_CLASSIC; // handhelds default to classic controls
#else
int32 CMenuManager::m_ControlMethod; int32 CMenuManager::m_ControlMethod;
#endif
int8 CMenuManager::m_PrefsDMA = 1; int8 CMenuManager::m_PrefsDMA = 1;
int32 CMenuManager::m_PrefsLanguage; int32 CMenuManager::m_PrefsLanguage;
uint8 CMenuManager::m_PrefsStereoMono; // unused except restore settings uint8 CMenuManager::m_PrefsStereoMono; // unused except restore settings
@@ -1656,6 +1660,13 @@ CMenuManager::Draw()
#endif #endif
} }
#ifdef PSP2
if (!strncmp(aScreens[m_nCurrScreen].m_aEntries[i].m_EntryName, "PSP2", 4)) {
leftText = TheText.Get("PSP2");
rightText = TheText.Get(useRearpad ? "FEM_ON" : "FEM_OFF");
}
#endif
float nextItemY = headerHeight + nextYToUse; float nextItemY = headerHeight + nextYToUse;
float bitAboveNextItemY = nextItemY - 2.0f; float bitAboveNextItemY = nextItemY - 2.0f;
int nextYToCheck = bitAboveNextItemY; int nextYToCheck = bitAboveNextItemY;
@@ -3685,7 +3696,7 @@ const char* controllerTypesPaths[] = {
nil, nil,
"MODELS/FRONTEND_DS3.TXD", "MODELS/FRONTEND_DS3.TXD",
"MODELS/FRONTEND_DS4.TXD", "MODELS/FRONTEND_DS4.TXD",
#ifndef RT #ifndef RT_CONTROLLERS
"MODELS/FRONTEND_X360.TXD", "MODELS/FRONTEND_X360.TXD",
#endif #endif
"MODELS/FRONTEND_XONE.TXD", "MODELS/FRONTEND_XONE.TXD",
@@ -3695,12 +3706,14 @@ const char* controllerTypesPaths[] = {
void void
CMenuManager::LoadController(int8 type) CMenuManager::LoadController(int8 type)
{ {
// A controller type saved by the other build variant can be out of range here: // A controller type saved by another build variant can be out of range here, in two
// the RT and vanilla controller enums differ in size (vanilla keeps CONTROLLER_XBOX360), // ways: the RT and vanilla enums differ in size (vanilla keeps CONTROLLER_XBOX360),
// so e.g. Nintendo Switch is index 5 in vanilla but 4 under RT. An out-of-range value // so e.g. Nintendo Switch is index 5 in vanilla but 4 under RT; and the handhelds
// would index controllerTypesPaths/controllerTypes out of bounds -> crash. Clamp it. // offer fewer types than the .ini may hold. Out of range means controllerTypes read
if (type < 0 || type >= (int8)ARRAY_SIZE(controllerTypesPaths)) { // out of bounds, a pad the menu can no longer select away from, and with it the wrong
type = CONTROLLER_NINTENDO_SWITCH; // button labels and the wrong menu confirm/cancel layout. Clamp it.
if (type < 0 || type >= (int8)NUM_MENU_CONTROLLER_TYPES) {
type = DEFAULT_CONTROLLER_TYPE;
m_PrefsControllerType = type; m_PrefsControllerType = type;
} }
@@ -3708,12 +3721,12 @@ CMenuManager::LoadController(int8 type)
{ {
case CONTROLLER_DUALSHOCK3: case CONTROLLER_DUALSHOCK3:
case CONTROLLER_DUALSHOCK4: case CONTROLLER_DUALSHOCK4:
#ifndef RT #ifndef RT_CONTROLLERS
case CONTROLLER_DUALSHOCK2: // real DualShock2 uses PlayStation buttons case CONTROLLER_DUALSHOCK2: // real DualShock2 uses PlayStation buttons
#endif #endif
CFont::LoadButtons("MODELS/PS3BTNS.TXD"); CFont::LoadButtons("MODELS/PS3BTNS.TXD");
break; break;
#ifdef RT #ifdef RT_CONTROLLERS
case CONTROLLER_DUALSHOCK2: // RT: the DS2 slot is a Switch Pro Controller case CONTROLLER_DUALSHOCK2: // RT: the DS2 slot is a Switch Pro Controller
#endif #endif
case CONTROLLER_NINTENDO_SWITCH: case CONTROLLER_NINTENDO_SWITCH:
@@ -5861,7 +5874,334 @@ CMenuManager::WaitForUserCD()
void void
CMenuManager::PrintController(void) CMenuManager::PrintController(void)
{ {
#ifdef RT #ifdef PSP2
// PSV: the Vita port draws labels against its own pad artwork with its own
// per-type nudges and justification, so it gets re3-vita's PrintController
// verbatim. The RT_CONTROLLERS (Switch) and vanilla bodies below are untouched.
const float scale = 0.9f;
const float CONTROLLER_SIZE_X = 384.0f;
const float CONTROLLER_SIZE_Y = 384.0f;
const float CONTROLLER_POS_X = (DEFAULT_SCREEN_WIDTH - CONTROLLER_SIZE_X) / 2.0f;
const float CONTROLLER_POS_Y = 140.0f;
float centerX = CONTROLLER_POS_X + CONTROLLER_SIZE_X / 2;
float centerY = CONTROLLER_POS_Y + CONTROLLER_SIZE_Y / 2;
#define X(f) ((f)*scale + centerX)
#define Y(f) ((f)*scale + centerY)
m_aFrontEndSprites[FE_CONTROLLERSH].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X((CONTROLLER_SIZE_X + 4.8f) * scale), MENU_Y((CONTROLLER_SIZE_Y + 4.8f) * scale), CRGBA(0, 0, 0, 255));
m_aFrontEndSprites[FE_CONTROLLER].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, 255));
if (m_DisplayControllerOnFoot) {
if (CTimer::GetTimeInMillisecondsPauseMode() & 0x400)
m_aFrontEndSprites[FE_ARROWS1].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, 255));
else
m_aFrontEndSprites[FE_ARROWS3].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, 255));
} else {
if (CTimer::GetTimeInMillisecondsPauseMode() & 0x400)
m_aFrontEndSprites[FE_ARROWS2].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, 255));
else
m_aFrontEndSprites[FE_ARROWS4].Draw(MENU_X_LEFT_ALIGNED(X(-CONTROLLER_SIZE_X / 2)), MENU_Y(Y(-CONTROLLER_SIZE_Y / 2)), MENU_X(CONTROLLER_SIZE_X * scale), MENU_Y(CONTROLLER_SIZE_Y * scale), CRGBA(255, 255, 255, 255));
}
CFont::SetFontStyle(FONT_LOCALE(FONT_BANK));
CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE * scale), MENU_Y(SMALLESTTEXT_Y_SCALE * scale)); // X
// CFont::SetColor(CRGBA(128, 128, 128, FadeIn(255)));
CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255)));
CFont::SetDropShadowPosition(1);
CFont::SetColor(CRGBA(255, 255, 255, FadeIn(255)));
CFont::SetWrapx(SCREEN_WIDTH);
float TEXT_L2_X = 106.0f + CONTROLLER_POS_X - centerX, TEXT_L2_Y = -7.0f + CONTROLLER_POS_Y - centerY;
float TEXT_L1_X = 2.0f + CONTROLLER_POS_X - centerX, TEXT_L1_Y = 25.0f + CONTROLLER_POS_Y - centerY, TEXT_L1_Y_VEH = 3.0f + TEXT_L1_Y;
float TEXT_DPAD_X = 2.0f + CONTROLLER_POS_X - centerX, TEXT_DPAD_Y = 65.0f + CONTROLLER_POS_Y - centerY;
float TEXT_LSTICK_X = 2.0f + CONTROLLER_POS_X - centerX, TEXT_LSTICK_Y = 101.0f + CONTROLLER_POS_Y - centerY;
float TEXT_SELECT_X = 382.0f + CONTROLLER_POS_X - centerX, TEXT_SELECT_Y = 141.0f + CONTROLLER_POS_Y - centerY;
float TEXT_START_X = 382.0f + CONTROLLER_POS_X - centerX, TEXT_START_Y = 124.0f + CONTROLLER_POS_Y - centerY;
float TEXT_R2_X = 274.0F + CONTROLLER_POS_X - centerX, TEXT_R2_Y = -7.0f + CONTROLLER_POS_Y - centerY;
float TEXT_R1_X = 382.0f + CONTROLLER_POS_X - centerX, TEXT_R1_Y = 25.0f + CONTROLLER_POS_Y - centerY;
float TEXT_SQUARE_X = 382.0f + CONTROLLER_POS_X - centerX, TEXT_SQUARE_Y = 39.0f + CONTROLLER_POS_Y - centerY;
float TEXT_TRIANGLE_X = 382.0f + CONTROLLER_POS_X - centerX, TEXT_TRIANGLE_Y = 52.0f + CONTROLLER_POS_Y - centerY;
float TEXT_CIRCLE_X = 382.0f + CONTROLLER_POS_X - centerX, TEXT_CIRCLE_Y = 65.0f + CONTROLLER_POS_Y - centerY;
float TEXT_CROSS_X = 382.0f + CONTROLLER_POS_X - centerX, TEXT_CROSS_Y = 78.0f + CONTROLLER_POS_Y - centerY;
float TEXT_RSTICK_X = 382.0f + CONTROLLER_POS_X - centerX, TEXT_RSTICK_Y = 102.0f + CONTROLLER_POS_Y - centerY;
float TEXT_R3_X = 382.0f + CONTROLLER_POS_X - centerX, TEXT_R3_Y = 158.0f + CONTROLLER_POS_Y - centerY;
float TEXT_L3_X = 2.0f + CONTROLLER_POS_X - centerX, TEXT_L3_Y = 158.0f + CONTROLLER_POS_Y - centerY;
float TEXT_L2R2_X = 192.0f + CONTROLLER_POS_X - centerX, TEXT_L2R2_Y = 6.0f + CONTROLLER_POS_Y - centerY;
switch (m_PrefsControllerType)
{
case CONTROLLER_DUALSHOCK4:
TEXT_L1_Y -= 2.0f;
TEXT_R1_Y -= 2.0f;
TEXT_L1_Y_VEH = TEXT_L1_Y;
TEXT_TRIANGLE_Y += 0.0f;
TEXT_CIRCLE_Y += 4.0f;
TEXT_CROSS_Y += 7.0f;
TEXT_SQUARE_Y -= 3.0f;
TEXT_RSTICK_Y += 3.0f;
TEXT_R3_Y -= 30.0f;
TEXT_DPAD_Y -= 3.0f;
TEXT_LSTICK_Y += 3.0f;
TEXT_L3_Y -= 30.0f;
TEXT_SELECT_X -= 240.0f;
TEXT_SELECT_Y += 13.0f;
TEXT_START_X -= 198.0f;
TEXT_START_Y += 12.0f;
break;
case CONTROLLER_DUALSHOCK3:
TEXT_L1_Y += 4.0f;
TEXT_L1_Y_VEH = TEXT_L1_Y;
TEXT_TRIANGLE_Y += 5.0f;
TEXT_CIRCLE_Y += 9.0f;
TEXT_CROSS_Y += 15.0f;
TEXT_RSTICK_Y += 17.0f;
TEXT_R3_Y -= 17.0f;
TEXT_DPAD_Y += 11.0f;
TEXT_LSTICK_Y += 17.0f;
TEXT_L3_Y -= 17.0f;
TEXT_SELECT_X -= 238.0f;
TEXT_SELECT_Y -= 112.0f;
TEXT_START_X -= 214.0f;
TEXT_START_Y += 28.0f;
break;
case CONTROLLER_XBOXONE:
TEXT_L2_X -= 2.0f;
TEXT_R2_X += 2.0f;
TEXT_L1_Y += 15.0f;
TEXT_L1_Y_VEH = TEXT_L1_Y;
TEXT_R1_Y += 15.0f;
TEXT_TRIANGLE_Y += 4.0f;
TEXT_CIRCLE_Y += 4.0f;
TEXT_CROSS_Y += 4.0f;
TEXT_RSTICK_Y += 1.0f;
TEXT_R3_Y += 1.0f;
TEXT_DPAD_Y += 29.0f;
TEXT_LSTICK_Y -= 22.0f;
TEXT_L3_X -= 36.0f;
TEXT_L2R2_Y += 5.0f;
TEXT_SELECT_X += 4.0f;
break;
case CONTROLLER_XBOX360:
TEXT_L2_X += 8.0f;
TEXT_R2_X -= 8.0f;
TEXT_L1_Y += 15.0f;
TEXT_L1_Y_VEH = TEXT_L1_Y;
TEXT_R1_Y += 15.0f;
TEXT_TRIANGLE_Y += 4.0f;
TEXT_CIRCLE_Y += 4.0f;
TEXT_CROSS_Y += 4.0f;
TEXT_RSTICK_Y += 4.0f;
TEXT_R3_Y += 4.0f;
TEXT_DPAD_Y += 30.0f;
TEXT_LSTICK_Y -= 21.0f;
TEXT_L3_X -= 36.0f;
TEXT_L2R2_Y += 5.0f;
TEXT_SELECT_X += 3.0f;
break;
case CONTROLLER_NINTENDO_SWITCH:
TEXT_L1_Y += 5.0f;
TEXT_L1_Y_VEH = TEXT_L1_Y;
TEXT_R1_Y += 5.0f;
TEXT_TRIANGLE_Y += 3.0f;
TEXT_CIRCLE_Y += 3.0f;
TEXT_CROSS_Y += 3.0f;
TEXT_LSTICK_Y -= 23.0f;
TEXT_DPAD_Y += 25.0;
TEXT_RSTICK_Y += 1.0f;
TEXT_R3_Y += 1.0f;
break;
};
if (m_DisplayControllerOnFoot) {
switch (CPad::GetPad(0)->Mode) {
case 0:
CFont::SetCentreOn();
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR"));
CFont::SetRightJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_LOF"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_MOV"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_TAR"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_ENV"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_ATT"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_RUN"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3"));
break;
case 1:
CFont::SetCentreOn();
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR"));
CFont::SetRightJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_LOF"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_CAM"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_NA"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_TAR"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_ENV"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_ATT"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_RUN"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3"));
break;
case 2:
CFont::SetCentreOn();
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR"));
CFont::SetRightJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_ENV"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_MOV"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_TAR"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_LOF"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_RUN"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ATT"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3"));
break;
case 3:
CFont::SetCentreOn();
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_CWL"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_CWR"));
CFont::SetRightJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y)), TheText.Get("FEC_TAR"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_NA"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_MOV"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_ATT"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_JUM"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_ENV"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_LOF"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_RUN"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_FPC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_LB3"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y + 13.0f)), TheText.Get("FEC_R3"));
break;
default:
return;
}
} else {
CFont::SetCentreOn();
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2R2_X)), MENU_Y(Y(TEXT_L2R2_Y)), TheText.Get("FEC_LB"));
switch (CPad::GetPad(0)->Mode) {
case 0:
CFont::SetCentreOn();
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR"));
CFont::SetRightJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_RSC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_VES"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_HO3"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_HAB"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_BRA"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_EXV"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_CAW"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ACC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_TUC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_SM3"));
break;
case 1:
CFont::SetCentreOn();
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR"));
CFont::SetRightJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_HOR"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_CAM"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_NA"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_RSC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_HAB"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_BRA"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_EXV"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_CAW"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ACC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_TUC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_SM3"));
break;
case 2:
CFont::SetCentreOn();
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR"));
CFont::SetRightJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_EXV"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_VES"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_RS3"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_HOR"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_BRA"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_HAB"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_CAW"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_ACC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_TUC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_SM3"));
break;
case 3:
CFont::SetCentreOn();
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L2_X)), MENU_Y(Y(TEXT_L2_Y)), TheText.Get("FEC_LL"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R2_X)), MENU_Y(Y(TEXT_R2_Y)), TheText.Get("FEC_LR"));
CFont::SetRightJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L1_X)), MENU_Y(Y(TEXT_L1_Y_VEH)), TheText.Get("FEC_HAB"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_DPAD_X)), MENU_Y(Y(TEXT_DPAD_Y)), TheText.Get("FEC_TUC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_LSTICK_X)), MENU_Y(Y(TEXT_LSTICK_Y)), TheText.Get("FEC_VES"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_L3_X)), MENU_Y(Y(TEXT_L3_Y)), TheText.Get("FEC_HO3"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SELECT_X)), MENU_Y(Y(TEXT_SELECT_Y)), TheText.Get("FEC_CAM"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_START_X)), MENU_Y(Y(TEXT_START_Y)), TheText.Get("FEC_PAU"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R1_X)), MENU_Y(Y(TEXT_R1_Y)), TheText.Get("FEC_CAW"));
CFont::SetJustifyOn(); // X
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_SQUARE_X)), MENU_Y(Y(TEXT_SQUARE_Y)), TheText.Get("FEC_SMT"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_TRIANGLE_X)), MENU_Y(Y(TEXT_TRIANGLE_Y)), TheText.Get("FEC_EXV"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CIRCLE_X)), MENU_Y(Y(TEXT_CIRCLE_Y)), TheText.Get("FEC_RSC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_CROSS_X)), MENU_Y(Y(TEXT_CROSS_Y)), TheText.Get("FEC_NA"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_RSTICK_X)), MENU_Y(Y(TEXT_RSTICK_Y)), TheText.Get("FEC_ACC"));
CFont::PrintString(MENU_X_LEFT_ALIGNED(X(TEXT_R3_X)), MENU_Y(Y(TEXT_R3_Y)), TheText.Get("FEC_BRA"));
break;
default:
return;
}
}
CFont::SetDropShadowPosition(0); // X
#undef X
#undef Y
#elif defined RT_CONTROLLERS
const float scale = 0.9f; const float scale = 0.9f;
const float CONTROLLER_SIZE_X = 384.0f; const float CONTROLLER_SIZE_X = 384.0f;
const float CONTROLLER_SIZE_Y = 384.0f; const float CONTROLLER_SIZE_Y = 384.0f;
+13 -1
View File
@@ -758,13 +758,25 @@ public:
CONTROLLER_DUALSHOCK2 = 0, CONTROLLER_DUALSHOCK2 = 0,
CONTROLLER_DUALSHOCK3, CONTROLLER_DUALSHOCK3,
CONTROLLER_DUALSHOCK4, CONTROLLER_DUALSHOCK4,
#ifndef RT #ifndef RT_CONTROLLERS
CONTROLLER_XBOX360, CONTROLLER_XBOX360,
#endif #endif
CONTROLLER_XBOXONE, CONTROLLER_XBOXONE,
CONTROLLER_NINTENDO_SWITCH, CONTROLLER_NINTENDO_SWITCH,
NUM_CONTROLLER_TYPES,
}; };
#ifdef PSP2
#define NUM_MENU_CONTROLLER_TYPES (CMenuManager::CONTROLLER_DUALSHOCK4 + 1) // the Vita itself, plus the DS3/DS4 a PSTV can pair with
#define DEFAULT_CONTROLLER_TYPE CMenuManager::CONTROLLER_DUALSHOCK2
#elif defined __SWITCH__
#define NUM_MENU_CONTROLLER_TYPES CMenuManager::NUM_CONTROLLER_TYPES
#define DEFAULT_CONTROLLER_TYPE CMenuManager::CONTROLLER_NINTENDO_SWITCH
#else
#define NUM_MENU_CONTROLLER_TYPES CMenuManager::NUM_CONTROLLER_TYPES
#define DEFAULT_CONTROLLER_TYPE CMenuManager::CONTROLLER_XBOXONE
#endif
static int8 m_PrefsControllerType; static int8 m_PrefsControllerType;
#endif #endif
+9
View File
@@ -244,6 +244,14 @@ CGame::InitialiseRenderWare(void)
#endif #endif
#ifdef LIBRW #ifdef LIBRW
// librw-vita predates the envMap* knobs and only exposes modulateEnvMap.
#ifdef PSP2
#ifdef PS2_MATFX
rw::MatFX::modulateEnvMap = true;
#else
rw::MatFX::modulateEnvMap = false;
#endif
#else
#ifdef PS2_MATFX #ifdef PS2_MATFX
rw::MatFX::envMapApplyLight = true; rw::MatFX::envMapApplyLight = true;
rw::MatFX::envMapUseMatColor = true; rw::MatFX::envMapUseMatColor = true;
@@ -255,6 +263,7 @@ CGame::InitialiseRenderWare(void)
#endif #endif
rw::RGBA envcol = { 128, 128, 128, 255 }; rw::RGBA envcol = { 128, 128, 128, 255 };
rw::MatFX::envMapColor = envcol; rw::MatFX::envMapColor = envcol;
#endif
#else #else
#ifdef PS2_MATFX #ifdef PS2_MATFX
ReplaceMatFxCallback(); ReplaceMatFxCallback();
+22 -5
View File
@@ -32,6 +32,10 @@
// Menu screens array is at the bottom of the file. // Menu screens array is at the bottom of the file.
#ifdef PSP2
extern bool useRearpad; // touch input: front panel or rear, see crossplatform.cpp
#endif
#ifdef PC_MENU #ifdef PC_MENU
#ifdef CUSTOM_FRONTEND_OPTIONS #ifdef CUSTOM_FRONTEND_OPTIONS
@@ -42,7 +46,9 @@
#define VIDEOMODE_SELECTOR #define VIDEOMODE_SELECTOR
#endif #endif
#ifdef MULTISAMPLING // Not on PSP2: vglInitExtended fixes the level at 4x, so the entry could never
// change anything, and stepping through it used to hang the game.
#if defined(MULTISAMPLING) && !defined(PSP2)
#define MULTISAMPLING_SELECTOR MENUACTION_CFO_DYNAMIC, "FED_AAS", { new CCFODynamic((int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, "Graphics", "MultiSampling", MultiSamplingDraw, MultiSamplingButtonPress) }, #define MULTISAMPLING_SELECTOR MENUACTION_CFO_DYNAMIC, "FED_AAS", { new CCFODynamic((int8*)&FrontEndMenuManager.m_nPrefsMSAALevel, "Graphics", "MultiSampling", MultiSamplingDraw, MultiSamplingButtonPress) },
#else #else
#define MULTISAMPLING_SELECTOR #define MULTISAMPLING_SELECTOR
@@ -96,7 +102,7 @@
#endif #endif
#ifdef GAMEPAD_MENU #ifdef GAMEPAD_MENU
#define SELECT_CONTROLLER_TYPE MENUACTION_CFO_SELECT, "FEC_TYP", { new CCFOSelect((int8*)&CMenuManager::m_PrefsControllerType, "Controller", "Type", controllerTypes, ARRAY_SIZE(controllerTypes), false, ControllerTypeAfterChange) }, #define SELECT_CONTROLLER_TYPE MENUACTION_CFO_SELECT, "FEC_TYP", { new CCFOSelect((int8*)&CMenuManager::m_PrefsControllerType, "Controller", "Type", controllerTypes, NUM_MENU_CONTROLLER_TYPES, false, ControllerTypeAfterChange) },
#else #else
#define SELECT_CONTROLLER_TYPE #define SELECT_CONTROLLER_TYPE
#endif #endif
@@ -242,7 +248,9 @@ void MultiSamplingButtonPress(int8 action) {
int i = 0; int i = 0;
int maxAA = RwD3D8EngineGetMaxMultiSamplingLevels(); int maxAA = RwD3D8EngineGetMaxMultiSamplingLevels();
while (maxAA != 1) { // > 1, not != 1: the PSP2 stub reports 0 levels, and 0 >> 1 stays 0,
// so the original condition never terminates and hangs the game.
while (maxAA > 1) {
i++; i++;
maxAA >>= 1; maxAA >>= 1;
} }
@@ -388,8 +396,10 @@ void DetectJoystickGoBack() {
#endif #endif
#ifdef GAMEPAD_MENU #ifdef GAMEPAD_MENU
// Stays parallel to the controller enum in Frontend.h - it is indexed by type, not
// iterated. The menu offers only the first NUM_MENU_CONTROLLER_TYPES of them.
const char* controllerTypes[] = { "FEC_DS2", "FEC_DS3", "FEC_DS4", const char* controllerTypes[] = { "FEC_DS2", "FEC_DS3", "FEC_DS4",
#ifndef RT #ifndef RT_CONTROLLERS
"FEC_360", "FEC_360",
#endif #endif
"FEC_ONE", "FEC_NSW" }; "FEC_ONE", "FEC_NSW" };
@@ -422,10 +432,17 @@ CMenuScreenCustom aScreens[MENUPAGES] = {
}, },
// MENUPAGE_CONTROLLER_SETTINGS = 4 // MENUPAGE_CONTROLLER_SETTINGS = 4
#if defined(GAMEPAD_MENU) && !defined(GTA_HANDHELD) #if defined(GAMEPAD_MENU) && !defined(GTA_HANDHELD) && !defined(PSP2)
{ "FET_AGS", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil, { "FET_AGS", MENUPAGE_CONTROLLER_PC, MENUPAGE_CONTROLLER_PC, nil, nil,
#elif defined(PSP2)
// No gamepad-selection page here: there is exactly one pad, and it gets its own
// entry below for choosing which touch panel to use.
{ "FET_CON", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
#else #else
{ "FET_AGS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil, { "FET_AGS", MENUPAGE_OPTIONS, MENUPAGE_OPTIONS, nil, nil,
#endif
#ifdef PSP2
MENUACTION_CFO_SELECT, "PSP2", { new CCFOSelect((int8*)&useRearpad, "Controller", "Rearpad", off_on, 2, false) },
#endif #endif
MENUACTION_CTRLCONFIG, "FEC_CCF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, MENUACTION_CTRLCONFIG, "FEC_CCF", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS },
MENUACTION_CTRLDISPLAY, "FEC_CDP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS }, MENUACTION_CTRLDISPLAY, "FEC_CDP", { nil, SAVESLOT_NONE, MENUPAGE_CONTROLLER_SETTINGS },
+13 -1
View File
@@ -769,7 +769,7 @@ void CPad::StartShake_Train(float fX, float fY)
static bool MenuUsesNintendoLayout() static bool MenuUsesNintendoLayout()
{ {
return CMenuManager::m_PrefsControllerType == CMenuManager::CONTROLLER_NINTENDO_SWITCH return CMenuManager::m_PrefsControllerType == CMenuManager::CONTROLLER_NINTENDO_SWITCH
#ifdef RT #ifdef RT_CONTROLLERS
|| CMenuManager::m_PrefsControllerType == CMenuManager::CONTROLLER_DUALSHOCK2 // RT: DS2 slot is a Switch Pro Controller || CMenuManager::m_PrefsControllerType == CMenuManager::CONTROLLER_DUALSHOCK2 // RT: DS2 slot is a Switch Pro Controller
#endif #endif
; ;
@@ -1178,6 +1178,18 @@ void CPad::Update(int16 pad)
{ {
OldState = NewState; OldState = NewState;
#ifdef PSP2
if ( ShakeDur )
{
ShakeDur = Max((int32_t)ShakeDur - (int32_t)CTimer::GetTimeStepInMilliseconds(), 0);
SceCtrlActuator handle;
handle.small = 0;
handle.large = ShakeDur == 0 ? 0 : (unsigned char)ShakeFreq;
sceCtrlSetActuator(pad + 1, &handle);
}
#endif
#ifdef GTA_PS2 #ifdef GTA_PS2
bObsoleteControllerMessage = false; bObsoleteControllerMessage = false;
+6
View File
@@ -1,5 +1,11 @@
#pragma once #pragma once
#ifdef PSP2
extern "C"{
#include <math_neon.h>
};
#endif
#define _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#pragma warning(disable: 4244) // int to float #pragma warning(disable: 4244) // int to float
+24 -3
View File
@@ -206,10 +206,20 @@ enum Config {
// Every other platform builds vanilla. Platform necessities (audio/loading tweaks) // Every other platform builds vanilla. Platform necessities (audio/loading tweaks)
// are gated on __SWITCH__ separately, so a vanilla NX build still keeps those. // are gated on __SWITCH__ separately, so a vanilla NX build still keeps those.
// Kept above VANILLA_DEFINES so the tunables below exist in every configuration. // Kept above VANILLA_DEFINES so the tunables below exist in every configuration.
#if defined(__SWITCH__) && !defined(NO_RT) // The Vita ships the same 10thAE resources, and its menu layout is drawn against
// them, so it is an RT build too. The controller half of RT stays Switch-only -
// see the RT && __SWITCH__ gates around the pad slots.
#if (defined(__SWITCH__) || defined(PSP2)) && !defined(NO_RT)
#define RT #define RT
#endif #endif
// The controller half of RT - dropping the X360 slot and repurposing DS2 as a
// Switch Pro Controller - only makes sense on the Switch. The Vita has its own
// three pads (DS2 is the console itself) and keeps the upstream slots.
#if defined(RT) && defined(__SWITCH__)
#define RT_CONTROLLERS
#endif
// RT tunables, centralized so shared code stays readable. RT off = upstream values. // RT tunables, centralized so shared code stays readable. RT off = upstream values.
#ifdef RT #ifdef RT
#define RT_RADAR_SCALE 1.3f // enlarge the minimap by 30% #define RT_RADAR_SCALE 1.3f // enlarge the minimap by 30%
@@ -318,22 +328,29 @@ enum Config {
#define USE_TXD_CDIMAGE // generate and load textures from txd.img #define USE_TXD_CDIMAGE // generate and load textures from txd.img
#define PS2_ALPHA_TEST // emulate ps2 alpha test #define PS2_ALPHA_TEST // emulate ps2 alpha test
#define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number #define IMPROVED_VIDEOMODE // save and load videomode parameters instead of a magic number
#ifndef __SWITCH__ #if !defined(__SWITCH__) && !defined(PSP2)
#define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time (kept on Switch to show it) #define DISABLE_LOADING_SCREEN // disable the loading screen which vastly improves the loading time (both handhelds keep it, to show it)
#endif #endif
#ifdef DISABLE_LOADING_SCREEN #ifdef DISABLE_LOADING_SCREEN
// enable the PC splash // enable the PC splash
#undef RANDOMSPLASH #undef RANDOMSPLASH
#endif #endif
#define DISABLE_VSYNC_ON_TEXTURE_CONVERSION // make texture conversion work faster by disabling vsync #define DISABLE_VSYNC_ON_TEXTURE_CONVERSION // make texture conversion work faster by disabling vsync
#ifndef PSP2
#define ANISOTROPIC_FILTERING // set all textures to max anisotropic filtering #define ANISOTROPIC_FILTERING // set all textures to max anisotropic filtering
#endif
//#define USE_TEXTURE_POOL //#define USE_TEXTURE_POOL
#ifdef LIBRW #ifdef LIBRW
#define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur) #define EXTENDED_COLOURFILTER // more options for colour filter (replaces mblur)
// Not on PSP2: librw-vita is an old fork with no setupVertexInput, no three-argument
// Shader::create and no UNIFORM_VEC4, so the Neo pipelines and the droplets cannot
// build against it. They would also need Cg versions of every shader.
#ifndef PSP2
#define EXTENDED_PIPELINES // custom render pipelines (includes Neo) #define EXTENDED_PIPELINES // custom render pipelines (includes Neo)
#define SCREEN_DROPLETS // neo water droplets #define SCREEN_DROPLETS // neo water droplets
#define NEW_RENDERER // leeds-like world rendering, needs librw #define NEW_RENDERER // leeds-like world rendering, needs librw
#endif #endif
#endif
#define FIX_SPRITES // fix sprites aspect ratio(moon, coronas, particle etc) #define FIX_SPRITES // fix sprites aspect ratio(moon, coronas, particle etc)
@@ -461,7 +478,11 @@ enum Config {
#define PAUSE_RADIO_IN_FRONTEND // pause radio when game is paused #define PAUSE_RADIO_IN_FRONTEND // pause radio when game is paused
#define ATTACH_RELEASING_SOUNDS_TO_ENTITIES // sounds would follow ped and vehicles coordinates if not being queued otherwise #define ATTACH_RELEASING_SOUNDS_TO_ENTITIES // sounds would follow ped and vehicles coordinates if not being queued otherwise
#define USE_TIME_SCALE_FOR_AUDIO // slow down/speed up sounds according to the speed of the game #define USE_TIME_SCALE_FOR_AUDIO // slow down/speed up sounds according to the speed of the game
// Not on PSP2: std::thread cannot start here, and with -fno-exceptions the
// system_error it throws goes straight to terminate().
#ifndef PSP2
#define MULTITHREADED_AUDIO // for streams. requires C++11 or later #define MULTITHREADED_AUDIO // for streams. requires C++11 or later
#endif
#ifdef AUDIO_OPUS #ifdef AUDIO_OPUS
#define AUDIO_OAL_USE_OPUS // enable support of opus files #define AUDIO_OAL_USE_OPUS // enable support of opus files
+23
View File
@@ -378,6 +378,11 @@ RwGrabScreen(RwCamera *camera, RwChar *filename)
#define TILE_WIDTH 576 #define TILE_WIDTH 576
#define TILE_HEIGHT 432 #define TILE_HEIGHT 432
#ifdef PSP2
extern GLuint fxfb;
bool using_fbo = false;
#endif
void void
DoRWStuffEndOfFrame(void) DoRWStuffEndOfFrame(void)
{ {
@@ -385,6 +390,19 @@ DoRWStuffEndOfFrame(void)
CDebug::DebugDisplayTextBuffer(); CDebug::DebugDisplayTextBuffer();
FlushObrsPrintfs(); FlushObrsPrintfs();
RwCameraEndUpdate(Scene.camera); RwCameraEndUpdate(Scene.camera);
#if defined(PSP2) && defined(EXTENDED_COLOURFILTER)
// Arm the next frame's capture: bind our FBO once CPostFX has asked for it, so
// the scene renders into fxraster and the colour filter can sample it.
if(CPostFX::NeedBackBuffer()){
if (using_fbo) {
glBindFramebuffer(GL_FRAMEBUFFER, fxfb);
using_fbo = false;
} else
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
#endif
RsCameraShowRaster(Scene.camera); RsCameraShowRaster(Scene.camera);
#ifndef MASTER #ifndef MASTER
char s[48]; char s[48];
@@ -1496,7 +1514,12 @@ Render2dStuff(void)
firstPersonWeapon = true; firstPersonWeapon = true;
// Draw black border for sniper and rocket launcher // Draw black border for sniper and rocket launcher
#ifdef FIX_BUGS
// The rocket launcher has no scope, so the border just blacks out the screen.
if(weaponType == WEAPONTYPE_SNIPERRIFLE && firstPersonWeapon){
#else
if((weaponType == WEAPONTYPE_SNIPERRIFLE || weaponType == WEAPONTYPE_ROCKETLAUNCHER) && firstPersonWeapon){ if((weaponType == WEAPONTYPE_SNIPERRIFLE || weaponType == WEAPONTYPE_ROCKETLAUNCHER) && firstPersonWeapon){
#endif
CRGBA black(0, 0, 0, 255); CRGBA black(0, 0, 0, 255);
// top and bottom strips // top and bottom strips
+7
View File
@@ -184,7 +184,14 @@ CustomFrontendOptionsPopulate(void)
#define MINI_CASE_SENSITIVE #define MINI_CASE_SENSITIVE
#include "ini.h" #include "ini.h"
#ifdef PSP2
// mINI opens the file with std::ifstream/ofstream, which bypasses the fcaseopen/
// casepath shims that resolve relative paths against the data dir, so a bare
// "re3.ini" never opens here and settings would not persist.
mINI::INIFile ini(PSP2_DATA_PATH "/re3.ini");
#else
mINI::INIFile ini("re3.ini"); mINI::INIFile ini("re3.ini");
#endif
mINI::INIStructure cfg; mINI::INIStructure cfg;
bool ReadIniIfExists(const char *cat, const char *key, uint32 *out) bool ReadIniIfExists(const char *cat, const char *key, uint32 *out)
+70 -17
View File
@@ -13,6 +13,11 @@
#include "MBlur.h" #include "MBlur.h"
#include "postfx.h" #include "postfx.h"
#ifdef PSP2
GLuint fxraster = 0xDEADBEEF, fxfb;
extern bool using_fbo;
#endif
RwRaster *CPostFX::pFrontBuffer; RwRaster *CPostFX::pFrontBuffer;
RwRaster *CPostFX::pBackBuffer; RwRaster *CPostFX::pBackBuffer;
bool CPostFX::bJustInitialised; bool CPostFX::bJustInitialised;
@@ -54,6 +59,10 @@ CPostFX::Open(RwCamera *cam)
uint32 width = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1); uint32 width = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1);
uint32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1); uint32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1);
uint32 depth = RwRasterGetDepth(RwCameraGetRaster(cam)); uint32 depth = RwRasterGetDepth(RwCameraGetRaster(cam));
#ifdef PSP2
width = RwRasterGetWidth(RwCameraGetRaster(cam));
height = RwRasterGetHeight(RwCameraGetRaster(cam));
#endif
pFrontBuffer = RwRasterCreate(width, height, depth, rwRASTERTYPECAMERATEXTURE); pFrontBuffer = RwRasterCreate(width, height, depth, rwRASTERTYPECAMERATEXTURE);
pBackBuffer = RwRasterCreate(width, height, depth, rwRASTERTYPECAMERATEXTURE); pBackBuffer = RwRasterCreate(width, height, depth, rwRASTERTYPECAMERATEXTURE);
bJustInitialised = true; bJustInitialised = true;
@@ -151,22 +160,39 @@ CPostFX::Open(RwCamera *cam)
contrast_PS = rw::d3d::createPixelShader(contrastPS_cso); contrast_PS = rw::d3d::createPixelShader(contrastPS_cso);
#endif #endif
#ifdef RW_OPENGL #ifdef RW_OPENGL
#ifdef PSP2
#include "shaders/im2d_v_cg.inc"
#endif
using namespace rw::gl3; using namespace rw::gl3;
{ {
#ifdef PSP2
#include "shaders/colourfilterIII_f_cg.inc"
const char *vs[] = { im2d_v_cg_src, nil };
const char *fs[] = { colourfilterIII_f_cg_src, nil };
colourFilterIII = Shader::create(vs, fs, true);
#else
#include "shaders/obj/im2d_vert.inc" #include "shaders/obj/im2d_vert.inc"
#include "shaders/obj/colourfilterIII_frag.inc" #include "shaders/obj/colourfilterIII_frag.inc"
const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil }; const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, colourfilterIII_frag_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, colourfilterIII_frag_src, nil };
colourFilterIII = Shader::create(vs, fs); colourFilterIII = Shader::create(vs, fs);
#endif
assert(colourFilterIII); assert(colourFilterIII);
} }
{ {
#ifdef PSP2
#include "shaders/contrast_f_cg.inc"
const char *vs[] = { im2d_v_cg_src, nil };
const char *fs[] = { contrast_f_cg_src, nil };
contrast = Shader::create(vs, fs, true);
#else
#include "shaders/obj/im2d_vert.inc" #include "shaders/obj/im2d_vert.inc"
#include "shaders/obj/contrast_frag.inc" #include "shaders/obj/contrast_frag.inc"
const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil }; const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil };
const char *fs[] = { shaderDecl, header_frag_src, contrast_frag_src, nil }; const char *fs[] = { shaderDecl, header_frag_src, contrast_frag_src, nil };
contrast = Shader::create(vs, fs); contrast = Shader::create(vs, fs);
#endif
assert(contrast); assert(contrast);
} }
@@ -305,6 +331,14 @@ CPostFX::RenderOverlayShader(RwCamera *cam, int32 r, int32 g, int32 b, int32 a)
glUniform4fv(colourFilterIII->uniformLocations[u_blurcolor], 1, blurcolors); glUniform4fv(colourFilterIII->uniformLocations[u_blurcolor], 1, blurcolors);
#endif #endif
} }
#ifdef PSP2
// The scene lives in our own FBO texture here, not in pBackBuffer.
glBindTexture(GL_TEXTURE_2D, fxraster);
RwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, 255);
RwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, 255);
RwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, 255);
RwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, 255);
#endif
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6); RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);
#ifdef RW_D3D9 #ifdef RW_D3D9
rw::d3d::im2dOverridePS = nil; rw::d3d::im2dOverridePS = nil;
@@ -432,8 +466,11 @@ CPostFX::Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blu
assert(pFrontBuffer); assert(pFrontBuffer);
assert(pBackBuffer); assert(pBackBuffer);
// PSP2 captures the scene through its own FBO a frame ahead instead.
#ifndef PSP2
if(NeedBackBuffer()) if(NeedBackBuffer())
GetBackBuffer(cam); GetBackBuffer(cam);
#endif
DefinedState(); DefinedState();
@@ -445,24 +482,40 @@ CPostFX::Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blu
if(type == MOTION_BLUR_SNIPER){ if(type == MOTION_BLUR_SNIPER){
if(!bJustInitialised) if(!bJustInitialised)
RenderOverlaySniper(cam, red, green, blue, blur); RenderOverlaySniper(cam, red, green, blue, blur);
}else switch(EffectSwitch){ }else{
case POSTFX_OFF: #if defined(PSP2) && defined(EXTENDED_COLOURFILTER)
// no actual rendering here if (NeedBackBuffer()) {
break; if(fxraster == 0xDEADBEEF){
case POSTFX_SIMPLE: glGenTextures(1, &fxraster);
RenderOverlaySimple(cam, red, green, blue, blur); glBindTexture(GL_TEXTURE_2D, fxraster);
break; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 960, 544, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
case POSTFX_NORMAL: glGenFramebuffers(1, &fxfb);
if(MotionBlurOn){ glBindFramebuffer(GL_FRAMEBUFFER, fxfb);
if(!bJustInitialised) glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fxraster, 0);
RenderOverlayBlur(cam, red, green, blue, blur); }
}else{ using_fbo = true;
RenderOverlayShader(cam, red, green, blue, blur); glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
#endif
switch(EffectSwitch){
case POSTFX_OFF:
// no actual rendering here
break;
case POSTFX_SIMPLE:
RenderOverlaySimple(cam, red, green, blue, blur);
break;
case POSTFX_NORMAL:
if(MotionBlurOn){
if(!bJustInitialised)
RenderOverlayBlur(cam, red, green, blue, blur);
}else{
RenderOverlayShader(cam, red, green, blue, blur);
}
break;
case POSTFX_MOBILE:
RenderOverlayShader(cam, red, green, blue, blur);
break;
} }
break;
case POSTFX_MOBILE:
RenderOverlayShader(cam, red, green, blue, blur);
break;
} }
// TODO? maybe we want this even without motion blur on sometimes? // TODO? maybe we want this even without motion blur on sometimes?
+38
View File
@@ -0,0 +1,38 @@
#define u_fogStart (u_fogData.x)
#define u_fogEnd (u_fogData.y)
#define u_fogRange (u_fogData.z)
#define u_fogDisable (u_fogData.w)
void DoAlphaTest(float a, half2 u_alphaRef)
{
if(a < u_alphaRef.x || a >= u_alphaRef.y)
discard;
}
float4 main(
half4 v_color : COLOR0,
half2 v_tex0 : TEXCOORD0,
fixed v_fog : FOG,
uniform half4 u_fogColor,
uniform half2 u_alphaRef,
uniform half4 u_blurcolor,
uniform sampler2D tex0
) {
half a = u_blurcolor.a;
half4 dst = v_color*tex2D(tex0, half2(v_tex0.x, 1.0-v_tex0.y));
dst.rgb = lerp(u_fogColor.rgb, dst.rgb, v_fog);
DoAlphaTest(dst.a, u_alphaRef);
half4 prev = dst;
for (int i = 0; i < 5; i++){
half4 tmp = dst*(1.0-a) + prev*u_blurcolor*a;
prev = clamp(tmp, 0.0, 1.0);
}
half4 color;
color.rgb = prev.rgb;
color.a = 1.0f;
return color;
}
@@ -0,0 +1,40 @@
const char *colourfilterIII_f_cg_src =
"#define u_fogStart (u_fogData.x)\n"
"#define u_fogEnd (u_fogData.y)\n"
"#define u_fogRange (u_fogData.z)\n"
"#define u_fogDisable (u_fogData.w)\n"
"void DoAlphaTest(float a, half2 u_alphaRef)\n"
"{\n"
" if(a < u_alphaRef.x || a >= u_alphaRef.y)\n"
" discard;\n"
"}\n"
"float4 main(\n"
" half4 v_color : COLOR0,\n"
" half2 v_tex0 : TEXCOORD0,\n"
" fixed v_fog : FOG,\n"
" uniform half4 u_fogColor,\n"
" uniform half2 u_alphaRef,\n"
" uniform half4 u_blurcolor,\n"
" uniform sampler2D tex0\n"
") {\n"
" half a = u_blurcolor.a;\n"
" half4 dst = v_color*tex2D(tex0, half2(v_tex0.x, 1.0-v_tex0.y));\n"
" dst.rgb = lerp(u_fogColor.rgb, dst.rgb, v_fog);\n"
" DoAlphaTest(dst.a, u_alphaRef);\n"
" half4 prev = dst;\n"
" for (int i = 0; i < 5; i++){\n"
" half4 tmp = dst*(1.0-a) + prev*u_blurcolor*a;\n"
" prev = clamp(tmp, 0.0, 1.0);\n"
" }\n"
" half4 color;\n"
" color.rgb = prev.rgb;\n"
" color.a = 1.0f;\n"
" return color;\n"
"}\n"
;
+33
View File
@@ -0,0 +1,33 @@
#define u_fogStart (u_fogData.x)
#define u_fogEnd (u_fogData.y)
#define u_fogRange (u_fogData.z)
#define u_fogDisable (u_fogData.w)
void DoAlphaTest(float a, half2 u_alphaRef)
{
if(a < u_alphaRef.x || a >= u_alphaRef.y)
discard;
}
float4 main(
half4 v_color : COLOR0,
half2 v_tex0 : TEXCOORD0,
fixed v_fog : FOG,
uniform half4 u_fogColor,
uniform half2 u_alphaRef,
uniform float3 u_contrastAdd,
uniform float3 u_contrastMult,
uniform sampler2D tex0
) {
half4 dst = v_color*tex2D(tex0, half2(v_tex0.x, 1.0-v_tex0.y));
dst.rgb = lerp(u_fogColor.rgb, dst.rgb, v_fog);
DoAlphaTest(dst.a, u_alphaRef);
half4 color;
color.rgb = dst.rgb*u_contrastMult + u_contrastAdd;
color.a = 1.0f;
return color;
}
+35
View File
@@ -0,0 +1,35 @@
const char *contrast_f_cg_src =
"#define u_fogStart (u_fogData.x)\n"
"#define u_fogEnd (u_fogData.y)\n"
"#define u_fogRange (u_fogData.z)\n"
"#define u_fogDisable (u_fogData.w)\n"
"void DoAlphaTest(float a, half2 u_alphaRef)\n"
"{\n"
" if(a < u_alphaRef.x || a >= u_alphaRef.y)\n"
" discard;\n"
"}\n"
"float4 main(\n"
" half4 v_color : COLOR0,\n"
" half2 v_tex0 : TEXCOORD0,\n"
" fixed v_fog : FOG,\n"
" uniform half4 u_fogColor,\n"
" uniform half2 u_alphaRef,\n"
" uniform float3 u_contrastAdd,\n"
" uniform float3 u_contrastMult,\n"
" uniform sampler2D tex0\n"
") {\n"
" half4 dst = v_color*tex2D(tex0, half2(v_tex0.x, 1.0-v_tex0.y));\n"
" dst.rgb = lerp(u_fogColor.rgb, dst.rgb, v_fog);\n"
" DoAlphaTest(dst.a, u_alphaRef);\n"
" half4 color;\n"
" color.rgb = dst.rgb*u_contrastMult + u_contrastAdd;\n"
" color.a = 1.0f;\n"
" return color;\n"
"}\n"
;
+35
View File
@@ -0,0 +1,35 @@
#define u_fogStart (u_fogData.x)
#define u_fogEnd (u_fogData.y)
#define u_fogRange (u_fogData.z)
#define u_fogDisable (u_fogData.w)
#define MAX_LIGHTS 8
#define surfAmbient (u_surfProps.x)
#define surfSpecular (u_surfProps.y)
#define surfDiffuse (u_surfProps.z)
fixed DoFog(float w, half4 u_fogData)
{
return clamp((w - u_fogEnd)*u_fogRange, u_fogDisable, 1.0);
}
void main(
float4 in_pos,
half4 in_color,
half2 in_tex0,
uniform half4 u_fogData,
uniform float4 u_xform,
half4 out v_color : COLOR0,
half2 out v_tex0 : TEXCOORD0,
fixed out v_fog : FOG,
float4 out gl_Position : POSITION
) {
gl_Position = in_pos;
gl_Position.w = 1.0;
gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;
v_fog = DoFog(gl_Position.z, u_fogData);
gl_Position.xyz *= gl_Position.w;
v_color = in_color;
v_tex0 = in_tex0;
}
+37
View File
@@ -0,0 +1,37 @@
const char *im2d_v_cg_src =
"#define u_fogStart (u_fogData.x)\n"
"#define u_fogEnd (u_fogData.y)\n"
"#define u_fogRange (u_fogData.z)\n"
"#define u_fogDisable (u_fogData.w)\n"
"#define MAX_LIGHTS 8\n"
"#define surfAmbient (u_surfProps.x)\n"
"#define surfSpecular (u_surfProps.y)\n"
"#define surfDiffuse (u_surfProps.z)\n"
"fixed DoFog(float w, half4 u_fogData)\n"
"{\n"
" return clamp((w - u_fogEnd)*u_fogRange, u_fogDisable, 1.0);\n"
"}\n"
"void main(\n"
" float4 in_pos,\n"
" half4 in_color,\n"
" half2 in_tex0,\n"
" uniform half4 u_fogData,\n"
" uniform float4 u_xform,\n"
" half4 out v_color : COLOR0,\n"
" half2 out v_tex0 : TEXCOORD0,\n"
" fixed out v_fog : FOG,\n"
" float4 out gl_Position : POSITION\n"
") {\n"
" gl_Position = in_pos;\n"
" gl_Position.w = 1.0;\n"
" gl_Position.xy = gl_Position.xy * u_xform.xy + u_xform.zw;\n"
" v_fog = DoFog(gl_Position.z, u_fogData);\n"
" gl_Position.xyz *= gl_Position.w;\n"
" v_color = in_color;\n"
" v_tex0 = in_tex0;\n"
"}\n"
;
+55 -2
View File
@@ -299,12 +299,40 @@ RwTextureAddressMode RwTextureGetAddressingV(const RwTexture *texture);
// TODO // TODO
void _rwD3D8TexDictionaryEnableRasterFormatConversion(bool enable) { } void _rwD3D8TexDictionaryEnableRasterFormatConversion(bool enable) { }
#ifdef PSP2
// librw-vita predates Raster::convertTexToCurrentPlatform, so do it by hand:
// round-trip through an Image, which also drops the palette the Vita cannot use.
static rw::Raster*
ConvertTexRaster(rw::Raster *ras)
{
using namespace rw;
if(ras->platform == rw::platform)
return ras;
// compatible platforms
if(ras->platform == PLATFORM_D3D8 && rw::platform == PLATFORM_D3D9 ||
ras->platform == PLATFORM_D3D9 && rw::platform == PLATFORM_D3D8)
return ras;
Image *img = ras->toImage();
ras->destroy();
img->unpalettize();
ras = Raster::createFromImage(img);
img->destroy();
return ras;
}
#endif
// hack for reading native textures // hack for reading native textures
RwBool rwNativeTextureHackRead(RwStream *stream, RwTexture **tex, RwInt32 size) RwBool rwNativeTextureHackRead(RwStream *stream, RwTexture **tex, RwInt32 size)
{ {
*tex = Texture::streamReadNative(stream); *tex = Texture::streamReadNative(stream);
#ifdef LIBRW #ifdef LIBRW
#ifdef PSP2
(*tex)->raster = ConvertTexRaster((*tex)->raster);
#else
(*tex)->raster = rw::Raster::convertTexToCurrentPlatform((*tex)->raster); (*tex)->raster = rw::Raster::convertTexToCurrentPlatform((*tex)->raster);
#endif
#endif #endif
return *tex != nil; return *tex != nil;
} }
@@ -550,6 +578,7 @@ static void *reallocWrap(void *p, size_t sz, uint32 hint) { return real_realloc(
// WARNING: unused parameters // WARNING: unused parameters
RwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize) { RwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize) {
#ifndef PSP2
if(memFuncs){ if(memFuncs){
real_malloc = memFuncs->rwmalloc; real_malloc = memFuncs->rwmalloc;
real_realloc = memFuncs->rwrealloc; real_realloc = memFuncs->rwrealloc;
@@ -560,6 +589,10 @@ RwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 re
}else{ }else{
Engine::init(nil); Engine::init(nil);
} }
#else
// librw-vita's Engine::init takes no memory functions.
Engine::init();
#endif
return true; return true;
} }
// TODO: this is platform dependent // TODO: this is platform dependent
@@ -601,8 +634,20 @@ void RwD3D8EngineSetRefreshRate(RwUInt32 refreshRate) {}
RwBool RwD3D8DeviceSupportsDXTTexture(void) { return true; } RwBool RwD3D8DeviceSupportsDXTTexture(void) { return true; }
void RwD3D8EngineSetMultiSamplingLevels(RwUInt32 level) { Engine::setMultiSamplingLevels(level); } // librw-vita has no multisampling controls - the level is fixed when vitaGL starts.
RwUInt32 RwD3D8EngineGetMaxMultiSamplingLevels(void) { return Engine::getMaxMultiSamplingLevels(); } // Reporting 0 levels is what keeps the menu entry out; see MenuScreensCustom.
void RwD3D8EngineSetMultiSamplingLevels(RwUInt32 level) {
#ifndef PSP2
Engine::setMultiSamplingLevels(level);
#endif
}
RwUInt32 RwD3D8EngineGetMaxMultiSamplingLevels(void) {
#ifndef PSP2
return Engine::getMaxMultiSamplingLevels();
#else
return 0;
#endif
}
RpMaterial *RpMaterialCreate(void) { return Material::create(); } RpMaterial *RpMaterialCreate(void) { return Material::create(); }
@@ -1004,7 +1049,15 @@ RwBool RtCharsetDestroy(RtCharset * charSet) { charSet->destroy(); return
#include <rpanisot.h> #include <rpanisot.h>
#ifdef PSP2
// librw-vita has no anisotropy plugin. Reporting zero keeps callers away from it.
RwInt8 RpAnisotGetMaxSupportedMaxAnisotropy(void) { return 0; }
RwTexture *RpAnisotTextureSetMaxAnisotropy(RwTexture *tex, RwInt8 val) { return tex; }
RwInt8 RpAnisotTextureGetMaxAnisotropy(RwTexture *tex) { return 0; }
RwBool RpAnisotPluginAttach(void) { return false; }
#else
RwInt8 RpAnisotGetMaxSupportedMaxAnisotropy(void) { return rw::getMaxSupportedMaxAnisotropy(); } RwInt8 RpAnisotGetMaxSupportedMaxAnisotropy(void) { return rw::getMaxSupportedMaxAnisotropy(); }
RwTexture *RpAnisotTextureSetMaxAnisotropy(RwTexture *tex, RwInt8 val) { tex->setMaxAnisotropy(val); return tex; } RwTexture *RpAnisotTextureSetMaxAnisotropy(RwTexture *tex, RwInt8 val) { tex->setMaxAnisotropy(val); return tex; }
RwInt8 RpAnisotTextureGetMaxAnisotropy(RwTexture *tex) { return tex->getMaxAnisotropy(); } RwInt8 RpAnisotTextureGetMaxAnisotropy(RwTexture *tex) { return tex->getMaxAnisotropy(); }
RwBool RpAnisotPluginAttach(void) { rw::registerAnisotropyPlugin(); return true; } RwBool RpAnisotPluginAttach(void) { rw::registerAnisotropyPlugin(); return true; }
#endif
+4
View File
@@ -3,6 +3,9 @@
void void
CVector::Normalise(void) CVector::Normalise(void)
{ {
#ifdef PSP2
normalize3_neon(&this->x, &this->x);
#else
float sq = MagnitudeSqr(); float sq = MagnitudeSqr();
if (sq > 0.0f) { if (sq > 0.0f) {
float invsqrt = RecipSqrt(sq); float invsqrt = RecipSqrt(sq);
@@ -11,6 +14,7 @@ CVector::Normalise(void)
z *= invsqrt; z *= invsqrt;
} else } else
x = 1.0f; x = 1.0f;
#endif
} }
CVector CVector
+12
View File
@@ -12,6 +12,10 @@
#include "MBlur.h" #include "MBlur.h"
#include "postfx.h" #include "postfx.h"
#ifdef PSP2
bool gPostFX = false;
#endif
// Originally taken from RW example 'mblur' // Originally taken from RW example 'mblur'
RwRaster *CMBlur::pFrontBuffer; RwRaster *CMBlur::pFrontBuffer;
@@ -216,15 +220,23 @@ CMBlur::MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, u
OverlayRender(cam, pFrontBuffer, color, type, bluralpha); OverlayRender(cam, pFrontBuffer, color, type, bluralpha);
#else #else
if(BlurOn){ if(BlurOn){
// On PSP2 the copy has to happen before the overlay: rasterRenderFast reads
// the display buffer, which still holds the previous frame at this point.
#if !defined(PSP2)
if(pFrontBuffer){ if(pFrontBuffer){
if(ms_bJustInitialised) if(ms_bJustInitialised)
ms_bJustInitialised = false; ms_bJustInitialised = false;
else else
OverlayRender(cam, pFrontBuffer, color, type, bluralpha); OverlayRender(cam, pFrontBuffer, color, type, bluralpha);
} }
#endif
RwRasterPushContext(pFrontBuffer); RwRasterPushContext(pFrontBuffer);
RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0); RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);
RwRasterPopContext(); RwRasterPopContext();
#ifdef PSP2
if(pFrontBuffer)
OverlayRender(cam, pFrontBuffer, color, type, bluralpha);
#endif
}else{ }else{
OverlayRender(cam, nil, color, type, bluralpha); OverlayRender(cam, nil, color, type, bluralpha);
} }
+43 -4
View File
@@ -182,7 +182,8 @@ GetGPUcaps(GPUcaps *caps)
caps->subplatform = 0; caps->subplatform = 0;
caps->dxtSupport = 0; caps->dxtSupport = 0;
// TODO: more later // TODO: more later
#ifdef RW_GL3 // librw-vita has no gl3Caps.
#if defined(RW_GL3) && !defined(PSP2)
caps->subplatform = rw::gl3::gl3Caps.gles; caps->subplatform = rw::gl3::gl3Caps.gles;
caps->dxtSupport = rw::gl3::gl3Caps.dxtSupported; caps->dxtSupport = rw::gl3::gl3Caps.dxtSupported;
#endif #endif
@@ -338,9 +339,46 @@ DealWithTxdWriteError(uint32 num, uint32 count, const char *text)
#define STREAMTELL(str) filesys->rwftell((str)->Type.file.fpFile) #define STREAMTELL(str) filesys->rwftell((str)->Type.file.fpFile)
#endif #endif
#ifdef PSP2
static void
ConvertNativeTXD(const char *filename)
{
RwStream *stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);
if(stream == nil)
return;
RwTexDictionary *txd = nil;
if(RwStreamFindChunk(stream, rwID_TEXDICTIONARY, nil, nil))
txd = RwTexDictionaryGtaStreamRead(stream);
RwStreamClose(stream, nil);
if(txd == nil)
return;
stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMWRITE, filename);
if(stream){
RwTexDictionaryStreamWrite(txd, stream);
RwStreamClose(stream, nil);
}
RwTexDictionaryDestroy(txd);
}
#endif
bool bool
CreateTxdImageForVideoCard() CreateTxdImageForVideoCard()
{ {
#ifdef PSP2
static const char *looseTxds[] = {
"models\\menu.txd", "models\\fonts.txd", "models\\fonts_j.txd",
"models\\fonts_p.txd", "models\\fonts_r.txd", "models\\frontend.txd",
"models\\generic.txd", "models\\hud.txd", "models\\MISC.TXD",
"models\\particle.txd", "models\\x360btns.txd",
"txd\\mainsc1.txd", "txd\\mainsc2.txd", "txd\\NEWS.TXD",
"txd\\SPLASH1.TXD", "txd\\SPLASH2.TXD", "txd\\SPLASH3.TXD",
};
for(uint32 i = 0; i < ARRAY_SIZE(looseTxds); i++){
ConvertNativeTXD(looseTxds[i]);
}
#endif
uint8 *buf = new uint8[CDSTREAM_SECTOR_SIZE]; uint8 *buf = new uint8[CDSTREAM_SECTOR_SIZE];
CDirectory *pDir = new CDirectory(TXDSTORESIZE); CDirectory *pDir = new CDirectory(TXDSTORESIZE);
CDirectory::DirectoryInfo dirInfo; CDirectory::DirectoryInfo dirInfo;
@@ -363,7 +401,8 @@ CreateTxdImageForVideoCard()
return false; return false;
} }
#ifdef RW_GL3 // librw-vita has no needToReadBackTextures - it always keeps texture data around.
#if defined(RW_GL3) && !defined(PSP2)
// so we can read back DXT with GLES // so we can read back DXT with GLES
// only works for textures that are not yet loaded // only works for textures that are not yet loaded
// so let's hope that is the case for all // so let's hope that is the case for all
@@ -406,7 +445,7 @@ CreateTxdImageForVideoCard()
delete []buf; delete []buf;
delete pDir; delete pDir;
CStreaming::RemoveTxd(i); CStreaming::RemoveTxd(i);
#ifdef RW_GL3 #if defined(RW_GL3) && !defined(PSP2)
rw::gl3::needToReadBackTextures = false; rw::gl3::needToReadBackTextures = false;
#endif #endif
return false; return false;
@@ -441,7 +480,7 @@ CreateTxdImageForVideoCard()
RwStreamClose(img, nil); RwStreamClose(img, nil);
delete []buf; delete []buf;
#ifdef RW_GL3 #if defined(RW_GL3) && !defined(PSP2)
rw::gl3::needToReadBackTextures = false; rw::gl3::needToReadBackTextures = false;
#endif #endif
+9
View File
@@ -22,7 +22,12 @@ template <typename T>
inline void inline void
ReadSaveBuf(T* out, uint8 *&buf) ReadSaveBuf(T* out, uint8 *&buf)
{ {
// Save buffers are not aligned, and the Vita traps unaligned wide loads.
#if !defined(PSP2)
*out = *(T *)buf; *out = *(T *)buf;
#else
sceClibMemcpy(out, buf, sizeof(T));
#endif
SkipSaveBuf(buf, sizeof(T)); SkipSaveBuf(buf, sizeof(T));
} }
@@ -31,7 +36,11 @@ inline T *
WriteSaveBuf(uint8 *&buf, const T &value) WriteSaveBuf(uint8 *&buf, const T &value)
{ {
T *p = (T *)buf; T *p = (T *)buf;
#if !defined(PSP2)
*p = value; *p = value;
#else
sceClibMemcpy(p, &value, sizeof(T));
#endif
SkipSaveBuf(buf, sizeof(T)); SkipSaveBuf(buf, sizeof(T));
return p; return p;
} }
+325 -1
View File
@@ -1,6 +1,322 @@
#include "common.h" #include "common.h"
#include "crossplatform.h" #include "crossplatform.h"
#ifdef PSP2
extern SceTouchPanelInfo panelInfo[2];
bool useRearpad = false;
void *memcpy(void *dest, const void *src, size_t n)
{
return sceClibMemcpy(dest, src, n);
}
static unsigned char gButtons[GLFW_GAMEPAD_BUTTON_LAST+1];
static float gAxes[GLFW_GAMEPAD_AXIS_LAST+1];
unsigned char* glfwGetJoystickButtons(int jid, int* count)
{
int port_id = useRearpad ? 1 : 0;
SceCtrlData pad;
SceTouchData touch;
sceCtrlPeekBufferPositiveExt2(0, &pad, 1);
sceTouchPeek(port_id, &touch, 1);
gButtons[GLFW_GAMEPAD_BUTTON_CROSS] = pad.buttons & SCE_CTRL_CROSS ? GLFW_PRESS : GLFW_RELEASE;
gButtons[GLFW_GAMEPAD_BUTTON_CIRCLE] = pad.buttons & SCE_CTRL_CIRCLE ? GLFW_PRESS : GLFW_RELEASE;
gButtons[GLFW_GAMEPAD_BUTTON_SQUARE] = pad.buttons & SCE_CTRL_SQUARE ? GLFW_PRESS : GLFW_RELEASE;
gButtons[GLFW_GAMEPAD_BUTTON_TRIANGLE] = pad.buttons & SCE_CTRL_TRIANGLE ? GLFW_PRESS : GLFW_RELEASE;
gButtons[GLFW_GAMEPAD_BUTTON_LEFT_BUMPER] = pad.buttons & SCE_CTRL_L1 ? GLFW_PRESS : GLFW_RELEASE;
gButtons[GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER] = pad.buttons & SCE_CTRL_R1 ? GLFW_PRESS : GLFW_RELEASE;
gButtons[GLFW_GAMEPAD_BUTTON_BACK] = pad.buttons & SCE_CTRL_SELECT ? GLFW_PRESS : GLFW_RELEASE;
gButtons[GLFW_GAMEPAD_BUTTON_START] = pad.buttons & SCE_CTRL_START ? GLFW_PRESS : GLFW_RELEASE;
gButtons[GLFW_GAMEPAD_BUTTON_GUIDE] = GLFW_RELEASE;
gButtons[GLFW_GAMEPAD_BUTTON_LEFT_THUMB] = pad.buttons & SCE_CTRL_L3 ? GLFW_PRESS : GLFW_RELEASE;
gButtons[GLFW_GAMEPAD_BUTTON_RIGHT_THUMB] = pad.buttons & SCE_CTRL_R3 ? GLFW_PRESS : GLFW_RELEASE;
for (int i = 0; i < touch.reportNum; i++) {
if (touch.report[i].y >= (panelInfo[port_id].minAaY + panelInfo[port_id].maxAaY) / 2) {
if (touch.report[i].x < (panelInfo[port_id].minAaX + panelInfo[port_id].maxAaX) / 2)
gButtons[GLFW_GAMEPAD_BUTTON_LEFT_THUMB] = GLFW_PRESS;
else
gButtons[GLFW_GAMEPAD_BUTTON_RIGHT_THUMB] = GLFW_PRESS;
}
}
gButtons[GLFW_GAMEPAD_BUTTON_DPAD_UP] = pad.buttons & SCE_CTRL_UP ? GLFW_PRESS : GLFW_RELEASE;
gButtons[GLFW_GAMEPAD_BUTTON_DPAD_RIGHT] = pad.buttons & SCE_CTRL_RIGHT ? GLFW_PRESS : GLFW_RELEASE;
gButtons[GLFW_GAMEPAD_BUTTON_DPAD_DOWN] = pad.buttons & SCE_CTRL_DOWN ? GLFW_PRESS : GLFW_RELEASE;
gButtons[GLFW_GAMEPAD_BUTTON_DPAD_LEFT] = pad.buttons & SCE_CTRL_LEFT ? GLFW_PRESS : GLFW_RELEASE;
if (count)
*count = GLFW_GAMEPAD_BUTTON_LAST+1;
return gButtons;
}
float* glfwGetJoystickAxes(int jid, int* count)
{
int port_id = useRearpad ? 1 : 0;
SceCtrlData pad;
SceTouchData touch;
sceCtrlPeekBufferPositiveExt2(0, &pad, 1);
sceTouchPeek(port_id, &touch, 1);
gAxes[GLFW_GAMEPAD_AXIS_LEFT_X] = ((float)pad.lx - 128.0f) / 128.0f;
gAxes[GLFW_GAMEPAD_AXIS_LEFT_Y] = ((float)pad.ly - 128.0f) / 128.0f;
gAxes[GLFW_GAMEPAD_AXIS_RIGHT_X] = ((float)pad.rx - 128.0f) / 128.0f;
gAxes[GLFW_GAMEPAD_AXIS_RIGHT_Y] = ((float)pad.ry - 128.0f) / 128.0f;
gAxes[GLFW_GAMEPAD_AXIS_LEFT_TRIGGER] = pad.buttons & SCE_CTRL_L2 ? 1.0f : -1.0f;
gAxes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER] = pad.buttons & SCE_CTRL_R2 ? 1.0f : -1.0f;
for (int i = 0; i < touch.reportNum; i++) {
if (touch.report[i].y < (panelInfo[port_id].minAaY + panelInfo[port_id].maxAaY) / 2) {
if (touch.report[i].x < (panelInfo[port_id].minAaX + panelInfo[port_id].maxAaX) / 2)
gAxes[GLFW_GAMEPAD_AXIS_LEFT_TRIGGER] = 1.0f;
else
gAxes[GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER] = 1.0f;
}
}
if (count)
*count = GLFW_GAMEPAD_AXIS_LAST+1;
return gAxes;
}
int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
{
unsigned char *buttons = glfwGetJoystickButtons(jid, NULL);
float *axes = glfwGetJoystickAxes(jid, NULL);
sceClibMemcpy(state->buttons, buttons, sizeof(state->buttons));
sceClibMemcpy(state->axes, axes, sizeof(state->axes));
return 1;
}
int glfwJoystickPresent(int jid)
{
return jid == 0;
}
int glfwJoystickIsGamepad(int jid)
{
return jid == 0;
}
int glfwGetKey(GLFWwindow* window, int key)
{
return GLFW_RELEASE;
}
int glfwGetMouseButton(GLFWwindow* window, int button)
{
return GLFW_RELEASE;
}
void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos)
{
if (xpos)
*xpos = 0.0f;
if (ypos)
*ypos = 0.0f;
return;
}
void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos)
{
return;
}
const char* glfwGetJoystickName(int jid)
{
return "Vita Pad";
}
int glfwWindowShouldClose(GLFWwindow* window)
{
return 0;
}
GLFWmonitor* glfwGetPrimaryMonitor(void)
{
return NULL;
}
static GLFWvidmode gVideoMode { .width = 960, .height = 544 };
const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor)
{
return &gVideoMode;
}
void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
{
return;
}
int clock_gettime(int clk_id, struct timespec *tp)
{
if (clk_id == CLOCK_MONOTONIC) {
SceKernelSysClock ticks;
sceKernelGetProcessTime(&ticks);
tp->tv_sec = ticks / (1000 * 1000);
tp->tv_nsec = (ticks * 1000) % (1000 * 1000 * 1000);
return 0;
} else if (clk_id == CLOCK_REALTIME) {
time_t seconds;
SceDateTime time;
sceRtcGetCurrentClockLocalTime(&time);
sceRtcGetTime_t(&time, &seconds);
tp->tv_sec = seconds;
tp->tv_nsec = time.microsecond * 1000;
return 0;
}
return -ENOSYS;
}
int _lstat(const char *path, struct stat *buf)
{
return stat(path, buf);
}
char cur_dir[PATH_MAX] = PSP2_DATA_PATH;
char *_getcwd(char *buf, size_t size)
{
if (buf != NULL)
strncpy(buf, cur_dir, size);
return cur_dir;
}
char *_realpath(const char *path, char *resolved_path)
{
char data_path[PATH_MAX];
_getcwd(data_path, sizeof(data_path));
if (strncmp(path, "ux0:", 4) == 0)
strcpy(resolved_path, path);
else
sprintf(resolved_path, "%s/%s", data_path, path);
return resolved_path;
}
ssize_t readlink(const char *path, char *buf, size_t bufsiz)
{
return 0;
}
int _chdir(const char *path)
{
if (strncmp(path, "ux0:", 4) == 0)
strcpy(cur_dir, path);
else
sprintf(cur_dir, "%s/%s", cur_dir, path);
return 0;
}
int _mkdir(const char *pathname, mode_t mode)
{
char* real = casepath(pathname);
int result = sceIoMkdir(real, mode) < 0 ? -1 : 0;
free(real);
return result;
}
int unlink(const char *pathname)
{
char* real = casepath(pathname);
int result = remove(real);
free(real);
return result;
}
int _caserename(const char *old_filename, const char *new_filename)
{
int result;
char *real_old = casepath(old_filename);
char *real_new = casepath(new_filename);
// hack so we don't even try to rename it to new_filename if it already exists
if (!real_new) {
free(real_old);
return -1;
}
if (!real_old)
result = rename(old_filename, real_new);
else
result = rename(real_old, real_new);
free(real_old);
free(real_new);
return result;
}
HANDLE FindFirstFile(const char* pathname, WIN32_FIND_DATA* firstfile) {
char pathCopy[MAX_PATH];
snprintf(pathCopy, sizeof(pathCopy), PSP2_DATA_PATH "/%s", pathname);
char *folder = strtok(pathCopy, "*");
char *extension = strtok(NULL, "*");
// because strtok doesn't return NULL for last delimiter
if (extension - folder == strlen(pathname))
extension = nil;
// Case-sensitivity and backslashes...
// Will be freed at the bottom
char *realFolder = casepath(folder);
if (realFolder) {
folder = realFolder;
}
strncpy(firstfile->folder, folder, sizeof(firstfile->folder));
if (extension)
strncpy(firstfile->extension, extension, sizeof(firstfile->extension));
else
firstfile->extension[0] = '\0';
if (realFolder)
free(realFolder);
HANDLE d;
if ((d = (HANDLE)opendir(firstfile->folder)) == NULL || !FindNextFile(d, firstfile))
return NULL;
return d;
}
bool FindNextFile(HANDLE d, WIN32_FIND_DATA* finddata) {
dirent *file;
static struct stat fileStats;
static char path[PATH_MAX], relativepath[NAME_MAX + sizeof(finddata->folder) + 1];
int extensionLen = strlen(finddata->extension);
while ((file = readdir((DIR*)d)) != NULL) {
// We only want "DT_REG"ular Files, but reportedly some FS and OSes gives DT_UNKNOWN as type.
if (extensionLen == 0 || strncasecmp(&file->d_name[strlen(file->d_name) - extensionLen], finddata->extension, extensionLen) == 0) {
sprintf(relativepath, "%s/%s", finddata->folder, file->d_name);
_realpath(relativepath, path);
stat(path, &fileStats);
strncpy(finddata->cFileName, file->d_name, sizeof(finddata->cFileName));
finddata->ftLastWriteTime = fileStats.st_mtime;
return true;
}
}
return false;
}
char* casepath(char const* path, bool checkPathFirst)
{
char* out = (char*)malloc(PATH_MAX);
_realpath(path, out);
size_t l = strlen(out);
for (int i = l-1; i >= 0; i--) {
if (out[i] == '\\' || out[i] == '/' || out[i] == ' ')
out[i] = '\0';
else
break;
}
return out;
}
#endif
// Codes compatible with Windows and Linux // Codes compatible with Windows and Linux
#ifndef _WIN32 #ifndef _WIN32
@@ -25,6 +341,9 @@ void GetLocalTime_CP(SYSTEMTIME *out) {
// Compatible with Linux/POSIX and MinGW on Windows // Compatible with Linux/POSIX and MinGW on Windows
#ifndef _WIN32 #ifndef _WIN32
// The Vita has its own pair above: dirent works there, but paths have to go through
// the casepath shim, and there is no cwd to resolve them against.
#ifndef PSP2
HANDLE FindFirstFile(const char* pathname, WIN32_FIND_DATA* firstfile) { HANDLE FindFirstFile(const char* pathname, WIN32_FIND_DATA* firstfile) {
char pathCopy[MAX_PATH]; char pathCopy[MAX_PATH];
strcpy(pathCopy, pathname); strcpy(pathCopy, pathname);
@@ -81,6 +400,7 @@ bool FindNextFile(HANDLE d, WIN32_FIND_DATA* finddata) {
} }
return false; return false;
} }
#endif // !PSP2
void GetDateFormat(int unused1, int unused2, SYSTEMTIME* in, int unused3, char* out, int size) { void GetDateFormat(int unused1, int unused2, SYSTEMTIME* in, int unused3, char* out, int size) {
tm linuxTime; tm linuxTime;
@@ -155,6 +475,9 @@ FILE* _fcaseopen(char const* filename, char const* mode)
return result; return result;
} }
// _fcaseopen above is shared - it only calls casepath. These two are not: the Vita
// supplies its own further up, resolving through sceIo and its faked cwd.
#ifndef PSP2
int _caserename(const char *old_filename, const char *new_filename) int _caserename(const char *old_filename, const char *new_filename)
{ {
int result; int result;
@@ -292,7 +615,8 @@ char* casepath(char const* path, bool checkPathFirst)
} }
return out; return out;
} }
#endif #endif // !PSP2
#endif // !_WIN32
#ifdef __SWITCH__ #ifdef __SWITCH__
/* Taken from glibc */ /* Taken from glibc */
+133
View File
@@ -1,6 +1,137 @@
#ifndef _CROSSPLATFORM_H_
#define _CROSSPLATFORM_H_
#include <time.h> #include <time.h>
#include <limits.h> #include <limits.h>
#ifdef PSP2
#define GLFW_RELEASE 0
#define GLFW_PRESS 1
#define GLFW_KEY_D 68
#define GLFW_KEY_R 82
#define GLFW_MOUSE_BUTTON_1 0
#define GLFW_MOUSE_BUTTON_2 1
#define GLFW_MOUSE_BUTTON_3 2
#define GLFW_MOUSE_BUTTON_4 3
#define GLFW_MOUSE_BUTTON_5 4
#define GLFW_MOUSE_BUTTON_6 5
#define GLFW_MOUSE_BUTTON_7 6
#define GLFW_MOUSE_BUTTON_8 7
#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8
#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1
#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2
#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3
#define GLFW_JOYSTICK_1 0
#define GLFW_JOYSTICK_2 1
#define GLFW_JOYSTICK_3 2
#define GLFW_JOYSTICK_4 3
#define GLFW_JOYSTICK_5 4
#define GLFW_JOYSTICK_6 5
#define GLFW_JOYSTICK_7 6
#define GLFW_JOYSTICK_8 7
#define GLFW_JOYSTICK_9 8
#define GLFW_JOYSTICK_10 9
#define GLFW_JOYSTICK_11 10
#define GLFW_JOYSTICK_12 11
#define GLFW_JOYSTICK_13 12
#define GLFW_JOYSTICK_14 13
#define GLFW_JOYSTICK_15 14
#define GLFW_JOYSTICK_16 15
#define GLFW_JOYSTICK_LAST GLFW_JOYSTICK_16
#define GLFW_GAMEPAD_BUTTON_A 0
#define GLFW_GAMEPAD_BUTTON_B 1
#define GLFW_GAMEPAD_BUTTON_X 2
#define GLFW_GAMEPAD_BUTTON_Y 3
#define GLFW_GAMEPAD_BUTTON_LEFT_BUMPER 4
#define GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER 5
#define GLFW_GAMEPAD_BUTTON_BACK 6
#define GLFW_GAMEPAD_BUTTON_START 7
#define GLFW_GAMEPAD_BUTTON_GUIDE 8
#define GLFW_GAMEPAD_BUTTON_LEFT_THUMB 9
#define GLFW_GAMEPAD_BUTTON_RIGHT_THUMB 10
#define GLFW_GAMEPAD_BUTTON_DPAD_UP 11
#define GLFW_GAMEPAD_BUTTON_DPAD_RIGHT 12
#define GLFW_GAMEPAD_BUTTON_DPAD_DOWN 13
#define GLFW_GAMEPAD_BUTTON_DPAD_LEFT 14
#define GLFW_GAMEPAD_BUTTON_LAST GLFW_GAMEPAD_BUTTON_DPAD_LEFT
#define GLFW_GAMEPAD_BUTTON_CROSS GLFW_GAMEPAD_BUTTON_A
#define GLFW_GAMEPAD_BUTTON_CIRCLE GLFW_GAMEPAD_BUTTON_B
#define GLFW_GAMEPAD_BUTTON_SQUARE GLFW_GAMEPAD_BUTTON_X
#define GLFW_GAMEPAD_BUTTON_TRIANGLE GLFW_GAMEPAD_BUTTON_Y
#define GLFW_GAMEPAD_AXIS_LEFT_X 0
#define GLFW_GAMEPAD_AXIS_LEFT_Y 1
#define GLFW_GAMEPAD_AXIS_RIGHT_X 2
#define GLFW_GAMEPAD_AXIS_RIGHT_Y 3
#define GLFW_GAMEPAD_AXIS_LEFT_TRIGGER 4
#define GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER 5
#define GLFW_GAMEPAD_AXIS_LAST GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
#define GLFW_CURSOR 0x00033001
#define GLFW_CURSOR_HIDDEN 0x00034002
#define GLFW_CURSOR_DISABLED 0x00034003
typedef struct GLFWgamepadstate
{
unsigned char buttons[15];
float axes[6];
} GLFWgamepadstate;
typedef struct GLFWvidmode
{
int width;
int height;
} GLFWvidmode;
typedef void GLFWmonitor;
typedef void GLFWwindow;
GLFWmonitor* glfwGetPrimaryMonitor(void);
int glfwWindowShouldClose(GLFWwindow* window);
const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
int glfwGetKey(GLFWwindow* window, int key);
int glfwGetMouseButton(GLFWwindow* window, int button);
void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);
void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);
int glfwJoystickPresent(int jid);
float* glfwGetJoystickAxes(int jid, int* count);
unsigned char* glfwGetJoystickButtons(int jid, int* count);
int glfwJoystickIsGamepad(int jid);
const char* glfwGetJoystickName(int jid);
int glfwGetGamepadState(int jid, GLFWgamepadstate* state);
void glfwSetInputMode(GLFWwindow* handle, int mode, int value);
#define PATH_MAX 1024
#define NAME_MAX 255
// One place for the data directory. There is no working directory on this platform,
// so everything relative gets resolved against this by _realpath/casepath.
#define PSP2_DATA_PATH "ux0:data/gta3"
int _lstat(const char *path, struct stat *buf);
char *_realpath(const char *path, char *resolved_path);
int _chdir(const char *path);
char *_getcwd(char *buf, size_t size);
int _mkdir(const char *pathname, mode_t mode);
#elif !defined(_WIN32)
// Shared code calls the underscored names so the Vita can resolve paths against
// its data directory (it has no working directory of its own). Everywhere else
// they are the POSIX originals. Windows is left alone - it has a real _mkdir.
#define _lstat lstat
#define _realpath realpath
#define _mkdir mkdir
#define _getcwd getcwd
#define _chdir chdir
#endif
// This is the common include for platform/renderer specific skeletons(glfw.cpp, win.cpp etc.) and using cross platform things (like Windows directories wrapper, platform specific global arrays etc.) // This is the common include for platform/renderer specific skeletons(glfw.cpp, win.cpp etc.) and using cross platform things (like Windows directories wrapper, platform specific global arrays etc.)
// Functions that's different on glfw and win but have same signature, should be located on platform.h. // Functions that's different on glfw and win but have same signature, should be located on platform.h.
@@ -182,3 +313,5 @@ void GetDateFormat(int, int, SYSTEMTIME*, int, char*, int);
#define GLFW_GAMEPAD_BUTTON_Y 2 #define GLFW_GAMEPAD_BUTTON_Y 2
#endif #endif
#endif
+294 -5
View File
@@ -1,11 +1,12 @@
// Nintendo Switch / GLFW movie player. Ported from the SDL2 build; only the // Nintendo Switch / GLFW movie player. Ported from the SDL2 build; only the
// windowing-system glue differs (GLFW proc address / buffer swap / timer). // windowing-system glue differs (GLFW proc address / buffer swap / timer).
// //
// Switch-only on purpose: Windows D3D9 builds play the intro through the win.cpp // The PS Vita gets its own backend further down, built on SceAvPlayer, behind the
// skeleton (DirectShow), and the other GLFW targets never played it at all - the // same interface. Windows D3D9 builds play the intro through the win.cpp skeleton
// MPEG states there have always just fallen through. Everyone else gets the stub // (DirectShow), and the remaining GLFW targets never played it at all - the MPEG
// at the bottom of this file, which keeps glfw.cpp's intro state machine linkable // states there have always just fallen through. Those get the stub at the bottom of
// without dragging pl_mpeg and OpenAL into those builds. // this file, which keeps glfw.cpp's intro state machine linkable without dragging
// pl_mpeg and OpenAL into their builds.
#if defined __SWITCH__ && defined RW_GL3 && !defined LIBRW_SDL2 && defined AUDIO_OAL #if defined __SWITCH__ && defined RW_GL3 && !defined LIBRW_SDL2 && defined AUDIO_OAL
#include "common.h" #include "common.h"
@@ -659,6 +660,294 @@ void MoviePlayer::Draw()
} }
} }
#elif defined PSP2
// PS Vita backend. Same interface, different everything else: decoding is done by
// SceAvPlayer rather than pl_mpeg, the frames arrive as GXM textures that are wrapped
// into GL ones, and audio is pumped by a dedicated thread instead of OpenAL.
// Lifted out of glfw.cpp, where it used to sit inline alongside the intro state machine.
#include "common.h"
#include <malloc.h> // memalign, for the SceAvPlayer allocator callbacks
#include <vitasdk.h>
#include <vitaGL.h>
#include "crossplatform.h"
#include "MoviePlayer.h"
#define FB_ALIGNMENT 0x40000
#define ALIGN_MEM(x, align) (((x) + ((align) - 1)) & ~((align) - 1))
SceAvPlayerHandle movie_player;
GLuint movie_frame[2];
uint8_t movie_frame_idx = 0;
SceGxmTexture *movie_tex[2];
GLuint movie_fs;
GLuint movie_vs;
GLuint movie_prog;
SceUID audio_thid;
int audio_new;
int audio_port;
int audio_len;
int audio_freq;
int audio_mode;
enum {
PLAYER_INACTIVE,
PLAYER_ACTIVE,
PLAYER_STOP,
};
int player_state = PLAYER_INACTIVE;
float movie_pos[8] = {
-1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, 1.0f,
1.0f, -1.0f
};
float movie_texcoord[8] = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f
};
void *mem_alloc(void *p, uint32_t align, uint32_t size) {
return memalign(align, size);
}
void mem_free(void *p, void *ptr) {
free(ptr);
}
void *gpu_alloc(void *p, uint32_t align, uint32_t size) {
if (align < FB_ALIGNMENT) {
align = FB_ALIGNMENT;
}
size = ALIGN_MEM(size, align);
return vglAlloc(size, VGL_MEM_SLOW);
}
void gpu_free(void *p, void *ptr) {
glFinish();
vglFree(ptr);
}
void movie_player_audio_init(void) {
audio_port = -1;
for (int i = 0; i < 8; i++) {
if (sceAudioOutGetConfig(i, SCE_AUDIO_OUT_CONFIG_TYPE_LEN) >= 0) {
audio_port = i;
break;
}
}
if (audio_port == -1) {
audio_port = sceAudioOutOpenPort(SCE_AUDIO_OUT_PORT_TYPE_MAIN, 1024, 48000, SCE_AUDIO_OUT_MODE_STEREO);
audio_new = 1;
} else {
audio_len = sceAudioOutGetConfig(audio_port, SCE_AUDIO_OUT_CONFIG_TYPE_LEN);
audio_freq = sceAudioOutGetConfig(audio_port, SCE_AUDIO_OUT_CONFIG_TYPE_FREQ);
audio_mode = sceAudioOutGetConfig(audio_port, SCE_AUDIO_OUT_CONFIG_TYPE_MODE);
audio_new = 0;
}
}
void movie_player_audio_shutdown(void) {
if (audio_new) {
sceAudioOutReleasePort(audio_port);
} else {
sceAudioOutSetConfig(audio_port, audio_len, audio_freq, (SceAudioOutMode)audio_mode);
}
}
int movie_player_audio_thread(SceSize args, void *argp) {
SceAvPlayerFrameInfo frame;
memset(&frame, 0, sizeof(SceAvPlayerFrameInfo));
while (player_state == PLAYER_ACTIVE && sceAvPlayerIsActive(movie_player)) {
if (sceAvPlayerGetAudioData(movie_player, &frame)) {
sceAudioOutSetConfig(audio_port, 1024, frame.details.audio.sampleRate, frame.details.audio.channelCount == 1 ? SCE_AUDIO_OUT_MODE_MONO : SCE_AUDIO_OUT_MODE_STEREO);
sceAudioOutOutput(audio_port, frame.pData);
} else {
sceKernelDelayThread(1000);
}
}
return sceKernelExitDeleteThread(0);
}
void movie_player_draw(void) {
if (player_state == PLAYER_ACTIVE) {
if (sceAvPlayerIsActive(movie_player)) {
SceAvPlayerFrameInfo frame;
if (sceAvPlayerGetVideoData(movie_player, &frame)) {
movie_frame_idx = (movie_frame_idx + 1) % 2;
sceGxmTextureInitLinear(
movie_tex[movie_frame_idx],
frame.pData,
SCE_GXM_TEXTURE_FORMAT_YVU420P2_CSC1,
frame.details.video.width,
frame.details.video.height, 0);
sceGxmTextureSetMinFilter(movie_tex[movie_frame_idx], SCE_GXM_TEXTURE_FILTER_LINEAR);
sceGxmTextureSetMagFilter(movie_tex[movie_frame_idx], SCE_GXM_TEXTURE_FILTER_LINEAR);
glUseProgram(movie_prog);
glBindTexture(GL_TEXTURE_2D, movie_frame[movie_frame_idx]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, &movie_pos[0]);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, &movie_texcoord[0]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
vglSwapBuffers(GL_FALSE);
}
} else {
player_state = PLAYER_STOP;
}
}
if (player_state == PLAYER_STOP) {
sceAvPlayerStop(movie_player);
sceKernelWaitThreadEnd(audio_thid, NULL, NULL);
sceAvPlayerClose(movie_player);
movie_player_audio_shutdown();
player_state = PLAYER_INACTIVE;
glClear(GL_COLOR_BUFFER_BIT);
vglSwapBuffers(GL_FALSE);
}
}
int movie_player_inited = 0;
void movie_player_init() {
if (movie_player_inited)
return;
sceSysmoduleLoadModule(SCE_SYSMODULE_AVPLAYER);
glGenTextures(2, movie_frame);
for (int i = 0; i < 2; i++) {
glBindTexture(GL_TEXTURE_2D, movie_frame[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 960, 544, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
movie_tex[i] = vglGetGxmTexture(GL_TEXTURE_2D);
vglFree(vglGetTexDataPointer(GL_TEXTURE_2D));
}
// The precompiled GXP blobs in shaders/movie_[vf].h can no longer be fed to
// glShaderBinary: it now expects a vitaGL-serialized blob, so unserialize_shader
// reads the "GXP\0" magic as a uniform count and walks off into garbage.
// Compile the original Cg source (kept as a comment in those headers) instead.
static const char *movie_v_src =
"void main(\n"
" float2 inPos,\n"
" float2 inTex,\n"
" float4 out pos : POSITION,\n"
" float2 out texcoord : TEXCOORD0\n"
") {\n"
" texcoord = inTex;\n"
" pos = float4(inPos, 1.f, 1.f);\n"
"}\n";
static const char *movie_f_src =
"float4 main(\n"
" float2 texcoord : TEXCOORD0,\n"
" uniform sampler2D tex\n"
") {\n"
" return tex2D(tex, texcoord);\n"
"}\n";
movie_vs = glCreateShader(GL_CG_VERTEX_SHADER_EXT);
glShaderSource(movie_vs, 1, &movie_v_src, NULL);
glCompileShader(movie_vs);
movie_fs = glCreateShader(GL_CG_FRAGMENT_SHADER_EXT);
glShaderSource(movie_fs, 1, &movie_f_src, NULL);
glCompileShader(movie_fs);
movie_prog = glCreateProgram();
glAttachShader(movie_prog, movie_vs);
glAttachShader(movie_prog, movie_fs);
glBindAttribLocation(movie_prog, 0, "inPos");
glBindAttribLocation(movie_prog, 1, "inTex");
glLinkProgram(movie_prog);
movie_player_inited = 1;
}
void movie_player_play(const char *file) {
SceIoStat st;
if (sceIoGetstat(file, &st) < 0)
return;
movie_player_init();
movie_player_audio_init();
SceAvPlayerInitData playerInit;
sceClibMemset(&playerInit, 0, sizeof(SceAvPlayerInitData));
playerInit.memoryReplacement.allocate = mem_alloc;
playerInit.memoryReplacement.deallocate = mem_free;
playerInit.memoryReplacement.allocateTexture = gpu_alloc;
playerInit.memoryReplacement.deallocateTexture = gpu_free;
playerInit.basePriority = 0xA0;
playerInit.numOutputVideoFrameBuffers = 2;
playerInit.autoStart = GL_TRUE;
movie_player = sceAvPlayerInit(&playerInit);
sceAvPlayerAddSource(movie_player, file);
audio_thid = sceKernelCreateThread("movie_audio_thread", movie_player_audio_thread, 0x10000100 - 10, 0x4000, 0, 0, NULL);
sceKernelStartThread(audio_thid, 0, NULL);
player_state = PLAYER_ACTIVE;
}
namespace MoviePlayer
{
void Play(const char *path)
{
// The shared intro code asks for pl_mpeg's .mpg by a path relative to the
// data directory; SceAvPlayer wants .mp4 and an absolute one.
char rel[256];
strncpy(rel, path, sizeof(rel) - 1);
rel[sizeof(rel) - 1] = '\0';
char *ext = strrchr(rel, '.');
if (ext != nil)
strcpy(ext, ".mp4");
char full[PATH_MAX];
_realpath(rel, full);
// This build has always shipped one set of intro videos, so the localised
// title reel the shared code asks for on French and German is not there.
// Fall back to the plain one rather than silently dropping the intro.
SceIoStat st;
if (sceIoGetstat(full, &st) < 0) {
char *ger = strstr(rel, "GER.mp4");
if (ger != nil) {
strcpy(ger, ".mp4");
_realpath(rel, full);
}
}
movie_player_play(full);
}
void Draw() { movie_player_draw(); }
bool IsActive() { return player_state != PLAYER_INACTIVE; }
void Stop()
{
if (player_state == PLAYER_ACTIVE)
player_state = PLAYER_STOP; // movie_player_draw does the teardown
}
}
#else // !(RW_GL3 && !LIBRW_SDL2) #else // !(RW_GL3 && !LIBRW_SDL2)
#include "MoviePlayer.h" #include "MoviePlayer.h"
+87 -9
View File
@@ -14,7 +14,9 @@ DWORD _dwOperatingSystemVersion;
long _dwOperatingSystemVersion; long _dwOperatingSystemVersion;
#ifndef __SWITCH__ #ifndef __SWITCH__
#ifndef __APPLE__ #ifndef __APPLE__
#if !defined(PSP2)
#include <sys/sysinfo.h> #include <sys/sysinfo.h>
#endif
#else #else
#include <mach/mach_host.h> #include <mach/mach_host.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
@@ -68,6 +70,18 @@ long _dwOperatingSystemVersion;
#define MAX_SUBSYSTEMS (16) #define MAX_SUBSYSTEMS (16)
#ifdef PSP2
#include <malloc.h>
#include <vitasdk.h>
#include <vitaGL.h>
#include "../message.h"
int _newlib_heap_size_user = 256 * 1024 * 1024;
#define DATA_PATH PSP2_DATA_PATH
#define RT_INI_PATH DATA_PATH "/" "10thae.ini"
#endif
rw::EngineOpenParams openParams; rw::EngineOpenParams openParams;
static RwBool ForegroundApp = TRUE; static RwBool ForegroundApp = TRUE;
@@ -122,11 +136,13 @@ void _psCreateFolder(const char *path)
#else #else
struct stat info; struct stat info;
char fullpath[PATH_MAX]; char fullpath[PATH_MAX];
realpath(path, fullpath); // Underscored names: the Vita resolves these against its data directory, every
// other platform aliases them to the POSIX originals in crossplatform.h.
_realpath(path, fullpath);
if (lstat(fullpath, &info) != 0) { if (_lstat(fullpath, &info) != 0) {
if (errno == ENOENT || (errno != EACCES && !S_ISDIR(info.st_mode))) { if (errno == ENOENT || (errno != EACCES && !S_ISDIR(info.st_mode))) {
mkdir(fullpath, 0755); _mkdir(fullpath, 0755);
} }
} }
#endif #endif
@@ -560,7 +576,7 @@ psInitialize(void)
#elif defined (__SWITCH__) #elif defined (__SWITCH__)
svcGetInfo(&_dwMemAvailPhys, InfoType_UsedMemorySize, CUR_PROCESS_HANDLE, 0); svcGetInfo(&_dwMemAvailPhys, InfoType_UsedMemorySize, CUR_PROCESS_HANDLE, 0);
debug("Physical memory size %llu\n", _dwMemAvailPhys); debug("Physical memory size %llu\n", _dwMemAvailPhys);
#else #elif !defined(PSP2)
struct sysinfo systemInfo; struct sysinfo systemInfo;
sysinfo(&systemInfo); sysinfo(&systemInfo);
_dwMemAvailPhys = systemInfo.freeram; _dwMemAvailPhys = systemInfo.freeram;
@@ -929,6 +945,9 @@ psSelectDevice()
return TRUE; return TRUE;
} }
// None of these exist on the Vita: there is no window and no real GLFW, only the
// input stubs in crossplatform.cpp.
#if !defined(PSP2)
#ifndef GET_KEYBOARD_INPUT_FROM_X11 #ifndef GET_KEYBOARD_INPUT_FROM_X11
void keypressCB(GLFWwindow* window, int key, int scancode, int action, int mods); void keypressCB(GLFWwindow* window, int key, int scancode, int action, int mods);
#endif #endif
@@ -939,6 +958,7 @@ void cursorEnterCB(GLFWwindow* window, int entered);
void windowFocusCB(GLFWwindow* window, int focused); void windowFocusCB(GLFWwindow* window, int focused);
void windowIconifyCB(GLFWwindow* window, int iconified); void windowIconifyCB(GLFWwindow* window, int iconified);
void joysChangeCB(int jid, int event); void joysChangeCB(int jid, int event);
#endif
bool IsThisJoystickBlacklisted(int i) bool IsThisJoystickBlacklisted(int i)
{ {
@@ -963,6 +983,8 @@ void _InputInitialiseJoys()
PSGLOBAL(joy1id) = -1; PSGLOBAL(joy1id) = -1;
PSGLOBAL(joy2id) = -1; PSGLOBAL(joy2id) = -1;
// The Vita reads its pad through SceCtrl, so there is nothing to remap.
#if !defined(PSP2)
// Load our gamepad mappings. // Load our gamepad mappings.
#define SDL_GAMEPAD_DB_PATH "gamecontrollerdb.txt" #define SDL_GAMEPAD_DB_PATH "gamecontrollerdb.txt"
FILE *f = fopen(SDL_GAMEPAD_DB_PATH, "rb"); FILE *f = fopen(SDL_GAMEPAD_DB_PATH, "rb");
@@ -992,6 +1014,7 @@ void _InputInitialiseJoys()
if (EnvControlConfig != nil) { if (EnvControlConfig != nil) {
glfwUpdateGamepadMappings(EnvControlConfig); glfwUpdateGamepadMappings(EnvControlConfig);
} }
#endif // !PSP2
for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) { for (int i = 0; i <= GLFW_JOYSTICK_LAST; i++) {
if (glfwJoystickPresent(i) && !IsThisJoystickBlacklisted(i)) { if (glfwJoystickPresent(i) && !IsThisJoystickBlacklisted(i)) {
@@ -1004,6 +1027,9 @@ void _InputInitialiseJoys()
} }
} }
#ifdef PSP2
ControlsManager.InitDefaultControlConfigJoyPad(16);
#else
if (PSGLOBAL(joy1id) != -1) { if (PSGLOBAL(joy1id) != -1) {
int count; int count;
glfwGetJoystickButtons(PSGLOBAL(joy1id), &count); glfwGetJoystickButtons(PSGLOBAL(joy1id), &count);
@@ -1012,11 +1038,14 @@ void _InputInitialiseJoys()
#endif #endif
ControlsManager.InitDefaultControlConfigJoyPad(count); ControlsManager.InitDefaultControlConfigJoyPad(count);
} }
#endif
} }
long _InputInitialiseMouse() long _InputInitialiseMouse()
{ {
#if !defined(PSP2)
glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, GLFW_CURSOR_HIDDEN); glfwSetInputMode(PSGLOBAL(window), GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
#endif
return 0; return 0;
} }
@@ -1025,6 +1054,8 @@ void psPostRWinit(void)
RwVideoMode vm; RwVideoMode vm;
RwEngineGetVideoModeInfo(&vm, GcurSelVM); RwEngineGetVideoModeInfo(&vm, GcurSelVM);
// There is no window to hang callbacks on under PSP2, and the resolution is fixed.
#if !defined(PSP2)
glfwSetFramebufferSizeCallback(PSGLOBAL(window), resizeCB); glfwSetFramebufferSizeCallback(PSGLOBAL(window), resizeCB);
#ifndef IGNORE_MOUSE_KEYBOARD #ifndef IGNORE_MOUSE_KEYBOARD
#ifndef GET_KEYBOARD_INPUT_FROM_X11 #ifndef GET_KEYBOARD_INPUT_FROM_X11
@@ -1037,12 +1068,15 @@ void psPostRWinit(void)
glfwSetWindowIconifyCallback(PSGLOBAL(window), windowIconifyCB); glfwSetWindowIconifyCallback(PSGLOBAL(window), windowIconifyCB);
glfwSetWindowFocusCallback(PSGLOBAL(window), windowFocusCB); glfwSetWindowFocusCallback(PSGLOBAL(window), windowFocusCB);
glfwSetJoystickCallback(joysChangeCB); glfwSetJoystickCallback(joysChangeCB);
#endif
_InputInitialiseJoys(); _InputInitialiseJoys();
_InputInitialiseMouse(); _InputInitialiseMouse();
#if !defined(PSP2)
if(!(vm.flags & rwVIDEOMODEEXCLUSIVE)) if(!(vm.flags & rwVIDEOMODEEXCLUSIVE))
glfwSetWindowSize(PSGLOBAL(window), RsGlobal.maximumWidth, RsGlobal.maximumHeight); glfwSetWindowSize(PSGLOBAL(window), RsGlobal.maximumWidth, RsGlobal.maximumHeight);
#endif
// Make sure all keys are released // Make sure all keys are released
CPad::GetPad(0)->Clear(true); CPad::GetPad(0)->Clear(true);
@@ -1341,7 +1375,7 @@ void HandleExit()
#endif #endif
} }
#ifndef _WIN32 #if !defined(_WIN32) && !defined(PSP2)
void terminateHandler(int sig, siginfo_t *info, void *ucontext) { void terminateHandler(int sig, siginfo_t *info, void *ucontext) {
RsGlobal.quit = TRUE; RsGlobal.quit = TRUE;
} }
@@ -1353,6 +1387,9 @@ void dummyHandler(int sig){
#endif #endif
#endif #endif
// Everything from here to the end of checkKeyPresses is GLFW window and keyboard
// plumbing that the Vita has no counterpart for.
#if !defined(PSP2)
void resizeCB(GLFWwindow* window, int width, int height) { void resizeCB(GLFWwindow* window, int width, int height) {
/* /*
* Handle event to ensure window contents are displayed during re-size * Handle event to ensure window contents are displayed during re-size
@@ -1797,14 +1834,18 @@ void checkKeyPresses()
} }
#endif #endif
#endif // !PSP2
// R* calls that in ControllerConfig, idk why // R* calls that in ControllerConfig, idk why
void void
_InputTranslateShiftKeyUpDown(RsKeyCodes *rs) { _InputTranslateShiftKeyUpDown(RsKeyCodes *rs) {
#if !defined(PSP2)
RsKeyboardEventHandler(lshiftStatus ? rsKEYDOWN : rsKEYUP, &(*rs = rsLSHIFT)); RsKeyboardEventHandler(lshiftStatus ? rsKEYDOWN : rsKEYUP, &(*rs = rsLSHIFT));
RsKeyboardEventHandler(rshiftStatus ? rsKEYDOWN : rsKEYUP, &(*rs = rsRSHIFT)); RsKeyboardEventHandler(rshiftStatus ? rsKEYDOWN : rsKEYUP, &(*rs = rsRSHIFT));
#endif
} }
#if !defined(PSP2)
// TODO this only works in frontend(and luckily only frontend use this). Fun fact: if I get pos manually in game, glfw reports that it's > 32000 // TODO this only works in frontend(and luckily only frontend use this). Fun fact: if I get pos manually in game, glfw reports that it's > 32000
void void
cursorCB(GLFWwindow* window, double xpos, double ypos) { cursorCB(GLFWwindow* window, double xpos, double ypos) {
@@ -1821,7 +1862,9 @@ void
cursorEnterCB(GLFWwindow* window, int entered) { cursorEnterCB(GLFWwindow* window, int entered) {
PSGLOBAL(cursorIsInWindow) = !!entered; PSGLOBAL(cursorIsInWindow) = !!entered;
} }
#endif // !PSP2
#if !defined(PSP2)
void void
windowFocusCB(GLFWwindow* window, int focused) { windowFocusCB(GLFWwindow* window, int focused) {
WindowFocused = !!focused; WindowFocused = !!focused;
@@ -1831,6 +1874,7 @@ void
windowIconifyCB(GLFWwindow* window, int iconified) { windowIconifyCB(GLFWwindow* window, int iconified) {
WindowIconified = !!iconified; WindowIconified = !!iconified;
} }
#endif // !PSP2
/* /*
***************************************************************************** *****************************************************************************
@@ -1869,9 +1913,35 @@ WinMain(HINSTANCE instance,
#endif #endif
#else #else
#ifdef PSP2
SceTouchPanelInfo panelInfo[2];
#endif
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
#ifdef PSP2
sceCtrlSetSamplingModeExt(SCE_CTRL_MODE_ANALOG_WIDE);
sceTouchSetSamplingState(SCE_TOUCH_PORT_FRONT, SCE_TOUCH_SAMPLING_STATE_START);
sceTouchSetSamplingState(SCE_TOUCH_PORT_BACK, SCE_TOUCH_SAMPLING_STATE_START);
// The stock clocks are not enough for this; the port has always overclocked.
scePowerSetArmClockFrequency(444);
scePowerSetBusClockFrequency(222);
scePowerSetGpuClockFrequency(222);
scePowerSetGpuXbarClockFrequency(166);
sceTouchGetPanelInfo(SCE_TOUCH_PORT_FRONT, &panelInfo[0]);
sceTouchGetPanelInfo(SCE_TOUCH_PORT_BACK, &panelInfo[1]);
// Marker file: bail out with a readable message instead of crashing later if the
// game data was never copied over.
if (!fileExists(RT_INI_PATH))
{
showMsgDialog("Liberty's gone quiet.\nNo game files found at " DATA_PATH);
sceKernelExitProcess(1);
}
#ifndef ENABLE_STDOUT
fclose(stdout);
#endif
#endif
#endif #endif
RwV2d pos; RwV2d pos;
RwInt32 i; RwInt32 i;
@@ -1880,7 +1950,7 @@ main(int argc, char *argv[])
InitMemoryMgr(); InitMemoryMgr();
#endif #endif
#if !defined(_WIN32) && !defined(__SWITCH__) #if !defined(_WIN32) && !defined(__SWITCH__) && !defined(PSP2)
struct sigaction act; struct sigaction act;
act.sa_sigaction = terminateHandler; act.sa_sigaction = terminateHandler;
act.sa_flags = SA_SIGINFO; act.sa_flags = SA_SIGINFO;
@@ -1933,7 +2003,9 @@ main(int argc, char *argv[])
openParams.width = RsGlobal.maximumWidth; openParams.width = RsGlobal.maximumWidth;
openParams.height = RsGlobal.maximumHeight; openParams.height = RsGlobal.maximumHeight;
openParams.windowtitle = RsGlobal.appName; openParams.windowtitle = RsGlobal.appName;
#if !defined(PSP2)
openParams.window = &PSGLOBAL(window); openParams.window = &PSGLOBAL(window);
#endif
ControlsManager.MakeControllerActionsBlank(); ControlsManager.MakeControllerActionsBlank();
ControlsManager.InitDefaultControlConfiguration(); ControlsManager.InitDefaultControlConfiguration();
@@ -2053,7 +2125,9 @@ main(int argc, char *argv[])
} }
#endif #endif
#if !defined(PSP2)
initkeymap(); initkeymap();
#endif
while ( TRUE ) while ( TRUE )
{ {
@@ -2096,7 +2170,9 @@ main(int argc, char *argv[])
while( !RsGlobal.quit && !FrontEndMenuManager.m_bWantToRestart && !glfwWindowShouldClose(PSGLOBAL(window))) while( !RsGlobal.quit && !FrontEndMenuManager.m_bWantToRestart && !glfwWindowShouldClose(PSGLOBAL(window)))
#endif #endif
{ {
#if !defined(PSP2)
glfwPollEvents(); glfwPollEvents();
#endif
#ifdef GET_KEYBOARD_INPUT_FROM_X11 #ifdef GET_KEYBOARD_INPUT_FROM_X11
checkKeyPresses(); checkKeyPresses();
#endif #endif
@@ -2174,7 +2250,7 @@ main(int argc, char *argv[])
case GS_INIT_ONCE: case GS_INIT_ONCE:
{ {
//CoUninitialize(); //CoUninitialize();
#ifdef PS2_MENU #ifdef PS2_MENU
extern char version_name[64]; extern char version_name[64];
if ( CGame::frenchGame || CGame::germanGame ) if ( CGame::frenchGame || CGame::germanGame )
@@ -2188,7 +2264,7 @@ main(int argc, char *argv[])
#endif #endif
if ( !CGame::InitialiseOnceAfterRW() ) if ( !CGame::InitialiseOnceAfterRW() )
RsGlobal.quit = TRUE; RsGlobal.quit = TRUE;
#ifdef PS2_MENU #ifdef PS2_MENU
gGameState = GS_INIT_PLAYING_GAME; gGameState = GS_INIT_PLAYING_GAME;
#else #else
@@ -2202,7 +2278,7 @@ main(int argc, char *argv[])
case GS_INIT_FRONTEND: case GS_INIT_FRONTEND:
{ {
LoadingScreen(nil, nil, "loadsc0"); LoadingScreen(nil, nil, "loadsc0");
FrontEndMenuManager.m_bGameNotLoaded = true; FrontEndMenuManager.m_bGameNotLoaded = true;
CMenuManager::m_bStartUpFrontEndRequested = true; CMenuManager::m_bStartUpFrontEndRequested = true;
@@ -2534,6 +2610,7 @@ void CapturePad(RwInt32 padID)
return; return;
} }
#if !defined(PSP2)
void joysChangeCB(int jid, int event) void joysChangeCB(int jid, int event)
{ {
if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) { if (event == GLFW_CONNECTED && !IsThisJoystickBlacklisted(jid)) {
@@ -2558,6 +2635,7 @@ void joysChangeCB(int jid, int event)
PSGLOBAL(joy2id) = -1; PSGLOBAL(joy2id) = -1;
} }
} }
#endif // !PSP2
#if (defined(_MSC_VER)) #if (defined(_MSC_VER))
int strcasecmp(const char* str1, const char* str2) int strcasecmp(const char* str1, const char* str2)
+119
View File
@@ -0,0 +1,119 @@
#include <cstdlib>
#include <psp2/display.h>
#include <psp2/message_dialog.h>
#include <psp2/io/stat.h>
#include <psp2/kernel/clib.h>
#include "message.h"
GxmDrawer::GxmDrawer() {
constexpr SceGxmInitializeParams params{
0, DISPLAY_MAX_PENDING_SWAPS, gxmVsyncCb, sizeof(void *),
SCE_GXM_DEFAULT_PARAMETER_BUFFER_SIZE};
sceGxmInitialize(&params);
for (auto &buf: displayBuf_) {
buf.data = dramAlloc(4 * DISPLAY_STRIDE_IN_PIXELS * DISPLAY_HEIGHT,
&buf.uid);
sceGxmColorSurfaceInit(&buf.surf, SCE_GXM_COLOR_FORMAT_A8B8G8R8,
SCE_GXM_COLOR_SURFACE_LINEAR,
SCE_GXM_COLOR_SURFACE_SCALE_NONE,
SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT,
DISPLAY_WIDTH, DISPLAY_HEIGHT,
DISPLAY_STRIDE_IN_PIXELS, buf.data);
sceGxmSyncObjectCreate(&buf.sync);
}
}
GxmDrawer::~GxmDrawer() {
sceGxmTerminate();
for (const auto &buf: displayBuf_) {
sceGxmSyncObjectDestroy(buf.sync);
sceKernelFreeMemBlock(buf.uid);
}
}
void GxmDrawer::gxmSwap() {
sceGxmPadHeartbeat(&displayBuf_[backBufferIndex_].surf,
displayBuf_[backBufferIndex_].sync);
sceGxmDisplayQueueAddEntry(displayBuf_[frontBufferIndex_].sync,
displayBuf_[backBufferIndex_].sync,
&displayBuf_[backBufferIndex_].data);
frontBufferIndex_ = backBufferIndex_;
backBufferIndex_ = (backBufferIndex_ + 1) % DISPLAY_BUFFER_COUNT;
}
void GxmDrawer::clearScreenBuffer() const {
sceClibMemset(displayBuf_[backBufferIndex_].data,
static_cast<int>(0xFF000000),
DISPLAY_HEIGHT * DISPLAY_STRIDE_IN_PIXELS * 4);
}
void GxmDrawer::updateSceDialog() const {
const SceCommonDialogUpdateParam updateParam{
{nullptr, displayBuf_[backBufferIndex_].data,
static_cast<SceGxmColorSurfaceType>(0),
static_cast<SceGxmColorFormat>(0), DISPLAY_WIDTH,
DISPLAY_HEIGHT, DISPLAY_STRIDE_IN_PIXELS},
displayBuf_[backBufferIndex_].sync};
sceCommonDialogUpdate(&updateParam);
}
void *GxmDrawer::dramAlloc(const std::uint32_t size, SceUID *uid) {
void *mem;
*uid = sceKernelAllocMemBlock("gpu_mem",
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
ALIGN(size, 256 * 1024), nullptr);
sceKernelGetMemBlockBase(*uid, &mem);
sceGxmMapMemory(mem, ALIGN(size, 256 * 1024),
static_cast<SceGxmMemoryAttribFlags>(
SCE_GXM_MEMORY_ATTRIB_READ |
SCE_GXM_MEMORY_ATTRIB_WRITE));
return mem;
}
void GxmDrawer::gxmVsyncCb(const void *callbackData) {
const SceDisplayFrameBuf fb{
sizeof(SceDisplayFrameBuf),
*static_cast<void **>(const_cast<void *>(callbackData)),
DISPLAY_STRIDE_IN_PIXELS,
0,
DISPLAY_WIDTH,
DISPLAY_HEIGHT};
sceDisplaySetFrameBuf(&fb, SCE_DISPLAY_SETBUF_NEXTFRAME);
}
void showMsgDialog(const char *message) {
GxmDrawer gxmDrawer;
SceMsgDialogUserMessageParam msgParam;
sceClibMemset(&msgParam, 0, sizeof(SceMsgDialogUserMessageParam));
msgParam.buttonType = SCE_MSG_DIALOG_BUTTON_TYPE_OK;
msgParam.msg = reinterpret_cast<const SceChar8 *>(message);
SceMsgDialogParam param;
sceMsgDialogParamInit(&param);
param.mode = SCE_MSG_DIALOG_MODE_USER_MSG;
param.userMsgParam = &msgParam;
constexpr SceCommonDialogConfigParam confParam{};
sceCommonDialogSetConfigParam(&confParam);
sceMsgDialogInit(&param);
while (sceMsgDialogGetStatus() != SCE_COMMON_DIALOG_STATUS_FINISHED) {
gxmDrawer.clearScreenBuffer();
gxmDrawer.updateSceDialog();
gxmDrawer.gxmSwap();
sceDisplayWaitVblankStart();
}
sceMsgDialogTerm();
}
int fileExists(const char *path) {
SceIoStat stat;
return sceIoGetstat(path, &stat) >= 0;
}
+47
View File
@@ -0,0 +1,47 @@
#ifndef MESSAGE_H
#define MESSAGE_H
#include <array>
#include <cstdint>
#include <psp2/gxm.h>
#include <psp2/kernel/sysmem.h>
#ifndef ALIGN
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
#endif // ALIGN
struct DisplayBuffer {
void *data;
SceGxmSyncObject *sync;
SceGxmColorSurface surf;
SceUID uid;
}; // struct DisplayBuffer
class GxmDrawer {
public:
GxmDrawer();
~GxmDrawer();
void gxmSwap();
void clearScreenBuffer() const;
void updateSceDialog() const;
static void *dramAlloc(std::uint32_t size, SceUID *uid);
static void gxmVsyncCb(const void *callbackData);
private:
static constexpr int DISPLAY_WIDTH{960};
static constexpr int DISPLAY_HEIGHT{544};
static constexpr int DISPLAY_STRIDE_IN_PIXELS{1024};
static constexpr int DISPLAY_BUFFER_COUNT{2};
static constexpr int DISPLAY_MAX_PENDING_SWAPS{1};
std::uint32_t backBufferIndex_{}, frontBufferIndex_{};
std::array<DisplayBuffer, DISPLAY_BUFFER_COUNT> displayBuf_{};
}; // class GxmDrawer
void showMsgDialog(const char *message);
int fileExists(const char *path);
#endif //MESSAGE_H