mirror of
https://github.com/doldecomp/sms.git
synced 2026-11-09 09:59:44 -10:00
140 lines
3.6 KiB
C++
140 lines
3.6 KiB
C++
#ifndef GC2D_CARD_MANAGER_HPP
|
|
#define GC2D_CARD_MANAGER_HPP
|
|
|
|
#include <dolphin/card.h>
|
|
|
|
class JSUMemoryInputStream;
|
|
class JSUMemoryOutputStream;
|
|
struct HeaderData;
|
|
struct TCardSector;
|
|
|
|
struct TCardBookmarkInfo {
|
|
/* 0x0 */ int unk0;
|
|
/* 0x4 */ u32 unk4;
|
|
/* 0x8 */ u64 unk8;
|
|
/* 0x10 */ u64 unk10;
|
|
/* 0x18 */ u32 unk18;
|
|
/* 0x1C */ u16 unk1C;
|
|
/* 0x1E */ u16 unk1E;
|
|
};
|
|
|
|
/**
|
|
* @brief Async wrapper around the CARD SDK API.
|
|
* @details Essentially, an SPSC two-way channel between the main thread and a
|
|
* worker thread that performs CARD operations. It also performs basic error
|
|
* checking in case of data loss.
|
|
*/
|
|
class TCardManager {
|
|
public:
|
|
struct TCriteria {
|
|
TCriteria() { mState = STATE_UNREAD; }
|
|
|
|
enum TEBlockStat {
|
|
STATE_UNREAD = 0,
|
|
STATE_EMPTY = 1,
|
|
STATE_CHECKSUM_BAD = 2,
|
|
STATE_VALID = 3,
|
|
};
|
|
|
|
void set(TEBlockStat, u32, const void*);
|
|
void setEmpty();
|
|
|
|
// fabricated
|
|
TEBlockStat getState() const { return mState; }
|
|
u32 getWriteCount() const { return mWriteCount; }
|
|
void* getPreviewBytes() { return mPreviewBytes; }
|
|
|
|
/* 0x0 */ TEBlockStat mState;
|
|
/* 0x4 */ u32 mWriteCount;
|
|
/* 0x8 */ u8 mPreviewBytes[0x20]; // first 0x20 bytes of the sector
|
|
};
|
|
|
|
static s32 decideUseSector(TCriteria*);
|
|
static s32 getLoadIndex(TCriteria*);
|
|
static s32 getWriteCount(TCriteria*);
|
|
static void copyTo(TCriteria*, TCardBookmarkInfo*);
|
|
|
|
TCardManager(void* sector_work_area, void* card_work_area, s32 channel,
|
|
s32 thread_prio, void* thread_stack, u32 thread_stack_size);
|
|
~TCardManager();
|
|
|
|
u32 probe();
|
|
s32 unmount();
|
|
void format();
|
|
void createFile();
|
|
void getBookmarkInfos(TCardBookmarkInfo* out_infos);
|
|
|
|
void readBlock(u32 index);
|
|
void writeBlock(u32 index);
|
|
|
|
void getReadStream(JSUMemoryInputStream* stream);
|
|
void getWriteStream(JSUMemoryOutputStream* stream);
|
|
|
|
void readOptionBlock();
|
|
void writeOptionBlock();
|
|
|
|
void getOptionReadStream(JSUMemoryInputStream* stream);
|
|
void getOptionWriteStream(JSUMemoryOutputStream* stream);
|
|
|
|
s32 getLastStatus();
|
|
|
|
s32 cmdLoop();
|
|
|
|
// fabricated
|
|
void setIcons(const void* icons) { mIcons = icons; }
|
|
void setBanner(const void* banner) { mBanner = banner; }
|
|
|
|
private:
|
|
void issue(s32 command);
|
|
s32 probe_();
|
|
s32 mount_(bool);
|
|
s32 unmount_();
|
|
s32 format_();
|
|
s32 createFile_();
|
|
s32 filledInitData_(CARDFileInfo* file);
|
|
s32 setCardStat_(CARDFileInfo* file);
|
|
void buildHeader_(HeaderData* header);
|
|
s32 open_(CARDFileInfo* file);
|
|
s32 getBookmarkInfos_();
|
|
s32 readBlock_(u32 index);
|
|
s32 readOptionBlock_();
|
|
s32 writeBlock_(u32 index);
|
|
s32 writeOptionBlock_();
|
|
s32 writeCardSector_(CARDFileInfo* file, s32 index, TCardSector* sector,
|
|
TCriteria* criteria);
|
|
|
|
private:
|
|
enum {
|
|
CMD_NONE = 0,
|
|
CMD_FORMAT = 1,
|
|
CMD_CREATE = 2,
|
|
CMD_BOOKMARK_SCAN = 3,
|
|
CMD_READ_BLOCK = 5,
|
|
CMD_WRITE_BLOCK = 6,
|
|
CMD_READ_OPTION = 7,
|
|
CMD_WRITE_OPTION = 8,
|
|
CMD_THREAD_EXIT = 9,
|
|
};
|
|
|
|
/* 0x0 */ s32 mChannel;
|
|
/* 0x4 */ const void* mIcons;
|
|
/* 0x8 */ const void* mBanner;
|
|
/* 0xC */ TCriteria mSectorCriteria[7];
|
|
/* 0x124 */ bool mNeedsInit;
|
|
/* 0x125 */ bool mIsMounted;
|
|
/* 0x126 */ bool mFsCheckedOk;
|
|
/* 0x128 */ u32 mLastStatus; // guarded by mMutex
|
|
/* 0x12C */ void* mCardMountWorkArea;
|
|
/* 0x130 */ void* mSector;
|
|
/* 0x134 */ char unk134[0x4];
|
|
/* 0x138 */ OSThread mWorkerThread;
|
|
/* 0x448 */ s32 mPendingCommand; // guarded by mMutex
|
|
/* 0x44C */ OSMutex mMutex;
|
|
/* 0x464 */ OSCond mCommandIsPending;
|
|
/* 0x46C */ TCardBookmarkInfo* mGetBookmarkInfosArg; // guarded by mMutex
|
|
/* 0x470 */ char unk470[0x4];
|
|
/* 0x474 */ u32 mReadWriteBlockArg; // guarded by mMutex
|
|
};
|
|
|
|
#endif
|