diff --git a/cmake/VitaPackage.cmake b/cmake/VitaPackage.cmake
new file mode 100644
index 00000000..42409f08
--- /dev/null
+++ b/cmake/VitaPackage.cmake
@@ -0,0 +1,85 @@
+include (CMakeParseArguments)
+include("${VITASDK}/share/vita.cmake" REQUIRED)
+set(GenerateVPKCurrentDir ${CMAKE_CURRENT_LIST_DIR})
+
+function(generate_vita_package target)
+ set (options)
+ set (oneValueArgs
+ APP_NAME
+ TITLE_ID
+ ICON
+ TEMPLATE
+ LOAD_IMAGE
+ BACKGROUND
+ VERSION
+ )
+ set (multiValueArgs)
+ cmake_parse_arguments(VITA "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ get_target_property(VITA_EXECUTABLE ${target} OUTPUT_NAME)
+
+ set(VITA_MKSFOEX_FLAGS "${VITA_MKSFOEX_FLAGS} -d ATTRIBUTE2=12")
+ vita_create_self(${VITA_EXECUTABLE}.self ${CMAKE_BINARY_DIR}/${VITA_EXECUTABLE})
+
+ if(NOT VITA_APP_NAME OR "${VITA_APP_NAME}" STREQUAL "")
+ set(VITA_APP_NAME "VitaApp")
+ endif()
+
+ if(NOT VITA_TITLE_ID OR "${VITA_TITLE_ID}" STREQUAL "")
+ set(VITA_TITLE_ID "UNKN00000")
+ endif()
+
+ if(NOT VITA_VERSION OR "${VITA_VERSION}" STREQUAL "")
+ set(VITA_VERSION "01.00")
+ endif()
+
+ if(NOT VITA_TEMPLATE OR "${VITA_TEMPLATE}" STREQUAL "")
+ set(VITA_TEMPLATE ${GenerateVPKCurrentDir}/template.xml)
+ list(APPEND VPK_FILE_LIST FILE ${VITA_TEMPLATE} sce_sys/livearea/contents/template.xml)
+ endif()
+
+ if(VITA_ICON)
+ find_package(ImageMagick COMPONENTS convert)
+
+ if(NOT ImageMagick_convert_FOUND)
+ message(WARNING "ImageMagick was not found, icons will not be generated.")
+ endif()
+
+ add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/${VITA_EXECUTABLE}_icon0.png"
+ COMMAND ${ImageMagick_convert_EXECUTABLE} -background none -density 72 -resize 128x128 -units "PixelsPerInch" -type Palette -colors 255 ${VITA_ICON} "${CMAKE_BINARY_DIR}/${VITA_EXECUTABLE}_icon0.png"
+ MAIN_DEPENDENCY ${VITA_ICON}
+ COMMENT "Vita Bubble Icon Generation: ${VITA_EXECUTABLE}_icon0.png"
+ )
+
+ add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/${VITA_EXECUTABLE}_startup.png"
+ COMMAND ${ImageMagick_convert_EXECUTABLE} -background none -density 72 -resize 158x158 -gravity center -extent 280x158 -type Palette -units "PixelsPerInch" -colors 255 ${VITA_ICON} "${CMAKE_BINARY_DIR}/${VITA_EXECUTABLE}_startup.png"
+ MAIN_DEPENDENCY ${VITA_ICON}
+ COMMENT "Vita Startup Icon Generation: ${VITA_EXECUTABLE}_startup.png"
+ )
+
+ add_custom_target(${VITA_EXECUTABLE}_icons
+ DEPENDS "${CMAKE_BINARY_DIR}/${VITA_EXECUTABLE}_icon0.png" "${CMAKE_BINARY_DIR}/${VITA_EXECUTABLE}_startup.png"
+ )
+
+ list(APPEND VPK_FILE_LIST FILE ${CMAKE_BINARY_DIR}/${VITA_EXECUTABLE}_icon0.png sce_sys/icon0.png)
+ list(APPEND VPK_FILE_LIST FILE ${CMAKE_BINARY_DIR}/${VITA_EXECUTABLE}_startup.png sce_sys/livearea/contents/startup.png)
+ add_dependencies(${VITA_EXECUTABLE}.self-self ${VITA_EXECUTABLE}_icons)
+ endif()
+
+ if(VITA_LOAD_IMAGE)
+ list(APPEND VPK_FILE_LIST FILE ${VITA_LOAD_IMAGE} sce_sys/pic0.png)
+ endif()
+
+ if(VITA_BACKGROUND)
+ list(APPEND VPK_FILE_LIST FILE ${VITA_BACKGROUND} sce_sys/livearea/contents/bg.png)
+ endif()
+
+ set(VITA_PACK_VPK_FLAGS "")
+
+ vita_create_vpk(${VITA_EXECUTABLE}.vpk ${VITA_TITLE_ID} ${CMAKE_CURRENT_BINARY_DIR}/${VITA_EXECUTABLE}.self
+ VERSION ${VITA_VERSION}
+ NAME ${VITA_APP_NAME}
+ ${VPK_FILE_LIST}
+ )
+ add_dependencies(${VITA_EXECUTABLE}.self-self ${target})
+endfunction()
\ No newline at end of file
diff --git a/cmake/template.xml b/cmake/template.xml
new file mode 100644
index 00000000..509124e0
--- /dev/null
+++ b/cmake/template.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ bg.png
+
+
+
+ startup.png
+
+
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index e689f6b1..0510096b 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -102,6 +102,8 @@ set(COMMON_SRC
if (WIN32)
list(APPEND COMMON_SRC file_win.cpp paths_win.cpp)
+elseif(VITA)
+ list(APPEND COMMON_SRC file_posix.cpp paths_vita.cpp)
else()
list(APPEND COMMON_SRC file_posix.cpp paths_posix.cpp)
endif()
@@ -170,6 +172,35 @@ target_compile_definitions(common PRIVATE FIXIT_FAST_LOAD $<$:_DEB
# Make build check state of git to check for uncommitted changes.
add_dependencies(common check_git)
+if(VITA)
+ target_compile_definitions(common PUBLIC VITA)
+ target_compile_options(common PUBLIC
+ -O2
+ -mcpu=cortex-a9
+ -mfpu=neon
+ -ffast-math
+ -ftree-vectorize
+ -fno-lto
+ )
+ target_link_libraries(common PUBLIC
+ SceMotion_stub
+ SceTouch_stub
+ SceAudio_stub
+ SceAudioIn_stub
+ SceCtrl_stub
+ SceGxm_stub
+ SceHid_stub
+ SceDisplay_stub
+ SceSysmodule_stub
+ SceCommonDialog_stub
+ ScePower_stub
+ SceAppUtil_stub
+ -Wl,--whole-archive
+ pthread
+ -Wl,--no-whole-archive
+ )
+endif()
+
if(BUILD_REMASTERTD OR BUILD_REMASTERRA)
add_library(commonr STATIC ${COMMONR_SRC})
target_compile_definitions(commonr PUBLIC $<$:_DEBUG> ${REMASTER_DEFS})
diff --git a/common/debugstring.cpp b/common/debugstring.cpp
index d02efab9..6bc70d43 100644
--- a/common/debugstring.cpp
+++ b/common/debugstring.cpp
@@ -9,6 +9,10 @@
#include
#endif
+#ifdef VITA
+#include
+#endif
+
static class DebugStateClass
{
public:
@@ -66,6 +70,16 @@ void Debug_String_Log(unsigned level, const char* file, int line, const char* fm
fflush(DebugState.File);
}
+#ifdef VITA
+ /* Don't print file and line numbers to stderr to avoid clogging it up with too much info */
+ va_list args;
+ sceClibPrintf("%-5s: ", levels[level]);
+ va_start(args, fmt);
+ char msg[200];
+ vsprintf(msg, fmt, args);
+ sceClibPrintf("%s\n", msg);
+ va_end(args);
+#else
/* Don't print file and line numbers to stderr to avoid clogging it up with too much info */
va_list args;
fprintf(stderr, "%-5s: ", levels[level]);
@@ -74,6 +88,7 @@ void Debug_String_Log(unsigned level, const char* file, int line, const char* fm
fprintf(stderr, "\n");
va_end(args);
fflush(stderr);
+#endif
}
void Debug_String_File(const char* file)
diff --git a/common/file_posix.cpp b/common/file_posix.cpp
index 387512f9..029f0ca7 100644
--- a/common/file_posix.cpp
+++ b/common/file_posix.cpp
@@ -8,6 +8,12 @@
#include
#include
+#ifdef VITA
+// TODO More definitions to move to a compat lib that tests for the symbols?
+#define PATH_MAX 256
+#define FNM_CASEFOLD 0
+#endif
+
class Find_File_Data_Posix : public Find_File_Data
{
public:
@@ -122,3 +128,51 @@ Find_File_Data* Find_File_Data::CreateFindData()
{
return new Find_File_Data_Posix();
}
+
+#ifdef VITA
+#include
+#include
+#include
+
+#define PATH_MAX 256
+
+std::string StringLower(std::string str)
+{
+ std::transform(str.begin(), str.end(), str.begin(), ::tolower);
+ return str;
+}
+
+// fnmatch is missing from vita newlib, this is here until otherwise.
+int fnmatch(const char *pattern, const char *string, int flags)
+{
+ //massive hackjob..
+ std::string filename = string;
+ std::string filter = pattern;
+ filename = StringLower(filename);
+ filter = StringLower(filter);
+ std::vector filter_split;
+ std::string delimiter = "*";
+ bool found = true;
+
+ size_t pos = 0;
+ std::string token;
+ while ((pos = filter.find(delimiter)) != std::string::npos) {
+ token = filter.substr(0, pos);
+ filter_split.push_back(token);
+ filter.erase(0, pos + delimiter.length());
+ }
+
+ if (!filter_split.empty()) {
+ for (int i = 0; i < filter_split.size(); ++i) {
+ if (filename.find(filter_split[i]) == std::string::npos) {
+ found = false;
+ break;
+ }
+ }
+ } else {
+ found = filename.find(filter) != std::string::npos;
+ }
+
+ return found ? 0 : 1;
+}
+#endif
diff --git a/common/mixfile.h b/common/mixfile.h
index 16ac97c5..04033362 100644
--- a/common/mixfile.h
+++ b/common/mixfile.h
@@ -34,6 +34,19 @@
#include // For basename()
#endif
+#ifdef VITA
+// TODO Another set of functions to move to a compat lib that tests for the function?
+#define PATH_MAX 256
+#define basename basename_vita
+
+// fails to link due to undefined basename. old newlib?
+static char* basename_vita(const char* filename)
+{
+ char* p = strrchr(filename, '/');
+ return p ? p + 1 : (char*)filename;
+}
+#endif
+
#ifndef _MAX_PATH
#define _MAX_PATH PATH_MAX
#endif
diff --git a/common/mssleep.h b/common/mssleep.h
index 649bfaa3..9e796eb8 100644
--- a/common/mssleep.h
+++ b/common/mssleep.h
@@ -8,6 +8,8 @@
#ifdef _WIN32
#include
+#elif defined VITA
+#include
#else /* Assuming recent posix*/
#define __USE_POSIX199309
#define _POSIX_C_SOURCE 199309L
diff --git a/common/paths_vita.cpp b/common/paths_vita.cpp
new file mode 100644
index 00000000..b462ab1c
--- /dev/null
+++ b/common/paths_vita.cpp
@@ -0,0 +1,92 @@
+// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
+// software: you can redistribute it and/or modify it under the terms of
+// the GNU General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+
+// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
+// in the hope that it will be useful, but with permitted additional restrictions
+// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
+// distributed with this program. You should have received a copy of the
+// GNU General Public License along with permitted additional restrictions
+// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
+
+#include "paths.h"
+
+#include
+#include
+#include
+
+#define PATH_MAX 256
+
+static std::string VitaGamePath;
+
+const char* PathsClass::Program_Path()
+{
+ if (ProgramPath.empty()) {
+ ProgramPath = VitaGamePath;
+ }
+
+ return ProgramPath.c_str();
+}
+
+const char* PathsClass::Data_Path()
+{
+ if (DataPath.empty()) {
+ if (ProgramPath.empty()) {
+ // Init the program path first if it hasn't been done already.
+ Program_Path();
+ }
+
+ DataPath = VitaGamePath;
+
+ if (!Suffix.empty()) {
+ DataPath += SEP + Suffix;
+ }
+ }
+
+ return DataPath.c_str();
+}
+
+const char* PathsClass::User_Path()
+{
+ if (UserPath.empty()) {
+ UserPath = VitaGamePath;
+
+ if (!Suffix.empty()) {
+ UserPath += SEP + Suffix;
+ }
+
+ Create_Directory(UserPath.c_str());
+ }
+
+ return UserPath.c_str();
+}
+
+bool PathsClass::Create_Directory(const char* dirname)
+{
+ bool ret = true;
+
+ if (dirname == nullptr) {
+ return ret;
+ }
+
+ std::string temp = dirname;
+ size_t pos = 0;
+ do {
+ pos = temp.find_first_of("/", pos + 1);
+ sceIoMkdir(temp.substr(0, pos).c_str(), 0700);
+ } while (pos != std::string::npos);
+
+ return ret;
+}
+
+bool PathsClass::Is_Absolute(const char* path)
+{
+ return path != nullptr && path[0] == 'u' && path[1] == 'x' && path[2] == '0';
+}
+
+std::string PathsClass::Argv_Path(const char* cmd_arg)
+{
+ VitaGamePath = cmd_arg;
+ return VitaGamePath;
+}
diff --git a/common/settings.cpp b/common/settings.cpp
index bff02b6d..27ca6d44 100644
--- a/common/settings.cpp
+++ b/common/settings.cpp
@@ -11,7 +11,12 @@ SettingsClass::SettingsClass()
*/
Mouse.RawInput = true;
Mouse.Sensitivity = 100;
+#ifdef VITA
+ // Default to enabled on platforms where controller is likely to be primary method.
+ Mouse.ControllerEnabled = true;
+#else
Mouse.ControllerEnabled = false;
+#endif
Mouse.ControllerPointerSpeed = 10;
Options.MouseWheelScrolling = true;
@@ -32,6 +37,12 @@ SettingsClass::SettingsClass()
Video.Scaler = "nearest";
Video.Driver = "default";
Video.PixelFormat = "default";
+
+#ifdef VITA
+ Vita.ScaleGameSurface = true;
+ Vita.RearTouchEnabled = true;
+ Vita.RearTouchSpeed = 5;
+#endif
}
void SettingsClass::Load(INIClass& ini)
@@ -77,6 +88,12 @@ void SettingsClass::Load(INIClass& ini)
if (Video.Boxing || Mouse.RawInput || Mouse.ControllerEnabled) {
Video.HardwareCursor = false;
}
+
+#ifdef VITA
+ Vita.ScaleGameSurface = ini.Get_Bool("Vita", "ScaleGameSurface", Vita.ScaleGameSurface);
+ Vita.RearTouchEnabled = ini.Get_Bool("Vita", "RearTouchEnabled", Vita.RearTouchEnabled);
+ Vita.RearTouchSpeed = ini.Get_Int("Vita", "RearTouchSpeed", Vita.RearTouchSpeed);
+#endif
}
void SettingsClass::Save(INIClass& ini)
@@ -111,4 +128,10 @@ void SettingsClass::Save(INIClass& ini)
** VQA and WSA interpolation mode 0 = scanlines, 1 = vertical doubling, 2 = linear
*/
ini.Put_Int("Video", "InterpolationMode", Video.InterpolationMode);
+
+#ifdef VITA
+ ini.Put_Bool("Vita", "ScaleGameSurface", Vita.ScaleGameSurface);
+ ini.Put_Bool("Vita", "RearTouchEnabled", Vita.RearTouchEnabled);
+ ini.Put_Int("Vita", "RearTouchSpeed", Vita.RearTouchSpeed);
+#endif
}
diff --git a/common/settings.h b/common/settings.h
index cd2b4ea3..f365c8cc 100644
--- a/common/settings.h
+++ b/common/settings.h
@@ -38,6 +38,15 @@ class SettingsClass
std::string PixelFormat;
} Video;
+#ifdef VITA
+ struct
+ {
+ bool ScaleGameSurface;
+ bool RearTouchEnabled;
+ int RearTouchSpeed;
+ } Vita;
+#endif
+
struct
{
bool MouseWheelScrolling;
diff --git a/common/sockets.h b/common/sockets.h
index fb2b052c..6e09e155 100644
--- a/common/sockets.h
+++ b/common/sockets.h
@@ -29,13 +29,19 @@ static inline int socket_cleanup(void)
{
return WSACleanup();
}
-
#else /* Assume posix style sockets on non-windows */
+#ifdef VITA
+// TODO vita networking stuff.
+#include
+#endif
+
#include
#include
#include // for getaddrinfo() and freeaddrinfo()
+#ifndef VITA
#include
+#endif
#include
#include
#include // for close()
diff --git a/common/video.h b/common/video.h
index 6e9ae737..f8f4b11b 100644
--- a/common/video.h
+++ b/common/video.h
@@ -70,6 +70,17 @@ void Reset_Video_Mode();
unsigned Get_Free_Video_Memory();
void Wait_Blit();
+#ifdef VITA
+#include
+
+const int32_t VITA_FULLSCREEN_WIDTH = 960;
+const int32_t VITA_FULLSCREEN_HEIGHT = 544;
+
+void Get_Game_Resolution(int& w, int& h);
+void Set_Video_Mouse(int x, int y);
+SDL_Rect Get_Render_Rect();
+#endif
+
/*
** Set desired cursor image in game palette.
*/
diff --git a/common/video_sdl2.cpp b/common/video_sdl2.cpp
index b84f7436..417841da 100644
--- a/common/video_sdl2.cpp
+++ b/common/video_sdl2.cpp
@@ -132,6 +132,39 @@ static void Update_HWCursor_Settings()
/*
** Update screen boxing settings.
*/
+#ifdef VITA
+ if (hwcursor.GameW != VITA_FULLSCREEN_WIDTH || hwcursor.GameH != VITA_FULLSCREEN_HEIGHT) {
+ render_dst.x = 0;
+ render_dst.y = 0;
+ render_dst.w = hwcursor.GameW;
+ render_dst.h = hwcursor.GameH;
+
+ if (Settings.Vita.ScaleGameSurface) {
+ //resize to fullscreen
+ if (Settings.Video.Boxing) {
+ if ((static_cast(VITA_FULLSCREEN_WIDTH) / VITA_FULLSCREEN_HEIGHT)
+ >= (static_cast(hwcursor.GameW) / hwcursor.GameH)) {
+ float scale = static_cast(VITA_FULLSCREEN_HEIGHT) / hwcursor.GameH;
+ render_dst.w = hwcursor.GameW * scale;
+ render_dst.h = VITA_FULLSCREEN_HEIGHT;
+ render_dst.x = (VITA_FULLSCREEN_WIDTH - render_dst.w) / 2;
+ } else {
+ float scale = static_cast(VITA_FULLSCREEN_WIDTH) / hwcursor.GameW;
+ render_dst.w = VITA_FULLSCREEN_WIDTH;
+ render_dst.h = hwcursor.GameH * scale;
+ render_dst.y = (VITA_FULLSCREEN_HEIGHT - render_dst.h) / 2;
+ }
+ } else {
+ render_dst.w = VITA_FULLSCREEN_WIDTH;
+ render_dst.h = VITA_FULLSCREEN_HEIGHT;
+ }
+ } else {
+ //center game area
+ render_dst.x = (VITA_FULLSCREEN_WIDTH - hwcursor.GameW) / 2;
+ render_dst.y = (VITA_FULLSCREEN_HEIGHT - hwcursor.GameH) / 2;
+ }
+ }
+#else
float ar = (float)hwcursor.GameW / hwcursor.GameH;
if (Settings.Video.Boxing) {
size_t colonPos = Settings.Video.BoxingAspectRatio.find(":");
@@ -166,6 +199,7 @@ static void Update_HWCursor_Settings()
render_dst.x = 0;
render_dst.y = 0;
}
+#endif
/*
** Ensure cursor clip is in the desired state.
@@ -279,7 +313,11 @@ bool Set_Video_Mode(int w, int h, int bits_per_pixel)
}
}
+#ifdef VITA
+ renderer = SDL_CreateRenderer(window, renderer_index, SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_PRESENTVSYNC);
+#else
renderer = SDL_CreateRenderer(window, renderer_index, SDL_RENDERER_TARGETTEXTURE);
+#endif
if (renderer == nullptr) {
DBG_ERROR("SDL_CreateRenderer failed: %s", SDL_GetError());
Reset_Video_Mode();
@@ -459,6 +497,25 @@ void Get_Video_Mouse(int& x, int& y)
}
}
+#ifdef VITA
+void Get_Game_Resolution(int& w, int& h)
+{
+ w = hwcursor.GameW;
+ h = hwcursor.GameH;
+}
+
+void Set_Video_Mouse(int x, int y)
+{
+ hwcursor.X = x;
+ hwcursor.Y = y;
+}
+
+SDL_Rect Get_Render_Rect()
+{
+ return render_dst;
+}
+#endif
+
/***********************************************************************************************
* Reset_Video_Mode -- Resets video mode and deletes Direct Draw Object *
* *
diff --git a/common/wwkeyboard.cpp b/common/wwkeyboard.cpp
index 6bf91ede..9cd36b93 100644
--- a/common/wwkeyboard.cpp
+++ b/common/wwkeyboard.cpp
@@ -630,6 +630,13 @@ void WWKeyboardClass::Fill_Buffer_From_System(void)
case SDL_CONTROLLERBUTTONUP:
Handle_Controller_Button_Event(event.cbutton);
break;
+#ifdef VITA
+ case SDL_FINGERDOWN:
+ case SDL_FINGERUP:
+ case SDL_FINGERMOTION:
+ Handle_Touch_Event(event.tfinger);
+ break;
+#endif
}
}
if (Is_Gamepad_Active()) {
@@ -662,6 +669,9 @@ void WWKeyboardClass::Open_Controller()
GameController = SDL_GameControllerOpen(i);
}
}
+#if SDL_VERSION_ATLEAST(2, 0, 10) && defined(VITA)
+ SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
+#endif
}
void WWKeyboardClass::Close_Controller()
@@ -678,6 +688,12 @@ void WWKeyboardClass::Process_Controller_Axis_Motion()
const float deltaTime = currentTime - LastControllerTime;
LastControllerTime = currentTime;
+#ifdef VITA
+ if (!AnalogStickMouse) {
+ return;
+ }
+#endif
+
if (ControllerLeftXAxis != 0 || ControllerLeftYAxis != 0) {
const int16_t xSign = (ControllerLeftXAxis > 0) - (ControllerLeftXAxis < 0);
const int16_t ySign = (ControllerLeftYAxis > 0) - (ControllerLeftYAxis < 0);
@@ -697,6 +713,15 @@ void WWKeyboardClass::Handle_Controller_Axis_Event(const SDL_ControllerAxisEvent
ScrollDirType directionX = SDIR_NONE;
ScrollDirType directionY = SDIR_NONE;
+#ifdef VITA
+ int CONTROLLER_L_DEADZONE;
+ if (!AnalogStickMouse) {
+ CONTROLLER_L_DEADZONE = CONTROLLER_L_DEADZONE_SCROLL;
+ } else {
+ CONTROLLER_L_DEADZONE = CONTROLLER_L_DEADZONE_MOUSE;
+ }
+#endif
+
if (motion.axis == SDL_CONTROLLER_AXIS_LEFTX) {
if (std::abs(motion.value) > CONTROLLER_L_DEADZONE)
ControllerLeftXAxis = motion.value;
@@ -724,6 +749,19 @@ void WWKeyboardClass::Handle_Controller_Axis_Event(const SDL_ControllerAxisEvent
ControllerSpeedBoost = 1;
}
+#ifdef VITA
+ if (!AnalogStickMouse) {
+ if (ControllerLeftXAxis != 0) {
+ AnalogScrollActive = true;
+ directionX = ControllerLeftXAxis > 0 ? SDIR_E : SDIR_W;
+ }
+ if (ControllerLeftYAxis != 0) {
+ AnalogScrollActive = true;
+ directionY = ControllerLeftYAxis > 0 ? SDIR_S : SDIR_N;
+ }
+ }
+#endif
+
if (ControllerRightXAxis != 0) {
AnalogScrollActive = true;
directionX = ControllerRightXAxis > 0 ? SDIR_E : SDIR_W;
@@ -819,6 +857,17 @@ void WWKeyboardClass::Handle_Controller_Button_Event(const SDL_ControllerButtonE
Get_Video_Mouse(x, y);
Put_Mouse_Message(key, x, y, button.state == SDL_RELEASED);
}
+
+#ifdef VITA
+ if (button.state == SDL_PRESSED
+ && (button.button == SDL_CONTROLLER_BUTTON_LEFTSHOULDER || button.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER
+ || button.button == SDL_CONTROLLER_BUTTON_START)) {
+ if (SDL_GameControllerGetButton(GameController, SDL_CONTROLLER_BUTTON_LEFTSHOULDER)
+ && SDL_GameControllerGetButton(GameController, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER)
+ && SDL_GameControllerGetButton(GameController, SDL_CONTROLLER_BUTTON_START))
+ AnalogStickMouse = !AnalogStickMouse;
+ }
+#endif
}
bool WWKeyboardClass::Is_Analog_Scroll_Active()
@@ -830,7 +879,86 @@ unsigned char WWKeyboardClass::Get_Scroll_Direction()
{
return ScrollDirection;
}
-#endif
+#ifdef VITA
+bool WWKeyboardClass::Is_Analog_Only_Scroll()
+{
+ return !AnalogStickMouse;
+}
+
+void WWKeyboardClass::Handle_Touch_Event(const SDL_TouchFingerEvent& event)
+{
+ // rear touchpad
+ if (event.touchId != 0) {
+ if (Settings.Vita.RearTouchEnabled) {
+ if (event.type == SDL_FINGERDOWN) {
+ ++RearNumTouches;
+ if (RearNumTouches == 1) {
+ RearFirstFingerId = event.fingerId;
+ }
+ LastRearTouchTime = SDL_GetTicks();
+ } else if (event.type == SDL_FINGERUP) {
+ --RearNumTouches;
+ if ((RearNumTouches == 0) && (SDL_GetTicks() - LastRearTouchTime < REAR_LMB_DELAY)) {
+ int emulatedPointerPosX;
+ int emulatedPointerPosY;
+ Get_Video_Mouse(emulatedPointerPosX, emulatedPointerPosY);
+ Put_Mouse_Message(VK_LBUTTON, emulatedPointerPosX, emulatedPointerPosY, 0);
+ Put_Mouse_Message(VK_LBUTTON, emulatedPointerPosX, emulatedPointerPosY, 1);
+ }
+ } else if (event.type == SDL_FINGERMOTION) {
+ if (RearFirstFingerId == event.fingerId) {
+ float movX = event.dx * REAR_TOUCH_SPEED_MOD * Settings.Vita.RearTouchSpeed;
+ float movY = event.dy * REAR_TOUCH_SPEED_MOD * Settings.Vita.RearTouchSpeed;
+ Move_Video_Mouse(movX, movY);
+ }
+ }
+ }
+ return;
+ }
+
+ if (event.type == SDL_FINGERDOWN) {
+ ++NumTouches;
+ if (NumTouches == 1) {
+ FirstFingerId = event.fingerId;
+ }
+ } else if (event.type == SDL_FINGERUP) {
+ --NumTouches;
+ }
+
+ if (FirstFingerId == event.fingerId) {
+ const int screenWidth = 960;
+ const int screenHeight = 544;
+ int gameWidth;
+ int gameHeight;
+ Get_Game_Resolution(gameWidth, gameHeight);
+ SDL_Rect renderRect = Get_Render_Rect();
+
+ float emulatedPointerPosX =
+ static_cast(screenWidth * event.x - renderRect.x) * (static_cast(gameWidth) / renderRect.w);
+ float emulatedPointerPosY = static_cast(screenHeight * event.y - renderRect.y)
+ * (static_cast(gameHeight) / renderRect.h);
+
+ if (emulatedPointerPosX < 0)
+ emulatedPointerPosX = 0;
+ else if (emulatedPointerPosX >= gameWidth)
+ emulatedPointerPosX = gameWidth - 1;
+
+ if (emulatedPointerPosY < 0)
+ emulatedPointerPosY = 0;
+ else if (emulatedPointerPosY >= gameHeight)
+ emulatedPointerPosY = gameHeight - 1;
+
+ Set_Video_Mouse(emulatedPointerPosX, emulatedPointerPosY);
+
+ if (event.type == SDL_FINGERDOWN) {
+ Put_Mouse_Message(VK_LBUTTON, emulatedPointerPosX, emulatedPointerPosY, 0);
+ } else if (event.type == SDL_FINGERUP) {
+ Put_Mouse_Message(VK_LBUTTON, emulatedPointerPosX, emulatedPointerPosY, 1);
+ }
+ }
+}
+#endif // VITA
+#endif // SDL2_BUILD
/***********************************************************************************************
* WWKeyboardClass::Clear -- Clears the keyboard buffer. *
diff --git a/common/wwkeyboard.h b/common/wwkeyboard.h
index 678ccb06..3613564d 100644
--- a/common/wwkeyboard.h
+++ b/common/wwkeyboard.h
@@ -763,6 +763,9 @@ class WWKeyboardClass
void Open_Controller();
void Close_Controller();
bool Is_Analog_Scroll_Active();
+#ifdef VITA
+ bool Is_Analog_Only_Scroll();
+#endif
unsigned char Get_Scroll_Direction();
#endif
@@ -828,7 +831,12 @@ class WWKeyboardClass
enum
{
+#ifdef VITA
+ CONTROLLER_L_DEADZONE_MOUSE = 4000,
+ CONTROLLER_L_DEADZONE_SCROLL = 6000,
+#else
CONTROLLER_L_DEADZONE = 4000,
+#endif
CONTROLLER_R_DEADZONE = 6000,
CONTROLLER_TRIGGER_R_DEADZONE = 3000
};
@@ -842,6 +850,19 @@ class WWKeyboardClass
float ControllerSpeedBoost = 1;
bool AnalogScrollActive = false;
ScrollDirType ScrollDirection = SDIR_NONE;
+
+#ifdef VITA
+ bool AnalogStickMouse = true;
+ void Handle_Touch_Event(const SDL_TouchFingerEvent& event);
+ SDL_FingerID FirstFingerId = 0;
+ int16_t NumTouches = 0;
+
+ static constexpr int REAR_TOUCH_SPEED_MOD = 100;
+ static constexpr int REAR_LMB_DELAY = 250;
+ uint32_t LastRearTouchTime = 0;
+ SDL_FingerID RearFirstFingerId = 0;
+ int16_t RearNumTouches = 0;
+#endif
#endif
};
diff --git a/common/wwstd.h b/common/wwstd.h
index ab99bcc1..439ba591 100644
--- a/common/wwstd.h
+++ b/common/wwstd.h
@@ -258,12 +258,15 @@ inline static void _splitpath(const char* path, char* drive, char* dir, char* fn
}
}
+#ifndef VITA
+// TODO Consider moving these functions to some kind of compat lib?
inline static char* strupr(char* str)
{
for (int i = 0; i < strlen(str); i++)
str[i] = toupper(str[i]);
return str;
}
+#endif
inline static void strrev(char* str)
{
diff --git a/redalert/CMakeLists.txt b/redalert/CMakeLists.txt
index 60a3e854..2ccf6bba 100644
--- a/redalert/CMakeLists.txt
+++ b/redalert/CMakeLists.txt
@@ -280,4 +280,12 @@ if(BUILD_VANILLARA)
-g3 -fno-omit-frame-pointer)
target_link_options(VanillaRA PUBLIC -fsanitize=address)
endif()
-endif()
\ No newline at end of file
+ if(VITA)
+ include(VitaPackage)
+ generate_vita_package(VanillaRA
+ APP_NAME "VanillaRA"
+ TITLE_ID "VCRA00001"
+ ICON "${CMAKE_SOURCE_DIR}/resources/vanillara_icon.svg"
+ )
+ endif()
+endif()
diff --git a/redalert/globals.cpp b/redalert/globals.cpp
index 0c364ea3..56707d87 100644
--- a/redalert/globals.cpp
+++ b/redalert/globals.cpp
@@ -650,7 +650,10 @@ int MouseInstalled;
//
// Variables for helping track how much time goes bye in routines
//
+#ifndef VITA
+//multiple definition of `LogLevel' with openal vita port.
int LogLevel = 0;
+#endif
unsigned int LogLevelTime[MAX_LOG_LEVEL] = {0};
unsigned int LogLastTime = 0;
bool LogDump_Print = false; // true = print the Log time Stuff
diff --git a/redalert/startup.cpp b/redalert/startup.cpp
index c9d164b2..9338eb44 100644
--- a/redalert/startup.cpp
+++ b/redalert/startup.cpp
@@ -61,6 +61,13 @@ HINSTANCE ProgramInstance;
#include
#define vc_chdir(x) chdir(x)
#endif
+
+#ifdef VITA
+int _newlib_heap_size_user = 340 * 1024 * 1024;
+#include
+#include
+#endif
+
extern bool RA95AlreadyRunning;
void Check_Use_Compressed_Shapes(void);
void Read_Setup_Options(RawFileClass* config_file);
@@ -291,7 +298,12 @@ int main(int argc, char* argv[])
/*
** Remember the current working directory and drive.
*/
- Paths.Init("vanillara", CONFIG_FILE_NAME, "REDALERT.MIX", args.ArgV[0]);
+#ifdef VITA
+ const char* progpath = "ux0:data";
+#else
+ const char* progpath = args.ArgV[0];
+#endif
+ Paths.Init("vanillara", CONFIG_FILE_NAME, "REDALERT.MIX", progpath);
vc_chdir(Paths.Data_Path());
CDFileClass::Refresh_Search_Drives();
@@ -516,6 +528,10 @@ int main(int argc, char* argv[])
return (EXIT_SUCCESS);
}
+#ifdef VITA
+ sceKernelExitProcess(0);
+#endif
+
return (EXIT_SUCCESS);
}
diff --git a/tiberiandawn/CMakeLists.txt b/tiberiandawn/CMakeLists.txt
index a26cf467..55a77e79 100644
--- a/tiberiandawn/CMakeLists.txt
+++ b/tiberiandawn/CMakeLists.txt
@@ -256,4 +256,12 @@ if(BUILD_VANILLATD)
-g3 -fno-omit-frame-pointer)
target_link_options(VanillaTD PUBLIC -fsanitize=address)
endif()
+ if(VITA)
+ include(VitaPackage)
+ generate_vita_package(VanillaTD
+ APP_NAME "VanillaTD"
+ TITLE_ID "VCTD00001"
+ ICON "${CMAKE_SOURCE_DIR}/resources/vanillatd_icon.svg"
+ )
+ endif()
endif()
diff --git a/tiberiandawn/startup.cpp b/tiberiandawn/startup.cpp
index 13d56340..735efaa1 100644
--- a/tiberiandawn/startup.cpp
+++ b/tiberiandawn/startup.cpp
@@ -54,6 +54,12 @@ HINSTANCE ProgramInstance;
#define vc_chdir(x) chdir(x)
#endif
+#ifdef VITA
+int _newlib_heap_size_user = 340 * 1024 * 1024;
+#include
+#include
+#endif
+
extern int ReadyToQuit;
void Read_Setup_Options(RawFileClass* config_file);
@@ -202,6 +208,9 @@ int DLL_Startup(const char* command_line_in)
int main(int argc, char** argv)
{
+#ifdef VITA
+ scePowerSetArmClockFrequency(444);
+#endif
UtfArgs args(argc, argv);
CCDebugString("C&C95 - Starting up.\n");
@@ -225,7 +234,12 @@ int main(int argc, char** argv)
/*
** Remember the current working directory and drive.
*/
- Paths.Init("vanillatd", "CONQUER.INI", "CONQUER.MIX", args.ArgV[0]);
+#ifdef VITA
+ const char* progpath = "ux0:data";
+#else
+ const char* progpath = args.ArgV[0];
+#endif
+ Paths.Init("vanillatd", "CONQUER.INI", "CONQUER.MIX", progpath);
vc_chdir(Paths.Data_Path());
CDFileClass::Refresh_Search_Drives();
@@ -497,6 +511,10 @@ int main(int argc, char** argv)
}
}
+#ifdef VITA
+ sceKernelExitProcess(0);
+#endif
+
return (EXIT_SUCCESS);
}