New code style refactor

This commit is contained in:
Jack Andersen 2018-12-07 19:20:24 -10:00
parent a1e2242691
commit f126245eef
22 changed files with 1906 additions and 2181 deletions

View File

@ -1,5 +1,5 @@
--- ---
IndentWidth: 4 BasedOnStyle: LLVM
ColumnLimit: 120 ColumnLimit: 120
UseTab: Never UseTab: Never
--- ---
@ -8,7 +8,6 @@ DerivePointerAlignment: false
PointerAlignment: Left PointerAlignment: Left
AlignAfterOpenBracket: Align AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false AlignConsecutiveAssignments: false
BreakBeforeBraces: Allman
IndentCaseLabels: false IndentCaseLabels: false
AllowShortBlocksOnASingleLine: true AllowShortBlocksOnASingleLine: true
AlignOperands: true AlignOperands: true
@ -24,6 +23,6 @@ NamespaceIndentation: None
BinPackArguments: true BinPackArguments: true
BinPackParameters: true BinPackParameters: true
SortIncludes: false SortIncludes: false
AccessModifierOffset: -4 AccessModifierOffset: -2
ConstructorInitializerIndentWidth: 0 ConstructorInitializerIndentWidth: 0
ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerAllOnOneLineOrOnePerLine: true

View File

@ -11,11 +11,9 @@ using SizeReturn = DWORD;
#include "Util.hpp" #include "Util.hpp"
#include <vector> #include <vector>
namespace kabufuda namespace kabufuda {
{
class AsyncIO class AsyncIO {
{
#ifndef _WIN32 #ifndef _WIN32
int m_fd = -1; int m_fd = -1;
std::vector<std::pair<struct aiocb, SizeReturn>> m_queue; std::vector<std::pair<struct aiocb, SizeReturn>> m_queue;
@ -25,6 +23,7 @@ class AsyncIO
#endif #endif
void _waitForOperation(size_t qIdx) const; void _waitForOperation(size_t qIdx) const;
size_t m_maxBlock = 0; size_t m_maxBlock = 0;
public: public:
AsyncIO() = default; AsyncIO() = default;
AsyncIO(SystemStringView filename, bool truncate = false); AsyncIO(SystemStringView filename, bool truncate = false);
@ -46,5 +45,4 @@ public:
#endif #endif
}; };
} } // namespace kabufuda

View File

