Vita porting

This commit is contained in:
2025-12-22 15:00:22 +01:00
parent 578f90b3cc
commit 73524105c9
17 changed files with 330 additions and 5 deletions

1
src/platform/vita/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
build/

View File

@@ -0,0 +1,101 @@
cmake_minimum_required(VERSION 3.16)
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
if(DEFINED ENV{VITASDK})
set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file")
else()
message(FATAL_ERROR "Please define VITASDK to point to your SDK path!")
endif()
endif()
project(sm)
include("${VITASDK}/share/vita.cmake" REQUIRED)
find_package(SDL2 REQUIRED PATHS ${VITASDK}/arm-vita-eabi/lib/cmake/SDL2)
set(VITA_APP_NAME "Super Metroid")
set(VITA_TITLEID "SPMETROID")
set(VITA_VERSION "00.10")
set(VITA_VPKNAME "sm")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q,--wrap,fopen,--wrap,mkdir -Ofast -fomit-frame-pointer -ffast-math \
-mfloat-abi=hard -ffast-math -fsingle-precision-constant -fno-tree-vectorize -mtune=cortex-a9 -mfpu=neon -DNDEBUG -D__VITA__")
add_executable(${PROJECT_NAME}
../../main.c
../../sm_80.c
../../sm_81.c
../../sm_82.c
../../sm_84.c
../../sm_85.c
../../sm_86.c
../../sm_87.c
../../sm_88.c
../../sm_89.c
../../sm_8b.c
../../sm_8d.c
../../sm_8f.c
../../sm_90.c
../../sm_91.c
../../sm_92.c
../../sm_93.c
../../sm_94.c
../../sm_9b.c
../../sm_a0.c
../../sm_a2.c
../../sm_a3.c
../../sm_a4.c
../../sm_a5.c
../../sm_a6.c
../../sm_a7.c
../../sm_a8.c
../../sm_a9.c
../../sm_aa.c
../../sm_ad.c
../../sm_b2.c
../../sm_b3.c
../../sm_b4.c
../../sm_cpu_infra.c
../../sm_rtl.c
../../snes/apu.c
../../snes/cart.c
../../snes/cpu.c
../../snes/dma.c
../../snes/dsp.c
../../snes/input.c
../../snes/ppu.c
../../snes/snes.c
../../snes/snes_other.c
../../snes/spc.c
../../spc_player.c
../../util.c
../../config.c
../../tracing.c
src/vita_impl.c
)
target_link_libraries(${PROJECT_NAME}
SDL2::SDL2
)
vita_create_self(${PROJECT_NAME}.self ${PROJECT_NAME})
vita_create_vpk(${PROJECT_NAME}.vpk ${VITA_TITLEID} ${PROJECT_NAME}.self
VERSION ${VITA_VERSION}
NAME ${VITA_APP_NAME}
FILE sm.ini sm.ini
FILE sce_sys/icon0.png sce_sys/icon0.png
FILE sce_sys/livearea/contents/bg.png sce_sys/livearea/contents/bg.png
FILE sce_sys/livearea/contents/startup.png sce_sys/livearea/contents/startup.png
FILE sce_sys/livearea/contents/template.xml sce_sys/livearea/contents/template.xml
)
set(PSVITAIP "192.168.178.32" CACHE STRING "PSVita IP (for FTP access)")
add_custom_target(send
COMMAND echo Sending to ${PSVITAIP}...
COMMAND echo destroy | nc ${PSVITAIP} 1338
COMMAND cp sm.self eboot.bin
COMMAND curl -T ftp://${PSVITAIP}:1337/ux0:/app/${VITA_TITLEID}/
COMMAND echo launch ${VITA_TITLEID} | nc ${PSVITAIP} 1338
DEPENDS ${VITA_VPKNAME}.vpk-vpk
)

View File

@@ -0,0 +1,4 @@
# Super Metroid Vita porting
To run, you need sm.smc (sha1 hash da957f0d63d14cb441d215462904c4fa8519c613). Create a directory in <code>ux0:data/smetroid</code> and put the file in it.
Finally, install sm.vpk using VitaShell and the app bubble will appear in your LiveArea.

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

View File

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

44
src/platform/vita/sm.ini Normal file
View File

