diff options
| author | John Wilbert M. Villamor <lameguy64@gmail.com> | 2019-07-17 11:30:07 +0800 |
|---|---|---|
| committer | John Wilbert M. Villamor <lameguy64@gmail.com> | 2019-07-17 11:30:07 +0800 |
| commit | 0d4345a9bf2623df079c50a3bc73cbb7deca1176 (patch) | |
| tree | 6cda70b844f39fc2d65a806b91a6010066433b56 | |
| parent | b956c5391b955e793a4d54572aa58872b4c66c30 (diff) | |
| download | psn00bsdk-0d4345a9bf2623df079c50a3bc73cbb7deca1176.tar.gz | |
Added C++ support, updated build instructions and makefiles, consolidated libc and libgcc (during build process), libraries now v0.12b and more
43 files changed, 1469 insertions, 327 deletions
@@ -1,10 +1,13 @@ .svn build bin +old +scrap *.a *.o *.elf *.exe *.lzp *.qlp -*.iso
\ No newline at end of file +*.iso +*.rom
\ No newline at end of file @@ -28,7 +28,7 @@ performance reasons. ## Notable features -As of libpsn00b run-time library v0.10b +As of libpsn00b run-time library v0.11b * Extensive GPU support with polygon primitives, high-speed DMA VRAM transfers and DMA ordering table processing. All video modes for both NTSC @@ -41,10 +41,10 @@ As of libpsn00b run-time library v0.10b matrix and vector functions, all calculations performed in fixed point integer math. -* Stable and easy to use interrupt service routine with callback system for +* Stable interrupt service routine with easy to use callback system for simplified handling of hardware and DMA interrupts, no crude event handlers - or kernel hacks used and should be compatible with HLE BIOS implementations - and homebrew loaders and menus. + or kernel hacks used and should be compatible with HLE BIOS implementations, + and should play well with writing loader programs. * Complete Serial I/O support with SIOCONS driver for tty console access through serial interface. @@ -58,7 +58,7 @@ As of libpsn00b run-time library v0.10b initialization. * Uses Sony SDK library syntax for familiarity to experienced programmers - and to make porting existing homebrew to PSn00bSDK easier. + and to make porting existing homebrew projects to PSn00bSDK easier. * Works on real hardware and most popular emulators. @@ -73,52 +73,72 @@ not included in this repository for Windows users are planned, though some arrangements would need to be made first. Perhaps once PSn00bSDK is considered halfway production ready. -A precompiled copy of the GCC 7.2.0 toolchain for Windows is available -in lameguy64's website (http://lameguy64.tk) in the PSn00bSDK page. This -should make building PSn00bSDK under Windows a bit easier as building the -toolchain is the hardest part of building PSn00bSDK as its more difficult -to get it to compile correctly under Windows than on Linux and BSDs. +A precompiled copy of the GCC 7.4.0 toolchain for Windows is available +in the PSn00bSDK page of Lameguy64's website +( http://lameguy64.tk/?page=psn00bsdk ). This should make building PSn00bSDK +under Windows a bit easier as building the toolchain is the hardest part +of building PSn00bSDK as its more difficult to get it to compile correctly +under Windows than on Linux and BSDs. ## Building the SDK -### Windows (needs work/testing): +### Windows: 1. Download the following: - * MinGW GCC (32-bit or 64-bit whichever you prefer) - * MSys2 (32-bit or 64-bit whichever you prefer) - * tinyxml2 (for lzpack and smxlink) - * GCC 7.2.0 for mipsel-unknown-elf (download from Lameguy64's website) -2. Install MSys2 and MinGW GCC. -3. Extract GCC 7.2.0 for mipsel-unknown-elf to the root of your C drive. -4. Update your PATH environment variable to point to the bin directories of - GCC 7.2.0 for mipsel-unknown-elf, MSys2 and MinGW GCC. Make sure you can - access gcc, mipsel-unknown-elf-gcc and make from any directory in the - command prompt. -5. Build tinyxml2 with MinGW GCC through MSys2's shell - (./configure then make). -6. Clone/download PSn00bSDK source files. -7. Enter libpsn00b directory and run make. -8. Enter tools directory and run make, then 'make install' to consolidate the - executables to a bin directory. Add this directory to your PATH - environment variable and make sure elf2x is accessible from any directory. -9. Compile the example programs to test if the SDK is set up correctly. - Update directory paths in sdk-common.mk when necessary. + * MSys2 (32-bit or 64-bit version whichever you prefer) + * GCC 7.4.0 for mipsel-unknown-elf (download from Lameguy64's website at + http://lameguy64.tk?page=psn00bsdk ) +2. Install MSys2, update packages (with pacman -Syu) then install the + following packages: + * git + * make + * mingw-w64-i686-gcc (for 32-bit) or mingw-w64-x86_64-gcc (64-bit) + * mingw-w64-i686-tinyxml2 (32-bit) or mingw-w64-x86_64-tinyxml2 (64-bit) + You will need to close and reopen MSys2 for the PATH environment to + update for MinGW. +3. Extract GCC 7.4.0 for mipsel-unknown-elf to the root of your C drive. +4. Edit `mipsel-unknown-elf/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x` + and update the .text definitions as explained in toolchain.txt. +5. Add `export PATH=$PATH:/c/mipsel-unknown-elf/bin` to your `.bash_profile` + file in MSys2. Test if mipsel-unknown-elf-gcc can be called from any + directory in the terminal. +6. Clone from PSn00bSDK source with + `git clone https://github.com/lameguy64/psn00bsdk` + Clone it in the root of your C drive or in any location you choose. +7. Enter tools directory in PSn00bSDK and run `make` to build all tools. + Then, run `make install` to consolidate all tools to a single bin + directory. Add this directory to your PATH variable + (with export=$PATH:<path to SDK>/tools/bin) and make sure `elf2x` can + be called from any directory. +8. Enter libpsn00b directory and run `make` to build all libpsn00b libraries. +9. Enter examples directory and run `make`, this also verifies if the SDK + has been set up correctly. Update directory paths in `sdk-common.mk` when + necessary. + +If you prefer to do things in the Command Prompt, you can add the paths +c:\msys64\usr\bin, c:\msys64\mingw64\bin (mingw32 for 32-bit), +c:\mipsel-unknown-elf\bin and c:\psn00bsdk\tools\bin (paths may vary +depending on where you've installed/extracted them) to your system's +PATH environment variable. This way, you can invoke make and compile +programs with PSn00bSDK within the Command Prompt. + ### Linux and Unix-likes: -1. Build and install the GNU GCC toolchain configured for mipsel-unknown-elf - (see toolchain.txt for details). -2. Update your PATH environment variable to point to the bin directory of the - toolchain. Make sure the toolchain executables are accessible from any - directory in the terminal. -2. Install the following (development) package: - * tinyxml2 -3. Clone/download PSn00bSDK source files. -4. Enter the libpsn00b directory and run make. -5. Enter the tools directory and run make, then 'make install' to consolidate - the executables to a bin directory. Add this directory to your PATH - variable and make sure elf2x is accessible from any directory. +1. Install gcc, make, texinfo, git and development packages of mpfr, mpc, + gmp, isl and tinyxml2 libraries. +2. Build and install the GNU GCC toolchain targeting mipsel-unknown-elf + (see toolchain.txt for details). Update your PATH environment variable to + include the bin directory of the toolchain and make sure they can be + accessed from any directory. +3. Clone from PSn00bSDK source with + `git clone https://github.com/lameguy64/psn00bsdk` +4. Enter tools directory and run `make`, then `make install` to consolidate + the tools to a bin directory. Add this directory to your PATH variable and + make sure `elf2x` is accessible from any directory. +5. Enter the libpsn00b directory and run `make`. You may need to edit the + `common.mk` file to correspond with the GCC version you're using. 6. Compile the example programs to test if the SDK is set up correctly. - Update directory paths in sdk-common.mk when necessary. + Update directory paths in `sdk-common.mk` when necessary. ## Examples @@ -130,20 +150,16 @@ and contributed example programs are welcome. ## To-do List -* libc: C++ support (getting classes, new and delete working is enough) - and better sprintf() (one from PSXSDK is slow due to unnecessary usage - of int64 and somewhat a bit buggy) yet to be implemented. More standard - C library stuff also yet to be implemented. - -* psxgpu: VRAM download and VRAM move functions, some more primitives - and macros yet to be implemented. +* psxgpu: VRAM move function, some primitives and macros yet to be + implemented. * psxgte: Higher level GTE rotate translate and perspective functions yet to be implemented. -* psxspu: Lots of work to do. +* psxspu: Plenty of work to be done. -* psxapi: Plenty of BIOS function calls yet to be added. +* psxapi: BIOS function calls intended for stdio may need to be in + libc instead. * psxetc: Text stream stuff (FntOpen(), FntPrint(), FndFlush()) for debug purposes yet to be implemented. @@ -170,6 +186,11 @@ back in return. Main developer: * Lameguy64 +Honorable mentions: +* ijacquez (for the helpful suggestions on getting C++ working) + +Helpful contributors can be found in the changelog. + References used: * nocash's PlayStation specs document (http://problemkaputt.de/psx-spx.htm) * Tails92's PSXSDK project. diff --git a/changelog.txt b/changelog.txt index 65717bd..8c50718 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,72 @@ PSn00bSDK changelog +Items that are lower in the log are more recently implemented. + + +07-17-2019 by Lameguy64: + +* LibPSn00b run-time library is officially version 1.12b. + +* libc: Added basic C++ support (many thanks to ijacquez). + +* libc: Updated start function that should make it possible for a child + executable to return to a parent executable, return logic automatically + calls EnterCriticalSection(). + +* libc: Updated build method which takes libgcc from the compiler and adds + its own object files into it, eliminating linker problems caused by having + to order libc and libgcc libraries in a specific manner. + +* psxgpu: Added RestartCallback(). + +* psxgpu: Added StoreImage() function. + +* psxgpu: Fixed bugged setRECT() macro. + +* libc: Added assert.h. + +* examples: Balls example now has 166% more balls. + +* psxgpu: Increased ISR stack size to 1024 bytes so printf can be used in + callbacks safely. + +* libc: Removed int64 (long long) printing in vsprintf() for better + performance, as the R3000 does not support 64-bit arithmetic natively + so its emulated like floats. int64 still used for processing floats and + doubles and old vsprintf.c file is still included for those who really + want int64 support for whatever reason. + +* libc: Removed stdarg.h which is part of GCC and not license compatible + with MPL. The toolchain compiled with libgcc provides stdarg.h and other + standard headers. + +* examples: Updated sdk-common.mk variable convention for better flexibility. + +* libpsn00b: Added common.mk file containing global values for all libraries. + +* Updated library and toolchain build instructions. + +* psxgpu: Fixed bug in DMACallback where the internal DMA handler would fail + to install due to GetInterruptCallback() retrieving the callback value + immediately in the branch delay slot of a jr instruction, which resuls to + an inconsistent return value. This also broke DrawSyncCallback(). + +* psxsio: Done fixes on _sio_control() from the aformentioned issues with load + instructions in delay slots. + +* psxgte: Added DVECTOR struct. + +* psxgpu: Added setLineF2(), setLineG2(), setLineF3() and setLineG3() + primitive macros. + +* Added more functions in documentation. + + +07-01-2019 by williamblair: + +* Fixed FntLoad() Y coordinate not working properly for debug font (due to + Y coordinate not being specified for the getTPage() macro. + 06-23-2019 by Lameguy64: diff --git a/doc/LibPSn00b Reference.odt b/doc/LibPSn00b Reference.odt Binary files differindex ca5346d..30d0058 100644 --- a/doc/LibPSn00b Reference.odt +++ b/doc/LibPSn00b Reference.odt diff --git a/examples/balls/main.c b/examples/balls/main.c index ba6a391..1be49e0 100644 --- a/examples/balls/main.c +++ b/examples/balls/main.c @@ -22,7 +22,7 @@ #include "ball16c.h" -#define MAX_BALLS 384 +#define MAX_BALLS 1024 #define OT_LEN 8 diff --git a/examples/balls/makefile b/examples/balls/makefile index b5c8d91..e0f6bc3 100644 --- a/examples/balls/makefile +++ b/examples/balls/makefile @@ -1,23 +1,40 @@ include ../sdk-common.mk +# Project target name TARGET = balls.elf +# Searches for C, C++ and S (assembler) files in local directory CFILES = $(notdir $(wildcard *.c)) CPPFILES = $(notdir $(wildcard *.cpp)) AFILES = $(notdir $(wildcard *.s)) -OFILES = $(addprefix build/,$(CFILES:.c=.o) $(CPPFILES:.cpp=.o) $(AFILES:.s=.o)) +# 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 += -LIBS = -lc -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lgcc +# 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 -LDFLAGS = -g -Ttext=0x80010000 -gc-sections +# Linker flags +LDFLAGS = -g -Ttext=0x80010000 -gc-sections \ + -T $(GCC_BASE)/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x + +# Toolchain programs CC = $(PREFIX)gcc CXX = $(PREFIX)g++ AS = $(PREFIX)as @@ -31,6 +48,10 @@ build/%.o: %.c @mkdir -p $(dir $@) $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ +build/%.o: %.cpp + @mkdir -p $(dir $@) + $(CXX) $(AFLAGS) $(INCLUDE) -c $< -o $@ + build/%.o: %.s @mkdir -p $(dir $@) $(CC) $(AFLAGS) $(INCLUDE) -c $< -o $@ diff --git a/examples/gte/makefile b/examples/gte/makefile index 763b3d8..89b27d3 100644 --- a/examples/gte/makefile +++ b/examples/gte/makefile @@ -16,7 +16,7 @@ LIBS = -lc -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lgcc CFLAGS = -g -O2 -fno-builtin -fdata-sections -ffunction-sections CPPFLAGS = $(CFLAGS) -fno-exceptions AFLAGS = -g -msoft-float -LDFLAGS = -g -Ttext=0x80010000 -gc-sections +LDFLAGS = -g -Ttext=0x80010000 -gc-sections -T $(GCC_BASE)/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x CC = $(PREFIX)gcc CXX = $(PREFIX)g++ diff --git a/examples/n00bdemo/makefile b/examples/n00bdemo/makefile index a87f299..8159a22 100644 --- a/examples/n00bdemo/makefile +++ b/examples/n00bdemo/makefile @@ -15,7 +15,7 @@ LIBS = -llzp -lc -lpsxetc -lpsxgpu -lpsxgte -lpsxspu -lpsxapi -lgcc CFLAGS = -g -O2 -fno-builtin -fdata-sections -ffunction-sections CPPFLAGS = $(CFLAGS) -fno-exceptions AFLAGS = -g -msoft-float -LDFLAGS = -g -Ttext=0x80010000 -gc-sections +LDFLAGS = -g -Ttext=0x80010000 -gc-sections -T $(GCC_BASE)/mipsel-unknown-elf/lib/ldscripts/elf32elmip.x CC = $(PREFIX)gcc CXX = $(PREFIX)g++ diff --git a/examples/sdk-common.mk b/examples/sdk-common.mk index 8a92dbf..0d97555 100644 --- a/examples/sdk-common.mk +++ b/examples/sdk-common.mk @@ -1,19 +1,27 @@ # Adjustable common makefile values for PSn00bSDK example programs. -# You may need to modify these values to correspond to your toolchain setup. +# You may need to modify these values to match with your toolchain setup. -# Toolchain prefix. Can include an absolute path to the toolchain executables. +# Toolchain prefix PREFIX = mipsel-unknown-elf- -# Include directories. +# Include directories INCLUDE = -I../../libpsn00b/include -# Library directories. Last entry must point to a directory containing libgcc. +# Library directories, last entry must point toolchain libraries LIBDIRS = -L../../libpsn00b -# Directory path for toolchain's libraries (you may need to change this) -ifeq "$(OS)" "Windows_NT" -# For Windows -LIBDIRS += -L/c/psn00bsdk/lib -else -# For Linux/BSDs -LIBDIRS += -L/usr/local/mipsel-unknown-elf/lib/gcc/mipsel-unknown-elf/6.3.0 + + +GCC_VERSION = 7.4.0 + +ifeq "$(OS)" "Windows_NT" # For Windows + +GCC_BASE = /c/mipsel-unknown-elf + +else # For Linux/BSDs + +GCC_BASE = /usr/local/mipsel-unknown-elf + endif + +LIBDIRS += -L$(GCC_BASE)/lib/gcc/mipsel-unknown-elf/$(GCC_VERSION) +INCLUDE += -I$(GCC_BASE)/lib/gcc/mipsel-unknown-elf/$(GCC_VERSION)/include diff --git a/libpsn00b/common.mk b/libpsn00b/common.mk new file mode 100644 index 0000000..83b45e9 --- /dev/null +++ b/libpsn00b/common.mk @@ -0,0 +1,27 @@ +# Adjustable common makefile values for PSn00bSDK example programs. +# You may need to modify these values to match with your toolchain setup. + +# GCC version +GCC_VERSION = 7.4.0 + +# GCC base paths +ifeq "$(OS)" "Windows_NT" # For Windows + +GCC_BASE = /c/mipsel-unknown-elf + +else # For Linux/BSDs + +GCC_BASE = /usr/local/mipsel-unknown-elf + +endif + + +# Toolchain prefix +PREFIX = mipsel-unknown-elf- + +# Include directories +INCLUDE = -I../include + +# Finish paths +LIBDIRS += -L$(GCC_BASE)/lib/gcc/mipsel-unknown-elf/$(GCC_VERSION) +INCLUDE += -I$(GCC_BASE)/lib/gcc/mipsel-unknown-elf/$(GCC_VERSION)/include diff --git a/libpsn00b/include/assert.h b/libpsn00b/include/assert.h new file mode 100644 index 0000000..3114b57 --- /dev/null +++ b/libpsn00b/include/assert.h @@ -0,0 +1,6 @@ +#ifndef _ASSERT_H +#define _ASSERT_H + +void assert(int e); + +#endif
\ No newline at end of file diff --git a/libpsn00b/include/ioctl.h b/libpsn00b/include/ioctl.h new file mode 100644 index 0000000..5c56422 --- /dev/null +++ b/libpsn00b/include/ioctl.h @@ -0,0 +1,19 @@ +#ifndef _IOCTL_H +#define _IOCTL_H + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef EOF +#define EOF -1 +#endif + +// General +#define FIONBLOCK (('f'<<8)|1) +#define FIOCSCAN (('f'<<8)|2) + +// disk +#define DIO_FORMAT (('d'<<8)|1) + +#endif
\ No newline at end of file diff --git a/libpsn00b/include/psxapi.h b/libpsn00b/include/psxapi.h index 68dac67..f5a3c07 100644 --- a/libpsn00b/include/psxapi.h +++ b/libpsn00b/include/psxapi.h @@ -79,7 +79,7 @@ void SysDeqIntRP(int pri, INT_RP *rp); // Event handler stuff -int OpenEvent(unsigned int class, int spec, int mode, void (*func)()); +int OpenEvent(unsigned int cl, int spec, int mode, void (*func)()); int CloseEvent(int ev_desc); int EnableEvent(int ev_desc); int DisableEvent(int ev_desc); diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h index 40b9159..2415c83 100644 --- a/libpsn00b/include/psxgpu.h +++ b/libpsn00b/include/psxgpu.h @@ -25,15 +25,11 @@ #define setVector( v, _x, _y, _z ) \ (v)->vx = _x, (v)->vy = _y, (v)->vz = _z -#define setRECT( r, _x, _y, _w, _h ) \ +#define setRECT( v, _x, _y, _w, _h ) \ (v)->x = _x, (v)->y = _y, (v)->w = _w, (v)->h = _h - - - -// Primitive macros - +// Primitive macros #define setDrawTPage( p, tp, abr, x, y ) \ ( (p)->code[0] = getTPage( tp, abr, x, y ), \ @@ -96,7 +92,6 @@ #define setWH( p, _w, _h ) \ (p)->w = _w, (p)->h = _h - /* * Set texture coordinates */ @@ -183,11 +178,16 @@ #define setTile16( p ) setlen( p, 2 ), setcode( p, 0x78 ) #define setTile( p ) setlen( p, 3 ), setcode( p, 0x60 ) +#define setLineF2( p ) setlen( p, 3 ), setcode( p, 0x40 ) #define setLineG2( p ) setlen( p, 4 ), setcode( p, 0x50 ) +#define setLineF3( p ) setlen( p, 5 ), setcode( p, 0x48 ), (p)->pad = 0x55555555 +#define setLineG3( p ) setlen( p, 7 ), setcode( p, 0x58 ), (p)->pad = 0x55555555, \ + (p)->p1 = 0, (p)->p2 = 0 + #define setLineF4( p ) setlen( p, 6 ), setcode( p, 0x4c ), (p)->pad = 0x55555555 #define setLineG4( p ) setlen( p, 9 ), setcode( p, 0x5c ), (p)->pad = 0x55555555, \ - (p)->p2 = 0, (p)->p3 = 0 + (p)->p1 = 0, (p)->p2 = 0, (p)->p3 = 0 #define setFill( p ) setlen( p, 3 ), setcode( p, 0x02 ) @@ -533,14 +533,18 @@ int DrawSync(int m); void WaitGPUcmd(); void WaitGPUdma(); +// Callback hook functions void *VSyncCallback(void (*func)()); void *DrawSyncCallback(void (*func)()); +// Interrupt callback functions void *DMACallback(int dma, void (*func)()); void *InterruptCallback(int irq, void (*func)()); void *GetInterruptCallback(int irq); // Original +void RestartCallback(); void LoadImage(RECT *rect, unsigned int *data); +void StoreImage(RECT *rect, unsigned int *data); void ClearOTagR(unsigned int* ot, int n); void DrawOTag(unsigned int* ot); diff --git a/libpsn00b/include/psxgte.h b/libpsn00b/include/psxgte.h index 0a8ded0..43d529a 100644 --- a/libpsn00b/include/psxgte.h +++ b/libpsn00b/include/psxgte.h @@ -29,6 +29,10 @@ typedef struct { unsigned char r, g, b, cd; } CVECTOR; +typedef struct { + short vx, vy; +} DVECTOR; + #ifdef __cplusplus extern "C" { @@ -46,8 +50,8 @@ int icos(int a); int hisin(int a); int hicos(int a); -void PushMatrix(); -void PopMatrix(); +void PushMatrix(void); +void PopMatrix(void); MATRIX *RotMatrix(SVECTOR *r, MATRIX *m); MATRIX *HiRotMatrix(VECTOR *r, MATRIX *m); diff --git a/libpsn00b/include/stdarg.h b/libpsn00b/include/stdarg.h deleted file mode 100644 index bdf4c00..0000000 --- a/libpsn00b/include/stdarg.h +++ /dev/null @@ -1,122 +0,0 @@ -/* Copyright (C) 1989-2018 Free Software Foundation, Inc. -This file is part of GCC. -GCC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3, or (at your option) -any later version. -GCC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -<http://www.gnu.org/licenses/>. */ - -/* - * ISO C Standard: 7.15 Variable arguments <stdarg.h> - */ - -#ifndef _STDARG_H -#ifndef _ANSI_STDARG_H_ -#ifndef __need___va_list -#define _STDARG_H -#define _ANSI_STDARG_H_ -#endif /* not __need___va_list */ -#undef __need___va_list - -/* Define __gnuc_va_list. */ - -#ifndef __GNUC_VA_LIST -#define __GNUC_VA_LIST -typedef __builtin_va_list __gnuc_va_list; -#endif - -/* Define the standard macros for the user, - if this invocation was from the user program. */ -#ifdef _STDARG_H - -#define va_start(v,l) __builtin_va_start(v,l) -#define va_end(v) __builtin_va_end(v) -#define va_arg(v,l) __builtin_va_arg(v,l) -#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L \ - || __cplusplus + 0 >= 201103L -#define va_copy(d,s) __builtin_va_copy(d,s) -#endif -#define __va_copy(d,s) __builtin_va_copy(d,s) - -/* Define va_list, if desired, from __gnuc_va_list. */ -/* We deliberately do not define va_list when called from - stdio.h, because ANSI C says that stdio.h is not supposed to define - va_list. stdio.h needs to have access to that data type, - but must not use that name. It should use the name __gnuc_va_list, - which is safe because it is reserved for the implementation. */ - -#ifdef _BSD_VA_LIST -#undef _BSD_VA_LIST -#endif - -#if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST)) -/* SVR4.2 uses _VA_LIST for an internal alias for va_list, - so we must avoid testing it and setting it here. - SVR4 uses _VA_LIST as a flag in stdarg.h, but we should - have no conflict with that. */ -#ifndef _VA_LIST_ -#define _VA_LIST_ -#ifdef __i860__ -#ifndef _VA_LIST -#define _VA_LIST va_list -#endif -#endif /* __i860__ */ -typedef __gnuc_va_list va_list; -#ifdef _SCO_DS -#define __VA_LIST -#endif -#endif /* _VA_LIST_ */ -#else /* not __svr4__ || _SCO_DS */ - -/* The macro _VA_LIST_ is the same thing used by this file in Ultrix. - But on BSD NET2 we must not test or define or undef it. - (Note that the comments in NET 2's ansi.h - are incorrect for _VA_LIST_--see stdio.h!) */ -#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT) -/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */ -#ifndef _VA_LIST_DEFINED -/* The macro _VA_LIST is used in SCO Unix 3.2. */ -#ifndef _VA_LIST -/* The macro _VA_LIST_T_H is used in the Bull dpx2 */ -#ifndef _VA_LIST_T_H -/* The macro __va_list__ is used by BeOS. */ -#ifndef __va_list__ -typedef __gnuc_va_list va_list; -#endif /* not __va_list__ */ -#endif /* not _VA_LIST_T_H */ -#endif /* not _VA_LIST */ -#endif /* not _VA_LIST_DEFINED */ -#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__)) -#define _VA_LIST_ -#endif -#ifndef _VA_LIST -#define _VA_LIST -#endif -#ifndef _VA_LIST_DEFINED -#define _VA_LIST_DEFINED -#endif -#ifndef _VA_LIST_T_H -#define _VA_LIST_T_H -#endif -#ifndef __va_list__ -#define __va_list__ -#endif - -#endif /* not _VA_LIST_, except on certain systems */ - -#endif /* not __svr4__ */ - -#endif /* _STDARG_H */ - -#endif /* not _ANSI_STDARG_H_ */ -#endif /* not _STDARG_H */
\ No newline at end of file diff --git a/libpsn00b/include/stdio.h b/libpsn00b/include/stdio.h index 98c69d0..81249de 100644 --- a/libpsn00b/include/stdio.h +++ b/libpsn00b/include/stdio.h @@ -43,10 +43,10 @@ extern int getchar(void); extern void putchar(int __c); // The following functions do not use the BIOS -int vsnprintf(char *string, unsigned int size, char *fmt, va_list ap); -int vsprintf(char *string, char *fmt, va_list ap); -int sprintf(char *string, char *fmt, ...); -int snprintf(char *string, unsigned int size, char *fmt, ...); +int vsnprintf(char *string, unsigned int size, const char *fmt, va_list ap); +int vsprintf(char *string, const char *fmt, va_list ap); +int sprintf(char *string, const char *fmt, ...); +int snprintf(char *string, unsigned int size, const char *fmt, ...); #ifdef __cplusplus } diff --git a/libpsn00b/include/sys/types.h b/libpsn00b/include/sys/types.h index 2f30a5f..c412700 100644 --- a/libpsn00b/include/sys/types.h +++ b/libpsn00b/include/sys/types.h @@ -6,4 +6,6 @@ typedef unsigned short u_short; typedef unsigned int u_int; typedef unsigned long u_long; +typedef unsigned int size_t; + #endif // _TYPES_H
\ No newline at end of file diff --git a/libpsn00b/libc/_mem_init.s b/libpsn00b/libc/_mem_init.s new file mode 100644 index 0000000..672ac2f --- /dev/null +++ b/libpsn00b/libc/_mem_init.s @@ -0,0 +1,20 @@ +.set noreorder + +.global _mem_init +.type _mem_init, @function +_mem_init: + +.section .text + +_mem_init: + la $a0, __bss_start + la $a1, _end +.Lclear_bss: + sb $0 , 0($a0) + blt $a0, $a1, .Lclear_bss + addiu $a0, 1 + la $a0, _end+4 # Initialize heap for malloc (does not use BIOS maalloc) + li $a1, 1572864 # Allocate 1.5MB at end of bss + j InitHeap + nop +
\ No newline at end of file diff --git a/libpsn00b/libc/abort.c b/libpsn00b/libc/abort.c new file mode 100644 index 0000000..ca5ab1d --- /dev/null +++ b/libpsn00b/libc/abort.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +void abort() { + + printf("abort()\n"); + + while(1); + +}
\ No newline at end of file diff --git a/libpsn00b/libc/c++-support.cxx b/libpsn00b/libc/c++-support.cxx new file mode 100644 index 0000000..fcf7cfc --- /dev/null +++ b/libpsn00b/libc/c++-support.cxx @@ -0,0 +1,40 @@ +#include <assert.h> +#include <sys/types.h> +#include <stdlib.h> +#include <malloc.h> + +extern "C" + +void __cxa_pure_virtual(void) { + /* Pure C++ virtual call; abort! */ + assert(false); +} + +void* operator new(size_t size) { + return malloc(size); +} + +void* operator new[](size_t size) { + return malloc(size); +} + +void operator delete(void* ptr) { + free(ptr); +} + +void operator delete[](void* ptr) { + free(ptr); +} + +/*- + * <https://en.cppreference.com/w/cpp/memory/new/operator_delete> + * + * Called if a user-defined replacement is provided, except that it's + * unspecified whether other overloads or this overload is called when deleting + * objects of incomplete type and arrays of non-class and trivially-destructible + * class types. + * + * A memory allocator can use the given size to be more efficient */ +void operator delete(void* ptr, unsigned int) { + free(ptr); +}
\ No newline at end of file diff --git a/libpsn00b/libc/makefile b/libpsn00b/libc/makefile index feadbdb..67f2284 100644 --- a/libpsn00b/libc/makefile +++ b/libpsn00b/libc/makefile @@ -2,20 +2,20 @@ # Part of the PSn00bSDK Project # 2019 Lameguy64 / Meido-Tek Productions -PREFIX = mipsel-unknown-elf- +include ../common.mk TARGET = ../libc.a -CFILES = $(notdir $(wildcard ./*.c)) -AFILES = $(notdir $(wildcard ./*.s)) -OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o)) +CFILES = $(notdir $(wildcard ./*.c)) +CXXFILES = $(notdir $(wildcard ./*.cxx)) +AFILES = $(notdir $(wildcard ./*.s)) +OFILES = $(addprefix build/,$(CFILES:.c=.o) $(CXXFILES:.cxx=.o) $(AFILES:.s=.o)) -INCLUDE = -I../include - -CFLAGS = -O2 -msoft-float -fno-builtin -fdata-sections -ffunction-sections -Wa,--strip-local-absolute -AFLAGS = -msoft-float -Wa,--strip-local-absolute +CFLAGS = -g -O2 -msoft-float -fno-builtin -fdata-sections -ffunction-sections -Wa,--strip-local-absolute +AFLAGS = -g -msoft-float -Wa,--strip-local-absolute CC = $(PREFIX)gcc +CXX = $(PREFIX)g++ AS = $(PREFIX)as AR = $(PREFIX)ar RANLIB = $(PREFIX)ranlib @@ -23,12 +23,17 @@ RANLIB = $(PREFIX)ranlib all: $(TARGET) $(TARGET): $(OFILES) - $(AR) cr $(TARGET) $(OFILES) + cp $(GCC_BASE)/lib/gcc/mipsel-unknown-elf/$(GCC_VERSION)/libgcc.a ./$(TARGET) + $(AR) r $(TARGET) $(OFILES) $(RANLIB) $(TARGET) build/%.o: %.c @mkdir -p $(dir $@) $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@ + +build/%.o: %.cxx + @mkdir -p $(dir $@) + $(CXX) $(CFLAGS) $(INCLUDE) -c $< -o $@ build/%.o: %.s @mkdir -p $(dir $@) diff --git a/libpsn00b/libc/start.c b/libpsn00b/libc/start.c new file mode 100644 index 0000000..c234e03 --- /dev/null +++ b/libpsn00b/libc/start.c @@ -0,0 +1,57 @@ +#include <stdio.h> +#include <malloc.h> + +#define load_gp() __asm__ volatile ( \ + "la $gp, _gp;" ) + +extern int _end; +extern int main(int argc, const char* argv[]); + +void _mem_init(void); + + +static void _call_global_ctors(void) +{ + extern void (*__CTOR_LIST__[])(void); + + // Constructors are called in reverse order of the list + int i; + for (i = (int)__CTOR_LIST__[0]; i >= 1; i--) { + // Each function handles one or more destructor (within + // file scope) + __CTOR_LIST__[i](); + } +} + +static void _call_global_dtors(void) +{ + extern void (*__DTOR_LIST__[])(void); + + /* Destructors in forward order */ + int i; + for (i = 0; i < (int)__DTOR_LIST__[0]; i++) { + /* Each function handles one or more destructor (within + * file scope) */ + __DTOR_LIST__[i + 1](); + } +} + +void _start(void) { + + // Load GP address + load_gp(); + + // Mem init assembly function (clears BSS and InitHeap to _end which is + // not possible to do purely in C because the linker complains about + // relocation truncated to fit: R_MIPS_GPREL16 against `_end' + // Workaround is to do it in assembly because la pseudo-op doesn't use + // stupid gp relative addressing + _mem_init(); + + _call_global_ctors(); + + main(0, NULL); + + _call_global_dtors(); + +}
\ No newline at end of file diff --git a/libpsn00b/libc/start.s b/libpsn00b/libc/start.s deleted file mode 100644 index 2cf6ed0..0000000 --- a/libpsn00b/libc/start.s +++ /dev/null @@ -1,39 +0,0 @@ -# Start function! -# This is essentially the entry point of the PS-EXE - -.set noreorder - -.section .text - -.global _start -.type _start, @function -_start: - addiu $sp, -4 - sw $ra, 0($sp) - - la $gp, _gp # Very important! - - la $a0, .bss # What are the CORRECT symbols for BSS start and end? - la $a1, _end -.Lclear_bss: - sb $0 , 0($a0) - blt $a0, $a1, .Lclear_bss - addiu $a0, 1 - - la $a0, _end+4 # Initialize heap for malloc (does not use BIOS maalloc) - li $a1, 1572864 - jal InitHeap - nop - - move $a0, $0 # No support for arguments for now - move $a1, $0 - - jal main - addiu $sp, -8 - addiu $sp, 8 - - lw $ra, 0($sp) # Return - addiu $sp, 4 - jr $ra - nop -
\ No newline at end of file diff --git a/libpsn00b/libc/vsprintf.c b/libpsn00b/libc/vsprintf.c new file mode 100644 index 0000000..153ca21 --- /dev/null +++ b/libpsn00b/libc/vsprintf.c @@ -0,0 +1,788 @@ +/* printf.c + * + * Inherited from the PSXSDK C library + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define SPRINTF_ALT_FLAG (1<<0) +#define SPRINTF_ZERO_FLAG (1<<1) +#define SPRINTF_NEGFIELD_FLAG (1<<2) +#define SPRINTF_SPACE_FLAG (1<<3) +#define SPRINTF_SIGN_FLAG (1<<4) + +// sprintf() macros to calculate the real padding and to write it +// these were made to not repeat the code in the function +// they can only be used in sprintf() + +// sprintf macros START + +#define calculate_real_padding() \ + y = 1; \ + \ + for(x=0;x<=19;x++) \ + { \ + if(x == 0) \ + pad_quantity--; \ + else \ + { \ + if(arg / y) \ + pad_quantity--; \ + } \ + \ + y *= 10; \ + } \ + \ + if(pad_quantity < 0) pad_quantity = 0; + +/*#define calculate_real_padding_hex() \ + for (x = 0; x < 8; x++) \ + { \ + if(x == 0) \ + pad_quantity--; \ + else \ + { \ + if((arg >> (x * 4)) & 0xf) \ + pad_quantity--; \ + } \ + }*/ + +#define calculate_real_padding_hex() \ + last = 0; \ + for (x = 0; x < 16; x++) \ + if((arg >> (x * 4)) & 0xf) \ + last = x; \ + \ + pad_quantity = (pad_quantity - 1) - last; \ + if(pad_quantity < 0) pad_quantity = 0; + +#define write_padding() \ + if(!(flags & SPRINTF_NEGFIELD_FLAG)) \ + for(x = 0; x < pad_quantity; x++) \ + { \ + if(flags & SPRINTF_ZERO_FLAG) \ + put_in_string(string, ssz, '0', string_pos++); \ + else \ + put_in_string(string, ssz, ' ', string_pos++); \ + } + +#define write_neg_padding() \ + if(flags & SPRINTF_NEGFIELD_FLAG) \ + { \ + for(x = 0; x < pad_quantity; x++) \ + put_in_string(string, ssz, ' ', string_pos++);\ + } + +// sprintf macros END + +enum +{ + SPRINTF_SIZE_CHAR, + SPRINTF_SIZE_SHORT, + SPRINTF_SIZE_INT, + SPRINTF_SIZE_LONG, + SPRINTF_SIZE_LONG_LONG, +}; + +unsigned int get_arg_in_size(int size, unsigned long *arg, unsigned int check_sign) +{ + int s = 0; + + switch(size) + { + case SPRINTF_SIZE_CHAR: + *arg &= 0xff; + + if(check_sign) + { + if(*arg & (1<<7)) + { + *arg |= 0xffffff00; + *arg = ~(*arg - 1); + s = 1; + } + } + break; + case SPRINTF_SIZE_SHORT: + *arg &= 0xffff; + + if(check_sign) + { + if(*arg & (1<<15)) + { + *arg |= 0xffff0000; + *arg = ~(*arg - 1); + s = 1; + } + } + break; + +// sizeof(long) == sizeof(int) on 32bit, so this will suffice for the psx + + case SPRINTF_SIZE_INT: + case SPRINTF_SIZE_LONG: + *arg &= 0xffffffff; + + /*if(check_sign) + { + if(*arg & (1<<31)) + { + *arg |= (long long)0xffffffff00000000; + *arg = ~(*arg - 1); + s = 1; + } + }*/ + break; + + /*case SPRINTF_SIZE_LONG_LONG: + if(check_sign) + { + if(*arg & ((long long)1<<63)) + { + *arg = ~(*arg - 1); + s = 1; + } + } + break;*/ + } + + return s; +} + +int put_in_string(char *string, unsigned int sz, char c, int pos) +{ + if(pos>=sz) + return 0; + else + string[pos] = c; + + return 1; +} + +int libc_ulltoa(unsigned long i, char *dst, int n) +{ + int x, y; + unsigned long a, b; + int empty_digit = 1; + int sp=0; + int n2=0; + + for(x=20;x>=0;x--) + { + a = 1; + for(y = 0; y<x; y++) + a *= 10; + + b = (i/a); + + if(b>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + i -= b*a; + + //put_in_string(string, ssz, b + '0', string_pos++); + if(n2!=n) + { + //printf("n2=%d\n",n2); + dst[sp++] = b + '0'; + n2++; + } + } + } + + if(n2!=n)dst[sp] = 0; + + return n2; +} + +void libc_float_to_string(float fl, char *dst, int n) +{ + unsigned int *p = (unsigned int*)&fl; + unsigned long long i = 0; + unsigned long long f = 0; + int e, m, s; + int x, y; + unsigned long long z; + + s = *p >> 31; + + e = (*p >> 23) & 0xff; + + m = *p & 0x7fffff; + + if(e == 255 && m == 0) // Infinity + { + if(s) strncpy(dst, "-inf", n); + else strncpy(dst, "inf", n); + }else if(e == 255 && m != 0) // NaN + { + strncpy(dst, "nan", n); + } + else + { + e -= 127; + m |= 1<<23; + + + + for(x = 23; x >= 0; x--) + { + if(m & (1<<x)) + { + if(e >= 0) + { + z = 1; + for(y=0;y<e;y++) + z*=2; + + i+=z; + } + else + { + z = 5000000000000000000; + for(y = 1; y < -e; y++) + z /= 2; + + f+=z; + } + } + e--; + } + + if(s && n) + { + *(dst++) = '-'; + n--; + } + + x = libc_ulltoa(i, dst, n); + n-=x; + dst+=x; + + if(n) + { + *(dst++) = '.'; + n--; + if(n) + { + x = libc_ulltoa(f, dst, n<6?n:6); + n-=x; + dst+=x; + + if(n) + *dst=0; + } + } + } +} + +void libc_double_to_string(double fl, char *dst, int n) +{ + unsigned long long *p = (unsigned long long *)&fl; + unsigned long long i = 0; + unsigned long long f = 0; + unsigned long long m, s; + long long e; + int x, y; + unsigned long long z; + + s = *p >> 63; + + e = (*p >> 52) & 0x7ff; + //printf("%d\n", e); + + m = *p & 0xfffffffffffff; + + for(x=0;x<52;x++) + if(m&((unsigned long long)1<<(52-x))) putchar('1'); else putchar('0'); + + if(e == 255 && m == 0) // Infinity + { + if(s) strncpy(dst, "-inf", n); + else strncpy(dst, "inf", n); + }else if(e == 255 && m != 0) // NaN + { + strncpy(dst, "nan", n); + } + else + { + e -= 1023; + m |= (unsigned long long)1<<52; + + for(x = 52; x >= 0; x--) + { + if(m & ((unsigned long long)1<<x)) + { + if(e >= 0) + { + z = (long long)1<<e; + + i+=z; + } + else + { + z = 5000000000000000000; + z >>= -(e + 1); + + f+=z; + } + } + e--; + } + + if(s && n) + { + *(dst++) = '-'; + n--; + } + + x = libc_ulltoa(i, dst, n); + n-=x; + dst+=x; + + if(n) + { + *(dst++) = '.'; + n--; + if(n) + libc_ulltoa(f, dst, n<6?n:6); + } + } +} + +char libc_sprintf_floatbuf[64]; + +int vsnprintf(char *string, unsigned int size, const char *fmt, va_list ap) +{ + int string_pos,fmt_pos; + int l; + unsigned long arg; + unsigned char *argcp; + unsigned char *argcp_tmp; + int directive_coming = 0; + int alternate_form = 0; + int flags = 0; + int argsize = 2; // int + int x, y; + unsigned long a, b; + int empty_digit; + int ssz = size - 1; + int zero_flag_imp = 0; + int pad_quantity = 0; + int last; + + l = strlen(fmt); + + string_pos = 0; + + for(fmt_pos=0;fmt_pos<l;fmt_pos++) + { + if(directive_coming) + { + switch(fmt[fmt_pos]) + { + case '%': + put_in_string(string, ssz, '%', string_pos++); + directive_coming = 0; + break; + case ' ': + flags |= SPRINTF_SPACE_FLAG; + break; + case '#': // Specify alternate form + flags |= SPRINTF_ALT_FLAG; + break; + case '+': // Specify sign in signed conversions + flags |= SPRINTF_SIGN_FLAG; + break; + case '0': // Padding with zeros... + if(zero_flag_imp == 0) + { + flags |= SPRINTF_ZERO_FLAG; + zero_flag_imp = 1; + //printf("Zero padding enabled!\n"); + } + else + { + pad_quantity *= 10; + //printf("pad_quantity = %d\n", pad_quantity); + } + break; + case '1' ... '9': // '...' cases are a GNU extension, + // but they simplify a lot + + pad_quantity *= 10; + pad_quantity += fmt[fmt_pos] - '0'; + zero_flag_imp = 1; + + //printf("pad_quantity = %d\n", pad_quantity); + break; + case '-': // Negative field flag + if(flags & SPRINTF_ZERO_FLAG) + flags &= ~SPRINTF_ZERO_FLAG; + + flags |= SPRINTF_NEGFIELD_FLAG; + break; + case 'h': // Half argument size + if(argsize) argsize--; + break; + case 'l': // Double argument size + if(argsize < 2) argsize = 2; + //else if(argsize < SPRINTF_SIZE_LONG_LONG) argsize++; + break; + case 'd': // signed decimal + case 'i': + empty_digit = 1; + + //printf("argsize = %d\n", argsize); + + //if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long)va_arg(ap, unsigned int); + //else + // arg = va_arg(ap, unsigned long); + + if(get_arg_in_size(argsize, &arg, 1)) + { + put_in_string(string, ssz, '-', string_pos++); + pad_quantity--; + } + else + { + if(flags & SPRINTF_SIGN_FLAG) + { + put_in_string(string, ssz, '+', string_pos++); + pad_quantity--; + } + } + + /* Calculate how much padding we have to write */ + + /*y = 1; + + for(x=0;x<=9;x++) + { + if(x == 0) + pad_quantity--; + else + { + if(arg / y) + pad_quantity--; + } + + y *= 10; + } + if(pad_quantity < 0) pad_quantity = 0;*/ + + calculate_real_padding(); + + //printf("Actual pad quantity = %d\n", pad_quantity); + + + + /*if(!(flags & SPRINTF_NEGFIELD_FLAG)) + { + for(x = 0; x < pad_quantity; x++) + { + if(flags & SPRINTF_ZERO_FLAG) + put_in_string(string, ssz, '0', string_pos++); + else + put_in_string(string, ssz, ' ', string_pos++); + } + }*/ + + write_padding(); + + for(x=19;x>=0;x--) + { + a = 1; + for(y = 0; y<x; y++) + a *= 10; + + b = (arg/a); + + if(b>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + arg -= b*a; + + put_in_string(string, ssz, b + '0', string_pos++); + } + } + + /*if(flags & SPRINTF_NEGFIELD_FLAG) + { + for(x = 0; x < pad_quantity; x++) + put_in_string(string, ssz, ' ', string_pos++); + }*/ + write_neg_padding(); + + directive_coming = 0; + break; + case 'u': // unsigned decimal + empty_digit = 1; + + //if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long)va_arg(ap, unsigned int); + //else + //arg = va_arg(ap, unsigned long long); + + get_arg_in_size(argsize, &arg, 0); + + calculate_real_padding(); + write_padding(); + + for(x=19;x>=0;x--) + { + a = 1; + for(y = 0; y<x; y++) + a *= 10; + + + + b = (arg/a); + + if(b>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + arg -= b*a; + + put_in_string(string, ssz, b + '0', string_pos++); + } + } + + write_neg_padding(); + + directive_coming = 0; + break; + case 'x': // Hexadecimal + case 'X': // Hexadecimal with big letters + case 'p': // Hexadecimal with small letters with '0x' prefix + empty_digit = 1; + + //if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long)va_arg(ap, unsigned int); + //else + // arg = va_arg(ap, unsigned long int); + + get_arg_in_size(argsize, &arg, 0); + + if(fmt_pos == 'p') + flags |= SPRINTF_ALT_FLAG; + + if(flags & SPRINTF_ALT_FLAG) + { + put_in_string(string, ssz, '0', string_pos++); + + if(fmt[fmt_pos] == 'X') + put_in_string(string, ssz, 'X', string_pos++); + else + put_in_string(string, ssz, 'x', string_pos++); + } + + calculate_real_padding_hex(); + write_padding(); + + for(x=7;x>=0;x--) + { + y = arg >> (x << 2); + y &= 0xf; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + { + if(y>=0 && y<=9) + put_in_string(string, ssz, y + '0', string_pos++); + else if(y>=0xA && y<=0xF) + { + if(fmt[fmt_pos] == 'X') + put_in_string(string, ssz, (y - 0xa) + 'A', string_pos++); + else + put_in_string(string, ssz, (y - 0xa) + 'a', string_pos++); + } + } + } + + write_neg_padding(); + + directive_coming = 0; + break; + case 'c': // character + arg = va_arg(ap, int); + + put_in_string(string, ssz, arg & 0xff, string_pos++); + + directive_coming = 0; + break; + case 's': // string + argcp = va_arg(ap, char *); + argcp_tmp = argcp; + + if(argcp == NULL) + { + // Non standard extension, but supported by Linux and the BSDs. + + put_in_string(string, ssz, '(', string_pos++); + put_in_string(string, ssz, 'n', string_pos++); + put_in_string(string, ssz, 'u', string_pos++); + put_in_string(string, ssz, 'l', string_pos++); + put_in_string(string, ssz, 'l', string_pos++); + put_in_string(string, ssz, ')', string_pos++); + + directive_coming = 0; + break; + } + + while(*argcp_tmp) + { + if(pad_quantity > 0) pad_quantity--; + argcp_tmp++; + } + + if(!(flags & SPRINTF_NEGFIELD_FLAG)) + { + while(pad_quantity > 0) + { + put_in_string(string,ssz, ' ', string_pos++); + pad_quantity--; + } + } + + while(*argcp) + { + put_in_string(string, ssz, *argcp, string_pos++); + argcp++; + } + + if(flags & SPRINTF_NEGFIELD_FLAG) + { + while(pad_quantity > 0) + { + put_in_string(string,ssz, ' ', string_pos++); + pad_quantity--; + } + } + + directive_coming = 0; + break; + case 'o': // Octal + empty_digit = 1; + + //if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long)va_arg(ap, unsigned int); + //else + // arg = va_arg(ap, unsigned long long); + + for(x=21;x>=0;x--) + { + y = arg >> (x * 3); + y &= 0x7; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + put_in_string(string, ssz, y + '0', string_pos++); + } + + directive_coming = 0; + break; + case '@': // Binary + empty_digit = 1; + + //if(argsize < SPRINTF_SIZE_LONG_LONG) + arg = (unsigned long)va_arg(ap, unsigned int); + //else + // arg = va_arg(ap, unsigned long long); + + for(x=31;x>=0;x--) + { + y = (arg >> x); + y &= 1; + + if(y>=1) + empty_digit = 0; + + if(empty_digit == 0 || x == 0) + put_in_string(string, ssz, y + '0', string_pos++); + } + + directive_coming = 0; + break; + + case 'f': + libc_double_to_string(va_arg(ap, double), libc_sprintf_floatbuf, 64); + + for(x=0;libc_sprintf_floatbuf[x]!=0;x++) + put_in_string(string, ssz, libc_sprintf_floatbuf[x], string_pos++); + + directive_coming = 0; + break; + case 'n': // Number of characters written + *(va_arg(ap,unsigned int*)) = string_pos; + + directive_coming = 0; + break; + // default + } + } + else + { + if(fmt[fmt_pos] == '%') + { + directive_coming = 1; + flags = 0; + argsize = 2; + pad_quantity = 0; + zero_flag_imp = 0; + } + else + put_in_string(string, ssz, fmt[fmt_pos], string_pos++); + } + } + string[string_pos] = 0; + return string_pos; +} + +int vsprintf(char *string, const char *fmt, va_list ap) +{ + return vsnprintf(string, 0xffffffff, fmt, ap); +} + +int sprintf(char *string, const char *fmt, ...) +{ + int r; + + va_list ap; + + va_start(ap, fmt); + + r = vsprintf(string, fmt, ap); + + va_end(ap); + + return r; +} + +int snprintf(char *string, unsigned int size, const char *fmt, ...) +{ + int r; + + va_list ap; + + va_start(ap, fmt); + + r = vsnprintf(string, size, fmt, ap); + + va_end(ap); + + return r; +} diff --git a/libpsn00b/libc/printf.c b/libpsn00b/libc/vsprintf.c-old index 7350648..9c68a1f 100644 --- a/libpsn00b/libc/printf.c +++ b/libpsn00b/libc/vsprintf.c-old @@ -356,7 +356,7 @@ void libc_double_to_string(double fl, char *dst, int n) char libc_sprintf_floatbuf[64]; -int vsnprintf(char *string, unsigned int size, char *fmt, va_list ap) +int vsnprintf(char *string, unsigned int size, const char *fmt, va_list ap) { int string_pos,fmt_pos; int l; @@ -752,12 +752,12 @@ int vsnprintf(char *string, unsigned int size, char *fmt, va_list ap) return string_pos; } -int vsprintf(char *string, char *fmt, va_list ap) +int vsprintf(char *string, const char *fmt, va_list ap) { return vsnprintf(string, 0xffffffff, fmt, ap); } -int sprintf(char *string, char *fmt, ...) +int sprintf(char *string, const char *fmt, ...) { int r; @@ -772,7 +772,7 @@ int sprintf(char *string, char *fmt, ...) return r; } -int snprintf(char *string, unsigned int size, char *fmt, ...) +int snprintf(char *string, unsigned int size, const char *fmt, ...) { int r; diff --git a/libpsn00b/lzp/makefile b/libpsn00b/lzp/makefile index 4f9974f..1560302 100644 --- a/libpsn00b/lzp/makefile +++ b/libpsn00b/lzp/makefile @@ -1,14 +1,12 @@ -PREFIX = mipsel-unknown-elf- +include ../common.mk TARGET = ../liblzp.a CFILES = $(notdir $(wildcard ./*.c)) OFILES = $(addprefix build/,$(CFILES:.c=.o)) -INCLUDE = -I../include - CFLAGS = -g -O2 -msoft-float -fno-builtin -nostdlib -Wa,--strip-local-absolute -AFLAGS = -msoft-float --strip-local-absolute +AFLAGS = -g -msoft-float --strip-local-absolute CC = $(PREFIX)gcc AR = $(PREFIX)ar diff --git a/libpsn00b/psxapi/makefile b/libpsn00b/psxapi/makefile index e97451c..49db884 100644 --- a/libpsn00b/psxapi/makefile +++ b/libpsn00b/psxapi/makefile @@ -2,7 +2,7 @@ # Part of the PSn00bSDK Project # 2019 Lameguy64 / Meido-Tek Productions -PREFIX = mipsel-unknown-elf- +include ../common.mk TARGET = ../libpsxapi.a @@ -11,9 +11,7 @@ SOURCES = stdio fs sys pad AFILES = $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.s)) OFILES = $(addprefix build/,$(AFILES:.s=.o)) -INCLUDE = -I../include - -AFLAGS = -msoft-float -Wa,--strip-local-absolute +AFLAGS = -g -msoft-float -Wa,--strip-local-absolute CC = $(PREFIX)gcc AS = $(PREFIX)as diff --git a/libpsn00b/psxetc/font.c b/libpsn00b/psxetc/font.c index 69d864c..46718d0 100644 --- a/libpsn00b/psxetc/font.c +++ b/libpsn00b/psxetc/font.c @@ -19,7 +19,7 @@ void FntLoad(int x, int y) { pos.x = x; pos.y = y; - _font_tpage = getTPage( 0, 0, pos.x, pos.y ) | 0x200; + _font_tpage = getTPage( 0, 0, pos.x, pos.y ); LoadImage( &pos, tim.paddr ); DrawSync(0); diff --git a/libpsn00b/psxetc/makefile b/libpsn00b/psxetc/makefile index fe29212..56bdce7 100644 --- a/libpsn00b/psxetc/makefile +++ b/libpsn00b/psxetc/makefile @@ -2,7 +2,7 @@ # Part of the PSn00bSDK Project # 2019 Lameguy64 / Meido-Tek Productions -PREFIX = mipsel-unknown-elf- +include ../common.mk TARGET = ../libpsxetc.a @@ -10,8 +10,6 @@ CFILES = $(notdir $(wildcard ./*.c)) AFILES = $(notdir $(wildcard ./*.s)) OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o)) -INCLUDE = -I../include - CFLAGS = -g -O2 -msoft-float -fno-builtin -nostdlib -Wa,--strip-local-absolute AFLAGS = -g -msoft-float --strip-local-absolute diff --git a/libpsn00b/psxgpu/drawsynccallback.s b/libpsn00b/psxgpu/drawsynccallback.s index c1e28fe..37c0375 100644 --- a/libpsn00b/psxgpu/drawsynccallback.s +++ b/libpsn00b/psxgpu/drawsynccallback.s @@ -17,9 +17,12 @@ DrawSyncCallback: beqz $a0, .Luninstall nop + la $a1, _drawsync_handler + lw $a1, 4($sp) jal DMACallback li $a0, 2 + b .Lcontinue nop @@ -52,7 +55,6 @@ DrawSyncCallback: _drawsync_handler: .Ldma_wait: - la $v0, _drawsync_func lw $v0, 0($v0) nop diff --git a/libpsn00b/psxgpu/getinterruptcallback.s b/libpsn00b/psxgpu/getinterruptcallback.s index b465567..510447f 100644 --- a/libpsn00b/psxgpu/getinterruptcallback.s +++ b/libpsn00b/psxgpu/getinterruptcallback.s @@ -11,7 +11,9 @@ GetInterruptCallback: la $a1, _irq_func_table sll $a0, 2 addu $a1, $a0 - - jr $ra lw $v0, 0($a1) + nop + jr $ra + nop +
\ No newline at end of file diff --git a/libpsn00b/psxgpu/makefile b/libpsn00b/psxgpu/makefile index 5eb6265..7a7de5d 100644 --- a/libpsn00b/psxgpu/makefile +++ b/libpsn00b/psxgpu/makefile @@ -2,7 +2,7 @@ # Part of the PSn00bSDK Project # 2019 Lameguy64 / Meido-Tek Productions -PREFIX = mipsel-unknown-elf- +include ../common.mk TARGET = ../libpsxgpu.a @@ -10,10 +10,8 @@ CFILES = $(notdir $(wildcard ./*.c)) AFILES = $(notdir $(wildcard ./*.s)) OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o)) -INCLUDE = -I../include - -CFLAGS = -O2 -msoft-float -fno-builtin -Wa,--strip-local-absolute -AFLAGS = -msoft-float -Wa,--strip-local-absolute +CFLAGS = -g -O2 -msoft-float -fno-builtin -Wa,--strip-local-absolute +AFLAGS = -g -msoft-float -Wa,--strip-local-absolute CC = $(PREFIX)gcc AS = $(PREFIX)as diff --git a/libpsn00b/psxgpu/resetgraph.s b/libpsn00b/psxgpu/resetgraph.s index ff0b353..93ce185 100644 --- a/libpsn00b/psxgpu/resetgraph.s +++ b/libpsn00b/psxgpu/resetgraph.s @@ -4,6 +4,7 @@ .section .text +.set ISR_STACK_SIZE, 1024 .global ResetGraph # Resets the GPU and installs a .type ResetGraph, @function # VSync event handler @@ -306,11 +307,12 @@ _vsync_irq_callback: .type _global_isr, @function _global_isr: - - lui $a0, IOBASE # Get IRQ status .Lisr_loop: + #la $gp, _gp # Keep restoring GP since it gets + # changed elsewhere sometimes + lui $a0, IOBASE # Get IRQ status lw $v0, IMASK($a0) nop @@ -392,10 +394,11 @@ _irq_func_table: .word 0 # Global ISR hook structure +.global _custom_exit .type _custom_exit, @object _custom_exit: .word _global_isr # pc - .word _custom_exit_stack # sp + .word _custom_exit_stack+ISR_STACK_SIZE # sp .word 0 # fp .word _irq_func_table # s0 .word 0 # s1 @@ -408,10 +411,10 @@ _custom_exit: .word _gp # gp # Global ISR stack - .fill 124 -_custom_exit_stack: - .fill 4 - +# .fill 1024 +#_custom_exit_stack: +# .fill 4 +.comm _custom_exit_stack, ISR_STACK_SIZE+4 .type vsynctimeout_msg, @object vsynctimeout_msg: diff --git a/libpsn00b/psxgpu/restartcallback.s b/libpsn00b/psxgpu/restartcallback.s new file mode 100644 index 0000000..ffdeecd --- /dev/null +++ b/libpsn00b/psxgpu/restartcallback.s @@ -0,0 +1,50 @@ +.set noreorder + +.include "hwregs_a.h" + +.section .text + +.global RestartCallback +.type RestartCallback, @function +RestartCallback: + + addiu $sp, -4 + sw $ra, 0($sp) + + la $a0, _custom_exit + jal SetCustomExitFromException + addiu $sp, -12 + + jal ChangeClearPAD + move $a0, $0 + + li $a0, 3 + jal ChangeClearRCnt + move $a1, $0 + + + la $a0, _irq_func_table + move $a1, $0 + move $v0, $0 + +.Lcheck_cbs: + lw $v1, 0($a0) + nop + beqz $v1, .Lno_cb + addiu $a0, 4 + li $v1, 1 + sll $v1, $a1 + or $v0, $v1 +.Lno_cb: + blt $a1, 10, .Lcheck_cbs + addiu $a1, 1 + + lui $a0, IOBASE + sw $0 , ISTAT($a0) + sw $v0, IMASK($a0) + + addiu $sp, 12 + lw $ra, 0($sp) + nop + jr $ra + nop
\ No newline at end of file diff --git a/libpsn00b/psxgpu/storeimage.s b/libpsn00b/psxgpu/storeimage.s new file mode 100644 index 0000000..5d4c793 --- /dev/null +++ b/libpsn00b/psxgpu/storeimage.s @@ -0,0 +1,76 @@ +.set noreorder + +.include "hwregs_a.h" + +.set RECT_x, 0 +.set RECT_y, 2 +.set RECT_w, 4 +.set RECT_h, 6 + +.section .text + + +.global StoreImage +.type StoreImage, @function +StoreImage: + addiu $sp, -8 + sw $ra, 0($sp) + sw $s0, 4($sp) + + lui $s0, 0x1f80 # Set I/O segment base address + +.Lgpu_wait: # Wait for GPU to be ready for commands and DMA + jal ReadGPUstat + nop + srl $v0, 0x1a + andi $v0, 0x5 + li $v1, 5 + bne $v0, $v1, .Lgpu_wait + nop + + lui $v0, 0x400 # Set DMA direction to off + sw $v0, GP1($s0) + + lui $v0, 0x0100 # Clear GPU cache + sw $v0, GP0($s0) + + lui $v1, 0xc000 # Store image from VRAM + sw $v1, GP0($s0) + lw $v0, RECT_x($a0) # Set XY and dimensions of image + lw $v1, RECT_w($a0) + sw $v0, GP0($s0) + sw $v1, GP0($s0) + + lui $v0, 0x400 # Set DMA direction to VRAMtoCPU + ori $v0, 0x3 + sw $v0, GP1($s0) + + lhu $v0, RECT_w($a0) # Get rectangle size + lhu $v1, RECT_h($a0) + nop + mult $v0, $v1 # Calculate BCR value + mflo $v1 + srl $v1, 0x4 + sll $v1, 0x10 + ori $v1, 0x8 + + sw $a1, D2_MADR($s0) # Set DMA base address and transfer length + sw $v1, D2_BCR($s0) + +.Lgpu_wait_2: # Wait for GPU to be ready for commands and DMA + jal ReadGPUstat + nop + srl $v0, 27 + andi $v0, 0x1 + beqz $v0, .Lgpu_wait_2 + nop + + lui $v0, 0x100 # Start DMA transfer + ori $v0, 0x200 + sw $v0, D2_CHCR($s0) + + lw $ra, 0($sp) + lw $s0, 4($sp) + jr $ra + addiu $sp, 8 + diff --git a/libpsn00b/psxgte/makefile b/libpsn00b/psxgte/makefile index 6b0cb28..f460a44 100644 --- a/libpsn00b/psxgte/makefile +++ b/libpsn00b/psxgte/makefile @@ -2,7 +2,7 @@ # Part of the PSn00bSDK Project # 2019 Lameguy64 / Meido-Tek Productions -PREFIX = mipsel-unknown-elf- +include ../common.mk TARGET = ../libpsxgte.a @@ -10,10 +10,8 @@ CFILES = $(notdir $(wildcard ./*.c)) AFILES = $(notdir $(wildcard ./*.s)) OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o)) -INCLUDE = -I../include - -CFLAGS = -O2 -msoft-float -fno-builtin -fdata-sections -ffunction-sections -Wa,--strip-local-absolute -AFLAGS = -msoft-float --strip-local-absolute +CFLAGS = -g -O2 -msoft-float -fno-builtin -fdata-sections -ffunction-sections -Wa,--strip-local-absolute +AFLAGS = -g -msoft-float --strip-local-absolute CC = $(PREFIX)gcc AS = $(PREFIX)as diff --git a/libpsn00b/psxsio/_sio_control.s b/libpsn00b/psxsio/_sio_control.s index bae7822..bf3b9b9 100644 --- a/libpsn00b/psxsio/_sio_control.s +++ b/libpsn00b/psxsio/_sio_control.s @@ -90,8 +90,9 @@ _sio_control: div $v1, $v0 nop nop - jr $ra mflo $v0 + jr $ra + nop .Lcmd0arg4: # Serial RX read @@ -117,14 +118,15 @@ _sio_control: .Lcmd1arg1: andi $v0, $a2, 0x1CFF - - jr $ra sh $a2, SIO_CTRL($a3) + jr $ra + nop .Lcmd1arg2: - jr $ra sh $a2, SIO_MODE($a3) + jr $ra + nop .Lcmd1arg3: diff --git a/libpsn00b/psxsio/makefile b/libpsn00b/psxsio/makefile index ecd6c65..b59f3c6 100644 --- a/libpsn00b/psxsio/makefile +++ b/libpsn00b/psxsio/makefile @@ -2,7 +2,7 @@ # Part of the PSn00bSDK Project # 2019 Lameguy64 / Meido-Tek Productions -PREFIX = mipsel-unknown-elf- +include ../common.mk TARGET = ../libpsxsio.a @@ -10,10 +10,8 @@ CFILES = $(notdir $(wildcard ./*.c)) AFILES = $(notdir $(wildcard ./*.s)) OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o)) -INCLUDE = -I../include - -CFLAGS = -O2 -msoft-float -fno-builtin -Wa,--strip-local-absolute -AFLAGS = -msoft-float -Wa,--strip-local-absolute +CFLAGS = -g -O2 -msoft-float -fno-builtin -Wa,--strip-local-absolute +AFLAGS = -g -msoft-float -Wa,--strip-local-absolute CC = $(PREFIX)gcc AS = $(PREFIX)as diff --git a/libpsn00b/psxspu/makefile b/libpsn00b/psxspu/makefile index d6b3604..661a32b 100644 --- a/libpsn00b/psxspu/makefile +++ b/libpsn00b/psxspu/makefile @@ -1,4 +1,4 @@ -PREFIX = mipsel-unknown-elf- +include ../common.mk TARGET = ../libpsxspu.a @@ -6,9 +6,7 @@ CFILES = $(notdir $(wildcard ./*.c)) AFILES = $(notdir $(wildcard ./*.s)) OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o)) -INCLUDE = -I../include - -CFLAGS = -O2 -g -msoft-float -Wa,--strip-local-absolute +CFLAGS = -g -O2 -msoft-float -Wa,--strip-local-absolute AFLAGS = -g -msoft-float --strip-local-absolute CC = $(PREFIX)gcc diff --git a/libpsn00b/psxspu/spuinit.s b/libpsn00b/psxspu/spuinit.s index 51a54ea..6bfe143 100644 --- a/libpsn00b/psxspu/spuinit.s +++ b/libpsn00b/psxspu/spuinit.s @@ -77,7 +77,7 @@ SpuInit: or $v0, $at sw $v0, DPCR($v1) - li $v0, 0xc000 # Enable SPU + li $v0, 0x8001 # Enable SPU sh $v0, SPUCNT($v1) jal SpuCtrlSync move $a0, $v0 @@ -89,6 +89,9 @@ SpuInit: sh $v0, SPU_CD_VOL($v1) # Activate CD volume sh $v0, SPU_CD_VOL+2($v1) + sh $v0, SPU_CD_VOL($v1) # Activate CD volume + sh $v0, SPU_CD_VOL+2($v1) + lw $ra, 0($sp) addiu $sp, 4 jr $ra diff --git a/toolchain.txt b/toolchain.txt index c9ae101..14807bb 100644 --- a/toolchain.txt +++ b/toolchain.txt @@ -1,44 +1,119 @@ -If you wish to build the toolchain yourself, beware that this process can get pretty tedious. A system with at least 4 physical cores or 8 total threads is recommended. You may have better success building the toolchain in ArchLinux especially if you want to build the most recent version of GCC. +If you wish to build the toolchain yourself, beware that this process can get +pretty tedious. A system with at least 4 to 8 total threads or more is +recommended. You may have better success building the toolchain in ArchLinux +especially if you want to build the most recent versions. -These instructions may work for Windows using MSys2 or Cygwin64. +It is recommended to stick with GCC 7.4.0 and Binutils 2.31 as this is the +version PSn00bSDK is most tested with. + +These instructions are only for Linux, though they can be adapted for +building in Windows using MSys2 or Cygwin64. Beware that libgcc cannot +be built under Windows as the libgcc build process depends on symlinks +which is not supported in Msys2 and Cygwin64. The only workaround is to +obtain a prebuilt copy of libgcc from a Linux build of GCC. + + +Before building, the following packages must be installed: +* make +* texinfo +* mpfr (development libs) +* isl (development libs) +* gmp (development libs) +* mpc (development libs) Building binutils: -* Download binutils source files at ftp://ftp.gnu.org and choose a version you prefer to use. -* Extract the contents of the archive. Preferably to a directory called gcc for example. +* Download binutils source files at ftp://ftp.gnu.org, choose a version you + with to use with PSn00bSDK. +* Extract the contents of the archive, preferably to a directory called gcc + for example. * Create a directory named binutils-build inside the gcc directory. -* Configure binutils from the binutils-build directory with the following parameters: +* Configure binutils from the binutils-build directory with the following + command line: -../binutils-<version>/configure --prefix=/usr/local/mipsel-unknown-elf --target=mipsel-unknown-elf --with-float=soft +../binutils-<version>/configure --prefix=/usr/local/mipsel-unknown-elf \ +--target=mipsel-unknown-elf --with-float=soft -Replace <version> with the version of binutils you downloaded. You may also want to change the prefix to a path you wish to install the toolchain to. -* Run 'make -j 4' to compile binutils (-j specifies how many jobs to execute at once). -* Run make install-strip to install binutils to the path specified by --prefix (may require root priviledges). Binutils needs to be installed in order for GCC to compile. +Replace <version> with the version of binutils you wish to use. You may also +want to change the prefix to a path you may wish to have the toolchain +installed to (ie. in your home folder). + +* Run `make -j 4` to compile binutils (-j specifies how many simultaneously + jobs to spawn at once). +* Run `make install-strip` to install binutils to the path specified by + --prefix (requires root privileges if you install at /usr/local). Binutils + needs to be built and installed first so that GCC can be build. Building gcc: -* Download gcc source files at ftp://ftp.gnu.org and choose a version you prefer to use. -* Extract it to the same directory you extracted binutils in. +* Download gcc source files at ftp://ftp.gnu.org and choose a version you + wish to use with PSn00bSDK. +* Extract it to the same gcc directory you extracted binutils in. * Create a directory named gcc-build inside the gcc directory. -* Configure gcc from the gcc-build directory with the following parameters: +* Configure gcc from the gcc-build directory with the following command + line: + +../gcc-<version>/configure --disable-nls --disable-libada --disable-libssp \ +--disable-libquadmath --disable-libstdc++-v3 --target=mipsel-unknown-elf \ +--prefix=/usr/local/mipsel-unknown-elf --with-float=soft \ +--enable-languages=c,c++ --with-gnu-as --with-gnu-ld -../gcc-<version>/configure --disable-nls --disable-libada --disable-libssp --disable-libquadmath --disable-libstdc++-v3 --target=mipsel-unknown-elf --prefix=/usr/local/mipsel-unknown-elf --with-float=soft --enable-languages=c,c++ --with-gnu-as --with-gnu-ld +Replace <version> with the version of gcc you downloaded. The prefix path +must be the same as what you've specified for binutils. -Replace <version> with the version of gcc you downloaded. The prefix must be the same as the prefix you specified for binutils. * Run make in the same manner as you built binutils to build gcc. -* Run make install-strip to install gcc (may require root priviledges). -* Include the path to the bin directory of the toolchain you just built into your PATH environment variable. The compiler and binutils programs are prefixed with mipsel-unknown-elf (ie. mipsel-unknown-elf-gcc). +* Run `make install-strip` to install gcc (may require root privileges). +* Include the path to the bin directory of the toolchain you just built + into your PATH environment variable. The compiler and binutils programs + are prefixed with mipsel-unknown-elf (ie. mipsel-unknown-elf-gcc). -Note regarding C++ support: +Update ldscript: -By default C++ support such as classes are unavailable due to the lack of a C++ support library as GCC's stdc++-v3 never seems to compile for mipsel-unknown-elf which explains why the suggested config disables it. Newlib may work instead but it might be too bloated to be practical to use on the PS1 considering the system only has 2MB of DRAM so more than 200KB taken up by libraries to support C++ is considered unacceptable in the PSn00bSDK project. +* Go to mipsel-unknown-elf/lib/ldscripts in the mipsel-unknown-elf toolchain + directory. +* Open elf32elmip.x in any text editor. +* Locate the .text definition (with the {} brackets) and place the following + inside the bracket block: +__CTOR_LIST__ = .; +___CTOR_LIST__ = .; +LONG (((__CTOR_END__ - __CTOR_LIST__) / 4) - 2) +KEEP (*(SORT (.ctors.*))) +KEEP (*(.ctors)) +LONG (0x00000000) +__CTOR_END__ = .; +. = ALIGN (0x10); -Note for Windows users: +__DTOR_LIST__ = .; +___DTOR_LIST__ = .; +LONG (((__DTOR_END__ - __DTOR_LIST__) / 4) - 2) +KEEP (*(SORT (.dtors.*))) +KEEP (*(.dtors)) +LONG (0x00000000) +__DTOR_END__ = .; +. = ALIGN (0x10); -From my experience GCC won't build with libgcc even in Msys, Msys2 and Cygwin64. To get around this you'll have to steal a copy of the libgcc libraries from a Linux build. A complete binary download of PSn00bSDK for Windows should have this library included. +* Save script changes. + +This is mandatory in order for libc to link correctly. These symbols are +necessary to get C++ constructors to work on program start and +deconstructors on program end. + +Since there's no known way to configure GCC to always use customized +scripts in the ldscripts directory, you must specify the modified +script during the linking stage of your programs. + +Alternatively, you can make a copy of the ldscript if you wish to customize +it for a specific project, particularly when using code overlays. + + +Note regarding C++ support: -If you don't compile with libgcc int64 and floating point emulation will be unavailable so the advice of getting GCC to compile by disabling libgcc is like repairing the flat tire of a car by taking out the tire entirely. Though use of in64 and floating point are not really optimal on the PS1 hardware to begin with.
\ No newline at end of file +C++ support in PSn00bSDK only goes as far as basic classes, namespaces and +the ability to dynamically create and delete class objects at any point of +your program, the required dependencies are supplied by libc of libpsn00b. +Standard C++ libraries are not implemented and likely never going to be +implemented due to bloat concerns. diff --git a/tools/smxlink/makefile b/tools/smxlink/makefile index b50fd26..ff759b1 100644 --- a/tools/smxlink/makefile +++ b/tools/smxlink/makefile @@ -4,6 +4,8 @@ CPPFILES = main.cpp timreader.cpp CFLAGS = -O2 LDFLAGS = -s +INCLUDE = +LIBDIRS = LIBS = -ltinyxml2 CC = gcc @@ -13,9 +15,10 @@ OFILES = $(addprefix build/,$(CPPFILES:.cpp=.o)) ifeq "$(OS)" "Windows_NT" -# Config for Windows +# Config for Windows (comment out if in msys2) INCLUDE = -I/c/tinyxml2 LIBDIRS = -L/c/tinyxml2 + TARGET := $(TARGET).exe else |
