Skip to content

Commit

Permalink
Initial Vita port.
Browse files Browse the repository at this point in the history
Based on Northfear's work for the Kyuhen homebrew contest.
  • Loading branch information
OmniBlade committed Sep 28, 2023
1 parent 59efc89 commit 5e6f503
Show file tree
Hide file tree
Showing 21 changed files with 632 additions and 5 deletions.
93 changes: 93 additions & 0 deletions cmake/VitaPackage.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
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 magick)

if(ImageMagick_magick_FOUND)
set(ImageMagick_convert_FOUND TRUE)
set(ImageMagick_convert_EXECUTABLE ${ImageMagick_magick_EXECUTABLE})
set(ImageMagick_convert_ARGS convert)
else()
find_package(ImageMagick COMPONENTS convert)
endif()

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} ${ImageMagick_convert_ARGS} -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} ${ImageMagick_convert_ARGS} -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()
11 changes: 11 additions & 0 deletions cmake/template.xml
Original file line number Diff line number Diff line change
@@ -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>
31 changes: 31 additions & 0 deletions common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -172,6 +174,35 @@ target_compile_definitions(common PRIVATE FIXIT_FAST_LOAD $<$<CONFIG:Debug>:_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(WIN32)
if(WIN9X)
target_compile_definitions(common PUBLIC _WIN32_WINNT=0x400)
Expand Down
15 changes: 15 additions & 0 deletions common/debugstring.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#include <io.h>
#endif

#ifdef VITA
#include <psp2/kernel/clib.h>
#endif

static class DebugStateClass
{
public:
Expand Down Expand Up @@ -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]);
Expand All @@ -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)
Expand Down
54 changes: 54 additions & 0 deletions common/file_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
#include <limits.h>
#include <fnmatch.h>

#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:
Expand Down Expand Up @@ -122,3 +128,51 @@ Find_File_Data* Find_File_Data::CreateFindData()
{
return new Find_File_Data_Posix();
}

#ifdef VITA
#include <algorithm>
#include <string>
#include <vector>

#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<std::string> 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
13 changes: 13 additions & 0 deletions common/mixfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@
#include <libgen.h> // 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
Expand Down
2 changes: 2 additions & 0 deletions common/mssleep.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include <winbase.h>
#elif defined(_WIN32)
#include <synchapi.h>
#elif defined VITA
#include <psp2/kernel/threadmgr.h>
#else /* Assuming recent posix*/
#define __USE_POSIX199309
#define _POSIX_C_SOURCE 199309L
Expand Down
97 changes: 97 additions & 0 deletions common/paths_vita.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// 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 <cstring>
#include <psp2/io/dirent.h>
#include <psp2/io/stat.h>

#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::Concatenate_Paths(const char* path1, const char* path2)
{
return std::string(path1) + SEP + path2;
}

std::string PathsClass::Argv_Path(const char* cmd_arg)
{
VitaGamePath = cmd_arg;
return VitaGamePath;
}
Loading

0 comments on commit 5e6f503

Please sign in to comment.