Giter Site home page Giter Site logo

lameguy64 / psn00bsdk Goto Github PK

View Code? Open in Web Editor NEW
790.0 40.0 64.0 18.53 MB

The most powerful open source SDK for the PS1 (as far as open source PS1 SDKs go). Not recommended for beginner use.

License: Other

C 64.31% C++ 5.64% Assembly 22.17% Python 2.95% CMake 4.58% Shell 0.22% Makefile 0.12%

psn00bsdk's Introduction

PSn00bSDK

PSn00bSDK is an open source homebrew software development kit for the original Sony PlayStation, consisting of a C/C++ compiler toolchain and a set of libraries that provide a layer of abstraction over the raw hardware in order to make game and app development easier. A CMake-based build system, CD-ROM image packing tool (mkpsxiso) and asset conversion utilities are also provided.

At the heart of PSn00bSDK is libpsn00b, a set of libraries that implements most of the core functionality of the official Sony SDK (excluding higher-level libraries) plus several new extensions to it. Most of the basic APIs commonly used by homebrew apps and games built with the official SDK are available, making PSn00bSDK a good starting point for those who have an existing codebase but want to move away from Sony tools.

Currently supported features include:

  • Full support for the GPU's functionality including all primitive types (lines, polygons, sprites) as well DMA transfers managed through a software-driven command queue that can optionally be extended with custom commands. Both NTSC and PAL video modes are fully supported.

  • Extensive GTE support with rotate, translate, perspective correction and lighting calculation fully supported through C and/or assembly GTE macros paired with high speed matrix and vector helper functions. All calculations performed in fixed point integer math, not a single float used.

  • BIOS-based interrupt dispatch system providing the ability to register custom callbacks for all IRQs and DMA channels while preserving compatibility with all functions provided by the BIOS.

  • Basic support for controller input through the BIOS, with optional limited support for manual polling.

  • Complete Serial I/O support with buffering and console driver to redirect BIOS standard input and output to the serial port. Hardware flow control supported.

  • CD-ROM support featuring asynchronous reading, CD-DA and XA-ADPCM audio playback and a built-in ISO9660 file system parser with no file count limit. Additional support for multi-session discs and bypassing region checks on supported console models.

  • Full MDEC support for hardware accelerated lossy image decompression and video playback.

  • Preliminary limited support for Konami System 573 arcade hardware.

  • Experimental support for dynamic linking at runtime, including function and variable introspection by loading a map file generated at build time.

Note that, while PSn00bSDK's API is to some extent compatible with the official SDK's, the project is not meant to be a drop-in replacement for it, both since reimplementing the entire SDK would be a major undertaking and because many parts of it are inefficient, clunky and/or provide relatively little value.

Obtaining PSn00bSDK

Prebuilt PSn00bSDK packages for Windows and Linux are available on the releases page and include the libraries, a copy of the GCC MIPS toolchain, command-line tools, examples and documentation. CMake is not included and must be installed separately, either from its website or via MSys2 or your distro's package manager.

The releases can be installed by simply extracting the archives into any directory and adding the bin subfolder to the PATH environment variable. share/psn00bsdk/template contains a barebones example project that can be used as a starting point.

For more information on how to get started, or if you wish to build the SDK yourself from source instead, refer to installation.md.

Tutorials and examples

The examples directory contains several example programs showcasing different parts of the SDK (mostly graphics); the source code of n00bdemo can also be found in the same directory. More example programs may be added in the future and contributed example programs are welcome.

Lameguy's PlayStation Programming Tutorial Series was written with older versions of PSn00bSDK in mind and is outdated at this point, but may still be useful as an introduction to the console's hardware and the basics of the graphics and controller APIs.

To-do List

  • libpsxgte: Rewrite all assembly functions from scratch as parts of them have been lifted as-is from Sony libraries. PSn00bSDK is currently (and will probably always be) in a legal gray area due to this.

  • libpsxspu: Plenty of work to be done. Some kind of MIDI sequencer (similar to the one present in the official SDK) should be added at some point, along with a proper API for audio streaming.

  • libpsxcd: Implement a command queue mechanism for the CD-ROM.

  • libpsxpress: Add an API for SPU-ADPCM audio encoding at runtime.

  • libc: Improve the memory allocation framework with multiple allocators, replace the string functions with optimized implementations and maybe add helpers to manage swapping between main RAM and VRAM/SPU RAM.

  • Add a full controller and memory card API that does not depend on the BIOS controller driver, and possibly a library for interfacing to IDE/ATAPI drives to make development for arcade systems easier.

Credits

Main developers/authors:

  • Lameguy64 (John "Lameguy" Wilbert Villamor)
  • spicyjpeg

Contributors:

  • Silent, G4Vi, Chromaryu: mkpsxiso and dumpsxiso (maintained as a separate repo).

Honorable mentions:

  • Soapy: wrote the original version of the inline_c.h header containing GTE macros.
  • ijacquez: helpful suggestions for getting C++ working.
  • Nicolas Noble: author of the pcsx-redux emulator, OpenBIOS and other projects which proved invaluable during development.

Helpful contributors can be found in the changelog.

References used:

Additional references can be found in individual source files.

psn00bsdk's People

Contributors

alextrevisan avatar annestrand avatar ckosmic avatar flannyh avatar greenaddress avatar jaczekanski avatar johnythecarrot avatar lameguy64 avatar niko1point0 avatar qbradq avatar root670 avatar saxbophone avatar spicyjpeg avatar thp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

psn00bsdk's Issues

Using newlib-nano

Hello,

As I saw in the Readme, you said Newlib was too bloated for the PSX why not using newlib-nano variant for the purpose, as it's embedded in newlib right now and just depends on using the nano.specs as a baseline for the linker ?

Look at here to see the size decrease by using the newlib-nano variant : http://pabigot.github.io/bspacm/newlib.html

Linux: Demo not working using PCSXR since commit `c800972`

I've been fiddling with the project at a surface level, mostly for the sake of building it and getting the demos running, all using the latest master (4139331).

The building step goes well once the correct MIPS gcc tool chain is correctly set, not much to report here, however: my experience at run time tells another story...

I load the iconic, freshly-built n00bdemo.exe using PCSXR and... nothing, black screen, but the emulator does not seems to report much meaningful info (compared to a successful run)

Fortunately: the last tagged release v0.19 (some 49 commits ago...) builds AND runs successfully as far as I can tell, so I decided to try and find out when/where things went dark.

By manually performing binary search (yes) on the commit list between now and then to test what was resulting in a working demo and what wasn't: I've pinned down commit c800972 as the faulty one

Much to my dismay: my non-existing MIPS-on-PSX knowledge does little to help me understand this and fix it myself, so instead I did the best I could by finding out where the issue originates from.

What more:

  • I'm using PCSXR from the AUR repository on Arch Linux (aur/pcsxr 1.9.95-2) with BIOS SCPH1001 if that helps.

  • MIPS gcc toolchain was the one provided in the release build for v0.19, namely: gcc-mipsel-none-elf-11.1.0-linux.zip

  • I've also tried loading the demo built from the latest master on ePSXe running on some Windows installation and same issue: black screen, that's why I'm assuming this issue is not emulator-specific, I've also tried different BIOSes (on both emulators): same thing.

  • Just for clarity: I've tried loading actual ISOs of real officially-released games to ensure the emulators were working at all, turned out they were, so there's that.

This whole project looks insane and I'm counting on further fiddling with it (at least I know I have some working version of it), so if you want me to provide more info or test more things on my side regarding this issue: I'm all ears!

Makefile adjustments

I noticed that, while building under WSL2, the subfolders do not have an install target. I also noticed that sdk-common.mk and common.mk are almost identical - so you could consider leaving sdk-common.mk within root and:

  • Use CROSS_ or X_ prefixed variables to reference the cross-compiler
  • Use EPREFIX instead of PREFIX
    • See GCC's and Binutils' configure for the reason why.
    • TL;DR: EPREFIX = Executable prefix; PREFIX = Installation prefix
  • PREFIX may replace GCC_BASE. Alternatively, have the user export PSN00BSDK or similiar variables.
    • Projects relying on PSN00BSDK might use this as well - as a uniform way of finding the SDK.
  • Refactor sdk-common.mk to also contain the build rules - no need to duplicate them :)
  • Consider providing a copy of the used ldscript and referencing that within sdk-common.mk already.

With the changes above, examples/beginner/hello/makefile could look like this instead:

include ../../sdk-common.mk

# Project target name
TARGET          = hello.elf

# Searches for C, C++ and S (assembler) files in local directory
CFILES          = $(notdir $(wildcard *.c))
CPPFILES        = $(notdir $(wildcard *.cpp))
AFILES          = $(notdir $(wildcard *.s))

