57using std::make_unique;
80 EmuTime::param time)
override;
81 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
91 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
92 void tabCompletion(std::vector<string>& tokens)
const override;
101 void execute(std::span<const TclObject> tokens,
TclObject& result)
override;
102 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
112 EmuTime::param time)
override;
113 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
114 void tabCompletion(std::vector<string>& tokens)
const override;
123 void execute(std::span<const TclObject> tokens,
125 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
134 void execute(std::span<const TclObject> tokens,
136 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
145 void execute(std::span<const TclObject> tokens,
147 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
148 void tabCompletion(std::vector<string>& tokens)
const override;
158 assert(providers.empty());
160 void execute(std::span<const TclObject> tokens,
162 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
163 void tabCompletion(std::vector<string>& tokens)
const override;
167 struct ProviderInfo {
169 : name(n), provider(p) {}
170 std::string_view name;
171 MediaInfoProvider* provider;
174 std::vector<ProviderInfo> providers;
181 void execute(std::span<const TclObject> tokens,
183 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
184 void tabCompletion(std::vector<string>& tokens)
const override;
193 void setTarget(EmuTime::param targetTime);
195 void executeUntil(EmuTime::param time)
override;
203 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
204 void write(
unsigned address,
byte value)
override;
217static unsigned machineIDCounter = 0;
221 , machineID(
strCat(
"machine", ++machineIDCounter))
222 , msxCliComm(make_unique<
MSXCliComm>(*this, reactor.getGlobalCliComm()))
226 reactor.getGlobalCommandController(), reactor,
227 *this, *msxEventDistributor, machineID))
230 reactor.getMixer(), *this,
231 reactor.getGlobalSettings()))
232 , videoSourceSetting(*msxCommandController)
233 , suppressMessagesSetting(*msxCommandController,
"suppressmessages",
234 "Suppress info, warning and error messages for this machine. "
235 "Intended use is for scripts that create temporary machines "
236 "of which you don't want to see warning messages about blank "
237 "SRAM content or PSG port directions for instance.",
241 , powerSetting(reactor.getGlobalSettings().getPowerSetting())
243 slotManager = make_unique<CartridgeSlotManager>(*
this);
244 reverseManager = make_unique<ReverseManager>(*
this);
245 resetCommand = make_unique<ResetCmd>(*
this);
246 loadMachineCommand = make_unique<LoadMachineCmd>(*
this);
247 listExtCommand = make_unique<ListExtCmd>(*
this);
248 extCommand = make_unique<ExtCmd>(*
this,
"ext");
249 removeExtCommand = make_unique<RemoveExtCmd>(*
this);
250 machineNameInfo = make_unique<MachineNameInfo>(*
this);
251 machineTypeInfo = make_unique<MachineTypeInfo>(*
this);
252 machineExtensionInfo = make_unique<MachineExtensionInfo>(*
this);
253 machineMediaInfo = make_unique<MachineMediaInfo>(*
this);
254 deviceInfo = make_unique<DeviceInfo>(*
this);
255 debugger = make_unique<Debugger>(*
this);
260 addRemoveUpdate = make_unique<AddRemoveUpdate>(*
this);
265 eventDelay = make_unique<EventDelay>(
266 *scheduler, *msxCommandController,
269 realTime = make_unique<RealTime>(
272 powerSetting.
attach(*settingObserver);
273 suppressMessagesSetting.
attach(*settingObserver);
278 suppressMessagesSetting.
detach(*settingObserver);
279 powerSetting.
detach(*settingObserver);
282 assert(mapperIOCounter == 0);
283 assert(availableDevices.empty());
284 assert(extensions.empty());
285 assert(!machineConfig2);
289void MSXMotherBoard::deleteMachine()
291 while (!extensions.empty()) {
294 }
catch (MSXException& e) {
295 std::cerr <<
"Internal error: failed to remove "
296 "extension while deleting a machine: "
297 << e.getMessage() <<
'\n';
302 machineConfig2.reset();
303 machineConfig =
nullptr;
309 machineConfig = machineConfig_;
313 msxCpu = make_unique<MSXCPU>(*
this);
314 msxCpuInterface = make_unique<MSXCPUInterface>(*
this);
320 if (
const auto* info = machine->getConfig().findChild(
"info")) {
321 if (
const auto* type = info->findChild(
"type")) {
322 return type->getData();
341 return devices.
findChild(
"T7775") !=
nullptr ||
349 assert(machineName.empty());
350 assert(extensions.empty());
351 assert(!machineConfig2);
358 throw MSXException(
"Machine \"", machine,
"\" not found: ",
361 throw MSXException(
"Error in \"", machine,
"\" machine: ",
368 throw MSXException(
"Error in \"", machine,
"\" machine: ",
374 machineName = machine;
382 *
this,
string(name), slotName);
385 "Extension \"", name,
"\" not found: ", e.getMessage());
388 "Error in \"", name,
"\" extension: ", e.getMessage());
393 std::string_view name, std::unique_ptr<HardwareConfig> extension)
396 extension->parseSlots();
397 extension->createDevices();
400 "Error in \"", name,
"\" extension: ", e.getMessage());
402 string result = extension->getName();
403 extensions.push_back(std::move(extension));
411 return (it !=
end(extensions)) ? it->get() :
nullptr;
419 [](
auto& e) {
return e.get(); });
420 extensions.erase(it);
431 if (!pluggingController) {
432 pluggingController = make_unique<PluggingController>(*
this);
434 return *pluggingController;
447 return *msxCpuInterface;
452 if (!panasonicMemory) {
453 panasonicMemory = make_unique<PanasonicMemory>(*
this);
455 return *panasonicMemory;
463 return *deviceSwitch;
473 cassettePort = make_unique<DummyCassettePort>(*
this);
476 return *cassettePort;
482 if (!joystickPort[0]) {
486 "JoystickPorts",
"AB");
487 if (ports !=
one_of(
"AB",
"",
"A",
"B")) {
489 "Invalid JoystickPorts specification, "
490 "should be one of '', 'A', 'B' or 'AB'.");
493 if (ports ==
one_of(
"AB",
"A")) {
494 joystickPort[0] = make_unique<JoystickPort>(
495 ctrl,
"joyporta",
"MSX Joystick port A");
497 joystickPort[0] = make_unique<DummyJoystickPort>();
499 if (ports ==
one_of(
"AB",
"B")) {
500 joystickPort[1] = make_unique<JoystickPort>(
501 ctrl,
"joyportb",
"MSX Joystick port B");
503 joystickPort[1] = make_unique<DummyJoystickPort>();
505 joyPortDebuggable = make_unique<JoyPortDebuggable>(*
this);
507 return *joystickPort[port];
514 renShaTurbo = make_unique<RenShaTurbo>(
525 ledStatus = make_unique<LedStatus>(
527 *msxCommandController,
535 return *msxCommandController;
540 return msxCommandController->getMachineInfoCommand();
545 return scheduler->getCurrentTime();
569 fastForwardHelper->setTarget(time);
596 availableDevices.push_back(&device);
606 if (!powered)
return;
611 for (
auto& d : availableDevices) {
623 for (
auto& d : availableDevices) {
624 result &= d->readIRQVector();
647 for (
auto& d : availableDevices) {
657void MSXMotherBoard::powerDown()
659 if (!powered)
return;
672 for (
auto& d : availableDevices) {
682 msxEventDistributor->distributeEvent(event, scheduler->getCurrentTime());
703 return (it !=
end(availableDevices)) ? *it :
nullptr;
708 if (mapperIOCounter == 0) {
719 assert(mapperIOCounter);
721 if (mapperIOCounter == 0) {
729 auto& s = userNames[hwName];
733 userName =
strCat(
"untitled", ++n);
735 s.push_back(userName);
741 auto& s = userNames[hwName];
747 machineMediaInfo->registerProvider(name, provider);
752 machineMediaInfo->unregisterProvider(provider);
759 : motherBoard(motherBoard_)
775 motherBoard_.getStateChangeDistributor(),
776 motherBoard_.getScheduler(),
778 , motherBoard(motherBoard_)
790 return "Resets the MSX.";
796 :
Command(motherBoard_.getCommandController(),
"load_machine")
797 , motherBoard(motherBoard_)
832 result = motherBoard.
loadMachine(
string(tokens[1].getString()));
837 return "Load a msx machine configuration into an empty machine.";
848 :
Command(motherBoard_.getCommandController(),
"list_extensions")
849 , motherBoard(motherBoard_)
861 return "Return a list of all inserted extensions.";
868 motherBoard_.getStateChangeDistributor(),
869 motherBoard_.getScheduler(),
871 , motherBoard(motherBoard_)
872 , commandName(
std::move(commandName_))
880 if (tokens.size() == 3 && tokens[1].getString() !=
"insert") {
884 auto name = tokens[tokens.size() - 1].getString();
885 auto slotName = (commandName.size() == 4)
886 ? std::string_view(&commandName[3], 1)
889 if (slotName !=
"any") {
891 if (
const auto* extConf = manager.getConfigForSlot(commandName[3] -
'a')) {
904 return "Insert a hardware extension.";
916 motherBoard_.getStateChangeDistributor(),
917 motherBoard_.getScheduler(),
919 , motherBoard(motherBoard_)
927 std::string_view extName = tokens[1].getString();
936 "': ", e.getMessage());
942 return "Remove an extension from the MSX machine.";
947 if (tokens.size() == 2) {
950 [](
auto& e) -> std::string_view { return e->getName(); }));
958 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"config_name")
959 , motherBoard(motherBoard_)
971 return "Returns the configuration name for this machine.";
977 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"type")
978 , motherBoard(motherBoard_)
990 return "Returns the machine type for this machine.";
997 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"extension")
998 , motherBoard(motherBoard_)
1006 if (tokens.size() == 2) {
1009 }
else if (tokens.size() == 3) {
1010 std::string_view extName = tokens[2].getString();
1021 const auto& filename = extension->
getConfig()
1035 return "Returns information about the given extension instance.";
1040 if (tokens.size() == 3) {
1043 [](
auto& e) -> std::string_view { return e->getName(); }));
1051 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"media")
1059 if (tokens.size() == 2) {
1062 }
else if (tokens.size() == 3) {
1063 auto name = tokens[2].getString();
1064 if (
auto it =
ranges::find(providers, name, &ProviderInfo::name);
1065 it != providers.end()) {
1066 it->provider->getMediaInfo(result);
1075 return "Returns information about the given media slot.";
1080 if (tokens.size() == 3) {
1082 providers, &ProviderInfo::name));
1088 assert(!
contains(providers, name, &ProviderInfo::name));
1089 assert(!
contains(providers, &provider, &ProviderInfo::provider));
1090 providers.emplace_back(name, &provider);
1102 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"device")
1103 , motherBoard(motherBoard_)
1110 switch (tokens.size()) {
1114 [](
auto& d) { return d->getName(); }));
1117 std::string_view deviceName = tokens[2].getString();
1130 return "Without any arguments, returns the list of used device names.\n"
1131 "With a device name as argument, returns the type (and for some "
1132 "devices the subtype) of the given device.";
1137 if (tokens.size() == 3) {
1139 motherBoard.availableDevices,
1140 [](
auto& d) -> std::string_view { return d->getName(); }));
1149 , motherBoard(motherBoard_)
1158void FastForwardHelper::executeUntil(EmuTime::param )
1185 : motherBoard(motherBoard_)
1191 if (&
setting == &motherBoard.powerSetting) {
1192 if (motherBoard.powerSetting.getBoolean()) {
1193 motherBoard.powerUp();
1195 motherBoard.powerDown();
1197 }
else if (&
setting == &motherBoard.suppressMessagesSetting) {
1198 motherBoard.msxCliComm->setSuppressMessages(motherBoard.suppressMessagesSetting.getBoolean());
1211template<
typename Archive>
1221 ar.serialize(
"scheduler", *scheduler);
1224 if constexpr (Archive::IS_LOADER) {
1228 ar.serialize(
"name", machineName);
1229 ar.serializeWithID(
"config", machineConfig2, std::ref(*
this));
1231 ar.serializeWithID(
"extensions", extensions, std::ref(*
this));
1233 if (mapperIO) ar.serialize(
"mapperIO", *mapperIO);
1237 ar.serialize(
"deviceSwitch", devSwitch);
1241 ar.serialize(
"cpu",
getCPU());
1246 ar.serialize(
"cassetteport", *port);
1248 if (ar.versionAtLeast(version, 4)) {
1250 joystickPort[0].get())) {
1251 ar.serialize(
"joystickportA", *port);
1254 joystickPort[1].get())) {
1255 ar.serialize(
"joystickportB", *port);
1258 if (ar.versionAtLeast(version, 5)) {
1259 if (renShaTurbo) ar.serialize(
"renShaTurbo", *renShaTurbo);
1262 if constexpr (Archive::IS_LOADER) {
1270 assert(Archive::IS_LOADER);
1271 unsigned reRecordCount = 0;
1272 ar.serialize(
"reRecordCount", reRecordCount);
Assign new value to some variable and restore the original value when this object goes out of scope.
AddRemoveUpdate(const AddRemoveUpdate &)=delete
AddRemoveUpdate & operator=(AddRemoveUpdate &&)=delete
AddRemoveUpdate(MSXMotherBoard &motherBoard)
AddRemoveUpdate(AddRemoveUpdate &&)=delete
AddRemoveUpdate & operator=(const AddRemoveUpdate &)=delete
bool getBoolean() const noexcept
Sent when the MSX resets or powers up.
void setAllowedInEmptyMachine(bool value)
static void completeString(std::vector< std::string > &tokens, ITER begin, ITER end, bool caseSensitive=true)
void checkNumArgs(std::span< const TclObject > tokens, unsigned exactly, const char *errMessage) const
static std::unique_ptr< MSXDeviceSwitch > createDeviceSwitch(const HardwareConfig &hwConf)
static std::unique_ptr< MSXMapperIO > createMapperIO(const HardwareConfig &hwConf)
DeviceInfo(MSXMotherBoard &motherBoard)
void execute(std::span< const TclObject > tokens, TclObject &result) const override
Show info on this topic.
string help(std::span< const TclObject > tokens) const override
Print help for this topic.
void tabCompletion(std::vector< string > &tokens) const override
Attempt tab completion for this command.
void distributeEvent(Event &&event)
Schedule the given event for delivery.
void tabCompletion(std::vector< std::string > &tokens) const override
Attempt tab completion for this command.
ExtCmd(MSXMotherBoard &motherBoard, std::string commandName)
void execute(std::span< const TclObject > tokens, TclObject &result, EmuTime::param time) override
This is like the execute() method of the Command class, it only has an extra time parameter.
std::string help(std::span< const TclObject > tokens) const override
Print help for this command.
void setTarget(EmuTime::param targetTime)
FastForwardHelper(MSXMotherBoard &motherBoard)
void update(UpdateType type, std::string_view name, std::string_view value) override
const std::string & getConfigName() const
static std::unique_ptr< HardwareConfig > createMachineConfig(MSXMotherBoard &motherBoard, std::string machineName)
const auto & getDevices() const
const std::string & getName() const
const XMLElement & getConfig() const
static std::unique_ptr< HardwareConfig > createExtensionConfig(MSXMotherBoard &motherBoard, std::string extensionName, std::string_view slotName)
void testRemove() const
Checks whether this HardwareConfig can be deleted.
void write(unsigned address, byte value) override
JoyPortDebuggable(MSXMotherBoard &motherBoard)
byte read(unsigned address, EmuTime::param time) override
virtual uint8_t read(EmuTime::param time)=0
void setLed(Led led, bool status)
void execute(std::span< const TclObject > tokens, TclObject &result) override
Execute this command.
ListExtCmd(MSXMotherBoard &motherBoard)
string help(std::span< const TclObject > tokens) const override
Print help for this command.
LoadMachineCmd(MSXMotherBoard &motherBoard)
string help(std::span< const TclObject > tokens) const override
Print help for this command.
void execute(std::span< const TclObject > tokens, TclObject &result) override
Execute this command.
void tabCompletion(std::vector< string > &tokens) const override
Attempt tab completion for this command.
void unregister_IO_InOut_range(byte port, unsigned num, MSXDevice *device)
void reset()
Reset (the slot state)
void register_IO_InOut_range(byte port, unsigned num, MSXDevice *device)
void exitCPULoopSync()
See CPUCore::exitCPULoopSync()
void doReset(EmuTime::param time)
Reset CPU.
void setPaused(bool paused)
(un)pause CPU.
void exitCPULoopAsync()
See CPUCore::exitCPULoopAsync()
void update(UpdateType type, std::string_view name, std::string_view value) override
bool hasRegisteredDevices() const
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
void getDeviceInfo(TclObject &result) const
Get device info.
virtual const std::string & getName() const
Returns a human-readable name for this device.
HardwareConfig * findExtension(std::string_view extensionName)
PluggingController & getPluggingController()
void activate(bool active)
void setMachineConfig(HardwareConfig *machineConfig)
RenShaTurbo & getRenShaTurbo()
void freeUserName(const std::string &hwName, const std::string &userName)
bool execute()
Run emulation.
EmuTime::param getCurrentTime() const
Convenience method: This is the same as getScheduler().getCurrentTime().
const HardwareConfig * getMachineConfig() const
MSXCPUInterface & getCPUInterface()
std::string getUserName(const std::string &hwName)
Keep track of which 'usernames' are in use.
std::unique_ptr< HardwareConfig > loadExtension(std::string_view extensionName, std::string_view slotName)
std::string loadMachine(const std::string &machine)
std::string_view getMachineName() const
void registerMediaInfo(std::string_view name, MediaInfoProvider &provider)
Register and unregister providers of media info, for the media info topic.
MSXDevice * findDevice(std::string_view name)
Find a MSXDevice by name.
CommandController & getCommandController()
void pause()
Pause MSX machine.
std::string insertExtension(std::string_view name, std::unique_ptr< HardwareConfig > extension)
void fastForward(EmuTime::param time, bool fast)
Run emulation until a certain time in fast forward mode.
void exitCPULoopAsync()
See CPU::exitCPULoopAsync().
MSXMotherBoard(const MSXMotherBoard &)=delete
void unregisterMediaInfo(MediaInfoProvider &provider)
MSXCliComm & getMSXCliComm()
LedStatus & getLedStatus()
bool hasToshibaEngine() const
byte readIRQVector() const
MSXDeviceSwitch & getDeviceSwitch()
void serialize(Archive &ar, unsigned version)
CartridgeSlotManager & getSlotManager()
void removeDevice(MSXDevice &device)
std::string_view getMachineID() const
void removeExtension(const HardwareConfig &extension)
ReverseManager & getReverseManager()
JoystickPortIf & getJoystickPort(unsigned port)
std::string_view getMachineType() const
const Extensions & getExtensions() const
CassettePortInterface & getCassettePort()
void addDevice(MSXDevice &device)
All MSXDevices should be registered by the MotherBoard.
PanasonicMemory & getPanasonicMemory()
MSXMapperIO & createMapperIO()
All memory mappers in one MSX machine share the same four (logical) memory mapper registers.
InfoCommand & getMachineInfoCommand()
Send when a machine is (de)activated.
void execute(std::span< const TclObject > tokens, TclObject &result) const override
Show info on this topic.
string help(std::span< const TclObject > tokens) const override
Print help for this topic.
void tabCompletion(std::vector< string > &tokens) const override
Attempt tab completion for this topic.
MachineExtensionInfo(MSXMotherBoard &motherBoard)
void execute(std::span< const TclObject > tokens, TclObject &result) const override
Show info on this topic.
MachineNameInfo(MSXMotherBoard &motherBoard)
string help(std::span< const TclObject > tokens) const override
Print help for this topic.
string help(std::span< const TclObject > tokens) const override
Print help for this topic.
void execute(std::span< const TclObject > tokens, TclObject &result) const override
Show info on this topic.
MachineTypeInfo(MSXMotherBoard &motherBoard)
Generic Gang-of-Four Observer class, templatized edition.
Central administration of Connectors and Pluggables.
Contains the main loop of openMSX.
GlobalSettings & getGlobalSettings()
GlobalCliComm & getGlobalCliComm()
RTScheduler & getRTScheduler()
EventDistributor & getEventDistributor()
static std::vector< std::string > getHwConfigs(std::string_view type)
Commands that directly influence the MSX state should send and events so that they can be recorded by...
RemoveExtCmd(MSXMotherBoard &motherBoard)
void tabCompletion(std::vector< string > &tokens) const override
Attempt tab completion for this command.
void execute(std::span< const TclObject > tokens, TclObject &result, EmuTime::param time) override
This is like the execute() method of the Command class, it only has an extra time parameter.
string help(std::span< const TclObject > tokens) const override
Print help for this command.
Ren-Sha Turbo is the autofire in several MSX 2+ models and in the MSX turbo R.
string help(std::span< const TclObject > tokens) const override
Print help for this command.
void execute(std::span< const TclObject > tokens, TclObject &result, EmuTime::param time) override
This is like the execute() method of the Command class, it only has an extra time parameter.
ResetCmd(MSXMotherBoard &motherBoard)
void setReRecordCount(unsigned count)
Every class that wants to get scheduled at some point must inherit from this class.
void setSyncPoint(EmuTime::param timestamp)
SettingObserver(MSXMotherBoard &motherBoard)
void update(const Setting &setting) noexcept override
MSXMotherBoard & getMotherBoard() const
void detach(Observer< T > &observer)
void attach(Observer< T > &observer)
void addListElements(ITER first, ITER last)
void addDictKeyValue(const Key &key, const Value &value)
const XMLElement * findChild(std::string_view childName) const
const XMLElement & getChild(std::string_view childName) const
std::string_view getChildData(std::string_view childName) const
This file implemented 3 utility functions:
std::variant< KeyUpEvent, KeyDownEvent, MouseMotionEvent, MouseButtonUpEvent, MouseButtonDownEvent, MouseWheelEvent, JoystickAxisMotionEvent, JoystickHatEvent, JoystickButtonUpEvent, JoystickButtonDownEvent, OsdControlReleaseEvent, OsdControlPressEvent, WindowEvent, TextEvent, FileDropEvent, QuitEvent, FinishFrameEvent, CliCommandEvent, GroupEvent, BootEvent, FrameDrawnEvent, BreakEvent, SwitchRendererEvent, TakeReverseSnapshotEvent, AfterTimedEvent, MachineLoadedEvent, MachineActivatedEvent, MachineDeactivatedEvent, MidiInReaderEvent, MidiInWindowsEvent, MidiInCoreMidiEvent, MidiInCoreMidiVirtualEvent, MidiInALSAEvent, Rs232TesterEvent, Rs232NetEvent, ImGuiDelayedActionEvent, ImGuiActiveEvent > Event
auto find(InputRange &&range, const T &value)
constexpr auto transform(Range &&range, UnaryOp op)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
void move_pop_back(VECTOR &v, typename VECTOR::iterator it)
Erase the pointed to element from the given vector.
auto rfind_unguarded(RANGE &range, const VAL &val, Proj proj={})
Similar to the find(_if)_unguarded functions above, but searches from the back to front.
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
constexpr auto end(const zstring_view &x)