aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorJohn "Lameguy" Wilbert Villamor <lameguy64@gmail.com>2022-10-19 17:57:06 +0800
committerGitHub <noreply@github.com>2022-10-19 17:57:06 +0800
commite08a3d9366f8ca14a76b3dd569dac1fb9f569748 (patch)
tree33654513b0b184c27f8035dbc405640fcbeb44ab /examples
parentc4a2533d21dfd05cde841ea48c67b05e0e6a853f (diff)
parent9b2ffc6078a850b7d354855cca7622090b41f30c (diff)
downloadpsn00bsdk-e08a3d9366f8ca14a76b3dd569dac1fb9f569748.tar.gz
Merge pull request #59 from spicyjpeg/psxmdec
IRQ handler fix, .STR playback example, multiple library builds (v0.21)
Diffstat (limited to 'examples')
-rw-r--r--examples/CMakeLists.txt2
-rw-r--r--examples/README.md13
-rw-r--r--examples/beginner/cppdemo/CMakeLists.txt4
-rw-r--r--examples/beginner/hello/CMakeLists.txt4
-rw-r--r--examples/cdrom/cdbrowse/CMakeLists.txt4
-rw-r--r--examples/cdrom/cdbrowse/iso.xml1
-rw-r--r--examples/cdrom/cdxa/CMakeLists.txt4
-rw-r--r--examples/cdrom/cdxa/iso.xml1
-rw-r--r--examples/cdrom/cdxa/main.c2
-rw-r--r--examples/demos/n00bdemo/CMakeLists.txt4
-rw-r--r--examples/graphics/balls/CMakeLists.txt4
-rw-r--r--examples/graphics/billboard/CMakeLists.txt4
-rw-r--r--examples/graphics/fpscam/CMakeLists.txt4
-rw-r--r--examples/graphics/gte/CMakeLists.txt4
-rw-r--r--examples/graphics/hdtv/CMakeLists.txt4
-rw-r--r--examples/graphics/render2tex/CMakeLists.txt4
-rw-r--r--examples/graphics/rgb24/CMakeLists.txt4
-rw-r--r--examples/graphics/tilesasm/CMakeLists.txt4
-rw-r--r--examples/io/pads/CMakeLists.txt4
-rw-r--r--examples/io/pads/main.c22
-rw-r--r--examples/io/pads/spi.c6
-rw-r--r--examples/io/system573/CMakeLists.txt4
-rw-r--r--examples/io/system573/iso.xml2
-rw-r--r--examples/io/system573/main.c22
-rw-r--r--examples/lowlevel/cartrom/CMakeLists.txt10
-rw-r--r--examples/mdec/mdecimage/CMakeLists.txt4
-rw-r--r--examples/mdec/strvideo/CMakeLists.txt24
-rw-r--r--examples/mdec/strvideo/iso.xml (renamed from examples/graphics/tilesasm/iso.xml)16
-rw-r--r--examples/mdec/strvideo/main.c439
-rw-r--r--examples/mdec/strvideo/system.cnf (renamed from examples/graphics/tilesasm/system.cnf)2
-rw-r--r--examples/sound/spustream/CMakeLists.txt4
-rw-r--r--examples/sound/spustream/iso.xml1
-rw-r--r--examples/sound/spustream/main.c91
-rw-r--r--examples/sound/vagsample/CMakeLists.txt4
-rw-r--r--examples/system/childexec/CMakeLists.txt20
-rw-r--r--examples/system/childexec/child/child.c8
-rw-r--r--examples/system/childexec/parent.c27
-rw-r--r--examples/system/console/CMakeLists.txt4
-rw-r--r--examples/system/dynlink/CMakeLists.txt4
-rw-r--r--examples/system/dynlink/library/balls.c27
-rw-r--r--examples/system/dynlink/library/cube.c14
-rw-r--r--examples/system/dynlink/library/dll_common.h11
-rw-r--r--examples/system/dynlink/main.c17
-rw-r--r--examples/system/timer/CMakeLists.txt4
-rw-r--r--examples/system/tty/CMakeLists.txt4
45 files changed, 670 insertions, 196 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 15212c8..2fbc4d9 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK examples build script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
PSn00bSDK-examples
diff --git a/examples/README.md b/examples/README.md
index 82d7698..ade94b0 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -24,7 +24,8 @@ Additional information may be found in the source code of each example.
| [`io/pads`](./io/pads) | Demonstrates reading controllers via low-level access | EXE | 3 |
| [`io/system573`](./io/system573) | Konami System 573 (PS1-based arcade board) example | CD | |
| [`lowlevel/cartrom`](./lowlevel/cartrom) | ROM firmware for cheat devices written using GNU GAS | ROM | 4 |
-| [`mdec/mdecimage`](./mdec/mdecimage) | Displays a (raw) MDEC format image using libpsxpress | EXE | |
+| [`mdec/mdecimage`](./mdec/mdecimage) | Displays a (raw) MDEC format image | EXE | |
+| [`mdec/strvideo`](./mdec/strvideo) | Plays a .STR video file using the MDEC | CD | 1 |
| [`sound/spustream`](./sound/spustream) | Custom (non XA) CD-ROM audio streaming using the SPU | CD | |
| [`sound/vagsample`](./sound/vagsample) | Demonstrates playing VAG sound files using the SPU | EXE | |
| [`system/childexec`](./system/childexec) | Loading a child program and returning to parent | EXE | |
@@ -35,9 +36,9 @@ Additional information may be found in the source code of each example.
Notes:
-1. `cdrom/cdxa` does not come with an example XA audio file. In order to run
- this example you'll have to provide your own file and build the CD image
- manually.
+1. `cdrom/cdxa` and `mdec/strvideo` do not come with example files. In order
+ to run these examples you'll have to provide your own files and build the CD
+ image manually.
2. `demos/n00bdemo` suffers from flickering on real hardware, especially when
masking/stencil buffering is used.
3. `io/pads` seems to work on real hardware, but fails to automatically enable
@@ -48,7 +49,7 @@ Notes:
## Building the examples
-The instructions below assume that PSn00bSDK, CMake 3.20+ and a GCC toolchain
+The instructions below assume that PSn00bSDK, CMake 3.21+ and a GCC toolchain
are already installed. Refer to the [installation guide](../doc/installation.md)
for details.
@@ -84,4 +85,4 @@ are for rebuilding the examples *after* the SDK has been installed.
CD images for each example.
-----------------------------------------
-_Last updated on 2022-08-11 by spicyjpeg_
+_Last updated on 2022-10-16 by spicyjpeg_
diff --git a/examples/beginner/cppdemo/CMakeLists.txt b/examples/beginner/cppdemo/CMakeLists.txt
index c43d4a1..11a35ed 100644
--- a/examples/beginner/cppdemo/CMakeLists.txt
+++ b/examples/beginner/cppdemo/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
cppdemo
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.cpp)
-psn00bsdk_add_executable(cppdemo STATIC ${_sources})
+psn00bsdk_add_executable(cppdemo GPREL ${_sources})
#psn00bsdk_add_cd_image(cppdemo_iso cppdemo iso.xml DEPENDS cppdemo)
install(FILES ${PROJECT_BINARY_DIR}/cppdemo.exe TYPE BIN)
diff --git a/examples/beginner/hello/CMakeLists.txt b/examples/beginner/hello/CMakeLists.txt
index d8297c5..98ab43b 100644
--- a/examples/beginner/hello/CMakeLists.txt
+++ b/examples/beginner/hello/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
hello
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(hello STATIC ${_sources})
+psn00bsdk_add_executable(hello GPREL ${_sources})
#psn00bsdk_add_cd_image(hello_iso hello iso.xml DEPENDS hello)
install(FILES ${PROJECT_BINARY_DIR}/hello.exe TYPE BIN)
diff --git a/examples/cdrom/cdbrowse/CMakeLists.txt b/examples/cdrom/cdbrowse/CMakeLists.txt
index c2e93fc..0cc091f 100644
--- a/examples/cdrom/cdbrowse/CMakeLists.txt
+++ b/examples/cdrom/cdbrowse/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
cdbrowse
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(cdbrowse STATIC ${_sources})
+psn00bsdk_add_executable(cdbrowse GPREL ${_sources})
psn00bsdk_add_cd_image(cdbrowse_iso cdbrowse iso.xml DEPENDS cdbrowse)
psn00bsdk_target_incbin(cdbrowse PRIVATE ball16c ball16c.tim)
diff --git a/examples/cdrom/cdbrowse/iso.xml b/examples/cdrom/cdbrowse/iso.xml
index 5ffca18..771b0e9 100644
--- a/examples/cdrom/cdbrowse/iso.xml
+++ b/examples/cdrom/cdbrowse/iso.xml
@@ -17,7 +17,6 @@
<directory_tree>
<file name="SYSTEM.CNF" type="data" source="${PROJECT_SOURCE_DIR}/system.cnf" />
<file name="CDBROWSE.EXE" type="data" source="cdbrowse.exe" />
- <file name="CDBROWSE.MAP" type="data" source="cdbrowse.map" />
<dir name="DIRA">
<dir name="DIRAA">
diff --git a/examples/cdrom/cdxa/CMakeLists.txt b/examples/cdrom/cdxa/CMakeLists.txt
index 70ef77c..fd2f653 100644
--- a/examples/cdrom/cdxa/CMakeLists.txt
+++ b/examples/cdrom/cdxa/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
cdxa
@@ -13,7 +13,7 @@ project(
# TODO: add rules to actually generate a valid .XA file
file(GLOB _sources *.c)
-psn00bsdk_add_executable(cdxa STATIC ${_sources})
+psn00bsdk_add_executable(cdxa GPREL ${_sources})
#psn00bsdk_add_cd_image(cdxa_iso cdxa iso.xml DEPENDS cdxa)
psn00bsdk_target_incbin(cdxa PRIVATE ball16c ball16c.tim)
diff --git a/examples/cdrom/cdxa/iso.xml b/examples/cdrom/cdxa/iso.xml
index b98a16f..6715f94 100644
--- a/examples/cdrom/cdxa/iso.xml
+++ b/examples/cdrom/cdxa/iso.xml
@@ -17,7 +17,6 @@
<directory_tree>
<file name="SYSTEM.CNF" type="data" source="${PROJECT_SOURCE_DIR}/system.cnf" />
<file name="CDXA.EXE" type="data" source="cdxa.exe" />
- <file name="CDXA.MAP" type="data" source="cdxa.map" />
<!-- CD-XA file, you'll have to provide your own to make this example work -->
<file name="XASAMPLE.XA" type="mixed" source="${PROJECT_SOURCE_DIR}/xasample.xa"/>
diff --git a/examples/cdrom/cdxa/main.c b/examples/cdrom/cdxa/main.c
index 4921658..93cf01a 100644
--- a/examples/cdrom/cdxa/main.c
+++ b/examples/cdrom/cdxa/main.c
@@ -349,7 +349,9 @@ int main(int argc, const char* argv[])
xa_loc = file.pos;
/* Hook XA callback function to CdReadyCallback (for auto stop/loop */
+ EnterCriticalSection();
CdReadyCallback(xa_callback);
+ ExitCriticalSection();
/* Set CD mode for XA streaming (2x speed, send XA to SPU, enable filter */
i = CdlModeSpeed|CdlModeRT|CdlModeSF;
diff --git a/examples/demos/n00bdemo/CMakeLists.txt b/examples/demos/n00bdemo/CMakeLists.txt
index a54c198..f7811b0 100644
--- a/examples/demos/n00bdemo/CMakeLists.txt
+++ b/examples/demos/n00bdemo/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
n00bdemo
@@ -28,7 +28,7 @@ add_custom_command(
)
file(GLOB _sources *.s *.c)
-psn00bsdk_add_executable(n00bdemo STATIC ${_sources})
+psn00bsdk_add_executable(n00bdemo GPREL ${_sources})
#psn00bsdk_add_cd_image(n00bdemo_iso n00bdemo iso.xml DEPENDS n00bdemo)
target_include_directories(n00bdemo PRIVATE ${PROJECT_SOURCE_DIR})
diff --git a/examples/graphics/balls/CMakeLists.txt b/examples/graphics/balls/CMakeLists.txt
index deee473..03c2720 100644
--- a/examples/graphics/balls/CMakeLists.txt
+++ b/examples/graphics/balls/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
balls
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(balls STATIC ${_sources})
+psn00bsdk_add_executable(balls GPREL ${_sources})
#psn00bsdk_add_cd_image(balls_iso balls iso.xml DEPENDS balls)
psn00bsdk_target_incbin(balls PRIVATE ball16c ball16c.tim)
diff --git a/examples/graphics/billboard/CMakeLists.txt b/examples/graphics/billboard/CMakeLists.txt
index 4fc668d..5288896 100644
--- a/examples/graphics/billboard/CMakeLists.txt
+++ b/examples/graphics/billboard/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
billboard
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(billboard STATIC ${_sources})
+psn00bsdk_add_executable(billboard GPREL ${_sources})
#psn00bsdk_add_cd_image(billboard_iso billboard iso.xml DEPENDS billboard)
psn00bsdk_target_incbin(billboard PRIVATE tim_image texture64.tim)
diff --git a/examples/graphics/fpscam/CMakeLists.txt b/examples/graphics/fpscam/CMakeLists.txt
index cb0c086..2c21296 100644
--- a/examples/graphics/fpscam/CMakeLists.txt
+++ b/examples/graphics/fpscam/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
fpscam
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(fpscam STATIC ${_sources})
+psn00bsdk_add_executable(fpscam GPREL ${_sources})
#psn00bsdk_add_cd_image(fpscam_iso fpscam iso.xml DEPENDS fpscam)
install(FILES ${PROJECT_BINARY_DIR}/fpscam.exe TYPE BIN)
diff --git a/examples/graphics/gte/CMakeLists.txt b/examples/graphics/gte/CMakeLists.txt
index 90d897b..e9ab4f3 100644
--- a/examples/graphics/gte/CMakeLists.txt
+++ b/examples/graphics/gte/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
gte
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(gte STATIC ${_sources})
+psn00bsdk_add_executable(gte GPREL ${_sources})
#psn00bsdk_add_cd_image(gte_iso gte iso.xml DEPENDS gte)
psn00bsdk_target_incbin(gte PRIVATE tim_texture texture.tim)
diff --git a/examples/graphics/hdtv/CMakeLists.txt b/examples/graphics/hdtv/CMakeLists.txt
index 804b096..78411f5 100644
--- a/examples/graphics/hdtv/CMakeLists.txt
+++ b/examples/graphics/hdtv/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
hdtv
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(hdtv STATIC ${_sources})
+psn00bsdk_add_executable(hdtv GPREL ${_sources})
#psn00bsdk_add_cd_image(hdtv_iso hdtv iso.xml DEPENDS hdtv)
install(FILES ${PROJECT_BINARY_DIR}/hdtv.exe TYPE BIN)
diff --git a/examples/graphics/render2tex/CMakeLists.txt b/examples/graphics/render2tex/CMakeLists.txt
index a97cf02..1ef36e0 100644
--- a/examples/graphics/render2tex/CMakeLists.txt
+++ b/examples/graphics/render2tex/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
render2tex
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(render2tex STATIC ${_sources})
+psn00bsdk_add_executable(render2tex GPREL ${_sources})
#psn00bsdk_add_cd_image(render2tex_iso render2tex iso.xml DEPENDS render2tex)
psn00bsdk_target_incbin(render2tex PRIVATE tim_blendpattern blendpattern-16c.tim)
diff --git a/examples/graphics/rgb24/CMakeLists.txt b/examples/graphics/rgb24/CMakeLists.txt
index 9565b8b..de81db0 100644
--- a/examples/graphics/rgb24/CMakeLists.txt
+++ b/examples/graphics/rgb24/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
rgb24
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(rgb24 STATIC ${_sources})
+psn00bsdk_add_executable(rgb24 GPREL ${_sources})
#psn00bsdk_add_cd_image(rgb24_iso rgb24 iso.xml DEPENDS rgb24)
psn00bsdk_target_incbin(rgb24 PRIVATE tim_image bunpattern.tim)
diff --git a/examples/graphics/tilesasm/CMakeLists.txt b/examples/graphics/tilesasm/CMakeLists.txt
index 5b8de96..21ceafc 100644
--- a/examples/graphics/tilesasm/CMakeLists.txt
+++ b/examples/graphics/tilesasm/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
tilesasm
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.s *.c)
-psn00bsdk_add_executable(tilesasm STATIC ${_sources})
+psn00bsdk_add_executable(tilesasm GPREL ${_sources})
#psn00bsdk_add_cd_image(tilesasm_iso tilesasm iso.xml DEPENDS tilesasm)
psn00bsdk_target_incbin(tilesasm PRIVATE tim_tileset tiles_256.tim)
diff --git a/examples/io/pads/CMakeLists.txt b/examples/io/pads/CMakeLists.txt
index cf5f817..618b696 100644
--- a/examples/io/pads/CMakeLists.txt
+++ b/examples/io/pads/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
pads
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c *.s)
-psn00bsdk_add_executable(pads STATIC ${_sources})
+psn00bsdk_add_executable(pads GPREL ${_sources})
#psn00bsdk_add_cd_image(pads_iso pads iso.xml DEPENDS pads)
install(FILES ${PROJECT_BINARY_DIR}/pads.exe TYPE BIN)
diff --git a/examples/io/pads/main.c b/examples/io/pads/main.c
index 17bf331..29bb527 100644
--- a/examples/io/pads/main.c
+++ b/examples/io/pads/main.c
@@ -62,17 +62,17 @@ static const char *const PAD_TYPEIDS[] = {
#define BGCOLOR_B 0
typedef struct {
- DISPENV disp;
- DRAWENV draw;
-} DB;
+ DISPENV disp;
+ DRAWENV draw;
+} Framebuffer;
typedef struct {
- DB db[2];
- uint32_t db_active;
-} CONTEXT;
+ Framebuffer db[2];
+ int db_active;
+} RenderContext;
-void init_context(CONTEXT *ctx) {
- DB *db;
+void init_context(RenderContext *ctx) {
+ Framebuffer *db;
ResetGraph(0);
ctx->db_active = 0;
@@ -99,8 +99,8 @@ void init_context(CONTEXT *ctx) {
FntOpen(8, 16, 304, 208, 2, 512);
}
-void display(CONTEXT *ctx) {
- DB *db;
+void display(RenderContext *ctx) {
+ Framebuffer *db;
DrawSync(0);
VSync(0);
@@ -227,7 +227,7 @@ void poll_cb(uint32_t port, const volatile uint8_t *buff, size_t rx_len) {
/* Main */
-static CONTEXT ctx;
+static RenderContext ctx;
int main(int argc, const char* argv[]) {
init_context(&ctx);
diff --git a/examples/io/pads/spi.c b/examples/io/pads/spi.c
index 133782c..292e682 100644
--- a/examples/io/pads/spi.c
+++ b/examples/io/pads/spi.c
@@ -46,9 +46,9 @@ typedef struct _SPI_Context {
SPI_Callback callback;
} SPI_Context;
-static volatile SPI_Context _context;
-static volatile SPI_Request volatile *_current_req;
-static volatile SPI_Callback _default_cb;
+static volatile SPI_Context _context;
+static volatile SPI_Request *_current_req;
+static volatile SPI_Callback _default_cb;
/* Request queue management */
diff --git a/examples/io/system573/CMakeLists.txt b/examples/io/system573/CMakeLists.txt
index 2a362e8..34b0d69 100644
--- a/examples/io/system573/CMakeLists.txt
+++ b/examples/io/system573/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
system573
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c *.s)
-psn00bsdk_add_executable(system573 STATIC ${_sources})
+psn00bsdk_add_executable(system573 GPREL ${_sources})
psn00bsdk_add_cd_image(system573_iso system573 iso.xml DEPENDS system573)
install(
diff --git a/examples/io/system573/iso.xml b/examples/io/system573/iso.xml
index 0bb84d5..2226089 100644
--- a/examples/io/system573/iso.xml
+++ b/examples/io/system573/iso.xml
@@ -30,8 +30,6 @@
-->
<!--<file name="SYSTEM.CNF" type="data" source="${PROJECT_SOURCE_DIR}/system.cnf" />-->
<file name="PSX.EXE" type="data" source="system573.exe" />
- <file name="PSX.MAP" type="data" source="system573.map" />
-
<file name="QSY.DXD" type="data" source="system573.exe" />
<file name="SSW.BXF" type="data" source="system573.exe" />
<file name="TSV.AXG" type="data" source="system573.exe" />
diff --git a/examples/io/system573/main.c b/examples/io/system573/main.c
index 3404ee4..39ddb64 100644
--- a/examples/io/system573/main.c
+++ b/examples/io/system573/main.c
@@ -83,17 +83,17 @@ const char *const IO_BOARD_TYPES[] = {
#define BGCOLOR_B 0
typedef struct {
- DISPENV disp;
- DRAWENV draw;
-} DB;
+ DISPENV disp;
+ DRAWENV draw;
+} Framebuffer;
typedef struct {
- DB db[2];
- uint32_t db_active;
-} CONTEXT;
+ Framebuffer db[2];
+ int db_active;
+} RenderContext;
-void init_context(CONTEXT *ctx) {
- DB *db;
+void init_context(RenderContext *ctx) {
+ Framebuffer *db;
ResetGraph(0);
ctx->db_active = 0;
@@ -120,8 +120,8 @@ void init_context(CONTEXT *ctx) {
FntOpen(8, 16, 304, 208, 2, 512);
}
-void display(CONTEXT *ctx) {
- DB *db;
+void display(RenderContext *ctx) {
+ Framebuffer *db;
DrawSync(0);
VSync(0);
@@ -135,7 +135,7 @@ void display(CONTEXT *ctx) {
/* Main */
-static CONTEXT ctx;
+static RenderContext ctx;
#define SHOW_STATUS(...) { FntPrint(-1, __VA_ARGS__); FntFlush(-1); display(&ctx); }
#define SHOW_ERROR(...) { SHOW_STATUS(__VA_ARGS__); while (1) __asm__("nop"); }
diff --git a/examples/lowlevel/cartrom/CMakeLists.txt b/examples/lowlevel/cartrom/CMakeLists.txt
index 7d5e86e..6a94d9f 100644
--- a/examples/lowlevel/cartrom/CMakeLists.txt
+++ b/examples/lowlevel/cartrom/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
cartrom
@@ -17,9 +17,13 @@ file(GLOB _sources *.c *.s)
# executable has to be created manually and converted into raw binary format
# (for testing on emulators or flashing to a cheat cartridge).
add_executable (cartrom ${_sources})
-target_link_libraries(cartrom psn00bsdk_static_exe)
-set_target_properties(cartrom PROPERTIES PREFIX "" SUFFIX ".elf")
target_link_options (cartrom PRIVATE -T${PROJECT_SOURCE_DIR}/rom.ld)
+set_target_properties(
+ cartrom PROPERTIES
+ PREFIX ""
+ SUFFIX ".elf"
+ PSN00BSDK_TARGET_TYPE EXECUTABLE_NOGPREL
+)
target_include_directories(cartrom PRIVATE ${PROJECT_SOURCE_DIR})
diff --git a/examples/mdec/mdecimage/CMakeLists.txt b/examples/mdec/mdecimage/CMakeLists.txt
index b76adb4..b3d8ae1 100644
--- a/examples/mdec/mdecimage/CMakeLists.txt
+++ b/examples/mdec/mdecimage/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
mdecimage
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(mdecimage STATIC ${_sources})
+psn00bsdk_add_executable(mdecimage GPREL ${_sources})
#psn00bsdk_add_cd_image(mdecimage_iso mdecimage iso.xml DEPENDS mdecimage)
psn00bsdk_target_incbin(mdecimage PRIVATE mdec_image image.bin)
diff --git a/examples/mdec/strvideo/CMakeLists.txt b/examples/mdec/strvideo/CMakeLists.txt
new file mode 100644
index 0000000..d41556b
--- /dev/null
+++ b/examples/mdec/strvideo/CMakeLists.txt
@@ -0,0 +1,24 @@
+# PSn00bSDK example CMake script
+# (C) 2021 spicyjpeg - MPL licensed
+
+cmake_minimum_required(VERSION 3.21)
+
+project(
+ strvideo
+ LANGUAGES C
+ VERSION 1.0.0
+ DESCRIPTION "PSn00bSDK .STR video playback example"
+ HOMEPAGE_URL "http://lameguy64.net/?page=psn00bsdk"
+)
+
+file(GLOB _sources *.c)
+psn00bsdk_add_executable(strvideo GPREL ${_sources})
+#psn00bsdk_add_cd_image(strvideo_iso strvideo iso.xml DEPENDS strvideo)
+
+install(
+ FILES
+ #${PROJECT_BINARY_DIR}/strvideo.bin
+ #${PROJECT_BINARY_DIR}/strvideo.cue
+ ${PROJECT_BINARY_DIR}/strvideo.exe
+ TYPE BIN
+)
diff --git a/examples/graphics/tilesasm/iso.xml b/examples/mdec/strvideo/iso.xml
index 477c636..65e0ff5 100644
--- a/examples/graphics/tilesasm/iso.xml
+++ b/examples/mdec/strvideo/iso.xml
@@ -1,11 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- This file is processed by CMake and used by mkpsxiso to build the CD image.
-
- NOTE: all paths are relative to the build directory; if you want to include
- a file from the source tree, you'll have to prepend its path with
- ${PROJECT_SOURCE_DIR}.
--->
<iso_project
image_name="${CD_IMAGE_NAME}.bin"
cue_sheet="${CD_IMAGE_NAME}.cue"
@@ -13,8 +6,8 @@
<track type="data">
<identifiers
system ="PLAYSTATION"
- volume ="PSN00BSDK_TEMPLATE"
- volume_set ="PSN00BSDK_TEMPLATE"
+ volume ="STRVIDEO"
+ volume_set ="STRVIDEO"
publisher ="MEIDOTEK"
data_preparer ="PSN00BSDK ${PSN00BSDK_VERSION}"
application ="PLAYSTATION"
@@ -23,8 +16,9 @@
<directory_tree>
<file name="SYSTEM.CNF" type="data" source="${PROJECT_SOURCE_DIR}/system.cnf" />
- <file name="TEMPLATE.EXE" type="data" source="template.exe" />
- <file name="TEMPLATE.MAP" type="data" source="template.map" />
+ <file name="STRVIDEO.EXE" type="data" source="strvideo.exe" />
+
+ <file name="VIDEO.STR" type="mixed" source="${PROJECT_SOURCE_DIR}/video.str"/>
<dummy sectors="1024"/>
</directory_tree>
diff --git a/examples/mdec/strvideo/main.c b/examples/mdec/strvideo/main.c
new file mode 100644
index 0000000..842bbb8
--- /dev/null
+++ b/examples/mdec/strvideo/main.c
@@ -0,0 +1,439 @@
+/*
+ * PSn00bSDK .STR FMV playback example
+ * (C) 2022 spicyjpeg - MPL licensed
+ *
+ * This example demonstrates playback of full-motion video in the standard .STR
+ * format, using the MDEC for frame decoding and XA for audio. Decoded frames
+ * are transferred directly to the main framebuffer in this example, but could
+ * also be output to another VRAM location and used as a background or texture
+ * for a 2D or 3D scene.
+ *
+ * Playing video files requires setting up a fairly complex pipeline, involving
+ * several buffers and components working in parallel:
+ *
+ * - .STR sectors are read continuously from the CD and each frame, usually
+ * spanning multiple sectors, is reassembled (demuxed) into a buffer in
+ * memory. In this example the task is performed by cd_sector_handler(). The
+ * CD drive handles XA-ADPCM sectors automatically, so no CPU intervention is
+ * necessary to play the audio track interleaved with the video.
+ * - Once a full frame has been demuxed, the bitstream data is parsed and
+ * decompressed by the CPU (using DecDCTvlc()) to an array of run-length
+ * codes to be fed to the MDEC. This is done in the main loop.
+ * - At the same time the last frame decompressed is read from RAM by the MDEC,
+ * which decodes it and outputs one 16-pixel-wide vertical slice at a time.
+ * - When a slice is ready, it is uploaded by mdec_dma_handler() to the current
+ * framebuffer in VRAM while the MDEC is decoding the next slice.
+ * A text overlay is drawn on top of the framebuffer using the GPU after the
+ * entire frame has been decoded.
+ *
+ * Since pretty much all buffers used are going to be read and written at the
+ * same time, double buffering is required for all of them. Every part of the
+ * pipeline must also run in lockstep with each other to prevent frame
+ * corruption, hence several functions and flag variables are used to stall the
+ * main loop until a frame is available for decoding and the MDEC is ready.
+ * Playback is stopped when a sector with the end-of-file flag set in the XA
+ * subheader (added at the end of the file by most .STR encoders) is
+ * encountered; in order to access the subheader, this example requests 2340
+ * bytes of data for each sector (rather than the usual 2048) from the drive.
+ *
+ * Note that PSn00bSDK's bitstream decoding API only supports version 1 and 2
+ * bitstreams currently, so make sure your .STR files are encoded as v2 and not
+ * v3.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <psxetc.h>
+#include <psxapi.h>
+#include <psxgpu.h>
+#include <psxgte.h>
+#include <psxspu.h>
+#include <psxcd.h>
+#include <psxpress.h>
+#include <hwregs_c.h>
+
+// Uncomment to display the video in 24bpp mode. Note that the GPU does not
+// support 24bpp rendering, so the text overlay is only enabled in 16bpp mode.
+//#define DISP_24BPP
+
+/* Display/GPU context utilities */
+
+#define SCREEN_XRES 320
+#define SCREEN_YRES 240
+
+#define BGCOLOR_R 0
+#define BGCOLOR_G 0
+#define BGCOLOR_B 0
+
+typedef struct {
+ DISPENV disp;
+ DRAWENV draw;
+} Framebuffer;
+
+typedef struct {
+ Framebuffer db[2];
+ int db_active;
+} RenderContext;
+
+void init_context(RenderContext *ctx) {
+ Framebuffer *db;
+
+ ResetGraph(0);
+ ctx->db_active = 0;
+
+ db = &(ctx->db[0]);
+ SetDefDispEnv(&(db->disp), 0, 0, SCREEN_XRES, SCREEN_YRES);
+ SetDefDrawEnv(&(db->draw), 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES);
+ setRGB0(&(db->draw), BGCOLOR_R, BGCOLOR_G, BGCOLOR_B);
+ db->draw.isbg = 1;
+ db->draw.dtd = 1;
+
+ db = &(ctx->db[1]);
+ SetDefDispEnv(&(db->disp), 0, SCREEN_YRES, SCREEN_XRES, SCREEN_YRES);
+ SetDefDrawEnv(&(db->draw), 0, 0, SCREEN_XRES, SCREEN_YRES);
+ setRGB0(&(db->draw), BGCOLOR_R, BGCOLOR_G, BGCOLOR_B);
+ db->draw.isbg = 1;
+ db->draw.dtd = 1;
+
+ PutDrawEnv(&(db->draw));
+ //PutDispEnv(&(db->disp));
+
+ // Create a text stream at the top of the screen.
+ FntLoad(960, 0);
+ FntOpen(4, 12, 312, 16, 2, 256);
+}
+
+void display(RenderContext *ctx, int sync) {
+ Framebuffer *db;
+ ctx->db_active ^= 1;
+
+ DrawSync(0);
+ if (sync)
+ VSync(0);
+
+ db = &(ctx->db[ctx->db_active]);
+ PutDrawEnv(&(db->draw));
+ PutDispEnv(&(db->disp));
+ SetDispMask(1);
+}
+
+/* CD and MDEC interrupt handlers */
+
+#ifdef DISP_24BPP
+#define BLOCK_SIZE 24
+#else
+#define BLOCK_SIZE 16
+#define DRAW_OVERLAY
+#endif
+
+#define VRAM_X_COORD(x) ((x) * BLOCK_SIZE / 16)
+
+// All non-audio sectors in .STR files begin with this 32-byte header, which
+// contains metadata about the sector and is followed by a chunk of frame
+// bitstream data.
+// https://problemkaputt.de/psx-spx.htm#cdromfilevideostrstreamingandbspicturecompressionsony
+typedef struct {
+ uint16_t magic; // Always 0x0160
+ uint16_t type; // 0x8001 for MDEC
+ uint16_t sector_id; // Chunk number (0 = first chunk of this frame)
+ uint16_t sector_count; // Total number of chunks for this frame
+ uint32_t frame_id; // Frame number
+ uint32_t bs_length; // Total length of this frame in bytes
+
+ uint16_t width, height;
+ uint8_t bs_header[8];
+ uint32_t _reserved;
+} STR_Header;
+
+// https://problemkaputt.de/psx-spx.htm#cdromxasubheaderfilechannelinterleave
+typedef struct {
+ uint8_t file, channel;
+ uint8_t submode, coding_info;
+} XA_Header;
+
+// https://problemkaputt.de/psx-spx.htm#cdromsectorencoding
+typedef struct {
+ CdlLOC pos;
+ XA_Header xa_header[2];
+ STR_Header str_header;
+ uint8_t data[2016];
+ uint32_t edc;
+ uint8_t ecc[276];
+} STR_Sector;
+
+typedef struct {
+ uint16_t width, height;
+ uint32_t bs_data[0x2000]; // Bitstream data read from the disc
+ uint32_t mdec_data[0x8000]; // Decompressed data to be fed to the MDEC
+} StreamBuffer;
+
+typedef struct {
+ StreamBuffer frames[2];
+ uint32_t slices[2][BLOCK_SIZE * SCREEN_YRES / 2];
+
+ int frame_id, sector_count;
+ int dropped_frames;
+ RECT slice_pos;
+ int frame_width;
+
+ volatile int8_t sector_pending, frame_ready;
+ volatile int8_t cur_frame, cur_slice;
+} StreamContext;
+
+StreamContext str_ctx;
+
+// This buffer is used by cd_sector_handler() as a temporary area for sectors
+// read from the CD. Due to DMA limitations it can't be allocated on the stack
+// (especially not in the interrupt callbacks' stack, whose size is very
+// limited).
+STR_Sector sector_buffer;
+
+void cd_sector_handler(void) {
+ // Fetch the .STR header of the sector that has been read and check if the
+ // end-of-file bit is set in the XA header.
+ CdGetSector(&sector_buffer, sizeof(STR_Sector) / 4);
+
+ if (
+ (sector_buffer.xa_header[0].submode & (1 << 7)) ||
+ (sector_buffer.xa_header[1].submode & (1 << 7))
+ ) {
+ CdControlF(CdlPause, 0);
+ str_ctx.frame_ready = -1;
+ return;
+ }
+
+ STR_Header *header = &sector_buffer.str_header;
+ StreamBuffer *frame = &str_ctx.frames[str_ctx.cur_frame];
+
+ // Ignore any non-MDEC sectors that might be present in the stream.
+ if (header->type != 0x8001)
+ return;
+
+ // If this sector is actually part of a new frame, validate the sectors
+ // that have been read so far and flip the bitstream data buffers.
+ if (header->frame_id != str_ctx.frame_id) {
+ // Do not set the ready flag if any sector has been missed.
+ if (str_ctx.sector_count)
+ str_ctx.dropped_frames++;
+ else
+ str_ctx.frame_ready = 1;
+
+ str_ctx.frame_id = header->frame_id;
+ str_ctx.sector_count = header->sector_count;
+ str_ctx.cur_frame ^= 1;
+
+ frame = &str_ctx.frames[str_ctx.cur_frame];
+
+ // Initialize the next frame. Dimensions must be rounded up to the
+ // nearest multiple of 16 as the MDEC operates on 16x16 pixel blocks.
+ frame->width = (header->width + 15) & 0xfff0;
+ frame->height = (header->height + 15) & 0xfff0;
+ }
+
+ // Append the payload contained in this sector to the current buffer.
+ memcpy(
+ &(frame->bs_data[2016 / 4 * header->sector_id]),
+ sector_buffer.data,
+ 2016
+ );
+ str_ctx.sector_count--;
+}
+
+void mdec_dma_handler(void) {
+ // Handle any sectors that were not processed by cd_event_handler() (see
+ // below) while a DMA transfer from the MDEC was in progress. As the MDEC
+ // has just finished decoding a slice, they can be safely handled now.
+ if (str_ctx.sector_pending) {
+ cd_sector_handler();
+ str_ctx.sector_pending = 0;
+ }
+
+ // Upload the decoded slice to VRAM and start decoding the next slice (into
+ // another buffer) if any.
+ LoadImage(&str_ctx.slice_pos, str_ctx.slices[str_ctx.cur_slice]);
+
+ str_ctx.cur_slice ^= 1;
+ str_ctx.slice_pos.x += BLOCK_SIZE;
+
+ if (str_ctx.slice_pos.x < str_ctx.frame_width)
+ DecDCTout(
+ str_ctx.slices[str_ctx.cur_slice],
+ BLOCK_SIZE * str_ctx.slice_pos.h / 2
+ );
+}
+
+void cd_event_handler(int event, uint8_t *payload) {
+ // Ignore all events other than a sector being ready.
+ if (event != CdlDataReady)
+ return;
+
+ // Only handle sectors immediately if the MDEC is not decoding a frame,
+ // otherwise defer handling to mdec_dma_handler(). This is a workaround for
+ // a hardware conflict between the DMA channels used for the CD drive and
+ // MDEC output, which shall not run simultaneously.
+ if (DecDCTinSync(1))
+ str_ctx.sector_pending = 1;
+ else
+ cd_sector_handler();
+}
+
+/* Stream helpers */
+
+void init_stream(void) {
+ EnterCriticalSection();
+ DMACallback(1, &mdec_dma_handler);
+ CdReadyCallback(&cd_event_handler);
+ ExitCriticalSection();
+
+ // Set the maximum amount of data DecDCTvlc() can output and copy the
+ // lookup table used for decompression to the scratchpad area. This is
+ // optional but makes the decompressor slightly faster. See the libpsxpress
+ // documentation for more details.
+ DecDCTvlcSize(0x8000);
+ DecDCTvlcCopyTable((DECDCTTAB *) 0x1f800000);
+
+ str_ctx.dropped_frames = 0;
+ str_ctx.cur_frame = 0;
+ str_ctx.cur_slice = 0;
+}
+
+StreamBuffer *get_next_frame(void) {
+ while (!str_ctx.frame_ready)
+ __asm__ volatile("");
+
+ if (str_ctx.frame_ready < 0)
+ return 0;
+
+ str_ctx.frame_ready = 0;
+ return &str_ctx.frames[str_ctx.cur_frame ^ 1];
+}
+
+void start_stream(CdlFILE *file) {
+ str_ctx.frame_id = -1;
+ str_ctx.sector_pending = 0;
+ str_ctx.frame_ready = 0;
+
+ CdSync(0, 0);
+
+ // Configure the CD drive to read 2340-byte sectors at 2x speed and to
+ // play any XA-ADPCM sectors that might be interleaved with the video data.
+ uint8_t mode = CdlModeSize | CdlModeRT | CdlModeSpeed;
+ CdControl(CdlSetmode, (const uint8_t *) &mode, 0);
+
+ // Start reading in real-time mode (i.e. without retrying in case of read
+ // errors) and wait for the first frame to be buffered.
+ CdControl(CdlReadS, &(file->pos), 0);
+
+ get_next_frame();
+}
+
+/* Main */
+
+static RenderContext ctx;
+
+#define SHOW_STATUS(...) { FntPrint(-1, __VA_ARGS__); FntFlush(-1); display(&ctx, 1); }
+#define SHOW_ERROR(...) { SHOW_STATUS(__VA_ARGS__); while (1) __asm__("nop"); }
+
+int main(int argc, const char* argv[]) {
+ init_context(&ctx);
+
+ SHOW_STATUS("INITIALIZING\n");
+ SpuInit();
+ CdInit();
+ InitGeom(); // Required for PSn00bSDK's DecDCTvlc()
+ DecDCTReset(0);
+
+ SHOW_STATUS("OPENING VIDEO FILE\n");
+
+ CdlFILE file;
+ if (!CdSearchFile(&file, "\\VIDEO.STR"))
+ SHOW_ERROR("FAILED TO FIND VIDEO.STR\n");
+
+ init_stream();
+ start_stream(&file);
+
+ // Disable framebuffer clearing to get rid of flickering during playback.
+ display(&ctx, 1);
+ ctx.db[0].draw.isbg = 0;
+ ctx.db[1].draw.isbg = 0;
+#ifdef DISP_24BPP
+ ctx.db[0].disp.isrgb24 = 1;
+ ctx.db[1].disp.isrgb24 = 1;
+#endif
+
+ int decode_errors = 0;
+
+ while (1) {
+ // Wait for a full frame to be read from the disc and decompress the
+ // bitstream into the format expected by the MDEC. If the video has
+ // ended, restart playback from the beginning.
+ StreamBuffer *frame = get_next_frame();
+ if (!frame) {
+ start_stream(&file);
+ continue;
+ }
+
+#ifdef DRAW_OVERLAY
+ // Measure CPU usage of the decompressor using the hblank counter.
+ int total_time = TIMER_VALUE(1) + 1;
+ TIMER_VALUE(1) = 0;
+#endif
+
+ if (DecDCTvlc(frame->bs_data, frame->mdec_data)) {
+ decode_errors++;
+ continue;
+ }
+
+#ifdef DRAW_OVERLAY
+ int cpu_usage = TIMER_VALUE(1) * 100 / total_time;
+#endif
+
+ // Wait for the MDEC to finish decoding the previous frame, then flip
+ // the framebuffers to display it and prepare the buffer for the next
+ // frame.
+ // NOTE: you should *not* call VSync(0) during playback, as the refresh
+ // rate of the GPU is not synced to the video's frame rate. If you want
+ // to minimize screen tearing, consider triple buffering instead (i.e.
+ // always keep 2 fully decoded frames in VRAM and use VSyncCallback()
+ // to register a function that displays the next decoded frame whenever
+ // vblank occurs).
+ DecDCTinSync(0);
+ DecDCToutSync(0);
+
+#ifdef DRAW_OVERLAY
+ FntPrint(-1, "FRAME:%5d READ ERRORS: %5d\n", str_ctx.frame_id, str_ctx.dropped_frames);
+ FntPrint(-1, "CPU: %5d%% DECODE ERRORS:%5d\n", cpu_usage, decode_errors);
+ FntFlush(-1);
+#endif
+ display(&ctx, 0);
+
+ // Feed the newly decompressed frame to the MDEC. The MDEC will not
+ // actually start decoding it until an output buffer is also configured
+ // by calling DecDCTout() (see below).
+#ifdef DISP_24BPP
+ DecDCTin(frame->mdec_data, DECDCT_MODE_24BPP);
+#else
+ DecDCTin(frame->mdec_data, DECDCT_MODE_16BPP);
+#endif
+
+ // Place the frame at the center of the currently active framebuffer
+ // and start decoding the first slice. Decoded slices will be uploaded
+ // to VRAM in the background by mdec_dma_handler().
+ RECT *fb_clip = &(ctx.db[ctx.db_active].draw.clip);
+ int x_offset = (fb_clip->w - frame->width) / 2;
+ int y_offset = (fb_clip->h - frame->height) / 2;
+
+ str_ctx.slice_pos.x = VRAM_X_COORD(fb_clip->x + x_offset);
+ str_ctx.slice_pos.y = fb_clip->y + y_offset;
+ str_ctx.slice_pos.w = BLOCK_SIZE;
+ str_ctx.slice_pos.h = frame->height;
+ str_ctx.frame_width = VRAM_X_COORD(frame->width);
+
+ DecDCTout(
+ str_ctx.slices[str_ctx.cur_slice],
+ BLOCK_SIZE * str_ctx.slice_pos.h / 2
+ );
+ }
+
+ return 0;
+}
diff --git a/examples/graphics/tilesasm/system.cnf b/examples/mdec/strvideo/system.cnf
index e221726..d199117 100644
--- a/examples/graphics/tilesasm/system.cnf
+++ b/examples/mdec/strvideo/system.cnf
@@ -1,4 +1,4 @@
-BOOT=cdrom:\template.exe;1
+BOOT=cdrom:\strvideo.exe;1
TCB=4
EVENT=10
STACK=801FFFF0
diff --git a/examples/sound/spustream/CMakeLists.txt b/examples/sound/spustream/CMakeLists.txt
index 397796a..63d113b 100644
--- a/examples/sound/spustream/CMakeLists.txt
+++ b/examples/sound/spustream/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
spustream
@@ -13,7 +13,7 @@ project(
# TODO: add rules to actually generate a valid STREAM.BIN file
file(GLOB _sources *.c)
-psn00bsdk_add_executable(spustream STATIC ${_sources})
+psn00bsdk_add_executable(spustream GPREL ${_sources})
psn00bsdk_add_cd_image(spustream_iso spustream iso.xml DEPENDS spustream)
install(
diff --git a/examples/sound/spustream/iso.xml b/examples/sound/spustream/iso.xml
index 3807046..050d673 100644
--- a/examples/sound/spustream/iso.xml
+++ b/examples/sound/spustream/iso.xml
@@ -17,7 +17,6 @@
<directory_tree>
<file name="SYSTEM.CNF" type="data" source="${PROJECT_SOURCE_DIR}/system.cnf" />
<file name="SPUSTRM.EXE" type="data" source="spustream.exe" />
- <file name="SPUSTRM.MAP" type="data" source="spustream.map" />
<file name="STREAM.BIN" type="data" source="${PROJECT_SOURCE_DIR}/stream.bin" />
diff --git a/examples/sound/spustream/main.c b/examples/sound/spustream/main.c
index 6179179..1fee883 100644
--- a/examples/sound/spustream/main.c
+++ b/examples/sound/spustream/main.c
@@ -117,17 +117,17 @@
#define BGCOLOR_B 0
typedef struct {
- DISPENV disp;
- DRAWENV draw;
-} DB;
+ DISPENV disp;
+ DRAWENV draw;
+} Framebuffer;
typedef struct {
- DB db[2];
- int db_active;
-} CONTEXT;
+ Framebuffer db[2];
+ int db_active;
+} RenderContext;
-void init_context(CONTEXT *ctx) {
- DB *db;
+void init_context(RenderContext *ctx) {
+ Framebuffer *db;
ResetGraph(0);
ctx->db_active = 0;
@@ -154,8 +154,8 @@ void init_context(CONTEXT *ctx) {
FntOpen(8, 16, 304, 208, 2, 512);
}
-void display(CONTEXT *ctx) {
- DB *db;
+void display(RenderContext *ctx) {
+ Framebuffer *db;
DrawSync(0);
VSync(0);
@@ -181,16 +181,14 @@ void display(CONTEXT *ctx) {
#define CHUNK_SIZE (BUFFER_SIZE * NUM_CHANNELS)
typedef struct {
- uint32_t lba;
- uint32_t length;
- uint32_t pos;
+ int lba, length;
- uint32_t spu_addr;
- uint32_t spu_pos;
- uint32_t db_active;
+ volatile int pos;
+ volatile int spu_addr, spu_pos;
+ volatile int db_active;
} StreamContext;
-static volatile StreamContext str_ctx;
+static StreamContext str_ctx;
// This buffer is used by cd_event_handler() as a temporary area for sectors
// read from the CD and uploaded to SPU RAM. Due to DMA limitations it can't be
@@ -316,10 +314,10 @@ void init_stream(CdlFILE *file) {
}
void start_stream(void) {
- SPU_KEY_OFF = CHANNEL_MASK;
+ uint32_t addr = BUFFER_START_ADDR + CHUNK_SIZE * str_ctx.db_active;
for (int i = 0; i < NUM_CHANNELS; i++) {
- SPU_CH_ADDR(i) = SPU_RAM_ADDR(BUFFER_START_ADDR + BUFFER_SIZE * i);
+ SPU_CH_ADDR(i) = SPU_RAM_ADDR(addr + BUFFER_SIZE * i);
SPU_CH_FREQ(i) = SAMPLE_RATE;
SPU_CH_ADSR(i) = 0x1fee80ff;
}
@@ -336,9 +334,21 @@ void start_stream(void) {
spu_irq_handler();
}
+// This is basically a variant of reset_spu_channels() that only resets the
+// channels used to play the stream, to (again) prevent them from triggering
+// the SPU IRQ while the stream is paused.
+void stop_stream(void) {
+ SPU_KEY_OFF = CHANNEL_MASK;
+
+ for (int i = 0; i < NUM_CHANNELS; i++)
+ SPU_CH_ADDR(i) = SPU_RAM_ADDR(DUMMY_BLOCK_ADDR);
+
+ SPU_KEY_ON = CHANNEL_MASK;
+}
+
/* Main */
-static CONTEXT ctx;
+static RenderContext ctx;
#define SHOW_STATUS(...) { FntPrint(-1, __VA_ARGS__); FntFlush(-1); display(&ctx); }
#define SHOW_ERROR(...) { SHOW_STATUS(__VA_ARGS__); while (1) __asm__("nop"); }
@@ -351,7 +361,13 @@ int main(int argc, const char* argv[]) {
CdInit();
reset_spu_channels();
- SHOW_STATUS("LOCATING STREAM FILE\n");
+ // Set up controller polling.
+ uint8_t pad_buff[2][34];
+ InitPAD(pad_buff[0], 34, pad_buff[1], 34);
+ StartPAD();
+ ChangeClearPAD(0);
+
+ SHOW_STATUS("OPENING STREAM FILE\n");
CdlFILE file;
if (!CdSearchFile(&file, "\\STREAM.BIN"))
@@ -361,28 +377,27 @@ int main(int argc, const char* argv[]) {
init_stream(&file);
start_stream();
- // Set up controller polling.
- uint8_t pad_buff[2][34];
- InitPAD(pad_buff[0], 34, pad_buff[1], 34);
- StartPAD();
- ChangeClearPAD(0);
+ int paused = 0;
uint16_t sample_rate = SAMPLE_RATE;
uint16_t last_buttons = 0xffff;
while (1) {
- FntPrint(-1, "PLAYING SPU STREAM\n");
+ FntPrint(-1, "PLAYING SPU STREAM\n\n");
+
+ FntPrint(-1, "BUFFER: %d\nSTATUS: ", str_ctx.db_active);
if (str_ctx.spu_pos >= CHUNK_SIZE)
- FntPrint(-1, "STATUS: IDLE\n\n");
- else if (!str_ctx.spu_pos)
- FntPrint(-1, "STATUS: SEEKING\n\n");
+ FntPrint(-1, "IDLE\n\n");
+ else if (str_ctx.spu_pos)
+ FntPrint(-1, "BUFFERING\n\n");
else
- FntPrint(-1, "STATUS: BUFFERING\n\n");
+ FntPrint(-1, "SEEKING\n\n");
- FntPrint(-1, "POSITION=%5d/%5d\n", str_ctx.pos, str_ctx.length);
- FntPrint(-1, "BUFFERED=%5d/%5d\n", str_ctx.spu_pos, CHUNK_SIZE);
- FntPrint(-1, "SMP RATE=%5d HZ\n\n", (sample_rate * 44100) >> 12);
+ FntPrint(-1, "POSITION: %5d/%5d\n", str_ctx.pos, str_ctx.length);
+ FntPrint(-1, "BUFFERED: %5d/%5d\n", str_ctx.spu_pos, CHUNK_SIZE);
+ FntPrint(-1, "SMP RATE: %5d HZ\n\n", (sample_rate * 44100) >> 12);
+ FntPrint(-1, "[START] %s\n", paused ? "RESUME" : "PAUSE");
FntPrint(-1, "[LEFT/RIGHT] SEEK\n");
FntPrint(-1, "[O] RESET POSITION\n");
FntPrint(-1, "[UP/DOWN] CHANGE SAMPLE RATE\n");
@@ -399,6 +414,14 @@ int main(int argc, const char* argv[]) {
if ((pad->type != 4) && (pad->type != 5) && (pad->type != 7))
continue;
+ if ((last_buttons & PAD_START) && !(pad->btn & PAD_START)) {
+ paused ^= 1;
+ if (paused)
+ stop_stream();
+ else
+ start_stream();
+ }
+
// Seeking by an arbitrary number of sectors isn't a problem as
// spu_irq_handler() always realigns the counter.
if (!(pad->btn & PAD_LEFT))
diff --git a/examples/sound/vagsample/CMakeLists.txt b/examples/sound/vagsample/CMakeLists.txt
index c9849ae..7d06afd 100644
--- a/examples/sound/vagsample/CMakeLists.txt
+++ b/examples/sound/vagsample/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
vagsample
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(vagsample STATIC ${_sources})
+psn00bsdk_add_executable(vagsample GPREL ${_sources})
#psn00bsdk_add_cd_image(vagsample_iso vagsample iso.xml DEPENDS vagsample)
psn00bsdk_target_incbin(vagsample PRIVATE proyt proyt.vag)
diff --git a/examples/system/childexec/CMakeLists.txt b/examples/system/childexec/CMakeLists.txt
index 7e91589..e542d2a 100644
--- a/examples/system/childexec/CMakeLists.txt
+++ b/examples/system/childexec/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
childexec
@@ -13,14 +13,14 @@ project(
file(GLOB _sources *.c)
file(GLOB _child_sources child/*.c)
-psn00bsdk_add_executable(parent STATIC ${_sources})
-psn00bsdk_add_executable(child STATIC ${_child_sources})
-#psn00bsdk_add_cd_image(childexec_iso childexec iso.xml DEPENDS parent)
+psn00bsdk_add_executable(childexec GPREL ${_sources})
+psn00bsdk_add_executable(childexec_child GPREL ${_child_sources})
+#psn00bsdk_add_cd_image(childexec_iso childexec iso.xml DEPENDS childexec)
-psn00bsdk_target_incbin(parent PRIVATE ball16c ball16c.tim)
+psn00bsdk_target_incbin(childexec PRIVATE ball16c ball16c.tim)
psn00bsdk_target_incbin(
- parent PRIVATE child_exe
- ${PROJECT_BINARY_DIR}/child.exe
+ childexec PRIVATE child_exe
+ ${PROJECT_BINARY_DIR}/childexec_child.exe
)
# Relocate the child executable to a non-default address to prevent it from
@@ -28,9 +28,9 @@ psn00bsdk_target_incbin(
# NOTE: child executables are not position-independent and can't be relocated
# at runtime. If you need your code to be relocatable (e.g. to load it into a
# dynamically-allocated buffer), consider using a DLL instead.
-target_link_options(child PRIVATE -Ttext=0x80030000)
+target_link_options(childexec_child PRIVATE -Ttext=0x80030000)
# Make sure the child executable is built before the parent.
-add_dependencies(parent child)
+add_dependencies(childexec childexec_child)
-install(FILES ${PROJECT_BINARY_DIR}/parent.exe TYPE BIN)
+install(FILES ${PROJECT_BINARY_DIR}/childexec.exe TYPE BIN)
diff --git a/examples/system/childexec/child/child.c b/examples/system/childexec/child/child.c
index bd17440..dcfbfaf 100644
--- a/examples/system/childexec/child/child.c
+++ b/examples/system/childexec/child/child.c
@@ -98,8 +98,8 @@ MATRIX light_mtx = {
char pad_buff[2][34];
/* Function declarations */
-void init();
-void display();
+void init(void);
+void display(void);
/* Main function */
@@ -245,7 +245,7 @@ int main(int argc, const char *argv[]) {
}
-void init() {
+void init(void) {
/* Reset the GPU, also installs a VSync event handler */
ResetGraph( 0 );
@@ -300,7 +300,7 @@ void init() {
}
-void display() {
+void display(void) {
/* Wait for GPU to finish drawing and vertical retrace */
DrawSync( 0 );
diff --git a/examples/system/childexec/parent.c b/examples/system/childexec/parent.c
index 3e7d218..83d964c 100644
--- a/examples/system/childexec/parent.c
+++ b/examples/system/childexec/parent.c
@@ -67,12 +67,12 @@ extern const uint32_t ball16c[];
TIM_IMAGE tim;
-void run_child();
+void run_child(void);
char pad_buff[2][34];
-void init() {
+void init(void) {
int i;
@@ -270,10 +270,7 @@ typedef struct {
// Child program address
extern char child_exe[];
-// Manually defined as its not defined in psxapi by default
-void SetDefaultExitFromException();
-
-void run_child() {
+void run_child(void) {
// Arguments for the child program
char *args[] =
@@ -289,29 +286,23 @@ void run_child() {
// Copy child executable to its intended adddress
memcpy((void*)exe->param.t_addr, child_exe+2048, exe->param.t_size);
- // Enter critical section to prepare for program execution
- EnterCriticalSection();
+ // Prepare for program execution and disable interrupts
+ //EnterCriticalSection();
+ StopCallback();
// Stop pads, enable auto acknowledge
StopPAD();
ChangeClearPAD(1);
ChangeClearRCnt(3, 1);
-
- // Set default exception handler just in case
- //SetDefaultExitFromException();
-
- // Last three function calls could be relegated to
- // a StopCallback() function in the future.
-
+
// Execute child
printf("Child exec!\n");
Exec(&exe->param, 3, args);
// Restore interrupts for this PS-EXE
- EnterCriticalSection();
RestartCallback();
- ExitCriticalSection();
-
+ //ExitCriticalSection();
+
// Re-init and re-enable pads
InitPAD(pad_buff[0], 34, pad_buff[1], 34);
StartPAD();
diff --git a/examples/system/console/CMakeLists.txt b/examples/system/console/CMakeLists.txt
index eeb8e62..c6fa573 100644
--- a/examples/system/console/CMakeLists.txt
+++ b/examples/system/console/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
console
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(console STATIC ${_sources})
+psn00bsdk_add_executable(console GPREL ${_sources})
#psn00bsdk_add_cd_image(console_iso console iso.xml DEPENDS console)
psn00bsdk_target_incbin(console PRIVATE ball16c ball16c.tim)
diff --git a/examples/system/dynlink/CMakeLists.txt b/examples/system/dynlink/CMakeLists.txt
index f5f4ea8..e750fd1 100644
--- a/examples/system/dynlink/CMakeLists.txt
+++ b/examples/system/dynlink/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
dynlink
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(dynlink_main DYNAMIC ${_sources})
+psn00bsdk_add_executable(dynlink_main NOGPREL ${_sources})
psn00bsdk_add_library (dynlink_cube SHARED library/cube.c)
psn00bsdk_add_library (dynlink_balls SHARED library/balls.c)
psn00bsdk_add_cd_image(
diff --git a/examples/system/dynlink/library/balls.c b/examples/system/dynlink/library/balls.c
index c537167..457ec4e 100644
--- a/examples/system/dynlink/library/balls.c
+++ b/examples/system/dynlink/library/balls.c
@@ -21,7 +21,7 @@ typedef struct {
int16_t x, y;
int16_t xdir, ydir;
uint8_t r, g, b, p;
-} BALL_TYPE;
+} Ball;
#define MAX_BALLS 512
@@ -35,12 +35,13 @@ typedef struct {
// initialize variables or hardware.
static uint32_t frame = 0;
-static BALL_TYPE balls[MAX_BALLS];
+static Ball balls[MAX_BALLS];
static TIM_IMAGE ball_tim;
-void init(CONTEXT *ctx) {
- GetTimInfo(ball16c, &ball_tim);
+void init(RenderContext *ctx) {
+ Framebuffer *db = &(ctx->db[ctx->db_active]);
+ GetTimInfo(ball16c, &ball_tim);
LoadImage(ball_tim.prect, ball_tim.paddr);
if (ball_tim.mode & 8)
LoadImage(ball_tim.crect, ball_tim.caddr);
@@ -48,10 +49,10 @@ void init(CONTEXT *ctx) {
// Initialize the balls by giving them a random initial position, velocity
// and color.
for (uint32_t i = 0; i < MAX_BALLS; i++) {
- BALL_TYPE *b = &(balls[i]);
+ Ball *b = &(balls[i]);
- b->x = rand() % (ctx->xres - 16);
- b->y = rand() % (ctx->yres - 16);
+ b->x = rand() % (db->draw.clip.w - 16);
+ b->y = rand() % (db->draw.clip.h - 16);
b->xdir = ((rand() & 1) ? 1 : -1) * ((rand() % 3) + 1);
b->ydir = ((rand() & 1) ? 1 : -1) * ((rand() % 3) + 1);
b->r = rand() & 0xff;
@@ -60,12 +61,12 @@ void init(CONTEXT *ctx) {
}
}
-void render(CONTEXT *ctx, uint16_t buttons) {
- DB *db = &(ctx->db[ctx->db_active]);
- SPRT_16 *sprt = (SPRT_16 *) ctx->db_nextpri;
+void render(RenderContext *ctx, uint16_t buttons) {
+ Framebuffer *db = &(ctx->db[ctx->db_active]);
+ SPRT_16 *sprt = (SPRT_16 *) ctx->db_nextpri;
for (uint32_t i = 0; i < MAX_BALLS; i++) {
- BALL_TYPE *b = &(balls[i]);
+ Ball *b = &(balls[i]);
setSprt16(sprt);
@@ -85,12 +86,12 @@ void render(CONTEXT *ctx, uint16_t buttons) {
if (
(b->x < 0) ||
- ((b->x + 16) > ctx->xres)
+ ((b->x + 16) > db->draw.clip.w)
)
b->xdir *= -1;
if (
(b->y < 0) ||
- ((b->y + 16) > ctx->yres)
+ ((b->y + 16) > db->draw.clip.h)
)
b->ydir *= -1;
}
diff --git a/examples/system/dynlink/library/cube.c b/examples/system/dynlink/library/cube.c
index 84fe552..22a805f 100644
--- a/examples/system/dynlink/library/cube.c
+++ b/examples/system/dynlink/library/cube.c
@@ -81,16 +81,18 @@ static SVECTOR rot = { 0 };
static VECTOR pos = { 0, 0, 400 };
static MATRIX mtx, lmtx;
-void init(CONTEXT *ctx) {
+void init(RenderContext *ctx) {
+ Framebuffer *db = &(ctx->db[ctx->db_active]);
+
InitGeom();
- gte_SetGeomOffset(ctx->xres / 2, ctx->yres / 2);
- gte_SetGeomScreen(ctx->xres / 2);
+ gte_SetGeomOffset(db->draw.clip.w / 2, db->draw.clip.h / 2);
+ gte_SetGeomScreen(db->draw.clip.w / 2);
gte_SetBackColor(63, 63, 63);
gte_SetColorMatrix(&color_mtx);
}
-void render(CONTEXT *ctx, uint16_t buttons) {
+void render(RenderContext *ctx, uint16_t buttons) {
RotMatrix(&rot, &mtx);
TransMatrix(&mtx, &pos);
MulMatrix0(&light_mtx, &mtx, &lmtx);
@@ -104,8 +106,8 @@ void render(CONTEXT *ctx, uint16_t buttons) {
rot.vx += step;
rot.vz += step;
- DB *db = &(ctx->db[ctx->db_active]);
- POLY_F4 *pol4 = (POLY_F4 *) ctx->db_nextpri;
+ Framebuffer *db = &(ctx->db[ctx->db_active]);
+ POLY_F4 *pol4 = (POLY_F4 *) ctx->db_nextpri;
for (uint32_t i = 0; i < CUBE_FACES; i++) {
int32_t p;
diff --git a/examples/system/dynlink/library/dll_common.h b/examples/system/dynlink/library/dll_common.h
index 315a993..6606bda 100644
--- a/examples/system/dynlink/library/dll_common.h
+++ b/examples/system/dynlink/library/dll_common.h
@@ -19,13 +19,12 @@ typedef struct {
DRAWENV draw;
uint32_t ot[OT_LEN];
uint8_t p[PACKET_LEN];
-} DB;
+} Framebuffer;
typedef struct {
- uint16_t xres, yres;
- DB db[2];
- uint32_t db_active;
- uint8_t *db_nextpri;
-} CONTEXT;
+ Framebuffer db[2];
+ int db_active;
+ uint8_t *db_nextpri;
+} RenderContext;
#endif
diff --git a/examples/system/dynlink/main.c b/examples/system/dynlink/main.c
index fff7aa5..fcce5b1 100644
--- a/examples/system/dynlink/main.c
+++ b/examples/system/dynlink/main.c
@@ -83,12 +83,10 @@ static const char *const DLL_FILENAMES[] = {
#define BGCOLOR_G 24
#define BGCOLOR_B 0
-void init_context(CONTEXT *ctx) {
- DB *db;
+void init_context(RenderContext *ctx) {
+ Framebuffer *db;
ResetGraph(0);
- ctx->xres = SCREEN_XRES;
- ctx->yres = SCREEN_YRES;
ctx->db_active = 0;
db = &(ctx->db[0]);
@@ -121,8 +119,8 @@ void init_context(CONTEXT *ctx) {
FntOpen(4, 12, 312, 32, 2, 256);
}
-void display(CONTEXT *ctx) {
- DB *db;
+void display(RenderContext *ctx) {
+ Framebuffer *db;
DrawSync(0);
VSync(0);
@@ -185,13 +183,14 @@ void *custom_resolver(DLL *dll, const char *name) {
// and the pointers returned by DL_GetDLLSymbol() should be saved and reused as
// much as possible.
typedef struct {
- void (*init)(CONTEXT *);
- void (*render)(CONTEXT *, uint16_t buttons);
+ void (*init)(RenderContext *);
+ void (*render)(RenderContext *, uint16_t buttons);
} DLL_API;
static DLL *dll = 0;
static DLL_API dll_api;
-static CONTEXT ctx;
+
+static RenderContext ctx;
/* Main */
diff --git a/examples/system/timer/CMakeLists.txt b/examples/system/timer/CMakeLists.txt
index 328e07e..30efbf3 100644
--- a/examples/system/timer/CMakeLists.txt
+++ b/examples/system/timer/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
timer
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(timer STATIC ${_sources})
+psn00bsdk_add_executable(timer GPREL ${_sources})
#psn00bsdk_add_cd_image(timer_iso timer iso.xml DEPENDS timer)
install(FILES ${PROJECT_BINARY_DIR}/timer.exe TYPE BIN)
diff --git a/examples/system/tty/CMakeLists.txt b/examples/system/tty/CMakeLists.txt
index 0664502..75ce689 100644
--- a/examples/system/tty/CMakeLists.txt
+++ b/examples/system/tty/CMakeLists.txt
@@ -1,7 +1,7 @@
# PSn00bSDK example CMake script
# (C) 2021 spicyjpeg - MPL licensed
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.21)
project(
tty
@@ -12,7 +12,7 @@ project(
)
file(GLOB _sources *.c)
-psn00bsdk_add_executable(tty STATIC ${_sources})
+psn00bsdk_add_executable(tty GPREL ${_sources})
#psn00bsdk_add_cd_image(tty_iso tty iso.xml DEPENDS tty)
install(FILES ${PROJECT_BINARY_DIR}/tty.exe TYPE BIN)