From 2129bfc570a88d5aca560effb128650b4f70f44d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Mon, 22 Jul 2019 18:02:48 -0400 Subject: [PATCH] Gets as far as testing ROMs against the missing list. Though now it strikes me that I've forgotten to retain the machine name. --- .../Clock Signal.xcodeproj/project.pbxproj | 14 +++-- .../ClockSignal-Bridging-Header.h | 2 + .../Documents/MachineDocument.swift | 56 +++++++++++++++++-- .../Mac/Clock Signal/Machine/NSData+CRC32.h | 17 ++++++ .../Mac/Clock Signal/Machine/NSData+CRC32.m | 19 +++++++ 5 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 OSBindings/Mac/Clock Signal/Machine/NSData+CRC32.h create mode 100644 OSBindings/Mac/Clock Signal/Machine/NSData+CRC32.m diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index aaef85a1f..29d85df7c 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -668,7 +668,8 @@ 4BDA00DA22E60EE300AC3CD0 /* ROMRequester.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BDA00D922E60EE300AC3CD0 /* ROMRequester.xib */; }; 4BDA00DD22E622C200AC3CD0 /* ROMImages in Resources */ = {isa = PBXBuildFile; fileRef = 4BC9DF441D044FCA00F44158 /* ROMImages */; }; 4BDA00E022E644AF00AC3CD0 /* CSROMReceiverView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BDA00DF22E644AF00AC3CD0 /* CSROMReceiverView.m */; }; - 4BDA00E122E64ABE00AC3CD0 /* ROMImages in Resources */ = {isa = PBXBuildFile; fileRef = 4BC9DF441D044FCA00F44158 /* ROMImages */; }; + 4BDA00E422E663B900AC3CD0 /* NSData+CRC32.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BDA00E222E663B900AC3CD0 /* NSData+CRC32.m */; }; + 4BDA00E522E669DC00AC3CD0 /* ROMImages in Resources */ = {isa = PBXBuildFile; fileRef = 4BC9DF441D044FCA00F44158 /* ROMImages */; }; 4BDB61EB2032806E0048AF91 /* CSAtari2600.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B2A539A1D117D36003C6002 /* CSAtari2600.mm */; }; 4BDB61EC203285AE0048AF91 /* Atari2600OptionsPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B8FE21F1DA19D7C0090D3CE /* Atari2600OptionsPanel.swift */; }; 4BDDBA991EF3451200347E61 /* Z80MachineCycleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */; }; @@ -1479,6 +1480,8 @@ 4BDA00D922E60EE300AC3CD0 /* ROMRequester.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ROMRequester.xib; sourceTree = ""; }; 4BDA00DE22E644AF00AC3CD0 /* CSROMReceiverView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSROMReceiverView.h; sourceTree = ""; }; 4BDA00DF22E644AF00AC3CD0 /* CSROMReceiverView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CSROMReceiverView.m; sourceTree = ""; }; + 4BDA00E222E663B900AC3CD0 /* NSData+CRC32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+CRC32.m"; sourceTree = ""; }; + 4BDA00E322E663B900AC3CD0 /* NSData+CRC32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+CRC32.h"; sourceTree = ""; }; 4BDB3D8522833321002D3CEE /* Keyboard.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Keyboard.hpp; sourceTree = ""; }; 4BDCC5F81FB27A5E001220C5 /* ROMMachine.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ROMMachine.hpp; sourceTree = ""; }; 4BDDBA981EF3451200347E61 /* Z80MachineCycleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Z80MachineCycleTests.swift; sourceTree = ""; }; @@ -1742,13 +1745,15 @@ 4BBC34241D2208B100FFC9DF /* CSFastLoading.h */, 4B2A53951D117D36003C6002 /* CSMachine.h */, 4B643F3C1D77AE5C00D431D6 /* CSMachine+Target.h */, - 4B98A05C1FFAD3F600ADF63B /* CSROMFetcher.hpp */, 4B2A53971D117D36003C6002 /* KeyCodes.h */, 4B8FE2251DA1DE2D0090D3CE /* NSBundle+DataResource.h */, + 4BDA00E322E663B900AC3CD0 /* NSData+CRC32.h */, 4BA61EAE1D91515900B3C876 /* NSData+StdVector.h */, - 4B98A05D1FFAD3F600ADF63B /* CSROMFetcher.mm */, + 4B98A05C1FFAD3F600ADF63B /* CSROMFetcher.hpp */, 4B8FE2261DA1DE2D0090D3CE /* NSBundle+DataResource.m */, + 4BDA00E222E663B900AC3CD0 /* NSData+CRC32.m */, 4B2A53961D117D36003C6002 /* CSMachine.mm */, + 4B98A05D1FFAD3F600ADF63B /* CSROMFetcher.mm */, 4BA61EAF1D91515900B3C876 /* NSData+StdVector.mm */, 4B643F3B1D77AD6D00D431D6 /* StaticAnalyser */, 4B2A53981D117D36003C6002 /* Wrappers */, @@ -3572,7 +3577,7 @@ 4B79E4441E3AF38600141F11 /* cassette.png in Resources */, 4BB73EAC1B587A5100552FC2 /* MainMenu.xib in Resources */, 4B8FE21D1DA19D5F0090D3CE /* QuickLoadCompositeOptions.xib in Resources */, - 4BDA00E122E64ABE00AC3CD0 /* ROMImages in Resources */, + 4BDA00E522E669DC00AC3CD0 /* ROMImages in Resources */, 4B79E4461E3AF38600141F11 /* floppy525.png in Resources */, 4BEEE6BD20DC72EB003723BF /* CompositeOptions.xib in Resources */, 4B1497981EE4B97F00CE2596 /* ZX8081Options.xib in Resources */, @@ -4086,6 +4091,7 @@ 4B595FAD2086DFBA0083CAA8 /* AudioToggle.cpp in Sources */, 4B1497921EE4B5A800CE2596 /* ZX8081.cpp in Sources */, 4B643F3F1D77B88000D431D6 /* DocumentController.swift in Sources */, + 4BDA00E422E663B900AC3CD0 /* NSData+CRC32.m in Sources */, 4BB4BFB022A42F290069048D /* MacintoshIMG.cpp in Sources */, 4B05401E219D1618001BF69C /* ScanTarget.cpp in Sources */, 4B4518861F75E91A00926311 /* MFMDiskController.cpp in Sources */, diff --git a/OSBindings/Mac/Clock Signal/ClockSignal-Bridging-Header.h b/OSBindings/Mac/Clock Signal/ClockSignal-Bridging-Header.h index 58bd8225d..5b21dd3fc 100644 --- a/OSBindings/Mac/Clock Signal/ClockSignal-Bridging-Header.h +++ b/OSBindings/Mac/Clock Signal/ClockSignal-Bridging-Header.h @@ -17,4 +17,6 @@ #import "CSBestEffortUpdater.h" #import "CSJoystickManager.h" +#import "NSData+CRC32.h" + #include "KeyCodes.h" diff --git a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift index 57959a255..edd7ebeb1 100644 --- a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift +++ b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift @@ -153,15 +153,27 @@ class MachineDocument: } // MARK: configuring + var missingROMs: [CSMissingROM] = [] + var selectedMachine: CSStaticAnalyser? + func configureAs(_ analysis: CSStaticAnalyser) { let missingROMs = NSMutableArray() if let machine = CSMachine(analyser: analysis, missingROMs: missingROMs) { + self.selectedMachine = nil self.machine = machine self.optionsPanelNibName = analysis.optionsPanelNibName setupMachineOutput() setupActivityDisplay() } else { - requestRoms(missingROMs: missingROMs) + // Store the selected machine and list of missing ROMs, and + // show the missing ROMs dialogue. + self.missingROMs = [] + for untypedMissingROM in missingROMs { + self.missingROMs.append(untypedMissingROM as! CSMissingROM) + } + + self.selectedMachine = analysis + requestRoms() } } @@ -325,7 +337,7 @@ class MachineDocument: @IBOutlet var romRequesterPanel: NSWindow? @IBOutlet var romRequesterText: NSTextField? @IBOutlet var romReceiverView: CSROMReceiverView? - func requestRoms(missingROMs: NSMutableArray) { + func requestRoms() { // Load the ROM requester dialogue. Bundle.main.loadNibNamed("ROMRequester", owner: self, topLevelObjects: nil) self.romReceiverView!.delegate = self @@ -333,8 +345,7 @@ class MachineDocument: // Fill in the missing details; first build a list of all the individual // line items. var requestLines: [String] = [] - for untypedMissingROM in missingROMs { - let missingROM = untypedMissingROM as! CSMissingROM + for missingROM in self.missingROMs { if let descriptiveName = missingROM.descriptiveName { requestLines.append("• " + descriptiveName) } else { @@ -365,7 +376,42 @@ class MachineDocument: } func romReceiverView(_ view: CSROMReceiverView, didReceiveFileAt URL: URL) { - Swift.print("Should test " + URL.absoluteString) + // Test whether the file identified matches any of the currently missing ROMs. + // If so then remove that ROM from the missing list and update the request screen. + // If no ROMs are still missing, start the machine. + do { + let fileData = try Data(contentsOf: URL) + + // Try to match by size first, CRC second. Accept that some ROMs may have + // some additional appended data. Arbitrarily allow them to be up to 10kb + // too large. + var index = 0 + for missingROM in self.missingROMs { + if fileData.count >= missingROM.size && fileData.count < missingROM.size + 10*1024 { + // Trim to size. + let trimmedData = fileData[0 ..< missingROM.size] + + // Get CRC. + if missingROM.crc32s.contains( (trimmedData as NSData).crc32 ) { + // This ROM matches; copy it into the application library, + // strike it from the missing ROM list and decide how to + // proceed. + Swift.print("Matches") + + self.missingROMs.remove(at: index) + break + } + } + + index = index + 1 + } + + if self.missingROMs.count == 0 { + Swift.print("Should start") + } + } catch let error { + Swift.print("TODO: couldn't open \(URL.absoluteString); \(error)") + } } // MARK: Joystick-via-the-keyboard selection diff --git a/OSBindings/Mac/Clock Signal/Machine/NSData+CRC32.h b/OSBindings/Mac/Clock Signal/Machine/NSData+CRC32.h new file mode 100644 index 000000000..c62f5ac97 --- /dev/null +++ b/OSBindings/Mac/Clock Signal/Machine/NSData+CRC32.h @@ -0,0 +1,17 @@ +// +// NSData+CRC32.m +// Clock Signal +// +// Created by Thomas Harte on 22/07/2019. +// Copyright 2019 Thomas Harte. All rights reserved. +// + +#import + +#include + +@interface NSData (CRC32) + +@property(nonnull, nonatomic, readonly) NSNumber *crc32; + +@end diff --git a/OSBindings/Mac/Clock Signal/Machine/NSData+CRC32.m b/OSBindings/Mac/Clock Signal/Machine/NSData+CRC32.m new file mode 100644 index 000000000..e31513f92 --- /dev/null +++ b/OSBindings/Mac/Clock Signal/Machine/NSData+CRC32.m @@ -0,0 +1,19 @@ +// +// NSData+CRC32.m +// Clock Signal +// +// Created by Thomas Harte on 22/07/2019. +// Copyright 2019 Thomas Harte. All rights reserved. +// + +#import "NSData+CRC32.h" + +#include + +@implementation NSData (StdVector) + +- (NSNumber *)crc32 { + return @(crc32(crc32(0, Z_NULL, 0), self.bytes, (uInt)self.length)); +} + +@end