Skip to content

Commit

Permalink
Initial Vita port
Browse files Browse the repository at this point in the history
  • Loading branch information
Northfear committed Apr 13, 2021
1 parent 9210c42 commit b055076
Show file tree
Hide file tree
Showing 40 changed files with 750 additions and 19 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/build*
.vscode
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,23 @@ if(OPENAL)
set(DSOUND OFF)
endif()

if(VITA)
add_definitions(-DVITA)
set(VITA_FLAGS "-Ofast -mcpu=cortex-a9 -mfpu=neon -fgraphite-identity -floop-nest-optimize -fno-lto -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${VITA_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${VITA_FLAGS}")
list(APPEND VANILLA_LIBS "-lSceMotion_stub -lSceTouch_stub -lSceAudio_stub -lSceAudioIn_stub -lSceCtrl_stub -lSceGxm_stub \
-lSceHid_stub -lSceDisplay_stub -lSceSysmodule_stub -lSceCommonDialog_stub -lScePower_stub -lSceAppUtil_stub")
endif()

add_subdirectory(common)
add_subdirectory(tiberiandawn)
add_subdirectory(redalert)

if(VITA)
include("${CMAKE_SOURCE_DIR}/vita/vctd_vita.cmake")
include("${CMAKE_SOURCE_DIR}/vita/vcra_vita.cmake")
endif()

feature_summary(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:")
feature_summary(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:")
67 changes: 67 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,70 @@
# Vanilla Conquer port for PS Vita

## Install
Download vanillatd.vpk or vanillara.vpk file from https://github.com/Northfear/Vanilla-Conquer-vita/releases. Install it to your PS Vita.

Copy content of installed Tiberium Dawn game folder into to ```ux0:data/VanillaTD/``` or installed Red Alert folder into ```ux0:data/VanillaRA/```.

Check Vanilla Conquer Wiki for more info about required folder/file structure and game versions compatibility:

[Installing VanillaTD](https://github.com/TheAssemblyArmada/Vanilla-Conquer/wiki/Installing-VanillaTD)

[Installing VanillaRA](https://github.com/TheAssemblyArmada/Vanilla-Conquer/wiki/Installing-VanillaRA)

```expand.mix, expand2.mix, hires1.mix``` files that are required for RA expansions can be aquired from 3.03 patch.

[rePatch reDux0](https://github.com/dots-tb/rePatch-reDux0) OR [FdFix](https://github.com/TheOfficialFloW/FdFix) plugin may be required for proper suspend/resume support (only use one at a time).

## Building

### Prerequisites
- VitaSDK
- SDL2
- OpenAL

### Build
```
mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=$VITASDK/share/vita.toolchain.cmake -DVITA=true -DCMAKE_BUILD_TYPE=Release
make
```

Debug output can be previewed with psp2shell

https://github.com/Cpasjuste/psp2shell

## Port info

### Controls

Game is optimized for touch controls.

- Left/Right analog stick - Map scrolling
- CIRCLE - Right mouse button (Cancel building, deselect unit..)
- CROSS - G (Guard Area)
- SQUARE - F (Formation. RA only I guess)
- TRIANGLE - X (Scatter Units)
- D-Pad Up/Right/Down/Left - 1/2/3/4 button
- R1 - Alt (force move)
- L1 - Ctrl (force attack)
- SELECT - Esc (opens menu, skips videos)
- START - Enter (to submit score after the mission)

Use R1 + D-Pad to create teams (1-4) and D-Pad to select them (same as Ctrl + 1-4 on keyboard). You can use DPad numbers while entering savegame names.

### Other

Game supports nearest and linear filtering. Nearest is used by default and it produces sharp, but pixelated image (that's especially noticeable on text). Linear is smooth, but somewhat blurred. To select linear filtering edit
```ux0:data/VanillaTD/vanillatd/conquer.ini``` or ```ux0:data/VanillaRA/vanillara/redalert.ini``` and change ```Scaler``` option to ```linear```

```
[Video]
Scaler=linear
```

Change it back to ```nearest``` to select nearest filtering again.


# Vanilla Conquer
Vanilla Conquer is a fully portable version of the first generation C&C engine and is capable of running both Tiberian Dawn and Red Alert on multiple platforms. It can also be used for mod development for the Remastered Collection.

Expand Down
2 changes: 2 additions & 0 deletions common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,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
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
47 changes: 47 additions & 0 deletions common/file_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,53 @@
#include <limits.h>
#include <fnmatch.h>

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

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

class Find_File_Data_Posix : public Find_File_Data
{
public:
Expand Down
12 changes: 12 additions & 0 deletions common/mixfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@
#include <libgen.h> // For basename()
#endif

#ifdef VITA
#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
6 changes: 6 additions & 0 deletions common/mssleep.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@
#include <time.h>
#endif

#ifdef VITA
#include "SDL2/SDL.h"
#endif

/**
* Yield the current thread for at least ms milliseconds.
*/
static inline void ms_sleep(unsigned ms)
{
#ifdef _WIN32
Sleep(ms);
#elif VITA
SDL_Delay(ms);
#else
struct timespec ts;
ts.tv_sec = ms / 1000;
Expand Down
100 changes: 100 additions & 0 deletions common/paths_vita.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// 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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <pwd.h>
#include <stdexcept>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <vector>

#define PATH_MAX 256

#include <psp2/io/dirent.h>

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;
}
5 changes: 5 additions & 0 deletions common/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ void SettingsClass::Load(INIClass& ini)
Video.Driver = ini.Get_String("Video", "Driver", Video.Driver);
Video.PixelFormat = ini.Get_String("Video", "PixelFormat", Video.PixelFormat);

#ifdef VITA
//touch to mouse translates badly with boxing on
Video.Boxing = false;
#endif

/*
** VQA and WSA interpolation mode 0 = scanlines, 1 = vertical doubling, 2 = linear
*/
Expand Down
16 changes: 15 additions & 1 deletion common/video_sdl2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,11 @@ bool Set_Video_Mode(int w, int h, int bits_per_pixel)
DBG_INFO(" %s%s", info.name, (i == renderer_index ? " (selected)" : ""));
}
}

#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();
Expand Down Expand Up @@ -333,6 +336,12 @@ bool Set_Video_Mode(int w, int h, int bits_per_pixel)
hwcursor.Y = h / 2;
Update_HWCursor_Settings();

#ifdef VITA
SDL_Init(SDL_INIT_GAMECONTROLLER);
extern WWKeyboardClass* Keyboard;
Keyboard->OpenController();
#endif

return true;
}

Expand Down Expand Up @@ -468,6 +477,11 @@ void Reset_Video_Mode(void)

SDL_DestroyWindow(window);
window = nullptr;

#ifdef VITA
extern WWKeyboardClass* Keyboard;
Keyboard->CloseController();
#endif
}

static void Update_HWCursor()
Expand Down
Loading

0 comments on commit b055076

Please sign in to comment.