From 73078e1a9eb76bd121fbc5c9e5f7aa3daafc1e12 Mon Sep 17 00:00:00 2001 From: tudnai Date: Thu, 25 Jun 2020 19:52:23 -0700 Subject: [PATCH] Save, SaveAs --- A2Mac/AppDelegate.swift | 14 +++--- A2Mac/Base.lproj/Main.storyboard | 7 ++- A2Mac/ViewController.swift | 77 +++++++++++++++++++++++++++++++- src/dev/disk/woz.c | 68 ++++++++++++++++++++++------ src/dev/disk/woz.h | 33 +++++--------- 5 files changed, 155 insertions(+), 44 deletions(-) diff --git a/A2Mac/AppDelegate.swift b/A2Mac/AppDelegate.swift index 771f15e..1a971f4 100644 --- a/A2Mac/AppDelegate.swift +++ b/A2Mac/AppDelegate.swift @@ -26,6 +26,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { if let menuIdentifier = sender.identifier { let woz_err = woz_loadFile( Bundle.main.resourcePath! + "/dsk/" + menuIdentifier.rawValue + ".woz" ) ViewController.current?.chk_woz_load(err: woz_err) + woz_flags.image_file_readonly = 1 } } @@ -49,14 +50,11 @@ class AppDelegate: NSObject, NSApplicationDelegate { } @IBAction func saveFile(_ sender: NSMenuItem) { - - let savePanel = NSSavePanel() - savePanel.begin { (result) in - if result.rawValue == NSApplication.ModalResponse.OK.rawValue { - woz_saveFile( savePanel.url?.path ); - } - } - + ViewController.current?.saveFile() + } + + @IBAction func saveFileAs(_ sender: NSMenuItem) { + ViewController.current?.saveFileAs() } @IBAction func showPreferences(_ sender: NSMenuItem) { diff --git a/A2Mac/Base.lproj/Main.storyboard b/A2Mac/Base.lproj/Main.storyboard index 0d9e238..442f8e7 100644 --- a/A2Mac/Base.lproj/Main.storyboard +++ b/A2Mac/Base.lproj/Main.storyboard @@ -87,11 +87,16 @@ - + + + + + + diff --git a/A2Mac/ViewController.swift b/A2Mac/ViewController.swift index 651359c..4e9dd55 100644 --- a/A2Mac/ViewController.swift +++ b/A2Mac/ViewController.swift @@ -913,6 +913,7 @@ class ViewController: NSViewController { let woz_err = woz_loadFile( Bundle.main.resourcePath! + "/dsk/Apple DOS 3.3 January 1983.woz" ) chk_woz_load(err: woz_err) + woz_flags.image_file_readonly = 1 //view.frame = CGRect(origin: CGPoint(), size: NSScreen.main!.visibleFrame.size) @@ -1133,7 +1134,7 @@ class ViewController: NSViewController { @objc func openDiskImage() { let openPanel = NSOpenPanel() - openPanel.title = "Disk Image" + openPanel.title = "Open Disk Image" openPanel.allowsMultipleSelection = false openPanel.canChooseDirectories = false openPanel.canCreateDirectories = false @@ -1162,6 +1163,37 @@ class ViewController: NSViewController { } + @objc func saveDiskImage() { + let openPanel = NSOpenPanel() + openPanel.title = "Save Disk Image" + openPanel.allowsMultipleSelection = false + openPanel.canChooseDirectories = false + openPanel.canCreateDirectories = false + openPanel.canChooseFiles = true + openPanel.allowedFileTypes = ["dsk","do","po","nib", "woz"] + + openPanel.begin { (result) -> Void in + if result == NSApplication.ModalResponse.OK { + print("file:", openPanel.url!.path) + //Do what you will + //If there's only one URL, surely 'openPanel.URL' + //but otherwise a for loop works + + if let filePath = openPanel.url?.path { + let woz_err = woz_loadFile( filePath ) + + if woz_err == WOZ_ERR_OK { + NSDocumentController.shared.noteNewRecentDocumentURL(URL(fileURLWithPath: filePath)) + } + else { + self.chk_woz_load(err: woz_err) + } + } + } + } + } + + @IBAction func openDocument(_ sender: Any?) { openDiskImage() } @@ -1178,5 +1210,48 @@ class ViewController: NSViewController { } } + + func saveFile() { + if ( woz_flags.image_file_readonly != 0 ) { + // it is readonly, save it to a different file... + saveFileAs() + } + else { + // save WOZ image file overwriting the original image + woz_saveFile(nil) + } + } + + func saveFileAs() { + let savePanel = NSSavePanel() + savePanel.title = "Save WOZ Disk Image As..." + savePanel.begin { (result) in + if result.rawValue == NSApplication.ModalResponse.OK.rawValue { + woz_saveFile( savePanel.url?.path ); + } + else { + let a = NSAlert() + a.messageText = "Are you sure?" + a.informativeText = "Are you sure you would like to cancel and lose all modification you have made to the Disk Image?\nALERT: You will lose all new files and modified files from this Disk Image since you loaded. Your decision if permanent and irreversible!" + a.addButton(withTitle: "Save") + a.addButton(withTitle: "Cancel") + a.alertStyle = .warning + + a.beginSheetModal(for: self.view.window!, completionHandler: { (modalResponse) -> Void in + if modalResponse == .alertFirstButtonReturn { + self.saveFileAs() + } + }) + } + } + } + + +} + + +@_cdecl("woz_ask_to_save") +func woz_ask_to_save() { + ViewController.current?.saveFile() } diff --git a/src/dev/disk/woz.c b/src/dev/disk/woz.c index cc26943..eb4d4d7 100644 --- a/src/dev/disk/woz.c +++ b/src/dev/disk/woz.c @@ -25,6 +25,8 @@ int bitOffset = 0; uint64_t clkelpased; +char woz_filename[MAXFILENAME]; +woz_flags_t woz_flags = {0,0,0,0}; size_t woz_file_size = 0; uint8_t * woz_file_buffer = NULL; woz_header_t * woz_header; @@ -368,6 +370,8 @@ void woz_write( uint8_t data ) { return; } + woz_flags.disk_modified = 1; + clkelpased = m6502.clktime + clkfrm - m6502.clklast; m6502.clklast = m6502.clktime + clkfrm; @@ -464,6 +468,17 @@ void woz_write( uint8_t data ) { } +void woz_free_buffer() { + if ( woz_file_buffer ) { + free(woz_file_buffer); + woz_file_buffer = NULL; + woz_header = NULL; + woz_tmap = NULL; + woz_trks = NULL; + } +} + + int woz_loadFile( const char * filename ) { // char fullpath[256]; @@ -478,16 +493,18 @@ int woz_loadFile( const char * filename ) { return WOZ_ERR_FILE_NOT_FOUND; } + woz_eject(); + // get file size fseek(f, 0, SEEK_END); woz_file_size = ftell(f); fseek(f, 0, SEEK_SET); - - if ( woz_file_buffer ) { - free(woz_file_buffer); - woz_file_buffer = NULL; - } + woz_flags.disk_modified = 0; + woz_flags.disk_write_protected = 0; + woz_flags.image_file_readonly = 0; + woz_flags.image_loaded = 1; + woz_file_buffer = malloc(woz_file_size); if (woz_file_buffer == NULL) { perror("Not Enough Memory: "); @@ -501,8 +518,7 @@ int woz_loadFile( const char * filename ) { fread( woz_file_buffer, woz_file_size, 1, f); fclose(f); if ( woz_header->magic != WOZ1_MAGIC ) { - free(woz_file_buffer); - woz_file_buffer = NULL; + woz_free_buffer(); return WOZ_ERR_NOT_WOZ_FILE; } @@ -510,21 +526,21 @@ int woz_loadFile( const char * filename ) { while ( bufOffs < woz_file_size ) { // beginning of the chunk, so we can skip it later - - woz_chunk_header = (woz_chunk_header_t*)(woz_file_buffer + bufOffs); - + + woz_chunk_header = (woz_chunk_header_t*) &woz_file_buffer[bufOffs]; + bufOffs += sizeof(woz_chunk_header_t); - + switch ( woz_chunk_header->magic ) { case WOZ_INFO_CHUNK_ID: break; case WOZ_TMAP_CHUNK_ID: - woz_tmap = (woz_tmap_t*)(woz_file_buffer + bufOffs); + woz_tmap = (woz_tmap_t*) &woz_file_buffer[bufOffs]; break; case WOZ_TRKS_CHUNK_ID: - woz_trks = (woz_trks_t*)(woz_file_buffer + bufOffs); + woz_trks = (woz_trks_t*) &woz_file_buffer[bufOffs]; break; case WOZ_META_CHUNK_ID: @@ -546,8 +562,32 @@ int woz_loadFile( const char * filename ) { return WOZ_ERR_OK; } + +void woz_ask_to_save(void); + + +void woz_eject() { + if ( woz_flags.disk_modified ) { + woz_ask_to_save(); + } + + woz_flags.disk_modified = 0; + woz_flags.disk_write_protected = 0; + woz_flags.image_file_readonly = 0; + woz_flags.image_loaded = 0; + + woz_file_size = 0; + + woz_free_buffer(); +} + + int woz_saveFile( const char * filename ) { + if ( filename == NULL ) { + filename = woz_filename; + } + FILE * f = fopen( filename, "wb" ); if (f == NULL) { perror("Failed to crete WOZ: "); @@ -557,6 +597,8 @@ int woz_saveFile( const char * filename ) { fwrite( woz_file_buffer, woz_file_size, 1, f ); fclose(f); + woz_flags.disk_modified = 0; + return WOZ_ERR_OK; } diff --git a/src/dev/disk/woz.h b/src/dev/disk/woz.h index 32ca66d..0585b54 100644 --- a/src/dev/disk/woz.h +++ b/src/dev/disk/woz.h @@ -13,6 +13,8 @@ #include "common.h" +#define MAXFILENAME 4096 + #define DISKII_MAXTRACKS 80 #define DISKII_PHASES 4 @@ -81,26 +83,6 @@ typedef woz_track_t woz_trks_t[DISKII_MAXTRACKS]; -#define __NO__WOZ_REAL_SPIN2 - -#ifdef WOZ_REAL_SPIN - -typedef union { - struct { - uint8_t next; - uint8_t data; - uint8_t prev; - uint8_t shift; - }; - struct { - uint32_t lower : 31; - uint32_t valid : 1; - }; - uint32_t shift32; -} WOZread_t; - -#else // WOZ_REAL_SPIN - typedef union { struct { uint8_t data; @@ -116,11 +98,19 @@ typedef union { uint64_t shift; } WOZread_t; -#endif // WOZ_REAL_SPIN + +typedef struct woz_flags_s { + uint8_t image_loaded : 1; + uint8_t image_file_readonly : 1; + uint8_t disk_write_protected : 1; + uint8_t disk_modified : 1; +} woz_flags_t; extern WOZread_t WOZread; extern uint8_t WOZlatch; +extern char woz_filename[MAXFILENAME]; +extern woz_flags_t woz_flags; //extern woz_header_t woz_header; //extern woz_chunk_header_t woz_chunk_header; @@ -132,5 +122,6 @@ extern uint8_t woz_read(void); extern void woz_write( uint8_t data ); extern int woz_loadFile( const char * filename ); extern int woz_saveFile( const char * filename ); +extern void woz_eject(void); #endif /* woz_h */