aboutsummaryrefslogtreecommitdiff
path: root/libpsn00b
diff options
context:
space:
mode:
authorJohn "Lameguy" Wilbert Villamor <lameguy64@gmail.com>2022-01-18 08:31:14 +0800
committerGitHub <noreply@github.com>2022-01-18 08:31:14 +0800
commit05d44488bd5587786f4bd0286fc0f555c79aa46a (patch)
tree5740f396d10a9580c3a39ca536544436898ff1b6 /libpsn00b
parent08de895e8582dbc70b639ae5f511ab9ebfb4d68a (diff)
parente9475e283a82665fe6c19bebc3318b5084f15a2e (diff)
downloadpsn00bsdk-05d44488bd5587786f4bd0286fc0f555c79aa46a.tar.gz
Merge pull request #44 from spicyjpeg/actions
GitHub Actions CI, psxcd and libc fixes, new examples
Diffstat (limited to 'libpsn00b')
-rw-r--r--libpsn00b/CMakeLists.txt20
-rw-r--r--libpsn00b/build.json.template8
-rw-r--r--libpsn00b/cmake/flags.cmake151
-rw-r--r--libpsn00b/cmake/internal_setup.cmake23
-rw-r--r--libpsn00b/cmake/sdk.cmake10
-rw-r--r--libpsn00b/cmake/virtual_targets.cmake109
-rw-r--r--libpsn00b/include/dlfcn.h101
-rw-r--r--libpsn00b/include/psxcd.h6
-rw-r--r--libpsn00b/include/psxgpu.h2
-rw-r--r--libpsn00b/include/psxpad.h328
-rw-r--r--libpsn00b/include/psxspu.h4
-rw-r--r--libpsn00b/ldscripts/dll.ld4
-rw-r--r--libpsn00b/ldscripts/exe.ld2
-rw-r--r--libpsn00b/libc/scanf.c7
-rw-r--r--libpsn00b/libc/string.c14
-rw-r--r--libpsn00b/libc/vsprintf.c11
-rw-r--r--libpsn00b/psxcd/cdgetsector.s3
-rw-r--r--libpsn00b/psxcd/isofs.c30
-rw-r--r--libpsn00b/psxcd/psxcd.c16
-rw-r--r--libpsn00b/psxetc/_dl_resolve_wrapper.s14
-rw-r--r--libpsn00b/psxetc/dl.c51
-rw-r--r--libpsn00b/psxgpu/gettimimage.c2
22 files changed, 537 insertions, 379 deletions
diff --git a/libpsn00b/CMakeLists.txt b/libpsn00b/CMakeLists.txt
index 7b5f7a5..829a2f7 100644
--- a/libpsn00b/CMakeLists.txt
+++ b/libpsn00b/CMakeLists.txt
@@ -58,12 +58,28 @@ add_custom_command(
## Installation
install(
- TARGETS ${PSN00BSDK_LIBRARIES} ${PSN00BSDK_VIRTUAL_TARGETS}
+ TARGETS ${PSN00BSDK_LIBRARIES}
DESTINATION ${CMAKE_INSTALL_LIBDIR}/libpsn00b
EXPORT libpsn00b
)
install(
- DIRECTORY cmake include ldscripts
+ DIRECTORY cmake ldscripts
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}/libpsn00b
+)
+install(
+ DIRECTORY include/
+ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/libpsn00b
+)
+
+# Generate build.json. This file is used to determine the SDK version after
+# installation and may contain additional metadata about the build.
+configure_file(
+ build.json.template build.json
+ ESCAPE_QUOTES
+ NEWLINE_STYLE LF
+)
+install(
+ FILES ${PROJECT_BINARY_DIR}/build.json
DESTINATION ${CMAKE_INSTALL_LIBDIR}/libpsn00b
)
diff --git a/libpsn00b/build.json.template b/libpsn00b/build.json.template
new file mode 100644
index 0000000..374b22a
--- /dev/null
+++ b/libpsn00b/build.json.template
@@ -0,0 +1,8 @@
+{
+ "version": "${PSN00BSDK_VERSION}",
+ "build_date": "${PSN00BSDK_BUILD_DATE}",
+ "git_tag": "${PSN00BSDK_GIT_TAG}",
+ "git_commit": "${PSN00BSDK_GIT_COMMIT}",
+ "cmake_version": "${CMAKE_VERSION}",
+ "host_system": "${CMAKE_HOST_SYSTEM_NAME}"
+}
diff --git a/libpsn00b/cmake/flags.cmake b/libpsn00b/cmake/flags.cmake
new file mode 100644
index 0000000..249c5b4
--- /dev/null
+++ b/libpsn00b/cmake/flags.cmake
@@ -0,0 +1,151 @@
+# libpsn00b interface targets
+# (C) 2021 spicyjpeg - MPL licensed
+
+# This script creates several "virtual" targets (psn00bsdk_*) that set include
+# directories and compiler flags when a target is linked against them. The
+# following targets are currently defined:
+# - psn00bsdk_common
+# - psn00bsdk_object_lib (same as psn00bsdk_common)
+# - psn00bsdk_static_exe
+# - psn00bsdk_dynamic_exe
+# - psn00bsdk_static_lib
+# - psn00bsdk_shared_lib
+# - psn00bsdk_module_lib (same as psn00bsdk_shared_lib)
+#
+# NOTE: building a static library and linking it as part of a DLL is currently
+# *not* supported.
+
+if(NOT TARGET psn00bsdk_common) # Include guard
+
+add_library(psn00bsdk_common INTERFACE)
+
+foreach(
+ _target IN ITEMS
+ object_lib
+ static_exe
+ dynamic_exe
+ static_lib
+ shared_lib
+ module_lib
+)
+ add_library (psn00bsdk_${_target} INTERFACE)
+ target_link_libraries(psn00bsdk_${_target} INTERFACE psn00bsdk_common)
+endforeach()
+
+# Options common to all target types:
+# - Define PLAYSTATION=1
+# - Optimize for MIPS R3000
+# - Inject zero checks into division operations (will throw breaks)
+# - All standard libraries (including libgcc) disabled
+# - Put all symbols into separate sections when building
+# - C++ features that require runtime support disabled
+# - Unused section stripping enabled
+target_compile_options(
+ psn00bsdk_common INTERFACE
+ # CPU options
+ -msoft-float
+ -march=r3000
+ -mtune=r3000
+ -mabi=32
+ -mdivide-breaks
+ -O2
+ # Standard library options
+ -ffreestanding
+ -fno-builtin
+ -nostdlib
+ # Other options
+ -fdata-sections
+ -ffunction-sections
+ -fsigned-char
+ -fno-strict-overflow
+ -fdiagnostics-color=always
+ $<$<COMPILE_LANGUAGE:CXX>:
+ # C++ options
+ -fno-exceptions
+ -fno-rtti
+ -fno-unwind-tables
+ -fno-threadsafe-statics
+ -fno-use-cxa-atexit
+ >
+)
+target_link_options(
+ psn00bsdk_common INTERFACE
+ -nostdlib
+ -Wl,-gc-sections
+)
+target_compile_definitions(
+ psn00bsdk_common INTERFACE
+ PLAYSTATION=1
+ $<$<CONFIG:DEBUG>:DEBUG=1>
+)
+
+# Options for executables without support for dynamic linking:
+# - Position-independent code disabled
+# - GP-relative addressing enabled only for local symbols
+# - ABI-compatible calls disabled (incompatible with GP-relative addr)
+target_compile_options(
+ psn00bsdk_static_exe INTERFACE
+ -G8
+ -fno-pic
+ -mno-abicalls
+ -mgpopt
+ -mno-extern-sdata
+)
+target_link_options(
+ psn00bsdk_static_exe INTERFACE
+ -G8
+ -static
+)
+
+# Options for executables with support for dynamic linking:
+# - Position-independent code disabled
+# - GP-relative addressing disabled
+# - ABI-compatible calls disabled (must be performed manually)
+target_compile_options(
+ psn00bsdk_dynamic_exe INTERFACE
+ -G0
+ -fno-pic
+ -mno-abicalls
+ -mno-gpopt
+)
+target_link_options(
+ psn00bsdk_dynamic_exe INTERFACE
+ -G0
+ -static
+)
+
+# Options for static libraries:
+# - Position-independent code disabled
+# - GP-relative addressing disabled
+# - ABI-compatible calls disabled
+# - Local stripping enabled
+target_compile_options(
+ psn00bsdk_static_lib INTERFACE
+ -G0
+ -fno-pic
+ -mno-abicalls
+ -mno-gpopt
+ -Wa,--strip-local-absolute
+)
+
+# Options for dynamically-loaded libraries:
+# - Position-independent code enabled
+# - GP-relative addressing disabled (incompatible with ABI calls)
+# - ABI-compatible calls enabled
+target_compile_options(
+ psn00bsdk_shared_lib INTERFACE
+ -G0
+ -fPIC
+ -mabicalls
+ -mno-gpopt
+ -mshared
+)
+target_link_options(
+ psn00bsdk_shared_lib INTERFACE
+ -G0
+ -shared
+)
+
+target_link_libraries(psn00bsdk_module_lib INTERFACE psn00bsdk_shared_lib)
+
+endif()
diff --git a/libpsn00b/cmake/internal_setup.cmake b/libpsn00b/cmake/internal_setup.cmake
index b0c4591..7d6bfdd 100644
--- a/libpsn00b/cmake/internal_setup.cmake
+++ b/libpsn00b/cmake/internal_setup.cmake
@@ -7,8 +7,15 @@
cmake_minimum_required(VERSION 3.20)
include(GNUInstallDirs)
-# IMPORTANT TODO: set a version number
-set(PSN00BSDK_VERSION 0.1.0)
+# Fetch SDK version information from build.json.
+if(NOT DEFINED PSN00BSDK_VERSION)
+ file(READ ${CMAKE_CURRENT_LIST_DIR}/../build.json _json)
+
+ string(JSON PSN00BSDK_VERSION GET ${_json} version)
+ string(JSON PSN00BSDK_BUILD_DATE GET ${_json} build_date)
+ string(JSON PSN00BSDK_GIT_TAG GET ${_json} git_tag)
+ string(JSON PSN00BSDK_GIT_COMMIT GET ${_json} git_commit)
+endif()
## Settings (can be overridden by projects)
@@ -22,9 +29,7 @@ set(PSN00BSDK_SYMBOL_MAP_SUFFIX ".map")
set(PSN00BSDK_LIBRARIES psxgpu psxgte psxspu psxcd psxsio psxetc psxapi lzp c)
include(${CMAKE_CURRENT_LIST_DIR}/libpsn00b.cmake OPTIONAL)
-if(NOT TARGET psn00bsdk_common)
- include(${CMAKE_CURRENT_LIST_DIR}/virtual_targets.cmake)
-endif()
+include(${CMAKE_CURRENT_LIST_DIR}/flags.cmake)
# Use the toolchain path to find libgcc (used to build libpsn00b). Of course
# different installers, packages and distros have different opinions when it
@@ -59,14 +64,18 @@ set(
find_program(ELF2X elf2x HINTS ${PSN00BSDK_TOOLS})
find_program(ELF2CPE elf2cpe HINTS ${PSN00BSDK_TOOLS})
-find_program(SMXLINK elf2x HINTS ${PSN00BSDK_TOOLS})
+find_program(SMXLINK smxlink HINTS ${PSN00BSDK_TOOLS})
find_program(LZPACK lzpack HINTS ${PSN00BSDK_TOOLS})
find_program(MKPSXISO mkpsxiso HINTS ${PSN00BSDK_TOOLS})
## Helper functions for executables
-set(PSN00BSDK_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../include)
set(PSN00BSDK_LDSCRIPTS ${CMAKE_CURRENT_LIST_DIR}/../ldscripts)
+if(IS_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/../include)
+ set(PSN00BSDK_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../include)
+else()
+ set(PSN00BSDK_INCLUDE ${CMAKE_CURRENT_LIST_DIR}/../../../include/libpsn00b)
+endif()
# psn00bsdk_add_executable(
# <target name> <STATIC|DYNAMIC>
diff --git a/libpsn00b/cmake/sdk.cmake b/libpsn00b/cmake/sdk.cmake
index ae23a06..d6d9bcd 100644
--- a/libpsn00b/cmake/sdk.cmake
+++ b/libpsn00b/cmake/sdk.cmake
@@ -4,11 +4,11 @@
cmake_minimum_required(VERSION 3.20)
set(
- PSN00BSDK_TC $ENV{PSN00BSDK_TC}
- CACHE PATH "Path to the GCC toolchain's installation directory"
+ PSN00BSDK_TC ""
+ CACHE PATH "Path to the GCC toolchain's installation directory (if not in PATH)"
)
set(
- PSN00BSDK_TARGET mipsel-unknown-elf
+ PSN00BSDK_TARGET mipsel-none-elf
CACHE STRING "GCC toolchain target triplet"
)
@@ -26,7 +26,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# toolchain settings to the generated test projects. This dodges missing C++
# standard library errors.
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
-set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES PSN00BSDK_TC PSN00BSDK_TARGET)
+set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES PSN00BSDK_TC PSN00BSDK_TARGET PSN00BSDK_VERSION)
## Toolchain path setup
@@ -56,7 +56,7 @@ cmake_path(GET _bin PARENT_PATH _toolchain)
if(NOT IS_DIRECTORY PSN00BSDK_TC)
set(
PSN00BSDK_TC ${_toolchain}
- CACHE PATH "Path to the GCC toolchain's installation directory"
+ CACHE PATH "Path to the GCC toolchain's installation directory (if not in PATH)"
FORCE
)
endif()
diff --git a/libpsn00b/cmake/virtual_targets.cmake b/libpsn00b/cmake/virtual_targets.cmake
deleted file mode 100644
index 9afcebd..0000000
--- a/libpsn00b/cmake/virtual_targets.cmake
+++ /dev/null
@@ -1,109 +0,0 @@
-# libpsn00b interface targets
-# (C) 2021 spicyjpeg - MPL licensed
-
-# This script creates several "virtual" targets (psn00bsdk_*) that set include
-# directories and compiler flags when a target is linked against them. These
-# all end up in the autogenerated libpsn00b setup script after installation,
-# so this file is only included when building libpsn00b.
-
-# The following targets are currently defined:
-# - psn00bsdk_common
-# - psn00bsdk_object_lib (same as psn00bsdk_common)
-# - psn00bsdk_static_exe
-# - psn00bsdk_dynamic_exe
-# - psn00bsdk_static_lib
-# - psn00bsdk_shared_lib
-# - psn00bsdk_module_lib (same as psn00bsdk_shared_lib)
-
-include(GNUInstallDirs)
-
-set(PSN00BSDK_VIRTUAL_TARGETS "")
-
-macro(_add_interface_target name)
- add_library(${name} INTERFACE)
- list(APPEND PSN00BSDK_VIRTUAL_TARGETS ${name})
-
- target_compile_options(
- ${name} INTERFACE
- ${_aflags}
- $<$<COMPILE_LANGUAGE:C,CXX>:${_cflags}>
- $<$<COMPILE_LANGUAGE:CXX>:${_cxxflags}>
- )
- target_link_options (${name} INTERFACE ${_ldflags})
- target_link_libraries(${name} INTERFACE ${ARGN})
-endmacro()
-
-macro(_add_alias_target name)
- #add_library(${name} ALIAS ${ARGN})
- add_library(${name} INTERFACE)
- list(APPEND PSN00BSDK_VIRTUAL_TARGETS ${name})
-
- target_link_libraries(${name} INTERFACE ${ARGN})
-endmacro()
-
-# Options common to all target types:
-# - Define PLAYSTATION=1 and set include directories
-# - Optimize for MIPS R3000
-# - Inject zero checks into division operations (will throw breaks)
-# - All standard libraries (including libgcc) disabled
-# - Put all symbols into separate sections when building
-# - C++ features that require runtime support disabled
-# - Unused section stripping enabled
-set(_aflags -msoft-float -march=r3000 -mtune=r3000 -mabi=32)
-set(_cflags -mdivide-breaks -O2 -ffreestanding -fno-builtin -nostdlib -fdata-sections -ffunction-sections -fsigned-char -fno-strict-overflow -fdiagnostics-color=always)
-set(_cxxflags -fno-exceptions -fno-rtti -fno-unwind-tables -fno-threadsafe-statics -fno-use-cxa-atexit)
-set(_ldflags -nostdlib -Wl,-gc-sections)
-
-_add_interface_target(psn00bsdk_common)
-_add_alias_target (psn00bsdk_object_lib psn00bsdk_common)
-
-target_compile_definitions(
- psn00bsdk_common INTERFACE
- PLAYSTATION=1
- $<$<CONFIG:DEBUG>:DEBUG=1>
-)
-
-# Options for executables without support for dynamic linking:
-# - Position-independent code disabled
-# - GP-relative addressing enabled only for local symbols
-# - ABI-compatible calls disabled (incompatible with GP-relative addr)
-set(_aflags -G8)
-set(_cflags -mno-abicalls -mgpopt -mno-extern-sdata)
-set(_cxxflags)
-set(_ldflags -G8 -static)
-
-_add_interface_target(psn00bsdk_static_exe psn00bsdk_common)
-
-# Options for executables with support for dynamic linking:
-# - Position-independent code disabled
-# - GP-relative addressing disabled
-# - ABI-compatible calls disabled (must be performed manually)
-set(_aflags -G0)
-set(_cflags -mno-abicalls -mno-gpopt)
-set(_cxxflags)
-set(_ldflags -G0 -static)
-
-_add_interface_target(psn00bsdk_dynamic_exe psn00bsdk_common)
-
-# Options for static libraries:
-# - GP-relative addressing disabled
-# - ABI-compatible calls disabled
-# - Local stripping enabled
-set(_aflags -G0 -Wa,--strip-local-absolute)
-set(_cflags -mno-abicalls -mno-gpopt)
-set(_cxxflags)
-set(_ldflags)
-
-_add_interface_target(psn00bsdk_static_lib psn00bsdk_common)
-
-# Options for dynamically-loaded libraries:
-# - Position-independent code enabled
-# - GP-relative addressing disabled (incompatible with ABI calls)
-# - ABI-compatible calls enabled
-set(_aflags -G0)
-set(_cflags -mabicalls -mshared -mno-gpopt -fPIC)
-set(_cxxflags)
-set(_ldflags -G0 -shared)
-
-_add_interface_target(psn00bsdk_shared_lib psn00bsdk_common)
-_add_alias_target (psn00bsdk_module_lib psn00bsdk_shared_lib)
diff --git a/libpsn00b/include/dlfcn.h b/libpsn00b/include/dlfcn.h
index b3a5cec..6874d06 100644
--- a/libpsn00b/include/dlfcn.h
+++ b/libpsn00b/include/dlfcn.h
@@ -21,39 +21,39 @@
#define RTLD_DEFAULT ((DLL *) 0)
typedef enum _DL_Error {
- RTLD_E_NONE = 0, // No error
- RTLD_E_FILE_OPEN = 1, // Unable to find or open file
- RTLD_E_FILE_ALLOC = 2, // Unable to allocate buffer to load file into
- RTLD_E_FILE_READ = 3, // Failed to read file
- RTLD_E_NO_MAP = 4, // No symbol map has been loaded yet
- RTLD_E_MAP_ALLOC = 5, // Unable to allocate symbol map structures
- RTLD_E_NO_SYMBOLS = 6, // No symbols found in symbol map
- RTLD_E_DLL_NULL = 7, // Unable to initialize DLL from null pointer
- RTLD_E_DLL_ALLOC = 8, // Unable to allocate DLL metadata structures
- RTLD_E_DLL_FORMAT = 9, // Unsupported DLL type or format
- RTLD_E_NO_FILE_API = 10, // psxetc has been built without file support
- RTLD_E_MAP_SYMBOL = 11, // Symbol not found in symbol map
- RTLD_E_DLL_SYMBOL = 12, // Symbol not found in DLL
- RTLD_E_HASH_LOOKUP = 13 // Hash table lookup failed due to internal error
+ RTLD_E_NONE = 0, // No error
+ RTLD_E_FILE_OPEN = 1, // Unable to find or open file
+ RTLD_E_FILE_ALLOC = 2, // Unable to allocate buffer to load file into
+ RTLD_E_FILE_READ = 3, // Failed to read file
+ RTLD_E_NO_MAP = 4, // No symbol map has been loaded yet
+ RTLD_E_MAP_ALLOC = 5, // Unable to allocate symbol map structures
+ RTLD_E_NO_SYMBOLS = 6, // No symbols found in symbol map
+ RTLD_E_DLL_NULL = 7, // Unable to initialize DLL from null pointer
+ RTLD_E_DLL_ALLOC = 8, // Unable to allocate DLL metadata structures
+ RTLD_E_DLL_FORMAT = 9, // Unsupported DLL type or format
+ RTLD_E_MAP_SYMBOL = 10, // Symbol not found in symbol map
+ RTLD_E_DLL_SYMBOL = 11, // Symbol not found in DLL
+ RTLD_E_HASH_LOOKUP = 12 // Hash table lookup failed due to internal error
} DL_Error;
typedef enum _DL_ResolveMode {
- RTLD_LAZY = 1, // Resolve functions when they are first called (default)
- RTLD_NOW = 2 // Resolve all symbols immediately on load
+ RTLD_LAZY = 1, // Resolve functions when they are first called (default)
+ RTLD_NOW = 2, // Resolve all symbols immediately on load
+ RTLD_FREE_ON_DESTROY = 4 // Automatically free DLL buffer when closing DLL
} DL_ResolveMode;
// Members of this struct should not be accessed directly in most cases, but
// they are intentionally exposed for easier expandability.
typedef struct _DLL {
- void *ptr;
- void *malloc_ptr;
- size_t size;
- const uint32_t *hash;
- uint32_t *got;
- Elf32_Sym *symtab;
- const char *strtab;
- uint16_t symbol_count;
- uint16_t got_length;
+ void *ptr;
+ void *malloc_ptr;
+ size_t size;
+ const uint32_t *hash;
+ uint32_t *got;
+ Elf32_Sym *symtab;
+ const char *strtab;
+ uint16_t symbol_count;
+ uint16_t got_length;
} DLL;
/* API */
@@ -62,8 +62,6 @@ typedef struct _DLL {
extern "C" {
#endif
-// TODO: rewrite these javadoc comments into proper documentation
-
/**
* @brief Reads the symbol table from the provided string buffer (which may or
* may not be null-terminated), parses it and stores the parsed entries into a
@@ -80,13 +78,14 @@ extern "C" {
* file in the appropriate format after building the executable, by using this
* command:
*
- * mipsel-unknown-elf-nm -f posix -l -n executable.elf >executable.map
+ * mipsel-none-elf-nm -f posix -l -n executable.elf >executable.map
*
* @param ptr
* @param size
* @return -1 or number of entries parsed
*/
int32_t DL_ParseSymbolMap(const char *ptr, size_t size);
+
/**
* @brief File wrapper around DL_ParseSymbolMap(). Allocates a temporary buffer
* then loads the specified map file into it (using BIOS APIs) and calls
@@ -96,14 +95,16 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size);
* @param filename Must always contain device name, e.g. "cdrom:MODULE.DLL;1"
* @return -1 or number of entries parsed
*/
-int32_t DL_LoadSymbolMap(const char *filename);
+//int32_t DL_LoadSymbolMapFromFile(const char *filename);
+
/**
* @brief Frees internal buffers containing the currently loaded symbol map.
* This is automatically done before loading a new symbol map so there is no
* need to call this function in most cases, however it can still be useful to
* free up space on the heap once the symbol map is no longer needed.
*/
-void DL_UnloadSymbolMap(void);
+void DL_UnloadSymbolMap(void);
+
/**
* @brief Queries the currently loaded symbol map for the symbol with the given
* name and returns a pointer to it, which can then be used to directly access
@@ -112,7 +113,8 @@ void DL_UnloadSymbolMap(void);
* @param name
* @return NULL or pointer to symbol (any type)
*/
-void *DL_GetSymbolByName(const char *name);
+void *DL_GetSymbolByName(const char *name);
+
/**
* @brief Sets a custom function to be called for resolving symbols in DLLs.
* The function will be given a pointer to the current DLL and the unresolved
@@ -123,7 +125,7 @@ void *DL_GetSymbolByName(const char *name);
*
* @param callback NULL or pointer to callback function
*/
-void DL_SetResolveCallback(void *(*callback)(DLL *, const char *));
+void DL_SetResolveCallback(void *(*callback)(DLL *, const char *));
/**
* @brief Initializes a buffer holding the contents of a dynamically-loaded
@@ -131,8 +133,8 @@ void DL_SetResolveCallback(void *(*callback)(DLL *, const char *));
* binary) *in-place*. A new DLL struct is allocated to store metadata but,
* unlike DL_ParseSymbolMap(), the DLL's actual code, data and tables are
* referenced directly from the provided buffer. The buffer must not be moved
- * or deallocated, at least not before calling dlclose() on the DLL struct
- * returned by this function.
+ * or deallocated, at least not before calling DL_DestroyDLL() on the DLL
+ * struct returned by this function.
*
* The third argument specifies when symbols in the DLL should be resolved.
* Setting it to RTLD_LAZY defers resolution of undefined functions to when
@@ -145,7 +147,8 @@ void DL_SetResolveCallback(void *(*callback)(DLL *, const char *));
* @param mode RTLD_LAZY or RTLD_NOW
* @return NULL or pointer to a new DLL struct
*/
-DLL *dlinit(void *ptr, size_t size, DL_ResolveMode mode);
+DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode);
+
/**
* @brief File wrapper around dlinit(). Allocates a new buffer, loads the
* specified file into it (using BIOS APIs) and calls dlinit() on that. When
@@ -153,19 +156,22 @@ DLL *dlinit(void *ptr, size_t size, DL_ResolveMode mode);
* automatically destroyed.
*
* @param filename Must always contain device name, e.g. "cdrom:MODULE.DLL;1"
- * @param mode RTLD_LAZY or RTLD_NOW
+ * @param mode RTLD_LAZY or RTLD_NOW + optionally RTLD_FREE_ON_DESTROY
* @return NULL or pointer to a new DLL struct
*/
-DLL *dlopen(const char *filename, DL_ResolveMode mode);
+//DLL *DL_LoadDLLFromFile(const char *filename, DL_ResolveMode mode);
+
/**
* @brief Destroys a loaded DLL by calling its global destructors and freeing
- * the buffer it's loaded in. Any pointer passed to dlclose() should no longer
- * be used after the call. If the DLL was initialized in-place using dlinit(),
- * dlclose() will *NOT* free the buffer initially passed to dlinit().
+ * the buffer it's loaded in. Any pointer passed to DL_DestroyDLL() should no
+ * longer be used after the call. If the DLL was initialized in-place using
+ * DL_CreateDLL(), DL_DestroyDLL() will only free the buffer initially passed
+ * to DL_CreateDLL() if RTLD_FREE_ON_DESTROY was used.
*
* @param dll
*/
-void dlclose(DLL *dll);
+void DL_DestroyDLL(DLL *dll);
+
/**
* @brief Returns a pointer to the DLL symbol with the given name, or null if
* it can't be found. If null or RTLD_DEFAULT is passed as first argument, the
@@ -176,7 +182,8 @@ void dlclose(DLL *dll);
* @param name
* @return NULL or pointer to symbol (any type)
*/
-void *dlsym(DLL *dll, const char *name);
+void *DL_GetDLLSymbol(const DLL *dll, const char *name);
+
/**
* @brief Returns a code describing the last error that occurred, or DL_E_NONE
* if no error has occurred since the last call to dlerror() (i.e. calling this
@@ -184,7 +191,15 @@ void *dlsym(DLL *dll, const char *name);
*
* @return NULL or member of DL_Error enum
*/
-DL_Error dlerror(void);
+DL_Error DL_GetLastError(void);
+
+/* POSIX "compatibility" macros */
+
+#define dlinit(ptr, size, mode) DL_CreateDLL(ptr, size, mode)
+//#define dlopen(filename, mode) DL_LoadDLLFromFile(filename, mode)
+#define dlsym(dll, name) DL_GetDLLSymbol(dll, name)
+#define dlclose(dll) DL_DestroyDLL(dll)
+#define dlerror() DL_GetLastError()
#ifdef __cplusplus
}
diff --git a/libpsn00b/include/psxcd.h b/libpsn00b/include/psxcd.h
index ffbe86b..3336963 100644
--- a/libpsn00b/include/psxcd.h
+++ b/libpsn00b/include/psxcd.h
@@ -132,9 +132,9 @@ CdlLOC* CdIntToPos(int i, CdlLOC *p);
int CdPosToInt(CdlLOC *p);
int CdGetToc(CdlLOC *toc);
-int CdControl(u_char com, u_char *param, u_char *result);
-int CdControlB(u_char com, u_char *param, u_char *result);
-int CdControlF(u_char com, u_char *param);
+int CdControl(u_char com, const void *param, u_char *result);
+int CdControlB(u_char com, const void *param, u_char *result);
+int CdControlF(u_char com, const void *param);
int CdSync(int mode, u_char *result);
u_long CdSyncCallback(CdlCB func);
diff --git a/libpsn00b/include/psxgpu.h b/libpsn00b/include/psxgpu.h
index f50b841..f061219 100644
--- a/libpsn00b/include/psxgpu.h
+++ b/libpsn00b/include/psxgpu.h
@@ -609,7 +609,7 @@ void AddPrim(u_long* ot, void* pri);
// Function definitions (C)
-int GetTimInfo(u_long *tim, TIM_IMAGE *timimg); /* ORIGINAL */
+int GetTimInfo(const u_long *tim, TIM_IMAGE *timimg); /* ORIGINAL */
DISPENV *SetDefDispEnv(DISPENV *disp, int x, int y, int w, int h);
DRAWENV *SetDefDrawEnv(DRAWENV *draw, int x, int y, int w, int h);
diff --git a/libpsn00b/include/psxpad.h b/libpsn00b/include/psxpad.h
index d152896..9638ec1 100644
--- a/libpsn00b/include/psxpad.h
+++ b/libpsn00b/include/psxpad.h
@@ -14,43 +14,48 @@
#ifndef _PSXPAD_H
#define _PSXPAD_H
-// Pad button definitions for digital pad, joystick, dual analog,
-// Dualshock and Jogcon
-#define PAD_SELECT 1
-#define PAD_L3 2
-#define PAD_R3 4
-#define PAD_START 8
-#define PAD_UP 16
-#define PAD_RIGHT 32
-#define PAD_DOWN 64
-#define PAD_LEFT 128
-#define PAD_L2 256
-#define PAD_R2 512
-#define PAD_L1 1024
-#define PAD_R1 2048
-#define PAD_TRIANGLE 4096
-#define PAD_CIRCLE 8192
-#define PAD_CROSS 16384
-#define PAD_SQUARE 32768
-
-// Mouse button definitions
-#define MOUSE_RIGHT 1024
-#define MOUSE_LEFT 2048
-
-// neGcon button definitions
-#define NCON_START 8
-#define NCON_UP 16
-#define NCON_RIGHT 32
-#define NCON_DOWN 64
-#define NCON_LEFT 128
-#define NCON_R 256
-#define NCON_B 512
-#define NCON_A 1024
-
-// Guncon button definitions
-#define GCON_A 8
-#define GCON_TRIGGER 8192
-#define GCON_B 16384
+#include <stdint.h>
+
+/* Controller type and button definitions */
+
+typedef enum {
+ // Standard pads, analog joystick, Jogcon
+ PAD_SELECT = 1 << 0,
+ PAD_L3 = 1 << 1,
+ PAD_R3 = 1 << 2,
+ PAD_START = 1 << 3,
+ PAD_UP = 1 << 4,
+ PAD_RIGHT = 1 << 5,
+ PAD_DOWN = 1 << 6,
+ PAD_LEFT = 1 << 7,
+ PAD_L2 = 1 << 8,
+ PAD_R2 = 1 << 9,
+ PAD_L1 = 1 << 10,
+ PAD_R1 = 1 << 11,
+ PAD_TRIANGLE = 1 << 12,
+ PAD_CIRCLE = 1 << 13,
+ PAD_CROSS = 1 << 14,
+ PAD_SQUARE = 1 << 15,
+
+ // Mouse
+ MOUSE_LEFT = 1 << 10,
+ MOUSE_RIGHT = 1 << 11,
+
+ // neGcon
+ NCON_START = 1 << 3,
+ NCON_UP = 1 << 4,
+ NCON_RIGHT = 1 << 5,
+ NCON_DOWN = 1 << 6,
+ NCON_LEFT = 1 << 7,
+ NCON_R = 1 << 8,
+ NCON_B = 1 << 9,
+ NCON_A = 1 << 10,
+
+ // Guncon
+ GCON_A = 1 << 3,
+ GCON_TRIGGER = 1 << 13,
+ GCON_B = 1 << 14
+} PadButton;
typedef enum {
PAD_ID_MOUSE = 0x1, // Sony PS1 mouse
@@ -64,9 +69,10 @@ typedef enum {
PAD_ID_JOGCON = 0xe, // Namco Jogcon
PAD_ID_CONFIG_MODE = 0xf, // Dual Analog/DualShock in config mode (if len == 0x3)
PAD_ID_NONE = 0xf // No pad connected (if len == 0xf)
-} PAD_TYPEID;
+} PadTypeID;
+
+/* Pad and memory card commands */
-// Controller command definitions
typedef enum {
PAD_CMD_INIT_PRESSURE = '@', // Initialize DS2 button pressure sensors (in config mode)
PAD_CMD_READ = 'B', // Read pad state and set rumble
@@ -74,131 +80,155 @@ typedef enum {
PAD_CMD_SET_ANALOG = 'D', // Set analog mode/LED state (in config mode)
PAD_CMD_GET_ANALOG = 'E', // Get analog mode/LED state (in config mode)
PAD_CMD_REQUEST_CONFIG = 'M', // Configure request/unlock vibration (in config mode)
- PAD_CMD_RESPONSE_CONFIG = 'O' // Configure response/unlock DS2 pressure (in config mode)
-} PAD_COMMAND;
+ PAD_CMD_RESPONSE_CONFIG = 'O', // Configure response/unlock DS2 pressure (in config mode)
-// Memory card command/response definitions
-typedef enum {
- MCD_CMD_READ = 'R', // Read sector
- MCD_CMD_IDENTIFY = 'S', // Retrieve ID and card size information
- MCD_CMD_WRITE = 'W' // Write sector
-} MCD_COMMAND;
+ MCD_CMD_READ_SECTOR = 'R', // Read 128-byte sector
+ MCD_CMD_IDENTIFY = 'S', // Retrieve ID and card size information (Sony cards only)
+ MCD_CMD_WRITE_SECTOR = 'W' // Erase and write 128-byte sector
+} PadCommand;
typedef enum {
MCD_STAT_OK = 'G',
MCD_STAT_BAD_CHECKSUM = 'N',
MCD_STAT_BAD_SECTOR = 0xff
-} MCD_STATUS;
-
-#define MCD_CMD_READ_LEN 139
-#define MCD_CMD_IDENTIFY_LEN 9
-#define MCD_CMD_WRITE_LEN 137
-
-// Memory card status flags
-#define MCD_FLAG_WRITE_ERROR 4 // Last write command failed
-#define MCD_FLAG_NOT_WRITTEN 8 // No writes have been issued yet
-#define MCD_FLAG_UNKNOWN 16 // Might be set on third-party cards
-
-// Struct for data returned by controllers
-typedef struct _PADTYPE {
- union { // Header:
- struct __attribute__((packed)) { // When parsing data returned by BIOS:
- unsigned char stat; // Status
- unsigned char len:4; // Payload length / 2, 0 for multitap
- unsigned char type:4; // Device type (PAD_TYPEID)
+} MemCardStatus;
+
+typedef enum {
+ MCD_FLAG_WRITE_ERROR = 1 << 2, // Last write command failed
+ MCD_FLAG_NOT_WRITTEN = 1 << 3, // No writes have been issued yet
+ MCD_FLAG_UNKNOWN = 1 << 4 // Might be set on third-party cards
+} MemCardStatusFlag;
+
+#define MEMCARD_CMD_READ_LEN 139
+#define MEMCARD_CMD_IDENTIFY_LEN 9
+#define MEMCARD_CMD_WRITE_LEN 137
+
+/* Controller response as returned by BIOS driver */
+
+typedef struct __attribute__((packed)) _PADTYPE {
+ uint8_t stat; // Status
+ uint8_t len:4; // Payload length / 2, 0 for multitap
+ uint8_t type:4; // Device type (PadTypeID)
+
+ uint16_t btn; // Button states
+ union {
+ struct { // Analog controller:
+ uint8_t rs_x,rs_y; // - Right stick coordinates
+ uint8_t ls_x,ls_y; // - Left stick coordinates
+ uint8_t press[12]; // - Button pressure (DualShock 2 only)
};
- struct __attribute__((packed)) { // When parsing raw controller response:
- unsigned char len:4; // Payload length / 2, 0 for multitap
- unsigned char type:4; // Device type (PAD_TYPEID)
- unsigned char prefix; // Must be 0x5a
- } raw;
- };
- struct { // Payload:
- unsigned short btn; // Button states
- union {
- struct { // Analog controller:
- unsigned char rs_x,rs_y; // Right stick coordinates
- unsigned char ls_x,ls_y; // Left stick coordinates
- unsigned char press[12]; // Button pressure (DualShock 2 only)
- };
- struct { // Mouse:
- char x_mov; // X movement of mouse
- char y_mov; // Y movement of mouse
- };
- struct { // neGcon:
- unsigned char twist; // Controller twist
- unsigned char btn_i; // I button value
- unsigned char btn_ii; // II button value
- unsigned char trg_l; // L trigger value
- };
- struct { // Jogcon:
- unsigned short jog_rot; // Jog rotation
- };
- struct { // Guncon:
- unsigned short gun_x; // Gun X position in dotclocks
- unsigned short gun_y; // Gun Y position in scanlines
- };
+ struct { // Mouse:
+ int8_t x_mov; // - X movement of mouse
+ int8_t y_mov; // - Y movement of mouse
+ };
+ struct { // neGcon:
+ uint8_t twist; // - Controller twist
+ uint8_t btn_i; // - I button value
+ uint8_t btn_ii; // - II button value
+ uint8_t trg_l; // - L trigger value
+ };
+ struct { // Jogcon:
+ uint16_t jog_rot; // - Jog rotation
+ };
+ struct { // Guncon:
+ uint16_t gun_x; // - Gun X position in dotclocks
+ uint16_t gun_y; // - Gun Y position in scanlines
};
};
} PADTYPE;
-typedef struct _MCDRESPONSE {
- unsigned char flags; // Status flags
- unsigned char type1; // Must be 0x5a
- unsigned char type2; // Must be 0x5d
+//typedef struct _PADTYPE MOUSETYPE;
+//typedef struct _PADTYPE NCONTYPE;
+//typedef struct _PADTYPE JCONTYPE;
+//typedef struct _PADTYPE GCONTYPE;
+
+/* Raw responses */
+
+typedef struct __attribute__((packed)) _PadResponse {
+ uint8_t len:4; // Payload length / 2, 0 for multitap
+ uint8_t type:4; // Device type (PadTypeID)
+ uint8_t prefix; // Must be 0x5a
+
+ uint16_t btn; // Button states
+ union {
+ struct { // Analog controller:
+ uint8_t rs_x,rs_y; // - Right stick coordinates
+ uint8_t ls_x,ls_y; // - Left stick coordinates
+ uint8_t press[12]; // - Button pressure (DualShock 2 only)
+ };
+ struct { // Mouse:
+ int8_t x_mov; // - X movement of mouse
+ int8_t y_mov; // - Y movement of mouse
+ };
+ struct { // neGcon:
+ uint8_t twist; // - Controller twist
+ uint8_t btn_i; // - I button value
+ uint8_t btn_ii; // - II button value
+ uint8_t trg_l; // - L trigger value
+ };
+ struct { // Jogcon:
+ uint16_t jog_rot; // - Jog rotation
+ };
+ struct { // Guncon:
+ uint16_t gun_x; // - Gun X position in dotclocks
+ uint16_t gun_y; // - Gun Y position in scanlines
+ };
+ };
+} PadResponse;
+
+typedef struct __attribute__((packed)) _MemCardResponse {
+ uint8_t flags; // Status flags (MemCardStatusFlag)
+ uint8_t type1; // Must be 0x5a
+ uint8_t type2; // Must be 0x5d
+
union {
- struct { // MCD_CMD_READ response:
- unsigned char dummy[2];
- unsigned char ack1; // Must be 0x5c
- unsigned char ack2; // Must be 0x5d
- unsigned char lba_h;
- unsigned char lba_l;
- unsigned char data[128];
- unsigned char checksum; // = lba_h ^ lba_l ^ data
- unsigned char stat; // Status (MCD_STATUS)
+ struct { // CMD_READ response:
+ uint8_t dummy[2];
+ uint8_t ack1; // Must be 0x5c
+ uint8_t ack2; // Must be 0x5d
+ uint8_t lba_h;
+ uint8_t lba_l;
+ uint8_t data[128];
+ uint8_t checksum; // = lba_h ^ lba_l ^ data
+ uint8_t stat; // Status (MemCardStatus)
} read;
- struct { // MCD_CMD_IDENTIFY response:
- unsigned char ack1; // Must be 0x5c
- unsigned char ack2; // Must be 0x5d
- unsigned char size_h; // Card capacity bits 8-15 (0x04 = 128KB)
- unsigned char size_l; // Card capacity bits 0-7 (0x00 = 128KB)
- unsigned char blksize_h; // Sector size bits 8-15 (must be 0x00)
- unsigned char blksize_l; // Sector size bits 0-7 (must be 0x80)
+ struct { // CMD_IDENTIFY response:
+ uint8_t ack1; // Must be 0x5c
+ uint8_t ack2; // Must be 0x5d
+ uint8_t size_h; // Card capacity bits 8-15 (0x04 = 128KB)
+ uint8_t size_l; // Card capacity bits 0-7 (0x00 = 128KB)
+ uint8_t blksize_h; // Sector size bits 8-15 (must be 0x00)
+ uint8_t blksize_l; // Sector size bits 0-7 (must be 0x80)
} identify;
- struct { // MCD_CMD_WRITE response:
- unsigned char dummy[131];
- unsigned char ack1; // Must be 0x5c
- unsigned char ack2; // Must be 0x5d
- unsigned char stat; // Status (MCD_STATUS)
+ struct { // CMD_WRITE response:
+ uint8_t dummy[131];
+ uint8_t ack1; // Must be 0x5c
+ uint8_t ack2; // Must be 0x5d
+ uint8_t stat; // Status (MemCardStatus)
} write;
};
-} MCDRESPONSE;
-
-//typedef PADTYPE MOUSETYPE;
-//typedef PADTYPE NCONTYPE;
-//typedef PADTYPE JCONTYPE;
-//typedef PADTYPE GCONTYPE;
-
-// Structs for raw controller request
-typedef struct _PADREQUEST {
- unsigned char addr; // Must be 0x01 (or 02/03/04 for multitap pads)
- unsigned char cmd; // Command (PAD_COMMAND)
- unsigned char tap_mode; // 0x01 to enable multitap response
- unsigned char motor_r; // Right motor control (on/off)
- unsigned char motor_l; // Left motor control (PWM)
- unsigned char dummy[4];
-} PADREQUEST;
-
-// Structs for raw memory card request
-typedef struct _MCDREQUEST {
- unsigned char addr; // Must be 0x81 (or 02/03/04 for multitap cards)
- unsigned char cmd; // Command (MCD_COMMAND)
- unsigned char dummy[2];
- unsigned char lba_h; // Sector address bits 8-15 (dummy for CMD_IDENTIFY)
- unsigned char lba_l; // Sector address bits 0-7 (dummy for CMD_IDENTIFY)
- unsigned char data[128]; // Sector payload (dummy for CMD_READ/CMD_IDENTIFY)
- unsigned char checksum; // = lba_h ^ lba_l ^ data (CMD_WRITE only)
- unsigned char dummy2[3];
-} MCDREQUEST;
+} MemCardResponse;
+
+/* Raw requests */
+
+typedef struct __attribute__((packed)) _PadRequest {
+ uint8_t addr; // Must be 0x01 (or 02/03/04 for multitap pads)
+ uint8_t cmd; // Command (PadCommand)
+ uint8_t tap_mode; // 0x01 to enable multitap response
+ uint8_t motor_r; // Right motor control (on/off)
+ uint8_t motor_l; // Left motor control (PWM)
+ uint8_t dummy[4];
+} PadRequest;
+
+typedef struct __attribute__((packed)) _MemCardRequest {
+ uint8_t addr; // Must be 0x81 (or 02/03/04 for multitap cards)
+ uint8_t cmd; // Command (MemCardCommand)
+ uint8_t dummy[2];
+ uint8_t lba_h; // Sector address bits 8-15 (dummy for CMD_IDENTIFY)
+ uint8_t lba_l; // Sector address bits 0-7 (dummy for CMD_IDENTIFY)
+ uint8_t data[128]; // Sector payload (dummy for CMD_READ/CMD_IDENTIFY)
+ uint8_t checksum; // = lba_h ^ lba_l ^ data (CMD_WRITE only)
+ uint8_t dummy2[3];
+} MemCardRequest;
#endif \ No newline at end of file
diff --git a/libpsn00b/include/psxspu.h b/libpsn00b/include/psxspu.h
index a87e347..da000e3 100644
--- a/libpsn00b/include/psxspu.h
+++ b/libpsn00b/include/psxspu.h
@@ -115,7 +115,7 @@ extern "C" {
void SpuInit();
-void SpuSetVoiceRaw( int voice, SpuVoiceRaw* param );
+void SpuSetVoiceRaw( int voice, const SpuVoiceRaw* param );
void SpuReverbOn( int voice );
void SpuSetReverb();
@@ -128,7 +128,7 @@ void SpuSetKey(int on_off, u_int voice_bit);
// SPU transfer functions
int SpuSetTransferMode(int mode);
int SpuSetTransferStartAddr(int addr);
-int SpuWrite(unsigned char* addr, int size);
+int SpuWrite(const unsigned char* addr, int size);
void SpuWait();
#ifdef __cplusplus
diff --git a/libpsn00b/ldscripts/dll.ld b/libpsn00b/ldscripts/dll.ld
index 59cbb53..a03a504 100644
--- a/libpsn00b/ldscripts/dll.ld
+++ b/libpsn00b/ldscripts/dll.ld
@@ -7,8 +7,8 @@
* replaced by the global offset table (GOT) and .bss being merged with .data.
*/
-OUTPUT_FORMAT(elf32-littlemips)
-/*ENTRY(_start)
+/*OUTPUT_FORMAT(elf32-littlemips)
+ENTRY(_start)
STARTUP(start.o)*/
MEMORY {
diff --git a/libpsn00b/ldscripts/exe.ld b/libpsn00b/ldscripts/exe.ld
index 3033636..c6b9f29 100644
--- a/libpsn00b/ldscripts/exe.ld
+++ b/libpsn00b/ldscripts/exe.ld
@@ -8,7 +8,7 @@
* compatible with dynamic linking, as DLLs require GP to be unused.
*/
-OUTPUT_FORMAT(elf32-littlemips)
+/*OUTPUT_FORMAT(elf32-littlemips)*/
ENTRY(_start)
/*STARTUP(start.o)*/
diff --git a/libpsn00b/libc/scanf.c b/libpsn00b/libc/scanf.c
index b6d4510..ae3c714 100644
--- a/libpsn00b/libc/scanf.c
+++ b/libpsn00b/libc/scanf.c
@@ -8,6 +8,9 @@
#include <string.h>
#include <strings.h>
+// Uncomment to enable support for %f.
+//#define ALLOW_FLOAT
+
char libc_vsscanf_buf[512];
char libc_vsscanf_allow[256];
@@ -354,7 +357,8 @@ int vsscanf(const char *str, const char *format, va_list ap)
r++;
}
break;
-
+
+#ifdef ALLOW_FLOAT
case 'f': // Floating point number
libc_vsscanf_get_element(libc_vsscanf_buf, &str[sp], elem_skip_space, fsz);
fbuf = strtod(libc_vsscanf_buf, &ep);
@@ -380,6 +384,7 @@ int vsscanf(const char *str, const char *format, va_list ap)
conv = 0;
break;
+#endif
}
}
diff --git a/libpsn00b/libc/string.c b/libpsn00b/libc/string.c
index 445b227..a1a9a05 100644
--- a/libpsn00b/libc/string.c
+++ b/libpsn00b/libc/string.c
@@ -8,6 +8,10 @@
#include <string.h>
#include <stdlib.h>
+// Uncomment to enable strtod(), strtold() and strtof(). Note that these
+// functions use extremely slow software floats.
+//#define ALLOW_FLOAT
+
int tolower(int chr)
{
return (chr >='A' && chr<='Z') ? (chr + 32) : (chr);
@@ -252,6 +256,8 @@ long strtol(const char *nptr, char **endptr, int base)
return (long)strtoll(nptr, endptr, base);
}
+#ifdef ALLOW_FLOAT
+
double strtod(const char *nptr, char **endptr)
{
char strbuf[64];
@@ -302,6 +308,8 @@ double strtod(const char *nptr, char **endptr)
return (i + d)*s;
}
+#endif
+
/* implementation by Lameguy64, behaves like OpenWatcom's strtok() */
/* BIOS strtok seemed either bugged, or designed for wide chars */
@@ -344,6 +352,8 @@ char *strtok( char *s1, char *s2 )
} /* strtok */
+#ifdef ALLOW_FLOAT
+
long double strtold(const char *nptr, char **endptr)
{
return (long double)strtod(nptr, endptr);
@@ -352,4 +362,6 @@ long double strtold(const char *nptr, char **endptr)
float strtof(const char *nptr, char **endptr)
{
return (float)strtod(nptr, endptr);
-} \ No newline at end of file
+}
+
+#endif
diff --git a/libpsn00b/libc/vsprintf.c b/libpsn00b/libc/vsprintf.c
index 0a99dcc..9ca4cc5 100644
--- a/libpsn00b/libc/vsprintf.c
+++ b/libpsn00b/libc/vsprintf.c
@@ -6,6 +6,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <stdarg.h>
+
+// Uncomment to enable support for %f.
+//#define ALLOW_FLOAT
#define SPRINTF_ALT_FLAG (1<<0)
#define SPRINTF_ZERO_FLAG (1<<1)
@@ -208,6 +212,8 @@ int libc_ulltoa(unsigned long i, char *dst, int n)
return n2;
}
+#ifdef ALLOW_FLOAT
+
void libc_float_to_string(float fl, char *dst, int n)
{
unsigned int *p = (unsigned int*)&fl;
@@ -365,6 +371,8 @@ void libc_double_to_string(double fl, char *dst, int n)
char libc_sprintf_floatbuf[64];
+#endif
+
int vsnprintf(char *string, unsigned int size, const char *fmt, va_list ap)
{
int string_pos,fmt_pos;
@@ -732,6 +740,7 @@ int vsnprintf(char *string, unsigned int size, const char *fmt, va_list ap)
directive_coming = 0;
break;
+#ifdef ALLOW_FLOAT
case 'f':
libc_double_to_string(va_arg(ap, double), libc_sprintf_floatbuf, 64);
@@ -740,6 +749,8 @@ int vsnprintf(char *string, unsigned int size, const char *fmt, va_list ap)
directive_coming = 0;
break;
+#endif
+
case 'n': // Number of characters written
*(va_arg(ap,unsigned int*)) = string_pos;
diff --git a/libpsn00b/psxcd/cdgetsector.s b/libpsn00b/psxcd/cdgetsector.s
index 9af3543..dbe95cb 100644
--- a/libpsn00b/psxcd/cdgetsector.s
+++ b/libpsn00b/psxcd/cdgetsector.s
@@ -18,7 +18,8 @@ CdGetSector:
# nop
lui $v0, 0x1
- srl $a1, 2
+# srl $a1, 2 # (the official implementation expects $a1/size
+ # to be in 32-bit words rather than bytes)
or $v0, $a1
sw $a0, D3_MADR($a2) # Set DMA base address and transfer length
sw $v0, D3_BCR($a2)
diff --git a/libpsn00b/psxcd/isofs.c b/libpsn00b/psxcd/isofs.c
index 40a40af..d1c1b18 100644
--- a/libpsn00b/psxcd/isofs.c
+++ b/libpsn00b/psxcd/isofs.c
@@ -10,6 +10,9 @@
// Uncommend to enable debug output
//#define DEBUG
+#define DEFAULT_PATH_SEP '\\'
+#define IS_PATH_SEP(ch) (((ch) == '/') || ((ch) == '\\'))
+
typedef struct _CdlDIR_INT
{
u_long _pos;
@@ -374,7 +377,7 @@ static char* resolve_pathtable_path(int entry, char *rbuff)
rbuff -= tbl_entry.nameLength;
memcpy(rbuff, namebuff, tbl_entry.nameLength);
rbuff--;
- *rbuff = '\\';
+ *rbuff = DEFAULT_PATH_SEP;
// Parse to the parent
entry = tbl_entry.dirLevel;
@@ -431,12 +434,15 @@ static int find_dir_entry(const char *name, ISO_DIR_ENTRY *dirent)
static char* get_pathname(char *path, const char *filename)
{
- char *c;
- c = strrchr(filename, '\\');
+ char *c = 0;
+ for (char *i = filename; *i; i++) {
+ if (IS_PATH_SEP(*i))
+ c = i;
+ }
if(( c == filename ) || ( !c ))
{
- path[0] = '\\';
+ path[0] = DEFAULT_PATH_SEP;
path[1] = 0;
return NULL;
}
@@ -447,11 +453,17 @@ static char* get_pathname(char *path, const char *filename)
static char* get_filename(char *name, const char *filename)
{
- char *c;
- c = strrchr(filename, '\\');
+ char *c = 0;
+ for (char *i = filename; *i; i++) {
+ if (IS_PATH_SEP(*i))
+ c = i;
+ }
- if(( c == filename ) || ( !c ))
- {
+ if (!c) {
+ strcpy(name, filename);
+ return name;
+ }
+ if (c == filename) {
strcpy(name, filename+1);
return name;
}
@@ -783,7 +795,7 @@ static void _scan_callback(int status, unsigned char *result)
{
if( status == CdlDataReady )
{
- CdGetSector((void*)_ses_scanbuff, 2048);
+ CdGetSector((void*)_ses_scanbuff, 512);
if( _ses_scanbuff[0] == 0x1 )
{
diff --git a/libpsn00b/psxcd/psxcd.c b/libpsn00b/psxcd/psxcd.c
index 74c6c1c..8f19c8d 100644
--- a/libpsn00b/psxcd/psxcd.c
+++ b/libpsn00b/psxcd/psxcd.c
@@ -21,7 +21,7 @@ volatile int _cd_last_sector_count;
int _cd_media_changed;
void _cd_init(void);
-void _cd_control(unsigned char com, unsigned char *param, int plen);
+void _cd_control(unsigned char com, const void *param, int plen);
void _cd_wait_ack(void);
void _cd_wait(void);
@@ -50,7 +50,7 @@ int CdInit(void)
return 1;
}
-int CdControl(unsigned char com, unsigned char *param, unsigned char *result)
+int CdControl(unsigned char com, const void *param, unsigned char *result)
{
// Don't issue command if ack is not received yet
if( _cd_ack_wait )
@@ -72,7 +72,7 @@ int CdControl(unsigned char com, unsigned char *param, unsigned char *result)
return 1;
}
-int CdControlB(unsigned char com, unsigned char *param, unsigned char *result)
+int CdControlB(unsigned char com, const void *param, unsigned char *result)
{
if( !CdControl(com, param, result) )
{
@@ -83,7 +83,7 @@ int CdControlB(unsigned char com, unsigned char *param, unsigned char *result)
return 1;
}
-int CdControlF(unsigned char com, unsigned char *param)
+int CdControlF(unsigned char com, const void *param)
{
int param_len=0;
@@ -255,7 +255,7 @@ static void _CdReadReadyCallback(int status, unsigned char *result)
CdGetSector((void*)_cd_read_addr, _cd_read_sector_sz);
// Increment destination address
- _cd_read_addr += _cd_read_sector_sz>>2;
+ _cd_read_addr += _cd_read_sector_sz;
// Subtract sector count
_cd_sector_count--;
@@ -290,15 +290,15 @@ int CdRead(int sectors, u_long *buf, int mode)
// Determine sector based on mode flags
if( mode & CdlModeSize0 )
{
- _cd_read_sector_sz = 2328;
+ _cd_read_sector_sz = 2328 / 4;
}
else if( mode & CdlModeSize1 )
{
- _cd_read_sector_sz = 2340;
+ _cd_read_sector_sz = 2340 / 4;
}
else
{
- _cd_read_sector_sz = 2048;
+ _cd_read_sector_sz = 2048 / 4;
}
_cd_read_counter = VSync(-1);
diff --git a/libpsn00b/psxetc/_dl_resolve_wrapper.s b/libpsn00b/psxetc/_dl_resolve_wrapper.s
index 069ee84..01ebf3a 100644
--- a/libpsn00b/psxetc/_dl_resolve_wrapper.s
+++ b/libpsn00b/psxetc/_dl_resolve_wrapper.s
@@ -4,7 +4,7 @@
# This function is called by the lazy loader stubs generated by GCC in the
# .plt/.MIPS.stubs section when attempting to call a GOT entry whose address
# hasn't yet been resolved. The generated stubs conform to the MIPS ABI and
-# uses the following registers to pass the following parameters:
+# uses the following registers:
# - $t7 = address the resolved function should return to (i.e. $ra of the
# caller that triggered the stub)
# - $t8 = index of the function in the .dynsym symbol table
@@ -25,13 +25,13 @@ _dl_resolve_wrapper:
# Figure out where the DLL's struct is. dlinit() places a pointer to the
# struct in the second GOT entry, so it's just a matter of indexing the GOT
- # using GP. Then call _dl_resolve_helper with the struct and $t8 as
+ # using $gp. Then call _dl_resolve_helper with the struct and $t8 as
# arguments, and store the return value into $t0.
- lw $a0, -0x7fec($gp) # sizeof(uint32_t) - 0x7ff0 (see dll.ld)
+ lw $a0, -0x7fec($gp) # (DLL *) sizeof(uint32_t) - 0x7ff0 [see dll.ld]
move $a1, $t8
jal _dl_resolve_helper
- addiu $sp, -8 # (branch delay)
+ addiu $sp, -8
addiu $sp, 8
move $t0, $v0
@@ -48,7 +48,9 @@ _dl_resolve_wrapper:
jr $t0
nop
-.global _dl_credits
-.type _dl_credits, @object
+.section .data
+
+.global _dl_credits
+.type _dl_credits, @object
_dl_credits:
.asciiz "psxetc runtime dynamic linker by spicyjpeg\n"
diff --git a/libpsn00b/psxetc/dl.c b/libpsn00b/psxetc/dl.c
index e43374f..cbdcb66 100644
--- a/libpsn00b/psxetc/dl.c
+++ b/libpsn00b/psxetc/dl.c
@@ -38,8 +38,9 @@
//#define DEBUG
// Comment before building to disable functions that rely on BIOS file APIs,
-// i.e. DL_LoadSymbolMap() and dlopen().
-#define USE_FILE_API
+// i.e. DL_LoadSymbolMapFromFile() and DL_LoadDLLFromFile().
+// FIXME: those seem to be broken currently, and shouldn't be used anyway
+//#define USE_FILE_API
/* Private types */
@@ -132,7 +133,7 @@ static uint32_t _elf_hash(const char *str) {
}
#ifdef USE_FILE_API
-static uint8_t *_load_file(const char *filename, size_t *size_output) {
+static uint8_t *_dl_load_file(const char *filename, size_t *size_output) {
int32_t fd = open(filename, 1);
if (fd < 0) {
_LOG("psxetc: Can't open %s, error = %d\n", filename, fd);
@@ -286,10 +287,10 @@ int32_t DL_ParseSymbolMap(const char *ptr, size_t size) {
return entries;
}
-int32_t DL_LoadSymbolMap(const char *filename) {
#ifdef USE_FILE_API
+int32_t DL_LoadSymbolMapFromFile(const char *filename) {
size_t size;
- char *ptr = _load_file(filename, &size);
+ char *ptr = _dl_load_file(filename, &size);
if (!ptr)
return -1;
@@ -297,10 +298,8 @@ int32_t DL_LoadSymbolMap(const char *filename) {
free(ptr);
return entries;
-#else
- _ERROR(RTLD_E_NO_FILE_API, -1);
-#endif
}
+#endif
void DL_UnloadSymbolMap(void) {
if (!_symbol_map.entries)
@@ -354,7 +353,7 @@ void DL_SetResolveCallback(void *(*callback)(DLL *, const char *)) {
/* Library loading and linking API */
-DLL *dlinit(void *ptr, size_t size, DL_ResolveMode mode) {
+DLL *DL_CreateDLL(void *ptr, size_t size, DL_ResolveMode mode) {
if (!ptr)
_ERROR(RTLD_E_DLL_NULL, 0);
@@ -365,7 +364,7 @@ DLL *dlinit(void *ptr, size_t size, DL_ResolveMode mode) {
}
dll->ptr = ptr;
- dll->malloc_ptr = 0;
+ dll->malloc_ptr = (mode & RTLD_FREE_ON_DESTROY) ? ptr : 0;
dll->size = size;
_LOG("psxetc: Initializing DLL at %08x\n", ptr);
@@ -548,7 +547,7 @@ DLL *dlinit(void *ptr, size_t size, DL_ResolveMode mode) {
// If RTLD_NOW was passed, resolve GOT entries ahead of time by
// cross-referencing them with the symbol table.
- if (mode != RTLD_NOW)
+ if (!(mode & RTLD_NOW))
continue;
for (uint32_t j = got_offset; j < dll->got_length; j++) {
@@ -584,7 +583,7 @@ DLL *dlinit(void *ptr, size_t size, DL_ResolveMode mode) {
// _start() for regular executables, but we have to do it outside of the
// DLL as there's no _start() or even a defined entry point within the
// DLL itself.
- const uint32_t *ctor_list = dlsym(dll, "__CTOR_LIST__");
+ const uint32_t *ctor_list = DL_GetDLLSymbol(dll, "__CTOR_LIST__");
if (ctor_list) {
for (uint32_t i = ((uint32_t) ctor_list[0]); i >= 1; i--) {
void (*ctor)(void) = (void (*)(void)) ctor_list[i];
@@ -595,32 +594,28 @@ DLL *dlinit(void *ptr, size_t size, DL_ResolveMode mode) {
return dll;
}
-DLL *dlopen(const char *filename, DL_ResolveMode mode) {
#ifdef USE_FILE_API
+DLL *DL_LoadDLLFromFile(const char *filename, DL_ResolveMode mode) {
size_t size;
- char *ptr = _load_file(filename, &size);
+ char *ptr = _dl_load_file(filename, &size);
if (!ptr)
return 0;
- DLL *dll = dlinit(ptr, size, mode);
- if (dll)
- dll->malloc_ptr = dll->ptr;
- else
+ DLL *dll = DL_CreateDLL(ptr, size, mode | RTLD_FREE_ON_DESTROY);
+ if (!dll)
free(ptr);
return dll;
-#else
- _ERROR(RTLD_E_NO_FILE_API, 0);
-#endif
}
+#endif
-void dlclose(DLL *dll) {
+void DL_DestroyDLL(DLL *dll) {
if (dll == RTLD_DEFAULT)
return;
if (dll->ptr) {
// Call the DLL's global destructors.
- const uint32_t *dtor_list = dlsym(dll, "__DTOR_LIST__");
+ const uint32_t *dtor_list = DL_GetDLLSymbol(dll, "__DTOR_LIST__");
if (dtor_list) {
for (uint32_t i = 0; i < ((uint32_t) dtor_list[0]); i++) {
void (*dtor)(void) = (void (*)(void)) dtor_list[i + 1];
@@ -629,15 +624,15 @@ void dlclose(DLL *dll) {
}
}
- // If the DLL is associated to a buffer allocated by dlopen(), free that
- // buffer.
+ // If the DLL is associated to a buffer allocated by DL_LoadDLLFromFile(),
+ // free that buffer.
if (dll->malloc_ptr)
free(dll->malloc_ptr);
free(dll);
}
-void *dlsym(DLL *dll, const char *name) {
+void *DL_GetDLLSymbol(const DLL *dll, const char *name) {
if (dll == RTLD_DEFAULT)
return DL_GetSymbolByName(name);
//return _dl_resolve_callback(RTLD_DEFAULT, name);
@@ -654,7 +649,7 @@ void *dlsym(DLL *dll, const char *name) {
// provided.
for (uint32_t i = bucket[hash_mod]; i != 0xffffffff;) {
if (i >= nchain) {
- _LOG("psxetc: dlsym() index out of bounds (i = %d, n = %d)\n", i, nchain);
+ _LOG("psxetc: DL_GetDLLSymbol() index out of bounds (i = %d, n = %d)\n", i, nchain);
_ERROR(RTLD_E_HASH_LOOKUP, 0);
}
@@ -673,7 +668,7 @@ void *dlsym(DLL *dll, const char *name) {
_ERROR(RTLD_E_DLL_SYMBOL, 0);
}
-DL_Error dlerror(void) {
+DL_Error DL_GetLastError(void) {
DL_Error last = _error_code;
_error_code = RTLD_E_NONE;
diff --git a/libpsn00b/psxgpu/gettimimage.c b/libpsn00b/psxgpu/gettimimage.c
index d9cf1bf..5598e07 100644
--- a/libpsn00b/psxgpu/gettimimage.c
+++ b/libpsn00b/psxgpu/gettimimage.c
@@ -1,7 +1,7 @@
#include <sys/types.h>
#include <psxgpu.h>
-int GetTimInfo(u_long *tim, TIM_IMAGE *timimg) {
+int GetTimInfo(const u_long *tim, TIM_IMAGE *timimg) {
u_long *rtim;