diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index 2c76f0d..43345ed 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -25,11 +25,9 @@ using ProFUSE::POSIXException; BlockDevice::BlockDevice() { - _cache = NULL; } BlockDevice::~BlockDevice() { - delete _cache; } void BlockDevice::zeroBlock(unsigned block) @@ -79,211 +77,3 @@ void *BlockDevice::read(TrackSector ts) return NULL; } - -#pragma mark - -#pragma mark DiskImage - -unsigned DiskImage::ImageType(const char *type, unsigned defv) -{ - const char *tmp; - - if (type == 0 || *type == 0) return defv; - - // type could be a filename, in which case we check the extension. - tmp = std::strrchr(type, '.'); - if (tmp) type = tmp + 1; - if (*type == 0) return defv; - - - if (::strcasecmp(type, "2mg") == 0) - return '2IMG'; - if (::strcasecmp(type, "2img") == 0) - return '2IMG'; - - if (::strcasecmp(type, "dc42") == 0) - return 'DC42'; - - if (::strcasecmp(type, "po") == 0) - return 'PO__'; - if (::strcasecmp(type, "dmg") == 0) - return 'PO__'; - - if (::strcasecmp(type, "dsk") == 0) - return 'DO__'; - if (::strcasecmp(type, "do") == 0) - return 'DO__'; - - if (::strcasecmp(type, "davex") == 0) - return 'DVX_'; - - /* - // not supported yet. - if (::strcasecmp(tmp, "sdk") == 0) - return 'SDK_'; - */ - return defv; -} - - - -DiskImage::DiskImage(const char *name, bool readOnly) : - _file(NULL) -{ - _file = new MappedFile(name, readOnly); -} - -DiskImage::DiskImage(MappedFile *file) : - _file(file) -{ -} - -DiskImage::~DiskImage() -{ - delete _file; -} - -bool DiskImage::readOnly() -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::readOnly" - - if (_file) return _file->readOnly(); - - throw Exception(__METHOD__ ": File not set."); -} - -unsigned DiskImage::blocks() -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::blocks" - - if (_file) return _file->blocks(); - - throw Exception(__METHOD__ ": File not set."); -} - -void DiskImage::read(unsigned block, void *bp) -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::read" - - - if (_file) return _file->readBlock(block, bp); - - throw Exception(__METHOD__ ": File not set."); -} - -void DiskImage::write(unsigned block, const void *bp) -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::write" - - if (_file) return _file->writeBlock(block, bp); - - throw Exception(__METHOD__ ": File not set."); -} - - - -void DiskImage::sync() -{ - #undef __METHOD__ - #define __METHOD__ "DiskImage::sync" - - if (_file) return _file->sync(); - - throw Exception(__METHOD__ ": File not set."); -} - - - -AbstractBlockCache *DiskImage::createBlockCache() -{ - if (_file->encoding() == MappedFile::ProDOSOrder) - return new MappedBlockCache(_file->imageData(), _file->blocks()); - - return BlockDevice::createBlockCache(); -} - - -ProDOSOrderDiskImage::ProDOSOrderDiskImage(const char *name, bool readOnly) : - DiskImage(name, readOnly) -{ - Validate(file()); -} - -ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) : - DiskImage(file) -{ -} - -ProDOSOrderDiskImage *ProDOSOrderDiskImage::Create(const char *name, size_t blocks) -{ - MappedFile *file = new MappedFile(name, blocks * 512); - file->setBlocks(blocks); - return new ProDOSOrderDiskImage(file); -} - -ProDOSOrderDiskImage *ProDOSOrderDiskImage::Open(MappedFile *file) -{ - Validate(file); - return new ProDOSOrderDiskImage(file); -} - -void ProDOSOrderDiskImage::Validate(MappedFile *f) -{ - #undef __METHOD__ - #define __METHOD__ "ProDOSOrderDiskImage::Validate" - - if (!f) throw Exception(__METHOD__ ": File not set."); - - size_t size = f->fileSize(); - - if (size % 512) - throw Exception(__METHOD__ ": Invalid file format."); - - f->reset(); - f->setBlocks(size / 512); -} - -DOSOrderDiskImage::DOSOrderDiskImage(const char *name, bool readOnly) : - DiskImage(name, readOnly) -{ - Validate(file()); -} - -DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) : - DiskImage(file) -{ -} - -DOSOrderDiskImage *DOSOrderDiskImage::Create(const char *name, size_t blocks) -{ - MappedFile *file = new MappedFile(name, blocks * 512); - file->setEncoding(MappedFile::DOSOrder); - file->setBlocks(blocks); - return new DOSOrderDiskImage(file); -} - -DOSOrderDiskImage *DOSOrderDiskImage::Open(MappedFile *file) -{ - Validate(file); - return new DOSOrderDiskImage(file); -} - -void DOSOrderDiskImage::Validate(MappedFile *f) -{ - #undef __METHOD__ - #define __METHOD__ "DOSOrderDiskImage::Validate" - - if (!f) throw Exception(__METHOD__ ": File not set."); - - size_t size = f->fileSize(); - - if (size % 512) - throw Exception(__METHOD__ ": Invalid file format."); - - f->reset(); - f->setEncoding(MappedFile::DOSOrder); - f->setBlocks(size / 512); -} diff --git a/Device/BlockDevice.h b/Device/BlockDevice.h index 7d8b262..17f6369 100644 --- a/Device/BlockDevice.h +++ b/Device/BlockDevice.h @@ -10,10 +10,7 @@ namespace Device { -class MappedFile; -class AbstractBlockCache; - - +class BlockCache; class BlockDevice { public: @@ -26,9 +23,6 @@ public: virtual void write(unsigned block, const void *bp) = 0; virtual void write(TrackSector ts, const void *bp); - // direct access to mapped memory (not always possible). - virtual void *read(unsigned block); - virtual void *read(TrackSector ts); virtual unsigned blocks() = 0; @@ -43,77 +37,15 @@ public: void zeroBlock(unsigned block); - AbstractBlockCache *blockCache(); - protected: BlockDevice(); - virtual AbstractBlockCache *createBlockCache(); - -private: - AbstractBlockCache *_cache; + + friend BlockCache; + virtual BlockCache *createBlockCache(); }; -class DiskImage : public BlockDevice { -public: - - static unsigned ImageType(const char *type, unsigned defv = 0); - - virtual ~DiskImage(); - - virtual void read(unsigned block, void *bp); - virtual void write(unsigned block, const void *bp); - virtual void sync(); - - virtual bool readOnly(); - virtual unsigned blocks(); - -protected: - - virtual AbstractBlockCache *createBlockCache(); - - DiskImage(MappedFile * = 0); - DiskImage(const char *name, bool readOnly); - - MappedFile *file() { return _file; } - void setFile(MappedFile *); - -private: - MappedFile *_file; -}; - - -class ProDOSOrderDiskImage : public DiskImage { -public: - - ProDOSOrderDiskImage(const char *name, bool readOnly); - - static ProDOSOrderDiskImage *Create(const char *name, size_t blocks); - static ProDOSOrderDiskImage *Open(MappedFile *); - -private: - ProDOSOrderDiskImage(MappedFile *); - static void Validate(MappedFile *); -}; - -class DOSOrderDiskImage : public DiskImage { -public: - - DOSOrderDiskImage(const char *name, bool readOnly); - - static DOSOrderDiskImage *Create(const char *name, size_t blocks); - static DOSOrderDiskImage *Open(MappedFile *); - -private: - DOSOrderDiskImage(MappedFile *); - static void Validate(MappedFile *); -}; - - - - - } #endif \ No newline at end of file diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp new file mode 100644 index 0000000..7237c8f --- /dev/null +++ b/Device/DiskImage.cpp @@ -0,0 +1,226 @@ + +#include +#include +#include + +#include +#include +#include + + +#include +#include + +#include + + +using namespace Device; + +using ProFUSE::Exception; +using ProFUSE::POSIXException; + + +unsigned DiskImage::ImageType(const char *type, unsigned defv) +{ + const char *tmp; + + if (type == 0 || *type == 0) return defv; + + // type could be a filename, in which case we check the extension. + tmp = std::strrchr(type, '.'); + if (tmp) type = tmp + 1; + if (*type == 0) return defv; + + + if (::strcasecmp(type, "2mg") == 0) + return '2IMG'; + if (::strcasecmp(type, "2img") == 0) + return '2IMG'; + + if (::strcasecmp(type, "dc42") == 0) + return 'DC42'; + + if (::strcasecmp(type, "po") == 0) + return 'PO__'; + if (::strcasecmp(type, "dmg") == 0) + return 'PO__'; + + if (::strcasecmp(type, "dsk") == 0) + return 'DO__'; + if (::strcasecmp(type, "do") == 0) + return 'DO__'; + + if (::strcasecmp(type, "davex") == 0) + return 'DVX_'; + + /* + // not supported yet. + if (::strcasecmp(tmp, "sdk") == 0) + return 'SDK_'; + */ + return defv; +} + + + +DiskImage::DiskImage(const char *name, bool readOnly) : + _file(NULL) +{ + _file = new MappedFile(name, readOnly); +} + +DiskImage::DiskImage(MappedFile *file) : + _file(file) +{ +} + +DiskImage::~DiskImage() +{ + delete _file; +} + +bool DiskImage::readOnly() +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::readOnly" + + if (_file) return _file->readOnly(); + + throw Exception(__METHOD__ ": File not set."); +} + +unsigned DiskImage::blocks() +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::blocks" + + if (_file) return _file->blocks(); + + throw Exception(__METHOD__ ": File not set."); +} + +void DiskImage::read(unsigned block, void *bp) +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::read" + + + if (_file) return _file->readBlock(block, bp); + + throw Exception(__METHOD__ ": File not set."); +} + +void DiskImage::write(unsigned block, const void *bp) +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::write" + + if (_file) return _file->writeBlock(block, bp); + + throw Exception(__METHOD__ ": File not set."); +} + + + +void DiskImage::sync() +{ + #undef __METHOD__ + #define __METHOD__ "DiskImage::sync" + + if (_file) return _file->sync(); + + throw Exception(__METHOD__ ": File not set."); +} + + + +AbstractBlockCache *DiskImage::createBlockCache() +{ + if (_file->encoding() == MappedFile::ProDOSOrder) + return new MappedBlockCache(_file->imageData(), _file->blocks()); + + return BlockDevice::createBlockCache(); +} + + +ProDOSOrderDiskImage::ProDOSOrderDiskImage(const char *name, bool readOnly) : + DiskImage(name, readOnly) +{ + Validate(file()); +} + +ProDOSOrderDiskImage::ProDOSOrderDiskImage(MappedFile *file) : + DiskImage(file) +{ +} + +ProDOSOrderDiskImage *ProDOSOrderDiskImage::Create(const char *name, size_t blocks) +{ + MappedFile *file = new MappedFile(name, blocks * 512); + file->setBlocks(blocks); + return new ProDOSOrderDiskImage(file); +} + +ProDOSOrderDiskImage *ProDOSOrderDiskImage::Open(MappedFile *file) +{ + Validate(file); + return new ProDOSOrderDiskImage(file); +} + +void ProDOSOrderDiskImage::Validate(MappedFile *f) +{ + #undef __METHOD__ + #define __METHOD__ "ProDOSOrderDiskImage::Validate" + + if (!f) throw Exception(__METHOD__ ": File not set."); + + size_t size = f->fileSize(); + + if (size % 512) + throw Exception(__METHOD__ ": Invalid file format."); + + f->reset(); + f->setBlocks(size / 512); +} + +DOSOrderDiskImage::DOSOrderDiskImage(const char *name, bool readOnly) : + DiskImage(name, readOnly) +{ + Validate(file()); +} + +DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) : + DiskImage(file) +{ +} + +DOSOrderDiskImage *DOSOrderDiskImage::Create(const char *name, size_t blocks) +{ + MappedFile *file = new MappedFile(name, blocks * 512); + file->setEncoding(MappedFile::DOSOrder); + file->setBlocks(blocks); + return new DOSOrderDiskImage(file); +} + +DOSOrderDiskImage *DOSOrderDiskImage::Open(MappedFile *file) +{ + Validate(file); + return new DOSOrderDiskImage(file); +} + +void DOSOrderDiskImage::Validate(MappedFile *f) +{ + #undef __METHOD__ + #define __METHOD__ "DOSOrderDiskImage::Validate" + + if (!f) throw Exception(__METHOD__ ": File not set."); + + size_t size = f->fileSize(); + + if (size % 512) + throw Exception(__METHOD__ ": Invalid file format."); + + f->reset(); + f->setEncoding(MappedFile::DOSOrder); + f->setBlocks(size / 512); +} diff --git a/Device/DiskImage.h b/Device/DiskImage.h new file mode 100644 index 0000000..ca93af7 --- /dev/null +++ b/Device/DiskImage.h @@ -0,0 +1,92 @@ +#ifndef __DISKIMAGE_H__ +#define __DISKIMAGE_H__ + +#include +#include + +#include + +#include + +#include + +namespace Device { + + +class DiskImage : public BlockDevice { +public: + + static unsigned ImageType(const char *type, unsigned defv = 0); + + virtual ~DiskImage(); + + virtual void read(unsigned block, void *bp); + virtual void write(unsigned block, const void *bp); + virtual void sync(); + + virtual bool readOnly(); + virtual unsigned blocks(); + +protected: + + + DiskImage(MappedFile * = 0); + DiskImage(const char *name, bool readOnly); + + void setOffset(uint32_t offset); + void *address() const { return _address; } + void *base() const { return _file.address(); } + + void readPO(unsigned block, void *bp); + void writePO(unsigned block, const void *bp); + + void readDO(unsigned block, void *bp); + void writeDO(unsigned block, const void *bp); + + // readNib + // writeNib + +private: + + MappedFile _file; + void *_address; + uint32_t _offset; + + bool _readOnly; + unsigned _blocks; +}; + + +class ProDOSOrderDiskImage : public DiskImage { +public: + + ProDOSOrderDiskImage(const char *name, bool readOnly); + + static ProDOSOrderDiskImage *Create(const char *name, size_t blocks); + static ProDOSOrderDiskImage *Open(MappedFile *); + +private: + ProDOSOrderDiskImage(MappedFile *); + static void Validate(MappedFile *); +}; + +class DOSOrderDiskImage : public DiskImage { +public: + + DOSOrderDiskImage(const char *name, bool readOnly); + + static DOSOrderDiskImage *Create(const char *name, size_t blocks); + static DOSOrderDiskImage *Open(MappedFile *); + +private: + DOSOrderDiskImage(MappedFile *); + static void Validate(MappedFile *); +}; + + + + + +} + +#endif \ No newline at end of file