OXYGENHUB
◆ main openmsx / src / CartridgeSlotManager.hh
4.7 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef CARTRIDGESLOTMANAGER_HH
2
#define CARTRIDGESLOTMANAGER_HH
3
4
#include "InfoTopic.hh"
5
#include "MSXMotherBoard.hh"
6
#include "RecordedCommand.hh"
7
#include "TclObject.hh"
8
9
#include "narrow.hh"
10
#include "strCat.hh"
11
12
#include <algorithm>
13
#include <array>
14
#include <cassert>
15
#include <optional>
16
#include <string_view>
17
18
namespace openmsx {
19
20
class HardwareConfig;
21
22
class CartridgeSlotManager
23
{
24
public:
25
	static constexpr unsigned MAX_SLOTS = 16 + 4;
26
27
public:
28
	explicit CartridgeSlotManager(MSXMotherBoard& motherBoard);
29
	~CartridgeSlotManager();
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>(std::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
		return strCat(ps, strCat_if(ss != -1, '-', ss));
72
	}
73
	[[nodiscard]] std::optional<unsigned> findSlotWith(const HardwareConfig& config) const {
74
		for (auto slot : xrange(MAX_SLOTS)) {
75
			if (slots[slot].config == &config) return slot;
76
		}
77
		return {};
78
	}
79
	/** The external slot at (ps, ss), if there is one. With 'convert' a
80
	  * primary slot that isn't expanded (ss == -1) also matches ss == 0. */
81
	[[nodiscard]] std::optional<unsigned> findSlot(int ps, int ss, bool convert) const {
82
		for (auto slot : xrange(MAX_SLOTS)) {
83
			if (!slots[slot].exists()) continue;
84
			int slotSs = (convert && (slots[slot].ss == -1)) ? 0 : slots[slot].ss;
85
			if ((slots[slot].ps == ps) && (slotSs == ss)) return slot;
86
		}
87
		return {};
88
	}
89
90
private:
91
	[[nodiscard]] const HardwareConfig* getExtensionConfig(std::string_view cartName) const;
92
	[[nodiscard]] unsigned getSlot(int ps, int ss) const;
93
	std::string insertCartridge(std::string_view cartName, std::string_view romName, std::span<const TclObject> options);
94
	void removeCartridge(std::string_view cartName);
95
96
private:
97
	MSXMotherBoard& motherBoard;
98
99
	class CartCmd final : public RecordedCommand {
100
	public:
101
		CartCmd(CartridgeSlotManager& manager, MSXMotherBoard& motherBoard,
102
			std::string_view commandName);
103
		void execute(std::span<const TclObject> tokens, TclObject& result,
104
			     EmuTime time) override;
105
		[[nodiscard]] std::string help(std::span<const TclObject> tokens) const override;
106
		void tabCompletion(std::vector<std::string>& tokens) const override;
107
		[[nodiscard]] bool needRecord(std::span<const TclObject> tokens) const override;
108
		[[nodiscard]] CartridgeSlotManager& getManager() { return manager; }
109
	private:
110
		CartridgeSlotManager& manager;
111
	} cartCmd;
112
113
	struct CartridgeSlotInfo final : InfoTopic {
114
		explicit CartridgeSlotInfo(InfoCommand& machineInfoCommand);
115
		void execute(std::span<const TclObject> tokens,
116
			     TclObject& result) const override;
117
		[[nodiscard]] std::string help(std::span<const TclObject> tokens) const override;
118
	} extSlotInfo;
119
120
	struct Slot : public MediaProvider {
121
		~Slot();
122
123
		// MediaInfoProvider
124
		void getMediaInfo(TclObject& result) override;
125
		void setMedia(const TclObject& info, EmuTime time) override;
126
127
		[[nodiscard]] bool exists() const;
128
		[[nodiscard]] bool used(const HardwareConfig* allowed = nullptr) const;
129
		void setConfig(const HardwareConfig* cfg);
130
131
		std::optional<CartCmd> cartCommand;
132
		std::optional<ExtCmd> extCommand;
133
		const HardwareConfig* config = nullptr;
134
		unsigned useCount = 0;
135
		int ps = 0;
136
		int ss = 0;
137
		MSXCPUInterface* cpuInterface;
138
	};
139
	std::array<Slot, MAX_SLOTS> slots;
140
};
141
142
} // namespace openmsx
143
144
#endif