commit 3f70c1b73aaf65b9c34fce2695313e37e160935d Author: Phillip Stephens Date: Fri Mar 25 21:26:51 2016 -0700 Initial Commit diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ec3be8a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.0) +project(Card) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wno-multichar -fno-exceptions") +include_directories(include) + +add_library(card STATIC + include/Card.hpp src/Card.cpp) + +add_subdirectory(test) diff --git a/include/Card.hpp b/include/Card.hpp new file mode 100644 index 0000000..e8a0b3d --- /dev/null +++ b/include/Card.hpp @@ -0,0 +1,142 @@ +#ifndef __CARD_HPP__ +#define __CARD_HPP__ + +#include +#include +#include +#include + +namespace card +{ +uint32_t constexpr BlockSize = 0x2000; +uint32_t constexpr MaxFiles = 127; + +enum class EPermissions : uint8_t +{ +}; +enum class EBannerFlags : uint8_t +{ +}; + +class File +{ + union + { + struct + { + uint8_t m_id[4]; + uint8_t m_maker[2]; + uint8_t m_reserved; + uint8_t m_bannerFlags; + char m_filename[0x20]; + uint32_t m_modifiedTime; + uint8_t m_permissions; + int8_t m_copyCounter; + uint16_t m_firstBlock; + uint16_t m_reserved2; + uint32_t m_commentAddr; + }; + uint8_t __raw[0x40] = {0xFF}; + }; +public: + File() {} + File(char data[0x40]) + { + memcpy(__raw, data, 0x40); + } + File(const char* filename) + { + memset(m_filename, 0, 0x20); + memcpy(m_filename, filename, 0x20); + } + ~File() {} +}; + +class BlockAllocationTable +{ + union + { + struct + { + uint16_t m_checksum; + uint16_t m_checksumInv; + uint16_t m_freeBlocks; + uint16_t m_lastAllocated; + uint16_t m_map[0xFFB]; + }; + uint8_t __raw[BlockSize] = {0xFF}; + }; +public: + BlockAllocationTable() {} + BlockAllocationTable(uint8_t data[BlockSize]); + ~BlockAllocationTable() {} +}; + +class Directory +{ + union + { + struct + { + File m_files[MaxFiles]; + uint8_t __padding[0x3a]; + uint16_t m_updateCounter; + uint16_t m_checksum; + uint16_t m_checksumInv; + }; + uint8_t __raw[BlockSize] = {0xFF}; + }; +public: + Directory() {} + Directory(uint8_t data[BlockSize]) + { + memcpy(__raw, data, BlockSize); + } + ~Directory() {} +}; + +class Card +{ + union + { + struct + { + std::string m_filepath; + uint8_t m_serial[12]; + uint64_t m_formatTime; + int32_t m_sramBias; + uint32_t m_sramLanguage; + uint32_t m_unknown; + uint16_t m_deviceId; /* 0 for Slot A, 1 for Slot B */ + uint16_t m_sizeMb; + uint16_t m_encoding; + uint8_t __padding[468]; + uint16_t m_updateCounter; + uint16_t m_checksum; + uint16_t m_checksumInv; + }; + uint8_t __raw[BlockSize] = {0xFF}; + }; + Directory m_dir; + Directory m_dirBackup; + Directory* m_dirInUse = nullptr; + BlockAllocationTable m_bat; + BlockAllocationTable m_batBackup; + BlockAllocationTable* m_batInUse = nullptr; + + char m_game[4]; /*!< The current selected game, if null requests return the first matching filename */ + char m_maker[2]; /*!< The current selected maker, if null requests return the first matching filename */ +public: + Card(); + Card(const std::string& filepath, const char* game = nullptr, const char* maker=nullptr); + ~Card() {} + + void setGame(const char* id); + const uint8_t* getGame() const; + void setMaker(const char* maker); + const uint8_t* getMaker() const; +}; +} + +#endif // __CARD_HPP__ + diff --git a/src/Card.cpp b/src/Card.cpp new file mode 100644 index 0000000..6945427 --- /dev/null +++ b/src/Card.cpp @@ -0,0 +1,46 @@ +#include "Card.hpp" +#include + +namespace card +{ +Card::Card() +{ + memset(__raw, 0xFF, BlockSize); +} + +Card::Card(const std::string &filepath, const char* game, const char* maker) + : m_filepath(filepath) +{ + memset(__raw, 0xFF, BlockSize); + if (game) + memcpy(m_game, game, 4); + if (maker) + memcpy(m_maker, maker, 2); +} + +void Card::setGame(const char* id) +{ + if (strlen(id) != 4) + return; + + memcpy(m_game, id, 4); +} + +const uint8_t* Card::getGame() const +{ + return reinterpret_cast(m_game); +} + +void Card::setMaker(const char* maker) +{ + if (strlen(maker) != 2) + return; + + memcpy(m_maker, maker, 2); +} + +const uint8_t* Card::getMaker() const +{ + return reinterpret_cast(m_maker); +} +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..9c8ab31 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,6 @@ + +add_executable(cardtest + main.cpp) + +target_link_libraries(cardtest + card) diff --git a/test/main.cpp b/test/main.cpp new file mode 100644 index 0000000..29c48c6 --- /dev/null +++ b/test/main.cpp @@ -0,0 +1,12 @@ +#include "Card.hpp" +#include + +int main() +{ + card::Card card{"test.mc"}; + card.setGame("GM8E"); + card.setMaker("01"); + printf("Selected Game ID: %.4s\n", card.getGame()); + printf("Selected Maker ID: %.2s\n", card.getMaker()); + return 0; +}