@@ -0,0 +1,44 @@
[General]
# Automatically save state on quit and reload on start
Autosave = 0
# Disable the SDL_Delay that happens each frame (Gives slightly better perf if your
# display is set to exactly 60hz)
DisableFrameDelay = 1
[Graphics]
# Window size ( Auto or WidthxHeight )
WindowSize = 960x544
# Window scale (1=100%, 2=200%, 3=300%, etc.)
WindowScale = 1
# Use an optimized (but potentially more buggy) SNES PPU implementation
NewRenderer = 1
# Display the world map with higher resolution
EnhancedMode7 = 0
# Don't keep the aspect ratio
IgnoreAspectRatio = 1
# Enable this option to remove the sprite limits per scan line
NoSpriteLimits = 0
[Sound]
EnableAudio = 1
# DSP frequency in samples per second (e.g. 48000, 44100, 32000, 22050, 11025)
AudioFreq = 48000
# number of separate sound channels (1=mono, 2=stereo)
AudioChannels = 2
# Audio buffer size in samples (power of 2; e.g., 4096, 2048, 1024) [try 1024 if sound is crackly]. The higher the more lag before you hear sounds.
AudioSamples = 512
[GamepadMap]
# Any keys used in KeyMap can be used also in this section.
# The shoulder button is called L1/Lb and L2, and the thumbstick button is called L3
Controls = DpadUp, DpadDown, DpadLeft, DpadRight, Back, Start, B, A, Y, X, Lb, Rb

View File

@@ -0,0 +1,114 @@
#include <vitasdk.h>
#include <stdio.h>
#include <SDL.h>
#include <sys/stat.h>
#include <stdbool.h>
#include "../../../types.h"
#include "../../../util.h"
int __real_mkdir(const char *fname, mode_t mode);
FILE * __real_fopen(char *fname, char *mode);
int _newlib_heap_size_user = 128 * 1024 * 1024;
void VitaImpl_Init() {
scePowerSetArmClockFrequency(444);
scePowerSetBusClockFrequency(222);
scePowerSetGpuClockFrequency(222);
scePowerSetGpuXbarClockFrequency(166);
//To create base directory if necessary
mkdir("", 0777);
}
void OpenGLRenderer_Create(struct RendererFuncs *funcs) {
}
// State Vita SDL Renderer
static SDL_Renderer *vita_renderer;
static SDL_Texture *vita_texture;
static SDL_Rect window_rect, rendering_rect, texture_rect;
static bool VitaRenderer_Init(SDL_Window *window) {
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == NULL) {
printf("Failed to create renderer: %s\n", SDL_GetError());
return false;
}
vita_renderer = renderer;
vita_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 256, 240);
if (vita_texture == NULL) {
printf("Failed to create texture: %s\n", SDL_GetError());
return false;
}
window_rect.x = 169;
window_rect.y = 0;
window_rect.w = 622;
window_rect.h = 544;
rendering_rect.x = 0;
rendering_rect.y = 0;
rendering_rect.w = 256;
rendering_rect.h = 240;
texture_rect.x = 0;
texture_rect.y = 0;
texture_rect.w = 256;
texture_rect.h = 224;
return true;
}
static void VitaRenderer_Destroy(void) {
SDL_DestroyTexture(vita_texture);
SDL_DestroyRenderer(vita_renderer);
}
static void VitaRenderer_BeforeFrame(void **memoryBuffer) {
int pitch;
if (SDL_LockTexture(vita_texture, &rendering_rect, memoryBuffer, &pitch) != 0) {
printf("Failed to lock texture: %s\n", SDL_GetError());
//TODO fail program
}
}
static void VitaRenderer_BeginDraw(int width, int height, uint8 **pixels, int *pitch) {
*pixels = NULL;
}
static void VitaRenderer_EndDraw(void) {
SDL_UnlockTexture(vita_texture);
SDL_RenderClear(vita_renderer);
SDL_RenderCopy(vita_renderer, vita_texture, &texture_rect, &window_rect);
SDL_RenderPresent(vita_renderer);
}
static const struct RendererFuncs kVitaRendererFuncs = {
&VitaRenderer_Init,
&VitaRenderer_Destroy,
&VitaRenderer_BeforeFrame,
&VitaRenderer_BeginDraw,
&VitaRenderer_EndDraw,
};
void VitaRenderer_Create(struct RendererFuncs *funcs) {
*funcs = kVitaRendererFuncs;
}
int __wrap_mkdir(const char *fname, mode_t mode) {
char patched_fname[256];
sprintf(patched_fname, "ux0:data/smetroid/%s", fname);
return __real_mkdir(patched_fname, mode);
}
FILE *__wrap_fopen(char *fname, char *mode) {
//Use the vpk-provided ini
if(strcmp(fname, "sm.ini") == 0) {
return __real_fopen(fname, mode);
}
char patched_fname[256];
sprintf(patched_fname, "ux0:data/smetroid/%s", fname);
return __real_fopen(patched_fname, mode);
}

View File

@@ -0,0 +1,5 @@
#pragma once
void VitaImpl_Init();
void VitaRenderer_Create(struct RendererFuncs *funcs);
bool VitaRenderer_BeforeFrame(void **memoryBuffer);