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
15namespace openmsx {
16
18 : reactor(reactor_)
19 , syncDirAsDSKSetting(
20 reactor.getCommandController(), "DirAsDSKmode",
21 "type of synchronisation between host directory and dir-as-dsk disk image",
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::BOOT_SECTOR_DOS2, EnumSetting<DirAsDSK::BootSectorType>::Map{
29 {"DOS1", DirAsDSK::BOOT_SECTOR_DOS1},
30 {"DOS2", DirAsDSK::BOOT_SECTOR_DOS2}})
31{
32}
33
34std::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 partition 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)
This class represents a filename.
Definition Filename.hh:20
Contains the main loop of openMSX.
Definition Reactor.hh:72
This file implemented 3 utility functions:
Definition Autofire.cc:11
FileContext userFileContext(string_view savePath)