diff options
Diffstat (limited to 'src/GBACart.h')
-rw-r--r-- | src/GBACart.h | 546 |
1 files changed, 289 insertions, 257 deletions
diff --git a/src/GBACart.h b/src/GBACart.h index a557089..493bf6b 100644 --- a/src/GBACart.h +++ b/src/GBACart.h @@ -1,257 +1,289 @@ -/*
- Copyright 2016-2023 melonDS team
-
- This file is part of melonDS.
-
- melonDS is free software: you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation, either version 3 of the License, or (at your option)
- any later version.
-
- melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with melonDS. If not, see http://www.gnu.org/licenses/.
-*/
-
-#ifndef GBACART_H
-#define GBACART_H
-
-#include <memory>
-#include "types.h"
-#include "Savestate.h"
-
-namespace melonDS::GBACart
-{
-
-enum CartType
-{
- Default = 0x001,
- Game = 0x101,
- GameSolarSensor = 0x102,
- RAMExpansion = 0x201,
-};
-
-// CartCommon -- base code shared by all cart types
-class CartCommon
-{
-public:
- CartCommon();
- virtual ~CartCommon();
-
- virtual u32 Type() const = 0;
- virtual u32 Checksum() const { return 0; }
-
- virtual void Reset();
-
- virtual void DoSavestate(Savestate* file);
-
- virtual void SetupSave(u32 type);
- virtual void LoadSave(const u8* savedata, u32 savelen);
-
- virtual int SetInput(int num, bool pressed);
-
- virtual u16 ROMRead(u32 addr) const;
- virtual void ROMWrite(u32 addr, u16 val);
-
- virtual u8 SRAMRead(u32 addr);
- virtual void SRAMWrite(u32 addr, u8 val);
-
- [[nodiscard]] virtual const u8* GetROM() const { return nullptr; }
- [[nodiscard]] virtual u32 GetROMLength() const { return 0; }
-
- virtual u8* GetSaveMemory() const;
- virtual u32 GetSaveMemoryLength() const;
-};
-
-// CartGame -- regular retail game cart (ROM, SRAM)
-class CartGame : public CartCommon
-{
-public:
- CartGame(u8* rom, u32 len);
- virtual ~CartGame() override;
-
- virtual u32 Type() const override { return CartType::Game; }
- virtual u32 Checksum() const override;
-
- virtual void Reset() override;
-
- virtual void DoSavestate(Savestate* file) override;
-
- virtual void SetupSave(u32 type) override;
- virtual void LoadSave(const u8* savedata, u32 savelen) override;
-
- virtual u16 ROMRead(u32 addr) const override;
- virtual void ROMWrite(u32 addr, u16 val) override;
-
- virtual u8 SRAMRead(u32 addr) override;
- virtual void SRAMWrite(u32 addr, u8 val) override;
-
- [[nodiscard]] const u8* GetROM() const override { return ROM; }
- [[nodiscard]] u32 GetROMLength() const override { return ROMLength; }
-
- virtual u8* GetSaveMemory() const override;
- virtual u32 GetSaveMemoryLength() const override;
-protected:
- virtual void ProcessGPIO();
-
- u8 SRAMRead_EEPROM(u32 addr);
- void SRAMWrite_EEPROM(u32 addr, u8 val);
- u8 SRAMRead_FLASH(u32 addr);
- void SRAMWrite_FLASH(u32 addr, u8 val);
- u8 SRAMRead_SRAM(u32 addr);
- void SRAMWrite_SRAM(u32 addr, u8 val);
-
- u8* ROM;
- u32 ROMLength;
-
- struct
- {
- u16 data;
- u16 direction;
- u16 control;
-
- } GPIO;
-
- enum SaveType
- {
- S_NULL,
- S_EEPROM4K,
- S_EEPROM64K,
- S_SRAM256K,
- S_FLASH512K,
- S_FLASH1M
- };
-
- // from DeSmuME
- struct
- {
- u8 state;
- u8 cmd;
- u8 device;
- u8 manufacturer;
- u8 bank;
-
- } SRAMFlashState;
-
- u8* SRAM;
- u32 SRAMLength;
- SaveType SRAMType;
-};
-
-// CartGameSolarSensor -- Boktai game cart
-class CartGameSolarSensor : public CartGame
-{
-public:
- CartGameSolarSensor(u8* rom, u32 len);
- virtual ~CartGameSolarSensor() override;
-
- virtual u32 Type() const override { return CartType::GameSolarSensor; }
-
- virtual void Reset() override;
-
- virtual void DoSavestate(Savestate* file) override;
-
- virtual int SetInput(int num, bool pressed) override;
-
-private:
- virtual void ProcessGPIO() override;
-
- static const int kLuxLevels[11];
-
- bool LightEdge;
- u8 LightCounter;
- u8 LightSample;
- u8 LightLevel;
-};
-
-// CartRAMExpansion -- RAM expansion cart (DS browser, ...)
-class CartRAMExpansion : public CartCommon
-{
-public:
- CartRAMExpansion();
- ~CartRAMExpansion() override;
-
- virtual u32 Type() const override { return CartType::RAMExpansion; }
-
- void Reset() override;
-
- void DoSavestate(Savestate* file) override;
-
- u16 ROMRead(u32 addr) const override;
- void ROMWrite(u32 addr, u16 val) override;
-
-private:
- u8 RAM[0x800000];
- u16 RAMEnable;
-};
-
-// possible inputs for GBA carts that might accept user input
-enum
-{
- Input_SolarSensorDown = 0,
- Input_SolarSensorUp,
-};
-
-class GBACartSlot
-{
-public:
- GBACartSlot() noexcept = default;
- ~GBACartSlot() noexcept = default;
- void Reset() noexcept;
- void DoSavestate(Savestate* file) noexcept;
- /// Applies the GBACartData to the emulator state and unloads an existing ROM if any.
- /// Upon successful insertion, \c cart will be nullptr and the global GBACart state
- /// (\c CartROM, CartInserted, etc.) will be updated.
- bool InsertROM(std::unique_ptr<CartCommon>&& cart) noexcept;
- bool LoadROM(const u8* romdata, u32 romlen) noexcept;
- void LoadSave(const u8* savedata, u32 savelen) noexcept;
-
- void LoadAddon(int type) noexcept;
-
- void EjectCart() noexcept;
-
- // TODO: make more flexible, support nonbinary inputs
- int SetInput(int num, bool pressed) noexcept;
-
- void SetOpenBusDecay(u16 val) noexcept { OpenBusDecay = val; }
-
- u16 ROMRead(u32 addr) const noexcept;
- void ROMWrite(u32 addr, u16 val) noexcept;
-
- u8 SRAMRead(u32 addr) noexcept;
- void SRAMWrite(u32 addr, u8 val) noexcept;
-
- /// This function is intended to allow frontends to save and load SRAM
- /// without using melonDS APIs.
- /// Modifying the emulated SRAM for any other reason is strongly discouraged.
- /// The returned pointer may be invalidated if the emulator is reset,
- /// or when a new game is loaded.
- /// Consequently, don't store the returned pointer for any longer than necessary.
- /// @returns Pointer to this cart's SRAM if a cart is loaded and supports SRAM, otherwise \c nullptr.
- [[nodiscard]] u8* GetSaveMemory() noexcept { return Cart ? Cart->GetSaveMemory() : nullptr; }
- [[nodiscard]] const u8* GetSaveMemory() const noexcept { return Cart ? Cart->GetSaveMemory() : nullptr; }
-
- /// @returns The length of the buffer returned by ::GetSaveMemory()
- /// if a cart is loaded and supports SRAM, otherwise zero.
- [[nodiscard]] u32 GetSaveMemoryLength() const noexcept { return Cart ? Cart->GetSaveMemoryLength() : 0; }
-private:
- std::unique_ptr<CartCommon> Cart = nullptr;
- u16 OpenBusDecay = 0;
-};
-
-/// Parses the given ROM data and constructs a \c GBACart::CartCommon subclass
-/// that can be inserted into the emulator or used to extract information about the cart beforehand.
-/// @param romdata The ROM data to parse.
-/// The returned cartridge will contain a copy of this data,
-/// so the caller may deallocate \c romdata after this function returns.
-/// @param romlen The length of the ROM data in bytes.
-/// @returns A \c GBACart::CartCommon object representing the parsed ROM,
-/// or \c nullptr if the ROM data couldn't be parsed.
-std::unique_ptr<CartCommon> ParseROM(const u8* romdata, u32 romlen);
-
-}
-
-#endif // GBACART_H
+/* + Copyright 2016-2023 melonDS team + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef GBACART_H +#define GBACART_H + +#include <memory> +#include "types.h" +#include "Savestate.h" + +namespace melonDS::GBACart +{ + +enum CartType +{ + Default = 0x001, + Game = 0x101, + GameSolarSensor = 0x102, + RAMExpansion = 0x201, +}; + +// CartCommon -- base code shared by all cart types +class CartCommon +{ +public: + virtual ~CartCommon() = default; + + [[nodiscard]] u32 Type() const { return CartType; } + virtual u32 Checksum() const { return 0; } + + virtual void Reset(); + + virtual void DoSavestate(Savestate* file); + + virtual int SetInput(int num, bool pressed); + + virtual u16 ROMRead(u32 addr) const; + virtual void ROMWrite(u32 addr, u16 val); + + virtual u8 SRAMRead(u32 addr); + virtual void SRAMWrite(u32 addr, u8 val); + + [[nodiscard]] virtual const u8* GetROM() const { return nullptr; } + [[nodiscard]] virtual u32 GetROMLength() const { return 0; } + + virtual u8* GetSaveMemory() const; + virtual u32 GetSaveMemoryLength() const; + virtual void SetSaveMemory(const u8* savedata, u32 savelen); +protected: + CartCommon(GBACart::CartType type); + friend class GBACartSlot; +private: + GBACart::CartType CartType; +}; + +// CartGame -- regular retail game cart (ROM, SRAM) +class CartGame : public CartCommon +{ +public: + CartGame(const u8* rom, u32 len, const u8* sram, u32 sramlen, GBACart::CartType type = GBACart::CartType::Game); + CartGame(std::unique_ptr<u8[]>&& rom, u32 len, std::unique_ptr<u8[]>&& sram, u32 sramlen, GBACart::CartType type = GBACart::CartType::Game); + ~CartGame() override; + + u32 Checksum() const override; + + void Reset() override; + + void DoSavestate(Savestate* file) override; + + u16 ROMRead(u32 addr) const override; + void ROMWrite(u32 addr, u16 val) override; + + u8 SRAMRead(u32 addr) override; + void SRAMWrite(u32 addr, u8 val) override; + + [[nodiscard]] const u8* GetROM() const override { return ROM.get(); } + [[nodiscard]] u32 GetROMLength() const override { return ROMLength; } + + u8* GetSaveMemory() const override; + u32 GetSaveMemoryLength() const override; + void SetSaveMemory(const u8* savedata, u32 savelen) override; +protected: + virtual void ProcessGPIO(); + + u8 SRAMRead_EEPROM(u32 addr); + void SRAMWrite_EEPROM(u32 addr, u8 val); + u8 SRAMRead_FLASH(u32 addr); + void SRAMWrite_FLASH(u32 addr, u8 val); + u8 SRAMRead_SRAM(u32 addr); + void SRAMWrite_SRAM(u32 addr, u8 val); + + std::unique_ptr<u8[]> ROM; + u32 ROMLength; + + struct + { + u16 data; + u16 direction; + u16 control; + + } GPIO {}; + + enum SaveType + { + S_NULL, + S_EEPROM4K, + S_EEPROM64K, + S_SRAM256K, + S_FLASH512K, + S_FLASH1M + }; + + // from DeSmuME + struct + { + u8 state; + u8 cmd; + u8 device; + u8 manufacturer; + u8 bank; + + } SRAMFlashState {}; + + std::unique_ptr<u8[]> SRAM = nullptr; + u32 SRAMLength = 0; + SaveType SRAMType = S_NULL; +private: + void SetupSave(u32 type); +}; + +// CartGameSolarSensor -- Boktai game cart +class CartGameSolarSensor : public CartGame +{ +public: + CartGameSolarSensor(const u8* rom, u32 len, const u8* sram, u32 sramlen); + CartGameSolarSensor(std::unique_ptr<u8[]>&& rom, u32 len, std::unique_ptr<u8[]>&& sram, u32 sramlen); + + void Reset() override; + + void DoSavestate(Savestate* file) override; + + int SetInput(int num, bool pressed) override; + +protected: + void ProcessGPIO() override; + +private: + static const int kLuxLevels[11]; + + bool LightEdge = false; + u8 LightCounter = 0; + u8 LightSample = 0; + u8 LightLevel = 0; +}; + +// CartRAMExpansion -- RAM expansion cart (DS browser, ...) +class CartRAMExpansion : public CartCommon +{ +public: + CartRAMExpansion(); + ~CartRAMExpansion() override; + + void Reset() override; + + void DoSavestate(Savestate* file) override; + + u16 ROMRead(u32 addr) const override; + void ROMWrite(u32 addr, u16 val) override; + +private: + u8 RAM[0x800000] {}; + u16 RAMEnable = 0; +}; + +// possible inputs for GBA carts that might accept user input +enum +{ + Input_SolarSensorDown = 0, + Input_SolarSensorUp, +}; + +class GBACartSlot +{ +public: + GBACartSlot(std::unique_ptr<CartCommon>&& cart = nullptr) noexcept; + ~GBACartSlot() noexcept = default; + void Reset() noexcept; + void DoSavestate(Savestate* file) noexcept; + + /// Ejects the cart in the GBA slot (if any) + /// and inserts the given one. + /// + /// To insert a cart that does not require ROM data + /// (such as the RAM expansion pack), + /// create it manually with std::make_unique and pass it here. + /// + /// @param cart Movable \c unique_ptr to the GBA cart object. + /// May be \c nullptr, in which case the cart slot remains empty. + /// @post \c cart is \c nullptr and the underlying object + /// is moved into the cart slot. + void SetCart(std::unique_ptr<CartCommon>&& cart) noexcept; + [[nodiscard]] CartCommon* GetCart() noexcept { return Cart.get(); } + [[nodiscard]] const CartCommon* GetCart() const noexcept { return Cart.get(); } + + void LoadAddon(int type) noexcept; + + /// @return The cart that was in the cart slot if any, + /// or \c nullptr if the cart slot was empty. + std::unique_ptr<CartCommon> EjectCart() noexcept; + + // TODO: make more flexible, support nonbinary inputs + int SetInput(int num, bool pressed) noexcept; + + void SetOpenBusDecay(u16 val) noexcept { OpenBusDecay = val; } + + u16 ROMRead(u32 addr) const noexcept; + void ROMWrite(u32 addr, u16 val) noexcept; + + u8 SRAMRead(u32 addr) noexcept; + void SRAMWrite(u32 addr, u8 val) noexcept; + + /// This function is intended to allow frontends to save and load SRAM + /// without using melonDS APIs. + /// Modifying the emulated SRAM for any other reason is strongly discouraged. + /// The returned pointer may be invalidated if the emulator is reset, + /// or when a new game is loaded. + /// Consequently, don't store the returned pointer for any longer than necessary. + /// @returns Pointer to this cart's SRAM if a cart is loaded and supports SRAM, otherwise \c nullptr. + [[nodiscard]] u8* GetSaveMemory() noexcept { return Cart ? Cart->GetSaveMemory() : nullptr; } + [[nodiscard]] const u8* GetSaveMemory() const noexcept { return Cart ? Cart->GetSaveMemory() : nullptr; } + + /// Sets the loaded cart's SRAM. + /// Does nothing if no cart is inserted + /// or the inserted cart doesn't support SRAM. + /// + /// @param savedata Buffer containing the raw contents of the SRAM. + /// The contents of this buffer are copied into the cart slot, + /// so the caller may dispose of it after this method returns. + /// @param savelen The length of the buffer in \c savedata, in bytes. + void SetSaveMemory(const u8* savedata, u32 savelen) noexcept; + + /// @returns The length of the buffer returned by ::GetSaveMemory() + /// if a cart is loaded and supports SRAM, otherwise zero. + [[nodiscard]] u32 GetSaveMemoryLength() const noexcept { return Cart ? Cart->GetSaveMemoryLength() : 0; } +private: + std::unique_ptr<CartCommon> Cart = nullptr; + u16 OpenBusDecay = 0; +}; + +/// Parses the given ROM data and constructs a \c GBACart::CartCommon subclass +/// that can be inserted into the emulator or used to extract information about the cart beforehand. +/// @param romdata The ROM data to parse. +/// The returned cartridge will contain a copy of this data, +/// so the caller may deallocate \c romdata after this function returns. +/// @param romlen The length of the ROM data in bytes. +/// @returns A \c GBACart::CartCommon object representing the parsed ROM, +/// or \c nullptr if the ROM data couldn't be parsed. +std::unique_ptr<CartCommon> ParseROM(const u8* romdata, u32 romlen); +std::unique_ptr<CartCommon> ParseROM(std::unique_ptr<u8[]>&& romdata, u32 romlen); +std::unique_ptr<CartCommon> ParseROM(const u8* romdata, u32 romlen, const u8* sramdata, u32 sramlen); + +/// @param romdata The ROM data to parse. Will be moved-from. +/// @param romlen Length of romdata in bytes. +/// @param sramdata The save data to add to the cart. +/// May be \c nullptr, in which case the cart will have no save data. +/// @param sramlen Length of sramdata in bytes. +/// May be zero, in which case the cart will have no save data. +/// @return Unique pointer to the parsed GBA cart, +/// or \c nullptr if there was an error. +std::unique_ptr<CartCommon> ParseROM(std::unique_ptr<u8[]>&& romdata, u32 romlen, std::unique_ptr<u8[]>&& sramdata, u32 sramlen); + +} + +#endif // GBACART_H |