// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin // SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0) #pragma once #include "common/bitfield.h" #include "controller.h" #include "memory_card_image.h" #include #include #include #include class TimingEvent; class MemoryCard final { public: MemoryCard(); ~MemoryCard(); static constexpr u32 STATE_SIZE = 1 + 1 + 2 + 1 + 1 + 1 + MemoryCardImage::DATA_SIZE + 1; static std::string SanitizeGameTitleForFileName(const std::string_view& name); static std::unique_ptr Create(); static std::unique_ptr Open(std::string_view filename); const MemoryCardImage::DataArray& GetData() const { return m_data; } MemoryCardImage::DataArray& GetData() { return m_data; } const std::string& GetFilename() const { return m_filename; } void SetFilename(std::string filename) { m_filename = std::move(filename); } void Reset(); bool DoState(StateWrapper& sw); void ResetTransferState(); bool Transfer(const u8 data_in, u8* data_out); void Format(); private: enum : u32 { // save in three seconds, that should be long enough for everything to finish writing SAVE_DELAY_IN_SECONDS = 5, }; union FLAG { u8 bits; BitField no_write_yet; BitField write_error; }; enum class State : u8 { Idle, Command, ReadCardID1, ReadCardID2, ReadAddressMSB, ReadAddressLSB, ReadACK1, ReadACK2, ReadConfirmAddressMSB, ReadConfirmAddressLSB, ReadData, ReadChecksum, ReadEnd, WriteCardID1, WriteCardID2, WriteAddressMSB, WriteAddressLSB, WriteData, WriteChecksum, WriteACK1, WriteACK2, WriteEnd, }; static TickCount GetSaveDelayInTicks(); bool LoadFromFile(); bool SaveIfChanged(bool display_osd_message); void QueueFileSave(); std::unique_ptr m_save_event; State m_state = State::Idle; FLAG m_FLAG = {}; u16 m_address = 0; u8 m_sector_offset = 0; u8 m_checksum = 0; u8 m_last_byte = 0; bool m_changed = false; MemoryCardImage::DataArray m_data{}; std::string m_filename; };