openMSX
CartridgeSlotManager.hh
Go to the documentation of this file.
1#ifndef CARTRIDGESLOTMANAGER_HH
2#define CARTRIDGESLOTMANAGER_HH
3
4#include "RecordedCommand.hh"
5#include "MSXMotherBoard.hh"
6#include "InfoTopic.hh"
7
8#include "TclObject.hh"
9#include "narrow.hh"
10#include "ranges.hh"
11#include "strCat.hh"
12
13#include <array>
14#include <cassert>
15#include <optional>
16#include <string_view>
17
18namespace openmsx {
19
20class HardwareConfig;
21
23{
24public:
25 static constexpr unsigned MAX_SLOTS = 16 + 4;
26
27public:
28 explicit CartridgeSlotManager(MSXMotherBoard& motherBoard);
30
31 static int getSlotNum(std::string_view slot);
32
33 void createExternalSlot(int ps);
34 void createExternalSlot(int ps, int ss);
35 void removeExternalSlot(int ps);
36 void removeExternalSlot(int ps, int ss);
37 void testRemoveExternalSlot(int ps, const HardwareConfig& allowed) const;
38 void testRemoveExternalSlot(int ps, int ss, const HardwareConfig& allowed) const;
39
40 // Query/allocate/free external slots
41 void getSpecificSlot(unsigned slot, int& ps, int& ss) const;
42 void getAnyFreeSlot(int& ps, int& ss) const;
43 void allocateSlot(int ps, int ss, const HardwareConfig& hwConfig);
44 void freeSlot(int ps, int ss, const HardwareConfig& hwConfig);
45
46 // Allocate/free external primary slots
47 [[nodiscard]] int allocateAnyPrimarySlot(const HardwareConfig& hwConfig);
48 [[nodiscard]] int allocateSpecificPrimarySlot(unsigned slot, const HardwareConfig& hwConfig);
49 void freePrimarySlot(int ps, const HardwareConfig& hwConfig);
50
51 [[nodiscard]] bool isExternalSlot(int ps, int ss, bool convert) const;
52
53 // TODO allow to query more info like cart or ext inserted ...
54 [[nodiscard]] bool slotExists(unsigned slot) const {
55 assert(slot < MAX_SLOTS);
56 return slots[slot].exists();
57 }
58 [[nodiscard]] int getNumberOfSlots() const {
59 return narrow<int>(ranges::count_if(slots, &Slot::exists));
60 }
61 [[nodiscard]] const HardwareConfig* getConfigForSlot(unsigned slot) const {
62 assert(slot < MAX_SLOTS);
63 return slots[slot].config;
64 }
65 [[nodiscard]] std::pair<int, int> getPsSs(unsigned slot) const {
66 assert(slot < MAX_SLOTS);
67 return {slots[slot].ps, slots[slot].ss};
68 }
69 [[nodiscard]] std::string getPsSsString(unsigned slot) const {
70 auto [ps, ss] = getPsSs(slot);
71 std::string result = strCat(ps);
72 if (ss != -1) strAppend(result, '-', ss);
73 return result;
74 }
75 [[nodiscard]] std::optional<unsigned> findSlotWith(const HardwareConfig& config) const {
76 for (auto slot : xrange(MAX_SLOTS)) {
77 if (slots[slot].config == &config) return slot;
78 }
79 return {};
80 }
81
82private:
83 [[nodiscard]] unsigned getSlot(int ps, int ss) const;
84
85private:
86 MSXMotherBoard& motherBoard;
87
88 class CartCmd final : public RecordedCommand {
89 public:
90 CartCmd(CartridgeSlotManager& manager, MSXMotherBoard& motherBoard,
91 std::string_view commandName);
92 void execute(std::span<const TclObject> tokens, TclObject& result,
93 EmuTime::param time) override;
94 [[nodiscard]] std::string help(std::span<const TclObject> tokens) const override;
95 void tabCompletion(std::vector<std::string>& tokens) const override;
96 [[nodiscard]] bool needRecord(std::span<const TclObject> tokens) const override;
97 private:
98 const HardwareConfig* getExtensionConfig(std::string_view cartName);
99 CartridgeSlotManager& manager;
100 CliComm& cliComm;
101 } cartCmd;
102
103 struct CartridgeSlotInfo final : InfoTopic {
104 explicit CartridgeSlotInfo(InfoCommand& machineInfoCommand);
105 void execute(std::span<const TclObject> tokens,
106 TclObject& result) const override;
107 [[nodiscard]] std::string help(std::span<const TclObject> tokens) const override;
108 } extSlotInfo;
109
110 struct Slot : public MediaInfoProvider {
111 ~Slot();
112
113 // MediaInfoProvider
114 void getMediaInfo(TclObject& result) override;
115
116 [[nodiscard]] bool exists() const;
117 [[nodiscard]] bool used(const HardwareConfig* allowed = nullptr) const;
118
119 std::optional<CartCmd> cartCommand;
120 std::optional<ExtCmd> extCommand;
121 const HardwareConfig* config = nullptr;
122 unsigned useCount = 0;
123 int ps = 0;
124 int ss = 0;
125 MSXCPUInterface* cpuInterface;
126 };
127 std::array<Slot, MAX_SLOTS> slots;
128};
129
130} // namespace openmsx
131
132#endif
void getAnyFreeSlot(int &ps, int &ss) const
static int getSlotNum(std::string_view slot)
void testRemoveExternalSlot(int ps, const HardwareConfig &allowed) const
static constexpr unsigned MAX_SLOTS
void getSpecificSlot(unsigned slot, int &ps, int &ss) const
bool isExternalSlot(int ps, int ss, bool convert) const
void freeSlot(int ps, int ss, const HardwareConfig &hwConfig)
std::pair< int, int > getPsSs(unsigned slot) const
std::optional< unsigned > findSlotWith(const HardwareConfig &config) const
int allocateAnyPrimarySlot(const HardwareConfig &hwConfig)
int allocateSpecificPrimarySlot(unsigned slot, const HardwareConfig &hwConfig)
std::string getPsSsString(unsigned slot) const
void allocateSlot(int ps, int ss, const HardwareConfig &hwConfig)
const HardwareConfig * getConfigForSlot(unsigned slot) const
void freePrimarySlot(int ps, const HardwareConfig &hwConfig)
bool slotExists(unsigned slot) const
Commands that directly influence the MSX state should send and events so that they can be recorded by...
bool exists(zstring_view filename)
Does this file (directory) exists?
This file implemented 3 utility functions:
Definition Autofire.cc:9
auto count_if(InputRange &&range, UnaryPredicate pred)
Definition ranges.hh:345
std::string strCat()
Definition strCat.hh:703
void strAppend(std::string &result, Ts &&...ts)
Definition strCat.hh:752
constexpr auto xrange(T e)
Definition xrange.hh:132