54 using std::make_unique;
75 EmuTime::param time)
override;
76 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
86 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
87 void tabCompletion(std::vector<string>& tokens)
const override;
97 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
107 EmuTime::param time)
override;
108 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
109 void tabCompletion(std::vector<string>& tokens)
const override;
118 void execute(std::span<const TclObject> tokens,
120 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
129 void execute(std::span<const TclObject> tokens,
131 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
140 void execute(std::span<const TclObject> tokens,
142 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
143 void tabCompletion(std::vector<string>& tokens)
const override;
152 void execute(std::span<const TclObject> tokens,
154 [[nodiscard]]
string help(std::span<const TclObject> tokens)
const override;
155 void tabCompletion(std::vector<string>& tokens)
const override;
164 void setTarget(EmuTime::param targetTime);
166 void executeUntil(EmuTime::param time)
override;
174 [[nodiscard]]
byte read(
unsigned address, EmuTime::param time)
override;
175 void write(
unsigned address,
byte value)
override;
188 static unsigned machineIDCounter = 0;
192 , machineID(
strCat(
"machine", ++machineIDCounter))
194 , machineConfig(nullptr)
195 , msxCliComm(make_unique<
MSXCliComm>(*this, reactor.getGlobalCliComm()))
199 reactor.getGlobalCommandController(), reactor,
200 *this, *msxEventDistributor, machineID))
203 reactor.getMixer(), *this,
204 reactor.getGlobalSettings()))
205 , videoSourceSetting(*msxCommandController)
208 , powerSetting(reactor.getGlobalSettings().getPowerSetting())
211 , fastForwarding(false)
213 slotManager = make_unique<CartridgeSlotManager>(*
this);
214 reverseManager = make_unique<ReverseManager>(*
this);
215 resetCommand = make_unique<ResetCmd>(*
this);
216 loadMachineCommand = make_unique<LoadMachineCmd>(*
this);
217 listExtCommand = make_unique<ListExtCmd>(*
this);
218 extCommand = make_unique<ExtCmd>(*
this,
"ext");
219 removeExtCommand = make_unique<RemoveExtCmd>(*
this);
220 machineNameInfo = make_unique<MachineNameInfo>(*
this);
221 machineTypeInfo = make_unique<MachineTypeInfo>(*
this);
222 machineExtensionInfo = make_unique<MachineExtensionInfo>(*
this);
223 deviceInfo = make_unique<DeviceInfo>(*
this);
224 debugger = make_unique<Debugger>(*
this);
231 addRemoveUpdate = make_unique<AddRemoveUpdate>(*
this);
236 eventDelay = make_unique<EventDelay>(
237 *scheduler, *msxCommandController,
240 realTime = make_unique<RealTime>(
243 powerSetting.
attach(*settingObserver);
248 powerSetting.
detach(*settingObserver);
251 assert(mapperIOCounter == 0);
252 assert(availableDevices.empty());
253 assert(extensions.empty());
254 assert(!machineConfig2);
258 void MSXMotherBoard::deleteMachine()
260 while (!extensions.empty()) {
263 }
catch (MSXException&
e) {
264 std::cerr <<
"Internal error: failed to remove "
265 "extension while deleting a machine: "
266 <<
e.getMessage() <<
'\n';
271 machineConfig2.reset();
272 machineConfig =
nullptr;
278 machineConfig = machineConfig_;
282 msxCpu = make_unique<MSXCPU>(*
this);
283 msxCpuInterface = make_unique<MSXCPUInterface>(*
this);
289 if (
const auto* info = machine->getConfig().findChild(
"info")) {
290 if (
const auto* type = info->findChild(
"type")) {
291 return type->getData();
310 return devices.
findChild(
"T7775") !=
nullptr ||
318 assert(machineName.empty());
319 assert(extensions.empty());
320 assert(!machineConfig2);
327 throw MSXException(
"Machine \"", machine,
"\" not found: ",
330 throw MSXException(
"Error in \"", machine,
"\" machine: ",
337 throw MSXException(
"Error in \"", machine,
"\" machine: ",
343 machineName = machine;
349 std::unique_ptr<HardwareConfig> extension;
352 *
this,
string(name), slotname);
355 "Extension \"", name,
"\" not found: ",
e.getMessage());
358 "Error in \"", name,
"\" extension: ",
e.getMessage());
364 std::string_view name, std::unique_ptr<HardwareConfig> extension)
367 extension->parseSlots();
368 extension->createDevices();
371 "Error in \"", name,
"\" extension: ",
e.getMessage());
373 string result = extension->getName();
374 extensions.push_back(std::move(extension));
382 return (it !=
end(extensions)) ? it->get() :
nullptr;
390 [](
auto&
e) {
return e.get(); });
391 extensions.erase(it);
402 if (!pluggingController) {
403 pluggingController = make_unique<PluggingController>(*
this);
405 return *pluggingController;
418 return *msxCpuInterface;
423 if (!panasonicMemory) {
424 panasonicMemory = make_unique<PanasonicMemory>(*
this);
426 return *panasonicMemory;
434 return *deviceSwitch;
444 cassettePort = make_unique<DummyCassettePort>();
447 return *cassettePort;
453 if (!joystickPort[0]) {
457 "JoystickPorts",
"AB");
458 if (ports !=
one_of(
"AB",
"",
"A",
"B")) {
460 "Invalid JoystickPorts specification, "
461 "should be one of '', 'A', 'B' or 'AB'.");
464 if (ports ==
one_of(
"AB",
"A")) {
465 joystickPort[0] = make_unique<JoystickPort>(
466 ctrl,
"joyporta",
"MSX Joystick port A");
468 joystickPort[0] = make_unique<DummyJoystickPort>();
470 if (ports ==
one_of(
"AB",
"B")) {
471 joystickPort[1] = make_unique<JoystickPort>(
472 ctrl,
"joyportb",
"MSX Joystick port B");
474 joystickPort[1] = make_unique<DummyJoystickPort>();
476 joyPortDebuggable = make_unique<JoyPortDebuggable>(*
this);
478 return *joystickPort[port];
485 renShaTurbo = make_unique<RenShaTurbo>(
496 ledStatus = make_unique<LedStatus>(
498 *msxCommandController,
506 return *msxCommandController;
511 return msxCommandController->getMachineInfoCommand();
516 return scheduler->getCurrentTime();
540 fastForwardHelper->setTarget(time);
567 availableDevices.push_back(&device);
577 if (!powered)
return;
582 for (
auto& d : availableDevices) {
589 Event::create<BootEvent>());
595 for (
auto& d : availableDevices) {
596 result &= d->readIRQVector();
619 for (
auto& d : availableDevices) {
627 Event::create<BootEvent>());
630 void MSXMotherBoard::powerDown()
632 if (!powered)
return;
645 for (
auto& d : availableDevices) {
653 auto event = active ? Event::create<MachineActivatedEvent>()
654 : Event::create<MachineDeactivatedEvent>();
655 msxEventDistributor->distributeEvent(event, scheduler->getCurrentTime());
676 return (it !=
end(availableDevices)) ? *it :
nullptr;
681 if (mapperIOCounter == 0) {
701 assert(mapperIOCounter);
703 if (mapperIOCounter == 0) {
720 auto& s = userNames[hwName];
724 userName =
strCat(
"untitled", ++n);
726 s.push_back(userName);
732 auto& s = userNames[hwName];
739 : motherBoard(motherBoard_)
755 motherBoard_.getStateChangeDistributor(),
756 motherBoard_.getScheduler(),
758 , motherBoard(motherBoard_)
770 return "Resets the MSX.";
776 :
Command(motherBoard_.getCommandController(),
"load_machine")
777 , motherBoard(motherBoard_)
812 result = motherBoard.
loadMachine(
string(tokens[1].getString()));
817 return "Load a msx machine configuration into an empty machine.";
828 :
Command(motherBoard_.getCommandController(),
"list_extensions")
829 , motherBoard(motherBoard_)
837 [&](
auto&
e) { return e->getName(); }));
842 return "Return a list of all inserted extensions.";
849 motherBoard_.getStateChangeDistributor(),
850 motherBoard_.getScheduler(),
852 , motherBoard(motherBoard_)
853 , commandName(std::move(commandName_))
862 auto slotname = (commandName.size() == 4)
863 ? std::string_view(&commandName[3], 1)
866 tokens[1].getString(), slotname);
874 return "Insert a hardware extension.";
886 motherBoard_.getStateChangeDistributor(),
887 motherBoard_.getScheduler(),
889 , motherBoard(motherBoard_)
897 std::string_view extName = tokens[1].getString();
906 "': ",
e.getMessage());
912 return "Remove an extension from the MSX machine.";
917 if (tokens.size() == 2) {
920 [](
auto&
e) -> std::string_view { return e->getName(); }));
928 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"config_name")
929 , motherBoard(motherBoard_)
941 return "Returns the configuration name for this machine.";
947 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"type")
948 , motherBoard(motherBoard_)
960 return "Returns the machine type for this machine.";
967 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"extension")
968 , motherBoard(motherBoard_)
976 if (tokens.size() == 2) {
979 [&](
auto&
e) { return e->getName(); }));
980 }
else if (tokens.size() == 3) {
981 std::string_view extName = tokens[2].getString();
1000 [&](
auto&
e) { return e->getName(); }));
1007 return "Returns information about the given extension instance.";
1012 if (tokens.size() == 3) {
1015 [](
auto&
e) -> std::string_view { return e->getName(); }));
1023 :
InfoTopic(motherBoard_.getMachineInfoCommand(),
"device")
1024 , motherBoard(motherBoard_)
1031 switch (tokens.size()) {
1035 [](
auto& d) { return d->getName(); }));
1038 std::string_view deviceName = tokens[2].getString();
1051 return "Without any arguments, returns the list of used device names.\n"
1052 "With a device name as argument, returns the type (and for some "
1053 "devices the subtype) of the given device.";
1058 if (tokens.size() == 3) {
1060 motherBoard.availableDevices,
1061 [](
auto& d) -> std::string_view { return d->getName(); }));
1070 , motherBoard(motherBoard_)
1079 void FastForwardHelper::executeUntil(EmuTime::param )
1106 : motherBoard(motherBoard_)
1112 if (&
setting == &motherBoard.powerSetting) {
1113 if (motherBoard.powerSetting.getBoolean()) {
1114 motherBoard.powerUp();
1116 motherBoard.powerDown();
1130 template<
typename Archive>
1140 ar.serialize(
"scheduler", *scheduler);
1143 if constexpr (Archive::IS_LOADER) {
1147 ar.serialize(
"name", machineName);
1148 ar.serializeWithID(
"config", machineConfig2, std::ref(*
this));
1150 ar.serializeWithID(
"extensions", extensions, std::ref(*
this));
1152 if (mapperIO) ar.serialize(
"mapperIO", *mapperIO);
1156 ar.serialize(
"deviceSwitch", devSwitch);
1160 ar.serialize(
"cpu",
getCPU());
1165 ar.serialize(
"cassetteport", *port);
1167 if (ar.versionAtLeast(version, 4)) {
1169 joystickPort[0].
get())) {
1170 ar.serialize(
"joystickportA", *port);
1173 joystickPort[1].
get())) {
1174 ar.serialize(
"joystickportB", *port);
1177 if (ar.versionAtLeast(version, 5)) {
1178 if (renShaTurbo) ar.serialize(
"renShaTurbo", *renShaTurbo);
1181 if constexpr (Archive::IS_LOADER) {
1189 assert(Archive::IS_LOADER);
1190 unsigned reRecordCount = 0;
1191 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(MSXMotherBoard &motherBoard)
AddRemoveUpdate & operator=(const AddRemoveUpdate &)=delete
bool getBoolean() const noexcept
virtual void update(UpdateType type, std::string_view name, std::string_view value)=0
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 topic.
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 XMLElement & getConfig() const
const auto & getDevices() const
const std::string & getConfigName() const
static std::unique_ptr< HardwareConfig > createMachineConfig(MSXMotherBoard &motherBoard, std::string machineName)
const std::string & getName() 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 byte 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()
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.
MSXCPUInterface & getCPUInterface()
std::string getUserName(const std::string &hwName)
Keep track of which 'usernames' are in use.
EmuTime::param getCurrentTime()
Convenience method: This is the same as getScheduler().getCurrentTime().
std::string loadMachine(const std::string &machine)
std::string_view getMachineName() const
ReverseManager & getReverseManager()
CliComm & getMSXCliComm()
MSXDevice * findDevice(std::string_view name)
Find a MSXDevice by name.
CommandController & getCommandController()
void pause()
Pause MSX machine.
const Extensions & getExtensions() const
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
LedStatus & getLedStatus()
bool hasToshibaEngine() const
MSXDeviceSwitch & getDeviceSwitch()
void serialize(Archive &ar, unsigned version)
void removeDevice(MSXDevice &device)
std::string_view getMachineID() const
const HardwareConfig * getMachineConfig() const
void removeExtension(const HardwareConfig &extension)
JoystickPortIf & getJoystickPort(unsigned port)
std::string loadExtension(std::string_view extensionName, std::string_view slotname)
std::string_view getMachineType() 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()
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.
EventDistributor & getEventDistributor()
GlobalSettings & getGlobalSettings()
GlobalCliComm & getGlobalCliComm()
RTScheduler & getRTScheduler()
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:
const T & get(const Event &event)
constexpr const char *const filename
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.
std::string strCat(Ts &&...ts)
constexpr auto end(const zstring_view &x)