ScummVM API documentation
disk_image.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #include "common/bitarray.h"
23 #include "common/ptr.h"
24 #include "common/file.h"
25 #include "common/debug.h"
26 
27 #ifndef COMMON_FORMATS_DISK_IMAGE_H
28 #define COMMON_FORMATS_DISK_IMAGE_H
29 
30 namespace Common {
31 
32 // Disk image parsers / decoders
33 //
34 // These classes handle floppy disk image files. Multiple formats are supported.
35 // An image's file name extension determines its format. DiskImage::open selects
36 // the format and expected disk size. Data can be read by track/sector/offset
37 // or by the calculated stream position. Several file systems can also be read.
38 //
39 // Supported image formats:
40 // .do Apple II disk sectors. 35 tracks, 16 sectors, no encoding.
41 // .dsk Same as .do. Note that alternative sector orders are not handled.
42 // Currently, if clients want to support images with a different sector
43 // order, then they will have to detect and handle it themselves.
44 // .d13 Apple II disk sectors. 35 tracks, 13 sectors, no encoding.
45 // .nib Apple II disk nibbles. 35 tracks, 13 or 16 sectors, nibble-encoded.
46 // .woz Apple II comprehensive disk bitstream. 35 tracks, 13 or 16 sectors.
47 // This encoding format takes a noticeable amount of time to decode.
48 // .img PC disk sectors. 40 tracks, 8 sectors, no encoding.
49 // .xfd Atari disk sectors. 40 tracks, 18 sectors, no encoding.
50 //
51 // For encoded formats, the default behavior is to decode every track when
52 // opening an image. Lazy decoding can also be enabled, causing tracks to be
53 // decoded when they are first accessed. This can significantly speed up access
54 // if the format is expensive to decode but only a little data is needed.
55 //
56 // This code was originally part of the ADL engine.
57 
58 class SeekableReadStream;
59 class String;
60 
65  DiskImageEncodingNone,
66  DiskImageEncodingNib,
67  DiskImageEncodingWoz
68 };
69 
70 // Used for disk image detection
71 int32 computeMD5(const Common::FSNode &node, Common::String &md5, uint32 md5Bytes);
72 
73 class DataBlock {
74 public:
75  virtual ~DataBlock() { }
76 
77  virtual Common::SeekableReadStream *createReadStream() const = 0;
78 };
79 
82 
83 class Files {
84 public:
85  virtual ~Files() { }
86 
87  virtual const DataBlockPtr getDataBlock(const Common::Path &filename, uint offset = 0) const = 0;
88  virtual Common::SeekableReadStream *createReadStream(const Common::Path &filename, uint offset = 0) const = 0;
89  virtual bool exists(const Common::Path &filename) const = 0;
90 
91 protected:
92  class DataBlock : public Common::DataBlock {
93  public:
94  DataBlock(const Files *files, const Common::Path &filename, uint offset) :
95  _files(files),
96  _filename(filename),
97  _offset(offset) { }
98 
99  Common::SeekableReadStream *createReadStream() const override {
100  return _files->createReadStream(_filename, _offset);
101  }
102 
103  private:
104  const Common::Path _filename;
105  uint _offset;
106  const Files *_files;
107  };
108 };
109 
110 class DiskImage {
111 public:
112  DiskImage() :
113  _inputStream(nullptr),
114  _decodeStream(nullptr),
115  _decodeBuffer(nullptr),
116  _encoding(DiskImageEncodingNone),
117  _lazyDecoding(false),
118  _tracks(0),
119  _sectorsPerTrack(0),
120  _bytesPerSector(0),
121  _sectorLimit(0),
122  _firstSector(0) { }
123 
124  ~DiskImage() {
125  delete _inputStream;
126  delete _decodeStream; // frees _decodeBuffer
127  }
128 
129  bool open(const Common::Path &filename);
130  bool open(const Common::FSNode &node);
131  const DataBlockPtr getDataBlock(uint track, uint sector, uint offset = 0, uint size = 0) const;
132  Common::SeekableReadStream *createReadStream(uint track, uint sector, uint offset = 0, uint size = 0, uint sectorsUsed = 0) const;
133  Common::SeekableReadStream *releaseStream();
134  Common::SeekableReadStream *getDiskStream() const { return _decodeBuffer ? _decodeStream : _inputStream; }
135  uint32 read(void *dataPtr, uint32 diskPosition, uint32 dataSize);
136  void setLazyDecoding(bool lazyDecoding) { _lazyDecoding = lazyDecoding; }
137  void setSectorLimit(uint sectorLimit) { _sectorLimit = sectorLimit; } // Maximum number of sectors to read per track before stepping
138  uint getBytesPerSector() const { return _bytesPerSector; }
139  uint getSectorsPerTrack() const { return _sectorsPerTrack; }
140  uint getTracks() const { return _tracks; }
141 
142 protected:
143  class DataBlock : public Common::DataBlock {
144  public:
145  DataBlock(const DiskImage *disk, uint track, uint sector, uint offset, uint size, uint sectorLimit) :
146  _track(track),
147  _sector(sector),
148  _offset(offset),
149  _size(size),
150  _sectorLimit(sectorLimit),
151  _disk(disk) { }
152 
153  Common::SeekableReadStream *createReadStream() const override {
154  return _disk->createReadStream(_track, _sector, _offset, _size, _sectorLimit);
155  }
156 
157  private:
158  uint _track, _sector, _offset, _size;
159  uint _sectorLimit;
160  const DiskImage *_disk;
161  };
162 
163  Common::String _name;
164  Common::SeekableReadStream *_inputStream;
165  Common::SeekableReadStream *_decodeStream;
166  byte *_decodeBuffer;
167  Common::BitArray _decodedTracks;
168  DiskImageEncoding _encoding;
169  bool _lazyDecoding;
170 
171  uint _tracks, _sectorsPerTrack, _bytesPerSector, _firstSector;
172  uint _sectorLimit;
173 
174 private:
175  bool open(const Common::String &name, Common::File *f);
176  void decodeTrack(uint track);
177 };
178 
179 // Data in plain files
180 class Files_Plain : public Files {
181 public:
182  const DataBlockPtr getDataBlock(const Common::Path &filename, uint offset = 0) const override;
183  Common::SeekableReadStream *createReadStream(const Common::Path &filename, uint offset = 0) const override;
184  bool exists(const Common::Path &filename) const override { return Common::File::exists(filename); }
185 };
186 
187 // Data in files contained in Apple DOS 3.3 disk image
188 class Files_AppleDOS : public Files {
189 public:
190  Files_AppleDOS();
191  ~Files_AppleDOS() override;
192 
193  bool open(const Common::Path &filename);
194  const DataBlockPtr getDataBlock(const Common::Path &filename, uint offset = 0) const override;
195  Common::SeekableReadStream *createReadStream(const Common::Path &filename, uint offset = 0) const override;
196  bool exists(const Common::Path &filename) const override { return _toc.contains(filename); }
197 
198 private:
199  enum FileType {
200  kFileTypeText = 0,
201  kFileTypeAppleSoft = 2,
202  kFileTypeBinary = 4
203  };
204 
205  enum {
206  kSectorSize = 256,
207  kFilenameLen = 30
208  };
209 
210  struct TrackSector {
211  byte track;
212  byte sector;
213  };
214 
215  struct TOCEntry {
216  byte type;
217  uint16 totalSectors;
219  };
220 
221  void readVTOC();
222  void readSectorList(TrackSector start, Common::Array<TrackSector> &list);
223  Common::SeekableReadStream *createReadStreamText(const TOCEntry &entry) const;
224  Common::SeekableReadStream *createReadStreamBinary(const TOCEntry &entry) const;
225 
226  DiskImage *_disk;
228 };
229 
230 } // End of namespace Common
231 
232 #endif
Definition: str.h:59
Definition: disk_image.h:92
Definition: disk_image.h:188
Definition: path.h:52
Definition: stream.h:745
Definition: disk_image.h:110
Definition: file.h:47
Definition: algorithm.h:29
Definition: fs.h:69
Definition: bitarray.h:29
static bool exists(const Path &filename)
Definition: disk_image.h:143
Definition: disk_image.h:83
DiskImageEncoding
Definition: disk_image.h:64
Definition: disk_image.h:73
Definition: disk_image.h:180