aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorspicyjpeg <88942473+spicyjpeg@users.noreply.github.com>2022-01-17 17:55:09 +0100
committerspicyjpeg <88942473+spicyjpeg@users.noreply.github.com>2022-01-17 17:55:09 +0100
commite9475e283a82665fe6c19bebc3318b5084f15a2e (patch)
tree5740f396d10a9580c3a39ca536544436898ff1b6
parentde38196a978548b61c4b45115d24ef743b9eef90 (diff)
parent08de895e8582dbc70b639ae5f511ab9ebfb4d68a (diff)
downloadpsn00bsdk-e9475e283a82665fe6c19bebc3318b5084f15a2e.tar.gz
Merge branch 'master' of github.com:Lameguy64/PSn00bSDK into latest-commit
-rw-r--r--CHANGELOG.md20
-rw-r--r--README.md68
-rw-r--r--doc/LibPSn00b Reference.odtbin150699 -> 152872 bytes
-rw-r--r--doc/libn00bref.odtbin36114 -> 0 bytes
-rw-r--r--examples/README.md82
-rw-r--r--examples/graphics/hdtv/main.c64
-rw-r--r--examples/graphics/tilesasm/CMakeLists.txt24
-rw-r--r--examples/graphics/tilesasm/data.s.template34
-rw-r--r--examples/graphics/tilesasm/drawtiles.s272
-rw-r--r--examples/graphics/tilesasm/iso.xml34
-rw-r--r--examples/graphics/tilesasm/main.c425
-rw-r--r--examples/graphics/tilesasm/system.cnf4
-rw-r--r--examples/graphics/tilesasm/tiles_256.pngbin0 -> 9362 bytes
-rw-r--r--examples/graphics/tilesasm/tiles_256.timbin0 -> 66080 bytes
-rw-r--r--examples/io/pads/main.c2
-rw-r--r--examples/io/pads/spi.c50
-rw-r--r--examples/io/pads/spi.h25
-rw-r--r--examples/io/system573/main.c30
-rw-r--r--examples/sound/spustream/main.c8
19 files changed, 1025 insertions, 117 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea4f4d2..0203265 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -19,6 +19,26 @@ to ensure the changelog can be parsed correctly.
-------------------------------------------------------------------------------
+## 2022-01-17
+
+Lameguy64:
+
+- docs: Removed old and incomplete `libn00bref.odt` document (a percussor of
+ the LibPSn00b Library Reference document) as it got included into a commit by
+ accident at some point.
+
+- examples: Improved description of `hdtv` example. Examples directory is now
+ copied into `share/psn00bsdk` directory for both installation and package
+ building. Build instructions for examples also included.
+
+- docs: Removed documentation for `SetDrawTPageVal()` as the function was
+ removed ages ago. Added documentation to `DR_AREA`, `DR_TWIN` and `DR_OFFSET`
+ primitives and their associated macros.
+
+- examples: Added `tilesasm` example.
+
+- Updated readme file.
+
## 2021-12-23
spicyjpeg:
diff --git a/README.md b/README.md
index 13ab7d1..f3fa7f5 100644
--- a/README.md
+++ b/README.md
@@ -2,28 +2,32 @@
# PSn00bSDK
PSn00bSDK is a 100% free and open source SDK project for the original Sony
-PlayStation for developing homebrew applications and games for the console
-100% freely. This SDK can be used for freeware, commercial, and open source
-homebrew projects.
-
-The SDK is composed mainly of libraries (`libpsn00b`) and some utilities that
-provide a basic framework for developing software for the PlayStation hardware,
-the compiler is separate (GCC) and should be acquired from GNU. The library API
-is intentionally written to resemble the library API of the official libraries
-as closely as possible. This design decision is not only for familiarity
-reasons to experienced programmers, but also so that existing sample code and
-tutorials would still apply to this SDK, as well as making the process of
-porting over existing homebrew originally made with official SDKs easier with
-minimal modification, provided it doesn't use `libgs`.
+PlayStation for developing homebrew applications and games for the console.
+This SDK may be used for freeware, commercial, and open source homebrew
+projects as far as what the SDK currently supports. Out of all the open
+source PS1 SDK projects that have come and gone from active development
+over the years, PSn00bSDK is arguably the most capable of them all.
+
+Much of the SDK is merely just a set of libraries (`libpsn00b`) and some
+utilities for converting executables and data files to formats more usable
+on the target platform. The compiler used is just the standard GNU GCC
+toolchain compiled to target mipsel and has to be acquired separately.
+The library API was deliberately written to resemble the library API of the
+official libraries as closely as possible not only for familiarity reasons
+to experienced programmers but also so that existing sample code and tutorials
+that have been written over the years would still apply to this SDK, as well
+as making the process of porting over existing homebrew originally made with
+official SDKs easier with minimal modificationn provided they do not depend
+on libgs.
PSn00bSDK is currently a work in progress and cannot really be considered
-production ready, but what is currently implemented should be enough to produce
-some interesting homebrew with the SDK, especially with its extensive support
-for the GPU and GTE hardware. There's no reason not to fully support hardware
-features of a target platform when said hardware features have been fully
-documented for years (nocash's PSX specs document in this case).
+production ready, but what is currently implemented should be enough to
+produce some interesting homebrew with the SDK especially with its extensive
+support for the GPU and GTE hardware. There's no reason not to fully support
+hardware features of a target platform when said hardware features have been
+fully documented for years (nocash's PSX specs document in this case).
-Most of `libpsn00b` is written mostly in MIPS assembly, moreso functions that
+Most of `libpsn00b` is written mostly in MIPS assembly more so functions that
interface with the hardware. Many of the standard C functions are implemented
in custom MIPS assembly instead of equivalents found in the BIOS ROM, for both
stability (the BIOS `libc` implementation of the PlayStation is actually buggy)
@@ -86,6 +90,7 @@ Prebuilt SDK packages and versions of the GCC toolchain for Windows and Linux
been published however, due to this project being in a work-in-progress state.
It is still recommended to build the SDK from source for the time being.
+
## Examples
There are a few examples and complete source code of `n00bdemo` included in the
@@ -116,27 +121,16 @@ apply to PSn00bSDK.
* Pad and memory card libraries that don't use the BIOS routines.
-## Usage terms (or lack thereof)
-
-PSn00bSDK falls under the terms and conditions of the Mozilla Public License. A
-quick summary of this license is that PSn00bSDK can be used freely in both free
-and open source projects and commercial closed source projects as projects
-using PSn00bSDK does not necessarily have to follow the MPL as well.
-
-If modifications to the SDK were made as part of the development of such
-projects that enhance its functionality, such changes must be contributed back
-in return.
+## Credits
-Homebrew made with PSn00bSDK may not be released under 'annoyingmous'. Although
-there's nothing that would enforce it, this term may as well be ignored despite
-it annoying this SDK's author.
+Main developer/author/whatever:
-## Credits
+* **Lameguy64** (John "Lameguy" Wilbert Villamor)
-Main developers:
+Contributors:
-* **Lameguy64**
* **spicyjpeg**: dynamic linker, CMake scripts, some docs and examples
+ (`system/dynlink`, `sound/spustream`, `io/pads`, `io/system573`).
Honorable mentions:
@@ -149,4 +143,8 @@ Helpful contributors can be found in the changelog.
References used:
* [nocash's PlayStation specs document](http://problemkaputt.de/psx-spx.htm)
+ and Nicolas Noble's [updated version](https://psx-spx.consoledev.net).
+* MIPS and System V ABI specs (for the dynamic linker).
* Tails92's PSXSDK project (during PSn00bSDK's infancy).
+
+Additional references can be found in individual source files.
diff --git a/doc/LibPSn00b Reference.odt b/doc/LibPSn00b Reference.odt
index b7fa52c..c997d2a 100644
--- a/doc/LibPSn00b Reference.odt
+++ b/doc/LibPSn00b Reference.odt
Binary files differ
diff --git a/doc/libn00bref.odt b/doc/libn00bref.odt
deleted file mode 100644
index 99de092..0000000
--- a/doc/libn00bref.odt
+++ /dev/null
Binary files differ
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..dfea465
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,82 @@
+
+# PSn00bSDK Example Programs
+
+## Examples summary
+
+The following list is a brief summary of all the example programs included.
+Additional information may be found in the source code of each example.
+
+| Path | Description | Type | Notes |
+| :--------------------------------------------- | :---------------------------------------------------- | :--: | :---: |
+| [`beginner/cppdemo`](./beginner/cppdemo) | Simple demonstration of (dynamic) C++ classes | EXE | |
+| [`beginner/hello`](./beginner/hello) | The obligatory "Hello World" example program | EXE | |
+| [`cdrom/cdbrowse`](./cdrom/cdbrowse) | File browser using libpsxcd's directory functions | CD | |
+| [`cdrom/cdxa`](./cdrom/cdxa) | CD-XA ADPCM audio player | CD | 1 |
+| [`demos/n00bdemo`](./demos/n00bdemo) | The premiere demonstration program of PSn00bSDK | EXE | |
+| [`graphics/balls`](./graphics/balls) | Draws colored balls bouncing around the screen | EXE | |
+| [`graphics/billboard`](./graphics/billboard) | Demonstrates how to draw 2D sprites in a 3D space | EXE | |
+| [`graphics/fpscam`](./graphics/fpscam) | First-person perspective camera with look-at | EXE | |
+| [`graphics/gte`](./graphics/gte) | Displays a rotating cube using GTE macros | EXE | |
+| [`graphics/hdtv`](./graphics/hdtv) | Demonstrates anamorphic widescreen at 704x480 | EXE | |
+| [`graphics/render2tex`](./graphics/render2tex) | Procedural texture effects using off-screen drawing | EXE | |
+| [`graphics/rgb24`](./graphics/rgb24) | Displays a 640x480 24-bit RGB image | EXE | |
+| [`graphics/tilesasm`](./graphics/tilesasm) | Drawing a tile-map with assembly language | EXE | |
+| [`io/pads`](./io/pads) | Demonstrates reading controllers via low-level access | EXE | |
+| [`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 | 2 |
+| [`sound/spustream`](./sound/spustream) | Custom (non XA) CD-ROM audio streaming using the SPU | CD | 1 |
+| [`sound/vagsample`](./sound/vagsample) | Demonstrates playing VAG sound files with the SPU | EXE | |
+| [`system/childexec`](./system/childexec) | Loading a child program and returning to parent | EXE | |
+| [`system/console`](./system/console) | TTY based text console that interrupts gameplay | EXE | |
+| [`system/dynlink`](./system/dynlink) | Demonstrates dynamically linked libraries | CD | |
+| [`system/timer`](./system/timer) | Demonstrates using hardware timers with interrupts | EXE | |
+| [`system/tty`](./system/tty) | Using TTY as a remote text console interface | EXE | |
+
+Notes:
+
+1. `cdrom/cdxa` and `sound/spustream` do not come with example audio files. In
+ order to run these examples you'll have to provide your own files (and, in
+ the case of `spustream`, convert them using the included Python script) and
+ build the CD image manually.
+2. The `lowlevel/cartrom` example is outdated and does not use SDK libraries.
+ It is kept for reference purposes only.
+
+## Building the examples
+
+The instructions below assume that PSn00bSDK, CMake 3.20+ and a GCC toolchain
+are already installed. Refer to the [installation guide](../doc/installation.md)
+for details.
+
+**NOTE**: all examples are compiled by default when building the PSn00bSDK
+libraries and tools (check the `build/examples` directory). These instructions
+are for rebuilding the examples *after* the SDK has been installed.
+
+1. Copy the contents of this directory (`share/psn00bsdk/examples` within the
+ PSn00bSDK installation directory) to your home directory or to another
+ folder you have write access to.
+
+2. Configure and build the examples by running:
+
+ ```bash
+ cmake -S . -B ./build -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=<INSTALL_PATH>/lib/libpsn00b/cmake/sdk.cmake
+ cmake --build ./build
+ ```
+
+ Replace `<INSTALL_PATH>` with the installation prefix you chose when
+ installing the SDK (usually `C:\Program Files\PSn00bSDK` or `/usr/local`,
+ so the full path to `sdk.cmake` would be
+ `C:\Program Files\PSn00bSDK\lib\libpsn00b\cmake\sdk.cmake` or
+ `/usr/local/lib/libpsn00b/cmake/sdk.cmake` respectively).
+
+ Add `-DPSN00BSDK_TARGET=mipsel-unknown-elf` to the first command if your
+ toolchain targets `mipsel-unknown-elf` rather than `mipsel-none-elf`. If you
+ can't get Ninja to work or don't have it installed, you can also replace
+ `-G "Ninja"` with `-G "Unix Makefiles"` (`-G "MSYS Makefiles"` on Windows)
+ to build using `make` instead.
+
+ This should create a `build` directory whose structure mirrors the one of
+ the parent directory, with each subfolder containing built executables and
+ CD images for each example.
+
+-----------------------------------------
+_Last updated on 2022-01-17 by spicyjpeg_
diff --git a/examples/graphics/hdtv/main.c b/examples/graphics/hdtv/main.c
index a4dcd79..827b096 100644
--- a/examples/graphics/hdtv/main.c
+++ b/examples/graphics/hdtv/main.c
@@ -4,33 +4,45 @@
* Full-resolution, Anamorphic Widescreen 3D Example
* 2020 - 2021 Meido-Tek Productions / PSn00bSDK Project
*
- * This example is a modification of the fpscam example demonstrating
- * a method for taking advantage of widescreen HDTVs by means of a
- * custom 704x480 video mode (as opposed to 640x480) and applying
- * anamorphic widescreen aspect correction to a 3D perspective.
+ * This example is a modification of the fpscam example incorporating
+ * techniques for taking advantage of wide-screen televisions by means
+ * of a custom 704x480 video mode (as opposed to 640x480) and applying
+ * anamorphic aspect correction to a 3D perspective matrix.
*
- * The extended horizontal resolution guarantees that the picture will
- * fill the entire screen of a widescreen television as the more
- * conventional 640x480 mode would often show a black border on the sides
- * of the picture. However, this extended video mode may cause odd effects
- * on some analog television displays, so its recommended to implement this
- * extended video mode as an option in your software title. Pixels are still
- * not aspect correct however, so widescreen has to be achieved through
- * anamorphic means, and is not exactly practical for most 2D graphics.
+ * The extended horizontal resolution guarantees that the video display
+ * will fill a wide-screen television in 16:9 mode fully, whereas the more
+ * conventional 640x480 mode displays black borders on the sides of the
+ * picture on most wide-screen television sets- notably LCD and Plasma type
+ * television sets.
*
- * If you wish to use a lower resolution 240/256 line mode but want to make
- * it presentable on a widescreen television, use 384x240 or 384x256 as
- * such a resolution would not only fill the entire screen of a widescreen
- * but it also has close to aspect correct pixels, which is well suited for
- * 2D games. The anamorphic aspect correction demonstrated in this example
- * should also work for 320x240/256 modes for 3D games, but prefer to use
- * 320x240 resolution.
+ * However, this extended video mode may cause display problems on some
+ * analog television sets- such as conventional ratio Sony Trinitron
+ * televisions if the video display is moved too close to the left of the
+ * screen. Therefore it is recommended to support this extended video mode
+ * as an option to ensure compatibility with affected televisions.
*
- * When using 240/256 line modes, you may want to include an option in your
- * software title to enable interlace even though your software title does not
- * run in high resolution mode. This helps with compatibility on HDTVs
- * immensely and in some cases, improves the image quality on such
- * televisions.
+ * Use of the extended video mode does not provide aspect correct pixels
+ * for widescreen displays (the extended mode merely displays more columns
+ * of pixels to fill the side borders of widescreen displays), thus 2D
+ * bitmap graphics will appear stretched as it would when using a more
+ * conventional 640x480 display resolution on a wide-screen ratio
+ * television.
+ *
+ * If lower resolution 240/256 line mode is desired whilst being presentable
+ * on a wide-screen television display, use 384x240 or 384x256 as those
+ * display resolutions can not only cover the side borders of a wide-screen
+ * television display but it also provides close to aspect correct pixels
+ * on such television sets and is well suited for 2D games. The anamorphic
+ * aspect correction demonstrated in this example can also work on the more
+ * conventional 320x240/256 modes for 3D games when such resolutions are more
+ * desired.
+ *
+ * When 240/256 line video modes are used, it is highly recommended to
+ * consider implementing an option to enable interlace even if the software
+ * title does not run in high resolution mode. This is to provide
+ * compatibility with digital EDTV or HDTV televisions as some of these
+ * televisions have issues accepting non-interlaced video signals. On some
+ * televisions enabling interlace can improve the picture quality.
*
* Controls:
* Up - Look up
@@ -43,7 +55,7 @@
* Circle - Strafe right
* R1 - Slide up
* R2 - Slide down
- * L1 - Look at cube
+ * L1 - Look at cube (tracking)
* Select - Exit program (only works with CD loaders)
*
*
@@ -51,6 +63,8 @@
*
* Changelog:
*
+ * November 23, 2021 - Improved example description.
+ *
* May 10, 2021 - Variable types updated for psxgpu.h changes.
*
* November 27, 2020 - Initial version.
diff --git a/examples/graphics/tilesasm/CMakeLists.txt b/examples/graphics/tilesasm/CMakeLists.txt
new file mode 100644
index 0000000..3384875
--- /dev/null
+++ b/examples/graphics/tilesasm/CMakeLists.txt
@@ -0,0 +1,24 @@
+# PSn00bSDK example CMake script
+# (C) 2021 spicyjpeg - MPL licensed
+
+cmake_minimum_required(VERSION 3.20)
+
+project(
+ tilesasm
+ LANGUAGES C ASM
+ VERSION 1.0.0
+ DESCRIPTION "PSn00bSDK Tiles drawing with assembly example"
+ HOMEPAGE_URL "http://lameguy64.net/?page=psn00bsdk"
+)
+
+configure_file(data.s.template data.s)
+
+file(GLOB _sources *.s *.c)
+psn00bsdk_add_executable(
+ tilesasm STATIC
+ ${_sources}
+ ${PROJECT_BINARY_DIR}/data.s
+)
+#psn00bsdk_add_cd_image(tilesasm_iso tilesasm iso.xml DEPENDS tilesasm)
+
+install(FILES ${PROJECT_BINARY_DIR}/tilesasm.exe TYPE BIN)
diff --git a/examples/graphics/tilesasm/data.s.template b/examples/graphics/tilesasm/data.s.template
new file mode 100644
index 0000000..1c4b01e
--- /dev/null
+++ b/examples/graphics/tilesasm/data.s.template
@@ -0,0 +1,34 @@
+#
+# LibPSn00b Example Programs
+#
+# Drawing Tile-maps with Assembler Routines
+# 2022 Meido-Tek Productions / PSn00bSDK Project
+#
+# Example by John "Lameguy" Wilbert Villamor (Lameguy64)
+#
+# This assembler file is used to include the file tiles.tim as an array named
+# 'tim_tileset' for use in this example program. Note how the variable name
+# itself is leading with an underscore (_) in this file. This is because
+# GNU C requires leading underscores for global variables, perhaps to prevent
+# function names and variable names from mixing up during the linking stage.
+
+# Tell assembler that the contents that follow must be in the .data section
+.section .data
+
+# This directive define the 'tim_tileset' label as a global symbol so that
+# main.c and other program modules can see this symbol during linking
+.global tim_tileset
+
+# This directive is not really required, but its best to define symbols
+# not pointing to program code as an object to help identify it as a
+# variable in debuggers
+.type tim_tileset, @object
+
+# The following line defines the variable 'tim_tileset' itself filled with the
+# contents of the file 'tiles.tim' by using the .incbin directive
+#
+# Remember the variable type of a symbol is always governed by how it is
+# declared in the C code
+#
+tim_tileset:
+ .incbin "${PROJECT_SOURCE_DIR}/tiles_256.tim"
diff --git a/examples/graphics/tilesasm/drawtiles.s b/examples/graphics/tilesasm/drawtiles.s
new file mode 100644
index 0000000..15a0707
--- /dev/null
+++ b/examples/graphics/tilesasm/drawtiles.s
@@ -0,0 +1,272 @@
+#
+# LibPSn00b Example Programs
+#
+# Drawing Tile-maps with Assembler Routines
+# 2022 Meido-Tek Productions / PSn00bSDK Project
+#
+# Example by John "Lameguy" Wilbert Villamor (Lameguy64)
+#
+# This file contains the assembler routine DrawTiles which can be called from
+# a C or C++ compiled module. The routine makes use of constants and assembler
+# macros written in the GNU GAS syntax.
+#
+# Assembler routines called from C-language modules can freely use registers
+# $v0-$v1, $at, $a0-$a3, $t0-$t9 without preserving through stack. Registers
+# $s0-$s9, $gp and $fp must be preserved through stack before returning and
+# registers $k0-$k1 should not be used for obvious reasons (kernel registers).
+# $sp and $ra is used as stack pointer and return address respectively.
+# $0 or $zero is constantly zero.
+#
+# A C caller always passes arguments as 32-bit values on registers $a0 to $a3
+# regardless of the data type specified in the function's C declaration.
+# Additional arguments are stored in the stack 16 bytes relative to the stack
+# pointer ($sp). To get around the stack being modified in different parts of
+# a larger routine the stack pointer would be copied to the frame pointer ($fp)
+# and the previous value of the frame pointer would be pushed into stack. This
+# way additional arguments may be read anywhere starting from $fp+20 instead.
+#
+.set noreorder # Disable GAS' annoying nop insertion
+
+.equ db, 1 # Constants for "emulating" SNASM style structs
+.equ dh, 2
+.equ dw, 4
+
+#
+# TILEDEF struct
+#
+ rs=0 # rs is used to emulate SNASM style structs
+.equ TILEDEF_uv , rs # Tile texture coordinate
+ rs=rs+dh
+.equ TILEDEF_clut , rs # Tile CLUT
+ rs=rs+dh
+.equ TILEDEF_pad , rs # Padding
+ rs=rs+dh
+.equ TILEDEF_tpage , rs # Tile tpage
+ rs=rs+dh
+.equ TILEDEF_len , rs # Entry length
+
+#
+# TILEINFO struct (to use as offsets)
+#
+ rs=0
+.equ TILEINFO_window_x , rs # \
+ rs=rs+dh # - Window coordinates
+.equ TILEINFO_window_y , rs # /
+ rs=rs+dh
+.equ TILEINFO_window_w , rs # \
+ rs=rs+dh # - Window size
+.equ TILEINFO_window_h , rs # /
+ rs=rs+dh
+.equ TILEINFO_tiles , rs # Pointer to TILEDEF entries
+ rs=rs+dw
+.equ TILEINFO_mapdata , rs # Pointer to map data
+ rs=rs+dw
+.equ TILEINFO_map_w , rs # Map width in tile units
+ rs=rs+dh
+.equ TILEINFO_map_h , rs # Map height in tile units
+ rs=rs+dh
+
+#
+# TILEPKT struct
+#
+ rs=0
+.equ TILEPKT_tag , rs # Primitive tag
+ rs=rs+dw
+.equ TILEPKT_tpage , rs # tpage packet
+ rs=rs+dw
+.equ TILEPKT_rgbc , rs # Tile color
+ rs=rs+dw
+.equ TILEPKT_x , rs # Tile screen coordinates
+ rs=rs+dh
+.equ TILEPKT_y , rs
+ rs=rs+dh
+.equ TILEPKT_uv , rs # Tile texture coordinates
+ rs=rs+dh
+.equ TILEPKT_clut , rs # Tile CLUT
+ rs=rs+dh
+.equ TILEPKT_len , rs # Packet length
+
+# addprim Macro
+#
+# Registers a primitive to a ordering table entry.
+#
+# Arguments:
+# ot - Register name of pointer to ordering table entry
+# pri - Pointer to a primitive packet
+# len - Size of packet in long words (specify as 0xnn00, ie. 0x2000)
+#
+# Destroys:
+# at, v0, v1
+#
+.macro addprim ot,pri,len
+ .set noat
+ lw $v0, 0(\ot) # Get OT entry
+ lui $at, 0x00ff # Mask out the packet length field
+ or $at, 0xffff
+ and $v0, $at
+ lui $v1, \len # Merge packet length
+ or $v1, $v0
+ sw $v1, 0(\pri) # Store updated OT entry to packet
+ lw $v0, 0(\ot) # Get OT entry
+ and \pri, $at # Mask out last 8-bits of packet address
+ lui $at, 0xff00 # Mask out OT entry's address
+ and $v0, $at
+ or $v0, \pri # Merge packet address to OT entry
+ sw $v0, 0(\ot) # Store updated OT entry
+ .set at
+.endm
+
+#
+# Start of text section
+#
+.section .text
+
+# DrawTiles Function
+#
+# Renders a tilemap by generating TILEPKT primitives (combined SPRT_16 and
+# DR_TPAGE primitives) and registering it to the specified ordering table.
+# The drawing region, tile definitions and the tilemap are specified through
+# a TILEINFO struct.
+#
+# C Declaration:
+# extern u_char *DrawTiles(int scroll_x, int scroll_y,
+# TILEINFO *info, long *ot, u_char *pri);
+#
+# Arguments:
+# scroll_x - X scrolling offset of tile-map
+# scroll_y - Y scrolling offset of tile-map
+# info - Pointer to a TILEINFO struct
+# ot - Pointer to a ordering table entry
+# pri - Pointer to next primitive (placed in stack)
+#
+# Returns:
+# New next primitive pointer value.
+#
+.global DrawTiles # Declare symbol as global
+.type DrawTiles, @function # Declare it as a function
+DrawTiles: # Symbol label of function
+
+ addiu $sp, -4 # Push frame pointer (fp) to stack
+ sw $fp, 0($sp)
+ move $fp, $sp # Copy stack pointer (sp) to fp
+
+ # Register reference:
+ #
+ # t0 - Packet address
+ # t1 - Map data address
+ # t2 - Tile X offset
+ # t3 - Tile Y offset
+ # t4 - Tile X coordinate backup
+ # t5 - Tile X loop counter
+ # t6 - Number of tiles to sort per row
+ # t7 - Number of tile rows to sort
+
+ lhu $t6, TILEINFO_window_w($a2) # Calculate size of window in tiles
+ lhu $t7, TILEINFO_window_h($a2)
+ addi $t6, 15 # So the result will be rounded-up
+ addi $t7, 15
+ srl $t6, 4 # Effectively divide by 16
+ srl $t7, 4
+
+ lw $t0, 20($sp) # Obtain next primitive pointer
+
+ srl $t2, $a0, 4 # Compute map offset in tile units
+ srl $t3, $a1, 4
+
+ bgez $a0, .Lno_neg_clip_X # Negative X clip test
+ sub $v0, $0 , $a0
+ move $t2, $0 # Force tile offset to zero
+ add $v0, 15 # Reduce number of tile columns
+ srl $v0, 4
+ sub $t6, $v0
+.Lno_neg_clip_X:
+ lhu $v1, TILEINFO_map_w($a2) # Positive X clip test
+ add $v0, $t2, $t6
+ addi $v0, 1
+ blt $v0, $v1, .Lno_pos_clip_X
+ nop
+ sub $v0, $v1 # Compute how many tiles to clip
+ sub $t6, $v0 # Reduce number of tile columns
+.Lno_pos_clip_X:
+ bgez $a1, .Lno_neg_clip_Y # Negative Y clip test
+ sub $v0, $0 , $a1
+ move $t3, $0
+ add $v0, 15
+ srl $v0, 4
+ sub $t7, $v0
+.Lno_neg_clip_Y:
+ lhu $v1, TILEINFO_map_h($a2) # Positive Y clip test
+ add $v0, $t3, $t7
+ addi $v0, 1
+ blt $v0, $v1, .Lno_pos_clip_Y
+ nop
+ sub $v0, $v1
+ sub $t7, $v0
+.Lno_pos_clip_Y:
+ bltz $t6, .Lno_draw # Exit when no tiles to draw
+ nop
+ bltz $t7, .Lno_draw
+ nop
+
+ lh $v0, TILEINFO_window_x($a2) # Compute pixel coordinates for
+ sub $a0, $v0, $a0 # tiles based on the scroll offset
+ sll $v0, $t2, 4
+ add $a0, $v0
+ lh $v0, TILEINFO_window_y($a2)
+ sub $a1, $v0, $a1
+ sll $v0, $t3, 4
+ add $a1, $v0
+ move $t4, $a0
+ sll $t2, 1
+
+.Lloop_y: # Begin of tile row loop
+ lhu $v0, TILEINFO_map_w($a2) # Get width of tilemap
+ move $t5, $t6 # n tiles to draw row
+ mult $t3, $v0 # Multiply Y offset by map width
+ lw $t1, TILEINFO_mapdata($a2) # Get tilemap address
+ nop
+ addu $t1, $t2 # Add X offset to address
+ mflo $v0 # Get Y offset result
+ sll $v0, 1 # Multiply by two
+ addu $t1, $v0 # Add to tile address
+
+.Lloop_x: # Begin of tile column loop
+ lhu $v1, 0($t1) # Load tile index
+ addiu $t1, 2 # Advance to next tile
+ beq $v1, 0xFFFF, .Lskip_tile # Skip tile if index is 0xFFFF
+ nop
+ lw $v0, TILEINFO_tiles($a2) # Get pointer to TILEDEF entries
+ sll $v1, 3 # Multiply by 8 (size of TILEDEFs)
+ addu $v1, $v0 # Adjust to tiledefs pointer
+ lw $v0, TILEDEF_uv($v1) # Obtain UV+CLUT
+ lhu $v1, TILEDEF_tpage($v1) # Obtain tpage
+ sw $v0, TILEPKT_uv($t0) # Start constructing packet
+ lui $v0, 0xE100 # tpage packet code
+ or $v0, $v1 # Merge tpage bits
+ sw $v0, TILEPKT_tpage($t0)
+ sh $a0, TILEPKT_x($t0) # Set tile screen coords
+ sh $a1, TILEPKT_y($t0)
+ li $v0, 0x7C7F7F7F # Packet code and color
+ sw $v0, TILEPKT_rgbc($t0)
+ addprim $a3, $t0, 0x0400 # Register to OT
+ addiu $t0, TILEPKT_len # Advance packet pointer
+.Lskip_tile:
+ addi $t5, -1 # Decrement and continue iterating
+ bgez $t5, .Lloop_x # if non-zero
+ addiu $a0, 16 # Advance X tile coordinate
+
+ move $a0, $t4 # Restore tile X coordinate
+ addi $t3, 1 # Increment Y offset
+ addi $t7, -1 # Decrement and continue iterating
+ bgez $t7, .Lloop_y # if non-zero
+ addiu $a1, 16 # Advance Y tile coordinate
+
+.Lno_draw:
+
+ move $v0, $t0 # Set packet pointer as return value
+
+ lw $fp, 0($sp) # Restore frame pointer and return
+ jr $ra
+ addiu $sp, 4
+ # DrawTiles
+ \ No newline at end of file
diff --git a/examples/graphics/tilesasm/iso.xml b/examples/graphics/tilesasm/iso.xml
new file mode 100644
index 0000000..477c636
--- /dev/null
+++ b/examples/graphics/tilesasm/iso.xml
@@ -0,0 +1,34 @@
+<?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"
+>
+ <track type="data">
+ <identifiers
+ system ="PLAYSTATION"
+ volume ="PSN00BSDK_TEMPLATE"
+ volume_set ="PSN00BSDK_TEMPLATE"
+ publisher ="MEIDOTEK"
+ data_preparer ="PSN00BSDK ${PSN00BSDK_VERSION}"
+ application ="PLAYSTATION"
+ copyright ="README.TXT;1"
+ />
+
+ <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" />
+
+ <dummy sectors="1024"/>
+ </directory_tree>
+ </track>
+
+ <!--<track type="audio" source="track2.wav" />-->
+</iso_project>
diff --git a/examples/graphics/tilesasm/main.c b/examples/graphics/tilesasm/main.c
new file mode 100644
index 0000000..7f7c7fe
--- /dev/null
+++ b/examples/graphics/tilesasm/main.c
@@ -0,0 +1,425 @@
+/*
+ * LibPSn00b Example Programs
+ *
+ * Drawing Tile-maps with Assembler Routines
+ * 2022 Meido-Tek Productions / PSn00bSDK Project
+ *
+ * Example by John "Lameguy" Wilbert Villamor (Lameguy64)
+ *
+ * Demonstrates the use of assembler code to write a high-speed graphics
+ * routine that draws a 2D tile-map by generating SPRT_16 primitives.
+ * The assembler routine is called from a compiled C module in a manner no
+ * different to calling a C routine... A program written in this manner is
+ * known as mixed-language programming which includes other programming
+ * languages, not just assembly.
+ *
+ * This example also demonstrates using assembler files to include data files
+ * into a program as arrays (see 'data.s'). Arguably much more elegant and
+ * convenient than converting files to C headers like in the old days.
+ *
+ * The tile data and drawing is handled in a manner similar to that of the
+ * tile-map drawing functions in libgs where the map data consists of 16-bit
+ * words with 0xFFFF being a transparent tile, with each tile entry defined
+ * by an array of structs specifying the tpage, clut and u,v coordinates for
+ * each tile number. This provides flexibility with how the tile data will be
+ * organized in the framebuffer.
+ *
+ * Per-pixel clipping of the tile-map is actually not performed by the
+ * DrawTiles function but rather with DR_AREA primitives. This method
+ * eliminates code overhead from performing the clipping operations in
+ * software and thus, yields the fastest possible performance for tile
+ * sorting. Use of the DR_AREA primitive must be handled with care, as
+ * setting it beyond the display buffers could overwrite textures and
+ * CLUT data.
+ *
+ * Changelog:
+ *
+ * January 16, 2022 - Initial version.
+ *
+ * Controls:
+ *
+ * D-pad - Scroll tile-map
+ * L1 (hold) - Move tile-map window with D-pad (must be shrunk first)
+ * L2 (hold) - Resize tile-map window with D-pad
+ *
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <psxetc.h>
+#include <psxgte.h>
+#include <psxgpu.h>
+#include <psxapi.h>
+#include <psxpad.h>
+
+/*
+ * Constants for convenience
+ */
+#define OT_LEN 4 /* Number of ordering table entries */
+#define PKTBUFF_LEN 32768 /* Size of packet buffer (in bytes) */
+
+/* Define display/draw environments for double buffering */
+DISPENV disp[2];
+DRAWENV draw[2];
+int db;
+
+/* Define the ordering table and packet buffer arrays */
+long ot[2][OT_LEN];
+char pkt[2][PKTBUFF_LEN];
+
+/* Next packet pointer for primitive generation */
+char *pkt_addr;
+
+/* Pad data buffer */
+char pad_buff[2][34];
+
+/*
+ * Tile definition structure (to define VRAM coordinates of tiles)
+ */
+typedef struct _TILEDEF
+{
+ u_char u,v; // Texture coordinates of tile
+ u_short clut; // CLUT number of tile
+ u_short pad; // Padding
+ u_short tpage; // Texture page number
+} TILEDEF;
+
+/*
+ * Tile info structure (for drawing function)
+ */
+typedef struct _TILEINFO
+{
+ RECT window; // Drawing window of tile info (only cull, not clip)
+ TILEDEF *tiles; // Pointer to TILEDEF array
+ u_short *mapdata; // Pointer to 16-bit map data
+ u_short map_w; // Tile map dimensions
+ u_short map_h;
+} TILEINFO;
+
+/* Define array of tiledefs */
+TILEDEF tiles[256];
+
+/*
+ * Declarations for data.s
+ */
+extern u_long tim_tileset[];
+
+/*
+ * Declarations for drawtiles.s
+ */
+extern u_char *DrawTiles(int scroll_x, int scroll_y,
+ TILEINFO *info, long *ot, u_char *pri);
+
+/*
+ * Init function
+ */
+void init(void)
+{
+ TIM_IMAGE tim;
+
+ int i,tx,ty;
+
+ // This not only resets the GPU but it also installs the library's
+ // ISR subsystem to the kernel
+ ResetGraph(0);
+
+ // Define display environments, first on top and second on bottom
+ SetDefDispEnv(&disp[0], 0, 0, 320, 240);
+ SetDefDispEnv(&disp[1], 0, 240, 320, 240);
+
+ // Define drawing environments, first on bottom and second on top
+ SetDefDrawEnv(&draw[0], 0, 240, 320, 240);
+ SetDefDrawEnv(&draw[1], 0, 0, 320, 240);
+
+ // Set and enable clear color
+ setRGB0(&draw[0], 0, 96, 0);
+ setRGB0(&draw[1], 0, 96, 0);
+ draw[0].isbg = 1;
+ draw[1].isbg = 1;
+
+ // Setup buffer counter, packet pointer and ordering tables
+ db = 0;
+ pkt_addr = pkt[db];
+
+ // Clear ordering tables
+ ClearOTagR(ot[0], OT_LEN);
+ ClearOTagR(ot[1], OT_LEN);
+
+ // Load test font
+ FntLoad(960, 0);
+
+ // Open up a test font text stream of 100 characters
+ FntOpen(0, 8, 320, 224, 0, 100);
+
+ // Upload tileset TIM
+ GetTimInfo((u_long*)tim_tileset, &tim); /* Get TIM parameters */
+ LoadImage(tim.prect, tim.paddr); /* Upload texture to VRAM */
+ if( tim.mode & 0x8 ) /* Upload CLUT if present */
+ LoadImage(tim.crect, tim.caddr);
+
+ // Initialize tiledefs with coords to the tileset TIM
+ i = 0;
+ for(ty=0; ty<16; ty++)
+ {
+ for(tx=0; tx<16; tx++)
+ {
+ tiles[i].u = tx<<4;
+ tiles[i].v = ty<<4;
+ tiles[i].tpage = getTPage(tim.mode & 3, 0,
+ tim.prect->x, tim.prect->y);
+ tiles[i].clut = getClut(tim.crect->x, tim.crect->y);
+ i++;
+ }
+ }
+
+ // Initialize pads
+ InitPAD(&pad_buff[0][0], 34, &pad_buff[1][0], 34);
+ StartPAD();
+ ChangeClearPAD(0);
+
+} /* init */
+
+/*
+ * Display function
+ */
+void display(void)
+{
+ // Wait for all drawing to complete
+ DrawSync(0);
+
+ // Wait for vertical sync to cap the logic to 60fps (or 50 in PAL mode)
+ // and avoid screen tearing
+ VSync(0);
+
+ // Switch pages
+ PutDispEnv(&disp[db]);
+ PutDrawEnv(&draw[db]);
+
+ // Begin drawing of the ordering table
+ DrawOTag(ot[db]+(OT_LEN-1));
+
+ // Toggle buffer index
+ db = !db;
+
+ // Clear next ordering table array
+ ClearOTagR(ot[db], OT_LEN);
+
+ // Reset packet pointer
+ pkt_addr = pkt[db];
+
+ // Enable display output, ResetGraph() disables it by default
+ SetDispMask(1);
+
+} /* display */
+
+/*
+ * Initializes a randomly generated tile map
+ */
+void initdata(u_short *tiledata, int w, int h)
+{
+ int tx,ty;
+
+ for(ty=0; ty<h; ty++)
+ {
+ srand(200+ty);
+ for(tx=0; tx<w; tx++)
+ {
+ *tiledata = rand() & 0xFF;
+ tiledata++;
+ }
+ }
+
+} /* initdata */
+
+/*
+ * Simple line sorting function
+ */
+void sortLine(int x1, int y1, int x2, int y2, long *ot)
+{
+ LINE_F2 *line_pkt;
+
+ line_pkt = (LINE_F2*)pkt_addr;
+ setLineF2(line_pkt);
+ setXY2(line_pkt, x1, y1, x2, y2);
+ setRGB0(line_pkt, 255, 255, 255);
+ addPrim(ot, line_pkt);
+ line_pkt++;
+
+ pkt_addr = (char*)line_pkt;
+
+} /* sortLine */
+
+/*
+ * Simple box sorting function
+ */
+void sortBox(RECT *rect)
+{
+ sortLine(rect->x, rect->y,
+ rect->x, rect->y+rect->h,
+ ot[db]);
+ sortLine(rect->x+rect->w, rect->y,
+ rect->x+rect->w, rect->y+rect->h,
+ ot[db]);
+ sortLine(rect->x, rect->y,
+ rect->x+rect->w, rect->y,
+ ot[db]);
+ sortLine(rect->x, rect->y+rect->h,
+ rect->x+rect->w, rect->y+rect->h, ot[db]);
+
+} /* sortBox */
+
+/*
+ * Sorts a draw area primitive for hardware clipping
+ */
+void sortDrawEnv(RECT *drawarea)
+{
+ DR_AREA *drawpkt;
+
+ drawpkt = (DR_AREA*)pkt_addr;
+ setDrawArea(drawpkt, drawarea);
+ addPrim(ot[db], drawpkt);
+ pkt_addr += sizeof(DR_AREA);
+
+} /* sortDrawEnv */
+
+/*
+ * Main function
+ */
+int main(int argc, const char *argv[])
+{
+ u_short *tiledata;
+ TILEINFO tileinfo;
+ PADTYPE *pad;
+ RECT cliprect;
+
+ int i,scroll_x,scroll_y;
+
+ /* Init stuff */
+ init();
+
+ /* Allocate buffer for tile data */
+ tiledata = (u_short*)malloc((256*256)<<1);
+
+ /* Generate a random tilemap of values 0-255 */
+ initdata(tiledata, 256, 256);
+
+ /* Define the TILEINFO struct */
+ tileinfo.window.x = 0;
+ tileinfo.window.y = 0;
+ tileinfo.window.w = 320;
+ tileinfo.window.h = 240;
+ tileinfo.tiles = tiles;
+ tileinfo.mapdata = tiledata;
+ tileinfo.map_w = 256;
+ tileinfo.map_h = 256;
+
+ /* Main loop */
+ scroll_x = 0;
+ scroll_y = 0;
+
+ while(1)
+ {
+ /* Handle inputs */
+ pad = (PADTYPE*)&pad_buff[0][0];
+
+ if( pad->stat == 0 )
+ {
+ if( ( pad->type == 0x4 ) ||
+ ( pad->type == 0x5 ) ||
+ ( pad->type == 0x7 ) )
+ {
+ if( !(pad->btn&PAD_L1) ) /* Window resize */
+ {
+ if( !(pad->btn&PAD_UP) && ( tileinfo.window.y > 0 ) )
+ {
+ tileinfo.window.y--;
+ }
+ i = tileinfo.window.y+tileinfo.window.h;
+ if( !(pad->btn&PAD_DOWN) && ( i < disp[db].disp.h ) )
+ {
+ tileinfo.window.y++;
+ }
+ if( !(pad->btn&PAD_LEFT) && ( tileinfo.window.x > 0 ) )
+ {
+ tileinfo.window.x--;
+ }
+ i = tileinfo.window.x+tileinfo.window.w;
+ if( !(pad->btn&PAD_RIGHT) && ( i < disp[db].disp.w ) )
+ {
+ tileinfo.window.x++;
+ }
+ }
+ else if( !(pad->btn&PAD_L2) ) /* Window move */
+ {
+ if( !(pad->btn&PAD_UP) && ( tileinfo.window.h > 0 ) )
+ {
+ tileinfo.window.h--;
+ }
+ i = tileinfo.window.y+tileinfo.window.h;
+ if( !(pad->btn&PAD_DOWN) && ( i < disp[db].disp.h ) )
+ {
+ tileinfo.window.h++;
+ }
+ if( !(pad->btn&PAD_LEFT) && ( tileinfo.window.w > 0 ) )
+ {
+ tileinfo.window.w--;
+ }
+ i = tileinfo.window.y+tileinfo.window.h;
+ if( !(pad->btn&PAD_RIGHT) && ( i < disp[db].disp.w ) )
+ {
+ tileinfo.window.w++;
+ }
+ }
+ else /* Scrolling */
+ {
+ if( !(pad->btn&PAD_UP) )
+ {
+ scroll_y-=2;
+ }
+ if( !(pad->btn&PAD_DOWN) )
+ {
+ scroll_y+=2;
+ }
+ if( !(pad->btn&PAD_LEFT) )
+ {
+ scroll_x-=2;
+ }
+ if( !(pad->btn&PAD_RIGHT) )
+ {
+ scroll_x+=2;
+ }
+ }
+ }
+ }
+
+ /* Draw a box around the tile-map window */
+ sortBox(&tileinfo.window);
+
+ /* Sort default clipping (this is processed last) */
+ sortDrawEnv(&draw[db].clip);
+
+ /* Sort the tiles */
+ pkt_addr = DrawTiles(scroll_x, scroll_y,
+ &tileinfo, ot[db], pkt_addr);
+
+ /* Sort clipping to the tile window */
+ cliprect = tileinfo.window;
+ cliprect.y += draw[db].clip.y;
+ sortDrawEnv(&cliprect);
+
+ /* Print stats */
+ FntPrint(-1, "X=%d Y=%d\n", scroll_x, scroll_y);
+ FntPrint(-1, "WINDOW POS. (%d,%d)\n",
+ tileinfo.window.x, tileinfo.window.y);
+ FntPrint(-1, "WINDOW SIZE (%d,%d)\n",
+ tileinfo.window.w, tileinfo.window.h);
+ FntFlush(-1);
+
+ /* Refresh display */
+ display();
+ }
+
+ return 0;
+
+} /* main */
diff --git a/examples/graphics/tilesasm/system.cnf b/examples/graphics/tilesasm/system.cnf
new file mode 100644
index 0000000..e221726
--- /dev/null
+++ b/examples/graphics/tilesasm/system.cnf
@@ -0,0 +1,4 @@
+BOOT=cdrom:\template.exe;1
+TCB=4
+EVENT=10
+STACK=801FFFF0
diff --git a/examples/graphics/tilesasm/tiles_256.png b/examples/graphics/tilesasm/tiles_256.png
new file mode 100644
index 0000000..e58c06c
--- /dev/null
+++ b/examples/graphics/tilesasm/tiles_256.png
Binary files differ
diff --git a/examples/graphics/tilesasm/tiles_256.tim b/examples/graphics/tilesasm/tiles_256.tim
new file mode 100644
index 0000000..1bb59bb
--- /dev/null
+++ b/examples/graphics/tilesasm/tiles_256.tim
Binary files differ
diff --git a/examples/io/pads/main.c b/examples/io/pads/main.c
index cc4ef56..d100482 100644
--- a/examples/io/pads/main.c
+++ b/examples/io/pads/main.c
@@ -127,7 +127,7 @@ void send_pad_cmd(
uint8_t arg2,
SPI_Callback callback
) {
- SPI_request *req = SPI_CreateRequest();
+ SPI_Request *req = SPI_CreateRequest();
req->len = 9;
req->port = port;
diff --git a/examples/io/pads/spi.c b/examples/io/pads/spi.c
index e01b3f6..ef75ffc 100644
--- a/examples/io/pads/spi.c
+++ b/examples/io/pads/spi.c
@@ -54,21 +54,21 @@
/* Internal structures and globals */
-typedef struct _SPICONTEXT {
- uint8_t tx_buff[SPI_BUFF_LEN];
- uint8_t rx_buff[SPI_BUFF_LEN];
- uint32_t tx_len, rx_len, port;
- SPICALLBACK callback;
-} SPICONTEXT;
+typedef struct _SPI_CONTEXT {
+ uint8_t tx_buff[SPI_BUFF_LEN];
+ uint8_t rx_buff[SPI_BUFF_LEN];
+ uint32_t tx_len, rx_len, port;
+ SPI_Callback callback;
+} SPI_Context;
-static volatile SPICONTEXT ctx;
-static volatile SPIREQUEST volatile *current_req;
-static SPICALLBACK default_cb;
+static volatile SPI_Context ctx;
+static volatile SPI_Request volatile *current_req;
+static SPI_Callback default_cb;
/* Request queue management */
-static void prepare_poll_req(void) {
- PADREQUEST *req = (PADREQUEST *) ctx.tx_buff;
+static void _spi_create_poll_req(void) {
+ PadRequest *req = (PadRequest *) ctx.tx_buff;
req->addr = 0x01;
req->cmd = PAD_CMD_READ;
@@ -82,7 +82,7 @@ static void prepare_poll_req(void) {
ctx.callback = default_cb;
}
-static void prepare_next_req(void) {
+static void _spi_next_req(void) {
// Copy the contents of the first request in the queue into the TX buffer.
memcpy((void *) ctx.tx_buff, (void *) current_req->data, current_req->len);
@@ -93,7 +93,7 @@ static void prepare_next_req(void) {
// Pop the first request from the queue by deallocating it and adjusting
// the pointer to the first queue item.
- SPIREQUEST *next = current_req->next;
+ SPI_Request *next = current_req->next;
free((void *) current_req);
current_req = next;
@@ -101,7 +101,7 @@ static void prepare_next_req(void) {
/* Interrupt handlers */
-static void poll_timer_tick(void) {
+static void _spi_poll_irq_handler(void) {
// Fetch the last response byte, which wasn't followed by a pulse on /ACK,
// from the RX FIFO.
if (JOY_STAT & 0x0002)
@@ -112,9 +112,9 @@ static void poll_timer_tick(void) {
// If the request queue is empty, create a pad polling request.
if (current_req)
- prepare_next_req();
+ _spi_next_req();
else
- prepare_poll_req();
+ _spi_create_poll_req();
// Prepare the SPI port by clearing any pending IRQ, pulling /CS high and
// enabling the /ACK IRQ. In order to communicate with controllers, /CS has
@@ -132,7 +132,7 @@ static void poll_timer_tick(void) {
JOY_TXRX = ctx.tx_buff[0];
}
-static void spi_ack_handler(void) {
+static void _spi_ack_irq_handler(void) {
// Wait until /ACK is pulled up by the controller before sending the next
// byte. According to nocash docs, this has to be done before resetting the
// IRQ.
@@ -166,8 +166,8 @@ static void spi_ack_handler(void) {
/* Public API */
-SPIREQUEST *spi_new_request(void) {
- SPIREQUEST *req = malloc(sizeof(SPIREQUEST));
+SPI_Request *SPI_CreateRequest(void) {
+ SPI_Request *req = malloc(sizeof(SPI_Request));
req->len = 0;
req->port = 0;
@@ -179,7 +179,7 @@ SPIREQUEST *spi_new_request(void) {
if (!current_req) {
current_req = req;
} else {
- volatile SPIREQUEST *volatile last = current_req;
+ volatile SPI_Request *volatile last = current_req;
while (last->next)
last = last->next;
@@ -189,7 +189,7 @@ SPIREQUEST *spi_new_request(void) {
return req;
}
-void spi_set_poll_rate(uint32_t value) {
+void SPI_SetPollRate(uint32_t value) {
TIM_CTRL(2) = 0x0258; // CLK/8 input, IRQ on reload, disable one-shot IRQ
if (value < 65)
@@ -198,21 +198,21 @@ void spi_set_poll_rate(uint32_t value) {
TIM_RELOAD(2) = (F_CPU / 8) / value;
}
-void spi_init(SPICALLBACK callback) {
+void SPI_Init(SPI_Callback callback) {
// Disable the BIOS timer handler (which for some stupid reason is enabled
// by default, even though it does nothing) and set up custom interrupt
// handlers.
EnterCriticalSection();
ChangeClearRCnt(2, 0);
- InterruptCallback(6, &poll_timer_tick);
- InterruptCallback(7, &spi_ack_handler);
+ InterruptCallback(6, &_spi_poll_irq_handler);
+ InterruptCallback(7, &_spi_ack_irq_handler);
ExitCriticalSection();
JOY_CTRL = 0x0040; // Reset all registers
JOY_MODE = 0x000d; // 1x multiplier, 8 data bits, no parity
JOY_BAUD = 0x0088; // 250000 bps
- spi_set_poll_rate(250);
+ SPI_SetPollRate(250);
current_req = 0;
default_cb = callback;
}
diff --git a/examples/io/pads/spi.h b/examples/io/pads/spi.h
index 1c473cd..c50e065 100644
--- a/examples/io/pads/spi.h
+++ b/examples/io/pads/spi.h
@@ -9,23 +9,24 @@
#include <stdint.h>
#include <psxpad.h>
+// Maximum request/response length (34 bytes for pads, 140 for memory cards)
//#define SPI_BUFF_LEN 34
#define SPI_BUFF_LEN 140
/* Request structures */
-typedef void (*SPICALLBACK)(uint32_t port, const volatile uint8_t *buff, size_t rx_len);
+typedef void (*SPI_Callback)(uint32_t port, const volatile uint8_t *buff, size_t rx_len);
-typedef struct _SPIREQUEST {
+typedef struct _SPI_Request {
union {
- uint8_t data[SPI_BUFF_LEN];
- PADREQUEST pad_req;
- MCDREQUEST mcd_req;
+ uint8_t data[SPI_BUFF_LEN];
+ PadRequest pad_req;
+ MemCardRequest mcd_req;
};
- uint32_t len, port;
- SPICALLBACK callback;
- struct _SPIREQUEST *next;
-} SPIREQUEST;
+ uint32_t len, port;
+ SPI_Callback callback;
+ struct _SPI_Request *next;
+} SPI_Request;
/* Public API */
@@ -34,7 +35,7 @@ typedef struct _SPIREQUEST {
* object must be populated afterwards by setting the length, callback and
* filling in the TX data buffer.
*/
-SPIREQUEST *spi_new_request(void);
+SPI_Request *SPI_CreateRequest(void);
/**
* @brief Changes the controller polling rate. The lowest supported rate is 65
@@ -43,7 +44,7 @@ SPIREQUEST *spi_new_request(void);
*
* @param value
*/
-void spi_set_poll_rate(uint32_t value);
+void SPI_SetPollRate(uint32_t value);
/**
* @brief Installs the SPI and timer 2 interrupt handlers and starts the poll
@@ -56,6 +57,6 @@ void spi_set_poll_rate(uint32_t value);
*
* @param callback
*/
-void spi_init(SPICALLBACK callback);
+void SPI_Init(SPI_Callback callback);
#endif
diff --git a/examples/io/system573/main.c b/examples/io/system573/main.c
index 95c3155..a06c4e5 100644
--- a/examples/io/system573/main.c
+++ b/examples/io/system573/main.c
@@ -185,9 +185,9 @@ typedef struct {
uint8_t p1_joy, p1_btn;
uint8_t p2_joy, p2_btn;
uint8_t coin, dip_sw;
-} JAMMA_INPUTS;
+} JAMMAInputs;
-void get_jamma_inputs(JAMMA_INPUTS *output) {
+void get_jamma_inputs(JAMMAInputs *output) {
uint16_t in1l = K573_IN1_L;
uint16_t in1h = K573_IN1_H;
uint16_t in2 = K573_IN2;
@@ -225,14 +225,14 @@ void get_jamma_inputs(JAMMA_INPUTS *output) {
void set_lights_analog(uint32_t lights) {
uint32_t bits;
- bits = (lights & 0x01010101) << 7; // Lamp 0 -> bit 7
- bits |= (lights & 0x02020202) << 5; // Lamp 1 -> bit 6
- bits |= (lights & 0x04040404) >> 1; // Lamp 2 -> bit 1
- bits |= (lights & 0x08080808) >> 3; // Lamp 3 -> bit 0
- bits |= (lights & 0x10101010) << 1; // Lamp 4 -> bit 5
- bits |= (lights & 0x20202020) >> 1; // Lamp 5 -> bit 4
- bits |= (lights & 0x40404040) >> 3; // Lamp 6 -> bit 3
- bits |= (lights & 0x80808080) >> 5; // Lamp 7 -> bit 2
+ bits = (lights & 0x01010101) << 7; // Lamp n*8+0 -> bit n*8+7
+ bits |= (lights & 0x02020202) << 5; // Lamp n*8+1 -> bit n*8+6
+ bits |= (lights & 0x04040404) >> 1; // Lamp n*8+2 -> bit n*8+1
+ bits |= (lights & 0x08080808) >> 3; // Lamp n*8+3 -> bit n*8+0
+ bits |= (lights & 0x10101010) << 1; // Lamp n*8+4 -> bit n*8+5
+ bits |= (lights & 0x20202020) >> 1; // Lamp n*8+5 -> bit n*8+4
+ bits |= (lights & 0x40404040) >> 3; // Lamp n*8+6 -> bit n*8+3
+ bits |= (lights & 0x80808080) >> 5; // Lamp n*8+7 -> bit n*8+2
K573_IO_BOARD[ANALOG_IO_LIGHTS0] = (bits) & 0xff;
K573_IO_BOARD[ANALOG_IO_LIGHTS1] = (bits >> 8) & 0xff;
@@ -247,10 +247,10 @@ void set_lights_analog(uint32_t lights) {
void set_lights_digital(uint32_t lights) {
uint32_t bits;
- bits = (lights & 0x11111111); // Lamp 0 -> bit 0
- bits |= (lights & 0x22222222) << 1; // Lamp 1 -> bit 2
- bits |= (lights & 0x44444444) << 1; // Lamp 2 -> bit 3
- bits |= (lights & 0x88888888) >> 2; // Lamp 3 -> bit 1
+ bits = (lights & 0x11111111); // Lamp n*4+0 -> bit n*4+0
+ bits |= (lights & 0x22222222) << 1; // Lamp n*4+1 -> bit n*4+2
+ bits |= (lights & 0x44444444) << 1; // Lamp n*4+2 -> bit n*4+3
+ bits |= (lights & 0x88888888) >> 2; // Lamp n*4+3 -> bit n*4+1
K573_IO_BOARD[DIGITAL_IO_LIGHTS0] = ((bits) & 0xf) << 12;
K573_IO_BOARD[DIGITAL_IO_LIGHTS1] = ((bits >> 4) & 0xf) << 12;
@@ -298,7 +298,7 @@ int main(int argc, const char* argv[]) {
while (1) {
FntPrint(-1, "COUNTER=%d\n", counter++);
- JAMMA_INPUTS inputs;
+ JAMMAInputs inputs;
get_jamma_inputs(&inputs);
FntPrint(-1, "\nJAMMA INPUTS:\n");
diff --git a/examples/sound/spustream/main.c b/examples/sound/spustream/main.c
index e268c7d..be095cb 100644
--- a/examples/sound/spustream/main.c
+++ b/examples/sound/spustream/main.c
@@ -117,7 +117,7 @@ typedef struct {
uint32_t adsr_param;
uint16_t _reserved;
uint16_t loop_addr;
-} SPUCHANNEL;
+} SPUChannel;
#define SPU_CTRL *((volatile uint16_t *) 0x1f801daa)
#define SPU_IRQ_ADDR *((volatile uint16_t *) 0x1f801da4)
@@ -125,7 +125,7 @@ typedef struct {
#define SPU_KEY_OFF *((volatile uint32_t *) 0x1f801d8c)
// SPU RAM is addressed in 8-byte units, using 16-bit pointers.
-#define SPU_CHANNELS ((volatile SPUCHANNEL *) 0x1f801c00)
+#define SPU_CHANNELS ((volatile SPUChannel *) 0x1f801c00)
#define SPU_RAM_ADDR(x) ((uint16_t) (((uint32_t) (x)) >> 3))
/* Display/GPU context utilities */
@@ -219,9 +219,9 @@ typedef struct {
uint32_t spu_addr;
uint32_t spu_pos;
uint32_t db_active;
-} STREAMCONTEXT;
+} StreamContext;
-static volatile STREAMCONTEXT str_ctx;
+static volatile 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