mirror of
https://github.com/spicyjpeg/573in1.git
synced 2025-03-01 07:20:42 +01:00
Update ldscript, split off util.cpp into multiple files
This commit is contained in:
parent
661cba0e1a
commit
3f06ea5c50
@ -87,7 +87,7 @@ target_compile_definitions(
|
||||
)
|
||||
link_libraries(common)
|
||||
|
||||
function(addExecutable name address stackTop)
|
||||
function(addPS1Executable name address stackTop)
|
||||
add_executable(${name} ${ARGN})
|
||||
target_link_options(${name} PRIVATE -Ttext=0x${address})
|
||||
|
||||
@ -110,13 +110,18 @@ endfunction()
|
||||
# IMPORTANT: these addresses assume the boot executable's size (including code,
|
||||
# heap and stack allocations as well as the resource archive) is <576 KB
|
||||
# (0x90000 bytes).
|
||||
addExecutable(
|
||||
addPS1Executable(
|
||||
main 800a0000 801dfff0
|
||||
src/common/file/fat.cpp
|
||||
src/common/file/file.cpp
|
||||
src/common/file/iso9660.cpp
|
||||
src/common/file/misc.cpp
|
||||
src/common/file/zip.cpp
|
||||
src/common/util/hash.cpp
|
||||
src/common/util/log.cpp
|
||||
src/common/util/misc.cpp
|
||||
src/common/util/string.cpp
|
||||
src/common/util/tween.cpp
|
||||
src/common/args.cpp
|
||||
src/common/gpu.cpp
|
||||
src/common/gpufont.cpp
|
||||
@ -126,7 +131,6 @@ addExecutable(
|
||||
src/common/rom.cpp
|
||||
src/common/romdrivers.cpp
|
||||
src/common/spu.cpp
|
||||
src/common/util.cpp
|
||||
src/libc/crt0.c
|
||||
src/main/app/app.cpp
|
||||
src/main/app/cartactions.cpp
|
||||
@ -188,16 +192,18 @@ target_compile_definitions(
|
||||
$<$<CONFIG:Debug>:
|
||||
#ENABLE_ARGV=1
|
||||
#ENABLE_LOGGING=1
|
||||
NDEBUG=1
|
||||
>
|
||||
)
|
||||
|
||||
function(addLauncher address stackTop)
|
||||
addExecutable(
|
||||
addPS1Executable(
|
||||
launcher${address} ${address} ${stackTop}
|
||||
src/common/util/hash.cpp
|
||||
src/common/util/misc.cpp
|
||||
src/common/args.cpp
|
||||
src/common/ide.cpp
|
||||
src/common/io.cpp
|
||||
src/common/util.cpp
|
||||
src/launcher/main.cpp
|
||||
src/libc/crt0.c
|
||||
src/vendor/printf.c
|
||||
@ -236,12 +242,13 @@ function(addBootStub name resourceName)
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
addExecutable(
|
||||
addPS1Executable(
|
||||
${name} 80010000 0
|
||||
src/boot/crt0.s
|
||||
src/boot/main.cpp
|
||||
src/common/util/misc.cpp
|
||||
src/common/util/string.cpp
|
||||
src/common/io.cpp
|
||||
src/common/util.cpp
|
||||
)
|
||||
addBinaryFile(
|
||||
${name} _resourceArchive _resourceArchiveLength
|
||||
|
@ -17,8 +17,7 @@
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY {
|
||||
KERNEL_RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 0x010000
|
||||
APP_RAM (rwx) : ORIGIN = 0x80010000, LENGTH = 0x7f0000
|
||||
APP_RAM (rwx) : ORIGIN = 0x80010000, LENGTH = 0x3f0000
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
@ -108,7 +107,7 @@ SECTIONS {
|
||||
} > APP_RAM
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.note.GNU-stack .gnu_debuglink .gnu.lto_*)
|
||||
*(.note.* .gnu_debuglink .gnu.lto_*)
|
||||
*(.MIPS.abiflags)
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,10 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util/misc.hpp"
|
||||
#include "common/util/string.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "ps1/system.h"
|
||||
|
||||
extern "C" const uint8_t _resourceArchive[];
|
||||
|
@ -16,8 +16,9 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/args.hpp"
|
||||
#include "common/util.hpp"
|
||||
|
||||
namespace args {
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/misc.hpp"
|
||||
|
||||
namespace args {
|
||||
|
||||
|
@ -18,9 +18,10 @@
|
||||
#include <stdint.h>
|
||||
#include "common/file/fat.hpp"
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/misc.hpp"
|
||||
#include "common/ide.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "ps1/system.h"
|
||||
#include "vendor/diskio.h"
|
||||
#include "vendor/ff.h"
|
||||
|
@ -19,8 +19,9 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/gpu.hpp"
|
||||
#include "common/util.hpp"
|
||||
|
||||
namespace file {
|
||||
|
||||
|
@ -18,9 +18,10 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/gpu.hpp"
|
||||
#include "common/spu.hpp"
|
||||
#include "common/util.hpp"
|
||||
|
||||
namespace file {
|
||||
|
||||
|
@ -18,8 +18,10 @@
|
||||
#include <stdint.h>
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/file/iso9660.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/ide.hpp"
|
||||
#include "common/util.hpp"
|
||||
|
||||
namespace file {
|
||||
|
||||
|
@ -19,8 +19,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/ide.hpp"
|
||||
#include "common/util.hpp"
|
||||
|
||||
namespace file {
|
||||
|
||||
|
@ -18,7 +18,9 @@
|
||||
#include <stdint.h>
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/file/misc.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "ps1/pcdrv.h"
|
||||
|
||||
namespace file {
|
||||
|
@ -19,7 +19,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "ps1/pcdrv.h"
|
||||
|
||||
namespace file {
|
||||
|
@ -18,7 +18,8 @@
|
||||
#include <stdint.h>
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/file/zip.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "vendor/miniz.h"
|
||||
|
||||
namespace file {
|
||||
|
@ -17,8 +17,9 @@
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util/misc.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/gpu.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "ps1/gpucmd.h"
|
||||
#include "ps1/registers.h"
|
||||
#include "ps1/system.h"
|
||||
|
@ -16,10 +16,11 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/ide.hpp"
|
||||
#include "common/idedefs.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "ps1/registers573.h"
|
||||
#include "ps1/system.h"
|
||||
|
||||
|
@ -18,8 +18,8 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/idedefs.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "ps1/registers573.h"
|
||||
|
||||
namespace ide {
|
||||
|
@ -16,8 +16,8 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util/misc.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "ps1/registers.h"
|
||||
#include "ps1/registers573.h"
|
||||
#include "ps1/system.h"
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/misc.hpp"
|
||||
#include "ps1/registers.h"
|
||||
#include "ps1/registers573.h"
|
||||
#include "ps1/system.h"
|
||||
|
@ -16,10 +16,12 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/rom.hpp"
|
||||
#include "common/romdrivers.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "ps1/registers.h"
|
||||
#include "ps1/registers573.h"
|
||||
|
||||
|
@ -18,7 +18,9 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/misc.hpp"
|
||||
#include "common/util/string.hpp"
|
||||
#include "ps1/registers.h"
|
||||
|
||||
namespace rom {
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/rom.hpp"
|
||||
#include "common/romdrivers.hpp"
|
||||
|
||||
|
@ -16,8 +16,9 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util/misc.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/spu.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "ps1/registers.h"
|
||||
#include "ps1/system.h"
|
||||
|
||||
|
@ -1,701 +0,0 @@
|
||||
/*
|
||||
* 573in1 - Copyright (C) 2022-2024 spicyjpeg
|
||||
*
|
||||
* 573in1 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 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 573in1 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "common/util.hpp"
|
||||
#include "ps1/registers.h"
|
||||
#include "ps1/system.h"
|
||||
|
||||
namespace util {
|
||||
|
||||
/* String hashing */
|
||||
|
||||
Hash hash(const char *str, char terminator) {
|
||||
auto _str = reinterpret_cast<const uint8_t *>(str);
|
||||
Hash value = 0;
|
||||
|
||||
while (*_str && (*_str != terminator))
|
||||
value = Hash(*(_str++)) + (value << 6) + (value << 16) - value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
Hash hash(const uint8_t *data, size_t length) {
|
||||
Hash value = 0;
|
||||
|
||||
for (; length; length--)
|
||||
value = Hash(*(data++)) + (value << 6) + (value << 16) - value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Date and time class */
|
||||
|
||||
bool Date::isValid(void) const {
|
||||
if ((hour > 23) || (minute > 59) || (second > 59))
|
||||
return false;
|
||||
if ((month < 1) || (month > 12))
|
||||
return false;
|
||||
if ((day < 1) || (day > getMonthDayCount()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Date::isLeapYear(void) const {
|
||||
if (year % 4)
|
||||
return false;
|
||||
if (!(year % 100) && (year % 400))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int Date::getDayOfWeek(void) const {
|
||||
// See https://datatracker.ietf.org/doc/html/rfc3339#appendix-B
|
||||
int _year = year, _month = month - 2;
|
||||
|
||||
if (_month <= 0) {
|
||||
_month += 12;
|
||||
_year--;
|
||||
}
|
||||
|
||||
int century = _year / 100;
|
||||
_year %= 100;
|
||||
|
||||
int weekday = 0
|
||||
+ day
|
||||
+ (_month * 26 - 2) / 10
|
||||
+ _year
|
||||
+ _year / 4
|
||||
+ century / 4
|
||||
+ century * 5;
|
||||
|
||||
return weekday % 7;
|
||||
}
|
||||
|
||||
int Date::getMonthDayCount(void) const {
|
||||
switch (month) {
|
||||
case 2:
|
||||
return isLeapYear() ? 29 : 28;
|
||||
|
||||
case 4:
|
||||
case 6:
|
||||
case 9:
|
||||
case 11:
|
||||
return 30;
|
||||
|
||||
default:
|
||||
return 31;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Date::toDOSTime(void) const {
|
||||
int _year = year - 1980;
|
||||
|
||||
if (!isValid())
|
||||
return 0;
|
||||
if ((_year < 0) || (_year > 127))
|
||||
return 0;
|
||||
|
||||
return 0
|
||||
| (_year << 25)
|
||||
| (month << 21)
|
||||
| (day << 16)
|
||||
| (hour << 11)
|
||||
| (minute << 5)
|
||||
| (second >> 1);
|
||||
}
|
||||
|
||||
size_t Date::toString(char *output) const {
|
||||
if (!isValid()) {
|
||||
*output = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
output, "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute,
|
||||
second
|
||||
);
|
||||
}
|
||||
|
||||
/* Tween/animation classes */
|
||||
|
||||
template<typename T, typename E> void Tween<T, E>::setValue(
|
||||
int time, T start, T target, int duration
|
||||
) {
|
||||
//assert(duration <= 0x800);
|
||||
|
||||
_base = start;
|
||||
_delta = target - start;
|
||||
|
||||
_endTime = time + duration;
|
||||
_timeScale = TWEEN_UNIT / duration;
|
||||
}
|
||||
|
||||
template<typename T, typename E> void Tween<T, E>::setValue(T target) {
|
||||
_base = target;
|
||||
_delta = static_cast<T>(0);
|
||||
|
||||
_endTime = 0;
|
||||
}
|
||||
|
||||
template<typename T, typename E> T Tween<T, E>::getValue(int time) const {
|
||||
int remaining = time - _endTime;
|
||||
|
||||
if (remaining >= 0)
|
||||
return _base + _delta;
|
||||
|
||||
return _base + (
|
||||
_delta * E::apply(remaining * _timeScale + TWEEN_UNIT)
|
||||
) / TWEEN_UNIT;
|
||||
}
|
||||
|
||||
template class Tween<int, LinearEasing>;
|
||||
template class Tween<int, QuadInEasing>;
|
||||
template class Tween<int, QuadOutEasing>;
|
||||
template class Tween<uint16_t, LinearEasing>;
|
||||
template class Tween<uint16_t, QuadInEasing>;
|
||||
template class Tween<uint16_t, QuadOutEasing>;
|
||||
template class Tween<uint32_t, LinearEasing>;
|
||||
template class Tween<uint32_t, QuadInEasing>;
|
||||
template class Tween<uint32_t, QuadOutEasing>;
|
||||
|
||||
/* Logging framework */
|
||||
|
||||
// Global state, I know, but it's a necessary evil.
|
||||
Logger logger;
|
||||
|
||||
void LogBuffer::clear(void) {
|
||||
for (auto line : _lines)
|
||||
line[0] = 0;
|
||||
}
|
||||
|
||||
char *LogBuffer::allocateLine(void) {
|
||||
size_t tail = _tail;
|
||||
_tail = (tail + 1) % MAX_LOG_LINES;
|
||||
|
||||
return _lines[tail];
|
||||
}
|
||||
|
||||
void Logger::setLogBuffer(LogBuffer *buffer) {
|
||||
util::CriticalSection sec;
|
||||
|
||||
_buffer = buffer;
|
||||
}
|
||||
|
||||
void Logger::setupSyslog(int baudRate) {
|
||||
util::CriticalSection sec;
|
||||
|
||||
if (baudRate) {
|
||||
initSerialIO(baudRate);
|
||||
_enableSyslog = true;
|
||||
} else {
|
||||
_enableSyslog = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::log(const char *format, ...) {
|
||||
util::CriticalSection sec;
|
||||
|
||||
va_list ap;
|
||||
|
||||
if (_buffer) {
|
||||
auto line = _buffer->allocateLine();
|
||||
|
||||
va_start(ap, format);
|
||||
vsnprintf(line, MAX_LOG_LINE_LENGTH, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (_enableSyslog)
|
||||
puts(line);
|
||||
} else if (_enableSyslog) {
|
||||
va_start(ap, format);
|
||||
vprintf(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
/* MD5 hash */
|
||||
|
||||
static const uint32_t _MD5_SEED[]{
|
||||
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
|
||||
};
|
||||
|
||||
static const uint32_t _MD5_ADD[][16]{
|
||||
{
|
||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821
|
||||
}, {
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a
|
||||
}, {
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665
|
||||
}, {
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
|
||||
}
|
||||
};
|
||||
|
||||
static const uint8_t _MD5_SHIFT[][4]{
|
||||
{ 7, 12, 17, 22 },
|
||||
{ 5, 9, 14, 20 },
|
||||
{ 4, 11, 16, 23 },
|
||||
{ 6, 10, 15, 21 }
|
||||
};
|
||||
|
||||
MD5::MD5(void)
|
||||
: _blockCount(0), _bufferLength(0) {
|
||||
__builtin_memcpy(_state, _MD5_SEED, sizeof(_state));
|
||||
}
|
||||
|
||||
void MD5::_flushBlock(const void *data) {
|
||||
auto input = reinterpret_cast<const uint32_t *>(data);
|
||||
|
||||
assertAligned<uint32_t>(data);
|
||||
|
||||
auto a = _state[0], b = _state[1], c = _state[2], d = _state[3];
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
auto _d = d;
|
||||
auto _e = a + _addF(b, c, d) + input[_indexF(i)] + _MD5_ADD[0][i];
|
||||
|
||||
d = c;
|
||||
c = b;
|
||||
b += rotateLeft(_e, _MD5_SHIFT[0][i % 4]);
|
||||
a = _d;
|
||||
}
|
||||
for (int i = 0; i < 16; i++) {
|
||||
auto _d = d;
|
||||
auto _e = a + _addG(b, c, d) + input[_indexG(i)] + _MD5_ADD[1][i];
|
||||
|
||||
d = c;
|
||||
c = b;
|
||||
b += rotateLeft(_e, _MD5_SHIFT[1][i % 4]);
|
||||
a = _d;
|
||||
}
|
||||
for (int i = 0; i < 16; i++) {
|
||||
auto _d = d;
|
||||
auto _e = a + _addH(b, c, d) + input[_indexH(i)] + _MD5_ADD[2][i];
|
||||
|
||||
d = c;
|
||||
c = b;
|
||||
b += rotateLeft(_e, _MD5_SHIFT[2][i % 4]);
|
||||
a = _d;
|
||||
}
|
||||
for (int i = 0; i < 16; i++) {
|
||||
auto _d = d;
|
||||
auto _e = a + _addI(b, c, d) + input[_indexI(i)] + _MD5_ADD[3][i];
|
||||
|
||||
d = c;
|
||||
c = b;
|
||||
b += rotateLeft(_e, _MD5_SHIFT[3][i % 4]);
|
||||
a = _d;
|
||||
}
|
||||
|
||||
_state[0] += a;
|
||||
_state[1] += b;
|
||||
_state[2] += c;
|
||||
_state[3] += d;
|
||||
_blockCount++;
|
||||
}
|
||||
|
||||
void MD5::update(const uint8_t *data, size_t length) {
|
||||
if (_bufferLength > 0) {
|
||||
auto ptr = &_blockBuffer[_bufferLength];
|
||||
auto freeSpace = sizeof(_blockBuffer) - _bufferLength;
|
||||
|
||||
if (length >= freeSpace) {
|
||||
__builtin_memcpy(ptr, data, freeSpace);
|
||||
_flushBlock(_blockBuffer);
|
||||
|
||||
data += freeSpace;
|
||||
length -= freeSpace;
|
||||
_bufferLength = 0;
|
||||
} else {
|
||||
__builtin_memcpy(ptr, data, length);
|
||||
|
||||
_bufferLength += length;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid copying data to the intermediate block buffer whenever possible.
|
||||
for (;
|
||||
length >= sizeof(_blockBuffer);
|
||||
length -= sizeof(_blockBuffer), data += sizeof(_blockBuffer)
|
||||
)
|
||||
_flushBlock(data);
|
||||
|
||||
if (length > 0) {
|
||||
__builtin_memcpy(_blockBuffer, data, length);
|
||||
_bufferLength = length;
|
||||
}
|
||||
}
|
||||
|
||||
void MD5::digest(uint8_t *output) {
|
||||
uint64_t length = (
|
||||
uint64_t(_blockCount) * sizeof(_blockBuffer) + uint64_t(_bufferLength)
|
||||
) * 8;
|
||||
|
||||
_blockBuffer[_bufferLength++] = 1 << 7;
|
||||
|
||||
while (_bufferLength != (sizeof(_blockBuffer) - 8)) {
|
||||
if (_bufferLength == sizeof(_blockBuffer)) {
|
||||
_flushBlock(_blockBuffer);
|
||||
_bufferLength = 0;
|
||||
}
|
||||
|
||||
_blockBuffer[_bufferLength++] = 0;
|
||||
}
|
||||
|
||||
for (int i = 8; i > 0; i--, length >>= 8)
|
||||
_blockBuffer[_bufferLength++] = uint8_t(length & 0xff);
|
||||
|
||||
_flushBlock(_blockBuffer);
|
||||
__builtin_memcpy(output, _state, sizeof(_state));
|
||||
}
|
||||
|
||||
/* LZ4 decompressor */
|
||||
|
||||
void decompressLZ4(
|
||||
uint8_t *output, const uint8_t *input, size_t maxOutputLength,
|
||||
size_t inputLength
|
||||
) {
|
||||
auto outputEnd = &output[maxOutputLength];
|
||||
auto inputEnd = &input[inputLength];
|
||||
|
||||
while (input < inputEnd) {
|
||||
uint8_t token = *(input++);
|
||||
|
||||
// Copy literals from the input stream.
|
||||
int literalLength = token >> 4;
|
||||
|
||||
if (literalLength == 0xf) {
|
||||
uint8_t addend;
|
||||
|
||||
do {
|
||||
addend = *(input++);
|
||||
literalLength += addend;
|
||||
} while (addend == 0xff);
|
||||
}
|
||||
|
||||
for (; literalLength && (output < outputEnd); literalLength--)
|
||||
*(output++) = *(input++);
|
||||
if (input >= inputEnd)
|
||||
break;
|
||||
|
||||
int offset = input[0] | (input[1] << 8);
|
||||
input += 2;
|
||||
|
||||
// Copy from previously decompressed data. Note that this *must* be done
|
||||
// one byte at a time, as the compressor relies on out-of-bounds copies
|
||||
// repeating the last byte.
|
||||
int copyLength = token & 0xf;
|
||||
|
||||
if (copyLength == 0xf) {
|
||||
uint8_t addend;
|
||||
|
||||
do {
|
||||
addend = *(input++);
|
||||
copyLength += addend;
|
||||
} while (addend == 0xff);
|
||||
}
|
||||
|
||||
auto copySource = output - offset;
|
||||
copyLength += 4;
|
||||
|
||||
for (; copyLength && (output < outputEnd); copyLength--)
|
||||
*(output++) = *(copySource++);
|
||||
}
|
||||
}
|
||||
|
||||
/* CRC calculation */
|
||||
|
||||
static constexpr uint8_t _CRC8_POLY = 0x8c;
|
||||
static constexpr uint16_t _CRC16_POLY = 0x1021;
|
||||
static constexpr uint32_t _CRC32_POLY = 0xedb88320;
|
||||
|
||||
uint8_t dsCRC8(const uint8_t *data, size_t length) {
|
||||
uint8_t crc = 0;
|
||||
|
||||
for (; length; length--) {
|
||||
uint8_t value = *(data++);
|
||||
|
||||
for (int bit = 8; bit; bit--) {
|
||||
uint8_t temp = crc ^ value;
|
||||
|
||||
value >>= 1;
|
||||
crc >>= 1;
|
||||
if (temp & 1)
|
||||
crc ^= _CRC8_POLY;
|
||||
}
|
||||
}
|
||||
|
||||
return crc & 0xff;
|
||||
}
|
||||
|
||||
uint16_t zsCRC16(const uint8_t *data, size_t length) {
|
||||
uint16_t crc = 0xffff;
|
||||
|
||||
for (; length; length--) {
|
||||
crc ^= *(data++) << 8;
|
||||
|
||||
for (int bit = 8; bit; bit--) {
|
||||
uint16_t temp = crc;
|
||||
|
||||
crc <<= 1;
|
||||
if (temp & (1 << 15))
|
||||
crc ^= _CRC16_POLY;
|
||||
}
|
||||
}
|
||||
|
||||
return (crc ^ 0xffff) & 0xffff;
|
||||
}
|
||||
|
||||
uint32_t zipCRC32(const uint8_t *data, size_t length, uint32_t crc) {
|
||||
// This CRC32 implementation uses a lookup table cached in the scratchpad
|
||||
// area in order to improve performance.
|
||||
auto table = reinterpret_cast<const uint32_t *>(CACHE_BASE);
|
||||
crc = ~crc;
|
||||
|
||||
for (; length; length--)
|
||||
crc = (crc >> 8) ^ table[(crc ^ *(data++)) & 0xff];
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
void initZipCRC32(void) {
|
||||
auto table = reinterpret_cast<uint32_t *>(CACHE_BASE);
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
uint32_t crc = i;
|
||||
|
||||
for (int bit = 8; bit; bit--) {
|
||||
uint32_t temp = crc;
|
||||
|
||||
crc >>= 1;
|
||||
if (temp & 1)
|
||||
crc ^= _CRC32_POLY;
|
||||
}
|
||||
|
||||
*(table++) = crc;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" uint32_t mz_crc32(uint32_t crc, const uint8_t *data, size_t length) {
|
||||
return zipCRC32(data, length, crc);
|
||||
}
|
||||
|
||||
/* String manipulation */
|
||||
|
||||
const char HEX_CHARSET[]{ "0123456789ABCDEF" };
|
||||
const char BASE41_CHARSET[]{ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./:" };
|
||||
|
||||
size_t hexValueToString(char *output, uint32_t value, size_t numDigits) {
|
||||
output += numDigits;
|
||||
*output = 0;
|
||||
|
||||
for (size_t i = numDigits; i; i--, value >>= 4)
|
||||
*(--output) = HEX_CHARSET[value & 0xf];
|
||||
|
||||
return numDigits;
|
||||
}
|
||||
|
||||
size_t hexToString(
|
||||
char *output, const uint8_t *input, size_t length, char separator
|
||||
) {
|
||||
size_t outLength = 0;
|
||||
|
||||
for (; length; length--) {
|
||||
uint8_t value = *(input++);
|
||||
|
||||
*(output++) = HEX_CHARSET[value >> 4];
|
||||
*(output++) = HEX_CHARSET[value & 0xf];
|
||||
|
||||
if (separator && (length > 1)) {
|
||||
*(output++) = separator;
|
||||
outLength += 3;
|
||||
} else {
|
||||
outLength += 2;
|
||||
}
|
||||
}
|
||||
|
||||
*output = 0;
|
||||
return outLength;
|
||||
}
|
||||
|
||||
size_t serialNumberToString(char *output, const uint8_t *input) {
|
||||
uint32_t value =
|
||||
input[0] | (input[1] << 8) | (input[2] << 16) | (input[3] << 24);
|
||||
|
||||
return sprintf(output, "%04d-%04d", (value / 10000) % 10000, value % 10000);
|
||||
}
|
||||
|
||||
// This format is used by Konami's tools to display trace IDs in the TID_81
|
||||
// format.
|
||||
static const char _TRACE_ID_CHECKSUM_CHARSET[]{ "0X987654321" };
|
||||
|
||||
size_t traceIDToString(char *output, const uint8_t *input) {
|
||||
uint16_t high = (input[0] << 8) | input[1];
|
||||
uint32_t low =
|
||||
(input[2] << 24) | (input[3] << 16) | (input[4] << 8) | input[5];
|
||||
|
||||
size_t length = sprintf(&output[1], "%02d-%04d", high % 100, low % 10000);
|
||||
|
||||
// The checksum is calculated in a very weird way:
|
||||
// code = AB-CDEF
|
||||
// checksum = (A*7 + B*6 + C*5 + D*4 + E*3 + F*2) % 11
|
||||
int checksum = 0, multiplier = 7;
|
||||
|
||||
for (const char *ptr = &output[1]; *ptr; ptr++) {
|
||||
if (*ptr != '-')
|
||||
checksum += (*ptr - '0') * (multiplier--);
|
||||
}
|
||||
|
||||
output[0] = _TRACE_ID_CHECKSUM_CHARSET[checksum % 11];
|
||||
return length + 1;
|
||||
}
|
||||
|
||||
// This encoding is similar to standard base45, but with some problematic
|
||||
// characters (' ', '$', '%', '*') excluded.
|
||||
size_t encodeBase41(char *output, const uint8_t *input, size_t length) {
|
||||
size_t outLength = 0;
|
||||
|
||||
for (int i = length + 1; i > 0; i -= 2) {
|
||||
int value = *(input++) << 8;
|
||||
value |= *(input++);
|
||||
|
||||
*(output++) = BASE41_CHARSET[value % 41];
|
||||
*(output++) = BASE41_CHARSET[(value / 41) % 41];
|
||||
*(output++) = BASE41_CHARSET[value / 1681];
|
||||
outLength += 3;
|
||||
}
|
||||
|
||||
*output = 0;
|
||||
return outLength;
|
||||
}
|
||||
|
||||
/* PS1 executable loader */
|
||||
|
||||
bool ExecutableHeader::validateMagic(void) const {
|
||||
#if 0
|
||||
return (
|
||||
hash(magic, sizeof(magic)) ==
|
||||
hash("PS-X EXE\0\0\0\0\0\0\0\0", sizeof(magic), 0)
|
||||
);
|
||||
#else
|
||||
return true
|
||||
&& (magic[0] == concatenate('P', 'S', '-', 'X'))
|
||||
&& (magic[1] == concatenate(' ', 'E', 'X', 'E'))
|
||||
&& !magic[2]
|
||||
&& !magic[3]
|
||||
&& !(entryPoint % 4)
|
||||
&& !(textOffset % 4)
|
||||
&& !(textLength % 2048)
|
||||
&& !dataLength
|
||||
&& !bssLength;
|
||||
#endif
|
||||
}
|
||||
|
||||
ExecutableLoader::ExecutableLoader(
|
||||
void *entryPoint, void *initialGP, void *stackTop
|
||||
) : _entryPoint(entryPoint), _initialGP(initialGP), _numArgs(0) {
|
||||
_argListPtr = reinterpret_cast<const char **>(uintptr_t(stackTop) & ~7)
|
||||
- MAX_EXECUTABLE_ARGS;
|
||||
_currentStackPtr = reinterpret_cast<char *>(_argListPtr);
|
||||
}
|
||||
|
||||
bool ExecutableLoader::addArgument(const char *arg) {
|
||||
if (_numArgs >= MAX_EXECUTABLE_ARGS)
|
||||
return false;
|
||||
|
||||
_argListPtr[_numArgs++] = arg;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExecutableLoader::copyArgument(const char *arg, size_t length) {
|
||||
if (_numArgs >= MAX_EXECUTABLE_ARGS)
|
||||
return false;
|
||||
|
||||
// Command-line arguments must be copied to the top of the new stack in
|
||||
// order to ensure the executable is going to be able to access them at any
|
||||
// time.
|
||||
*(--_currentStackPtr) = 0;
|
||||
_currentStackPtr -= length;
|
||||
__builtin_memcpy(_currentStackPtr, arg, length);
|
||||
|
||||
_argListPtr[_numArgs++] = _currentStackPtr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExecutableLoader::formatArgument(const char *format, ...) {
|
||||
char buffer[64];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
int length = vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return copyArgument(buffer, length + 1);
|
||||
}
|
||||
|
||||
[[noreturn]] void ExecutableLoader::run(
|
||||
int rawArgc, const char *const *rawArgv
|
||||
) {
|
||||
#if 0
|
||||
disableInterrupts();
|
||||
flushCache();
|
||||
#endif
|
||||
|
||||
register int a0 __asm__("a0") = rawArgc;
|
||||
register const char *const *a1 __asm__("a1") = rawArgv;
|
||||
register void *gp __asm__("gp") = _initialGP;
|
||||
|
||||
auto stackTop = uintptr_t(_currentStackPtr) & ~7;
|
||||
|
||||
// Changing the stack pointer and return address is not something that
|
||||
// should be done in a C++ function, but hopefully it's fine here since
|
||||
// we're jumping out right after setting it.
|
||||
__asm__ volatile(
|
||||
".set push\n"
|
||||
".set noreorder\n"
|
||||
"li $ra, %0\n"
|
||||
"jr %1\n"
|
||||
"addiu $sp, %2, -8\n"
|
||||
".set pop\n"
|
||||
:: "i"(DEV2_BASE), "r"(_entryPoint), "r"(stackTop),
|
||||
"r"(a0), "r"(a1), "r"(gp)
|
||||
);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
}
|
@ -1,518 +0,0 @@
|
||||
/*
|
||||
* 573in1 - Copyright (C) 2022-2024 spicyjpeg
|
||||
*
|
||||
* 573in1 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 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 573in1 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "ps1/system.h"
|
||||
|
||||
namespace util {
|
||||
|
||||
/* Misc. template utilities */
|
||||
|
||||
template<typename T> static inline uint32_t sum(const T *data, size_t length) {
|
||||
uint32_t value = 0;
|
||||
|
||||
for (; length; length--)
|
||||
value += uint32_t(*(data++));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T> static inline T min(T a, T b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
template<typename T> static inline T max(T a, T b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
template<typename T> static inline T clamp(T value, T minValue, T maxValue) {
|
||||
return (value < minValue) ? minValue :
|
||||
((value > maxValue) ? maxValue : value);
|
||||
}
|
||||
|
||||
template<typename T> static inline T rotateLeft(T value, int amount) {
|
||||
return T((value << amount) | (value >> (sizeof(T) * 8 - amount)));
|
||||
}
|
||||
|
||||
template<typename T> static inline T rotateRight(T value, int amount) {
|
||||
return T((value >> amount) | (value << (sizeof(T) * 8 - amount)));
|
||||
}
|
||||
|
||||
// These shall only be used with unsigned types.
|
||||
template<typename T> static inline T truncateToMultiple(T value, T length) {
|
||||
return value - (value % length);
|
||||
}
|
||||
|
||||
template<typename T> static inline T roundUpToMultiple(T value, T length) {
|
||||
T diff = value % length;
|
||||
return diff ? (value - diff + length) : value;
|
||||
}
|
||||
|
||||
template<typename T, typename X> static inline void assertAligned(X *ptr) {
|
||||
assert(!(reinterpret_cast<uintptr_t>(ptr) % alignof(T)));
|
||||
}
|
||||
|
||||
template<typename T> static inline void clear(T &obj, uint8_t value = 0) {
|
||||
__builtin_memset(&obj, value, sizeof(obj));
|
||||
}
|
||||
|
||||
template<typename T> static constexpr inline size_t countOf(T &array) {
|
||||
return sizeof(array) / sizeof(array[0]);
|
||||
}
|
||||
|
||||
template<typename T, typename X> static inline T forcedCast(X item) {
|
||||
return reinterpret_cast<T>(reinterpret_cast<void *>(item));
|
||||
}
|
||||
|
||||
static constexpr inline uint16_t concatenate(uint8_t a, uint8_t b) {
|
||||
return a | (b << 8);
|
||||
}
|
||||
|
||||
static constexpr inline uint32_t concatenate(
|
||||
uint8_t a, uint8_t b, uint8_t c, uint8_t d
|
||||
) {
|
||||
return a | (b << 8) | (c << 16) | (d << 24);
|
||||
}
|
||||
|
||||
/* String hashing (http://www.cse.yorku.ca/~oz/hash.html) */
|
||||
|
||||
using Hash = uint32_t;
|
||||
|
||||
template<typename T> static constexpr inline Hash hash(
|
||||
const T *const data, size_t length = -1, Hash value = 0
|
||||
) {
|
||||
if (*data && length)
|
||||
return hash(
|
||||
&data[1], length - 1,
|
||||
Hash(*data) + (value << 6) + (value << 16) - value
|
||||
);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
Hash hash(const char *str, char terminator = 0);
|
||||
Hash hash(const uint8_t *data, size_t length);
|
||||
|
||||
/* Critical section helper */
|
||||
|
||||
class CriticalSection {
|
||||
private:
|
||||
bool _enable;
|
||||
|
||||
public:
|
||||
inline CriticalSection(void) {
|
||||
_enable = disableInterrupts();
|
||||
}
|
||||
inline ~CriticalSection(void) {
|
||||
if (_enable)
|
||||
enableInterrupts();
|
||||
}
|
||||
};
|
||||
|
||||
class ThreadCriticalSection {
|
||||
public:
|
||||
inline ThreadCriticalSection(void) {
|
||||
bool enable = disableInterrupts();
|
||||
|
||||
assert(enable);
|
||||
}
|
||||
inline ~ThreadCriticalSection(void) {
|
||||
enableInterrupts();
|
||||
}
|
||||
};
|
||||
|
||||
/* Simple "smart" pointer */
|
||||
|
||||
class Data {
|
||||
public:
|
||||
void *ptr;
|
||||
size_t length;
|
||||
|
||||
inline Data(void)
|
||||
: ptr(nullptr), length(0) {}
|
||||
inline ~Data(void) {
|
||||
destroy();
|
||||
}
|
||||
|
||||
template<typename T> inline T *as(void) {
|
||||
return reinterpret_cast<T *>(ptr);
|
||||
}
|
||||
template<typename T> inline const T *as(void) const {
|
||||
return reinterpret_cast<const T *>(ptr);
|
||||
}
|
||||
template<typename T> inline T *allocate(size_t count = 1) {
|
||||
return reinterpret_cast<T *>(allocate(sizeof(T) * count));
|
||||
}
|
||||
|
||||
inline void *allocate(size_t _length) {
|
||||
if (ptr)
|
||||
delete[] as<uint8_t>();
|
||||
|
||||
ptr = _length ? (new uint8_t[_length]) : nullptr;
|
||||
length = _length;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
inline void destroy(void) {
|
||||
if (ptr) {
|
||||
delete[] as<uint8_t>();
|
||||
ptr = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Simple ring buffer */
|
||||
|
||||
template<typename T, size_t N> class RingBuffer {
|
||||
private:
|
||||
T _items[N];
|
||||
size_t _head, _tail;
|
||||
|
||||
public:
|
||||
size_t length;
|
||||
|
||||
inline RingBuffer(void)
|
||||
: _head(0), _tail(0), length(0) {}
|
||||
|
||||
inline T *pushItem(void) volatile {
|
||||
if (length >= N)
|
||||
return nullptr;
|
||||
|
||||
size_t i = _tail;
|
||||
_tail = (i + 1) % N;
|
||||
length++;
|
||||
|
||||
return &_items[i];
|
||||
}
|
||||
inline T *popItem(void) volatile {
|
||||
if (!length)
|
||||
return nullptr;
|
||||
|
||||
size_t i = _head;
|
||||
_head = (i + 1) % N;
|
||||
length--;
|
||||
|
||||
return &_items[i];
|
||||
}
|
||||
inline T *peekItem(void) const {
|
||||
if (!length)
|
||||
return nullptr;
|
||||
|
||||
return &_items[_head];
|
||||
}
|
||||
};
|
||||
|
||||
/* Date and time class */
|
||||
|
||||
class Date {
|
||||
public:
|
||||
uint16_t year;
|
||||
uint8_t month, day, hour, minute, second;
|
||||
|
||||
inline void reset(void) {
|
||||
year = 2024;
|
||||
month = 1;
|
||||
day = 1;
|
||||
hour = 0;
|
||||
minute = 0;
|
||||
second = 0;
|
||||
}
|
||||
|
||||
bool isValid(void) const;
|
||||
bool isLeapYear(void) const;
|
||||
int getDayOfWeek(void) const;
|
||||
int getMonthDayCount(void) const;
|
||||
uint32_t toDOSTime(void) const;
|
||||
size_t toString(char *output) const;
|
||||
};
|
||||
|
||||
/* Tween/animation classes */
|
||||
|
||||
static constexpr int TWEEN_UNIT = 1 << 12;
|
||||
|
||||
class LinearEasing {
|
||||
public:
|
||||
template<typename T> static inline T apply(T value) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
class QuadInEasing {
|
||||
public:
|
||||
template<typename T> static inline T apply(T value) {
|
||||
return (value * value) / TWEEN_UNIT;
|
||||
}
|
||||
};
|
||||
|
||||
class QuadOutEasing {
|
||||
public:
|
||||
template<typename T> static inline T apply(T value) {
|
||||
return (value * 2) - ((value * value) / TWEEN_UNIT);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename E> class Tween {
|
||||
private:
|
||||
T _base, _delta;
|
||||
int _endTime, _timeScale;
|
||||
|
||||
public:
|
||||
inline Tween(void) {
|
||||
setValue(static_cast<T>(0));
|
||||
}
|
||||
inline Tween(T start) {
|
||||
setValue(start);
|
||||
}
|
||||
|
||||
inline T getTargetValue(void) const {
|
||||
return _base + _delta;
|
||||
}
|
||||
inline bool isDone(int time) const {
|
||||
return time >= _endTime;
|
||||
}
|
||||
inline void setValue(int time, T target, int duration) {
|
||||
setValue(time, getValue(time), target, duration);
|
||||
}
|
||||
|
||||
void setValue(int time, T start, T target, int duration);
|
||||
void setValue(T target);
|
||||
T getValue(int time) const;
|
||||
};
|
||||
|
||||
/* Logging framework */
|
||||
|
||||
static constexpr int MAX_LOG_LINE_LENGTH = 128;
|
||||
static constexpr int MAX_LOG_LINES = 64;
|
||||
|
||||
class LogBuffer {
|
||||
private:
|
||||
char _lines[MAX_LOG_LINES][MAX_LOG_LINE_LENGTH];
|
||||
int _tail;
|
||||
|
||||
public:
|
||||
inline LogBuffer(void)
|
||||
: _tail(0) {
|
||||
clear();
|
||||
}
|
||||
|
||||
// 0 = last line, 1 = second to last, etc.
|
||||
inline const char *getLine(int line) const {
|
||||
return _lines[size_t(_tail - (line + 1)) % MAX_LOG_LINES];
|
||||
}
|
||||
|
||||
void clear(void);
|
||||
char *allocateLine(void);
|
||||
};
|
||||
|
||||
class Logger {
|
||||
private:
|
||||
LogBuffer *_buffer;
|
||||
bool _enableSyslog;
|
||||
|
||||
public:
|
||||
inline Logger(void)
|
||||
: _buffer(nullptr), _enableSyslog(false) {}
|
||||
|
||||
void setLogBuffer(LogBuffer *buffer);
|
||||
void setupSyslog(int baudRate);
|
||||
void log(const char *format, ...);
|
||||
};
|
||||
|
||||
extern Logger logger;
|
||||
|
||||
/* PS1 executable loader */
|
||||
|
||||
static constexpr size_t EXECUTABLE_BODY_OFFSET = 2048;
|
||||
static constexpr size_t MAX_EXECUTABLE_ARGS = 32;
|
||||
|
||||
class ExecutableHeader {
|
||||
public:
|
||||
uint32_t magic[4];
|
||||
|
||||
uint32_t entryPoint, initialGP;
|
||||
uint32_t textOffset, textLength;
|
||||
uint32_t dataOffset, dataLength;
|
||||
uint32_t bssOffset, bssLength;
|
||||
uint32_t stackOffset, stackLength;
|
||||
uint32_t _reserved[5];
|
||||
|
||||
inline void *getEntryPoint(void) const {
|
||||
return reinterpret_cast<void *>(entryPoint);
|
||||
}
|
||||
inline void *getInitialGP(void) const {
|
||||
return reinterpret_cast<void *>(initialGP);
|
||||
}
|
||||
inline void *getTextPtr(void) const {
|
||||
return reinterpret_cast<void *>(textOffset);
|
||||
}
|
||||
inline void *getStackPtr(void) const {
|
||||
return reinterpret_cast<void *>(stackOffset + stackLength);
|
||||
}
|
||||
inline const char *getRegionString(void) const {
|
||||
return reinterpret_cast<const char *>(this + 1);
|
||||
}
|
||||
inline void relocateText(const void *source) const {
|
||||
__builtin_memcpy(getTextPtr(), source, textLength);
|
||||
}
|
||||
|
||||
bool validateMagic(void) const;
|
||||
};
|
||||
|
||||
class ExecutableLoader {
|
||||
private:
|
||||
void *_entryPoint, *_initialGP;
|
||||
|
||||
size_t _numArgs;
|
||||
const char **_argListPtr;
|
||||
char *_currentStackPtr;
|
||||
|
||||
public:
|
||||
inline bool copyArgument(const char *arg) {
|
||||
return copyArgument(arg, __builtin_strlen(arg));
|
||||
}
|
||||
[[noreturn]] inline void run(void) {
|
||||
run(_numArgs, _argListPtr);
|
||||
}
|
||||
|
||||
ExecutableLoader(void *entryPoint, void *initialGP, void *stackTop);
|
||||
bool addArgument(const char *arg);
|
||||
bool copyArgument(const char *arg, size_t length);
|
||||
bool formatArgument(const char *format, ...);
|
||||
[[noreturn]] void run(int rawArgc, const char *const *rawArgv);
|
||||
};
|
||||
|
||||
/* MD5 hash */
|
||||
|
||||
class MD5 {
|
||||
private:
|
||||
uint32_t _state[4];
|
||||
uint8_t _blockBuffer[64];
|
||||
size_t _blockCount, _bufferLength;
|
||||
|
||||
static inline int _indexF(int index) {
|
||||
return index;
|
||||
}
|
||||
static inline uint32_t _addF(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return z ^ (x & (y ^ z)); // (x & y) | ((~x) & z)
|
||||
}
|
||||
static inline int _indexG(int index) {
|
||||
return ((index * 5) + 1) % 16;
|
||||
}
|
||||
static inline uint32_t _addG(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return y ^ (z & (x ^ y)); // (x & z) | (y & (~z))
|
||||
}
|
||||
static inline int _indexH(int index) {
|
||||
return ((index * 3) + 5) % 16;
|
||||
}
|
||||
static inline uint32_t _addH(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return x ^ y ^ z;
|
||||
}
|
||||
static inline int _indexI(int index) {
|
||||
return (index * 7) % 16;
|
||||
}
|
||||
static inline uint32_t _addI(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return (y ^ (x | (~z)));
|
||||
}
|
||||
|
||||
void _flushBlock(const void *data);
|
||||
|
||||
public:
|
||||
MD5(void);
|
||||
void update(const uint8_t *data, size_t length);
|
||||
void digest(uint8_t *output);
|
||||
};
|
||||
|
||||
/* Other APIs */
|
||||
|
||||
static inline size_t getLZ4InPlaceMargin(size_t inputLength) {
|
||||
return (inputLength >> 8) + 32;
|
||||
}
|
||||
|
||||
void decompressLZ4(
|
||||
uint8_t *output, const uint8_t *input, size_t maxOutputLength,
|
||||
size_t inputLength
|
||||
);
|
||||
|
||||
uint8_t dsCRC8(const uint8_t *data, size_t length);
|
||||
uint16_t zsCRC16(const uint8_t *data, size_t length);
|
||||
uint32_t zipCRC32(const uint8_t *data, size_t length, uint32_t crc = 0);
|
||||
void initZipCRC32(void);
|
||||
|
||||
extern const char HEX_CHARSET[], BASE41_CHARSET[];
|
||||
|
||||
size_t hexValueToString(char *output, uint32_t value, size_t numDigits = 8);
|
||||
size_t hexToString(
|
||||
char *output, const uint8_t *input, size_t length, char separator = 0
|
||||
);
|
||||
size_t serialNumberToString(char *output, const uint8_t *input);
|
||||
size_t traceIDToString(char *output, const uint8_t *input);
|
||||
size_t encodeBase41(char *output, const uint8_t *input, size_t length);
|
||||
|
||||
}
|
||||
|
||||
static constexpr inline util::Hash operator""_h(
|
||||
const char *const literal, size_t length
|
||||
) {
|
||||
return util::hash(literal, length);
|
||||
}
|
||||
|
||||
/* Logging macros */
|
||||
|
||||
#define LOG(type, fmt, ...) \
|
||||
util::logger.log( \
|
||||
type ",%s(%d): " fmt, __func__, __LINE__ __VA_OPT__(,) __VA_ARGS__ \
|
||||
)
|
||||
|
||||
#ifdef ENABLE_APP_LOGGING
|
||||
#define LOG_APP(fmt, ...) LOG("app", fmt __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_APP(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CART_IO_LOGGING
|
||||
#define LOG_CART_IO(fmt, ...) LOG("cart", fmt __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_CART_IO(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CART_DATA_LOGGING
|
||||
#define LOG_CART_DATA(fmt, ...) LOG("data", fmt __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_CART_DATA(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_ROM_LOGGING
|
||||
#define LOG_ROM(fmt, ...) LOG("rom", fmt __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_ROM(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_IDE_LOGGING
|
||||
#define LOG_IDE(fmt, ...) LOG("ide", fmt __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_IDE(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FS_LOGGING
|
||||
#define LOG_FS(fmt, ...) LOG("fs", fmt __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_FS(fmt, ...)
|
||||
#endif
|
272
src/common/util/hash.cpp
Normal file
272
src/common/util/hash.cpp
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
* 573in1 - Copyright (C) 2022-2024 spicyjpeg
|
||||
*
|
||||
* 573in1 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 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 573in1 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "ps1/registers.h"
|
||||
|
||||
namespace util {
|
||||
|
||||
/* String hashing (http://www.cse.yorku.ca/~oz/hash.html) */
|
||||
|
||||
Hash hash(const char *str, char terminator) {
|
||||
auto _str = reinterpret_cast<const uint8_t *>(str);
|
||||
Hash value = 0;
|
||||
|
||||
while (*_str && (*_str != terminator))
|
||||
value = Hash(*(_str++)) + (value << 6) + (value << 16) - value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
Hash hash(const uint8_t *data, size_t length) {
|
||||
Hash value = 0;
|
||||
|
||||
for (; length; length--)
|
||||
value = Hash(*(data++)) + (value << 6) + (value << 16) - value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* CRC calculation */
|
||||
|
||||
static constexpr uint8_t _CRC8_POLY = 0x8c;
|
||||
static constexpr uint16_t _CRC16_POLY = 0x1021;
|
||||
static constexpr uint32_t _CRC32_POLY = 0xedb88320;
|
||||
|
||||
uint8_t dsCRC8(const uint8_t *data, size_t length) {
|
||||
uint8_t crc = 0;
|
||||
|
||||
for (; length; length--) {
|
||||
uint8_t value = *(data++);
|
||||
|
||||
for (int bit = 8; bit; bit--) {
|
||||
uint8_t temp = crc ^ value;
|
||||
|
||||
value >>= 1;
|
||||
crc >>= 1;
|
||||
if (temp & 1)
|
||||
crc ^= _CRC8_POLY;
|
||||
}
|
||||
}
|
||||
|
||||
return crc & 0xff;
|
||||
}
|
||||
|
||||
uint16_t zsCRC16(const uint8_t *data, size_t length) {
|
||||
uint16_t crc = 0xffff;
|
||||
|
||||
for (; length; length--) {
|
||||
crc ^= *(data++) << 8;
|
||||
|
||||
for (int bit = 8; bit; bit--) {
|
||||
uint16_t temp = crc;
|
||||
|
||||
crc <<= 1;
|
||||
if (temp & (1 << 15))
|
||||
crc ^= _CRC16_POLY;
|
||||
}
|
||||
}
|
||||
|
||||
return (crc ^ 0xffff) & 0xffff;
|
||||
}
|
||||
|
||||
uint32_t zipCRC32(const uint8_t *data, size_t length, uint32_t crc) {
|
||||
// This CRC32 implementation uses a lookup table cached in the scratchpad
|
||||
// area in order to improve performance.
|
||||
auto table = reinterpret_cast<const uint32_t *>(CACHE_BASE);
|
||||
crc = ~crc;
|
||||
|
||||
for (; length; length--)
|
||||
crc = (crc >> 8) ^ table[(crc ^ *(data++)) & 0xff];
|
||||
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
void initZipCRC32(void) {
|
||||
auto table = reinterpret_cast<uint32_t *>(CACHE_BASE);
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
uint32_t crc = i;
|
||||
|
||||
for (int bit = 8; bit; bit--) {
|
||||
uint32_t temp = crc;
|
||||
|
||||
crc >>= 1;
|
||||
if (temp & 1)
|
||||
crc ^= _CRC32_POLY;
|
||||
}
|
||||
|
||||
*(table++) = crc;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" uint32_t mz_crc32(uint32_t crc, const uint8_t *data, size_t length) {
|
||||
return zipCRC32(data, length, crc);
|
||||
}
|
||||
|
||||
/* MD5 hash */
|
||||
|
||||
static const uint32_t _MD5_SEED[]{
|
||||
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
|
||||
};
|
||||
|
||||
static const uint32_t _MD5_ADD[][16]{
|
||||
{
|
||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821
|
||||
}, {
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a
|
||||
}, {
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665
|
||||
}, {
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
|
||||
}
|
||||
};
|
||||
|
||||
static const uint8_t _MD5_SHIFT[][4]{
|
||||
{ 7, 12, 17, 22 },
|
||||
{ 5, 9, 14, 20 },
|
||||
{ 4, 11, 16, 23 },
|
||||
{ 6, 10, 15, 21 }
|
||||
};
|
||||
|
||||
MD5::MD5(void)
|
||||
: _blockCount(0), _bufferLength(0) {
|
||||
__builtin_memcpy(_state, _MD5_SEED, sizeof(_state));
|
||||
}
|
||||
|
||||
void MD5::_flushBlock(const void *data) {
|
||||
auto input = reinterpret_cast<const uint32_t *>(data);
|
||||
|
||||
assertAligned<uint32_t>(data);
|
||||
|
||||
auto a = _state[0], b = _state[1], c = _state[2], d = _state[3];
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
auto _d = d;
|
||||
auto _e = a + _addF(b, c, d) + input[_indexF(i)] + _MD5_ADD[0][i];
|
||||
|
||||
d = c;
|
||||
c = b;
|
||||
b += rotateLeft(_e, _MD5_SHIFT[0][i % 4]);
|
||||
a = _d;
|
||||
}
|
||||
for (int i = 0; i < 16; i++) {
|
||||
auto _d = d;
|
||||
auto _e = a + _addG(b, c, d) + input[_indexG(i)] + _MD5_ADD[1][i];
|
||||
|
||||
d = c;
|
||||
c = b;
|
||||
b += rotateLeft(_e, _MD5_SHIFT[1][i % 4]);
|
||||
a = _d;
|
||||
}
|
||||
for (int i = 0; i < 16; i++) {
|
||||
auto _d = d;
|
||||
auto _e = a + _addH(b, c, d) + input[_indexH(i)] + _MD5_ADD[2][i];
|
||||
|
||||
d = c;
|
||||
c = b;
|
||||
b += rotateLeft(_e, _MD5_SHIFT[2][i % 4]);
|
||||
a = _d;
|
||||
}
|
||||
for (int i = 0; i < 16; i++) {
|
||||
auto _d = d;
|
||||
auto _e = a + _addI(b, c, d) + input[_indexI(i)] + _MD5_ADD[3][i];
|
||||
|
||||
d = c;
|
||||
c = b;
|
||||
b += rotateLeft(_e, _MD5_SHIFT[3][i % 4]);
|
||||
a = _d;
|
||||
}
|
||||
|
||||
_state[0] += a;
|
||||
_state[1] += b;
|
||||
_state[2] += c;
|
||||
_state[3] += d;
|
||||
_blockCount++;
|
||||
}
|
||||
|
||||
void MD5::update(const uint8_t *data, size_t length) {
|
||||
if (_bufferLength > 0) {
|
||||
auto ptr = &_blockBuffer[_bufferLength];
|
||||
auto freeSpace = sizeof(_blockBuffer) - _bufferLength;
|
||||
|
||||
if (length >= freeSpace) {
|
||||
__builtin_memcpy(ptr, data, freeSpace);
|
||||
_flushBlock(_blockBuffer);
|
||||
|
||||
data += freeSpace;
|
||||
length -= freeSpace;
|
||||
_bufferLength = 0;
|
||||
} else {
|
||||
__builtin_memcpy(ptr, data, length);
|
||||
|
||||
_bufferLength += length;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid copying data to the intermediate block buffer whenever possible.
|
||||
for (;
|
||||
length >= sizeof(_blockBuffer);
|
||||
length -= sizeof(_blockBuffer), data += sizeof(_blockBuffer)
|
||||
)
|
||||
_flushBlock(data);
|
||||
|
||||
if (length > 0) {
|
||||
__builtin_memcpy(_blockBuffer, data, length);
|
||||
_bufferLength = length;
|
||||
}
|
||||
}
|
||||
|
||||
void MD5::digest(uint8_t *output) {
|
||||
uint64_t length = (
|
||||
uint64_t(_blockCount) * sizeof(_blockBuffer) + uint64_t(_bufferLength)
|
||||
) * 8;
|
||||
|
||||
_blockBuffer[_bufferLength++] = 1 << 7;
|
||||
|
||||
while (_bufferLength != (sizeof(_blockBuffer) - 8)) {
|
||||
if (_bufferLength == sizeof(_blockBuffer)) {
|
||||
_flushBlock(_blockBuffer);
|
||||
_bufferLength = 0;
|
||||
}
|
||||
|
||||
_blockBuffer[_bufferLength++] = 0;
|
||||
}
|
||||
|
||||
for (int i = 8; i > 0; i--, length >>= 8)
|
||||
_blockBuffer[_bufferLength++] = uint8_t(length & 0xff);
|
||||
|
||||
_flushBlock(_blockBuffer);
|
||||
__builtin_memcpy(output, _state, sizeof(_state));
|
||||
}
|
||||
|
||||
}
|
99
src/common/util/hash.hpp
Normal file
99
src/common/util/hash.hpp
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 573in1 - Copyright (C) 2022-2024 spicyjpeg
|
||||
*
|
||||
* 573in1 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 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 573in1 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace util {
|
||||
|
||||
/* String hashing (http://www.cse.yorku.ca/~oz/hash.html) */
|
||||
|
||||
using Hash = uint32_t;
|
||||
|
||||
template<typename T> static constexpr inline Hash hash(
|
||||
const T *const data, size_t length = -1, Hash value = 0
|
||||
) {
|
||||
if (*data && length)
|
||||
return hash(
|
||||
&data[1], length - 1,
|
||||
Hash(*data) + (value << 6) + (value << 16) - value
|
||||
);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
Hash hash(const char *str, char terminator = 0);
|
||||
Hash hash(const uint8_t *data, size_t length);
|
||||
|
||||
/* CRC calculation */
|
||||
|
||||
uint8_t dsCRC8(const uint8_t *data, size_t length);
|
||||
uint16_t zsCRC16(const uint8_t *data, size_t length);
|
||||
uint32_t zipCRC32(const uint8_t *data, size_t length, uint32_t crc = 0);
|
||||
void initZipCRC32(void);
|
||||
|
||||
/* MD5 hash */
|
||||
|
||||
class MD5 {
|
||||
private:
|
||||
uint32_t _state[4];
|
||||
uint8_t _blockBuffer[64];
|
||||
size_t _blockCount, _bufferLength;
|
||||
|
||||
static inline int _indexF(int index) {
|
||||
return index;
|
||||
}
|
||||
static inline uint32_t _addF(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return z ^ (x & (y ^ z)); // (x & y) | ((~x) & z)
|
||||
}
|
||||
static inline int _indexG(int index) {
|
||||
return ((index * 5) + 1) % 16;
|
||||
}
|
||||
static inline uint32_t _addG(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return y ^ (z & (x ^ y)); // (x & z) | (y & (~z))
|
||||
}
|
||||
static inline int _indexH(int index) {
|
||||
return ((index * 3) + 5) % 16;
|
||||
}
|
||||
static inline uint32_t _addH(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return x ^ y ^ z;
|
||||
}
|
||||
static inline int _indexI(int index) {
|
||||
return (index * 7) % 16;
|
||||
}
|
||||
static inline uint32_t _addI(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return (y ^ (x | (~z)));
|
||||
}
|
||||
|
||||
void _flushBlock(const void *data);
|
||||
|
||||
public:
|
||||
MD5(void);
|
||||
void update(const uint8_t *data, size_t length);
|
||||
void digest(uint8_t *output);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/* String hashing operator */
|
||||
|
||||
static constexpr inline util::Hash operator""_h(
|
||||
const char *const literal, size_t length
|
||||
) {
|
||||
return util::hash(literal, length);
|
||||
}
|
81
src/common/util/log.cpp
Normal file
81
src/common/util/log.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 573in1 - Copyright (C) 2022-2024 spicyjpeg
|
||||
*
|
||||
* 573in1 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 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 573in1 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/misc.hpp"
|
||||
|
||||
namespace util {
|
||||
|
||||
/* Logging framework */
|
||||
|
||||
Logger logger;
|
||||
|
||||
void LogBuffer::clear(void) {
|
||||
for (auto line : _lines)
|
||||
line[0] = 0;
|
||||
}
|
||||
|
||||
char *LogBuffer::allocateLine(void) {
|
||||
size_t tail = _tail;
|
||||
_tail = (tail + 1) % MAX_LOG_LINES;
|
||||
|
||||
return _lines[tail];
|
||||
}
|
||||
|
||||
void Logger::setLogBuffer(LogBuffer *buffer) {
|
||||
CriticalSection sec;
|
||||
|
||||
_buffer = buffer;
|
||||
}
|
||||
|
||||
void Logger::setupSyslog(int baudRate) {
|
||||
CriticalSection sec;
|
||||
|
||||
if (baudRate) {
|
||||
initSerialIO(baudRate);
|
||||
_enableSyslog = true;
|
||||
} else {
|
||||
_enableSyslog = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::log(const char *format, ...) {
|
||||
CriticalSection sec;
|
||||
|
||||
va_list ap;
|
||||
|
||||
if (_buffer) {
|
||||
auto line = _buffer->allocateLine();
|
||||
|
||||
va_start(ap, format);
|
||||
vsnprintf(line, MAX_LOG_LINE_LENGTH, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (_enableSyslog)
|
||||
puts(line);
|
||||
} else if (_enableSyslog) {
|
||||
va_start(ap, format);
|
||||
vprintf(format, ap);
|
||||
va_end(ap);
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
107
src/common/util/log.hpp
Normal file
107
src/common/util/log.hpp
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 573in1 - Copyright (C) 2022-2024 spicyjpeg
|
||||
*
|
||||
* 573in1 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 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 573in1 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace util {
|
||||
|
||||
/* Logging framework */
|
||||
|
||||
static constexpr int MAX_LOG_LINE_LENGTH = 128;
|
||||
static constexpr int MAX_LOG_LINES = 64;
|
||||
|
||||
class LogBuffer {
|
||||
private:
|
||||
char _lines[MAX_LOG_LINES][MAX_LOG_LINE_LENGTH];
|
||||
int _tail;
|
||||
|
||||
public:
|
||||
inline LogBuffer(void)
|
||||
: _tail(0) {
|
||||
clear();
|
||||
}
|
||||
|
||||
// 0 = last line, 1 = second to last, etc.
|
||||
inline const char *getLine(int line) const {
|
||||
return _lines[size_t(_tail - (line + 1)) % MAX_LOG_LINES];
|
||||
}
|
||||
|
||||
void clear(void);
|
||||
char *allocateLine(void);
|
||||
};
|
||||
|
||||
class Logger {
|
||||
private:
|
||||
LogBuffer *_buffer;
|
||||
bool _enableSyslog;
|
||||
|
||||
public:
|
||||
inline Logger(void)
|
||||
: _buffer(nullptr), _enableSyslog(false) {}
|
||||
|
||||
void setLogBuffer(LogBuffer *buffer);
|
||||
void setupSyslog(int baudRate);
|
||||
void log(const char *format, ...);
|
||||
};
|
||||
|
||||
extern Logger logger;
|
||||
|
||||
}
|
||||
|
||||
/* Logging macros */
|
||||
|
||||
#define LOG(type, fmt, ...) \
|
||||
util::logger.log( \
|
||||
type ",%s(%d): " fmt, __func__, __LINE__ __VA_OPT__(,) __VA_ARGS__ \
|
||||
)
|
||||
|
||||
#ifdef ENABLE_APP_LOGGING
|
||||
#define LOG_APP(fmt, ...) LOG("app", fmt __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_APP(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CART_IO_LOGGING
|
||||
#define LOG_CART_IO(fmt, ...) LOG("cart", fmt __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_CART_IO(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CART_DATA_LOGGING
|
||||
#define LOG_CART_DATA(fmt, ...) LOG("data", fmt __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_CART_DATA(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_ROM_LOGGING
|
||||
#define LOG_ROM(fmt, ...) LOG("rom", fmt __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_ROM(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_IDE_LOGGING
|
||||
#define LOG_IDE(fmt, ...) LOG("ide", fmt __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_IDE(fmt, ...)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FS_LOGGING
|
||||
#define LOG_FS(fmt, ...) LOG("fs", fmt __VA_OPT__(,) __VA_ARGS__)
|
||||
#else
|
||||
#define LOG_FS(fmt, ...)
|
||||
#endif
|
211
src/common/util/misc.cpp
Normal file
211
src/common/util/misc.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* 573in1 - Copyright (C) 2022-2024 spicyjpeg
|
||||
*
|
||||
* 573in1 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 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 573in1 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/misc.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "ps1/system.h"
|
||||
|
||||
namespace util {
|
||||
|
||||
/* Date and time class */
|
||||
|
||||
bool Date::isValid(void) const {
|
||||
if ((hour > 23) || (minute > 59) || (second > 59))
|
||||
return false;
|
||||
if ((month < 1) || (month > 12))
|
||||
return false;
|
||||
if ((day < 1) || (day > getMonthDayCount()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Date::isLeapYear(void) const {
|
||||
if (year % 4)
|
||||
return false;
|
||||
if (!(year % 100) && (year % 400))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int Date::getDayOfWeek(void) const {
|
||||
// See https://datatracker.ietf.org/doc/html/rfc3339#appendix-B
|
||||
int _year = year, _month = month - 2;
|
||||
|
||||
if (_month <= 0) {
|
||||
_month += 12;
|
||||
_year--;
|
||||
}
|
||||
|
||||
int century = _year / 100;
|
||||
_year %= 100;
|
||||
|
||||
int weekday = 0
|
||||
+ day
|
||||
+ (_month * 26 - 2) / 10
|
||||
+ _year
|
||||
+ _year / 4
|
||||
+ century / 4
|
||||
+ century * 5;
|
||||
|
||||
return weekday % 7;
|
||||
}
|
||||
|
||||
int Date::getMonthDayCount(void) const {
|
||||
switch (month) {
|
||||
case 2:
|
||||
return isLeapYear() ? 29 : 28;
|
||||
|
||||
case 4:
|
||||
case 6:
|
||||
case 9:
|
||||
case 11:
|
||||
return 30;
|
||||
|
||||
default:
|
||||
return 31;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Date::toDOSTime(void) const {
|
||||
int _year = year - 1980;
|
||||
|
||||
if (!isValid())
|
||||
return 0;
|
||||
if ((_year < 0) || (_year > 127))
|
||||
return 0;
|
||||
|
||||
return 0
|
||||
| (_year << 25)
|
||||
| (month << 21)
|
||||
| (day << 16)
|
||||
| (hour << 11)
|
||||
| (minute << 5)
|
||||
| (second >> 1);
|
||||
}
|
||||
|
||||
size_t Date::toString(char *output) const {
|
||||
if (!isValid()) {
|
||||
*output = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
output, "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute,
|
||||
second
|
||||
);
|
||||
}
|
||||
|
||||
/* PS1 executable loader */
|
||||
|
||||
bool ExecutableHeader::validateMagic(void) const {
|
||||
#if 0
|
||||
return (
|
||||
hash(magic, sizeof(magic)) ==
|
||||
hash("PS-X EXE\0\0\0\0\0\0\0\0", sizeof(magic), 0)
|
||||
);
|
||||
#else
|
||||
return true
|
||||
&& (magic[0] == concatenate('P', 'S', '-', 'X'))
|
||||
&& (magic[1] == concatenate(' ', 'E', 'X', 'E'))
|
||||
&& !magic[2]
|
||||
&& !magic[3]
|
||||
&& !(entryPoint % 4)
|
||||
&& !(textOffset % 4)
|
||||
&& !(textLength % 2048)
|
||||
&& !dataLength
|
||||
&& !bssLength;
|
||||
#endif
|
||||
}
|
||||
|
||||
ExecutableLoader::ExecutableLoader(
|
||||
void *entryPoint, void *initialGP, void *stackTop
|
||||
) : _entryPoint(entryPoint), _initialGP(initialGP), _numArgs(0) {
|
||||
_argListPtr = reinterpret_cast<const char **>(uintptr_t(stackTop) & ~7)
|
||||
- MAX_EXECUTABLE_ARGS;
|
||||
_currentStackPtr = reinterpret_cast<char *>(_argListPtr);
|
||||
}
|
||||
|
||||
bool ExecutableLoader::addArgument(const char *arg) {
|
||||
if (_numArgs >= MAX_EXECUTABLE_ARGS)
|
||||
return false;
|
||||
|
||||
_argListPtr[_numArgs++] = arg;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExecutableLoader::copyArgument(const char *arg, size_t length) {
|
||||
if (_numArgs >= MAX_EXECUTABLE_ARGS)
|
||||
return false;
|
||||
|
||||
// Command-line arguments must be copied to the top of the new stack in
|
||||
// order to ensure the executable is going to be able to access them at any
|
||||
// time.
|
||||
*(--_currentStackPtr) = 0;
|
||||
_currentStackPtr -= length;
|
||||
__builtin_memcpy(_currentStackPtr, arg, length);
|
||||
|
||||
_argListPtr[_numArgs++] = _currentStackPtr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExecutableLoader::formatArgument(const char *format, ...) {
|
||||
char buffer[64];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
int length = vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return copyArgument(buffer, length + 1);
|
||||
}
|
||||
|
||||
[[noreturn]] void ExecutableLoader::run(
|
||||
int rawArgc, const char *const *rawArgv
|
||||
) {
|
||||
#if 0
|
||||
disableInterrupts();
|
||||
flushCache();
|
||||
#endif
|
||||
|
||||
register int a0 __asm__("a0") = rawArgc;
|
||||
register const char *const *a1 __asm__("a1") = rawArgv;
|
||||
register void *gp __asm__("gp") = _initialGP;
|
||||
|
||||
auto stackTop = uintptr_t(_currentStackPtr) & ~7;
|
||||
|
||||
// Changing the stack pointer and return address is not something that
|
||||
// should be done in a C++ function, but hopefully it's fine here since
|
||||
// we're jumping out right after setting it.
|
||||
__asm__ volatile(
|
||||
".set push\n"
|
||||
".set noreorder\n"
|
||||
"li $ra, %0\n"
|
||||
"jr %1\n"
|
||||
"addiu $sp, %2, -8\n"
|
||||
".set pop\n"
|
||||
:: "i"(DEV2_BASE), "r"(_entryPoint), "r"(stackTop),
|
||||
"r"(a0), "r"(a1), "r"(gp)
|
||||
);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
}
|
139
src/common/util/misc.hpp
Normal file
139
src/common/util/misc.hpp
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 573in1 - Copyright (C) 2022-2024 spicyjpeg
|
||||
*
|
||||
* 573in1 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 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 573in1 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "ps1/system.h"
|
||||
|
||||
namespace util {
|
||||
|
||||
/* Date and time class */
|
||||
|
||||
class Date {
|
||||
public:
|
||||
uint16_t year;
|
||||
uint8_t month, day, hour, minute, second;
|
||||
|
||||
inline void reset(void) {
|
||||
year = 2024;
|
||||
month = 1;
|
||||
day = 1;
|
||||
hour = 0;
|
||||
minute = 0;
|
||||
second = 0;
|
||||
}
|
||||
|
||||
bool isValid(void) const;
|
||||
bool isLeapYear(void) const;
|
||||
int getDayOfWeek(void) const;
|
||||
int getMonthDayCount(void) const;
|
||||
uint32_t toDOSTime(void) const;
|
||||
size_t toString(char *output) const;
|
||||
};
|
||||
|
||||
/* Critical section helper */
|
||||
|
||||
class CriticalSection {
|
||||
private:
|
||||
bool _enable;
|
||||
|
||||
public:
|
||||
inline CriticalSection(void) {
|
||||
_enable = disableInterrupts();
|
||||
}
|
||||
inline ~CriticalSection(void) {
|
||||
if (_enable)
|
||||
enableInterrupts();
|
||||
}
|
||||
};
|
||||
|
||||
class ThreadCriticalSection {
|
||||
public:
|
||||
inline ThreadCriticalSection(void) {
|
||||
bool enable = disableInterrupts();
|
||||
|
||||
//assert(enable);
|
||||
}
|
||||
inline ~ThreadCriticalSection(void) {
|
||||
enableInterrupts();
|
||||
}
|
||||
};
|
||||
|
||||
/* PS1 executable loader */
|
||||
|
||||
static constexpr size_t EXECUTABLE_BODY_OFFSET = 2048;
|
||||
static constexpr size_t MAX_EXECUTABLE_ARGS = 32;
|
||||
|
||||
class ExecutableHeader {
|
||||
public:
|
||||
uint32_t magic[4];
|
||||
|
||||
uint32_t entryPoint, initialGP;
|
||||
uint32_t textOffset, textLength;
|
||||
uint32_t dataOffset, dataLength;
|
||||
uint32_t bssOffset, bssLength;
|
||||
uint32_t stackOffset, stackLength;
|
||||
uint32_t _reserved[5];
|
||||
|
||||
inline void *getEntryPoint(void) const {
|
||||
return reinterpret_cast<void *>(entryPoint);
|
||||
}
|
||||
inline void *getInitialGP(void) const {
|
||||
return reinterpret_cast<void *>(initialGP);
|
||||
}
|
||||
inline void *getTextPtr(void) const {
|
||||
return reinterpret_cast<void *>(textOffset);
|
||||
}
|
||||
inline void *getStackPtr(void) const {
|
||||
return reinterpret_cast<void *>(stackOffset + stackLength);
|
||||
}
|
||||
inline const char *getRegionString(void) const {
|
||||
return reinterpret_cast<const char *>(this + 1);
|
||||
}
|
||||
inline void relocateText(const void *source) const {
|
||||
__builtin_memcpy(getTextPtr(), source, textLength);
|
||||
}
|
||||
|
||||
bool validateMagic(void) const;
|
||||
};
|
||||
|
||||
class ExecutableLoader {
|
||||
private:
|
||||
void *_entryPoint, *_initialGP;
|
||||
|
||||
size_t _numArgs;
|
||||
const char **_argListPtr;
|
||||
char *_currentStackPtr;
|
||||
|
||||
public:
|
||||
inline bool copyArgument(const char *arg) {
|
||||
return copyArgument(arg, __builtin_strlen(arg));
|
||||
}
|
||||
[[noreturn]] inline void run(void) {
|
||||
run(_numArgs, _argListPtr);
|
||||
}
|
||||
|
||||
ExecutableLoader(void *entryPoint, void *initialGP, void *stackTop);
|
||||
bool addArgument(const char *arg);
|
||||
bool copyArgument(const char *arg, size_t length);
|
||||
bool formatArgument(const char *format, ...);
|
||||
[[noreturn]] void run(int rawArgc, const char *const *rawArgv);
|
||||
};
|
||||
|
||||
}
|
167
src/common/util/string.cpp
Normal file
167
src/common/util/string.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* 573in1 - Copyright (C) 2022-2024 spicyjpeg
|
||||
*
|
||||
* 573in1 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 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 573in1 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "common/util/string.hpp"
|
||||
|
||||
namespace util {
|
||||
|
||||
/* String manipulation */
|
||||
|
||||
const char HEX_CHARSET[]{ "0123456789ABCDEF" };
|
||||
const char BASE41_CHARSET[]{ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./:" };
|
||||
|
||||
size_t hexValueToString(char *output, uint32_t value, size_t numDigits) {
|
||||
output += numDigits;
|
||||
*output = 0;
|
||||
|
||||
for (size_t i = numDigits; i; i--, value >>= 4)
|
||||
*(--output) = HEX_CHARSET[value & 0xf];
|
||||
|
||||
return numDigits;
|
||||
}
|
||||
|
||||
size_t hexToString(
|
||||
char *output, const uint8_t *input, size_t length, char separator
|
||||
) {
|
||||
size_t outLength = 0;
|
||||
|
||||
for (; length; length--) {
|
||||
uint8_t value = *(input++);
|
||||
|
||||
*(output++) = HEX_CHARSET[value >> 4];
|
||||
*(output++) = HEX_CHARSET[value & 0xf];
|
||||
|
||||
if (separator && (length > 1)) {
|
||||
*(output++) = separator;
|
||||
outLength += 3;
|
||||
} else {
|
||||
outLength += 2;
|
||||
}
|
||||
}
|
||||
|
||||
*output = 0;
|
||||
return outLength;
|
||||
}
|
||||
|
||||
size_t serialNumberToString(char *output, const uint8_t *input) {
|
||||
uint32_t value =
|
||||
input[0] | (input[1] << 8) | (input[2] << 16) | (input[3] << 24);
|
||||
|
||||
return sprintf(output, "%04d-%04d", (value / 10000) % 10000, value % 10000);
|
||||
}
|
||||
|
||||
// This format is used by Konami's tools to display trace IDs in the TID_81
|
||||
// format.
|
||||
static const char _TRACE_ID_CHECKSUM_CHARSET[]{ "0X987654321" };
|
||||
|
||||
size_t traceIDToString(char *output, const uint8_t *input) {
|
||||
uint16_t high = (input[0] << 8) | input[1];
|
||||
uint32_t low =
|
||||
(input[2] << 24) | (input[3] << 16) | (input[4] << 8) | input[5];
|
||||
|
||||
size_t length = sprintf(&output[1], "%02d-%04d", high % 100, low % 10000);
|
||||
|
||||
// The checksum is calculated in a very weird way:
|
||||
// code = AB-CDEF
|
||||
// checksum = (A*7 + B*6 + C*5 + D*4 + E*3 + F*2) % 11
|
||||
int checksum = 0, multiplier = 7;
|
||||
|
||||
for (const char *ptr = &output[1]; *ptr; ptr++) {
|
||||
if (*ptr != '-')
|
||||
checksum += (*ptr - '0') * (multiplier--);
|
||||
}
|
||||
|
||||
output[0] = _TRACE_ID_CHECKSUM_CHARSET[checksum % 11];
|
||||
return length + 1;
|
||||
}
|
||||
|
||||
// This encoding is similar to standard base45, but with some problematic
|
||||
// characters (' ', '$', '%', '*') excluded.
|
||||
size_t encodeBase41(char *output, const uint8_t *input, size_t length) {
|
||||
size_t outLength = 0;
|
||||
|
||||
for (int i = length + 1; i > 0; i -= 2) {
|
||||
int value = *(input++) << 8;
|
||||
value |= *(input++);
|
||||
|
||||
*(output++) = BASE41_CHARSET[value % 41];
|
||||
*(output++) = BASE41_CHARSET[(value / 41) % 41];
|
||||
*(output++) = BASE41_CHARSET[value / 1681];
|
||||
outLength += 3;
|
||||
}
|
||||
|
||||
*output = 0;
|
||||
return outLength;
|
||||
}
|
||||
|
||||
/* LZ4 decompressor */
|
||||
|
||||
void decompressLZ4(
|
||||
uint8_t *output, const uint8_t *input, size_t maxOutputLength,
|
||||
size_t inputLength
|
||||
) {
|
||||
auto outputEnd = &output[maxOutputLength];
|
||||
auto inputEnd = &input[inputLength];
|
||||
|
||||
while (input < inputEnd) {
|
||||
uint8_t token = *(input++);
|
||||
|
||||
// Copy literals from the input stream.
|
||||
int literalLength = token >> 4;
|
||||
|
||||
if (literalLength == 0xf) {
|
||||
uint8_t addend;
|
||||
|
||||
do {
|
||||
addend = *(input++);
|
||||
literalLength += addend;
|
||||
} while (addend == 0xff);
|
||||
}
|
||||
|
||||
for (; literalLength && (output < outputEnd); literalLength--)
|
||||
*(output++) = *(input++);
|
||||
if (input >= inputEnd)
|
||||
break;
|
||||
|
||||
int offset = input[0] | (input[1] << 8);
|
||||
input += 2;
|
||||
|
||||
// Copy from previously decompressed data. Note that this *must* be done
|
||||
// one byte at a time, as the compressor relies on out-of-bounds copies
|
||||
// repeating the last byte.
|
||||
int copyLength = token & 0xf;
|
||||
|
||||
if (copyLength == 0xf) {
|
||||
uint8_t addend;
|
||||
|
||||
do {
|
||||
addend = *(input++);
|
||||
copyLength += addend;
|
||||
} while (addend == 0xff);
|
||||
}
|
||||
|
||||
auto copySource = output - offset;
|
||||
copyLength += 4;
|
||||
|
||||
for (; copyLength && (output < outputEnd); copyLength--)
|
||||
*(output++) = *(copySource++);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
47
src/common/util/string.hpp
Normal file
47
src/common/util/string.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 573in1 - Copyright (C) 2022-2024 spicyjpeg
|
||||
*
|
||||
* 573in1 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 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 573in1 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace util {
|
||||
|
||||
/* String manipulation */
|
||||
|
||||
extern const char HEX_CHARSET[], BASE41_CHARSET[];
|
||||
|
||||
size_t hexValueToString(char *output, uint32_t value, size_t numDigits = 8);
|
||||
size_t hexToString(
|
||||
char *output, const uint8_t *input, size_t length, char separator = 0
|
||||
);
|
||||
size_t serialNumberToString(char *output, const uint8_t *input);
|
||||
size_t traceIDToString(char *output, const uint8_t *input);
|
||||
size_t encodeBase41(char *output, const uint8_t *input, size_t length);
|
||||
|
||||
/* LZ4 decompressor */
|
||||
|
||||
static inline size_t getLZ4InPlaceMargin(size_t inputLength) {
|
||||
return (inputLength >> 8) + 32;
|
||||
}
|
||||
|
||||
void decompressLZ4(
|
||||
uint8_t *output, const uint8_t *input, size_t maxOutputLength,
|
||||
size_t inputLength
|
||||
);
|
||||
|
||||
}
|
174
src/common/util/templates.hpp
Normal file
174
src/common/util/templates.hpp
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* 573in1 - Copyright (C) 2022-2024 spicyjpeg
|
||||
*
|
||||
* 573in1 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 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 573in1 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace util {
|
||||
|
||||
/* Misc. template utilities */
|
||||
|
||||
template<typename T> static inline uint32_t sum(const T *data, size_t length) {
|
||||
uint32_t value = 0;
|
||||
|
||||
for (; length; length--)
|
||||
value += uint32_t(*(data++));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T> static inline T min(T a, T b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
template<typename T> static inline T max(T a, T b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
template<typename T> static inline T clamp(T value, T minValue, T maxValue) {
|
||||
return (value < minValue) ? minValue :
|
||||
((value > maxValue) ? maxValue : value);
|
||||
}
|
||||
|
||||
template<typename T> static inline T rotateLeft(T value, int amount) {
|
||||
return T((value << amount) | (value >> (sizeof(T) * 8 - amount)));
|
||||
}
|
||||
|
||||
template<typename T> static inline T rotateRight(T value, int amount) {
|
||||
return T((value >> amount) | (value << (sizeof(T) * 8 - amount)));
|
||||
}
|
||||
|
||||
// These shall only be used with unsigned types.
|
||||
template<typename T> static inline T truncateToMultiple(T value, T length) {
|
||||
return value - (value % length);
|
||||
}
|
||||
|
||||
template<typename T> static inline T roundUpToMultiple(T value, T length) {
|
||||
T diff = value % length;
|
||||
return diff ? (value - diff + length) : value;
|
||||
}
|
||||
|
||||
template<typename T, typename X> static inline void assertAligned(X *ptr) {
|
||||
//assert(!(reinterpret_cast<uintptr_t>(ptr) % alignof(T)));
|
||||
}
|
||||
|
||||
template<typename T> static inline void clear(T &obj, uint8_t value = 0) {
|
||||
__builtin_memset(&obj, value, sizeof(obj));
|
||||
}
|
||||
|
||||
template<typename T> static constexpr inline size_t countOf(T &array) {
|
||||
return sizeof(array) / sizeof(array[0]);
|
||||
}
|
||||
|
||||
template<typename T, typename X> static inline T forcedCast(X item) {
|
||||
return reinterpret_cast<T>(reinterpret_cast<void *>(item));
|
||||
}
|
||||
|
||||
static constexpr inline uint16_t concatenate(uint8_t a, uint8_t b) {
|
||||
return a | (b << 8);
|
||||
}
|
||||
|
||||
static constexpr inline uint32_t concatenate(
|
||||
uint8_t a, uint8_t b, uint8_t c, uint8_t d
|
||||
) {
|
||||
return a | (b << 8) | (c << 16) | (d << 24);
|
||||
}
|
||||
|
||||
/* Simple "smart" pointer */
|
||||
|
||||
class Data {
|
||||
public:
|
||||
void *ptr;
|
||||
size_t length;
|
||||
|
||||
inline Data(void)
|
||||
: ptr(nullptr), length(0) {}
|
||||
inline ~Data(void) {
|
||||
destroy();
|
||||
}
|
||||
|
||||
template<typename T> inline T *as(void) {
|
||||
return reinterpret_cast<T *>(ptr);
|
||||
}
|
||||
template<typename T> inline const T *as(void) const {
|
||||
return reinterpret_cast<const T *>(ptr);
|
||||
}
|
||||
template<typename T> inline T *allocate(size_t count = 1) {
|
||||
return reinterpret_cast<T *>(allocate(sizeof(T) * count));
|
||||
}
|
||||
|
||||
inline void *allocate(size_t _length) {
|
||||
if (ptr)
|
||||
delete[] as<uint8_t>();
|
||||
|
||||
ptr = _length ? (new uint8_t[_length]) : nullptr;
|
||||
length = _length;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
inline void destroy(void) {
|
||||
if (ptr) {
|
||||
delete[] as<uint8_t>();
|
||||
ptr = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Simple ring buffer */
|
||||
|
||||
template<typename T, size_t N> class RingBuffer {
|
||||
private:
|
||||
T _items[N];
|
||||
size_t _head, _tail;
|
||||
|
||||
public:
|
||||
size_t length;
|
||||
|
||||
inline RingBuffer(void)
|
||||
: _head(0), _tail(0), length(0) {}
|
||||
|
||||
inline T *pushItem(void) volatile {
|
||||
if (length >= N)
|
||||
return nullptr;
|
||||
|
||||
size_t i = _tail;
|
||||
_tail = (i + 1) % N;
|
||||
length++;
|
||||
|
||||
return &_items[i];
|
||||
}
|
||||
inline T *popItem(void) volatile {
|
||||
if (!length)
|
||||
return nullptr;
|
||||
|
||||
size_t i = _head;
|
||||
_head = (i + 1) % N;
|
||||
length--;
|
||||
|
||||
return &_items[i];
|
||||
}
|
||||
inline T *peekItem(void) const {
|
||||
if (!length)
|
||||
return nullptr;
|
||||
|
||||
return &_items[_head];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
63
src/common/util/tween.cpp
Normal file
63
src/common/util/tween.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 573in1 - Copyright (C) 2022-2024 spicyjpeg
|
||||
*
|
||||
* 573in1 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 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 573in1 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util/tween.hpp"
|
||||
|
||||
namespace util {
|
||||
|
||||
template<typename T, typename E> void Tween<T, E>::setValue(
|
||||
int time, T start, T target, int duration
|
||||
) {
|
||||
//assert(duration <= 0x800);
|
||||
|
||||
_base = start;
|
||||
_delta = target - start;
|
||||
|
||||
_endTime = time + duration;
|
||||
_timeScale = TWEEN_UNIT / duration;
|
||||
}
|
||||
|
||||
template<typename T, typename E> void Tween<T, E>::setValue(T target) {
|
||||
_base = target;
|
||||
_delta = static_cast<T>(0);
|
||||
|
||||
_endTime = 0;
|
||||
}
|
||||
|
||||
template<typename T, typename E> T Tween<T, E>::getValue(int time) const {
|
||||
int remaining = time - _endTime;
|
||||
|
||||
if (remaining >= 0)
|
||||
return _base + _delta;
|
||||
|
||||
return _base + (
|
||||
_delta * E::apply(remaining * _timeScale + TWEEN_UNIT)
|
||||
) / TWEEN_UNIT;
|
||||
}
|
||||
|
||||
template class Tween<int, LinearEasing>;
|
||||
template class Tween<int, QuadInEasing>;
|
||||
template class Tween<int, QuadOutEasing>;
|
||||
template class Tween<uint16_t, LinearEasing>;
|
||||
template class Tween<uint16_t, QuadInEasing>;
|
||||
template class Tween<uint16_t, QuadOutEasing>;
|
||||
template class Tween<uint32_t, LinearEasing>;
|
||||
template class Tween<uint32_t, QuadInEasing>;
|
||||
template class Tween<uint32_t, QuadOutEasing>;
|
||||
|
||||
}
|
72
src/common/util/tween.hpp
Normal file
72
src/common/util/tween.hpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 573in1 - Copyright (C) 2022-2024 spicyjpeg
|
||||
*
|
||||
* 573in1 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 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 573in1 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace util {
|
||||
|
||||
static constexpr int TWEEN_UNIT = 1 << 12;
|
||||
|
||||
class LinearEasing {
|
||||
public:
|
||||
template<typename T> static inline T apply(T value) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
class QuadInEasing {
|
||||
public:
|
||||
template<typename T> static inline T apply(T value) {
|
||||
return (value * value) / TWEEN_UNIT;
|
||||
}
|
||||
};
|
||||
|
||||
class QuadOutEasing {
|
||||
public:
|
||||
template<typename T> static inline T apply(T value) {
|
||||
return (value * 2) - ((value * value) / TWEEN_UNIT);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename E> class Tween {
|
||||
private:
|
||||
T _base, _delta;
|
||||
int _endTime, _timeScale;
|
||||
|
||||
public:
|
||||
inline Tween(void) {
|
||||
setValue(static_cast<T>(0));
|
||||
}
|
||||
inline Tween(T start) {
|
||||
setValue(start);
|
||||
}
|
||||
|
||||
inline T getTargetValue(void) const {
|
||||
return _base + _delta;
|
||||
}
|
||||
inline bool isDone(int time) const {
|
||||
return time >= _endTime;
|
||||
}
|
||||
inline void setValue(int time, T target, int duration) {
|
||||
setValue(time, getValue(time), target, duration);
|
||||
}
|
||||
|
||||
void setValue(int time, T start, T target, int duration);
|
||||
void setValue(T target);
|
||||
T getValue(int time) const;
|
||||
};
|
||||
|
||||
}
|
@ -15,10 +15,12 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/misc.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/args.hpp"
|
||||
#include "common/ide.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "ps1/system.h"
|
||||
|
||||
extern "C" uint8_t _textStart[];
|
||||
|
@ -21,12 +21,14 @@
|
||||
#include "common/file/iso9660.hpp"
|
||||
#include "common/file/misc.hpp"
|
||||
#include "common/file/zip.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/misc.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/defs.hpp"
|
||||
#include "common/gpu.hpp"
|
||||
#include "common/ide.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/spu.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/app/app.hpp"
|
||||
#include "main/cart/cart.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/file/misc.hpp"
|
||||
#include "common/file/zip.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/ide.hpp"
|
||||
#include "main/app/cartactions.hpp"
|
||||
#include "main/app/cartunlock.hpp"
|
||||
|
@ -14,7 +14,10 @@
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/string.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "main/app/cartactions.hpp"
|
||||
#include "main/app/app.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
|
@ -15,7 +15,10 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/string.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "main/app/app.hpp"
|
||||
#include "main/app/cartunlock.hpp"
|
||||
#include "main/cart/cartdata.hpp"
|
||||
|
@ -18,9 +18,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/defs.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/app/app.hpp"
|
||||
#include "main/cart/cart.hpp"
|
||||
#include "main/cart/cartdata.hpp"
|
||||
|
@ -15,7 +15,8 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "main/app/app.hpp"
|
||||
#include "main/app/main.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
|
@ -18,10 +18,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/ide.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/spu.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/app/app.hpp"
|
||||
#include "main/app/misc.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
|
@ -17,8 +17,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/spu.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
#include "main/uicommon.hpp"
|
||||
#include "main/uimodals.hpp"
|
||||
|
@ -17,12 +17,14 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/misc.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/defs.hpp"
|
||||
#include "common/ide.hpp"
|
||||
#include "common/idedefs.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/rom.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/app/app.hpp"
|
||||
#include "ps1/system.h"
|
||||
|
||||
|
@ -18,9 +18,11 @@
|
||||
#include <stdio.h>
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/file/misc.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/defs.hpp"
|
||||
#include "common/ide.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/app/app.hpp"
|
||||
#include "main/app/modals.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
|
@ -17,8 +17,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/ide.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
#include "main/uicommon.hpp"
|
||||
#include "main/uimodals.hpp"
|
||||
|
@ -15,9 +15,9 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/rom.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/app/app.hpp"
|
||||
#include "main/app/romactions.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
|
@ -18,10 +18,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "common/file/file.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/defs.hpp"
|
||||
#include "common/rom.hpp"
|
||||
#include "common/romdrivers.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/app/app.hpp"
|
||||
#include "main/app/romactions.hpp"
|
||||
|
||||
|
@ -14,10 +14,13 @@
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/string.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/gpu.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/spu.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/app/app.hpp"
|
||||
#include "main/app/tests.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
|
@ -16,7 +16,10 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/string.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "main/cart/cart.hpp"
|
||||
#include "vendor/miniz.h"
|
||||
|
||||
|
@ -18,8 +18,9 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util/string.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/rom.hpp"
|
||||
#include "common/util.hpp"
|
||||
|
||||
namespace cart {
|
||||
|
||||
|
@ -16,7 +16,9 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "main/cart/cart.hpp"
|
||||
#include "main/cart/cartdata.hpp"
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "main/cart/cart.hpp"
|
||||
|
||||
namespace cart {
|
||||
|
@ -15,8 +15,11 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/misc.hpp"
|
||||
#include "common/util/string.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/cart/cart.hpp"
|
||||
#include "main/cart/cartio.hpp"
|
||||
#include "main/cart/zs01.hpp"
|
||||
|
@ -16,7 +16,8 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "main/cart/zs01.hpp"
|
||||
|
||||
namespace cart {
|
||||
|
@ -14,11 +14,12 @@
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/util/hash.hpp"
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/args.hpp"
|
||||
#include "common/gpu.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/spu.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/app/app.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
#include "ps1/gpucmd.h"
|
||||
|
@ -15,11 +15,13 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/util/tween.hpp"
|
||||
#include "common/gpu.hpp"
|
||||
#include "common/gpufont.hpp"
|
||||
#include "common/io.hpp"
|
||||
#include "common/pad.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
#include "ps1/gpucmd.h"
|
||||
|
||||
|
@ -17,10 +17,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common/util/log.hpp"
|
||||
#include "common/util/tween.hpp"
|
||||
#include "common/gpu.hpp"
|
||||
#include "common/gpufont.hpp"
|
||||
#include "common/spu.hpp"
|
||||
#include "common/util.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
* 573in1. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/defs.hpp"
|
||||
#include "common/gpu.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
|
@ -17,8 +17,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common/util/tween.hpp"
|
||||
#include "common/gpu.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
@ -16,8 +16,11 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "common/util/misc.hpp"
|
||||
#include "common/util/string.hpp"
|
||||
#include "common/util/templates.hpp"
|
||||
#include "common/util/tween.hpp"
|
||||
#include "common/gpu.hpp"
|
||||
#include "common/util.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
#include "main/uimodals.hpp"
|
||||
|
||||
|
@ -17,7 +17,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "common/util.hpp"
|
||||
#include "common/util/misc.hpp"
|
||||
#include "common/util/tween.hpp"
|
||||
#include "main/uibase.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
Loading…
x
Reference in New Issue
Block a user