Add protocol launch support and PS Vita packaging
Generated by Moon Code. Co-Authored-By: Moon Code <moon-code@users.noreply.github.com>
@@ -6,20 +6,35 @@
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>armsx</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>armsx.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>armsx.app.0</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>armsx</string>
|
||||
<string>ARMSX</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.10.4-alpha</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.10.4-alpha</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>cloud.nanodata.armsx</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>armsx</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.9</string>
|
||||
<string>10.15</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true/>
|
||||
</dict>
|
||||
|
||||
@@ -33,6 +33,8 @@ IOS_DEPLOYMENT_TARGET ?= 14.0
|
||||
MACOS_DEPLOYMENT_TARGET ?= 10.15
|
||||
WINDOWS_TARGET ?= 0
|
||||
UWP_TARGET ?= 0
|
||||
PSVITA_TARGET ?= 0
|
||||
VITASDK ?=
|
||||
IOS_SDL_FRAMEWORK ?= $(CURDIR)/ios/Frameworks/SDL2.xcframework/ios-arm64/SDL2.framework
|
||||
IOS_SDL_FRAMEWORK_PARENT := $(dir $(IOS_SDL_FRAMEWORK))
|
||||
SDKROOT ?=
|
||||
@@ -41,6 +43,19 @@ FSUI_DIR := third_party/fsui-lib
|
||||
FSUI_BUILD_DIR ?= build/fsui/native
|
||||
WASM_HTML_POSTPROCESS := $(FSUI_DIR)/cmake/postprocess_web_html.cmake
|
||||
|
||||
ifeq ($(PSVITA_TARGET),1)
|
||||
ifeq ($(strip $(VITASDK)),)
|
||||
$(error VITASDK must be set when PSVITA_TARGET=1)
|
||||
endif
|
||||
SDL_CONFIG := $(VITASDK)/bin/arm-vita-eabi-pkg-config
|
||||
CC := $(VITASDK)/bin/arm-vita-eabi-gcc
|
||||
CXX := $(VITASDK)/bin/arm-vita-eabi-g++
|
||||
AR ?= $(VITASDK)/bin/arm-vita-eabi-ar
|
||||
RANLIB ?= $(VITASDK)/bin/arm-vita-eabi-ranlib
|
||||
PLATFORM := Vita
|
||||
SDL_STATIC := 1
|
||||
endif
|
||||
|
||||
ifeq ($(IOS_TARGET),1)
|
||||
SDKROOT ?= $(shell xcrun --sdk $(IOS_SDK) --show-sdk-path)
|
||||
CC ?= $(shell xcrun --sdk $(IOS_SDK) --find clang)
|
||||
@@ -82,11 +97,21 @@ ifeq ($(UWP_TARGET),1)
|
||||
BASE_CXXFLAGS += -DUWP_TARGET
|
||||
endif
|
||||
|
||||
ifeq ($(PSVITA_TARGET),1)
|
||||
BASE_CFLAGS += -DPSVITA_TARGET -D__DLL_BUILD
|
||||
BASE_CXXFLAGS += -DPSVITA_TARGET -D__DLL_BUILD
|
||||
endif
|
||||
|
||||
ifeq ($(WASM_TARGET),wasm)
|
||||
BASE_CFLAGS := $(filter-out -flto,$(BASE_CFLAGS))
|
||||
BASE_CXXFLAGS := $(filter-out -flto,$(BASE_CXXFLAGS))
|
||||
endif
|
||||
|
||||
ifeq ($(PSVITA_TARGET),1)
|
||||
BASE_CFLAGS := $(filter-out -flto,$(BASE_CFLAGS))
|
||||
BASE_CXXFLAGS := $(filter-out -flto,$(BASE_CXXFLAGS))
|
||||
endif
|
||||
|
||||
ifeq ($(IOS_TARGET),1)
|
||||
BASE_CFLAGS += -fembed-bitcode
|
||||
BASE_CXXFLAGS += -fembed-bitcode
|
||||
@@ -94,6 +119,8 @@ endif
|
||||
|
||||
ifeq ($(WASM_TARGET),wasm)
|
||||
OS_INFO := Emscripten
|
||||
else ifeq ($(PSVITA_TARGET),1)
|
||||
OS_INFO := PS Vita
|
||||
else ifneq ($(IOS_TARGET),1)
|
||||
OS_INFO := $(shell uname -rmo)
|
||||
else
|
||||
@@ -131,6 +158,8 @@ COMMIT_HASH := $(shell git rev-parse --short HEAD)
|
||||
BIN_DIR := bin
|
||||
ifeq ($(WASM_TARGET),wasm)
|
||||
BIN_DIR := bin/wasm
|
||||
else ifeq ($(PSVITA_TARGET),1)
|
||||
BIN_DIR := bin/psvita
|
||||
endif
|
||||
OBJ_DIR := $(BIN_DIR)/obj
|
||||
|
||||
@@ -141,8 +170,10 @@ else ifeq ($(WINDOWS_TARGET),1)
|
||||
BIN := $(BIN_DIR)/armsx.exe
|
||||
endif
|
||||
SHARED_BIN := $(BIN_DIR)/libarmsx$(SHARED_EXT)
|
||||
RUNTIME_ICON_SRC := icons/AppIconLarge.png
|
||||
RUNTIME_ICON_DEST := $(BIN_DIR)/icons/AppIconLarge.png
|
||||
VITA_NATIVE_LIB := $(BIN_DIR)/libarmsx_vita.a
|
||||
RUNTIME_ICON_SRC := icons/FsuiAppIcon.png
|
||||
RUNTIME_ICON_DEST := $(BIN_DIR)/icons/FsuiAppIcon.png
|
||||
WINDRES ?= windres
|
||||
|
||||
C_SOURCES := $(wildcard psx/*.c) \
|
||||
$(wildcard psx/dev/*.c) \
|
||||
@@ -163,15 +194,22 @@ FSUI_LIBS := \
|
||||
$(FSUI_BUILD_DIR)/libfsui-platform-sdl2.a \
|
||||
$(FSUI_BUILD_DIR)/libfsui-renderer-sdl2.a \
|
||||
$(FSUI_BUILD_DIR)/libfsui-renderer-sdl2surface.a \
|
||||
$(FSUI_BUILD_DIR)/libfsui-renderer-opengl.a \
|
||||
$(FSUI_BUILD_DIR)/libfsui-core.a \
|
||||
$(FSUI_BUILD_DIR)/libfsui_imgui.a \
|
||||
$(FSUI_BUILD_DIR)/libfsui_resources.a
|
||||
|
||||
ifeq ($(PSVITA_TARGET),1)
|
||||
FSUI_LIBS += \
|
||||
$(FSUI_BUILD_DIR)/libfsui-renderer-opengl.a \
|
||||
$(FSUI_BUILD_DIR)/libfsui_glad.a
|
||||
else
|
||||
|
||||
ifneq ($(WASM_TARGET),wasm)
|
||||
FSUI_LIBS += \
|
||||
$(FSUI_BUILD_DIR)/libfsui-renderer-opengl.a \
|
||||
$(FSUI_BUILD_DIR)/libfsui_glad.a
|
||||
endif
|
||||
endif
|
||||
|
||||
PLATFORM_EXTRA_LDFLAGS :=
|
||||
PLATFORM_EXTRA_LIBS :=
|
||||
@@ -196,7 +234,12 @@ endif
|
||||
C_OBJS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(C_SOURCES))
|
||||
C_OBJS_SHARED := $(patsubst %.c,$(OBJ_DIR)/%.o,$(C_SOURCES_SHARED))
|
||||
CPP_OBJS := $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(CPP_SOURCES))
|
||||
ALL_OBJS := $(C_OBJS) $(CPP_OBJS)
|
||||
RC_SOURCES :=
|
||||
ifeq ($(WINDOWS_TARGET),1)
|
||||
RC_SOURCES += resources/windows/armsx.rc
|
||||
endif
|
||||
RC_OBJS := $(patsubst %.rc,$(OBJ_DIR)/%.o,$(RC_SOURCES))
|
||||
ALL_OBJS := $(C_OBJS) $(CPP_OBJS) $(RC_OBJS)
|
||||
ALL_OBJS_SHARED := $(C_OBJS_SHARED) $(CPP_OBJS)
|
||||
|
||||
# Force dynamic SDL when building the shared library
|
||||
@@ -214,7 +257,7 @@ endif
|
||||
SDL_LIBS := $(if $(filter 1,$(SDL_STATIC)),$(SDL_LIBS_STATIC),$(SDL_LIBS_DYNAMIC))
|
||||
SDL_LIBS_SHARED := $(SDL_LIBS_DYNAMIC)
|
||||
|
||||
.PHONY: all clean shared wasm
|
||||
.PHONY: all clean shared wasm psvita-lib
|
||||
|
||||
all: $(BIN)
|
||||
|
||||
@@ -222,6 +265,8 @@ shared: $(SHARED_BIN)
|
||||
|
||||
wasm: $(BIN)
|
||||
|
||||
psvita-lib: $(VITA_NATIVE_LIB)
|
||||
|
||||
$(BIN_DIR):
|
||||
mkdir -p $(BIN_DIR)
|
||||
|
||||
@@ -242,6 +287,10 @@ $(OBJ_DIR)/%.o: %.cpp | $(OBJ_DIR)
|
||||
-DREP_VERSION="$(VERSION_TAG)" \
|
||||
-DREP_COMMIT_HASH="$(COMMIT_HASH)"
|
||||
|
||||
$(OBJ_DIR)/%.o: %.rc | $(OBJ_DIR)
|
||||
mkdir -p $(dir $@)
|
||||
$(WINDRES) -I. $< $@
|
||||
|
||||
$(RUNTIME_ICON_DEST): $(RUNTIME_ICON_SRC) | $(BIN_DIR)
|
||||
mkdir -p $(dir $@)
|
||||
cp $< $@
|
||||
@@ -252,6 +301,10 @@ ifeq ($(WASM_TARGET),wasm)
|
||||
cmake -DINPUT_FILE="$(BIN)" -P "$(WASM_HTML_POSTPROCESS)"
|
||||
endif
|
||||
|
||||
$(VITA_NATIVE_LIB): $(ALL_OBJS) $(RUNTIME_ICON_DEST) | $(BIN_DIR)
|
||||
$(AR) rcs $@ $(ALL_OBJS)
|
||||
$(RANLIB) $@
|
||||
|
||||
$(SHARED_BIN): $(ALL_OBJS_SHARED) | $(BIN_DIR)
|
||||
$(CXX) $(SHARED_LDFLAGS) $(ALL_OBJS_SHARED) $(FSUI_LIBS) -o $(SHARED_BIN) $(SDL_LIBS_SHARED) $(PLATFORM_EXTRA_LDFLAGS) $(PLATFORM_EXTRA_LIBS)
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ set -e
|
||||
# ./build.sh macosapp -> build desktop exe and bundle armsx.app
|
||||
# ./build.sh wasm -> build WebAssembly target to bin/wasm using emscripten
|
||||
# ./build.sh android -> build SDL2/libarmsx for Android and stage under android/app/src/main/jniLibs
|
||||
# ./build.sh psvita -> build Vita native archive + Rust SDL host and package ARMSX.vpk
|
||||
|
||||
MODE="$1"
|
||||
BUILD_JOBS="${BUILD_JOBS:-4}"
|
||||
@@ -42,11 +43,29 @@ build_fsui_wasm() {
|
||||
cmake --build build/fsui/wasm -j"${BUILD_JOBS}"
|
||||
}
|
||||
|
||||
build_fsui_psvita() {
|
||||
if [ -z "${VITASDK:-}" ]; then
|
||||
echo "VITASDK must be set for PSVita builds."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cmake -S cmake/psvita-fsui -B build/fsui/psvita \
|
||||
-DCMAKE_TOOLCHAIN_FILE="${VITASDK}/share/vita.toolchain.cmake" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DVITASDK="${VITASDK}" \
|
||||
-DFSUI_BUILD_SAMPLES=OFF \
|
||||
-DFSUI_ENABLE_INSTALL=OFF \
|
||||
-DFSUI_PLATFORM_BACKEND=SDL2 \
|
||||
-DFSUI_IMGUI_OPENGL_ES3=ON
|
||||
cmake --build build/fsui/psvita -j"${BUILD_JOBS}"
|
||||
}
|
||||
|
||||
bundle_macos_app() {
|
||||
rm -rf armsx.app/Contents/Libraries
|
||||
mkdir -p armsx.app/Contents/MacOS
|
||||
mkdir -p armsx.app/Contents/Resources/icons
|
||||
cp bin/armsx armsx.app/Contents/MacOS
|
||||
cp icons/ArmsxDesktop.icns armsx.app/Contents/Resources/armsx.icns
|
||||
cp -R icons/. armsx.app/Contents/Resources/icons/
|
||||
chmod 777 armsx.app/Contents/MacOS/armsx
|
||||
dylibbundler -b -x ./armsx.app/Contents/MacOS/armsx -d ./armsx.app/Contents/Libraries/ -p @executable_path/../Libraries/ -cd
|
||||
@@ -250,6 +269,64 @@ elif [ "$MODE" = "android" ]; then
|
||||
cp "${SDL_SHARED_LIB}" "${JNI_LIB_DIR}/"
|
||||
cp bin/libarmsx.so "${JNI_LIB_DIR}/"
|
||||
|
||||
elif [ "$MODE" = "psvita" ]; then
|
||||
if [ -z "${VITASDK:-}" ]; then
|
||||
echo "VITASDK must be set for PSVita builds."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v cargo >/dev/null 2>&1; then
|
||||
echo "cargo is required for the PSVita Rust host build."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export PATH="${VITASDK}/bin:${PATH}"
|
||||
build_fsui_psvita
|
||||
|
||||
make clean
|
||||
VITASDK="${VITASDK}" PSVITA_TARGET=1 FSUI_BUILD_DIR="$(pwd)/build/fsui/psvita" make psvita-lib
|
||||
|
||||
export PKG_CONFIG_ALLOW_CROSS=1
|
||||
export PKG_CONFIG="${VITASDK}/bin/arm-vita-eabi-pkg-config"
|
||||
export CARGO_TARGET_ARMV7_SONY_VITA_NEWLIBEABIHF_LINKER=arm-vita-eabi-g++
|
||||
export ARMSX_VITA_NATIVE_DIR="$(pwd)/bin/psvita"
|
||||
export ARMSX_VITA_FSUI_DIR="$(pwd)/build/fsui/psvita"
|
||||
|
||||
cargo build \
|
||||
--manifest-path psvita/Cargo.toml \
|
||||
--release \
|
||||
--target armv7-sony-vita-newlibeabihf \
|
||||
-Z build-std=std,panic_abort
|
||||
|
||||
VITA_PACKAGE_DIR="$(pwd)/build/psvita/package"
|
||||
VITA_TARGET_DIR="$(pwd)/psvita/target/armv7-sony-vita-newlibeabihf/release"
|
||||
VITA_ELF="${VITA_TARGET_DIR}/ARMSX_vita"
|
||||
VITA_VELF="${VITA_PACKAGE_DIR}/eboot.velf"
|
||||
VITA_EBOOT="${VITA_PACKAGE_DIR}/eboot.bin"
|
||||
VITA_PARAM="${VITA_PACKAGE_DIR}/param.sfo"
|
||||
VITA_VPK="${VITA_PACKAGE_DIR}/ARMSX.vpk"
|
||||
|
||||
if [ ! -f "${VITA_ELF}" ]; then
|
||||
echo "Expected Vita host ELF not found at ${VITA_ELF}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf "${VITA_PACKAGE_DIR}"
|
||||
mkdir -p "${VITA_PACKAGE_DIR}/sce_sys"
|
||||
cp icons/FsuiAppIcon.png "${VITA_PACKAGE_DIR}/sce_sys/icon0.png"
|
||||
|
||||
vita-mksfoex -s TITLE_ID=ARMSX001 "ARMSX PSVita" "${VITA_PARAM}"
|
||||
vita-elf-create -s "${VITA_ELF}" "${VITA_VELF}"
|
||||
vita-make-fself -s "${VITA_VELF}" "${VITA_EBOOT}"
|
||||
vita-pack-vpk "${VITA_VPK}" \
|
||||
-s "${VITA_PARAM}" \
|
||||
-b "${VITA_EBOOT}" \
|
||||
-a "$(pwd)/icons=icons" \
|
||||
-a "${VITA_PACKAGE_DIR}/sce_sys=sce_sys"
|
||||
|
||||
cp "${VITA_VPK}" bin/psvita/
|
||||
echo "Packaged Vita build at bin/psvita/ARMSX.vpk"
|
||||
|
||||
elif [ "$MODE" = "wasm" ]; then
|
||||
build_fsui_wasm
|
||||
make clean
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(armsx_psvita_fsui LANGUAGES C CXX)
|
||||
|
||||
if(NOT DEFINED VITASDK)
|
||||
if(DEFINED ENV{VITASDK})
|
||||
set(VITASDK "$ENV{VITASDK}")
|
||||
else()
|
||||
message(FATAL_ERROR "VITASDK must be set for PSVita FSUI builds.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include_directories(BEFORE "${CMAKE_CURRENT_LIST_DIR}/include")
|
||||
|
||||
add_library(SDL2::SDL2 INTERFACE IMPORTED GLOBAL)
|
||||
target_include_directories(SDL2::SDL2 INTERFACE
|
||||
"${VITASDK}/arm-vita-eabi/include"
|
||||
"${VITASDK}/arm-vita-eabi/include/SDL2"
|
||||
)
|
||||
target_link_directories(SDL2::SDL2 INTERFACE "${VITASDK}/arm-vita-eabi/lib")
|
||||
target_link_libraries(SDL2::SDL2 INTERFACE
|
||||
SDL2
|
||||
SceGxm_stub
|
||||
SceDisplay_stub
|
||||
SceCtrl_stub
|
||||
SceAppMgr_stub
|
||||
SceAppUtil_stub
|
||||
SceAudio_stub
|
||||
SceAudioIn_stub
|
||||
SceSysmodule_stub
|
||||
SceIofilemgr_stub
|
||||
SceCommonDialog_stub
|
||||
SceTouch_stub
|
||||
SceHid_stub
|
||||
SceMotion_stub
|
||||
ScePower_stub
|
||||
SceProcessmgr_stub
|
||||
m
|
||||
)
|
||||
|
||||
set(FSUI_BUILD_SAMPLES OFF CACHE BOOL "Build the fsui sample applications" FORCE)
|
||||
set(FSUI_ENABLE_INSTALL OFF CACHE BOOL "Enable install/export rules for the fsui package" FORCE)
|
||||
set(FSUI_PLATFORM_BACKEND SDL2 CACHE STRING "Platform backend to build" FORCE)
|
||||
set(FSUI_IMGUI_OPENGL_ES3 ON CACHE BOOL "Build the fsui OpenGL backend in OpenGL ES 3 mode" FORCE)
|
||||
set(FSUI_USE_SYSTEM_SDL2 OFF CACHE BOOL "Prefer a system SDL2 package when an SDL target is not already available" FORCE)
|
||||
|
||||
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../../third_party/fsui-lib" "${CMAKE_BINARY_DIR}/fsui-lib")
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include <glad/gles2.h>
|
||||
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 2.8 MiB |
|
After Width: | Height: | Size: 292 KiB |
@@ -3,10 +3,9 @@ name = "ARMSX_vita"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
sdl2 = "0.34"
|
||||
|
||||
[package.metadata.vita]
|
||||
title_id = "ARMSX001"
|
||||
title_name = "ARMSX PSVita"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
|
||||
@@ -1,19 +1,83 @@
|
||||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
fn main() {
|
||||
let target = std::env::var("TARGET").unwrap();
|
||||
if target.contains("vita") {
|
||||
let vitasdk = std::env::var("VITASDK").expect("VITASDK environment variable must be set");
|
||||
println!("cargo:rerun-if-env-changed=VITASDK");
|
||||
println!("cargo:rerun-if-env-changed=ARMSX_VITA_NATIVE_DIR");
|
||||
println!("cargo:rerun-if-env-changed=ARMSX_VITA_FSUI_DIR");
|
||||
|
||||
let target = env::var("TARGET").unwrap_or_default();
|
||||
if !target.contains("vita") {
|
||||
return;
|
||||
}
|
||||
|
||||
let vitasdk = env::var("VITASDK").expect("VITASDK environment variable must be set");
|
||||
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR must be set"));
|
||||
let repo_root = manifest_dir.parent().expect("psvita crate must live under the repo root");
|
||||
let native_dir = env::var_os("ARMSX_VITA_NATIVE_DIR")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|| repo_root.join("bin/psvita"));
|
||||
let fsui_dir = env::var_os("ARMSX_VITA_FSUI_DIR")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|| repo_root.join("build/fsui/psvita"));
|
||||
|
||||
let native_archive = require_file(native_dir.join("libarmsx_vita.a"));
|
||||
let fsui_archives = [
|
||||
"libfsui-donor.a",
|
||||
"libfsui-backend-sdl.a",
|
||||
"libfsui-platform-sdl2.a",
|
||||
"libfsui-renderer-opengl.a",
|
||||
"libfsui-renderer-sdl2.a",
|
||||
"libfsui-renderer-sdl2surface.a",
|
||||
"libfsui-core.a",
|
||||
"libfsui_imgui.a",
|
||||
"libfsui_resources.a",
|
||||
"libfsui_glad.a",
|
||||
]
|
||||
.into_iter()
|
||||
.map(|name| require_file(fsui_dir.join(name)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
println!("cargo:rustc-link-search=native={}/arm-vita-eabi/lib", vitasdk);
|
||||
println!("cargo:rustc-link-lib=SDL2");
|
||||
println!("cargo:rustc-link-lib=SceGxm_stub");
|
||||
println!("cargo:rustc-link-lib=SceDisplay_stub");
|
||||
println!("cargo:rustc-link-lib=SceAudio_stub");
|
||||
println!("cargo:rustc-link-lib=SceAudioIn_stub");
|
||||
println!("cargo:rustc-link-lib=SceCtrl_stub");
|
||||
println!("cargo:rustc-link-lib=SceHid_stub");
|
||||
println!("cargo:rustc-link-lib=SceMotion_stub");
|
||||
println!("cargo:rustc-link-lib=SceIme_stub");
|
||||
println!("cargo:rustc-link-lib=SceCommonDialog_stub");
|
||||
println!("cargo:rustc-link-lib=SceTouch_stub");
|
||||
println!("cargo:rustc-link-lib=SceLibKernel_stub");
|
||||
println!("cargo:rustc-link-lib=stdc++");
|
||||
println!("cargo:rustc-link-arg=-Wl,--start-group");
|
||||
println!("cargo:rustc-link-arg={}", native_archive.display());
|
||||
for archive in &fsui_archives {
|
||||
println!("cargo:rustc-link-arg={}", archive.display());
|
||||
}
|
||||
println!("cargo:rustc-link-arg=-Wl,--end-group");
|
||||
|
||||
emit_sdl2_link_flags(&vitasdk);
|
||||
}
|
||||
|
||||
fn require_file(path: PathBuf) -> PathBuf {
|
||||
assert!(path.is_file(), "required Vita build artifact is missing: {}", path.display());
|
||||
path
|
||||
}
|
||||
|
||||
fn emit_sdl2_link_flags(vitasdk: &str) {
|
||||
let pkg_config = Path::new(vitasdk).join("bin/arm-vita-eabi-pkg-config");
|
||||
let output = Command::new(&pkg_config)
|
||||
.args(["--libs", "sdl2"])
|
||||
.output()
|
||||
.expect("failed to execute arm-vita-eabi-pkg-config");
|
||||
|
||||
if !output.status.success() {
|
||||
panic!(
|
||||
"arm-vita-eabi-pkg-config --libs sdl2 failed: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
let libs = String::from_utf8(output.stdout).expect("pkg-config output must be UTF-8");
|
||||
for token in libs.split_whitespace() {
|
||||
if let Some(path) = token.strip_prefix("-L") {
|
||||
println!("cargo:rustc-link-search=native={path}");
|
||||
} else if let Some(lib) = token.strip_prefix("-l") {
|
||||
println!("cargo:rustc-link-lib={lib}");
|
||||
} else if token.starts_with("-Wl,") {
|
||||
println!("cargo:rustc-link-arg={token}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +1,104 @@
|
||||
extern crate sdl2;
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::env;
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::os::raw::{c_char, c_int, c_void};
|
||||
|
||||
unsafe extern "C" {
|
||||
fn external_main(argc: c_int, argv: *const *const c_char, external_window: *mut c_void, external_renderer: *mut c_void) -> c_int;
|
||||
fn SDL_Init(flags: u32) -> c_int;
|
||||
fn SDL_Quit();
|
||||
fn SDL_CreateWindow(
|
||||
title: *const c_char,
|
||||
x: c_int,
|
||||
y: c_int,
|
||||
w: c_int,
|
||||
h: c_int,
|
||||
flags: u32,
|
||||
) -> *mut c_void;
|
||||
fn SDL_CreateRenderer(window: *mut c_void, index: c_int, flags: u32) -> *mut c_void;
|
||||
fn SDL_DestroyRenderer(renderer: *mut c_void);
|
||||
fn SDL_DestroyWindow(window: *mut c_void);
|
||||
fn SDL_GetError() -> *const c_char;
|
||||
}
|
||||
|
||||
fn main() -> Result<(), String> {
|
||||
let sdl_context = sdl2::init()?;
|
||||
let video_subsystem = sdl_context.video()?;
|
||||
const SDL_INIT_AUDIO: u32 = 0x0000_0010;
|
||||
const SDL_INIT_VIDEO: u32 = 0x0000_0020;
|
||||
const SDL_INIT_GAMECONTROLLER: u32 = 0x0000_2000;
|
||||
const SDL_INIT_EVENTS: u32 = 0x0000_4000;
|
||||
const SDL_WINDOWPOS_CENTERED: i32 = 0x2FFF_0000u32 as i32;
|
||||
const SDL_RENDERER_ACCELERATED: u32 = 0x0000_0002;
|
||||
const SDL_RENDERER_PRESENTVSYNC: u32 = 0x0000_0004;
|
||||
|
||||
let _ = env::set_current_dir("app0:/");
|
||||
unsafe {
|
||||
if SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS | SDL_INIT_GAMECONTROLLER) != 0 {
|
||||
return Err(sdl_error("SDL_Init"));
|
||||
}
|
||||
}
|
||||
|
||||
let title = CString::new("ARMSX PSVita Host").map_err(|err| err.to_string())?;
|
||||
let width = 960;
|
||||
let height = 544;
|
||||
let window = video_subsystem
|
||||
.window("ARMSX PSVita Host", width, height)
|
||||
.position_centered()
|
||||
.build()
|
||||
.map_err(|e| e.to_string())?;
|
||||
let raw_window = unsafe {
|
||||
SDL_CreateWindow(
|
||||
title.as_ptr(),
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
)
|
||||
};
|
||||
if raw_window.is_null() {
|
||||
unsafe { SDL_Quit() };
|
||||
return Err(sdl_error("SDL_CreateWindow"));
|
||||
}
|
||||
|
||||
let canvas = window
|
||||
.into_canvas()
|
||||
.present_vsync()
|
||||
.accelerated()
|
||||
.build()
|
||||
.map_err(|e| e.to_string())?;
|
||||
let raw_renderer =
|
||||
unsafe { SDL_CreateRenderer(raw_window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC) };
|
||||
if raw_renderer.is_null() {
|
||||
unsafe {
|
||||
SDL_DestroyWindow(raw_window);
|
||||
SDL_Quit();
|
||||
}
|
||||
return Err(sdl_error("SDL_CreateRenderer"));
|
||||
}
|
||||
|
||||
let args = vec!["psvita", "", ""];
|
||||
let cstrings: Vec<CString> = args.iter().map(|s| CString::new(*s).unwrap()).collect();
|
||||
let mut args = env::args().collect::<Vec<_>>();
|
||||
if args.is_empty() {
|
||||
args.push(String::from("armsx"));
|
||||
}
|
||||
let cstrings: Vec<CString> = args
|
||||
.iter()
|
||||
.map(|s| CString::new(s.as_str()).map_err(|err| err.to_string()))
|
||||
.collect::<Result<_, _>>()?;
|
||||
let mut ptrs: Vec<*const c_char> = cstrings.iter().map(|s| s.as_ptr()).collect();
|
||||
ptrs.push(std::ptr::null());
|
||||
|
||||
let raw_window = canvas.window().raw() as *mut c_void;
|
||||
let raw_renderer = canvas.raw() as *mut c_void;
|
||||
|
||||
let ret = unsafe { external_main((ptrs.len() - 1) as c_int, ptrs.as_ptr(), raw_window, raw_renderer) };
|
||||
|
||||
unsafe {
|
||||
SDL_DestroyRenderer(raw_renderer);
|
||||
SDL_DestroyWindow(raw_window);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
if ret != 0 {
|
||||
return Err(format!("external_main returned non-zero: {}", ret));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sdl_error(prefix: &str) -> String {
|
||||
let message = unsafe {
|
||||
let raw = SDL_GetError();
|
||||
if raw.is_null() {
|
||||
String::from("unknown SDL error")
|
||||
} else {
|
||||
CStr::from_ptr(raw).to_string_lossy().into_owned()
|
||||
}
|
||||
};
|
||||
|
||||
format!("{prefix} failed: {message}")
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
APPICON ICON "icons/ArmsxDesktop.ico"
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.8 KiB |