From 6df5ff2826d698f1b69268d5d738e6033197b8a5 Mon Sep 17 00:00:00 2001 From: Denis Molony Date: Thu, 9 Apr 2020 19:47:30 +1000 Subject: [PATCH] scaled images --- .../diskbrowser/disk/DiskAddress.java | 14 ++ .../diskbrowser/disk/DiskFactory.java | 21 +- .../diskbrowser/dos/CatalogEntry.java | 27 ++- .../diskbrowser/dos/DosCatalogSector.java | 2 +- .../diskbrowser/dos/DosVTOCSector.java | 209 +++++------------- .../bytezone/diskbrowser/gui/DataPanel.java | 19 +- .../bytezone/diskbrowser/gui/DiskBrowser.java | 4 + .../bytezone/diskbrowser/gui/MenuHandler.java | 3 - .../bytezone/diskbrowser/gui/ScaleAction.java | 39 ++++ 9 files changed, 173 insertions(+), 165 deletions(-) create mode 100644 src/com/bytezone/diskbrowser/gui/ScaleAction.java diff --git a/src/com/bytezone/diskbrowser/disk/DiskAddress.java b/src/com/bytezone/diskbrowser/disk/DiskAddress.java index b6438f1..46e5d59 100755 --- a/src/com/bytezone/diskbrowser/disk/DiskAddress.java +++ b/src/com/bytezone/diskbrowser/disk/DiskAddress.java @@ -13,4 +13,18 @@ public interface DiskAddress extends Comparable public Disk getDisk (); public boolean matches (DiskAddress other); + + // ---------------------------------------------------------------------------------// + public default byte[] readSector () + // ---------------------------------------------------------------------------------// + { + return getDisk ().readSector (this); + } + + // ---------------------------------------------------------------------------------// + public default boolean isValidAddress () + // ---------------------------------------------------------------------------------// + { + return getDisk ().isValidAddress (this); + } } \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/disk/DiskFactory.java b/src/com/bytezone/diskbrowser/disk/DiskFactory.java index 573c7e0..c28f030 100755 --- a/src/com/bytezone/diskbrowser/disk/DiskFactory.java +++ b/src/com/bytezone/diskbrowser/disk/DiskFactory.java @@ -598,7 +598,6 @@ public class DiskFactory if (tracks * 4096 != file.length ()) { System.out.println ("*** extended ***"); // System Addons.hdv - // System.out.println (tracks); } AppleDisk disk = new AppleDisk (file, tracks, 8); if (ProdosDisk.isCorrectFormat (disk)) @@ -669,14 +668,18 @@ public class DiskFactory try { AppleDisk disk = new AppleDisk (file, 0, 0); - if (disk.getTotalBlocks () > 0 && ProdosDisk.isCorrectFormat (disk)) - return new ProdosDisk (disk); + if (disk.getTotalBlocks () > 0) + { + if (ProdosDisk.isCorrectFormat (disk)) + return new ProdosDisk (disk); - // switch sector size - disk.switchToDos (); - // System.out.println (disk); - if (disk.getTotalBlocks () > 0 && DosDisk.isCorrectFormat (disk)) - return new DosDisk (disk); + if (file.length () == 143424) + { + disk.switchToDos (); // switch sector size + if (DosDisk.isCorrectFormat (disk)) + return new DosDisk (disk); + } + } } catch (Exception e) { @@ -684,7 +687,7 @@ public class DiskFactory // System.out.println (e); } if (debug) - System.out.println ("Not a Prodos 2mg disk"); + System.out.println ("Not a 2mg disk"); return null; } diff --git a/src/com/bytezone/diskbrowser/dos/CatalogEntry.java b/src/com/bytezone/diskbrowser/dos/CatalogEntry.java index fa82c0f..e3052c6 100644 --- a/src/com/bytezone/diskbrowser/dos/CatalogEntry.java +++ b/src/com/bytezone/diskbrowser/dos/CatalogEntry.java @@ -28,13 +28,22 @@ class CatalogEntry extends AbstractCatalogEntry loop: while (da.getBlock () > 0 || ((AppleDiskAddress) da).zeroFlag ()) { if (dosDisk.stillAvailable (da)) - dosDisk.sectorTypes[da.getBlock ()] = dosDisk.tsListSector; + { + if (isValidCatalogSector (da)) + dosDisk.sectorTypes[da.getBlock ()] = dosDisk.tsListSector; + else + { + System.out.printf ("Attempt to assign invalid TS sector " + ": %s from %s%n", + da, name); + break; + } + } else { System.out.printf ( "Attempt to assign TS sector to occupied sector " + ": %s from %s%n", da, name); - // break; + break; } tsSectors.add (da); byte[] sectorBuffer = disk.readSector (da); @@ -131,6 +140,20 @@ class CatalogEntry extends AbstractCatalogEntry } } + // ---------------------------------------------------------------------------------// + private boolean isValidCatalogSector (DiskAddress da) + // ---------------------------------------------------------------------------------// + { + byte[] buffer = da.readSector (); + + if (!da.getDisk ().isValidAddress (buffer[1], buffer[2])) + return false; + if (buffer[4] != 0) + return false; + + return true; + } + // ---------------------------------------------------------------------------------// String getDetails () // ---------------------------------------------------------------------------------// diff --git a/src/com/bytezone/diskbrowser/dos/DosCatalogSector.java b/src/com/bytezone/diskbrowser/dos/DosCatalogSector.java index ef1de0a..b86fe03 100755 --- a/src/com/bytezone/diskbrowser/dos/DosCatalogSector.java +++ b/src/com/bytezone/diskbrowser/dos/DosCatalogSector.java @@ -129,7 +129,7 @@ class DosCatalogSector extends AbstractSector } // ---------------------------------------------------------------------------------// - private String getName (byte[] buffer, int offset, int length) + static String getName (byte[] buffer, int offset, int length) // ---------------------------------------------------------------------------------// { StringBuilder text = new StringBuilder (); diff --git a/src/com/bytezone/diskbrowser/dos/DosVTOCSector.java b/src/com/bytezone/diskbrowser/dos/DosVTOCSector.java index 14fe378..7c00acf 100755 --- a/src/com/bytezone/diskbrowser/dos/DosVTOCSector.java +++ b/src/com/bytezone/diskbrowser/dos/DosVTOCSector.java @@ -45,69 +45,11 @@ class DosVTOCSector extends AbstractSector public String createText () // ---------------------------------------------------------------------------------// { - return dosVersion <= 3 ? createDosText () : createDos4Text (); + return dosVersion <= 3 ? createDos3Text () : createDos4Text (); } // ---------------------------------------------------------------------------------// - private String createDos4Text () - // ---------------------------------------------------------------------------------// - { - StringBuilder text = getHeader ("DOS 4 VTOC Sector"); - addText (text, buffer, 0, 1, "Not used"); - addText (text, buffer, 1, 2, "First directory track/sector"); - addText (text, buffer, 3, 1, "DOS release number"); - addText (text, buffer, 4, 1, "Build number"); - addText (text, buffer, 5, 1, "Ram DOS " + (char) (buffer[5] & 0x7F)); - - addTextAndDecimal (text, buffer, 6, 1, "Diskette volume"); - String diskType = - buffer[7] == (byte) 0xC4 ? " = Data" : buffer[7] == (byte) 0xC2 ? " = Boot" : ""; - addText (text, buffer, 7, 1, "Volume type: " + (char) (buffer[7] & 0x7F) + diskType); - - int ptr = 8; - addText (text, buffer, ptr, 4, "Volume name: " + getName (buffer, ptr)); - for (int j = 4; j < 24; j += 4) - addText (text, buffer, ptr + j, 4, ""); - - addText (text, buffer, 0x20, 3, - "Date/time initialised: " + Utility.getDateTime (buffer, 0x20)); - addText (text, buffer, 0x23, 3, ""); - addText (text, buffer, 0x26, 1, "VTOC Phase"); - - addTextAndDecimal (text, buffer, 0x27, 1, "Maximum TS pairs"); - addText (text, buffer, 0x28, 2, "Volume library"); - addText (text, buffer, 0x2A, 3, - "Date/time modified: " + Utility.getDateTime (buffer, 0x2A)); - addText (text, buffer, 0x2D, 3, ""); - - addTextAndDecimal (text, buffer, 0x30, 1, "Last allocated track"); - addText (text, buffer, 0x31, 1, "Direction to look when allocating the next file"); - addText (text, buffer, 0x32, 2, "Not used"); - addTextAndDecimal (text, buffer, 0x34, 1, "Maximum tracks"); - addTextAndDecimal (text, buffer, 0x35, 1, "Maximum sectors"); - addTextAndDecimal (text, buffer, 0x36, 2, "Bytes per sector"); - - boolean bootSectorEmpty = parentDisk.getDisk ().isSectorEmpty (0); - int firstSector = 0x38; - int max = maxTracks * 4 + firstSector; - for (int i = firstSector; i < max; i += 4) - { - String extra = ""; - if (i == firstSector && bootSectorEmpty) - extra = "(unusable)"; - else if (i == 124) - extra = "(VTOC and Catalog)"; - addText (text, buffer, i, 4, String.format ("Track %02X %s %s", - (i - firstSector) / 4, getBitmap (buffer, i), extra)); - } - - text.deleteCharAt (text.length () - 1); - - return text.toString (); - } - - // ---------------------------------------------------------------------------------// - private String createDosText () + private String createDos3Text () // ---------------------------------------------------------------------------------// { StringBuilder text = getHeader ("VTOC Sector"); @@ -153,33 +95,64 @@ class DosVTOCSector extends AbstractSector return text.toString (); } - // private String getBitmap (byte left, byte right) - // { - // StringBuilder text = new StringBuilder (); - // - // int base = maxSectors == 13 ? 3 : 0; - // right >>= base; - // - // for (int i = base; i < 8; i++) - // { - // if ((right & 0x01) == 1) - // text.append ("."); - // else - // text.append ("X"); - // right >>= 1; - // } - // - // for (int i = 0; i < 8; i++) - // { - // if ((left & 0x01) == 1) - // text.append ("."); - // else - // text.append ("X"); - // left >>= 1; - // } - // - // return text.toString (); - // } + // ---------------------------------------------------------------------------------// + private String createDos4Text () + // ---------------------------------------------------------------------------------// + { + StringBuilder text = getHeader ("DOS 4 VTOC Sector"); + addText (text, buffer, 0, 1, "Not used"); + addText (text, buffer, 1, 2, "First directory track/sector"); + addText (text, buffer, 3, 1, "DOS release number"); + addText (text, buffer, 4, 1, "Build number"); + addText (text, buffer, 5, 1, "Ram DOS " + (char) (buffer[5] & 0x7F)); + + addTextAndDecimal (text, buffer, 6, 1, "Diskette volume"); + String diskType = + buffer[7] == (byte) 0xC4 ? " = Data" : buffer[7] == (byte) 0xC2 ? " = Boot" : ""; + addText (text, buffer, 7, 1, "Volume type: " + (char) (buffer[7] & 0x7F) + diskType); + + int ptr = 8; + addText (text, buffer, ptr, 4, + "Volume name: " + DosCatalogSector.getName (buffer, ptr, 30)); + for (int j = 4; j < 24; j += 4) + addText (text, buffer, ptr + j, 4, ""); + + addText (text, buffer, 0x20, 3, + "Date/time initialised: " + Utility.getDateTime (buffer, 0x20)); + addText (text, buffer, 0x23, 3, ""); + addText (text, buffer, 0x26, 1, "VTOC Phase"); + + addTextAndDecimal (text, buffer, 0x27, 1, "Maximum TS pairs"); + addText (text, buffer, 0x28, 2, "Volume library"); + addText (text, buffer, 0x2A, 3, + "Date/time modified: " + Utility.getDateTime (buffer, 0x2A)); + addText (text, buffer, 0x2D, 3, ""); + + addTextAndDecimal (text, buffer, 0x30, 1, "Last allocated track"); + addText (text, buffer, 0x31, 1, "Direction to look when allocating the next file"); + addText (text, buffer, 0x32, 2, "Not used"); + addTextAndDecimal (text, buffer, 0x34, 1, "Maximum tracks"); + addTextAndDecimal (text, buffer, 0x35, 1, "Maximum sectors"); + addTextAndDecimal (text, buffer, 0x36, 2, "Bytes per sector"); + + boolean bootSectorEmpty = parentDisk.getDisk ().isSectorEmpty (0); + int firstSector = 0x38; + int max = maxTracks * 4 + firstSector; + for (int i = firstSector; i < max; i += 4) + { + String extra = ""; + if (i == firstSector && bootSectorEmpty) + extra = "(unusable)"; + else if (i == 124) + extra = "(VTOC and Catalog)"; + addText (text, buffer, i, 4, String.format ("Track %02X %s %s", + (i - firstSector) / 4, getBitmap (buffer, i), extra)); + } + + text.deleteCharAt (text.length () - 1); + + return text.toString (); + } // ---------------------------------------------------------------------------------// private String getBitmap (byte[] buffer, int offset) @@ -209,12 +182,10 @@ class DosVTOCSector extends AbstractSector int track = (i - firstSector) / 4; String bits = getBitmap (buffer, i); - // System.out.printf ("%08X %s%n", track, bits); int blockNo = track * maxSectors; char[] chars = bits.toCharArray (); for (int sector = 0; sector < maxSectors; sector++) { - // System.out.printf ("%3d %s%n", blockNo, chars[sector]); if (chars[sector] == '.') { parentDisk.setSectorFree (blockNo, true); @@ -230,66 +201,6 @@ class DosVTOCSector extends AbstractSector } } - // private void flagSectors () - // { - // int block = 0; - // int base = maxSectors == 13 ? 3 : 0; - // int firstSector = 0x38; - // int max = maxTracks * 4 + firstSector; - // for (int i = firstSector; i < max; i += 4) - // { - // block = check (buffer[i + 1], block, base); - // block = check (buffer[i], block, 0); - // } - // } - - // private int check (byte b, int block, int base) - // { - // b >>= base; - // for (int i = base; i < 8; i++) - // { - // if ((b & 0x01) == 1) - // { - // parentDisk.setSectorFree (block, true); - // ++freeSectors; - // } - // else - // { - // parentDisk.setSectorFree (block, false); - // ++usedSectors; - // } - // block++; - // b >>= 1; - // } - // return block; - // } - - // duplicate of DosCatalogSector.getName() - // ---------------------------------------------------------------------------------// - private String getName (byte[] buffer, int offset) - // ---------------------------------------------------------------------------------// - { - StringBuilder text = new StringBuilder (); - int max = 24; - for (int i = 0; i < max; i++) - { - int c = buffer[i + offset] & 0xFF; - if (c == 136) - { - if (text.length () > 0) - text.deleteCharAt (text.length () - 1); - continue; - } - if (c > 127) - c -= c < 160 ? 64 : 128; - if (c < 32) // non-printable - text.append ("^" + (char) (c + 64)); - else - text.append ((char) c); // standard ascii - } - return text.toString (); - } - // ---------------------------------------------------------------------------------// @Override public String toString () diff --git a/src/com/bytezone/diskbrowser/gui/DataPanel.java b/src/com/bytezone/diskbrowser/gui/DataPanel.java index 9e8c3a9..3defd4d 100755 --- a/src/com/bytezone/diskbrowser/gui/DataPanel.java +++ b/src/com/bytezone/diskbrowser/gui/DataPanel.java @@ -221,6 +221,18 @@ class DataPanel extends JTabbedPane implements DiskSelectionListener, } } + // ---------------------------------------------------------------------------------// + public void setScale (double scale) + // ---------------------------------------------------------------------------------// + { + imagePanel.setScale (scale); + if (currentDataSource instanceof HiResImage) + { + HiResImage image = (HiResImage) currentDataSource; + imagePanel.setImage (image.getImage ()); + } + } + // ---------------------------------------------------------------------------------// public void setDebug (boolean value) // ---------------------------------------------------------------------------------// @@ -374,13 +386,18 @@ class DataPanel extends JTabbedPane implements DiskSelectionListener, { private BufferedImage image; private double scale = 1; - private double userScale = 1.5; + private double userScale = .5; public ImagePanel () { this.setBackground (new Color (BACKGROUND, BACKGROUND, BACKGROUND)); } + private void setScale (double scale) + { + this.userScale = scale; + } + private void setImage (BufferedImage image) { this.image = image; diff --git a/src/com/bytezone/diskbrowser/gui/DiskBrowser.java b/src/com/bytezone/diskbrowser/gui/DiskBrowser.java index d0265be..2e742f1 100755 --- a/src/com/bytezone/diskbrowser/gui/DiskBrowser.java +++ b/src/com/bytezone/diskbrowser/gui/DiskBrowser.java @@ -118,6 +118,10 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi duplicateAction.addTableSelectionListener (catalogPanel); + menuHandler.scale1Item.setAction (new ScaleAction (dataPanel, 1.0, 1)); + menuHandler.scale2Item.setAction (new ScaleAction (dataPanel, 1.5, 2)); + menuHandler.scale3Item.setAction (new ScaleAction (dataPanel, 2.0, 3)); + redoHandler.addRedoListener (catalogPanel); redoHandler.addRedoListener (diskLayoutPanel); diff --git a/src/com/bytezone/diskbrowser/gui/MenuHandler.java b/src/com/bytezone/diskbrowser/gui/MenuHandler.java index 6def211..5d2eade 100755 --- a/src/com/bytezone/diskbrowser/gui/MenuHandler.java +++ b/src/com/bytezone/diskbrowser/gui/MenuHandler.java @@ -454,15 +454,12 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL switch (prefs.getInt (PREFS_SCALE, 2)) { case 1: - scale1Item.setSelected (true); scale1Item.doClick (); break; case 2: - scale2Item.setSelected (true); scale2Item.doClick (); break; case 3: - scale3Item.setSelected (true); scale3Item.doClick (); break; } diff --git a/src/com/bytezone/diskbrowser/gui/ScaleAction.java b/src/com/bytezone/diskbrowser/gui/ScaleAction.java new file mode 100644 index 0000000..253e6cc --- /dev/null +++ b/src/com/bytezone/diskbrowser/gui/ScaleAction.java @@ -0,0 +1,39 @@ +package com.bytezone.diskbrowser.gui; + +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.KeyStroke; + +public class ScaleAction extends AbstractAction +{ + private final DataPanel owner; + private double scale; + + // ---------------------------------------------------------------------------------// + public ScaleAction (DataPanel owner, double scale, int menu) + // ---------------------------------------------------------------------------------// + { + super ("Scale " + scale); + + int mask = Toolkit.getDefaultToolkit ().getMenuShortcutKeyMaskEx (); + + putValue (Action.SHORT_DESCRIPTION, "Scale image"); + putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ( + (menu == 1 ? KeyEvent.VK_1 : menu == 2 ? KeyEvent.VK_2 : KeyEvent.VK_3), mask)); + + this.owner = owner; + this.scale = scale; + } + + // ---------------------------------------------------------------------------------// + @Override + public void actionPerformed (ActionEvent e) + // ---------------------------------------------------------------------------------// + { + owner.setScale (scale); + } +}