Initial CARD stubout

This commit is contained in:
Phillip Stephens 2025-04-16 02:16:45 -07:00
parent 0a4784596c
commit 1cc3040d86
4 changed files with 593 additions and 0 deletions

8
cmake/aurora_card.cmake Normal file
View File

@ -0,0 +1,8 @@
add_library(aurora_card STATIC
lib/dolphin/card.cpp
)
add_library(aurora::card ALIAS aurora_card)
target_link_libraries(aurora_card PUBLIC aurora::core)
target_include_directories(aurora_card PRIVATE include)

57
cmake/kabufuda.cmake Normal file
View File

@ -0,0 +1,57 @@
add_library(kabufuda STATIC
include/kabufuda/Constants.hpp
include/kabufuda/AsyncIO.hpp
include/kabufuda/BlockAllocationTable.hpp lib/kabufuda/BlockAllocationTable.cpp
include/kabufuda/Card.hpp lib/kabufuda/Card.cpp
include/kabufuda/Directory.hpp lib/kabufuda/Directory.cpp
include/kabufuda/File.hpp lib/kabufuda/File.cpp
include/kabufuda/Util.hpp lib/kabufuda/Util.cpp
include/kabufuda/SRAM.hpp lib/kabufuda/SRAM.cpp
)
if (WIN32)
if (MSVC)
target_compile_options(kabufuda PRIVATE
# Enforce various standards compliant behavior.
$<$<COMPILE_LANGUAGE:CXX>:/permissive->
# Enable standard volatile semantics.
$<$<COMPILE_LANGUAGE:CXX>:/volatile:iso>
# Reports the proper value for the __cplusplus preprocessor macro.
$<$<COMPILE_LANGUAGE:CXX>:/Zc:__cplusplus>
# Use latest C++ standard.
$<$<COMPILE_LANGUAGE:CXX>:/std:c++latest>
)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
# Flags for MSVC (not clang-cl)
target_compile_options(kabufuda PRIVATE
# Allow constexpr variables to have explicit external linkage.
$<$<COMPILE_LANGUAGE:CXX>:/Zc:externConstexpr>
# Assume that new throws exceptions, allowing better code generation.
$<$<COMPILE_LANGUAGE:CXX>:/Zc:throwingNew>
)
endif ()
endif ()
target_sources(kabufuda PRIVATE
lib/kabufuda/AsyncIOWin32.cpp
)
elseif (NX OR EMSCRIPTEN)
target_sources(kabufuda PRIVATE
lib/kabufuda/AsyncIONX.cpp
)
else ()
target_sources(kabufuda PRIVATE
lib/kabufuda/AsyncIOPosix.cpp
)
if (NOT APPLE)
target_link_libraries(kabufuda PUBLIC rt)
endif ()
endif ()
target_include_directories(kabufuda PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
add_subdirectory(test)

181
include/dolphin/card.h Normal file
View File

@ -0,0 +1,181 @@
#ifndef _DOLPHIN_CARD
#define _DOLPHIN_CARD
#include "dolphin/types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CARD_ENCODE_ANSI 0u
#define CARD_ENCODE_SJIS 1u
/* Sizes */
#define CARD_WORKAREA_SIZE (5 * 8 * 1024)
#define CARD_READ_SIZE 512
#define CARD_MAX_FILE 127
#define CARD_COMMENT_SIZE 64
#define CARD_FILENAME_MAX 32
#define CARD_ICON_MAX 8
#define CARD_ICON_WIDTH 32
#define CARD_ICON_HEIGHT 32
#define CARD_BANNER_WIDTH 96
#define CARD_BANNER_HEIGHT 32
/* Icon animation */
#define CARD_MODE_NORMAL 0
#define CARD_MODE_FAST 1
#define CARDGetBannerFormat(stat) (((stat)->bannerFormat) & CARD_STAT_BANNER_MASK)
#define CARDGetIconAnim(stat) (((stat)->bannerFormat) & CARD_STAT_ANIM_MASK)
#define CARDGetIconFormat(stat, n) (((stat)->iconFormat >> (2 * (n))) & CARD_STAT_ICON_MASK)
#define CARDGetIconSpeed(stat, n) (((stat)->iconSpeed >> (2 * (n))) & CARD_STAT_SPEED_MASK)
#define CARDSetBannerFormat(stat, f) \
((stat)->bannerFormat = (u8)(((stat)->bannerFormat & ~CARD_STAT_BANNER_MASK) | (f)))
#define CARDSetIconAnim(stat, f) \
((stat)->bannerFormat = (u8)(((stat)->bannerFormat & ~CARD_STAT_ANIM_MASK) | (f)))
#define CARDSetIconFormat(stat, n, f) \
((stat)->iconFormat = \
(u16)(((stat)->iconFormat & ~(CARD_STAT_ICON_MASK << (2 * (n)))) | ((f) << (2 * (n)))))
#define CARDSetIconSpeed(stat, n, f) \
((stat)->iconSpeed = \
(u16)(((stat)->iconSpeed & ~(CARD_STAT_SPEED_MASK << (2 * (n)))) | ((f) << (2 * (n)))))
#define CARDSetIconAddress(stat, addr) ((stat)->iconAddr = (u32)(addr))
#define CARDSetCommentAddress(stat, addr) ((stat)->commentAddr = (u32)(addr))
#define CARDGetFileNo(fileInfo) ((fileInfo)->fileNo)
#define CARD_RESULT_UNLOCKED 1
#define CARD_RESULT_READY 0
#define CARD_RESULT_BUSY -1
#define CARD_RESULT_WRONGDEVICE -2
#define CARD_RESULT_NOCARD -3
#define CARD_RESULT_NOFILE -4
#define CARD_RESULT_IOERROR -5
#define CARD_RESULT_BROKEN -6
#define CARD_RESULT_EXIST -7
#define CARD_RESULT_NOENT -8
#define CARD_RESULT_INSSPACE -9
#define CARD_RESULT_NOPERM -10
#define CARD_RESULT_LIMIT -11
#define CARD_RESULT_NAMETOOLONG -12
#define CARD_RESULT_ENCODING -13
#define CARD_RESULT_CANCELED -14
#define CARD_RESULT_FATAL_ERROR -128
#define CARD_STAT_ICON_NONE 0
#define CARD_STAT_ICON_C8 1
#define CARD_STAT_ICON_RGB5A3 2
#define CARD_STAT_ICON_MASK 3
#define CARD_STAT_BANNER_NONE 0
#define CARD_STAT_BANNER_C8 1
#define CARD_STAT_BANNER_RGB5A3 2
#define CARD_STAT_BANNER_MASK 3
#define CARD_STAT_ANIM_LOOP 0x00
#define CARD_STAT_ANIM_BOUNCE 0x04
#define CARD_STAT_ANIM_MASK 0x04
#define CARD_STAT_SPEED_END 0
#define CARD_STAT_SPEED_FAST 1
#define CARD_STAT_SPEED_MIDDLE 2
#define CARD_STAT_SPEED_SLOW 3
#define CARD_STAT_SPEED_MASK 3
#define CARD_ATTR_PUBLIC 0x04u
#define CARD_ATTR_NO_COPY 0x08u
#define CARD_ATTR_NO_MOVE 0x10u
#define CARD_ATTR_GLOBAL 0x20u
#define CARD_ATTR_COMPANY 0x40u
typedef struct CARDFileInfo {
s32 chan;
s32 fileNo;
s32 offset;
s32 length;
u16 iBlock;
u16 __padding;
} CARDFileInfo;
typedef struct CARDStat {
char fileName[CARD_FILENAME_MAX];
u32 length;
u32 time; // seconds since 01/01/2000 midnight
u8 gameName[4];
u8 company[2];
u8 bannerFormat;
u8 __padding;
u32 iconAddr; // offset to the banner, bannerTlut, icon, iconTlut data set.
u16 iconFormat;
u16 iconSpeed;
u32 commentAddr; // offset to the pair of 32 byte character strings.
u32 offsetBanner;
u32 offsetBannerTlut;
u32 offsetIcon[CARD_ICON_MAX];
u32 offsetIconTlut;
u32 offsetData;
} CARDStat;
typedef void (*CARDCallback)(s32 chan, s32 result);
#ifdef TARGET_PC
void CARDInit(const char* memcardFile, const char* game, const char* maker);
void CARDSetGameAndMaker(s32 chan, const char* game, const char* maker);
#else
void CARDInit(void);
#endif
BOOL CARDGetFastMode(void);
BOOL CARDSetFastMode(BOOL enable);
s32 CARDCheck(s32 chan);
s32 CARDCheckAsync(s32 chan, CARDCallback callback);
s32 CARDCheckEx(s32 chan, s32* xferBytes);
s32 CARDCheckExAsync(s32 chan, s32* xferBytes, CARDCallback callback);
s32 CARDCreate(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo);
s32 CARDCreateAsync(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo,
CARDCallback callback);
s32 CARDDelete(s32 chan, const char* fileName);
s32 CARDDeleteAsync(s32 chan, const char* fileName, CARDCallback callback);
s32 CARDFastDelete(s32 chan, s32 fileNo);
s32 CARDFastDeleteAsync(s32 chan, s32 fileNo, CARDCallback callback);
s32 CARDFastOpen(s32 chan, s32 fileNo, CARDFileInfo* fileInfo);
s32 CARDFormat(s32 chan);
s32 CARDFormatAsync(s32 chan, CARDCallback callback);
s32 CARDFreeBlocks(s32 chan, s32* byteNotUsed, s32* filesNotUsed);
s32 CARDGetAttributes(s32 chan, s32 fileNo, u8* attr);
s32 CARDGetEncoding(s32 chan, u16* encode);
s32 CARDGetMemSize(s32 chan, u16* size);
s32 CARDGetResultCode(s32 chan);
s32 CARDGetSectorSize(s32 chan, u32* size);
s32 CARDGetSerialNo(s32 chan, u64* serialNo);
s32 CARDGetStatus(s32 chan, s32 fileNo, CARDStat* stat);
s32 CARDGetXferredBytes(s32 chan);
s32 CARDMount(s32 chan, void* workArea, CARDCallback detachCallback);
s32 CARDMountAsync(s32 chan, void* workArea, CARDCallback detachCallback,
CARDCallback attachCallback);
s32 CARDOpen(s32 chan, const char* fileName, CARDFileInfo* fileInfo);
BOOL CARDProbe(s32 chan);
s32 CARDProbeEx(s32 chan, s32* memSize, s32* sectorSize);
s32 CARDRename(s32 chan, const char* oldName, const char* newName);
s32 CARDRenameAsync(s32 chan, const char* oldName, const char* newName, CARDCallback callback);
s32 CARDSetAttributesAsync(s32 chan, s32 fileNo, u8 attr, CARDCallback callback);
s32 CARDSetAttributes(s32 chan, s32 fileNo, u8 attr);
s32 CARDSetStatus(s32 chan, s32 fileNo, CARDStat* stat);
s32 CARDSetStatusAsync(s32 chan, s32 fileNo, CARDStat* stat, CARDCallback callback);
s32 CARDUnmount(s32 chan);
s32 CARDGetCurrentMode(s32 chan, u32* mode);
s32 CARDCancel(CARDFileInfo* fileInfo);
s32 CARDClose(CARDFileInfo* fileInfo);
s32 CARDRead(CARDFileInfo* fileInfo, void* addr, s32 length, s32 offset);
s32 CARDReadAsync(CARDFileInfo* fileInfo, void* addr, s32 length, s32 offset,
CARDCallback callback);
s32 CARDWrite(CARDFileInfo* fileInfo, const void* addr, s32 length, s32 offset);
s32 CARDWriteAsync(CARDFileInfo* fileInfo, const void* addr, s32 length, s32 offset,
CARDCallback callback);
#ifdef __cplusplus
}
#endif
#endif // _DOLPHIN_CARD

