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
UseTab: Never
---
@ -8,7 +8,6 @@ DerivePointerAlignment: false
PointerAlignment: Left
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
BreakBeforeBraces: Allman
IndentCaseLabels: false
AllowShortBlocksOnASingleLine: true
AlignOperands: true
@ -24,6 +23,6 @@ NamespaceIndentation: None
BinPackArguments: true
BinPackParameters: true
SortIncludes: false
AccessModifierOffset: -4
AccessModifierOffset: -2
ConstructorInitializerIndentWidth: 0
ConstructorInitializerAllOnOneLineOrOnePerLine: true

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -25,25 +25,22 @@ must not be misrepresented as being the original software.
distribution.
-------------------------------------------------------------*/
namespace kabufuda
{
#pragma pack(push,1)
union SRAMFlags
{
namespace kabufuda {
#pragma pack(push, 1)
union SRAMFlags {
uint8_t Hex;
struct
{
struct {
uint8_t : 2;
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 : 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
};
};
union SRAM
{
union SRAM {
uint8_t p_SRAM[64];
struct // Stored configuration value from the system SRAM area
{
@ -70,5 +67,4 @@ union SRAM
#pragma pack(pop)
extern const SRAM g_SRAM;
}
} // namespace kabufuda

View File

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

View File

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

View File

@ -8,5 +8,4 @@
#endif
#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"
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));
}
AsyncIO::~AsyncIO()
{
if (*this)
{
AsyncIO::~AsyncIO() {
if (*this) {
aio_cancel(m_fd, nullptr);
close(m_fd);
}
}
AsyncIO::AsyncIO(AsyncIO&& other)
{
AsyncIO::AsyncIO(AsyncIO&& other) {
m_fd = other.m_fd;
other.m_fd = -1;
m_queue = std::move(other.m_queue);
m_maxBlock = other.m_maxBlock;
}
AsyncIO& AsyncIO::operator=(AsyncIO&& other)
{
if (*this)
{
AsyncIO& AsyncIO::operator=(AsyncIO&& other) {
if (*this) {
aio_cancel(m_fd, nullptr);
close(m_fd);
}
@ -39,8 +32,7 @@ AsyncIO& AsyncIO::operator=(AsyncIO&& other)
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];
if (aio.first.aio_fildes == 0)
return;
@ -52,11 +44,9 @@ void AsyncIO::_waitForOperation(size_t qIdx) const
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;
if (aio.aio_fildes)
{
if (aio.aio_fildes) {
#ifndef NDEBUG
fprintf(stderr, "WARNING: synchronous kabufuda fallback, check access polling\n");
#endif
@ -71,11 +61,9 @@ bool AsyncIO::asyncRead(size_t qIdx, void* buf, size_t length, off_t offset)
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;
if (aio.aio_fildes)
{
if (aio.aio_fildes) {
#ifndef NDEBUG
fprintf(stderr, "WARNING: synchronous kabufuda fallback, check access polling\n");
#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;
}
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];
if (aio.first.aio_fildes == 0)
{
if (aio.first.aio_fildes == 0) {
if (szRet)
*szRet = aio.second;
return ECardResult::READY;
}
switch (aio_error(&aio.first))
{
switch (aio_error(&aio.first)) {
case 0:
aio.second = aio_return(&aio.first);
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;
for (auto it = const_cast<AsyncIO*>(this)->m_queue.begin();
it != const_cast<AsyncIO*>(this)->m_queue.begin() + m_maxBlock;
++it)
{
it != const_cast<AsyncIO*>(this)->m_queue.begin() + m_maxBlock; ++it) {
auto& aio = *it;
if (aio.first.aio_fildes == 0)
continue;
switch (aio_error(&aio.first))
{
switch (aio_error(&aio.first)) {
case 0:
aio.second = aio_return(&aio.first);
aio.first.aio_fildes = 0;
@ -151,11 +132,10 @@ ECardResult AsyncIO::pollStatus() const
return result;
}
void AsyncIO::waitForCompletion() const
{
for (size_t i=0 ; i<m_maxBlock ; ++i)
void AsyncIO::waitForCompletion() const {
for (size_t i = 0; i < m_maxBlock; ++i)
_waitForOperation(i);
const_cast<AsyncIO*>(this)->m_maxBlock = 0;
}
}
} // namespace kabufuda

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,10 +1,8 @@
#include "kabufuda/Util.hpp"
#include <ctime>
namespace kabufuda
{
uint64_t getGCTime()
{
namespace kabufuda {
uint64_t getGCTime() {
time_t sysTime, tzDiff, tzDST;
struct tm* gmTime;
@ -24,12 +22,10 @@ uint64_t getGCTime()
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;
*checksumInv = 0;
for (size_t i = 0; i < len; ++i)
{
for (size_t i = 0; i < len; ++i) {
*checksum += SBig(data[i]);
*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;
}
}
} // namespace kabufuda

View File

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

View File

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

View File

@ -1,8 +1,7 @@
#include "kabufuda/Card.hpp"
#include <iostream>
int main()
{
int main() {
kabufuda::Card mc{"GM8E", "01"};
mc.open(_SYS_STR("test.USA.raw"));
mc.format(kabufuda::ECardSlot::SlotA, kabufuda::ECardSize::Card2043Mb);
@ -11,8 +10,7 @@ int main()
kabufuda::FileHandle 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'};
sprintf(name, "Metroid Prime %i", i);
kabufuda::ECardResult res = mc.createFile(name, kabufuda::BlockSize, f);