mirror of
https://github.com/spicyjpeg/573in1.git
synced 2025-02-13 00:44:33 +01:00
230 lines
4.8 KiB
C++
230 lines
4.8 KiB
C++
|
|
#pragma once
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include "ps1/system.h"
|
|
|
|
namespace util {
|
|
|
|
/* Misc. template utilities */
|
|
|
|
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);
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
static inline uint16_t swapEndian(uint16_t value) {
|
|
value = ((value & 0x00ff) << 8) | ((value & 0xff00) >> 8);
|
|
|
|
return value;
|
|
}
|
|
|
|
static inline uint32_t swapEndian(uint32_t value) {
|
|
value = ((value & 0x0000ffff) << 16) | ((value & 0xffff0000) >> 16);
|
|
value = ((value & 0x00ff00ff) << 8) | ((value & 0xff00ff00) >> 8);
|
|
|
|
return value;
|
|
}
|
|
|
|
template<typename T, typename X> static constexpr inline T forcedCast(X item) {
|
|
return reinterpret_cast<T>(reinterpret_cast<void *>(item));
|
|
}
|
|
|
|
/* 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);
|
|
|
|
/* 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];
|
|
}
|
|
};
|
|
|
|
/* 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 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;
|
|
}
|
|
inline T getTargetValue(void) const {
|
|
return _base + _delta;
|
|
}
|
|
inline bool isDone(int time) const {
|
|
return time >= _endTime;
|
|
}
|
|
|
|
inline void setValue(int time, T start, T target, int duration) {
|
|
//assert(duration <= 0x800);
|
|
|
|
_base = start;
|
|
_delta = target - start;
|
|
|
|
_endTime = time + duration;
|
|
_timeScale = TWEEN_UNIT / duration;
|
|
}
|
|
inline void setValue(int time, T target, int duration) {
|
|
setValue(time, getValue(time), target, duration);
|
|
}
|
|
inline void setValue(T target) {
|
|
_base = target;
|
|
_delta = static_cast<T>(0);
|
|
_endTime = 0;
|
|
}
|
|
};
|
|
|
|
/* Logger (basically a ring buffer of lines) */
|
|
|
|
static constexpr int MAX_LOG_LINE_LENGTH = 128;
|
|
static constexpr int MAX_LOG_LINES = 32;
|
|
|
|
class Logger {
|
|
private:
|
|
char _lines[MAX_LOG_LINES][MAX_LOG_LINE_LENGTH];
|
|
int _tail;
|
|
|
|
public:
|
|
bool enableSyslog;
|
|
|
|
// 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];
|
|
}
|
|
|
|
Logger(void);
|
|
void clear(void);
|
|
void log(const char *format, ...);
|
|
};
|
|
|
|
extern Logger logger;
|
|
|
|
/* Other APIs */
|
|
|
|
uint8_t dsCRC8(const uint8_t *data, size_t length);
|
|
uint16_t zsCRC16(const uint8_t *data, size_t length);
|
|
|
|
size_t hexToString(char *output, const uint8_t *input, size_t length, char sep = 0);
|
|
size_t serialNumberToString(char *output, const uint8_t *input);
|
|
size_t encodeBase45(char *output, const uint8_t *input, size_t length);
|
|
|
|
}
|
|
|
|
//#define LOG(...) util::logger.log(__VA_ARGS__)
|
|
#define LOG(fmt, ...) \
|
|
util::logger.log("%s(%d): " fmt, __func__, __LINE__ __VA_OPT__(,) __VA_ARGS__)
|
|
|
|
static constexpr inline util::Hash operator""_h(
|
|
const char *const literal, size_t length
|
|
) {
|
|
return util::hash(literal, length);
|
|
}
|