openMSX
DiskFactory.cc
Go to the documentation of this file.
1 #include "DiskFactory.hh"
2 #include "Reactor.hh"
3 #include "File.hh"
4 #include "FileContext.hh"
5 #include "DSKDiskImage.hh"
6 #include "XSADiskImage.hh"
7 #include "DMKDiskImage.hh"
8 #include "RamDSKDiskImage.hh"
9 #include "DirAsDSK.hh"
10 #include "DiskPartition.hh"
11 #include "MSXException.hh"
12 #include "StringOp.hh"
13 #include <memory>
14 #include <stdexcept>
15 
16 using std::string;
17 
18 namespace openmsx {
19 
21  : reactor(reactor_)
22  , syncDirAsDSKSetting(
23  reactor.getCommandController(), "DirAsDSKmode",
24  "type of syncronisation between host directory and dir-as-dsk diskimage",
25  DirAsDSK::SYNC_FULL, EnumSetting<DirAsDSK::SyncMode>::Map{
26  {"read_only", DirAsDSK::SYNC_READONLY},
27  {"full", DirAsDSK::SYNC_FULL}})
28  , bootSectorSetting(
29  reactor.getCommandController(), "bootsector",
30  "boot sector type for dir-as-dsk",
32  {"DOS1", DirAsDSK::BOOTSECTOR_DOS1},
33  {"DOS2", DirAsDSK::BOOTSECTOR_DOS2}})
34 {
35 }
36 
37 std::unique_ptr<Disk> DiskFactory::createDisk(
38  const string& diskImage, DiskChanger& diskChanger)
39 {
40  if (diskImage == "ramdsk") {
41  return std::make_unique<RamDSKDiskImage>();
42  }
43 
44  Filename filename(diskImage, userFileContext());
45  try {
46  // First try DirAsDSK
47  return std::make_unique<DirAsDSK>(
48  diskChanger,
49  reactor.getCliComm(),
50  filename,
51  syncDirAsDSKSetting.getEnum(),
52  bootSectorSetting.getEnum());
53  } catch (MSXException&) {
54  // DirAsDSK didn't work, no problem
55  }
56  try {
57  auto file = std::make_shared<File>(filename, File::PRE_CACHE);
58  try {
59  // first try XSA
60  return std::make_unique<XSADiskImage>(filename, *file);
61  } catch (MSXException&) {
62  // XSA didn't work, still no problem
63  }
64  try {
65  // next try dmk
66  file->seek(0);
67  return std::make_unique<DMKDiskImage>(filename, file);
68  } catch (MSXException& /*e*/) {
69  // DMK didn't work, still no problem
70  }
71  // next try normal DSK
72  return std::make_unique<DSKDiskImage>(filename, std::move(file));
73 
74  } catch (MSXException& e) {
75  // File could not be opened or (very rare) something is wrong
76  // with the DSK image. Try to interpret the filename as
77  // <filename>:<partition-number>
78  // Try this last because the ':' character could be
79  // part of the filename itself. So only try this if
80  // the name could not be interpreted as a valid
81  // filename.
82  auto pos = diskImage.find_last_of(':');
83  if (pos == string::npos) {
84  // does not contain ':', throw previous exception
85  throw;
86  }
87  std::shared_ptr<SectorAccessibleDisk> wholeDisk;
88  try {
89  Filename filename2(diskImage.substr(0, pos));
90  wholeDisk = std::make_shared<DSKDiskImage>(filename2);
91  } catch (MSXException&) {
92  // If this fails we still prefer to show the
93  // previous error message, because it's most
94  // likely more descriptive.
95  throw e;
96  }
97  unsigned num;
98  try {
99  num = StringOp::fast_stou(std::string_view(diskImage).substr(pos + 1));
100  } catch (std::invalid_argument&) {
101  // not a valid partion number, throw previous exception
102  throw e;
103  }
104  SectorAccessibleDisk& disk = *wholeDisk;
105  return std::make_unique<DiskPartition>(disk, num, std::move(wholeDisk));
106  }
107 }
108 
109 } // namespace openmsx
T getEnum() const noexcept
Definition: EnumSetting.hh:92
Contains the main loop of openMSX.
Definition: Reactor.hh:66
unsigned fast_stou(string_view s)
Definition: StringOp.cc:265
std::string_view substr(std::string_view utf8, std::string_view::size_type first=0, std::string_view::size_type len=std::string_view::npos)
CommandController & getCommandController()
Definition: Reactor.cc:316
FileContext userFileContext(string_view savePath)
Definition: FileContext.cc:161
constexpr const char *const filename
This class represents a filename.
Definition: Filename.hh:17
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
DiskFactory(Reactor &reactor)
Definition: DiskFactory.cc:20
CliComm & getCliComm()
Definition: Reactor.cc:306
std::unique_ptr< Disk > createDisk(const std::string &diskImage, DiskChanger &diskChanger)
Definition: DiskFactory.cc:37