diff --git a/Emulator/Base/Defaults.cpp b/Emulator/Base/Defaults.cpp index 18cf668e8..620a5a844 100644 --- a/Emulator/Base/Defaults.cpp +++ b/Emulator/Base/Defaults.cpp @@ -33,6 +33,7 @@ Defaults::Defaults() setFallback(OPT_C64_SNAP_AUTO, false); setFallback(OPT_C64_SNAP_DELAY, 10); + setFallback(OPT_C64_SNAP_COMPRESS, true); setFallback(OPT_POWER_GRID, GRID_STABLE_50HZ); diff --git a/Emulator/Base/MsgQueueTypes.h b/Emulator/Base/MsgQueueTypes.h index 33ac8a686..19cc668c1 100644 --- a/Emulator/Base/MsgQueueTypes.h +++ b/Emulator/Base/MsgQueueTypes.h @@ -95,7 +95,7 @@ enum_long(MSG_TYPE) MSG_SHAKING, ///< A shaking mouse has been detected // Snapshots - MSG_SNAPSHOT_TAKEN, ///< A snapshot has been taken (see OPT_SNAPSHOTS) + MSG_SNAPSHOT_TAKEN, ///< A snapshot has been taken (see OPT_C64_SNAP_AUTO) MSG_SNAPSHOT_RESTORED, ///< A snapshot has been restored // Screen recording diff --git a/Emulator/Base/Option.cpp b/Emulator/Base/Option.cpp index 42bb12ce7..203e1ba0c 100644 --- a/Emulator/Base/Option.cpp +++ b/Emulator/Base/Option.cpp @@ -41,6 +41,7 @@ OptionParser::create(Option opt, i64 arg) case OPT_C64_SNAP_AUTO: return boolParser(); case OPT_C64_SNAP_DELAY: return numParser(" sec"); + case OPT_C64_SNAP_COMPRESS: return boolParser(); case OPT_VICII_REVISION: return enumParser.template operator()(); case OPT_VICII_GRAY_DOT_BUG: return boolParser(); diff --git a/Emulator/Base/OptionTypes.h b/Emulator/Base/OptionTypes.h index 5eb61e2a6..cec7911d1 100644 --- a/Emulator/Base/OptionTypes.h +++ b/Emulator/Base/OptionTypes.h @@ -40,6 +40,7 @@ enum_long(OPT) // Snapshots OPT_C64_SNAP_AUTO, ///< Automatically take a snapshots OPT_C64_SNAP_DELAY, ///< Delay between two snapshots in seconds + OPT_C64_SNAP_COMPRESS, ///< Compress snapshot data // VICII OPT_VICII_REVISION, ///< Chip revision @@ -219,6 +220,7 @@ struct OptionEnum : util::Reflection { case OPT_C64_SNAP_AUTO: return "C64.SNAP_AUTO"; case OPT_C64_SNAP_DELAY: return "C64.SNAP_DELAY"; + case OPT_C64_SNAP_COMPRESS: return "C64.SNAP_COMPRESS"; case OPT_VICII_REVISION: return "VICII.REVISION"; case OPT_VICII_GRAY_DOT_BUG: return "VICII.GRAY_DOT_BUG"; @@ -372,6 +374,7 @@ struct OptionEnum : util::Reflection { case OPT_C64_SNAP_AUTO: return "Automatically take snapshots"; case OPT_C64_SNAP_DELAY: return "Time span between two snapshots"; + case OPT_C64_SNAP_COMPRESS: return "Compress snapshot data"; case OPT_VICII_REVISION: return "Chip revision"; case OPT_VICII_GRAY_DOT_BUG: return "Emulate gray-dot bug"; diff --git a/Emulator/Components/C64.cpp b/Emulator/Components/C64.cpp index 933fc09b2..b4a471e78 100644 --- a/Emulator/Components/C64.cpp +++ b/Emulator/Components/C64.cpp @@ -1249,10 +1249,15 @@ C64::clearFlag(u32 flag) MediaFile * C64::takeSnapshot() { - { SUSPENDED + Snapshot *result; - return new Snapshot(*this); - } + // Take the snapshot + { SUSPENDED result = new Snapshot(*this); } + + // Compress the snapshot if requested + if (config.compressSnapshots) result->compress(); + + return result; } void @@ -1260,7 +1265,13 @@ C64::loadSnapshot(const MediaFile &file) { try { - const Snapshot &snapshot = dynamic_cast(file); + const Snapshot &snap = dynamic_cast(file); + + // Make a copy so we can modify the snapshot + Snapshot snapshot(snap); + + // Uncompress the snapshot + snapshot.uncompress(); { SUSPENDED diff --git a/Emulator/Components/C64.h b/Emulator/Components/C64.h index 21b95e1e7..014e936ea 100644 --- a/Emulator/Components/C64.h +++ b/Emulator/Components/C64.h @@ -114,6 +114,7 @@ class C64 final : public CoreComponent, public Inspectable { OPT_C64_RUN_AHEAD, OPT_C64_SNAP_AUTO, OPT_C64_SNAP_DELAY, + OPT_C64_SNAP_COMPRESS }; private: diff --git a/Emulator/Components/C64Base.cpp b/Emulator/Components/C64Base.cpp index 1ac0cafb8..1fecae85b 100644 --- a/Emulator/Components/C64Base.cpp +++ b/Emulator/Components/C64Base.cpp @@ -191,6 +191,7 @@ C64::getOption(Option opt) const case OPT_C64_RUN_AHEAD: return config.runAhead; case OPT_C64_SNAP_AUTO: return config.snapshots; case OPT_C64_SNAP_DELAY: return config.snapshotDelay; + case OPT_C64_SNAP_COMPRESS: return config.compressSnapshots; default: fatalError; @@ -242,6 +243,10 @@ C64::checkOption(Option opt, i64 value) } return; + case OPT_C64_SNAP_COMPRESS: + + return; + default: throw Error(VC64ERROR_OPT_UNSUPPORTED); } @@ -275,6 +280,11 @@ C64::setOption(Option opt, i64 value) updateClockFrequency(); return; + case OPT_C64_RUN_AHEAD: + + config.runAhead = isize(value); + return; + case OPT_C64_SNAP_AUTO: config.snapshots = bool(value); @@ -287,9 +297,9 @@ C64::setOption(Option opt, i64 value) scheduleNextSNPEvent(); return; - case OPT_C64_RUN_AHEAD: + case OPT_C64_SNAP_COMPRESS: - config.runAhead = isize(value); + config.compressSnapshots = bool(value); return; default: diff --git a/Emulator/Components/C64Types.h b/Emulator/Components/C64Types.h index 7b079bd96..ef29a8b10 100644 --- a/Emulator/Components/C64Types.h +++ b/Emulator/Components/C64Types.h @@ -279,7 +279,7 @@ typedef struct isize snapshotDelay; //! Indicates whether snapshots should be stored in compressed form - bool snapshotCompress; + bool compressSnapshots; } C64Config; diff --git a/Emulator/Media/MediaFile.h b/Emulator/Media/MediaFile.h index c2101e293..d4a229de2 100644 --- a/Emulator/Media/MediaFile.h +++ b/Emulator/Media/MediaFile.h @@ -75,6 +75,11 @@ class MediaFile { // Return a preview image (only available for snapshot files) virtual const u32 *previewImageData() const { return nullptr; } + // Handels data compression (only implemented by snapshot files) + virtual bool isCompressed() const { return false; } + virtual void compress() { } + virtual void uncompress() { } + // virtual void flash(u8 *buf, isize offset = 0) const = 0; @@ -85,8 +90,6 @@ class MediaFile { public: - // virtual isize readFromStream(std::istream &stream) = 0; - // virtual isize readFromFile(const std::filesystem::path &path) = 0; virtual isize readFromBuffer(const u8 *buf, isize len) = 0; virtual isize writeToStream(std::ostream &stream) = 0; diff --git a/Emulator/Media/Snapshot.cpp b/Emulator/Media/Snapshot.cpp index f77a54b29..508ee6f67 100644 --- a/Emulator/Media/Snapshot.cpp +++ b/Emulator/Media/Snapshot.cpp @@ -91,10 +91,6 @@ Snapshot::Snapshot(C64 &c64) : Snapshot(c64.size()) if (SNP_DEBUG) c64.dump(Category::State); c64.save(getSnapshotData()); - - // REMOVE ASAP (TEST CODE FOR THE RUN-LENGTH ENCODER) - compress(); - uncompress(); } void diff --git a/Emulator/Media/Snapshot.h b/Emulator/Media/Snapshot.h index ea22853fe..024a5a2cc 100644 --- a/Emulator/Media/Snapshot.h +++ b/Emulator/Media/Snapshot.h @@ -128,11 +128,11 @@ class Snapshot : public AnyFile { // // Indicates whether the snapshot is compressed - bool isCompressed() { return getHeader()->compressed; } + bool isCompressed() const override { return getHeader()->compressed; } // Compresses or uncompresses the snapshot - void compress(); - void uncompress(); + void compress() override; + void uncompress() override; }; } diff --git a/Emulator/Utilities/IOUtils.cpp b/Emulator/Utilities/IOUtils.cpp index d2dd5a0e9..8175cecca 100644 --- a/Emulator/Utilities/IOUtils.cpp +++ b/Emulator/Utilities/IOUtils.cpp @@ -188,7 +188,7 @@ bool matchingBufferHeader(const u8 *buf, isize blen, const string &header, isize bool matchingBufferHeader(const u8 *buf, const string &header, isize offset) { - auto blen = isize(std::numeric_limits::max); + auto blen = std::numeric_limits::max(); return matchingBufferHeader(buf, blen, header, offset); } diff --git a/GUI/Panels/Captures/SnapshotViewer.swift b/GUI/Panels/Captures/SnapshotViewer.swift index 7b9ad3851..d8ccec5c8 100644 --- a/GUI/Panels/Captures/SnapshotViewer.swift +++ b/GUI/Panels/Captures/SnapshotViewer.swift @@ -62,9 +62,10 @@ class SnapshotViewer: DialogController { if let snapshot = myDocument.snapshots.element(at: currentItem) { let takenAt = snapshot.timeStamp + let compressed = snapshot.compressed ? "(Compressed)" : "" text1.stringValue = "Taken at " + timeInfo(time: takenAt) text2.stringValue = Date.elapsed(time: takenAt) - text3.stringValue = "\(snapshot.size / 1024) KB" + text3.stringValue = "\(snapshot.size / 1024) KB " + compressed message.stringValue = "" } else { nr.stringValue = "No snapshots taken" diff --git a/Proxy/EmulatorProxy.h b/Proxy/EmulatorProxy.h index 07c890445..3b8dc2952 100644 --- a/Proxy/EmulatorProxy.h +++ b/Proxy/EmulatorProxy.h @@ -665,6 +665,7 @@ struct GuardInfo { @property (readonly) FileType type; @property (readonly) u64 fnv; @property (readonly) NSInteger size; +@property (readonly) BOOL compressed; - (void)writeToFile:(NSString *)path exception:(ExceptionWrapper *)ex; diff --git a/Proxy/EmulatorProxy.mm b/Proxy/EmulatorProxy.mm index 163a7108a..793e29ed1 100644 --- a/Proxy/EmulatorProxy.mm +++ b/Proxy/EmulatorProxy.mm @@ -1271,6 +1271,11 @@ - (NSInteger)size return [self file]->getSize(); } +- (BOOL)compressed +{ + return [self file]->isCompressed(); +} + - (void)writeToFile:(NSString *)path exception:(ExceptionWrapper *)ex { try { [self file]->writeToFile(string([path fileSystemRepresentation])); }