41 virtual void execute(
const vector<TclObject>& tokens,
43 virtual string help(
const vector<string>& tokens)
const;
45 virtual bool needRecord(
const vector<string>& tokens)
const;
51 const string& driveName_,
53 : controller(board.getCommandController())
54 , stateChangeDistributor(&board.getStateChangeDistributor())
55 , scheduler(&board.getScheduler())
56 , filePool(&board.getReactor().getFilePool())
57 , diskFactory(board.getReactor().getDiskFactory())
58 , manipulator(board.getReactor().getDiskManipulator())
59 , driveName(driveName_)
69 : controller(controller_)
70 , stateChangeDistributor(nullptr)
73 , diskFactory(diskFactory_)
74 , manipulator(manipulator_)
75 , driveName(driveName_)
80 void DiskChanger::init(
const string& prefix,
bool createCmd)
85 if (stateChangeDistributor) {
92 if (diskCommand.get())
return;
93 diskCommand = make_unique<DiskCommand>(controller, *
this);
98 if (stateChangeDistributor) {
111 return disk->getName();
116 bool ret = diskChangedFlag;
117 diskChangedFlag =
false;
123 return diskChangedFlag;
128 diskChangedFlag =
true;
138 if (dynamic_cast<DummyDisk*>(disk.get())) {
149 void DiskChanger::sendChangeDiskEvent(
const vector<string>& args)
152 if (stateChangeDistributor) {
154 std::make_shared<MSXCommandEvent>(
157 signalStateChange(std::make_shared<MSXCommandEvent>(
162 void DiskChanger::signalStateChange(
const std::shared_ptr<StateChange>& event)
164 auto commandEvent =
dynamic_cast<MSXCommandEvent*
>(
event.get());
165 if (!commandEvent)
return;
167 const vector<TclObject>& tokens = commandEvent->getTokens();
169 if (tokens[1].getString() ==
"eject") {
184 vector<TclObject> args;
199 std::unique_ptr<Disk> newDisk(diskFactory.
createDisk(diskImage, *
this));
200 for (
unsigned i = 2; i < args.size(); ++i) {
201 Filename filename(args[i].getString().str(), context);
202 newDisk->applyPatch(filename);
209 void DiskChanger::ejectDisk()
216 disk = std::move(newDisk);
217 diskChangedFlag =
true;
227 :
Command(commandController, diskChanger_.driveName)
228 , diskChanger(diskChanger_)
234 if (tokens.size() == 1) {
239 if (dynamic_cast<DummyDisk*>(diskChanger.disk.get())) {
241 }
else if (dynamic_cast<DirAsDSK*>(diskChanger.disk.get())) {
242 options.addListElement(
"dirasdisk");
243 }
else if (dynamic_cast<RamDSKDiskImage*>(diskChanger.disk.get())) {
244 options.addListElement(
"ramdsk");
246 if (diskChanger.disk->isWriteProtected()) {
247 options.addListElement(
"readonly");
249 if (options.getListLength() != 0) {
253 }
else if (tokens[1].getString() ==
"ramdsk") {
256 args.push_back(tokens[1].getString().str());
257 diskChanger.sendChangeDiskEvent(args);
258 }
else if (tokens[1].getString() ==
"-ramdsk") {
261 args.push_back(
"ramdsk");
262 diskChanger.sendChangeDiskEvent(args);
264 "Warning: use of '-ramdsk' is deprecated, instead use the 'ramdsk' subcommand");
265 }
else if (tokens[1].getString() ==
"-eject") {
268 args.push_back(
"eject");
269 diskChanger.sendChangeDiskEvent(args);
271 "Warning: use of '-eject' is deprecated, instead use the 'eject' subcommand");
272 }
else if (tokens[1].getString() ==
"eject") {
275 args.push_back(
"eject");
276 diskChanger.sendChangeDiskEvent(args);
278 int firstFileToken = 1;
279 if (tokens[1].getString() ==
"insert") {
280 if (tokens.size() > 2) {
289 for (
unsigned i = firstFileToken; i < tokens.size(); ++i) {
291 if (option ==
"-ips") {
292 if (++i == tokens.size()) {
294 "Missing argument for option \"" + option +
'\"');
296 args.push_back(tokens[i].getString().str());
299 args.push_back(option.
str());
302 diskChanger.sendChangeDiskEvent(args);
312 return name +
" eject : remove disk from virtual drive\n" +
313 name +
" ramdsk : create a virtual disk in RAM\n" +
314 name +
" insert <filename> : change the disk file\n" +
315 name +
" <filename> : change the disk file\n" +
316 name +
" : show which disk image is in drive";
321 if (tokens.size() >= 2) {
322 static const char*
const extra[] = {
323 "eject",
"ramdsk",
"insert",
331 return tokens.size() > 1;
341 template<
typename Archive>
344 DiskName diskname = disk->getName();
345 if (ar.versionBelow(version, 2)) {
355 ar.serialize(
"disk", diskname);
358 vector<Filename> patches;
359 if (!ar.isLoader()) {
362 ar.serialize(
"patches", patches);
365 if (!ar.isLoader()) {
368 ar.serialize(
"checksum", oldChecksum);
382 assert(!oldChecksum.empty());
383 std::unique_ptr<File> file = filePool->
getFile(
386 name = file->getURL();
389 vector<TclObject> args;
392 for (
auto& p : patches) {
393 p.updateAfterLoadState();
394 args.push_back(
TclObject(p.getResolved()));
401 "Couldn't reinsert disk in drive " +
409 if (oldChecksum != newChecksum) {
411 "The content of the diskimage " +
413 " has changed since the time this savestate was "
414 "created. This might result in emulation problems "
415 "or even diskcorruption. To prevent the latter, "
416 "the disk is now write-protected (eject and "
417 "reinsert the disk if you want to override this).");
423 ar.serialize(
"diskChanged", diskChangedFlag);
429 typedef std::tuple<std::string>
type;
431 template<
typename Archive>
437 template<
typename Archive>
type load(Archive& ar,
unsigned )
440 ar.serialize(
"driveName", driveName);
441 return make_tuple(driveName);
447 std::reference_wrapper<MSXMotherBoard>);