VirtualC64 v5.0 beta
Commodore 64 Emulator
Loading...
Searching...
No Matches
FileSystem.h
1// -----------------------------------------------------------------------------
2// This file is part of VirtualC64
3//
4// Copyright (C) Dirk W. Hoffmann. www.dirkwhoffmann.de
5// This FILE is dual-licensed. You are free to choose between:
6//
7// - The GNU General Public License v3 (or any later version)
8// - The Mozilla Public License v2
9//
10// SPDX-License-Identifier: GPL-3.0-or-later OR MPL-2.0
11// -----------------------------------------------------------------------------
12
13#pragma once
14
15#include "FSDescriptors.h"
16#include "FSBlock.h"
17#include "FSDirEntry.h"
18#include "D64File.h"
19#include "AnyCollection.h"
20#include "IOUtils.h"
21#include <vector>
22
23namespace vc64 {
24
25class FileSystem : CoreObject {
26
27 friend class FSBlock;
28
29 // The block storage
30 std::vector<BlockPtr> blocks;
31
32public:
33
34 // Layout descriptor for this device
35 FSDeviceDescriptor layout;
36
37 // Result of the latest directory scan
38 std::vector<FSDirEntry *> dir;
39
40
41 //
42 // Initializing
43 //
44
45public:
46
47 FileSystem(isize capacity) { init(capacity); }
48 FileSystem(FSDeviceDescriptor &layout) { init(layout); }
49 FileSystem(DiskType type, DOSType vType) { init(type, vType); }
50 FileSystem(const class D64File &d64) throws { init(d64); }
51 FileSystem(class Disk &disk) throws { init(disk); }
52 FileSystem(AnyCollection &collection) throws { init(collection); }
53 FileSystem(MediaFile &file) throws;
54 FileSystem(const fs::path &path) throws { init(path); }
55 ~FileSystem();
56
57private:
58
59 void init(isize capacity);
60 void init(FSDeviceDescriptor &layout);
61 void init(DiskType type, DOSType vType);
62 void init(const class D64File &d64) throws;
63 void init(class Disk &disk) throws;
64 void init(AnyCollection &collection) throws;
65 void init(MediaFile &file) throws;
66 void init(const fs::path &path) throws;
67
68
69public:
70
71 const char *objectName() const override { return "FSVolume"; }
72
73 // Prints information about this volume
74 void info();
75
76
77 //
78 // Debugging
79 //
80
81public:
82
83 // Prints debug information
84 void dump() const;
85
86 // Prints a directory listing
87 void printDirectory();
88
89
90 //
91 // Querying file system properties
92 //
93
94public:
95
96 // Returns the DOS version of this file system
97 DOSType dos() const { return layout.dos; }
98
99 // Gets or sets the disk name
100 PETName<16> getName() const;
101 void setName(PETName<16> name);
102
103 // Gets or sets the disk ID
104 PETName<2> getID() const;
105 void setID(PETName<2> name);
106
107 // Returns the first or second disk ID character
108 u8 diskId1() const { return bamPtr()->data[0xA2]; }
109 u8 diskId2() const { return bamPtr()->data[0xA3]; }
110
111 // Reports layout information
112 isize getNumCyls() const { return layout.numCyls; }
113 isize getNumHeads() const { return layout.numHeads; }
114 isize getNumTracks() const { return layout.numTracks(); }
115 isize getNumSectors(Track track) const { return layout.numSectors(track); }
116 isize getNumBlocks() const { return layout.numBlocks(); }
117 isize getNumBytes() const { return getNumBlocks() * 256; }
118
119 // Reports usage information
120 isize freeBlocks() const;
121 isize usedBlocks() const;
122 isize freeBytes() const { return freeBlocks() * 256; }
123 isize usedBytes() const { return usedBlocks() * 256; }
124 double fillLevel() const { return double(100) * usedBlocks() / getNumBlocks(); }
125
126 // Returns the number of stored files (run a directory scan first!)
127 isize numFiles() const { return isize(dir.size()); }
128
129
130 //
131 // Accessing blocks
132 //
133
134public:
135
136 // Returns the type of a certain block
137 FSBlockType blockType(Block b) const;
138 FSBlockType blockType(TSLink ts) const { return blockType(layout.blockNr(ts)); }
139
140 // Informs about the usage of a certain byte in a certain block
141 FSUsage usage(Block b, u32 pos) const;
142 FSUsage usage(TSLink ts, u32 pos) const { return usage(layout.blockNr(ts), pos); }
143
144 // Gets or sets the error code for a certain block
145 u8 getErrorCode(Block b) const;
146 u8 getErrorCode(TSLink ts) const { return getErrorCode(layout.blockNr(ts)); }
147 void setErrorCode(Block b, u8 code);
148 void setErrorCode(TSLink ts, u8 code) { setErrorCode(layout.blockNr(ts), code); }
149
150 // Queries a pointer from the block storage (may return nullptr)
151 FSBlock *blockPtr(Block b) const;
152 FSBlock *blockPtr(TSLink ts) const { return blockPtr(layout.blockNr(ts)); }
153 FSBlock *bamPtr() const { return blocks[357]; }
154
155 // Follows the block chain link of a specific block
156 FSBlock *nextBlockPtr(Block b) const;
157 FSBlock *nextBlockPtr(TSLink ts) const { return nextBlockPtr(layout.blockNr(ts)); }
158 FSBlock *nextBlockPtr(FSBlock *ptr) const;
159
160
161 //
162 // Working with the BAM (Block Allocation Map)
163 //
164
165 // Checks if a block is marked as free in the allocation bitmap
166 bool isFree(Block b) const { return isFree(layout.tsLink(b)); }
167 bool isFree(TSLink ts) const;
168
169 // Returns the first or the next free block in the interleaving chain
170 TSLink nextFreeBlock(TSLink start) const;
171 TSLink firstFreeBlock() const { return nextFreeBlock({1,0}); }
172
173 // Marks a block as allocated or free
174 void markAsAllocated(Block b) { setAllocBit(b, 0); }
175 void markAsAllocated(TSLink ts) { setAllocBit(ts, 0); }
176
177 void markAsFree(Block b) { setAllocBit(b, 1); }
178 void markAsFree(TSLink ts) { setAllocBit(ts, 1); }
179
180 void setAllocBit(Block b, bool value) { setAllocBit(layout.tsLink(b), value); }
181 void setAllocBit(TSLink ts, bool value);
182
183 // Allocates a certain amount of (interleaved) blocks
184 std::vector<TSLink> allocate(TSLink ref, u32 n);
185 std::vector<TSLink> allocate(u32 n) { return allocate( TSLink{1,0}, n); }
186
187private:
188
189 // Locates the allocation bit for a certain block
190 FSBlock *locateAllocBit(Block b, isize *byte, isize *bit) const;
191 FSBlock *locateAllocBit(TSLink ref, isize *byte, isize *bit) const;
192
193
194 //
195 // Reading files
196 //
197
198public:
199
200 // Returns the name of a file
201 PETName<16> fileName(isize nr) const;
202 PETName<16> fileName(FSDirEntry *entry) const;
203
204 // Returns the type of a file
205 FSFileType fileType(isize nr) const;
206 FSFileType fileType(FSDirEntry *entry) const;
207
208 // Returns the precise size of a file in bytes
209 isize fileSize(isize nr) const;
210 isize fileSize(FSDirEntry *entry) const;
211
212 // Returns the size of a file in blocks (read from the BAM)
213 isize fileBlocks(isize nr) const;
214 isize fileBlocks(FSDirEntry *entry) const;
215
216 // Returns the load address of a file
217 u16 loadAddr(isize nr) const;
218 u16 loadAddr(FSDirEntry *entry) const;
219
220 // Copies the file contents into a buffer
221 void copyFile(isize nr, u8 *buf, u64 len, u64 offset = 0) const;
222 void copyFile(FSDirEntry *entry, u8 *buf, u64 len, u64 offset = 0) const;
223
224 // Scans the directory and stores the result in variable 'dir'
225 void scanDirectory(bool skipInvisible = true);
226
227
228 //
229 // Writing files
230 //
231
232 // Creates a new file
233 bool makeFile(PETName<16> name, const u8 *buf, isize cnt);
234
235private:
236
237 bool makeFile(PETName<16> name, FSDirEntry *entry, const u8 *buf, isize cnt);
238
239 // Returns the next free directory entry or creates one
240 FSDirEntry *getOrCreateNextFreeDirEntry();
241
242
243 //
244 // Integrity checking
245 //
246
247public:
248
249 // Checks all blocks in this volume
250 FSErrorReport check(bool strict);
251
252 // Checks a single byte in a certain block
253 ErrorCode check(isize blockNr, u32 pos, u8 *expected, bool strict);
254
255 // Checks if the block with the given number is part of the volume
256 bool isBlockNumber(isize nr) const { return nr >= 0 && nr < getNumBlocks(); }
257
258 // Returns the position in the corrupted block list (0 = OK)
259 isize getCorrupted(isize blockNr) const;
260
261 // Checks if a certain block is corrupted
262 bool isCorrupted(isize blockNr) const { return getCorrupted(blockNr) != 0; }
263
264 // Returns the number of the next or previous corrupted block
265 isize nextCorrupted(isize blockNr) const;
266 isize prevCorrupted(isize blockNr) const;
267
268 // Checks if a certain block is the n-th corrupted block
269 bool isCorrupted(isize blockNr, isize n) const;
270
271 // Returns the number of the the n-th corrupted block
272 isize seekCorruptedBlock(isize n) const;
273
274
275 //
276 // Importing and exporting
277 //
278
279public:
280
281 // Reads a single byte from a block
282 u8 readByte(Block block, isize offset) const;
283 u8 readByte(TSLink ts, isize offset) const { return readByte(layout.blockNr(ts), offset); }
284
285 // Returns a portion of the block as an ASCII dump
286 string ascii(Block nr, isize offset, isize len) const;
287
288 // Imports the volume from a buffer
289 void importVolume(const u8 *src, isize size) throws;
290 bool importVolume(const u8 *src, isize size, ErrorCode *err);
291
292 // Imports a folder from the host file system
293 void importDirectory(const fs::path &path) throws;
294 void importDirectory(const fs::directory_entry &dir) throws;
295
296 // Exports the volume to a buffer
297 bool exportVolume(u8 *dst, isize size, ErrorCode *err = nullptr);
298
299 // Exports a single block or a range of blocks
300 bool exportBlock(isize nr, u8 *dst, isize size, ErrorCode *err = nullptr);
301 bool exportBlocks(isize first, isize last, u8 *dst, isize size, ErrorCode *err = nullptr);
302
303 // Exports all files or a single file to a folder in the host file system
304 void exportDirectory(const fs::path &path, bool createDir = true) throws;
305 void exportFile(FSDirEntry *item, const fs::path &path) throws;
306 void exportFile(FSDirEntry *entry, std::ofstream &stream) throws;
307
308
309 //
310 // GUI helper functions
311 //
312
313 // Determines how the layout image should look like in a certain column
314 FSBlockType getDisplayType(isize column);
315
316 // Determines how the diagnose image should look like in a certain column
317 isize diagnoseImageSlice(isize column);
318
319 // Searches the block list for a block of a specific type
320 isize nextBlockOfType(FSBlockType type, isize after);
321
322 // Searches the block list for a corrupted block
323 isize nextCorruptedBlock(isize after);
324};
325
326}
VirtualC64 project namespace.
Definition CmdQueue.cpp:16