Add PSVita port (#541)
* add psvita to cmake * no PIE for vita * add modules to vpk * use custom pvr apphint * select correct renderer for sdl renderer * patch sdl3 shaders, got something on screen! * use proper cmake patch for sdl * add missing module * remove test window which causes a bug in the vita sdl port to show up * add gxm renderer (not working with display yet) * avoid sdl renderer for vita, seems broken * make gxm renderer work with new d3drm * fix rendering somewhat, some geometry shows up * support paletted textures directly to avoid copying the texture twice * fix Draw2DImage * make 3d work, broken lights * clean up a bit * fix normals matrix * remove some unneeded changes * forgot env var * wrong env dest * run clang format * correct texture address mode, use tlsf instead of sceClibMspace * double buffered uniforms seem to work now * missed a line * update GXMRenderer_EnumDevice * hopefully actually fix uniform buffers * run clang-format * remove a change thats not needed * improve fragment shader performance * add vita to dist folder * add base for vita config app * add config self to vpk * transform touch events to virtual size * add livearea graphics * Update cmake file to include livearea assets * put manual in the right place * add sample rco * add messagebox on vita * triple buffer textures because fences arent a thing on vita and making draw&cpu sync would be too slow * make config app not crash on launch * change defaults * update gxm renderer with interface changes * split 2d and 3d shaders completely * update gxm renderer * fix transition on gxm * clang format * move config cmake * move CONFIG_vita * always clear before drawing 2d image * hopefully fix windows build * clang-format fix broken includes * order again * undo moving qt cmake to its own list * move uic search path * use ifdefs for all d3drm backends, cpack to generate vpk * cmake wrong escape * small cleanups in gxm renderer * defer texture delete to avoid overwriting the texture during a frame * clang-format * more of the layout for config * remove top buttons * use SceAppSettings instead of custom ui * use select for back to info center on vita, to make screenshots possible again * remove accidentally left in add_subdirectory * adjust diskpath to be like other ports * use vita_create_vpk and not cpack * gxm: msaa support, fix wrong file path * gxm: add mipmaps (disabled) * clang-format * fix open isle.ini with fopen * add missing strings * use iniparser_set not dictionary_set * add default save path to config * load config app after initializing ini on vita * fix config build * change the default disk & cd path, update the paf library * update paf library headers * include orders for clang-format * clean up * make shader compiler not required * move asm language * warn instead of error when shader source is changed when no compiler is found --------- Co-authored-by: Li <li@silica.codes> Co-authored-by: Christian Semmler <mail@csemmler.com>
23
.github/workflows/ci.yml
vendored
@ -48,6 +48,7 @@ jobs:
|
||||
- { name: 'Nintendo 3DS', os: 'ubuntu-latest', generator: 'Ninja', dx5: false, config: false, n3ds: true, werror: true, clang-tidy: false, container: 'devkitpro/devkitarm:latest', cmake-args: '-DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/3DS.cmake' }
|
||||
- { name: 'Xbox One', os: 'windows-latest', generator: 'Visual Studio 17 2022', dx5: false, config: false, msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64', cmake-args: '-DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0.26100.0', xbox-one: true}
|
||||
- { name: 'Android', os: 'ubuntu-latest', generator: 'Ninja', dx5: false, config: false, android: true, werror: true, clang-tidy: false,}
|
||||
- { name: 'Vita', os: 'ubuntu-latest', generator: 'Ninja', dx5: false, config: false, vita: true, werror: true, clang-tidy: false, cmake-args: '--toolchain /usr/local/vitasdk/share/vita.toolchain.cmake'}
|
||||
steps:
|
||||
- name: Setup vcvars
|
||||
if: ${{ !!matrix.msvc }}
|
||||
@ -117,6 +118,18 @@ jobs:
|
||||
- name: Setup ninja
|
||||
if: ${{ matrix.msvc }}
|
||||
uses: ashutoshvarma/setup-ninja@master
|
||||
|
||||
- name: Setup vitasdk
|
||||
if: ${{ matrix.vita }}
|
||||
run: |
|
||||
git clone https://github.com/vitasdk/vdpm
|
||||
cd vdpm
|
||||
./bootstrap-vitasdk.sh
|
||||
export VITASDK=/usr/local/vitasdk
|
||||
export PATH=$VITASDK/bin:$PATH
|
||||
echo "VITASDK=/usr/local/vitasdk" >> $GITHUB_ENV
|
||||
echo "$VITASDK/bin" >> $GITHUB_PATH
|
||||
./install-all.sh
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@ -177,7 +190,7 @@ jobs:
|
||||
run: cmake --build build --verbose --config Release
|
||||
|
||||
- name: Package (CPack)
|
||||
if: ${{ !matrix.n3ds && !matrix.android }}
|
||||
if: ${{ !matrix.n3ds && !matrix.android && !matrix.vita }}
|
||||
run: |
|
||||
cd build
|
||||
success=0
|
||||
@ -225,6 +238,13 @@ jobs:
|
||||
mkdir dist
|
||||
mv *.3dsx dist/
|
||||
mv *.cia dist/
|
||||
|
||||
- name: Package (Vita)
|
||||
if: ${{ matrix.vita }}
|
||||
run: |
|
||||
cd build
|
||||
mkdir dist
|
||||
mv *.vpk dist/
|
||||
|
||||
- name: Package (Android)
|
||||
if: ${{ matrix.android }}
|
||||
@ -246,6 +266,7 @@ jobs:
|
||||
build/dist/*.3dsx
|
||||
build/dist/*.cia
|
||||
build/dist/*.apk
|
||||
build/dist/*.vpk
|
||||
|
||||
flatpak:
|
||||
name: "Flatpak (${{ matrix.arch }})"
|
||||
|
||||
@ -46,18 +46,18 @@ option(ISLE_BUILD_ASSETS "Build assets from the /assets directory" OFF)
|
||||
option(ISLE_ASAN "Enable Address Sanitizer" OFF)
|
||||
option(ISLE_UBSAN "Enable Undefined Behavior Sanitizer" OFF)
|
||||
option(ISLE_WERROR "Treat warnings as errors" OFF)
|
||||
option(ISLE_DEBUG "Enable imgui debug" ON)
|
||||
cmake_dependent_option(ISLE_DEBUG "Enable imgui debug" ON "NOT VITA" OFF)
|
||||
cmake_dependent_option(ISLE_USE_DX5 "Build with internal DirectX 5 SDK" "${NOT_MINGW}" "WIN32;CMAKE_SIZEOF_VOID_P EQUAL 4" OFF)
|
||||
cmake_dependent_option(ISLE_MINIWIN "Use miniwin" ON "NOT ISLE_USE_DX5" OFF)
|
||||
cmake_dependent_option(ISLE_EXTENSIONS "Use extensions" ON "NOT ISLE_USE_DX5;NOT WINDOWS_STORE" OFF)
|
||||
cmake_dependent_option(ISLE_BUILD_CONFIG "Build CONFIG.EXE application" ON "MSVC OR ISLE_MINIWIN;NOT NINTENDO_3DS;NOT WINDOWS_STORE" OFF)
|
||||
cmake_dependent_option(ISLE_BUILD_CONFIG "Build CONFIG.EXE application" ON "MSVC OR ISLE_MINIWIN;NOT NINTENDO_3DS;NOT WINDOWS_STORE;NOT VITA" OFF)
|
||||
cmake_dependent_option(ISLE_COMPILE_SHADERS "Compile shaders" ON "SDL_SHADERCROSS_BIN;TARGET Python3::Interpreter" OFF)
|
||||
option(CMAKE_POSITION_INDEPENDENT_CODE "Build with -fPIC" ON)
|
||||
cmake_dependent_option(CMAKE_POSITION_INDEPENDENT_CODE "Build with -fPIC" ON "NOT VITA" OFF)
|
||||
option(ENABLE_CLANG_TIDY "Enable clang-tidy")
|
||||
option(DOWNLOAD_DEPENDENCIES "Download dependencies" ON)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" CACHE PATH "Directory where to put executables and dll")
|
||||
set(ISLE_EMSCRIPTEN_HOST "" CACHE STRING "Host URL for Emscripten streaming (e.g., https://test.com)")
|
||||
cmake_dependent_option(BUILD_SHARED_LIBS "Build lego1 as a shared library" ON "NOT EMSCRIPTEN" OFF)
|
||||
cmake_dependent_option(BUILD_SHARED_LIBS "Build lego1 as a shared library" ON "NOT EMSCRIPTEN;NOT VITA" OFF)
|
||||
|
||||
message(STATUS "Isle app: ${ISLE_BUILD_APP}")
|
||||
message(STATUS "Config app: ${ISLE_BUILD_CONFIG}")
|
||||
@ -90,6 +90,7 @@ if (DOWNLOAD_DEPENDENCIES)
|
||||
SDL3
|
||||
GIT_REPOSITORY "https://github.com/libsdl-org/SDL.git"
|
||||
GIT_TAG "main"
|
||||
UPDATE_DISCONNECTED TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
endif()
|
||||
@ -100,6 +101,7 @@ if (DOWNLOAD_DEPENDENCIES)
|
||||
iniparser
|
||||
GIT_REPOSITORY "https://gitlab.com/iniparser/iniparser.git"
|
||||
GIT_TAG "main"
|
||||
UPDATE_DISCONNECTED TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
block()
|
||||
@ -598,6 +600,12 @@ if (ISLE_BUILD_APP)
|
||||
ISLE/android/config.cpp
|
||||
)
|
||||
endif()
|
||||
if(VITA)
|
||||
target_sources(isle PRIVATE
|
||||
ISLE/vita/config.cpp
|
||||
ISLE/vita/messagebox.cpp
|
||||
)
|
||||
endif()
|
||||
if(Python3_FOUND)
|
||||
if(NOT DEFINED PYTHON_PIL_AVAILABLE)
|
||||
execute_process(
|
||||
@ -639,18 +647,18 @@ if (ISLE_BUILD_CONFIG)
|
||||
qt_add_executable(isle-config WIN32
|
||||
LEGO1/mxdirectx/mxdirectxinfo.cpp
|
||||
LEGO1/mxdirectx/legodxinfo.cpp
|
||||
CONFIG/config.cpp
|
||||
CONFIG/AboutDlg.cpp
|
||||
CONFIG/MainDlg.cpp
|
||||
CONFIG/detectdx5.cpp
|
||||
CONFIG/res/config.rc
|
||||
CONFIG/res/config.qrc
|
||||
CONFIG/qt/config.cpp
|
||||
CONFIG/qt/AboutDlg.cpp
|
||||
CONFIG/qt/MainDlg.cpp
|
||||
CONFIG/qt/detectdx5.cpp
|
||||
CONFIG/qt/res/config.rc
|
||||
CONFIG/qt/res/config.qrc
|
||||
)
|
||||
target_link_libraries(isle-config PRIVATE Qt6::Core Qt6::Widgets)
|
||||
set_property(TARGET isle-config PROPERTY AUTOMOC ON)
|
||||
set_property(TARGET isle-config PROPERTY AUTORCC ON)
|
||||
set_property(TARGET isle-config PROPERTY AUTOUIC ON)
|
||||
set_property(TARGET isle-config PROPERTY AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/CONFIG/res")
|
||||
set_property(TARGET isle-config PROPERTY AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/CONFIG/qt/res")
|
||||
list(APPEND isle_targets isle-config)
|
||||
target_compile_definitions(isle-config PRIVATE _AFXDLL MXDIRECTX_FOR_CONFIG)
|
||||
target_include_directories(isle-config PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/LEGO1")
|
||||
@ -782,7 +790,7 @@ endif()
|
||||
if(BUILD_SHARED_LIBS)
|
||||
list(APPEND install_extra_targets lego1)
|
||||
endif()
|
||||
if (NOT (NINTENDO_3DS OR WINDOWS_STORE))
|
||||
if (NOT (NINTENDO_3DS OR WINDOWS_STORE OR VITA))
|
||||
install(TARGETS isle ${install_extra_targets}
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
@ -881,6 +889,35 @@ if(WINDOWS_STORE)
|
||||
PATTERN "*/*.msix"
|
||||
PATTERN "*/*.msixbundle")
|
||||
endif()
|
||||
if(VITA)
|
||||
include("${VITASDK}/share/vita.cmake" REQUIRED)
|
||||
|
||||
add_subdirectory(CONFIG/vita)
|
||||
|
||||
set(ISLE_PACKAGE_NAME "vita-isle")
|
||||
set(VITA_APP_NAME "Lego Island")
|
||||
set(VITA_TITLEID "LEGO00001")
|
||||
set(VITA_VERSION "01.00")
|
||||
|
||||
vita_create_self(isle.self isle UNSAFE)
|
||||
|
||||
set(VPK_FILE_ARGS "")
|
||||
file(GLOB_RECURSE SCE_SYS_FILES packaging/vita/sce_sys/*)
|
||||
foreach(FILE ${SCE_SYS_FILES})
|
||||
file(RELATIVE_PATH REL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/packaging/vita/ ${FILE})
|
||||
list(APPEND VPK_FILE_ARGS FILE ${FILE} ${REL_FILE})
|
||||
endforeach()
|
||||
|
||||
vita_create_vpk(isle.vpk ${VITA_TITLEID} isle.self
|
||||
FILE "${CMAKE_CURRENT_BINARY_DIR}/CONFIG/vita/isle-config.self" isle-config.self
|
||||
FILE "${CMAKE_CURRENT_BINARY_DIR}/CONFIG/vita/config_plugin.rco" config_plugin.rco
|
||||
VERSION ${VITA_VERSION}
|
||||
NAME ${VITA_APP_NAME}
|
||||
${VPK_FILE_ARGS}
|
||||
)
|
||||
add_dependencies(isle.vpk-vpk config_plugin.rco_target)
|
||||
endif()
|
||||
|
||||
if(MSVC OR IOS)
|
||||
set(CPACK_GENERATOR ZIP)
|
||||
if(IOS)
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 477 B After Width: | Height: | Size: 477 B |
|
Before Width: | Height: | Size: 397 B After Width: | Height: | Size: 397 B |
|
Before Width: | Height: | Size: 526 B After Width: | Height: | Size: 526 B |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
73
CONFIG/vita/CMakeLists.txt
Normal file
@ -0,0 +1,73 @@
|
||||
cmake_minimum_required(VERSION 3.25...4.0 FATAL_ERROR)
|
||||
|
||||
project(isle-config LANGUAGES CXX C VERSION 0.1)
|
||||
|
||||
include("${VITASDK}/share/vita.cmake" REQUIRED)
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
ScePaf_External
|
||||
URL https://github.com/olebeck/ScePaf/releases/download/v21/ScePaf-1.0.0.zip
|
||||
URL_HASH SHA256=357b914a5c99ea17afe0edc8787a05cbf2ecce2f1d73bb9be69f371a294b8943
|
||||
UPDATE_DISCONNECTED TRUE
|
||||
)
|
||||
FetchContent_MakeAvailable(ScePaf_External)
|
||||
|
||||
|
||||
FetchContent_Declare(
|
||||
iniparser_paf
|
||||
GIT_REPOSITORY "https://gitlab.com/iniparser/iniparser.git"
|
||||
GIT_TAG "v4.2.6"
|
||||
UPDATE_DISCONNECTED TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
PATCH_COMMAND patch -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/iniparser_paf.patch
|
||||
)
|
||||
block()
|
||||
set(BUILD_DOCS off)
|
||||
set(BUILD_SHARED_LIBS off)
|
||||
FetchContent_MakeAvailable(iniparser_paf)
|
||||
endblock()
|
||||
|
||||
add_executable(isle-config
|
||||
src/paf_runtime.cpp
|
||||
src/app.cpp
|
||||
)
|
||||
|
||||
set_target_properties(isle-config PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
target_compile_options(isle-config PRIVATE
|
||||
-fno-rtti -fno-exceptions -Wl,-q -Wall -fno-builtin -fshort-wchar -Wno-unused-function -Wno-sign-compare -fno-use-cxa-atexit
|
||||
)
|
||||
|
||||
target_link_options(isle-config PRIVATE
|
||||
-nostartfiles -nostdlib
|
||||
)
|
||||
|
||||
target_link_libraries(isle-config PRIVATE
|
||||
SceAppMgr_stub
|
||||
SceLibKernel_stub
|
||||
SceSysmodule_stub
|
||||
|
||||
ScePafToplevel_stub
|
||||
ScePafResource_stub
|
||||
ScePafWidget_stub
|
||||
ScePafCommon_stub
|
||||
ScePafStdc_stub
|
||||
SceAppSettings_stub
|
||||
SceFios2_stub
|
||||
SceLibc_stub
|
||||
|
||||
iniparser_paf-static
|
||||
)
|
||||
|
||||
vita_create_self(isle-config.self isle-config
|
||||
CONFIG exports.yml
|
||||
UNSAFE
|
||||
STRIPPED
|
||||
REL_OPTIMIZE
|
||||
)
|
||||
|
||||
include(${scepaf_external_SOURCE_DIR}/rco.cmake)
|
||||
make_rco(cxml/config_plugin.xml config_plugin.rco)
|
||||
34
CONFIG/vita/cxml/config_plugin.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<resource version="0.1" type="normal" id="config_plugin">
|
||||
<filetable>
|
||||
<file src="settings.xml" type="application/xml" id="settings.xml" compress="off" />
|
||||
</filetable>
|
||||
|
||||
<stringtable>
|
||||
<!--
|
||||
<locale src_="locale/ja.xml" compress="on" id="ja" />
|
||||
-->
|
||||
<locale src="locale/en.xml" compress="on" id="en" />
|
||||
<!--
|
||||
<locale src_="locale/en-gb.xml" compress="on" id="en-gb" />
|
||||
<locale src_="locale/zh-s.xml" compress="on" id="zh-s" />
|
||||
<locale src_="locale/zh-t.xml" compress="on" id="zh-t" />
|
||||
<locale src_="locale/da.xml" compress="on" id="da" />
|
||||
<locale src_="locale/nl.xml" compress="on" id="nl" />
|
||||
<locale src_="locale/fi.xml" compress="on" id="fi" />
|
||||
<locale src_="locale/fr.xml" compress="on" id="fr" />
|
||||
<locale src_="locale/de.xml" compress="on" id="de" />
|
||||
<locale src_="locale/it.xml" compress="on" id="it" />
|
||||
<locale src_="locale/ko.xml" compress="on" id="ko" />
|
||||
<locale src_="locale/no.xml" compress="on" id="no" />
|
||||
<locale src_="locale/pl.xml" compress="on" id="pl" />
|
||||
<locale src_="locale/pt.xml" compress="on" id="pt" />
|
||||
<locale src_="locale/ru.xml" compress="on" id="ru" />
|
||||
<locale src_="locale/es.xml" compress="on" id="es" />
|
||||
<locale src_="locale/sv.xml" compress="on" id="sv" />
|
||||
<locale src_="locale/pt-br.xml" compress="on" id="pt-br" />
|
||||
<locale src_="locale/tr.xml" compress="on" id="tr" />
|
||||
-->
|
||||
</stringtable>
|
||||
</resource>
|
||||
57
CONFIG/vita/cxml/locale/en.xml
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<stringset>
|
||||
<!-- Main Page -->
|
||||
<string id="msg_lego_island_config" src="Lego Island Config"/>
|
||||
<string id="msg_page_game" src="Game" />
|
||||
<string id="msg_page_graphics" src="Graphics" />
|
||||
<string id="msg_page_controls" src="Controls" />
|
||||
<string id="msg_page_extensions" src="Extensions" />
|
||||
|
||||
<!-- Game Page -->
|
||||
<string id="msg_disk_path" src="Disk Path" />
|
||||
<string id="msg_cd_path" src="CD Path" />
|
||||
<string id="msg_save_path" src="Save Path" />
|
||||
<string id="msg_3d_sound" src="3D Sound" />
|
||||
<string id="msg_music" src="Music" />
|
||||
|
||||
<string id="msg_transition_type" src="Transition Type" />
|
||||
<string id="msg_transition_none" src="none" />
|
||||
<string id="msg_transition_dissolve" src="dissolve" />
|
||||
<string id="msg_transition_mosaic" src="mosaic" />
|
||||
<string id="msg_transition_wipe_down" src="wipe down" />
|
||||
<string id="msg_transition_windows" src="windows" />
|
||||
|
||||
<!-- Graphics -->
|
||||
<string id="msg_island_texture_quality" src="Island Texture Quality" />
|
||||
<string id="msg_texture_fast" src="fast" />
|
||||
<string id="msg_texture_high" src="high" />
|
||||
|
||||
<string id="msg_island_model_quality" src="Island Model Quality" />
|
||||
<string id="msg_quality_low" src="low" />
|
||||
<string id="msg_quality_medium" src="medium" />
|
||||
<string id="msg_quality_high" src="high" />
|
||||
|
||||
<string id="msg_max_lod" src="Maximum LOD" />
|
||||
<string id="msg_max_actors" src="Maximum Actors" />
|
||||
|
||||
<string id="msg_msaa" src="MSAA" />
|
||||
<string id="msg_1x" src="1x" />
|
||||
<string id="msg_2x" src="2x" />
|
||||
<string id="msg_4x" src="4x" />
|
||||
|
||||
<!-- Controls -->
|
||||
<string id="msg_touch_control_scheme" src="Touch Control Scheme" />
|
||||
<string id="msg_virtual_gamepad" src="Virtual Gamepad" />
|
||||
<string id="msg_virtual_arrow_keys" src="Virtual Arrow Keys" />
|
||||
<string id="msg_virtual_mouse" src="Virtual Mouse" />
|
||||
<string id="msg_rumble" src="Rumble" />
|
||||
|
||||
<!-- Extensions -->
|
||||
<string id="msg_texture_loader_extension" src="Texture Loader Extension" />
|
||||
<string id="msg_texture_loader_path" src="Texture Loader Path" />
|
||||
|
||||
<!-- footer -->
|
||||
<string id="msg_save_exit" src="Save & Exit" />
|
||||
<string id="msg_save_launch" src="Save & Launch" />
|
||||
<string id="msg_exit" src="Exit" />
|
||||
</stringset>
|
||||
51
CONFIG/vita/cxml/settings.xml
Normal file
@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<application_settings version="1.0" bg_color="4.0, 21.0, 105.0, 255.0">
|
||||
<setting_list id="lego_island_config" title="msg_lego_island_config">
|
||||
<setting_list id="page_game" title="msg_page_game" style="edit" icon="tex_spanner">
|
||||
<text_field id="disk_path" title="msg_disk_path" max_length="255" min_length="0" keyboard_type="alphabet" key="disk_path" default_value=""/>
|
||||
<text_field id="cd_path" title="msg_cd_path" max_length="255" min_length="0" keyboard_type="alphabet" key="cd_path" default_value=""/>
|
||||
<text_field id="save_path" title="msg_save_path" max_length="255" min_length="0" keyboard_type="alphabet" key="save_path" default_value=""/>
|
||||
<list id="transition_type" title="msg_transition_type" key="transition_type" default_value="0">
|
||||
<list_item id="transition_none" title="msg_transition_none" value="0" />
|
||||
<list_item id="transition_dissolve" title="msg_transition_dissolve" value="2" />
|
||||
<list_item id="transition_mosaic" title="msg_transition_mosaic" value="3" />
|
||||
<list_item id="transition_wipe_down" title="msg_transition_wipe_down" value="4" />
|
||||
<list_item id="transition_windows" title="msg_transition_windows" value="5" />
|
||||
</list>
|
||||
<toggle_switch id="music" title="msg_music" key="music" default_value="1"/>
|
||||
<toggle_switch id="3d_sound" title="msg_3d_sound" key="3d_sound" default_value="1"/>
|
||||
</setting_list>
|
||||
|
||||
<setting_list id="page_graphics" title="msg_page_graphics" style="edit" icon="tex_spanner">
|
||||
<list id="island_texture_quality" title="msg_island_texture_quality" key="island_texture_quality" default_value="0">
|
||||
<list_item id="texture_fast" title="msg_texture_fast" value="0" />
|
||||
<list_item id="texture_high" title="msg_texture_high" value="1" />
|
||||
</list>
|
||||
<list id="island_model_quality" title="msg_island_model_quality" key="island_model_quality" default_value="0">
|
||||
<list_item id="quality_low" title="msg_quality_low" value="0" />
|
||||
<list_item id="quality_medium" title="msg_quality_medium" value="1" />
|
||||
<list_item id="quality_high" title="msg_quality_high" value="2" />
|
||||
</list>
|
||||
<list id="msaa" title="msg_msaa" key="msaa" default_value="4">
|
||||
<list_item id="msaa_1" title="msg_1x" value="1" />
|
||||
<list_item id="msaa_2" title="msg_2x" value="2" />
|
||||
<list_item id="msaa_4" title="msg_4x" value="4" />
|
||||
</list>
|
||||
</setting_list>
|
||||
|
||||
<setting_list id="page_controls" title="msg_page_controls" style="edit" icon="tex_spanner">
|
||||
<list id="touch_control_scheme" title="msg_touch_control_scheme" key="touch_control_scheme" default_value="0">
|
||||
<list_item id="virtual_gamepad" title="msg_virtual_gamepad" value="0" />
|
||||
<list_item id="virtual_arrow_keys" title="msg_virtual_arrow_keys" value="1" />
|
||||
<list_item id="virtual_mouse" title="msg_virtual_mouse" value="2" />
|
||||
</list>
|
||||
<toggle_switch id="rumble" title="msg_rumble" key="rumble" default_value="1"/>
|
||||
</setting_list>
|
||||
|
||||
<setting_list id="page_extensions" title="msg_page_extensions" style="edit" icon="tex_spanner">
|
||||
<toggle_switch id="texture_loader_extension" title="msg_texture_loader_extension" key="texture_loader_extension" default_value="0"/>
|
||||
<text_field id="texture_loader_path" title="msg_texture_loader_path" max_length="255" min_length="0" keyboard_type="alphabet" key="texture_loader_path" default_value=""/>
|
||||
</setting_list>
|
||||
</setting_list>
|
||||
</application_settings>
|
||||
8
CONFIG/vita/exports.yml
Normal file
@ -0,0 +1,8 @@
|
||||
isle-config:
|
||||
attributes: 0
|
||||
process_image: true
|
||||
version:
|
||||
major: 1
|
||||
minor: 1
|
||||
main:
|
||||
start: module_start
|
||||
53
CONFIG/vita/iniparser_paf.patch
Normal file
@ -0,0 +1,53 @@
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 4f7fdba..d388fc8 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
|
||||
project(
|
||||
- iniparser
|
||||
+ iniparser_paf
|
||||
DESCRIPTION "C library for parsing INI-style files"
|
||||
HOMEPAGE_URL https://gitlab.com/iniparser/iniparser/
|
||||
LANGUAGES C
|
||||
@@ -108,6 +108,19 @@ foreach(TARGET_TYPE ${TARGET_TYPES})
|
||||
-pedantic)
|
||||
endif(UNIX)
|
||||
|
||||
+ if(VITA)
|
||||
+ target_compile_options(
|
||||
+ ${TARGET_NAME}
|
||||
+ PRIVATE -Wl,-q -Wall -fshort-wchar)
|
||||
+ target_link_libraries(
|
||||
+ ${TARGET_NAME}
|
||||
+ PRIVATE SceLibc_stub
|
||||
+ )
|
||||
+ target_link_options(
|
||||
+ ${TARGET_NAME}
|
||||
+ PUBLIC -nostartfiles -nostdlib)
|
||||
+ endif()
|
||||
+
|
||||
# install targets
|
||||
install(
|
||||
TARGETS ${TARGET_NAME}
|
||||
diff --git a/src/iniparser.c b/src/iniparser.c
|
||||
index 1086b46..8e0e9c2 100644
|
||||
--- a/src/iniparser.c
|
||||
+++ b/src/iniparser.c
|
||||
@@ -14,6 +14,15 @@
|
||||
#include <inttypes.h>
|
||||
#include "iniparser.h"
|
||||
|
||||
+#ifdef __vita__
|
||||
+extern FILE* _Stderr;
|
||||
+#undef stderr
|
||||
+#define stderr _Stderr
|
||||
+extern const char _Ctype[];
|
||||
+#undef __locale_ctype_ptr
|
||||
+#define __locale_ctype_ptr() _Ctype
|
||||
+#endif
|
||||
+
|
||||
/*---------------------------- Defines -------------------------------------*/
|
||||
#define ASCIILINESZ (1024)
|
||||
#define INI_INVALID_KEY ((char*)-1)
|
||||
430
CONFIG/vita/src/app.cpp
Normal file
@ -0,0 +1,430 @@
|
||||
#include <app_settings.h>
|
||||
#include <iniparser.h>
|
||||
#include <paf.h>
|
||||
#include <psp2/appmgr.h>
|
||||
#include <psp2/io/fcntl.h>
|
||||
#include <psp2/kernel/clib.h>
|
||||
#include <psp2/kernel/modulemgr.h>
|
||||
#include <psp2/sysmodule.h>
|
||||
|
||||
int sceLibcHeapSize = 10 * 1024 * 1024;
|
||||
|
||||
const char* g_iniPath = "ux0:data/isledecomp/isle/isle.ini";
|
||||
|
||||
paf::Framework* g_fw;
|
||||
paf::Plugin* g_configPlugin;
|
||||
sce::AppSettings* g_appSettings;
|
||||
sce::AppSettings::Interface* g_appSetIf;
|
||||
|
||||
void merge_dicts(dictionary* dst, dictionary* src)
|
||||
{
|
||||
for (int i = 0; i < src->n; i++) {
|
||||
dictionary_set(dst, src->key[i], src->val[i]);
|
||||
}
|
||||
}
|
||||
|
||||
struct setting_map {
|
||||
const char* key_ini;
|
||||
const char* key_app;
|
||||
const char type;
|
||||
};
|
||||
|
||||
// mapping from ini key to settings.xml key
|
||||
const setting_map key_map[] = {
|
||||
// Game
|
||||
{"isle:diskpath", "disk_path", 's'},
|
||||
{"isle:cdpath", "cd_path", 's'},
|
||||
{"isle:savepath", "save_path", 's'},
|
||||
{"isle:Transition Type", "transition_type", 'i'},
|
||||
{"isle:Music", "music", 'b'},
|
||||
{"isle:3DSound", "3d_sound", 'b'},
|
||||
|
||||
// Graphics
|
||||
{"isle:Island Texture", "island_texture_quality", 'i'},
|
||||
{"isle:Island Quality", "island_model_quality", 'i'},
|
||||
//{"isle:Max LOD", "max_lod", 'f'},
|
||||
//{"isle:Max Allowed Extras", "max_extras", 'i' },
|
||||
{"isle:MSAA", "msaa", 'i'},
|
||||
|
||||
// Controls
|
||||
{"isle:Touch Scheme", "touch_control_scheme", 'i'},
|
||||
{"isle:Haptic", "rumble", 'b'},
|
||||
|
||||
// Extensions
|
||||
{"extensions:texture loader", "texture_loader_extension", 'b'},
|
||||
{"texture loader:texture path", "texture_loader_path", 's'}
|
||||
};
|
||||
|
||||
struct Config {
|
||||
sce::AppSettings* settings;
|
||||
dictionary* dict;
|
||||
char buffer[128];
|
||||
|
||||
#define GetDictInt(x, name) x = iniparser_getint(this->dict, name, x)
|
||||
#define GetDictFloat(x, name) x = iniparser_getdouble(this->dict, name, x)
|
||||
#define GetDictString(x, name) \
|
||||
{ \
|
||||
const char* val = iniparser_getstring(this->dict, name, nullptr); \
|
||||
if (val != nullptr) { \
|
||||
x = val; \
|
||||
} \
|
||||
}
|
||||
#define GetDictBool(x, name) x = iniparser_getboolean(this->dict, name, x)
|
||||
|
||||
#define SetDictBool(NAME, VALUE) \
|
||||
{ \
|
||||
const char* v = VALUE ? "true" : "false"; \
|
||||
sceClibPrintf("SetIniBool(%s, %s)\n", NAME, v); \
|
||||
iniparser_set(this->dict, NAME, v); \
|
||||
}
|
||||
#define SetDictInt(NAME, VALUE) \
|
||||
{ \
|
||||
sceClibSnprintf(buffer, sizeof(buffer), "%d", VALUE); \
|
||||
sceClibPrintf("SetIniInt(%s, %d)\n", NAME, VALUE); \
|
||||
iniparser_set(this->dict, NAME, buffer); \
|
||||
}
|
||||
#define SetDictFloat(NAME, VALUE) \
|
||||
{ \
|
||||
sceClibSnprintf(buffer, sizeof(buffer), "%f", VALUE); \
|
||||
sceClibPrintf("SetIniFloat(%s, %f)\n", NAME, VALUE); \
|
||||
iniparser_set(this->dict, NAME, buffer); \
|
||||
}
|
||||
#define SetDictString(NAME, VALUE) \
|
||||
{ \
|
||||
sceClibPrintf("SetString(%s, %s)\n", NAME, VALUE); \
|
||||
iniparser_set(this->dict, NAME, VALUE); \
|
||||
}
|
||||
|
||||
void Init(sce::AppSettings* settings)
|
||||
{
|
||||
this->settings = settings;
|
||||
dict = dictionary_new(0);
|
||||
|
||||
// set defaults
|
||||
iniparser_set(this->dict, "isle", nullptr);
|
||||
iniparser_set(dict, "extensions", NULL);
|
||||
iniparser_set(this->dict, "texture loader", nullptr);
|
||||
|
||||
SetDictString("isle:diskpath", "ux0:data/isledecomp/isle/disk");
|
||||
SetDictString("isle:cdpath", "ux0:data/isledecomp/isle/cd");
|
||||
SetDictString("isle:savepath", "ux0:data/isledecomp/isle");
|
||||
SetDictInt("isle:MSAA", 4);
|
||||
|
||||
SetDictInt("isle:Display Bit Depth", 32);
|
||||
SetDictBool("isle:Flip Surfaces", false);
|
||||
SetDictBool("isle:Full Screen", true);
|
||||
SetDictBool("isle:Exclusive Full Screen", true);
|
||||
SetDictBool("isle:Wide View Angle", true);
|
||||
|
||||
SetDictInt("isle:Transition Type", 3); // 3: Mosaic
|
||||
SetDictInt("isle:Touch Scheme", 2);
|
||||
|
||||
SetDictBool("isle:3DSound", true);
|
||||
SetDictBool("isle:Music", true);
|
||||
SetDictBool("isle:Haptic", true);
|
||||
|
||||
SetDictBool("isle:UseJoystick", true);
|
||||
SetDictInt("isle:JoystickIndex", 0);
|
||||
SetDictBool("isle:Draw Cursor", true);
|
||||
|
||||
SetDictBool("extensions:texture loader", false);
|
||||
SetDictString("texture loader:texture path", "textures/");
|
||||
|
||||
SetDictBool("isle:Back Buffers in Video RAM", true);
|
||||
|
||||
SetDictInt("isle:Island Quality", 2);
|
||||
SetDictInt("isle:Island Texture", 1);
|
||||
SetDictInt("isle:MSAA", 4);
|
||||
|
||||
SetDictFloat("isle:Max LOD", 3.5);
|
||||
SetDictInt("isle:Max Allowed Extras", 20);
|
||||
|
||||
SetDictInt("isle:Aspect Ratio", 0);
|
||||
SetDictInt("isle:Horizontal Resolution", 640);
|
||||
SetDictInt("isle:Vertical Resolution", 480);
|
||||
SetDictFloat("isle:Frame Delta", 10.0f);
|
||||
}
|
||||
|
||||
void LoadIni()
|
||||
{
|
||||
dictionary* ini = iniparser_load(g_iniPath);
|
||||
if (ini) {
|
||||
merge_dicts(this->dict, ini);
|
||||
iniparser_freedict(ini);
|
||||
}
|
||||
}
|
||||
|
||||
bool SaveIni()
|
||||
{
|
||||
FILE* fd = fopen(g_iniPath, "w");
|
||||
if (fd) {
|
||||
iniparser_dump_ini(this->dict, fd);
|
||||
}
|
||||
else {
|
||||
sceClibPrintf("failed to write isle.ini\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ToSettings()
|
||||
{
|
||||
const int len = sizeof(key_map) / sizeof(key_map[0]);
|
||||
for (int i = 0; i < len; i++) {
|
||||
const setting_map m = key_map[i];
|
||||
switch (m.type) {
|
||||
case 'f': // float, AppSettings doesnt have float so just use string
|
||||
case 's': {
|
||||
const char* value = iniparser_getstring(this->dict, m.key_ini, "");
|
||||
this->settings->SetString(m.key_app, value);
|
||||
sceClibPrintf("ini->settings %s = %s\n", m.key_app, value);
|
||||
break;
|
||||
}
|
||||
case 'i': {
|
||||
int32_t value = iniparser_getint(this->dict, m.key_ini, 0);
|
||||
this->settings->SetInt(m.key_app, value);
|
||||
sceClibPrintf("ini->settings %s = %d\n", m.key_app, value);
|
||||
break;
|
||||
}
|
||||
case 'b': {
|
||||
bool value = iniparser_getboolean(this->dict, m.key_ini, 0) == 1;
|
||||
this->settings->SetBool(m.key_app, value);
|
||||
sceClibPrintf("ini->settings %s = %s\n", m.key_app, value ? "true" : "false");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sceClibPrintf("invalid setting map entry %s %s %c\n", m.key_app, m.key_ini, m.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FromSettings()
|
||||
{
|
||||
const int len = sizeof(key_map) / sizeof(key_map[0]);
|
||||
for (int i = 0; i < len; i++) {
|
||||
const setting_map m = key_map[i];
|
||||
switch (m.type) {
|
||||
case 'f': // float, AppSettings doesnt have float so just use string
|
||||
case 's': {
|
||||
const char* def = iniparser_getstring(this->dict, m.key_ini, "");
|
||||
this->settings->GetString(m.key_app, this->buffer, sizeof(this->buffer), def);
|
||||
iniparser_set(this->dict, m.key_ini, buffer);
|
||||
sceClibPrintf("settings->ini %s = %s\n", m.key_ini, buffer);
|
||||
break;
|
||||
}
|
||||
case 'i': {
|
||||
int32_t value = iniparser_getint(this->dict, m.key_ini, 0);
|
||||
this->settings->GetInt(m.key_app, &value, value);
|
||||
SetDictInt(m.key_ini, value);
|
||||
sceClibPrintf("settings->ini %s = %d\n", m.key_ini, value);
|
||||
break;
|
||||
}
|
||||
case 'b': {
|
||||
bool value = iniparser_getboolean(this->dict, m.key_ini, 0) == 1;
|
||||
this->settings->GetBool(m.key_app, &value, value);
|
||||
SetDictBool(m.key_ini, value);
|
||||
sceClibPrintf("settings->ini %s = %s\n", m.key_ini, value ? "true" : "false");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sceClibPrintf("invalid setting map entry %s %s %c\n", m.key_app, m.key_ini, m.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Config g_config;
|
||||
|
||||
paf::Plugin* load_config_plugin(paf::Framework* paf_fw)
|
||||
{
|
||||
paf::Plugin::InitParam pluginParam;
|
||||
pluginParam.name = "config_plugin";
|
||||
pluginParam.caller_name = "__main__";
|
||||
pluginParam.resource_file = "app0:/config_plugin.rco";
|
||||
pluginParam.init_func = NULL;
|
||||
pluginParam.start_func = NULL;
|
||||
pluginParam.stop_func = NULL;
|
||||
pluginParam.exit_func = NULL;
|
||||
paf::Plugin::LoadSync(pluginParam);
|
||||
return paf_fw->FindPlugin("config_plugin");
|
||||
}
|
||||
|
||||
int load_app_settings_plugin()
|
||||
{
|
||||
paf::Plugin::InitParam pluginParam;
|
||||
sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_BXCE);
|
||||
sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_INI_FILE_PROCESSOR);
|
||||
sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_COMMON_GUI_DIALOG);
|
||||
|
||||
pluginParam.name = "app_settings_plugin";
|
||||
pluginParam.resource_file = "vs0:vsh/common/app_settings_plugin.rco";
|
||||
pluginParam.caller_name = "__main__";
|
||||
pluginParam.set_param_func = sce::AppSettings::PluginSetParamCB;
|
||||
pluginParam.init_func = sce::AppSettings::PluginInitCB;
|
||||
pluginParam.start_func = sce::AppSettings::PluginStartCB;
|
||||
pluginParam.stop_func = sce::AppSettings::PluginStopCB;
|
||||
pluginParam.exit_func = sce::AppSettings::PluginExitCB;
|
||||
pluginParam.module_file = "vs0:vsh/common/app_settings.suprx";
|
||||
pluginParam.draw_priority = 0x96;
|
||||
paf::Plugin::LoadSync(pluginParam);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int exit_type = 0;
|
||||
|
||||
void save_and_exit()
|
||||
{
|
||||
g_config.FromSettings();
|
||||
g_config.SaveIni();
|
||||
g_fw->RequestShutdown();
|
||||
exit_type = 1;
|
||||
}
|
||||
|
||||
void save_and_launch()
|
||||
{
|
||||
g_config.FromSettings();
|
||||
g_config.SaveIni();
|
||||
g_fw->RequestShutdown();
|
||||
exit_type = 2;
|
||||
}
|
||||
|
||||
void CBOnStartPageTransition(const char* elementId, int32_t type)
|
||||
{
|
||||
}
|
||||
|
||||
void CBOnPageActivate(const char* elementId, int32_t type)
|
||||
{
|
||||
}
|
||||
|
||||
void CBOnPageDeactivate(const char* elementId, int32_t type)
|
||||
{
|
||||
}
|
||||
|
||||
int32_t CBOnCheckVisible(const char* elementId, bool* pIsVisible)
|
||||
{
|
||||
*pIsVisible = true;
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
int32_t CBOnPreCreate(const char* elementId, sce::AppSettings::Element* element)
|
||||
{
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
int32_t CBOnPostCreate(const char* elementId, paf::ui::Widget* widget)
|
||||
{
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
int32_t CBOnPress(const char* elementId, const char* newValue)
|
||||
{
|
||||
if (sce_paf_strcmp(elementId, "save_exit_button") == 0) {
|
||||
save_and_exit();
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
if (sce_paf_strcmp(elementId, "save_launch_button") == 0) {
|
||||
save_and_launch();
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
sceClibPrintf("OnPress %s %s\n", elementId, newValue);
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
int32_t CBOnPress2(const char* elementId, const char* newValue)
|
||||
{
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
void CBOnTerm(int32_t result)
|
||||
{
|
||||
if (exit_type == 0) {
|
||||
sceKernelExitProcess(0);
|
||||
}
|
||||
}
|
||||
|
||||
const wchar_t* CBOnGetString(const char* elementId)
|
||||
{
|
||||
wchar_t* res = g_configPlugin->GetString(elementId);
|
||||
if (res[0] != 0) {
|
||||
return res;
|
||||
}
|
||||
return L"unknown string";
|
||||
}
|
||||
|
||||
int32_t CBOnGetSurface(paf::graph::Surface** surf, const char* elementId)
|
||||
{
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
void open_settings()
|
||||
{
|
||||
g_config.Init(g_appSettings);
|
||||
g_config.LoadIni();
|
||||
g_config.ToSettings();
|
||||
|
||||
sce::AppSettings::InterfaceCallbacks ifCb;
|
||||
ifCb.onStartPageTransitionCb = CBOnStartPageTransition;
|
||||
ifCb.onPageActivateCb = CBOnPageActivate;
|
||||
ifCb.onPageDeactivateCb = CBOnPageDeactivate;
|
||||
ifCb.onCheckVisible = CBOnCheckVisible;
|
||||
ifCb.onPreCreateCb = CBOnPreCreate;
|
||||
ifCb.onPostCreateCb = CBOnPostCreate;
|
||||
ifCb.onPressCb = CBOnPress;
|
||||
ifCb.onPressCb2 = CBOnPress2;
|
||||
ifCb.onTermCb = CBOnTerm;
|
||||
ifCb.onGetStringCb = (sce::AppSettings::InterfaceCallbacks::GetStringCallback) CBOnGetString;
|
||||
ifCb.onGetSurfaceCb = CBOnGetSurface;
|
||||
|
||||
paf::wstring msg_save_exit(g_configPlugin->GetString("msg_save_exit"));
|
||||
paf::wstring msg_save_launch(g_configPlugin->GetString("msg_save_launch"));
|
||||
paf::wstring msg_exit(g_configPlugin->GetString("msg_exit"));
|
||||
|
||||
paf::Plugin* appSetPlug = paf::Plugin::Find("app_settings_plugin");
|
||||
g_appSetIf = (sce::AppSettings::Interface*) appSetPlug->GetInterface(1);
|
||||
g_appSetIf->Show(&ifCb);
|
||||
g_appSetIf->AddFooterButton("save_exit_button", &msg_save_exit, 1);
|
||||
g_appSetIf->AddFooterButton("save_launch_button", &msg_save_launch, 2);
|
||||
g_appSetIf->ShowFooter();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
paf::Framework::InitParam fwParam;
|
||||
fwParam.mode = paf::Framework::Mode_Normal;
|
||||
|
||||
paf::Framework* paf_fw = new paf::Framework(fwParam);
|
||||
g_fw = paf_fw;
|
||||
|
||||
paf_fw->LoadCommonResourceSync();
|
||||
load_app_settings_plugin();
|
||||
paf::Plugin* configPlugin = load_config_plugin(paf_fw);
|
||||
g_configPlugin = configPlugin;
|
||||
configPlugin->SetLocale(Locale_EN);
|
||||
|
||||
size_t fileSize = 0;
|
||||
const char* mimeType = nullptr;
|
||||
auto settingsXmlFile = configPlugin->GetResource()->GetFile("settings.xml", &fileSize, &mimeType);
|
||||
|
||||
sce::AppSettings::InitParam settingsParam;
|
||||
settingsParam.xml_file = settingsXmlFile;
|
||||
settingsParam.alloc_cb = sce_paf_malloc;
|
||||
settingsParam.free_cb = sce_paf_free;
|
||||
settingsParam.realloc_cb = sce_paf_realloc;
|
||||
settingsParam.safemem_offset = 0;
|
||||
settingsParam.safemem_size = 0x400;
|
||||
|
||||
sce::AppSettings::GetInstance(settingsParam, &g_appSettings);
|
||||
g_appSettings->Initialize();
|
||||
|
||||
open_settings();
|
||||
paf_fw->Run();
|
||||
|
||||
if (exit_type == 2) {
|
||||
int ret = sceAppMgrLoadExec("app0:/eboot.bin", NULL, NULL);
|
||||
printf("sceAppMgrLoadExec: %08x\n", ret);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
169
CONFIG/vita/src/paf_runtime.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
#include <paf.h>
|
||||
#include <psp2/kernel/clib.h>
|
||||
#include <psp2/kernel/modulemgr.h>
|
||||
#include <psp2/kernel/processmgr.h>
|
||||
#include <psp2/sysmodule.h>
|
||||
|
||||
char sceUserMainThreadName[] = "isle_config";
|
||||
int sceUserMainThreadPriority = 0x10000100;
|
||||
int sceUserMainThreadCpuAffinityMask = 0x70000;
|
||||
SceSize sceUserMainThreadStackSize = 0x4000;
|
||||
|
||||
void operator delete(void* ptr, unsigned int n)
|
||||
{
|
||||
return sce_paf_free(ptr);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void user_malloc_init()
|
||||
{
|
||||
}
|
||||
|
||||
void user_malloc_finalize(void)
|
||||
{
|
||||
}
|
||||
|
||||
void* user_malloc(size_t size)
|
||||
{
|
||||
return sce_paf_malloc(size);
|
||||
}
|
||||
|
||||
void user_free(void* ptr)
|
||||
{
|
||||
sce_paf_free(ptr);
|
||||
}
|
||||
|
||||
void* user_calloc(size_t nelem, size_t size)
|
||||
{
|
||||
return sce_paf_calloc(nelem, size);
|
||||
}
|
||||
|
||||
void* user_realloc(void* ptr, size_t new_size)
|
||||
{
|
||||
return sce_paf_realloc(ptr, new_size);
|
||||
}
|
||||
|
||||
void* user_memalign(size_t boundary, size_t size)
|
||||
{
|
||||
return sce_paf_memalign(boundary, size);
|
||||
}
|
||||
|
||||
void* user_reallocalign(void* ptr, size_t size, size_t boundary)
|
||||
{
|
||||
sceClibPrintf("[PAF2LIBC] reallocalign is not supported\n");
|
||||
abort();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int user_malloc_stats(struct malloc_managed_size* mmsize)
|
||||
{
|
||||
sceClibPrintf("malloc_stats\n");
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user_malloc_stats_fast(struct malloc_managed_size* mmsize)
|
||||
{
|
||||
sceClibPrintf("user_malloc_stats_fast\n");
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t user_malloc_usable_size(void* ptr)
|
||||
{
|
||||
return sce_paf_musable_size(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void* user_new(std::size_t size)
|
||||
{
|
||||
return sce_paf_malloc(size);
|
||||
}
|
||||
|
||||
void* user_new(std::size_t size, const std::nothrow_t& x)
|
||||
{
|
||||
return sce_paf_malloc(size);
|
||||
}
|
||||
|
||||
void* user_new_array(std::size_t size)
|
||||
{
|
||||
return sce_paf_malloc(size);
|
||||
}
|
||||
|
||||
void* user_new_array(std::size_t size, const std::nothrow_t& x)
|
||||
{
|
||||
return sce_paf_malloc(size);
|
||||
}
|
||||
|
||||
void user_delete(void* ptr)
|
||||
{
|
||||
sce_paf_free(ptr);
|
||||
}
|
||||
|
||||
void user_delete(void* ptr, const std::nothrow_t& x)
|
||||
{
|
||||
sce_paf_free(ptr);
|
||||
}
|
||||
|
||||
void user_delete_array(void* ptr)
|
||||
{
|
||||
sce_paf_free(ptr);
|
||||
}
|
||||
|
||||
void user_delete_array(void* ptr, const std::nothrow_t& x)
|
||||
{
|
||||
sce_paf_free(ptr);
|
||||
}
|
||||
|
||||
int paf_init()
|
||||
{
|
||||
int load_res;
|
||||
ScePafInit init_param;
|
||||
SceSysmoduleOpt sysmodule_opt;
|
||||
|
||||
init_param.global_heap_size = 0x1000000;
|
||||
init_param.cdlg_mode = 0;
|
||||
init_param.global_heap_alignment = 0;
|
||||
init_param.global_heap_disable_assert_on_alloc_failure = 0;
|
||||
|
||||
load_res = 0xDEADBEEF;
|
||||
sysmodule_opt.flags = 0;
|
||||
sysmodule_opt.result = &load_res;
|
||||
|
||||
int res = sceSysmoduleLoadModuleInternalWithArg(
|
||||
SCE_SYSMODULE_INTERNAL_PAF,
|
||||
sizeof(init_param),
|
||||
&init_param,
|
||||
&sysmodule_opt
|
||||
);
|
||||
if ((res | load_res) != 0) {
|
||||
sceClibPrintf(
|
||||
"[PAF PRX Loader] Failed to load the PAF prx. (return value 0x%x, result code 0x%x )\n",
|
||||
res,
|
||||
load_res
|
||||
);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main();
|
||||
|
||||
extern "C" int module_start(SceSize args, void* argp)
|
||||
{
|
||||
int res = paf_init();
|
||||
if (res < 0) {
|
||||
sceKernelExitProcess(res);
|
||||
return SCE_KERNEL_START_FAILED;
|
||||
}
|
||||
|
||||
res = main();
|
||||
sceKernelExitProcess(res);
|
||||
return SCE_KERNEL_START_SUCCESS;
|
||||
}
|
||||
|
||||
extern "C" void _start()
|
||||
{
|
||||
module_start(0, nullptr);
|
||||
}
|
||||
@ -77,6 +77,14 @@
|
||||
#include "android/config.h"
|
||||
#endif
|
||||
|
||||
#ifdef __vita__
|
||||
#include "vita/config.h"
|
||||
#include "vita/messagebox.h"
|
||||
|
||||
#include <psp2/appmgr.h>
|
||||
#include <psp2/kernel/clib.h>
|
||||
#endif
|
||||
|
||||
DECOMP_SIZE_ASSERT(IsleApp, 0x8c)
|
||||
|
||||
// GLOBAL: ISLE 0x410030
|
||||
@ -316,6 +324,23 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv)
|
||||
// Create global app instance
|
||||
g_isle = new IsleApp();
|
||||
|
||||
#ifdef __vita__
|
||||
SceAppUtilInitParam appUtilInitParam = {0};
|
||||
SceAppUtilBootParam appUtilBootParam = {0};
|
||||
sceAppUtilInit(&appUtilInitParam, &appUtilBootParam);
|
||||
SceAppUtilAppEventParam eventParam = {0};
|
||||
sceAppUtilReceiveAppEvent(&eventParam);
|
||||
if (eventParam.type == 0x05) {
|
||||
g_isle->LoadConfig();
|
||||
char buffer[2048];
|
||||
sceAppUtilAppEventParseLiveArea(&eventParam, buffer);
|
||||
if (strstr(buffer, "-config")) {
|
||||
sceClibPrintf("Loading Config App.\n");
|
||||
sceAppMgrLoadExec("app0:/isle-config.self", NULL, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (g_isle->ParseArguments(argc, argv)) {
|
||||
case SDL_APP_FAILURE:
|
||||
Any_ShowSimpleMessageBox(
|
||||
@ -452,6 +477,19 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef __vita__
|
||||
// reject back touch panel
|
||||
switch (event->type) {
|
||||
case SDL_EVENT_FINGER_MOTION:
|
||||
case SDL_EVENT_FINGER_DOWN:
|
||||
case SDL_EVENT_FINGER_UP:
|
||||
case SDL_EVENT_FINGER_CANCELED:
|
||||
if (event->tfinger.touchID == 2) {
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (event->type) {
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||
if (!IsleDebug_Enabled()) {
|
||||
@ -556,7 +594,11 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event)
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef __vita__ // conflicts with screenshot button combination
|
||||
case SDL_GAMEPAD_BUTTON_BACK:
|
||||
#else
|
||||
case SDL_GAMEPAD_BUTTON_START:
|
||||
#endif
|
||||
if (InputManager()) {
|
||||
InputManager()->QueueEvent(c_notificationKeyPress, SDLK_ESCAPE, 0, 0, SDLK_ESCAPE);
|
||||
}
|
||||
@ -884,7 +926,7 @@ MxResult IsleApp::SetupWindow()
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, g_targetHeight);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN, m_fullScreen);
|
||||
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, WINDOW_TITLE);
|
||||
#if defined(MINIWIN) && !defined(__3DS__) && !defined(WINDOWS_STORE)
|
||||
#if defined(MINIWIN) && !defined(__3DS__) && !defined(WINDOWS_STORE) && !defined(__vita__)
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_OPENGL_BOOLEAN, true);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
@ -1110,6 +1152,9 @@ bool IsleApp::LoadConfig()
|
||||
Android_SetupDefaultConfigOverrides(dict);
|
||||
#endif
|
||||
|
||||
#ifdef __vita__
|
||||
VITA_SetupDefaultConfigOverrides(dict);
|
||||
#endif
|
||||
iniparser_dump_ini(dict, iniFP);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "New config written at '%s'", iniConfig.GetData());
|
||||
fclose(iniFP);
|
||||
|
||||
13
ISLE/vita/config.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <SDL3/SDL_log.h>
|
||||
#include <iniparser.h>
|
||||
|
||||
void VITA_SetupDefaultConfigOverrides(dictionary* p_dictionary)
|
||||
{
|
||||
SDL_Log("Overriding default config for VITA");
|
||||
|
||||
iniparser_set(p_dictionary, "isle:diskpath", "ux0:data/isledecomp/isle/disk");
|
||||
iniparser_set(p_dictionary, "isle:cdpath", "ux0:data/isledecomp/isle/cd");
|
||||
iniparser_set(p_dictionary, "isle:MSAA", "4");
|
||||
}
|
||||
8
ISLE/vita/config.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef VITA_CONFIG_H
|
||||
#define VITA_CONFIG_H
|
||||
|
||||
#include "dictionary.h"
|
||||
|
||||
void VITA_SetupDefaultConfigOverrides(dictionary* p_dictionary);
|
||||
|
||||
#endif // VITA_CONFIG_H
|
||||
52
ISLE/vita/messagebox.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "messagebox.h"
|
||||
|
||||
#include "../../miniwin/src/d3drm/backends/gxm/gxm_context.h"
|
||||
|
||||
#include <psp2/common_dialog.h>
|
||||
#include <psp2/message_dialog.h>
|
||||
|
||||
bool Vita_ShowSimpleMessageBox(SDL_MessageBoxFlags flags, const char* title, const char* message, SDL_Window* window)
|
||||
{
|
||||
int ret;
|
||||
SceMsgDialogParam param;
|
||||
SceMsgDialogUserMessageParam msgParam;
|
||||
SceMsgDialogButtonsParam buttonParam;
|
||||
SceMsgDialogResult dialog_result;
|
||||
SceCommonDialogErrorCode init_result;
|
||||
bool setup_minimal_gxm = false;
|
||||
|
||||
SDL_zero(param);
|
||||
sceMsgDialogParamInit(¶m);
|
||||
param.mode = SCE_MSG_DIALOG_MODE_USER_MSG;
|
||||
|
||||
SDL_zero(msgParam);
|
||||
char message_data[0x1000];
|
||||
SDL_snprintf(message_data, sizeof(message_data), "%s\r\n\r\n%s", title, message);
|
||||
|
||||
msgParam.msg = (const SceChar8*) message_data;
|
||||
msgParam.buttonType = SCE_MSG_DIALOG_BUTTON_TYPE_OK;
|
||||
param.userMsgParam = &msgParam;
|
||||
|
||||
if (!gxm) {
|
||||
gxm = (GXMContext*) SDL_malloc(sizeof(GXMContext));
|
||||
}
|
||||
if (ret = gxm->init(SCE_GXM_MULTISAMPLE_NONE); ret < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
init_result = (SceCommonDialogErrorCode) sceMsgDialogInit(¶m);
|
||||
if (init_result >= 0) {
|
||||
while (sceMsgDialogGetStatus() == SCE_COMMON_DIALOG_STATUS_RUNNING) {
|
||||
gxm->clear(0, 0, 0, true);
|
||||
gxm->swap_display();
|
||||
}
|
||||
SDL_zero(dialog_result);
|
||||
sceMsgDialogGetResult(&dialog_result);
|
||||
sceMsgDialogTerm();
|
||||
return dialog_result.buttonId == SCE_MSG_DIALOG_BUTTON_ID_OK;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
8
ISLE/vita/messagebox.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef VITA_MESSAGE_BOX_H
|
||||
#define VITA_MESSAGE_BOX_H
|
||||
|
||||
#include <SDL3/SDL_messagebox.h>
|
||||
|
||||
bool Vita_ShowSimpleMessageBox(SDL_MessageBoxFlags flags, const char* title, const char* message, SDL_Window* window);
|
||||
|
||||
#endif // VITA_MESSAGE_BOX_H
|
||||
@ -18,6 +18,7 @@ Please note: this project is primarily dedicated to achieving platform independe
|
||||
| Xbox One | [](https://github.com/isledecomp/isle-portable/actions/workflows/ci.yml) |
|
||||
| iOS | [](https://github.com/isledecomp/isle-portable/actions/workflows/ci.yml) |
|
||||
| Android | [](https://github.com/isledecomp/isle-portable/actions/workflows/ci.yml) |
|
||||
| Playstation Vita | [](https://github.com/isledecomp/isle-portable/actions/workflows/ci.yml) |
|
||||
|
||||
We are actively working to support more platforms. If you have experience with a particular platform, we encourage you to contribute to `isle-portable`. You can find a [list of ongoing efforts](https://github.com/isledecomp/isle-portable/wiki/Work%E2%80%90in%E2%80%90progress-ports) in our Wiki.
|
||||
|
||||
|
||||
@ -30,7 +30,7 @@ target_compile_definitions(miniwin PRIVATE
|
||||
list(APPEND GRAPHICS_BACKENDS USE_SOFTWARE_RENDER)
|
||||
list(APPEND GRAPHICS_BACKENDS USE_SDL_GPU)
|
||||
|
||||
if(NOT WINDOWS_STORE)
|
||||
if(NOT (VITA OR WINDOWS_STORE))
|
||||
find_package(OpenGL)
|
||||
if(OpenGL_FOUND)
|
||||
message(STATUS "Found OpenGL: enabling OpenGL 1.x renderer")
|
||||
@ -69,6 +69,25 @@ if(NOT WINDOWS_STORE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(VITA)
|
||||
add_subdirectory(src/d3drm/backends/gxm/shaders)
|
||||
|
||||
target_sources(miniwin PRIVATE
|
||||
src/d3drm/backends/gxm/gxm_context.cpp
|
||||
src/d3drm/backends/gxm/gxm_renderer.cpp
|
||||
src/d3drm/backends/gxm/gxm_memory.cpp
|
||||
src/d3drm/backends/gxm/tlsf.c
|
||||
)
|
||||
target_link_libraries(miniwin PRIVATE
|
||||
SceGxm_stub
|
||||
SceRazorCapture_stub
|
||||
SceRazorHud_stub
|
||||
taihen_stub
|
||||
gxm_shaders
|
||||
)
|
||||
list(APPEND GRAPHICS_BACKENDS USE_GXM)
|
||||
list(REMOVE_ITEM GRAPHICS_BACKENDS USE_SOFTWARE_RENDER USE_SDL_GPU)
|
||||
endif()
|
||||
|
||||
if(NINTENDO_3DS)
|
||||
if(ISLE_DEBUG)
|
||||
|
||||
680
miniwin/src/d3drm/backends/gxm/gxm_context.cpp
Normal file
@ -0,0 +1,680 @@
|
||||
#include "gxm_context.h"
|
||||
|
||||
#include "gxm_memory.h"
|
||||
#include "shaders/gxm_shaders.h"
|
||||
#include "tlsf.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <psp2/common_dialog.h>
|
||||
#include <psp2/display.h>
|
||||
#include <psp2/gxm.h>
|
||||
#include <psp2/kernel/sysmem.h>
|
||||
|
||||
static bool gxm_initialized = false;
|
||||
|
||||
bool with_razor_capture;
|
||||
bool with_razor_hud;
|
||||
|
||||
#define CDRAM_POOL_SIZE 64 * 1024 * 1024
|
||||
#define VITA_GXM_COLOR_FORMAT SCE_GXM_COLOR_FORMAT_A8B8G8R8
|
||||
|
||||
typedef struct GXMDisplayData {
|
||||
void* address;
|
||||
int index;
|
||||
} GXMDisplayData;
|
||||
|
||||
static void display_callback(const void* callback_data)
|
||||
{
|
||||
const GXMDisplayData* display_data = (const GXMDisplayData*) callback_data;
|
||||
|
||||
SceDisplayFrameBuf framebuf;
|
||||
SDL_memset(&framebuf, 0x00, sizeof(SceDisplayFrameBuf));
|
||||
framebuf.size = sizeof(SceDisplayFrameBuf);
|
||||
framebuf.base = display_data->address;
|
||||
framebuf.pitch = VITA_GXM_SCREEN_STRIDE;
|
||||
framebuf.pixelformat = VITA_GXM_PIXEL_FORMAT;
|
||||
framebuf.width = VITA_GXM_SCREEN_WIDTH;
|
||||
framebuf.height = VITA_GXM_SCREEN_HEIGHT;
|
||||
sceDisplaySetFrameBuf(&framebuf, SCE_DISPLAY_SETBUF_NEXTFRAME);
|
||||
sceDisplayWaitSetFrameBuf();
|
||||
}
|
||||
|
||||
#ifdef GXM_WITH_RAZOR
|
||||
static int load_suprx(const char* name)
|
||||
{
|
||||
sceClibPrintf("loading %s\n", name);
|
||||
int modid = _sceKernelLoadModule(name, 0, nullptr);
|
||||
if (modid < 0) {
|
||||
sceClibPrintf("%s load: 0x%08x\n", name, modid);
|
||||
return modid;
|
||||
}
|
||||
int status;
|
||||
int ret = sceKernelStartModule(modid, 0, nullptr, 0, nullptr, &status);
|
||||
if (ret < 0) {
|
||||
sceClibPrintf("%s start: 0x%08x\n", name, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void load_razor()
|
||||
{
|
||||
with_razor_capture = false;
|
||||
with_razor_hud = false;
|
||||
if (load_suprx("app0:librazorcapture_es4.suprx") >= 0) {
|
||||
with_razor_capture = true;
|
||||
}
|
||||
|
||||
if (with_razor_capture) {
|
||||
// sceRazorGpuCaptureEnableSalvage("ux0:data/gpu_crash.sgx");
|
||||
}
|
||||
|
||||
if (with_razor_hud) {
|
||||
sceRazorGpuTraceSetFilename("ux0:data/gpu_trace", 3);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int gxm_library_init()
|
||||
{
|
||||
if (gxm_initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef GXM_WITH_RAZOR
|
||||
load_razor();
|
||||
#endif
|
||||
|
||||
SceGxmInitializeParams initializeParams;
|
||||
SDL_memset(&initializeParams, 0, sizeof(SceGxmInitializeParams));
|
||||
initializeParams.flags = 0;
|
||||
initializeParams.displayQueueMaxPendingCount = VITA_GXM_PENDING_SWAPS;
|
||||
initializeParams.displayQueueCallback = display_callback;
|
||||
initializeParams.displayQueueCallbackDataSize = sizeof(GXMDisplayData);
|
||||
initializeParams.parameterBufferSize = SCE_GXM_DEFAULT_PARAMETER_BUFFER_SIZE;
|
||||
|
||||
int err = sceGxmInitialize(&initializeParams);
|
||||
if (err != 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_RENDER, "gxm init failed: %d", err);
|
||||
return err;
|
||||
}
|
||||
gxm_initialized = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
GXMContext* gxm;
|
||||
|
||||
void GXMContext::init_cdram_allocator()
|
||||
{
|
||||
// allocator
|
||||
this->cdramMem = vita_mem_alloc(
|
||||
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
|
||||
CDRAM_POOL_SIZE,
|
||||
16,
|
||||
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
|
||||
&this->cdramUID,
|
||||
"cdram_pool"
|
||||
);
|
||||
this->cdramPool = SDL_malloc(tlsf_size());
|
||||
tlsf_create(this->cdramPool);
|
||||
tlsf_add_pool(this->cdramPool, this->cdramMem, CDRAM_POOL_SIZE);
|
||||
}
|
||||
|
||||
int GXMContext::init_context()
|
||||
{
|
||||
int ret;
|
||||
|
||||
const unsigned int patcherBufferSize = 64 * 1024;
|
||||
const unsigned int patcherVertexUsseSize = 64 * 1024;
|
||||
const unsigned int patcherFragmentUsseSize = 64 * 1024;
|
||||
|
||||
// allocate buffers
|
||||
this->vdmRingBuffer = vita_mem_alloc(
|
||||
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
|
||||
SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE,
|
||||
4,
|
||||
SCE_GXM_MEMORY_ATTRIB_READ,
|
||||
&this->vdmRingBufferUid,
|
||||
"vdmRingBuffer"
|
||||
);
|
||||
|
||||
this->vertexRingBuffer = vita_mem_alloc(
|
||||
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
|
||||
SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE,
|
||||
4,
|
||||
SCE_GXM_MEMORY_ATTRIB_READ,
|
||||
&this->vertexRingBufferUid,
|
||||
"vertexRingBuffer"
|
||||
);
|
||||
|
||||
this->fragmentRingBuffer = vita_mem_alloc(
|
||||
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
|
||||
SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE,
|
||||
4,
|
||||
SCE_GXM_MEMORY_ATTRIB_READ,
|
||||
&this->fragmentRingBufferUid,
|
||||
"fragmentRingBuffer"
|
||||
);
|
||||
|
||||
this->fragmentUsseRingBuffer = vita_mem_fragment_usse_alloc(
|
||||
SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE,
|
||||
&this->fragmentUsseRingBufferUid,
|
||||
&this->fragmentUsseRingBufferOffset
|
||||
);
|
||||
|
||||
// create context
|
||||
SceGxmContextParams contextParams;
|
||||
memset(&contextParams, 0, sizeof(SceGxmContextParams));
|
||||
contextParams.hostMem = SDL_malloc(SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE);
|
||||
contextParams.hostMemSize = SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE;
|
||||
contextParams.vdmRingBufferMem = this->vdmRingBuffer;
|
||||
contextParams.vdmRingBufferMemSize = SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE;
|
||||
contextParams.vertexRingBufferMem = this->vertexRingBuffer;
|
||||
contextParams.vertexRingBufferMemSize = SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE;
|
||||
contextParams.fragmentRingBufferMem = this->fragmentRingBuffer;
|
||||
contextParams.fragmentRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE;
|
||||
contextParams.fragmentUsseRingBufferMem = this->fragmentUsseRingBuffer;
|
||||
contextParams.fragmentUsseRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE;
|
||||
contextParams.fragmentUsseRingBufferOffset = this->fragmentUsseRingBufferOffset;
|
||||
|
||||
ret = SCE_ERR(sceGxmCreateContext, &contextParams, &this->context);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
this->contextHostMem = contextParams.hostMem;
|
||||
|
||||
// shader patcher
|
||||
this->patcherBuffer = vita_mem_alloc(
|
||||
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
|
||||
patcherBufferSize,
|
||||
4,
|
||||
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
|
||||
&this->patcherBufferUid,
|
||||
"patcherBuffer"
|
||||
);
|
||||
|
||||
this->patcherVertexUsse =
|
||||
vita_mem_vertex_usse_alloc(patcherVertexUsseSize, &this->patcherVertexUsseUid, &this->patcherVertexUsseOffset);
|
||||
|
||||
this->patcherFragmentUsse = vita_mem_fragment_usse_alloc(
|
||||
patcherFragmentUsseSize,
|
||||
&this->patcherFragmentUsseUid,
|
||||
&this->patcherFragmentUsseOffset
|
||||
);
|
||||
|
||||
SceGxmShaderPatcherParams patcherParams;
|
||||
memset(&patcherParams, 0, sizeof(SceGxmShaderPatcherParams));
|
||||
patcherParams.userData = NULL;
|
||||
patcherParams.hostAllocCallback = &patcher_host_alloc;
|
||||
patcherParams.hostFreeCallback = &patcher_host_free;
|
||||
patcherParams.bufferAllocCallback = NULL;
|
||||
patcherParams.bufferFreeCallback = NULL;
|
||||
patcherParams.bufferMem = this->patcherBuffer;
|
||||
patcherParams.bufferMemSize = patcherBufferSize;
|
||||
patcherParams.vertexUsseAllocCallback = NULL;
|
||||
patcherParams.vertexUsseFreeCallback = NULL;
|
||||
patcherParams.vertexUsseMem = this->patcherVertexUsse;
|
||||
patcherParams.vertexUsseMemSize = patcherVertexUsseSize;
|
||||
patcherParams.vertexUsseOffset = this->patcherVertexUsseOffset;
|
||||
patcherParams.fragmentUsseAllocCallback = NULL;
|
||||
patcherParams.fragmentUsseFreeCallback = NULL;
|
||||
patcherParams.fragmentUsseMem = this->patcherFragmentUsse;
|
||||
patcherParams.fragmentUsseMemSize = patcherFragmentUsseSize;
|
||||
patcherParams.fragmentUsseOffset = this->patcherFragmentUsseOffset;
|
||||
|
||||
ret = SCE_ERR(sceGxmShaderPatcherCreate, &patcherParams, &this->shaderPatcher);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GXMContext::create_display_buffers(SceGxmMultisampleMode msaaMode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
const uint32_t alignedWidth = ALIGN(VITA_GXM_SCREEN_WIDTH, SCE_GXM_TILE_SIZEX);
|
||||
const uint32_t alignedHeight = ALIGN(VITA_GXM_SCREEN_HEIGHT, SCE_GXM_TILE_SIZEY);
|
||||
uint32_t sampleCount = alignedWidth * alignedHeight;
|
||||
uint32_t depthStrideInSamples = alignedWidth;
|
||||
|
||||
if (msaaMode == SCE_GXM_MULTISAMPLE_4X) {
|
||||
sampleCount *= 4;
|
||||
depthStrideInSamples *= 2;
|
||||
}
|
||||
else if (msaaMode == SCE_GXM_MULTISAMPLE_2X) {
|
||||
sampleCount *= 2;
|
||||
}
|
||||
|
||||
// render target
|
||||
SceGxmRenderTargetParams renderTargetParams;
|
||||
memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams));
|
||||
renderTargetParams.flags = 0;
|
||||
renderTargetParams.width = VITA_GXM_SCREEN_WIDTH;
|
||||
renderTargetParams.height = VITA_GXM_SCREEN_HEIGHT;
|
||||
renderTargetParams.scenesPerFrame = 1;
|
||||
renderTargetParams.multisampleMode = msaaMode;
|
||||
renderTargetParams.multisampleLocations = 0;
|
||||
renderTargetParams.driverMemBlock = -1; // Invalid UID
|
||||
ret = SCE_ERR(sceGxmCreateRenderTarget, &renderTargetParams, &this->renderTarget);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
this->renderTargetInit = true;
|
||||
|
||||
for (int i = 0; i < GXM_DISPLAY_BUFFER_COUNT; i++) {
|
||||
this->displayBuffers[i] = vita_mem_alloc(
|
||||
SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW,
|
||||
4 * VITA_GXM_SCREEN_STRIDE * VITA_GXM_SCREEN_HEIGHT,
|
||||
SCE_GXM_COLOR_SURFACE_ALIGNMENT,
|
||||
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
|
||||
&this->displayBuffersUid[i],
|
||||
"displayBuffers"
|
||||
);
|
||||
|
||||
ret = SCE_ERR(
|
||||
sceGxmColorSurfaceInit,
|
||||
&this->displayBuffersSurface[i],
|
||||
SCE_GXM_COLOR_FORMAT_A8B8G8R8,
|
||||
SCE_GXM_COLOR_SURFACE_LINEAR,
|
||||
(msaaMode == SCE_GXM_MULTISAMPLE_NONE) ? SCE_GXM_COLOR_SURFACE_SCALE_NONE
|
||||
: SCE_GXM_COLOR_SURFACE_SCALE_MSAA_DOWNSCALE,
|
||||
SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT,
|
||||
VITA_GXM_SCREEN_WIDTH,
|
||||
VITA_GXM_SCREEN_HEIGHT,
|
||||
VITA_GXM_SCREEN_STRIDE,
|
||||
this->displayBuffers[i]
|
||||
);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = SCE_ERR(sceGxmSyncObjectCreate, &this->displayBuffersSync[i]);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
// depth & stencil
|
||||
this->depthBufferData = vita_mem_alloc(
|
||||
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
|
||||
4 * sampleCount,
|
||||
SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
|
||||
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
|
||||
&this->depthBufferUid,
|
||||
"depthBufferData"
|
||||
);
|
||||
|
||||
this->stencilBufferData = vita_mem_alloc(
|
||||
SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE,
|
||||
1 * sampleCount,
|
||||
SCE_GXM_DEPTHSTENCIL_SURFACE_ALIGNMENT,
|
||||
SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE,
|
||||
&this->stencilBufferUid,
|
||||
"stencilBufferData"
|
||||
);
|
||||
|
||||
ret = SCE_ERR(
|
||||
sceGxmDepthStencilSurfaceInit,
|
||||
&this->depthSurface,
|
||||
SCE_GXM_DEPTH_STENCIL_FORMAT_DF32_S8,
|
||||
SCE_GXM_DEPTH_STENCIL_SURFACE_TILED,
|
||||
depthStrideInSamples,
|
||||
this->depthBufferData,
|
||||
this->stencilBufferData
|
||||
);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GXMContext::destroy_display_buffers()
|
||||
{
|
||||
if (this->renderTargetInit) {
|
||||
sceGxmFinish(this->context);
|
||||
sceGxmDestroyRenderTarget(this->renderTarget);
|
||||
this->renderTargetInit = false;
|
||||
}
|
||||
for (int i = 0; i < GXM_DISPLAY_BUFFER_COUNT; i++) {
|
||||
if (this->displayBuffers[i]) {
|
||||
vita_mem_free(this->displayBuffersUid[i]);
|
||||
this->displayBuffers[i] = nullptr;
|
||||
this->displayBuffersUid[i] = -1;
|
||||
sceGxmSyncObjectDestroy(this->displayBuffersSync[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->depthBufferData) {
|
||||
vita_mem_free(this->depthBufferUid);
|
||||
this->depthBufferData = nullptr;
|
||||
this->depthBufferUid = -1;
|
||||
}
|
||||
|
||||
if (this->stencilBufferData) {
|
||||
vita_mem_free(this->stencilBufferUid);
|
||||
this->stencilBufferData = nullptr;
|
||||
this->stencilBufferUid = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void GXMContext::init_clear_mesh()
|
||||
{
|
||||
this->clearVertices = static_cast<GXMVertex2D*>(this->alloc(sizeof(GXMVertex2D) * 4, 4));
|
||||
this->clearVertices[0] = {.position = {-1.0, 1.0}, .texCoord = {0, 0}};
|
||||
this->clearVertices[1] = {.position = {1.0, 1.0}, .texCoord = {0, 0}};
|
||||
this->clearVertices[2] = {.position = {-1.0, -1.0}, .texCoord = {0, 0}};
|
||||
this->clearVertices[3] = {.position = {1.0, -1.0}, .texCoord = {0, 0}};
|
||||
|
||||
this->clearIndices = static_cast<uint16_t*>(this->alloc(sizeof(uint16_t) * 4, 4));
|
||||
this->clearIndices[0] = 0;
|
||||
this->clearIndices[1] = 1;
|
||||
this->clearIndices[2] = 2;
|
||||
this->clearIndices[3] = 3;
|
||||
}
|
||||
|
||||
int GXMContext::register_base_shaders()
|
||||
{
|
||||
int ret;
|
||||
// register plane, color, image shaders
|
||||
ret = SCE_ERR(
|
||||
sceGxmShaderPatcherRegisterProgram,
|
||||
this->shaderPatcher,
|
||||
planeVertexProgramGxp,
|
||||
&this->planeVertexProgramId
|
||||
);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = SCE_ERR(
|
||||
sceGxmShaderPatcherRegisterProgram,
|
||||
this->shaderPatcher,
|
||||
colorFragmentProgramGxp,
|
||||
&this->colorFragmentProgramId
|
||||
);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = SCE_ERR(
|
||||
sceGxmShaderPatcherRegisterProgram,
|
||||
this->shaderPatcher,
|
||||
imageFragmentProgramGxp,
|
||||
&this->imageFragmentProgramId
|
||||
);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
this->color_uColor = sceGxmProgramFindParameterByName(colorFragmentProgramGxp, "uColor"); // vec4
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GXMContext::patch_base_shaders(SceGxmMultisampleMode msaaMode)
|
||||
{
|
||||
int ret;
|
||||
{
|
||||
GET_SHADER_PARAM(positionAttribute, planeVertexProgramGxp, "aPosition", -1);
|
||||
GET_SHADER_PARAM(texCoordAttribute, planeVertexProgramGxp, "aTexCoord", -1);
|
||||
|
||||
SceGxmVertexAttribute vertexAttributes[2];
|
||||
SceGxmVertexStream vertexStreams[1];
|
||||
|
||||
// position
|
||||
vertexAttributes[0].streamIndex = 0;
|
||||
vertexAttributes[0].offset = 0;
|
||||
vertexAttributes[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
|
||||
vertexAttributes[0].componentCount = 2;
|
||||
vertexAttributes[0].regIndex = sceGxmProgramParameterGetResourceIndex(positionAttribute);
|
||||
|
||||
// uv
|
||||
vertexAttributes[1].streamIndex = 0;
|
||||
vertexAttributes[1].offset = 8;
|
||||
vertexAttributes[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32;
|
||||
vertexAttributes[1].componentCount = 2;
|
||||
vertexAttributes[1].regIndex = sceGxmProgramParameterGetResourceIndex(texCoordAttribute);
|
||||
|
||||
vertexStreams[0].stride = sizeof(GXMVertex2D);
|
||||
vertexStreams[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT;
|
||||
|
||||
ret = SCE_ERR(
|
||||
sceGxmShaderPatcherCreateVertexProgram,
|
||||
this->shaderPatcher,
|
||||
this->planeVertexProgramId,
|
||||
vertexAttributes,
|
||||
2,
|
||||
vertexStreams,
|
||||
1,
|
||||
&this->planeVertexProgram
|
||||
);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = SCE_ERR(
|
||||
sceGxmShaderPatcherCreateFragmentProgram,
|
||||
this->shaderPatcher,
|
||||
this->colorFragmentProgramId,
|
||||
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
|
||||
msaaMode,
|
||||
NULL,
|
||||
planeVertexProgramGxp,
|
||||
&this->colorFragmentProgram
|
||||
);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = SCE_ERR(
|
||||
sceGxmShaderPatcherCreateFragmentProgram,
|
||||
this->shaderPatcher,
|
||||
this->imageFragmentProgramId,
|
||||
SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4,
|
||||
msaaMode,
|
||||
&blendInfoTransparent,
|
||||
planeVertexProgramGxp,
|
||||
&this->imageFragmentProgram
|
||||
);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GXMContext::destroy_base_shaders()
|
||||
{
|
||||
sceGxmShaderPatcherReleaseVertexProgram(this->shaderPatcher, this->planeVertexProgram);
|
||||
sceGxmShaderPatcherReleaseFragmentProgram(this->shaderPatcher, this->colorFragmentProgram);
|
||||
sceGxmShaderPatcherReleaseFragmentProgram(this->shaderPatcher, this->imageFragmentProgram);
|
||||
}
|
||||
|
||||
int GXMContext::init(SceGxmMultisampleMode msaaMode)
|
||||
{
|
||||
int ret = 0;
|
||||
ret = gxm_library_init();
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
if (this->cdramPool == nullptr) {
|
||||
this->init_cdram_allocator();
|
||||
}
|
||||
|
||||
if (this->context == nullptr) {
|
||||
ret = this->init_context();
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->planeVertexProgramId == 0) {
|
||||
ret = this->register_base_shaders();
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->clearVertices == nullptr) {
|
||||
this->init_clear_mesh();
|
||||
}
|
||||
|
||||
// recreate when msaa is different
|
||||
if (msaaMode != this->displayMsaa && this->renderTargetInit) {
|
||||
this->destroy_display_buffers();
|
||||
this->destroy_base_shaders();
|
||||
}
|
||||
|
||||
if (!this->renderTargetInit) {
|
||||
ret = this->create_display_buffers(msaaMode);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
ret = this->patch_base_shaders(msaaMode);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int inuse_mem = 0;
|
||||
void* GXMContext::alloc(size_t size, size_t align)
|
||||
{
|
||||
if (this->cdramPool == nullptr) {
|
||||
this->init_cdram_allocator();
|
||||
}
|
||||
DEBUG_ONLY_PRINTF("cdram_alloc(%d, %d) inuse=%d ", size, align, inuse_mem);
|
||||
void* ptr = tlsf_memalign(this->cdramPool, align, size);
|
||||
DEBUG_ONLY_PRINTF("ptr=%p\n", ptr);
|
||||
inuse_mem += tlsf_block_size(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void GXMContext::free(void* ptr)
|
||||
{
|
||||
inuse_mem -= tlsf_block_size(ptr);
|
||||
DEBUG_ONLY_PRINTF("cdram_free(%p)\n", ptr);
|
||||
tlsf_free(this->cdramPool, ptr);
|
||||
}
|
||||
|
||||
void GXMContext::clear(float r, float g, float b, bool new_scene)
|
||||
{
|
||||
new_scene = new_scene && !this->sceneStarted;
|
||||
if (new_scene) {
|
||||
sceGxmBeginScene(
|
||||
this->context,
|
||||
0,
|
||||
this->renderTarget,
|
||||
nullptr,
|
||||
nullptr,
|
||||
this->displayBuffersSync[this->backBufferIndex],
|
||||
&this->displayBuffersSurface[this->backBufferIndex],
|
||||
&this->depthSurface
|
||||
);
|
||||
this->sceneStarted = true;
|
||||
}
|
||||
|
||||
float color[] = {r, g, b, 1};
|
||||
|
||||
sceGxmSetVertexProgram(this->context, this->planeVertexProgram);
|
||||
sceGxmSetFragmentProgram(this->context, this->colorFragmentProgram);
|
||||
|
||||
void* vertUniforms;
|
||||
void* fragUniforms;
|
||||
sceGxmReserveVertexDefaultUniformBuffer(gxm->context, &vertUniforms);
|
||||
sceGxmReserveFragmentDefaultUniformBuffer(gxm->context, &fragUniforms);
|
||||
|
||||
sceGxmSetVertexStream(gxm->context, 0, this->clearVertices);
|
||||
sceGxmSetUniformDataF(fragUniforms, this->color_uColor, 0, 4, color);
|
||||
|
||||
sceGxmSetFrontDepthFunc(gxm->context, SCE_GXM_DEPTH_FUNC_ALWAYS);
|
||||
sceGxmDraw(gxm->context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, this->clearIndices, 4);
|
||||
if (new_scene) {
|
||||
sceGxmEndScene(this->context, nullptr, nullptr);
|
||||
this->sceneStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
void GXMContext::copy_frontbuffer()
|
||||
{
|
||||
SceGxmTexture texture;
|
||||
sceGxmTextureInitLinearStrided(
|
||||
&texture,
|
||||
this->displayBuffers[this->frontBufferIndex],
|
||||
SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR,
|
||||
VITA_GXM_SCREEN_WIDTH,
|
||||
VITA_GXM_SCREEN_HEIGHT,
|
||||
VITA_GXM_SCREEN_STRIDE * 4
|
||||
);
|
||||
sceGxmSetVertexProgram(this->context, this->planeVertexProgram);
|
||||
sceGxmSetFragmentProgram(this->context, this->imageFragmentProgram);
|
||||
|
||||
void* vertUniforms;
|
||||
void* fragUniforms;
|
||||
sceGxmReserveVertexDefaultUniformBuffer(this->context, &vertUniforms);
|
||||
sceGxmReserveFragmentDefaultUniformBuffer(this->context, &fragUniforms);
|
||||
|
||||
sceGxmSetVertexStream(this->context, 0, this->clearVertices);
|
||||
sceGxmSetFragmentTexture(this->context, 0, &texture);
|
||||
|
||||
sceGxmSetFrontDepthFunc(this->context, SCE_GXM_DEPTH_FUNC_ALWAYS);
|
||||
sceGxmDraw(this->context, SCE_GXM_PRIMITIVE_TRIANGLE_STRIP, SCE_GXM_INDEX_FORMAT_U16, this->clearIndices, 4);
|
||||
}
|
||||
|
||||
void GXMContext::destroy()
|
||||
{
|
||||
sceGxmDisplayQueueFinish();
|
||||
if (gxm->context) {
|
||||
sceGxmFinish(gxm->context);
|
||||
}
|
||||
|
||||
this->destroy_display_buffers();
|
||||
this->destroy_base_shaders();
|
||||
|
||||
sceGxmShaderPatcherDestroy(this->shaderPatcher);
|
||||
sceGxmDestroyContext(this->context);
|
||||
vita_mem_fragment_usse_free(this->fragmentUsseRingBufferUid);
|
||||
vita_mem_free(this->fragmentRingBufferUid);
|
||||
vita_mem_free(this->vertexRingBufferUid);
|
||||
vita_mem_free(this->vdmRingBufferUid);
|
||||
SDL_free(this->contextHostMem);
|
||||
}
|
||||
|
||||
void GXMContext::swap_display()
|
||||
{
|
||||
if (this->sceneStarted) {
|
||||
sceGxmEndScene(gxm->context, nullptr, nullptr);
|
||||
this->sceneStarted = false;
|
||||
}
|
||||
|
||||
SceCommonDialogUpdateParam updateParam;
|
||||
SDL_zero(updateParam);
|
||||
updateParam.renderTarget.colorFormat = VITA_GXM_COLOR_FORMAT;
|
||||
updateParam.renderTarget.surfaceType = SCE_GXM_COLOR_SURFACE_LINEAR;
|
||||
updateParam.renderTarget.width = VITA_GXM_SCREEN_WIDTH;
|
||||
updateParam.renderTarget.height = VITA_GXM_SCREEN_HEIGHT;
|
||||
updateParam.renderTarget.strideInPixels = VITA_GXM_SCREEN_STRIDE;
|
||||
updateParam.renderTarget.colorSurfaceData = this->displayBuffers[this->backBufferIndex];
|
||||
updateParam.displaySyncObject = this->displayBuffersSync[this->backBufferIndex];
|
||||
sceCommonDialogUpdate(&updateParam);
|
||||
|
||||
sceGxmPadHeartbeat(
|
||||
&this->displayBuffersSurface[this->backBufferIndex],
|
||||
this->displayBuffersSync[this->backBufferIndex]
|
||||
);
|
||||
|
||||
// display
|
||||
GXMDisplayData displayData;
|
||||
displayData.address = this->displayBuffers[this->backBufferIndex];
|
||||
displayData.index = this->backBufferIndex;
|
||||
sceGxmDisplayQueueAddEntry(
|
||||
this->displayBuffersSync[this->frontBufferIndex],
|
||||
this->displayBuffersSync[this->backBufferIndex],
|
||||
&displayData
|
||||
);
|
||||
|
||||
this->frontBufferIndex = this->backBufferIndex;
|
||||
this->backBufferIndex = (this->backBufferIndex + 1) % GXM_DISPLAY_BUFFER_COUNT;
|
||||
}
|
||||
105
miniwin/src/d3drm/backends/gxm/gxm_context.h
Normal file
@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include <psp2/gxm.h>
|
||||
|
||||
#define VITA_GXM_SCREEN_WIDTH 960
|
||||
#define VITA_GXM_SCREEN_HEIGHT 544
|
||||
#define VITA_GXM_SCREEN_STRIDE 1024
|
||||
#define VITA_GXM_PENDING_SWAPS 2
|
||||
#define VITA_GXM_PIXEL_FORMAT SCE_DISPLAY_PIXELFORMAT_A8B8G8R8
|
||||
|
||||
#define GXM_DISPLAY_BUFFER_COUNT 3
|
||||
|
||||
typedef struct GXMVertex2D {
|
||||
float position[2];
|
||||
float texCoord[2];
|
||||
} GXMVertex2D;
|
||||
|
||||
typedef struct GXMContext {
|
||||
// context
|
||||
SceUID vdmRingBufferUid;
|
||||
SceUID vertexRingBufferUid;
|
||||
SceUID fragmentRingBufferUid;
|
||||
SceUID fragmentUsseRingBufferUid;
|
||||
size_t fragmentUsseRingBufferOffset;
|
||||
|
||||
void* vdmRingBuffer;
|
||||
void* vertexRingBuffer;
|
||||
void* fragmentRingBuffer;
|
||||
void* fragmentUsseRingBuffer;
|
||||
|
||||
void* contextHostMem;
|
||||
SceGxmContext* context;
|
||||
|
||||
// shader patcher
|
||||
SceUID patcherBufferUid;
|
||||
void* patcherBuffer;
|
||||
|
||||
SceUID patcherVertexUsseUid;
|
||||
size_t patcherVertexUsseOffset;
|
||||
void* patcherVertexUsse;
|
||||
SceUID patcherFragmentUsseUid;
|
||||
size_t patcherFragmentUsseOffset;
|
||||
void* patcherFragmentUsse;
|
||||
|
||||
SceGxmShaderPatcher* shaderPatcher;
|
||||
|
||||
// clear
|
||||
SceGxmShaderPatcherId planeVertexProgramId;
|
||||
SceGxmShaderPatcherId colorFragmentProgramId;
|
||||
SceGxmShaderPatcherId imageFragmentProgramId;
|
||||
SceGxmVertexProgram* planeVertexProgram;
|
||||
SceGxmFragmentProgram* colorFragmentProgram;
|
||||
SceGxmFragmentProgram* imageFragmentProgram;
|
||||
const SceGxmProgramParameter* color_uColor;
|
||||
GXMVertex2D* clearVertices;
|
||||
uint16_t* clearIndices;
|
||||
|
||||
// display
|
||||
SceGxmRenderTarget* renderTarget;
|
||||
bool renderTargetInit = false;
|
||||
void* displayBuffers[GXM_DISPLAY_BUFFER_COUNT];
|
||||
SceUID displayBuffersUid[GXM_DISPLAY_BUFFER_COUNT];
|
||||
SceGxmColorSurface displayBuffersSurface[GXM_DISPLAY_BUFFER_COUNT];
|
||||
SceGxmSyncObject* displayBuffersSync[GXM_DISPLAY_BUFFER_COUNT];
|
||||
int backBufferIndex = 0;
|
||||
int frontBufferIndex = 1;
|
||||
SceGxmMultisampleMode displayMsaa;
|
||||
|
||||
// depth buffer
|
||||
SceUID depthBufferUid;
|
||||
void* depthBufferData;
|
||||
SceUID stencilBufferUid;
|
||||
void* stencilBufferData;
|
||||
SceGxmDepthStencilSurface depthSurface;
|
||||
|
||||
// allocator
|
||||
SceUID cdramUID;
|
||||
void* cdramMem;
|
||||
void* cdramPool;
|
||||
|
||||
bool sceneStarted;
|
||||
|
||||
void swap_display();
|
||||
void copy_frontbuffer();
|
||||
int init(SceGxmMultisampleMode msaaMode);
|
||||
void init_cdram_allocator();
|
||||
int init_context();
|
||||
int create_display_buffers(SceGxmMultisampleMode msaaMode);
|
||||
void init_clear_mesh();
|
||||
void destroy_display_buffers();
|
||||
int register_base_shaders();
|
||||
int patch_base_shaders(SceGxmMultisampleMode msaaMode);
|
||||
void destroy_base_shaders();
|
||||
|
||||
void destroy();
|
||||
void clear(float r, float g, float b, bool new_scene);
|
||||
void* alloc(size_t size, size_t align);
|
||||
void free(void* ptr);
|
||||
} GXMContext;
|
||||
|
||||
// global so that common dialog can be rendererd without GXMRenderer
|
||||
extern GXMContext* gxm;
|
||||
|
||||
extern bool with_razor_capture;
|
||||
extern bool with_razor_hud;
|
||||
119
miniwin/src/d3drm/backends/gxm/gxm_memory.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
#include "gxm_memory.h"
|
||||
|
||||
#include "tlsf.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <SDL3/SDL_stdinc.h>
|
||||
#include <psp2/gxm.h>
|
||||
#include <psp2/kernel/clib.h>
|
||||
#include <psp2/kernel/sysmem.h>
|
||||
|
||||
void* patcher_host_alloc(void* user_data, unsigned int size)
|
||||
{
|
||||
void* mem = SDL_malloc(size);
|
||||
(void) user_data;
|
||||
return mem;
|
||||
}
|
||||
|
||||
void patcher_host_free(void* user_data, void* mem)
|
||||
{
|
||||
(void) user_data;
|
||||
SDL_free(mem);
|
||||
}
|
||||
|
||||
void* vita_mem_alloc(unsigned int type, size_t size, size_t alignment, int attribs, SceUID* uid, const char* name)
|
||||
{
|
||||
void* mem;
|
||||
|
||||
if (type == SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW) {
|
||||
size = ALIGN(size, 256 * 1024);
|
||||
}
|
||||
else if (type == SCE_KERNEL_MEMBLOCK_TYPE_USER_MAIN_PHYCONT_NC_RW) {
|
||||
size = ALIGN(size, 1024 * 1024);
|
||||
}
|
||||
else {
|
||||
size = ALIGN(size, 4 * 1024);
|
||||
}
|
||||
|
||||
*uid = sceKernelAllocMemBlock(name, type, size, NULL);
|
||||
|
||||
if (*uid < 0) {
|
||||
SDL_Log("sceKernelAllocMemBlock: 0x%x", *uid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sceKernelGetMemBlockBase(*uid, &mem) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sceGxmMapMemory(mem, size, (SceGxmMemoryAttribFlags) attribs) < 0) {
|
||||
SDL_Log("sceGxmMapMemory 0x%x 0x%x %d failed", mem, size, attribs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
void vita_mem_free(SceUID uid)
|
||||
{
|
||||
void* mem = NULL;
|
||||
if (sceKernelGetMemBlockBase(uid, &mem) < 0) {
|
||||
return;
|
||||
}
|
||||
sceGxmUnmapMemory(mem);
|
||||
sceKernelFreeMemBlock(uid);
|
||||
}
|
||||
|
||||
void* vita_mem_vertex_usse_alloc(unsigned int size, SceUID* uid, unsigned int* usse_offset)
|
||||
{
|
||||
void* mem = NULL;
|
||||
|
||||
size = ALIGN(size, 4096);
|
||||
*uid = sceKernelAllocMemBlock("vertex_usse", SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, size, NULL);
|
||||
|
||||
if (sceKernelGetMemBlockBase(*uid, &mem) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (sceGxmMapVertexUsseMemory(mem, size, usse_offset) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
void vita_mem_vertex_usse_free(SceUID uid)
|
||||
{
|
||||
void* mem = NULL;
|
||||
if (sceKernelGetMemBlockBase(uid, &mem) < 0) {
|
||||
return;
|
||||
}
|
||||
sceGxmUnmapVertexUsseMemory(mem);
|
||||
sceKernelFreeMemBlock(uid);
|
||||
}
|
||||
|
||||
void* vita_mem_fragment_usse_alloc(unsigned int size, SceUID* uid, unsigned int* usse_offset)
|
||||
{
|
||||
void* mem = NULL;
|
||||
|
||||
size = ALIGN(size, 4096);
|
||||
*uid = sceKernelAllocMemBlock("fragment_usse", SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, size, NULL);
|
||||
|
||||
if (sceKernelGetMemBlockBase(*uid, &mem) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (sceGxmMapFragmentUsseMemory(mem, size, usse_offset) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
void vita_mem_fragment_usse_free(SceUID uid)
|
||||
{
|
||||
void* mem = NULL;
|
||||
if (sceKernelGetMemBlockBase(uid, &mem) < 0) {
|
||||
return;
|
||||
}
|
||||
sceGxmUnmapFragmentUsseMemory(mem);
|
||||
sceKernelFreeMemBlock(uid);
|
||||
}
|
||||
15
miniwin/src/d3drm/backends/gxm/gxm_memory.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL_stdinc.h>
|
||||
#include <psp2/types.h>
|
||||
|
||||
void* patcher_host_alloc(void* user_data, unsigned int size);
|
||||
void patcher_host_free(void* user_data, void* mem);
|
||||
|
||||
void* vita_mem_alloc(unsigned int type, size_t size, size_t alignment, int attribs, SceUID* uid, const char* name);
|
||||
void vita_mem_free(SceUID uid);
|
||||
|
||||
void* vita_mem_vertex_usse_alloc(unsigned int size, SceUID* uid, unsigned int* usse_offset);
|
||||
void vita_mem_vertex_usse_free(SceUID uid);
|
||||
void* vita_mem_fragment_usse_alloc(unsigned int size, SceUID* uid, unsigned int* usse_offset);
|
||||
void vita_mem_fragment_usse_free(SceUID uid);
|
||||
1101
miniwin/src/d3drm/backends/gxm/gxm_renderer.cpp
Normal file
13
miniwin/src/d3drm/backends/gxm/razor.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <psp2/razor_capture.h>
|
||||
#include <psp2/razor_hud.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern int sceRazorGpuCaptureSetTrigger(int frames, const char* path);
|
||||
|
||||
extern int sceRazorGpuTraceTrigger();
|
||||
extern int sceRazorGpuTraceSetFilename(const char* filename, int counter);
|
||||
extern int sceRazorHudSetDisplayEnabled(bool enable);
|
||||
}
|
||||
2
miniwin/src/d3drm/backends/gxm/shaders/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.exe
|
||||
cache/
|
||||
106
miniwin/src/d3drm/backends/gxm/shaders/CMakeLists.txt
Normal file
@ -0,0 +1,106 @@
|
||||
cmake_minimum_required(VERSION 3.25...4.0 FATAL_ERROR)
|
||||
|
||||
enable_language(ASM)
|
||||
|
||||
find_program(PSP2CGC NAMES ${CMAKE_CURRENT_SOURCE_DIR}/psp2cgc.exe psp2cgc.exe psp2cgc)
|
||||
find_program(PSP2SHADERPERF NAMES ${CMAKE_CURRENT_SOURCE_DIR}/psp2shaderperf.exe psp2shaderperf.exe psp2shaderperf)
|
||||
|
||||
list(APPEND CGC_COMMON_FLAGS "-Wperf" "-cache" "-cachedir" "${CMAKE_CURRENT_BINARY_DIR}/cache" "-W4" "-Wsuppress=5206,5203")
|
||||
|
||||
make_directory("${CMAKE_CURRENT_BINARY_DIR}/cache")
|
||||
|
||||
# compile .cg to .gxp if psp2cgc is found
|
||||
macro(COMPILE_SHADER INPUT_CG OUTPUT_GXP PROFILE)
|
||||
set(EXTRA_FLAGS "${ARGN}")
|
||||
|
||||
set(INPUT_CG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${INPUT_CG}")
|
||||
set(OUTPUT_GXP_PATH "${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_GXP}")
|
||||
set(TRACKED_GXP_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${OUTPUT_GXP}")
|
||||
|
||||
if(PSP2CGC)
|
||||
if(EXISTS ${TRACKED_GXP_PATH})
|
||||
file(COPY ${TRACKED_GXP_PATH} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endif()
|
||||
add_custom_command(
|
||||
OUTPUT "${OUTPUT_GXP_PATH}"
|
||||
COMMAND "${PSP2CGC}" ${CGC_COMMON_FLAGS} -profile "${PROFILE}" ${EXTRA_FLAGS} "${INPUT_CG_PATH}" -o "${OUTPUT_GXP_PATH}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${OUTPUT_GXP_PATH}" "${TRACKED_GXP_PATH}"
|
||||
DEPENDS "${INPUT_CG_PATH}"
|
||||
COMMENT "Compiling ${INPUT_CG} -> ${OUTPUT_GXP} ${PROFILE}"
|
||||
)
|
||||
else()
|
||||
if(NOT EXISTS "${TRACKED_GXP_PATH}")
|
||||
message(FATAL_ERROR "missing shader ${TRACKED_GXP_PATH} ${INPUT_CG}, but psp2cgc.exe not found")
|
||||
endif()
|
||||
add_custom_command(
|
||||
OUTPUT "${OUTPUT_GXP_PATH}"
|
||||
COMMAND /usr/bin/env bash
|
||||
ARGS "-c"
|
||||
"if [ \"${INPUT_CG_PATH}\" -nt \"${TRACKED_GXP_PATH}\" ]; then
|
||||
echo 'warning: ${INPUT_CG} changed but dont have psp2cgc, cant recompile' >&2;
|
||||
fi"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${TRACKED_GXP_PATH}" "${OUTPUT_GXP_PATH}"
|
||||
DEPENDS "${INPUT_CG_PATH}" "${TRACKED_GXP_PATH}"
|
||||
VERBATIM
|
||||
COMMENT "Copy ${TRACKED_GXP_PATH} -> ${OUTPUT_GXP} ${PROFILE}"
|
||||
)
|
||||
endif()
|
||||
set(TARGET_NAME "compile_${OUTPUT_GXP}")
|
||||
string(REPLACE "." "_" TARGET_NAME "${TARGET_NAME}")
|
||||
add_custom_target("${TARGET_NAME}" DEPENDS "${OUTPUT_GXP_PATH}")
|
||||
add_dependencies(gxm_shaders_compile "${TARGET_NAME}")
|
||||
endmacro()
|
||||
|
||||
|
||||
# analyze gxp to create a .perf.txt
|
||||
macro(GENERATE_PERF GXP_FILE)
|
||||
set(GXP_PATH "${CMAKE_CURRENT_BINARY_DIR}/${GXP_FILE}")
|
||||
string(REPLACE ".gxp" ".perf.txt" PERF_FILE_NAME "${GXP_FILE}")
|
||||
set(PERF_FILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${PERF_FILE_NAME}")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${PERF_FILE_PATH}"
|
||||
COMMAND "${PSP2SHADERPERF}" -stats -symbols -disasm "${GXP_PATH}" > "${PERF_FILE_PATH}"
|
||||
DEPENDS "${GXP_PATH}"
|
||||
COMMENT "Generating performance analysis for ${GXP_FILE}"
|
||||
)
|
||||
set(TARGET_NAME "perf_${PERF_FILE_NAME}")
|
||||
string(REPLACE "." "_" TARGET_NAME "${TARGET_NAME}")
|
||||
add_custom_target("${TARGET_NAME}" DEPENDS "${PERF_FILE_PATH}")
|
||||
add_dependencies(gxm_perfs "${TARGET_NAME}" )
|
||||
endmacro()
|
||||
|
||||
|
||||
|
||||
add_library(gxm_shaders STATIC gxm_shaders.s)
|
||||
|
||||
target_include_directories(gxm_shaders PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
add_custom_target(gxm_shaders_compile)
|
||||
add_dependencies(gxm_shaders gxm_shaders_compile)
|
||||
|
||||
COMPILE_SHADER(plane.vert.cg plane.vert.gxp sce_vp_psp2)
|
||||
COMPILE_SHADER(color.frag.cg color.frag.gxp sce_fp_psp2)
|
||||
COMPILE_SHADER(image.frag.cg image.frag.gxp sce_fp_psp2)
|
||||
COMPILE_SHADER(main.vert.cg main.vert.gxp sce_vp_psp2)
|
||||
COMPILE_SHADER(main.frag.cg main.color.frag.gxp sce_fp_psp2)
|
||||
COMPILE_SHADER(main.frag.cg main.texture.frag.gxp sce_fp_psp2 -DTEXTURED=1)
|
||||
|
||||
|
||||
# .perf.txt
|
||||
if(PSP2SHADERPERF)
|
||||
add_custom_target(gxm_perfs)
|
||||
add_dependencies(gxm_shaders gxm_perfs)
|
||||
GENERATE_PERF(plane.vert.gxp)
|
||||
GENERATE_PERF(color.frag.gxp)
|
||||
GENERATE_PERF(image.frag.gxp)
|
||||
GENERATE_PERF(main.vert.gxp)
|
||||
GENERATE_PERF(main.color.frag.gxp)
|
||||
GENERATE_PERF(main.texture.frag.gxp)
|
||||
else()
|
||||
message(STATUS "psp2shaderperf not found")
|
||||
endif()
|
||||
|
||||
|
||||
6
miniwin/src/d3drm/backends/gxm/shaders/color.frag.cg
Normal file
@ -0,0 +1,6 @@
|
||||
void main(
|
||||
uniform float4 uColor : COLOR,
|
||||
out float4 outColor : COLOR
|
||||
) {
|
||||
outColor = uColor;
|
||||
}
|
||||
BIN
miniwin/src/d3drm/backends/gxm/shaders/color.frag.gxp
Normal file
26
miniwin/src/d3drm/backends/gxm/shaders/color.frag.perf.txt
Normal file
@ -0,0 +1,26 @@
|
||||
Total estimated cost: 1 cycles, parallel mode
|
||||
Register count: 2 PAs, 0 temps, 4 SAs *
|
||||
Texture reads: 0 non-dependent, dependent: 0 unconditional, 0 conditional
|
||||
|
||||
High level analysis:
|
||||
No warnings.
|
||||
|
||||
* Please refer to the Razor documentation for details regarding the meaning of these numbers. Decreasing the number of registers used will not necessarily increase performance
|
||||
|
||||
Instruction statistics:
|
||||
Number of alu ops: 1
|
||||
Number of mem ops: 0
|
||||
Number of tex ops: 0
|
||||
Number of floating point ops: 0
|
||||
Number of integer ops: 0
|
||||
Number of pack ops: 1
|
||||
Number of mov ops: 0
|
||||
Number of nop ops: 0
|
||||
|
||||
Constants:
|
||||
[DEFAULT + 0 ] sa0 = (float4) uColor
|
||||
|
||||
|
||||
Primary program:
|
||||
0: pack.f16.f32 pa0.xyzw, sa0.xyzw
|
||||
|
||||
32
miniwin/src/d3drm/backends/gxm/shaders/gxm_shaders.h
Normal file
@ -0,0 +1,32 @@
|
||||
#include <psp2/gxm.h>
|
||||
|
||||
#define GXP(sym) \
|
||||
extern uint8_t _inc_##sym[]; \
|
||||
static const SceGxmProgram* sym = (const SceGxmProgram*) _inc_##sym;
|
||||
|
||||
GXP(mainVertexProgramGxp);
|
||||
GXP(mainColorFragmentProgramGxp);
|
||||
GXP(mainTextureFragmentProgramGxp);
|
||||
GXP(planeVertexProgramGxp);
|
||||
GXP(imageFragmentProgramGxp);
|
||||
GXP(colorFragmentProgramGxp);
|
||||
|
||||
static const SceGxmBlendInfo blendInfoOpaque = {
|
||||
.colorMask = SCE_GXM_COLOR_MASK_ALL,
|
||||
.colorFunc = SCE_GXM_BLEND_FUNC_NONE,
|
||||
.alphaFunc = SCE_GXM_BLEND_FUNC_NONE,
|
||||
.colorSrc = SCE_GXM_BLEND_FACTOR_ZERO,
|
||||
.colorDst = SCE_GXM_BLEND_FACTOR_ZERO,
|
||||
.alphaSrc = SCE_GXM_BLEND_FACTOR_ZERO,
|
||||
.alphaDst = SCE_GXM_BLEND_FACTOR_ZERO,
|
||||
};
|
||||
|
||||
static const SceGxmBlendInfo blendInfoTransparent = {
|
||||
.colorMask = SCE_GXM_COLOR_MASK_ALL,
|
||||
.colorFunc = SCE_GXM_BLEND_FUNC_ADD,
|
||||
.alphaFunc = SCE_GXM_BLEND_FUNC_ADD,
|
||||
.colorSrc = SCE_GXM_BLEND_FACTOR_SRC_ALPHA,
|
||||
.colorDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||
.alphaSrc = SCE_GXM_BLEND_FACTOR_ONE,
|
||||
.alphaDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||
};
|
||||
15
miniwin/src/d3drm/backends/gxm/shaders/gxm_shaders.s
Normal file
@ -0,0 +1,15 @@
|
||||
.section .rodata, "a", %progbits
|
||||
|
||||
.macro embed file, symbol
|
||||
.global _inc_\symbol
|
||||
.align 16
|
||||
_inc_\symbol:
|
||||
.incbin "\file"
|
||||
.endm
|
||||
|
||||
embed "main.vert.gxp", mainVertexProgramGxp
|
||||
embed "main.color.frag.gxp", mainColorFragmentProgramGxp
|
||||
embed "main.texture.frag.gxp", mainTextureFragmentProgramGxp
|
||||
embed "plane.vert.gxp", planeVertexProgramGxp
|
||||
embed "image.frag.gxp", imageFragmentProgramGxp
|
||||
embed "color.frag.gxp", colorFragmentProgramGxp
|
||||
10
miniwin/src/d3drm/backends/gxm/shaders/image.frag.cg
Normal file
@ -0,0 +1,10 @@
|
||||
void main(
|
||||
float4 vPosition : POSITION,
|
||||
float2 vTexCoord : TEXCOORD0,
|
||||
|
||||
uniform sampler2D uTexture,
|
||||
|
||||
out float4 outColor : COLOR
|
||||
) {
|
||||
outColor = tex2D(uTexture, vTexCoord);
|
||||
}
|
||||
BIN
miniwin/src/d3drm/backends/gxm/shaders/image.frag.gxp
Normal file
29
miniwin/src/d3drm/backends/gxm/shaders/image.frag.perf.txt
Normal file
@ -0,0 +1,29 @@
|
||||
Total estimated cost: 0 cycles, parallel mode
|
||||
Register count: 2 PAs, 0 temps, 0 SAs *
|
||||
Texture reads: 1 non-dependent, dependent: 0 unconditional, 0 conditional
|
||||
|
||||
High level analysis:
|
||||
No warnings.
|
||||
|
||||
* Please refer to the Razor documentation for details regarding the meaning of these numbers. Decreasing the number of registers used will not necessarily increase performance
|
||||
|
||||
Instruction statistics:
|
||||
Number of alu ops: 0
|
||||
Number of mem ops: 0
|
||||
Number of tex ops: 0
|
||||
Number of floating point ops: 0
|
||||
Number of integer ops: 0
|
||||
Number of pack ops: 0
|
||||
Number of mov ops: 0
|
||||
Number of nop ops: 0
|
||||
|
||||
|
||||
Samplers:
|
||||
TEXUNIT0 = uTexture
|
||||
|
||||
Iterators:
|
||||
|
||||
|
||||
Primary program:
|
||||
pa0 = tex2D<half4>(uTexture, TEXCOORD0.xy)
|
||||
|
||||
BIN
miniwin/src/d3drm/backends/gxm/shaders/main.color.frag.gxp
Normal file
134
miniwin/src/d3drm/backends/gxm/shaders/main.color.frag.perf.txt
Normal file
@ -0,0 +1,134 @@
|
||||
Total estimated cost: 63.5 cycles, parallel mode
|
||||
Register count: 8 PAs, 16 temps, 38 SAs *
|
||||
Texture reads: 0 non-dependent, dependent: 0 unconditional, 0 conditional
|
||||
|
||||
High level analysis:
|
||||
No warnings.
|
||||
|
||||
* Please refer to the Razor documentation for details regarding the meaning of these numbers. Decreasing the number of registers used will not necessarily increase performance
|
||||
|
||||
Instruction statistics:
|
||||
Number of alu ops: 63
|
||||
Number of mem ops: 0
|
||||
Number of tex ops: 0
|
||||
Number of floating point ops: 43
|
||||
Number of integer ops: 1
|
||||
Number of pack ops: 1
|
||||
Number of mov ops: 15
|
||||
Number of nop ops: 2
|
||||
|
||||
Constants:
|
||||
[DEFAULT + 0 ] sa0 = (float1) uShininess
|
||||
[DEFAULT + 2 ] sa2 = (float4) uColor
|
||||
[BUFFER0 + 0 ] = (float4) uLights[0].color
|
||||
[BUFFER0 + 4 ] = (float4) uLights[0].vec
|
||||
[BUFFER0 + 8 ] = (float1) uLights[0].isDirectional
|
||||
[BUFFER0 + 10 ] = (float4) uLights[1].color
|
||||
[BUFFER0 + 14 ] = (float4) uLights[1].vec
|
||||
[BUFFER0 + 18 ] = (float1) uLights[1].isDirectional
|
||||
[BUFFER0 + 20 ] = (float3) uAmbientLight
|
||||
[LITERAL + 1 ] sa7 = 0xffffffff (-1.#QNAN0f) (-1.#QNANh, -1.#QNANh)
|
||||
[LITERAL + 2 ] sa8 = 0x3f800000 (1.000000f) (0.00000h, 1.87500h)
|
||||
[BUFFER0 ] sa6 = buffer base address
|
||||
|
||||
Iterators:
|
||||
pa0 = (float4) TEXCOORD1
|
||||
pa4 = (float4) TEXCOORD2
|
||||
|
||||
|
||||
Secondary program:
|
||||
0 : lda32 sa1, [sa6, 0x9]
|
||||
1 : lda32.fetch3 sa9, [sa6, 0x4]
|
||||
2 : mul.f32 sa32.xy, -sa8.yz, sa0.yy
|
||||
3 : mul.f32 sa34.x, -sa10.y, sa0.y
|
||||
4 : lda32.fetch4 sa12, [sa6, 0x0]
|
||||
5 : mov.f32 sa36.xy, {0, 0}
|
||||
6 : mov.f32 sa30.x, {0}
|
||||
7 : lda32 sa15, [sa6, 0x13]
|
||||
8 : lda32.fetch3 sa16, [sa6, 0xe]
|
||||
9 : mul.f32 sa26.xy, -sa16.xy, sa14.yy
|
||||
10: mul.f32 sa28.x, -sa18.x, sa14.y
|
||||
11: lda32.fetch4 sa19, [sa6, 0xa]
|
||||
12: lda32.fetch3 sa22, [sa6, 0x14]
|
||||
13: nop
|
||||
|
||||
Primary program:
|
||||
0 : cmp.gt.f32 p0, sa0.x, {0}
|
||||
1 : mov.f32 i0.xyz, pa0.xyz
|
||||
2 : add.f32 i1.xyz, sa8.yzw, -i0.xyz
|
||||
2 : +dot.f32 pa3.x, i0.xyz, i0.xyz
|
||||
3 : mov.f32 i2.xyz, sa32.xyz
|
||||
4 : mad.f32 i2.xyz, -sa0.yyy, i1.xyz, i2.xyz
|
||||
5 : add.f32 i1.xyz, i2.xyz, i1.xyz
|
||||
5 : +rsq.f32 pa3.x, pa3.x
|
||||
6 : dot.f32 i2.x, i1.xyz, i1.xyz
|
||||
7 : rsq.f32 pa3.x, i2.x
|
||||
7 : +mul.f32 i0.xyz, -i0.xyz, pa2.yyy
|
||||
8 : mad.f32 i2.xyz, pa2.yyy, i1.xyz, i0.xyz
|
||||
8 : +mov.f32 r6.xy, i0.xy
|
||||
9 : mov.f32 r8.x, i0.z
|
||||
10: dot.f32 i0.x, i2.xyz, i2.xyz
|
||||
10: +mov.f32 r2.xy, i2.xy
|
||||
11: mov.f32 r4.x, i2.z
|
||||
12: rsq.f32 pa3.x, i0.x
|
||||
12: +mul.f32 i0.xyz, i1.xyz, pa2.yyy
|
||||
13: dot.f32 i0.x, pa4.xyz, i0.xyz
|
||||
14: max.f32 r14.x, i0.x, {0}
|
||||
15: p0 br #19
|
||||
16: mov.f32 r10.xy, sa36.xy
|
||||
17: or.u32 r12.x, sa30.x, 0x0
|
||||
18: br #30
|
||||
#19: cmov.lezero.f32 r0.x, r14.x, {0}, sa8.x
|
||||
20: cmov.ltzero.f32 i0.x, r14.x, sa8.x, {0}
|
||||
21: mad.f32 i0.x, r0.x, {1}, -i0.x
|
||||
22: mul.f32 i1.xyz, r2.xyz, pa2.yyy
|
||||
23: dot.f32 i1.x, pa4.xyz, i1.xyz
|
||||
24: max.f32 i1.x, i1.x, {0}
|
||||
25: mul.f32 i0.xyz, sa12.xyz, i0.xxx
|
||||
25: +log.f32 pa3.x, i1.x
|
||||
26: mul.f32 i1.x, sa0.x, pa2.y
|
||||
27: exp.f32 i1.x, i1.x
|
||||
28: mad.f32 r10.xy, i0.xy, i1.xx, {0, 0}
|
||||
29: mul.f32 r12.x, i0.z, i1.x
|
||||
#30: nop
|
||||
31: mov.f32 i0.xyz, sa16.xyz
|
||||
32: mad.f32 i0.xyz, -pa0.xyz, {1, 1, 1}, i0.xyz
|
||||
33: mov.f32 i1.xyz, sa26.xyz
|
||||
34: mad.f32 i1.xyz, -sa14.yyy, i0.xyz, i1.xyz
|
||||
35: add.f32 i0.xyz, i1.xyz, i0.xyz
|
||||
35: +mov.f32 i2.xyz, r6.xyz
|
||||
36: dot.f32 i1.x, i0.xyz, i0.xyz
|
||||
37: rsq.f32 i1.x, i1.x
|
||||
38: mad.f32 i2.xyz, i1.xxx, i0.xyz, i2.xyz
|
||||
39: mul.f32 i0.xyz, i0.xyz, i1.xxx
|
||||
39: +mov.f32 r0.xy, i2.xy
|
||||
40: dot.f32 i0.x, pa4.xyz, i0.xyz
|
||||
41: max.f32 pa2.x, i0.x, {0}
|
||||
42: dot.f32 i0.x, i2.xyz, i2.xyz
|
||||
43: mov.f32 r2.x, i2.z
|
||||
44: rsq.f32 pa0.-y, i0.x
|
||||
45: !p0 br #57
|
||||
46: cmov.lezero.f32 pa0.x, pa2.x, {0}, sa8.x
|
||||
47: cmov.ltzero.f32 i0.x, pa2.x, sa8.x, {0}
|
||||
48: mad.f32 i0.x, pa0.x, {1}, -i0.x
|
||||
49: mul.f32 i1.xyz, r0.xyz, pa0.yyy
|
||||
50: dot.f32 i1.x, pa4.xyz, i1.xyz
|
||||
51: max.f32 i1.x, i1.x, {0}
|
||||
52: mul.f32 i0.xyz, sa18.yzw, i0.xxx
|
||||
52: +log.f32 pa0.x, i1.x
|
||||
53: mul.f32 i1.x, sa0.x, pa0.x
|
||||
54: exp.f32 i1.x, i1.x
|
||||
55: mad.f32 r10.xy, i0.xy, i1.xx, r10.xy
|
||||
56: mad.f32 r12.x, i0.z, i1.x, r12.x
|
||||
#57: nop
|
||||
58: mad.f32 i0.xy, r14.xx, sa12.xy, sa22.xy
|
||||
59: mad.f32 i0.--z, r14.--x, sa14.--x, sa24.--x
|
||||
60: mov.f32 i1.xyz, sa18.yzw
|
||||
61: mad.f32 i0.xyz, pa2.xxx, i1.xyz, i0.xyz
|
||||
62: mov.f32 i1.xyz, r10.xyz
|
||||
63: mov.f32 i2.xyzw, sa2.xyzw
|
||||
64: mad.f32 i0.xyz, i2.xyz, i0.xyz, i1.xyz
|
||||
65: min.f32 i0.xyz, i0.xyz, {1, 1, 1}
|
||||
66: max.f32 i2.xyz, i0.xyz, {0, 0, 0}
|
||||
67: pack.f16.f32 pa0.xyzw, i2.xyzw
|
||||
|
||||
54
miniwin/src/d3drm/backends/gxm/shaders/main.frag.cg
Normal file
@ -0,0 +1,54 @@
|
||||
struct SceneLight {
|
||||
float4 color;
|
||||
float4 vec;
|
||||
float isDirectional;
|
||||
};
|
||||
|
||||
void main(
|
||||
float4 vPosition : POSITION,
|
||||
float2 vTexCoord : TEXCOORD0,
|
||||
float3 vViewPos : TEXCOORD1,
|
||||
float3 vNormal : TEXCOORD2,
|
||||
|
||||
uniform __nostrip SceneLight uLights[2] : BUFFER[0],
|
||||
uniform __nostrip float3 uAmbientLight : BUFFER[0],
|
||||
uniform __nostrip float uShininess,
|
||||
uniform __nostrip float4 uColor,
|
||||
uniform __nostrip sampler2D uTexture,
|
||||
|
||||
out float4 outColor : COLOR
|
||||
) {
|
||||
float3 diffuse = float3(0.0, 0.0, 0.0);
|
||||
float3 specular = float3(0.0, 0.0, 0.0);
|
||||
|
||||
float3 viewVec = normalize(-vViewPos); // Assuming camera at origin
|
||||
|
||||
diffuse += uAmbientLight;
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
float3 lightColor = uLights[i].color.rgb;
|
||||
float isDirectional = uLights[i].isDirectional;
|
||||
|
||||
float3 lightVec = normalize(lerp(uLights[i].vec.xyz - vViewPos, -uLights[i].vec.xyz, isDirectional));
|
||||
|
||||
float3 halfVec = normalize(viewVec + lightVec);
|
||||
float dotNL = max(dot(vNormal, lightVec), 0.0);
|
||||
float dotNH = max(dot(vNormal, halfVec), 0.0);
|
||||
|
||||
// Diffuse contribution
|
||||
diffuse += dotNL * lightColor;
|
||||
|
||||
// Specular
|
||||
float spec = pow(dotNH, uShininess);
|
||||
if(uShininess > 0.0) {
|
||||
specular += spec * lightColor * sign(dotNL);
|
||||
}
|
||||
}
|
||||
|
||||
outColor.rgb = clamp(diffuse * uColor.rgb + specular, 0.0, 1.0);
|
||||
outColor.a = uColor.a;
|
||||
#if TEXTURED
|
||||
float4 texel = tex2D(uTexture, vTexCoord);
|
||||
outColor.rgb *= texel.rgb;
|
||||
#endif
|
||||
}
|
||||
BIN
miniwin/src/d3drm/backends/gxm/shaders/main.texture.frag.gxp
Normal file
@ -0,0 +1,139 @@
|
||||
Total estimated cost: 64.5 cycles, parallel mode
|
||||
Register count: 12 PAs, 16 temps, 38 SAs *
|
||||
Texture reads: 1 non-dependent, dependent: 0 unconditional, 0 conditional
|
||||
|
||||
High level analysis:
|
||||
No warnings.
|
||||
|
||||
* Please refer to the Razor documentation for details regarding the meaning of these numbers. Decreasing the number of registers used will not necessarily increase performance
|
||||
|
||||
Instruction statistics:
|
||||
Number of alu ops: 64
|
||||
Number of mem ops: 0
|
||||
Number of tex ops: 0
|
||||
Number of floating point ops: 44
|
||||
Number of integer ops: 1
|
||||
Number of pack ops: 1
|
||||
Number of mov ops: 15
|
||||
Number of nop ops: 2
|
||||
|
||||
Constants:
|
||||
[DEFAULT + 0 ] sa0 = (float1) uShininess
|
||||
[DEFAULT + 2 ] sa2 = (float4) uColor
|
||||
[BUFFER0 + 0 ] = (float4) uLights[0].color
|
||||
[BUFFER0 + 4 ] = (float4) uLights[0].vec
|
||||
[BUFFER0 + 8 ] = (float1) uLights[0].isDirectional
|
||||
[BUFFER0 + 10 ] = (float4) uLights[1].color
|
||||
[BUFFER0 + 14 ] = (float4) uLights[1].vec
|
||||
[BUFFER0 + 18 ] = (float1) uLights[1].isDirectional
|
||||
[BUFFER0 + 20 ] = (float3) uAmbientLight
|
||||
[LITERAL + 1 ] sa7 = 0xffffffff (-1.#QNAN0f) (-1.#QNANh, -1.#QNANh)
|
||||
[LITERAL + 2 ] sa8 = 0x3f800000 (1.000000f) (0.00000h, 1.87500h)
|
||||
[BUFFER0 ] sa6 = buffer base address
|
||||
|
||||
Samplers:
|
||||
TEXUNIT0 = uTexture
|
||||
|
||||
Iterators:
|
||||
pa0 = (float4) TEXCOORD1
|
||||
pa8 = (float4) TEXCOORD2
|
||||
|
||||
|
||||
Secondary program:
|
||||
0 : lda32 sa1, [sa6, 0x9]
|
||||
1 : lda32.fetch3 sa9, [sa6, 0x4]
|
||||
2 : mul.f32 sa32.xy, -sa8.yz, sa0.yy
|
||||
3 : mul.f32 sa34.x, -sa10.y, sa0.y
|
||||
4 : lda32.fetch4 sa12, [sa6, 0x0]
|
||||
5 : mov.f32 sa36.xy, {0, 0}
|
||||
6 : mov.f32 sa30.x, {0}
|
||||
7 : lda32 sa15, [sa6, 0x13]
|
||||
8 : lda32.fetch3 sa16, [sa6, 0xe]
|
||||
9 : mul.f32 sa26.xy, -sa16.xy, sa14.yy
|
||||
10: mul.f32 sa28.x, -sa18.x, sa14.y
|
||||
11: lda32.fetch4 sa19, [sa6, 0xa]
|
||||
12: lda32.fetch3 sa22, [sa6, 0x14]
|
||||
13: nop
|
||||
|
||||
Primary program:
|
||||
pa4 = tex2D<float4>(uTexture, TEXCOORD0.xy)
|
||||
0 : cmp.gt.f32 p0, sa0.x, {0}
|
||||
1 : mov.f32 i0.xyz, pa0.xyz
|
||||
2 : add.f32 i1.xyz, sa8.yzw, -i0.xyz
|
||||
2 : +dot.f32 pa3.x, i0.xyz, i0.xyz
|
||||
3 : mov.f32 i2.xyz, sa32.xyz
|
||||
4 : mad.f32 i2.xyz, -sa0.yyy, i1.xyz, i2.xyz
|
||||
5 : add.f32 i1.xyz, i2.xyz, i1.xyz
|
||||
5 : +rsq.f32 pa3.x, pa3.x
|
||||
6 : dot.f32 i2.x, i1.xyz, i1.xyz
|
||||
7 : rsq.f32 pa3.x, i2.x
|
||||
7 : +mul.f32 i0.xyz, -i0.xyz, pa2.yyy
|
||||
8 : mad.f32 i2.xyz, pa2.yyy, i1.xyz, i0.xyz
|
||||
8 : +mov.f32 r6.xy, i0.xy
|
||||
9 : mov.f32 r8.x, i0.z
|
||||
10: dot.f32 i0.x, i2.xyz, i2.xyz
|
||||
10: +mov.f32 r2.xy, i2.xy
|
||||
11: mov.f32 r4.x, i2.z
|
||||
12: rsq.f32 pa3.x, i0.x
|
||||
12: +mul.f32 i0.xyz, i1.xyz, pa2.yyy
|
||||
13: dot.f32 i0.x, pa8.xyz, i0.xyz
|
||||
14: max.f32 r14.x, i0.x, {0}
|
||||
15: p0 br #19
|
||||
16: mov.f32 r10.xy, sa36.xy
|
||||
17: or.u32 r12.x, sa30.x, 0x0
|
||||
18: br #30
|
||||
#19: cmov.lezero.f32 r0.x, r14.x, {0}, sa8.x
|
||||
20: cmov.ltzero.f32 i0.x, r14.x, sa8.x, {0}
|
||||
21: mad.f32 i0.x, r0.x, {1}, -i0.x
|
||||
22: mul.f32 i1.xyz, r2.xyz, pa2.yyy
|
||||
23: dot.f32 i1.x, pa8.xyz, i1.xyz
|
||||
24: max.f32 i1.x, i1.x, {0}
|
||||
25: mul.f32 i0.xyz, sa12.xyz, i0.xxx
|
||||
25: +log.f32 pa3.x, i1.x
|
||||
26: mul.f32 i1.x, sa0.x, pa2.y
|
||||
27: exp.f32 i1.x, i1.x
|
||||
28: mad.f32 r10.xy, i0.xy, i1.xx, {0, 0}
|
||||
29: mul.f32 r12.x, i0.z, i1.x
|
||||
#30: nop
|
||||
31: mov.f32 i0.xyz, sa16.xyz
|
||||
32: mad.f32 i0.xyz, -pa0.xyz, {1, 1, 1}, i0.xyz
|
||||
33: mov.f32 i1.xyz, sa26.xyz
|
||||
34: mad.f32 i1.xyz, -sa14.yyy, i0.xyz, i1.xyz
|
||||
35: add.f32 i0.xyz, i1.xyz, i0.xyz
|
||||
35: +mov.f32 i2.xyz, r6.xyz
|
||||
36: dot.f32 i1.x, i0.xyz, i0.xyz
|
||||
37: rsq.f32 i1.x, i1.x
|
||||
38: mad.f32 i2.xyz, i1.xxx, i0.xyz, i2.xyz
|
||||
39: mul.f32 i0.xyz, i0.xyz, i1.xxx
|
||||
39: +mov.f32 r0.xy, i2.xy
|
||||
40: dot.f32 i0.x, pa8.xyz, i0.xyz
|
||||
41: max.f32 pa2.x, i0.x, {0}
|
||||
42: dot.f32 i0.x, i2.xyz, i2.xyz
|
||||
43: mov.f32 r2.x, i2.z
|
||||
44: rsq.f32 pa0.-y, i0.x
|
||||
45: !p0 br #57
|
||||
46: cmov.lezero.f32 pa0.x, pa2.x, {0}, sa8.x
|
||||
47: cmov.ltzero.f32 i0.x, pa2.x, sa8.x, {0}
|
||||
48: mad.f32 i0.x, pa0.x, {1}, -i0.x
|
||||
49: mul.f32 i1.xyz, r0.xyz, pa0.yyy
|
||||
50: dot.f32 i1.x, pa8.xyz, i1.xyz
|
||||
51: max.f32 i1.x, i1.x, {0}
|
||||
52: mul.f32 i0.xyz, sa18.yzw, i0.xxx
|
||||
52: +log.f32 pa0.x, i1.x
|
||||
53: mul.f32 i1.x, sa0.x, pa0.x
|
||||
54: exp.f32 i1.x, i1.x
|
||||
55: mad.f32 r10.xy, i0.xy, i1.xx, r10.xy
|
||||
56: mad.f32 r12.x, i0.z, i1.x, r12.x
|
||||
#57: nop
|
||||
58: mad.f32 i0.xy, r14.xx, sa12.xy, sa22.xy
|
||||
59: mad.f32 i0.--z, r14.--x, sa14.--x, sa24.--x
|
||||
60: mov.f32 i1.xyz, sa18.yzw
|
||||
61: mad.f32 i0.xyz, pa2.xxx, i1.xyz, i0.xyz
|
||||
62: mov.f32 i1.xyz, r10.xyz
|
||||
63: mov.f32 i2.xyzw, sa2.xyzw
|
||||
64: mad.f32 i0.xyz, i2.xyz, i0.xyz, i1.xyz
|
||||
65: min.f32 i0.xyz, i0.xyz, {1, 1, 1}
|
||||
66: max.f32 i0.xyz, i0.xyz, {0, 0, 0}
|
||||
67: mad.f32 i2.xyz, pa4.xyz, i0.xyz, {0, 0, 0}
|
||||
68: pack.f16.f32 pa0.xyzw, i2.xyzw
|
||||
|
||||
20
miniwin/src/d3drm/backends/gxm/shaders/main.vert.cg
Normal file
@ -0,0 +1,20 @@
|
||||
void main(
|
||||
float3 aPosition : POSITION,
|
||||
float3 aNormal : NORMAL,
|
||||
float2 aTexCoord : TEXCOORD0,
|
||||
|
||||
column_major uniform float4x4 uModelViewMatrix,
|
||||
column_major uniform float3x3 uNormalMatrix,
|
||||
column_major uniform float4x4 uProjectionMatrix,
|
||||
|
||||
out float4 vPosition : POSITION,
|
||||
out float2 vTexCoord : TEXCOORD0,
|
||||
out float3 vViewPos : TEXCOORD1,
|
||||
out float3 vNormal : TEXCOORD2
|
||||
) {
|
||||
float4 viewPos = mul(uModelViewMatrix, float4(aPosition, 1.0));
|
||||
vPosition = mul(uProjectionMatrix, viewPos);
|
||||
vViewPos = viewPos.xyz;
|
||||
vNormal = normalize(mul(uNormalMatrix, aNormal));
|
||||
vTexCoord = aTexCoord;
|
||||
}
|
||||
BIN
miniwin/src/d3drm/backends/gxm/shaders/main.vert.gxp
Normal file
87
miniwin/src/d3drm/backends/gxm/shaders/main.vert.perf.txt
Normal file
@ -0,0 +1,87 @@
|
||||
Total estimated cost: 18 cycles, parallel mode
|
||||
Register count: 12 PAs, 0 temps, 56 SAs *
|
||||
Texture reads: 0 non-dependent, dependent: 0 unconditional, 0 conditional
|
||||
|
||||
High level analysis:
|
||||
- One or multiple vertex outputs are misaligned due to a three coefficient TEXCOORD vertex output. This will lead to additional data movement instructions being generated. If only one three coefficient TEXCOORD output is present, assigning it the coordinate with the greatest index will allow the previous coordinates to be aligned.
|
||||
|
||||
* Please refer to the Razor documentation for details regarding the meaning of these numbers. Decreasing the number of registers used will not necessarily increase performance
|
||||
|
||||
Instruction statistics:
|
||||
Number of alu ops: 19
|
||||
Number of mem ops: 0
|
||||
Number of tex ops: 0
|
||||
Number of floating point ops: 14
|
||||
Number of integer ops: 0
|
||||
Number of pack ops: 0
|
||||
Number of mov ops: 4
|
||||
Number of nop ops: 0
|
||||
|
||||
Constants:
|
||||
[DEFAULT + 0 ] sa0 = (float4) uModelViewMatrix[4]
|
||||
[DEFAULT + 32 ] sa32 = (float3) uNormalMatrix[3]
|
||||
[DEFAULT + 16 ] sa16 = (float4) uProjectionMatrix[4]
|
||||
|
||||
Vertex attributes:
|
||||
pa0 = (float4) aPosition
|
||||
pa4 = (float4) aNormal
|
||||
pa8 = (float4) aTexCoord
|
||||
|
||||
|
||||
Secondary program:
|
||||
0 : nop
|
||||
1 : mov.f32 i0.xyzw, sa8.xyzw
|
||||
2 : mul.f32 i1.xyzw, sa16.xyzw, i0.xxxx
|
||||
3 : mad.f32 i1.xyzw, sa20.xyzw, i0.yyyy, i1.xyzw
|
||||
4 : mad.f32 i1.xyzw, sa24.xyzw, i0.zzzz, i1.xyzw
|
||||
5 : mad.f32 sa52.xy, sa28.xy, i0.ww, i1.xy
|
||||
6 : mad.f32 sa54.xy, sa30.xy, i0.ww, i1.zw
|
||||
7 : mov.f32 i1.xyzw, sa12.xyzw
|
||||
8 : mul.f32 i2.xyzw, sa28.xyzw, i1.wwww
|
||||
9 : mad.f32 i2.xyzw, sa24.xyzw, i1.zzzz, i2.xyzw
|
||||
10: mad.f32 i2.xyzw, sa20.xyzw, i1.yyyy, i2.xyzw
|
||||
11: mad.f32 sa48.xy, sa16.xy, i1.xx, i2.xy
|
||||
12: mad.f32 sa50.xy, sa18.xy, i1.xx, i2.zw
|
||||
13: mov.f32 i2.xyzw, sa4.xyzw
|
||||
14: mul.f32 i1.xyzw, sa16.xyzw, i2.xxxx
|
||||
15: mad.f32 i1.xyzw, sa20.xyzw, i2.yyyy, i1.xyzw
|
||||
16: mad.f32 i1.xyzw, sa24.xyzw, i2.zzzz, i1.xyzw
|
||||
17: mad.f32 sa44.xy, sa28.xy, i2.ww, i1.xy
|
||||
18: mad.f32 sa46.xy, sa30.xy, i2.ww, i1.zw
|
||||
19: mov.f32 i1.xyzw, sa0.xyzw
|
||||
20: mul.f32 i0.xyzw, sa16.xyzw, i1.xxxx
|
||||
20: +mov.f32 sa4.xy, i1.yy
|
||||
21: mad.f32 i0.xyzw, sa20.xyzw, i1.yyyy, i0.xyzw
|
||||
22: mad.f32 i0.xyzw, sa24.xyzw, i1.zzzz, i0.xyzw
|
||||
23: mad.f32 sa18.xy, sa28.xy, i1.ww, i0.xy
|
||||
24: mad.f32 sa16.xy, sa30.xy, i1.ww, i0.zw
|
||||
25: mov.f32 sa4.-y, i2.-y
|
||||
26: mov.f32 sa6.xy, (sa8.y, sa12.y)
|
||||
27: mov.f32 sa0.x, i1.x
|
||||
28: mov.f32 sa0.-y, i2.-x
|
||||
29: mov.f32 sa8.-y, sa12.-x
|
||||
30: mov.f32 sa10.-y, sa14.-x
|
||||
31: mov.f32 sa2.xy, sa8.xy
|
||||
32: mov.f32 sa8.x, i1.z
|
||||
33: mov.f32 sa8.-y, i2.-z
|
||||
|
||||
Primary program:
|
||||
0 : mov.f32 o4.xy, pa8.xy
|
||||
1 : mov.f32 i0.xyz, pa4.xyz
|
||||
2 : mad.f32 i1.xyz, sa32.xyz, i0.xxx, {0, 0, 0}
|
||||
3 : mad.f32 i1.xyz, sa36.xyz, i0.yyy, i1.xyz
|
||||
4 : mad.f32 i0.xyz, sa40.xyz, i0.zzz, i1.xyz
|
||||
5 : mov.f32 i1.xyz, pa0.xyz
|
||||
6 : mov.f32 i2.xyzw, sa48.xyzw
|
||||
7 : mad.f32 i2.xyzw, sa52.xyzw, i1.zzzz, i2.xyzw
|
||||
8 : mad.f32 i2.xyzw, sa44.xyzw, i1.yyyy, i2.xyzw
|
||||
9 : mad.f32 o0.xy, sa18.xy, i1.xx, i2.xy
|
||||
10: mad.f32 o2.xy, sa16.xy, i1.xx, i2.zw
|
||||
11: dot.f32 o6.x, sa0.xyzw, i1.xyz1
|
||||
12: dot.f32 o6.-y, sa4.xyzw, i1.xyz1
|
||||
13: dot.f32 o6.--z, sa8.xyzw, i1.xyz1
|
||||
14: dot.f32 i1.x, i0.xyz, i0.xyz
|
||||
15: rsq.f32 i1.x, i1.x
|
||||
16: mad.f32 o10.xy, i0.yz, i1.xx, {0, 0}
|
||||
17: mad.f32 o8.-y, i0.-x, i1.-x, {0, 0}
|
||||
|
||||
11
miniwin/src/d3drm/backends/gxm/shaders/plane.vert.cg
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
void main(
|
||||
float2 aPosition : POSITION,
|
||||
float2 aTexCoord : TEXCOORD0,
|
||||
|
||||
out float4 vPosition : POSITION,
|
||||
out float2 vTexCoord : TEXCOORD0
|
||||
) : POSITION {
|
||||
vPosition = float4(aPosition, 1.f, 1.f);
|
||||
vTexCoord = aTexCoord;
|
||||
}
|
||||
BIN
miniwin/src/d3drm/backends/gxm/shaders/plane.vert.gxp
Normal file
30
miniwin/src/d3drm/backends/gxm/shaders/plane.vert.perf.txt
Normal file
@ -0,0 +1,30 @@
|
||||
Total estimated cost: 3 cycles, parallel mode
|
||||
Register count: 8 PAs, 0 temps, 0 SAs *
|
||||
Texture reads: 0 non-dependent, dependent: 0 unconditional, 0 conditional
|
||||
|
||||
High level analysis:
|
||||
No warnings.
|
||||
|
||||
* Please refer to the Razor documentation for details regarding the meaning of these numbers. Decreasing the number of registers used will not necessarily increase performance
|
||||
|
||||
Instruction statistics:
|
||||
Number of alu ops: 4
|
||||
Number of mem ops: 0
|
||||
Number of tex ops: 0
|
||||
Number of floating point ops: 2
|
||||
Number of integer ops: 0
|
||||
Number of pack ops: 0
|
||||
Number of mov ops: 1
|
||||
Number of nop ops: 0
|
||||
|
||||
|
||||
Vertex attributes:
|
||||
pa0 = (float4) aPosition
|
||||
pa4 = (float4) aTexCoord
|
||||
|
||||
|
||||
Primary program:
|
||||
0: mov.f32 o4.xy, pa4.xy
|
||||
1: mul.f32 o0.xy, pa0.xy, {1, 1}
|
||||
2: mul.f32 o2.xy, {1, 1}, {1, 1}
|
||||
|
||||
1264
miniwin/src/d3drm/backends/gxm/tlsf.c
Normal file
91
miniwin/src/d3drm/backends/gxm/tlsf.h
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef INCLUDED_tlsf
|
||||
#define INCLUDED_tlsf
|
||||
|
||||
/*
|
||||
** Two Level Segregated Fit memory allocator, version 3.1.
|
||||
** Written by Matthew Conte
|
||||
** http://tlsf.baisoku.org
|
||||
**
|
||||
** Based on the original documentation by Miguel Masmano:
|
||||
** http://www.gii.upv.es/tlsf/main/docs
|
||||
**
|
||||
** This implementation was written to the specification
|
||||
** of the document, therefore no GPL restrictions apply.
|
||||
**
|
||||
** Copyright (c) 2006-2016, Matthew Conte
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** * Neither the name of the copyright holder nor the
|
||||
** names of its contributors may be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
** DISCLAIMED. IN NO EVENT SHALL MATTHEW CONTE BE LIABLE FOR ANY
|
||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* tlsf_t: a TLSF structure. Can contain 1 to N pools. */
|
||||
/* pool_t: a block of memory that TLSF can manage. */
|
||||
typedef void* tlsf_t;
|
||||
typedef void* pool_t;
|
||||
|
||||
/* Create/destroy a memory pool. */
|
||||
tlsf_t tlsf_create(void* mem);
|
||||
tlsf_t tlsf_create_with_pool(void* mem, size_t bytes);
|
||||
void tlsf_destroy(tlsf_t tlsf);
|
||||
pool_t tlsf_get_pool(tlsf_t tlsf);
|
||||
|
||||
/* Add/remove memory pools. */
|
||||
pool_t tlsf_add_pool(tlsf_t tlsf, void* mem, size_t bytes);
|
||||
void tlsf_remove_pool(tlsf_t tlsf, pool_t pool);
|
||||
|
||||
/* malloc/memalign/realloc/free replacements. */
|
||||
void* tlsf_malloc(tlsf_t tlsf, size_t bytes);
|
||||
void* tlsf_memalign(tlsf_t tlsf, size_t align, size_t bytes);
|
||||
void* tlsf_realloc(tlsf_t tlsf, void* ptr, size_t size);
|
||||
void tlsf_free(tlsf_t tlsf, void* ptr);
|
||||
|
||||
/* Returns internal block size, not original request size */
|
||||
size_t tlsf_block_size(void* ptr);
|
||||
|
||||
/* Overheads/limits of internal structures. */
|
||||
size_t tlsf_size(void);
|
||||
size_t tlsf_align_size(void);
|
||||
size_t tlsf_block_size_min(void);
|
||||
size_t tlsf_block_size_max(void);
|
||||
size_t tlsf_pool_overhead(void);
|
||||
size_t tlsf_alloc_overhead(void);
|
||||
|
||||
/* Debugging. */
|
||||
typedef void (*tlsf_walker)(void* ptr, size_t size, int used, void* user);
|
||||
void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user);
|
||||
/* Returns nonzero if any internal consistency check fails. */
|
||||
int tlsf_check(tlsf_t tlsf);
|
||||
int tlsf_check_pool(pool_t pool);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
48
miniwin/src/d3drm/backends/gxm/utils.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL_log.h>
|
||||
#include <psp2/gxm.h>
|
||||
#include <psp2/kernel/clib.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#define DEBUG_ONLY_PRINTF(...) sceClibPrintf(__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_ONLY_PRINTF(...)
|
||||
#endif
|
||||
|
||||
#define SCE_ERR(func, ...) \
|
||||
({ \
|
||||
DEBUG_ONLY_PRINTF("%s\n", #func); \
|
||||
int __sce_err_ret_val = func(__VA_ARGS__); \
|
||||
if (__sce_err_ret_val < 0) { \
|
||||
sceClibPrintf(#func " error: 0x%x\n", __sce_err_ret_val); \
|
||||
} \
|
||||
__sce_err_ret_val; \
|
||||
})
|
||||
|
||||
#define ALIGN(x, a) (((x) + ((a) -1)) & ~((a) -1))
|
||||
|
||||
#define ALIGNMENT(n, a) (((a) - ((n) % (a))) % (a))
|
||||
|
||||
#define SET_UNIFORM(buffer, param, value) \
|
||||
do { \
|
||||
size_t __offset = sceGxmProgramParameterGetResourceIndex(param); \
|
||||
void* __dst = (uint8_t*) (buffer) + (__offset * sizeof(uint32_t)); \
|
||||
memcpy(__dst, reinterpret_cast<const void*>(&(value)), sizeof(value)); \
|
||||
} while (0)
|
||||
|
||||
#define GET_SHADER_PARAM(var, gxp, name, ret) \
|
||||
const SceGxmProgramParameter* var = sceGxmProgramFindParameterByName(gxp, name); \
|
||||
if (!var) { \
|
||||
SDL_Log("Failed to find param %s", name); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
static void printMatrix4x4(const float mat[4][4])
|
||||
{
|
||||
sceClibPrintf("mat4{\n");
|
||||
for (int i = 0; i < 4; i++) {
|
||||
sceClibPrintf("%f %f %f %f\n", mat[i][0], mat[i][1], mat[i][2], mat[i][3]);
|
||||
}
|
||||
sceClibPrintf("}\n");
|
||||
}
|
||||
@ -20,6 +20,9 @@
|
||||
#ifdef USE_SOFTWARE_RENDER
|
||||
#include "d3drmrenderer_software.h"
|
||||
#endif
|
||||
#ifdef USE_GXM
|
||||
#include "d3drmrenderer_gxm.h"
|
||||
#endif
|
||||
|
||||
Direct3DRMRenderer* CreateDirect3DRMRenderer(
|
||||
const IDirect3DMiniwin* d3d,
|
||||
@ -66,6 +69,11 @@ Direct3DRMRenderer* CreateDirect3DRMRenderer(
|
||||
if (SDL_memcmp(guid, &DirectX9_GUID, sizeof(GUID)) == 0) {
|
||||
return DirectX9Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_GXM
|
||||
if (SDL_memcmp(guid, &GXM_GUID, sizeof(GUID)) == 0) {
|
||||
return GXMRenderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight, d3d->GetMSAASamples());
|
||||
}
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
@ -93,4 +101,7 @@ void Direct3DRMRenderer_EnumDevices(const IDirect3DMiniwin* d3d, LPD3DENUMDEVICE
|
||||
#ifdef USE_SOFTWARE_RENDER
|
||||
Direct3DRMSoftware_EnumDevice(cb, ctx);
|
||||
#endif
|
||||
#ifdef USE_GXM
|
||||
GXMRenderer_EnumDevice(cb, ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
181
miniwin/src/internal/d3drmrenderer_gxm.h
Normal file
@ -0,0 +1,181 @@
|
||||
#pragma once
|
||||
|
||||
#include "../d3drm/backends/gxm/gxm_context.h"
|
||||
#include "d3drmrenderer.h"
|
||||
#include "d3drmtexture_impl.h"
|
||||
#include "ddpalette_impl.h"
|
||||
#include "ddraw_impl.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <psp2/gxm.h>
|
||||
#include <psp2/kernel/clib.h>
|
||||
#include <psp2/types.h>
|
||||
#include <vector>
|
||||
|
||||
DEFINE_GUID(GXM_GUID, 0x682656F3, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x58, 0x4D);
|
||||
|
||||
#define GXM_VERTEX_BUFFER_COUNT 2
|
||||
#define GXM_FRAGMENT_BUFFER_COUNT 3
|
||||
|
||||
#define GXM_WITH_RAZOR DEBUG
|
||||
|
||||
struct GXMTextureCacheEntry {
|
||||
IDirect3DRMTexture* texture;
|
||||
Uint32 version;
|
||||
SceGxmTexture gxmTexture;
|
||||
SceGxmNotification* notification; // latest frame it was used in
|
||||
};
|
||||
|
||||
struct GXMMeshCacheEntry {
|
||||
const MeshGroup* meshGroup;
|
||||
int version;
|
||||
bool flat;
|
||||
|
||||
void* meshData;
|
||||
void* vertexBuffer;
|
||||
void* indexBuffer;
|
||||
uint16_t indexCount;
|
||||
};
|
||||
|
||||
struct SceneLightGXM {
|
||||
float color[4];
|
||||
float vec[4];
|
||||
float isDirectional;
|
||||
float _align;
|
||||
};
|
||||
|
||||
struct GXMSceneLightUniform {
|
||||
SceneLightGXM lights[2];
|
||||
float ambientLight[3];
|
||||
};
|
||||
|
||||
class GXMRenderer : public Direct3DRMRenderer {
|
||||
public:
|
||||
static Direct3DRMRenderer* Create(DWORD width, DWORD height, DWORD msaaSamples);
|
||||
GXMRenderer(DWORD width, DWORD height, SceGxmMultisampleMode msaaMode);
|
||||
~GXMRenderer() override;
|
||||
|
||||
void PushLights(const SceneLight* lightsArray, size_t count) override;
|
||||
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
||||
void SetFrustumPlanes(const Plane* frustumPlanes) override;
|
||||
Uint32 GetTextureId(IDirect3DRMTexture* texture, bool isUi, float scaleX, float scaleY) override;
|
||||
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
|
||||
HRESULT BeginFrame() override;
|
||||
void EnableTransparency() override;
|
||||
void SubmitDraw(
|
||||
DWORD meshId,
|
||||
const D3DRMMATRIX4D& modelViewMatrix,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const D3DRMMATRIX4D& viewMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
) override;
|
||||
HRESULT FinalizeFrame() override;
|
||||
void Resize(int width, int height, const ViewportTransform& viewportTransform) override;
|
||||
void Clear(float r, float g, float b) override;
|
||||
void Flip() override;
|
||||
void Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect, FColor color) override;
|
||||
void Download(SDL_Surface* target) override;
|
||||
void SetDither(bool dither) override;
|
||||
|
||||
void DeferredDelete(int index);
|
||||
|
||||
private:
|
||||
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
||||
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
|
||||
|
||||
GXMMeshCacheEntry GXMUploadMesh(const MeshGroup& meshGroup);
|
||||
|
||||
void StartScene();
|
||||
const SceGxmTexture* UseTexture(GXMTextureCacheEntry& texture);
|
||||
|
||||
inline GXMVertex2D* QuadVerticesBuffer()
|
||||
{
|
||||
GXMVertex2D* verts = &this->quadVertices[this->currentVertexBufferIndex][this->quadsUsed * 4];
|
||||
this->quadsUsed += 1;
|
||||
if (this->quadsUsed >= 50) {
|
||||
SDL_Log("QuadVerticesBuffer overflow");
|
||||
this->quadsUsed = 0; // declare bankruptcy
|
||||
}
|
||||
return verts;
|
||||
}
|
||||
|
||||
inline GXMSceneLightUniform* LightsBuffer() { return this->lights[this->currentFragmentBufferIndex]; }
|
||||
|
||||
std::vector<GXMTextureCacheEntry> m_textures;
|
||||
std::vector<GXMMeshCacheEntry> m_meshes;
|
||||
D3DRMMATRIX4D m_projection;
|
||||
std::vector<SceneLight> m_lights;
|
||||
std::vector<SceGxmTexture> m_textures_delete[GXM_FRAGMENT_BUFFER_COUNT];
|
||||
std::vector<void*> m_buffers_delete[GXM_FRAGMENT_BUFFER_COUNT];
|
||||
|
||||
bool transparencyEnabled = false;
|
||||
|
||||
// shader
|
||||
SceGxmShaderPatcherId mainVertexProgramId;
|
||||
SceGxmShaderPatcherId mainColorFragmentProgramId;
|
||||
SceGxmShaderPatcherId mainTextureFragmentProgramId;
|
||||
|
||||
SceGxmVertexProgram* mainVertexProgram;
|
||||
SceGxmFragmentProgram* opaqueColorFragmentProgram;
|
||||
SceGxmFragmentProgram* blendedColorFragmentProgram;
|
||||
SceGxmFragmentProgram* opaqueTextureFragmentProgram;
|
||||
SceGxmFragmentProgram* blendedTextureFragmentProgram;
|
||||
|
||||
// main shader vertex uniforms
|
||||
const SceGxmProgramParameter* uModelViewMatrix;
|
||||
const SceGxmProgramParameter* uNormalMatrix;
|
||||
const SceGxmProgramParameter* uProjectionMatrix;
|
||||
|
||||
// main shader fragment uniforms
|
||||
const SceGxmProgramParameter* uShininess;
|
||||
const SceGxmProgramParameter* uColor;
|
||||
const SceGxmProgramParameter* uLights;
|
||||
const SceGxmProgramParameter* uAmbientLight;
|
||||
|
||||
// uniforms / quad meshes
|
||||
GXMSceneLightUniform* lights[GXM_FRAGMENT_BUFFER_COUNT];
|
||||
GXMVertex2D* quadVertices[GXM_VERTEX_BUFFER_COUNT];
|
||||
uint16_t* quadIndices;
|
||||
int quadsUsed = 0;
|
||||
bool cleared = false;
|
||||
|
||||
SceGxmNotification vertexNotifications[GXM_VERTEX_BUFFER_COUNT];
|
||||
SceGxmNotification fragmentNotifications[GXM_FRAGMENT_BUFFER_COUNT];
|
||||
int currentFragmentBufferIndex = 0;
|
||||
int currentVertexBufferIndex = 0;
|
||||
|
||||
#ifdef GXM_WITH_RAZOR
|
||||
bool last_dpad_up;
|
||||
bool last_dpad_down;
|
||||
bool last_dpad_left;
|
||||
bool last_dpad_right;
|
||||
#endif
|
||||
|
||||
bool m_initialized = false;
|
||||
};
|
||||
|
||||
int gxm_library_init();
|
||||
|
||||
inline static void GXMRenderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
|
||||
{
|
||||
D3DDEVICEDESC halDesc = {};
|
||||
halDesc.dcmColorModel = D3DCOLORMODEL::RGB;
|
||||
halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH;
|
||||
halDesc.dwDeviceZBufferBitDepth = DDBD_16;
|
||||
halDesc.dwDeviceZBufferBitDepth |= DDBD_32;
|
||||
halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE;
|
||||
halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND;
|
||||
halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR;
|
||||
|
||||
D3DDEVICEDESC helDesc = {};
|
||||
helDesc.dwDeviceRenderBitDepth = DDBD_32;
|
||||
|
||||
int ret = gxm_library_init();
|
||||
if (ret < 0) {
|
||||
SDL_Log("gxm_library_init failed: %08x", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
EnumDevice(cb, ctx, "GXM HAL", &halDesc, &helDesc, GXM_GUID);
|
||||
}
|
||||
BIN
packaging/vita/sce_sys/icon0.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
packaging/vita/sce_sys/livearea/contents/bg.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
packaging/vita/sce_sys/livearea/contents/configure.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
packaging/vita/sce_sys/livearea/contents/gate.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
packaging/vita/sce_sys/livearea/contents/logo.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
23
packaging/vita/sce_sys/livearea/contents/template.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?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>gate.png</startup-image>
|
||||
</gate>
|
||||
<frame id="frame3">
|
||||
<liveitem>
|
||||
<image align="center" valign="top" x="0" y="0" height="0" origin="background">logo.png</image>
|
||||
</liveitem>
|
||||
</frame>
|
||||
<frame id="frame2">
|
||||
<liveitem>
|
||||
<target>psla:-config</target>
|
||||
<image>configure.png</image>
|
||||
<text align="center" valign="center" x="0" y="-64" origin="background" text-align="center" text-valign="center">
|
||||
<str color="#ff4500" bold="on" oblique="off" shadow="on" emboss="off">Configure</str>
|
||||
</text>
|
||||
</liveitem>
|
||||
</frame>
|
||||
</livearea>
|
||||
BIN
packaging/vita/sce_sys/manual/001.png
Normal file
|
After Width: | Height: | Size: 236 KiB |
BIN
packaging/vita/sce_sys/manual/002.png
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
packaging/vita/sce_sys/manual/003.png
Normal file
|
After Width: | Height: | Size: 192 KiB |
BIN
packaging/vita/sce_sys/manual/004.png
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
packaging/vita/sce_sys/manual/005.png
Normal file
|
After Width: | Height: | Size: 146 KiB |
BIN
packaging/vita/sce_sys/manual/006.png
Normal file
|
After Width: | Height: | Size: 148 KiB |
BIN
packaging/vita/sce_sys/manual/007.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
packaging/vita/sce_sys/manual/008.png
Normal file
|
After Width: | Height: | Size: 153 KiB |
BIN
packaging/vita/sce_sys/manual/009.png
Normal file
|
After Width: | Height: | Size: 160 KiB |
BIN
packaging/vita/sce_sys/manual/010.png
Normal file
|
After Width: | Height: | Size: 152 KiB |
BIN
packaging/vita/sce_sys/manual/011.png
Normal file
|
After Width: | Height: | Size: 171 KiB |
BIN
packaging/vita/sce_sys/manual/012.png
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
packaging/vita/sce_sys/manual/013.png
Normal file
|
After Width: | Height: | Size: 146 KiB |
BIN
packaging/vita/sce_sys/manual/014.png
Normal file
|
After Width: | Height: | Size: 144 KiB |
BIN
packaging/vita/sce_sys/manual/015.png
Normal file
|
After Width: | Height: | Size: 132 KiB |
BIN
packaging/vita/sce_sys/manual/016.png
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
packaging/vita/sce_sys/manual/017.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
packaging/vita/sce_sys/manual/018.png
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
packaging/vita/sce_sys/manual/019.png
Normal file
|
After Width: | Height: | Size: 186 KiB |
BIN
packaging/vita/sce_sys/manual/020.png
Normal file
|
After Width: | Height: | Size: 152 KiB |
BIN
packaging/vita/sce_sys/manual/021.png
Normal file
|
After Width: | Height: | Size: 123 KiB |
BIN
packaging/vita/sce_sys/manual/022.png
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
packaging/vita/sce_sys/manual/023.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
packaging/vita/sce_sys/manual/024.png
Normal file
|
After Width: | Height: | Size: 145 KiB |
BIN
packaging/vita/sce_sys/manual/025.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
packaging/vita/sce_sys/manual/026.png
Normal file
|
After Width: | Height: | Size: 202 KiB |
BIN
packaging/vita/sce_sys/manual/027.png
Normal file
|
After Width: | Height: | Size: 138 KiB |