# Determine object files
OFILES          = $(addprefix build/,$(CFILES:.c=.o)) \
                        $(addprefix build/,$(CPPFILES:.cpp=.o)) \
                        $(addprefix build/,$(AFILES:.s=.o))

# Project specific include and library directories
# (use -I for include dirs, -L for library dirs)
INCLUDE         +=
LIBDIRS         +=

# Libraries to link
LIBS            = -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lc

# C compiler flags
CFLAGS          = -g -O2 -fno-builtin -fdata-sections -ffunction-sections

# C++ compiler flags
CPPFLAGS        = $(CFLAGS) -fno-exceptions

# Assembler flags
AFLAGS          = -g -msoft-float

# Linker flags
LDFLAGS         = -g -Ttext=0x80010000 -gc-sections \
                        -T $(PSN00BSDK)/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x

# Toolchain programs
# Move those to sdk-common.mk
ifndef PSN00BSDK
$(error PSN00BSDK is not set)
endif
EPREFIX                 = mipsel-unknown-elf-
X_CC                      = $(PSN00BSDK)/bin/$(EPREFIX)gcc
X_CXX                     = $(PSN00BSDK)/bin/$(EPREFIX)g++
X_AS                      = $(PSN00BSDK)/bin/$(EPREFIX)as
X_LD                      = $(PSN00BSDK)/bin/$(EPREFIX)ld

all: $(OFILES)
        $(X_LD) $(LDFLAGS) $(LIBDIRS) $(OFILES) $(LIBS) -o $(TARGET)
        elf2x -q $(TARGET)

build/%.o: %.c
        @mkdir -p $(dir $@)
        $(X_CC) $(CFLAGS) $(INCLUDE) -c $< -o $@

build/%.o: %.cpp
        @mkdir -p $(dir $@)
        $(X_CXX)  $(CPPFLAGS) $(INCLUDE) -c $< -o $@

build/%.o: %.s
        @mkdir -p $(dir $@)
        $(X_CC) $(AFLAGS) $(INCLUDE) -c $< -o $@

clean:
        rm -rf build $(TARGET) $(TARGET:.elf=.exe)

These changes allow:

  • Testing alternative GCC/Binutils combinations by just making a new installation - i.e. /opt/psn00bsdk/gcc74_binutils231 - and installing into those, then using them by exporting PSN00BSDK=....
  • Using CC and X_CC allows for a native tool - i.e. bin2h - to be built alongside the project, which could then be used in order to build resources that will be compiled for the target.
  • Putting the default values into a sdk-common.mk that lives at the root of $PSN00BSDK allows projects to just include that file. If it fails, either the variable is not set, or the SDK not fully installed.

Those are, however, just my thoughts and ideas that came up while setting it up. I just compiled the demos and just need to test them out on an emulator to see if the patched ldscript does work as intended. :)

Also, I will put together a small shell script to setup the toolchain automatically - because why not. Might come in handy.

Switching to (or adding support for) CMake

Would it make sense for PSn00bSDK to move to, or at least to add support for, a CMake-based build system?

