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>();
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) {
712 for (
auto port : {0xfc, 0xfd, 0xfe, 0xff}) {
714 cpuInterface.
register_IO_In (narrow_cast<byte>(port), mapperIO.get());
724 assert(mapperIOCounter);
726 if (mapperIOCounter == 0) {
728 for (
auto port : {0xfc, 0xfd, 0xfe, 0xff}) {
739 auto& s = userNames[hwName];
743 userName =
strCat(
"untitled", ++n);
745 s.push_back(userName);
751 auto& s = userNames[hwName];
757 machineMediaInfo->registerProvider(name, provider);
762 machineMediaInfo->unregisterProvider(provider);
769 : motherBoard(motherBoard_)
785 motherBoard_.getStateChangeDistributor(),
786 motherBoard_.getScheduler(),
788 , motherBoard(motherBoard_)
800 return "Resets the MSX.";
806 :
Command(motherBoard_.getCommandController(),
"load_machine")
807 , motherBoard(motherBoard_)
842 result = motherBoard.
loadMachine(
string(tokens[1].getString()));
847 return "Load a msx machine configuration into an empty machine.";
858 :
Command(motherBoard_.getCommandController(),
"list_extensions")
859 , motherBoard(motherBoard_)
871 return "Return a list of all inserted extensions.";
878 motherBoard_.getStateChangeDistributor(),
879 motherBoard_.getScheduler(),
881 , motherBoard(motherBoard_)
882 , commandName(
std::move(commandName_))
890 if (tokens.size() == 3 && tokens[1].getString() !=
"insert") {
894 auto name = tokens[tokens.size() - 1].getString();
895 auto slotName = (commandName.size() == 4)
896 ? std::string_view(&commandName[3], 1)
899 if (slotName !=
"any") {
901 if (
const auto* extConf = manager.getConfigForSlot(commandName[3] -
'a')) {
914 return "Insert a hardware extension.";
926 motherBoard_.getStateChangeDistributor(),
927 motherBoard_.getScheduler(),
929 , motherBoard(motherBoard_)
937 std::string_view extName = tokens[1].getString();
946 "': ", e.getMessage());
952 return "Remove an extension from the MSX machine.";
957 if (tokens.size() == 2) {
960 [](
auto& e) -> std::string_view { return e->getName(); }));
968 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"config_name")
969 , motherBoard(motherBoard_)
981 return "Returns the configuration name for this machine.";
987 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"type")
988 , motherBoard(motherBoard_)
1000 return "Returns the machine type for this machine.";
1007 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"extension")
1008 , motherBoard(motherBoard_)
1016 if (tokens.size() == 2) {
1019 }
else if (tokens.size() == 3) {
1020 std::string_view extName = tokens[2].getString();
1031 const auto& filename = extension->
getConfig()
1045 return "Returns information about the given extension instance.";
1050 if (tokens.size() == 3) {
1053 [](
auto& e) -> std::string_view { return e->getName(); }));
1061 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"media")
1069 if (tokens.size() == 2) {
1072 }
else if (tokens.size() == 3) {
1073 auto name = tokens[2].getString();
1074 if (
auto it =
ranges::find(providers, name, &ProviderInfo::name);
1075 it != providers.end()) {
1076 it->provider->getMediaInfo(result);
1085 return "Returns information about the given media slot.";
1090 if (tokens.size() == 3) {
1092 providers, &ProviderInfo::name));
1098 assert(!
contains(providers, name, &ProviderInfo::name));
1099 assert(!
contains(providers, &provider, &ProviderInfo::provider));
1100 providers.emplace_back(name, &provider);
1112 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"device")
1113 , motherBoard(motherBoard_)
1120 switch (tokens.size()) {
1124 [](
auto& d) { return d->getName(); }));
1127 std::string_view deviceName = tokens[2].getString();
1140 return "Without any arguments, returns the list of used device names.\n"
1141 "With a device name as argument, returns the type (and for some "
1142 "devices the subtype) of the given device.";
1147 if (tokens.size() == 3) {
1149 motherBoard.availableDevices,
1150 [](
auto& d) -> std::string_view { return d->getName(); }));
1159 , motherBoard(motherBoard_)
1168void FastForwardHelper::executeUntil(EmuTime::param )
1195 : motherBoard(motherBoard_)
1201 if (&
setting == &motherBoard.powerSetting) {
1202 if (motherBoard.powerSetting.getBoolean()) {
1203 motherBoard.powerUp();
1205 motherBoard.powerDown();
1207 }
else if (&
setting == &motherBoard.suppressMessagesSetting) {
1208 motherBoard.msxCliComm->setSuppressMessages(motherBoard.suppressMessagesSetting.getBoolean());
1221template<
typename Archive>
1231 ar.serialize(
"scheduler", *scheduler);
1234 if constexpr (Archive::IS_LOADER) {
1238 ar.serialize(
"name", machineName);
1239 ar.serializeWithID(
"config", machineConfig2, std::ref(*
this));
1241 ar.serializeWithID(
"extensions", extensions, std::ref(*
this));
1243 if (mapperIO) ar.serialize(
"mapperIO", *mapperIO);
1247 ar.serialize(
"deviceSwitch", devSwitch);
1251 ar.serialize(
"cpu",
getCPU());
1256 ar.serialize(
"cassetteport", *port);
1258 if (ar.versionAtLeast(version, 4)) {
1260 joystickPort[0].get())) {
1261 ar.serialize(
"joystickportA", *port);
1264 joystickPort[1].get())) {
1265 ar.serialize(
"joystickportB", *port);
1268 if (ar.versionAtLeast(version, 5)) {
1269 if (renShaTurbo) ar.serialize(
"renShaTurbo", *renShaTurbo);
1272 if constexpr (Archive::IS_LOADER) {
1280 assert(Archive::IS_LOADER);
1281 unsigned reRecordCount = 0;
1282 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 register_IO_Out(byte port, MSXDevice *device)
Devices can register their Out ports.
void register_IO_In(byte port, MSXDevice *device)
Devices can register their In ports.
void unregister_IO_In(byte port, MSXDevice *device)
void reset()
Reset (the slot state)
void unregister_IO_Out(byte port, 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)