mirror of
https://github.com/AxioDL/kabufuda.git
synced 2025-07-04 04:05:51 +00:00
New code style refactor
This commit is contained in:
parent
a1e2242691
commit
f126245eef
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
@ -257,15 +244,11 @@ uint64_t getGCTime();
|
|||||||
#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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -9,4 +9,3 @@
|
|||||||
#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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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,8 +792,7 @@ 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);
|
||||||
}
|
}
|
||||||
@ -891,20 +802,17 @@ void Card::format(ECardSlot id, ECardSize size, EEncoding encoding)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -12,8 +12,7 @@
|
|||||||
* 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;
|
||||||
@ -23,8 +22,7 @@ void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen)
|
|||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user