Compare commits
13 Commits
5cea284906
...
097c8c00f9
| Author | SHA1 | Date | |
|---|---|---|---|
| 097c8c00f9 | |||
| aa5b41fe31 | |||
| 0d56859d94 | |||
| 1af5f238e4 | |||
| dd697d5650 | |||
| 5cf299a1c7 | |||
| 67bf825cc9 | |||
| 56e1696cd4 | |||
| d955fb6430 | |||
| dd910a31aa | |||
| 708c4d0ec3 | |||
| ad13d6c6a1 | |||
| 1c32158142 |
5
.ci/dolphin/Dockerfile
Normal file
5
.ci/dolphin/Dockerfile
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
FROM devkitpro/devkitppc
|
||||||
|
|
||||||
|
RUN apt update && \
|
||||||
|
apt install -y python3 python3-pip python3-polib python3-pil python3-dotenv python3-pyqt5 python3-opengl && \
|
||||||
|
dkp-pacman -S --needed --noconfirm gamecube-sdl2 ppc-liblzma ppc-libzip
|
||||||
12
.ci/dolphin/build-gamecube.sh
Executable file
12
.ci/dolphin/build-gamecube.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
docker build -t myapp:latest -f .ci/dolphin/Dockerfile .
|
||||||
|
docker run -it -v ./:/workdir myapp:latest /bin/bash -c ' \
|
||||||
|
export PATH="$DEVKITPPC/bin:$PATH" && \
|
||||||
|
cd /workdir && \
|
||||||
|
rm -rf build-gamecube && \
|
||||||
|
mkdir -p build-gamecube && \
|
||||||
|
cmake -S. -Bbuild-gamecube -DDUSK_TARGET_SYSTEM=gamecube -DCMAKE_TOOLCHAIN_FILE="$DEVKITPRO/cmake/GameCube.cmake" && \
|
||||||
|
cd build-gamecube && \
|
||||||
|
make VERBOSE=1
|
||||||
|
'
|
||||||
|
# docker run -it -v ./:/workdir myapp:latest /bin/bash
|
||||||
13
.ci/dolphin/build-wii.sh
Executable file
13
.ci/dolphin/build-wii.sh
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
docker build -t myapp:latest -f .ci/dolphin/Dockerfile .
|
||||||
|
docker run -it -v ./:/workdir myapp:latest /bin/bash -c ' \
|
||||||
|
export PATH="$DEVKITPPC/bin:$PATH" && \
|
||||||
|
cd /workdir && \
|
||||||
|
rm -rf build-wii && \
|
||||||
|
mkdir -p build-wii && \
|
||||||
|
cmake -S. -Bbuild-wii -DDUSK_TARGET_SYSTEM=wii -DCMAKE_TOOLCHAIN_FILE="$DEVKITPRO/cmake/Wii.cmake" && \
|
||||||
|
cd build-wii && \
|
||||||
|
make VERBOSE=1 && \
|
||||||
|
mv ./Dusk.dol ./boot.dol
|
||||||
|
'
|
||||||
|
# docker run -it -v ./:/workdir myapp:latest /bin/bash
|
||||||
@@ -72,3 +72,16 @@ jobs:
|
|||||||
name: dusk-psp
|
name: dusk-psp
|
||||||
path: build/gitea/
|
path: build/gitea/
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
|
build-dolphin:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y docker.io
|
||||||
|
- name: Docker test
|
||||||
|
run: |
|
||||||
|
./.ci/dolphin/build-gamecube.sh
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -102,3 +102,6 @@ yarn.lock
|
|||||||
|
|
||||||
.editor
|
.editor
|
||||||
.venv
|
.venv
|
||||||
|
|
||||||
|
/build2
|
||||||
|
/build*
|
||||||
107
CMakeLists.txt
107
CMakeLists.txt
@@ -4,18 +4,13 @@
|
|||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
# Setup
|
# Setup
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.18)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
|
||||||
|
|
||||||
option(ENABLE_TESTS "Enable tests" ON)
|
option(ENABLE_TESTS "Enable tests" OFF)
|
||||||
|
|
||||||
# Set target system
|
|
||||||
if(NOT DEFINED DUSK_TARGET_SYSTEM)
|
|
||||||
set(DUSK_TARGET_SYSTEM "linux")
|
|
||||||
# set(DUSK_TARGET_SYSTEM "psp")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Prep cache
|
# Prep cache
|
||||||
set(DUSK_CACHE_TARGET "dusk-target")
|
set(DUSK_CACHE_TARGET "dusk-target")
|
||||||
@@ -42,28 +37,48 @@ file(MAKE_DIRECTORY ${DUSK_GENERATED_HEADERS_DIR})
|
|||||||
# Find packages
|
# Find packages
|
||||||
find_package(Python3 COMPONENTS Interpreter REQUIRED)
|
find_package(Python3 COMPONENTS Interpreter REQUIRED)
|
||||||
|
|
||||||
|
# Set target system
|
||||||
|
# message(FATAL_ERROR "DISABLED FOR NOW2 ${DUSK_TARGET_SYSTEM}")
|
||||||
|
|
||||||
|
if(NOT DEFINED DUSK_TARGET_SYSTEM)
|
||||||
|
set(DUSK_TARGET_SYSTEM "linux")
|
||||||
|
# set(DUSK_TARGET_SYSTEM "psp")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Toolchains
|
# Toolchains
|
||||||
if(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
if(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
||||||
find_package(pspsdk REQUIRED)
|
find_package(pspsdk REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii")
|
||||||
|
# Override to make library and binary be the same.
|
||||||
|
set(DUSK_LIBRARY_TARGET_NAME "${DUSK_LIBRARY_TARGET_NAME}.elf" CACHE INTERNAL ${DUSK_CACHE_TARGET})
|
||||||
|
endif()
|
||||||
|
|
||||||
# Init Project.
|
# Init Project.
|
||||||
project(${DUSK_LIBRARY_TARGET_NAME}
|
project(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
VERSION 1.0.0
|
VERSION 1.0.0
|
||||||
LANGUAGES C
|
LANGUAGES C CXX
|
||||||
)
|
)
|
||||||
|
|
||||||
# MainLibrary
|
# Either, create library and binary separately (used for tests), or make them
|
||||||
add_library(${DUSK_LIBRARY_TARGET_NAME})
|
# one in the same so all code is in the binary.
|
||||||
|
if(ENABLE_TESTS)
|
||||||
|
# MainLibrary
|
||||||
|
add_library(${DUSK_LIBRARY_TARGET_NAME} STATIC)
|
||||||
|
|
||||||
# Binary Executable
|
# Binary Executable
|
||||||
add_executable(${DUSK_BINARY_TARGET_NAME})
|
add_executable(${DUSK_BINARY_TARGET_NAME} ${DUSK_SOURCES_DIR}/null.c)
|
||||||
|
|
||||||
# Link library to binary and test
|
# Link library to binary
|
||||||
target_link_libraries(${DUSK_BINARY_TARGET_NAME}
|
target_link_libraries(${DUSK_BINARY_TARGET_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
${DUSK_LIBRARY_TARGET_NAME}
|
${DUSK_LIBRARY_TARGET_NAME}
|
||||||
)
|
)
|
||||||
|
else()
|
||||||
|
set(DUSK_BINARY_TARGET_NAME "${DUSK_LIBRARY_TARGET_NAME}" CACHE INTERNAL ${DUSK_CACHE_TARGET})
|
||||||
|
add_executable(${DUSK_BINARY_TARGET_NAME} ${DUSK_SOURCES_DIR}/null.c)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Add tools
|
# Add tools
|
||||||
add_subdirectory(tools)
|
add_subdirectory(tools)
|
||||||
@@ -77,8 +92,10 @@ if(DUSK_TARGET_SYSTEM STREQUAL "linux")
|
|||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
||||||
SDL2
|
SDL2
|
||||||
|
pthread
|
||||||
OpenGL::GL
|
OpenGL::GL
|
||||||
GL
|
GL
|
||||||
|
m
|
||||||
)
|
)
|
||||||
|
|
||||||
elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
||||||
@@ -87,6 +104,7 @@ elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
|||||||
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
||||||
${SDL2_LIBRARIES}
|
${SDL2_LIBRARIES}
|
||||||
SDL2
|
SDL2
|
||||||
|
pthread
|
||||||
OpenGL::GL
|
OpenGL::GL
|
||||||
zip
|
zip
|
||||||
bz2
|
bz2
|
||||||
@@ -94,18 +112,61 @@ elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
|||||||
mbedtls
|
mbedtls
|
||||||
mbedcrypto
|
mbedcrypto
|
||||||
lzma
|
lzma
|
||||||
|
m
|
||||||
)
|
)
|
||||||
target_include_directories(${DUSK_LIBRARY_TARGET_NAME} PRIVATE
|
target_include_directories(${DUSK_LIBRARY_TARGET_NAME} PRIVATE
|
||||||
${SDL2_INCLUDE_DIRS}
|
${SDL2_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii")
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
|
||||||
|
configure_file(opengl.pc.in opengl.pc @ONLY)
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(zip IMPORTED_TARGET libzip)
|
||||||
|
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
||||||
|
DOLPHIN
|
||||||
|
)
|
||||||
|
|
||||||
|
# Custom flags for cglm
|
||||||
|
set(CGLM_SHARED OFF CACHE BOOL "Build cglm shared" FORCE)
|
||||||
|
set(CGLM_STATIC ON CACHE BOOL "Build cglm static" FORCE)
|
||||||
|
find_package(cglm REQUIRED)
|
||||||
|
|
||||||
|
# Compile lua
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(
|
||||||
|
liblua
|
||||||
|
URL https://www.lua.org/ftp/lua-5.5.0.tar.gz
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(liblua)
|
||||||
|
set(LUA_SRC_DIR "${liblua_SOURCE_DIR}/src")
|
||||||
|
set(LUA_C_FILES
|
||||||
|
lapi.c lauxlib.c lbaselib.c lcode.c lcorolib.c lctype.c ldblib.c ldebug.c
|
||||||
|
ldo.c ldump.c lfunc.c lgc.c linit.c liolib.c llex.c lmathlib.c lmem.c
|
||||||
|
loadlib.c lobject.c lopcodes.c loslib.c lparser.c lstate.c lstring.c
|
||||||
|
lstrlib.c ltable.c ltablib.c ltm.c lundump.c lutf8lib.c lvm.c lzio.c
|
||||||
|
)
|
||||||
|
list(TRANSFORM LUA_C_FILES PREPEND "${LUA_SRC_DIR}/")
|
||||||
|
add_library(liblua STATIC ${LUA_C_FILES})
|
||||||
|
target_include_directories(liblua PUBLIC "${LUA_SRC_DIR}")
|
||||||
|
target_compile_definitions(liblua PRIVATE LUA_USE_C89)
|
||||||
|
add_library(lua::lua ALIAS liblua)
|
||||||
|
set(Lua_FOUND TRUE CACHE BOOL "Lua found" FORCE)
|
||||||
|
|
||||||
|
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PRIVATE
|
||||||
|
cglm
|
||||||
|
liblua
|
||||||
|
m
|
||||||
|
fat
|
||||||
|
PkgConfig::zip
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Force turn tests off for now
|
# Force turn tests off for now
|
||||||
set(ENABLE_TESTS OFF CACHE BOOL "Enable tests" FORCE)
|
set(ENABLE_TESTS OFF CACHE BOOL "Enable tests" FORCE)
|
||||||
|
|
||||||
# Add code
|
# Add code
|
||||||
add_subdirectory(src)
|
add_subdirectory(${DUSK_SOURCES_DIR})
|
||||||
|
|
||||||
# Handle tests
|
# Handle tests
|
||||||
if(ENABLE_TESTS)
|
if(ENABLE_TESTS)
|
||||||
@@ -141,4 +202,12 @@ if(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
|||||||
PSAR_PATH ${DUSK_BUILD_DIR}/dusk.dsk
|
PSAR_PATH ${DUSK_BUILD_DIR}/dusk.dsk
|
||||||
VERSION 01.00
|
VERSION 01.00
|
||||||
)
|
)
|
||||||
|
elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii")
|
||||||
|
set(DUSK_BINARY_TARGET_NAME_DOL "${DUSK_BUILD_DIR}/Dusk.dol")
|
||||||
|
add_custom_command(TARGET ${DUSK_BINARY_TARGET_NAME} POST_BUILD
|
||||||
|
COMMAND elf2dol
|
||||||
|
"$<TARGET_FILE:${DUSK_BINARY_TARGET_NAME}>"
|
||||||
|
"${DUSK_BINARY_TARGET_NAME_DOL}"
|
||||||
|
COMMENT "Generating ${DUSK_BINARY_TARGET_NAME_DOL} from ${DUSK_BINARY_TARGET_NAME}"
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "uiframe.h"
|
#include "uiframe.h"
|
||||||
#include "display/spritebatch.h"
|
#include "display/spritebatch.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include <math.h>
|
#include "util/math.h"
|
||||||
|
|
||||||
void uiFrameDraw(
|
void uiFrameDraw(
|
||||||
const float_t x,
|
const float_t x,
|
||||||
|
|||||||
@@ -16,6 +16,21 @@ if PLATFORM == "psp" then
|
|||||||
inputBind("lstick_down", INPUT_ACTION_DOWN)
|
inputBind("lstick_down", INPUT_ACTION_DOWN)
|
||||||
inputBind("lstick_left", INPUT_ACTION_LEFT)
|
inputBind("lstick_left", INPUT_ACTION_LEFT)
|
||||||
inputBind("lstick_right", INPUT_ACTION_RIGHT)
|
inputBind("lstick_right", INPUT_ACTION_RIGHT)
|
||||||
|
|
||||||
|
elseif PLATFORM == "gamecube" then
|
||||||
|
-- inputBind("start", INPUT_ACTION_RAGEQUIT)
|
||||||
|
-- inputBind("dpad_up", INPUT_ACTION_UP)
|
||||||
|
-- inputBind("dpad_down", INPUT_ACTION_DOWN)
|
||||||
|
-- inputBind("dpad_left", INPUT_ACTION_LEFT)
|
||||||
|
-- inputBind("dpad_right", INPUT_ACTION_RIGHT)
|
||||||
|
-- inputBind("button_b", INPUT_ACTION_CANCEL)
|
||||||
|
-- inputBind("button_a", INPUT_ACTION_ACCEPT)
|
||||||
|
-- inputBind("button_start", INPUT_ACTION_RAGEQUIT)
|
||||||
|
-- inputBind("lstick_up", INPUT_ACTION_UP)
|
||||||
|
-- inputBind("lstick_down", INPUT_ACTION_DOWN)
|
||||||
|
-- inputBind("lstick_left", INPUT_ACTION_LEFT)
|
||||||
|
-- inputBind("lstick_right", INPUT_ACTION_RIGHT)
|
||||||
|
|
||||||
else
|
else
|
||||||
if INPUT_KEYBOARD then
|
if INPUT_KEYBOARD then
|
||||||
inputBind("w", INPUT_ACTION_UP)
|
inputBind("w", INPUT_ACTION_UP)
|
||||||
@@ -37,5 +52,5 @@ else
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
localeSet(DUSK_LOCALE_EN_US)
|
-- localeSet(DUSK_LOCALE_EN_US)
|
||||||
sceneSet('scene/initial.dsf')
|
sceneSet('scene/initial.dsf')
|
||||||
@@ -8,37 +8,59 @@ module('time')
|
|||||||
module('map')
|
module('map')
|
||||||
module('glm')
|
module('glm')
|
||||||
|
|
||||||
screenSetBackground(colorBlack())
|
screenSetBackground(colorLime())
|
||||||
mapLoad('map/testmap/testmap.dmf')
|
|
||||||
camera = cameraCreate(CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC)
|
|
||||||
mapCamera = cameraCreate()
|
mapCamera = cameraCreate()
|
||||||
|
text = "Hello, Dusk!"
|
||||||
|
|
||||||
text = "Hello World"
|
x = -35
|
||||||
|
y = 0
|
||||||
|
|
||||||
function sceneDispose()
|
function sceneDispose()
|
||||||
end
|
end
|
||||||
|
|
||||||
function sceneUpdate()
|
function sceneUpdate()
|
||||||
end
|
end
|
||||||
|
|
||||||
function sceneRender()
|
function sceneRender()
|
||||||
-- Map Test
|
mapCamera.position = vec3(50, 50, 50)
|
||||||
cameraPushMatrix(mapCamera)
|
cameraPushMatrix(mapCamera)
|
||||||
mapCamera.position = vec3(300, 300, 300)
|
|
||||||
mapRender()
|
|
||||||
cameraPopMatrix()
|
|
||||||
|
|
||||||
-- UI Test
|
textDraw(x, y, text, colorBlue())
|
||||||
cameraPushMatrix(camera)
|
|
||||||
camera.bottom = screenGetHeight()
|
|
||||||
camera.right = screenGetWidth()
|
|
||||||
|
|
||||||
width, height = textMeasure(text)
|
|
||||||
x = (screenGetWidth() - width)
|
|
||||||
x = math.sin(TIME.time * 2) * (x / 2) + (x / 2)
|
|
||||||
y = (screenGetHeight() - height) / 2
|
|
||||||
y = math.cos(TIME.time * 3) * (y) + (y)
|
|
||||||
textDraw(x, y, text, colorMagenta())
|
|
||||||
|
|
||||||
|
spriteBatchFlush()
|
||||||
cameraPopMatrix()
|
cameraPopMatrix()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- screenSetBackground(colorBlack())
|
||||||
|
-- mapLoad('map/testmap/testmap.dmf')
|
||||||
|
-- camera = cameraCreate(CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC)
|
||||||
|
-- mapCamera = cameraCreate()
|
||||||
|
|
||||||
|
-- text = "Hello World"
|
||||||
|
|
||||||
|
-- function sceneDispose()
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- function sceneUpdate()
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- function sceneRender()
|
||||||
|
-- -- Map Test
|
||||||
|
-- mapCamera.position = vec3(300, 300, 300)
|
||||||
|
-- cameraPushMatrix(mapCamera)
|
||||||
|
-- mapRender()
|
||||||
|
-- cameraPopMatrix()
|
||||||
|
|
||||||
|
-- -- UI Test
|
||||||
|
-- cameraPushMatrix(camera)
|
||||||
|
-- camera.bottom = screenGetHeight()
|
||||||
|
-- camera.right = screenGetWidth()
|
||||||
|
|
||||||
|
-- width, height = textMeasure(text)
|
||||||
|
-- x = (screenGetWidth() - width)
|
||||||
|
-- x = math.sin(TIME.time * 2) * (x / 2) + (x / 2)
|
||||||
|
-- y = (screenGetHeight() - height) / 2
|
||||||
|
-- y = math.cos(TIME.time * 3) * (y) + (y)
|
||||||
|
-- textDraw(x, y, text, colorMagenta())
|
||||||
|
|
||||||
|
-- cameraPopMatrix()
|
||||||
|
-- end
|
||||||
@@ -3,4 +3,5 @@
|
|||||||
# This software is released under the MIT License.
|
# This software is released under the MIT License.
|
||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
add_asset(TILESET minogram.png type=PALETTIZED tileWidth=6 tileHeight=10 columns=16 rows=6)# Fixes PSP rendering
|
add_asset(TILESET minogram.png type=ALPHA tileWidth=6 tileHeight=10 columns=16 rows=6)# Fixes PSP rendering
|
||||||
|
# add_asset(TILESET minogram.png type=PALETTIZED tileWidth=6 tileHeight=10 columns=16 rows=6)# Fixes PSP rendering
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
cglm
|
cglm
|
||||||
GIT_REPOSITORY https://github.com/recp/cglm.git
|
GIT_REPOSITORY https://github.com/recp/cglm.git
|
||||||
|
|||||||
10
opengl.pc.in
Normal file
10
opengl.pc.in
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
|
libdir=${prefix}/lib
|
||||||
|
includedir=${prefix}/include
|
||||||
|
|
||||||
|
Name: OpenGL
|
||||||
|
Description: OpenGL (without GLX) library and headers.
|
||||||
|
Version: @PROJECT_VERSION@
|
||||||
|
Libs.private: -lstdc++ -logc -lm
|
||||||
|
Libs: -L${libdir} -lopengx
|
||||||
|
Cflags: -I${includedir}
|
||||||
@@ -3,29 +3,31 @@
|
|||||||
# This software is released under the MIT License.
|
# This software is released under the MIT License.
|
||||||
# https://opensource.org/licenses/MIT
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
find_package(cglm REQUIRED)
|
if(NOT cglm_FOUND)
|
||||||
find_package(libzip REQUIRED)
|
find_package(cglm REQUIRED)
|
||||||
find_package(Lua REQUIRED)
|
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC cglm)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(Lua_FOUND AND NOT TARGET Lua::Lua)
|
if(NOT libzip_FOUND)
|
||||||
add_library(Lua::Lua INTERFACE IMPORTED)
|
find_package(libzip REQUIRED)
|
||||||
set_target_properties(
|
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC zip)
|
||||||
Lua::Lua
|
endif()
|
||||||
PROPERTIES
|
|
||||||
INTERFACE_INCLUDE_DIRECTORIES "${LUA_INCLUDE_DIR}"
|
if(NOT Lua_FOUND)
|
||||||
INTERFACE_LINK_LIBRARIES "${LUA_LIBRARIES}"
|
find_package(Lua REQUIRED)
|
||||||
)
|
if(Lua_FOUND AND NOT TARGET Lua::Lua)
|
||||||
|
add_library(Lua::Lua INTERFACE IMPORTED)
|
||||||
|
set_target_properties(
|
||||||
|
Lua::Lua
|
||||||
|
PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${LUA_INCLUDE_DIR}"
|
||||||
|
INTERFACE_LINK_LIBRARIES "${LUA_LIBRARIES}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC Lua::Lua)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Libs
|
# Libs
|
||||||
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME}
|
|
||||||
PUBLIC
|
|
||||||
m
|
|
||||||
cglm
|
|
||||||
zip
|
|
||||||
pthread
|
|
||||||
Lua::Lua
|
|
||||||
)
|
|
||||||
|
|
||||||
# Includes
|
# Includes
|
||||||
target_include_directories(${DUSK_LIBRARY_TARGET_NAME}
|
target_include_directories(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
@@ -63,7 +65,10 @@ add_subdirectory(map)
|
|||||||
add_subdirectory(scene)
|
add_subdirectory(scene)
|
||||||
add_subdirectory(script)
|
add_subdirectory(script)
|
||||||
add_subdirectory(story)
|
add_subdirectory(story)
|
||||||
add_subdirectory(thread)
|
|
||||||
add_subdirectory(time)
|
add_subdirectory(time)
|
||||||
add_subdirectory(ui)
|
add_subdirectory(ui)
|
||||||
add_subdirectory(util)
|
add_subdirectory(util)
|
||||||
|
|
||||||
|
if(DUSK_TARGET_SYSTEM STREQUAL "linux" OR DUSK_TARGET_SYSTEM STREQUAL "psp")
|
||||||
|
add_subdirectory(thread)
|
||||||
|
endif()
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
line,
|
line,
|
||||||
message
|
message
|
||||||
);
|
);
|
||||||
|
debugFlush();
|
||||||
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,66 @@
|
|||||||
#include "asset/assettype.h"
|
#include "asset/assettype.h"
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
errorret_t assetInit(void) {
|
errorret_t assetInit(void) {
|
||||||
memoryZero(&ASSET, sizeof(asset_t));
|
memoryZero(&ASSET, sizeof(asset_t));
|
||||||
|
|
||||||
|
#if DOLPHIN
|
||||||
|
// Init FAT driver.
|
||||||
|
if(!fatInitDefault()) errorThrow("Failed to initialize FAT filesystem.");
|
||||||
|
|
||||||
|
char_t **dolphinSearchPath = (char_t **)ASSET_DOLPHIN_PATHS;
|
||||||
|
char_t foundPath[FILENAME_MAX];
|
||||||
|
foundPath[0] = '\0';
|
||||||
|
do {
|
||||||
|
// Try open dir
|
||||||
|
DIR *pdir = opendir(*dolphinSearchPath);
|
||||||
|
if(pdir == NULL) continue;
|
||||||
|
|
||||||
|
|
||||||
|
// Scan if file is present
|
||||||
|
while(true) {
|
||||||
|
struct dirent* pent = readdir(pdir);
|
||||||
|
if(pent == NULL) break;
|
||||||
|
|
||||||
|
if(stringCompareInsensitive(pent->d_name, ASSET_FILE) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy out filename
|
||||||
|
snprintf(
|
||||||
|
foundPath,
|
||||||
|
FILENAME_MAX,
|
||||||
|
"%s/%s",
|
||||||
|
*dolphinSearchPath,
|
||||||
|
ASSET_FILE
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close dir.
|
||||||
|
closedir(pdir);
|
||||||
|
|
||||||
|
// Did we find the file here?
|
||||||
|
if(foundPath[0] != '\0') break;
|
||||||
|
} while(*(++dolphinSearchPath) != NULL);
|
||||||
|
|
||||||
|
if(foundPath[0] != '\0') {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Did we find the asset file?
|
||||||
|
if(foundPath[0] == '\0') {
|
||||||
|
errorThrow("Failed to find asset file on FAT filesystem.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSET.zip = zip_open(foundPath, ZIP_RDONLY, NULL);
|
||||||
|
if(ASSET.zip == NULL) {
|
||||||
|
errorThrow("Failed to open asset file on FAT filesystem.");
|
||||||
|
}
|
||||||
|
errorOk();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Engine may have been provided the launch path
|
// Engine may have been provided the launch path
|
||||||
if(ENGINE.argc > 0) {
|
if(ENGINE.argc > 0) {
|
||||||
// Get the directory of the executable
|
// Get the directory of the executable
|
||||||
@@ -177,6 +233,19 @@ errorret_t assetLoad(const char_t *filename, void *output) {
|
|||||||
assertStrLenMax(filename, FILENAME_MAX, "Filename too long.");
|
assertStrLenMax(filename, FILENAME_MAX, "Filename too long.");
|
||||||
assertNotNull(output, "Output pointer cannot be NULL.");
|
assertNotNull(output, "Output pointer cannot be NULL.");
|
||||||
|
|
||||||
|
// Get file size of the asset.
|
||||||
|
zip_stat_t st;
|
||||||
|
zip_stat_init(&st);
|
||||||
|
if(!zip_stat(ASSET.zip, filename, 0, &st) == 0) {
|
||||||
|
errorThrow("Failed to stat asset file: %s", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Minimum file size.
|
||||||
|
zip_int64_t fileSize = (zip_int64_t)st.size;
|
||||||
|
if(fileSize < sizeof(assetheader_t)) {
|
||||||
|
errorThrow("Asset file too small to contain header: %s", filename);
|
||||||
|
}
|
||||||
|
|
||||||
// Try to open the file
|
// Try to open the file
|
||||||
zip_file_t *file = zip_fopen(ASSET.zip, filename, 0);
|
zip_file_t *file = zip_fopen(ASSET.zip, filename, 0);
|
||||||
if(file == NULL) {
|
if(file == NULL) {
|
||||||
@@ -184,13 +253,22 @@ errorret_t assetLoad(const char_t *filename, void *output) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read the header.
|
// Read the header.
|
||||||
|
zip_int64_t bytesRemaining = fileSize;
|
||||||
assetheader_t header;
|
assetheader_t header;
|
||||||
memoryZero(&header, sizeof(assetheader_t));
|
memoryZero(&header, sizeof(assetheader_t));
|
||||||
zip_int64_t bytesRead = zip_fread(file, &header, sizeof(assetheader_t));
|
zip_int64_t bytesRead = zip_fread(
|
||||||
if(bytesRead != sizeof(assetheader_t)) {
|
file,
|
||||||
|
&header,
|
||||||
|
(zip_uint64_t)sizeof(assetheader_t)
|
||||||
|
);
|
||||||
|
if((size_t)bytesRead != sizeof(assetheader_t)) {
|
||||||
zip_fclose(file);
|
zip_fclose(file);
|
||||||
errorThrow("Failed to read asset header for: %s", filename);
|
errorThrow("Failed to read asset header for: %s", filename);
|
||||||
}
|
}
|
||||||
|
bytesRemaining -= (zip_uint64_t)bytesRead;
|
||||||
|
|
||||||
|
assertTrue(sizeof(assetheader_t) == ASSET_HEADER_SIZE, "Asset header size mismatch.");
|
||||||
|
assertTrue(bytesRead == ASSET_HEADER_SIZE, "Asset header read size mismatch.");
|
||||||
|
|
||||||
// Find the asset type based on the header
|
// Find the asset type based on the header
|
||||||
const assettypedef_t *def = NULL;
|
const assettypedef_t *def = NULL;
|
||||||
@@ -220,13 +298,36 @@ errorret_t assetLoad(const char_t *filename, void *output) {
|
|||||||
switch(def->loadStrategy) {
|
switch(def->loadStrategy) {
|
||||||
case ASSET_LOAD_STRAT_ENTIRE:
|
case ASSET_LOAD_STRAT_ENTIRE:
|
||||||
assertNotNull(def->entire, "Asset load function cannot be NULL.");
|
assertNotNull(def->entire, "Asset load function cannot be NULL.");
|
||||||
void *data = memoryAllocate(def->dataSize);
|
|
||||||
bytesRead = zip_fread(file, data, def->dataSize);
|
// Must have more to read
|
||||||
if(bytesRead == 0 || bytesRead > def->dataSize) {
|
if(bytesRemaining <= 0) {
|
||||||
|
zip_fclose(file);
|
||||||
|
errorThrow("No data remaining to read for asset: %s", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bytesRemaining > def->dataSize) {
|
||||||
|
zip_fclose(file);
|
||||||
|
errorThrow(
|
||||||
|
"Asset file has too much data remaining after header: %s",
|
||||||
|
filename
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create space to read the entire asset data
|
||||||
|
void *data = memoryAllocate(bytesRemaining);
|
||||||
|
if(!data) {
|
||||||
|
zip_fclose(file);
|
||||||
|
errorThrow("Failed to allocate memory for asset data of file: %s", filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read in the asset data.
|
||||||
|
bytesRead = zip_fread(file, data, bytesRemaining);
|
||||||
|
if(bytesRead == 0 || bytesRead > bytesRemaining) {
|
||||||
memoryFree(data);
|
memoryFree(data);
|
||||||
zip_fclose(file);
|
zip_fclose(file);
|
||||||
errorThrow("Failed to read asset data for file: %s", filename);
|
errorThrow("Failed to read asset data for file: %s", filename);
|
||||||
}
|
}
|
||||||
|
bytesRemaining -= bytesRead;
|
||||||
|
|
||||||
// Close the file now we have the data
|
// Close the file now we have the data
|
||||||
zip_fclose(file);
|
zip_fclose(file);
|
||||||
@@ -234,6 +335,7 @@ errorret_t assetLoad(const char_t *filename, void *output) {
|
|||||||
// Pass to the asset type loader
|
// Pass to the asset type loader
|
||||||
errorret_t ret = def->entire(data, output);
|
errorret_t ret = def->entire(data, output);
|
||||||
memoryFree(data);
|
memoryFree(data);
|
||||||
|
|
||||||
errorChain(ret);
|
errorChain(ret);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -9,27 +9,54 @@
|
|||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "assettype.h"
|
#include "assettype.h"
|
||||||
|
|
||||||
#if ASSET_TYPE == wad
|
#if PSP
|
||||||
#if PSP
|
#define ASSET_PBP_READ_PBP_FROM_HOST 0
|
||||||
#define ASSET_PBP_READ_PBP_FROM_HOST 0
|
#define ASSET_PBP_SIGNATURE_SIZE 4
|
||||||
#define ASSET_PBP_SIGNATURE_SIZE 4
|
#define ASSET_PBP_SIGNATURE "\0PBP"
|
||||||
#define ASSET_PBP_SIGNATURE "\0PBP"
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char_t signature[ASSET_PBP_SIGNATURE_SIZE];
|
char_t signature[ASSET_PBP_SIGNATURE_SIZE];
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
uint32_t sfoOffset;
|
uint32_t sfoOffset;
|
||||||
uint32_t icon0Offset;
|
uint32_t icon0Offset;
|
||||||
uint32_t icon1Offset;
|
uint32_t icon1Offset;
|
||||||
uint32_t pic0Offset;
|
uint32_t pic0Offset;
|
||||||
uint32_t pic1Offset;
|
uint32_t pic1Offset;
|
||||||
uint32_t snd0Offset;
|
uint32_t snd0Offset;
|
||||||
uint32_t pspOffset;
|
uint32_t pspOffset;
|
||||||
uint32_t psarOffset;
|
uint32_t psarOffset;
|
||||||
} assetpbp_t;
|
} assetpbp_t;
|
||||||
#endif
|
|
||||||
#else
|
#elif DOLPHIN
|
||||||
#error "Unsupported ASSET_TYPE"
|
#include <fat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static const char_t *ASSET_DOLPHIN_PATHS[] = {
|
||||||
|
"/",
|
||||||
|
"/Dusk",
|
||||||
|
"/dusk",
|
||||||
|
"/DUSK",
|
||||||
|
"/apps",
|
||||||
|
"/apps/Dusk",
|
||||||
|
"/apps/dusk",
|
||||||
|
"/apps/DUSK",
|
||||||
|
".",
|
||||||
|
"./",
|
||||||
|
"./Dusk",
|
||||||
|
"./dusk",
|
||||||
|
"./DUSK",
|
||||||
|
"./apps",
|
||||||
|
"./apps/Dusk",
|
||||||
|
"./apps/dusk",
|
||||||
|
"./apps/DUSK",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ASSET_FILE "dusk.dsk"
|
#define ASSET_FILE "dusk.dsk"
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "display/texture.h"
|
#include "display/texture.h"
|
||||||
|
|
||||||
|
#include "debug/debug.h"
|
||||||
|
|
||||||
errorret_t assetAlphaImageLoad(void *data, void *output) {
|
errorret_t assetAlphaImageLoad(void *data, void *output) {
|
||||||
assertNotNull(data, "Data pointer cannot be NULL.");
|
assertNotNull(data, "Data pointer cannot be NULL.");
|
||||||
assertNotNull(output, "Output pointer cannot be NULL.");
|
assertNotNull(output, "Output pointer cannot be NULL.");
|
||||||
@@ -16,6 +18,10 @@ errorret_t assetAlphaImageLoad(void *data, void *output) {
|
|||||||
assetalphaimage_t *dataPtr = (assetalphaimage_t *)data;
|
assetalphaimage_t *dataPtr = (assetalphaimage_t *)data;
|
||||||
texture_t *outputPtr = (texture_t *)output;
|
texture_t *outputPtr = (texture_t *)output;
|
||||||
|
|
||||||
|
// Fix endian
|
||||||
|
dataPtr->width = le32toh(dataPtr->width);
|
||||||
|
dataPtr->height = le32toh(dataPtr->height);
|
||||||
|
|
||||||
textureInit(
|
textureInit(
|
||||||
outputPtr,
|
outputPtr,
|
||||||
dataPtr->width,
|
dataPtr->width,
|
||||||
|
|||||||
@@ -43,6 +43,13 @@ errorret_t assetLanguageInit(
|
|||||||
errorThrow("Failed to read language asset header.");
|
errorThrow("Failed to read language asset header.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix the endianness of the header data.
|
||||||
|
for(uint32_t i = 0; i < LANG_KEY_COUNT; i++) {
|
||||||
|
lang->header.strings[i].chunk = le32toh(lang->header.strings[i].chunk);
|
||||||
|
lang->header.strings[i].offset = le32toh(lang->header.strings[i].offset);
|
||||||
|
lang->header.strings[i].length = le32toh(lang->header.strings[i].length);
|
||||||
|
}
|
||||||
|
|
||||||
lang->chunksOffset = zip_ftell(lang->zip);
|
lang->chunksOffset = zip_ftell(lang->zip);
|
||||||
if(lang->chunksOffset <= 0) {
|
if(lang->chunksOffset <= 0) {
|
||||||
zip_fclose(lang->zip);
|
zip_fclose(lang->zip);
|
||||||
|
|||||||
@@ -55,6 +55,9 @@ errorret_t assetMapChunkHandler(assetcustom_t custom) {
|
|||||||
errorThrow("Failed to read chunk asset header.");
|
errorThrow("Failed to read chunk asset header.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix endianess if necessary
|
||||||
|
header.tileCount = le32toh(header.tileCount);
|
||||||
|
|
||||||
if(header.tileCount != CHUNK_TILE_COUNT) {
|
if(header.tileCount != CHUNK_TILE_COUNT) {
|
||||||
zip_fclose(custom.zipFile);
|
zip_fclose(custom.zipFile);
|
||||||
errorThrow(
|
errorThrow(
|
||||||
@@ -107,6 +110,9 @@ errorret_t assetMapChunkHandler(assetcustom_t custom) {
|
|||||||
errorThrow("Failed to read chunk model header.");
|
errorThrow("Failed to read chunk model header.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix endianess if necessary
|
||||||
|
modelHeader.vertexCount = le32toh(modelHeader.vertexCount);
|
||||||
|
|
||||||
if(
|
if(
|
||||||
vertexIndex + modelHeader.vertexCount >
|
vertexIndex + modelHeader.vertexCount >
|
||||||
CHUNK_VERTEX_COUNT_MAX
|
CHUNK_VERTEX_COUNT_MAX
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ errorret_t assetPaletteImageLoad(void *data, void *output) {
|
|||||||
assetpaletteimage_t *assetData = (assetpaletteimage_t *)data;
|
assetpaletteimage_t *assetData = (assetpaletteimage_t *)data;
|
||||||
texture_t *texture = (texture_t *)output;
|
texture_t *texture = (texture_t *)output;
|
||||||
|
|
||||||
|
// Fix endian
|
||||||
|
assetData->width = le32toh(assetData->width);
|
||||||
|
assetData->height = le32toh(assetData->height);
|
||||||
|
|
||||||
textureInit(
|
textureInit(
|
||||||
texture,
|
texture,
|
||||||
assetData->width,
|
assetData->width,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "duskdefs.h"
|
#include "duskdefs.h"
|
||||||
#include <zip.h>
|
#include <zip.h>
|
||||||
#include <lua.h>
|
#include "script/scriptcontext.h"
|
||||||
|
|
||||||
#define ASSET_SCRIPT_BUFFER_SIZE 1024
|
#define ASSET_SCRIPT_BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#if DOLPHIN
|
||||||
|
#include "display/display.h"
|
||||||
|
|
||||||
|
static char_t DEBUG_ERROR_BUFFER[16*1024] = {0};
|
||||||
|
#endif
|
||||||
|
|
||||||
void debugPrint(const char_t *message, ...) {
|
void debugPrint(const char_t *message, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, message);
|
va_start(args, message);
|
||||||
vprintf(message, args);
|
vprintf(message, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
#if PSP
|
#if PSP
|
||||||
FILE *file = fopen("ms0:/PSP/GAME/Dusk/debug.log", "a");
|
FILE *file = fopen("ms0:/PSP/GAME/Dusk/debug.log", "a");
|
||||||
@@ -22,5 +26,70 @@ void debugPrint(const char_t *message, ...) {
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif DOLPHIN
|
||||||
|
// append to error buffer
|
||||||
|
size_t start = strlen(DEBUG_ERROR_BUFFER);
|
||||||
|
va_start(args, message);
|
||||||
|
vsnprintf(
|
||||||
|
DEBUG_ERROR_BUFFER + start,
|
||||||
|
sizeof(DEBUG_ERROR_BUFFER) - start,
|
||||||
|
message,
|
||||||
|
args
|
||||||
|
);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void debugFlush() {
|
||||||
|
#if PSP
|
||||||
|
// No buffering, so nothing to flush
|
||||||
|
#elif DOLPHIN
|
||||||
|
// Either create graphics, or hijack the displays' graphics.
|
||||||
|
void *xfb = NULL;
|
||||||
|
GXRModeObj *rmode = NULL;
|
||||||
|
void *framebuffer;
|
||||||
|
|
||||||
|
if(DISPLAY.frameBuffer[0]) {
|
||||||
|
console_init(
|
||||||
|
DISPLAY.frameBuffer[0],
|
||||||
|
20,
|
||||||
|
20,
|
||||||
|
DISPLAY.screenMode->fbWidth,
|
||||||
|
DISPLAY.screenMode->xfbHeight,
|
||||||
|
DISPLAY.screenMode->fbWidth * VI_DISPLAY_PIX_SZ
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
VIDEO_Init();
|
||||||
|
rmode = VIDEO_GetPreferredMode(NULL);
|
||||||
|
framebuffer = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
||||||
|
console_init(
|
||||||
|
framebuffer,
|
||||||
|
20,
|
||||||
|
20,
|
||||||
|
rmode->fbWidth,
|
||||||
|
rmode->xfbHeight,
|
||||||
|
rmode->fbWidth*VI_DISPLAY_PIX_SZ
|
||||||
|
);
|
||||||
|
VIDEO_Configure(rmode);
|
||||||
|
VIDEO_SetNextFramebuffer(framebuffer);
|
||||||
|
VIDEO_SetBlack(FALSE);
|
||||||
|
VIDEO_Flush();
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printf
|
||||||
|
printf("SOB\n");
|
||||||
|
printf(DEBUG_ERROR_BUFFER);
|
||||||
|
printf("\nEOB.");
|
||||||
|
|
||||||
|
while(SYS_MainLoop()) {
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -15,3 +15,8 @@
|
|||||||
* @param ... Additional arguments for the format string.
|
* @param ... Additional arguments for the format string.
|
||||||
*/
|
*/
|
||||||
void debugPrint(const char_t *message, ...);
|
void debugPrint(const char_t *message, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flushes the debug output buffer.
|
||||||
|
*/
|
||||||
|
void debugFlush();
|
||||||
@@ -38,6 +38,15 @@ elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
|||||||
DISPLAY_HEIGHT=272
|
DISPLAY_HEIGHT=272
|
||||||
DISPLAY_SIZE_DYNAMIC=0
|
DISPLAY_SIZE_DYNAMIC=0
|
||||||
)
|
)
|
||||||
|
elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii")
|
||||||
|
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
DISPLAY_WINDOW_WIDTH_DEFAULT=640
|
||||||
|
DISPLAY_WINDOW_HEIGHT_DEFAULT=480
|
||||||
|
DISPLAY_WIDTH=640
|
||||||
|
DISPLAY_HEIGHT=480
|
||||||
|
DISPLAY_SIZE_DYNAMIC=0
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
dusk_run_python(
|
dusk_run_python(
|
||||||
|
|||||||
@@ -48,6 +48,97 @@ void cameraInitOrthographic(camera_t *camera) {
|
|||||||
void cameraPushMatrix(camera_t *camera) {
|
void cameraPushMatrix(camera_t *camera) {
|
||||||
assertNotNull(camera, "Not a camera component");
|
assertNotNull(camera, "Not a camera component");
|
||||||
|
|
||||||
|
#if DOLPHIN
|
||||||
|
Mtx44 guProjection;
|
||||||
|
Mtx guView;
|
||||||
|
Mtx modelView;
|
||||||
|
|
||||||
|
switch(camera->projType) {
|
||||||
|
case CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC:
|
||||||
|
guOrtho(
|
||||||
|
guProjection,
|
||||||
|
camera->orthographic.left,
|
||||||
|
camera->orthographic.right,
|
||||||
|
camera->orthographic.bottom,
|
||||||
|
camera->orthographic.top,
|
||||||
|
camera->nearClip,
|
||||||
|
camera->farClip
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CAMERA_PROJECTION_TYPE_PERSPECTIVE:
|
||||||
|
guPerspective(
|
||||||
|
guProjection,
|
||||||
|
// FOV is in degrees.
|
||||||
|
camera->perspective.fov * (180.0f / GLM_PIf),
|
||||||
|
(float_t)frameBufferGetWidth(FRAMEBUFFER_BOUND) /
|
||||||
|
(float_t)frameBufferGetHeight(FRAMEBUFFER_BOUND),
|
||||||
|
camera->nearClip,
|
||||||
|
camera->farClip
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED:
|
||||||
|
assertUnreachable("Flipped perspective not implemented on Dolphin");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assertUnreachable("Invalid camera projection type");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(camera->viewType) {
|
||||||
|
case CAMERA_VIEW_TYPE_LOOKAT:
|
||||||
|
guVector eye = {
|
||||||
|
camera->lookat.position[0],
|
||||||
|
camera->lookat.position[1],
|
||||||
|
camera->lookat.position[2]
|
||||||
|
};
|
||||||
|
guVector up = {
|
||||||
|
camera->lookat.up[0],
|
||||||
|
camera->lookat.up[1],
|
||||||
|
camera->lookat.up[2]
|
||||||
|
};
|
||||||
|
guVector look = {
|
||||||
|
camera->lookat.target[0],
|
||||||
|
camera->lookat.target[1],
|
||||||
|
camera->lookat.target[2]
|
||||||
|
};
|
||||||
|
guLookAt(guView, &eye, &up, &look);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CAMERA_VIEW_TYPE_MATRIX:
|
||||||
|
assertUnreachable("Matrix camera not implemented");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CAMERA_VIEW_TYPE_LOOKAT_PIXEL_PERFECT:
|
||||||
|
assertUnreachable("Pixel perfect camera not implemented");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CAMERA_VIEW_TYPE_2D:
|
||||||
|
assertUnreachable("2D camera not implemented");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assertUnreachable("Invalid camera view type");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Projection Matrix
|
||||||
|
GX_LoadProjectionMtx(
|
||||||
|
guProjection,
|
||||||
|
camera->projType == CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC ?
|
||||||
|
GX_ORTHOGRAPHIC :
|
||||||
|
GX_PERSPECTIVE
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set view and model matrix. Dunno how I'll handle models but whatever.
|
||||||
|
guMtxIdentity(modelView);
|
||||||
|
guMtxTransApply(modelView, modelView, 0.0F, 0.0F, 0.0F);
|
||||||
|
guMtxConcat(guView,modelView,modelView);
|
||||||
|
GX_LoadPosMtxImm(modelView, GX_PNMTX0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
mat4 projection;
|
mat4 projection;
|
||||||
mat4 view;
|
mat4 view;
|
||||||
|
|
||||||
|
|||||||
@@ -15,10 +15,19 @@
|
|||||||
#include "ui/ui.h"
|
#include "ui/ui.h"
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
#include "display/text.h"
|
#include "display/text.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "util/memory.h"
|
||||||
|
|
||||||
display_t DISPLAY;
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
display_t DISPLAY = { 0 };
|
||||||
|
|
||||||
errorret_t displayInit(void) {
|
errorret_t displayInit(void) {
|
||||||
|
memoryZero(&DISPLAY, sizeof(DISPLAY));
|
||||||
|
|
||||||
#if DISPLAY_SDL2
|
#if DISPLAY_SDL2
|
||||||
uint32_t flags = SDL_INIT_VIDEO;
|
uint32_t flags = SDL_INIT_VIDEO;
|
||||||
#if INPUT_GAMEPAD == 1
|
#if INPUT_GAMEPAD == 1
|
||||||
@@ -69,6 +78,68 @@ errorret_t displayInit(void) {
|
|||||||
glEnableClientState(GL_COLOR_ARRAY);// To confirm: every frame on PSP?
|
glEnableClientState(GL_COLOR_ARRAY);// To confirm: every frame on PSP?
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
|
#elif DOLPHIN
|
||||||
|
VIDEO_Init();
|
||||||
|
DISPLAY.screenMode = VIDEO_GetPreferredMode(NULL);
|
||||||
|
DISPLAY.frameBuffer[0] = MEM_K0_TO_K1(
|
||||||
|
SYS_AllocateFramebuffer(DISPLAY.screenMode)
|
||||||
|
);
|
||||||
|
DISPLAY.frameBuffer[1] = MEM_K0_TO_K1(
|
||||||
|
SYS_AllocateFramebuffer(DISPLAY.screenMode)
|
||||||
|
);
|
||||||
|
VIDEO_Configure(DISPLAY.screenMode);
|
||||||
|
|
||||||
|
VIDEO_SetNextFramebuffer(DISPLAY.frameBuffer[DISPLAY.whichFrameBuffer]);
|
||||||
|
// VIDEO_SetPostRetraceCallback(copy_buffers);
|
||||||
|
VIDEO_SetBlack(FALSE);
|
||||||
|
VIDEO_Flush();
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
if(DISPLAY.screenMode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||||
|
|
||||||
|
DISPLAY.fifoBuffer = memalign(32, DISPLAY_FIFO_SIZE);
|
||||||
|
memoryZero(DISPLAY.fifoBuffer, DISPLAY_FIFO_SIZE);
|
||||||
|
|
||||||
|
GX_Init(DISPLAY.fifoBuffer, DISPLAY_FIFO_SIZE);
|
||||||
|
|
||||||
|
// This seems to be mostly related to interlacing vs progressive
|
||||||
|
GX_SetViewport(
|
||||||
|
0, 0,
|
||||||
|
DISPLAY.screenMode->fbWidth, DISPLAY.screenMode->efbHeight,
|
||||||
|
0, 1
|
||||||
|
);
|
||||||
|
float_t yscale = GX_GetYScaleFactor(
|
||||||
|
DISPLAY.screenMode->efbHeight, DISPLAY.screenMode->xfbHeight
|
||||||
|
);
|
||||||
|
uint32_t xfbHeight = GX_SetDispCopyYScale(yscale);
|
||||||
|
GX_SetScissor(
|
||||||
|
0, 0,
|
||||||
|
DISPLAY.screenMode->fbWidth, DISPLAY.screenMode->efbHeight
|
||||||
|
);
|
||||||
|
GX_SetDispCopySrc(
|
||||||
|
0, 0,
|
||||||
|
DISPLAY.screenMode->fbWidth, DISPLAY.screenMode->efbHeight
|
||||||
|
);
|
||||||
|
GX_SetDispCopyDst(DISPLAY.screenMode->fbWidth, xfbHeight);
|
||||||
|
GX_SetCopyFilter(
|
||||||
|
DISPLAY.screenMode->aa,
|
||||||
|
DISPLAY.screenMode->sample_pattern,
|
||||||
|
GX_TRUE,
|
||||||
|
DISPLAY.screenMode->vfilter
|
||||||
|
);
|
||||||
|
GX_SetFieldMode(
|
||||||
|
DISPLAY.screenMode->field_rendering,
|
||||||
|
(
|
||||||
|
(DISPLAY.screenMode->viHeight == 2 * DISPLAY.screenMode->xfbHeight) ?
|
||||||
|
GX_ENABLE :
|
||||||
|
GX_DISABLE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Setup cull modes
|
||||||
|
GX_SetCullMode(GX_CULL_NONE);
|
||||||
|
GX_CopyDisp(DISPLAY.frameBuffer[DISPLAY.whichFrameBuffer], GX_TRUE);
|
||||||
|
GX_SetDispCopyGamma(GX_GM_1_0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
quadInit();
|
quadInit();
|
||||||
@@ -110,6 +181,10 @@ errorret_t displayUpdate(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDL_GL_MakeCurrent(DISPLAY.window, DISPLAY.glContext);
|
SDL_GL_MakeCurrent(DISPLAY.window, DISPLAY.glContext);
|
||||||
|
|
||||||
|
#elif DOLPHIN
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Reset state
|
// Reset state
|
||||||
@@ -125,7 +200,7 @@ errorret_t displayUpdate(void) {
|
|||||||
errorChain(sceneRender());
|
errorChain(sceneRender());
|
||||||
|
|
||||||
// Render UI
|
// Render UI
|
||||||
uiRender();
|
// uiRender();
|
||||||
|
|
||||||
// Finish up
|
// Finish up
|
||||||
screenUnbind();
|
screenUnbind();
|
||||||
@@ -133,12 +208,22 @@ errorret_t displayUpdate(void) {
|
|||||||
|
|
||||||
#if DISPLAY_SDL2
|
#if DISPLAY_SDL2
|
||||||
SDL_GL_SwapWindow(DISPLAY.window);
|
SDL_GL_SwapWindow(DISPLAY.window);
|
||||||
#endif
|
|
||||||
|
|
||||||
GLenum err;
|
GLenum err;
|
||||||
while((err = glGetError()) != GL_NO_ERROR) {
|
while((err = glGetError()) != GL_NO_ERROR) {
|
||||||
debugPrint("GL Error: %d\n", err);
|
debugPrint("GL Error: %d\n", err);
|
||||||
}
|
}
|
||||||
|
#elif DOLPHIN
|
||||||
|
GX_DrawDone();
|
||||||
|
|
||||||
|
DISPLAY.whichFrameBuffer ^= 1;
|
||||||
|
GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
|
||||||
|
GX_SetColorUpdate(GX_TRUE);
|
||||||
|
GX_CopyDisp(DISPLAY.frameBuffer[DISPLAY.whichFrameBuffer], GX_TRUE);
|
||||||
|
VIDEO_SetNextFramebuffer(DISPLAY.frameBuffer[DISPLAY.whichFrameBuffer]);
|
||||||
|
VIDEO_Flush();
|
||||||
|
VIDEO_WaitVSync();
|
||||||
|
#endif
|
||||||
|
|
||||||
// For now, we just return an OK error.
|
// For now, we just return an OK error.
|
||||||
errorOk();
|
errorOk();
|
||||||
|
|||||||
@@ -15,6 +15,13 @@ typedef struct {
|
|||||||
#if DISPLAY_SDL2
|
#if DISPLAY_SDL2
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
SDL_GLContext glContext;
|
SDL_GLContext glContext;
|
||||||
|
|
||||||
|
#elif DOLPHIN
|
||||||
|
void *frameBuffer[2];// Double-Bufferred
|
||||||
|
int whichFrameBuffer;
|
||||||
|
GXRModeObj *screenMode;
|
||||||
|
void *fifoBuffer;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
} display_t;
|
} display_t;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "dusk.h"
|
||||||
|
|
||||||
#if DISPLAY_SDL2
|
#if DISPLAY_SDL2
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
@@ -17,6 +18,9 @@
|
|||||||
#ifndef DISPLAY_SIZE_DYNAMIC
|
#ifndef DISPLAY_SIZE_DYNAMIC
|
||||||
#define DISPLAY_SIZE_DYNAMIC 1
|
#define DISPLAY_SIZE_DYNAMIC 1
|
||||||
#endif
|
#endif
|
||||||
|
#elif DOLPHIN
|
||||||
|
// Dolphin.
|
||||||
|
#define DISPLAY_FIFO_SIZE (256*1024)
|
||||||
#else
|
#else
|
||||||
#error "Need to specify display backend."
|
#error "Need to specify display backend."
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -68,6 +68,13 @@ int32_t frameBufferGetWidth(const framebuffer_t *framebuffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return framebuffer->texture.width;
|
return framebuffer->texture.width;
|
||||||
|
|
||||||
|
#elif DOLPHIN
|
||||||
|
return DISPLAY.screenMode->fbWidth;
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Unsupported DISPLAY_TYPE."
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,15 +91,19 @@ int32_t frameBufferGetHeight(const framebuffer_t *framebuffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return framebuffer->texture.height;
|
return framebuffer->texture.height;
|
||||||
|
|
||||||
|
#elif DOLPHIN
|
||||||
|
return DISPLAY.screenMode->efbHeight;
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Unsupported DISPLAY_TYPE."
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void frameBufferBind(const framebuffer_t *framebuffer) {
|
void frameBufferBind(const framebuffer_t *framebuffer) {
|
||||||
if(framebuffer == NULL) {
|
if(framebuffer == NULL) {
|
||||||
#if DISPLAY_SDL2
|
frameBufferBind(&FRAMEBUFFER_BACKBUFFER);
|
||||||
frameBufferBind(&FRAMEBUFFER_BACKBUFFER);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FRAMEBUFFER_BOUND = &FRAMEBUFFER_BACKBUFFER;
|
FRAMEBUFFER_BOUND = &FRAMEBUFFER_BACKBUFFER;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -117,6 +128,18 @@ void frameBufferBind(const framebuffer_t *framebuffer) {
|
|||||||
0, 0,
|
0, 0,
|
||||||
frameBufferGetWidth(framebuffer), frameBufferGetHeight(framebuffer)
|
frameBufferGetWidth(framebuffer), frameBufferGetHeight(framebuffer)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#elif DOLPHIN
|
||||||
|
GX_InvVtxCache();
|
||||||
|
GX_InvalidateTexAll();
|
||||||
|
|
||||||
|
GX_SetViewport(
|
||||||
|
0, 0,
|
||||||
|
frameBufferGetWidth(framebuffer),
|
||||||
|
frameBufferGetHeight(framebuffer),
|
||||||
|
0, 1
|
||||||
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FRAMEBUFFER_BOUND = framebuffer;
|
FRAMEBUFFER_BOUND = framebuffer;
|
||||||
@@ -141,6 +164,12 @@ void frameBufferClear(uint8_t flags, color_t color) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
glClear(glFlags);
|
glClear(glFlags);
|
||||||
|
#elif DOLPHIN
|
||||||
|
GX_SetCopyClear(
|
||||||
|
(GXColor){ color.r, color.g, color.b, color.a },
|
||||||
|
GX_MAX_Z24
|
||||||
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ typedef struct {
|
|||||||
// OpenGL Framebuffer Object ID
|
// OpenGL Framebuffer Object ID
|
||||||
GLuint id;
|
GLuint id;
|
||||||
texture_t texture;
|
texture_t texture;
|
||||||
|
#elif DOLPHIN
|
||||||
|
// --- IGNORE ---
|
||||||
|
uint8_t id;
|
||||||
#else
|
#else
|
||||||
#error "Framebuffers not implemented on this platform."
|
#error "Framebuffers not implemented on this platform."
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
|
|
||||||
|
#if DOLPHIN
|
||||||
|
#include "display/texture.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
void meshInit(
|
void meshInit(
|
||||||
mesh_t *mesh,
|
mesh_t *mesh,
|
||||||
const meshprimitivetype_t primitiveType,
|
const meshprimitivetype_t primitiveType,
|
||||||
@@ -69,6 +73,37 @@ void meshDraw(
|
|||||||
0,
|
0,
|
||||||
count
|
count
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#elif DOLPHIN
|
||||||
|
// Prepare Vertex descriptor
|
||||||
|
DCFlushRange(
|
||||||
|
(void*)&mesh->vertices[offset],
|
||||||
|
sizeof(meshvertex_t) * count
|
||||||
|
);
|
||||||
|
GX_ClearVtxDesc();// Just clears so may be un-needed?
|
||||||
|
|
||||||
|
GX_SetVtxDesc(GX_VA_POS, GX_INDEX16);
|
||||||
|
GX_SetVtxDesc(GX_VA_CLR0, GX_INDEX16);
|
||||||
|
GX_SetVtxDesc(GX_VA_TEX0, GX_INDEX16);
|
||||||
|
|
||||||
|
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
||||||
|
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
||||||
|
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
||||||
|
|
||||||
|
const u8 stride = (u8)sizeof(meshvertex_t);
|
||||||
|
GX_SetArray(GX_VA_POS, &mesh->vertices[offset].pos[0], stride);
|
||||||
|
GX_SetArray(GX_VA_CLR0, &mesh->vertices[offset].color, stride);
|
||||||
|
GX_SetArray(GX_VA_TEX0, &mesh->vertices[offset].uv[0], stride);
|
||||||
|
|
||||||
|
textureDolphinUploadTEV();
|
||||||
|
|
||||||
|
GX_Begin(mesh->primitiveType, GX_VTXFMT0, (uint16_t)count);
|
||||||
|
for(u16 i = 0; i < (u16)count; ++i) {
|
||||||
|
GX_Position1x16(i);
|
||||||
|
GX_Color1x16(i);
|
||||||
|
GX_TexCoord1x16(i);
|
||||||
|
}
|
||||||
|
GX_End();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ typedef enum {
|
|||||||
MESH_PRIMITIVE_TRIANGLES = GL_TRIANGLES,
|
MESH_PRIMITIVE_TRIANGLES = GL_TRIANGLES,
|
||||||
MESH_PRIMITIVE_LINES = GL_LINES,
|
MESH_PRIMITIVE_LINES = GL_LINES,
|
||||||
MESH_PRIMITIVE_POINTS = GL_POINTS,
|
MESH_PRIMITIVE_POINTS = GL_POINTS,
|
||||||
|
#elif DOLPHIN
|
||||||
|
MESH_PRIMITIVE_TRIANGLES = GX_TRIANGLES,
|
||||||
|
MESH_PRIMITIVE_LINES = GX_LINES,
|
||||||
|
MESH_PRIMITIVE_POINTS = GX_POINTS,
|
||||||
#endif
|
#endif
|
||||||
} meshprimitivetype_t;
|
} meshprimitivetype_t;
|
||||||
|
|
||||||
@@ -19,11 +23,9 @@ typedef enum {
|
|||||||
#define MESH_VERTEX_POS_SIZE 3
|
#define MESH_VERTEX_POS_SIZE 3
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
#if DISPLAY_SDL2
|
color_t color;
|
||||||
color4b_t color;
|
float uv[MESH_VERTEX_UV_SIZE];
|
||||||
GLfloat uv[MESH_VERTEX_UV_SIZE];
|
float pos[MESH_VERTEX_POS_SIZE];
|
||||||
GLfloat pos[MESH_VERTEX_POS_SIZE];
|
|
||||||
#endif
|
|
||||||
} meshvertex_t;
|
} meshvertex_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -10,13 +10,13 @@
|
|||||||
|
|
||||||
mesh_t QUAD_MESH_SIMPLE;
|
mesh_t QUAD_MESH_SIMPLE;
|
||||||
meshvertex_t QUAD_MESH_SIMPLE_VERTICES[QUAD_VERTEX_COUNT] = {
|
meshvertex_t QUAD_MESH_SIMPLE_VERTICES[QUAD_VERTEX_COUNT] = {
|
||||||
{ COLOR_WHITE_4B, { 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
|
{ .color = COLOR_WHITE_4B, .uv = { 0.0f, 0.0f }, .pos = { 0.0f, 0.0f, 0.0f } },
|
||||||
{ COLOR_WHITE_4B, { 1.0f, 0.0f }, { 1.0f, 0.0f, 0.0f } },
|
{ .color = COLOR_WHITE_4B, .uv = { 1.0f, 0.0f }, .pos = { 1.0f, 0.0f, 0.0f } },
|
||||||
{ COLOR_WHITE_4B, { 1.0f, 1.0f }, { 1.0f, 1.0f, 0.0f } },
|
{ .color = COLOR_WHITE_4B, .uv = { 1.0f, 1.0f }, .pos = { 1.0f, 1.0f, 0.0f } },
|
||||||
|
|
||||||
{ COLOR_WHITE_4B, { 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
|
{ .color = COLOR_WHITE_4B, .uv = { 0.0f, 0.0f }, .pos = { 0.0f, 0.0f, 0.0f } },
|
||||||
{ COLOR_WHITE_4B, { 1.0f, 1.0f }, { 1.0f, 1.0f, 0.0f } },
|
{ .color = COLOR_WHITE_4B, .uv = { 1.0f, 1.0f }, .pos = { 1.0f, 1.0f, 0.0f } },
|
||||||
{ COLOR_WHITE_4B, { 0.0f, 1.0f }, { 0.0f, 1.0f, 0.0f } }
|
{ .color = COLOR_WHITE_4B, .uv = { 0.0f, 1.0f }, .pos = { 0.0f, 1.0f, 0.0f } }
|
||||||
};
|
};
|
||||||
|
|
||||||
void quadInit() {
|
void quadInit() {
|
||||||
@@ -44,38 +44,48 @@ void quadBuffer(
|
|||||||
assertNotNull(vertices, "Vertices cannot be NULL");
|
assertNotNull(vertices, "Vertices cannot be NULL");
|
||||||
|
|
||||||
// First triangle
|
// First triangle
|
||||||
vertices[0] = (meshvertex_t) {
|
vertices[0].color = color;
|
||||||
{ color.r, color.g, color.b, color.a }, // Color
|
vertices[0].uv[0] = u0;
|
||||||
{ u0, v0 }, // UV
|
vertices[0].uv[1] = v1;
|
||||||
{ minX, minY, z } // Position
|
vertices[0].pos[0] = minX;
|
||||||
};
|
vertices[0].pos[1] = maxY;
|
||||||
vertices[1] = (meshvertex_t) {
|
vertices[0].pos[2] = z;
|
||||||
{ color.r, color.g, color.b, color.a }, // Color
|
|
||||||
{ u1, v0 }, // UV
|
vertices[2].color = color;
|
||||||
{ maxX, minY, z } // Position
|
vertices[2].uv[0] = u0;
|
||||||
};
|
vertices[2].uv[1] = v0;
|
||||||
vertices[2] = (meshvertex_t) {
|
vertices[2].pos[0] = minX;
|
||||||
{ color.r, color.g, color.b, color.a }, // Color
|
vertices[2].pos[1] = minY;
|
||||||
{ u1, v1 }, // UV
|
vertices[2].pos[2] = z;
|
||||||
{ maxX, maxY, z } // Position
|
|
||||||
};
|
vertices[1].color = color;
|
||||||
|
vertices[1].uv[0] = u1;
|
||||||
|
vertices[1].uv[1] = v0;
|
||||||
|
vertices[1].pos[0] = maxX;
|
||||||
|
vertices[1].pos[1] = minY;
|
||||||
|
vertices[1].pos[2] = z;
|
||||||
|
|
||||||
// Second triangle
|
// Second triangle
|
||||||
vertices[3] = (meshvertex_t) {
|
vertices[3].color = color;
|
||||||
{ color.r, color.g, color.b, color.a }, // Color
|
vertices[3].uv[0] = u0;
|
||||||
{ u0, v0 }, // UV
|
vertices[3].uv[1] = v1;
|
||||||
{ minX, minY, z } // Position
|
vertices[3].pos[0] = minX;
|
||||||
};
|
vertices[3].pos[1] = maxY;
|
||||||
vertices[4] = (meshvertex_t) {
|
vertices[3].pos[2] = z;
|
||||||
{ color.r, color.g, color.b, color.a }, // Color
|
|
||||||
{ u1, v1 }, // UV
|
vertices[5].color = color;
|
||||||
{ maxX, maxY, z } // Position
|
vertices[5].uv[0] = u1;
|
||||||
};
|
vertices[5].uv[1] = v0;
|
||||||
vertices[5] = (meshvertex_t) {
|
vertices[5].pos[0] = maxX;
|
||||||
{ color.r, color.g, color.b, color.a }, // Color
|
vertices[5].pos[1] = minY;
|
||||||
{ u0, v1 }, // UV
|
vertices[5].pos[2] = z;
|
||||||
{ minX, maxY, z } // Position
|
|
||||||
};
|
vertices[4].color = color;
|
||||||
|
vertices[4].uv[0] = u1;
|
||||||
|
vertices[4].uv[1] = v1;
|
||||||
|
vertices[4].pos[0] = maxX;
|
||||||
|
vertices[4].pos[1] = maxY;
|
||||||
|
vertices[4].pos[2] = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
void quadBuffer3D(
|
void quadBuffer3D(
|
||||||
@@ -93,36 +103,46 @@ void quadBuffer3D(
|
|||||||
assertNotNull(uvMax, "UV Max vector cannot be NULL");
|
assertNotNull(uvMax, "UV Max vector cannot be NULL");
|
||||||
|
|
||||||
// First triangle
|
// First triangle
|
||||||
vertices[0] = (meshvertex_t) {
|
vertices[0].color = color;
|
||||||
{ color.r, color.g, color.b, color.a }, // Color
|
vertices[0].uv[0] = uvMin[0];
|
||||||
{ uvMin[0], uvMin[1] }, // UV
|
vertices[0].uv[1] = uvMin[1];
|
||||||
{ min[0], min[1], min[2] } // Position
|
vertices[0].pos[0] = min[0];
|
||||||
};
|
vertices[0].pos[1] = min[1];
|
||||||
vertices[1] = (meshvertex_t) {
|
vertices[0].pos[2] = min[2];
|
||||||
{ color.r, color.g, color.b, color.a }, // Color
|
|
||||||
{ uvMax[0], uvMin[1] }, // UV
|
vertices[1].color = color;
|
||||||
{ max[0], min[1], min[2] } // Position
|
vertices[1].uv[0] = uvMax[0];
|
||||||
};
|
vertices[1].uv[1] = uvMin[1];
|
||||||
vertices[2] = (meshvertex_t) {
|
vertices[1].pos[0] = max[0];
|
||||||
{ color.r, color.g, color.b, color.a }, // Color
|
vertices[1].pos[1] = min[1];
|
||||||
{ uvMax[0], uvMax[1] }, // UV
|
vertices[1].pos[2] = min[2];
|
||||||
{ max[0], max[1], min[2] } // Position
|
|
||||||
};
|
vertices[2].color = color;
|
||||||
|
vertices[2].uv[0] = uvMax[0];
|
||||||
|
vertices[2].uv[1] = uvMax[1];
|
||||||
|
vertices[2].pos[0] = max[0];
|
||||||
|
vertices[2].pos[1] = max[1];
|
||||||
|
vertices[2].pos[2] = min[2];
|
||||||
|
|
||||||
// Second triangle
|
// Second triangle
|
||||||
vertices[3] = (meshvertex_t) {
|
vertices[3].color = color;
|
||||||
{ color.r, color.g, color.b, color.a }, // Color
|
vertices[3].uv[0] = uvMin[0];
|
||||||
{ uvMin[0], uvMin[1] }, // UV
|
vertices[3].uv[1] = uvMin[1];
|
||||||
{ min[0], min[1], min[2] } // Position
|
vertices[3].pos[0] = min[0];
|
||||||
};
|
vertices[3].pos[1] = min[1];
|
||||||
vertices[4] = (meshvertex_t) {
|
vertices[3].pos[2] = min[2];
|
||||||
{ color.r, color.g, color.b, color.a }, // Color
|
|
||||||
{ uvMax[0], uvMax[1] }, // UV
|
vertices[4].color = color;
|
||||||
{ max[0], max[1], min[2] } // Position
|
vertices[4].uv[0] = uvMax[0];
|
||||||
};
|
vertices[4].uv[1] = uvMax[1];
|
||||||
vertices[5] = (meshvertex_t) {
|
vertices[4].pos[0] = max[0];
|
||||||
{ color.r, color.g, color.b, color.a }, // Color
|
vertices[4].pos[1] = max[1];
|
||||||
{ uvMin[0], uvMax[1] }, // UV
|
vertices[4].pos[2] = min[2];
|
||||||
{ min[0], max[1], min[2] } // Position
|
|
||||||
};
|
vertices[5].color = color;
|
||||||
|
vertices[5].uv[0] = uvMin[0];
|
||||||
|
vertices[5].uv[1] = uvMax[1];
|
||||||
|
vertices[5].pos[0] = min[0];
|
||||||
|
vertices[5].pos[1] = max[1];
|
||||||
|
vertices[5].pos[2] = min[2];
|
||||||
}
|
}
|
||||||
@@ -9,9 +9,12 @@
|
|||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
|
||||||
|
meshvertex_t SPRITEBATCH_VERTICES[SPRITEBATCH_VERTEX_COUNT];
|
||||||
spritebatch_t SPRITEBATCH;
|
spritebatch_t SPRITEBATCH;
|
||||||
|
|
||||||
void spriteBatchInit() {
|
void spriteBatchInit() {
|
||||||
|
memoryZero(&SPRITEBATCH, sizeof(spritebatch_t));
|
||||||
|
|
||||||
SPRITEBATCH.spriteCount = 0;
|
SPRITEBATCH.spriteCount = 0;
|
||||||
SPRITEBATCH.currentTexture = NULL;
|
SPRITEBATCH.currentTexture = NULL;
|
||||||
|
|
||||||
@@ -19,7 +22,7 @@ void spriteBatchInit() {
|
|||||||
&SPRITEBATCH.mesh,
|
&SPRITEBATCH.mesh,
|
||||||
MESH_PRIMITIVE_TRIANGLES,
|
MESH_PRIMITIVE_TRIANGLES,
|
||||||
SPRITEBATCH_VERTEX_COUNT,
|
SPRITEBATCH_VERTEX_COUNT,
|
||||||
&SPRITEBATCH.vertices[0]
|
&SPRITEBATCH_VERTICES[0]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +48,7 @@ void spriteBatchPush(
|
|||||||
}
|
}
|
||||||
|
|
||||||
quadBuffer(
|
quadBuffer(
|
||||||
&SPRITEBATCH.vertices[SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT],
|
&SPRITEBATCH_VERTICES[SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT],
|
||||||
minX, minY, maxX, maxY,
|
minX, minY, maxX, maxY,
|
||||||
color,
|
color,
|
||||||
u0, v0, u1, v1
|
u0, v0, u1, v1
|
||||||
@@ -72,7 +75,7 @@ void spriteBatchPush3D(
|
|||||||
}
|
}
|
||||||
|
|
||||||
quadBuffer3D(
|
quadBuffer3D(
|
||||||
&SPRITEBATCH.vertices[SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT],
|
&SPRITEBATCH_VERTICES[SPRITEBATCH.spriteCount * QUAD_VERTEX_COUNT],
|
||||||
min, max, color, uv0, uv1
|
min, max, color, uv0, uv1
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "display/mesh/quad.h"
|
#include "display/mesh/quad.h"
|
||||||
#include "display/texture.h"
|
#include "display/texture.h"
|
||||||
|
|
||||||
#define SPRITEBATCH_SPRITES_MAX 1
|
#define SPRITEBATCH_SPRITES_MAX 32
|
||||||
#define SPRITEBATCH_VERTEX_COUNT (SPRITEBATCH_SPRITES_MAX * QUAD_VERTEX_COUNT)
|
#define SPRITEBATCH_VERTEX_COUNT (SPRITEBATCH_SPRITES_MAX * QUAD_VERTEX_COUNT)
|
||||||
|
|
||||||
|
|
||||||
@@ -17,9 +17,11 @@ typedef struct {
|
|||||||
mesh_t mesh;
|
mesh_t mesh;
|
||||||
int32_t spriteCount;
|
int32_t spriteCount;
|
||||||
texture_t *currentTexture;
|
texture_t *currentTexture;
|
||||||
meshvertex_t vertices[SPRITEBATCH_VERTEX_COUNT];
|
|
||||||
} spritebatch_t;
|
} spritebatch_t;
|
||||||
|
|
||||||
|
// Have to define these seperately because of alignment in certain platforms.
|
||||||
|
// (Looking at you Dolphin)/
|
||||||
|
extern meshvertex_t SPRITEBATCH_VERTICES[SPRITEBATCH_VERTEX_COUNT];
|
||||||
extern spritebatch_t SPRITEBATCH;
|
extern spritebatch_t SPRITEBATCH;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -144,10 +144,148 @@ void textureInit(
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
texture->ready = true;
|
||||||
|
|
||||||
|
#elif DOLPHIN
|
||||||
|
texture->format = format;
|
||||||
|
|
||||||
|
switch(format) {
|
||||||
|
case TEXTURE_FORMAT_RGBA:
|
||||||
|
assertTrue(
|
||||||
|
(width % 4) == 0 && (height % 4) == 0,
|
||||||
|
"RGB5A3 requires w/h multiple of 4 (or pad)"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Convert to RGB5A3 format
|
||||||
|
size_t rgbaSize = width * height * sizeof(u16);
|
||||||
|
texture->rgba = (u16*)memalign(32, rgbaSize);
|
||||||
|
assertNotNull(texture->rgba, "Failed to allocate texture RGBA data");
|
||||||
|
|
||||||
|
for(uint32_t y = 0; y < height; ++y) {
|
||||||
|
for(uint32_t x = 0; x < width; ++x) {
|
||||||
|
const int src = y * width + x;
|
||||||
|
|
||||||
|
const int tileX = x >> 2;
|
||||||
|
const int tileY = y >> 2;
|
||||||
|
const int tilesPerRow = width >> 2;
|
||||||
|
const int tileIndex = tileY * tilesPerRow + tileX;
|
||||||
|
const int tileBaseWords = tileIndex * 16;
|
||||||
|
const int inTile = ((y & 3) << 2) + (x & 3);
|
||||||
|
const int dest = tileBaseWords + inTile;
|
||||||
|
|
||||||
|
color4b_t col = data.rgba.colors[src];
|
||||||
|
|
||||||
|
u16 outCol;
|
||||||
|
if(col.a < 255) {
|
||||||
|
// 0AAA RRRR GGGG BBBB
|
||||||
|
outCol = (
|
||||||
|
(0u << 15) |
|
||||||
|
((u16)(col.a >> 5) << 12) |
|
||||||
|
((u16)(col.r >> 4) << 8) |
|
||||||
|
((u16)(col.g >> 4) << 4) |
|
||||||
|
((u16)(col.b >> 4) << 0)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// 1RRRR RRGG GGGB BBBB
|
||||||
|
outCol = (
|
||||||
|
(1u << 15) |
|
||||||
|
((u16)(col.r >> 3) << 10) |
|
||||||
|
((u16)(col.g >> 3) << 5) |
|
||||||
|
((u16)(col.b >> 3) << 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
texture->rgba[dest] = outCol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DCFlushRange(texture->rgba, rgbaSize);
|
||||||
|
GX_InitTexObj(
|
||||||
|
&texture->texObj,
|
||||||
|
texture->rgba,
|
||||||
|
width, height,
|
||||||
|
GX_TF_RGB5A3,
|
||||||
|
GX_CLAMP, GX_CLAMP,
|
||||||
|
GX_FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
DCFlushRange(texture->rgba, rgbaSize);
|
||||||
|
GX_InvalidateTexAll();
|
||||||
|
|
||||||
|
GX_InitTexObjLOD(
|
||||||
|
&texture->texObj,
|
||||||
|
GX_NEAR, GX_NEAR,
|
||||||
|
0.0f, 0.0f, 0.0f,
|
||||||
|
GX_FALSE,
|
||||||
|
GX_FALSE,
|
||||||
|
GX_ANISO_1
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEXTURE_FORMAT_ALPHA:
|
||||||
|
assertTrue(
|
||||||
|
(width % 4) == 0 && (height % 4) == 0,
|
||||||
|
"GX_TF_I8 requires w/h multiple of 4 (or pad)"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 1 byte per pixel (I8), GX expects 4x4 tiled layout
|
||||||
|
const size_t alphaSize = (size_t)width * (size_t)height;
|
||||||
|
|
||||||
|
texture->alpha = (u8*)memalign(32, alphaSize);
|
||||||
|
assertNotNull(texture->alpha, "Failed to allocate alpha texture data");
|
||||||
|
|
||||||
|
const u32 tilesPerRow = ((u32)width) >> 3; // /8
|
||||||
|
|
||||||
|
for (u32 y = 0; y < (u32)height; ++y) {
|
||||||
|
const u32 tileY = y >> 2; // /4
|
||||||
|
const u32 inTileY = (y & 3) << 3; // (y%4)*8
|
||||||
|
|
||||||
|
for (u32 x = 0; x < (u32)width; ++x) {
|
||||||
|
const u32 srcI = y * (u32)width + x;
|
||||||
|
const u8 srcA = data.alpha.data[srcI]; // linear input
|
||||||
|
|
||||||
|
const u32 tileX = x >> 3; // /8
|
||||||
|
const u32 tileIndex = tileY * tilesPerRow + tileX;
|
||||||
|
|
||||||
|
const u32 tileBase = tileIndex * 32; // 8*4*1 = 32 bytes per tile
|
||||||
|
const u32 inTile = inTileY + (x & 7); // (y%4)*8 + (x%8)
|
||||||
|
|
||||||
|
texture->alpha[tileBase + inTile] = 0xFF - srcA;// Fixes inverted alpha.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush CPU cache so GX sees the swizzled I8 texture data
|
||||||
|
DCFlushRange(texture->alpha, alphaSize);
|
||||||
|
|
||||||
|
// Initialize GX texture object with swizzled data
|
||||||
|
GX_InitTexObj(
|
||||||
|
&texture->texObj,
|
||||||
|
texture->alpha,
|
||||||
|
width, height,
|
||||||
|
GX_TF_I8,
|
||||||
|
GX_CLAMP, GX_CLAMP,
|
||||||
|
GX_FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
GX_InitTexObjLOD(
|
||||||
|
&texture->texObj,
|
||||||
|
GX_NEAR, GX_NEAR,
|
||||||
|
0.0f, 0.0f, 0.0f,
|
||||||
|
GX_FALSE,
|
||||||
|
GX_FALSE,
|
||||||
|
GX_ANISO_1
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assertUnreachable("Unsupported texture format for Dolphin");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture->ready = true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void textureBind(const texture_t *texture) {
|
void textureBind(texture_t *texture) {
|
||||||
if(TEXTURE_BOUND == texture) return;
|
if(TEXTURE_BOUND == texture) return;
|
||||||
|
|
||||||
if(texture == NULL) {
|
if(texture == NULL) {
|
||||||
@@ -158,10 +296,7 @@ void textureBind(const texture_t *texture) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(
|
assertTrue(texture->ready, "Texture ID must be ready");
|
||||||
texture->id != 0,
|
|
||||||
"Texture ID must not be 0"
|
|
||||||
);
|
|
||||||
assertTrue(
|
assertTrue(
|
||||||
texture->width > 0 && texture->height > 0,
|
texture->width > 0 && texture->height > 0,
|
||||||
"Texture width and height must be greater than 0"
|
"Texture width and height must be greater than 0"
|
||||||
@@ -171,15 +306,143 @@ void textureBind(const texture_t *texture) {
|
|||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture->id);
|
glBindTexture(GL_TEXTURE_2D, texture->id);
|
||||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||||
|
#elif DOLPHIN
|
||||||
|
GX_LoadTexObj(&texture->texObj, GX_TEXMAP0);
|
||||||
#endif
|
#endif
|
||||||
TEXTURE_BOUND = texture;
|
TEXTURE_BOUND = texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void textureDispose(texture_t *texture) {
|
void textureDispose(texture_t *texture) {
|
||||||
assertNotNull(texture, "Texture cannot be NULL");
|
assertNotNull(texture, "Texture cannot be NULL");
|
||||||
assertTrue(texture->id != 0, "Texture ID must not be 0");
|
assertTrue(texture->ready, "Texture ID must be ready");
|
||||||
|
|
||||||
|
if(TEXTURE_BOUND == texture) {
|
||||||
|
textureBind(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
#if DISPLAY_SDL2
|
#if DISPLAY_SDL2
|
||||||
glDeleteTextures(1, &texture->id);
|
glDeleteTextures(1, &texture->id);
|
||||||
|
#elif DOLPHIN
|
||||||
|
switch(texture->format) {
|
||||||
|
case TEXTURE_FORMAT_RGBA:
|
||||||
|
free(texture->rgba);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEXTURE_FORMAT_ALPHA:
|
||||||
|
free(texture->alpha);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memoryZero(texture, sizeof(texture_t));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DOLPHIN
|
||||||
|
void textureDolphinUploadTEV() {
|
||||||
|
// Add channel for vertex color
|
||||||
|
GX_SetNumChans(1);
|
||||||
|
GX_SetChanCtrl(
|
||||||
|
GX_COLOR0A0,// Store in color channel 0
|
||||||
|
GX_DISABLE,// Lighting disabled
|
||||||
|
GX_SRC_REG,// Ambient color?
|
||||||
|
GX_SRC_VTX,// Material color?
|
||||||
|
GX_LIGHTNULL,// Light Mask
|
||||||
|
GX_DF_NONE,// Diffuse function
|
||||||
|
GX_AF_NONE// Attenuation function
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!TEXTURE_BOUND) {
|
||||||
|
GX_SetNumTexGens(0);
|
||||||
|
GX_SetNumTevStages(1);
|
||||||
|
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// One set of UVs
|
||||||
|
GX_SetNumTexGens(1);
|
||||||
|
GX_SetTexCoordGen(
|
||||||
|
GX_TEXCOORD0,
|
||||||
|
GX_TG_MTX2x4,
|
||||||
|
GX_TG_TEX0,
|
||||||
|
GX_IDENTITY
|
||||||
|
);
|
||||||
|
|
||||||
|
// Basically the shader setup
|
||||||
|
switch(TEXTURE_BOUND->format) {
|
||||||
|
case TEXTURE_FORMAT_RGBA:
|
||||||
|
// One TEV stage: vertex color * texture color
|
||||||
|
GX_SetNumTevStages(1);
|
||||||
|
GX_SetTevOrder(
|
||||||
|
GX_TEVSTAGE0,
|
||||||
|
GX_TEXCOORD0,
|
||||||
|
GX_TEXMAP0,
|
||||||
|
GX_COLOR0A0
|
||||||
|
);
|
||||||
|
GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TEXTURE_FORMAT_ALPHA:
|
||||||
|
// One TEV stage: vertex color * texture color
|
||||||
|
GX_SetNumTevStages(1);
|
||||||
|
GX_SetTevOrder(
|
||||||
|
GX_TEVSTAGE0,
|
||||||
|
GX_TEXCOORD0,
|
||||||
|
GX_TEXMAP0,
|
||||||
|
GX_COLOR0A0
|
||||||
|
);
|
||||||
|
|
||||||
|
// Color = vertex color
|
||||||
|
GX_SetTevColorIn(
|
||||||
|
GX_TEVSTAGE0,
|
||||||
|
GX_CC_RASC,
|
||||||
|
GX_CC_ZERO,
|
||||||
|
GX_CC_ZERO,
|
||||||
|
GX_CC_ZERO
|
||||||
|
);
|
||||||
|
GX_SetTevColorOp(
|
||||||
|
GX_TEVSTAGE0,
|
||||||
|
GX_TEV_ADD,
|
||||||
|
GX_TB_ZERO,
|
||||||
|
GX_CS_SCALE_1,
|
||||||
|
GX_TRUE,
|
||||||
|
GX_TEVPREV
|
||||||
|
);
|
||||||
|
|
||||||
|
// Alpha = vertex alpha * I8 intensity
|
||||||
|
GX_SetTevAlphaIn(
|
||||||
|
GX_TEVSTAGE0,
|
||||||
|
GX_CA_RASA,
|
||||||
|
GX_CA_ZERO,
|
||||||
|
GX_CA_TEXA,
|
||||||
|
GX_CA_ZERO
|
||||||
|
);
|
||||||
|
GX_SetTevAlphaOp(
|
||||||
|
GX_TEVSTAGE0,
|
||||||
|
GX_TEV_ADD,
|
||||||
|
GX_TB_ZERO,
|
||||||
|
GX_CS_SCALE_1,
|
||||||
|
GX_TRUE,
|
||||||
|
GX_TEVPREV
|
||||||
|
);
|
||||||
|
|
||||||
|
GX_SetBlendMode(
|
||||||
|
GX_BM_BLEND,
|
||||||
|
GX_BL_SRCALPHA,
|
||||||
|
GX_BL_INVSRCALPHA,
|
||||||
|
GX_LO_CLEAR
|
||||||
|
);
|
||||||
|
|
||||||
|
GX_SetColorUpdate(GX_TRUE);
|
||||||
|
GX_SetAlphaUpdate(GX_TRUE);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assertUnreachable("Unknown texture format in meshDraw");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -14,14 +14,26 @@ typedef enum {
|
|||||||
TEXTURE_FORMAT_RGBA = GL_RGBA,
|
TEXTURE_FORMAT_RGBA = GL_RGBA,
|
||||||
TEXTURE_FORMAT_ALPHA = GL_ALPHA,
|
TEXTURE_FORMAT_ALPHA = GL_ALPHA,
|
||||||
TEXTURE_FORMAT_PALETTE = GL_COLOR_INDEX8_EXT,
|
TEXTURE_FORMAT_PALETTE = GL_COLOR_INDEX8_EXT,
|
||||||
|
#elif DOLPHIN
|
||||||
|
TEXTURE_FORMAT_RGBA = GX_TF_RGBA8,
|
||||||
|
TEXTURE_FORMAT_ALPHA = GX_TF_A8,
|
||||||
|
TEXTURE_FORMAT_PALETTE = GX_TF_CI8,
|
||||||
#endif
|
#endif
|
||||||
} textureformat_t;
|
} textureformat_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
#if DISPLAY_SDL2
|
#if DISPLAY_SDL2
|
||||||
GLuint id;
|
GLuint id;
|
||||||
|
#elif DOLPHIN
|
||||||
|
GXTexObj texObj;
|
||||||
|
textureformat_t format;
|
||||||
|
union {
|
||||||
|
u16 *rgba;
|
||||||
|
u8 *alpha;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool_t ready;
|
||||||
int32_t width;
|
int32_t width;
|
||||||
int32_t height;
|
int32_t height;
|
||||||
} texture_t;
|
} texture_t;
|
||||||
@@ -65,7 +77,7 @@ void textureInit(
|
|||||||
*
|
*
|
||||||
* @param texture The texture to bind.
|
* @param texture The texture to bind.
|
||||||
*/
|
*/
|
||||||
void textureBind(const texture_t *texture);
|
void textureBind(texture_t *texture);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disposes a texture.
|
* Disposes a texture.
|
||||||
@@ -73,3 +85,10 @@ void textureBind(const texture_t *texture);
|
|||||||
* @param texture The texture to dispose.
|
* @param texture The texture to dispose.
|
||||||
*/
|
*/
|
||||||
void textureDispose(texture_t *texture);
|
void textureDispose(texture_t *texture);
|
||||||
|
|
||||||
|
#if DOLPHIN
|
||||||
|
/**
|
||||||
|
* Uploads the TEV settings for the currently bound texture.
|
||||||
|
*/
|
||||||
|
void textureDolphinUploadTEV();
|
||||||
|
#endif
|
||||||
@@ -29,6 +29,15 @@
|
|||||||
#include <psphprm.h>
|
#include <psphprm.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if DOLPHIN
|
||||||
|
#include <ogcsys.h>
|
||||||
|
#include <gccore.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <sys/endian.h>
|
||||||
|
#else
|
||||||
|
#include <endian.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef bool bool_t;
|
typedef bool bool_t;
|
||||||
typedef int int_t;
|
typedef int int_t;
|
||||||
typedef float float_t;
|
typedef float float_t;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "script/scriptmanager.h"
|
#include "script/scriptmanager.h"
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
#include "item/backpack.h"
|
#include "item/backpack.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
|
||||||
engine_t ENGINE;
|
engine_t ENGINE;
|
||||||
|
|
||||||
@@ -37,7 +38,6 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
|||||||
errorChain(uiInit());
|
errorChain(uiInit());
|
||||||
errorChain(mapInit());
|
errorChain(mapInit());
|
||||||
errorChain(sceneInit());
|
errorChain(sceneInit());
|
||||||
|
|
||||||
backpackInit();
|
backpackInit();
|
||||||
|
|
||||||
// Run the initial script.
|
// Run the initial script.
|
||||||
@@ -50,6 +50,10 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
errorret_t engineUpdate(void) {
|
errorret_t engineUpdate(void) {
|
||||||
|
#if DOLPHIN
|
||||||
|
ENGINE.running = SYS_MainLoop();
|
||||||
|
#endif
|
||||||
|
|
||||||
timeUpdate();
|
timeUpdate();
|
||||||
inputUpdate();
|
inputUpdate();
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,19 @@ if(DUSK_TARGET_SYSTEM STREQUAL "linux")
|
|||||||
INPUT_MOUSE=1
|
INPUT_MOUSE=1
|
||||||
INPUT_GAMEPAD=1
|
INPUT_GAMEPAD=1
|
||||||
)
|
)
|
||||||
|
|
||||||
elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
||||||
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
|
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
PUBLIC
|
PUBLIC
|
||||||
INPUT_SDL2=1
|
INPUT_SDL2=1
|
||||||
INPUT_GAMEPAD=1
|
INPUT_GAMEPAD=1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii")
|
||||||
|
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
INPUT_GAMEPAD=1
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# CSV
|
# CSV
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "util/math.h"
|
#include "util/math.h"
|
||||||
#include "time/time.h"
|
#include "time/time.h"
|
||||||
|
#include "debug/debug.h"
|
||||||
|
|
||||||
input_t INPUT;
|
input_t INPUT;
|
||||||
|
|
||||||
@@ -23,7 +24,13 @@ void inputInit(void) {
|
|||||||
INPUT.actions[i].currentValue = 0.0f;
|
INPUT.actions[i].currentValue = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
INPUT.deadzone = 0.2f;
|
#if INPUT_GAMEPAD == 1
|
||||||
|
INPUT.deadzone = 0.2f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if DOLPHIN
|
||||||
|
PAD_Init();
|
||||||
|
#endif
|
||||||
|
|
||||||
eventInit(
|
eventInit(
|
||||||
&INPUT.eventPressed, INPUT.pressedListeners, INPUT_LISTENER_PRESSED_MAX
|
&INPUT.eventPressed, INPUT.pressedListeners, INPUT_LISTENER_PRESSED_MAX
|
||||||
@@ -47,6 +54,19 @@ void inputUpdate(void) {
|
|||||||
#if INPUT_KEYBOARD == 1
|
#if INPUT_KEYBOARD == 1
|
||||||
INPUT.keyboardState = SDL_GetKeyboardState(NULL);
|
INPUT.keyboardState = SDL_GetKeyboardState(NULL);
|
||||||
#endif
|
#endif
|
||||||
|
#elif DOLPHIN
|
||||||
|
PAD_ScanPads();
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < INPUT_PAD_COUNT; i++) {
|
||||||
|
INPUT.padState[i] = PAD_ButtonsDown(i);
|
||||||
|
INPUT.pads[i][INPUT_GAMEPAD_AXIS_LEFT_X] = INPUT_AXIS_FLOAT(PAD_StickX(i));
|
||||||
|
INPUT.pads[i][INPUT_GAMEPAD_AXIS_LEFT_Y] = INPUT_AXIS_FLOAT(PAD_StickY(i));
|
||||||
|
INPUT.pads[i][INPUT_GAMEPAD_AXIS_C_X] = INPUT_AXIS_FLOAT(PAD_SubStickX(i));
|
||||||
|
INPUT.pads[i][INPUT_GAMEPAD_AXIS_C_Y] = INPUT_AXIS_FLOAT(PAD_SubStickY(i));
|
||||||
|
INPUT.pads[i][INPUT_GAMEPAD_AXIS_TRIGGER_LEFT] = INPUT_AXIS_FLOAT(PAD_TriggerL(i));
|
||||||
|
INPUT.pads[i][INPUT_GAMEPAD_AXIS_TRIGGER_RIGHT] = INPUT_AXIS_FLOAT(PAD_TriggerR(i));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Reset all actions
|
// Reset all actions
|
||||||
@@ -69,7 +89,7 @@ void inputUpdate(void) {
|
|||||||
|
|
||||||
// For each button...
|
// For each button...
|
||||||
inputbuttondata_t *cur = &INPUT_BUTTON_DATA[0];
|
inputbuttondata_t *cur = &INPUT_BUTTON_DATA[0];
|
||||||
do {
|
while(cur->name) {
|
||||||
cur->lastVal = cur->curVal;
|
cur->lastVal = cur->curVal;
|
||||||
cur->curVal = inputButtonGetValue(cur->button);
|
cur->curVal = inputButtonGetValue(cur->button);
|
||||||
|
|
||||||
@@ -95,7 +115,7 @@ void inputUpdate(void) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
cur++;
|
cur++;
|
||||||
} while(cur->name);
|
}
|
||||||
|
|
||||||
// Do we need to fire off events?
|
// Do we need to fire off events?
|
||||||
#if TIME_FIXED == 0
|
#if TIME_FIXED == 0
|
||||||
|
|||||||
@@ -10,6 +10,11 @@
|
|||||||
#include "inputaction.h"
|
#include "inputaction.h"
|
||||||
#include "event/event.h"
|
#include "event/event.h"
|
||||||
|
|
||||||
|
#if DOLPHIN
|
||||||
|
#define INPUT_PAD_COUNT PAD_CHANMAX
|
||||||
|
#define INPUT_AXIS_FLOAT(value) ((float_t)(value) / 128.0f)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define INPUT_LISTENER_PRESSED_MAX 16
|
#define INPUT_LISTENER_PRESSED_MAX 16
|
||||||
#define INPUT_LISTENER_RELEASED_MAX INPUT_LISTENER_PRESSED_MAX
|
#define INPUT_LISTENER_RELEASED_MAX INPUT_LISTENER_PRESSED_MAX
|
||||||
|
|
||||||
@@ -37,6 +42,11 @@ typedef struct {
|
|||||||
#if INPUT_KEYBOARD == 1
|
#if INPUT_KEYBOARD == 1
|
||||||
const uint8_t *keyboardState;
|
const uint8_t *keyboardState;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#elif DOLPHIN
|
||||||
|
int padState[INPUT_PAD_COUNT];
|
||||||
|
float_t pads[INPUT_PAD_COUNT][INPUT_GAMEPAD_AXIS_COUNT];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
} input_t;
|
} input_t;
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ inputbuttondata_t INPUT_BUTTON_DATA[] = {
|
|||||||
{ .name = "lstick_negative_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = false } } },
|
{ .name = "lstick_negative_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = false } } },
|
||||||
{ .name = "lstick_positive_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = true } } },
|
{ .name = "lstick_positive_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = true } } },
|
||||||
{ .name = "lstick_negative_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = false } } },
|
{ .name = "lstick_negative_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = false } } },
|
||||||
#else
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -172,6 +171,61 @@ inputbuttondata_t INPUT_BUTTON_DATA[] = {
|
|||||||
{ .name = "kp_enter", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_ENTER } },
|
{ .name = "kp_enter", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_ENTER } },
|
||||||
{ .name = "kp_equals", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_EQUALS } },
|
{ .name = "kp_equals", { .type = INPUT_BUTTON_TYPE_KEYBOARD, .scancode = SDL_SCANCODE_KP_EQUALS } },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#elif DOLPHIN
|
||||||
|
#if WII
|
||||||
|
#if INPUT_GAMEPAD == 1
|
||||||
|
{ .name = "a", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_A } },
|
||||||
|
{ .name = "b", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_B } },
|
||||||
|
{ .name = "x", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_X } },
|
||||||
|
{ .name = "y", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_Y } },
|
||||||
|
{ .name = "start", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_START } },
|
||||||
|
{ .name = "dpad_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_UP } },
|
||||||
|
{ .name = "dpad_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_DOWN } },
|
||||||
|
{ .name = "dpad_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_LEFT } },
|
||||||
|
{ .name = "dpad_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_RIGHT } },
|
||||||
|
{ .name = "l", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_L } },
|
||||||
|
{ .name = "r", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_R } },
|
||||||
|
{ .name = "z", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_Z } },
|
||||||
|
{ .name = "menu", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_MENU } },
|
||||||
|
{ .name = "lstick_positive_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = true } } },
|
||||||
|
{ .name = "lstick_negative_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = false } } },
|
||||||
|
{ .name = "lstick_positive_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = true } } },
|
||||||
|
{ .name = "lstick_negative_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = false } } },
|
||||||
|
{ .name = "cstick_positive_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = true } } },
|
||||||
|
{ .name = "cstick_negative_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = false } } },
|
||||||
|
{ .name = "cstick_positive_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = true } } },
|
||||||
|
{ .name = "cstick_negative_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = false } } },
|
||||||
|
{ .name = "ltrigger", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_TRIGGER_LEFT, .positive = true } } },
|
||||||
|
{ .name = "rtrigger", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_TRIGGER_RIGHT, .positive = true } } },
|
||||||
|
#endif
|
||||||
|
#elif GAMECUBE
|
||||||
|
#if INPUT_GAMEPAD == 1
|
||||||
|
{ .name = "a", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_A } },
|
||||||
|
{ .name = "b", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_B } },
|
||||||
|
{ .name = "x", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_X } },
|
||||||
|
{ .name = "y", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_Y } },
|
||||||
|
{ .name = "start", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_START } },
|
||||||
|
{ .name = "dpad_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_UP } },
|
||||||
|
{ .name = "dpad_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_DOWN } },
|
||||||
|
{ .name = "dpad_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_LEFT } },
|
||||||
|
{ .name = "dpad_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_RIGHT } },
|
||||||
|
{ .name = "l", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_L } },
|
||||||
|
{ .name = "r", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_R } },
|
||||||
|
{ .name = "z", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_TRIGGER_Z } },
|
||||||
|
{ .name = "menu", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = PAD_BUTTON_MENU } },
|
||||||
|
{ .name = "lstick_positive_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = true } } },
|
||||||
|
{ .name = "lstick_negative_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_X, .positive = false } } },
|
||||||
|
{ .name = "lstick_positive_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = true } } },
|
||||||
|
{ .name = "lstick_negative_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_LEFT_Y, .positive = false } } },
|
||||||
|
{ .name = "cstick_positive_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = true } } },
|
||||||
|
{ .name = "cstick_negative_x", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_X, .positive = false } } },
|
||||||
|
{ .name = "cstick_positive_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = true } } },
|
||||||
|
{ .name = "cstick_negative_y", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_C_Y, .positive = false } } },
|
||||||
|
{ .name = "ltrigger", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_TRIGGER_LEFT, .positive = true } } },
|
||||||
|
{ .name = "rtrigger", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = INPUT_GAMEPAD_AXIS_TRIGGER_RIGHT, .positive = true } } },
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{ .name = NULL }
|
{ .name = NULL }
|
||||||
@@ -197,9 +251,9 @@ float_t inputButtonGetValue(const inputbutton_t button) {
|
|||||||
case INPUT_BUTTON_TYPE_KEYBOARD: {
|
case INPUT_BUTTON_TYPE_KEYBOARD: {
|
||||||
#if INPUT_SDL2 == 1
|
#if INPUT_SDL2 == 1
|
||||||
return INPUT.keyboardState[button.scancode] ? 1.0f : 0.0f;
|
return INPUT.keyboardState[button.scancode] ? 1.0f : 0.0f;
|
||||||
#else
|
|
||||||
return 0.0f;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return 0.0f;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -209,19 +263,29 @@ float_t inputButtonGetValue(const inputbutton_t button) {
|
|||||||
if(SDL_GameControllerGetButton(INPUT.controller, button.gpButton)) {
|
if(SDL_GameControllerGetButton(INPUT.controller, button.gpButton)) {
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
|
#elif DOLPHIN
|
||||||
|
if(INPUT.padState[0] & button.gpButton) return 1.0f;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
case INPUT_BUTTON_TYPE_GAMEPAD_AXIS: {
|
case INPUT_BUTTON_TYPE_GAMEPAD_AXIS: {
|
||||||
|
float_t value = 0.0f;
|
||||||
|
|
||||||
#if INPUT_SDL2 == 1
|
#if INPUT_SDL2 == 1
|
||||||
Sint16 axis = SDL_GameControllerGetAxis(INPUT.controller, button.gpAxis.axis);
|
Sint16 axis = SDL_GameControllerGetAxis(INPUT.controller, button.gpAxis.axis);
|
||||||
if(!button.gpAxis.positive) axis = -axis;
|
value = (float_t)axis / 32767.0f;
|
||||||
float_t value = (float_t)axis / 32767.0f;
|
|
||||||
// Deadzone
|
#elif DOLPHIN
|
||||||
if(value < INPUT.deadzone) return 0.0f;
|
value = INPUT.pads[0][button.gpAxis.axis];
|
||||||
return value;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if(!button.gpAxis.positive) value = -value;
|
||||||
|
if(value >= INPUT.deadzone) return value;
|
||||||
|
return 0.0f;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#if INPUT_SDL2 == 1
|
#if INPUT_SDL2 == 1
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#elif DOLPHIN
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "No input backend defined"
|
#error "No input backend defined"
|
||||||
#endif
|
#endif
|
||||||
@@ -26,6 +28,18 @@
|
|||||||
#if INPUT_SDL2 == 1
|
#if INPUT_SDL2 == 1
|
||||||
typedef SDL_GameControllerButton inputgamepadbutton_t;
|
typedef SDL_GameControllerButton inputgamepadbutton_t;
|
||||||
typedef SDL_GameControllerAxis inputgamepadaxis_t;
|
typedef SDL_GameControllerAxis inputgamepadaxis_t;
|
||||||
|
#elif DOLPHIN == 1
|
||||||
|
typedef u16 inputgamepadbutton_t;
|
||||||
|
typedef enum {
|
||||||
|
INPUT_GAMEPAD_AXIS_LEFT_X,
|
||||||
|
INPUT_GAMEPAD_AXIS_LEFT_Y,
|
||||||
|
INPUT_GAMEPAD_AXIS_C_X,
|
||||||
|
INPUT_GAMEPAD_AXIS_C_Y,
|
||||||
|
INPUT_GAMEPAD_AXIS_TRIGGER_LEFT,
|
||||||
|
INPUT_GAMEPAD_AXIS_TRIGGER_RIGHT,
|
||||||
|
|
||||||
|
INPUT_GAMEPAD_AXIS_COUNT
|
||||||
|
} inputgamepadaxis_t;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -35,6 +49,7 @@ typedef enum {
|
|||||||
#if INPUT_KEYBOARD == 1
|
#if INPUT_KEYBOARD == 1
|
||||||
INPUT_BUTTON_TYPE_KEYBOARD,
|
INPUT_BUTTON_TYPE_KEYBOARD,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if INPUT_GAMEPAD == 1
|
#if INPUT_GAMEPAD == 1
|
||||||
INPUT_BUTTON_TYPE_GAMEPAD,
|
INPUT_BUTTON_TYPE_GAMEPAD,
|
||||||
INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
|
INPUT_BUTTON_TYPE_GAMEPAD_AXIS,
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ localemanager_t LOCALE;
|
|||||||
|
|
||||||
errorret_t localeManagerInit() {
|
errorret_t localeManagerInit() {
|
||||||
memoryZero(&LOCALE, sizeof(localemanager_t));
|
memoryZero(&LOCALE, sizeof(localemanager_t));
|
||||||
// errorChain(localeManagerSetLocale(DUSK_LOCALE_EN_US));
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
#include "asset/asset.h"
|
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
#include "input/input.h"
|
#include "input/input.h"
|
||||||
|
|
||||||
|
|||||||
11
src/null.c
Normal file
11
src/null.c
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Empty C file for annoying platforms.
|
||||||
|
void nothing(void) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -76,7 +76,6 @@ errorret_t sceneSet(const char_t *script) {
|
|||||||
// Create a new script context.
|
// Create a new script context.
|
||||||
errorChain(scriptContextInit(&SCENE.scriptContext));
|
errorChain(scriptContextInit(&SCENE.scriptContext));
|
||||||
errorChain(scriptContextExecFile(&SCENE.scriptContext, script));
|
errorChain(scriptContextExecFile(&SCENE.scriptContext, script));
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +86,7 @@ void sceneDispose(void) {
|
|||||||
const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1);
|
const char_t *strErr = lua_tostring(SCENE.scriptContext.luaState, -1);
|
||||||
lua_pop(SCENE.scriptContext.luaState, 1);
|
lua_pop(SCENE.scriptContext.luaState, 1);
|
||||||
debugPrint("Failed to call function '%s': %s\n", "sceneDispose", strErr);
|
debugPrint("Failed to call function '%s': %s\n", "sceneDispose", strErr);
|
||||||
|
debugFlush();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lua_pop(SCENE.scriptContext.luaState, 1);
|
lua_pop(SCENE.scriptContext.luaState, 1);
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ int moduleSysPrint(lua_State *L) {
|
|||||||
luaL_pushresult(&b);
|
luaL_pushresult(&b);
|
||||||
const char *msg = lua_tostring(L, -1);
|
const char *msg = lua_tostring(L, -1);
|
||||||
debugPrint("%s\n", msg);
|
debugPrint("%s\n", msg);
|
||||||
|
debugFlush();
|
||||||
return 0; // no values returned to Lua
|
return 0; // no values returned to Lua
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ errorret_t scriptContextExec(scriptcontext_t *context, const char_t *script) {
|
|||||||
if(luaL_dostring(context->luaState, script) != LUA_OK) {
|
if(luaL_dostring(context->luaState, script) != LUA_OK) {
|
||||||
const char_t *strErr = lua_tostring(context->luaState, -1);
|
const char_t *strErr = lua_tostring(context->luaState, -1);
|
||||||
lua_pop(context->luaState, 1);
|
lua_pop(context->luaState, 1);
|
||||||
errorThrow("Failed to execute Lua: ", strErr);
|
errorThrow("Failed to execute Lua: %s", strErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
errorOk();
|
errorOk();
|
||||||
|
|||||||
@@ -21,4 +21,8 @@ elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
|||||||
PUBLIC
|
PUBLIC
|
||||||
THREAD_PTHREAD=1
|
THREAD_PTHREAD=1
|
||||||
)
|
)
|
||||||
|
elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii")
|
||||||
|
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
@@ -21,4 +21,9 @@ elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
|
|||||||
PUBLIC
|
PUBLIC
|
||||||
TIME_FIXED=1
|
TIME_FIXED=1
|
||||||
)
|
)
|
||||||
|
elseif(DUSK_TARGET_SYSTEM STREQUAL "gamecube" OR DUSK_TARGET_SYSTEM STREQUAL "wii")
|
||||||
|
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
TIME_FIXED=1
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
#include "display/spritebatch.h"
|
#include "display/spritebatch.h"
|
||||||
#include "display/screen.h"
|
#include "display/screen.h"
|
||||||
|
|
||||||
|
#include "debug/debug.h"
|
||||||
|
|
||||||
ui_t UI;
|
ui_t UI;
|
||||||
|
|
||||||
errorret_t uiInit(void) {
|
errorret_t uiInit(void) {
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ void memoryFree(void *ptr) {
|
|||||||
MEMORY_POINTERS_IN_USE--;
|
MEMORY_POINTERS_IN_USE--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void memoryCopy(void *dest, const void *src, const size_t size) {
|
void memoryCopy(void *dest, const void *src, const size_t size) {
|
||||||
assertNotNull(dest, "Cannot copy to NULL memory.");
|
assertNotNull(dest, "Cannot copy to NULL memory.");
|
||||||
assertNotNull(src, "Cannot copy from NULL memory.");
|
assertNotNull(src, "Cannot copy from NULL memory.");
|
||||||
|
|||||||
Reference in New Issue
Block a user