Renders on PSP identically.
This commit is contained in:
@@ -12,6 +12,17 @@ target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
|||||||
mbedcrypto
|
mbedcrypto
|
||||||
lzma
|
lzma
|
||||||
m
|
m
|
||||||
|
pspdebug
|
||||||
|
pspdisplay
|
||||||
|
pspge
|
||||||
|
pspctrl
|
||||||
|
pspgu
|
||||||
|
pspaudio
|
||||||
|
pspaudiolib
|
||||||
|
psputility
|
||||||
|
pspvfpu
|
||||||
|
pspvram
|
||||||
|
psphprm
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(${DUSK_LIBRARY_TARGET_NAME} PRIVATE
|
target_include_directories(${DUSK_LIBRARY_TARGET_NAME} PRIVATE
|
||||||
@@ -24,6 +35,8 @@ target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
|
|||||||
DUSK_PSP
|
DUSK_PSP
|
||||||
DUSK_INPUT_GAMEPAD
|
DUSK_INPUT_GAMEPAD
|
||||||
DUSK_PLATFORM_ENDIAN_LITTLE
|
DUSK_PLATFORM_ENDIAN_LITTLE
|
||||||
|
DUSK_DISPLAY_WIDTH=480
|
||||||
|
DUSK_DISPLAY_HEIGHT=272
|
||||||
)
|
)
|
||||||
|
|
||||||
# Postbuild, create .pbp file for PSP.
|
# Postbuild, create .pbp file for PSP.
|
||||||
|
|||||||
@@ -2,6 +2,6 @@ FROM pspdev/pspdev:latest
|
|||||||
WORKDIR /workdir
|
WORKDIR /workdir
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
python3 \
|
python3 \
|
||||||
py3-pip
|
py3-pip \
|
||||||
|
py3-dotenv
|
||||||
VOLUME ["/workdir"]
|
VOLUME ["/workdir"]
|
||||||
CMD [ "/bin/bash", "-c", "./scripts/build-psp.sh" ]
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
docker build -t dusk-psp -f docker/psp/Dockerfile .
|
docker build -t dusk-psp -f docker/psp/Dockerfile .
|
||||||
docker run --rm -v $(pwd):/workdir dusk-psp
|
docker run --rm -v $(pwd):/workdir dusk-psp /bin/bash -c "./scripts/build-psp.sh"
|
||||||
@@ -6,5 +6,6 @@ fi
|
|||||||
|
|
||||||
mkdir -p build-psp
|
mkdir -p build-psp
|
||||||
cd build-psp
|
cd build-psp
|
||||||
cmake .. -DDUSK_TARGET_SYSTEM=psp -DCMAKE_TOOLCHAIN_FILE=$PSPDEV/psp/share/pspdev.cmake
|
psp-cmake -DDUSK_TARGET_SYSTEM=psp -DCMAKE_TOOLCHAIN_FILE=$PSPDEV/psp/share/pspdev.cmake -DBUILD_PRX=1 -DCMAKE_BUILD_TYPE=Debug ..
|
||||||
make -j$(nproc)
|
make
|
||||||
|
# make -j$(nproc)
|
||||||
@@ -17,8 +17,8 @@
|
|||||||
#ifndef DUSK_DISPLAY_HEIGHT
|
#ifndef DUSK_DISPLAY_HEIGHT
|
||||||
#error "DUSK_DISPLAY_HEIGHT must be defined"
|
#error "DUSK_DISPLAY_HEIGHT must be defined"
|
||||||
#endif
|
#endif
|
||||||
#define DISPLAY_WINDOW_WIDTH_DEFAULT DUSK_DISPLAY_WIDTH
|
#define DUSK_DISPLAY_WIDTH_DEFAULT DUSK_DISPLAY_WIDTH
|
||||||
#define DISPLAY_WINDOW_HEIGHT_DEFAULT DUSK_DISPLAY_HEIGHT
|
#define DUSK_DISPLAY_HEIGHT_DEFAULT DUSK_DISPLAY_HEIGHT
|
||||||
#else
|
#else
|
||||||
#ifndef DUSK_DISPLAY_WIDTH_DEFAULT
|
#ifndef DUSK_DISPLAY_WIDTH_DEFAULT
|
||||||
#error "DUSK_DISPLAY_WIDTH_DEFAULT must be defined."
|
#error "DUSK_DISPLAY_WIDTH_DEFAULT must be defined."
|
||||||
|
|||||||
@@ -9,5 +9,13 @@ target_include_directories(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
${CMAKE_CURRENT_LIST_DIR}
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Sources
|
||||||
|
target_sources(${DUSK_BINARY_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
# hello.c
|
||||||
|
)
|
||||||
|
|
||||||
# Subdirs
|
# Subdirs
|
||||||
add_subdirectory(debug)
|
add_subdirectory(debug)
|
||||||
|
add_subdirectory(asset)
|
||||||
|
add_subdirectory(input)
|
||||||
11
src/duskpsp/asset/CMakeLists.txt
Normal file
11
src/duskpsp/asset/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Copyright (c) 2026 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
# Sources
|
||||||
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
assetpbp.c
|
||||||
|
assetpsp.c
|
||||||
|
)
|
||||||
@@ -1,87 +1,113 @@
|
|||||||
assertTrue(ENGINE.argc >= 1, "PSP requires launch argument.");
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
// PSP is given either the prx OR the PBP file.
|
#include "asset/asset.h"
|
||||||
// In the format of "ms0:/PSP/GAME/DUSK/EBOOT.PBP" or "host0:/Dusk.prx"
|
#include "assert/assert.h"
|
||||||
// IF the file is the PBP file, we are loading directly on the PSP itself.
|
#include "util/memory.h"
|
||||||
// IF the file is the .prx then we are debugging and fopen will return
|
|
||||||
// relative filepaths correctly, e.g. host0:/dusk.dsk will be on host.
|
|
||||||
if(
|
|
||||||
stringEndsWithCaseInsensitive(ENGINE.argv[0], ".pbp") ||
|
|
||||||
ASSET_PBP_READ_PBP_FROM_HOST
|
|
||||||
) {
|
|
||||||
const char_t *pbpPath = (
|
|
||||||
ASSET_PBP_READ_PBP_FROM_HOST ? "./EBOOT.PBP" : ENGINE.argv[0]
|
|
||||||
);
|
|
||||||
ASSET.pbpFile = fopen(pbpPath, "rb");
|
|
||||||
if(ASSET.pbpFile == NULL) {
|
|
||||||
errorThrow("Failed to open PBP file: %s", pbpPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get size of PBP file.
|
errorret_t assetInitPBP(const char_t *pbpPath) {
|
||||||
if(fseek(ASSET.pbpFile, 0, SEEK_END) != 0) {
|
assertNotNull(pbpPath, "PBP path cannot be null.");
|
||||||
fclose(ASSET.pbpFile);
|
assertStrLenMin(pbpPath, 1, "PBP path cannot be empty.");
|
||||||
errorThrow("Failed to seek to end of PBP file : %s", pbpPath);
|
assertStrLenMax(pbpPath, FILENAME_MAX, "PBP path is too long.");
|
||||||
}
|
|
||||||
size_t pbpSize = ftell(ASSET.pbpFile);
|
|
||||||
|
|
||||||
// Rewind to start
|
ASSET.platform.pbpFile = fopen(pbpPath, "rb");
|
||||||
if(fseek(ASSET.pbpFile, 0, SEEK_SET) != 0) {
|
if(ASSET.platform.pbpFile == NULL) {
|
||||||
fclose(ASSET.pbpFile);
|
errorThrow("Failed to open PBP file: %s", pbpPath);
|
||||||
errorThrow("Failed to seek to start of PBP file : %s", pbpPath);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Read the PBP header
|
// Get size of PBP file.
|
||||||
size_t read = fread(
|
if(fseek(ASSET.platform.pbpFile, 0, SEEK_END) != 0) {
|
||||||
&ASSET.pbpHeader,
|
fclose(ASSET.platform.pbpFile);
|
||||||
1,
|
errorThrow("Failed to seek to end of PBP file : %s", pbpPath);
|
||||||
sizeof(assetpbp_t),
|
}
|
||||||
ASSET.pbpFile
|
|
||||||
);
|
|
||||||
if(read != sizeof(assetpbp_t)) {
|
|
||||||
fclose(ASSET.pbpFile);
|
|
||||||
errorThrow("Failed to read PBP header", pbpPath);
|
|
||||||
}
|
|
||||||
if(memoryCompare(
|
|
||||||
ASSET.pbpHeader.signature,
|
|
||||||
ASSET_PBP_SIGNATURE,
|
|
||||||
sizeof(ASSET_PBP_SIGNATURE)
|
|
||||||
) != 0) {
|
|
||||||
fclose(ASSET.pbpFile);
|
|
||||||
errorThrow("Invalid PBP signature in file: %s", pbpPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we seek to the PSAR offset, we can read the WAD file from there
|
size_t pbpSize = ftell(ASSET.platform.pbpFile);
|
||||||
if(fseek(ASSET.pbpFile, ASSET.pbpHeader.psarOffset, SEEK_SET) != 0) {
|
if(pbpSize == -1L) {
|
||||||
fclose(ASSET.pbpFile);
|
fclose(ASSET.platform.pbpFile);
|
||||||
errorThrow("Failed to seek to PSAR offset in PBP file: %s", pbpPath);
|
errorThrow("Failed to get size of PBP file : %s", pbpPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
zip_uint64_t zipPsarOffset = (zip_uint64_t)ASSET.pbpHeader.psarOffset;
|
if(pbpSize < sizeof(assetpbpheader_t)) {
|
||||||
zip_int64_t zipPsarSize = (zip_int64_t)(
|
fclose(ASSET.platform.pbpFile);
|
||||||
pbpSize - ASSET.pbpHeader.psarOffset
|
errorThrow("PBP file is too small to be valid: %s", pbpPath);
|
||||||
);
|
}
|
||||||
|
|
||||||
zip_source_t *psarSource = zip_source_filep_create(
|
// Rewind to start
|
||||||
ASSET.pbpFile,
|
if(fseek(ASSET.platform.pbpFile, 0, SEEK_SET) != 0) {
|
||||||
zipPsarOffset,
|
fclose(ASSET.platform.pbpFile);
|
||||||
zipPsarSize,
|
errorThrow("Failed to seek to start of PBP file : %s", pbpPath);
|
||||||
NULL
|
}
|
||||||
);
|
|
||||||
if(psarSource == NULL) {
|
|
||||||
fclose(ASSET.pbpFile);
|
|
||||||
errorThrow("Failed to create zip source in PBP file: %s", pbpPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSET.zip = zip_open_from_source(
|
// Read the PBP header
|
||||||
psarSource,
|
size_t read = fread(
|
||||||
ZIP_RDONLY,
|
&ASSET.platform.pbpHeader,
|
||||||
NULL
|
1,
|
||||||
);
|
sizeof(assetpbpheader_t),
|
||||||
if(ASSET.zip == NULL) {
|
ASSET.platform.pbpFile
|
||||||
zip_source_free(psarSource);
|
);
|
||||||
fclose(ASSET.pbpFile);
|
if(read != sizeof(assetpbpheader_t)) {
|
||||||
errorThrow("Failed to open zip from PBP file: %s", pbpPath);
|
fclose(ASSET.platform.pbpFile);
|
||||||
}
|
errorThrow("Failed to read PBP header", pbpPath);
|
||||||
|
}
|
||||||
|
|
||||||
errorOk();
|
if(memoryCompare(
|
||||||
}
|
ASSET.platform.pbpHeader.signature,
|
||||||
|
ASSET_PBP_SIGNATURE,
|
||||||
|
sizeof(ASSET_PBP_SIGNATURE)
|
||||||
|
) != 0) {
|
||||||
|
fclose(ASSET.platform.pbpFile);
|
||||||
|
errorThrow("Invalid PBP signature in file: %s", pbpPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we seek to the PSAR offset, we can read the WAD file from there.
|
||||||
|
// I'm not sure what PSAR was intended for, but it holds any user data we
|
||||||
|
// want, so I shoved the entire dusk wad there.
|
||||||
|
if(fseek(
|
||||||
|
ASSET.platform.pbpFile, ASSET.platform.pbpHeader.psarOffset, SEEK_SET
|
||||||
|
) != 0) {
|
||||||
|
fclose(ASSET.platform.pbpFile);
|
||||||
|
errorThrow("Failed to seek to PSAR offset in PBP file: %s", pbpPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
zip_uint64_t zipPsarOffset = (zip_uint64_t)ASSET.platform.pbpHeader.psarOffset;
|
||||||
|
zip_int64_t zipPsarSize = (zip_int64_t)(
|
||||||
|
pbpSize - ASSET.platform.pbpHeader.psarOffset
|
||||||
|
);
|
||||||
|
|
||||||
|
zip_source_t *psarSource = zip_source_filep_create(
|
||||||
|
ASSET.platform.pbpFile,
|
||||||
|
zipPsarOffset,
|
||||||
|
zipPsarSize,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if(psarSource == NULL) {
|
||||||
|
fclose(ASSET.platform.pbpFile);
|
||||||
|
errorThrow("Failed to create zip source in PBP file: %s", pbpPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSET.zip = zip_open_from_source(
|
||||||
|
psarSource,
|
||||||
|
ZIP_RDONLY,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
if(ASSET.zip == NULL) {
|
||||||
|
zip_source_free(psarSource);
|
||||||
|
fclose(ASSET.platform.pbpFile);
|
||||||
|
errorThrow("Failed to open zip from PBP file: %s", pbpPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t assetDisposePBP(void) {
|
||||||
|
if(ASSET.platform.pbpFile != NULL) {
|
||||||
|
fclose(ASSET.platform.pbpFile);
|
||||||
|
ASSET.platform.pbpFile = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
@@ -6,9 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "dusk.h"
|
#include "error/error.h"
|
||||||
|
|
||||||
#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"
|
||||||
|
|
||||||
@@ -29,3 +28,18 @@ typedef struct {
|
|||||||
FILE *pbpFile;
|
FILE *pbpFile;
|
||||||
assetpbpheader_t pbpHeader;
|
assetpbpheader_t pbpHeader;
|
||||||
} assetpbp_t;
|
} assetpbp_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the PBP style asset system.
|
||||||
|
*
|
||||||
|
* @param pbpPath The file path to the PBP file to read.
|
||||||
|
* @returns An errorret_t indicating success or failure of the operation.
|
||||||
|
*/
|
||||||
|
errorret_t assetInitPBP(const char_t *pbpPath);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes the PBP style asset system.
|
||||||
|
*
|
||||||
|
* @returns An errorret_t indicating success or failure of the operation.
|
||||||
|
*/
|
||||||
|
errorret_t assetDisposePBP(void);
|
||||||
13
src/duskpsp/asset/assetplatform.h
Normal file
13
src/duskpsp/asset/assetplatform.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "assetpsp.h"
|
||||||
|
|
||||||
|
typedef assetpsp_t assetplatform_t;
|
||||||
|
#define assetInitPlatform assetInitPSP
|
||||||
|
#define assetDisposePlatform assetDisposePSP
|
||||||
40
src/duskpsp/asset/assetpsp.c
Normal file
40
src/duskpsp/asset/assetpsp.c
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "asset/asset.h"
|
||||||
|
#include "engine/engine.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
|
errorret_t assetInitPSP(void) {
|
||||||
|
assertTrue(ENGINE.argc >= 1, "PSP requires launch argument.");
|
||||||
|
|
||||||
|
// PSP is given either the prx OR the PBP file.
|
||||||
|
// In the format of "ms0:/PSP/GAME/DUSK/EBOOT.PBP" or "host0:/Dusk.prx"
|
||||||
|
// IF the file is the PBP file, we are loading directly on the PSP itself.
|
||||||
|
// IF the file is the .prx then we are debugging and fopen will return
|
||||||
|
// relative filepaths correctly, e.g. host0:/dusk.dsk will be on host.
|
||||||
|
|
||||||
|
// Originally I was going to allow host to read the .dsk directly but then
|
||||||
|
// I'd have to maintain two file implementations.
|
||||||
|
|
||||||
|
const char_t *pbpPath;
|
||||||
|
if(stringEndsWithCaseInsensitive(ENGINE.argv[0], ASSET_PSP_EXTENSION_PBP)) {
|
||||||
|
pbpPath = ENGINE.argv[0];
|
||||||
|
} else {
|
||||||
|
// In Debugging this would be next to host0:/Dusk.prx
|
||||||
|
pbpPath = "./EBOOT.PBP";
|
||||||
|
}
|
||||||
|
|
||||||
|
errorChain(assetInitPBP(pbpPath));
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t assetDisposePSP(void) {
|
||||||
|
errorChain(assetDisposePBP());
|
||||||
|
errorOk();
|
||||||
|
}
|
||||||
27
src/duskpsp/asset/assetpsp.h
Normal file
27
src/duskpsp/asset/assetpsp.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "assetpbp.h"
|
||||||
|
|
||||||
|
#define ASSET_PSP_EXTENSION_PBP ".pbp"
|
||||||
|
|
||||||
|
typedef assetpbp_t assetpsp_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the PSP style asset system.
|
||||||
|
*
|
||||||
|
* @returns An errorret_t indicating success or failure of the operation.
|
||||||
|
*/
|
||||||
|
errorret_t assetInitPSP(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes the PSP style asset system.
|
||||||
|
*
|
||||||
|
* @returns An errorret_t indicating success or failure of the operation.
|
||||||
|
*/
|
||||||
|
errorret_t assetDisposePSP(void);
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
* https://opensource.org/licenses/MIT
|
* https://opensource.org/licenses/MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "psp.h"
|
#include "debug/debug.h"
|
||||||
|
|
||||||
void debugPrint(const char_t *message, ...) {
|
void debugPrint(const char_t *message, ...) {
|
||||||
FILE *file = fopen("ms0:/PSP/GAME/Dusk/debug.log", "a");
|
FILE *file = fopen("ms0:/PSP/GAME/Dusk/debug.log", "a");
|
||||||
|
|||||||
16
src/duskpsp/display/displayplatform.h
Normal file
16
src/duskpsp/display/displayplatform.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "display/displaysdl2.h"
|
||||||
|
|
||||||
|
typedef displaysdl2_t displayplatform_t;
|
||||||
|
|
||||||
|
#define displayPlatformInit displaySDL2Init
|
||||||
|
#define displayPlatformUpdate displaySDL2Update
|
||||||
|
#define displayPlatformSwap displaySDL2Swap
|
||||||
|
#define displayPlatformDispose displaySDL2Dispose
|
||||||
@@ -11,3 +11,4 @@
|
|||||||
#include <pspdisplay.h>
|
#include <pspdisplay.h>
|
||||||
#include <pspctrl.h>
|
#include <pspctrl.h>
|
||||||
#include <psphprm.h>
|
#include <psphprm.h>
|
||||||
|
#include "dusksdl2.h"
|
||||||
41
src/duskpsp/hello.c
Normal file
41
src/duskpsp/hello.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include <pspuser.h>
|
||||||
|
#include <pspdebug.h>
|
||||||
|
#include <pspdisplay.h>
|
||||||
|
|
||||||
|
// PSP_MODULE_INFO is required
|
||||||
|
PSP_MODULE_INFO("Hello World", 0, 1, 0);
|
||||||
|
PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_USER);
|
||||||
|
|
||||||
|
int exit_callback(int arg1, int arg2, void *common) {
|
||||||
|
sceKernelExitGame();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int callback_thread(SceSize args, void *argp) {
|
||||||
|
int cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
|
||||||
|
sceKernelRegisterExitCallback(cbid);
|
||||||
|
sceKernelSleepThreadCB();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int setup_callbacks(void) {
|
||||||
|
int thid = sceKernelCreateThread("update_thread", callback_thread, 0x11, 0xFA0, 0, 0);
|
||||||
|
if(thid >= 0)
|
||||||
|
sceKernelStartThread(thid, 0, 0);
|
||||||
|
return thid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
// Use above functions to make exiting possible
|
||||||
|
setup_callbacks();
|
||||||
|
|
||||||
|
// Print Hello World! on a debug screen on a loop
|
||||||
|
pspDebugScreenInit();
|
||||||
|
while(1) {
|
||||||
|
pspDebugScreenSetXY(0, 0);
|
||||||
|
pspDebugScreenPrintf("Hello World!");
|
||||||
|
sceDisplayWaitVblankStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
10
src/duskpsp/input/CMakeLists.txt
Normal file
10
src/duskpsp/input/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Copyright (c) 2026 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
# Sources
|
||||||
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
inputpsp.c
|
||||||
|
)
|
||||||
30
src/duskpsp/input/inputpsp.c
Normal file
30
src/duskpsp/input/inputpsp.c
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "input/input.h"
|
||||||
|
|
||||||
|
inputbuttondata_t INPUT_BUTTON_DATA[] = {
|
||||||
|
{ .name = "triangle", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_Y } },
|
||||||
|
{ .name = "cross", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_A } },
|
||||||
|
{ .name = "circle", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_B } },
|
||||||
|
{ .name = "square", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_X } },
|
||||||
|
{ .name = "start", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_START } },
|
||||||
|
{ .name = "select", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_BACK } },
|
||||||
|
{ .name = "up", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_UP } },
|
||||||
|
{ .name = "down", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_DOWN } },
|
||||||
|
{ .name = "left", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_LEFT } },
|
||||||
|
{ .name = "right", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_DPAD_RIGHT } },
|
||||||
|
{ .name = "l", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_LEFTSHOULDER } },
|
||||||
|
{ .name = "r", { .type = INPUT_BUTTON_TYPE_GAMEPAD, .gpButton = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER } },
|
||||||
|
|
||||||
|
{ .name = "lstick_down", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = true } } },
|
||||||
|
{ .name = "lstick_up", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTX, .positive = false } } },
|
||||||
|
{ .name = "lstick_right", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = true } } },
|
||||||
|
{ .name = "lstick_left", { .type = INPUT_BUTTON_TYPE_GAMEPAD_AXIS, .gpAxis = { .axis = SDL_CONTROLLER_AXIS_LEFTY, .positive = false } } },
|
||||||
|
|
||||||
|
{ .name = NULL }
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user