diff --git a/src/com/bytezone/diskbrowser/applefile/HiResImage.java b/src/com/bytezone/diskbrowser/applefile/HiResImage.java index 308b0a9..d1e50b6 100755 --- a/src/com/bytezone/diskbrowser/applefile/HiResImage.java +++ b/src/com/bytezone/diskbrowser/applefile/HiResImage.java @@ -11,16 +11,25 @@ import com.bytezone.diskbrowser.HexFormatter; public class HiResImage extends AbstractFile { - private static final int[][] colours = { { 0x000000, 0xBB66FF, 0x00FF00, 0xFFFFFF }, - { 0x000000, 0x0000FF, 0xFF0000, 0xFFFFFF } }; + private static final int WHITE = 0xFFFFFF; + private static final int BLACK = 0x000000; + private static final int RED = 0xFF0000; + private static final int GREEN = 0x00FF00; + private static final int BLUE = 0x0000FF; + private static final int VIOLET = 0xBB66FF; + private static final int[][] colours = { { VIOLET, GREEN }, { BLUE, RED } }; - int fileType; - int auxType; - byte[] unpackedBuffer; + private static int[] line = new int[280]; + + private int fileType; + private int auxType; + private byte[] unpackedBuffer; + private static boolean colourQuirks; public HiResImage (String name, byte[] buffer) { super (name, buffer); + if (name.equals ("FLY LOGO") || name.equals ("BIGBAT.PAC")) { this.buffer = unscrunch (buffer); @@ -50,6 +59,20 @@ public class HiResImage extends AbstractFile } } + public static void setDefaultColourQuirks (boolean value) + { + colourQuirks = value; + } + + public void setColourQuirks (boolean value) + { + if (colourQuirks == value) + return; + + colourQuirks = value; + drawColour (buffer); + } + private void drawMonochrome (byte[] buffer) { int rows = buffer.length <= 8192 ? 192 : 384; @@ -91,74 +114,6 @@ public class HiResImage extends AbstractFile image = new BufferedImage (280, rows, BufferedImage.TYPE_INT_RGB); DataBuffer db = image.getRaster ().getDataBuffer (); - int[][] colours = { { 0xBB66FF, 0x00FF00 }, { 0x0000FF, 0xFF0000 } }; - - int element = 0; - - int[] line = new int[280]; - int linePtr = 0; - - for (int z = 0; z < rows / 192; z++) - { - int zz = z * 0x2000; - for (int i = 0; i < 3; i++) - { - int ii = zz + i * 0x28; - for (int j = 0; j < 8; j++) - { - int jj = ii + j * 0x80; - for (int k = 0; k < 8; k++) - { - int base = jj + k * 0x400; - int max = Math.min (base + 40, buffer.length); - - for (int ptr = base; ptr < max; ptr++) - { - int colourBit = (buffer[ptr] & 0x80) >> 7; - int value = buffer[ptr] & 0x7F; - - for (int px = 0; px < 7; px++) - { - int val = (value >> px) & 0x01; - int column = (ptr + px) % 2; - line[linePtr++] = val == 0 ? 0 : colours[colourBit][column]; - } - } - - // convert ALL consecutive ON pixels to white - for (int x = 0; x < line.length - 1; x++) - if (line[x] != 0 && line[x + 1] != 0) - line[x] = line[x + 1] = 0xFFFFFF; - - // convert single coloured pixels to double - this can be ugly - if (false) - { - for (int x = 0; x < line.length - 1; x += 2) - if (line[x] != 0 && line[x] != 0xFFFFFF && line[x + 1] == 0) - line[x + 1] = line[x]; - else if (line[x] == 0 && line[x + 1] != 0 && line[x + 1] != 0xFFFFFF) - line[x] = line[x + 1]; - } - - for (int pixel : line) - db.setElem (element++, pixel); - linePtr = 0; - } - } - } - - } - } - - private void drawSolidColour (byte[] buffer) - { - int rows = buffer.length <= 8192 ? 192 : 384; - image = new BufferedImage (280, rows, BufferedImage.TYPE_INT_RGB); - - DataBuffer db = image.getRaster ().getDataBuffer (); - int[][] colours = { { 0x000000, 0xBB66FF, 0x00FF00, 0xFFFFFF }, - { 0x000000, 0x0000FF, 0xFF0000, 0xFFFFFF } }; - int element = 0; for (int z = 0; z < rows / 192; z++) @@ -167,35 +122,71 @@ public class HiResImage extends AbstractFile for (int k = 0; k < 8; k++) { int base = i * 0x28 + j * 0x80 + k * 0x400 + z * 0x2000; - int max = Math.min (base + 40, buffer.length); - - for (int ptr = base; ptr < max; ptr += 2) - { - int colourBit1 = (buffer[ptr] & 0x80) >> 7; - int colourBit2 = (buffer[ptr + 1] & 0x80) >> 7; - - int value = ((buffer[ptr + 1] & 0x7F) << 7) + (buffer[ptr] & 0x7F); - - for (int px = 0; px < 7; px++) - { - int val = value & 0x03; - value >>= 2; - int colour = 0; - - if (px <= 2) - colour = colours[colourBit1][val]; - else if (px == 3) - colour = colours[val >= 2 ? colourBit1 : colourBit2][val]; - else - colour = colours[colourBit2][val]; - - db.setElem (element++, colour); - db.setElem (element++, colour); - } - } + element = drawLine (db, element, base); } } + private int drawLine (DataBuffer db, int element, int base) + { + int max = Math.min (base + 40, buffer.length); + int linePtr = 0; + + for (int ptr = base; ptr < max; ptr++) + { + int colourBit = (buffer[ptr] & 0x80) >> 7; + int value = buffer[ptr] & 0x7F; + + for (int px = 0; px < 7; px++) + { + int val = (value >> px) & 0x01; + int column = (ptr + px) % 2; + line[linePtr++] = val == 0 ? 0 : colours[colourBit][column]; + } + } + + // convert ALL consecutive ON pixels to white + for (int x = 0; x < line.length - 1; x++) + if (line[x] != BLACK && line[x + 1] != BLACK) + line[x] = line[x + 1] = WHITE; + + // convert WOZ quirks + if (colourQuirks) + { + for (int x = 0; x < line.length - 4; x++) + { + if (line[x + 1] == BLACK) + { + // V-B-V-B -> V-V-V-B + if (line[x + 3] == BLACK && line[x] == line[x + 2] && line[x] != BLACK + && line[x] != WHITE) + line[x + 1] = line[x]; + + // V-B-W-W -> V-V-W-W + if (line[x] != BLACK && line[x] != WHITE && line[x + 3] == WHITE + && line[x + 2] == WHITE) + line[x + 1] = line[x]; + } + if (line[x + 2] == BLACK) + { + // B-G-B-G -> B-G-G-G + if (line[x] == BLACK && line[x + 1] == line[x + 3] && line[x + 1] != WHITE + && line[x + 1] != BLACK) + line[x + 2] = line[x + 1]; + + // W-W-B-G -> W-W-G-G + if (line[x] == WHITE && line[x + 1] == WHITE && line[x + 3] != BLACK + && line[x + 3] != WHITE) + line[x + 2] = line[x + 3]; + } + } + } + + for (int pixel : line) + db.setElem (element++, pixel); + + return element; + } + private void makeScreen2 (byte[] buffer) { // System.out.println (HexFormatter.format (buffer, 32000, 640)); diff --git a/src/com/bytezone/diskbrowser/gui/ColourQuirksAction.java b/src/com/bytezone/diskbrowser/gui/ColourQuirksAction.java new file mode 100644 index 0000000..558be2a --- /dev/null +++ b/src/com/bytezone/diskbrowser/gui/ColourQuirksAction.java @@ -0,0 +1,29 @@ +package com.bytezone.diskbrowser.gui; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JMenuItem; +import javax.swing.KeyStroke; + +public class ColourQuirksAction extends AbstractAction +{ + private final DataPanel owner; + + public ColourQuirksAction (DataPanel owner) + { + super ("Colour quirks"); + putValue (Action.SHORT_DESCRIPTION, "Display pixels like a TV screen"); + putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt Q")); + putValue (Action.MNEMONIC_KEY, KeyEvent.VK_Q); + this.owner = owner; + } + + @Override + public void actionPerformed (ActionEvent e) + { + owner.setColourQuirks (((JMenuItem) e.getSource ()).isSelected ()); + } +} \ No newline at end of file diff --git a/src/com/bytezone/diskbrowser/gui/DataPanel.java b/src/com/bytezone/diskbrowser/gui/DataPanel.java index 89f0dc3..193edee 100755 --- a/src/com/bytezone/diskbrowser/gui/DataPanel.java +++ b/src/com/bytezone/diskbrowser/gui/DataPanel.java @@ -1,28 +1,18 @@ package com.bytezone.diskbrowser.gui; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.RenderingHints; +import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.util.List; import java.util.prefs.Preferences; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTabbedPane; -import javax.swing.JTextArea; -import javax.swing.ScrollPaneConstants; -import javax.swing.SwingConstants; +import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import com.bytezone.common.FontAction.FontChangeEvent; import com.bytezone.common.FontAction.FontChangeListener; +import com.bytezone.diskbrowser.applefile.HiResImage; import com.bytezone.diskbrowser.disk.DiskAddress; import com.bytezone.diskbrowser.disk.SectorList; @@ -41,7 +31,7 @@ class DataPanel extends JTabbedPane JScrollPane imagePane; JTextArea formattedText; - ImagePanel imagePanel;// internal class + ImagePanel imagePanel; // internal class boolean imageVisible = false; @@ -57,10 +47,11 @@ class DataPanel extends JTabbedPane public DataPanel (MenuHandler mh, Preferences prefs) { // String dataFontName = - // prefs.get (PreferencesDialog.prefsDataFont, PreferencesDialog.defaultFontName); + // prefs.get (PreferencesDialog.prefsDataFont, PreferencesDialog.defaultFontName); // System.out.println (dataFontName); // int dataFontSize = - // prefs.getInt (PreferencesDialog.prefsDataFontSize, PreferencesDialog.defaultFontSize); + // prefs.getInt (PreferencesDialog.prefsDataFontSize, + // PreferencesDialog.defaultFontSize); // font = new Font (dataFontName, Font.PLAIN, dataFontSize); this.menuHandler = mh; @@ -133,6 +124,17 @@ class DataPanel extends JTabbedPane }); mh.lineWrapItem.setAction (new LineWrapAction (formattedText)); + mh.colourQuirksItem.setAction (new ColourQuirksAction (this)); + } + + public void setColourQuirks (boolean value) + { + if (currentDataSource instanceof HiResImage) + { + HiResImage image = (HiResImage) currentDataSource; + image.setColourQuirks (value); + imagePanel.setImage (image.getImage ()); + } } private void setTabsFont (Font font) @@ -158,7 +160,7 @@ class DataPanel extends JTabbedPane JScrollPane outputScrollPane = new JScrollPane (outputPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); - outputScrollPane.setBorder (null);// remove the ugly default border + outputScrollPane.setBorder (null); // remove the ugly default border add (outputScrollPane, tabName); return outputScrollPane; } @@ -171,7 +173,7 @@ class DataPanel extends JTabbedPane formattedText.setText (""); hexText.setText (""); disassemblyText.setText (""); - checkImage (); + removeImage (); return; } @@ -206,9 +208,7 @@ class DataPanel extends JTabbedPane BufferedImage image = dataSource.getImage (); if (image == null) - { - checkImage (); - } + removeImage (); else { imagePanel.setImage (image); @@ -224,7 +224,7 @@ class DataPanel extends JTabbedPane } } - private void checkImage () + private void removeImage () { if (imageVisible) { @@ -326,7 +326,8 @@ class DataPanel extends JTabbedPane // if (evt.getKey ().equals (PreferencesDialog.prefsDataFont)) // font = new Font (evt.getNewValue (), Font.PLAIN, font.getSize ()); // if (evt.getKey ().equals (PreferencesDialog.prefsDataFontSize)) - // font = new Font (font.getFontName (), Font.PLAIN, Integer.parseInt (evt.getNewValue ())); + // font = new Font (font.getFontName (), + // Font.PLAIN, Integer.parseInt (evt.getNewValue ())); // setTabsFont (font); // } diff --git a/src/com/bytezone/diskbrowser/gui/DiskBrowser.java b/src/com/bytezone/diskbrowser/gui/DiskBrowser.java index 4911745..a250be9 100755 --- a/src/com/bytezone/diskbrowser/gui/DiskBrowser.java +++ b/src/com/bytezone/diskbrowser/gui/DiskBrowser.java @@ -47,18 +47,21 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi // create and add the right-hand disk layout panel DiskLayoutPanel diskLayoutPanel = new DiskLayoutPanel (); - JPanel layoutBorderPanel = addPanel (diskLayoutPanel, "Disk layout", BorderLayout.EAST); + JPanel layoutBorderPanel = + addPanel (diskLayoutPanel, "Disk layout", BorderLayout.EAST); // create actions - RootDirectoryAction rootDirectoryAction = new RootDirectoryAction (null, catalogPanel); + RootDirectoryAction rootDirectoryAction = + new RootDirectoryAction (null, catalogPanel); RefreshTreeAction refreshTreeAction = new RefreshTreeAction (catalogPanel); // PreferencesAction preferencesAction = new PreferencesAction (this, prefs); AbstractAction print = new PrintAction (dataPanel); AboutAction aboutAction = new AboutAction (); - HideCatalogAction hideCatalogAction = new HideCatalogAction (this, catalogBorderPanel); + HideCatalogAction hideCatalogAction = + new HideCatalogAction (this, catalogBorderPanel); HideLayoutAction hideLayoutAction = new HideLayoutAction (this, layoutBorderPanel); ShowFreeSectorsAction showFreeAction = - new ShowFreeSectorsAction (menuHandler, diskLayoutPanel); + new ShowFreeSectorsAction (menuHandler, diskLayoutPanel); DuplicateAction duplicateAction = new DuplicateAction (); CloseTabAction closeTabAction = new CloseTabAction (catalogPanel); @@ -149,8 +152,8 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi @Override public void diskSelected (DiskSelectedEvent e) { - setTitle (windowTitle + e.getFormattedDisk () == null ? "" : e.getFormattedDisk () - .getName ()); + setTitle (windowTitle + e.getFormattedDisk () == null ? "" + : e.getFormattedDisk ().getName ()); } public static void main (String[] args) diff --git a/src/com/bytezone/diskbrowser/gui/MenuHandler.java b/src/com/bytezone/diskbrowser/gui/MenuHandler.java index aed2e04..29b4cec 100755 --- a/src/com/bytezone/diskbrowser/gui/MenuHandler.java +++ b/src/com/bytezone/diskbrowser/gui/MenuHandler.java @@ -7,17 +7,23 @@ import java.util.prefs.Preferences; import javax.swing.*; -import com.bytezone.common.*; +import com.bytezone.common.EnvironmentAction; +import com.bytezone.common.FontAction; +import com.bytezone.common.OSXAdapter; +import com.bytezone.common.Platform; import com.bytezone.common.QuitAction.QuitListener; +import com.bytezone.diskbrowser.applefile.HiResImage; import com.bytezone.diskbrowser.disk.DataDisk; import com.bytezone.diskbrowser.disk.FormattedDisk; -public class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitListener +public class MenuHandler + implements DiskSelectionListener, FileSelectionListener, QuitListener { private static final String PREFS_LINE_WRAP = "line wrap"; private static final String PREFS_SHOW_CATALOG = "show catalog"; private static final String PREFS_SHOW_LAYOUT = "show layout"; private static final String PREFS_SHOW_FREE_SECTORS = "show free sectors"; + private static final String PREFS_COLOUR_QUIRKS = "colour quirks"; FormattedDisk currentDisk; @@ -40,8 +46,8 @@ public class MenuHandler implements DiskSelectionListener, FileSelectionListener FontAction fontAction; // Format menu items - JMenuItem lineWrapItem = new JCheckBoxMenuItem ("Line wrap"); - JMenuItem showLayoutItem = new JCheckBoxMenuItem ("Show layout panel"); + final JMenuItem lineWrapItem = new JCheckBoxMenuItem ("Line wrap"); + final JMenuItem showLayoutItem = new JCheckBoxMenuItem ("Show layout panel"); JMenuItem showCatalogItem = new JCheckBoxMenuItem ("Show catalog panel"); JMenuItem showFreeSectorsItem = new JCheckBoxMenuItem ("Show free sectors"); @@ -52,6 +58,8 @@ public class MenuHandler implements DiskSelectionListener, FileSelectionListener JMenuItem interleave2Item = new JRadioButtonMenuItem (new InterleaveAction (2)); JMenuItem interleave3Item = new JRadioButtonMenuItem (new InterleaveAction (3)); + JMenuItem colourQuirksItem = new JCheckBoxMenuItem ("Colour quirks"); + public MenuHandler (Preferences prefs) { menuBar.add (fileMenu); @@ -73,9 +81,9 @@ public class MenuHandler implements DiskSelectionListener, FileSelectionListener JMenuItem fontItem = new JMenuItem (fontAction); fileMenu.add (fontItem); fontAction.setSampleText ("120 FOR Z = 14 TO 24:\n" + " VTAB 5:\n" + " HTAB Z:\n" - + " PRINT AB$:\n" + " FOR TI = 1 TO 50:\n" + " NEXT :\n" + " POKE 0,Z + 40:\n" - + " POKE 1,9:\n" + " CALL MU:\n" + " VTAB 5:\n" + " HTAB Z:\n" - + " PRINT SPC(12):\n" + "NEXT :\n" + "VTAB 5:\n" + "HTAB 24:\n" + "PRINT AB$\n"); + + " PRINT AB$:\n" + " FOR TI = 1 TO 50:\n" + " NEXT :\n" + " POKE 0,Z + 40:\n" + + " POKE 1,9:\n" + " CALL MU:\n" + " VTAB 5:\n" + " HTAB Z:\n" + + " PRINT SPC(12):\n" + "NEXT :\n" + "VTAB 5:\n" + "HTAB 24:\n" + "PRINT AB$\n"); if (false) { @@ -97,6 +105,8 @@ public class MenuHandler implements DiskSelectionListener, FileSelectionListener formatMenu.addSeparator (); formatMenu.add (sector256Item); formatMenu.add (sector512Item); + formatMenu.addSeparator (); + formatMenu.add (colourQuirksItem); helpMenu.add (new JMenuItem (new EnvironmentAction ())); @@ -105,10 +115,6 @@ public class MenuHandler implements DiskSelectionListener, FileSelectionListener sector512Item.setActionCommand ("512"); sector512Item.setAccelerator (KeyStroke.getKeyStroke ("alt 5")); - lineWrapItem.setAccelerator (KeyStroke.getKeyStroke ("alt W")); - printItem.setAccelerator (KeyStroke.getKeyStroke ("control P")); - - // ButtonGroup dosGroup = new ButtonGroup (); ButtonGroup sectorGroup = new ButtonGroup (); ButtonGroup interleaveGroup = new ButtonGroup (); @@ -126,6 +132,8 @@ public class MenuHandler implements DiskSelectionListener, FileSelectionListener showLayoutItem.setSelected (prefs.getBoolean (PREFS_SHOW_LAYOUT, true)); showCatalogItem.setSelected (prefs.getBoolean (PREFS_SHOW_CATALOG, true)); showFreeSectorsItem.setSelected (prefs.getBoolean (PREFS_SHOW_FREE_SECTORS, false)); + colourQuirksItem.setSelected (prefs.getBoolean (PREFS_COLOUR_QUIRKS, false)); + HiResImage.setDefaultColourQuirks (colourQuirksItem.isSelected ()); } void addHelpMenuAction (Action action, String functionName) @@ -135,14 +143,11 @@ public class MenuHandler implements DiskSelectionListener, FileSelectionListener try { if (functionName.equals ("about")) - OSXAdapter.setAboutHandler (action, - action.getClass ().getDeclaredMethod (functionName, - (Class[]) null)); + OSXAdapter.setAboutHandler (action, action.getClass () + .getDeclaredMethod (functionName, (Class[]) null)); else if (functionName.equals ("prefs")) - OSXAdapter.setPreferencesHandler (action, - action.getClass () - .getDeclaredMethod (functionName, - (Class[]) null)); + OSXAdapter.setPreferencesHandler (action, action.getClass () + .getDeclaredMethod (functionName, (Class[]) null)); } catch (Exception e) { @@ -182,6 +187,7 @@ public class MenuHandler implements DiskSelectionListener, FileSelectionListener prefs.putBoolean (PREFS_SHOW_LAYOUT, showLayoutItem.isSelected ()); prefs.putBoolean (PREFS_SHOW_CATALOG, showCatalogItem.isSelected ()); prefs.putBoolean (PREFS_SHOW_FREE_SECTORS, showFreeSectorsItem.isSelected ()); + prefs.putBoolean (PREFS_COLOUR_QUIRKS, colourQuirksItem.isSelected ()); } @Override @@ -247,7 +253,12 @@ public class MenuHandler implements DiskSelectionListener, FileSelectionListener } @Override - public void restore (Preferences preferences) + public void restore (Preferences prefs) { + // lineWrapItem.setSelected (prefs.getBoolean (PREFS_LINE_WRAP, true)); + // showLayoutItem.setSelected (prefs.getBoolean (PREFS_SHOW_LAYOUT, true)); + // showCatalogItem.setSelected (prefs.getBoolean (PREFS_SHOW_CATALOG, true)); + // showFreeSectorsItem.setSelected (prefs.getBoolean (PREFS_SHOW_FREE_SECTORS, false)); + // colourQuirksItem.setSelected (prefs.getBoolean (PREFS_COLOUR_QUIRKS, false)); } } \ No newline at end of file