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