#ifndef CARD_H #define CARD_H #include #include #include #ifdef __cplusplus extern "C" { #endif /*----------------------------------------------------------------------------- -- macros -----------------------------------------------------------------------------*/ #define MAX_CARD_RETRIES 10 #define LPKM_BACKUP_TYPE_4MBIT_FLASH 0xFF1302 /*----------------------------------------------------------------------------- -- type definitions -----------------------------------------------------------------------------*/ typedef void (*CardCallbackFn)(void*); /*----------------------------------------------------------------------------- -- enums -----------------------------------------------------------------------------*/ typedef enum CardResult { RESULT_SUCCESS = 0, RESULT_FAIL = 1, RESULT_INVALID_PARAM = 2, RESULT_UNSUPPORTED = 3, RESULT_TIMEOUT = 4, RESULT_ERROR = 5, RESULT_NO_RESPONSE = 6, RESULT_CANCELED = 7 } CardResult; typedef enum CardRequest { REQUEST_INIT = 0, REQUEST_ACK = 1, REQUEST_IDENTIFY = 2, REQUEST_READ_ID = 3, REQUEST_READ_ROM = 4, REQUEST_WRITE_ROM = 5, REQUEST_READ_BACKUP = 6, REQUEST_WRITE_BACKUP = 7, REQUEST_PROGRAM_BACKUP = 8, REQUEST_VERIFY_BACKUP = 9, REQUEST_ERASE_PAGE_BACKUP = 10, REQUEST_ERASE_SECTOR_BACKUP = 11, REQUEST_ERASE_CHIP_BACKUP = 12, REQUEST_READ_STATUS = 13, REQUEST_WRITE_STATUS = 14, REQUEST_ERASE_SUBSECTOR_BACKUP = 15, REQUEST_MAX = 16 } CardRequest; typedef enum CardRequestMode { REQUEST_MODE_RECV = 0, REQUEST_MODE_SEND = 1, REQUEST_MODE_SEND_VERIFY = 2, REQUEST_MODE_SPECIAL = 3 } CardRequestMode; /*----------------------------------------------------------------------------- -- structs -----------------------------------------------------------------------------*/ typedef struct RomRegion { u32 offset; u32 length; } RomRegion; /*----------------------------------------------------------------------------- -- types -----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------- -- inline Functions -----------------------------------------------------------------------------*/ _INLINE bool ReadCardBackupHw(u32 src, void* dest, u32 size, CardCallbackFn cb, void* cb_arg, bool is_async) { return CARDi_RequestStreamCommand((u32)src, (u32)dest, size, cb, cb_arg, is_async, REQUEST_READ_BACKUP, 1, REQUEST_MODE_RECV); } /* ReadSave args: src: offset to start reading at in the save- 0 if you're reading from the top dest: buffer to read into size: read size cb: callback function- this is the function that will be run if the save read completes successfully. use NULL if you don't need one. cb_arg: callback function argument- ptr to the argument for the callback function. also NULL if unused. */ _INLINE bool ReadSave(u32 src, void* dest, u32 size, CardCallbackFn cb, void* cb_arg) { return ReadCardBackupHw(src, dest, size, cb, cb_arg, TRUE); } /* to use: bool g_save_read = FALSE; void SetSavReadFlag() { save_read = TRUE; } const char* sav_src = "save_src.cpp"; void* save_buf = allocateBlockFromExpHeap(GRP_ID_SAV_BLK, BLK_LEN, TRUE, sav_src, SAV_BLK_LOAD_MK); bool save_result = ReadSave(0 + block_address_you_use_if_any, save_buf, BLK_LEN, SetSavReadFlag, NULL); */ //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- _INLINE void WriteCardBackupHw(u32 dest, const void* src, u32 size, CardCallbackFn cb, void* cb_arg, bool is_async) { CARDi_RequestStreamCommand((u32)src, (u32)dest, size, cb, cb_arg, is_async, REQUEST_WRITE_BACKUP, MAX_CARD_RETRIES, REQUEST_MODE_SEND_VERIFY); } /* WriteSave args: dest: offset into the save to write src: address in memory to start writing from size: write size cb: callback function- this is the function that will be run if the save read completes successfully. use NULL if you don't need one. cb_arg: callback function argument- ptr to the argument for the callback function. also NULL if unused. */ _INLINE void WriteSave(u32 dest, const void* src, u32 size, CallbackFn cb, void* cb_arg) { WriteCardBackupHw(dest, src, size, cb, cb_arg, TRUE); } /*----------------------------------------------------------------------------- -- function declarations -----------------------------------------------------------------------------*/ bool CARD_IsEnabled(); void CARD_CheckEnabled(); void CARD_Enable(bool enable); CardResult CARD_GetResultCode(); const u8* CARD_GetRomHeader(); void CARD_LockRom(u16 lock_id); // lock access to card rom - you call OS_GetLockID first to get the lock id to use here, lock_id is basically the owner of the current lock/unlock action void CARD_UnlockRom(u16 lock_id); // once you unlock access, use the same os lock id void CARD_LockBackup(u16 lock_id); // lock access to card backup - call OS_GetLockID first void CARD_UnlockBackup(u16 lock_id); bool CARDi_RequestStreamCommand(u32 src, u32 dst, u32 len, CallbackFn callback, void *arg, BOOL is_async, CardRequest req_type, int req_retry, CardRequestMode req_mode); bool CARD_IdentifyBackup(u32 backup_type); // you CAN use this, but you don't have to. the type of backup is pre-identified by gamefreak. u32 CARD_GetBackupSectorSize(); bool CARD_WaitBackupAsync(); bool CARD_TryWaitBackupAsync(); void CARD_CancelBackupAsync(); // kill the currently running async process for the card void CARD_WaitRomAsync(); bool CARD_IsPulledOut(); #ifdef __cplusplus } /* extern "C"*/ #endif #endif // CARD_H /* full example of reading from a save: bool g_save_read = FALSE; void ReadInSavBlk(u32 read_size, void* data_dest, u32 read_offset) { s32 id = OS_GetLockID(); if(id == LOCK_ID_ERR) { assert_fail(); } CARD_LockBackup((u16)id); UnsetSavReadFlag(); ReadSave(read_offset, data_dest, read_size, SetSavReadFlag, NULL); CARD_UnlockBackup((u16)id); OS_ReleaseLockID((u16)id); } void SetSavReadFlag() { save_read = TRUE; } void UnsetSavReadFlag() { save_read = FALSE; } */ // NOTE: you do not have to use a callback. this is just a demonstration of how to.