@ -2,15 +2,12 @@
#include "Constants.hpp" #include "Constants.hpp"
namespace kabufuda namespace kabufuda {
{ class BlockAllocationTable {
class BlockAllocationTable
{
friend class Card; friend class Card;
#pragma pack(push, 4) #pragma pack(push, 4)
union { union {
struct struct {
{
uint16_t m_checksum; uint16_t m_checksum;
uint16_t m_checksumInv; uint16_t m_checksumInv;
uint16_t m_updateCounter; uint16_t m_updateCounter;
@ -37,4 +34,4 @@ public:
uint16_t allocateBlocks(uint16_t count, uint16_t maxBlocks); uint16_t allocateBlocks(uint16_t count, uint16_t maxBlocks);
uint16_t numFreeBlocks() const { return m_freeBlocks; } uint16_t numFreeBlocks() const { return m_freeBlocks; }
}; };
} } // namespace kabufuda

View File

@ -13,30 +13,27 @@
#define CARD_FILENAME_MAX 32 #define CARD_FILENAME_MAX 32
#define CARD_ICON_MAX 8 #define CARD_ICON_MAX 8
namespace kabufuda namespace kabufuda {
{
class FileHandle class FileHandle {
{
friend class Card; friend class Card;
uint32_t idx = -1; uint32_t idx = -1;
int32_t offset = 0; int32_t offset = 0;
FileHandle(uint32_t idx) : idx(idx) {} FileHandle(uint32_t idx) : idx(idx) {}
public: public:
FileHandle() = default; FileHandle() = default;
uint32_t getFileNo() const { return idx; } uint32_t getFileNo() const { return idx; }
operator bool() const { return getFileNo() != -1; } operator bool() const { return getFileNo() != -1; }
}; };
struct ProbeResults struct ProbeResults {
{
ECardResult x0_error; ECardResult x0_error;
uint32_t x4_cardSize; /* in megabits */ uint32_t x4_cardSize; /* in megabits */
uint32_t x8_sectorSize; /* in bytes */ uint32_t x8_sectorSize; /* in bytes */
}; };
struct CardStat struct CardStat {
{
/* read-only (Set by Card::getStatus) */ /* read-only (Set by Card::getStatus) */
char x0_fileName[CARD_FILENAME_MAX]; char x0_fileName[CARD_FILENAME_MAX];
uint32_t x20_length; uint32_t x20_length;
@ -64,13 +61,11 @@ struct CardStat
EImageFormat GetBannerFormat() const { return EImageFormat(x2e_bannerFormat & 0x3); } EImageFormat GetBannerFormat() const { return EImageFormat(x2e_bannerFormat & 0x3); }
void SetBannerFormat(EImageFormat fmt) { x2e_bannerFormat = (x2e_bannerFormat & ~0x3) | uint8_t(fmt); } void SetBannerFormat(EImageFormat fmt) { x2e_bannerFormat = (x2e_bannerFormat & ~0x3) | uint8_t(fmt); }
EImageFormat GetIconFormat(int idx) const { return EImageFormat((x34_iconFormat >> (idx * 2)) & 0x3); } EImageFormat GetIconFormat(int idx) const { return EImageFormat((x34_iconFormat >> (idx * 2)) & 0x3); }
void SetIconFormat(EImageFormat fmt, int idx) void SetIconFormat(EImageFormat fmt, int idx) {
{
x34_iconFormat &= ~(0x3 << (idx * 2)); x34_iconFormat &= ~(0x3 << (idx * 2));
x34_iconFormat |= uint16_t(fmt) << (idx * 2); x34_iconFormat |= uint16_t(fmt) << (idx * 2);
} }
void SetIconSpeed(EAnimationSpeed sp, int idx) void SetIconSpeed(EAnimationSpeed sp, int idx) {
{
x36_iconSpeed &= ~(0x3 << (idx * 2)); x36_iconSpeed &= ~(0x3 << (idx * 2));
x36_iconSpeed |= uint16_t(sp) << (idx * 2); x36_iconSpeed |= uint16_t(sp) << (idx * 2);
} }
@ -80,11 +75,9 @@ struct CardStat
void SetCommentAddr(uint32_t addr) { x38_commentAddr = addr; } void SetCommentAddr(uint32_t addr) { x38_commentAddr = addr; }
}; };
class Card class Card {
{
#pragma pack(push, 4) #pragma pack(push, 4)
struct CardHeader struct CardHeader {
{
uint8_t m_serial[12]; uint8_t m_serial[12];
uint64_t m_formatTime; uint64_t m_formatTime;
int32_t m_sramBias; int32_t m_sramBias;
@ -435,5 +428,4 @@ public:
operator bool() const { return getError() == ECardResult::READY; } operator bool() const { return getError() == ECardResult::READY; }
}; };
} } // namespace kabufuda

View File

@ -3,8 +3,7 @@
#include <stdint.h> #include <stdint.h>
#include "Util.hpp" #include "Util.hpp"
namespace kabufuda namespace kabufuda {
{
uint32_t constexpr BlockSize = 0x2000; uint32_t constexpr BlockSize = 0x2000;
uint32_t constexpr MaxFiles = 127; uint32_t constexpr MaxFiles = 127;
uint32_t constexpr FSTBlocks = 5; uint32_t constexpr FSTBlocks = 5;
@ -14,8 +13,7 @@ uint32_t constexpr BATSize = 0xFFB;
/** /**
* @brief The EPermissions enum * @brief The EPermissions enum
*/ */
enum class EPermissions : uint8_t enum class EPermissions : uint8_t {
{
Public = (1 << 2), Public = (1 << 2),
NoCopy = (1 << 3), NoCopy = (1 << 3),
NoMove = (1 << 4), NoMove = (1 << 4),
@ -24,48 +22,35 @@ enum class EPermissions : uint8_t
}; };
ENABLE_BITWISE_ENUM(EPermissions) ENABLE_BITWISE_ENUM(EPermissions)
enum class EImageFormat : uint8_t enum class EImageFormat : uint8_t {
{
None, None,
C8, C8,
RGB5A3, RGB5A3,
}; };
enum class EAnimationType enum class EAnimationType {
{
Loop = 0, Loop = 0,
Bounce = 2, Bounce = 2,
}; };
enum class EAnimationSpeed enum class EAnimationSpeed {
{
End, End,
Fast, Fast,
Middle, Middle,
Slow, Slow,
}; };
enum class SeekOrigin enum class SeekOrigin { Begin, Current, End };
{
Begin,
Current,
End
};
/** /**
* @brief The ECardSlot enum * @brief The ECardSlot enum
*/ */
enum class ECardSlot : uint16_t enum class ECardSlot : uint16_t { SlotA, SlotB };
{
SlotA,
SlotB
};
/** /**
* @brief The ECardSize enum * @brief The ECardSize enum
*/ */
enum class ECardSize : uint16_t enum class ECardSize : uint16_t {
{
Card59Mb = 0x04, Card59Mb = 0x04,
Card123Mb = 0x08, Card123Mb = 0x08,
Card251Mb = 0x10, Card251Mb = 0x10,
@ -82,10 +67,8 @@ static constexpr uint32_t IconHeight = 32;
/** /**
* @brief The EEncoding enum * @brief The EEncoding enum
*/ */
enum class EEncoding : uint16_t enum class EEncoding : uint16_t {
{
ASCII, /**< Standard ASCII Encoding */ ASCII, /**< Standard ASCII Encoding */
SJIS /**< SJIS Encoding for japanese */ SJIS /**< SJIS Encoding for japanese */
}; };
} } // namespace kabufuda

View File

@ -2,15 +2,12 @@
#include "File.hpp" #include "File.hpp"
namespace kabufuda namespace kabufuda {
{ class Directory {
class Directory
{
friend class Card; friend class Card;
#pragma pack(push, 4) #pragma pack(push, 4)
union { union {
struct struct {
{
File m_files[MaxFiles]; File m_files[MaxFiles];
uint8_t __padding[0x3a]; uint8_t __padding[0x3a];
uint16_t m_updateCounter; uint16_t m_updateCounter;
@ -38,5 +35,4 @@ public:
File* getFile(uint32_t idx); File* getFile(uint32_t idx);
int32_t indexForFile(File* f); int32_t indexForFile(File* f);
}; };
} } // namespace kabufuda

View File

@ -2,17 +2,14 @@
#include "Constants.hpp" #include "Constants.hpp"
namespace kabufuda namespace kabufuda {
{ class File {
class File
{
friend class IFileHandle; friend class IFileHandle;
friend class Directory; friend class Directory;
friend class Card; friend class Card;
#pragma pack(push, 4) #pragma pack(push, 4)
union { union {
struct struct {
{
uint8_t m_game[4]; uint8_t m_game[4];
uint8_t m_maker[2]; uint8_t m_maker[2];
uint8_t m_reserved; uint8_t m_reserved;
@ -41,5 +38,4 @@ public:
File(const char* filename); File(const char* filename);
~File() = default; ~File() = default;
}; };
} } // namespace kabufuda

View File

@ -25,25 +25,22 @@ must not be misrepresented as being the original software.
distribution. distribution.
-------------------------------------------------------------*/ -------------------------------------------------------------*/
namespace kabufuda namespace kabufuda {
{ #pragma pack(push, 1)
#pragma pack(push,1) union SRAMFlags {
union SRAMFlags
{
uint8_t Hex; uint8_t Hex;
struct struct {
{
uint8_t : 2; uint8_t : 2;
uint8_t sound : 1; // Audio settings; 0 = Mono, 1 = Stereo uint8_t sound : 1; // Audio settings; 0 = Mono, 1 = Stereo
uint8_t initialized : 1; // if 0, displays prompt to set language on boot and asks user to set options and time/date uint8_t initialized : 1; // if 0, displays prompt to set language on boot and asks user to set options and time/date
uint8_t : 2; uint8_t : 2;
uint8_t boot_menu : 1; // if 1, skips logo animation and boots into the system menu regardless of if there is a disc inserted uint8_t boot_menu : 1; // if 1, skips logo animation and boots into the system menu regardless of if there is a
// disc inserted
uint8_t progressive : 1; // if 1, automatically displays Progressive Scan prompt in games that support it uint8_t progressive : 1; // if 1, automatically displays Progressive Scan prompt in games that support it
}; };
}; };
union SRAM union SRAM {
{
uint8_t p_SRAM[64]; uint8_t p_SRAM[64];
struct // Stored configuration value from the system SRAM area struct // Stored configuration value from the system SRAM area
{ {
@ -70,5 +67,4 @@ union SRAM
#pragma pack(pop) #pragma pack(pop)
extern const SRAM g_SRAM; extern const SRAM g_SRAM;
} } // namespace kabufuda

View File

@ -39,42 +39,35 @@
#ifndef ENABLE_BITWISE_ENUM #ifndef ENABLE_BITWISE_ENUM
#define ENABLE_BITWISE_ENUM(type) \ #define ENABLE_BITWISE_ENUM(type) \
constexpr type operator|(type a, type b) \ constexpr type operator|(type a, type b) { \
{ \
using T = std::underlying_type_t<type>; \ using T = std::underlying_type_t<type>; \
return type(static_cast<T>(a) | static_cast<T>(b)); \ return type(static_cast<T>(a) | static_cast<T>(b)); \
} \ } \
constexpr type operator&(type a, type b) \ constexpr type operator&(type a, type b) { \
{ \
using T = std::underlying_type_t<type>; \ using T = std::underlying_type_t<type>; \
return type(static_cast<T>(a) & static_cast<T>(b)); \ return type(static_cast<T>(a) & static_cast<T>(b)); \
} \ } \
inline type& operator|=(type& a, const type& b) \ inline type& operator|=(type& a, const type& b) { \
{ \
using T = std::underlying_type_t<type>; \ using T = std::underlying_type_t<type>; \
a = type(static_cast<T>(a) | static_cast<T>(b)); \ a = type(static_cast<T>(a) | static_cast<T>(b)); \
return a; \ return a; \
} \ } \
inline type& operator&=(type& a, const type& b) \ inline type& operator&=(type& a, const type& b) { \
{ \
using T = std::underlying_type_t<type>; \ using T = std::underlying_type_t<type>; \
a = type(static_cast<T>(a) & static_cast<T>(b)); \ a = type(static_cast<T>(a) & static_cast<T>(b)); \
return a; \ return a; \
} \ } \
inline type operator~(const type& key) \ inline type operator~(const type& key) { \
{ \
using T = std::underlying_type_t<type>; \ using T = std::underlying_type_t<type>; \
return type(~static_cast<T>(key)); \ return type(~static_cast<T>(key)); \
} }
#endif #endif
namespace kabufuda namespace kabufuda {
{
/* Type-sensitive byte swappers */ /* Type-sensitive byte swappers */
template <typename T> template <typename T>
static inline T bswap16(T val) static inline T bswap16(T val) {
{
#if __GNUC__ #if __GNUC__
return __builtin_bswap16(val); return __builtin_bswap16(val);
#elif _WIN32 #elif _WIN32
@ -85,8 +78,7 @@ static inline T bswap16(T val)
} }
template <typename T> template <typename T>
static inline T bswap32(T val) static inline T bswap32(T val) {
{
#if __GNUC__ #if __GNUC__
return __builtin_bswap32(val); return __builtin_bswap32(val);
#elif _WIN32 #elif _WIN32
@ -99,8 +91,7 @@ static inline T bswap32(T val)
} }
template <typename T> template <typename T>
static inline T bswap64(T val) static inline T bswap64(T val) {
{
#if __GNUC__ #if __GNUC__
return __builtin_bswap64(val); return __builtin_bswap64(val);
#elif _WIN32 #elif _WIN32
@ -120,13 +111,11 @@ static inline int32_t SBig(int32_t val) { return bswap32(val); }
static inline uint32_t SBig(uint32_t val) { return bswap32(val); } static inline uint32_t SBig(uint32_t val) { return bswap32(val); }
static inline int64_t SBig(int64_t val) { return bswap64(val); } static inline int64_t SBig(int64_t val) { return bswap64(val); }
static inline uint64_t SBig(uint64_t val) { return bswap64(val); } static inline uint64_t SBig(uint64_t val) { return bswap64(val); }
static inline float SBig(float val) static inline float SBig(float val) {
{
int32_t ival = bswap32(*((int32_t*)(&val))); int32_t ival = bswap32(*((int32_t*)(&val)));
return *((float*)(&ival)); return *((float*)(&ival));
} }
static inline double SBig(double val) static inline double SBig(double val) {
{
int64_t ival = bswap64(*((int64_t*)(&val))); int64_t ival = bswap64(*((int64_t*)(&val)));
return *((double*)(&ival)); return *((double*)(&ival));
} }
@ -152,13 +141,11 @@ static inline int32_t SLittle(int32_t val) { return bswap32(val); }
static inline uint32_t SLittle(uint32_t val) { return bswap32(val); } static inline uint32_t SLittle(uint32_t val) { return bswap32(val); }
static inline int64_t SLittle(int64_t val) { return bswap64(val); } static inline int64_t SLittle(int64_t val) { return bswap64(val); }
static inline uint64_t SLittle(uint64_t val) { return bswap64(val); } static inline uint64_t SLittle(uint64_t val) { return bswap64(val); }
static inline float SLittle(float val) static inline float SLittle(float val) {
{
int32_t ival = bswap32(*((int32_t*)(&val))); int32_t ival = bswap32(*((int32_t*)(&val)));
return *((float*)(&ival)); return *((float*)(&ival));
} }
static inline double SLittle(double val) static inline double SLittle(double val) {
{
int64_t ival = bswap64(*((int64_t*)(&val))); int64_t ival = bswap64(*((int64_t*)(&val)));
return *((double*)(&ival)); return *((double*)(&ival));
} }
@ -186,8 +173,7 @@ typedef std::wstring SystemString;
typedef std::wstring_view SystemStringView; typedef std::wstring_view SystemStringView;
static inline void ToLower(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), towlower); } static inline void ToLower(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), towlower); }
static inline void ToUpper(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), towupper); } static inline void ToUpper(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), towupper); }
class SystemUTF8Conv class SystemUTF8Conv {
{
std::string m_utf8; std::string m_utf8;
public: public:
@ -197,8 +183,7 @@ public:
std::string operator+(std::string_view other) const { return m_utf8 + other.data(); } std::string operator+(std::string_view other) const { return m_utf8 + other.data(); }
}; };
inline std::string operator+(std::string_view lhs, const SystemUTF8Conv& rhs) { return std::string(lhs) + rhs.c_str(); } inline std::string operator+(std::string_view lhs, const SystemUTF8Conv& rhs) { return std::string(lhs) + rhs.c_str(); }
class SystemStringConv class SystemStringConv {
{
std::wstring m_sys; std::wstring m_sys;
public: public:
@ -207,7 +192,9 @@ public:
const SystemChar* c_str() const { return m_sys.c_str(); } const SystemChar* c_str() const { return m_sys.c_str(); }
std::wstring operator+(const std::wstring_view other) const { return m_sys + other.data(); } std::wstring operator+(const std::wstring_view other) const { return m_sys + other.data(); }
}; };
inline std::wstring operator+(const std::wstring_view lhs, const SystemStringConv& rhs) { return std::wstring(lhs) + rhs.c_str(); } inline std::wstring operator+(const std::wstring_view lhs, const SystemStringConv& rhs) {
return std::wstring(lhs) + rhs.c_str();
}
#ifndef _SYS_STR #ifndef _SYS_STR
#define _SYS_STR(val) L##val #define _SYS_STR(val) L##val
#endif #endif
@ -219,8 +206,7 @@ typedef std::string SystemString;
typedef std::string_view SystemStringView; typedef std::string_view SystemStringView;
static inline void ToLower(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), tolower); } static inline void ToLower(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), tolower); }
static inline void ToUpper(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), toupper); } static inline void ToUpper(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), toupper); }
class SystemUTF8Conv class SystemUTF8Conv {
{
std::string_view m_utf8; std::string_view m_utf8;
public: public:
@ -230,8 +216,7 @@ public:
std::string operator+(std::string_view other) const { return std::string(m_utf8) + other.data(); } std::string operator+(std::string_view other) const { return std::string(m_utf8) + other.data(); }
}; };
inline std::string operator+(std::string_view lhs, const SystemUTF8Conv& rhs) { return std::string(lhs) + rhs.c_str(); } inline std::string operator+(std::string_view lhs, const SystemUTF8Conv& rhs) { return std::string(lhs) + rhs.c_str(); }
class SystemStringConv class SystemStringConv {
{
SystemStringView m_sys; SystemStringView m_sys;
public: public:
@ -240,7 +225,9 @@ public:
const SystemChar* c_str() const { return m_sys.data(); } const SystemChar* c_str() const { return m_sys.data(); }
std::string operator+(std::string_view other) const { return std::string(m_sys) + other.data(); } std::string operator+(std::string_view other) const { return std::string(m_sys) + other.data(); }
}; };
inline std::string operator+(std::string_view lhs, const SystemStringConv& rhs) { return std::string(lhs) + rhs.c_str(); } inline std::string operator+(std::string_view lhs, const SystemStringConv& rhs) {
return std::string(lhs) + rhs.c_str();
}
#ifndef _SYS_STR #ifndef _SYS_STR
#define _SYS_STR(val) val #define _SYS_STR(val) val
#endif #endif
@ -250,22 +237,18 @@ typedef struct stat Sstat;
uint64_t getGCTime(); uint64_t getGCTime();
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG) #if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
#endif #endif
#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR) #if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
#endif #endif
static inline int Stat(const SystemChar* path, Sstat* statOut) static inline int Stat(const SystemChar* path, Sstat* statOut) {
{
#if CARD_UCS2 #if CARD_UCS2
size_t pos; size_t pos;
for (pos = 0; pos < 3 && path[pos] != L'\0'; ++pos) for (pos = 0; pos < 3 && path[pos] != L'\0'; ++pos) {}
{ if (pos == 2 && path[1] == L':') {
}
if (pos == 2 && path[1] == L':')
{
SystemChar fixPath[4] = {path[0], L':', L'/', L'\0'}; SystemChar fixPath[4] = {path[0], L':', L'/', L'\0'};
return _wstat(fixPath, statOut); return _wstat(fixPath, statOut);
} }
@ -286,8 +269,7 @@ void calculateChecksumBE(const uint16_t* data, size_t len, uint16_t* checksum, u
#undef NOFILE #undef NOFILE
enum class ECardResult enum class ECardResult {
{
CRC_MISMATCH = -1003, /* Extension enum for Retro's CRC check */ CRC_MISMATCH = -1003, /* Extension enum for Retro's CRC check */
FATAL_ERROR = -128, FATAL_ERROR = -128,
ENCODING = -13, ENCODING = -13,
@ -303,5 +285,4 @@ enum class ECardResult
BUSY = -1, BUSY = -1,
READY = 0 READY = 0
}; };
} } // namespace kabufuda

View File

@ -2,9 +2,7 @@
#include <string> #include <string>
namespace kabufuda namespace kabufuda {
{
std::string WideToUTF8(std::wstring_view src); std::string WideToUTF8(std::wstring_view src);
std::wstring UTF8ToWide(std::string_view src); std::wstring UTF8ToWide(std::string_view src);
} } // namespace kabufuda

View File

@ -8,5 +8,4 @@
#endif #endif
#include "windows.h" #include "windows.h"
void* memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen); void* memmem(const void* haystack, size_t hlen, const void* needle, size_t nlen);

View File

@ -1,34 +1,27 @@
#include "kabufuda/AsyncIO.hpp" #include "kabufuda/AsyncIO.hpp"
namespace kabufuda namespace kabufuda {
{
AsyncIO::AsyncIO(SystemStringView filename, bool truncate) AsyncIO::AsyncIO(SystemStringView filename, bool truncate) {
{
m_fd = open(filename.data(), O_RDWR | O_CREAT | (truncate ? O_TRUNC : 0)); m_fd = open(filename.data(), O_RDWR | O_CREAT | (truncate ? O_TRUNC : 0));
} }
AsyncIO::~AsyncIO() AsyncIO::~AsyncIO() {
{ if (*this) {
if (*this)
{
aio_cancel(m_fd, nullptr); aio_cancel(m_fd, nullptr);
close(m_fd); close(m_fd);
} }
} }
AsyncIO::AsyncIO(AsyncIO&& other) AsyncIO::AsyncIO(AsyncIO&& other) {
{
m_fd = other.m_fd; m_fd = other.m_fd;
other.m_fd = -1; other.m_fd = -1;
m_queue = std::move(other.m_queue); m_queue = std::move(other.m_queue);
m_maxBlock = other.m_maxBlock; m_maxBlock = other.m_maxBlock;
} }
AsyncIO& AsyncIO::operator=(AsyncIO&& other) AsyncIO& AsyncIO::operator=(AsyncIO&& other) {
{ if (*this) {
if (*this)
{
aio_cancel(m_fd, nullptr); aio_cancel(m_fd, nullptr);
close(m_fd); close(m_fd);
} }
@ -39,8 +32,7 @@ AsyncIO& AsyncIO::operator=(AsyncIO&& other)
return *this; return *this;
} }
void AsyncIO::_waitForOperation(size_t qIdx) const void AsyncIO::_waitForOperation(size_t qIdx) const {
{
auto& aio = const_cast<AsyncIO*>(this)->m_queue[qIdx]; auto& aio = const_cast<AsyncIO*>(this)->m_queue[qIdx];
if (aio.first.aio_fildes == 0) if (aio.first.aio_fildes == 0)
return; return;
@ -52,11 +44,9 @@ void AsyncIO::_waitForOperation(size_t qIdx) const
aio.first.aio_fildes = 0; aio.first.aio_fildes = 0;
} }
bool AsyncIO::asyncRead(size_t qIdx, void* buf, size_t length, off_t offset) bool AsyncIO::asyncRead(size_t qIdx, void* buf, size_t length, off_t offset) {
{
struct aiocb& aio = m_queue[qIdx].first; struct aiocb& aio = m_queue[qIdx].first;
if (aio.aio_fildes) if (aio.aio_fildes) {
{
#ifndef NDEBUG #ifndef NDEBUG
fprintf(stderr, "WARNING: synchronous kabufuda fallback, check access polling\n"); fprintf(stderr, "WARNING: synchronous kabufuda fallback, check access polling\n");
#endif #endif
@ -71,11 +61,9 @@ bool AsyncIO::asyncRead(size_t qIdx, void* buf, size_t length, off_t offset)
return aio_read(&aio) == 0; return aio_read(&aio) == 0;
} }
bool AsyncIO::asyncWrite(size_t qIdx, const void* buf, size_t length, off_t offset) bool AsyncIO::asyncWrite(size_t qIdx, const void* buf, size_t length, off_t offset) {
{
struct aiocb& aio = m_queue[qIdx].first; struct aiocb& aio = m_queue[qIdx].first;
if (aio.aio_fildes) if (aio.aio_fildes) {
{
#ifndef NDEBUG #ifndef NDEBUG
fprintf(stderr, "WARNING: synchronous kabufuda fallback, check access polling\n"); fprintf(stderr, "WARNING: synchronous kabufuda fallback, check access polling\n");
#endif #endif
@ -90,17 +78,14 @@ bool AsyncIO::asyncWrite(size_t qIdx, const void* buf, size_t length, off_t offs
return aio_write(&aio) == 0; return aio_write(&aio) == 0;
} }
ECardResult AsyncIO::pollStatus(size_t qIdx, SizeReturn* szRet) const ECardResult AsyncIO::pollStatus(size_t qIdx, SizeReturn* szRet) const {
{
auto& aio = const_cast<AsyncIO*>(this)->m_queue[qIdx]; auto& aio = const_cast<AsyncIO*>(this)->m_queue[qIdx];
if (aio.first.aio_fildes == 0) if (aio.first.aio_fildes == 0) {
{
if (szRet) if (szRet)
*szRet = aio.second; *szRet = aio.second;
return ECardResult::READY; return ECardResult::READY;
} }
switch (aio_error(&aio.first)) switch (aio_error(&aio.first)) {
{
case 0: case 0:
aio.second = aio_return(&aio.first); aio.second = aio_return(&aio.first);
aio.first.aio_fildes = 0; aio.first.aio_fildes = 0;
@ -118,18 +103,14 @@ ECardResult AsyncIO::pollStatus(size_t qIdx, SizeReturn* szRet) const
} }
} }
ECardResult AsyncIO::pollStatus() const ECardResult AsyncIO::pollStatus() const {
{
ECardResult result = ECardResult::READY; ECardResult result = ECardResult::READY;
for (auto it = const_cast<AsyncIO*>(this)->m_queue.begin(); for (auto it = const_cast<AsyncIO*>(this)->m_queue.begin();
it != const_cast<AsyncIO*>(this)->m_queue.begin() + m_maxBlock; it != const_cast<AsyncIO*>(this)->m_queue.begin() + m_maxBlock; ++it) {
++it)
{
auto& aio = *it; auto& aio = *it;
if (aio.first.aio_fildes == 0) if (aio.first.aio_fildes == 0)
continue; continue;
switch (aio_error(&aio.first)) switch (aio_error(&aio.first)) {
{
case 0: case 0:
aio.second = aio_return(&aio.first); aio.second = aio_return(&aio.first);
aio.first.aio_fildes = 0; aio.first.aio_fildes = 0;
@ -151,11 +132,10 @@ ECardResult AsyncIO::pollStatus() const
return result; return result;
} }
void AsyncIO::waitForCompletion() const void AsyncIO::waitForCompletion() const {
{ for (size_t i = 0; i < m_maxBlock; ++i)
for (size_t i=0 ; i<m_maxBlock ; ++i)
_waitForOperation(i); _waitForOperation(i);
const_cast<AsyncIO*>(this)->m_maxBlock = 0; const_cast<AsyncIO*>(this)->m_maxBlock = 0;
} }
} } // namespace kabufuda

View File

@ -1,59 +1,48 @@
#include "kabufuda/AsyncIO.hpp" #include "kabufuda/AsyncIO.hpp"
namespace kabufuda namespace kabufuda {
{
#undef min #undef min
#undef max #undef max
static void ResetOverlapped(OVERLAPPED& aio, DWORD offset = 0) static void ResetOverlapped(OVERLAPPED& aio, DWORD offset = 0) {
{
aio.Internal = 0; aio.Internal = 0;
aio.InternalHigh = 0; aio.InternalHigh = 0;
aio.Offset = offset; aio.Offset = offset;
aio.OffsetHigh = 0; aio.OffsetHigh = 0;
} }
AsyncIO::AsyncIO(SystemStringView filename, bool truncate) AsyncIO::AsyncIO(SystemStringView filename, bool truncate) {
{
#if WINDOWS_STORE #if WINDOWS_STORE
CREATEFILE2_EXTENDED_PARAMETERS parms = {}; CREATEFILE2_EXTENDED_PARAMETERS parms = {};
parms.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); parms.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
parms.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; parms.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
parms.dwFileFlags = FILE_FLAG_OVERLAPPED; parms.dwFileFlags = FILE_FLAG_OVERLAPPED;
m_fh = CreateFile2(filename.data(), GENERIC_READ | GENERIC_WRITE, m_fh = CreateFile2(filename.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
truncate ? CREATE_ALWAYS : OPEN_ALWAYS, &parms); truncate ? CREATE_ALWAYS : OPEN_ALWAYS, &parms);
#else #else
m_fh = CreateFileW(filename.data(), GENERIC_READ | GENERIC_WRITE, m_fh = CreateFileW(filename.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
FILE_SHARE_READ | FILE_SHARE_WRITE, truncate ? CREATE_ALWAYS : OPEN_ALWAYS, FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL, nullptr);
nullptr, truncate ? CREATE_ALWAYS : OPEN_ALWAYS,
FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL, nullptr);
#endif #endif
} }
AsyncIO::~AsyncIO() AsyncIO::~AsyncIO() {
{ if (*this) {
if (*this)
{
if (CancelIoEx(m_fh, nullptr)) if (CancelIoEx(m_fh, nullptr))
waitForCompletion(); waitForCompletion();
CloseHandle(m_fh); CloseHandle(m_fh);
} }
} }
AsyncIO::AsyncIO(AsyncIO&& other) AsyncIO::AsyncIO(AsyncIO&& other) {
{
m_fh = other.m_fh; m_fh = other.m_fh;
other.m_fh = INVALID_HANDLE_VALUE; other.m_fh = INVALID_HANDLE_VALUE;
m_queue = std::move(other.m_queue); m_queue = std::move(other.m_queue);
m_maxBlock = other.m_maxBlock; m_maxBlock = other.m_maxBlock;
} }
AsyncIO& AsyncIO::operator=(AsyncIO&& other) AsyncIO& AsyncIO::operator=(AsyncIO&& other) {
{ if (*this) {
if (*this)
{
if (CancelIoEx(m_fh, nullptr)) if (CancelIoEx(m_fh, nullptr))
waitForCompletion(); waitForCompletion();
CloseHandle(m_fh); CloseHandle(m_fh);
@ -65,8 +54,7 @@ AsyncIO& AsyncIO::operator=(AsyncIO&& other)
return *this; return *this;
} }
void AsyncIO::_waitForOperation(size_t qIdx) const void AsyncIO::_waitForOperation(size_t qIdx) const {
{
auto& aio = const_cast<AsyncIO*>(this)->m_queue[qIdx]; auto& aio = const_cast<AsyncIO*>(this)->m_queue[qIdx];
if (aio.first.hEvent == 0) if (aio.first.hEvent == 0)
return; return;
@ -75,18 +63,14 @@ void AsyncIO::_waitForOperation(size_t qIdx) const
aio.first.hEvent = 0; aio.first.hEvent = 0;
} }
bool AsyncIO::asyncRead(size_t qIdx, void* buf, size_t length, off_t offset) bool AsyncIO::asyncRead(size_t qIdx, void* buf, size_t length, off_t offset) {
{
OVERLAPPED& aio = m_queue[qIdx].first; OVERLAPPED& aio = m_queue[qIdx].first;
if (aio.hEvent) if (aio.hEvent) {
{
#ifndef NDEBUG #ifndef NDEBUG
fprintf(stderr, "WARNING: synchronous kabufuda fallback, check access polling\n"); fprintf(stderr, "WARNING: synchronous kabufuda fallback, check access polling\n");
#endif #endif
_waitForOperation(qIdx); _waitForOperation(qIdx);
} } else {
else
{
aio.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); aio.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
} }
ResetOverlapped(aio, DWORD(offset)); ResetOverlapped(aio, DWORD(offset));
@ -95,18 +79,14 @@ bool AsyncIO::asyncRead(size_t qIdx, void* buf, size_t length, off_t offset)
return res == TRUE || GetLastError() == ERROR_IO_PENDING; return res == TRUE || GetLastError() == ERROR_IO_PENDING;
} }
bool AsyncIO::asyncWrite(size_t qIdx, const void* buf, size_t length, off_t offset) bool AsyncIO::asyncWrite(size_t qIdx, const void* buf, size_t length, off_t offset) {
{
OVERLAPPED& aio = m_queue[qIdx].first; OVERLAPPED& aio = m_queue[qIdx].first;
if (aio.hEvent) if (aio.hEvent) {
{
#ifndef NDEBUG #ifndef NDEBUG
fprintf(stderr, "WARNING: synchronous kabufuda fallback, check access polling\n"); fprintf(stderr, "WARNING: synchronous kabufuda fallback, check access polling\n");
#endif #endif
_waitForOperation(qIdx); _waitForOperation(qIdx);
} } else {
else
{
aio.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); aio.hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
} }
ResetOverlapped(aio, DWORD(offset)); ResetOverlapped(aio, DWORD(offset));
@ -115,61 +95,44 @@ bool AsyncIO::asyncWrite(size_t qIdx, const void* buf, size_t length, off_t offs
return res == TRUE || GetLastError() == ERROR_IO_PENDING; return res == TRUE || GetLastError() == ERROR_IO_PENDING;
} }
ECardResult AsyncIO::pollStatus(size_t qIdx, SizeReturn* szRet) const ECardResult AsyncIO::pollStatus(size_t qIdx, SizeReturn* szRet) const {
{
auto& aio = const_cast<AsyncIO*>(this)->m_queue[qIdx]; auto& aio = const_cast<AsyncIO*>(this)->m_queue[qIdx];
if (aio.first.hEvent == 0) if (aio.first.hEvent == 0) {
{
if (szRet) if (szRet)
*szRet = aio.second; *szRet = aio.second;
return ECardResult::READY; return ECardResult::READY;
} }
if (GetOverlappedResult(m_fh, &aio.first, &aio.second, FALSE)) if (GetOverlappedResult(m_fh, &aio.first, &aio.second, FALSE)) {
{
CloseHandle(aio.first.hEvent); CloseHandle(aio.first.hEvent);
aio.first.hEvent = 0; aio.first.hEvent = 0;
if (szRet) if (szRet)
*szRet = aio.second; *szRet = aio.second;
return ECardResult::READY; return ECardResult::READY;
} } else {
else if (GetLastError() == ERROR_IO_INCOMPLETE) {
{
if (GetLastError() == ERROR_IO_INCOMPLETE)
{
return ECardResult::BUSY; return ECardResult::BUSY;
} } else {
else
{
_waitForOperation(qIdx); _waitForOperation(qIdx);
return ECardResult::IOERROR; return ECardResult::IOERROR;
} }
} }
} }
ECardResult AsyncIO::pollStatus() const ECardResult AsyncIO::pollStatus() const {
{
ECardResult result = ECardResult::READY; ECardResult result = ECardResult::READY;
for (auto it = const_cast<AsyncIO*>(this)->m_queue.begin(); for (auto it = const_cast<AsyncIO*>(this)->m_queue.begin();
it != const_cast<AsyncIO*>(this)->m_queue.begin() + m_maxBlock; it != const_cast<AsyncIO*>(this)->m_queue.begin() + m_maxBlock; ++it) {
++it)
{
auto& aio = *it; auto& aio = *it;
if (aio.first.hEvent == 0) if (aio.first.hEvent == 0)
continue; continue;
if (GetOverlappedResult(m_fh, &aio.first, &aio.second, FALSE)) if (GetOverlappedResult(m_fh, &aio.first, &aio.second, FALSE)) {
{
CloseHandle(aio.first.hEvent); CloseHandle(aio.first.hEvent);
aio.first.hEvent = 0; aio.first.hEvent = 0;
} } else {
else if (GetLastError() == ERROR_IO_INCOMPLETE) {
{
if (GetLastError() == ERROR_IO_INCOMPLETE)
{
if (result > ECardResult::BUSY) if (result > ECardResult::BUSY)
result = ECardResult::BUSY; result = ECardResult::BUSY;
} } else {
else
{
_waitForOperation(it - m_queue.cbegin()); _waitForOperation(it - m_queue.cbegin());
if (result > ECardResult::IOERROR) if (result > ECardResult::IOERROR)
result = ECardResult::IOERROR; result = ECardResult::IOERROR;
@ -181,11 +144,10 @@ ECardResult AsyncIO::pollStatus() const
return result; return result;
} }
void AsyncIO::waitForCompletion() const void AsyncIO::waitForCompletion() const {
{ for (size_t i = 0; i < m_maxBlock; ++i)
for (size_t i=0 ; i<m_maxBlock ; ++i)
_waitForOperation(i); _waitForOperation(i);
const_cast<AsyncIO*>(this)->m_maxBlock = 0; const_cast<AsyncIO*>(this)->m_maxBlock = 0;
} }
} } // namespace kabufuda

View File

@ -2,10 +2,8 @@
#include "kabufuda/Util.hpp" #include "kabufuda/Util.hpp"
#include <vector> #include <vector>
namespace kabufuda namespace kabufuda {
{ void BlockAllocationTable::swapEndian() {
void BlockAllocationTable::swapEndian()
{
m_checksum = SBig(m_checksum); m_checksum = SBig(m_checksum);
m_checksumInv = SBig(m_checksumInv); m_checksumInv = SBig(m_checksumInv);
m_updateCounter = SBig(m_updateCounter); m_updateCounter = SBig(m_updateCounter);
@ -14,15 +12,13 @@ void BlockAllocationTable::swapEndian()
std::for_each(std::begin(m_map), std::end(m_map), [](uint16_t& val) { val = SBig(val); }); std::for_each(std::begin(m_map), std::end(m_map), [](uint16_t& val) { val = SBig(val); });
} }
void BlockAllocationTable::updateChecksum() void BlockAllocationTable::updateChecksum() {
{
swapEndian(); swapEndian();
calculateChecksumBE(reinterpret_cast<uint16_t*>(__raw + 4), 0xFFE, &m_checksum, &m_checksumInv); calculateChecksumBE(reinterpret_cast<uint16_t*>(__raw + 4), 0xFFE, &m_checksum, &m_checksumInv);
swapEndian(); swapEndian();
} }
bool BlockAllocationTable::valid() const bool BlockAllocationTable::valid() const {
{
uint16_t ckSum, ckSumInv; uint16_t ckSum, ckSumInv;
const_cast<BlockAllocationTable&>(*this).swapEndian(); const_cast<BlockAllocationTable&>(*this).swapEndian();
calculateChecksumBE(reinterpret_cast<const uint16_t*>(__raw + 4), 0xFFE, &ckSum, &ckSumInv); calculateChecksumBE(reinterpret_cast<const uint16_t*>(__raw + 4), 0xFFE, &ckSum, &ckSumInv);
@ -31,26 +27,22 @@ bool BlockAllocationTable::valid() const
return res; return res;
} }
BlockAllocationTable::BlockAllocationTable(uint32_t blockCount) BlockAllocationTable::BlockAllocationTable(uint32_t blockCount) {
{
memset(__raw, 0, BlockSize); memset(__raw, 0, BlockSize);
m_freeBlocks = uint16_t(blockCount - FSTBlocks); m_freeBlocks = uint16_t(blockCount - FSTBlocks);
m_lastAllocated = 4; m_lastAllocated = 4;
updateChecksum(); updateChecksum();
} }
uint16_t BlockAllocationTable::getNextBlock(uint16_t block) const uint16_t BlockAllocationTable::getNextBlock(uint16_t block) const {
{
if ((block < FSTBlocks) || (block > (BATSize - FSTBlocks))) if ((block < FSTBlocks) || (block > (BATSize - FSTBlocks)))
return 0xFFFF; return 0xFFFF;
return m_map[block - FSTBlocks]; return m_map[block - FSTBlocks];
} }
uint16_t BlockAllocationTable::nextFreeBlock(uint16_t maxBlock, uint16_t startingBlock) const uint16_t BlockAllocationTable::nextFreeBlock(uint16_t maxBlock, uint16_t startingBlock) const {
{ if (m_freeBlocks > 0) {
if (m_freeBlocks > 0)
{
maxBlock = std::min(maxBlock, uint16_t(BATSize)); maxBlock = std::min(maxBlock, uint16_t(BATSize));
for (uint16_t i = startingBlock; i < maxBlock; ++i) for (uint16_t i = startingBlock; i < maxBlock; ++i)
if (m_map[i - FSTBlocks] == 0) if (m_map[i - FSTBlocks] == 0)
@ -64,16 +56,13 @@ uint16_t BlockAllocationTable::nextFreeBlock(uint16_t maxBlock, uint16_t startin
return 0xFFFF; return 0xFFFF;
} }
bool BlockAllocationTable::clear(uint16_t first, uint16_t count) bool BlockAllocationTable::clear(uint16_t first, uint16_t count) {
{
std::vector<uint16_t> blocks; std::vector<uint16_t> blocks;
while (first != 0xFFFF && first != 0) while (first != 0xFFFF && first != 0) {
{
blocks.push_back(first); blocks.push_back(first);
first = getNextBlock(first); first = getNextBlock(first);
} }
if (first > 0) if (first > 0) {
{
size_t length = blocks.size(); size_t length = blocks.size();
if (length != count) if (length != count)
return false; return false;
@ -86,18 +75,14 @@ bool BlockAllocationTable::clear(uint16_t first, uint16_t count)
return false; return false;
} }
uint16_t BlockAllocationTable::allocateBlocks(uint16_t count, uint16_t maxBlocks) uint16_t BlockAllocationTable::allocateBlocks(uint16_t count, uint16_t maxBlocks) {
{
uint16_t firstBlock = nextFreeBlock(maxBlocks - FSTBlocks, m_lastAllocated + 1); uint16_t firstBlock = nextFreeBlock(maxBlocks - FSTBlocks, m_lastAllocated + 1);
uint16_t freeBlock = firstBlock; uint16_t freeBlock = firstBlock;
if (freeBlock != 0xFFFF) if (freeBlock != 0xFFFF) {
{
uint16_t tmpCount = count; uint16_t tmpCount = count;
while ((count--) > 0 && freeBlock != 0xFFFF) while ((count--) > 0 && freeBlock != 0xFFFF) {
{
m_map[(freeBlock - FSTBlocks)] = 0xFFFF; m_map[(freeBlock - FSTBlocks)] = 0xFFFF;
if (count != 0) if (count != 0) {
{
m_map[(freeBlock - FSTBlocks)] = nextFreeBlock(maxBlocks - FSTBlocks, freeBlock + 1); m_map[(freeBlock - FSTBlocks)] = nextFreeBlock(maxBlocks - FSTBlocks, freeBlock + 1);
freeBlock = m_map[(freeBlock - FSTBlocks)]; freeBlock = m_map[(freeBlock - FSTBlocks)];
} }
@ -110,4 +95,4 @@ uint16_t BlockAllocationTable::allocateBlocks(uint16_t count, uint16_t maxBlocks
} }
return firstBlock; return firstBlock;
} }
} } // namespace kabufuda

View File

@ -5,18 +5,13 @@
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
namespace kabufuda namespace kabufuda {
{
#define ROUND_UP_8192(val) (((val) + 8191) & ~8191) #define ROUND_UP_8192(val) (((val) + 8191) & ~8191)
static void NullFileAccess() static void NullFileAccess() { fprintf(stderr, "Attempted to access null file\n"); }
{
fprintf(stderr, "Attempted to access null file\n");
}
void Card::CardHeader::_swapEndian() void Card::CardHeader::_swapEndian() {
{
m_formatTime = SBig(m_formatTime); m_formatTime = SBig(m_formatTime);
m_sramBias = SBig(m_sramBias); m_sramBias = SBig(m_sramBias);
m_sramLanguage = SBig(m_sramLanguage); m_sramLanguage = SBig(m_sramLanguage);
@ -31,8 +26,7 @@ void Card::CardHeader::_swapEndian()
Card::Card() { memset(__raw, 0xFF, BlockSize); } Card::Card() { memset(__raw, 0xFF, BlockSize); }
Card::Card(Card&& other) Card::Card(Card&& other) {
{
memmove(__raw, other.__raw, BlockSize); memmove(__raw, other.__raw, BlockSize);
m_filename = std::move(other.m_filename); m_filename = std::move(other.m_filename);
m_fileHandle = std::move(other.m_fileHandle); m_fileHandle = std::move(other.m_fileHandle);
@ -48,8 +42,7 @@ Card::Card(Card&& other)
memmove(m_maker, other.m_maker, 3); memmove(m_maker, other.m_maker, 3);
} }
Card& Card::operator=(Card&& other) Card& Card::operator=(Card&& other) {
{
close(); close();
memmove(__raw, other.__raw, BlockSize); memmove(__raw, other.__raw, BlockSize);
@ -69,8 +62,7 @@ Card& Card::operator=(Card&& other)
return *this; return *this;
} }
ECardResult Card::_pumpOpen() ECardResult Card::_pumpOpen() {
{
if (m_opened) if (m_opened)
return ECardResult::READY; return ECardResult::READY;
@ -78,8 +70,7 @@ ECardResult Card::_pumpOpen()
return ECardResult::NOCARD; return ECardResult::NOCARD;
ECardResult res = m_fileHandle.pollStatus(); ECardResult res = m_fileHandle.pollStatus();
if (res == ECardResult::READY) if (res == ECardResult::READY) {
{
m_ch._swapEndian(); m_ch._swapEndian();
m_maxBlock = m_ch.m_sizeMb * MbitToBlocks; m_maxBlock = m_ch.m_sizeMb * MbitToBlocks;
m_fileHandle.resizeQueue(m_maxBlock); m_fileHandle.resizeQueue(m_maxBlock);
@ -115,8 +106,7 @@ ECardResult Card::_pumpOpen()
return res; return res;
} }
Card::Card(const char* game, const char* maker) Card::Card(const char* game, const char* maker) {
{
memset(__raw, 0xFF, BlockSize); memset(__raw, 0xFF, BlockSize);
if (game && strlen(game) == 4) if (game && strlen(game) == 4)
memcpy(m_game, game, 4); memcpy(m_game, game, 4);
@ -124,13 +114,9 @@ Card::Card(const char* game, const char* maker)
memcpy(m_maker, maker, 2); memcpy(m_maker, maker, 2);
} }
Card::~Card() Card::~Card() { close(); }
{
close();
}
ECardResult Card::openFile(const char* filename, FileHandle& handleOut) ECardResult Card::openFile(const char* filename, FileHandle& handleOut) {
{
ECardResult openRes = _pumpOpen(); ECardResult openRes = _pumpOpen();
if (openRes != ECardResult::READY) if (openRes != ECardResult::READY)
return openRes; return openRes;
@ -140,16 +126,14 @@ ECardResult Card::openFile(const char* filename, FileHandle& handleOut)
if (!f || f->m_game[0] == 0xFF) if (!f || f->m_game[0] == 0xFF)
return ECardResult::NOFILE; return ECardResult::NOFILE;
int32_t idx = m_dirs[m_currentDir].indexForFile(f); int32_t idx = m_dirs[m_currentDir].indexForFile(f);
if (idx != -1) if (idx != -1) {
{
handleOut = FileHandle(idx); handleOut = FileHandle(idx);
return ECardResult::READY; return ECardResult::READY;
} }
return ECardResult::FATAL_ERROR; return ECardResult::FATAL_ERROR;
} }
ECardResult Card::openFile(uint32_t fileno, FileHandle& handleOut) ECardResult Card::openFile(uint32_t fileno, FileHandle& handleOut) {
{
ECardResult openRes = _pumpOpen(); ECardResult openRes = _pumpOpen();
if (openRes != ECardResult::READY) if (openRes != ECardResult::READY)
return openRes; return openRes;
@ -162,8 +146,7 @@ ECardResult Card::openFile(uint32_t fileno, FileHandle& handleOut)
return ECardResult::READY; return ECardResult::READY;
} }
void Card::_updateDirAndBat(const Directory& dir, const BlockAllocationTable& bat) void Card::_updateDirAndBat(const Directory& dir, const BlockAllocationTable& bat) {
{
m_currentDir = !m_currentDir; m_currentDir = !m_currentDir;
Directory& updateDir = m_dirs[m_currentDir]; Directory& updateDir = m_dirs[m_currentDir];
updateDir = dir; updateDir = dir;
@ -179,26 +162,21 @@ void Card::_updateDirAndBat(const Directory& dir, const BlockAllocationTable& ba
m_dirty = true; m_dirty = true;
} }
void Card::_updateChecksum() void Card::_updateChecksum() {
{
m_ch._swapEndian(); m_ch._swapEndian();
calculateChecksumBE(reinterpret_cast<uint16_t*>(__raw), 0xFE, &m_ch.m_checksum, &m_ch.m_checksumInv); calculateChecksumBE(reinterpret_cast<uint16_t*>(__raw), 0xFE, &m_ch.m_checksum, &m_ch.m_checksumInv);
m_ch._swapEndian(); m_ch._swapEndian();
} }
File* Card::_fileFromHandle(const FileHandle& fh) const File* Card::_fileFromHandle(const FileHandle& fh) const {
{ if (!fh) {
if (!fh)
{
NullFileAccess(); NullFileAccess();
return nullptr; return nullptr;
} }
return const_cast<Directory&>(m_dirs[m_currentDir]).getFile(fh.idx); return const_cast<Directory&>(m_dirs[m_currentDir]).getFile(fh.idx);
} }
ECardResult Card::createFile(const char* filename, size_t size, ECardResult Card::createFile(const char* filename, size_t size, FileHandle& handleOut) {
FileHandle& handleOut)
{
ECardResult openRes = _pumpOpen(); ECardResult openRes = _pumpOpen();
if (openRes != ECardResult::READY) if (openRes != ECardResult::READY)
return openRes; return openRes;
@ -221,8 +199,7 @@ ECardResult Card::createFile(const char* filename, size_t size,
BlockAllocationTable bat = m_bats[m_currentBat]; BlockAllocationTable bat = m_bats[m_currentBat];
File* f = dir.getFirstFreeFile(m_game, m_maker, filename); File* f = dir.getFirstFreeFile(m_game, m_maker, filename);
uint16_t block = bat.allocateBlocks(neededBlocks, m_maxBlock - FSTBlocks); uint16_t block = bat.allocateBlocks(neededBlocks, m_maxBlock - FSTBlocks);
if (f && block != 0xFFFF) if (f && block != 0xFFFF) {
{
f->m_modifiedTime = uint32_t(getGCTime()); f->m_modifiedTime = uint32_t(getGCTime());
f->m_firstBlock = block; f->m_firstBlock = block;
f->m_blockCount = neededBlocks; f->m_blockCount = neededBlocks;
@ -235,14 +212,12 @@ ECardResult Card::createFile(const char* filename, size_t size,
return ECardResult::FATAL_ERROR; return ECardResult::FATAL_ERROR;
} }
ECardResult Card::closeFile(FileHandle& fh) ECardResult Card::closeFile(FileHandle& fh) {
{
fh.offset = 0; fh.offset = 0;
return ECardResult::READY; return ECardResult::READY;
} }
FileHandle Card::firstFile() FileHandle Card::firstFile() {
{
File* f = m_dirs[m_currentDir].getFirstNonFreeFile(0, m_game, m_maker); File* f = m_dirs[m_currentDir].getFirstNonFreeFile(0, m_game, m_maker);
if (f) if (f)
return FileHandle(m_dirs[m_currentDir].indexForFile(f)); return FileHandle(m_dirs[m_currentDir].indexForFile(f));
@ -250,10 +225,8 @@ FileHandle Card::firstFile()
return {}; return {};
} }
FileHandle Card::nextFile(const FileHandle& cur) FileHandle Card::nextFile(const FileHandle& cur) {
{ if (!cur) {
if (!cur)
{
NullFileAccess(); NullFileAccess();
return {}; return {};
} }
@ -263,19 +236,16 @@ FileHandle Card::nextFile(const FileHandle& cur)
return FileHandle(m_dirs[m_currentDir].indexForFile(next)); return FileHandle(m_dirs[m_currentDir].indexForFile(next));
} }
const char* Card::getFilename(const FileHandle& fh) const char* Card::getFilename(const FileHandle& fh) {
{
File* f = _fileFromHandle(fh); File* f = _fileFromHandle(fh);
if (!f) if (!f)
return nullptr; return nullptr;
return f->m_filename; return f->m_filename;
} }
void Card::_deleteFile(File& f, BlockAllocationTable& bat) void Card::_deleteFile(File& f, BlockAllocationTable& bat) {
{
uint16_t block = f.m_firstBlock; uint16_t block = f.m_firstBlock;
while (block != 0xFFFF) while (block != 0xFFFF) {
{
/* TODO: add a fragmentation check */ /* TODO: add a fragmentation check */
uint16_t nextBlock = bat.getNextBlock(block); uint16_t nextBlock = bat.getNextBlock(block);
bat.clear(block, 1); bat.clear(block, 1);
@ -284,10 +254,8 @@ void Card::_deleteFile(File& f, BlockAllocationTable& bat)
f = File(); f = File();
} }
void Card::deleteFile(const FileHandle& fh) void Card::deleteFile(const FileHandle& fh) {
{ if (!fh) {
if (!fh)
{
NullFileAccess(); NullFileAccess();
return; return;
} }
@ -297,8 +265,7 @@ void Card::deleteFile(const FileHandle& fh)
_updateDirAndBat(dir, bat); _updateDirAndBat(dir, bat);
} }
ECardResult Card::deleteFile(const char* filename) ECardResult Card::deleteFile(const char* filename) {
{
ECardResult openRes = _pumpOpen(); ECardResult openRes = _pumpOpen();
if (openRes != ECardResult::READY) if (openRes != ECardResult::READY)
return openRes; return openRes;
@ -314,8 +281,7 @@ ECardResult Card::deleteFile(const char* filename)
return ECardResult::READY; return ECardResult::READY;
} }
ECardResult Card::deleteFile(uint32_t fileno) ECardResult Card::deleteFile(uint32_t fileno) {
{
ECardResult openRes = _pumpOpen(); ECardResult openRes = _pumpOpen();
if (openRes != ECardResult::READY) if (openRes != ECardResult::READY)
return openRes; return openRes;
@ -331,8 +297,7 @@ ECardResult Card::deleteFile(uint32_t fileno)
return ECardResult::READY; return ECardResult::READY;
} }
ECardResult Card::renameFile(const char* oldName, const char* newName) ECardResult Card::renameFile(const char* oldName, const char* newName) {
{
ECardResult openRes = _pumpOpen(); ECardResult openRes = _pumpOpen();
if (openRes != ECardResult::READY) if (openRes != ECardResult::READY)
return openRes; return openRes;
@ -345,29 +310,24 @@ ECardResult Card::renameFile(const char* oldName, const char* newName)
if (!f) if (!f)
return ECardResult::NOFILE; return ECardResult::NOFILE;
if (File* replF = dir.getFile(m_game, m_maker, newName)) if (File* replF = dir.getFile(m_game, m_maker, newName)) {
{
BlockAllocationTable bat = m_bats[m_currentBat]; BlockAllocationTable bat = m_bats[m_currentBat];
_deleteFile(*replF, bat); _deleteFile(*replF, bat);
strncpy(f->m_filename, newName, 32); strncpy(f->m_filename, newName, 32);
_updateDirAndBat(dir, bat); _updateDirAndBat(dir, bat);
} } else {
else
{
strncpy(f->m_filename, newName, 32); strncpy(f->m_filename, newName, 32);
_updateDirAndBat(dir, m_bats[m_currentBat]); _updateDirAndBat(dir, m_bats[m_currentBat]);
} }
return ECardResult::READY; return ECardResult::READY;
} }
ECardResult Card::asyncWrite(FileHandle& fh, const void* buf, size_t size) ECardResult Card::asyncWrite(FileHandle& fh, const void* buf, size_t size) {
{
ECardResult openRes = _pumpOpen(); ECardResult openRes = _pumpOpen();
if (openRes != ECardResult::READY) if (openRes != ECardResult::READY)
return openRes; return openRes;
if (!fh) if (!fh) {
{
NullFileAccess(); NullFileAccess();
return ECardResult::NOFILE; return ECardResult::NOFILE;
} }
@ -388,8 +348,7 @@ ECardResult Card::asyncWrite(FileHandle& fh, const void* buf, size_t size)
uint16_t curBlock = block; uint16_t curBlock = block;
uint32_t blockOffset = fh.offset % BlockSize; uint32_t blockOffset = fh.offset % BlockSize;
size_t rem = size; size_t rem = size;
while (rem) while (rem) {
{
if (curBlock == 0xFFFF) if (curBlock == 0xFFFF)
return ECardResult::NOFILE; return ECardResult::NOFILE;
@ -402,8 +361,7 @@ ECardResult Card::asyncWrite(FileHandle& fh, const void* buf, size_t size)
tmpBuf += cacheSize; tmpBuf += cacheSize;
rem -= cacheSize; rem -= cacheSize;
blockOffset += cacheSize; blockOffset += cacheSize;
if (blockOffset >= BlockSize) if (blockOffset >= BlockSize) {
{
curBlock = m_bats[m_currentBat].getNextBlock(curBlock); curBlock = m_bats[m_currentBat].getNextBlock(curBlock);
blockOffset = 0; blockOffset = 0;
} }
@ -413,14 +371,12 @@ ECardResult Card::asyncWrite(FileHandle& fh, const void* buf, size_t size)
return ECardResult::READY; return ECardResult::READY;
} }
ECardResult Card::asyncRead(FileHandle& fh, void* dst, size_t size) ECardResult Card::asyncRead(FileHandle& fh, void* dst, size_t size) {
{
ECardResult openRes = _pumpOpen(); ECardResult openRes = _pumpOpen();
if (openRes != ECardResult::READY) if (openRes != ECardResult::READY)
return openRes; return openRes;
if (!fh) if (!fh) {
{
NullFileAccess(); NullFileAccess();
return ECardResult::NOFILE; return ECardResult::NOFILE;
} }
@ -440,8 +396,7 @@ ECardResult Card::asyncRead(FileHandle& fh, void* dst, size_t size)
uint16_t curBlock = block; uint16_t curBlock = block;
uint32_t blockOffset = fh.offset % BlockSize; uint32_t blockOffset = fh.offset % BlockSize;
size_t rem = size; size_t rem = size;
while (rem) while (rem) {
{
if (curBlock == 0xFFFF) if (curBlock == 0xFFFF)
return ECardResult::NOFILE; return ECardResult::NOFILE;
@ -454,8 +409,7 @@ ECardResult Card::asyncRead(FileHandle& fh, void* dst, size_t size)
tmpBuf += cacheSize; tmpBuf += cacheSize;
rem -= cacheSize; rem -= cacheSize;
blockOffset += cacheSize; blockOffset += cacheSize;
if (blockOffset >= BlockSize) if (blockOffset >= BlockSize) {
{
curBlock = m_bats[m_currentBat].getNextBlock(curBlock); curBlock = m_bats[m_currentBat].getNextBlock(curBlock);
blockOffset = 0; blockOffset = 0;
} }
@ -465,10 +419,8 @@ ECardResult Card::asyncRead(FileHandle& fh, void* dst, size_t size)
return ECardResult::READY; return ECardResult::READY;
} }
void Card::seek(FileHandle& fh, int32_t pos, SeekOrigin whence) void Card::seek(FileHandle& fh, int32_t pos, SeekOrigin whence) {
{ if (!fh) {
if (!fh)
{
NullFileAccess(); NullFileAccess();
return; return;
} }
@ -476,8 +428,7 @@ void Card::seek(FileHandle& fh, int32_t pos, SeekOrigin whence)
if (!file) if (!file)
return; return;
switch (whence) switch (whence) {
{
case SeekOrigin::Begin: case SeekOrigin::Begin:
fh.offset = pos; fh.offset = pos;
break; break;
@ -490,13 +441,9 @@ void Card::seek(FileHandle& fh, int32_t pos, SeekOrigin whence)
} }
} }
int32_t Card::tell(const FileHandle& fh) int32_t Card::tell(const FileHandle& fh) { return fh.offset; }
{
return fh.offset;
}
void Card::setPublic(const FileHandle& fh, bool pub) void Card::setPublic(const FileHandle& fh, bool pub) {
{
File* file = _fileFromHandle(fh); File* file = _fileFromHandle(fh);
if (!file) if (!file)
return; return;
@ -507,8 +454,7 @@ void Card::setPublic(const FileHandle& fh, bool pub)
file->m_permissions &= ~EPermissions::Public; file->m_permissions &= ~EPermissions::Public;
} }
bool Card::isPublic(const FileHandle& fh) const bool Card::isPublic(const FileHandle& fh) const {
{
File* file = _fileFromHandle(fh); File* file = _fileFromHandle(fh);
if (!file) if (!file)
return false; return false;
@ -516,8 +462,7 @@ bool Card::isPublic(const FileHandle& fh) const
return bool(file->m_permissions & EPermissions::Public); return bool(file->m_permissions & EPermissions::Public);
} }
void Card::setCanCopy(const FileHandle& fh, bool copy) const void Card::setCanCopy(const FileHandle& fh, bool copy) const {
{
File* file = _fileFromHandle(fh); File* file = _fileFromHandle(fh);
if (!file) if (!file)
return; return;
@ -528,8 +473,7 @@ void Card::setCanCopy(const FileHandle& fh, bool copy) const
file->m_permissions |= EPermissions::NoCopy; file->m_permissions |= EPermissions::NoCopy;
} }
bool Card::canCopy(const FileHandle& fh) const bool Card::canCopy(const FileHandle& fh) const {
{
File* file = _fileFromHandle(fh); File* file = _fileFromHandle(fh);
if (!file) if (!file)
return false; return false;
@ -537,8 +481,7 @@ bool Card::canCopy(const FileHandle& fh) const
return !bool(file->m_permissions & EPermissions::NoCopy); return !bool(file->m_permissions & EPermissions::NoCopy);
} }
void Card::setCanMove(const FileHandle& fh, bool move) void Card::setCanMove(const FileHandle& fh, bool move) {
{
File* file = _fileFromHandle(fh); File* file = _fileFromHandle(fh);
if (!file) if (!file)
return; return;
@ -549,8 +492,7 @@ void Card::setCanMove(const FileHandle& fh, bool move)
file->m_permissions |= EPermissions::NoMove; file->m_permissions |= EPermissions::NoMove;
} }
bool Card::canMove(const FileHandle& fh) const bool Card::canMove(const FileHandle& fh) const {
{
File* file = _fileFromHandle(fh); File* file = _fileFromHandle(fh);
if (!file) if (!file)
return false; return false;
@ -558,10 +500,8 @@ bool Card::canMove(const FileHandle& fh) const
return !bool(file->m_permissions & EPermissions::NoMove); return !bool(file->m_permissions & EPermissions::NoMove);
} }
static uint32_t BannerSize(EImageFormat fmt) static uint32_t BannerSize(EImageFormat fmt) {
{ switch (fmt) {
switch (fmt)
{
default: default:
case EImageFormat::None: case EImageFormat::None:
return 0; return 0;
@ -572,10 +512,8 @@ static uint32_t BannerSize(EImageFormat fmt)
} }
} }
static uint32_t IconSize(EImageFormat fmt) static uint32_t IconSize(EImageFormat fmt) {
{ switch (fmt) {
switch (fmt)
{
default: default:
case EImageFormat::None: case EImageFormat::None:
return 0; return 0;
@ -586,10 +524,8 @@ static uint32_t IconSize(EImageFormat fmt)
} }
} }
static uint32_t TlutSize(EImageFormat fmt) static uint32_t TlutSize(EImageFormat fmt) {
{ switch (fmt) {
switch (fmt)
{
default: default:
case EImageFormat::None: case EImageFormat::None:
case EImageFormat::RGB5A3: case EImageFormat::RGB5A3:
@ -599,18 +535,15 @@ static uint32_t TlutSize(EImageFormat fmt)
} }
} }
ECardResult Card::getStatus(const FileHandle& fh, CardStat& statOut) const ECardResult Card::getStatus(const FileHandle& fh, CardStat& statOut) const {
{ if (!fh) {
if (!fh)
{
NullFileAccess(); NullFileAccess();
return ECardResult::NOFILE; return ECardResult::NOFILE;
} }
return getStatus(fh.idx, statOut); return getStatus(fh.idx, statOut);
} }
ECardResult Card::getStatus(uint32_t fileNo, CardStat& statOut) const ECardResult Card::getStatus(uint32_t fileNo, CardStat& statOut) const {
{
ECardResult openRes = const_cast<Card*>(this)->_pumpOpen(); ECardResult openRes = const_cast<Card*>(this)->_pumpOpen();
if (openRes != ECardResult::READY) if (openRes != ECardResult::READY)
return openRes; return openRes;
@ -631,37 +564,31 @@ ECardResult Card::getStatus(uint32_t fileNo, CardStat& statOut) const
statOut.x36_iconSpeed = file->m_animSpeed; statOut.x36_iconSpeed = file->m_animSpeed;
statOut.x38_commentAddr = file->m_commentAddr; statOut.x38_commentAddr = file->m_commentAddr;
if (file->m_iconAddress == -1) if (file->m_iconAddress == -1) {
{
statOut.x3c_offsetBanner = -1; statOut.x3c_offsetBanner = -1;
statOut.x40_offsetBannerTlut = -1; statOut.x40_offsetBannerTlut = -1;
for (int i=0 ; i<CARD_ICON_MAX ; ++i) for (int i = 0; i < CARD_ICON_MAX; ++i)
statOut.x44_offsetIcon[i] = -1; statOut.x44_offsetIcon[i] = -1;
statOut.x64_offsetIconTlut = -1; statOut.x64_offsetIconTlut = -1;
statOut.x68_offsetData = file->m_commentAddr + 64; statOut.x68_offsetData = file->m_commentAddr + 64;
} } else {
else
{
uint32_t cur = file->m_iconAddress; uint32_t cur = file->m_iconAddress;
statOut.x3c_offsetBanner = cur; statOut.x3c_offsetBanner = cur;
cur += BannerSize(statOut.GetBannerFormat()); cur += BannerSize(statOut.GetBannerFormat());
statOut.x40_offsetBannerTlut = cur; statOut.x40_offsetBannerTlut = cur;
cur += TlutSize(statOut.GetBannerFormat()); cur += TlutSize(statOut.GetBannerFormat());
bool palette = false; bool palette = false;
for (int i=0 ; i<CARD_ICON_MAX ; ++i) for (int i = 0; i < CARD_ICON_MAX; ++i) {
{
statOut.x44_offsetIcon[i] = cur; statOut.x44_offsetIcon[i] = cur;
EImageFormat fmt = statOut.GetIconFormat(i); EImageFormat fmt = statOut.GetIconFormat(i);
if (fmt == EImageFormat::C8) if (fmt == EImageFormat::C8)
palette = true; palette = true;
cur += IconSize(fmt); cur += IconSize(fmt);
} }
if (palette) if (palette) {
{
statOut.x64_offsetIconTlut = cur; statOut.x64_offsetIconTlut = cur;
cur += TlutSize(EImageFormat::C8); cur += TlutSize(EImageFormat::C8);
} } else
else
statOut.x64_offsetIconTlut = -1; statOut.x64_offsetIconTlut = -1;
statOut.x68_offsetData = cur; statOut.x68_offsetData = cur;
} }
@ -669,18 +596,15 @@ ECardResult Card::getStatus(uint32_t fileNo, CardStat& statOut) const
return ECardResult::READY; return ECardResult::READY;
} }
ECardResult Card::setStatus(const FileHandle& fh, const CardStat& stat) ECardResult Card::setStatus(const FileHandle& fh, const CardStat& stat) {
{ if (!fh) {
if (!fh)
{
NullFileAccess(); NullFileAccess();
return ECardResult::NOFILE; return ECardResult::NOFILE;
} }
return setStatus(fh.idx, stat); return setStatus(fh.idx, stat);
} }
ECardResult Card::setStatus(uint32_t fileNo, const CardStat& stat) ECardResult Card::setStatus(uint32_t fileNo, const CardStat& stat) {
{
ECardResult openRes = _pumpOpen(); ECardResult openRes = _pumpOpen();
if (openRes != ECardResult::READY) if (openRes != ECardResult::READY)
return openRes; return openRes;
@ -761,10 +685,8 @@ bool Card::moveFileTo(FileHandle& fh, Card& dest)
} }
#endif #endif
void Card::setCurrentGame(const char* game) void Card::setCurrentGame(const char* game) {
{ if (game == nullptr) {
if (game == nullptr)
{
memset(m_game, 0, 2); memset(m_game, 0, 2);
return; return;
} }
@ -775,18 +697,15 @@ void Card::setCurrentGame(const char* game)
memcpy(m_game, game, 4); memcpy(m_game, game, 4);
} }
const uint8_t* Card::getCurrentGame() const const uint8_t* Card::getCurrentGame() const {
{
if (strlen(m_game) == 4) if (strlen(m_game) == 4)
return reinterpret_cast<const uint8_t*>(m_game); return reinterpret_cast<const uint8_t*>(m_game);
return nullptr; return nullptr;
} }
void Card::setCurrentMaker(const char* maker) void Card::setCurrentMaker(const char* maker) {
{ if (maker == nullptr) {
if (maker == nullptr)
{
memset(m_maker, 0, 2); memset(m_maker, 0, 2);
return; return;
} }
@ -797,15 +716,13 @@ void Card::setCurrentMaker(const char* maker)
memcpy(m_maker, maker, 2); memcpy(m_maker, maker, 2);
} }
const uint8_t* Card::getCurrentMaker() const const uint8_t* Card::getCurrentMaker() const {
{
if (strlen(m_maker) == 2) if (strlen(m_maker) == 2)
return reinterpret_cast<const uint8_t*>(m_maker); return reinterpret_cast<const uint8_t*>(m_maker);
return nullptr; return nullptr;
} }
void Card::getSerial(uint64_t& serial) void Card::getSerial(uint64_t& serial) {
{
m_ch._swapEndian(); m_ch._swapEndian();
uint32_t serialBuf[8]; uint32_t serialBuf[8];
for (uint32_t i = 0; i < 8; i++) for (uint32_t i = 0; i < 8; i++)
@ -815,27 +732,23 @@ void Card::getSerial(uint64_t& serial)
m_ch._swapEndian(); m_ch._swapEndian();
} }
void Card::getChecksum(uint16_t& checksum, uint16_t& inverse) void Card::getChecksum(uint16_t& checksum, uint16_t& inverse) {
{
checksum = m_ch.m_checksum; checksum = m_ch.m_checksum;
inverse = m_ch.m_checksumInv; inverse = m_ch.m_checksumInv;
} }
void Card::getFreeBlocks(int32_t& bytesNotUsed, int32_t& filesNotUsed) void Card::getFreeBlocks(int32_t& bytesNotUsed, int32_t& filesNotUsed) {
{
bytesNotUsed = m_bats[m_currentBat].numFreeBlocks() * 0x2000; bytesNotUsed = m_bats[m_currentBat].numFreeBlocks() * 0x2000;
filesNotUsed = m_dirs[m_currentDir].numFreeFiles(); filesNotUsed = m_dirs[m_currentDir].numFreeFiles();
} }
static std::unique_ptr<uint8_t[]> DummyBlock; static std::unique_ptr<uint8_t[]> DummyBlock;
void Card::format(ECardSlot id, ECardSize size, EEncoding encoding) void Card::format(ECardSlot id, ECardSize size, EEncoding encoding) {
{
memset(__raw, 0xFF, BlockSize); memset(__raw, 0xFF, BlockSize);
uint64_t rand = uint64_t(getGCTime()); uint64_t rand = uint64_t(getGCTime());
m_ch.m_formatTime = rand; m_ch.m_formatTime = rand;
for (int i = 0; i < 12; i++) for (int i = 0; i < 12; i++) {
{
rand = (((rand * uint64_t(0x41c64e6d)) + uint64_t(0x3039)) >> 16); rand = (((rand * uint64_t(0x41c64e6d)) + uint64_t(0x3039)) >> 16);
m_ch.m_serial[i] = uint8_t(g_SRAM.flash_id[uint32_t(id)][i] + uint32_t(rand)); m_ch.m_serial[i] = uint8_t(g_SRAM.flash_id[uint32_t(id)][i] + uint32_t(rand));
rand = (((rand * uint64_t(0x41c64e6d)) + uint64_t(0x3039)) >> 16); rand = (((rand * uint64_t(0x41c64e6d)) + uint64_t(0x3039)) >> 16);
@ -860,8 +773,7 @@ void Card::format(ECardSlot id, ECardSize size, EEncoding encoding)
m_fileHandle = {}; m_fileHandle = {};
m_fileHandle = AsyncIO(m_filename.c_str(), true); m_fileHandle = AsyncIO(m_filename.c_str(), true);
if (m_fileHandle) if (m_fileHandle) {
{
uint32_t blockCount = (uint32_t(size) * MbitToBlocks) - 5; uint32_t blockCount = (uint32_t(size) * MbitToBlocks) - 5;
m_tmpCh = m_ch; m_tmpCh = m_ch;
@ -880,31 +792,27 @@ void Card::format(ECardSlot id, ECardSize size, EEncoding encoding)
m_tmpBats[1] = m_bats[1]; m_tmpBats[1] = m_bats[1];
m_tmpBats[1].swapEndian(); m_tmpBats[1].swapEndian();
m_fileHandle.asyncWrite(4, m_tmpBats[1].__raw, BlockSize, BlockSize * 4); m_fileHandle.asyncWrite(4, m_tmpBats[1].__raw, BlockSize, BlockSize * 4);
if (!DummyBlock) if (!DummyBlock) {
{
DummyBlock.reset(new uint8_t[BlockSize]); DummyBlock.reset(new uint8_t[BlockSize]);
memset(DummyBlock.get(), 0xFF, BlockSize); memset(DummyBlock.get(), 0xFF, BlockSize);
} }
for (uint32_t i=0 ; i<blockCount ; ++i) for (uint32_t i = 0; i < blockCount; ++i)
m_fileHandle.asyncWrite(i + 5, DummyBlock.get(), BlockSize, BlockSize * (i + 5)); m_fileHandle.asyncWrite(i + 5, DummyBlock.get(), BlockSize, BlockSize * (i + 5));
m_dirty = false; m_dirty = false;
} }
} }
ProbeResults Card::probeCardFile(SystemStringView filename) ProbeResults Card::probeCardFile(SystemStringView filename) {
{
Sstat stat; Sstat stat;
if (Stat(filename.data(), &stat) || !S_ISREG(stat.st_mode)) if (Stat(filename.data(), &stat) || !S_ISREG(stat.st_mode))
return { ECardResult::NOCARD, 0, 0 }; return {ECardResult::NOCARD, 0, 0};
return { ECardResult::READY, uint32_t(stat.st_size / BlockSize) / MbitToBlocks, 0x2000 }; return {ECardResult::READY, uint32_t(stat.st_size / BlockSize) / MbitToBlocks, 0x2000};
} }
void Card::commit() void Card::commit() {
{
if (!m_dirty) if (!m_dirty)
return; return;
if (m_fileHandle) if (m_fileHandle) {
{
m_tmpCh = m_ch; m_tmpCh = m_ch;
m_tmpCh._swapEndian(); m_tmpCh._swapEndian();
m_fileHandle.asyncWrite(0, &m_tmpCh, BlockSize, 0); m_fileHandle.asyncWrite(0, &m_tmpCh, BlockSize, 0);
@ -928,13 +836,11 @@ void Card::commit()
} }
} }
bool Card::open(SystemStringView filepath) bool Card::open(SystemStringView filepath) {
{
m_opened = false; m_opened = false;
m_filename = filepath; m_filename = filepath;
m_fileHandle = AsyncIO(m_filename); m_fileHandle = AsyncIO(m_filename);
if (m_fileHandle) if (m_fileHandle) {
{
m_fileHandle.resizeQueue(5); m_fileHandle.resizeQueue(5);
if (!m_fileHandle.asyncRead(0, __raw, BlockSize, 0)) if (!m_fileHandle.asyncRead(0, __raw, BlockSize, 0))
return false; return false;
@ -951,19 +857,16 @@ bool Card::open(SystemStringView filepath)
return false; return false;
} }
void Card::close() void Card::close() {
{
m_opened = false; m_opened = false;
if (m_fileHandle) if (m_fileHandle) {
{
commit(); commit();
m_fileHandle.waitForCompletion(); m_fileHandle.waitForCompletion();
m_fileHandle = {}; m_fileHandle = {};
} }
} }
ECardResult Card::getError() const ECardResult Card::getError() const {
{
if (!m_fileHandle) if (!m_fileHandle)
return ECardResult::NOCARD; return ECardResult::NOCARD;
@ -991,10 +894,9 @@ ECardResult Card::getError() const
return ECardResult::READY; return ECardResult::READY;
} }
void Card::waitForCompletion() const void Card::waitForCompletion() const {
{
if (!m_fileHandle) if (!m_fileHandle)
return; return;
m_fileHandle.waitForCompletion(); m_fileHandle.waitForCompletion();
} }
} } // namespace kabufuda

View File

@ -2,10 +2,8 @@
#include "kabufuda/Util.hpp" #include "kabufuda/Util.hpp"
#include <cstring> #include <cstring>
namespace kabufuda namespace kabufuda {
{ void Directory::swapEndian() {
void Directory::swapEndian()
{
std::for_each(std::begin(m_files), std::end(m_files), [](File& f) { f.swapEndian(); }); std::for_each(std::begin(m_files), std::end(m_files), [](File& f) { f.swapEndian(); });
m_updateCounter = SBig(m_updateCounter); m_updateCounter = SBig(m_updateCounter);
@ -13,15 +11,13 @@ void Directory::swapEndian()
m_checksumInv = SBig(m_checksumInv); m_checksumInv = SBig(m_checksumInv);
} }
void Directory::updateChecksum() void Directory::updateChecksum() {
{
swapEndian(); swapEndian();
calculateChecksumBE(reinterpret_cast<uint16_t*>(__raw), 0xFFE, &m_checksum, &m_checksumInv); calculateChecksumBE(reinterpret_cast<uint16_t*>(__raw), 0xFFE, &m_checksum, &m_checksumInv);
swapEndian(); swapEndian();
} }
bool Directory::valid() const bool Directory::valid() const {
{
uint16_t ckSum, ckSumInv; uint16_t ckSum, ckSumInv;
const_cast<Directory&>(*this).swapEndian(); const_cast<Directory&>(*this).swapEndian();
calculateChecksumBE(reinterpret_cast<const uint16_t*>(__raw), 0xFFE, &ckSum, &ckSumInv); calculateChecksumBE(reinterpret_cast<const uint16_t*>(__raw), 0xFFE, &ckSum, &ckSumInv);
@ -30,8 +26,7 @@ bool Directory::valid() const
return res; return res;
} }
Directory::Directory() Directory::Directory() {
{
memset(__raw, 0xFF, BlockSize); memset(__raw, 0xFF, BlockSize);
m_updateCounter = 0; m_updateCounter = 0;
updateChecksum(); updateChecksum();
@ -39,16 +34,14 @@ Directory::Directory()
Directory::Directory(uint8_t data[]) { memcpy(__raw, data, BlockSize); } Directory::Directory(uint8_t data[]) { memcpy(__raw, data, BlockSize); }
bool Directory::hasFreeFile() const bool Directory::hasFreeFile() const {
{
for (uint16_t i = 0; i < 127; i++) for (uint16_t i = 0; i < 127; i++)
if (m_files[i].m_game[0] == 0xFF) if (m_files[i].m_game[0] == 0xFF)
return true; return true;
return false; return false;
} }
int32_t Directory::numFreeFiles() const int32_t Directory::numFreeFiles() const {
{
int32_t ret = 0; int32_t ret = 0;
for (uint16_t i = 0; i < 127; i++) for (uint16_t i = 0; i < 127; i++)
if (m_files[i].m_game[0] == 0xFF) if (m_files[i].m_game[0] == 0xFF)
@ -56,12 +49,9 @@ int32_t Directory::numFreeFiles() const
return ret; return ret;
} }
File* Directory::getFirstFreeFile(const char* game, const char* maker, const char* filename) File* Directory::getFirstFreeFile(const char* game, const char* maker, const char* filename) {
{ for (uint16_t i = 0; i < 127; i++) {
for (uint16_t i = 0; i < 127; i++) if (m_files[i].m_game[0] == 0xFF) {
{
if (m_files[i].m_game[0] == 0xFF)
{
File* ret = &m_files[i]; File* ret = &m_files[i];
*ret = File(filename); *ret = File(filename);
if (game && strlen(game) == 4) if (game && strlen(game) == 4)
@ -75,18 +65,13 @@ File* Directory::getFirstFreeFile(const char* game, const char* maker, const cha
return nullptr; return nullptr;
} }
File* Directory::getFirstNonFreeFile(uint32_t start, const char* game, const char* maker) File* Directory::getFirstNonFreeFile(uint32_t start, const char* game, const char* maker) {
{ for (uint16_t i = start; i < 127; i++) {
for (uint16_t i = start; i < 127; i++) if (m_files[i].m_game[0] != 0xFF) {
{
if (m_files[i].m_game[0] != 0xFF)
{
File* ret = &m_files[i]; File* ret = &m_files[i];
if (game && std::strlen(game) == 4 && if (game && std::strlen(game) == 4 && std::strncmp(reinterpret_cast<const char*>(ret->m_game), game, 4) != 0)
std::strncmp(reinterpret_cast<const char*>(ret->m_game), game, 4) != 0)
continue; continue;
if (maker && std::strlen(maker) == 2 && if (maker && std::strlen(maker) == 2 && std::strncmp(reinterpret_cast<const char*>(ret->m_maker), maker, 2) != 0)
std::strncmp(reinterpret_cast<const char*>(ret->m_maker), maker, 2) != 0)
continue; continue;
return ret; return ret;
} }
@ -95,10 +80,8 @@ File* Directory::getFirstNonFreeFile(uint32_t start, const char* game, const cha
return nullptr; return nullptr;
} }
File* Directory::getFile(const char* game, const char* maker, const char* filename) File* Directory::getFile(const char* game, const char* maker, const char* filename) {
{ for (uint16_t i = 0; i < 127; i++) {
for (uint16_t i = 0; i < 127; i++)
{
if (game && strlen(game) == 4 && memcmp(m_files[i].m_game, game, 4)) if (game && strlen(game) == 4 && memcmp(m_files[i].m_game, game, 4))
continue; continue;
if (maker && strlen(maker) == 2 && memcmp(m_files[i].m_maker, maker, 2)) if (maker && strlen(maker) == 2 && memcmp(m_files[i].m_maker, maker, 2))
@ -110,23 +93,20 @@ File* Directory::getFile(const char* game, const char* maker, const char* filena
return nullptr; return nullptr;
} }
File* Directory::getFile(uint32_t idx) File* Directory::getFile(uint32_t idx) {
{
if (idx >= 127) if (idx >= 127)
return nullptr; return nullptr;
return &m_files[idx]; return &m_files[idx];
} }
int32_t Directory::indexForFile(File* f) int32_t Directory::indexForFile(File* f) {
{
if (!f) if (!f)
return -1; return -1;
auto it = auto it = std::find_if(std::begin(m_files), std::end(m_files), [&f](const File& file) -> bool { return f == &file; });
std::find_if(std::begin(m_files), std::end(m_files), [&f](const File& file) -> bool { return f == &file; });
if (it == std::end(m_files)) if (it == std::end(m_files))
return -1; return -1;
return it - std::begin(m_files); return it - std::begin(m_files);
} }
} } // namespace kabufuda

View File

@ -1,20 +1,17 @@
#include "kabufuda/File.hpp" #include "kabufuda/File.hpp"
#include "kabufuda/Util.hpp" #include "kabufuda/Util.hpp"
namespace kabufuda namespace kabufuda {
{
File::File() { memset(__raw, 0xFF, 0x40); } File::File() { memset(__raw, 0xFF, 0x40); }
File::File(char data[]) { memcpy(__raw, data, 0x40); } File::File(char data[]) { memcpy(__raw, data, 0x40); }
File::File(const char* filename) File::File(const char* filename) {
{
memset(__raw, 0, 0x40); memset(__raw, 0, 0x40);
memset(m_filename, 0, 32); memset(m_filename, 0, 32);
strncpy(m_filename, filename, 32); strncpy(m_filename, filename, 32);
} }
void File::swapEndian() void File::swapEndian() {
{
m_modifiedTime = SBig(m_modifiedTime); m_modifiedTime = SBig(m_modifiedTime);
m_iconAddress = SBig(m_iconAddress); m_iconAddress = SBig(m_iconAddress);
m_iconFmt = SBig(m_iconFmt); m_iconFmt = SBig(m_iconFmt);
@ -24,4 +21,4 @@ void File::swapEndian()
m_reserved2 = SBig(m_reserved2); m_reserved2 = SBig(m_reserved2);
m_commentAddr = SBig(m_commentAddr); m_commentAddr = SBig(m_commentAddr);
} }
} } // namespace kabufuda

View File

@ -1,6 +1,5 @@
#include "kabufuda/SRAM.hpp" #include "kabufuda/SRAM.hpp"
namespace kabufuda namespace kabufuda {
{
// clang-format off // clang-format off
const SRAM g_SRAM = const SRAM g_SRAM =
{{ {{
@ -27,4 +26,4 @@ const SRAM g_SRAM =
0x00, 0x00 0x00, 0x00
}}; }};
// clang-format on // clang-format on
} } // namespace kabufuda

View File

@ -1,10 +1,8 @@
#include "kabufuda/Util.hpp" #include "kabufuda/Util.hpp"
#include <ctime> #include <ctime>
namespace kabufuda namespace kabufuda {
{ uint64_t getGCTime() {
uint64_t getGCTime()
{
time_t sysTime, tzDiff, tzDST; time_t sysTime, tzDiff, tzDST;
struct tm* gmTime; struct tm* gmTime;
@ -24,12 +22,10 @@ uint64_t getGCTime()
return (uint64_t)(sysTime + tzDiff + tzDST) - 0x386D4380; return (uint64_t)(sysTime + tzDiff + tzDST) - 0x386D4380;
} }
void calculateChecksumBE(const uint16_t* data, size_t len, uint16_t* checksum, uint16_t* checksumInv) void calculateChecksumBE(const uint16_t* data, size_t len, uint16_t* checksum, uint16_t* checksumInv) {
{
*checksum = 0; *checksum = 0;
*checksumInv = 0; *checksumInv = 0;
for (size_t i = 0; i < len; ++i) for (size_t i = 0; i < len; ++i) {
{
*checksum += SBig(data[i]); *checksum += SBig(data[i]);
*checksumInv += SBig(uint16_t(data[i] ^ 0xFFFF)); *checksumInv += SBig(uint16_t(data[i] ^ 0xFFFF));
} }
@ -42,4 +38,4 @@ void calculateChecksumBE(const uint16_t* data, size_t len, uint16_t* checksum, u
*checksumInv = 0; *checksumInv = 0;
} }
} } // namespace kabufuda

View File

@ -1,18 +1,14 @@
#include "kabufuda/WideStringConvert.hpp" #include "kabufuda/WideStringConvert.hpp"
#include "utf8proc.h" #include "utf8proc.h"
namespace kabufuda namespace kabufuda {
{ std::string WideToUTF8(std::wstring_view src) {
std::string WideToUTF8(std::wstring_view src)
{
std::string retval; std::string retval;
retval.reserve(src.length()); retval.reserve(src.length());
for (wchar_t ch : src) for (wchar_t ch : src) {
{
utf8proc_uint8_t mb[4]; utf8proc_uint8_t mb[4];
utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb); utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb);
if (c < 0) if (c < 0) {
{
fprintf(stderr, "invalid UTF-8 character while encoding"); fprintf(stderr, "invalid UTF-8 character while encoding");
return retval; return retval;
} }
@ -21,17 +17,14 @@ std::string WideToUTF8(std::wstring_view src)
return retval; return retval;
} }
std::wstring UTF8ToWide(std::string_view src) std::wstring UTF8ToWide(std::string_view src) {
{
std::wstring retval; std::wstring retval;
retval.reserve(src.length()); retval.reserve(src.length());
const utf8proc_uint8_t* buf = reinterpret_cast<const utf8proc_uint8_t*>(src.data()); const utf8proc_uint8_t* buf = reinterpret_cast<const utf8proc_uint8_t*>(src.data());
while (*buf) while (*buf) {
{
utf8proc_int32_t wc; utf8proc_int32_t wc;
utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc); utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc);
if (len < 0) if (len < 0) {
{
fprintf(stderr, "invalid UTF-8 character while decoding"); fprintf(stderr, "invalid UTF-8 character while decoding");
return retval; return retval;
} }
@ -40,4 +33,4 @@ std::wstring UTF8ToWide(std::string_view src)
} }
return retval; return retval;
} }
} } // namespace kabufuda

View File

@ -5,28 +5,26 @@
#include "hecl/winsupport.hpp" #include "hecl/winsupport.hpp"
/* /*
* The memmem() function finds the start of the first occurrence of the * The memmem() function finds the start of the first occurrence of the
* substring 'needle' of length 'nlen' in the memory area 'haystack' of * substring 'needle' of length 'nlen' in the memory area 'haystack' of
* length 'hlen'. * length 'hlen'.
* *
* The return value is a pointer to the beginning of the sub-string, or * The return value is a pointer to the beginning of the sub-string, or
* NULL if the substring is not found. * NULL if the substring is not found.
*/ */
void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen) void* memmem(const void* haystack, size_t hlen, const void* needle, size_t nlen) {
{
int needle_first; int needle_first;
const uint8_t *p = static_cast<const uint8_t*>(haystack); const uint8_t* p = static_cast<const uint8_t*>(haystack);
size_t plen = hlen; size_t plen = hlen;
if (!nlen) if (!nlen)
return NULL; return NULL;
needle_first = *(unsigned char *)needle; needle_first = *(unsigned char*)needle;
while (plen >= nlen && (p = static_cast<const uint8_t*>(memchr(p, needle_first, plen - nlen + 1)))) while (plen >= nlen && (p = static_cast<const uint8_t*>(memchr(p, needle_first, plen - nlen + 1)))) {
{
if (!memcmp(p, needle, nlen)) if (!memcmp(p, needle, nlen))
return (void *)p; return (void*)p;
p++; p++;
plen = hlen - (p - static_cast<const uint8_t*>(haystack)); plen = hlen - (p - static_cast<const uint8_t*>(haystack));

View File

@ -1,8 +1,7 @@
#include "kabufuda/Card.hpp" #include "kabufuda/Card.hpp"
#include <iostream> #include <iostream>
int main() int main() {
{
kabufuda::Card mc{"GM8E", "01"}; kabufuda::Card mc{"GM8E", "01"};
mc.open(_SYS_STR("test.USA.raw")); mc.open(_SYS_STR("test.USA.raw"));
mc.format(kabufuda::ECardSlot::SlotA, kabufuda::ECardSize::Card2043Mb); mc.format(kabufuda::ECardSlot::SlotA, kabufuda::ECardSize::Card2043Mb);
@ -11,8 +10,7 @@ int main()
kabufuda::FileHandle f; kabufuda::FileHandle f;
mc.openFile("MetroidPrime A", f); mc.openFile("MetroidPrime A", f);
for (uint32_t i = 0; i < 127; i++) for (uint32_t i = 0; i < 127; i++) {
{
char name[32] = {'\0'}; char name[32] = {'\0'};
sprintf(name, "Metroid Prime %i", i); sprintf(name, "Metroid Prime %i", i);
kabufuda::ECardResult res = mc.createFile(name, kabufuda::BlockSize, f); kabufuda::ECardResult res = mc.createFile(name, kabufuda::BlockSize, f);