In my PR (#36) to add support for dynamic linking I had to edit pretty much all Makefiles, and it became clear that they are not the easiest thing to maintain when there are almost 30 of them. I am already using CMake (modern 3.20, not the ancient 2.8 stuff) in my upcoming PS1 homebrew project and it's very easy to set up for cross-compiling, only requiring two files to be added. With those in place, a simple project's CMakeLists.txt would just be the following:

cmake_minimum_required(VERSION 3.20)

set(CMAKE_TOOLCHAIN_FILE ../psn00bsdk-toolchain.cmake)
project(
	hello_world
	DESCRIPTION "PSn00bSDK CMake example"
	LANGUAGES C CXX ASM
)
include(../psn00bsdk-setup.cmake)

psn00bsdk_add_executable(main.exe main.c)
psn00bsdk_add_cd_image(hello_world.iso iso.xml.template)
# other macros could be defined e.g. for converting TIM images

If CMake support is added it would make sense to use CMake for building the libraries and examples as well, ditching the current Makefiles altogether. It would also help making the SDK easier to use with an IDE and/or under Windows, as CMake integrates with various IDEs and build systems that don't need Cygwin or MSys.

CDXA example locks on loop

The CDXA example locks on looping, it detects the video termination sector, then just locks in the CdControlF(CdlReadS, (u_char*)&xa_loc); call.

Looks like it gets stuck here inside _cd_control.s:

I'm not too familar with the inner CD logic at this point to delve further.

This is a sample I created, first 5 channels have the same track (37800Hz stereo) interleaved in it the last 3 are blank.
xasample.zip

Can't compile tools

Description

Hey! I'm trying to build psn00bsdk on a Docker machine running Ubuntu 18.04.1, and I'm stuck on compiling tools while running make inside the folder (libpsn00b compiles without problems).

Seems like the assembler isn't happy, and I can't seem to figure it out. Any suggestions?

Logs

Here's a snippet of tools/util's build log:

make -C util 
make[1]: Entering directory '/psn00bsdk/tools/util'
gcc -O2 -s elf2x.c -o elf2x
elf2x.c: In function 'main':
elf2x.c:137:2: warning: ignoring return value of 'fread', declared with attribute warn_unused_result [-Wunused-result]
  fread( &head, 1, sizeof(head), fp );
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
elf2x.c:176:3: warning: ignoring return value of 'fread', declared with attribute warn_unused_result [-Wunused-result]
   fread( &prg_heads[i], 1, sizeof(PRG_HEADER), fp );
   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
elf2x.c:229:3: warning: ignoring return value of 'fread', declared with attribute warn_unused_result [-Wunused-result]
   fread( &binary[(int)(prg_heads[i].p_vaddr-exe_taddr)],
   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1, prg_heads[i].p_filesz, fp );
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/ccBi70Rb.s: Assembler messages:
/tmp/ccBi70Rb.s:69: Error: unrecognized opcode `pushq %r15'
/tmp/ccBi70Rb.s:72: Error: unrecognized opcode `pushq %r14'
/tmp/ccBi70Rb.s:75: Error: unrecognized opcode `pushq %r13'
[TRUNCATED SIMILAR LINES]
/tmp/ccBi70Rb.s:432: Error: unrecognized opcode `xorl %edi,%edi'
/tmp/ccBi70Rb.s:433: Error: unrecognized opcode `call fclose@PLT'
/tmp/ccBi70Rb.s:434: Error: unrecognized opcode `jmp .L29'
/tmp/ccBi70Rb.s:436: Error: unrecognized opcode `call __stack_chk_fail@PLT'
makefile:12: recipe for target 'all' failed
make[1]: *** [all] Error 1
make[1]: Leaving directory '/psn00bsdk/tools/util'
makefile:7: recipe for target 'util' failed
make: *** [util] Error 2
make: Target 'all' not remade because of errors.

Environment

Program Version
gcc 7.4.0
g++ 7.4.0
ld 2.30
as 2.31.1
mipsel-unknown-elf-gcc 7.4.0
root@9ac3f90e0553:/# uname -a
Linux 9ac3f90e0553 4.14.154-boot2docker #1 SMP Thu Nov 14 19:19:08 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

None of the demos work with Mednafen

Using verified SCPH-5500 bios, tried with both opengl and software rendering
For example, here's the log with psx.dbg_level 2 for fpscam (which works in ePSXe, though it's one of the only ones that do):
`
Starting Mednafen 1.24.3
Build information:
Compiled with gcc 4.9.4
Running with MinGW-W64 Runtime 5.0 (alpha - rev. 0) 0000-00-00
Compiled against zlib 1.2.8, running with zlib 1.2.8(flags=0x00000065)
Compiled against libiconv 15.1, running with libiconv 15.1
Compiled against SDL 2.0.8(hg-11835:f622a4457a25), running with SDL 2.0.8(hg-11835:f622a4457a25)
Running with libsndfile-1.0.28
Base directory: C:\dev\PSn00bSDK\mednafen
Emulation modules: apple2 nes snes gb gba pce lynx md pcfx ngp psx ss ssfplay vb wswan sms gg snes_faust pce_fast demo cdplay
Opening lockfile...
Loading settings from "C:\dev\PSn00bSDK\mednafen\mednafen.cfg"...
Loaded 7544 valid settings and 0 unknown settings.
Initializing joysticks...
ID: 0x000000000000000000010004f3ff0000 - XInput Unknown Controller
Loading fpscam.exe...
Applying IPS file ".\fpscam.exe.ips"...
Failed: Error opening file ".\fpscam.exe.ips": No such file or directory
Using module: psx(Sony PlayStation)
Loading override settings from "C:\dev\PSn00bSDK\mednafen\psx.cfg"...
Failed: Error opening file "C:\dev\PSn00bSDK\mednafen\psx.cfg": No such file or directory
Loading override settings from "C:\dev\PSn00bSDK\mednafen\pgconfig\fpscam.psx.cfg"...
Failed: Error opening file "C:\dev\PSn00bSDK\mednafen\pgconfig\fpscam.psx.cfg": No such file or directory

Region: Japan

Multitap on PSX Port 1: Disabled
Multitap on PSX Port 2: Disabled
PC=0x80012b20
SP=0x00000000
TextStart=0x80010000
TextSize=0x00008000

Loading cheats from C:\dev\PSn00bSDK\mednafen\cheats\psx.cht...
Error opening file "C:\dev\PSn00bSDK\mednafen\cheats\psx.cht": No such file or directory

Initializing sound...
Using "WASAPI(Shared mode)" audio driver with SexyAL's default device selection.
Format: 16 bits(signed, 2 bytes, little-endian)
Rate: 44100
Channels: 2
Buffer size: 1411 sample frames(31.995465 ms)
Latency: 1411 sample frames(31.995465 ms)
Initializing video...
Driver: OpenGL
Display Mode: 1920 x 1080 x 24 bpp @ 144Hz (Window: 960 x 720)
Shader: none
Fullscreen: No
Special Scaler: None
Scanlines: Off
Destination Rectangle: X=0, Y=0, W=960, H=720
OpenGL Implementation: NVIDIA Corporation GeForce GTX 1060 6GB/PCIe/SSE2 4.6.0 NVIDIA 442.74
Checking extensions:
GL_ARB_texture_non_power_of_two found.
GL_ARB_sync found.
Using non-power-of-2 sized textures.
Checking maximum texture size...
Apparently it is at least: 32768 x 32768
Using GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV for texture source data.
[MEM] Unknown write32 to 1f801060 at time 40, =00000b88(2952)
[MEM] Unknown write32 to 1f801060 at time 91902, =00000b88(2952)
[MEM] Unknown write8 to 1f802041 at time 92017, =0000000f(15)
[MEM] Unknown write8 to 1f802041 at time 92290, =0000000e(14)
[MEM] Unknown write8 to 1f802041 at time 94143, =00000001(1)
[MEM] Unknown write8 to 1f802041 at time 94340, =00000002(2)
[MEM] Unknown write8 to 1f802041 at time 405693, =00000003(3)
[MEM] Unknown write8 to 1f802041 at time 419632, =00000004(4)
[MEM] Unknown write8 to 1f802041 at time 422787, =00000001(1)
[MEM] Unknown write8 to 1f802041 at time 422867, =00000003(3)
[MEM] Unknown write8 to 1f802041 at time 423301, =00000004(4)
[MEM] Unknown write8 to 1f802041 at time 433711, =00000005(5)
[MEM] Unknown write8 to 1f802041 at time 436482, =00000006(6)
[MEM] Unknown write8 to 1f802041 at time 436544, =00000002(2)
[MEM] Unknown write8 to 1f802041 at time 457375, =00000005(5)

PS-X Realtime Kernel Ver.2.5
Copyright 1993,1994 (C) Sony Computer Entertainment Inc.
[MEM] Unknown write8 to 1f802041 at time 514809, =00000006(6)
KERNEL SETUP!

Configuration : EvCB 0x10 TCB 0x04
[MEM] Unknown write8 to 1f802041 at time 566203, =00000007(7)
[MEM] Unknown write32 to fffffffc at time 864080, =bfc06998(-1077909096)
[MEM] Unknown write32 to fffffff8 at time 864081, =00000000(0)
[MEM] Unknown write32 to fffffff4 at time 864082, =00000000(0)
[MEM] Unknown write32 to fffffff0 at time 864090, =00000000(0)
[MEM] Unknown write32 to ffffffdc at time 973276, =80012b84(-2147406972)
[MEM] Unknown write32 to ffffffd8 at time 973277, =801fff00(-2145386752)
[MEM] Unknown write32 to ffffffd4 at time 973278, =00000000(0)
[MEM] Unknown write32 to ffffffd0 at time 973286, =00000000(0)
[MEM] Unknown write32 to ffffffcc at time 973287, =00000000(0)
[MEM] Unknown write32 to ffffffc8 at time 973288, =00000000(0)
[MEM] Unknown write32 to ffffffc4 at time 973289, =00000000(0)
[MEM] Unknown write32 to ffffffc0 at time 973297, =80010000(-2147418112)
[MEM] Unknown write32 to ffffffbc at time 973298, =00000000(0)
[MEM] Unknown write32 to ffffffb8 at time 973300, =00000000(0)
[MEM] Unknown write32 to fffff5ec at time 973309, =00000000(0)
[MEM] Unknown write32 to fffff5e8 at time 973317, =00000000(0)
[MEM] Unknown write32 to fffff5fc at time 973320, =80010030(-2147418064)
[MEM] Unknown write32 to fffff5f8 at time 973328, =00000000(0)
[MEM] Unknown write32 to fffff5f4 at time 973329, =00000000(0)
[MEM] Unknown write32 to fffff5f0 at time 973330, =80010000(-2147418112)
[MEM] Unknown write32 to fffff5c8 at time 973348, =80011184(-2147413628)
[MEM] Unknown write32 to fffff5cc at time 973349, =00000000(0)
[MEM] Unknown write32 to fffff5c4 at time 973769, =8001208c(-2147409780)
[MEM] Unknown write32 to fffff5ac at time 975113, =bfc07320(-1077906656)
[MEM] Unknown read32 from fffff5ac at time 975346
`

Creating a new project seems to require an (undocumented) step on Linux

This is a small issue and I was able to resolve it eventually - but it did seem to take some time to figure out.

I've just moved over from Windows to Linux (Ubuntu) and had a bit of trouble getting the CMake scripts to work. (It's not a tool I'm very familiar with)

When I ran cmake --preset default . I would get the output

$ cmake --preset default .

Preset CMake variables:
  CMAKE_BUILD_TYPE="Debug"
  PSN00BSDK_TARGET="mipsel-none-elf"
  PSN00BSDK_TC=""

CMake Error at CMakeLists.txt:14 (psn00bsdk_add_executable):
  Unknown CMake command "psn00bsdk_add_executable".

-- Configuring incomplete, errors occurred!

This was surprising because the library path environment variable was set up correctly:

$ echo $PSN00BSDK_LIBS
/opt/psn00bsdk/lib/libpsn00b

Turns out (?) I needed to run an extra step, which I actually found in the instructions for building the examples:

cmake -S . -B ./build -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=/opt/psn00bsdk/lib/libpsn00b/cmake/sdk.cmake

I think this works because it adds a CMake cache entry CMAKE_TOOLCHAIN_FILE:FILEPATH="/cmake/sdk.cmake". Again, I'm not sure if it's 'supposed' to rely on this, I know next to nothing about CMake.

Weirdly this isn't strictly required on Windows. On Windows I have build scripts that delete the /build dir every time, but this caused issues on Linux.

tl;dr: the Installation.md may be missing a step

Documentation of rather complex functions do not exist

First of all. I love this project. You seem to put a lot of effort into this.
But to make it usable for other people, there is more documentation required.
Especially with functions like CompMatrixLV and ApplyMatrixLV. There is no documentation at all about these and I have a hard time.
I would encourage to use something like Doxygen to describe the functionality and replace the manually written documentation with a automatic generated one.
The nice thing about Doxygen is that some IDEs are even capable of presenting these descriptions as you write your code.

If you are not entirely sure about how to start with a Doxygen project I would offer to kickstart it for you with a pull request and some examples with the functions I do understand.

Realloc does not correctly request sized block with malloc in fresh-alloc-copy state.

During the invocation of realloc, the last case for resizing a block to a new given size is done via a call to malloc(...) and then a subsequent memcpy(...) between the old and new blocks.

However, the invocation of malloc is passed the _size parameter instead of size which already has the header bytes added:

size_t      _size = _align(size + sizeof(BlockHeader), 8); // <-- Full memory block size calculated
BlockHeader *prev = (BlockHeader *) ((uintptr_t) ptr - sizeof(BlockHeader));

// ... snip .. other resizing cases

// No luck.
void *new = malloc(_size); // <-- This is incorrect, has sizeof(BlockHeader) additionally, should be size
if (!new) return 0;

__builtin_memcpy(new, ptr, prev->size);
free(ptr);
return new;

The issue is that malloc(...) also adds the sizeof(BlockHeader) padding to a requested size:

__attribute__((weak)) void *malloc(size_t size) {
	if (!size) return 0;

	// Extra sizeof(BlockHeader) padding added here
	size_t _size = _align(size + sizeof(BlockHeader), 8);

	// ... snip ... other malloc code
}

So an initial request size of 92 bytes plus the 16 bytes for the header, aligned to 8 bytes is 112 bytes total. Passing that to malloc, 112 bytes plus the 16 bytes for the header, aligned to 8 bytes is 128 bytes.

So we have over allocated a total of 16 bytes:

#include <stdio.h>

#define _align(x, n) (((x) + ((n) - 1)) & ~((n) - 1))

int main() {
    int req = 92 + 16;
    int _size = _align(req, 8);
    int next_size = _size + 16;
    int m_size = _align(next_size, 8);
    
    printf("%d => %d, %d => %d\n", req, _size, next_size, m_size);

    return 0;
}

Result: 108 => 112, 128 => 128.

Assuming that everything I've stated is correct (happy to be corrected if not), then this would be good for a PR to fix, a simple one liner at that.

Needed an example of playing multiple vag files, in the current state of the SDK.

Hi.
This is not an issue but a call for help.
I cannot find a way to play vsg files with the SDK.
I am very new to ps1 homebrew and only read your tutorial and had a look at the nolibgs_hello_worlds.
It will help me very much if you can provide an example, cause I do not want to use the PSYQ + Nuggets (even thought it works well).
Thanks.

Core math library missing

Hi this is my first dabble into PSX coding, sorry if I am missing something obvious

I need implementations of cos(), sqrt(), asin(), atan2(), sin() and pow() to build a project, what solutions do other people use for these basic functions?

I cannot find a core math library in here (no libm or libmath), and the other PSX SDKs seem to provide one, do I need to roll my own cos() and sin() etc?

Black Screen?

I am trying to run the template in ePSXe but I only get a black screen. I am following the instructions in installation.md under "Creating a project". Here is the output when I do cmake --preset default .:

`Preset CMake variables:

  CMAKE_BUILD_TYPE="Debug"
  CMAKE_TOOLCHAIN_FILE="C:\RandomMe\PSn00bSDK-0.20-win32\lib\libpsn00b/cmake/sdk.cmake"
  PSN00BSDK_TARGET="mipsel-none-elf"
  PSN00BSDK_TC=""

System is unknown to cmake, create:
Platform/PlayStation to use this system, please post your config file on discourse.cmake.org so it can be added to cmake
Your CMakeCache.txt file was copied to CopyOfCMakeCache.txt. Please post that file on discourse.cmake.org.
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/gfray/Documents/Visual Studio 2022/Projects/PSnoobTest/template/build`

and then when I:
cmake --build ./build

`C:\Users\gfray\Documents\Visual Studio 2022\Projects\PSnoobTest\template>cmake --build ./build
[1/1] Building CD image template
MKPSXISO 2.02 - PlayStation ISO Image Maker
2017-2022 Meido-Tek Productions (John "Lameguy" Wilbert Villamor/Lameguy64)
2021-2022 Silent, Chromaryu, G4Vi, and spicyjpeg

Building ISO Image: template.bin + template.cue
Scanning tracks...

  Track #1 data:
    Identifiers:
      System       : PLAYSTATION
      Application  : PLAYSTATION
      Volume       : PSN00BSDK_TEMPLATE
      Volume Set   : PSN00BSDK_TEMPLATE
      Publisher    : MEIDOTEK
      Data Preparer: PSN00BSDK 0.20
      Copyright    : README.TXT;1

    Parsing directory tree...
      Files Total: 3
      Directories: 0
      Total file system size: 2495472 bytes (1061 sectors)

Writing ISO
    Writing files...
      Packing C:\Users\gfray\Documents\Visual Studio 2022\Projects\PSnoobTest\template\system.cnf... Done.
      Packing template.exe... Done.
      Packing template.map... Done.

    Writing CDDA tracks...

    Writing directories... Ok.
ISO image generated successfully.
Total image size: 2495472 bytes (1061 sectors)`

For what it's worth. running the .cue file gives me this in ePSXe's debug:

`* Running ePSXe emulator version 2.0.5.
 * Memory handlers init.
 * ePSXe: using HLE BIOS (compatibility limited)
 * Loading Single CUE File ok
 * Loading ISO Format [MDF/BIN/IMG2352] ok
 * First/Last track: 1 1
 * Track 1: (DATA)  - Start 1: (00,02,00) -  Length 00:12
 * NTSC cdrom detected. (SLU__006.74)
 * GPU supports GTE Accurate
 * Doing init gpu[0]...
 * Init OpenGLv2...
OpenGL Screen Resolution 800x600 Ratio: StretchVendor: Intel
Renderer: Intel(R) UHD Graphics 620
 * Gpu open[0]...
 * Direct input init ok.
 * Init core spu ...  ok
 * Frames per second (14.942) - Time 59 frames -> 4.147 seconds.
 * Frames per second (18.1040) - Time 59 frames -> 3.220 seconds.
 * Frames per second (18.2552) - Time 59 frames -> 3.136 seconds.
 * Frames per second (18.2642) - Time 59 frames -> 3.131 seconds.
 * Frames per second (18.1454) - Time 59 frames -> 3.197 seconds.
 * Frames per second (19.024) - Time 59 frames -> 3.104 seconds.
 * Frames per second (18.2444) - Time 59 frames -> 3.142 seconds.
 * Frames per second (17.2764) - Time 59 frames -> 3.308 seconds.
 * Frames per second (17.1353) - Time 59 frames -> 3.391 seconds.
 * Frames per second (17.3121) - Time 59 frames -> 3.287 seconds.
 * Frames per second (18.410) - Time 59 frames -> 3.255 seconds.
 * Frames per second (18.644) - Time 59 frames -> 3.242 seconds.
 * Frames per second (18.482) - Time 59 frames -> 3.251 seconds.
 * Frames per second (17.2220) - Time 59 frames -> 3.340 seconds.
 * Frames per second (16.1272) - Time 59 frames -> 3.608 seconds.
 * Frames per second (17.3172) - Time 59 frames -> 3.284 seconds.`

Any idea what is going wrong? I am running a 64 bit Windows 10. I am using for the sdk "PSn00bSDK-0.20-win32", is that wrong for my system? What would be correct? Thank you!

Wrong documentation

/**
 * @brief Gets sine of angle (fixed-point, high precision version)
 *
 * @details Returns the sine of angle a.
 *
 * @param a Angle in fixed-point format (131072 = 360 degrees)
 * @return Sine value in 20.12 fixed-point format (4096 = 1.0).
 */
int isin(int a);

I think this documentation is wrong, it is the same on hisin. I don't know the exact values to make a PR.
In my tests it is 131072 for isin/icos and 131072<<5 for hisin and hicos.
If this values are correct I can make a PR

Compiling in windows 10 64bit

Hi!.
Love this sdk, very impressive samples and awesome project.

I posted a message at http://www.psxdev.net/ but I think it is better here. I could not compile the sdk by following the steps in the readme, so I had to compile file by file until I got all libs and utils.

There was no error or warning message while compiling utils and libs, and everything looked good... But compiling a sample shows this error (looks like a very bad one :)).

C:\PSn00bSDK\examples\hello>make mipsel-unknown-elf-ld -g -Ttext=0x80010000 -gc-sections -T C:\MinGW\mipsel-unknown-elf/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x -L/c:/PSn00bSDK/lib build/main.o -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lc -o hello.elf C:\MinGW\mipsel-unknown-elf\bin\mipsel-unknown-elf-ld.exe: warning: cannot find entry symbol _start; defaulting to 0000000080010000 elf2x -q hello.elf

The exe is generated but it does nothing or crashes emulators.
I think I changed all paths correctly (I didn't want mipsel-unknown-elf folder in C:).

Thanks a lot.

EDIT: Sorry for the issue... It was my fault adding the wrong libc :/.

Buffer Overflow in lzpack

Present on master@d9232579a11b8d9dceefdee308d54bd91979c85e

When making examples/n00bdemo I get the following error:

lzpack data.xml
LZPack v0.61b - File Compression and Packing Utility
2016-2019 Meido-Tek Productions (Lameguy64)

Creating textures.qlp in QLP format...
   Packing data/petscum16c.tim as petscum... Done.
   Packing data/bungirl.tim as bungirl... Done.
   Packing data/clktower.tim as clocktex... Done.
   Packing data/riftbld1.tim as riftbldg1... Done.
   Packing data/riftbld2.tim as riftbldg2... Done.
   Packing data/hatkid.tim as hatkid... Done.
   Packing data/celmapi.tim as celmap... Done.
   Packing data/lamelotl16c.tim as lamelotl... Done.
   Packing data/n00blogo-pixel.tim as n00blogo... Done.
   Packing data/font.tim as font... Done.
Packed 10 file(s) totaling 66900 bytes.
Creating data.lzp in LZP format...
   Packing data/mtekdisk.smd as mtekdisk... Ok. (45.62%)
   Packing data/mtektext.smd as mtektext... Ok. (46.07%)
   Packing data/star.smd as starsprite... Ok. (50.45%)
   Packing data/psn00blogo.smd as psn00blogo... Ok. (40.94%)
   Packing data/logo.smd as n00blogo... Ok. (37.08%)
   Packing data/petscum.smd as lightworld... Ok. (32.43%)
   Packing data/bulb.smd as lightbulb... Ok. (46.02%)
   Packing data/bungirl.smd as bungirl... Ok. (63.61%)
   Packing data/star_mask.smd as starmask... Ok. (52.73%)
   Packing data/timerift.smd as timerift... Ok. (47.88%)
   Packing data/rbowshade.smd as rbowshade... Ok. (44.23%)
   Packing data/hatkid.smd as hatkid... Ok. (54.04%)
   Packing textures.qlp as textures... Ok. (18.12%)
*** buffer overflow detected ***: lzpack terminated
makefile:38: recipe for target 'resources' failed
make: *** [resources] Aborted (core dumped)

GCC isn't wanting to give me debugging symbols, not sure why, so I can't give you the full backtrace. Here's what I have:

Reading symbols from ../../tools/bin/lzpack...(no debugging symbols found)...done.
[New LWP 27712]
Core was generated by `lzpack data.xml'.
Program terminated with signal SIGABRT, Aborted.
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51	../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007f8263613801 in __GI_abort () at abort.c:79
#2  0x00007f826365c897 in __libc_message (action=action@entry=(do_abort | do_backtrace), fmt=fmt@entry=0x7f8263789988 "*** %s ***: %s terminated\n") at ../sysdeps/posix/libc_fatal.c:181
#3  0x00007f8263707cff in __GI___fortify_fail_abort (need_backtrace=need_backtrace@entry=true, msg=msg@entry=0x7f8263789905 "buffer overflow detected") at fortify_fail.c:33
#4  0x00007f8263707d21 in __GI___fortify_fail (msg=msg@entry=0x7f8263789905 "buffer overflow detected") at fortify_fail.c:44
#5  0x00007f8263705a10 in __GI___chk_fail () at chk_fail.c:28
#6  0x00007f8263704e49 in __strncpy_chk (s1=<optimized out>, s2=<optimized out>, n=<optimized out>, s1len=<optimized out>) at strncpy_chk.c:26
#7  0x00005626e74118dd in ?? ()
#8  0x00005626e741246f in ?? ()
#9  0x00005626e7411358 in ?? ()
#10 0x00007f82635f4b97 in __libc_start_main (main=0x5626e7411200, argc=2, argv=0x7fff20bead78, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff20bead68) at ../csu/libc-start.c:310
#11 0x00005626e74114ba in ?? ()
(gdb) 

I can't be 100% sure, but I think the issue is caused by

strncpy(head.id, "LZP", 4);
. The strncpy call gives a buffer length of 4, but LZP_HEAD.id is a char[3]. I am working on a PR now.

System Details:

qbradq@qbradq-AB350-Gaming:~/PSn00bSDK/examples/n00bdemo$ uname --all
Linux qbradq-AB350-Gaming 4.15.0-45-generic #48-Ubuntu SMP Tue Jan 29 16:28:13 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
qbradq@qbradq-AB350-Gaming:~/PSn00bSDK/examples/n00bdemo$ gcc --version
gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

qbradq@qbradq-AB350-Gaming:~/PSn00bSDK/examples/n00bdemo$ mipsel-unknown-elf-gcc --version
mipsel-unknown-elf-gcc (GCC) 9.1.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

_mem_init grabs an extra 64KB of memory

in start.c:

int ram_used = (0x10000 + exe_size + stack_max_size) & 0xfffffffc;

seems to grab an extra 64KB even though stack_max_size is passed as 0x20000?

Is this deliberate? or just an unwanted knock-on from refactoring? Thanks!

PSXSDK compatibility/incooperability

A while ago, I was working on getting the (PSXSDK)[http://unhaut.x10host.com/psxsdk/] working on macOS and have since had it installed on my maschine to test it out.

Seeing this SDK, I wonder how well it is compatible with it. The compiler that comes out of that SDK is like so:

[email protected] ~ $ mipsel-unknown-elf-gcc -v
Es werden eingebaute Spezifikationen verwendet.
COLLECT_GCC=mipsel-unknown-elf-gcc
COLLECT_LTO_WRAPPER=/usr/local/psxsdk/libexec/gcc/mipsel-unknown-elf/7.2.0/lto-wrapper
Ziel: mipsel-unknown-elf
Konfiguriert mit: /Users/Ingwie/Work/Compilers/gcc-7.2.0/configure --disable-libada --disable-libssp --target=mipsel-unknown-elf --prefix=/usr/local/psxsdk --with-float=soft --with-newlib --without-headers --disable-libstdcxx --enable-languages=c,c++
Thread-Modell: single
gcc-Version 7.2.0 (GCC) 
[email protected] ~ $ mipsel-unknown-elf-gcc --version
mipsel-unknown-elf-gcc (GCC) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
Dies ist freie Software; die Kopierbedingungen stehen in den Quellen. Es
gibt KEINE Garantie; auch nicht fรผr MARKTGร„NGIGKEIT oder FรœR SPEZIELLE ZWECKE.

(Excuse all the german here, I tend to forget how to force GCC into outputting stuff in english...)

In theory, this should be able to compile this SDK - but what can I expect from it? PSXSDK offers CD-ROM access - so what if I was to use psn00bSDK's assembly based libraries but PSXSDK's CD-ROM APIs?

Kind regards,
Ingwie

smxlink Segmentation fault

smxlink cositantly crashes at certain strcasecmp.
I think I fixed the issue by modifying the if, something like this:

const char* attribute_shading = smxPrimitive->Attribute( "shading" );
if( attribute_shading && strcasecmp( "F", attribute_shading ) == 0 ) {
// ...

over

if( strcasecmp( "F", smxPrimitive->Attribute( "shading" ) ) == 0 ) {
// ...

The main issue seemed to be that smxPrimitive->Attribute( "shading" ) was returning NULL.

Moreover, once "fixed" the outputted file seemed to not have been converted correctly.
Using the n00bdemo as an example, I converted some of the existing smx files to smd and found that my converted files did not match the premade ones. Mine were slightly larger.
star freezes the program when they are supposed to appear during the starting animation.
petscum doesn't cause problems, but was completely invisible or simply not there.

Note:
I am using Linux (Pop!_OS 21.04)
Everything else works like a charm, all example projects compile, etc.

How to run the demos on a real playstation?

I used mkpsxiso to create bin/cue files of the balls demo, with SCEA licence data (because it uses an NTSC video mode; I initially tried without any licence data which didn't work either), and I can run it in PCSXR, but when I burn it to a CD-R and try to run it on my PAL Playstation using tonyhax, it just hangs on "Starting". Any idea what I'm missing?

iso.xml


<iso_project image_name="balls.bin" cue_sheet="balls.cue">

	<track type="data">

		<identifiers
			system			="PLAYSTATION"
			application		="PLAYSTATION"
			volume			="PSN00BSDK"
			volume_set		="PSN00BSDK"
			publisher		="MEIDOTEK"
		/>

		<license file="license_data.dat"/>

		<directory_tree>

			<file name="system.cnf"	type="data" source="system.cnf"/>
			<file name="balls.exe" type="data" source="balls.exe"/>
			
			<dummy sectors="1024"/>

		</directory_tree>

	</track>

</iso_project>

system.cnf

BOOT=cdrom:\balls.exe;1
TCB=4
EVENT=10
STACK=801FFFF0

Struggling With Chapter 1.3 Tutorial, Sprite Is 'Glitched'

First of all, thank you for all of your work on this project. I have been banging my head against the wall trying to implement your chapter 1.3 tutorial. I have tried and re-read this page many times only to get the same result. I successfully followed every other chapter up to this one in the guide however.

As you most likely know, the tutorials are a bit outdated when used with the latest PSN00bSDK. So I will try to go as in-depth as possible to make this as easily debuggable for you.

I first start by creating a new directory 'test'. I copy the entire contents of the balls example into the test directory, as well as a copy of cmake-presets.json.

I then copy the entire sample code from chapter 1.3 into the 'main.c' file and save it, and then do the following changes:

#include <libetc.h> // Includes some functions that controls the display
#include <libgte.h> // GTE header, not really used but libgpu.h depends on it
#include <libgpu.h> // GPU library header

needs to be changed to:

#include <psxetc.h> // Includes some functions that controls the display
#include <psxgte.h> // GTE header, not really used but libgpu.h depends on it
#include <psxgpu.h> // GPU library header

for the new toolchain.

I also change this:
// Read TIM parameters (PsyQ)
OpenTIM(tim);
ReadTIM(tparam);

// Read TIM parameters (PSn00bSDK)
//GetTimInfo(tim, tparam);

to

// Read TIM parameters (PsyQ)
// OpenTIM(tim);
//ReadTIM(tparam);

// Read TIM parameters (PSn00bSDK)
GetTimInfo(tim, tparam);

For PSN00bSDK functionality.

I also change this line CMakeLists.txt:
psn00bsdk_target_incbin(balls PRIVATE ball16c ball16c.tim)

to

psn00bsdk_target_incbin(balls PRIVATE tim_my_image ball16c.tim)

It compiles fine now. I did see this:
// PSn00bSDK requires having all u_long types replaced with // u_int, as u_long in modern GCC that PSn00bSDK uses defines it as a 64-bit integer.

So I find and replace recursively u_long to u_int32_t in my text editor. I tried to replace it with just u_int but I get some warnings.

So at this point I need to change the original balls16c.tim to the image in the tutorial. I downloaded the png from the tutorial. I also downloaded and opened timtool 0.10a windows (via wine, I'm using Linux and didn't yet compile a native version). Now in Timedit I import the png and using all default options save it as an 8 bit TIM. I double checked that the following is true:

a 8-bit TIM file with image coordinates of 640,0 and CLUT coordinates of 0,480.

attached are some screenshots of me doing this in timedit.

import options

save imported tim

tim-imported

Now I believe that I should finally be able to see the texture in DuckStation. However I see this screen:

duckstation

For the life of me I can't figure it out. Real hardware is the same.

Also, attached is my entire little 'test' folder for help with further debugging. Thank you for your time reading all of this. It may be a small issue on my part, but alas I have exhausted everything I know on this subject (which is very little).

test.zip

I have compiled the SDK and toolchain with a script I wrote that does this:
build-psn00bsdk.zip

And I set the env vars with another script I wrote

psn00b-env.zip

Could not find _gcc using the following names: mipsel-none-elf-gcc

I'm almost giving up on compiling this, can someone help

I think the cause of this errors, is because during the instalation appeared a warning saying that it could not edit the path, because it was too long, so, if someone post the path entries (I think is that what is called), I could edit it mannualy.
Screenshot_1

Weird issue

When I compile the template I get a weird message in CMake.
Here's the log:

Preset CMake variables:

  CMAKE_BUILD_TYPE="Debug"
  CMAKE_TOOLCHAIN_FILE="C:\PSn00bSDK\lib\libpsn00b/cmake/sdk.cmake"
  PSN00BSDK_TARGET="mipsel-none-elf"
  PSN00BSDK_TC=""

CMake Error: CMake was unable to find a build program corresponding to "Ninja".  CMAKE_MAKE_PROGRAM is not set.  You probably need to select a different build tool.
-- Configuring incomplete, errors occurred!
See also "/d/template/build/CMakeFiles/CMakeOutput.log".

It seems it can't find the program names "Ninja". Do I need to install something or am I doing something wrong?

elf2x: wrong ELF parsing leads to huge t_size, producing ~2GiB output

Hi!

I followed your guide and have built mipsel-unknown-elf-gcc (experimental 11.0.1 20210411) successfully on MSYS2, including libc (it worked for me out-of-the-box). It compiles C programs, including the provided beginner/hello example, without warnings or errors.

When I tried to run the ELF through elf2x though, the tool started allocating a ~2GiB chunk of memory and then produced a binary with the same size. I've attached an example ELF (of the hello example) below. No matter what compile options (including those from the example makefiles) or program I've tried, the produced ELF causes the same issue. I also used both my own modified elf32elmip.x and the one from psn00bsdk to no avail.

I'm not familiar at all with the ELF format, but did some digging. I modified elf2x.c to add some printf debugging:

	// Load program headers and determine binary size and load address

	fseek( fp, head.prg_head_pos, SEEK_SET );
	for( i=0; i<head.prg_entry_count; i++ ) {
		printf("i = %d\n", i);
		
		fread( &prg_heads[i], 1, sizeof(PRG_HEADER), fp );

		if( prg_heads[i].flags == 4 ) {
			continue;
		}

		if( prg_heads[i].p_vaddr < exe_taddr ) {
			printf("p_vaddr < exe_taddr, p_vaddr = %d\n", prg_heads[i].p_vaddr);
			exe_taddr = prg_heads[i].p_vaddr;
		}

		if( prg_heads[i].p_vaddr > exe_haddr ) {
			printf("p_vaddr > exe_taddr, p_vaddr = %d\n", prg_heads[i].p_vaddr);
			exe_haddr = prg_heads[i].p_vaddr;
		}
		printf("exe_haddr: %d\n", exe_haddr);
	}
	exe_tsize = (exe_haddr-exe_taddr);
	printf("exe_tsize: %d\n", exe_tsize);
	exe_tsize += prg_heads[head.prg_entry_count-1].p_filesz;

The program's output (with main.Og.elf):

i = 0
i = 1
p_vaddr < exe_taddr, p_vaddr = 4194304
p_vaddr > exe_taddr, p_vaddr = 4194304
exe_haddr: 4194304
i = 2
p_vaddr > exe_taddr, p_vaddr = -2147418112
exe_haddr: -2147418112
i = 3
p_vaddr > exe_taddr, p_vaddr = -2147385100
exe_haddr: -2147385100
exe_tsize: 2143387892
pc:800115f0 t_addr:00400000 t_size:2143390364

Looks like either the p_vaddr of the third and fourth program headers are corrupted somehow, or elf2x is parsing the values from a place in the ELF it's not supposed to read from. mipsel-unknown-elf-objdump -x parses the ELF just fine, so I think it's the latter case
main.Og.zip

not able to compile a simple test program

mipsel-none-elf-gcc is not accepting -EL as an option when trying to build CMakeTmp/testCCompiler.c. unrecognized option '-EL'. Also getting warning that the target architecture is unknown.

Examples: Builds fail due to LD error

Cross-Compiler GCC Version: 8.2.0 (also tried with 9.3.0)
Cross-Compiler Binutils Version: 2.31
Operating System: Debian 10 (Buster) Linux

Instructions for building the toolchain and SDK were all (hopefully) followed, .mk versions set to 8.2.0.
The errors mainly complain about:
undefined reference to '__CTOR_LIST__'
undefined reference to '__DTOR_LIST__'
Full log can be found here.

issue installing?

sorry, new to linux.
I thought i installed and exported everything I needed to but when trying to make binutils i get

../binutils/configure --prefix=/usr/local/mipsel-unknown-elf --target=mipsel-unknown-elf --with-float=soft
creating cache ./config.cache
checking host system type... Invalid configuration x86_64-unknown-linux-gnu': machine x86_64-unknown' not recognized

checking target system type... mipsel-unknown-elf
checking build system type... Invalid configuration x86_64-unknown-linux-gnu': machine x86_64-unknown' not recognized

checking for a BSD compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking whether make sets ${MAKE}... yes
checking for working aclocal... found
checking for working autoconf... found
checking for working automake... found
checking for working autoheader... found
checking for working makeinfo... found
checking for ranlib... ranlib
checking for gcc... gcc
checking whether the C compiler (gcc ) works... yes
checking whether the C compiler (gcc ) is a cross-compiler... no
checking whether we are using GNU C... yes
checking whether gcc accepts -g... yes
checking for ld used by GCC... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... yes
checking for BSD-compatible nm... /usr/bin/nm -B
checking whether ln -s works... yes
ltconfig: you must specify a host type if you use --no-verify' Try ltconfig --help' for more information.
configure: error: libtool configure failed

ZSF3 and ZSF4 during InitGeom might not be correct

I've experimented a bit with your library and I think I found a bug.
In initgeom.s there is this InitGeom function.

	li   $v0, 0x155				# Set ZSF3 and ZSF4 defaults
	ctc2 $v0, $29
	li   $v0, 0x100
	ctc2 $v0, $30

I do believe that ZSF3 and ZSF4 have to be multplied by 4 to be accurate. It almost feels like an copy pasta error somehow.
During most of the examples you are performing a divison by 4 on Z during addPrim. It seems to be doubled here.
For example, if you use gte_rtps and gte_stsz you get the correct result while you get the result divided by 4 if you use gte_rtpt and gte_avsz3 even so all 3 points are at the same coordinate.

I just wanted to point that out. Please correct me if I'm wrong. I've stumbled on this issue as I've written something which uses billboards and polygon meshes in combination. The billboards have a Z coordinate which is 4 times bigger than the mesh.
I've combined your gte and billboard example to implement it.

`realloc` size in `BlockHeader` incorrect causing `_find_fit` negative sizes

Hi all,

I'm back again with another allocator bug (I think ๐Ÿคฃ).

Background

With calls to _find_fit(BlockHeader* head, size_t size), blocks are traversed to check free space between each relative to the input parameter size. The nature of the implementation expects that the offset calculated from an allocated block to a candidate free address block is always before/smaller than the base address of the next allocated block.

uintptr_t next_bot = (uintptr_t) prev->next;
next_bot          -= (uintptr_t) prev->ptr + prev->size;
//                   |_________________________________|
//                       This should be <= prev->next

So, we should expect that (prev->ptr + prev->size) <= prev->next, however this is ONLY the case when two conditions are met universally within the allocator:

  1. The BlockHeader.size parameter represents the 8-byte aligned requested size (not including sizeof(BlockHeader)).
  2. The size parameter given to _find_fit(...) is the requested size + sizeof(BlockHeader) aligned to 8 bytes.

Implementation Issue

Within the malloc(size_t size) implementation, we can see that the second condition is correctly met:

// ... snip from alloc ...
size_t _size = _align(size + sizeof(BlockHeader), 8);
// ... snip ...
BlockHeader *prev = _find_fit(_alloc_head, _size);
// ... snip ...

In the implementation of realloc(...) however, the first condition is not met. All of the instances where the BlockHeader.size field is set, the value is the 8-byte aligned value of size + sizeof(BlockHeader). This is also present in the free(...) implementation (not shown here, see the PR linked at the bottom of this issue description).

// malloc.c
// ... snip from realloc ...
// New memory block shorter?
if (prev->size >= _size) {
	TrackHeapUsage(size - prev->size);
	prev->size = _size; // <-- HERE

	if (!prev->next)
		sbrk((ptr - sbrk(0)) + _size);

	return ptr;
}

// New memory block larger; is it the last one?
if (!prev->next) {
	void *new = sbrk(_size - prev->size);
	if (!new)
		return 0;

	TrackHeapUsage(size - prev->size);
	prev->size = _size; // <-- HERE
	return ptr;
}

// Do we have free memory after it?
if (((prev->next)->ptr - ptr) > _size) {
	TrackHeapUsage(size - prev->size);
	prev->size = _size; // <-- HERE
	return ptr;
}
// ... snip ...

The result of this, we can get integer underflow occurring with the offset to the free block in _find_fit(...) when two blocks of memory are sequentially allocated and reallocated several times.

Specifically, rev->ptr + prev->size exceeds the actual free space, since size should represent free space, but can have up to an additional sizeof(BlockHeader) (aligned) space which causes next_bot to underflow on the subtraction and then exceed prev->next, thus the following check (next in the _find_fit implementation) will be true:

if (next-bot >= size) {
	return prev;
}

As a result, with sequentially allocated and re-sized blocks this can cause the header of the reallocated error to be placed within the header or allocated space of the next block. This thus causes invalid read/write to addresses that are invalid or potentially non-existent (from userspace) depending on where exactly the reallocated header is placed within the next block and what the existing data in that block was.

Example and Memory Layout

Using a minimal example (with the help of a library cvector) and adding some logs to both the malloc.c implementation in PSn00bSDK and the cvector library, we can see the issue itself. A buildable/complete example can be found in my current project https://github.com/EngineersBox/PSX-Minecraft/tree/ab1052d1f9a062b33040847bf7adb13d53d61691 at commit ab1052d1f9a062b33040847bf7adb13d53d61691 (That link goes directly to the repo at that commit).

The code is as follows:

#include <stdint.h>
#include <stdio.h>
#include <psxgte.h>
#include <cvector.h>

#include "core/display.h"

typedef struct {
    SMD smd;
    cvector(SVECTOR) vec1;
    cvector(SVECTOR) vec2;
} TestMinRep;

void __destruct(void *elem) {
}

void initRep(TestMinRep *rep) {
    rep->vec1 = NULL;
    rep->vec2 = NULL;
    cvector_init(rep->vec1, 1, __destruct);
    cvector_init(rep->vec2, 1, __destruct);
}

int main() {
	init(); // Some basic init stuff
    TestMinRep obj;
    initRep(&obj);
    uint32_t i1 = 0;
    uint32_t i2 = 0;
    int should_break = 0;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 4; j++) {
            printf("VERTEX %d: %p\n", j, obj.vec1);
            cvector_metadata_t *meta = cvector_vec_to_base(obj.vec1);
            printf("  [BEFORE] Size: %d, Cap: %d, Dest: %p\n", meta->size, meta->capacity, meta->elem_destructor);
            cvector_metadata_t *meta2 = cvector_vec_to_base(obj.vec2);
            printf("  [Normal: %p] [BEFORE] Size: %d, Cap: %d, Dest: %p\n", obj.vec2, meta2->size, meta2->capacity,
                   meta2->elem_destructor);
            cvector_push_back(obj.vec1, (SVECTOR){});
            meta = cvector_vec_to_base(obj.vec1);
            printf("  [AFTER] Size: %d, Cap: %d, Dest: %p\n", meta->size, meta->capacity, meta->elem_destructor);
            meta2 = cvector_vec_to_base(obj.vec2);
            printf("  [Normal: %p] [AFTER] Size: %d, Cap: %d, Dest: %p\n", obj.vec2, meta2->size, meta2->capacity,
                   meta2->elem_destructor);
            SVECTOR *curr = &obj.vec1[i1];
            curr->vx = i;
            curr->vy = j;
            curr->vz = i1;
            i1++;
			// This stops the loop at exactly the right spot
			// comment this out to let it run in full (lots of corruption)
            if (i == 2 && j == 1) {
                should_break = 1;
                break;
            }
        }
		// This stops the loop at exactly the right spot
		// comment this out to let it run in full (lots of corruption)
        if (should_break) {
            break;
        }
        printf("NORMAL: %p\n", obj.vec2);
        cvector_metadata_t *meta2 = cvector_vec_to_base(obj.vec2);
        printf("  [BEFORE] Size: %d, Cap: %d, Dest: %p\n", meta2->size, meta2->capacity, meta2->elem_destructor);
        cvector_push_back(obj.vec2, (SVECTOR){});
        meta2 = cvector_vec_to_base(obj.vec2);
        printf("  [AFTER] Size: %d, Cap: %d, Dest: %p\n", meta2->size, meta2->capacity, meta2->elem_destructor);
        SVECTOR *curr1 = &obj.vec2[i2];
        curr1->vx = i;
        curr1->vx = i2;
        curr1->vz = rand();
        i2++;
    }
    while (1) {
        display(&dctx); // Swap buffers, etc
    }
    return 0;
}

Running this example, opening logs and dumping the memory layout we can see the following.

Broken Memory Layout With Logs

The left side memory editor (Memory Editor #1) shows the spot where the size of the normals cvector instance was held previously (just ahead of the BlockHeader), the top-right memory editor showcases the previous location of vertices cvector instance, the bottom left has the new location of the vertices cvector instance.

In the logs on the right side, we can see the integer underflow occur on the third iteration within the _find_fit(...) call when resizing the vertices cvector memory. Here lies the issue, since the if statement is true with the effectively negative (converted to uintptr_t) size becoming very large, thus matching the condition for next_bot >= size is met. The address that is returned here is partially within the BlockHeader of the next memory block, which is sequentially allocated in a struct and thus corresponds to the normals cvector instance.

Applying the fix to the realloc(BlockHeader* head, size_t size) implementation, we can see that these issues are now resolved.

Fixed Memory Layout With Logs

Changes

I've submitted a pull request to fix these issues, and as per the last issue I raised, it's probably a good idea to forward these fixes onto the original implementation used in the PCSX-Redux emulator (I think that's what it was).

PR link is here: #81

No realloc in libc

As per title, realloc is not implemented. It'd be nice, since malloc->memcpy->free can be way less efficient.

Issue making tools (Windows)

I'm following the Windows installation process over in the README file and when compiling tools I get this error.

make -C lzpack make[1]: Entering directory '/c/psn00bsdk/tools/lzpack' g++ -O2 -I/c/tinyxml2 -I../../libpsn00b -c main.cpp -o build/main.o make[1]: g++: No such file or directory make[1]: *** [makefile:32: build/main.o] Error 127 make[1]: Leaving directory '/c/psn00bsdk/tools/lzpack' make: *** [makefile:7: lzpack] Error 2

Probably the error suggests I haven't installed something important though I've done every single thing the installation guide told me to do.

Thanks in advance. Hope you answer soon.

error: 'SS_SERIAL_A' undeclared

I'm trying to compile a xalib under PSN00BSDK, and I get this following error during compilation:

/usr/local/mipsel-psx-elf/bin/mipsel-psx-elf-gcc -g -msoft-float -march=r3000 -mtune=r3000 -mabi=32  -mdivide
-breaks -O2 -ffreestanding -fno-builtin -nostdlib -fdata-sections -ffunction-sections -fsigned-char -fno-strict-
                -G0 -mno-abicalls -mno-gpopt -I../include -I../lzp -c xa.c -o build/xa.o&nbsp;
xa.c: In function 'XAcallback':
xa.c:29:5: warning: implicit declaration of function 'SsSetSerialVol' [-Wimplicit-function-declaration]
   29 |     SsSetSerialVol(SS_SERIAL_A, 0, 0);
      |     ^~~~~~~~~~~~~~
xa.c:29:20: error: 'SS_SERIAL_A' undeclared (first use in this function)
   29 |     SsSetSerialVol(SS_SERIAL_A, 0, 0);
      |                    ^~~~~~~~~~~
xa.c:29:20: note: each undeclared identifier is reported only once for each function it appears in
xa.c: In function 'XAsetup':
xa.c:86:16: warning: assignment to 'CdlCB' {aka 'void (*)(int,  unsigned char *)'} from 'long int' makes pointer
 from integer without a cast [-Wint-conversion]
   86 |  XAoldCallback = CdReadyCallback((CdlCB)XAcallback);
      |                ^
xa.c: In function 'XAremove':
xa.c:105:17: error: 'SS_SERIAL_A' undeclared (first use in this function)
  105 |  SsSetSerialVol(SS_SERIAL_A, 0, 0);
      |                 ^~~~~~~~~~~
xa.c: In function 'XAsetVolume':
xa.c:126:17: error: 'SS_SERIAL_A' undeclared (first use in this function)
  126 |  SsSetSerialVol(SS_SERIAL_A, volleft, volright);
      |                 ^~~~~~~~~~~
xa.c: In function 'XAplayChannel':
xa.c:139:19: error: 'SS_SERIAL_A' undeclared (first use in this function)
  139 |  SsSetSerialVol  (SS_SERIAL_A, 0, 0);
      |                   ^~~~~~~~~~~
make[1]: *** [makefile:42: build/xa.o] Error 1

I need some serious help

Source Code License Question

Does this mean that I have to give away the source code I made with the SDK, or is it talking about the changes I make with the SDK itself?

antivirus flags as unsafe

My antivirus flags every single file in the build unsafe and deletes them. Is there a way to make sure this doesn't happen?

Compiler options producing non-working PS-EXE & liblzp issue

I've been testing this SDK more under Linux land and I seem to find that the gcc configure options described in toolchain.txt seems to produce unstable or non-working PS-EXEs which results to the gte example to not run. Use these options for configuring the gcc toolchain instead:

../gcc-7.2.0/configure --disable-nls --disable-libada --disable-libssp --disable-libquadmath --disable-libstdc++-v3 --disable-libgcc --target=mipsel-unknown-elf --prefix=/usr/local/mips-unknown-elf --with-float=soft --enable-languages=c,c++ --with-gnu-as --with-gnu-ld

I also discovered that n00bdemo fails while loading textures to RAM as the qlpFileAddr() function which is part of liblzp appears to be returning incorrect/bugged addresses. This issue might be related to the lzpack tool producing bugged qlp archive files when compiled in Linux as that tool was primarily developed in Windows but I've yet to study this further.

cmake build error

So basically I've ran these commands:
cmake -S . -B ./build -G Ninja --install-prefix ~/disobin/psx/sdk
and then..
cmake --build ./build
... everything is alright up to this moment

[15/16] Building CXX object CMakeFiles/smxlink.dir/smxlink/main.cpp.o
[16/16] Linking CXX executable smxlink
[24/40] Performing download step (git clone) for 'mkpsxiso'
FAILED: mkpsxiso-prefix/src/mkpsxiso-stamp/mkpsxiso-download /home/edvin/Downloads/PSn00bSDK/build/mkpsxiso-prefix/src/mkpsxiso-stamp/mkpsxiso-download
cd /home/edvin/Downloads/PSn00bSDK/build/mkpsxiso-prefix/src && /usr/bin/cmake -P /home/edvin/Downloads/PSn00bSDK/build/mkpsxiso-prefix/tmp/mkpsxiso-gitclone.cmake && /usr/bin/cmake -E touch /home/edvin/Downloads/PSn00bSDK/build/mkpsxiso-prefix/src/mkpsxiso-stamp/mkpsxiso-download
Cloning into 'mkpsxiso'...
fatal: invalid reference: cmake
CMake Error at /home/edvin/Downloads/PSn00bSDK/build/mkpsxiso-prefix/tmp/mkpsxiso-gitclone.cmake:40 (message):
Failed to checkout tag: 'cmake'

[25/40] Performing install step for 'tools'
[0/1] Install the project...
-- Install configuration: ""
-- Installing: /home/edvin/Downloads/PSn00bSDK/build/install_tree/bin/elf2x
-- Installing: /home/edvin/Downloads/PSn00bSDK/build/install_tree/bin/elf2cpe
-- Installing: /home/edvin/Downloads/PSn00bSDK/build/install_tree/bin/smxlink
-- Installing: /home/edvin/Downloads/PSn00bSDK/build/install_tree/bin/lzpack
-- Installing: /home/edvin/Downloads/PSn00bSDK/build/install_tree/share/psn00bsdk/plugin
-- Installing: /home/edvin/Downloads/PSn00bSDK/build/install_tree/share/psn00bsdk/plugin/io_export_smx_v3.py
ninja: build stopped: subcommand failed.

SpuInit locks up in certain emulators in SpuCtrlSync

Calling SpuInit(); at the beginning of a program seems to lock up in certain official emulators.

If I comment out both calls to SpuCtrlSync in that function, it seems to work (on the emulator at least, haven't tested on real hardware yet):

Interestingly, the SpuWrite function has a similar comment:

        #jal            SpuCtrlSync                             # Locks up on most emulators (bit 5 in
        #move   $a0, $v0                                        # SPUSTAT likely not updating, seems to
                                                                                # be okay to not wait for it on real HW)

Not sure if it helps or is related at all, but I found this while doing a random web search:

NB. writing the SAME transfer mode value to SPUCNT does mean that one cannot sense when the write gets applied (since SPUSTAT already contained that same transfer mode setting), so, instead, one must use some hardcoded delay (the BIOS is performing some crazy super-slow delay for that purpose... but I guess that a delay of one 44100Hz cycle (around 300h clks) should be enough). [source link]

Audio streaming sample breaking on custom VAG file

Decided to give the samples a spin today, I tried the VAG streaming sample in Duckstation which indeed works, but then when I substitute my own custom VAG file, it totally blows up. I'm lucky if I can hear anything more than a second or so of audio before it just halts playback altogether, occasionally I've had it produce short bursts of screeching sounds before halting, or even interleaved playback with what sounds like portions of the PSX startup jingle?

I've attached the VAG file as well as the source WAV that was used to encode it. I used psxavenc to encode it (with psxavenc -t vagi -f 44100 -c 2 -i 4096 title_test.wav title.vag).

The included VAG file plays perfectly, so I'm really at a loss as to what I could be doing wrong. It seems like maybe a format problem, but adding some more debug info confirms it's the same samplerate, same number of channels, same chunk size, etc... I also checked with vgmstream and it has no problems decoding my VAG file so ๐Ÿคทโ€โ™€๏ธ

title_test.zip

Batch STR conversion utility

Hi. I was wondering if a utility exists that could convert a video file to a STR file from the command line? Preferably in Linux but through wine would be ok too.

I've checked through your old posts about this and several other tools, they all seem to point back to MC32 as the final step, which appears to only let you convert through a GUI (and only Windows).

I might be interested in creating such a tool myself if nothing exists, but wanted to check here first. Especially if there's some good documentation on the format.

`vsnprintf` putting terminator char in wrong place causing memory corruption

Background
I ran into a memory corruption issue in my code (compiling with psn00bsdk using C++ and PCSX Redux). Stepping through the assembly, using Redux I found the corruption to happen in vsnprintf. Looking at the code for vsnprintf it is pretty obvious what the problem is.

The bug
vsnprintf writes the characters to the output buffer calling:

put_in_string(string, ssz, character_to_write, string_pos++);	

I.e. ssz is the size of the output buffer (minus 1 so there is space for terminator), and string_pos is the current position to write to.
However, if the size of the output buffer (ssz) is less than string_pos then it will write nothing. But string_pos is still incremented.

Then, right before returning from the function it does this:

string[string_pos] = 0;

I.e., regardless of how big the output buffer string is, it indiscriminately writes the terminator character at the position where the end of the string would be had the buffer been big enough for it.

Note, I use the function like so (snprintf calls vsnprintf):

char dummy_buffy;
int32 num_chars_to_write = snprintf(&dummy_buffy, 1, some_format, some args... );

to gauge how big of a buffer I should allocate for the string.

A fix...
I currently don't have the time to fix the issue, but might look at it later.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.