347
lib/dolphin/card.cpp Normal file
View File

@ -0,0 +1,347 @@
#include "dolphin/card.h"
#include "dolphin/types.h"
#include <kabufuda/Card.hpp>
#include "../logging.hpp"
namespace {
aurora::Module Log("aurora::card");
std::array<kabufuda::Card, 2> CardChannels = {{
kabufuda::Card{nullptr, nullptr},
kabufuda::Card{nullptr, nullptr},
}};
bool Initialized = false;
} // namespace
extern "C" {
void CARDInit(const char* game, const char* maker) {
if (Initialized) {
return;
}
Initialized = true;
Log.info("CARD API Initialized BUILT <{} {}>", __DATE__, __TIME__);
CardChannels[0] = kabufuda::Card{game, maker};
CardChannels[1] = kabufuda::Card{game, maker};
}
void CARDSetGameAndMaker(const s32 chan, const char* game, const char* maker) {
if (chan < 0 || chan >= 2) {
return;
}
CardChannels[chan].setCurrentGame(game);
CardChannels[chan].setCurrentMaker(maker);
}
BOOL CARDGetFastMode() {
// TODO?
return false;
}
BOOL CARDSetFastMode() {
// TODO?
return false;
}
s32 CARDCheck(const s32 chan) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO
return CARD_RESULT_NOCARD;
}
s32 CARDCheckAsync(const s32 chan, CARDCallback callback) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO
return CARD_RESULT_NOCARD;
}
s32 CARDCheckEx(s32 chan, s32* xferBytes) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDCheckExAsync(s32 chan, s32* xferBytes, CARDCallback callback) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDCreate(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDCreateAsync(s32 chan, const char* fileName, u32 size, CARDFileInfo* fileInfo, CARDCallback callback) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDDelete(s32 chan, const char* fileName) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDDeleteAsync(s32 chan, const char* fileName, CARDCallback callback) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDFastDelete(s32 chan, s32 fileNo) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDFastDeleteAsync(s32 chan, s32 fileNo, CARDCallback callback);
{
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDFastOpen(s32 chan, s32 fileNo, CARDFileInfo* fileInfo) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDFormat(s32 chan) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDFormatAsync(s32 chan, CARDCallback callback) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDFreeBlocks(s32 chan, s32* byteNotUsed, s32* filesNotUsed) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDGetAttributes(s32 chan, s32 fileNo, u8* attr) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDGetEncoding(s32 chan, u16* encode) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDGetMemSize(s32 chan, u16* size) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDGetResultCode(s32 chan) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDGetSectorSize(s32 chan, u32* size) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDGetSerialNo(s32 chan, u64* serialNo) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDGetStatus(s32 chan, s32 fileNo, CARDStat* stat) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDGetXferredBytes(s32 chan) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDMount(s32 chan, void* workArea, CARDCallback detachCallback) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDMountAsync(s32 chan, void* workArea, CARDCallback detachCallback, CARDCallback attachCallback) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDOpen(s32 chan, const char* fileName, CARDFileInfo* fileInfo) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
BOOL CARDProbe(s32 chan) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDProbeEx(s32 chan, s32* memSize, s32* sectorSize) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDRename(s32 chan, const char* oldName, const char* newName) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDRenameAsync(s32 chan, const char* oldName, const char* newName, CARDCallback callback) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDSetAttributesAsync(s32 chan, s32 fileNo, u8 attr, CARDCallback callback) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDSetAttributes(s32 chan, s32 fileNo, u8 attr) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDSetStatus(s32 chan, s32 fileNo, CARDStat* stat) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDSetStatusAsync(s32 chan, s32 fileNo, CARDStat* stat, CARDCallback callback) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDUnmount(s32 chan) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDGetCurrentMode(s32 chan, u32* mode) {
if (chan < 0 || chan >= 2) {
return CARD_RESULT_FATAL_ERROR;
}
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDCancel(CARDFileInfo* fileInfo) {
// TODO:ge
return CARD_RESULT_NOCARD;
}
s32 CARDClose(CARDFileInfo* fileInfo) {
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDRead(CARDFileInfo* fileInfo, void* addr, s32 length, s32 offset) {
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDReadAsync(CARDFileInfo* fileInfo, void* addr, s32 length, s32 offset, CARDCallback callback) {
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDWrite(CARDFileInfo* fileInfo, const void* addr, s32 length, s32 offset) {
// TODO:
return CARD_RESULT_NOCARD;
}
s32 CARDWriteAsync(CARDFileInfo* fileInfo, const void* addr, s32 length, s32 offset, CARDCallback callback) {
// TODO:
return CARD_RESULT_NOCARD;
}
}