Compare commits
191 Commits
Author | SHA1 | Date |
---|---|---|
Denis Molony | 2bc330e377 | |
Denis Molony | 6c81bcc93b | |
Denis Molony | 171fd66ba1 | |
Denis Molony | aa77ec1cd4 | |
Denis Molony | 8f95988596 | |
Denis Molony | 8cb682f068 | |
Denis Molony | dfc7a68580 | |
Denis Molony | 4b476457d3 | |
Denis Molony | 3bf972a761 | |
Denis Molony | fd5bee6e5c | |
Denis Molony | 0af6714119 | |
Denis Molony | 22dfaf65c6 | |
Denis Molony | f4a6465b04 | |
Denis Molony | 64d5ce9ee2 | |
Denis Molony | 4e48437adc | |
Denis Molony | e2abdcabc9 | |
Denis Molony | bc0993e9d3 | |
Denis Molony | 9fba3893ba | |
Denis Molony | 09c4542118 | |
Denis Molony | af3ead0441 | |
Denis Molony | c12392200b | |
frankmilliron | 794fef8610 | |
frankmilliron | 2ec0e10c5e | |
Denis Molony | 668ed719fa | |
Denis Molony | 23b95675cf | |
Denis Molony | b98ecbed8d | |
Denis Molony | 82381a6a47 | |
Denis Molony | 3f2f1bfbca | |
Denis Molony | a7119528a6 | |
Denis Molony | 6f943ae8c2 | |
Denis Molony | 5add6c0729 | |
Denis Molony | 921c946ab5 | |
Denis Molony | 898587b23b | |
Denis Molony | 37c489f252 | |
Denis Molony | 036e47b9b1 | |
Denis Molony | 250c1a9bd9 | |
Denis Molony | b19e89d7cf | |
Denis Molony | d71cabb754 | |
Denis Molony | 848b2469ae | |
Denis Molony | 989b1d5ab9 | |
Denis Molony | e0a2c50d5b | |
Denis Molony | 8765299cf4 | |
Denis Molony | 97fe58d94d | |
Denis Molony | 7d4d8c75e6 | |
Denis Molony | f5664a9ce9 | |
Denis Molony | 9d8cdcd67b | |
Denis Molony | 12b74f9d21 | |
Denis Molony | 1b405c6f38 | |
Denis Molony | 66d6910f91 | |
Denis Molony | 572ee8c3a1 | |
Denis Molony | 2a14b7baad | |
Denis Molony | a633e28ed3 | |
Denis Molony | ca11e8ee68 | |
Denis Molony | ce52253f5d | |
Denis Molony | e408aa3d62 | |
Denis Molony | c4b4d17f52 | |
Denis Molony | 0b72f1a37d | |
Denis Molony | 1b86b31233 | |
Denis Molony | 1b9e9d47ac | |
Denis Molony | decc781572 | |
Denis Molony | 16ccc2632a | |
Denis Molony | 40c2afbd48 | |
Denis Molony | f9038810d2 | |
Denis Molony | 3435e825df | |
Denis Molony | ff7c6fd126 | |
Denis Molony | 91846d8563 | |
Denis Molony | 19b6339ac5 | |
Denis Molony | db4953618c | |
Denis Molony | c1deee56a0 | |
Denis Molony | b1ed1a74ba | |
Denis Molony | cf0cfd278b | |
Denis Molony | 48aca6e1eb | |
Denis Molony | d83ac3afda | |
Denis Molony | 2270b1f6db | |
Denis Molony | da67dbe0d7 | |
Denis Molony | 133352ba31 | |
Denis Molony | 761c43dc3d | |
Denis Molony | d03de97247 | |
Denis Molony | e67bbeaf8b | |
Denis Molony | 6dfc72b2d2 | |
Denis Molony | fb748df4ae | |
Denis Molony | 4a03c411fc | |
Denis Molony | 54db7d95d6 | |
Denis Molony | 59b22be2bd | |
Denis Molony | 47a07f5cfe | |
Denis Molony | bca12f0738 | |
Denis Molony | 27100ad38e | |
Denis Molony | 2a6fd74013 | |
Denis Molony | 4767c317d0 | |
Denis Molony | 068f382c87 | |
Denis Molony | e7d8c4ebc2 | |
Denis Molony | 9ef0f82dea | |
Denis Molony | fba8c07142 | |
Denis Molony | 4aefc8b695 | |
Denis Molony | a8574d24f8 | |
Denis Molony | 449e6c0e9a | |
Denis Molony | 09b6f66855 | |
Denis Molony | f30fe1a78a | |
Denis Molony | 0e40e25710 | |
Denis Molony | f02c932d91 | |
Denis Molony | c18cfe9ed7 | |
Denis Molony | dcb3e32845 | |
Denis Molony | 08d6d1b136 | |
Denis Molony | 954b0c0bd8 | |
Denis Molony | f22b4dcd46 | |
Denis Molony | c42481637e | |
Denis Molony | 7ca8160d13 | |
Denis Molony | 26316a82a9 | |
Denis Molony | 5f29cfcd09 | |
Denis Molony | 7f2e963689 | |
Denis Molony | 8ea18c8cc1 | |
Denis Molony | f92fe5b57e | |
Denis Molony | bb4dcbdd7c | |
Denis Molony | 8aec65449e | |
Denis Molony | ff273e7df9 | |
Denis Molony | 1a1f9df93f | |
Denis Molony | 80a07c0496 | |
Denis Molony | 8369e4a788 | |
Denis Molony | bfeab1477c | |
Denis Molony | ad8464c6c2 | |
Denis Molony | b1ff2f7740 | |
Denis Molony | 4040238bbf | |
Denis Molony | 70f21070d5 | |
Denis Molony | 91693bbc37 | |
Denis Molony | 8a9b824302 | |
Denis Molony | 06f4713baa | |
Denis Molony | e7ded68b03 | |
Denis Molony | 58cec66535 | |
Denis Molony | c105d07e60 | |
Denis Molony | 3e32b3caf0 | |
Denis Molony | 7aa80b8b5e | |
Denis Molony | 5e053872a9 | |
Denis Molony | 7d162a4baf | |
Denis Molony | 83d5be3f9f | |
Denis Molony | ea0a827331 | |
Denis Molony | dc551285bb | |
Denis Molony | 95538f5282 | |
Denis Molony | 9d706d62ef | |
Denis Molony | 63fc59accc | |
Denis Molony | beb0830c25 | |
Denis Molony | ae1188ae27 | |
Denis Molony | 1b27ea02e7 | |
Denis Molony | c2f2277717 | |
Denis Molony | 79ccd6793c | |
Denis Molony | 5be0236845 | |
Denis Molony | 59bf768d14 | |
Denis Molony | 566479450a | |
Denis Molony | b45e7d7e54 | |
Denis Molony | 9dddd2be3e | |
Denis Molony | d3f21e0d49 | |
Denis Molony | af706e03c7 | |
Denis Molony | b6496e9c87 | |
Denis Molony | a33aedd750 | |
Denis Molony | 13647213c6 | |
Denis Molony | 5ea96a260d | |
Denis Molony | 438dd9dd4c | |
Denis Molony | 45a97d2959 | |
Denis Molony | a8de9099b1 | |
Denis Molony | adf77ba603 | |
Denis Molony | 62c09af14f | |
Denis Molony | ddadfd3198 | |
Denis Molony | 4f95871d83 | |
Denis Molony | fe2df5247c | |
Denis Molony | 3bd836a828 | |
Denis Molony | a72bdff81d | |
Denis Molony | 90f8657722 | |
Denis Molony | b7106787d1 | |
Denis Molony | 3c2816baf0 | |
Denis Molony | c6443ff89e | |
Denis Molony | 269a1bbd83 | |
Denis Molony | 768111571e | |
Denis Molony | d6d0b1672e | |
Denis Molony | 76b2d4a291 | |
Denis Molony | c3ee00673d | |
Denis Molony | 7ec277e0a3 | |
Denis Molony | 33b58e8d79 | |
Denis Molony | 73e964fe76 | |
Denis Molony | 7d79f8f365 | |
Denis Molony | 2dff5a966c | |
Denis Molony | ccbfc47a66 | |
Denis Molony | 032da321c3 | |
Denis Molony | 39269d3b27 | |
Denis Molony | a006053297 | |
Denis Molony | 4353d0e0ca | |
Denis Molony | f7b455a7f1 | |
Denis Molony | bb1a7af6c8 | |
Denis Molony | 0032b0c2bb | |
Denis Molony | 113917e278 | |
Denis Molony | 8db6489649 | |
Denis Molony | e135b65948 | |
Denis Molony | d0bfde2e80 |
|
@ -1,4 +0,0 @@
|
|||
/bin/
|
||||
.project
|
||||
.classpath
|
||||
build.xml
|
17
README.md
|
@ -1,5 +1,6 @@
|
|||
# Apple II Disk Browser
|
||||
|
||||
### Alternative
|
||||
There is a new release of [DiskBrowser2](https://github.com/dmolony/diskbrowser2) available.
|
||||
### Features
|
||||
- Cross-platform (Windows, MacOS, Linux)
|
||||
- Disk formats
|
||||
|
@ -30,7 +31,7 @@
|
|||
* [Usage](resources/usage.md)
|
||||
|
||||
### Installation
|
||||
* Install the **latest** version of the [JDK](http://www.oracle.com/technetwork/java/javase/downloads/index.html).
|
||||
* Install the **latest** version of the [JDK](https://www.oracle.com/java/technologies/downloads/).
|
||||
* Download DiskBrowser.jar from the [releases](https://github.com/dmolony/diskbrowser/releases) page.
|
||||
* Double-click the jar file, or enter 'java -jar DiskBrowser.jar' in the terminal.
|
||||
* Set your root folder (the top-level folder where you keep your disk images).
|
||||
|
@ -52,14 +53,24 @@ Java runs on Windows, MacOS and Linux.
|
|||
#### Graphics
|
||||
![Graphics](resources/graphics.png?raw=true "Graphics")
|
||||
#### Applesoft Formatting and Analysis
|
||||
Applesoft programs are displayed in a modern, easily-readable format. A comprehensive cross-listing of variables, strings, calls and jumps is available. Easily find duplicate variable names.
|
||||
For the truly retro look, programs can be displayed in the [original 40-column line wrap](resources/basic.md) mode.
|
||||
![Applesoft](resources/basic.png?raw=true "Applesoft")
|
||||
#### Pascal code
|
||||
![Pascal](resources/pascal.png?raw=true "Pascal")
|
||||
![Pascal](resources/pascal1.png?raw=true "Pascal text")
|
||||
![Pascal](resources/pascal2.png?raw=true "Pascal internals")
|
||||
#### Infocom
|
||||
![Infocom](resources/zork.png?raw=true "Infocom")
|
||||
#### Wizardry
|
||||
Wizardry scenarios 1 to 3 are reasonably complete, Wizardry IV and V are partially done. For a dedicated Wizardry application see [WizardryApp](https://github.com/dmolony/WizardryApp).
|
||||
![Wizardry](resources/wizardry.png?raw=true "Wizardry")
|
||||
Scenarios 4 and 5 come on multiple disks, and they need to be named so that the only difference between disk names is the identifier before the '.dsk' suffix.
|
||||
![Wizardry](resources/wizardry4.png?raw=true "Wizardry IV")
|
||||
#### Visicalc
|
||||
DiskBrowser has an inbuilt Visicalc processor which will evaluate the sheet and display the results.
|
||||
![Visicalc](resources/visicalc.png?raw=true "Visicalc")
|
||||
#### Complete Disk List
|
||||
Generates a list of all the disks in your collection. The list can be sorted by any of the table headings. Checksums can be generated as needed, or for the whole collection.
|
||||
![Disk List](resources/disklist.png?raw=true "Disk List")
|
||||
Select a disk and click the duplicates button to see all of the disks that share the same checksum.
|
||||
![Duplicates](resources/duplicates.png?raw=true "Duplicates")
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<project name="DiskBrowser" default="jar" basedir=".">
|
||||
|
||||
<property name="srcDir" location="src" />
|
||||
<property name="binDir" location="bin" />
|
||||
<property name="jarDir" location="${user.home}/Dropbox/Java" />
|
||||
<property name="jarFile" location="${jarDir}/DiskBrowser.jar" />
|
||||
|
||||
<target name="version">
|
||||
<echo>DiskBrowser.jar</echo>
|
||||
<echo>${ant.version}</echo>
|
||||
<echo>Java/JVM version: ${ant.java.version}</echo>
|
||||
<echo>Java/JVM detail version: ${java.version}</echo>
|
||||
</target>
|
||||
|
||||
<target name="init" depends="version">
|
||||
<delete file="${binDir}/*.class" />
|
||||
<delete file="${jarFile}" />
|
||||
</target>
|
||||
|
||||
<target name="compile" depends="init">
|
||||
<javac debug="on" srcdir="${srcDir}" destdir="${binDir}" includeantruntime="false">
|
||||
<classpath>
|
||||
<pathelement location="." />
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<target name="jar" depends="compile">
|
||||
<jar destfile="${jarFile}">
|
||||
<fileset dir="${binDir}" />
|
||||
<zipfileset src="${jarDir}/InputPanel.jar" />
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="com.bytezone.diskbrowser.gui.DiskBrowser" />
|
||||
</manifest>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,13 @@
|
|||
### Applesoft program listing
|
||||
|
||||
#### State of the art circa 1980
|
||||
<img src="basic0.png" alt="terrible" width="700"/>
|
||||
|
||||
#### Original (using Print Char 21)
|
||||
<img src="basic5.png" alt="truly awful" width="400"/>
|
||||
|
||||
#### No formatting
|
||||
<img src="basic2.png" alt="better" width="850"/>
|
||||
|
||||
#### Formatted
|
||||
<img src="basic3.png" alt="best" width="550"/>
|
After Width: | Height: | Size: 730 KiB |
After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 73 KiB |
After Width: | Height: | Size: 128 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 784 KiB After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 373 KiB |
Before Width: | Height: | Size: 788 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 642 KiB After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 1.0 MiB |
|
@ -6,6 +6,7 @@ import javax.swing.JComponent;
|
|||
import javax.swing.JPanel;
|
||||
|
||||
import com.bytezone.diskbrowser.gui.DataSource;
|
||||
import com.bytezone.diskbrowser.prodos.ResourceFork;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
|
@ -16,9 +17,10 @@ public abstract class AbstractFile implements DataSource
|
|||
|
||||
protected String name;
|
||||
public byte[] buffer;
|
||||
protected AssemblerProgram assembler;
|
||||
AssemblerProgram assembler;
|
||||
protected BufferedImage image;
|
||||
protected int loadAddress;
|
||||
int loadAddress;
|
||||
ResourceFork resourceFork;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public AbstractFile (String name, byte[] buffer)
|
||||
|
@ -28,12 +30,37 @@ public abstract class AbstractFile implements DataSource
|
|||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void setName (String name)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.name = name; // Infocom ZObject uses this - but it sucks
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText () // Override this to get a tailored text representation
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return "Name : " + name + "\n\nNo text description";
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
text.append ("Name : " + name + "\n\nNo text description");
|
||||
|
||||
if (resourceFork != null)
|
||||
{
|
||||
text.append ("\n\nResource Fork:\n\n");
|
||||
text.append (resourceFork);
|
||||
}
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public byte[] getBuffer ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -43,6 +70,13 @@ public abstract class AbstractFile implements DataSource
|
|||
showDebugText = value;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void setResourceFork (ResourceFork resourceFork)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.resourceFork = resourceFork;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public static void setDebug (boolean value)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -106,7 +140,6 @@ public abstract class AbstractFile implements DataSource
|
|||
public JComponent getComponent ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
JPanel panel = new JPanel ();
|
||||
return panel;
|
||||
return new JPanel ();
|
||||
}
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
package com.bytezone.diskbrowser.applefile;
|
||||
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.isControlCharacter;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
class Alignment implements ApplesoftConstants
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -34,8 +32,6 @@ class Alignment implements ApplesoftConstants
|
|||
void check (SubLine subline)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
// System.out.printf ("%-20s %d %d%n", subline, subline.equalsPosition,
|
||||
// subline.endPosition - subline.equalsPosition);
|
||||
if (equalsPosition < subline.equalsPosition)
|
||||
equalsPosition = subline.equalsPosition;
|
||||
|
||||
|
@ -50,7 +46,7 @@ class Alignment implements ApplesoftConstants
|
|||
public String getAlignedText (SubLine subline)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder line = toStringBuilder (subline); // get line
|
||||
StringBuilder line = subline.toStringBuilder (); // get line
|
||||
|
||||
if (equalsPosition == 0 || subline.is (TOKEN_REM))
|
||||
return line.toString ();
|
||||
|
@ -59,48 +55,28 @@ class Alignment implements ApplesoftConstants
|
|||
int targetLength = subline.endPosition - equalsPosition;
|
||||
|
||||
// insert spaces before '=' until it lines up with the other assignment lines
|
||||
while (alignEqualsPos-- > equalsPosition)
|
||||
line.insert (equalsPosition, ' ');
|
||||
while (alignEqualsPos-- > subline.equalsPosition)
|
||||
line.insert (subline.equalsPosition, ' ');
|
||||
|
||||
if (line.charAt (line.length () - 1) == ':')
|
||||
while (targetLength++ <= targetLength)
|
||||
while (targetLength++ <= this.targetLength)
|
||||
line.append (" ");
|
||||
|
||||
return line.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private StringBuilder toStringBuilder (SubLine subline)
|
||||
@Override
|
||||
public String toString ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder line = new StringBuilder ();
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
// All sublines end with 0 or : except IF lines that are split into two
|
||||
int max = subline.startPtr + subline.length - 1;
|
||||
if (subline.buffer[max] == 0)
|
||||
--max;
|
||||
text.append (String.format ("Equals position ..... %d%n", equalsPosition));
|
||||
text.append (String.format ("Target length ....... %d%n", targetLength));
|
||||
text.append (String.format ("First subline ....... %s%n", firstSubLine));
|
||||
text.append (String.format ("Last subline ........ %s", lastSubLine));
|
||||
|
||||
if (subline.isImpliedGoto () && !ApplesoftBasicProgram.basicPreferences.showThen)
|
||||
line.append ("GOTO ");
|
||||
|
||||
for (int p = subline.startPtr; p <= max; p++)
|
||||
{
|
||||
byte b = subline.buffer[p];
|
||||
if (subline.isToken (b))
|
||||
{
|
||||
if (line.length () > 0 && line.charAt (line.length () - 1) != ' ')
|
||||
line.append (' ');
|
||||
int val = b & 0x7F;
|
||||
if (b != TOKEN_THEN || ApplesoftBasicProgram.basicPreferences.showThen)
|
||||
line.append (ApplesoftConstants.tokens[val] + " ");
|
||||
}
|
||||
// else if (Utility.isControlCharacter (b))
|
||||
// line.append (ApplesoftBasicProgram.basicPreferences.showCaret
|
||||
// ? "^" + (char) (b + 64) : "?");
|
||||
else if (!isControlCharacter (b))
|
||||
line.append ((char) b);
|
||||
}
|
||||
|
||||
return line;
|
||||
return text.toString ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ import static com.bytezone.diskbrowser.utilities.Utility.ASCII_BACKSPACE;
|
|||
import static com.bytezone.diskbrowser.utilities.Utility.ASCII_CR;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.ASCII_LF;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.getIndent;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.getShort;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.isHighBitSet;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.unsignedShort;
|
||||
|
||||
import com.bytezone.diskbrowser.gui.BasicPreferences;
|
||||
|
||||
|
@ -37,9 +37,9 @@ public class AppleBasicFormatter extends BasicFormatter
|
|||
LineFormatter formatter =
|
||||
basicPreferences.appleLineWrap ? wrapFormatter : flatFormatter;
|
||||
|
||||
while ((linkField = unsignedShort (buffer, ptr)) != 0)
|
||||
while ((linkField = getShort (buffer, ptr)) != 0)
|
||||
{
|
||||
int lineNumber = unsignedShort (buffer, ptr + 2);
|
||||
int lineNumber = getShort (buffer, ptr + 2);
|
||||
currentLine.append (String.format (" %d ", lineNumber));
|
||||
ptr += 4;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ public class ApplesoftBasicProgram extends BasicProgram implements ApplesoftCons
|
|||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final List<SourceLine> sourceLines = new ArrayList<> ();
|
||||
private int ptr; // end-of-program marker
|
||||
private int ptr = 0; // end-of-program marker
|
||||
|
||||
private final UserBasicFormatter userBasicFormatter;
|
||||
private final AppleBasicFormatter appleBasicFormatter;
|
||||
|
@ -78,13 +78,6 @@ public class ApplesoftBasicProgram extends BasicProgram implements ApplesoftCons
|
|||
return sourceLines;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
byte[] getBuffer ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
int getEndPtr ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.bytezone.diskbrowser.applefile;
|
||||
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.unsignedShort;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.getShort;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -35,14 +35,14 @@ public abstract class BasicFormatter implements ApplesoftConstants
|
|||
int getLoadAddress ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return (buffer.length > 3) ? unsignedShort (buffer, 0) - getFirstLineLength () : 0;
|
||||
return (buffer.length > 3) ? getShort (buffer, 0) - getFirstLineLength () : 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private int getFirstLineLength ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int linkField = unsignedShort (buffer, 0);
|
||||
int linkField = getShort (buffer, 0);
|
||||
if (linkField == 0)
|
||||
return 2;
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ public class BasicProgramGS extends BasicProgram
|
|||
ptr += labelLength;
|
||||
|
||||
int lineLength = buffer[ptr] & 0xFF;
|
||||
lineNumber = Utility.intValue (buffer[ptr + 1], buffer[ptr + 2]);
|
||||
lineNumber = Utility.getShort (buffer, ptr + 1);
|
||||
length = labelLength + lineLength;
|
||||
|
||||
if (lineNumber == 0)
|
||||
|
|
|
@ -8,8 +8,8 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
|
|||
public class BasicTextFile extends TextFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static String underline = "------------------------------------------"
|
||||
+ "------------------------------------\n";
|
||||
private static String underline =
|
||||
"------------------------------------------" + "------------------------------------\n";
|
||||
private static String fullUnderline = "---------- ------- " + underline;
|
||||
private int recordLength; // prodos aux
|
||||
private List<TextBuffer> buffers; // only used if it is a Prodos text file
|
||||
|
@ -30,6 +30,7 @@ public class BasicTextFile extends TextFile
|
|||
super (name, buffer);
|
||||
|
||||
this.eof = eof;
|
||||
|
||||
recordLength = auxType;
|
||||
prodosFile = true;
|
||||
}
|
||||
|
@ -42,6 +43,7 @@ public class BasicTextFile extends TextFile
|
|||
|
||||
this.buffers = buffers;
|
||||
this.eof = eof;
|
||||
|
||||
recordLength = auxType;
|
||||
prodosFile = true;
|
||||
}
|
||||
|
@ -167,8 +169,7 @@ public class BasicTextFile extends TextFile
|
|||
if (textPreferences.showTextOffsets)
|
||||
{
|
||||
line = line.replaceAll ("\\n", "\n ");
|
||||
text.append (
|
||||
String.format ("%,10d %,8d %s%n", recNo * recordLength, recNo, line));
|
||||
text.append (String.format ("%,10d %,8d %s%n", recNo * recordLength, recNo, line));
|
||||
}
|
||||
else
|
||||
text.append (String.format ("%s%n", line));
|
||||
|
|
|
@ -0,0 +1,229 @@
|
|||
package com.bytezone.diskbrowser.applefile;
|
||||
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.getShort;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class CPMBasicFile extends BasicProgram
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
String[] tokens = { //
|
||||
"", "END", "FOR", "NEXT", "DATA", "INPUT", "DIM", "READ", // 0x80
|
||||
"LET", "GOTO", "RUN", "IF", "RESTORE", "GOSUB", "RETURN", "REM", // 0x88
|
||||
"STOP", "PRINT", "CLEAR", "LIST", "NEW", "ON", "DEF", "POKE", // 0x90
|
||||
"", "", "", "LPRINT", "LLIST", "WIDTH", "ELSE", "", // 0x98
|
||||
"", "SWAP", "ERASE", "", "ERROR", "RESUME", "DELETE", "", // 0xA0
|
||||
"RENUM", "DEFSTR", "DEFINT", "", "DEFDBL", "LINE", "", "WHILE", // 0xA8
|
||||
"WEND", "CALL", "WRITE", "COMMON", "CHAIN", // 0xB0
|
||||
"OPTION", "RANDOMIZE", "SYSTEM", // 0xB5
|
||||
"OPEN", "FIELD", "GET", "PUT", "CLOSE", "LOAD", "MERGE", "", // 0xB8
|
||||
"NAME", "KILL", "LSET", "RSET", "SAVE", "RESET", "TEXT", "HOME", // 0xC0
|
||||
"VTAB", "HTAB", "INVERSE", "NORMAL", "", "", "", "", // 0xC8
|
||||
"", "", "", "", "", "WAIT", "", "", // 0xD0
|
||||
"", "", "", "", "", "TO", "THEN", "TAB(", // 0xD8
|
||||
"STEP", "USR", "FN", "SPC(", "", "ERL", "ERR", "STRING$", // 0xE0
|
||||
"USING", "INSTR", "'", "VARPTR", "", "", "INKEY$", ">", // 0xE8
|
||||
"=", "<", "+", "-", "*", "/", "", "AND", // 0xF0
|
||||
"OR", "", "", "", "MOD", "/", "", "", // 0xF8
|
||||
};
|
||||
|
||||
String[] functions = { //
|
||||
"", "LEFT$", "RIGHT$", "MID$", "SGN", "INT", "ABS", "SQR", // 0x80
|
||||
"RND", "SIN", "LOG", "EXP", "COS", "TAN", "ATN", "FRE", // 0x88
|
||||
"POS", "LEN", "STR$", "VAL", "ASC", "CHR$", "PEEK", "SPACE$", // 0x90
|
||||
"OCT$", "HEX$", "LPOS", "CINT", "CSNG", "CDBL", "FIX", "", // 0x98
|
||||
"", "", "", "", "", "", "", "", // 0xA0
|
||||
"", "", "CVI", "CVS", "CVD", "", "EOF", "LOC", // 0xA8
|
||||
"", "MKI$", "MKS$", "MKD$", // 0xB0
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public CPMBasicFile (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
if (basicPreferences.showHeader)
|
||||
text.append ("Name : " + name + "\n\n");
|
||||
|
||||
int ptr = 5;
|
||||
while (buffer[ptr] != 0)
|
||||
ptr++;
|
||||
|
||||
if (showDebugText)
|
||||
return debugText ();
|
||||
|
||||
ptr = 1;
|
||||
while (ptr < buffer.length)
|
||||
{
|
||||
int nextAddress = getShort (buffer, ptr);
|
||||
|
||||
if (nextAddress == 0)
|
||||
break;
|
||||
|
||||
int lineNumber = getShort (buffer, ptr + 2);
|
||||
|
||||
text.append (String.format (" %d ", lineNumber));
|
||||
ptr += 4;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int val = buffer[ptr++] & 0xFF;
|
||||
|
||||
if (val == 0)
|
||||
break;
|
||||
|
||||
if ((val & 0x80) != 0)
|
||||
{
|
||||
if (val == 0xFF)
|
||||
{
|
||||
val = buffer[ptr++] & 0xFF;
|
||||
String token = functions[val & 0x7F];
|
||||
if (token.length () == 0)
|
||||
token = String.format ("<FF %02X>", val);
|
||||
text.append (token);
|
||||
}
|
||||
else
|
||||
{
|
||||
String token = tokens[val & 0x7F];
|
||||
if (token.length () == 0)
|
||||
token = String.format ("<%02X>", val);
|
||||
text.append (token);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (val >= 0x20 && val <= 0x7E) // printable
|
||||
{
|
||||
// check for stupid apostrophe comment
|
||||
if (val == 0x3A && ptr + 1 < buffer.length && buffer[ptr] == (byte) 0x8F
|
||||
&& buffer[ptr + 1] == (byte) 0xEA)
|
||||
{
|
||||
text.append ("'");
|
||||
ptr += 2;
|
||||
}
|
||||
else if (val == 0x3A && ptr < buffer.length && buffer[ptr] == (byte) 0x9E)
|
||||
{
|
||||
// ignore colon before ELSE
|
||||
}
|
||||
else
|
||||
text.append (String.format ("%s", (char) val));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (val >= 0x11 && val <= 0x1A) // inline numbers
|
||||
{
|
||||
text.append (val - 0x11);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (val)
|
||||
{
|
||||
case 0x07:
|
||||
text.append ("<BELL>");
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
text.append (" ");
|
||||
break;
|
||||
|
||||
case 0x0A:
|
||||
text.append ("\n ");
|
||||
break;
|
||||
|
||||
case 0x0C:
|
||||
text.append ("&H" + String.format ("%X", Utility.getShort (buffer, ptr)));
|
||||
ptr += 2;
|
||||
break;
|
||||
|
||||
case 0x0E: // same as 0x1C ??
|
||||
text.append (Utility.getShort (buffer, ptr));
|
||||
ptr += 2;
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
text.append (buffer[ptr++] & 0xFF);
|
||||
break;
|
||||
|
||||
case 0x1C: // same as 0x0E ??
|
||||
text.append (Utility.getShort (buffer, ptr));
|
||||
ptr += 2;
|
||||
break;
|
||||
|
||||
case 0x1D:
|
||||
String d4 = Utility.floatValueMS4 (buffer, ptr) + "";
|
||||
if (d4.endsWith (".0"))
|
||||
d4 = d4.substring (0, d4.length () - 2);
|
||||
text.append (d4 + "!");
|
||||
ptr += 4;
|
||||
break;
|
||||
|
||||
case 0x1F:
|
||||
String d8 = Utility.floatValueMS8 (buffer, ptr) + "";
|
||||
if (d8.endsWith (".0"))
|
||||
d8 = d8.substring (0, d8.length () - 2);
|
||||
text.append (d8 + "#");
|
||||
ptr += 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
text.append (String.format ("<%02X>", val));
|
||||
}
|
||||
}
|
||||
|
||||
text.append ("\n");
|
||||
}
|
||||
|
||||
return Utility.rtrim (text);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private String debugText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
int ptr = 1;
|
||||
int lastPtr;
|
||||
|
||||
while (ptr < buffer.length)
|
||||
{
|
||||
int nextAddress = getShort (buffer, ptr);
|
||||
if (nextAddress == 0)
|
||||
break;
|
||||
|
||||
int lineNumber = getShort (buffer, ptr + 2);
|
||||
lastPtr = ptr;
|
||||
|
||||
ptr += 4;
|
||||
|
||||
int val;
|
||||
while ((val = buffer[ptr++]) != 0)
|
||||
{
|
||||
ptr += switch (val)
|
||||
{
|
||||
case 0x0C, 0x0E, 0x1C -> 2; // 2 byte numeric
|
||||
case 0x1D -> 4; // 4 byte single precision
|
||||
case 0x1F -> 8; // 8 byte double precision
|
||||
case 0x0F, 0xFF -> 1; // 1 byte numeric, function table entry
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
text.append (String.format (" %d %s%n", lineNumber,
|
||||
HexFormatter.getHexString (buffer, lastPtr + 4, ptr - lastPtr - 4)));
|
||||
}
|
||||
|
||||
return Utility.rtrim (text);
|
||||
}
|
||||
}
|
|
@ -26,7 +26,10 @@ public class CPMTextFile extends TextFile
|
|||
{
|
||||
String line = getLine (ptr);
|
||||
text.append (line + "\n");
|
||||
ptr += line.length () + 2;
|
||||
ptr += line.length () + 1;
|
||||
if (ptr < buffer.length && buffer[ptr - 1] == 0x0D && buffer[ptr] == 0x0A)
|
||||
++ptr;
|
||||
|
||||
while (ptr < buffer.length && buffer[ptr] == 0)
|
||||
++ptr;
|
||||
}
|
||||
|
@ -43,8 +46,8 @@ public class CPMTextFile extends TextFile
|
|||
{
|
||||
StringBuilder line = new StringBuilder ();
|
||||
|
||||
int max = buffer.length - 1;
|
||||
while (ptr < max && buffer[ptr] != 0x0D && buffer[ptr + 1] != 0x0A)
|
||||
// int max = buffer.length - 1;
|
||||
while (ptr < buffer.length && buffer[ptr] != 0x0D && buffer[ptr] != 0x0A)
|
||||
line.append ((char) (buffer[ptr++] & 0x7F));
|
||||
|
||||
return line.toString ();
|
||||
|
|
|
@ -18,6 +18,7 @@ public class DefaultAppleFile extends AbstractFile
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
|
||||
this.text = "Name : " + name + "\n\n" + text;
|
||||
}
|
||||
|
||||
|
@ -35,8 +36,10 @@ public class DefaultAppleFile extends AbstractFile
|
|||
{
|
||||
if (text != null)
|
||||
return text;
|
||||
|
||||
if (buffer == null)
|
||||
return "Invalid file : " + name;
|
||||
|
||||
return super.getText ();
|
||||
}
|
||||
}
|
|
@ -44,22 +44,22 @@ public class DosMasterFile extends AbstractFile
|
|||
System.out.print ("\nFirst Block : ");
|
||||
for (int i = 0; i < 16; i += 2)
|
||||
{
|
||||
System.out.printf ("%04X ", Utility.unsignedShort (buffer, 0x40 + i));
|
||||
System.out.printf ("%04X ", Utility.getShort (buffer, 0x40 + i));
|
||||
if (i % 4 == 2)
|
||||
System.out.print (": ");
|
||||
}
|
||||
|
||||
System.out.print ("\nLast Block : ");
|
||||
for (int i = 0; i < 8; i += 2)
|
||||
System.out.printf ("%04X : ", Utility.unsignedShort (buffer, 0x50 + i));
|
||||
System.out.printf ("%04X : ", Utility.getShort (buffer, 0x50 + i));
|
||||
|
||||
System.out.print ("\nImage Size : ");
|
||||
for (int i = 0; i < 8; i += 2)
|
||||
System.out.printf ("%04X : ", Utility.unsignedShort (buffer, 0x58 + i));
|
||||
System.out.printf ("%04X : ", Utility.getShort (buffer, 0x58 + i));
|
||||
|
||||
System.out.print ("\nAddress : ");
|
||||
for (int i = 0; i < 8; i += 2)
|
||||
System.out.printf ("%04X : ", Utility.unsignedShort (buffer, 0x60 + i));
|
||||
System.out.printf ("%04X : ", Utility.getShort (buffer, 0x60 + i));
|
||||
|
||||
System.out.println ();
|
||||
System.out.println ();
|
||||
|
@ -75,12 +75,12 @@ public class DosMasterFile extends AbstractFile
|
|||
|
||||
int slot = (slotDrive & 0x70) >>> 4;
|
||||
int drive = ((slotDrive & 0x80) >>> 7) + 1;
|
||||
int firstBlock = Utility.unsignedShort (buffer, 0x40 + i * 2); // of first volume
|
||||
int firstBlock = Utility.getShort (buffer, 0x40 + i * 2); // of first volume
|
||||
|
||||
int skip = i / 2 * 2; // 0, 0, 2, 2, 4, 4, 6, 6 - same for both drives
|
||||
|
||||
int lastBlock = Utility.unsignedShort (buffer, 0x50 + skip); // of last volume
|
||||
int volSize = Utility.unsignedShort (buffer, 0x58 + skip);
|
||||
int lastBlock = Utility.getShort (buffer, 0x50 + skip); // of last volume
|
||||
int volSize = Utility.getShort (buffer, 0x58 + skip);
|
||||
|
||||
int originalFirstBlock = firstBlock;
|
||||
if (firstBlock > lastBlock) // WTF?
|
||||
|
@ -176,9 +176,9 @@ public class DosMasterFile extends AbstractFile
|
|||
text.append (String.format ("Slot %d, Drive %d has", s / 16, dr + 1));
|
||||
|
||||
int ptr = v0 + 2 * d0 + 2 * dr;
|
||||
int st = Utility.unsignedShort (buffer, ptr); // start block of first volume
|
||||
int v = Utility.unsignedShort (buffer, size + d0); // end block of last volume
|
||||
int sz = Utility.unsignedShort (buffer, vsiz + d0); // blocks per volume
|
||||
int st = Utility.getShort (buffer, ptr); // start block of first volume
|
||||
int v = Utility.getShort (buffer, size + d0); // end block of last volume
|
||||
int sz = Utility.getShort (buffer, vsiz + d0); // blocks per volume
|
||||
|
||||
if (st > v)
|
||||
st -= 16 * 4096;
|
||||
|
|
|
@ -84,7 +84,7 @@ public class ExoBuffer
|
|||
return false;
|
||||
}
|
||||
|
||||
int address = Utility.unsignedShort (buffer, buffer.length - 2);
|
||||
int address = Utility.getShort (buffer, buffer.length - 2);
|
||||
|
||||
if (address != 0x6000 && address != 0x8000 && address != 0xA000)
|
||||
{
|
||||
|
|
|
@ -28,11 +28,11 @@ public class FileTypeDescriptorTable extends AbstractFile
|
|||
|
||||
versionMajor = buffer[0] & 0xFF;
|
||||
versionMinor = buffer[1] & 0xFF;
|
||||
flags = Utility.unsignedShort (buffer, 2);
|
||||
numEntries = Utility.unsignedShort (buffer, 4);
|
||||
spareWord = Utility.unsignedShort (buffer, 6);
|
||||
indexRecordSize = Utility.unsignedShort (buffer, 8);
|
||||
offsetToIdx = Utility.unsignedShort (buffer, 10);
|
||||
flags = Utility.getShort (buffer, 2);
|
||||
numEntries = Utility.getShort (buffer, 4);
|
||||
spareWord = Utility.getShort (buffer, 6);
|
||||
indexRecordSize = Utility.getShort (buffer, 8);
|
||||
offsetToIdx = Utility.getShort (buffer, 10);
|
||||
|
||||
int ptr = offsetToIdx;
|
||||
for (int i = 0; i < numEntries; i++)
|
||||
|
@ -80,10 +80,10 @@ public class FileTypeDescriptorTable extends AbstractFile
|
|||
|
||||
public IndexRecord (byte[] buffer, int offset)
|
||||
{
|
||||
fileType = Utility.unsignedShort (buffer, offset);
|
||||
auxType = Utility.unsignedLong (buffer, offset + 2);
|
||||
flags = Utility.unsignedShort (buffer, offset + 6);
|
||||
this.offset = Utility.unsignedShort (buffer, offset + 8);
|
||||
fileType = Utility.getShort (buffer, offset);
|
||||
auxType = Utility.getLong (buffer, offset + 2);
|
||||
flags = Utility.getShort (buffer, offset + 6);
|
||||
this.offset = Utility.getShort (buffer, offset + 8);
|
||||
string = HexFormatter.getPascalString (buffer, this.offset);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,98 +18,101 @@ public abstract class HiResImage extends AbstractFile
|
|||
{
|
||||
static final String[] auxTypes =
|
||||
{ "Paintworks Packed SHR Image", "Packed Super Hi-Res Image",
|
||||
"Super Hi-Res Image (Apple Preferred Format)", "Packed QuickDraw II PICT File",
|
||||
"Packed Super Hi-Res 3200 color image" };
|
||||
"Super Hi-Res Image (Apple Preferred Format)", "Packed QuickDraw II PICT File",
|
||||
"Packed Super Hi-Res 3200 color image", "DreamGraphix" };
|
||||
|
||||
static final int COLOR_TABLE_SIZE = 32;
|
||||
static final int COLOR_TABLE_OFFSET_AUX_0 = 32_256;
|
||||
static final int COLOR_TABLE_OFFSET_AUX_2 = 32_000;
|
||||
public static final int FADDEN_AUX = 0x8066;
|
||||
|
||||
private byte[] fourBuf = new byte[4];
|
||||
private ColorTable defaultColorTable320 = new ColorTable (0, 0x00);
|
||||
private ColorTable defaultColorTable640 = new ColorTable (0, 0x80);
|
||||
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
// File Type Aux Name Description
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
// $06 BIN isGif() OriginalHiResImage
|
||||
// $06 BIN isPng() OriginalHiResImage
|
||||
// $06 BIN .BMP isBmp() OriginalHiResImage
|
||||
// $06 BIN .AUX DoubleHiResImage
|
||||
// $06 BIN .PAC DoubleHiResImage
|
||||
// $06 BIN .A2FC DoubleHiResImage
|
||||
// $06 BIN $2000 eof $4000 DoubleHiResImage
|
||||
// $06 BIN $1FFF eof $1FF8/$1FFF/$2000/$4000 OriginalHiResImage
|
||||
// $06 BIN $2000 eof $1FF8/$1FFF/$2000/$4000 OriginalHiResImage
|
||||
// $06 BIN $4000 eof $1FF8/$1FFF/$2000/$4000 OriginalHiResImage (?)
|
||||
// $06 BIN $4000 eof $4000 DoubleHiResImage (?)
|
||||
// $06 BIN .3200 SHRPictureFile2
|
||||
// $06 BIN .3201 SHRPictureFile2 packed
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
// $08 FOT <$4000 Apple II Graphics File OriginalHiResImage
|
||||
// $08 FOT $4000 Packed Hi-Res file ???
|
||||
// $08 FOT $4001 Packed Double Hi-Res file ???
|
||||
// $08 FOT $8066 Fadden Hi-res FaddenHiResImage
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
// * $C0 PNT $0000 Paintworks Packed Super Hi-Res SHRPictureFile2
|
||||
// * $C0 PNT $0001 Packed IIGS Super Hi-Res Image SHRPictureFile2
|
||||
// * $C0 PNT $0002 IIGS Super Hi-Res Picture File (APF) SHRPictureFile1
|
||||
// $C0 PNT $0003 Packed IIGS QuickDraw II PICT File SHRPictureFile2 *
|
||||
// * $C0 PNT $0004 Packed Super Hi-Res 3200 (Brooks) SHRPictureFile2 .3201
|
||||
// $C0 PNT $1000
|
||||
// $C0 PNT $8000 Drawplus? Paintworks Gold?
|
||||
// $C0 PNT $8001 GTv background picture
|
||||
// $C0 PNT $8005 DreamGraphix document
|
||||
// $C0 PNT $8006 GIF
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
// * $C1 PIC $0000 IIGS Super Hi-Res Image SHRPictureFile2
|
||||
// $C1 PIC $0001 IIGS QuickDraw II PICT File SHRPictureFile2 *
|
||||
// * $C1 PIC $0002 Super Hi-Res 3200 (Brooks) SHRPictureFile2 .3200
|
||||
// $C1 PIC $2000 = $C1/0000
|
||||
// $C1 PIC $4100 = $C1/0000
|
||||
// $C1 PIC $4950 = $C1/0000
|
||||
// $C1 PIC $8001 Allison raw image
|
||||
// $C1 PIC $8002 Thunderscan
|
||||
// $C1 PIC $8003 DreamGraphix
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
// $C2 ANI Paintworks animation
|
||||
// $C3 PAL Paintworks palette
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
// File Type Aux Name Description
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
// $06 BIN isGif() OriginalHiResImage
|
||||
// $06 BIN isPng() OriginalHiResImage
|
||||
// $06 BIN .BMP isBmp() OriginalHiResImage
|
||||
// $06 BIN .AUX DoubleHiResImage
|
||||
// $06 BIN .PAC DoubleHiResImage
|
||||
// $06 BIN .A2FC DoubleHiResImage
|
||||
// $06 BIN $2000 eof $4000 DoubleHiResImage
|
||||
// $06 BIN $1FFF eof $1FF8/$1FFF/$2000/$4000 OriginalHiResImage
|
||||
// $06 BIN $2000 eof $1FF8/$1FFF/$2000/$4000 OriginalHiResImage
|
||||
// $06 BIN $4000 eof $1FF8/$1FFF/$2000/$4000 OriginalHiResImage (?)
|
||||
// $06 BIN $4000 eof $4000 DoubleHiResImage (?)
|
||||
// $06 BIN .3200 SHRPictureFile2
|
||||
// $06 BIN .3201 SHRPictureFile2 packed
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
// $08 FOT <$4000 Apple II Graphics File OriginalHiResImage
|
||||
// $08 FOT $4000 Packed Hi-Res file ???
|
||||
// $08 FOT $4001 Packed Double Hi-Res file ???
|
||||
// $08 FOT $8066 Fadden Hi-res FaddenHiResImage
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
// * $C0 PNT $0000 Paintworks Packed Super Hi-Res SHRPictureFile2
|
||||
// * $C0 PNT $0001 Packed IIGS Super Hi-Res Image SHRPictureFile2
|
||||
// * $C0 PNT $0002 IIGS Super Hi-Res Picture File (APF) SHRPictureFile1
|
||||
// $C0 PNT $0003 Packed IIGS QuickDraw II PICT File SHRPictureFile2 *
|
||||
// * $C0 PNT $0004 Packed Super Hi-Res 3200 (Brooks) SHRPictureFile2 .3201
|
||||
// $C0 PNT $1000
|
||||
// $C0 PNT $8000 Drawplus? Paintworks Gold?
|
||||
// $C0 PNT $8001 GTv background picture
|
||||
// $C0 PNT $8005 DreamGraphix document SHRPictureFile2
|
||||
// $C0 PNT $8006 GIF
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
// * $C1 PIC $0000 IIGS Super Hi-Res Image SHRPictureFile2
|
||||
// $C1 PIC $0001 IIGS QuickDraw II PICT File SHRPictureFile2 *
|
||||
// * $C1 PIC $0002 Super Hi-Res 3200 (Brooks) SHRPictureFile2 .3200
|
||||
// $C1 PIC $2000 = $C1/0000
|
||||
// $C1 PIC $4100 = $C1/0000
|
||||
// $C1 PIC $4950 = $C1/0000
|
||||
// $C1 PIC $8001 Allison raw image
|
||||
// $C1 PIC $8002 Thunderscan
|
||||
// $C1 PIC $8003 DreamGraphix
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
// $C2 ANI Paintworks animation
|
||||
// $C3 PAL Paintworks palette
|
||||
// ---- ---- ------ -------------------------------------- ------------------------
|
||||
|
||||
// packed unpacked
|
||||
// $06.3200 1
|
||||
// $06.3201 .
|
||||
// $08 0000 .
|
||||
// $08 4000 .
|
||||
// $08 4001 .
|
||||
// $08 8066 3
|
||||
// $C0 0000 1
|
||||
// $C0 0001 $C1 0000 2 1
|
||||
// $C0 0002 1,5
|
||||
// $C0 0003 $C1 0001 . .
|
||||
// $C0 0004 $C1 0002 . 1
|
||||
// $C0 1000 .
|
||||
// $C0 8000 .
|
||||
// $C0 8001 .
|
||||
// $C0 8005 .
|
||||
// $C0 8006 .
|
||||
// $C1 0042 4
|
||||
// $C1 0043 4
|
||||
// $C1 2000 .
|
||||
// $C1 4100 1
|
||||
// $C1 4950 .
|
||||
// $C1 8001 .
|
||||
// $C1 8002 .
|
||||
// $C1 8003 .
|
||||
// packed unpacked
|
||||
// $06.3200 1
|
||||
// $06.3201 .
|
||||
// $08 0000 .
|
||||
// $08 4000 .
|
||||
// $08 4001 .
|
||||
// $08 8066 3
|
||||
// $C0 0000 1
|
||||
// $C0 0001 $C1 0000 2 1
|
||||
// $C0 0002 1,5
|
||||
// $C0 0003 $C1 0001 . .
|
||||
// $C0 0004 $C1 0002 . 1
|
||||
// $C0 1000 .
|
||||
// $C0 8000 .
|
||||
// $C0 8001 .
|
||||
// $C0 8005 6
|
||||
// $C0 8006 .
|
||||
// $C1 0042 4
|
||||
// $C1 0043 4
|
||||
// $C1 2000 .
|
||||
// $C1 4100 1
|
||||
// $C1 4950 .
|
||||
// $C1 8001 .
|
||||
// $C1 8002 .
|
||||
// $C1 8003 .
|
||||
|
||||
// 1 Graphics & Animation.2mg
|
||||
// 2 0603 Katie's Farm - Disk 2.po
|
||||
// 3 CompressedSlides.do
|
||||
// 4 System Addons.hdv
|
||||
// 5 gfx.po
|
||||
//
|
||||
// 6 Dream Grafix v1.02.po
|
||||
|
||||
// see also - https://docs.google.com/spreadsheets/d
|
||||
// /1rKR6A_bVniSCtIP_rrv8QLWJdj4h6jEU1jJj0AebWwg/edit#gid=0
|
||||
// . /1rKR6A_bVniSCtIP_rrv8QLWJdj4h6jEU1jJj0AebWwg/edit#gid=0
|
||||
// also - http://lukazi.blogspot.com/2017/03/double-high-resolution-graphics-dhgr.html
|
||||
|
||||
static PaletteFactory paletteFactory = new PaletteFactory ();
|
||||
|
||||
|
@ -297,7 +300,10 @@ public abstract class HiResImage extends AbstractFile
|
|||
break;
|
||||
|
||||
case ProdosConstants.FILE_TYPE_PNT: // 0xC0
|
||||
auxText = auxType > 4 ? "Unknown aux: " + auxType : auxTypes[auxType];
|
||||
if (auxType == 0x8005)
|
||||
auxText = auxTypes[5];
|
||||
else
|
||||
auxText = auxType > 4 ? "Unknown aux: " + auxType : auxTypes[auxType];
|
||||
break;
|
||||
|
||||
case ProdosConstants.FILE_TYPE_PIC: // 0xC1
|
||||
|
@ -495,7 +501,7 @@ public abstract class HiResImage extends AbstractFile
|
|||
int calculateBufferSize (byte[] buffer, int ptr)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
// int ptr = 0;
|
||||
// int ptr = 0;
|
||||
int size = 0;
|
||||
while (ptr < buffer.length)
|
||||
{
|
||||
|
@ -620,15 +626,15 @@ public abstract class HiResImage extends AbstractFile
|
|||
return false;
|
||||
|
||||
String text = new String (buffer, 0, 2);
|
||||
int size = Utility.unsignedLong (buffer, 2);
|
||||
int size = Utility.getLong (buffer, 2);
|
||||
|
||||
if (false)
|
||||
{
|
||||
int empty = Utility.unsignedLong (buffer, 6);
|
||||
int offset = Utility.unsignedLong (buffer, 10);
|
||||
int header = Utility.unsignedLong (buffer, 14);
|
||||
int width = Utility.unsignedLong (buffer, 18);
|
||||
int height = Utility.unsignedLong (buffer, 22);
|
||||
int empty = Utility.getLong (buffer, 6);
|
||||
int offset = Utility.getLong (buffer, 10);
|
||||
int header = Utility.getLong (buffer, 14);
|
||||
int width = Utility.getLong (buffer, 18);
|
||||
int height = Utility.getLong (buffer, 22);
|
||||
|
||||
System.out.println (buffer.length);
|
||||
System.out.println (size);
|
||||
|
@ -800,7 +806,7 @@ public abstract class HiResImage extends AbstractFile
|
|||
public ColorEntry (byte[] data, int offset)
|
||||
// -------------------------------------------------------------------------------//
|
||||
{
|
||||
value = Utility.unsignedShort (data, offset);
|
||||
value = Utility.getShort (data, offset);
|
||||
|
||||
int red = ((value >> 8) & 0x0f) * 17;
|
||||
int green = ((value >> 4) & 0x0f) * 17;
|
||||
|
@ -829,8 +835,8 @@ public abstract class HiResImage extends AbstractFile
|
|||
public DirEntry (byte[] data, int offset)
|
||||
// -------------------------------------------------------------------------------//
|
||||
{
|
||||
numBytes = Utility.unsignedShort (data, offset);
|
||||
mode = Utility.unsignedShort (data, offset + 2);
|
||||
numBytes = Utility.getShort (data, offset);
|
||||
mode = Utility.getShort (data, offset + 2);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------//
|
||||
|
|
|
@ -29,16 +29,16 @@ public class IconFile extends AbstractFile implements ProdosConstants
|
|||
{
|
||||
super (name, buffer);
|
||||
|
||||
iBlkNext = Utility.unsignedLong (buffer, 0);
|
||||
iBlkID = Utility.unsignedShort (buffer, 4);
|
||||
iBlkPath = Utility.unsignedLong (buffer, 6);
|
||||
iBlkNext = Utility.getLong (buffer, 0);
|
||||
iBlkID = Utility.getShort (buffer, 4);
|
||||
iBlkPath = Utility.getLong (buffer, 6);
|
||||
iBlkName = HexFormatter.getHexString (buffer, 10, 16);
|
||||
|
||||
int ptr = 26;
|
||||
|
||||
while (true)
|
||||
{
|
||||
int dataLen = Utility.unsignedShort (buffer, ptr);
|
||||
int dataLen = Utility.getShort (buffer, ptr);
|
||||
if (dataLen == 0 || (dataLen + ptr) > buffer.length)
|
||||
break;
|
||||
|
||||
|
@ -131,7 +131,7 @@ public class IconFile extends AbstractFile implements ProdosConstants
|
|||
public Icon (byte[] fullBuffer, int ptr)
|
||||
// -------------------------------------------------------------------------------//
|
||||
{
|
||||
iDataLen = Utility.unsignedShort (fullBuffer, ptr);
|
||||
iDataLen = Utility.getShort (fullBuffer, ptr);
|
||||
|
||||
buffer = new byte[iDataLen];
|
||||
System.arraycopy (fullBuffer, ptr, buffer, 0, buffer.length);
|
||||
|
@ -142,8 +142,8 @@ public class IconFile extends AbstractFile implements ProdosConstants
|
|||
len = buffer[66] & 0xFF;
|
||||
dataName = new String (buffer, 67, len);
|
||||
|
||||
iDataType = Utility.unsignedShort (buffer, 82);
|
||||
iDataAux = Utility.unsignedShort (buffer, 84);
|
||||
iDataType = Utility.getShort (buffer, 82);
|
||||
iDataAux = Utility.getShort (buffer, 84);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
|
@ -200,10 +200,10 @@ public class IconFile extends AbstractFile implements ProdosConstants
|
|||
public Image (byte[] buffer, int ptr) throws InvalidImageException
|
||||
// -------------------------------------------------------------------------------//
|
||||
{
|
||||
iconType = Utility.unsignedShort (buffer, ptr);
|
||||
iconSize = Utility.unsignedShort (buffer, ptr + 2);
|
||||
iconHeight = Utility.unsignedShort (buffer, ptr + 4);
|
||||
iconWidth = Utility.unsignedShort (buffer, ptr + 6);
|
||||
iconType = Utility.getShort (buffer, ptr);
|
||||
iconSize = Utility.getShort (buffer, ptr + 2);
|
||||
iconHeight = Utility.getShort (buffer, ptr + 4);
|
||||
iconWidth = Utility.getShort (buffer, ptr + 6);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
|
|
|
@ -70,6 +70,8 @@ public class OriginalHiResImage extends HiResImage
|
|||
for (int ptr = base; ptr < max; ptr++)
|
||||
{
|
||||
int value = buffer[ptr] & 0x7F;
|
||||
if ((buffer[ptr] & 0x80) != 0)
|
||||
System.out.printf ("bit shift pixel found in %s%n", name);
|
||||
for (int px = 0; px < 7; px++)
|
||||
{
|
||||
int val = (value >> px) & 0x01;
|
||||
|
|
|
@ -22,13 +22,13 @@ public class PascalArea extends AbstractFile
|
|||
{
|
||||
super (name, buffer);
|
||||
|
||||
size = Utility.unsignedShort (buffer, 0);
|
||||
volumes = Utility.unsignedShort (buffer, 2);
|
||||
size = Utility.getShort (buffer, 0);
|
||||
volumes = Utility.getShort (buffer, 2);
|
||||
ppmName = HexFormatter.getPascalString (buffer, 4);
|
||||
start = Utility.unsignedShort (buffer, 8);
|
||||
length = Utility.unsignedShort (buffer, 11);
|
||||
start = Utility.getShort (buffer, 8);
|
||||
length = Utility.getShort (buffer, 11);
|
||||
defaultUnit = buffer[13] & 0xFF;
|
||||
oldDriver = Utility.unsignedShort (buffer, 14);
|
||||
oldDriver = Utility.getShort (buffer, 14);
|
||||
// writeProtected = buffer[12] != 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ public class PascalCode extends AbstractFile
|
|||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
String codeName = HexFormatter.getString (buffer, 0x40 + i * 8, 8).trim ();
|
||||
int size = Utility.intValue (buffer[i * 4 + 2], buffer[i * 4 + 3]);
|
||||
int size = Utility.getShort (buffer, i * 4 + 2);
|
||||
if (codeName.length () == 0 && size > 0)
|
||||
codeName = "<NULL" + ++nonameCounter + ">";
|
||||
if (size > 0)
|
||||
|
|
|
@ -79,10 +79,8 @@ public class PascalCodeStatement implements PascalConstants
|
|||
int min = ptr + padding + 7;
|
||||
int max = min + (p2 - p1) * 2;
|
||||
for (int i = min; i <= max; i += 2)
|
||||
{
|
||||
jumps.add (
|
||||
new Jump (i, i - Utility.intValue (buffer[i], buffer[i + 1]), v++));
|
||||
}
|
||||
jumps.add (new Jump (i, i - Utility.getShort (buffer, i), v++));
|
||||
|
||||
break;
|
||||
|
||||
// UB, <block> - word aligned
|
||||
|
|
|
@ -36,7 +36,7 @@ public class PascalProcedure
|
|||
this.buffer = buffer;
|
||||
this.slot = slot;
|
||||
int p = buffer.length - 2 - slot * 2;
|
||||
offset = Utility.intValue (buffer[p], buffer[p + 1]);
|
||||
offset = Utility.getShort (buffer, p);
|
||||
procOffset = p - offset;
|
||||
valid = procOffset > 0;
|
||||
|
||||
|
@ -44,10 +44,10 @@ public class PascalProcedure
|
|||
{
|
||||
procedureNo = buffer[procOffset] & 0xFF;
|
||||
procLevel = buffer[procOffset + 1] & 0xFF;
|
||||
codeStart = Utility.intValue (buffer[procOffset - 2], buffer[procOffset - 1]);
|
||||
codeEnd = Utility.intValue (buffer[procOffset - 4], buffer[procOffset - 3]);
|
||||
parmSize = Utility.intValue (buffer[procOffset - 6], buffer[procOffset - 5]);
|
||||
dataSize = Utility.intValue (buffer[procOffset - 8], buffer[procOffset - 7]);
|
||||
codeStart = Utility.getShort (buffer, procOffset - 2);
|
||||
codeEnd = Utility.getShort (buffer, procOffset - 4);
|
||||
parmSize = Utility.getShort (buffer, procOffset - 6);
|
||||
dataSize = Utility.getShort (buffer, procOffset - 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,14 +43,12 @@ public class PascalSegment extends AbstractFile implements PascalConstants
|
|||
// this.blockOffset = blockOffset;
|
||||
// this.relocator = relocator;
|
||||
|
||||
this.blockNo = Utility.intValue (fullBuffer[seq * 4], fullBuffer[seq * 4 + 1]);
|
||||
this.size = Utility.intValue (fullBuffer[seq * 4 + 2], fullBuffer[seq * 4 + 3]);
|
||||
this.blockNo = Utility.getShort (fullBuffer, seq * 4);
|
||||
this.size = Utility.getShort (fullBuffer, seq * 4 + 2);
|
||||
|
||||
segKind =
|
||||
Utility.intValue (fullBuffer[0xC0 + seq * 2], fullBuffer[0xC0 + seq * 2 + 1]);
|
||||
segKind = Utility.getShort (fullBuffer, 0xC0 + seq * 2);
|
||||
|
||||
textAddress =
|
||||
Utility.intValue (fullBuffer[0xE0 + seq * 2], fullBuffer[0xE0 + seq * 2 + 1]);
|
||||
textAddress = Utility.getShort (fullBuffer, 0xE0 + seq * 2);
|
||||
|
||||
// segment 1 is the main segment, 2-6 are used by the system, and 7
|
||||
// onwards is for the program
|
||||
|
@ -65,10 +63,8 @@ public class PascalSegment extends AbstractFile implements PascalConstants
|
|||
|
||||
version = (flags & 0xD0) >> 5;
|
||||
|
||||
intrinsSegs1 =
|
||||
Utility.intValue (fullBuffer[0x120 + seq * 4], fullBuffer[0x120 + seq * 4 + 1]);
|
||||
intrinsSegs2 = Utility.intValue (fullBuffer[0x120 + seq * 4 + 2],
|
||||
fullBuffer[0x120 + seq * 4 + 3]);
|
||||
intrinsSegs1 = Utility.getShort (fullBuffer, 0x120 + seq * 4);
|
||||
intrinsSegs2 = Utility.getShort (fullBuffer, 0x120 + seq * 4 + 2);
|
||||
|
||||
int offset = blockNo * 512;
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ package com.bytezone.diskbrowser.applefile;
|
|||
public class PascalText extends TextFile
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final static int PAGE_SIZE = 1024;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public PascalText (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -16,26 +18,34 @@ public class PascalText extends TextFile
|
|||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
// Text files are broken up into 1024-byte pages.
|
||||
// [DLE] [indent] [text] [CR] ... [nulls]
|
||||
|
||||
StringBuilder text = new StringBuilder (getHeader ());
|
||||
|
||||
int ptr = 0x400;
|
||||
int ptr = PAGE_SIZE; // skip text editor header
|
||||
|
||||
while (ptr < buffer.length)
|
||||
{
|
||||
if (buffer[ptr] == 0x00)
|
||||
if (buffer[ptr] == 0x00) // padding to page boundary
|
||||
{
|
||||
++ptr;
|
||||
ptr = (ptr / PAGE_SIZE + 1) * PAGE_SIZE; // skip to next page
|
||||
continue;
|
||||
}
|
||||
if (buffer[ptr] == 0x10)
|
||||
|
||||
if (buffer[ptr] == 0x10) // Data Link Escape code
|
||||
{
|
||||
int tab = buffer[ptr + 1] - 0x20;
|
||||
int tab = (buffer[ptr + 1] & 0xFF) - 32; // indent amaount
|
||||
while (tab-- > 0)
|
||||
text.append (" ");
|
||||
ptr += 2;
|
||||
}
|
||||
String line = getLine (ptr);
|
||||
text.append (line + "\n");
|
||||
ptr += line.length () + 1;
|
||||
|
||||
while (buffer[ptr] != 0x0D)
|
||||
text.append ((char) buffer[ptr++]);
|
||||
|
||||
text.append ("\n");
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (text.length () > 0)
|
||||
|
@ -43,14 +53,4 @@ public class PascalText extends TextFile
|
|||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private String getLine (int ptr)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder line = new StringBuilder ();
|
||||
while (buffer[ptr] != 0x0D)
|
||||
line.append ((char) buffer[ptr++]);
|
||||
return line.toString ();
|
||||
}
|
||||
}
|
|
@ -1,19 +1,28 @@
|
|||
package com.bytezone.diskbrowser.prodos;
|
||||
package com.bytezone.diskbrowser.applefile;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
||||
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
||||
import com.bytezone.diskbrowser.prodos.DirectoryHeader;
|
||||
import com.bytezone.diskbrowser.prodos.ProdosConstants;
|
||||
import com.bytezone.diskbrowser.prodos.ProdosDisk;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||
public class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static Locale US = Locale.US; // to force 3 character months
|
||||
static final DateTimeFormatter df = DateTimeFormatter.ofPattern ("d-LLL-yy", US);
|
||||
static final DateTimeFormatter tf = DateTimeFormatter.ofPattern ("H:mm");
|
||||
static final String UNDERLINE =
|
||||
"----------------------------------------------------\n";
|
||||
|
||||
private static final String NO_DATE = "<NO DATE>";
|
||||
private static final String newLine = String.format ("%n");
|
||||
private static final String newLine2 = newLine + newLine;
|
||||
|
||||
private final ProdosDisk parentFD;
|
||||
private final int totalBlocks;
|
||||
|
@ -21,8 +30,8 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
|
|||
private final int usedBlocks;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
ProdosDirectory (FormattedDisk parent, String name, byte[] buffer, int totalBlocks,
|
||||
int freeBlocks, int usedBlocks)
|
||||
public ProdosDirectory (FormattedDisk parent, String name, byte[] buffer,
|
||||
int totalBlocks, int freeBlocks, int usedBlocks)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (name, buffer);
|
||||
|
@ -38,8 +47,38 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
|
|||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuffer text = new StringBuffer ();
|
||||
text.append ("File : " + parentFD.getDisplayPath () + newLine2);
|
||||
if (showDebugText)
|
||||
return getDebugText ();
|
||||
else
|
||||
return getDirectoryText ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private String getDebugText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
List<DirectoryHeader> directoryHeaders = parentFD.getDirectoryHeaders ();
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
for (DirectoryHeader directoryHeader : directoryHeaders)
|
||||
{
|
||||
text.append (UNDERLINE);
|
||||
text.append (directoryHeader.getText ());
|
||||
text.append ("\n");
|
||||
text.append (UNDERLINE);
|
||||
directoryHeader.listFileEntries (text);
|
||||
}
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private String getDirectoryText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
text.append ("File : " + parentFD.getDisplayPath () + "\n\n");
|
||||
for (int i = 0; i < buffer.length; i += ENTRY_SIZE)
|
||||
{
|
||||
int storageType = (buffer[i] & 0xF0) >> 4;
|
||||
|
@ -49,16 +88,15 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
|
|||
int nameLength = buffer[i] & 0x0F;
|
||||
String filename = HexFormatter.getString (buffer, i + 1, nameLength);
|
||||
String subType = "";
|
||||
String locked;
|
||||
|
||||
switch (storageType)
|
||||
{
|
||||
case VOLUME_HEADER:
|
||||
case SUBDIRECTORY_HEADER:
|
||||
String root = storageType == VOLUME_HEADER ? "/" : "";
|
||||
text.append (root + filename + newLine2);
|
||||
text.append (root + filename + "\n\n");
|
||||
text.append (" NAME TYPE BLOCKS "
|
||||
+ "MODIFIED CREATED ENDFILE SUBTYPE" + newLine2);
|
||||
+ "MODIFIED CREATED ENDFILE SUBTYPE" + "\n\n");
|
||||
break;
|
||||
|
||||
case FREE:
|
||||
|
@ -69,27 +107,27 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
|
|||
case GSOS_EXTENDED_FILE:
|
||||
case SUBDIRECTORY:
|
||||
int type = buffer[i + 16] & 0xFF;
|
||||
int blocks = Utility.intValue (buffer[i + 19], buffer[i + 20]);
|
||||
int blocks = Utility.getShort (buffer, i + 19);
|
||||
|
||||
LocalDateTime createdDate = Utility.getAppleDate (buffer, i + 24);
|
||||
LocalDateTime modifiedDate = Utility.getAppleDate (buffer, i + 33);
|
||||
|
||||
String dateC = createdDate == null ? NO_DATE
|
||||
: createdDate.format (ProdosDisk.df).toUpperCase ();
|
||||
String dateM = modifiedDate == null ? NO_DATE
|
||||
: modifiedDate.format (ProdosDisk.df).toUpperCase ();
|
||||
String dateC =
|
||||
createdDate == null ? NO_DATE : createdDate.format (df).toUpperCase ();
|
||||
String dateM =
|
||||
modifiedDate == null ? NO_DATE : modifiedDate.format (df).toUpperCase ();
|
||||
|
||||
String timeC = createdDate == null ? "" : createdDate.format (ProdosDisk.tf);
|
||||
String timeM = modifiedDate == null ? "" : modifiedDate.format (ProdosDisk.tf);
|
||||
String timeC = createdDate == null ? "" : createdDate.format (tf);
|
||||
String timeM = modifiedDate == null ? "" : modifiedDate.format (tf);
|
||||
|
||||
int eof = Utility.intValue (buffer[i + 21], buffer[i + 22], buffer[i + 23]);
|
||||
int fileType = buffer[i + 16] & 0xFF;
|
||||
locked = (buffer[i + 30] & 0xE0) == 0xE0 ? " " : "*";
|
||||
String locked = (buffer[i + 30] & 0xE0) == 0xE0 ? " " : "*";
|
||||
int aux = Utility.getShort (buffer, i + 31);
|
||||
|
||||
switch (fileType)
|
||||
{
|
||||
case FILE_TYPE_TEXT:
|
||||
int aux = Utility.intValue (buffer[i + 31], buffer[i + 32]);
|
||||
subType = String.format ("R=%5d", aux);
|
||||
break;
|
||||
|
||||
|
@ -97,32 +135,35 @@ class ProdosDirectory extends AbstractFile implements ProdosConstants
|
|||
case FILE_TYPE_PNT:
|
||||
case FILE_TYPE_PIC:
|
||||
case FILE_TYPE_FOT:
|
||||
aux = Utility.intValue (buffer[i + 31], buffer[i + 32]);
|
||||
subType = String.format ("A=$%4X", aux);
|
||||
break;
|
||||
|
||||
case FILE_TYPE_AWP:
|
||||
aux = Utility.intValue (buffer[i + 32], buffer[i + 31]); // backwards!
|
||||
if (aux != 0)
|
||||
filename = convert (filename, aux);
|
||||
int flags = Utility.intValue (buffer[i + 32], buffer[i + 31]); // aux backwards!
|
||||
if (flags != 0)
|
||||
filename = convert (filename, flags);
|
||||
break;
|
||||
|
||||
default:
|
||||
subType = "";
|
||||
}
|
||||
|
||||
text.append (String.format ("%s%-15s %3s %5d %9s %5s %9s %5s %8d %7s%n",
|
||||
locked, filename, ProdosConstants.fileTypes[type], blocks, dateM, timeM,
|
||||
dateC, timeC, eof, subType));
|
||||
String forkFlag = storageType == 5 ? "+" : " ";
|
||||
text.append (
|
||||
String.format ("%s%-15s %3s%s %5d %9s %5s %9s %5s %8d %7s %04X%n",
|
||||
locked, filename, ProdosConstants.fileTypes[type], forkFlag, blocks,
|
||||
dateM, timeM, dateC, timeC, eof, subType, aux));
|
||||
break;
|
||||
|
||||
default:
|
||||
text.append (" <Unknown strage type : " + storageType + newLine);
|
||||
text.append (" <Unknown strage type : " + storageType + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
text.append (
|
||||
String.format ("%nBLOCKS FREE:%5d BLOCKS USED:%5d TOTAL BLOCKS:%5d%n",
|
||||
freeBlocks, usedBlocks, totalBlocks));
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
|
@ -72,37 +72,37 @@ public class QuickDrawFont extends CharacterList
|
|||
|
||||
int ptr = nameLength + 1; // start of header record
|
||||
|
||||
headerSize = Utility.unsignedShort (buffer, ptr);
|
||||
headerSize = Utility.getShort (buffer, ptr);
|
||||
fontDefinitionOffset = nameLength + 1 + headerSize * 2;
|
||||
|
||||
fontFamily = Utility.unsignedShort (buffer, ptr + 2);
|
||||
fontStyle = Utility.unsignedShort (buffer, ptr + 4);
|
||||
fontSize = Utility.unsignedShort (buffer, ptr + 6);
|
||||
fontFamily = Utility.getShort (buffer, ptr + 2);
|
||||
fontStyle = Utility.getShort (buffer, ptr + 4);
|
||||
fontSize = Utility.getShort (buffer, ptr + 6);
|
||||
versionMajor = buffer[ptr + 8] & 0xFF;
|
||||
versionMinor = buffer[ptr + 9] & 0xFF;
|
||||
extent = Utility.unsignedShort (buffer, ptr + 10);
|
||||
extent = Utility.getShort (buffer, ptr + 10);
|
||||
|
||||
ptr = fontDefinitionOffset;
|
||||
|
||||
fontType = Utility.unsignedShort (buffer, ptr);
|
||||
firstChar = Utility.unsignedShort (buffer, ptr + 2);
|
||||
lastChar = Utility.unsignedShort (buffer, ptr + 4);
|
||||
widMax = Utility.unsignedShort (buffer, ptr + 6);
|
||||
kernMax = Utility.signedShort (buffer, ptr + 8);
|
||||
nDescent = Utility.signedShort (buffer, ptr + 10);
|
||||
fRectWidth = Utility.unsignedShort (buffer, ptr + 12);
|
||||
fRectHeight = Utility.unsignedShort (buffer, ptr + 14);
|
||||
fontType = Utility.getShort (buffer, ptr);
|
||||
firstChar = Utility.getShort (buffer, ptr + 2);
|
||||
lastChar = Utility.getShort (buffer, ptr + 4);
|
||||
widMax = Utility.getShort (buffer, ptr + 6);
|
||||
kernMax = Utility.getSignedShort (buffer, ptr + 8);
|
||||
nDescent = Utility.getSignedShort (buffer, ptr + 10);
|
||||
fRectWidth = Utility.getShort (buffer, ptr + 12);
|
||||
fRectHeight = Utility.getShort (buffer, ptr + 14);
|
||||
|
||||
owTLoc = Utility.unsignedShort (buffer, ptr + 16);
|
||||
owTLoc = Utility.getShort (buffer, ptr + 16);
|
||||
|
||||
offsetWidthTableOffset = (ptr + 16) + owTLoc * 2;
|
||||
locationTableOffset = offsetWidthTableOffset - (lastChar - firstChar + 3) * 2;
|
||||
bitImageOffset = ptr + 26;
|
||||
|
||||
ascent = Utility.unsignedShort (buffer, ptr + 18);
|
||||
descent = Utility.unsignedShort (buffer, ptr + 20);
|
||||
leading = Utility.unsignedShort (buffer, ptr + 22);
|
||||
rowWords = Utility.unsignedShort (buffer, ptr + 24);
|
||||
ascent = Utility.getShort (buffer, ptr + 18);
|
||||
descent = Utility.getShort (buffer, ptr + 20);
|
||||
leading = Utility.getShort (buffer, ptr + 22);
|
||||
rowWords = Utility.getShort (buffer, ptr + 24);
|
||||
|
||||
totalCharacters = lastChar - firstChar + 2; // includes 'missing' character
|
||||
|
||||
|
@ -151,12 +151,12 @@ public class QuickDrawFont extends CharacterList
|
|||
for (int i = 0, max = totalCharacters + 1; i < max; i++)
|
||||
{
|
||||
// index into the strike
|
||||
int location = Utility.unsignedShort (buffer, locationTableOffset + i * 2);
|
||||
int location = Utility.getShort (buffer, locationTableOffset + i * 2);
|
||||
|
||||
int j = i + 1; // next character
|
||||
if (j < max)
|
||||
{
|
||||
int nextLocation = Utility.unsignedShort (buffer, locationTableOffset + j * 2);
|
||||
int nextLocation = Utility.getShort (buffer, locationTableOffset + j * 2);
|
||||
int pixelWidth = nextLocation - location;
|
||||
|
||||
if (pixelWidth > 0)
|
||||
|
@ -259,9 +259,8 @@ public class QuickDrawFont extends CharacterList
|
|||
if (offset == 255 && width == 255)
|
||||
continue;
|
||||
|
||||
int location = Utility.unsignedShort (buffer, locationTableOffset + i * 2);
|
||||
int nextLocation =
|
||||
Utility.unsignedShort (buffer, locationTableOffset + (i + 1) * 2);
|
||||
int location = Utility.getShort (buffer, locationTableOffset + i * 2);
|
||||
int nextLocation = Utility.getShort (buffer, locationTableOffset + (i + 1) * 2);
|
||||
int pixelWidth = nextLocation - location;
|
||||
|
||||
text.append (String.format (
|
||||
|
|
|
@ -27,7 +27,7 @@ public class SHRPictureFile1 extends HiResImage
|
|||
int ptr = 0;
|
||||
while (ptr < buffer.length)
|
||||
{
|
||||
int len = Utility.unsignedLong (buffer, ptr);
|
||||
int len = Utility.getLong (buffer, ptr);
|
||||
if (len == 0 || len > buffer.length)
|
||||
{
|
||||
System.out.printf ("Block length: %d%n", len);
|
||||
|
@ -141,7 +141,7 @@ public class SHRPictureFile1 extends HiResImage
|
|||
int lo = dirEntry.mode & 0x00FF; // mode bit if hi == 0
|
||||
|
||||
boolean fillMode = (dirEntry.mode & 0x20) != 0;
|
||||
// assert fillMode == false;
|
||||
// assert fillMode == false;
|
||||
|
||||
if (hi != 0)
|
||||
System.out.println ("hi not zero");
|
||||
|
@ -232,7 +232,7 @@ public class SHRPictureFile1 extends HiResImage
|
|||
super (kind, data);
|
||||
|
||||
int ptr = 5 + kind.length ();
|
||||
numColorTables = Utility.unsignedShort (data, ptr);
|
||||
numColorTables = Utility.getShort (data, ptr);
|
||||
|
||||
ptr += 2;
|
||||
colorTables = new ColorTable[numColorTables];
|
||||
|
@ -242,7 +242,8 @@ public class SHRPictureFile1 extends HiResImage
|
|||
if (ptr < data.length - 32)
|
||||
colorTables[i] = new ColorTable (i, data, ptr);
|
||||
else
|
||||
colorTables[i] = new ColorTable (i, 0x00); // default empty table !! not finished
|
||||
colorTables[i] = new ColorTable (i, 0x00); // default empty table !! not
|
||||
// finished
|
||||
ptr += 32;
|
||||
}
|
||||
}
|
||||
|
@ -286,9 +287,9 @@ public class SHRPictureFile1 extends HiResImage
|
|||
super (kind, data);
|
||||
|
||||
int ptr = 5 + kind.length ();
|
||||
masterMode = Utility.unsignedShort (data, ptr);
|
||||
pixelsPerScanLine = Utility.unsignedShort (data, ptr + 2);
|
||||
numColorTables = Utility.unsignedShort (data, ptr + 4);
|
||||
masterMode = Utility.getShort (data, ptr);
|
||||
pixelsPerScanLine = Utility.getShort (data, ptr + 2);
|
||||
numColorTables = Utility.getShort (data, ptr + 4);
|
||||
mode640 = (masterMode & 0x80) != 0;
|
||||
|
||||
ptr += 6;
|
||||
|
@ -299,7 +300,7 @@ public class SHRPictureFile1 extends HiResImage
|
|||
ptr += 32;
|
||||
}
|
||||
|
||||
numScanLines = Utility.unsignedShort (data, ptr);
|
||||
numScanLines = Utility.getShort (data, ptr);
|
||||
ptr += 2;
|
||||
|
||||
scanLineDirectory = new DirEntry[numScanLines];
|
||||
|
@ -332,11 +333,11 @@ public class SHRPictureFile1 extends HiResImage
|
|||
ptr = 0;
|
||||
for (int line = 0; line < numScanLines; line++)
|
||||
{
|
||||
// if (isOddAndEmpty (packedScanLines[line]))
|
||||
// {
|
||||
// System.out.println ("Odd number of bytes in empty buffer in " + name);
|
||||
// break;
|
||||
// }
|
||||
// if (isOddAndEmpty (packedScanLines[line]))
|
||||
// {
|
||||
// System.out.println ("Odd number of bytes in empty buffer in " + name);
|
||||
// break;
|
||||
// }
|
||||
|
||||
int bytesUnpacked = unpack (packedScanLines[line], 0,
|
||||
packedScanLines[line].length, unpackedBuffer, ptr);
|
||||
|
@ -352,16 +353,17 @@ public class SHRPictureFile1 extends HiResImage
|
|||
}
|
||||
|
||||
// -------------------------------------------------------------------------------//
|
||||
// private boolean isOddAndEmpty (byte[] buffer)
|
||||
// // -------------------------------------------------------------------------------//
|
||||
// {
|
||||
// if (buffer.length % 2 == 0)
|
||||
// return false;
|
||||
// for (byte b : buffer)
|
||||
// if (b != 0)
|
||||
// return false;
|
||||
// return true;
|
||||
// }
|
||||
// private boolean isOddAndEmpty (byte[] buffer)
|
||||
// //
|
||||
// -------------------------------------------------------------------------------//
|
||||
// {
|
||||
// if (buffer.length % 2 == 0)
|
||||
// return false;
|
||||
// for (byte b : buffer)
|
||||
// if (b != 0)
|
||||
// return false;
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// -------------------------------------------------------------------------------//
|
||||
@Override
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.awt.image.DataBuffer;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.nufx.LZW3;
|
||||
import com.bytezone.diskbrowser.prodos.ProdosConstants;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
@ -99,10 +100,10 @@ public class SHRPictureFile2 extends HiResImage
|
|||
unpack (buffer, 0, buffer.length, newBuffer, 0);
|
||||
buffer = newBuffer;
|
||||
|
||||
int mode = Utility.unsignedShort (this.buffer, 0);
|
||||
int rect1 = Utility.unsignedLong (this.buffer, 2);
|
||||
int rect2 = Utility.unsignedLong (this.buffer, 6);
|
||||
int version = Utility.unsignedShort (this.buffer, 10); // $8211
|
||||
int mode = Utility.getShort (this.buffer, 0);
|
||||
int rect1 = Utility.getLong (this.buffer, 2);
|
||||
int rect2 = Utility.getLong (this.buffer, 6);
|
||||
int version = Utility.getShort (this.buffer, 10); // $8211
|
||||
|
||||
break;
|
||||
|
||||
|
@ -144,6 +145,36 @@ public class SHRPictureFile2 extends HiResImage
|
|||
|
||||
break;
|
||||
|
||||
case 0x8005:
|
||||
int ptr = buffer.length - 17;
|
||||
|
||||
int imageType = Utility.getShort (buffer, ptr);
|
||||
int imageHeight = Utility.getShort (buffer, ptr + 2);
|
||||
int imageWidth = Utility.getShort (buffer, ptr + 4);
|
||||
|
||||
String id = HexFormatter.getPascalString (buffer, ptr + 6);
|
||||
assert "DreamWorld".equals (id);
|
||||
|
||||
int expectedLen = 32000 + 512;
|
||||
if (imageType == 0) // 256 colours
|
||||
expectedLen += (256 + 512);
|
||||
else // 3200 colours
|
||||
expectedLen += 6400;
|
||||
|
||||
byte[] dstBuffer = new byte[expectedLen + 1024];
|
||||
LZW3 lzw3 = new LZW3 ();
|
||||
int bytes = lzw3.unpack (buffer, dstBuffer, expectedLen);
|
||||
buffer = dstBuffer;
|
||||
|
||||
colorTables = new ColorTable[imageHeight];
|
||||
for (int i = 0; i < colorTables.length; i++)
|
||||
{
|
||||
colorTables[i] = new ColorTable (i, this.buffer, 32000 + i * COLOR_TABLE_SIZE);
|
||||
colorTables[i].reverse ();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
System.out.printf ("%s: PNT unknown aux: %04X%n", name, auxType);
|
||||
failureReason = "unknown PNT aux";
|
||||
|
@ -154,13 +185,13 @@ public class SHRPictureFile2 extends HiResImage
|
|||
private void doAnimation ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
// int len = HexFormatter.unsignedLong (buffer, 0x8000);
|
||||
delay = Utility.unsignedLong (buffer, 0x8004);
|
||||
// int len = HexFormatter.getLong (buffer, 0x8000);
|
||||
delay = Utility.getLong (buffer, 0x8004);
|
||||
if (delay > 60)
|
||||
delay = 10;
|
||||
delay = delay * 1000 / 60;
|
||||
|
||||
// int offset = HexFormatter.unsignedLong (buffer, 0x8008);
|
||||
// int offset = HexFormatter.getLong (buffer, 0x8008);
|
||||
// int blockLen = eof - 0x8008;
|
||||
|
||||
// System.out.printf ("Delay: %,d%n", delay);
|
||||
|
@ -173,7 +204,7 @@ public class SHRPictureFile2 extends HiResImage
|
|||
int start = ptr;
|
||||
while (ptr < buffer.length)
|
||||
{
|
||||
int off = Utility.unsignedShort (buffer, ptr);
|
||||
int off = Utility.getShort (buffer, ptr);
|
||||
|
||||
ptr += 4;
|
||||
if (off == 0)
|
||||
|
@ -299,7 +330,7 @@ public class SHRPictureFile2 extends HiResImage
|
|||
|
||||
while (true)
|
||||
{
|
||||
int offset = Utility.unsignedShort (buffer, ptr);
|
||||
int offset = Utility.getShort (buffer, ptr);
|
||||
if (offset == 0)
|
||||
break;
|
||||
|
||||
|
|
|
@ -1,16 +1,40 @@
|
|||
package com.bytezone.diskbrowser.applefile;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class SegmentDictionary
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final boolean isValid;
|
||||
private int[] codeAddress = new int[16];
|
||||
private int[] codeLength = new int[16];
|
||||
private String[] segName = new String[16];
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public SegmentDictionary (String name, byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
isValid = !name.equals ("SYSTEM.INTERP"); // temporary
|
||||
|
||||
int ptr = 0;
|
||||
for (int seg = 0; seg < 16; seg++)
|
||||
{
|
||||
codeAddress[seg] = Utility.getShort (buffer, ptr);
|
||||
ptr += 2;
|
||||
codeLength[seg] = Utility.getShort (buffer, ptr);
|
||||
ptr += 2;
|
||||
}
|
||||
|
||||
ptr = 64;
|
||||
for (int seg = 0; seg < 16; seg++)
|
||||
{
|
||||
segName[seg] = new String (buffer, ptr, 8);
|
||||
ptr += 8;
|
||||
}
|
||||
|
||||
// for (int seg = 0; seg < 16; seg++)
|
||||
// System.out.printf ("%04X %04X %s%n", codeAddress[seg], codeLength[seg], segName[seg]);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
|
@ -37,6 +37,8 @@ public class SegmentHeader
|
|||
String loadname;
|
||||
String segname;
|
||||
|
||||
boolean debug = false;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public SegmentHeader (byte[] buffer, int offset)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -52,20 +54,20 @@ public class SegmentHeader
|
|||
version = buffer[offset + 15] & 0xFF;
|
||||
|
||||
banksize = Utility.getLong (buffer, offset + 16);
|
||||
kind2 = Utility.getWord (buffer, offset + 20);
|
||||
unused = Utility.getWord (buffer, offset + 22);
|
||||
kind2 = Utility.getShort (buffer, offset + 20);
|
||||
unused = Utility.getShort (buffer, offset + 22);
|
||||
org = Utility.getLong (buffer, offset + 24);
|
||||
align = Utility.getLong (buffer, offset + 28);
|
||||
|
||||
numsex = buffer[offset + 32] & 0xFF;
|
||||
lcbank = buffer[offset + 33] & 0xFF;
|
||||
|
||||
segnum = Utility.getWord (buffer, offset + 34);
|
||||
segnum = Utility.getShort (buffer, offset + 34);
|
||||
|
||||
entry = Utility.getLong (buffer, offset + 36);
|
||||
|
||||
dispname = Utility.getWord (buffer, offset + 40);
|
||||
dispdata = Utility.getWord (buffer, offset + 42);
|
||||
dispname = Utility.getShort (buffer, offset + 40);
|
||||
dispdata = Utility.getShort (buffer, offset + 42);
|
||||
|
||||
decodeKind ();
|
||||
|
||||
|
@ -79,7 +81,8 @@ public class SegmentHeader
|
|||
else
|
||||
segname = "not finished";
|
||||
|
||||
System.out.println (this);
|
||||
if (debug)
|
||||
System.out.println (this);
|
||||
|
||||
int ptr = offset + dispdata;
|
||||
while (true)
|
||||
|
@ -89,25 +92,33 @@ public class SegmentHeader
|
|||
|
||||
if (recType > 0 && recType <= 0xDF)
|
||||
{
|
||||
System.out.printf ("Const: %02X%n", recType);
|
||||
System.out.println (HexFormatter.format (buffer, ptr, recType + 1, ptr));
|
||||
if (debug)
|
||||
{
|
||||
System.out.printf ("Const: %02X%n", recType);
|
||||
System.out.println (HexFormatter.format (buffer, ptr, recType + 1, ptr));
|
||||
}
|
||||
ptr += recType + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
System.out.printf ("%02X ", recType);
|
||||
if (debug)
|
||||
System.out.printf ("%02X ", recType);
|
||||
|
||||
switch (recType)
|
||||
{
|
||||
case 0x00: // END
|
||||
System.out.println ("END");
|
||||
if (debug)
|
||||
System.out.println ("END");
|
||||
break;
|
||||
|
||||
case 0xE0: // ALIGN
|
||||
System.out.printf ("ALIGN:%n");
|
||||
if (debug)
|
||||
System.out.printf ("ALIGN:%n");
|
||||
break;
|
||||
|
||||
case 0xE1: // ORG
|
||||
System.out.printf ("ORG:%n");
|
||||
if (debug)
|
||||
System.out.printf ("ORG:%n");
|
||||
break;
|
||||
|
||||
case 0xE2: // RELOC
|
||||
|
@ -115,8 +126,9 @@ public class SegmentHeader
|
|||
int bitShift = buffer[ptr + 2] & 0xFF;
|
||||
int segmentOffset = Utility.getLong (buffer, ptr + 3);
|
||||
int value = Utility.getLong (buffer, ptr + 7);
|
||||
System.out.printf ("RELOC: %02X %02X %08X %08X%n", bytesRelocated, bitShift,
|
||||
segmentOffset, value);
|
||||
if (debug)
|
||||
System.out.printf ("RELOC: %02X %02X %08X %08X%n", bytesRelocated, bitShift,
|
||||
segmentOffset, value);
|
||||
ptr += 11;
|
||||
continue;
|
||||
|
||||
|
@ -124,102 +136,121 @@ public class SegmentHeader
|
|||
int count1 = buffer[ptr + 1] & 0xFF;
|
||||
int count2 = buffer[ptr + 2] & 0xFF;
|
||||
int operandOffset = Utility.getLong (buffer, ptr + 3);
|
||||
int fileNo = Utility.getWord (buffer, ptr + 7);
|
||||
int segNo = Utility.getWord (buffer, ptr + 9);
|
||||
int fileNo = Utility.getShort (buffer, ptr + 7);
|
||||
int segNo = Utility.getShort (buffer, ptr + 9);
|
||||
int subroutineOffset = Utility.getLong (buffer, ptr + 11);
|
||||
System.out.printf ("INTERSEG: %02X %02X %08X %04X %04X %08X%n", count1, count2,
|
||||
operandOffset, fileNo, segNo, subroutineOffset);
|
||||
if (debug)
|
||||
System.out.printf ("INTERSEG: %02X %02X %08X %04X %04X %08X%n", count1,
|
||||
count2, operandOffset, fileNo, segNo, subroutineOffset);
|
||||
ptr += 15;
|
||||
break;
|
||||
|
||||
case 0xE4: // USING
|
||||
System.out.printf ("USING:%n");
|
||||
if (debug)
|
||||
System.out.printf ("USING:%n");
|
||||
break;
|
||||
|
||||
case 0xE5: // STRONG
|
||||
System.out.printf ("STRONG:%n");
|
||||
if (debug)
|
||||
System.out.printf ("STRONG:%n");
|
||||
break;
|
||||
|
||||
case 0xE6: // GLOBAL
|
||||
System.out.printf ("GLOBAL:%n");
|
||||
if (debug)
|
||||
System.out.printf ("GLOBAL:%n");
|
||||
break;
|
||||
|
||||
case 0xE7: // GEQU
|
||||
System.out.printf ("GEQU:%n");
|
||||
if (debug)
|
||||
System.out.printf ("GEQU:%n");
|
||||
break;
|
||||
|
||||
case 0xE8: // MEM
|
||||
System.out.printf ("MEM:%n");
|
||||
if (debug)
|
||||
System.out.printf ("MEM:%n");
|
||||
break;
|
||||
|
||||
case 0xEB: // EXPR
|
||||
System.out.printf ("EXPR:%n");
|
||||
if (debug)
|
||||
System.out.printf ("EXPR:%n");
|
||||
break;
|
||||
|
||||
case 0xEC: // ZEXPR
|
||||
System.out.printf ("ZEXPR:%n");
|
||||
if (debug)
|
||||
System.out.printf ("ZEXPR:%n");
|
||||
break;
|
||||
|
||||
case 0xED: // BEXPR
|
||||
System.out.printf ("BEXPR:%n");
|
||||
if (debug)
|
||||
System.out.printf ("BEXPR:%n");
|
||||
break;
|
||||
|
||||
case 0xEE: // RELEXPR
|
||||
System.out.printf ("RELEXPR:%n");
|
||||
if (debug)
|
||||
System.out.printf ("RELEXPR:%n");
|
||||
break;
|
||||
|
||||
case 0xEF: // LOCAL
|
||||
System.out.printf ("LOCAL:%n");
|
||||
if (debug)
|
||||
System.out.printf ("LOCAL:%n");
|
||||
break;
|
||||
|
||||
case 0xF0: // EQU
|
||||
String label = HexFormatter.getPascalString (buffer, ptr + 1);
|
||||
System.out.printf ("EQU: %s%n", label);
|
||||
if (debug)
|
||||
System.out.printf ("EQU: %s%n", label);
|
||||
break;
|
||||
|
||||
case 0xF1: // DS
|
||||
System.out.printf ("DS:%n");
|
||||
if (debug)
|
||||
System.out.printf ("DS:%n");
|
||||
break;
|
||||
|
||||
case 0xF2: // LCONST
|
||||
int constLength = Utility.getLong (buffer, ptr + 1);
|
||||
System.out.printf ("Const: %04X%n", constLength);
|
||||
if (debug)
|
||||
System.out.printf ("Const: %04X%n", constLength);
|
||||
ptr += constLength + 5;
|
||||
continue;
|
||||
|
||||
case 0xF3: // LEXPR
|
||||
System.out.printf ("LEXPR:%n");
|
||||
if (debug)
|
||||
System.out.printf ("LEXPR:%n");
|
||||
break;
|
||||
|
||||
case 0xF4: // ENTRY
|
||||
System.out.printf ("ENTRY:%n");
|
||||
if (debug)
|
||||
System.out.printf ("ENTRY:%n");
|
||||
break;
|
||||
|
||||
case 0xF5: // cRELOC
|
||||
int cBytesRelocated = buffer[ptr + 1] & 0xFF;
|
||||
int cBitShift = buffer[ptr + 2] & 0xFF;
|
||||
int cSegmentOffset = Utility.getWord (buffer, ptr + 3);
|
||||
int cValue = Utility.getWord (buffer, ptr + 5);
|
||||
System.out.printf ("cRELOC: %02X %02X %08X %08X%n", cBytesRelocated, cBitShift,
|
||||
cSegmentOffset, cValue);
|
||||
int cSegmentOffset = Utility.getShort (buffer, ptr + 3);
|
||||
int cValue = Utility.getShort (buffer, ptr + 5);
|
||||
if (debug)
|
||||
System.out.printf ("cRELOC: %02X %02X %08X %08X%n", cBytesRelocated,
|
||||
cBitShift, cSegmentOffset, cValue);
|
||||
ptr += 7;
|
||||
continue;
|
||||
|
||||
case 0xF6: // cINTERSEG
|
||||
int cCount1 = buffer[ptr + 1] & 0xFF;
|
||||
int cCount2 = buffer[ptr + 2] & 0xFF;
|
||||
int cOperandOffset = Utility.getWord (buffer, ptr + 3);
|
||||
int cOperandOffset = Utility.getShort (buffer, ptr + 3);
|
||||
int cSegNo = buffer[ptr + 5] & 0xFF;
|
||||
int cSubroutineOffset = Utility.getWord (buffer, ptr + 6);
|
||||
System.out.printf ("cINTERSEG: %02X %02X %04X %02X %04X%n", cCount1, cCount2,
|
||||
cOperandOffset, cSegNo, cSubroutineOffset);
|
||||
int cSubroutineOffset = Utility.getShort (buffer, ptr + 6);
|
||||
if (debug)
|
||||
System.out.printf ("cINTERSEG: %02X %02X %04X %02X %04X%n", cCount1, cCount2,
|
||||
cOperandOffset, cSegNo, cSubroutineOffset);
|
||||
ptr += 8;
|
||||
continue;
|
||||
|
||||
case 0xF7: // SUPER
|
||||
int superLength = Utility.getLong (buffer, ptr + 1);
|
||||
int recordType = buffer[ptr + 5] & 0xFF;
|
||||
System.out.printf ("Super type %02X%n", recordType);
|
||||
if (debug)
|
||||
System.out.printf ("Super type %02X%n", recordType);
|
||||
ptr += superLength + 5;
|
||||
continue;
|
||||
|
||||
|
@ -228,7 +259,8 @@ public class SegmentHeader
|
|||
break;
|
||||
}
|
||||
|
||||
System.out.println ();
|
||||
if (debug)
|
||||
System.out.println ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -258,33 +290,18 @@ public class SegmentHeader
|
|||
kindPrivate = (segAttr & 0x40) != 0;
|
||||
kindStatic = (segAttr & 0x80) == 0;
|
||||
|
||||
switch (segType)
|
||||
kindWhereText = switch (segType)
|
||||
{
|
||||
case 0:
|
||||
kindWhereText = "Code Segment";
|
||||
break;
|
||||
case 1:
|
||||
kindWhereText = "Data Segment";
|
||||
break;
|
||||
case 2:
|
||||
kindWhereText = "Jump Table Segment";
|
||||
break;
|
||||
case 4:
|
||||
kindWhereText = "Pathname Segment";
|
||||
break;
|
||||
case 8:
|
||||
kindWhereText = "Library Dictionary Segment";
|
||||
break;
|
||||
case 0x10:
|
||||
kindWhereText = "Initialization Segment";
|
||||
break;
|
||||
case 0x11:
|
||||
kindWhereText = "Absolute Bank Segment";
|
||||
break;
|
||||
case 0x12:
|
||||
kindWhereText = "Direct Page / Stack Segment";
|
||||
break;
|
||||
}
|
||||
case 0x00 -> "Code Segment";
|
||||
case 0x01 -> "Data Segment";
|
||||
case 0x02 -> "Jump Table Segment";
|
||||
case 0x04 -> "Pathname Segment";
|
||||
case 0x08 -> "Library Dictionary Segment";
|
||||
case 0x10 -> "Initialization Segment";
|
||||
case 0x11 -> "Absolute Bank Segment";
|
||||
case 0x12 -> "Direct Page / Stack Segment";
|
||||
default -> "Unknown";
|
||||
};
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
|
@ -39,7 +39,7 @@ class Shape
|
|||
int row = startRow;
|
||||
int col = startCol;
|
||||
|
||||
offset = Utility.unsignedShort (buffer, index * 2 + 2);
|
||||
offset = Utility.getShort (buffer, index * 2 + 2);
|
||||
|
||||
int ptr = offset;
|
||||
while (ptr < buffer.length)
|
||||
|
|
|
@ -128,7 +128,7 @@ public class ShapeTable extends AbstractFile
|
|||
return false;
|
||||
|
||||
// check index points inside the file
|
||||
int offset = Utility.unsignedShort (buffer, ptr);
|
||||
int offset = Utility.getShort (buffer, ptr);
|
||||
if (offset == 0 || offset >= buffer.length)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -32,6 +32,13 @@ public class SimpleText extends AbstractFile
|
|||
if (ptr < buffer.length && buffer[ptr] == 0x0A)
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (resourceFork != null)
|
||||
{
|
||||
text.append ("\n\nResource Fork\n=============\n");
|
||||
text.append (resourceFork);
|
||||
}
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.bytezone.diskbrowser.applefile;
|
|||
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.ASCII_COLON;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.ASCII_QUOTE;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.unsignedShort;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.getShort;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -30,8 +30,8 @@ public class SourceLine implements ApplesoftConstants
|
|||
this.buffer = buffer;
|
||||
|
||||
linePtr = ptr;
|
||||
linkField = unsignedShort (buffer, ptr);
|
||||
lineNumber = unsignedShort (buffer, ptr + 2);
|
||||
linkField = getShort (buffer, ptr);
|
||||
lineNumber = getShort (buffer, ptr + 2);
|
||||
|
||||
int startPtr = ptr += 4; // skip link field and lineNumber
|
||||
boolean inString = false; // can toggle
|
||||
|
|
|
@ -26,10 +26,10 @@ public class StoredVariables extends AbstractFile
|
|||
int strPtr = buffer.length;
|
||||
|
||||
text.append ("File length : " + HexFormatter.format4 (buffer.length));
|
||||
int totalLength = Utility.intValue (buffer[0], buffer[1]);
|
||||
int totalLength = Utility.getShort (buffer, 0);
|
||||
text.append ("\nTotal length : " + HexFormatter.format4 (totalLength));
|
||||
|
||||
int varLength = Utility.intValue (buffer[2], buffer[3]);
|
||||
int varLength = Utility.getShort (buffer, 2);
|
||||
text.append ("\nVar length : " + HexFormatter.format4 (varLength));
|
||||
text.append ("\n\n");
|
||||
|
||||
|
@ -51,8 +51,8 @@ public class StoredVariables extends AbstractFile
|
|||
}
|
||||
else if (suffix == '%')
|
||||
{
|
||||
intValue = Utility.intValue (buffer[ptr + 3], buffer[ptr + 2]);
|
||||
if ((buffer[ptr + 2] & 0x80) > 0)
|
||||
intValue = Utility.intValue (buffer[ptr + 3], buffer[ptr + 2]); // backwards!
|
||||
if ((buffer[ptr + 2] & 0x80) != 0)
|
||||
intValue -= 65536;
|
||||
text.append (" = " + intValue);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ public class StoredVariables extends AbstractFile
|
|||
{
|
||||
if (hasValue (ptr + 2))
|
||||
{
|
||||
String value = HexFormatter.floatValue (buffer, ptr + 2) + "";
|
||||
String value = Utility.floatValue (buffer, ptr + 2) + "";
|
||||
if (value.endsWith (".0"))
|
||||
text.append (" = " + value.substring (0, value.length () - 2));
|
||||
else
|
||||
|
@ -101,7 +101,7 @@ public class StoredVariables extends AbstractFile
|
|||
suffix = ' ';
|
||||
}
|
||||
|
||||
StringBuffer variableName = new StringBuffer ();
|
||||
StringBuilder variableName = new StringBuilder ();
|
||||
variableName.append (c1);
|
||||
if (c2 > 32)
|
||||
variableName.append (c2);
|
||||
|
@ -116,12 +116,14 @@ public class StoredVariables extends AbstractFile
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ("(");
|
||||
|
||||
for (int i = 0; i < values.length; i++)
|
||||
{
|
||||
text.append (values[i]);
|
||||
if (i < values.length - 1)
|
||||
text.append (',');
|
||||
}
|
||||
|
||||
return text.append (')').toString ();
|
||||
}
|
||||
|
||||
|
@ -133,14 +135,14 @@ public class StoredVariables extends AbstractFile
|
|||
{
|
||||
String variableName = getVariableName (buffer[ptr], buffer[ptr + 1]);
|
||||
text.append ("\n");
|
||||
int offset = Utility.intValue (buffer[ptr + 2], buffer[ptr + 3]);
|
||||
int offset = Utility.getShort (buffer, ptr + 2);
|
||||
int dimensions = buffer[ptr + 4] & 0xFF;
|
||||
int[] dimensionSizes = new int[dimensions];
|
||||
int totalElements = 0;
|
||||
for (int i = 0; i < dimensions; i++)
|
||||
{
|
||||
int p = i * 2 + 5 + ptr;
|
||||
int elements = Utility.intValue (buffer[p + 1], buffer[p]);
|
||||
int elements = Utility.intValue (buffer[p + 1], buffer[p]); // backwards!
|
||||
dimensionSizes[dimensions - i - 1] = elements - 1;
|
||||
if (totalElements == 0)
|
||||
totalElements = elements;
|
||||
|
@ -160,7 +162,7 @@ public class StoredVariables extends AbstractFile
|
|||
text.append (variableName + " " + getDimensionText (values) + " = ");
|
||||
if (elementSize == 2)
|
||||
{
|
||||
int intValue = Utility.intValue (buffer[p + 1], buffer[p]);
|
||||
int intValue = Utility.intValue (buffer[p + 1], buffer[p]); // backwards
|
||||
if ((buffer[p] & 0x80) > 0)
|
||||
intValue -= 65536;
|
||||
text.append (intValue + "\n");
|
||||
|
@ -178,7 +180,7 @@ public class StoredVariables extends AbstractFile
|
|||
else if (elementSize == 5)
|
||||
{
|
||||
if (hasValue (p))
|
||||
text.append (HexFormatter.floatValue (buffer, p));
|
||||
text.append (Utility.floatValue (buffer, p));
|
||||
text.append ("\n");
|
||||
}
|
||||
p += elementSize;
|
||||
|
@ -201,6 +203,7 @@ public class StoredVariables extends AbstractFile
|
|||
for (int i = 0; i < 5; i++)
|
||||
if (buffer[p + i] != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -212,10 +215,10 @@ public class StoredVariables extends AbstractFile
|
|||
StringBuffer text = new StringBuffer ();
|
||||
|
||||
text.append ("File length : " + HexFormatter.format4 (buffer.length));
|
||||
int totalLength = Utility.intValue (buffer[0], buffer[1]);
|
||||
int totalLength = Utility.getShort (buffer, 0);
|
||||
text.append ("\nTotal length : " + HexFormatter.format4 (totalLength));
|
||||
|
||||
int varLength = Utility.intValue (buffer[2], buffer[3]);
|
||||
int varLength = Utility.getShort (buffer, 2);
|
||||
text.append ("\nVar length : " + HexFormatter.format4 (varLength));
|
||||
|
||||
int unknown = buffer[4] & 0xFF;
|
||||
|
@ -232,14 +235,14 @@ public class StoredVariables extends AbstractFile
|
|||
text.append ("\nArrays : \n\n");
|
||||
while (ptr < totalLength + 5)
|
||||
{
|
||||
int offset = Utility.intValue (buffer[ptr + 2], buffer[ptr + 3]);
|
||||
int offset = Utility.getShort (buffer, ptr + 2);
|
||||
int dimensions = buffer[ptr + 4] & 0xFF;
|
||||
int[] dimensionSizes = new int[dimensions];
|
||||
int totalElements = 0;
|
||||
for (int i = 0; i < dimensions; i++)
|
||||
{
|
||||
int p = i * 2 + 5 + ptr;
|
||||
int elements = Utility.intValue (buffer[p + 1], buffer[p]);
|
||||
int elements = Utility.intValue (buffer[p + 1], buffer[p]); // backwards!
|
||||
dimensionSizes[dimensions - i - 1] = elements;
|
||||
if (totalElements == 0)
|
||||
totalElements = elements;
|
||||
|
|
|
@ -12,6 +12,7 @@ import static com.bytezone.diskbrowser.utilities.Utility.ASCII_PERCENT;
|
|||
import static com.bytezone.diskbrowser.utilities.Utility.ASCII_QUOTE;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.ASCII_RIGHT_BRACKET;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.getIndent;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.isControlCharacter;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.isDigit;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.isHighBitSet;
|
||||
import static com.bytezone.diskbrowser.utilities.Utility.isLetter;
|
||||
|
@ -201,7 +202,7 @@ public class SubLine implements ApplesoftConstants
|
|||
private void checkFunction (String var, byte terminator)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
assert terminator == ASCII_LEFT_BRACKET;
|
||||
// assert terminator == ASCII_LEFT_BRACKET;
|
||||
|
||||
if (!functions.contains (var))
|
||||
functions.add (var);
|
||||
|
@ -612,29 +613,6 @@ public class SubLine implements ApplesoftConstants
|
|||
return false;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
// public String getAlignedText (ApplesoftFormatter alignment)
|
||||
// // ---------------------------------------------------------------------------------//
|
||||
// {
|
||||
// StringBuilder line = toStringBuilder (); // get line
|
||||
//
|
||||
// if (alignment.equalsPosition == 0 || is (TOKEN_REM))
|
||||
// return line.toString ();
|
||||
//
|
||||
// int alignEqualsPos = alignment.equalsPosition;
|
||||
// int targetLength = endPosition - equalsPosition;
|
||||
//
|
||||
// // insert spaces before '=' until it lines up with the other assignment lines
|
||||
// while (alignEqualsPos-- > equalsPosition)
|
||||
// line.insert (equalsPosition, ' ');
|
||||
//
|
||||
// if (line.charAt (line.length () - 1) == ':')
|
||||
// while (targetLength++ <= alignment.targetLength)
|
||||
// line.append (" ");
|
||||
//
|
||||
// return line.toString ();
|
||||
// }
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public byte[] getBuffer ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -712,45 +690,45 @@ public class SubLine implements ApplesoftConstants
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
// private StringBuilder toStringBuilder ()
|
||||
// // ---------------------------------------------------------------------------------//
|
||||
// {
|
||||
// StringBuilder line = new StringBuilder ();
|
||||
//
|
||||
// // All sublines end with 0 or : except IF lines that are split into two
|
||||
// int max = startPtr + length - 1;
|
||||
// if (buffer[max] == 0)
|
||||
// --max;
|
||||
//
|
||||
// if (isImpliedGoto () && !ApplesoftBasicProgram.basicPreferences.showThen)
|
||||
// line.append ("GOTO ");
|
||||
//
|
||||
// for (int p = startPtr; p <= max; p++)
|
||||
// {
|
||||
// byte b = buffer[p];
|
||||
// if (isToken (b))
|
||||
// {
|
||||
// if (line.length () > 0 && line.charAt (line.length () - 1) != ' ')
|
||||
// line.append (' ');
|
||||
// int val = b & 0x7F;
|
||||
// if (b != TOKEN_THEN || ApplesoftBasicProgram.basicPreferences.showThen)
|
||||
// line.append (ApplesoftConstants.tokens[val] + " ");
|
||||
// }
|
||||
// // else if (Utility.isControlCharacter (b))
|
||||
// // line.append (ApplesoftBasicProgram.basicPreferences.showCaret
|
||||
// // ? "^" + (char) (b + 64) : "?");
|
||||
// else if (!isControlCharacter (b))
|
||||
// line.append ((char) b);
|
||||
// }
|
||||
//
|
||||
// return line;
|
||||
// }
|
||||
StringBuilder toStringBuilder ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder line = new StringBuilder ();
|
||||
|
||||
// All sublines end with 0 or : except IF lines that are split into two
|
||||
int max = startPtr + length - 1;
|
||||
if (buffer[max] == 0)
|
||||
--max;
|
||||
|
||||
if (isImpliedGoto () && !ApplesoftBasicProgram.basicPreferences.showThen)
|
||||
line.append ("GOTO ");
|
||||
|
||||
for (int p = startPtr; p <= max; p++)
|
||||
{
|
||||
byte b = buffer[p];
|
||||
if (isToken (b))
|
||||
{
|
||||
if (line.length () > 0 && line.charAt (line.length () - 1) != ' ')
|
||||
line.append (' ');
|
||||
int val = b & 0x7F;
|
||||
if (b != TOKEN_THEN || ApplesoftBasicProgram.basicPreferences.showThen)
|
||||
line.append (ApplesoftConstants.tokens[val] + " ");
|
||||
}
|
||||
// else if (Utility.isControlCharacter (b))
|
||||
// line.append (ApplesoftBasicProgram.basicPreferences.showCaret
|
||||
// ? "^" + (char) (b + 64) : "?");
|
||||
else if (!isControlCharacter (b))
|
||||
line.append ((char) b);
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
// @Override
|
||||
// public String toString ()
|
||||
// // ---------------------------------------------------------------------------------//
|
||||
// {
|
||||
// return toStringBuilder ().toString ();
|
||||
// }
|
||||
@Override
|
||||
public String toString ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return toStringBuilder ().toString ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ public class UserBasicFormatter extends BasicFormatter
|
|||
private static final int INDENT_SIZE = 2;
|
||||
private static final String EIGHT_SPACES = " ";
|
||||
private static final String FOUR_SPACES = " ";
|
||||
private static boolean FORCE = true;
|
||||
private static boolean NO_FORCE = false;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public UserBasicFormatter (ApplesoftBasicProgram program,
|
||||
|
@ -45,8 +47,8 @@ public class UserBasicFormatter extends BasicFormatter
|
|||
{
|
||||
StringBuilder text = new StringBuilder (String.format ("%5d", (line.lineNumber)));
|
||||
|
||||
int indentLevel = loopVariables.size (); // each full line starts at the loop indent
|
||||
int ifIndent = 0; // IF statement(s) limit back indentation by NEXT
|
||||
int indentLevel = loopVariables.size (); // each full line starts at the loop indent
|
||||
int ifIndent = 0; // IF statement(s) limit back indentation by NEXT
|
||||
|
||||
for (SubLine subline : line.sublines)
|
||||
{
|
||||
|
@ -105,20 +107,29 @@ public class UserBasicFormatter extends BasicFormatter
|
|||
String lineText = alignment.getAlignedText (subline);
|
||||
|
||||
if (subline.is (TOKEN_DATA) && basicPreferences.deleteExtraDataSpace)
|
||||
lineText = lineText.replaceFirst ("DATA ", "DATA ");
|
||||
lineText = lineText.replaceFirst ("DATA +", "DATA "); // regex
|
||||
|
||||
// Check for a wrappable REM/DATA/DIM statement
|
||||
// (see SEA BATTLE on DISK283.DSK)
|
||||
int inset = Math.max (text.length (), getIndent (fullText)) + 1;
|
||||
if (subline.is (TOKEN_REM) && lineText.length () > basicPreferences.wrapRemAt)
|
||||
{
|
||||
List<String> lines = splitLine (lineText, basicPreferences.wrapRemAt, ' ');
|
||||
List<String> lines =
|
||||
splitLine (lineText, basicPreferences.wrapRemAt, ' ', FORCE);
|
||||
addSplitLines (lines, text, inset);
|
||||
}
|
||||
else if (subline.is (TOKEN_DATA)
|
||||
&& lineText.length () > basicPreferences.wrapDataAt)
|
||||
{
|
||||
List<String> lines = splitLine (lineText, basicPreferences.wrapDataAt, ',');
|
||||
List<String> lines =
|
||||
splitLine (lineText, basicPreferences.wrapDataAt, ',', FORCE);
|
||||
addSplitLines (lines, text, inset);
|
||||
}
|
||||
else if (subline.is (TOKEN_PRINT)
|
||||
&& lineText.length () > basicPreferences.wrapPrintAt)
|
||||
{
|
||||
List<String> lines =
|
||||
splitLine (lineText, basicPreferences.wrapDataAt, ';', NO_FORCE);
|
||||
addSplitLines (lines, text, inset);
|
||||
}
|
||||
else if (subline.is (TOKEN_DIM) && basicPreferences.splitDim)
|
||||
|
@ -162,7 +173,8 @@ public class UserBasicFormatter extends BasicFormatter
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private List<String> splitLine (String line, int wrapLength, char breakChar)
|
||||
private List<String> splitLine (String line, int wrapLength, char breakChar,
|
||||
boolean force)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int spaceAt = 0;
|
||||
|
@ -182,14 +194,15 @@ public class UserBasicFormatter extends BasicFormatter
|
|||
break;
|
||||
|
||||
lines.add (line.substring (0, breakAt + 1)); // keep breakChar at end
|
||||
line = indent + line.substring (breakAt + 1);
|
||||
line = indent + line.substring (breakAt + 1).trim ();
|
||||
}
|
||||
|
||||
while (line.length () > wrapLength) // no breakChars found
|
||||
{
|
||||
lines.add (line.substring (0, wrapLength));
|
||||
line = indent + line.substring (wrapLength);
|
||||
}
|
||||
if (force)
|
||||
while (line.length () > wrapLength) // no breakChars found
|
||||
{
|
||||
lines.add (line.substring (0, wrapLength));
|
||||
line = indent + line.substring (wrapLength);
|
||||
}
|
||||
|
||||
lines.add (line);
|
||||
return lines;
|
||||
|
@ -258,6 +271,7 @@ public class UserBasicFormatter extends BasicFormatter
|
|||
.size (); i++)
|
||||
{
|
||||
boolean precededByIf = false;
|
||||
|
||||
for (SubLine subline : sourceLines.get (i).sublines)
|
||||
{
|
||||
if (started)
|
||||
|
|
|
@ -22,10 +22,19 @@
|
|||
0035 YSAV1
|
||||
0036 CSWL
|
||||
0037 CSHW
|
||||
0044 A5L - volume number?
|
||||
003D A1H
|
||||
003C A1L
|
||||
003F A2H
|
||||
003E A2L
|
||||
0041 A3H
|
||||
0040 A3L
|
||||
0043 A4H
|
||||
0042 A4L
|
||||
0045 A5H
|
||||
0044 A5L
|
||||
004E RND-LO
|
||||
004F RND-HI
|
||||
0050 LINNUM
|
||||
0050 LINNUM line number, unsigned word
|
||||
0067 Basic program address LO
|
||||
0068 Basic program address HI
|
||||
0069 Basic variables address LO
|
||||
|
@ -52,8 +61,48 @@
|
|||
0200 Input buffer
|
||||
|
||||
03D0 Applesoft warm start
|
||||
03EA VECT
|
||||
A56E catalog routine
|
||||
|
||||
03F2 RST: Control-reset vector
|
||||
03F3 RST: Control-reset vector
|
||||
03F4 RST: Control-reset checksum (EOR #$A5)
|
||||
03FB NMI: Non-Maskable Interrupt vector
|
||||
03FC NMI: Non-Maskable Interrupt vector
|
||||
03F8 USR: user vector (Control-Y)
|
||||
03F9 USR: user vector (Control-Y)
|
||||
03FE IRQ: Interrupt Request/BRK vector
|
||||
03FF IRQ: Interrupt Request/BRK vector
|
||||
|
||||
A54F DOS 3.3 INIT
|
||||
A413 DOS 3.3 LOAD
|
||||
A397 DOS 3.3 SAVE
|
||||
A4D1 DOS 3.3 RUN
|
||||
A4F0 DOS 3.3 CHAIN
|
||||
A263 DOS 3.3 DELETE
|
||||
A271 DOS 3.3 LOCK
|
||||
A275 DOS 3.3 UNLOCK
|
||||
A2EA DOS 3.3 CLOSE
|
||||
A51B DOS 3.3 READ
|
||||
A5C6 DOS 3.3 EXEC
|
||||
A510 DOS 3.3 WRITE
|
||||
A5DD DOS 3.3 POSITION
|
||||
A2A3 DOS 3.3 OPEN
|
||||
A298 DOS 3.3 APPEND
|
||||
A281 DOS 3.3 RENAME
|
||||
A56E DOS 3.3 CATALOG
|
||||
A233 DOS 3.3 MON
|
||||
A23D DOS 3.3 NOMON
|
||||
A229 DOS 3.3 PR#
|
||||
A22E DOS 3.3 IN#
|
||||
A251 DOS 3.3 MAXFILES
|
||||
A57A DOS 3.3 FP
|
||||
A59E DOS 3.3 INT
|
||||
A331 DOS 3.3 BSAVE
|
||||
A35D DOS 3.3 BLOAD
|
||||
A38E DOS 3.3 BRUN
|
||||
A27D DOS 3.3 VERIFY
|
||||
|
||||
BF00 ProDOS MLI entry point
|
||||
BF98 ProDOS Machine ID Byte
|
||||
|
||||
* C000 80STOREOFF Allow page2 to switch video page1 page2
|
||||
C001 80STOREON Allow page2 to switch main & aux video memory
|
||||
|
@ -68,8 +117,12 @@ C009 ALTZPON Enable aux memory from $0000-$01FF & avl BSR
|
|||
C00A SLOTC3ROMOFF Enable main ROM from $C300-$C3FF
|
||||
C00B SLOTC3ROMON Enable slot ROM from $C300-$C3FF
|
||||
|
||||
C000 KYBD - last key pressed
|
||||
C010 STROBE - Clear KYBD
|
||||
C000 KBD - Last key pressed
|
||||
C010 KBDSTRB - Clear KYBD
|
||||
C019 VBL - Vertical Blank
|
||||
C020 TAPEOUT - Toggle cassette output
|
||||
C030 SPKR - Toggle speaker
|
||||
C040 STROBE - Output strobe pulse to game I/O connector
|
||||
C050 TXTCLR - Display Graphics
|
||||
C051 TXTSET - Display Text
|
||||
C052 MIXCLR - Display Full Screen
|
||||
|
@ -78,6 +131,15 @@ C054 TXTPAGE1 - Display Page 1
|
|||
C055 TXTPAGE2 - If 80STORE Off: Display Page 2, If 80STORE On: Read/Write Aux Display Mem
|
||||
C056 LORES - Display LoRes Graphics
|
||||
C057 HIRES - Display HiRes Graphics
|
||||
C060 TAPEIN - Read audio from cassette input
|
||||
C061 PB0 - Read joystick button 0/Open-Apple key
|
||||
C062 PB1 - Read joystick button 1/Closed-Apple key
|
||||
C063 PB2 - Read joystick button 2
|
||||
C064 PADDL0 - Read paddle/joystick 0
|
||||
C065 PADDL1 - Read paddle/joystick 1
|
||||
C066 PADDL2 - Read paddle/joystick 2
|
||||
C067 PADDL3 - Read paddle/joystick 3
|
||||
C070 PTRIG - Clear paddle/joystick timer
|
||||
|
||||
C080 Read RAM bank 2; no write
|
||||
C081 ROMIN - Read ROM; write RAM bank 2
|
||||
|
@ -96,6 +158,9 @@ C08D Read ROM; write RAM bank 1
|
|||
C08E Read ROM; no write
|
||||
C08F Read/write RAM bank 1
|
||||
|
||||
C600 BOOT0 - Disk II controller ROM
|
||||
0801 BOOT1 - Disk II bootstrap RAM
|
||||
|
||||
D52C INLIN numeric input
|
||||
DB3A STROUT - output a string
|
||||
DB5C output a character
|
||||
|
@ -106,6 +171,7 @@ DEC0 SYNCHR
|
|||
DEC9 syntax error
|
||||
DFE3 PTRGET
|
||||
|
||||
E000 Applesoft BASIC entry
|
||||
E053 find a variable
|
||||
E10C convert FP to INT
|
||||
E2F2 GIVAYF - convert (A,Y) to FP
|
||||
|
@ -177,15 +243,16 @@ F941 PRINTAX - print AX registers in hex
|
|||
F948 PRBLNK - print 3 spaces
|
||||
F94A PRBL2 - print X blank spaces
|
||||
|
||||
FAA6 reboot DOS
|
||||
FAA6 PWRUP - reboot
|
||||
FAFF 0 = Autostart ROM, 1 = Old Monitor
|
||||
|
||||
FB1E PREAD - read game paddle
|
||||
FB2F initialise text screen
|
||||
FB2F INIT - initialise text screen
|
||||
FB39 text mode - SETTXT
|
||||
FB40 SETGR
|
||||
FB5B TABV - monitor tab routine
|
||||
FB6F set powerup checksum
|
||||
FB6F SETPWRC - set powerup checksum
|
||||
FBB3 VERSION - monitor ROM ID byte
|
||||
FBC1 BASCALC - calculate video address
|
||||
FBDD BELL1 - beep speaker
|
||||
FBF4 CURSRIT - move cursor right
|
||||
|
@ -193,6 +260,7 @@ FBF4 CURSRIT - move cursor right
|
|||
FC10 CURSLFT - move cursor left
|
||||
FC1A CURSUP - move cursor up
|
||||
FC22 VTAB
|
||||
FC24 VTABZ
|
||||
FC42 CLREOP - clear to end of page
|
||||
FC58 HOME - clear screen
|
||||
FC62 CR
|
||||
|
@ -215,12 +283,13 @@ FDE3 PRHEX - print a hex digit
|
|||
FDED COUT - print a character (in Acc)
|
||||
FDF0 COUT1 - print character to screen
|
||||
|
||||
FE2C move a block of memory
|
||||
FE1F IDROUTINE - detect //gs
|
||||
FE2C MOVE - move a block of memory
|
||||
FE80 SETINV - set inverse mode
|
||||
FE84 SETNORM - set normal mode
|
||||
FE89 disconnect DOS from I/O links
|
||||
FE89 SETKBD - disconnect DOS from I/O links
|
||||
FE8B INPORT
|
||||
FE93 disconnect DOS from I/O links
|
||||
FE93 SETVID - disconnect DOS from I/O links
|
||||
FE95 OUTPORT
|
||||
FECD WRITE
|
||||
FEFD READ
|
||||
|
@ -231,6 +300,14 @@ FF3A BELL
|
|||
FF3F IOREST - restore all registers
|
||||
FF4A IOSAVE - save all registers
|
||||
FF58 RTS - jump to <address on stack> + 1
|
||||
FF59 Monitor cold entry point
|
||||
FF59 MON - Monitor cold entry point (w/BELL)
|
||||
FF69 MONZ - Monitor entry point from BASIC (CALL -151)
|
||||
FFA7 GETNUM - move num to A2L.A2H
|
||||
FFC7 ZMODE - monitor get ASCII return
|
||||
|
||||
FFFA NMI_VECTOR
|
||||
FFFB NMI_VECTOR
|
||||
FFFC RESET_VECTOR
|
||||
FFFD RESET_VECTOR
|
||||
FFFE IRQ_VECTOR
|
||||
FFFF IRQ_VECTOR
|
||||
|
|
|
@ -52,7 +52,7 @@ public class AppleworksADBFile extends AbstractFile
|
|||
|
||||
dbMinVersion = buffer[218] & 0xFF;
|
||||
|
||||
headerSize = Utility.unsignedShort (buffer, 0);
|
||||
headerSize = Utility.getShort (buffer, 0);
|
||||
cursorDirectionSRL = buffer[30];
|
||||
cursorDirectionMRL = (char) buffer[31];
|
||||
currentDisplay = (char) buffer[34];
|
||||
|
@ -60,7 +60,7 @@ public class AppleworksADBFile extends AbstractFile
|
|||
categoryNames = new String[categories];
|
||||
|
||||
totalReports = buffer[38] & 0xFF;
|
||||
int recs = Utility.unsignedShort (buffer, 36);
|
||||
int recs = Utility.getShort (buffer, 36);
|
||||
totalRecords = dbMinVersion == 0 ? recs : recs & 0x7FFF;
|
||||
|
||||
for (int i = 0; i < 30; i++)
|
||||
|
@ -79,9 +79,9 @@ public class AppleworksADBFile extends AbstractFile
|
|||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
selectionRules[i] = Utility.unsignedShort (buffer, 223 + i * 2);
|
||||
testTypes[i] = Utility.unsignedShort (buffer, 229 + i * 2);
|
||||
continuation[i] = Utility.unsignedShort (buffer, 235 + i * 2);
|
||||
selectionRules[i] = Utility.getShort (buffer, 223 + i * 2);
|
||||
testTypes[i] = Utility.getShort (buffer, 229 + i * 2);
|
||||
continuation[i] = Utility.getShort (buffer, 235 + i * 2);
|
||||
comparison[i] = new String (buffer, 241 + i * 20, 20);
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ public class AppleworksADBFile extends AbstractFile
|
|||
ptr += 600;
|
||||
}
|
||||
|
||||
int length = Utility.unsignedShort (buffer, ptr);
|
||||
int length = Utility.getShort (buffer, ptr);
|
||||
ptr += 2;
|
||||
|
||||
if (length == 0)
|
||||
|
@ -118,7 +118,7 @@ public class AppleworksADBFile extends AbstractFile
|
|||
|
||||
for (int recordNo = 0; recordNo < totalRecords; recordNo++)
|
||||
{
|
||||
length = Utility.unsignedShort (buffer, ptr);
|
||||
length = Utility.getShort (buffer, ptr);
|
||||
ptr += 2;
|
||||
if (length == 0)
|
||||
break;
|
||||
|
|
|
@ -25,7 +25,7 @@ public class AppleworksSSFile extends AbstractFile
|
|||
int ptr = header.ssMinVers == 0 ? 300 : 302;
|
||||
while (ptr < buffer.length)
|
||||
{
|
||||
int length = Utility.unsignedShort (buffer, ptr);
|
||||
int length = Utility.getShort (buffer, ptr);
|
||||
|
||||
if (length == 0xFFFF)
|
||||
break;
|
||||
|
@ -103,7 +103,7 @@ public class AppleworksSSFile extends AbstractFile
|
|||
|
||||
calcOrder = (char) buffer[131];
|
||||
calcFrequency = (char) buffer[132];
|
||||
lastRow = Utility.unsignedShort (buffer, 133);
|
||||
lastRow = Utility.getShort (buffer, 133);
|
||||
lastColumn = buffer[135] & 0xFF;
|
||||
windowLayout = (char) buffer[136];
|
||||
windowSynch = buffer[137] != 0;
|
||||
|
@ -204,15 +204,15 @@ public class AppleworksSSFile extends AbstractFile
|
|||
|
||||
r1 = buffer[offset + 3] & 0xFF;
|
||||
c1 = buffer[offset + 4] & 0xFF;
|
||||
r2 = Utility.unsignedShort (buffer, offset + 5);
|
||||
r2 = Utility.getShort (buffer, offset + 5);
|
||||
c2 = buffer[offset + 7] & 0xFF;
|
||||
r3 = Utility.unsignedShort (buffer, offset + 8);
|
||||
r3 = Utility.getShort (buffer, offset + 8);
|
||||
c3 = buffer[offset + 10] & 0xFF;
|
||||
r4 = Utility.unsignedShort (buffer, offset + 11);
|
||||
r4 = Utility.getShort (buffer, offset + 11);
|
||||
c4 = buffer[offset + 13] & 0xFF;
|
||||
r5 = buffer[offset + 14] & 0xFF;
|
||||
c5 = buffer[offset + 15] & 0xFF;
|
||||
r6 = Utility.unsignedShort (buffer, offset + 16);
|
||||
r6 = Utility.getShort (buffer, offset + 16);
|
||||
c6 = buffer[offset + 18] & 0xFF;
|
||||
r7 = buffer[offset + 19] & 0xFF;
|
||||
c7 = buffer[offset + 20] & 0xFF;
|
||||
|
@ -265,7 +265,7 @@ public class AppleworksSSFile extends AbstractFile
|
|||
|
||||
public Row (int ptr)
|
||||
{
|
||||
rowNumber = Utility.unsignedShort (buffer, ptr);
|
||||
rowNumber = Utility.getShort (buffer, ptr);
|
||||
ptr += 2; // first control byte
|
||||
|
||||
int column = 0;
|
||||
|
|
|
@ -139,7 +139,7 @@ public class AppleworksWPFile extends AbstractFile
|
|||
break;
|
||||
|
||||
default:
|
||||
System.out.printf ("Unknown value in %s: %02X %02X%n", name, b1, b2);
|
||||
System.out.printf ("Unknown value in %s: %02X %02X%n", getName (), b1, b2);
|
||||
}
|
||||
ptr += 2;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ class CellAddress
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
colRef = buffer[offset];
|
||||
rowRef = Utility.intValue (buffer[offset + 1], buffer[offset + 2]);
|
||||
rowRef = Utility.getShort (buffer, offset + 1);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
|
@ -131,9 +131,9 @@ abstract class Report
|
|||
if (buffer[offset + 480 + fudge] == 0) // test high byte
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
selectionRules[i] = Utility.unsignedShort (buffer, offset + 479 + i * 2 + fudge);
|
||||
testTypes[i] = Utility.unsignedShort (buffer, offset + 485 + i * 2 + fudge);
|
||||
continuation[i] = Utility.unsignedShort (buffer, offset + 491 + i * 2 + fudge);
|
||||
selectionRules[i] = Utility.getShort (buffer, offset + 479 + i * 2 + fudge);
|
||||
testTypes[i] = Utility.getShort (buffer, offset + 485 + i * 2 + fudge);
|
||||
continuation[i] = Utility.getShort (buffer, offset + 491 + i * 2 + fudge);
|
||||
comparison[i] = pascalString (buffer, offset + 497 + i * 32 + fudge);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -26,23 +26,28 @@ class CPMCatalogSector extends AbstractSector
|
|||
|
||||
for (int i = 0; i <= 255; i += CATALOG_ENTRY_SIZE)
|
||||
{
|
||||
if (buffer[i] == (byte) 0xE5)
|
||||
if (buffer[i] == (byte) 0xE5 && buffer[i + 1] == (byte) 0xE5)
|
||||
break;
|
||||
|
||||
int userNumber = buffer[i] & 0xFF;
|
||||
if (userNumber > 31 && userNumber != (byte) 0xE5)
|
||||
break;
|
||||
|
||||
boolean readOnly = (buffer[i + 9] & 0x80) != 0;
|
||||
boolean systemFile = (buffer[i + 10] & 0x80) != 0;
|
||||
boolean unknown = (buffer[i + 11] & 0x80) != 0;
|
||||
String type;
|
||||
String extra;
|
||||
|
||||
if (readOnly || systemFile)
|
||||
if (readOnly || systemFile || unknown)
|
||||
{
|
||||
byte[] typeBuffer = new byte[3];
|
||||
typeBuffer[0] = (byte) (buffer[i + 9] & 0x7F);
|
||||
typeBuffer[1] = (byte) (buffer[i + 10] & 0x7F);
|
||||
typeBuffer[2] = buffer[i + 11];
|
||||
typeBuffer[2] = (byte) (buffer[i + 11] & 0x7F);
|
||||
type = new String (typeBuffer).trim ();
|
||||
extra = String.format (" (%s%s)", readOnly ? "read only" : "",
|
||||
systemFile ? "system file" : "");
|
||||
extra = String.format (" (%s%s%s)", readOnly ? "read only" : "",
|
||||
systemFile ? "system file" : "", unknown ? "unknown" : "");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -50,8 +55,14 @@ class CPMCatalogSector extends AbstractSector
|
|||
extra = "";
|
||||
}
|
||||
|
||||
addText (text, buffer, i, 1, "User number");
|
||||
addText (text, buffer, i + 1, 4, "File name : " + new String (buffer, i + 1, 8));
|
||||
if (buffer[i] == (byte) 0xE5)
|
||||
addText (text, buffer, i, 1, "Deleted file?");
|
||||
else
|
||||
addText (text, buffer, i, 1, "User number");
|
||||
if (buffer[i + 1] == 0)
|
||||
addText (text, buffer, i + 1, 4, "File name : ");
|
||||
else
|
||||
addText (text, buffer, i + 1, 4, "File name : " + new String (buffer, i + 1, 8));
|
||||
addText (text, buffer, i + 5, 4, "");
|
||||
addText (text, buffer, i + 9, 3, "File type : " + type + extra);
|
||||
addText (text, buffer, i + 12, 1, "Extent counter LO");
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.bytezone.diskbrowser.cpm;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
@ -13,11 +14,15 @@ import com.bytezone.diskbrowser.disk.Disk;
|
|||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||
import com.bytezone.diskbrowser.disk.SectorType;
|
||||
import com.bytezone.diskbrowser.gui.DataSource;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
|
||||
// https://www.retrotechnology.com/dri/howto_cpm.html
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class CPMDisk extends AbstractFormattedDisk
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static final int EMPTY_BYTE_VALUE = 0xE5;
|
||||
|
||||
private final Color green = new Color (0, 200, 0);
|
||||
|
||||
public final SectorType catalogSector = new SectorType ("Catalog", green);
|
||||
|
@ -50,7 +55,7 @@ public class CPMDisk extends AbstractFormattedDisk
|
|||
sectorTypesList.add (macSector);
|
||||
sectorTypesList.add (otherSector);
|
||||
|
||||
setEmptyByte ((byte) 0xE5);
|
||||
setEmptyByte ((byte) EMPTY_BYTE_VALUE);
|
||||
|
||||
// search for the version string
|
||||
for (int i = 8; i >= 4; i -= 2)
|
||||
|
@ -74,22 +79,28 @@ public class CPMDisk extends AbstractFormattedDisk
|
|||
|
||||
sectorTypes[da.getBlockNo ()] = catalogSector;
|
||||
byte[] buffer = disk.readBlock (da);
|
||||
|
||||
int b1 = buffer[0] & 0xFF;
|
||||
int b2 = buffer[1] & 0xFF;
|
||||
if (b1 == 0xE5)
|
||||
|
||||
if (b1 == EMPTY_BYTE_VALUE && (b2 == EMPTY_BYTE_VALUE || b2 == 0))
|
||||
continue;
|
||||
if (b1 > 31)
|
||||
|
||||
if (b1 > 31 && b1 != EMPTY_BYTE_VALUE)
|
||||
break;
|
||||
if (b2 < 32 || (b2 > 126 && b2 != 0xE5))
|
||||
|
||||
if (b2 <= 32 || (b2 > 126 && b2 != EMPTY_BYTE_VALUE))
|
||||
break;
|
||||
|
||||
for (int i = 0; i < buffer.length; i += 32)
|
||||
{
|
||||
b1 = buffer[i] & 0xFF;
|
||||
b2 = buffer[i + 1] & 0xFF;
|
||||
if (b1 == 0xE5)
|
||||
break;
|
||||
if (b2 < 32 || (b2 > 126 && b2 != 0xE5))
|
||||
|
||||
if (b1 == EMPTY_BYTE_VALUE) // deleted file??
|
||||
continue;
|
||||
|
||||
if (b2 <= 32 || (b2 > 126 && b2 != EMPTY_BYTE_VALUE))
|
||||
break;
|
||||
|
||||
DirectoryEntry entry = new DirectoryEntry (this, buffer, i);
|
||||
|
@ -111,9 +122,6 @@ public class CPMDisk extends AbstractFormattedDisk
|
|||
}
|
||||
}
|
||||
|
||||
// root.setUserObject (getCatalog ()); // override the disk's default display
|
||||
// makeNodeVisible (rootNode.getFirstLeaf ());
|
||||
|
||||
volumeNode.setUserObject (getCatalog ());
|
||||
makeNodeVisible (volumeNode.getFirstLeaf ());
|
||||
}
|
||||
|
@ -147,6 +155,7 @@ public class CPMDisk extends AbstractFormattedDisk
|
|||
{
|
||||
if (fileEntries.size () > 0 && fileEntries.size () > fileNo)
|
||||
return fileEntries.get (fileNo).getSectors ();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -180,19 +189,17 @@ public class CPMDisk extends AbstractFormattedDisk
|
|||
public AppleFileSource getCatalog ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
String newLine = String.format ("%n");
|
||||
String line =
|
||||
"---- --------- --- - - -- -- -- -- ----------------------------"
|
||||
+ "-------------------" + newLine;
|
||||
String line = "---- --------- --- - - -- -- -- -- ----------------------------"
|
||||
+ "-------------------\n";
|
||||
StringBuilder text = new StringBuilder ();
|
||||
text.append (String.format ("File : %s%n%n", getDisplayPath ()));
|
||||
text.append ("User Name Typ R S Ex S2 S1 RC Blocks" + newLine);
|
||||
text.append ("User Name Typ R S Ex S2 S1 RC Blocks\n");
|
||||
text.append (line);
|
||||
|
||||
for (AppleFileSource entry : fileEntries)
|
||||
{
|
||||
text.append (((DirectoryEntry) entry).line ());
|
||||
text.append (newLine);
|
||||
text.append ("\n");
|
||||
}
|
||||
text.append (line);
|
||||
if (version != 0)
|
||||
|
@ -204,6 +211,64 @@ public class CPMDisk extends AbstractFormattedDisk
|
|||
// ---------------------------------------------------------------------------------//
|
||||
public static boolean isCorrectFormat (AppleDisk disk)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
boolean debug = false;
|
||||
|
||||
disk.setInterleave (3);
|
||||
|
||||
// collect catalog sectors
|
||||
List<DiskAddress> catalog = new ArrayList<> ();
|
||||
for (int i = 0; i < 8; i++)
|
||||
catalog.add (disk.getDiskAddress (3, i));
|
||||
byte[] buffer = disk.readBlocks (catalog);
|
||||
|
||||
if (debug)
|
||||
System.out.println (HexFormatter.format (buffer));
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
int start = i * 1024;
|
||||
int end = start + 1024;
|
||||
|
||||
for (int ptr = start; ptr < end; ptr += 32)
|
||||
{
|
||||
if (buffer[ptr] == (byte) EMPTY_BYTE_VALUE)
|
||||
{
|
||||
if (buffer[ptr + 1] == (byte) EMPTY_BYTE_VALUE //
|
||||
|| buffer[ptr + 1] == 0) // finished this block
|
||||
break;
|
||||
continue; // deleted file?
|
||||
}
|
||||
|
||||
int userNo = buffer[ptr] & 0xFF;
|
||||
if (userNo > 31)
|
||||
return false;
|
||||
|
||||
for (int j = 1; j < 12; j++)
|
||||
{
|
||||
int ch = buffer[ptr + j] & 0x7F; // remove flag
|
||||
if (ch < 32 || ch > 126) // invalid ascii
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
String fileName = new String (buffer, ptr + 1, 8);
|
||||
String fileType = new String (buffer, ptr + 9, 3);
|
||||
System.out.printf ("%2d %s %s%n", userNo, fileName, fileType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (debug)
|
||||
System.out.println ("CP/M disk");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private static boolean isCorrectFormat2 (AppleDisk disk)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
disk.setInterleave (3);
|
||||
|
||||
|
@ -222,26 +287,60 @@ public class CPMDisk extends AbstractFormattedDisk
|
|||
for (int sector = 0; sector < 8; sector++)
|
||||
{
|
||||
byte[] buffer = disk.readBlock (3, sector);
|
||||
System.out.println (HexFormatter.format (buffer));
|
||||
|
||||
// check if entire sector is empty (everything == 0xE5)
|
||||
if (bufferContainsAll (buffer, (byte) 0xE5))
|
||||
if (bufferContainsAll (buffer, (byte) EMPTY_BYTE_VALUE))
|
||||
break;
|
||||
|
||||
int b1 = buffer[0] & 0xFF;
|
||||
int b2 = buffer[1] & 0xFF;
|
||||
|
||||
if (b1 == EMPTY_BYTE_VALUE && (b2 == EMPTY_BYTE_VALUE || b2 == 0))
|
||||
continue;
|
||||
|
||||
if (b1 > 31 && b1 != EMPTY_BYTE_VALUE)
|
||||
break;
|
||||
|
||||
if (b2 < 32 || (b2 > 126 && b2 != EMPTY_BYTE_VALUE))
|
||||
break;
|
||||
|
||||
for (int i = 0; i < buffer.length; i += 32)
|
||||
{
|
||||
int val = buffer[i] & 0xFF;
|
||||
if (val == 0xE5)
|
||||
break;
|
||||
b1 = buffer[i] & 0xFF;
|
||||
b2 = buffer[i + 1] & 0xFF;
|
||||
|
||||
if (val > 31)
|
||||
if (b1 == EMPTY_BYTE_VALUE) // deleted file??
|
||||
continue;
|
||||
|
||||
if (b2 < 32 || (b2 > 126 && b2 != EMPTY_BYTE_VALUE))
|
||||
return false;
|
||||
|
||||
for (int j = 1; j <= 8; j++)
|
||||
{
|
||||
val = buffer[i + j] & 0xFF;
|
||||
if (val < 32 || (val > 126 && val != 0xE5))
|
||||
return false;
|
||||
}
|
||||
// int val = buffer[i] & 0xFF;
|
||||
// if (val == EMPTY_BYTE_VALUE)
|
||||
// {
|
||||
// if (debug)
|
||||
// System.out.println ("empty value found - deleted file?");
|
||||
// break;
|
||||
// }
|
||||
|
||||
// if (val > 31)
|
||||
// {
|
||||
// if (debug)
|
||||
// System.out.println ("val > 31");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// for (int j = 1; j <= 8; j++)
|
||||
// {
|
||||
// val = buffer[i + j] & 0xFF;
|
||||
// if (val < 32 || (val > 126 && val != EMPTY_BYTE_VALUE))
|
||||
// {
|
||||
// if (debug)
|
||||
// System.out.println ("val < 32 || val > 126");
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
||||
import com.bytezone.diskbrowser.applefile.CPMBasicFile;
|
||||
import com.bytezone.diskbrowser.applefile.CPMTextFile;
|
||||
import com.bytezone.diskbrowser.applefile.DefaultAppleFile;
|
||||
import com.bytezone.diskbrowser.disk.AppleDiskAddress;
|
||||
|
@ -54,7 +55,11 @@ class DirectoryEntry implements AppleFileSource
|
|||
type = new String (typeBuffer).trim ();
|
||||
|
||||
userNumber = buffer[offset] & 0xFF;
|
||||
name = new String (buffer, offset + 1, 8).trim ();
|
||||
if (userNumber == 0xE5 && buffer[offset + 1] == 0)
|
||||
name = "";
|
||||
else
|
||||
name = new String (buffer, offset + 1, 8).trim ();
|
||||
|
||||
extent = buffer[offset + 12] & 0xFF;
|
||||
s2 = buffer[offset + 13] & 0xFF;
|
||||
s1 = buffer[offset + 14] & 0xFF;
|
||||
|
@ -77,9 +82,6 @@ class DirectoryEntry implements AppleFileSource
|
|||
for (int i = 0; i < 4; i++)
|
||||
blocks.add (new AppleDiskAddress (disk, blockNumber + i));
|
||||
}
|
||||
// if (name.equals ("cp/m"))
|
||||
// for (DiskAddress da : blocks)
|
||||
// System.out.println (da);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -123,6 +125,7 @@ class DirectoryEntry implements AppleFileSource
|
|||
for (DiskAddress sector : blocks)
|
||||
if (sector.matches (da))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -136,9 +139,8 @@ class DirectoryEntry implements AppleFileSource
|
|||
char ro = readOnly ? '*' : ' ';
|
||||
char sf = systemFile ? '*' : ' ';
|
||||
|
||||
String text =
|
||||
String.format ("%3d %-8s %-3s %s %s %02X %02X %02X %02X %s",
|
||||
userNumber, name, type, ro, sf, extent, s2, s1, recordsUsed, bytes);
|
||||
String text = String.format ("%3d %-8s %-3s %s %s %02X %02X %02X %02X %s",
|
||||
userNumber, name, type, ro, sf, extent, s2, s1, recordsUsed, bytes);
|
||||
for (DirectoryEntry entry : entries)
|
||||
text = text + "\n" + entry.line ();
|
||||
|
||||
|
@ -210,23 +212,18 @@ class DirectoryEntry implements AppleFileSource
|
|||
byte[] exactBuffer = new byte[len];
|
||||
System.arraycopy (buffer, 0, exactBuffer, 0, len);
|
||||
|
||||
int max = Math.min (256, exactBuffer.length);
|
||||
int count = 0;
|
||||
for (int i = 1; i < max; i++)
|
||||
{
|
||||
if (exactBuffer[i - 1] == 0x0D && exactBuffer[i] == 0x0A)
|
||||
++count;
|
||||
}
|
||||
|
||||
if ("COM".equals (type))
|
||||
appleFile = new DefaultAppleFile (name, exactBuffer, "COM File");
|
||||
else if ("DVR".equals (type))
|
||||
appleFile = new DefaultAppleFile (name, exactBuffer, "DVR File");
|
||||
else if ("ASM".equals (type) || "DOC".equals (type) || "TXT".equals (type)
|
||||
|| count > 2)
|
||||
else if ("ASM".equals (type) || "DOC".equals (type) || "COB".equals (type)
|
||||
|| "HLP".equals (type) || "TXT".equals (type) || "LET".equals (type) || "ALX".equals (type)
|
||||
|| "SRC".equals (type) || "H".equals (type) || exactBuffer[len - 1] == 0x1A)
|
||||
appleFile = new CPMTextFile (name, exactBuffer);
|
||||
else if ("BAS".equals (type))
|
||||
appleFile = new CPMBasicFile (name, exactBuffer);
|
||||
else
|
||||
appleFile = new DefaultAppleFile (name, exactBuffer, "CPM File : " + type);
|
||||
appleFile = new DefaultAppleFile (name, exactBuffer, "CPM File : " + name + "." + type);
|
||||
|
||||
return appleFile;
|
||||
}
|
||||
|
|
|
@ -85,7 +85,8 @@ public abstract class AbstractFormattedDisk implements FormattedDisk
|
|||
name = "tmp.dsk";
|
||||
|
||||
DefaultAppleFileSource afs =
|
||||
new DefaultAppleFileSource (name, disk.toString (), this);
|
||||
// new DefaultAppleFileSource (name, disk.toString (), this);
|
||||
new DefaultAppleFileSource (name, new DefaultDataSource (disk), this);
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode (afs);
|
||||
DefaultTreeModel treeModel = new DefaultTreeModel (root);
|
||||
catalogTree = new JTree (treeModel);
|
||||
|
@ -205,8 +206,7 @@ public abstract class AbstractFormattedDisk implements FormattedDisk
|
|||
|
||||
DefaultMutableTreeNode root = getCatalogTreeRoot ();
|
||||
if (root.getUserObject () == null)
|
||||
root.setUserObject (
|
||||
new DefaultAppleFileSource (getName (), disk.toString (), this));
|
||||
root.setUserObject (new DefaultAppleFileSource (getName (), disk.toString (), this));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -233,15 +233,15 @@ public abstract class AbstractFormattedDisk implements FormattedDisk
|
|||
public String getDisplayPath ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
// if (originalPath != null)
|
||||
// return originalPath.toString ();
|
||||
|
||||
String home = System.getProperty ("user.home");
|
||||
|
||||
String path = originalPath != null ? originalPath.toString ()
|
||||
: disk.getFile ().getAbsolutePath ();
|
||||
if (path.startsWith (home))
|
||||
return "~" + path.substring (home.length ());
|
||||
String path =
|
||||
originalPath != null ? originalPath.toString () : disk.getFile ().getAbsolutePath ();
|
||||
|
||||
int pos = path.indexOf (home);
|
||||
|
||||
if (pos == 0 || (path.startsWith ("/Volumes/") && pos > 0))
|
||||
return "~" + path.substring (home.length () + pos);
|
||||
|
||||
return disk.getFile ().getAbsolutePath ();
|
||||
}
|
||||
|
@ -326,8 +326,7 @@ public abstract class AbstractFormattedDisk implements FormattedDisk
|
|||
if (children != null)
|
||||
while (children.hasMoreElements ())
|
||||
{
|
||||
DefaultMutableTreeNode childNode =
|
||||
(DefaultMutableTreeNode) children.nextElement ();
|
||||
DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) children.nextElement ();
|
||||
if (childNode.getUserObject ().toString ().indexOf (name) > 0)
|
||||
return childNode;
|
||||
}
|
||||
|
|
|
@ -8,14 +8,12 @@ import javax.swing.JPanel;
|
|||
import com.bytezone.diskbrowser.applefile.AssemblerProgram;
|
||||
import com.bytezone.diskbrowser.gui.DataSource;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public abstract class AbstractSector implements DataSource
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static String newLine = String.format ("%n");
|
||||
private static String newLine2 = newLine + newLine;
|
||||
|
||||
final public byte[] buffer;
|
||||
protected Disk disk;
|
||||
protected DiskAddress diskAddress;
|
||||
|
@ -56,6 +54,14 @@ public abstract class AbstractSector implements DataSource
|
|||
return HexFormatter.format (buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public byte[] getBuffer ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public BufferedImage getImage ()
|
||||
|
@ -82,10 +88,11 @@ public abstract class AbstractSector implements DataSource
|
|||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
text.append (title + newLine2);
|
||||
text.append ("Offset Value Description" + newLine);
|
||||
text.append (title + "\n\n");
|
||||
text.append ("Offset Value Description\n");
|
||||
text.append ("======= =========== "
|
||||
+ "===============================================================" + newLine);
|
||||
+ "===============================================================\n");
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
@ -135,14 +142,13 @@ public abstract class AbstractSector implements DataSource
|
|||
String desc)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (size == 1)
|
||||
desc += " (" + (b[offset] & 0xFF) + ")";
|
||||
else if (size == 2)
|
||||
desc +=
|
||||
String.format (" (%,d)", ((b[offset + 1] & 0xFF) * 256 + (b[offset] & 0xFF)));
|
||||
else if (size == 3)
|
||||
desc += String.format (" (%,d)", ((b[offset + 2] & 0xFF) * 65536)
|
||||
+ ((b[offset + 1] & 0xFF) * 256) + (b[offset] & 0xFF));
|
||||
desc += switch (size)
|
||||
{
|
||||
case 1 -> " (" + (b[offset] & 0xFF) + ")";
|
||||
case 2 -> String.format (" (%,d)", Utility.getShort (b, offset));
|
||||
case 3 -> String.format (" (%,d)", Utility.readTriple (b, offset));
|
||||
default -> "";
|
||||
};
|
||||
|
||||
addText (text, b, offset, size, desc);
|
||||
}
|
||||
|
|
|
@ -13,11 +13,13 @@ import java.util.List;
|
|||
import java.util.zip.CRC32;
|
||||
import java.util.zip.Checksum;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
||||
import com.bytezone.diskbrowser.nib.NibFile;
|
||||
import com.bytezone.diskbrowser.nib.V2dFile;
|
||||
import com.bytezone.diskbrowser.nib.WozFile;
|
||||
import com.bytezone.diskbrowser.nufx.Binary2;
|
||||
import com.bytezone.diskbrowser.nufx.NuFX;
|
||||
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class AppleDisk implements Disk
|
||||
|
@ -38,13 +40,19 @@ public class AppleDisk implements Disk
|
|||
private final int trackSize; // 4096
|
||||
public int sectorSize; // 256 or 512
|
||||
|
||||
private NuFX nuFX;
|
||||
private Binary2 bin2;
|
||||
private WozFile wozFile;
|
||||
private PrefixDiskCopy prefixDiskCopy;
|
||||
private Prefix2mg prefix2mg;
|
||||
|
||||
private int interleave = 0;
|
||||
private static int[][] interleaveSector = //
|
||||
{ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
|
||||
22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }, // None
|
||||
{ 0, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 15 }, // Prodos/Pascal
|
||||
{ 0, 13, 11, 9, 7, 5, 3, 1, 14, 12, 10, 8, 6, 4, 2, 15 }, // Infocom
|
||||
{ 0, 6, 12, 3, 9, 15, 14, 5, 11, 2, 8, 7, 13, 4, 10, 1 } }; // CPM
|
||||
{ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, //
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }, // None
|
||||
{ 0, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 15 }, // Prodos/Pascal
|
||||
{ 0, 13, 11, 9, 7, 5, 3, 1, 14, 12, 10, 8, 6, 4, 2, 15 }, // Infocom
|
||||
{ 0, 6, 12, 3, 9, 15, 14, 5, 11, 2, 8, 7, 13, 4, 10, 1 } }; // CPM
|
||||
|
||||
// Physical disk interleave:
|
||||
// Info from http://www.applelogic.org/TheAppleIIEGettingStarted.html
|
||||
|
@ -83,8 +91,6 @@ public class AppleDisk implements Disk
|
|||
private ActionListener actionListenerList;
|
||||
private List<DiskAddress> blockList;
|
||||
|
||||
private WozFile wozFile;
|
||||
|
||||
private final boolean debug = false;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -95,8 +101,7 @@ public class AppleDisk implements Disk
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public AppleDisk (File file, int tracks, int sectors, int skip)
|
||||
throws FileFormatException
|
||||
public AppleDisk (File file, int tracks, int sectors, int skip) throws FileFormatException
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
assert (file.exists ()) : "No such path :" + file.getAbsolutePath ();
|
||||
|
@ -114,15 +119,14 @@ public class AppleDisk implements Disk
|
|||
|
||||
if ("2mg".equalsIgnoreCase (suffix) || "2IMG".equals (prefix))
|
||||
{
|
||||
// System.out.println ("checking 2mg");
|
||||
if ("2IMG".equals (prefix))
|
||||
{
|
||||
Prefix2mg prefix2mg = new Prefix2mg (buffer);
|
||||
prefix2mg = new Prefix2mg (buffer);
|
||||
if (debug)
|
||||
System.out.println (prefix2mg);
|
||||
|
||||
if (prefix2mg.diskData > 0)
|
||||
this.blocks = prefix2mg.diskData / 4096 * 8; // reduce blocks to a multiple of 8
|
||||
if (prefix2mg.length > 0)
|
||||
this.blocks = prefix2mg.length / 4096 * 8; // reduce blocks to a multiple of 8
|
||||
|
||||
this.sectorSize = 512;
|
||||
this.trackSize = 8 * sectorSize;
|
||||
|
@ -143,7 +147,7 @@ public class AppleDisk implements Disk
|
|||
}
|
||||
else if ("img".equals (suffix) || "dimg".equals (suffix))
|
||||
{
|
||||
PrefixDiskCopy prefixDiskCopy = new PrefixDiskCopy (buffer);
|
||||
prefixDiskCopy = new PrefixDiskCopy (buffer);
|
||||
|
||||
blocks = prefixDiskCopy.getBlocks ();
|
||||
this.sectorSize = 512;
|
||||
|
@ -153,7 +157,7 @@ public class AppleDisk implements Disk
|
|||
tracks = blocks / 8; // change parameter!
|
||||
sectors = 8; // change parameter!
|
||||
}
|
||||
else if (suffix.equalsIgnoreCase ("HDV")
|
||||
else if (suffix.equalsIgnoreCase ("HDV") //
|
||||
|| (suffix.equalsIgnoreCase ("po") && tracks > 50)) // ULTIMATE APPLE1 CFFA 3.5.po
|
||||
{
|
||||
//this.blocks = (int) file.length () / 4096 * 8; // reduce blocks to a multiple of 8
|
||||
|
@ -161,7 +165,7 @@ public class AppleDisk implements Disk
|
|||
this.sectorSize = 512;
|
||||
this.trackSize = sectors * sectorSize;
|
||||
}
|
||||
else if (file.length () == 143360 && tracks == 256 && sectors == 8) // wiz4
|
||||
else if (file.length () == 143360 && tracks == 256 && sectors == 8) // wiz4 or wiz5
|
||||
{
|
||||
this.blocks = tracks * sectors;
|
||||
this.sectorSize = 512;
|
||||
|
@ -233,12 +237,27 @@ public class AppleDisk implements Disk
|
|||
checkSectorsForData ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void setNuFX (NuFX nufx)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.nuFX = nufx;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void setBinary2 (Binary2 bin2)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.bin2 = bin2;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public AppleDisk (V2dFile disk, int tracks, int sectors)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.tracks = tracks;
|
||||
this.sectors = sectors;
|
||||
|
||||
file = disk.file;
|
||||
diskBuffer = disk.getDiskBuffer ();
|
||||
|
||||
|
@ -343,7 +362,6 @@ public class AppleDisk implements Disk
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.dosVersion = version;
|
||||
// System.out.printf ("DOS version %02X%n", version);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -449,6 +467,7 @@ public class AppleDisk implements Disk
|
|||
readBuffer (da, buffer, ptr);
|
||||
ptr += sectorSize;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -537,8 +556,7 @@ public class AppleDisk implements Disk
|
|||
{
|
||||
if (!isValidAddress (block))
|
||||
{
|
||||
System.out.printf ("getDiskAddress: Invalid block : %d of %d%n", block,
|
||||
this.blocks);
|
||||
System.out.printf ("getDiskAddress: Invalid block : %d of %d%n", block, this.blocks);
|
||||
return null;
|
||||
// return new AppleDiskAddress (this, 0); // this was looping 26/07/2016
|
||||
}
|
||||
|
@ -604,10 +622,9 @@ public class AppleDisk implements Disk
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
assert da.getDisk () == this : "Disk address not applicable to this disk";
|
||||
assert sectorSize == SECTOR_SIZE
|
||||
|| sectorSize == BLOCK_SIZE : "Invalid sector size : " + sectorSize;
|
||||
assert interleave >= 0 && interleave <= MAX_INTERLEAVE : "Invalid interleave : "
|
||||
+ interleave;
|
||||
assert sectorSize == SECTOR_SIZE || sectorSize == BLOCK_SIZE : "Invalid sector size : "
|
||||
+ sectorSize;
|
||||
assert interleave >= 0 && interleave <= MAX_INTERLEAVE : "Invalid interleave : " + interleave;
|
||||
|
||||
if (sectorSize == SECTOR_SIZE)
|
||||
{
|
||||
|
@ -620,8 +637,7 @@ public class AppleDisk implements Disk
|
|||
System.arraycopy (diskBuffer, diskOffset, buffer, bufferOffset, SECTOR_SIZE);
|
||||
|
||||
diskOffset = getBufferOffset (da, 1);
|
||||
System.arraycopy (diskBuffer, diskOffset, buffer, bufferOffset + SECTOR_SIZE,
|
||||
SECTOR_SIZE);
|
||||
System.arraycopy (diskBuffer, diskOffset, buffer, bufferOffset + SECTOR_SIZE, SECTOR_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -630,10 +646,9 @@ public class AppleDisk implements Disk
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
assert da.getDisk () == this : "Disk address not applicable to this disk";
|
||||
assert sectorSize == SECTOR_SIZE
|
||||
|| sectorSize == BLOCK_SIZE : "Invalid sector size : " + sectorSize;
|
||||
assert interleave >= 0 && interleave <= MAX_INTERLEAVE : "Invalid interleave : "
|
||||
+ interleave;
|
||||
assert sectorSize == SECTOR_SIZE || sectorSize == BLOCK_SIZE : "Invalid sector size : "
|
||||
+ sectorSize;
|
||||
assert interleave >= 0 && interleave <= MAX_INTERLEAVE : "Invalid interleave : " + interleave;
|
||||
|
||||
if (sectorSize == SECTOR_SIZE)
|
||||
{
|
||||
|
@ -650,6 +665,13 @@ public class AppleDisk implements Disk
|
|||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public byte[] getBuffer ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return diskBuffer;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private int getBufferOffset (DiskAddress da)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -698,11 +720,11 @@ public class AppleDisk implements Disk
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public AppleFileSource getDetails ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return new DefaultAppleFileSource (toString (), file.getName (), null);
|
||||
}
|
||||
// private AppleFileSource getDetails ()
|
||||
// // ---------------------------------------------------------------------------------//
|
||||
// {
|
||||
// return new DefaultAppleFileSource (toString (), file.getName (), null);
|
||||
// }
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
|
@ -711,28 +733,29 @@ public class AppleDisk implements Disk
|
|||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
String path = file.getAbsolutePath ();
|
||||
String home = System.getProperty ("user.home");
|
||||
if (path.startsWith (home))
|
||||
path = "~" + path.substring (home.length ());
|
||||
|
||||
text.append (String.format ("Path................. %s%n", path));
|
||||
text.append (String.format ("File name............ %s%n", file.getName ()));
|
||||
text.append (String.format ("File size............ %,d%n", file.length ()));
|
||||
text.append (String.format ("Tracks............... %d%n", tracks));
|
||||
text.append (String.format ("Sectors.............. %d%n", sectors));
|
||||
text.append (String.format ("Blocks............... %,d%n", blocks));
|
||||
text.append (String.format ("Track size........... %,d%n", trackSize));
|
||||
text.append (String.format ("Sector size.......... %d%n", sectorSize));
|
||||
text.append (String.format ("Interleave........... %d", interleave));
|
||||
text.append (
|
||||
String.format ("Path ......... %s%n", Utility.getShortPath (file.getAbsolutePath ())));
|
||||
text.append (String.format ("File name .... %s%n", file.getName ()));
|
||||
text.append (String.format ("File size .... %,d%n", file.length ()));
|
||||
text.append (String.format ("Tracks ....... %d%n", tracks));
|
||||
text.append (String.format ("Sectors ...... %d%n", sectors));
|
||||
text.append (String.format ("Blocks ....... %,d%n", blocks));
|
||||
text.append (String.format ("Track size ... %,d%n", trackSize));
|
||||
text.append (String.format ("Sector size .. %d%n", sectorSize));
|
||||
text.append (String.format ("Interleave ... %d%n%n", interleave));
|
||||
|
||||
if (wozFile != null)
|
||||
{
|
||||
text.append ("\n\n");
|
||||
text.append (wozFile);
|
||||
}
|
||||
else if (nuFX != null)
|
||||
text.append (nuFX);
|
||||
else if (bin2 != null)
|
||||
text.append (bin2);
|
||||
else if (prefixDiskCopy != null)
|
||||
text.append (prefixDiskCopy);
|
||||
else if (prefix2mg != null)
|
||||
text.append (prefix2mg);
|
||||
|
||||
return text.toString ();
|
||||
return Utility.rtrim (text).toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
|
@ -49,8 +49,8 @@ public class DefaultAppleFileSource implements AppleFileSource
|
|||
{
|
||||
this (title, file, owner);
|
||||
this.blocks = blocks;
|
||||
if (file instanceof DefaultDataSource)
|
||||
((DefaultDataSource) file).buffer = owner.getDisk ().readBlocks (blocks);
|
||||
if (file instanceof DefaultDataSource dds)
|
||||
dds.buffer = owner.getDisk ().readBlocks (blocks);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -58,8 +58,8 @@ public class DefaultAppleFileSource implements AppleFileSource
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.blocks = blocks;
|
||||
if (file instanceof DefaultDataSource)
|
||||
((DefaultDataSource) file).buffer = owner.getDisk ().readBlocks (blocks);
|
||||
if (file instanceof DefaultDataSource dds)
|
||||
dds.buffer = owner.getDisk ().readBlocks (blocks);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
|
@ -14,6 +14,7 @@ public class DefaultDataSource implements DataSource
|
|||
{
|
||||
public String text;
|
||||
byte[] buffer;
|
||||
Object textSource;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public DefaultDataSource (String text)
|
||||
|
@ -22,6 +23,13 @@ public class DefaultDataSource implements DataSource
|
|||
this.text = text;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public DefaultDataSource (Object textSource)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.textSource = textSource;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String getAssembler ()
|
||||
|
@ -40,6 +48,14 @@ public class DefaultDataSource implements DataSource
|
|||
return null;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public byte[] getBuffer ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public BufferedImage getImage ()
|
||||
|
@ -53,7 +69,7 @@ public class DefaultDataSource implements DataSource
|
|||
public String getText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return text;
|
||||
return textSource == null ? text : textSource.toString ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -61,7 +77,6 @@ public class DefaultDataSource implements DataSource
|
|||
public JComponent getComponent ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
System.out.println ("In DefaultDataSource.getComponent()");
|
||||
JPanel panel = new JPanel ();
|
||||
return panel;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.bytezone.diskbrowser.disk;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -18,10 +19,12 @@ import com.bytezone.diskbrowser.infocom.InfocomDisk;
|
|||
import com.bytezone.diskbrowser.nib.NibFile;
|
||||
import com.bytezone.diskbrowser.nib.V2dFile;
|
||||
import com.bytezone.diskbrowser.nib.WozFile;
|
||||
import com.bytezone.diskbrowser.nufx.Binary2;
|
||||
import com.bytezone.diskbrowser.nufx.NuFX;
|
||||
import com.bytezone.diskbrowser.pascal.PascalDisk;
|
||||
import com.bytezone.diskbrowser.prodos.ProdosDisk;
|
||||
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
||||
import com.bytezone.diskbrowser.utilities.NuFX;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
import com.bytezone.diskbrowser.wizardry.Wizardry4BootDisk;
|
||||
import com.bytezone.diskbrowser.wizardry.WizardryScenarioDisk;
|
||||
|
@ -32,6 +35,13 @@ public class DiskFactory
|
|||
{
|
||||
private static boolean debug = false;
|
||||
|
||||
private static final int DISK_800K = 819200;
|
||||
private static final int DISK_143K = 143360;
|
||||
private static final int DISK_116K = 116480;
|
||||
|
||||
private static NuFX nuFX;
|
||||
private static Binary2 binary2;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private DiskFactory ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -48,23 +58,13 @@ public class DiskFactory
|
|||
// ---------------------------------------------------------------------------------//
|
||||
public static FormattedDisk createDisk (String pathName)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
FormattedDisk disk = create (pathName);
|
||||
// if (disk.getDisk ().getInterleave () > 0)
|
||||
// {
|
||||
// System.out.println (disk);
|
||||
// System.out.println ();
|
||||
// }
|
||||
return disk;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private static FormattedDisk create (String pathName)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (debug)
|
||||
System.out.println ("\nFactory : " + pathName);
|
||||
|
||||
nuFX = null;
|
||||
binary2 = null;
|
||||
|
||||
File file = new File (pathName);
|
||||
if (!file.exists ())
|
||||
return null;
|
||||
|
@ -98,7 +98,7 @@ public class DiskFactory
|
|||
}
|
||||
catch (IOException e) // can get EOFException: Unexpected end of ZLIB input stream
|
||||
{
|
||||
e.printStackTrace ();
|
||||
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -141,20 +141,26 @@ public class DiskFactory
|
|||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace ();
|
||||
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if ("sdk".equals (suffix) || "shk".equals (suffix)) // shrinkit disk/file archive
|
||||
if ("sdk".equals (suffix) // NuFX disk
|
||||
|| "shk".equals (suffix) // NuFX files or disk
|
||||
|| "bxy".equals (suffix)) // NuFX in Bin2
|
||||
{
|
||||
if (debug)
|
||||
System.out.println (" ** sdk/shk **");
|
||||
System.out.println (" ** sdk/shk/bxy **");
|
||||
try
|
||||
{
|
||||
NuFX nuFX = new NuFX (file.toPath ());
|
||||
nuFX = new NuFX (file.toPath ());
|
||||
if (nuFX.getTotalDisks () == 0 && nuFX.getTotalFiles () == 0)
|
||||
{
|
||||
if (debug)
|
||||
System.out.println ("Empty NuFX file");
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] diskBuffer = nuFX.getDiskBuffer ();
|
||||
if (diskBuffer == null)
|
||||
|
@ -169,16 +175,54 @@ public class DiskFactory
|
|||
suffix = "dsk";
|
||||
compressed = true;
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace ();
|
||||
// e.printStackTrace ();
|
||||
if (e.getMessage () == null)
|
||||
System.out.println (e);
|
||||
else
|
||||
System.out.println (e.getMessage ());
|
||||
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
|
||||
// System.out.println (nuFX);
|
||||
return null;
|
||||
}
|
||||
catch (FileFormatException e)
|
||||
}
|
||||
else if ("bny".equals (suffix) || "bqy".equals (suffix)) // Binary2 uncompressed files
|
||||
{
|
||||
if (debug)
|
||||
System.out.println (" ** bny/bqy **");
|
||||
try
|
||||
{
|
||||
binary2 = new Binary2 (file.toPath ());
|
||||
byte[] diskBuffer = binary2.getDiskBuffer ();
|
||||
|
||||
File tmp = File.createTempFile (suffix, null);
|
||||
FileOutputStream fos = new FileOutputStream (tmp);
|
||||
fos.write (diskBuffer);
|
||||
fos.close ();
|
||||
|
||||
tmp.deleteOnExit ();
|
||||
file = tmp;
|
||||
suffix = "dsk";
|
||||
compressed = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// e.printStackTrace ();
|
||||
System.out.println (e.getMessage ());
|
||||
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
|
||||
// System.out.println (binary2);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if ("bsq".equals (suffix))
|
||||
{
|
||||
if (debug)
|
||||
System.out.println (" ** bsq **");
|
||||
byte[] prefix = getPrefix (file);
|
||||
System.out.println (HexFormatter.format (prefix));
|
||||
String key = "FiLeStArTfIlEsTaRt";
|
||||
}
|
||||
|
||||
FormattedDisk disk = null;
|
||||
FormattedDisk disk2 = null;
|
||||
|
@ -228,34 +272,34 @@ public class DiskFactory
|
|||
|
||||
// Toolkit.do = 143488
|
||||
if (((suffix.equals ("po") || suffix.equals ("dsk") || suffix.equals ("do"))
|
||||
&& file.length () > 143360))
|
||||
&& file.length () > DISK_143K))
|
||||
{
|
||||
if (file.length () < 143500) // slightly bigger than a floppy
|
||||
{
|
||||
System.out.println ("File length is wrong: " + file.length ());
|
||||
disk = checkDos (new AppleDisk (file, 35, 16));
|
||||
if (disk != null)
|
||||
return disk;
|
||||
return check (disk);
|
||||
}
|
||||
|
||||
if (debug)
|
||||
System.out.printf (" Checking po or dsk hard drive: %,d%n", file.length ());
|
||||
System.out.printf ("Checking po or dsk hard drive: %,d%n", file.length ());
|
||||
|
||||
disk = checkHardDisk (file);
|
||||
if (disk != null)
|
||||
{
|
||||
if (compressed)
|
||||
disk.setOriginalPath (originalPath);
|
||||
return disk;
|
||||
return check (disk);
|
||||
}
|
||||
|
||||
if (file.length () == 819200) // 800K 3.5"
|
||||
if (file.length () == DISK_800K) // 800K 3.5"
|
||||
{
|
||||
if (debug)
|
||||
System.out.println ("UniDos ?");
|
||||
// 2 x 400k disk images
|
||||
AppleDisk appleDisk1 = new AppleDisk (file, 50, 32);
|
||||
AppleDisk appleDisk2 = new AppleDisk (file, 50, 32, (int) (file.length () / 2));
|
||||
AppleDisk appleDisk2 = new AppleDisk (file, 50, 32, 0x64000);
|
||||
disk = checkUnidos (appleDisk1, 1);
|
||||
disk2 = checkUnidos (appleDisk2, 2);
|
||||
if (disk != null && disk2 != null)
|
||||
|
@ -306,9 +350,10 @@ public class DiskFactory
|
|||
{
|
||||
if (debug)
|
||||
System.out.println (" --> PRODOS hard disk");
|
||||
return new ProdosDisk (disk800);
|
||||
disk = new ProdosDisk (disk800);
|
||||
}
|
||||
disk = new DataDisk (disk800);
|
||||
else
|
||||
disk = new DataDisk (disk800);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -316,11 +361,15 @@ public class DiskFactory
|
|||
disk = checkDos (appleDisk256);
|
||||
if (disk == null)
|
||||
disk = checkProdos (new AppleDisk (wozFile, 35, 8));
|
||||
if (disk == null)
|
||||
disk = checkPascalDisk (new AppleDisk (wozFile, 35, 8));
|
||||
if (disk == null)
|
||||
disk = new DataDisk (appleDisk256);
|
||||
}
|
||||
}
|
||||
|
||||
disk.setOriginalPath (originalPath); // allow Save converted disk...
|
||||
|
||||
return disk;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -355,7 +404,7 @@ public class DiskFactory
|
|||
|
||||
long length = file.length ();
|
||||
|
||||
if (length == 116480) // 13 sector disk
|
||||
if (length == DISK_116K) // 13 sector floppy disk
|
||||
{
|
||||
if (debug)
|
||||
System.out.println (" ** 13 sector **");
|
||||
|
@ -367,7 +416,7 @@ public class DiskFactory
|
|||
return disk == null ? new DataDisk (appleDisk) : disk;
|
||||
}
|
||||
|
||||
if (length != 143360)
|
||||
if (length != DISK_143K) // 16 sector floppy disk
|
||||
{
|
||||
System.out.printf ("%s: invalid file length : %,d%n", file.getName (),
|
||||
file.length ());
|
||||
|
@ -379,7 +428,7 @@ public class DiskFactory
|
|||
|
||||
if (true)
|
||||
{
|
||||
// long checksum = appleDisk256.getBootChecksum ();
|
||||
// long checksum = appleDisk256.getBootChecksum ();
|
||||
long checksum = 0;
|
||||
|
||||
if (checksum == 227968344L) // empty boot sector
|
||||
|
@ -404,7 +453,7 @@ public class DiskFactory
|
|||
if (debug)
|
||||
System.out.println (" known DOS checksum : " + checksum);
|
||||
disk = checkDos (appleDisk256);
|
||||
// disk2 = checkProdos (appleDisk512); // no need for this
|
||||
// disk2 = checkProdos (appleDisk512); // no need for this
|
||||
if (disk2 != null && disk != null) // should be impossible
|
||||
{
|
||||
if (debug)
|
||||
|
@ -450,17 +499,17 @@ public class DiskFactory
|
|||
else if (debug)
|
||||
System.out.println (" unknown checksum : " + checksum);
|
||||
|
||||
// else if (checksum == 1212926910L || checksum == 1365043894L
|
||||
// || checksum == 2128073918L)
|
||||
// disk = checkCPMDisk (file);
|
||||
// else if (checksum == 1212926910L || checksum == 1365043894L
|
||||
// || checksum == 2128073918L)
|
||||
// disk = checkCPMDisk (file);
|
||||
|
||||
// System.out.println (checksum);
|
||||
// System.out.println (checksum);
|
||||
|
||||
if (disk != null)
|
||||
{
|
||||
if (compressed)
|
||||
disk.setOriginalPath (originalPath);
|
||||
return disk;
|
||||
return check (disk);
|
||||
}
|
||||
|
||||
// empty boot sector
|
||||
|
@ -536,6 +585,21 @@ public class DiskFactory
|
|||
if (disk != null && compressed)
|
||||
disk.setOriginalPath (originalPath);
|
||||
|
||||
return check (disk);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private static FormattedDisk check (FormattedDisk disk)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (disk.getDisk () instanceof AppleDisk appleDisk)
|
||||
{
|
||||
if (nuFX != null)
|
||||
appleDisk.setNuFX (nuFX);
|
||||
else if (binary2 != null)
|
||||
appleDisk.setBinary2 (binary2);
|
||||
}
|
||||
|
||||
return disk;
|
||||
}
|
||||
|
||||
|
@ -553,7 +617,7 @@ public class DiskFactory
|
|||
if (debug)
|
||||
System.out.println (" --> DOS");
|
||||
DosDisk dosDisk = new DosDisk (disk);
|
||||
// disk.setDosVersion (dosDisk.getVersion ());
|
||||
// disk.setDosVersion (dosDisk.getVersion ());
|
||||
|
||||
return dosDisk;
|
||||
}
|
||||
|
@ -622,7 +686,7 @@ public class DiskFactory
|
|||
{
|
||||
if (debug)
|
||||
{
|
||||
System.out.println ("\nChecking Prodos hard disk");
|
||||
System.out.println ("\nChecking Prodos/Pascal hard disk");
|
||||
System.out.printf ("Total blocks : %f%n", (float) file.length () / 512);
|
||||
System.out.printf ("Total tracks : %f%n", (float) file.length () / 4096);
|
||||
System.out.printf ("File length : %d%n", file.length ());
|
||||
|
@ -645,13 +709,19 @@ public class DiskFactory
|
|||
{
|
||||
System.out.println ("*** extended ***"); // System Addons.hdv
|
||||
}
|
||||
AppleDisk disk = new AppleDisk (file, tracks, 8);
|
||||
AppleDisk disk;
|
||||
// if (nuFX == null)
|
||||
disk = new AppleDisk (file, tracks, 8);
|
||||
// else
|
||||
// disk = new AppleDisk (file, tracks, 8, nuFX);
|
||||
|
||||
if (ProdosDisk.isCorrectFormat (disk))
|
||||
{
|
||||
if (debug)
|
||||
System.out.println (" --> PRODOS hard disk");
|
||||
return new ProdosDisk (disk);
|
||||
}
|
||||
|
||||
if (PascalDisk.isCorrectFormat (disk, debug))
|
||||
{
|
||||
if (debug)
|
||||
|
@ -662,11 +732,12 @@ public class DiskFactory
|
|||
catch (Exception e)
|
||||
{
|
||||
System.out.println (e);
|
||||
e.printStackTrace ();
|
||||
System.out.println ("Prodos hard disk had error");
|
||||
}
|
||||
|
||||
if (debug)
|
||||
System.out.println (" not a Prodos hard disk\n");
|
||||
System.out.println (" not a Prodos/Pascal hard disk\n");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -791,11 +862,16 @@ public class DiskFactory
|
|||
|
||||
if (Wizardry4BootDisk.isWizardryIVorV (disk, debug))
|
||||
{
|
||||
if (debug)
|
||||
System.out.println ("checking Wizardry IV or V");
|
||||
|
||||
String fileName = file.getAbsolutePath ().toLowerCase ();
|
||||
int pos = file.getAbsolutePath ().indexOf ('.');
|
||||
char c = fileName.charAt (pos - 1);
|
||||
// String suffix = fileName.substring (pos + 1);
|
||||
int requiredDisks = c == '1' ? 6 : c == 'a' ? 10 : 0;
|
||||
int pos = fileName.lastIndexOf ('.');
|
||||
char c = fileName.charAt (pos - 1); // '1' (wiz4) or 'a' (wiz5)
|
||||
int requiredDisks = c == '1' ? 7 : c == 'a' ? 10 : 0;
|
||||
|
||||
if (debug)
|
||||
System.out.printf ("Required disks: %d%n", requiredDisks);
|
||||
|
||||
if (requiredDisks > 0)
|
||||
{
|
||||
|
@ -816,7 +892,7 @@ public class DiskFactory
|
|||
}
|
||||
}
|
||||
if (debug)
|
||||
System.out.println ("Not a Wizardry IV disk");
|
||||
System.out.println ("Not a Wizardry IV or V disk");
|
||||
|
||||
PascalDisk pascalDisk = new PascalDisk (disk);
|
||||
return pascalDisk;
|
||||
|
@ -826,6 +902,9 @@ public class DiskFactory
|
|||
private static boolean collectDataDisks (String fileName, int dotPos, AppleDisk[] disks)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (debug)
|
||||
System.out.println ("Collecting Wizardry disks");
|
||||
|
||||
char c = fileName.charAt (dotPos - 1);
|
||||
String suffix = fileName.substring (dotPos + 1);
|
||||
|
||||
|
@ -833,14 +912,16 @@ public class DiskFactory
|
|||
{
|
||||
String old = new String (c + "." + suffix);
|
||||
String rep = new String ((char) (c + i - 1) + "." + suffix);
|
||||
|
||||
File f = new File (fileName.replace (old, rep));
|
||||
|
||||
if (debug)
|
||||
System.out.println (f);
|
||||
|
||||
if (!f.exists () || !f.isFile ())
|
||||
return false;
|
||||
|
||||
AppleDisk dataDisk = new AppleDisk (f, 35, 8);
|
||||
dataDisk.setInterleave (1);
|
||||
disks[i] = dataDisk;
|
||||
disks[i] = new AppleDisk (f, 35, 8);
|
||||
disks[i].setInterleave (1);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -881,4 +962,22 @@ public class DiskFactory
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private static byte[] getPrefix (File file)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
byte[] buffer = new byte[1024];
|
||||
try (BufferedInputStream bis = new BufferedInputStream (new FileInputStream (file)))
|
||||
{
|
||||
bis.read (buffer);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace ();
|
||||
System.exit (1);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
|
@ -81,7 +81,4 @@ public interface FormattedDisk
|
|||
public int falseNegativeBlocks ();
|
||||
|
||||
public String getName ();
|
||||
}
|
||||
|
||||
// getFileTypeList ()
|
||||
// getFiles (FileType type)
|
||||
}
|
|
@ -7,13 +7,25 @@ import com.bytezone.diskbrowser.utilities.Utility;
|
|||
public class Prefix2mg
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
String[] creators = { "!nfc", "B2TR", "CTKG", "CdrP", "ShIm", "WOOF", "XGS!" };
|
||||
String[] images = { "Dos3.3", "Prodos", "Nibbized" };
|
||||
|
||||
String prefix;
|
||||
String creator;
|
||||
int headerSize;
|
||||
int version;
|
||||
byte format;
|
||||
int diskData;
|
||||
int format;
|
||||
int flags;
|
||||
int length;
|
||||
int blocks;
|
||||
int offset;
|
||||
int commentOffset;
|
||||
int commentLength;
|
||||
int creatorOffset;
|
||||
int creatorLength;
|
||||
|
||||
boolean flagsLocked;
|
||||
int flagsVolume;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public Prefix2mg (byte[] buffer)
|
||||
|
@ -21,14 +33,29 @@ public class Prefix2mg
|
|||
{
|
||||
prefix = new String (buffer, 0, 4);
|
||||
creator = new String (buffer, 4, 4);
|
||||
headerSize = Utility.getWord (buffer, 8);
|
||||
version = Utility.getWord (buffer, 10);
|
||||
format = buffer[12];
|
||||
headerSize = Utility.getShort (buffer, 0x08);
|
||||
version = Utility.getShort (buffer, 0x0A);
|
||||
format = Utility.getLong (buffer, 0x0C);
|
||||
flags = Utility.getLong (buffer, 0x10);
|
||||
blocks = Utility.getLong (buffer, 0x14); // 1600
|
||||
offset = Utility.getLong (buffer, 0x18);
|
||||
length = Utility.getLong (buffer, 0x1C);
|
||||
commentOffset = Utility.getLong (buffer, 0x20);
|
||||
commentLength = Utility.getLong (buffer, 0x24);
|
||||
creatorOffset = Utility.getLong (buffer, 0x28);
|
||||
creatorLength = Utility.getLong (buffer, 0x2C);
|
||||
|
||||
diskData = Utility.getLong (buffer, 28);
|
||||
blocks = Utility.intValue (buffer[20], buffer[21]); // 1600
|
||||
flagsLocked = (flags & 0x80000000) != 0;
|
||||
if ((flags & 0x0100) != 0)
|
||||
flagsVolume = flags & 0xFF;
|
||||
if (format == 0 && flagsVolume == 0)
|
||||
flagsVolume = 254;
|
||||
|
||||
if (length == 0)
|
||||
length = 512 * blocks;
|
||||
|
||||
// see /Asimov disks/images/gs/os/prodos16/ProDOS 16v1_3.2mg
|
||||
// System.out.println (this);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -38,14 +65,21 @@ public class Prefix2mg
|
|||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
text.append (String.format ("Prefix : %s%n", prefix));
|
||||
text.append (String.format ("Creator : %s%n", creator));
|
||||
text.append (String.format ("Header : %d%n", headerSize));
|
||||
text.append (String.format ("Version : %d%n", version));
|
||||
text.append (String.format ("Format : %02X%n", format));
|
||||
|
||||
text.append (String.format ("Data size : %08X (%<,d)%n", diskData));
|
||||
text.append (String.format ("Blocks : %,d%n", blocks));
|
||||
text.append (String.format ("Prefix : %s%n", prefix));
|
||||
text.append (String.format ("Creator : %s%n", creator));
|
||||
text.append (String.format ("Header : %d%n", headerSize));
|
||||
text.append (String.format ("Version : %d%n", version));
|
||||
text.append (String.format ("Format : %02X%n", format));
|
||||
text.append (String.format ("Flags : %,d%n", flags));
|
||||
text.append (String.format ("Locked : %s%n", flagsLocked));
|
||||
text.append (String.format ("DOS Volume : %,d%n", flagsVolume));
|
||||
text.append (String.format ("Blocks : %,d%n", blocks));
|
||||
text.append (String.format ("Offset : %,d%n", offset));
|
||||
text.append (String.format ("Length : %08X (%<,d)%n", length));
|
||||
text.append (String.format ("Comment Offset : %,d%n", commentOffset));
|
||||
text.append (String.format ("Comment Length : %08X (%<,d)%n", commentLength));
|
||||
text.append (String.format ("Creator Offset : %,d%n", creatorOffset));
|
||||
text.append (String.format ("Creator Length : %08X (%<,d)", creatorLength));
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
|
|||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// https://www.discferret.com/wiki/Apple_DiskCopy_4.2
|
||||
// Apple II File Type Notes $E0/0005 (macintosh)
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class PrefixDiskCopy
|
||||
// -----------------------------------------------------------------------------------//
|
||||
|
@ -11,9 +12,11 @@ public class PrefixDiskCopy
|
|||
private String name;
|
||||
private int dataSize;
|
||||
private int tagSize;
|
||||
private int encoding;
|
||||
private int dataChecksum;
|
||||
private int tagChecksum;
|
||||
private int diskFormat;
|
||||
private int format;
|
||||
private int id;
|
||||
private int id; // should be 0x0100
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public PrefixDiskCopy (byte[] buffer)
|
||||
|
@ -24,9 +27,11 @@ public class PrefixDiskCopy
|
|||
name = HexFormatter.getPascalString (buffer, 0);
|
||||
dataSize = Utility.getLongBigEndian (buffer, 0x40);
|
||||
tagSize = Utility.getLongBigEndian (buffer, 0x44);
|
||||
encoding = buffer[0x50] & 0xFF;
|
||||
dataChecksum = Utility.getLongBigEndian (buffer, 0x48);
|
||||
tagChecksum = Utility.getLongBigEndian (buffer, 0x4C);
|
||||
diskFormat = buffer[0x50] & 0xFF;
|
||||
format = buffer[0x51] & 0xFF;
|
||||
id = Utility.getWordBigEndian (buffer, 0x52);
|
||||
id = Utility.getShortBigEndian (buffer, 0x52);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -43,12 +48,14 @@ public class PrefixDiskCopy
|
|||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
text.append (String.format ("Name : %s%n", name));
|
||||
text.append (String.format ("Data size : %08X (%<,d)%n", dataSize));
|
||||
text.append (String.format ("Tag size : %08X (%<,d)%n", tagSize));
|
||||
text.append (String.format ("Encoding : %02X%n", encoding));
|
||||
text.append (String.format ("Format : %02X%n", format));
|
||||
text.append (String.format ("ID : %04X%n", id));
|
||||
text.append (String.format ("Name : %s%n", name));
|
||||
text.append (String.format ("Data size : %08X (%<,d)%n", dataSize));
|
||||
text.append (String.format ("Tag size : %08X (%<,d)%n", tagSize));
|
||||
text.append (String.format ("Data checksum : %08X (%<,d)%n", dataChecksum));
|
||||
text.append (String.format ("Tag checksum : %08X (%<,d)%n", tagChecksum));
|
||||
text.append (String.format ("Disk format : %02X%n", diskFormat));
|
||||
text.append (String.format ("Format byte : %02X%n", format));
|
||||
text.append (String.format ("ID : %04X%n", id));
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
|
|
@ -17,8 +17,7 @@ public class SectorListConverter
|
|||
sectors = new ArrayList<> ();
|
||||
sectorText = text;
|
||||
|
||||
String[] blocks = text.split (";");
|
||||
for (String s : blocks)
|
||||
for (String s : text.split (";"))
|
||||
{
|
||||
int pos = s.indexOf ('-');
|
||||
if (pos > 0)
|
||||
|
|
|
@ -67,7 +67,7 @@ abstract class AbstractCatalogEntry implements AppleFileSource
|
|||
this.catalogSectorDA = catalogSector;
|
||||
|
||||
name = getName ("", entryBuffer);
|
||||
reportedSize = Utility.unsignedShort (entryBuffer, 33);
|
||||
reportedSize = Utility.getShort (entryBuffer, 33);
|
||||
|
||||
int type = entryBuffer[2] & 0x7F;
|
||||
locked = (entryBuffer[2] & 0x80) != 0;
|
||||
|
@ -89,8 +89,8 @@ abstract class AbstractCatalogEntry implements AppleFileSource
|
|||
lastModified = Utility.getDateTime (entryBuffer, 0x1B);
|
||||
|
||||
// CATALOG command only formats the LO byte - see Beneath Apple DOS pp4-6
|
||||
String base = String.format ("%s%s %03d ", locked ? "*" : " ", getFileType (),
|
||||
reportedSize & 0xFF);
|
||||
String base =
|
||||
String.format ("%s%s %03d ", locked ? "*" : " ", getFileType (), reportedSize & 0xFF);
|
||||
catalogName = getName (base, entryBuffer);
|
||||
displayName = getDisplayName (entryBuffer);
|
||||
}
|
||||
|
@ -234,30 +234,40 @@ abstract class AbstractCatalogEntry implements AppleFileSource
|
|||
break;
|
||||
|
||||
case IntegerBasic:
|
||||
reportedLength = Utility.unsignedShort (buffer, 0);
|
||||
exactBuffer = new byte[reportedLength];
|
||||
System.arraycopy (buffer, 2, exactBuffer, 0, reportedLength);
|
||||
appleFile = new IntegerBasicProgram (name, exactBuffer);
|
||||
reportedLength = Utility.getShort (buffer, 0);
|
||||
if (reportedLength > 0)
|
||||
{
|
||||
exactBuffer = new byte[reportedLength];
|
||||
System.arraycopy (buffer, 2, exactBuffer, 0, reportedLength);
|
||||
appleFile = new IntegerBasicProgram (name, exactBuffer);
|
||||
}
|
||||
else
|
||||
appleFile = new DefaultAppleFile (name, buffer);
|
||||
break;
|
||||
|
||||
case ApplesoftBasic:
|
||||
reportedLength = Utility.unsignedShort (buffer, 0);
|
||||
exactBuffer = new byte[reportedLength];
|
||||
if (reportedLength > buffer.length)
|
||||
reportedLength = buffer.length - 2;
|
||||
System.arraycopy (buffer, 2, exactBuffer, 0, reportedLength);
|
||||
appleFile = new ApplesoftBasicProgram (name, exactBuffer);
|
||||
reportedLength = Utility.getShort (buffer, 0);
|
||||
if (reportedLength > 0)
|
||||
{
|
||||
exactBuffer = new byte[reportedLength];
|
||||
if (reportedLength > buffer.length)
|
||||
reportedLength = buffer.length - 2;
|
||||
System.arraycopy (buffer, 2, exactBuffer, 0, reportedLength);
|
||||
appleFile = new ApplesoftBasicProgram (name, exactBuffer);
|
||||
}
|
||||
else
|
||||
appleFile = new DefaultAppleFile (name, buffer);
|
||||
break;
|
||||
|
||||
case Binary: // binary file
|
||||
case Relocatable: // relocatable binary file
|
||||
case BB:
|
||||
int loadAddress = Utility.unsignedShort (buffer, 0);
|
||||
reportedLength = Utility.unsignedShort (buffer, 2);
|
||||
int loadAddress = Utility.getShort (buffer, 0);
|
||||
reportedLength = Utility.getShort (buffer, 2);
|
||||
if (reportedLength == 0)
|
||||
{
|
||||
System.out.println (name.trim () + " reported length : 0 - reverting to "
|
||||
+ (buffer.length - 4));
|
||||
System.out.println (
|
||||
name.trim () + " reported length : 0 - reverting to " + (buffer.length - 4));
|
||||
reportedLength = buffer.length - 4;
|
||||
}
|
||||
|
||||
|
@ -268,9 +278,8 @@ abstract class AbstractCatalogEntry implements AppleFileSource
|
|||
exactBuffer = new byte[buffer.length - 4]; // reported length is too long
|
||||
System.arraycopy (buffer, 4, exactBuffer, 0, exactBuffer.length);
|
||||
|
||||
if ((name.endsWith (".FONT") || name.endsWith (" FONT")
|
||||
|| name.endsWith (".SET") || name.startsWith ("ASCII."))
|
||||
&& FontFile.isFont (exactBuffer))
|
||||
if ((name.endsWith (".FONT") || name.endsWith (" FONT") || name.endsWith (".SET")
|
||||
|| name.startsWith ("ASCII.")) && FontFile.isFont (exactBuffer))
|
||||
appleFile = new FontFile (name, exactBuffer, loadAddress);
|
||||
else if (name.endsWith (".MW"))
|
||||
appleFile = new MagicWindowText (name, exactBuffer);
|
||||
|
@ -305,8 +314,7 @@ abstract class AbstractCatalogEntry implements AppleFileSource
|
|||
appleFile = new AssemblerProgram (name, exactBuffer, loadAddress);
|
||||
}
|
||||
else if (reportedLength == 0x240 //
|
||||
&& (loadAddress == 0x5800 || loadAddress == 0x6000
|
||||
|| loadAddress == 0x7800))
|
||||
&& (loadAddress == 0x5800 || loadAddress == 0x6000 || loadAddress == 0x7800))
|
||||
appleFile = new PrintShopGraphic (name, exactBuffer);
|
||||
else if (isRunCommand (exactBuffer))
|
||||
{
|
||||
|
@ -319,8 +327,8 @@ abstract class AbstractCatalogEntry implements AppleFileSource
|
|||
{
|
||||
appleFile = new AssemblerProgram (name, exactBuffer, loadAddress);
|
||||
if ((exactBuffer.length + 4) < buffer.length)
|
||||
((AssemblerProgram) appleFile).setExtraBuffer (buffer,
|
||||
exactBuffer.length + 4, buffer.length - (exactBuffer.length + 4));
|
||||
((AssemblerProgram) appleFile).setExtraBuffer (buffer, exactBuffer.length + 4,
|
||||
buffer.length - (exactBuffer.length + 4));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -359,11 +367,11 @@ abstract class AbstractCatalogEntry implements AppleFileSource
|
|||
{
|
||||
byte[] exactBuffer;
|
||||
|
||||
int reportedLength = Utility.unsignedShort (buffer, 2);
|
||||
int reportedLength = Utility.getShort (buffer, 2);
|
||||
if (reportedLength == 0)
|
||||
{
|
||||
System.out.println (
|
||||
name.trim () + " reported length : 0 - reverting to " + (buffer.length - 4));
|
||||
System.out
|
||||
.println (name.trim () + " reported length : 0 - reverting to " + (buffer.length - 4));
|
||||
reportedLength = buffer.length - 4;
|
||||
}
|
||||
|
||||
|
|
|
@ -131,12 +131,12 @@ class CatalogEntry extends AbstractCatalogEntry
|
|||
{
|
||||
case IntegerBasic:
|
||||
case ApplesoftBasic:
|
||||
length = Utility.intValue (buffer[0], buffer[1]);
|
||||
length = Utility.getShort (buffer, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
address = Utility.intValue (buffer[0], buffer[1]);
|
||||
length = Utility.intValue (buffer[2], buffer[3]);
|
||||
address = Utility.getShort (buffer, 0);
|
||||
length = Utility.getShort (buffer, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -326,6 +326,8 @@ public class DosDisk extends AbstractFormattedDisk
|
|||
return "4.2";
|
||||
case 0x43:
|
||||
return "4.3";
|
||||
case 0x45:
|
||||
return "4.5";
|
||||
default:
|
||||
return "??";
|
||||
}
|
||||
|
@ -376,7 +378,7 @@ public class DosDisk extends AbstractFormattedDisk
|
|||
int version = buffer[3] & 0xFF;
|
||||
if (debug)
|
||||
System.out.printf ("Version: %02X%n", buffer[3]);
|
||||
if (version == 0 || (version > 0x43 && version != 0xFF))
|
||||
if (version == 0 || (version > 0x45 && version != 0xFF))
|
||||
{
|
||||
if (debug)
|
||||
System.out.printf ("Bad version : %02X%n", version);
|
||||
|
|
|
@ -82,7 +82,7 @@ class DosTSListSector extends AbstractSector
|
|||
addText (text, buffer, 7, 4, "Not used");
|
||||
addText (text, buffer, 11, 1, "Not used");
|
||||
|
||||
int sectorBase = Utility.intValue (buffer[5], buffer[6]);
|
||||
int sectorBase = Utility.getShort (buffer, 5);
|
||||
|
||||
for (int i = 12; i <= 255; i += 2)
|
||||
{
|
||||
|
|
|
@ -35,7 +35,7 @@ class DosVTOCSector extends AbstractSector
|
|||
direction = buffer[49];
|
||||
maxTracks = buffer[52] & 0xFF;
|
||||
maxSectors = buffer[53] & 0xFF;
|
||||
sectorSize = Utility.intValue (buffer[54], buffer[55]);
|
||||
sectorSize = Utility.getShort (buffer, 54);
|
||||
|
||||
flagSectors ();
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ public class DisksWindow extends JFrame
|
|||
}
|
||||
});
|
||||
|
||||
scrollPane.setPreferredSize (new Dimension (1200, 700));
|
||||
scrollPane.setPreferredSize (new Dimension (1200, 693));
|
||||
setDefaultCloseOperation (HIDE_ON_CLOSE);
|
||||
|
||||
deleteWindow = new DeleteWindow (rootFolderData);
|
||||
|
@ -188,11 +188,11 @@ public class DisksWindow extends JFrame
|
|||
}
|
||||
});
|
||||
|
||||
for (int i = 0; i < Utility.suffixes.size (); i++)
|
||||
for (int i = 0; i < Utility.getTotalSuffixes (); i++)
|
||||
{
|
||||
int total = rootFolderData.getTotalType (i);
|
||||
JCheckBox btn =
|
||||
new JCheckBox (String.format ("%s (%,d)", Utility.suffixes.get (i), total));
|
||||
new JCheckBox (String.format ("%s (%,d)", Utility.getSuffix (i), total));
|
||||
topPanel.add (btn);
|
||||
boxes.add (btn);
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ import java.awt.Graphics;
|
|||
import java.awt.Graphics2D;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -20,11 +22,10 @@ import javax.swing.JFrame;
|
|||
import javax.swing.JPanel;
|
||||
|
||||
import com.bytezone.diskbrowser.gui.DuplicateAction.DiskTableSelectionListener;
|
||||
import com.bytezone.diskbrowser.gui.RootDirectoryChangeListener;
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class RootFolderData implements RootDirectoryChangeListener
|
||||
public class RootFolderData implements PropertyChangeListener
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static final String header =
|
||||
|
@ -66,7 +67,7 @@ public class RootFolderData implements RootDirectoryChangeListener
|
|||
btnOK = new JButton ("OK");
|
||||
|
||||
progressPanel = new ProgressPanel ();
|
||||
progressPanel.setPreferredSize (new Dimension (560, 340));
|
||||
progressPanel.setPreferredSize (new Dimension (560, 380));
|
||||
|
||||
dialogTotals = new JFrame ("Disk Totals");
|
||||
dialogTotals.add (progressPanel, BorderLayout.CENTER);
|
||||
|
@ -154,7 +155,7 @@ public class RootFolderData implements RootDirectoryChangeListener
|
|||
private void clear ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
typeTotals = new int[4][Utility.suffixes.size ()];
|
||||
typeTotals = new int[4][Utility.getTotalSuffixes ()];
|
||||
totalDisks = 0;
|
||||
totalFolders = 0;
|
||||
|
||||
|
@ -177,38 +178,35 @@ public class RootFolderData implements RootDirectoryChangeListener
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void incrementType (File file, String filename)
|
||||
public void incrementType (File file, String fileName)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int pos = Utility.getSuffixNo (filename);
|
||||
int pos = Utility.getSuffixNo (fileName);
|
||||
if (pos >= 0)
|
||||
{
|
||||
int cmp = 0;
|
||||
if (filename.endsWith (".gz"))
|
||||
cmp = 1;
|
||||
else if (filename.endsWith (".zip"))
|
||||
cmp = 2;
|
||||
int cmp = fileName.endsWith (".zip") ? 2 : fileName.endsWith (".gz") ? 1 : 0;
|
||||
|
||||
typeTotals[cmp][pos]++;
|
||||
typeTotals[3][pos]++;
|
||||
++totalDisks;
|
||||
}
|
||||
else
|
||||
System.out.println ("no suffix: " + filename);
|
||||
System.out.println ("no suffix: " + fileName);
|
||||
|
||||
checkDuplicates (file, filename);
|
||||
checkDuplicates (file, fileName);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void checkDuplicates (File file, String filename)
|
||||
private void checkDuplicates (File file, String fileName)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
String rootName = file.getAbsolutePath ().substring (rootFolderNameLength);
|
||||
DiskDetails diskDetails = new DiskDetails (file, rootName, filename, doChecksums);
|
||||
DiskDetails diskDetails = new DiskDetails (file, rootName, fileName, doChecksums);
|
||||
|
||||
if (fileNameMap.containsKey (filename))
|
||||
fileNameMap.get (filename).addDuplicateName (diskDetails);
|
||||
if (fileNameMap.containsKey (fileName))
|
||||
fileNameMap.get (fileName).addDuplicateName (diskDetails);
|
||||
else
|
||||
fileNameMap.put (filename, diskDetails);
|
||||
fileNameMap.put (fileName, diskDetails);
|
||||
|
||||
if (doChecksums)
|
||||
{
|
||||
|
@ -256,7 +254,7 @@ public class RootFolderData implements RootDirectoryChangeListener
|
|||
System.out.println (line);
|
||||
for (int i = 0; i < typeTotals[0].length; i++)
|
||||
{
|
||||
System.out.printf ("%14.14s ", Utility.suffixes.get (i) + " ...........");
|
||||
System.out.printf ("%14.14s ", Utility.getSuffix (i) + " ...........");
|
||||
for (int j = 0; j < typeTotals.length; j++)
|
||||
{
|
||||
System.out.printf ("%,7d ", typeTotals[j][i]);
|
||||
|
@ -277,8 +275,7 @@ public class RootFolderData implements RootDirectoryChangeListener
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void rootDirectoryChanged (File oldRootFolder, File newRootFolder)
|
||||
private void rootDirectoryChanged (File oldRootFolder, File newRootFolder)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
rootFolder = newRootFolder;
|
||||
|
@ -286,6 +283,15 @@ public class RootFolderData implements RootDirectoryChangeListener
|
|||
disksWindow = null; // force a recount
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void propertyChange (PropertyChangeEvent evt)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (evt.getPropertyName ().equals ("RootDirectory"))
|
||||
rootDirectoryChanged ((File) evt.getOldValue (), (File) evt.getNewValue ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public String toString ()
|
||||
|
@ -326,16 +332,16 @@ public class RootFolderData implements RootDirectoryChangeListener
|
|||
int grandTotal[] = new int[4];
|
||||
|
||||
for (int i = 0; i < typeTotals[0].length; i++)
|
||||
{
|
||||
line = String.format ("%14.14s %,7d %,7d %,7d %,7d",
|
||||
Utility.suffixes.get (i) + " ...........", typeTotals[0][i], typeTotals[1][i],
|
||||
typeTotals[2][i], typeTotals[3][i]);
|
||||
g.drawString (line, x, y);
|
||||
for (int j = 0; j < typeTotals.length; j++)
|
||||
grandTotal[j] += typeTotals[j][i];
|
||||
|
||||
y += lineHeight;
|
||||
}
|
||||
if (typeTotals[3][i] > 0)
|
||||
{
|
||||
line = String.format ("%14.14s %,7d %,7d %,7d %,7d",
|
||||
Utility.getSuffix (i) + " ...........", typeTotals[0][i], typeTotals[1][i],
|
||||
typeTotals[2][i], typeTotals[3][i]);
|
||||
g.drawString (line, x, y);
|
||||
for (int j = 0; j < typeTotals.length; j++)
|
||||
grandTotal[j] += typeTotals[j][i];
|
||||
y += lineHeight;
|
||||
}
|
||||
|
||||
line = String.format ("Total %,7d %,7d %,7d %,7d%n%n", grandTotal[0],
|
||||
grandTotal[1], grandTotal[2], grandTotal[3]);
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package com.bytezone.diskbrowser.gui;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.DefaultAction;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public abstract class AbstractSaveAction extends DefaultAction
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
protected JFileChooser fileChooser = new JFileChooser ();
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public AbstractSaveAction (String menuText, String tip, String dialogTitle)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (menuText, tip);
|
||||
|
||||
fileChooser.setDialogTitle (dialogTitle);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void setSelectedFile (File file)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
fileChooser.setSelectedFile (file);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void saveBuffer (byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
File file = fileChooser.getSelectedFile ();
|
||||
try
|
||||
{
|
||||
Files.write (file.toPath (), buffer, StandardOpenOption.CREATE_NEW);
|
||||
JOptionPane.showMessageDialog (null, String.format ("File %s saved", file.getName ()));
|
||||
}
|
||||
catch (FileAlreadyExistsException e)
|
||||
{
|
||||
JOptionPane.showMessageDialog (null, "File " + file.getName () + " already exists", "Failed",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace ();
|
||||
JOptionPane.showMessageDialog (null, "File failed to save - " + e.getMessage (), "Failed",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package com.bytezone.diskbrowser.gui;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.SHRPictureFile2;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class AnimationWorker extends SwingWorker<Void, Integer>
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
volatile boolean running;
|
||||
SHRPictureFile2 image;
|
||||
OutputPanel owner;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public AnimationWorker (OutputPanel owner, SHRPictureFile2 image)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
assert image.isAnimation ();
|
||||
this.image = image;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void cancel ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
running = false;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
protected Void doInBackground () throws Exception
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
running = true;
|
||||
try
|
||||
{
|
||||
while (running)
|
||||
{
|
||||
Thread.sleep (image.getDelay ());
|
||||
publish (0);
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace ();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
protected void process (List<Integer> chunks)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
image.nextFrame ();
|
||||
owner.update ();
|
||||
}
|
||||
}
|
|
@ -158,9 +158,9 @@ class AppleDiskTab extends AbstractTab
|
|||
|
||||
// check for multi-volume disk (only search the current branch)
|
||||
FormattedDisk fd = ((AppleFileSource) rootNode.getUserObject ()).getFormattedDisk ();
|
||||
if (fd instanceof HybridDisk)
|
||||
if (fd instanceof HybridDisk hd)
|
||||
{
|
||||
int volume = ((HybridDisk) fd).getCurrentDiskNo ();
|
||||
int volume = hd.getCurrentDiskNo ();
|
||||
rootNode = (DefaultMutableTreeNode) rootNode.getChildAt (volume);
|
||||
}
|
||||
|
||||
|
@ -169,8 +169,8 @@ class AppleDiskTab extends AbstractTab
|
|||
{
|
||||
DefaultMutableTreeNode node = (DefaultMutableTreeNode) children.nextElement ();
|
||||
Object userObject = node.getUserObject ();
|
||||
if (userObject instanceof AppleFileSource
|
||||
&& nodeName.equals (((AppleFileSource) userObject).getUniqueName ()))
|
||||
if (userObject instanceof AppleFileSource afs
|
||||
&& nodeName.equals (afs.getUniqueName ()))
|
||||
return node;
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -26,7 +26,7 @@ public class BasicPreferences
|
|||
public boolean showConstants = false;
|
||||
public boolean showDuplicateSymbols = false;
|
||||
|
||||
public int wrapPrintAt = 0;
|
||||
public int wrapPrintAt = 80;
|
||||
public int wrapRemAt = 80;
|
||||
public int wrapDataAt = 80;
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ import java.awt.Dimension;
|
|||
import java.awt.Font;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EventObject;
|
||||
|
@ -36,9 +38,8 @@ import com.bytezone.diskbrowser.gui.RedoHandler.RedoListener;
|
|||
import com.bytezone.diskbrowser.gui.TreeBuilder.FileNode;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class CatalogPanel extends JTabbedPane
|
||||
implements RedoListener, SectorSelectionListener, QuitListener, FontChangeListener,
|
||||
RootDirectoryChangeListener, DiskTableSelectionListener
|
||||
class CatalogPanel extends JTabbedPane implements RedoListener, SectorSelectionListener,
|
||||
QuitListener, FontChangeListener, DiskTableSelectionListener, PropertyChangeListener
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static final String prefsLastDiskUsed = "Last disk used";
|
||||
|
@ -66,8 +67,7 @@ class CatalogPanel extends JTabbedPane
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void rootDirectoryChanged (File oldRootFolder, File newRootFolder)
|
||||
private void rootDirectoryChanged (File oldRootFolder, File newRootFolder)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
rootFolder = newRootFolder;
|
||||
|
@ -82,6 +82,18 @@ class CatalogPanel extends JTabbedPane
|
|||
setSelectedIndex (0);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void propertyChange (PropertyChangeEvent evt)
|
||||
// -------------------------------------------------------------------------------//
|
||||
{
|
||||
if (evt.getPropertyName ().equals ("RootDirectory"))
|
||||
rootDirectoryChanged ((File) evt.getOldValue (), (File) evt.getNewValue ());
|
||||
// else
|
||||
// closeCurrentTab ();
|
||||
// System.out.println (evt.getPropertyName ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void insertFileSystemTab (DiskSelectedEvent diskEvent)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -146,11 +158,10 @@ class CatalogPanel extends JTabbedPane
|
|||
tab.refresh ();
|
||||
|
||||
// Any newly created disk needs to appear in the FileSystemTab's tree
|
||||
if (tab instanceof AppleDiskTab)
|
||||
fileTab.replaceDisk (((AppleDiskTab) tab).disk);
|
||||
if (tab instanceof AppleDiskTab appleDiskTab)
|
||||
fileTab.replaceDisk (appleDiskTab.disk);
|
||||
}
|
||||
|
||||
// called from CloseTabAction
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void closeCurrentTab ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -174,10 +185,7 @@ class CatalogPanel extends JTabbedPane
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
Tab tab = (Tab) getSelectedComponent ();
|
||||
if (diskTabs.size () > 1 && tab instanceof AppleDiskTab)
|
||||
closeTabAction.setEnabled (true);
|
||||
else
|
||||
closeTabAction.setEnabled (false);
|
||||
closeTabAction.setEnabled (diskTabs.size () > 1 && tab instanceof AppleDiskTab);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -213,8 +221,8 @@ class CatalogPanel extends JTabbedPane
|
|||
|
||||
FormattedDisk fd = ((AppleDiskTab) selectedTab).disk;
|
||||
prefs.put (prefsLastDiskUsed, fd.getAbsolutePath ());
|
||||
if (fd instanceof HybridDisk)
|
||||
prefs.putInt (prefsLastDosUsed, ((HybridDisk) fd).getCurrentDiskNo ());
|
||||
if (fd instanceof HybridDisk hybridDisk)
|
||||
prefs.putInt (prefsLastDosUsed, hybridDisk.getCurrentDiskNo ());
|
||||
else
|
||||
prefs.putInt (prefsLastDosUsed, -1);
|
||||
|
||||
|
@ -223,16 +231,16 @@ class CatalogPanel extends JTabbedPane
|
|||
{
|
||||
EventObject event = redoEvent.value;
|
||||
|
||||
if (event instanceof FileSelectedEvent)
|
||||
if (event instanceof FileSelectedEvent fileSelectedEvent)
|
||||
{
|
||||
AppleFileSource afs = ((FileSelectedEvent) event).appleFileSource;
|
||||
AppleFileSource afs = fileSelectedEvent.appleFileSource;
|
||||
prefs.put (prefsLastFileUsed, afs == null ? "" : afs.getUniqueName ());
|
||||
prefs.put (prefsLastSectorsUsed, "");
|
||||
}
|
||||
else if (event instanceof SectorSelectedEvent)
|
||||
else if (event instanceof SectorSelectedEvent sectorSelectedEvent)
|
||||
{
|
||||
prefs.put (prefsLastFileUsed, "");
|
||||
prefs.put (prefsLastSectorsUsed, ((SectorSelectedEvent) event).toText ());
|
||||
prefs.put (prefsLastSectorsUsed, sectorSelectedEvent.toText ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -265,8 +273,8 @@ class CatalogPanel extends JTabbedPane
|
|||
if (diskEvent != null)
|
||||
{
|
||||
fd1 = diskEvent.getFormattedDisk ();
|
||||
if (lastDosUsed >= 0 && fd1 instanceof HybridDisk)
|
||||
((HybridDisk) fd1).setCurrentDiskNo (lastDosUsed);
|
||||
if (lastDosUsed >= 0 && fd1 instanceof HybridDisk hybridDisk)
|
||||
hybridDisk.setCurrentDiskNo (lastDosUsed);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -321,6 +329,14 @@ class CatalogPanel extends JTabbedPane
|
|||
selector.addDiskSelectionListener (listener);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void addDiskSelectionListener (DiskSelectionListener... listeners)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (DiskSelectionListener diskSelectionListener : listeners)
|
||||
selector.addDiskSelectionListener (diskSelectionListener);
|
||||
}
|
||||
|
||||
// Pass through to DiskSelector
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void addFileSelectionListener (FileSelectionListener listener)
|
||||
|
@ -329,6 +345,14 @@ class CatalogPanel extends JTabbedPane
|
|||
selector.addFileSelectionListener (listener);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void addFileSelectionListener (FileSelectionListener... listeners)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (FileSelectionListener fileSelectionListener : listeners)
|
||||
selector.addFileSelectionListener (fileSelectionListener);
|
||||
}
|
||||
|
||||
// Pass through to DiskSelector
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void addFileNodeSelectionListener (FileNodeSelectionListener listener)
|
||||
|
@ -337,6 +361,14 @@ class CatalogPanel extends JTabbedPane
|
|||
selector.addFileNodeSelectionListener (listener);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void addFileNodeSelectionListener (FileNodeSelectionListener... listeners)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (FileNodeSelectionListener fileNodeSelectionListener : listeners)
|
||||
selector.addFileNodeSelectionListener (fileNodeSelectionListener);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private class TabChangeListener implements ChangeListener
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -367,13 +399,13 @@ class CatalogPanel extends JTabbedPane
|
|||
{
|
||||
case "DiskEvent":
|
||||
case "FileNodeEvent":
|
||||
if (tab instanceof FileSystemTab)
|
||||
((FileSystemTab) tab).redoEvent (event);
|
||||
if (tab instanceof FileSystemTab fileSystemTab)
|
||||
fileSystemTab.redoEvent (event);
|
||||
break;
|
||||
|
||||
case "FileEvent":
|
||||
if (tab instanceof AppleDiskTab)
|
||||
((AppleDiskTab) tab).redoEvent (event);
|
||||
if (tab instanceof AppleDiskTab appleDiskTab)
|
||||
appleDiskTab.redoEvent (event);
|
||||
break;
|
||||
|
||||
case "SectorEvent":
|
||||
|
@ -394,8 +426,8 @@ class CatalogPanel extends JTabbedPane
|
|||
{
|
||||
// user has clicked in the DiskLayoutPanel, so turn off any current file selection
|
||||
Tab tab = (Tab) getSelectedComponent ();
|
||||
if (tab instanceof AppleDiskTab)
|
||||
((AppleDiskTab) tab).tree.setSelectionPath (null);
|
||||
if (tab instanceof AppleDiskTab appleDiskTab)
|
||||
appleDiskTab.tree.setSelectionPath (null);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -430,7 +462,7 @@ class CatalogPanel extends JTabbedPane
|
|||
FileNode node = (FileNode) selectedNode.getUserObject ();
|
||||
if (node.file.isDirectory ())
|
||||
{
|
||||
// lister.catalogLister.setNode (selectedNode);
|
||||
// lister.catalogLister.setNode (selectedNode);
|
||||
}
|
||||
else if (e.getClickCount () == 2)
|
||||
addDiskPanel (node.getFormattedDisk (), true);
|
||||
|
|
|
@ -19,6 +19,7 @@ public class CloseTabAction extends AbstractAction
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Close Tab");
|
||||
|
||||
putValue (Action.SHORT_DESCRIPTION, "Close the current disk tab");
|
||||
// putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("ctrl W"));
|
||||
int mask = Toolkit.getDefaultToolkit ().getMenuShortcutKeyMaskEx ();
|
||||
|
|
|
@ -12,17 +12,15 @@ import javax.swing.KeyStroke;
|
|||
public class ColourQuirksAction extends AbstractAction
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final DataPanel owner;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public ColourQuirksAction (DataPanel owner)
|
||||
public ColourQuirksAction ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Smear HGR");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -30,6 +28,7 @@ public class ColourQuirksAction extends AbstractAction
|
|||
public void actionPerformed (ActionEvent e)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
owner.setColourQuirks (((JMenuItem) e.getSource ()).isSelected ());
|
||||
firePropertyChange (e.getActionCommand (), null,
|
||||
((JMenuItem) e.getSource ()).isSelected ());
|
||||
}
|
||||
}
|
|
@ -17,4 +17,6 @@ public interface DataSource
|
|||
public BufferedImage getImage ();
|
||||
|
||||
public JComponent getComponent ();
|
||||
|
||||
public byte[] getBuffer ();
|
||||
}
|
|
@ -11,16 +11,14 @@ import javax.swing.KeyStroke;
|
|||
public class DebuggingAction extends AbstractAction
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final DataPanel owner;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public DebuggingAction (DataPanel owner)
|
||||
public DebuggingAction ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Debugging");
|
||||
|
||||
putValue (Action.SHORT_DESCRIPTION, "Show debugging information");
|
||||
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("meta D"));
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -28,6 +26,7 @@ public class DebuggingAction extends AbstractAction
|
|||
public void actionPerformed (ActionEvent e)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
owner.setDebug (((JMenuItem) e.getSource ()).isSelected ());
|
||||
firePropertyChange (e.getActionCommand (), null,
|
||||
((JMenuItem) e.getSource ()).isSelected ());
|
||||
}
|
||||
}
|
|
@ -6,6 +6,8 @@ import java.awt.Desktop;
|
|||
import java.awt.EventQueue;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.prefs.Preferences;
|
||||
|
@ -22,7 +24,8 @@ import javax.swing.UIManager;
|
|||
import com.bytezone.diskbrowser.duplicates.RootFolderData;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitListener
|
||||
public class DiskBrowser extends JFrame
|
||||
implements DiskSelectionListener, QuitListener, PropertyChangeListener
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static String[] args;
|
||||
|
@ -35,13 +38,21 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||
|
||||
private final RootFolderData rootFolderData = new RootFolderData ();
|
||||
|
||||
private final List<QuitListener> quitListeners = new ArrayList<> ();
|
||||
|
||||
private final JPanel catalogBorderPanel;
|
||||
private final JPanel layoutBorderPanel;
|
||||
|
||||
private final HideCatalogAction hideCatalogAction = new HideCatalogAction ();
|
||||
private final HideLayoutAction hideLayoutAction = new HideLayoutAction ();
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public DiskBrowser ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (windowTitle);
|
||||
|
||||
UIManager.put ("TabbedPane.foreground", Color.BLACK); // java bug fix
|
||||
// UIManager.put ("TabbedPane.foreground", Color.BLACK); // java bug fix
|
||||
|
||||
if (args.length > 0 && "-reset".equals (args[0]))
|
||||
new WindowState (prefs).clear ();
|
||||
|
@ -59,64 +70,56 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||
|
||||
// create and add the left-hand catalog panel
|
||||
CatalogPanel catalogPanel = new CatalogPanel (redoHandler);
|
||||
JPanel catalogBorderPanel = addPanel (catalogPanel, "Catalog", BorderLayout.WEST);
|
||||
catalogBorderPanel = addPanel (catalogPanel, "Catalog", BorderLayout.WEST);
|
||||
|
||||
// create and add the centre output panel
|
||||
DataPanel dataPanel = new DataPanel (menuHandler);
|
||||
OutputPanel dataPanel = new OutputPanel (menuHandler);
|
||||
addPanel (dataPanel, "Output", BorderLayout.CENTER);
|
||||
|
||||
// create and add the right-hand disk layout panel
|
||||
DiskLayoutPanel diskLayoutPanel = new DiskLayoutPanel ();
|
||||
JPanel layoutBorderPanel =
|
||||
addPanel (diskLayoutPanel, "Disk layout", BorderLayout.EAST);
|
||||
layoutBorderPanel = addPanel (diskLayoutPanel, "Disk layout", BorderLayout.EAST);
|
||||
|
||||
// create actions
|
||||
DuplicateAction duplicateAction = new DuplicateAction (rootFolderData);
|
||||
RootDirectoryAction rootDirectoryAction = new RootDirectoryAction ();
|
||||
|
||||
RefreshTreeAction refreshTreeAction = new RefreshTreeAction (catalogPanel);
|
||||
// PreferencesAction preferencesAction = new PreferencesAction (this, prefs);
|
||||
// PreferencesAction preferencesAction = new PreferencesAction (this, prefs);
|
||||
AbstractAction print = new PrintAction (dataPanel);
|
||||
// AboutAction aboutAction = new AboutAction ();
|
||||
HideCatalogAction hideCatalogAction =
|
||||
new HideCatalogAction (this, catalogBorderPanel);
|
||||
HideLayoutAction hideLayoutAction = new HideLayoutAction (this, layoutBorderPanel);
|
||||
ShowFreeSectorsAction showFreeAction =
|
||||
new ShowFreeSectorsAction (menuHandler, diskLayoutPanel);
|
||||
// AboutAction aboutAction = new AboutAction ();
|
||||
// HideLayoutAction hideLayoutAction = new HideLayoutAction (this, layoutBorderPanel);
|
||||
ShowFreeSectorsAction showFreeAction = new ShowFreeSectorsAction ();
|
||||
|
||||
CloseTabAction closeTabAction = new CloseTabAction (catalogPanel);
|
||||
// closeTabAction.addPropertyChangeListener (catalogPanel);
|
||||
|
||||
hideCatalogAction.addPropertyChangeListener (this);
|
||||
hideLayoutAction.addPropertyChangeListener (this);
|
||||
|
||||
// add action buttons to toolbar
|
||||
toolBar.add (rootDirectoryAction);
|
||||
toolBar.add (refreshTreeAction);
|
||||
// toolBar.add (preferencesAction);
|
||||
// toolBar.add (preferencesAction);
|
||||
toolBar.add (duplicateAction);
|
||||
toolBar.add (print);
|
||||
// toolBar.add (aboutAction);
|
||||
// toolBar.add (aboutAction);
|
||||
|
||||
// set the listeners
|
||||
rootDirectoryAction.addListener (rootFolderData);
|
||||
rootDirectoryAction.addListener (catalogPanel);
|
||||
rootDirectoryAction.addListener (duplicateAction);
|
||||
rootDirectoryAction.addPropertyChangeListener (rootFolderData);
|
||||
rootDirectoryAction.addPropertyChangeListener (catalogPanel);
|
||||
rootDirectoryAction.addPropertyChangeListener (duplicateAction);
|
||||
|
||||
catalogPanel.addDiskSelectionListener (this);
|
||||
catalogPanel.addDiskSelectionListener (dataPanel);
|
||||
catalogPanel.addDiskSelectionListener (diskLayoutPanel);
|
||||
catalogPanel.addDiskSelectionListener (redoHandler);
|
||||
catalogPanel.addDiskSelectionListener (menuHandler);
|
||||
catalogPanel.addDiskSelectionListener (this, dataPanel, diskLayoutPanel, redoHandler,
|
||||
menuHandler, menuHandler.saveDiskAction);
|
||||
|
||||
catalogPanel.addFileSelectionListener (dataPanel);
|
||||
catalogPanel.addFileSelectionListener (diskLayoutPanel);
|
||||
catalogPanel.addFileSelectionListener (redoHandler);
|
||||
catalogPanel.addFileSelectionListener (menuHandler);
|
||||
catalogPanel.addFileSelectionListener (dataPanel, diskLayoutPanel, redoHandler, menuHandler,
|
||||
menuHandler.saveFileAction);
|
||||
|
||||
catalogPanel.addFileNodeSelectionListener (dataPanel);
|
||||
catalogPanel.addFileNodeSelectionListener (redoHandler);
|
||||
catalogPanel.addFileNodeSelectionListener (dataPanel, redoHandler);
|
||||
|
||||
diskLayoutPanel.addSectorSelectionListener (dataPanel);
|
||||
diskLayoutPanel.addSectorSelectionListener (redoHandler);
|
||||
diskLayoutPanel.addSectorSelectionListener (catalogPanel);
|
||||
diskLayoutPanel.addSectorSelectionListener (menuHandler);
|
||||
diskLayoutPanel.addSectorSelectionListener (menuHandler.saveSectorsAction);
|
||||
diskLayoutPanel.addSectorSelectionListener (dataPanel, redoHandler, catalogPanel,
|
||||
menuHandler.saveSectorsAction);
|
||||
|
||||
duplicateAction.addTableSelectionListener (catalogPanel);
|
||||
|
||||
|
@ -129,12 +132,10 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||
|
||||
menuHandler.fontAction.addFontChangeListener (dataPanel);
|
||||
menuHandler.fontAction.addFontChangeListener (catalogPanel);
|
||||
// menuHandler.fontAction.addFontChangeListener (diskLayoutPanel);
|
||||
// menuHandler.fontAction.addFontChangeListener (diskLayoutPanel);
|
||||
|
||||
// set the MenuItem Actions
|
||||
menuHandler.printItem.setAction (print);
|
||||
// menuHandler.addHelpMenuAction (preferencesAction, "prefs");
|
||||
// menuHandler.addHelpMenuAction (aboutAction, "about");
|
||||
menuHandler.refreshTreeItem.setAction (refreshTreeAction);
|
||||
menuHandler.rootItem.setAction (rootDirectoryAction);
|
||||
menuHandler.showCatalogItem.setAction (hideCatalogAction);
|
||||
|
@ -143,10 +144,12 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||
menuHandler.duplicateItem.setAction (duplicateAction);
|
||||
menuHandler.closeTabItem.setAction (closeTabAction);
|
||||
|
||||
addQuitListener (rootDirectoryAction);
|
||||
addQuitListener (menuHandler);
|
||||
addQuitListener (catalogPanel);
|
||||
addQuitListener (this);
|
||||
showFreeAction.addPropertyChangeListener (diskLayoutPanel);
|
||||
|
||||
quitListeners.add (rootDirectoryAction);
|
||||
quitListeners.add (menuHandler);
|
||||
quitListeners.add (catalogPanel);
|
||||
quitListeners.add (this);
|
||||
|
||||
if (Desktop.isDesktopSupported ())
|
||||
{
|
||||
|
@ -157,14 +160,14 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||
"Author - Denis Molony\nGitHub - https://github.com/dmolony/DiskBrowser",
|
||||
"About DiskBrowser", JOptionPane.INFORMATION_MESSAGE));
|
||||
|
||||
if (desktop.isSupported (Desktop.Action.APP_PREFERENCES) && false)
|
||||
desktop.setPreferencesHandler (
|
||||
e -> JOptionPane.showMessageDialog (null, "Preferences dialog"));
|
||||
// if (desktop.isSupported (Desktop.Action.APP_PREFERENCES) && false)
|
||||
// desktop.setPreferencesHandler (
|
||||
// e -> JOptionPane.showMessageDialog (null, "Preferences dialog"));
|
||||
|
||||
if (desktop.isSupported (Desktop.Action.APP_QUIT_HANDLER))
|
||||
desktop.setQuitHandler ( (e, r) -> fireQuitEvent ());
|
||||
// else
|
||||
setQuitHandler ();
|
||||
desktop.setQuitHandler ( (e, r) -> fireQuitEvent ()); // needed for cmd-Q
|
||||
// else
|
||||
setQuitHandler (); // needed for the close button
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -184,9 +187,9 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||
|
||||
// Remove the two optional panels if they were previously hidden
|
||||
if (!menuHandler.showLayoutItem.isSelected ())
|
||||
hideLayoutAction.set (false);
|
||||
setLayoutPanel (false);
|
||||
if (!menuHandler.showCatalogItem.isSelected ())
|
||||
hideCatalogAction.set (false);
|
||||
setCatalogPanel (false);
|
||||
|
||||
menuHandler.addBasicPreferencesListener (dataPanel);
|
||||
menuHandler.addAssemblerPreferencesListener (dataPanel);
|
||||
|
@ -208,7 +211,6 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||
fireQuitEvent ();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -223,13 +225,47 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||
return panel;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void propertyChange (PropertyChangeEvent evt)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (evt.getSource () == hideCatalogAction)
|
||||
setCatalogPanel ((boolean) evt.getNewValue ());
|
||||
else if (evt.getSource () == hideLayoutAction)
|
||||
setLayoutPanel ((boolean) evt.getNewValue ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void setCatalogPanel (boolean show)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (show)
|
||||
add (catalogBorderPanel, BorderLayout.WEST);
|
||||
else
|
||||
remove (catalogBorderPanel);
|
||||
|
||||
validate ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void setLayoutPanel (boolean show)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (show)
|
||||
add (layoutBorderPanel, BorderLayout.EAST);
|
||||
else
|
||||
remove (layoutBorderPanel);
|
||||
|
||||
validate ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void diskSelected (DiskSelectedEvent e)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
setTitle (windowTitle + e.getFormattedDisk () == null ? ""
|
||||
: e.getFormattedDisk ().getName ());
|
||||
setTitle (windowTitle + e.getFormattedDisk () == null ? "" : e.getFormattedDisk ().getName ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -249,31 +285,15 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||
windowSaver.restoreWindow ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public static void main (String[] args)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
DiskBrowser.args = args;
|
||||
EventQueue.invokeLater (new Runnable ()
|
||||
{
|
||||
@Override
|
||||
public void run ()
|
||||
{
|
||||
setLookAndFeel ();
|
||||
new DiskBrowser ().setVisible (true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private static void setLookAndFeel ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
// FlatLightLaf.install ();
|
||||
// FlatLightLaf.install ();
|
||||
try
|
||||
{
|
||||
UIManager.setLookAndFeel (UIManager.getSystemLookAndFeelClassName ());
|
||||
// UIManager.setLookAndFeel (new FlatLightLaf ());
|
||||
// UIManager.setLookAndFeel (new FlatLightLaf ());
|
||||
if (MAC)
|
||||
System.setProperty ("apple.laf.useScreenMenuBar", "true");
|
||||
}
|
||||
|
@ -283,22 +303,6 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||
}
|
||||
}
|
||||
|
||||
List<QuitListener> quitListeners = new ArrayList<> ();
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void addQuitListener (QuitListener listener)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
quitListeners.add (listener);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void removeQuitListener (QuitListener listener)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
quitListeners.remove (listener);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void fireQuitEvent ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -316,4 +320,20 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||
for (QuitListener listener : quitListeners)
|
||||
listener.restore (prefs);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public static void main (String[] args)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
DiskBrowser.args = args;
|
||||
EventQueue.invokeLater (new Runnable ()
|
||||
{
|
||||
@Override
|
||||
public void run ()
|
||||
{
|
||||
setLookAndFeel ();
|
||||
new DiskBrowser ().setVisible (true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -97,9 +97,10 @@ class DiskLayoutImage extends DiskPanel implements Scrollable, RedoListener
|
|||
selectionHandler.setSelection (sectors);
|
||||
if (sectors != null && sectors.size () > 0)
|
||||
{
|
||||
DiskAddress da = sectors.size () == 1 ? sectors.get (0) : sectors.get (1);
|
||||
if (da != null)
|
||||
scrollRectToVisible (layoutDetails.getLocation (da));
|
||||
// DiskAddress da = sectors.size () == 1 ? sectors.get (0) : sectors.get (1);
|
||||
// if (da != null)
|
||||
// scrollRectToVisible (layoutDetails.getLocation (da));
|
||||
scrollRectToVisible (layoutDetails.getLocation (sectors.get (0)));
|
||||
}
|
||||
repaint ();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ import java.awt.event.ActionEvent;
|
|||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
|
@ -19,14 +21,14 @@ import javax.swing.JScrollPane;
|
|||
|
||||
import com.bytezone.diskbrowser.disk.Disk;
|
||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||
import com.bytezone.diskbrowser.disk.HybridDisk;
|
||||
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
||||
import com.bytezone.diskbrowser.disk.HybridDisk;
|
||||
import com.bytezone.diskbrowser.gui.RedoHandler.RedoEvent;
|
||||
import com.bytezone.diskbrowser.gui.RedoHandler.RedoListener;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class DiskLayoutPanel extends JPanel
|
||||
implements DiskSelectionListener, FileSelectionListener, RedoListener
|
||||
class DiskLayoutPanel extends JPanel implements DiskSelectionListener,
|
||||
FileSelectionListener, RedoListener, PropertyChangeListener
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static final int SIZE = 15; // basic unit of a display block
|
||||
|
@ -134,6 +136,14 @@ class DiskLayoutPanel extends JPanel
|
|||
diskLayoutImage.setShowFreeSectors (free);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void propertyChange (PropertyChangeEvent evt)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
setFree ((Boolean) evt.getNewValue ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void addSectorSelectionListener (SectorSelectionListener listener)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -141,6 +151,14 @@ class DiskLayoutPanel extends JPanel
|
|||
diskLayoutImage.addSectorSelectionListener (listener);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void addSectorSelectionListener (SectorSelectionListener... listeners)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (SectorSelectionListener sectorSelectionListener : listeners)
|
||||
diskLayoutImage.addSectorSelectionListener (sectorSelectionListener);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void removeSectorSelectionListener (SectorSelectionListener listener)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -244,8 +262,8 @@ class DiskLayoutPanel extends JPanel
|
|||
|
||||
private void checkCorrectDisk (FormattedDisk newDisk)
|
||||
{
|
||||
if (newDisk instanceof HybridDisk)
|
||||
newDisk = ((HybridDisk) newDisk).getCurrentDisk (); // never set to a Dual-dos disk
|
||||
if (newDisk instanceof HybridDisk hybridDisk)
|
||||
newDisk = hybridDisk.getCurrentDisk (); // never set to a hybrid disk
|
||||
if (newDisk != diskLayoutImage.getDisk ())
|
||||
{
|
||||
LayoutDetails layout = new LayoutDetails (newDisk);
|
||||
|
|
|
@ -157,6 +157,7 @@ class DiskLayoutSelection implements Iterable<DiskAddress>
|
|||
for (DiskAddress selection : highlights)
|
||||
if (selection != null && da.matches (selection))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,14 +85,13 @@ class DiskLegendPanel extends DiskPanel
|
|||
int val = formattedDisk.falseNegativeBlocks ();
|
||||
if (val > 0)
|
||||
{
|
||||
g.drawString (
|
||||
val + " unused sector" + (val == 1 ? "" : "s") + " marked as unavailable", 10,
|
||||
y);
|
||||
g.drawString (val + " unused sector" + (val == 1 ? "" : "s") //
|
||||
+ " marked as unavailable", 10, y);
|
||||
y += lineHeight;
|
||||
}
|
||||
val = formattedDisk.falsePositiveBlocks ();
|
||||
if (val > 0)
|
||||
g.drawString (val + " used sector" + (val == 1 ? "" : "s") + " marked as available",
|
||||
10, y);
|
||||
g.drawString (val + " used sector" + (val == 1 ? "" : "s") //
|
||||
+ " marked as available", 10, y);
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ public class DiskPanel extends JPanel
|
|||
{
|
||||
FormattedDisk formattedDisk;
|
||||
LayoutDetails layoutDetails;
|
||||
|
||||
int blockWidth = 30; // default
|
||||
int blockHeight = 15; // default
|
||||
int centerOffset;
|
||||
|
@ -20,11 +21,11 @@ public class DiskPanel extends JPanel
|
|||
Color backgroundColor = new Color (0xE0, 0xE0, 0xE0);
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void setDisk (FormattedDisk disk, LayoutDetails details)
|
||||
public void setDisk (FormattedDisk formattedDisk, LayoutDetails layoutDetails)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
formattedDisk = disk;
|
||||
layoutDetails = details;
|
||||
this.formattedDisk = formattedDisk;
|
||||
this.layoutDetails = layoutDetails;
|
||||
|
||||
blockWidth = layoutDetails.block.width;
|
||||
blockHeight = layoutDetails.block.height;
|
||||
|
|
|
@ -9,7 +9,7 @@ import com.bytezone.diskbrowser.disk.FormattedDisk;
|
|||
class DiskSelectedEvent extends EventObject
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final FormattedDisk owner;
|
||||
private final FormattedDisk formattedDisk;
|
||||
boolean redo;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -17,14 +17,14 @@ class DiskSelectedEvent extends EventObject
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (source);
|
||||
this.owner = disk;
|
||||
this.formattedDisk = disk;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public FormattedDisk getFormattedDisk ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return owner;
|
||||
return formattedDisk;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -32,14 +32,14 @@ class DiskSelectedEvent extends EventObject
|
|||
public String toString ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return owner.getDisk ().getFile ().getAbsolutePath ();
|
||||
return formattedDisk.getDisk ().getFile ().getAbsolutePath ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public String toText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return owner.getAbsolutePath ();
|
||||
return formattedDisk.getAbsolutePath ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.bytezone.diskbrowser.gui;
|
|||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.Action;
|
||||
|
@ -14,7 +16,7 @@ import com.bytezone.diskbrowser.duplicates.RootFolderData;
|
|||
import com.bytezone.diskbrowser.utilities.DefaultAction;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class DuplicateAction extends DefaultAction implements RootDirectoryChangeListener
|
||||
public class DuplicateAction extends DefaultAction implements PropertyChangeListener
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
RootFolderData rootFolderData;
|
||||
|
@ -36,14 +38,22 @@ public class DuplicateAction extends DefaultAction implements RootDirectoryChang
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void rootDirectoryChanged (File oldRootFolder, File newRootFolder)
|
||||
private void rootDirectoryChanged (File oldRootFolder, File newRootFolder)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
assert rootFolderData.getRootFolder () == newRootFolder;
|
||||
setEnabled (rootFolderData.getRootFolder () != null);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void propertyChange (PropertyChangeEvent evt)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (evt.getPropertyName ().equals ("RootDirectory"))
|
||||
rootDirectoryChanged ((File) evt.getOldValue (), (File) evt.getNewValue ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void actionPerformed (ActionEvent arg0)
|
||||
|
|
|
@ -3,8 +3,8 @@ package com.bytezone.diskbrowser.gui;
|
|||
import java.util.EventObject;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
||||
import com.bytezone.diskbrowser.disk.HybridDisk;
|
||||
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
||||
import com.bytezone.diskbrowser.disk.HybridDisk;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class FileSelectedEvent extends EventObject
|
||||
|
@ -21,8 +21,9 @@ class FileSelectedEvent extends EventObject
|
|||
super (source);
|
||||
this.appleFileSource = appleFileSource;
|
||||
|
||||
// If a file is selected from a disk which is contained in a Dual-dos disk, then the DDS
|
||||
// must be told so that it can ensure its internal currentDisk is set correctly
|
||||
// If a file is selected from a disk which is part of a hybrid disk, then the
|
||||
// parent must be told so that it can ensure its internal currentDisk is set
|
||||
// correctly
|
||||
FormattedDisk fd = appleFileSource.getFormattedDisk ();
|
||||
HybridDisk ddd = (HybridDisk) fd.getParent ();
|
||||
if (ddd != null)
|
||||
|
|
|
@ -36,6 +36,7 @@ public class FontAction extends DefaultAction implements QuitListener
|
|||
{
|
||||
super ("Set Font...", "Set display to a different font or font size",
|
||||
"/com/bytezone/loadlister/");
|
||||
|
||||
int mask = Toolkit.getDefaultToolkit ().getMenuShortcutKeyMaskEx ();
|
||||
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke (KeyEvent.VK_F, mask));
|
||||
}
|
||||
|
@ -146,8 +147,7 @@ public class FontAction extends DefaultAction implements QuitListener
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
FontChangeEvent fontChangeEvent = new FontChangeEvent (font);
|
||||
FontChangeListener[] listeners =
|
||||
(listenerList.getListeners (FontChangeListener.class));
|
||||
FontChangeListener[] listeners = (listenerList.getListeners (FontChangeListener.class));
|
||||
for (FontChangeListener listener : listeners)
|
||||
listener.changeFont (fontChangeEvent);
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ public class FontFrame extends JFrame
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Font Selection");
|
||||
|
||||
this.fontAction = fontAction;
|
||||
buildLayout ();
|
||||
getFonts ();
|
||||
|
@ -96,8 +97,7 @@ public class FontFrame extends JFrame
|
|||
public String getSelectedValue ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
String fontName = fontList.getSelectedValue ();
|
||||
return fontName;
|
||||
return fontList.getSelectedValue ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -112,8 +112,7 @@ public class FontFrame extends JFrame
|
|||
public String getSelectedSize ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
String fontSize = fontSizePanel.getSelectedText ();
|
||||
return fontSize;
|
||||
return fontSizePanel.getSelectedText ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -130,20 +129,22 @@ public class FontFrame extends JFrame
|
|||
{
|
||||
String fonts[] =
|
||||
GraphicsEnvironment.getLocalGraphicsEnvironment ().getAvailableFontFamilyNames ();
|
||||
// for (String font : fonts)
|
||||
// System.out.println (font);
|
||||
String pf[] =
|
||||
{ "Andale Mono", "Anonymous Pro", "Anonymous Pro Minus", "Apple2Forever",
|
||||
"Apple2Forever80", "Consolas", "Bitstream Vera Sans Mono", "Consolas",
|
||||
"Courier", "Courier New", "DejaVu Sans Mono", "Envy Code R", "Inconsolata",
|
||||
"Input Mono", "Input Mono Narrow", "Iosevka", "Lucida Sans Typewriter",
|
||||
"Luculent", "Menlo", "Monaco", "monofur", "Monospaced", "Nimbus Mono L",
|
||||
"PCMyungjo", "PR Number 3", "Pragmata", "Print Char 21", "ProFont", "ProFontX",
|
||||
"Proggy", "PT Mono", "Source Code Pro", "Ubuntu Mono" };
|
||||
{ "Andale Mono", "Anonymous Pro", "Anonymous Pro Minus", "Apple II Display Pro",
|
||||
"Apple II Pro", "Apple2Forever", "Apple2Forever80", "Bitstream Vera Sans Mono",
|
||||
"Consolas", "Courier", "Courier New", "DejaVu Sans Mono", "Envy Code R",
|
||||
"Inconsolata", "Input Mono", "Input Mono Narrow", "Iosevka",
|
||||
"Lucida Sans Typewriter", "Luculent", "Menlo", "Monaco", "monofur",
|
||||
"Monospaced", "Nimbus Mono L", "PCMyungjo", "PR Number 3", "Pragmata",
|
||||
"Print Char 21", "ProFont", "ProFontX", "Proggy", "PT Mono", "Source Code Pro",
|
||||
"Ubuntu Mono" };
|
||||
|
||||
DefaultListModel<String> lm = (DefaultListModel<String>) fontList.getModel ();
|
||||
|
||||
int ptr = 0;
|
||||
for (String fontName : fonts)
|
||||
{
|
||||
while (ptr < pf.length)
|
||||
{
|
||||
int result = fontName.compareToIgnoreCase (pf[ptr]);
|
||||
|
@ -156,7 +157,6 @@ public class FontFrame extends JFrame
|
|||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fontList.setSelectedValue (initialFont, true);
|
||||
}
|
||||
|
@ -251,13 +251,14 @@ public class FontFrame extends JFrame
|
|||
private Font getCurrentFont ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
String fontName = getSelectedValue ();
|
||||
String fontSize = getSelectedSize ();
|
||||
if (fontSize.isEmpty ())
|
||||
return null;
|
||||
|
||||
int pos = fontSize.indexOf (' ');
|
||||
int size = Integer.parseInt (fontSize.substring (0, pos));
|
||||
return new Font (fontName, Font.PLAIN, size);
|
||||
|
||||
return new Font (getSelectedValue (), Font.PLAIN, size);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -266,8 +267,10 @@ public class FontFrame extends JFrame
|
|||
{
|
||||
initialFont = getSelectedValue ();
|
||||
initialSize = getSelectedSize ();
|
||||
|
||||
int pos = initialSize.indexOf (' ');
|
||||
int size = Integer.parseInt (initialSize.substring (0, pos));
|
||||
|
||||
Font font = new Font (initialFont, Font.PLAIN, size);
|
||||
fontAction.fireFontChangeEvent (font);
|
||||
}
|
||||
|
|
|
@ -1,33 +1,26 @@
|
|||
package com.bytezone.diskbrowser.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class HideCatalogAction extends AbstractAction
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
JFrame owner;
|
||||
JPanel catalogPanel;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public HideCatalogAction (JFrame owner, JPanel catalogPanel)
|
||||
public HideCatalogAction ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Show catalog panel");
|
||||
|
||||
putValue (Action.SHORT_DESCRIPTION, "Show/hide the catalog panel");
|
||||
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt C"));
|
||||
putValue (Action.MNEMONIC_KEY, KeyEvent.VK_C);
|
||||
this.owner = owner;
|
||||
this.catalogPanel = catalogPanel;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -35,22 +28,7 @@ class HideCatalogAction extends AbstractAction
|
|||
public void actionPerformed (ActionEvent e)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
set (((JMenuItem) e.getSource ()).isSelected ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void set (boolean show)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (show)
|
||||
{
|
||||
owner.add (catalogPanel, BorderLayout.WEST);
|
||||
owner.validate ();
|
||||
}
|
||||
else
|
||||
{
|
||||
owner.remove (catalogPanel);
|
||||
owner.validate ();
|
||||
}
|
||||
firePropertyChange (e.getActionCommand (), null,
|
||||
((JMenuItem) e.getSource ()).isSelected ());
|
||||
}
|
||||
}
|
|
@ -1,33 +1,26 @@
|
|||
package com.bytezone.diskbrowser.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class HideLayoutAction extends AbstractAction
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
JFrame owner;
|
||||
JPanel layoutPanel;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public HideLayoutAction (JFrame owner, JPanel layoutPanel)
|
||||
public HideLayoutAction ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Show disk layout panel");
|
||||
|
||||
putValue (Action.SHORT_DESCRIPTION, "Show/hide the disk layout panel");
|
||||
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt D"));
|
||||
putValue (Action.MNEMONIC_KEY, KeyEvent.VK_D);
|
||||
this.owner = owner;
|
||||
this.layoutPanel = layoutPanel;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -35,22 +28,7 @@ class HideLayoutAction extends AbstractAction
|
|||
public void actionPerformed (ActionEvent e)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
set (((JMenuItem) e.getSource ()).isSelected ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void set (boolean show)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (show)
|
||||
{
|
||||
owner.add (layoutPanel, BorderLayout.EAST);
|
||||
owner.validate ();
|
||||
}
|
||||
else
|
||||
{
|
||||
owner.remove (layoutPanel);
|
||||
owner.validate ();
|
||||
}
|
||||
firePropertyChange (e.getActionCommand (), null,
|
||||
((JMenuItem) e.getSource ()).isSelected ());
|
||||
}
|
||||
}
|