Compare commits
154 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2bc330e377 | ||
|
6c81bcc93b | ||
|
171fd66ba1 | ||
|
aa77ec1cd4 | ||
|
8f95988596 | ||
|
8cb682f068 | ||
|
dfc7a68580 | ||
|
4b476457d3 | ||
|
3bf972a761 | ||
|
fd5bee6e5c | ||
|
0af6714119 | ||
|
22dfaf65c6 | ||
|
f4a6465b04 | ||
|
64d5ce9ee2 | ||
|
4e48437adc | ||
|
e2abdcabc9 | ||
|
bc0993e9d3 | ||
|
9fba3893ba | ||
|
09c4542118 | ||
|
af3ead0441 | ||
|
c12392200b | ||
|
794fef8610 | ||
|
2ec0e10c5e | ||
|
668ed719fa | ||
|
23b95675cf | ||
|
b98ecbed8d | ||
|
82381a6a47 | ||
|
3f2f1bfbca | ||
|
a7119528a6 | ||
|
6f943ae8c2 | ||
|
5add6c0729 | ||
|
921c946ab5 | ||
|
898587b23b | ||
|
37c489f252 | ||
|
036e47b9b1 | ||
|
250c1a9bd9 | ||
|
b19e89d7cf | ||
|
d71cabb754 | ||
|
848b2469ae | ||
|
989b1d5ab9 | ||
|
e0a2c50d5b | ||
|
8765299cf4 | ||
|
97fe58d94d | ||
|
7d4d8c75e6 | ||
|
f5664a9ce9 | ||
|
9d8cdcd67b | ||
|
12b74f9d21 | ||
|
1b405c6f38 | ||
|
66d6910f91 | ||
|
572ee8c3a1 | ||
|
2a14b7baad | ||
|
a633e28ed3 | ||
|
ca11e8ee68 | ||
|
ce52253f5d | ||
|
e408aa3d62 | ||
|
c4b4d17f52 | ||
|
0b72f1a37d | ||
|
1b86b31233 | ||
|
1b9e9d47ac | ||
|
decc781572 | ||
|
16ccc2632a | ||
|
40c2afbd48 | ||
|
f9038810d2 | ||
|
3435e825df | ||
|
ff7c6fd126 | ||
|
91846d8563 | ||
|
19b6339ac5 | ||
|
db4953618c | ||
|
c1deee56a0 | ||
|
b1ed1a74ba | ||
|
cf0cfd278b | ||
|
48aca6e1eb | ||
|
d83ac3afda | ||
|
2270b1f6db | ||
|
da67dbe0d7 | ||
|
133352ba31 | ||
|
761c43dc3d | ||
|
d03de97247 | ||
|
e67bbeaf8b | ||
|
6dfc72b2d2 | ||
|
fb748df4ae | ||
|
4a03c411fc | ||
|
54db7d95d6 | ||
|
59b22be2bd | ||
|
47a07f5cfe | ||
|
bca12f0738 | ||
|
27100ad38e | ||
|
2a6fd74013 | ||
|
4767c317d0 | ||
|
068f382c87 | ||
|
e7d8c4ebc2 | ||
|
9ef0f82dea | ||
|
fba8c07142 | ||
|
4aefc8b695 | ||
|
a8574d24f8 | ||
|
449e6c0e9a | ||
|
09b6f66855 | ||
|
f30fe1a78a | ||
|
0e40e25710 | ||
|
f02c932d91 | ||
|
c18cfe9ed7 | ||
|
dcb3e32845 | ||
|
08d6d1b136 | ||
|
954b0c0bd8 | ||
|
f22b4dcd46 | ||
|
c42481637e | ||
|
7ca8160d13 | ||
|
26316a82a9 | ||
|
5f29cfcd09 | ||
|
7f2e963689 | ||
|
8ea18c8cc1 | ||
|
f92fe5b57e | ||
|
bb4dcbdd7c | ||
|
8aec65449e | ||
|
ff273e7df9 | ||
|
1a1f9df93f | ||
|
80a07c0496 | ||
|
8369e4a788 | ||
|
bfeab1477c | ||
|
ad8464c6c2 | ||
|
b1ff2f7740 | ||
|
4040238bbf | ||
|
70f21070d5 | ||
|
91693bbc37 | ||
|
8a9b824302 | ||
|
06f4713baa | ||
|
e7ded68b03 | ||
|
58cec66535 | ||
|
c105d07e60 | ||
|
3e32b3caf0 | ||
|
7aa80b8b5e | ||
|
5e053872a9 | ||
|
7d162a4baf | ||
|
83d5be3f9f | ||
|
ea0a827331 | ||
|
dc551285bb | ||
|
95538f5282 | ||
|
9d706d62ef | ||
|
63fc59accc | ||
|
beb0830c25 | ||
|
ae1188ae27 | ||
|
1b27ea02e7 | ||
|
c2f2277717 | ||
|
79ccd6793c | ||
|
5be0236845 | ||
|
59bf768d14 | ||
|
566479450a | ||
|
b45e7d7e54 | ||
|
9dddd2be3e | ||
|
d3f21e0d49 | ||
|
af706e03c7 | ||
|
b6496e9c87 | ||
|
a33aedd750 | ||
|
13647213c6 |
4
.gitignore
vendored
|
@ -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")
|
||||
|
|
40
build.xml
Normal file
|
@ -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>
|
13
resources/basic.md
Normal file
|
@ -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"/>
|
BIN
resources/basic0.png
Normal file
After Width: | Height: | Size: 730 KiB |
BIN
resources/basic1.png
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
resources/basic2.png
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
resources/basic3.png
Normal file
After Width: | Height: | Size: 128 KiB |
BIN
resources/basic4.png
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
resources/basic5.png
Normal file
After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 784 KiB After Width: | Height: | Size: 1.1 MiB |
BIN
resources/duplicates.png
Normal file
After Width: | Height: | Size: 373 KiB |
Before Width: | Height: | Size: 788 KiB |
BIN
resources/pascal1.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
resources/pascal2.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 642 KiB After Width: | Height: | Size: 1.0 MiB |
BIN
resources/wizardry4.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
|
@ -17,9 +17,9 @@ 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;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -30,12 +30,29 @@ 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 ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
|
@ -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 ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
|
@ -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));
|
||||
|
|
229
src/com/bytezone/diskbrowser/applefile/CPMBasicFile.java
Normal file
|
@ -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 ();
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ 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.disk.FormattedDisk;
|
||||
import com.bytezone.diskbrowser.prodos.DirectoryHeader;
|
||||
|
@ -15,7 +16,8 @@ import com.bytezone.diskbrowser.utilities.Utility;
|
|||
public class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
static final DateTimeFormatter df = DateTimeFormatter.ofPattern ("d-LLL-yy");
|
||||
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";
|
||||
|
@ -86,7 +88,6 @@ public 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)
|
||||
{
|
||||
|
@ -121,12 +122,12 @@ public class ProdosDirectory extends AbstractFile implements ProdosConstants
|
|||
|
||||
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.getShort (buffer, i + 31);
|
||||
subType = String.format ("R=%5d", aux);
|
||||
break;
|
||||
|
||||
|
@ -134,14 +135,13 @@ public class ProdosDirectory extends AbstractFile implements ProdosConstants
|
|||
case FILE_TYPE_PNT:
|
||||
case FILE_TYPE_PIC:
|
||||
case FILE_TYPE_FOT:
|
||||
aux = Utility.getShort (buffer, i + 31);
|
||||
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:
|
||||
|
@ -149,9 +149,10 @@ public class ProdosDirectory extends AbstractFile implements ProdosConstants
|
|||
}
|
||||
|
||||
String forkFlag = storageType == 5 ? "+" : " ";
|
||||
text.append (String.format ("%s%-15s %3s%s %5d %9s %5s %9s %5s %8d %7s%n",
|
||||
locked, filename, ProdosConstants.fileTypes[type], forkFlag, blocks, dateM,
|
||||
timeM, dateC, timeC, eof, subType));
|
||||
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:
|
||||
|
|
|
@ -88,8 +88,8 @@ public class QuickDrawFont extends CharacterList
|
|||
firstChar = Utility.getShort (buffer, ptr + 2);
|
||||
lastChar = Utility.getShort (buffer, ptr + 4);
|
||||
widMax = Utility.getShort (buffer, ptr + 6);
|
||||
kernMax = Utility.signedShort (buffer, ptr + 8);
|
||||
nDescent = Utility.signedShort (buffer, ptr + 10);
|
||||
kernMax = Utility.getSignedShort (buffer, ptr + 8);
|
||||
nDescent = Utility.getSignedShort (buffer, ptr + 10);
|
||||
fRectWidth = Utility.getShort (buffer, ptr + 12);
|
||||
fRectHeight = Utility.getShort (buffer, ptr + 14);
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
|
@ -52,7 +52,7 @@ public class StoredVariables extends AbstractFile
|
|||
else if (suffix == '%')
|
||||
{
|
||||
intValue = Utility.intValue (buffer[ptr + 3], buffer[ptr + 2]); // backwards!
|
||||
if ((buffer[ptr + 2] & 0x80) > 0)
|
||||
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 ();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -202,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);
|
||||
|
|
|
@ -47,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)
|
||||
{
|
||||
|
@ -107,7 +107,7 @@ 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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -206,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));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -234,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 ();
|
||||
}
|
||||
|
@ -327,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;
|
||||
|
@ -90,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;
|
||||
}
|
||||
|
||||
|
@ -143,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);
|
||||
}
|
||||
|
|
|
@ -16,9 +16,9 @@ import java.util.zip.Checksum;
|
|||
import com.bytezone.diskbrowser.nib.NibFile;
|
||||
import com.bytezone.diskbrowser.nib.V2dFile;
|
||||
import com.bytezone.diskbrowser.nib.WozFile;
|
||||
import com.bytezone.diskbrowser.utilities.Binary2;
|
||||
import com.bytezone.diskbrowser.nufx.Binary2;
|
||||
import com.bytezone.diskbrowser.nufx.NuFX;
|
||||
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
||||
import com.bytezone.diskbrowser.utilities.NuFX;
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
|
@ -48,11 +48,11 @@ public class AppleDisk implements Disk
|
|||
|
||||
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
|
||||
|
@ -101,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 ();
|
||||
|
@ -158,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
|
||||
|
@ -166,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;
|
||||
|
@ -363,7 +362,6 @@ public class AppleDisk implements Disk
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.dosVersion = version;
|
||||
// System.out.printf ("DOS version %02X%n", version);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -469,6 +467,7 @@ public class AppleDisk implements Disk
|
|||
readBuffer (da, buffer, ptr);
|
||||
ptr += sectorSize;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -557,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
|
||||
}
|
||||
|
@ -624,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)
|
||||
{
|
||||
|
@ -640,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -650,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)
|
||||
{
|
||||
|
@ -670,6 +665,13 @@ public class AppleDisk implements Disk
|
|||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public byte[] getBuffer ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return diskBuffer;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private int getBufferOffset (DiskAddress da)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -731,12 +733,8 @@ 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 ("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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
|
@ -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,11 +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.Binary2;
|
||||
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 +34,7 @@ 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;
|
||||
|
@ -145,7 +148,7 @@ public class DiskFactory
|
|||
|
||||
if ("sdk".equals (suffix) // NuFX disk
|
||||
|| "shk".equals (suffix) // NuFX files or disk
|
||||
|| "bxy".equals (suffix)) // NuFX in Binary2
|
||||
|| "bxy".equals (suffix)) // NuFX in Bin2
|
||||
{
|
||||
if (debug)
|
||||
System.out.println (" ** sdk/shk/bxy **");
|
||||
|
@ -153,7 +156,11 @@ public class DiskFactory
|
|||
{
|
||||
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)
|
||||
|
@ -176,14 +183,14 @@ public class DiskFactory
|
|||
else
|
||||
System.out.println (e.getMessage ());
|
||||
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
|
||||
// System.out.println (nuFX);
|
||||
// System.out.println (nuFX);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if ("bny".equals (suffix)) // Binary2 uncompressed files
|
||||
else if ("bny".equals (suffix) || "bqy".equals (suffix)) // Binary2 uncompressed files
|
||||
{
|
||||
if (debug)
|
||||
System.out.println (" ** bny **");
|
||||
System.out.println (" ** bny/bqy **");
|
||||
try
|
||||
{
|
||||
binary2 = new Binary2 (file.toPath ());
|
||||
|
@ -201,13 +208,21 @@ public class DiskFactory
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// e.printStackTrace ();
|
||||
// e.printStackTrace ();
|
||||
System.out.println (e.getMessage ());
|
||||
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
|
||||
// System.out.println (binary2);
|
||||
// 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;
|
||||
|
@ -268,7 +283,7 @@ public class DiskFactory
|
|||
}
|
||||
|
||||
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)
|
||||
|
@ -335,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
|
||||
{
|
||||
|
@ -345,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)
|
||||
|
@ -408,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
|
||||
|
@ -433,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)
|
||||
|
@ -479,11 +499,11 @@ 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)
|
||||
{
|
||||
|
@ -572,7 +592,7 @@ public class DiskFactory
|
|||
private static FormattedDisk check (FormattedDisk disk)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (disk.getDisk ()instanceof AppleDisk appleDisk)
|
||||
if (disk.getDisk () instanceof AppleDisk appleDisk)
|
||||
{
|
||||
if (nuFX != null)
|
||||
appleDisk.setNuFX (nuFX);
|
||||
|
@ -597,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;
|
||||
}
|
||||
|
@ -666,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 ());
|
||||
|
@ -690,10 +710,10 @@ public class DiskFactory
|
|||
System.out.println ("*** extended ***"); // System Addons.hdv
|
||||
}
|
||||
AppleDisk disk;
|
||||
// if (nuFX == null)
|
||||
// if (nuFX == null)
|
||||
disk = new AppleDisk (file, tracks, 8);
|
||||
// else
|
||||
// disk = new AppleDisk (file, tracks, 8, nuFX);
|
||||
// else
|
||||
// disk = new AppleDisk (file, tracks, 8, nuFX);
|
||||
|
||||
if (ProdosDisk.isCorrectFormat (disk))
|
||||
{
|
||||
|
@ -701,6 +721,7 @@ public class DiskFactory
|
|||
System.out.println (" --> PRODOS hard disk");
|
||||
return new ProdosDisk (disk);
|
||||
}
|
||||
|
||||
if (PascalDisk.isCorrectFormat (disk, debug))
|
||||
{
|
||||
if (debug)
|
||||
|
@ -716,7 +737,7 @@ public class DiskFactory
|
|||
}
|
||||
|
||||
if (debug)
|
||||
System.out.println (" not a Prodos hard disk\n");
|
||||
System.out.println (" not a Prodos/Pascal hard disk\n");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -841,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)
|
||||
{
|
||||
|
@ -866,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;
|
||||
|
@ -876,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);
|
||||
|
||||
|
@ -883,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;
|
||||
|
@ -931,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;
|
||||
}
|
||||
}
|
|
@ -51,6 +51,9 @@ public class Prefix2mg
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
@ -235,18 +235,28 @@ abstract class AbstractCatalogEntry implements AppleFileSource
|
|||
|
||||
case IntegerBasic:
|
||||
reportedLength = Utility.getShort (buffer, 0);
|
||||
exactBuffer = new byte[reportedLength];
|
||||
System.arraycopy (buffer, 2, exactBuffer, 0, reportedLength);
|
||||
appleFile = new IntegerBasicProgram (name, exactBuffer);
|
||||
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.getShort (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);
|
||||
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
|
||||
|
@ -256,8 +266,8 @@ abstract class AbstractCatalogEntry implements AppleFileSource
|
|||
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;
|
||||
|
||||
|
@ -362,8 +370,8 @@ abstract class AbstractCatalogEntry implements AppleFileSource
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 =
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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.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;
|
||||
}
|
||||
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]);
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
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;
|
||||
|
||||
|
@ -8,13 +15,44 @@ import com.bytezone.diskbrowser.utilities.DefaultAction;
|
|||
public abstract class AbstractSaveAction extends DefaultAction
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
JFileChooser fileChooser;
|
||||
protected JFileChooser fileChooser = new JFileChooser ();
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public AbstractSaveAction (String text, String tip)
|
||||
public AbstractSaveAction (String menuText, String tip, String dialogTitle)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (text, tip);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
62
src/com/bytezone/diskbrowser/gui/AnimationWorker.java
Normal file
|
@ -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;
|
||||
|
|
|
@ -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 ());
|
||||
}
|
||||
}
|
|
@ -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,65 +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 (menuHandler.saveDiskAction);
|
||||
catalogPanel.addDiskSelectionListener (this, dataPanel, diskLayoutPanel, redoHandler,
|
||||
menuHandler, menuHandler.saveDiskAction);
|
||||
|
||||
catalogPanel.addFileSelectionListener (dataPanel);
|
||||
catalogPanel.addFileSelectionListener (diskLayoutPanel);
|
||||
catalogPanel.addFileSelectionListener (redoHandler);
|
||||
catalogPanel.addFileSelectionListener (menuHandler);
|
||||
catalogPanel.addFileSelectionListener (menuHandler.saveFileAction);
|
||||
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.saveSectorsAction);
|
||||
diskLayoutPanel.addSectorSelectionListener (dataPanel, redoHandler, catalogPanel,
|
||||
menuHandler.saveSectorsAction);
|
||||
|
||||
duplicateAction.addTableSelectionListener (catalogPanel);
|
||||
|
||||
|
@ -130,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);
|
||||
|
@ -144,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 ())
|
||||
{
|
||||
|
@ -158,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
|
||||
{
|
||||
|
@ -185,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);
|
||||
|
@ -209,7 +211,6 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
|
|||
fireQuitEvent ();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -224,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 ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -250,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");
|
||||
}
|
||||
|
@ -284,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 ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -317,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 ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -146,7 +145,6 @@ public class FontFrame extends JFrame
|
|||
|
||||
int ptr = 0;
|
||||
for (String fontName : fonts)
|
||||
{
|
||||
while (ptr < pf.length)
|
||||
{
|
||||
int result = fontName.compareToIgnoreCase (pf[ptr]);
|
||||
|
@ -159,7 +157,6 @@ public class FontFrame extends JFrame
|
|||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fontList.setSelectedValue (initialFont, true);
|
||||
}
|
||||
|
@ -254,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);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -269,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 ());
|
||||
}
|
||||
}
|
84
src/com/bytezone/diskbrowser/gui/ImagePanel.java
Normal file
|
@ -0,0 +1,84 @@
|
|||
package com.bytezone.diskbrowser.gui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class ImagePanel extends JPanel
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static final int BACKGROUND = 245;
|
||||
|
||||
private BufferedImage image;
|
||||
private double scale = 1;
|
||||
private double userScale = .5;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public ImagePanel ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.setBackground (new Color (BACKGROUND, BACKGROUND, BACKGROUND));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void setScale (double scale)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.userScale = scale;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void setImage (BufferedImage image)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.image = image;
|
||||
int width, height;
|
||||
|
||||
if (image != null)
|
||||
{
|
||||
Graphics2D g2 = image.createGraphics ();
|
||||
g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
width = image.getWidth ();
|
||||
height = image.getHeight ();
|
||||
}
|
||||
else
|
||||
width = height = 0;
|
||||
|
||||
if (true)
|
||||
{
|
||||
if (width < 400 && width > 0)
|
||||
scale = (400 - 1) / width + 1;
|
||||
else
|
||||
scale = 1;
|
||||
if (scale > 4)
|
||||
scale = 4;
|
||||
}
|
||||
|
||||
scale *= userScale;
|
||||
|
||||
setPreferredSize (new Dimension ((int) (width * scale), (int) (height * scale)));
|
||||
repaint ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void paintComponent (Graphics g)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super.paintComponent (g);
|
||||
|
||||
if (image != null)
|
||||
{
|
||||
Graphics2D g2 = ((Graphics2D) g);
|
||||
g2.transform (AffineTransform.getScaleInstance (scale, scale));
|
||||
g2.drawImage (image, (int) ((getWidth () - image.getWidth () * scale) / 2 / scale), 4, this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,45 +2,33 @@ package com.bytezone.diskbrowser.gui;
|
|||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class LineWrapAction extends AbstractAction
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
List<JTextArea> listeners = new ArrayList<> ();
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public LineWrapAction ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Line wrap");
|
||||
putValue (Action.SHORT_DESCRIPTION, "Print the contents of the output panel");
|
||||
|
||||
putValue (Action.SHORT_DESCRIPTION, "Wrap/don't wrap the text in the output panel");
|
||||
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt W"));
|
||||
putValue (Action.MNEMONIC_KEY, KeyEvent.VK_W);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void addListener (JTextArea listener)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (!listeners.contains (listener))
|
||||
listeners.add (listener);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void actionPerformed (ActionEvent e)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
for (JTextArea listener : listeners)
|
||||
listener.setLineWrap (((JMenuItem) e.getSource ()).isSelected ());
|
||||
firePropertyChange (e.getActionCommand (), null,
|
||||
((JMenuItem) e.getSource ()).isSelected ());
|
||||
}
|
||||
}
|
|
@ -76,7 +76,6 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
|
|||
|
||||
private static final String PREFS_PALETTE = "palette";
|
||||
|
||||
FormattedDisk currentDisk;
|
||||
final SaveDiskAction saveDiskAction = new SaveDiskAction ();
|
||||
final SaveFileAction saveFileAction = new SaveFileAction ();
|
||||
final SaveSectorsAction saveSectorsAction = new SaveSectorsAction ();
|
||||
|
@ -186,6 +185,8 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
|
|||
|
||||
ButtonGroup paletteGroup = new ButtonGroup ();
|
||||
|
||||
FormattedDisk currentDisk;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
MenuHandler ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -211,7 +212,7 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
|
|||
addLauncherMenu ();
|
||||
|
||||
fileMenu.add (printItem);
|
||||
// fileMenu.addSeparator ();
|
||||
// fileMenu.addSeparator ();
|
||||
fileMenu.add (closeTabItem);
|
||||
|
||||
JMenuItem fontItem = new JMenuItem (fontAction);
|
||||
|
@ -270,13 +271,13 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
|
|||
applesoftMenu.add (splitRemarkItem);
|
||||
applesoftMenu.add (splitDimItem);
|
||||
applesoftMenu.add (alignAssignItem);
|
||||
// applesoftMenu.add (showBasicTargetsItem);
|
||||
// applesoftMenu.add (onlyShowTargetLinesItem);
|
||||
// applesoftMenu.add (showBasicTargetsItem);
|
||||
// applesoftMenu.add (onlyShowTargetLinesItem);
|
||||
applesoftMenu.add (showCaretItem);
|
||||
applesoftMenu.add (showThenItem);
|
||||
applesoftMenu.add (blankAfterReturnItem);
|
||||
applesoftMenu.add (formatRemItem);
|
||||
// applesoftMenu.add (deleteExtraRemSpace);
|
||||
// applesoftMenu.add (deleteExtraRemSpace);
|
||||
applesoftMenu.add (deleteExtraDataSpace);
|
||||
applesoftMenu.addSeparator ();
|
||||
applesoftMenu.add (showXrefItem);
|
||||
|
@ -284,7 +285,7 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
|
|||
applesoftMenu.add (showSymbolsItem);
|
||||
applesoftMenu.add (showFunctionsItem);
|
||||
applesoftMenu.add (showConstantsItem);
|
||||
// applesoftMenu.add (listStringsItem);
|
||||
// applesoftMenu.add (listStringsItem);
|
||||
applesoftMenu.add (showDuplicateSymbolsItem);
|
||||
|
||||
assemblerMenu.add (showAssemblerHeaderItem);
|
||||
|
@ -347,6 +348,7 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
|
|||
showAllFormatItem.addActionListener (basicPreferencesAction);
|
||||
showAllXrefItem.addActionListener (basicPreferencesAction);
|
||||
appleLineWrapItem.addActionListener (basicPreferencesAction);
|
||||
|
||||
for (JMenuItem item : applesoftFormatItems)
|
||||
item.addActionListener (basicPreferencesAction);
|
||||
for (JMenuItem item : applesoftXrefItems)
|
||||
|
@ -374,10 +376,12 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
|
|||
|
||||
sectorGroup.add (sector256Item);
|
||||
sectorGroup.add (sector512Item);
|
||||
|
||||
interleaveGroup.add (interleave0Item);
|
||||
interleaveGroup.add (interleave1Item);
|
||||
interleaveGroup.add (interleave2Item);
|
||||
interleaveGroup.add (interleave3Item);
|
||||
|
||||
scaleGroup.add (scale1Item);
|
||||
scaleGroup.add (scale2Item);
|
||||
scaleGroup.add (scale3Item);
|
||||
|
@ -546,6 +550,7 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
|
|||
openSupported = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!openSupported)
|
||||
return;
|
||||
|
||||
|
@ -554,60 +559,6 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
|
|||
fileMenu.addSeparator ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void quit (Preferences prefs)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
prefs.putBoolean (PREFS_LINE_WRAP, lineWrapItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_LAYOUT, showLayoutItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_CATALOG, showCatalogItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_FREE_SECTORS, showFreeSectorsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_COLOUR_QUIRKS, colourQuirksItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_MONOCHROME, monochromeItem.isSelected ());
|
||||
prefs.putInt (PREFS_PALETTE,
|
||||
HiResImage.getPaletteFactory ().getCurrentPaletteIndex ());
|
||||
fontAction.quit (prefs);
|
||||
|
||||
int scale = scale1Item.isSelected () ? 1 : scale2Item.isSelected () ? 2 : 3;
|
||||
prefs.putInt (PREFS_SCALE, scale);
|
||||
|
||||
prefs.putBoolean (PREFS_SHOW_HEADER, showHeaderItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_ALL_FORMAT, showAllFormatItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_ALL_XREF, showAllXrefItem.isSelected ());
|
||||
|
||||
prefs.putBoolean (PREFS_APPLE_LINE_WRAP, appleLineWrapItem.isSelected ());
|
||||
|
||||
prefs.putBoolean (PREFS_SPLIT_REMARKS, splitRemarkItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SPLIT_DIM, splitDimItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_ALIGN_ASSIGN, alignAssignItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_CARET, showCaretItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_THEN, showThenItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_BLANK_AFTER_RETURN, blankAfterReturnItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_FORMAT_REM, formatRemItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_DELETE_EXTRA_DATA_SPACE, deleteExtraDataSpace.isSelected ());
|
||||
|
||||
prefs.putBoolean (PREFS_SHOW_GOSUB_GOTO, showXrefItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_CALLS, showCallsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_SYMBOLS, showSymbolsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_FUNCTIONS, showFunctionsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_CONSTANTS, showConstantsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_DUPLICATE_SYMBOLS,
|
||||
showDuplicateSymbolsItem.isSelected ());
|
||||
|
||||
prefs.putBoolean (PREFS_SHOW_ASSEMBLER_TARGETS,
|
||||
showAssemblerTargetsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_ASSEMBLER_STRINGS,
|
||||
showAssemblerStringsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_ASSEMBLER_HEADER, showAssemblerHeaderItem.isSelected ());
|
||||
|
||||
prefs.putBoolean (PREFS_PRODOS_SORT_DIRECTORIES,
|
||||
prodosSortDirectoriesItem.isSelected ());
|
||||
|
||||
prefs.putBoolean (PREFS_TEXT_SHOW_OFFSETS, showTextOffsetsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_TEXT_SHOW_HEADER, showTextHeaderItem.isSelected ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void restore (Preferences prefs)
|
||||
|
@ -697,6 +648,60 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
|
|||
fontAction.restore (prefs);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void quit (Preferences prefs)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
prefs.putBoolean (PREFS_LINE_WRAP, lineWrapItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_LAYOUT, showLayoutItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_CATALOG, showCatalogItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_FREE_SECTORS, showFreeSectorsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_COLOUR_QUIRKS, colourQuirksItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_MONOCHROME, monochromeItem.isSelected ());
|
||||
prefs.putInt (PREFS_PALETTE,
|
||||
HiResImage.getPaletteFactory ().getCurrentPaletteIndex ());
|
||||
fontAction.quit (prefs);
|
||||
|
||||
int scale = scale1Item.isSelected () ? 1 : scale2Item.isSelected () ? 2 : 3;
|
||||
prefs.putInt (PREFS_SCALE, scale);
|
||||
|
||||
prefs.putBoolean (PREFS_SHOW_HEADER, showHeaderItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_ALL_FORMAT, showAllFormatItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_ALL_XREF, showAllXrefItem.isSelected ());
|
||||
|
||||
prefs.putBoolean (PREFS_APPLE_LINE_WRAP, appleLineWrapItem.isSelected ());
|
||||
|
||||
prefs.putBoolean (PREFS_SPLIT_REMARKS, splitRemarkItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SPLIT_DIM, splitDimItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_ALIGN_ASSIGN, alignAssignItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_CARET, showCaretItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_THEN, showThenItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_BLANK_AFTER_RETURN, blankAfterReturnItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_FORMAT_REM, formatRemItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_DELETE_EXTRA_DATA_SPACE, deleteExtraDataSpace.isSelected ());
|
||||
|
||||
prefs.putBoolean (PREFS_SHOW_GOSUB_GOTO, showXrefItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_CALLS, showCallsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_SYMBOLS, showSymbolsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_FUNCTIONS, showFunctionsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_CONSTANTS, showConstantsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_DUPLICATE_SYMBOLS,
|
||||
showDuplicateSymbolsItem.isSelected ());
|
||||
|
||||
prefs.putBoolean (PREFS_SHOW_ASSEMBLER_TARGETS,
|
||||
showAssemblerTargetsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_ASSEMBLER_STRINGS,
|
||||
showAssemblerStringsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_SHOW_ASSEMBLER_HEADER, showAssemblerHeaderItem.isSelected ());
|
||||
|
||||
prefs.putBoolean (PREFS_PRODOS_SORT_DIRECTORIES,
|
||||
prodosSortDirectoriesItem.isSelected ());
|
||||
|
||||
prefs.putBoolean (PREFS_TEXT_SHOW_OFFSETS, showTextOffsetsItem.isSelected ());
|
||||
prefs.putBoolean (PREFS_TEXT_SHOW_HEADER, showTextHeaderItem.isSelected ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void diskSelected (DiskSelectedEvent event)
|
||||
|
@ -733,7 +738,7 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
|
|||
interleave3Item.setSelected (disk.getDisk ().getInterleave () == 3);
|
||||
}
|
||||
|
||||
boolean isDataDisk = (disk instanceof DataDisk);
|
||||
boolean isDataDisk = disk instanceof DataDisk;
|
||||
|
||||
sector256Item.setEnabled (isDataDisk);
|
||||
sector512Item.setEnabled (isDataDisk);
|
||||
|
|
|
@ -12,17 +12,15 @@ import javax.swing.KeyStroke;
|
|||
class MonochromeAction extends AbstractAction
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final DataPanel owner;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
MonochromeAction (DataPanel owner)
|
||||
MonochromeAction ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Monochrome");
|
||||
|
||||
putValue (Action.SHORT_DESCRIPTION, "Display image in monochrome or color");
|
||||
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt M"));
|
||||
putValue (Action.MNEMONIC_KEY, KeyEvent.VK_M);
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -30,6 +28,7 @@ class MonochromeAction extends AbstractAction
|
|||
public void actionPerformed (ActionEvent e)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
owner.setMonochrome (((JMenuItem) e.getSource ()).isSelected ());
|
||||
firePropertyChange (e.getActionCommand (), null,
|
||||
((JMenuItem) e.getSource ()).isSelected ());
|
||||
}
|
||||
}
|
|
@ -17,11 +17,11 @@ import com.bytezone.diskbrowser.applefile.PaletteFactory.CycleDirection;
|
|||
class NextPaletteAction extends AbstractAction
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final DataPanel owner;
|
||||
private final OutputPanel owner;
|
||||
private final ButtonGroup buttonGroup;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
NextPaletteAction (DataPanel owner, ButtonGroup buttonGroup)
|
||||
NextPaletteAction (OutputPanel owner, ButtonGroup buttonGroup)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Next Palette");
|
||||
|
|
|
@ -1,27 +1,21 @@
|
|||
package com.bytezone.diskbrowser.gui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
|
@ -39,17 +33,18 @@ import com.bytezone.diskbrowser.disk.DiskAddress;
|
|||
import com.bytezone.diskbrowser.disk.SectorList;
|
||||
import com.bytezone.diskbrowser.gui.FontAction.FontChangeEvent;
|
||||
import com.bytezone.diskbrowser.gui.FontAction.FontChangeListener;
|
||||
import com.bytezone.diskbrowser.wizardry.MazeLevel;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class DataPanel extends JTabbedPane
|
||||
public class OutputPanel extends JTabbedPane
|
||||
implements DiskSelectionListener, FileSelectionListener, SectorSelectionListener,
|
||||
FileNodeSelectionListener, FontChangeListener, BasicPreferencesListener,
|
||||
AssemblerPreferencesListener, TextPreferencesListener
|
||||
AssemblerPreferencesListener, TextPreferencesListener, PropertyChangeListener
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static final int TEXT_WIDTH = 65;
|
||||
private static final int BACKGROUND = 245;
|
||||
|
||||
// final MenuHandler menuHandler;
|
||||
private final JTextArea formattedText;
|
||||
private final JTextArea hexText;
|
||||
private final JTextArea disassemblyText;
|
||||
|
@ -57,41 +52,42 @@ public class DataPanel extends JTabbedPane
|
|||
// these two panes are interchangeable
|
||||
private final JScrollPane formattedPane;
|
||||
private final JScrollPane imagePane;
|
||||
|
||||
private boolean imageVisible = false;
|
||||
|
||||
private final ImagePanel imagePanel; // internal class
|
||||
private final ImagePanel imagePanel = new ImagePanel ();
|
||||
private AnimationWorker animation;
|
||||
private boolean debugMode;
|
||||
private DataSource currentDataSource;
|
||||
|
||||
// used to determine whether the text has been set
|
||||
boolean formattedTextValid;
|
||||
boolean hexTextValid;
|
||||
boolean assemblerTextValid;
|
||||
DataSource currentDataSource;
|
||||
private boolean formattedTextValid;
|
||||
private boolean hexTextValid;
|
||||
private boolean assemblerTextValid;
|
||||
|
||||
private Worker animation;
|
||||
private DebuggingAction debuggingAction = new DebuggingAction ();
|
||||
private MonochromeAction monochromeAction = new MonochromeAction ();
|
||||
private ColourQuirksAction colourQuirksAction = new ColourQuirksAction ();
|
||||
private LineWrapAction lineWrapAction = new LineWrapAction ();
|
||||
|
||||
final MenuHandler menuHandler;
|
||||
|
||||
enum TabType
|
||||
private enum TabType
|
||||
{
|
||||
FORMATTED, HEX, DISASSEMBLED
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public DataPanel (MenuHandler mh)
|
||||
public OutputPanel (MenuHandler menuHandler)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.menuHandler = mh;
|
||||
setTabPlacement (SwingConstants.BOTTOM);
|
||||
|
||||
formattedText = new JTextArea (10, TEXT_WIDTH);
|
||||
formattedPane = setPanel (formattedText, "Formatted");
|
||||
// formattedText.setLineWrap (prefs.getBoolean (MenuHandler.PREFS_LINE_WRAP, true));
|
||||
// formattedText.setLineWrap (prefs.getBoolean (MenuHandler.PREFS_LINE_WRAP, true));
|
||||
formattedText.setText ("Please use the 'File->Set HOME folder...' command to "
|
||||
+ "\ntell DiskBrowser where your Apple disks are located."
|
||||
+ "\n\nTo see the contents of a disk in more detail, double-click"
|
||||
+ "\nthe disk. You will then be able to select individual files to "
|
||||
+ "view completely.");
|
||||
+ "\nthe disk. You will then be able to select individual files to " + "view them.");
|
||||
|
||||
hexText = new JTextArea (10, TEXT_WIDTH);
|
||||
setPanel (hexText, "Hex dump");
|
||||
|
@ -99,10 +95,8 @@ public class DataPanel extends JTabbedPane
|
|||
disassemblyText = new JTextArea (10, TEXT_WIDTH);
|
||||
setPanel (disassemblyText, "Disassembly");
|
||||
|
||||
imagePanel = new ImagePanel ();
|
||||
imagePane =
|
||||
new JScrollPane (imagePanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
imagePane = new JScrollPane (imagePanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
|
||||
imagePane.setBorder (null);
|
||||
|
||||
|
@ -126,6 +120,7 @@ public class DataPanel extends JTabbedPane
|
|||
formattedTextValid = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // Hex
|
||||
if (!hexTextValid)
|
||||
{
|
||||
|
@ -136,6 +131,7 @@ public class DataPanel extends JTabbedPane
|
|||
hexTextValid = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Assembler
|
||||
if (!assemblerTextValid)
|
||||
{
|
||||
|
@ -146,19 +142,24 @@ public class DataPanel extends JTabbedPane
|
|||
assemblerTextValid = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
System.out.println ("Invalid index selected in DataPanel");
|
||||
System.out.println ("Impossible - Invalid index selected in DataPanel");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
LineWrapAction lineWrapAction = new LineWrapAction ();
|
||||
menuHandler.lineWrapItem.setAction (lineWrapAction);
|
||||
lineWrapAction.addListener (formattedText);
|
||||
lineWrapAction.addPropertyChangeListener (this);
|
||||
|
||||
menuHandler.colourQuirksItem.setAction (new ColourQuirksAction (this));
|
||||
menuHandler.monochromeItem.setAction (new MonochromeAction (this));
|
||||
menuHandler.debuggingItem.setAction (new DebuggingAction (this));
|
||||
colourQuirksAction.addPropertyChangeListener (this);
|
||||
menuHandler.colourQuirksItem.setAction (colourQuirksAction);
|
||||
|
||||
monochromeAction.addPropertyChangeListener (this);
|
||||
menuHandler.monochromeItem.setAction (monochromeAction);
|
||||
|
||||
debuggingAction.addPropertyChangeListener (this);
|
||||
menuHandler.debuggingItem.setAction (debuggingAction);
|
||||
|
||||
// fill in the placeholders created by the MenuHandler
|
||||
List<Palette> palettes = HiResImage.getPalettes ();
|
||||
|
@ -170,6 +171,7 @@ public class DataPanel extends JTabbedPane
|
|||
JCheckBoxMenuItem item = (JCheckBoxMenuItem) enumeration.nextElement ();
|
||||
item.setAction (new PaletteAction (this, palettes.get (ndx++)));
|
||||
}
|
||||
|
||||
menuHandler.nextPaletteItem.setAction (new NextPaletteAction (this, buttonGroup));
|
||||
menuHandler.prevPaletteItem.setAction (new PreviousPaletteAction (this, buttonGroup));
|
||||
}
|
||||
|
@ -179,9 +181,8 @@ public class DataPanel extends JTabbedPane
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
HiResImage.getPaletteFactory ().setCurrentPalette (palette);
|
||||
if (currentDataSource instanceof HiResImage)
|
||||
if (currentDataSource instanceof HiResImage image)
|
||||
{
|
||||
HiResImage image = (HiResImage) currentDataSource;
|
||||
image.setPalette ();
|
||||
imagePanel.setImage (image.getImage ());
|
||||
}
|
||||
|
@ -192,15 +193,29 @@ public class DataPanel extends JTabbedPane
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
Palette palette = HiResImage.getPaletteFactory ().cyclePalette (direction);
|
||||
if (currentDataSource instanceof HiResImage)
|
||||
if (currentDataSource instanceof HiResImage image)
|
||||
{
|
||||
HiResImage image = (HiResImage) currentDataSource;
|
||||
image.setPalette ();
|
||||
imagePanel.setImage (image.getImage ());
|
||||
}
|
||||
return palette;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void propertyChange (PropertyChangeEvent evt)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (evt.getSource () == debuggingAction)
|
||||
setDebug ((Boolean) evt.getNewValue ());
|
||||
else if (evt.getSource () == monochromeAction)
|
||||
setMonochrome ((Boolean) evt.getNewValue ());
|
||||
else if (evt.getSource () == colourQuirksAction)
|
||||
setColourQuirks ((Boolean) evt.getNewValue ());
|
||||
else if (evt.getSource () == lineWrapAction)
|
||||
setLineWrap ((Boolean) evt.getNewValue ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void setLineWrap (boolean lineWrap)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -212,9 +227,8 @@ public class DataPanel extends JTabbedPane
|
|||
public void setColourQuirks (boolean value)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (currentDataSource instanceof HiResImage)
|
||||
if (currentDataSource instanceof HiResImage image)
|
||||
{
|
||||
HiResImage image = (HiResImage) currentDataSource;
|
||||
image.setColourQuirks (value);
|
||||
imagePanel.setImage (image.getImage ());
|
||||
}
|
||||
|
@ -224,9 +238,8 @@ public class DataPanel extends JTabbedPane
|
|||
public void setMonochrome (boolean value)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (currentDataSource instanceof HiResImage)
|
||||
if (currentDataSource instanceof HiResImage image)
|
||||
{
|
||||
HiResImage image = (HiResImage) currentDataSource;
|
||||
image.setMonochrome (value);
|
||||
imagePanel.setImage (image.getImage ());
|
||||
}
|
||||
|
@ -237,22 +250,16 @@ public class DataPanel extends JTabbedPane
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
imagePanel.setScale (scale);
|
||||
if (currentDataSource instanceof HiResImage)
|
||||
{
|
||||
HiResImage image = (HiResImage) currentDataSource;
|
||||
if (currentDataSource instanceof HiResImage image)
|
||||
imagePanel.setImage (image.getImage ());
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void update ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (currentDataSource instanceof HiResImage)
|
||||
{
|
||||
HiResImage image = (HiResImage) currentDataSource;
|
||||
if (currentDataSource instanceof HiResImage image)
|
||||
imagePanel.setImage (image.getImage ());
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -264,9 +271,10 @@ public class DataPanel extends JTabbedPane
|
|||
AbstractFile.setDebug (value);
|
||||
setText (formattedText, currentDataSource.getText ());
|
||||
|
||||
if (currentDataSource instanceof HiResImage
|
||||
if (currentDataSource instanceof HiResImage //
|
||||
|| currentDataSource instanceof MazeLevel // Wizardry
|
||||
|| currentDataSource instanceof QuickDrawFont)
|
||||
setDataSource (currentDataSource); // toggles text/image
|
||||
setDataSource (currentDataSource); // toggles text/image
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -298,6 +306,7 @@ public class DataPanel extends JTabbedPane
|
|||
JScrollPane outputScrollPane =
|
||||
new JScrollPane (outputPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
|
||||
outputScrollPane.setBorder (null); // remove the ugly default border
|
||||
add (outputScrollPane, tabName);
|
||||
return outputScrollPane;
|
||||
|
@ -355,15 +364,15 @@ public class DataPanel extends JTabbedPane
|
|||
removeImage ();
|
||||
else
|
||||
{
|
||||
if (dataSource instanceof HiResImage)
|
||||
if (dataSource instanceof HiResImage hri)
|
||||
{
|
||||
((HiResImage) dataSource).checkPalette ();
|
||||
hri.checkPalette ();
|
||||
image = dataSource.getImage ();
|
||||
if (((HiResImage) dataSource).isAnimation ())
|
||||
{
|
||||
if (animation != null)
|
||||
animation.cancel ();
|
||||
animation = new Worker ((SHRPictureFile2) dataSource);
|
||||
animation = new AnimationWorker (this, (SHRPictureFile2) dataSource);
|
||||
animation.execute ();
|
||||
}
|
||||
}
|
||||
|
@ -411,71 +420,6 @@ public class DataPanel extends JTabbedPane
|
|||
textArea.setCaretPosition (0);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private class ImagePanel extends JPanel
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
private BufferedImage image;
|
||||
private double scale = 1;
|
||||
private double userScale = .5;
|
||||
|
||||
public ImagePanel ()
|
||||
{
|
||||
this.setBackground (new Color (BACKGROUND, BACKGROUND, BACKGROUND));
|
||||
}
|
||||
|
||||
private void setScale (double scale)
|
||||
{
|
||||
this.userScale = scale;
|
||||
}
|
||||
|
||||
private void setImage (BufferedImage image)
|
||||
{
|
||||
this.image = image;
|
||||
int width, height;
|
||||
|
||||
if (image != null)
|
||||
{
|
||||
Graphics2D g2 = image.createGraphics ();
|
||||
g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING,
|
||||
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
width = image.getWidth ();
|
||||
height = image.getHeight ();
|
||||
}
|
||||
else
|
||||
width = height = 0;
|
||||
|
||||
if (true)
|
||||
{
|
||||
if (width < 400 && width > 0)
|
||||
scale = (400 - 1) / width + 1;
|
||||
else
|
||||
scale = 1;
|
||||
if (scale > 4)
|
||||
scale = 4;
|
||||
}
|
||||
|
||||
scale *= userScale;
|
||||
|
||||
setPreferredSize (new Dimension ((int) (width * scale), (int) (height * scale)));
|
||||
repaint ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent (Graphics g)
|
||||
{
|
||||
super.paintComponent (g);
|
||||
|
||||
if (image != null)
|
||||
{
|
||||
Graphics2D g2 = ((Graphics2D) g);
|
||||
g2.transform (AffineTransform.getScaleInstance (scale, scale));
|
||||
g2.drawImage (image,
|
||||
(int) ((getWidth () - image.getWidth () * scale) / 2 / scale), 4, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void diskSelected (DiskSelectedEvent event)
|
||||
|
@ -483,6 +427,7 @@ public class DataPanel extends JTabbedPane
|
|||
{
|
||||
setSelectedIndex (0);
|
||||
setDataSource (null);
|
||||
|
||||
if (event.getFormattedDisk () != null)
|
||||
setDataSource (event.getFormattedDisk ().getCatalog ().getDataSource ());
|
||||
else
|
||||
|
@ -524,7 +469,6 @@ public class DataPanel extends JTabbedPane
|
|||
{
|
||||
setSelectedIndex (0);
|
||||
setDataSource (event.getFileNode ());
|
||||
// FileNode node = event.getFileNode ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -549,8 +493,7 @@ public class DataPanel extends JTabbedPane
|
|||
public void setAssemblerPreferences (AssemblerPreferences assemblerPreferences)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (currentDataSource instanceof AssemblerProgram
|
||||
|| currentDataSource instanceof BootSector)
|
||||
if (currentDataSource instanceof AssemblerProgram || currentDataSource instanceof BootSector)
|
||||
setDataSource (currentDataSource);
|
||||
}
|
||||
|
||||
|
@ -562,49 +505,4 @@ public class DataPanel extends JTabbedPane
|
|||
if (currentDataSource instanceof BasicTextFile)
|
||||
setDataSource (currentDataSource);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
class Worker extends SwingWorker<Void, Integer>
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
volatile boolean running;
|
||||
SHRPictureFile2 image;
|
||||
|
||||
public Worker (SHRPictureFile2 image)
|
||||
{
|
||||
assert image.isAnimation ();
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
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 ();
|
||||
update ();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,10 +12,10 @@ class PaletteAction extends AbstractAction
|
|||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final Palette palette;
|
||||
private final DataPanel owner;
|
||||
private final OutputPanel owner;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
PaletteAction (DataPanel owner, Palette palette)
|
||||
PaletteAction (OutputPanel owner, Palette palette)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (palette.getName ());
|
||||
|
|
|
@ -17,11 +17,11 @@ import com.bytezone.diskbrowser.applefile.PaletteFactory.CycleDirection;
|
|||
class PreviousPaletteAction extends AbstractAction
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final DataPanel owner;
|
||||
private final OutputPanel owner;
|
||||
private final ButtonGroup buttonGroup;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
PreviousPaletteAction (DataPanel owner, ButtonGroup buttonGroup)
|
||||
PreviousPaletteAction (OutputPanel owner, ButtonGroup buttonGroup)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Previous Palette");
|
||||
|
|
|
@ -16,10 +16,10 @@ import com.bytezone.diskbrowser.utilities.DefaultAction;
|
|||
class PrintAction extends DefaultAction
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
DataPanel owner;
|
||||
OutputPanel owner;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public PrintAction (DataPanel owner)
|
||||
public PrintAction (OutputPanel owner)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Print...", "Print the contents of the output panel",
|
||||
|
|
|
@ -3,8 +3,6 @@ package com.bytezone.diskbrowser.gui;
|
|||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import javax.swing.Action;
|
||||
|
@ -18,7 +16,7 @@ class RootDirectoryAction extends DefaultAction implements QuitListener
|
|||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static final String prefsRootDirectory = "Root directory";
|
||||
private final List<RootDirectoryChangeListener> listeners = new ArrayList<> ();
|
||||
|
||||
private File rootFolder;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -27,6 +25,7 @@ class RootDirectoryAction extends DefaultAction implements QuitListener
|
|||
{
|
||||
super ("Set HOME folder...", "Defines root folder where the disk images are kept",
|
||||
"/com/bytezone/diskbrowser/icons/");
|
||||
|
||||
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt H"));
|
||||
putValue (Action.MNEMONIC_KEY, KeyEvent.VK_H);
|
||||
|
||||
|
@ -56,14 +55,6 @@ class RootDirectoryAction extends DefaultAction implements QuitListener
|
|||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void addListener (RootDirectoryChangeListener listener)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (!listeners.contains (listener))
|
||||
listeners.add (listener);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
@Override
|
||||
public void quit (Preferences prefs)
|
||||
|
@ -78,9 +69,7 @@ class RootDirectoryAction extends DefaultAction implements QuitListener
|
|||
public void restore (Preferences prefs)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
String rootDirectory = prefs.get (prefsRootDirectory, "");
|
||||
|
||||
File rootDirectoryFile = new File (rootDirectory);
|
||||
File rootDirectoryFile = new File (prefs.get (prefsRootDirectory, ""));
|
||||
|
||||
if (!rootDirectoryFile.exists () || !rootDirectoryFile.isDirectory ())
|
||||
{
|
||||
|
@ -96,7 +85,7 @@ class RootDirectoryAction extends DefaultAction implements QuitListener
|
|||
{
|
||||
File oldRootFolder = rootFolder;
|
||||
rootFolder = newRootFolder;
|
||||
for (RootDirectoryChangeListener listener : listeners)
|
||||
listener.rootDirectoryChanged (oldRootFolder, newRootFolder);
|
||||
|
||||
firePropertyChange ("RootDirectory", oldRootFolder, newRootFolder);
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package com.bytezone.diskbrowser.gui;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public interface RootDirectoryChangeListener
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
public void rootDirectoryChanged (File oldRootFolder, File newRootFolder);
|
||||
}
|
|
@ -2,25 +2,25 @@ package com.bytezone.diskbrowser.gui;
|
|||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import com.bytezone.diskbrowser.disk.AppleDisk;
|
||||
import com.bytezone.diskbrowser.disk.Disk;
|
||||
import com.bytezone.diskbrowser.disk.FormattedDisk;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class SaveDiskAction extends AbstractSaveAction implements DiskSelectionListener
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
FormattedDisk disk;
|
||||
FormattedDisk formattedDisk;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
SaveDiskAction ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Save converted disk...", "Save converted disk");
|
||||
super ("Save converted disk...", "Save converted disk", "Save converted disk");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -28,35 +28,25 @@ class SaveDiskAction extends AbstractSaveAction implements DiskSelectionListener
|
|||
public void actionPerformed (ActionEvent evt)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
if (disk == null)
|
||||
if (formattedDisk == null)
|
||||
{
|
||||
JOptionPane.showMessageDialog (null, "No disk selected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileChooser == null)
|
||||
Disk disk = formattedDisk.getDisk ();
|
||||
if (disk instanceof AppleDisk appleDisk)
|
||||
{
|
||||
fileChooser = new JFileChooser ();
|
||||
fileChooser.setDialogTitle ("Save converted disk");
|
||||
}
|
||||
int blocks = disk.getTotalBlocks ();
|
||||
String suffix = blocks <= 560 ? ".dsk" : ".hdv";
|
||||
|
||||
fileChooser.setSelectedFile (new File (disk.getName () + ".dsk"));
|
||||
setSelectedFile (new File (formattedDisk.getName () + suffix));
|
||||
|
||||
if (fileChooser.showSaveDialog (null) == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
File file = fileChooser.getSelectedFile ();
|
||||
try
|
||||
{
|
||||
Files.copy (disk.getDisk ().getFile ().toPath (), file.toPath ());
|
||||
JOptionPane.showMessageDialog (null,
|
||||
String.format ("File %s saved", file.getName ()));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace ();
|
||||
JOptionPane.showMessageDialog (null, "Disk failed to save");
|
||||
}
|
||||
if (fileChooser.showSaveDialog (null) == JFileChooser.APPROVE_OPTION)
|
||||
saveBuffer (appleDisk.getBuffer ());
|
||||
}
|
||||
else
|
||||
System.out.println ("Not an AppleDisk"); // impossible
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -64,7 +54,7 @@ class SaveDiskAction extends AbstractSaveAction implements DiskSelectionListener
|
|||
public void diskSelected (DiskSelectedEvent event)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.disk = event.getFormattedDisk ();
|
||||
setEnabled (disk != null && disk.isTempDisk ());
|
||||
formattedDisk = event.getFormattedDisk ();
|
||||
setEnabled (formattedDisk != null && formattedDisk.isTempDisk ());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
package com.bytezone.diskbrowser.gui;
|
||||
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
import com.bytezone.diskbrowser.applefile.AppleFileSource;
|
||||
|
||||
|
@ -16,12 +18,17 @@ class SaveFileAction extends AbstractSaveAction implements FileSelectionListener
|
|||
//-----------------------------------------------------------------------------------//
|
||||
{
|
||||
AppleFileSource appleFileSource;
|
||||
private JCheckBox formatted = new JCheckBox ("Formatted");
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
SaveFileAction ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Save file...", "Save currently selected file");
|
||||
super ("Save file...", "Save currently selected file", "Save File");
|
||||
|
||||
fileChooser.setAccessory (formatted);
|
||||
int mask = Toolkit.getDefaultToolkit ().getMenuShortcutKeyMaskEx ();
|
||||
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke (KeyEvent.VK_S, mask));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -35,30 +42,18 @@ class SaveFileAction extends AbstractSaveAction implements FileSelectionListener
|
|||
return;
|
||||
}
|
||||
|
||||
if (fileChooser == null)
|
||||
{
|
||||
fileChooser = new JFileChooser ();
|
||||
fileChooser.setDialogTitle ("Save File");
|
||||
}
|
||||
if (formatted.isSelected ())
|
||||
setSelectedFile (new File (appleFileSource.getUniqueName () + ".txt"));
|
||||
else
|
||||
setSelectedFile (new File (appleFileSource.getUniqueName () + ".bin"));
|
||||
|
||||
fileChooser.setSelectedFile (new File (appleFileSource.getUniqueName () + ".bin"));
|
||||
if (fileChooser.showSaveDialog (null) != JFileChooser.APPROVE_OPTION)
|
||||
return;
|
||||
|
||||
if (fileChooser.showSaveDialog (null) == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
File file = fileChooser.getSelectedFile ();
|
||||
try
|
||||
{
|
||||
Files.write (file.toPath (), appleFileSource.getDataSource ().getBuffer (),
|
||||
StandardOpenOption.CREATE_NEW);
|
||||
JOptionPane.showMessageDialog (null,
|
||||
String.format ("File %s saved", file.getName ()));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace ();
|
||||
JOptionPane.showMessageDialog (null, "File failed to save");
|
||||
}
|
||||
}
|
||||
if (formatted.isSelected ())
|
||||
saveBuffer (appleFileSource.getDataSource ().getText ().getBytes ());
|
||||
else
|
||||
saveBuffer (appleFileSource.getDataSource ().getBuffer ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -67,8 +62,8 @@ class SaveFileAction extends AbstractSaveAction implements FileSelectionListener
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.appleFileSource = event.appleFileSource;
|
||||
setEnabled (
|
||||
event.appleFileSource != null && event.appleFileSource.getDataSource () != null
|
||||
&& event.appleFileSource.getDataSource ().getBuffer () != null);
|
||||
|
||||
setEnabled (appleFileSource != null && appleFileSource.getDataSource () != null
|
||||
&& appleFileSource.getDataSource ().getBuffer () != null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,14 @@ package com.bytezone.diskbrowser.gui;
|
|||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import com.bytezone.diskbrowser.disk.Disk;
|
||||
import com.bytezone.diskbrowser.disk.DiskAddress;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class SaveSectorsAction extends AbstractSaveAction implements SectorSelectionListener
|
||||
// -----------------------------------------------------------------------------------//
|
||||
|
@ -19,7 +20,7 @@ class SaveSectorsAction extends AbstractSaveAction implements SectorSelectionLis
|
|||
SaveSectorsAction ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Save sectors...", "Save currently selected sectors");
|
||||
super ("Save sectors...", "Save currently selected sectors", "Save sectors");
|
||||
this.setEnabled (false);
|
||||
}
|
||||
|
||||
|
@ -34,31 +35,16 @@ class SaveSectorsAction extends AbstractSaveAction implements SectorSelectionLis
|
|||
return;
|
||||
}
|
||||
|
||||
if (fileChooser == null)
|
||||
{
|
||||
fileChooser = new JFileChooser ();
|
||||
fileChooser.setDialogTitle ("Save sectors");
|
||||
}
|
||||
// block 0 will not read when it is the only DiskAddress in the list
|
||||
List<DiskAddress> blocks = event.getSectors ();
|
||||
Disk disk = event.getFormattedDisk ().getDisk ();
|
||||
byte[] buffer =
|
||||
blocks.size () == 1 ? disk.readBlock (blocks.get (0)) : disk.readBlocks (blocks);
|
||||
|
||||
fileChooser.setSelectedFile (new File ("savedSectors.bin"));
|
||||
setSelectedFile (new File ("SavedSectors.bin"));
|
||||
|
||||
if (fileChooser.showSaveDialog (null) == JFileChooser.APPROVE_OPTION)
|
||||
{
|
||||
File file = fileChooser.getSelectedFile ();
|
||||
try
|
||||
{
|
||||
byte[] buffer =
|
||||
event.getFormattedDisk ().getDisk ().readBlocks (event.getSectors ());
|
||||
Files.write (file.toPath (), buffer, StandardOpenOption.CREATE_NEW);
|
||||
JOptionPane.showMessageDialog (null,
|
||||
String.format ("File %s saved", file.getName ()));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace ();
|
||||
JOptionPane.showMessageDialog (null, "File failed to save");
|
||||
}
|
||||
}
|
||||
saveBuffer (buffer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
|
@ -10,11 +10,11 @@ import javax.swing.KeyStroke;
|
|||
|
||||
public class ScaleAction extends AbstractAction
|
||||
{
|
||||
private final DataPanel owner;
|
||||
private final OutputPanel owner;
|
||||
private double scale;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public ScaleAction (DataPanel owner, double scale, int menu)
|
||||
public ScaleAction (OutputPanel owner, double scale, int menu)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Scale " + scale);
|
||||
|
|
|
@ -29,14 +29,14 @@ class ScrollRuler extends JComponent
|
|||
private boolean isHex = true;
|
||||
private boolean isTrackMode = true;
|
||||
private LayoutDetails layoutDetails;
|
||||
private final JComponent image;
|
||||
private final DiskLayoutImage diskLayoutImage;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
ScrollRuler (JComponent image, int orientation)
|
||||
ScrollRuler (DiskLayoutImage diskLayoutImage, int orientation)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.orientation = orientation;
|
||||
this.image = image;
|
||||
this.diskLayoutImage = diskLayoutImage;
|
||||
|
||||
// set defaults until setLayout is called
|
||||
if (orientation == HORIZONTAL)
|
||||
|
@ -46,20 +46,20 @@ class ScrollRuler extends JComponent
|
|||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public void setLayout (LayoutDetails layout)
|
||||
public void setLayout (LayoutDetails layoutDetails)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.layoutDetails = layout;
|
||||
this.layoutDetails = layoutDetails;
|
||||
|
||||
// Must match the preferred size of DiskLayoutImage
|
||||
if (orientation == HORIZONTAL)
|
||||
setPreferredSize (
|
||||
new Dimension (layout.block.width * layout.grid.width + 1, HEIGHT));
|
||||
setPreferredSize (new Dimension (
|
||||
layoutDetails.block.width * layoutDetails.grid.width + 1, HEIGHT));
|
||||
else
|
||||
setPreferredSize (
|
||||
new Dimension (WIDTH, layout.block.height * layout.grid.height + 1));
|
||||
setPreferredSize (new Dimension (WIDTH,
|
||||
layoutDetails.block.height * layoutDetails.grid.height + 1));
|
||||
|
||||
setTrackMode (layout.grid.width == 16 || layout.grid.width == 13);
|
||||
setTrackMode (layoutDetails.grid.width == 16 || layoutDetails.grid.width == 13);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -105,7 +105,7 @@ class ScrollRuler extends JComponent
|
|||
{
|
||||
int start = (clipRect.x / width);
|
||||
int end = start + clipRect.width / width;
|
||||
end = Math.min (end, image.getWidth () / width - 1);
|
||||
end = Math.min (end, diskLayoutImage.getWidth () / width - 1);
|
||||
|
||||
String format;
|
||||
int offset;
|
||||
|
@ -131,7 +131,7 @@ class ScrollRuler extends JComponent
|
|||
{
|
||||
int start = (clipRect.y / height);
|
||||
int end = start + clipRect.height / height;
|
||||
end = Math.min (end, image.getHeight () / height - 1);
|
||||
end = Math.min (end, diskLayoutImage.getHeight () / height - 1);
|
||||
|
||||
String format = isHex ? "%04X" : "%04d";
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ class SectorSelectedEvent extends EventObject
|
|||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private final List<DiskAddress> sectors;
|
||||
private final FormattedDisk owner;
|
||||
private final FormattedDisk owner; // for dual-format disks
|
||||
boolean redo;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -20,6 +20,7 @@ class SectorSelectedEvent extends EventObject
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super (source);
|
||||
|
||||
this.sectors = sectors;
|
||||
// always store the parent if this disk is part of a dual-dos disk
|
||||
this.owner = owner.getParent () == null ? owner : owner.getParent ();
|
||||
|
@ -44,8 +45,10 @@ class SectorSelectedEvent extends EventObject
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
SectorListConverter slc = new SectorListConverter (sectors);
|
||||
text.append (slc.sectorText);
|
||||
|
||||
SectorListConverter sectorListConverter = new SectorListConverter (sectors);
|
||||
text.append (sectorListConverter.sectorText);
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,26 +5,23 @@ import java.awt.event.KeyEvent;
|
|||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class ShowFreeSectorsAction extends AbstractAction
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
DiskLayoutPanel panel;
|
||||
MenuHandler mh;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
ShowFreeSectorsAction (MenuHandler mh, DiskLayoutPanel panel)
|
||||
ShowFreeSectorsAction ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
super ("Show free sectors");
|
||||
|
||||
putValue (Action.SHORT_DESCRIPTION,
|
||||
"Display which sectors are marked free in the disk layout panel");
|
||||
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt F"));
|
||||
putValue (Action.MNEMONIC_KEY, KeyEvent.VK_F);
|
||||
this.panel = panel;
|
||||
this.mh = mh;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -32,6 +29,7 @@ class ShowFreeSectorsAction extends AbstractAction
|
|||
public void actionPerformed (ActionEvent e)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
panel.setFree (mh.showFreeSectorsItem.isSelected ());
|
||||
firePropertyChange (e.getActionCommand (), null,
|
||||
((JMenuItem) e.getSource ()).isSelected ());
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@ import com.bytezone.diskbrowser.utilities.Utility;
|
|||
class TreeBuilder
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static SimpleDateFormat sdf = new SimpleDateFormat ("dd MMM yyyy");
|
||||
private static SimpleDateFormat sdf = new SimpleDateFormat ("dd LLL yyyy");
|
||||
|
||||
private final FileComparator fileComparator = new FileComparator ();
|
||||
private final JTree tree;
|
||||
|
@ -219,8 +219,7 @@ class TreeBuilder
|
|||
String type = pos > 0 && !f.isDirectory () ? name.substring (pos) : "";
|
||||
String size = f.isDirectory () ? "" : String.format ("%,14d", f.length ());
|
||||
text.append (String.format ("%s %-40.40s %s %-14s %s%n",
|
||||
f.isDirectory () ? "D" : " ", name, sdf.format (d).replace (".", ""), size,
|
||||
type));
|
||||
f.isDirectory () ? "D" : " ", name, sdf.format (d), size, type));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ class ZObject extends AbstractFile implements Comparable<ZObject>
|
|||
propertyTablePtr = header.getWord (offset + 7);
|
||||
int ptr = propertyTablePtr;
|
||||
int nameLength = header.getByte (ptr) * 2;
|
||||
this.name = nameLength == 0 ? "<<" + id + ">>" : new ZString (header, ++ptr).value;
|
||||
setName (nameLength == 0 ? "<<" + id + ">>" : new ZString (header, ++ptr).value);
|
||||
ptr += nameLength;
|
||||
|
||||
// read each property
|
||||
|
@ -84,11 +84,11 @@ class ZObject extends AbstractFile implements Comparable<ZObject>
|
|||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
text.append (String.format ("ID : %02X (%<3d) %s%n%n", id, name));
|
||||
text.append (String.format ("ID : %02X (%<3d) %s%n%n", id, getName ()));
|
||||
|
||||
String obj1 = parent == 0 ? "" : header.getObject (parent - 1).name;
|
||||
String obj2 = sibling == 0 ? "" : header.getObject (sibling - 1).name;
|
||||
String obj3 = child == 0 ? "" : header.getObject (child - 1).name;
|
||||
String obj1 = parent == 0 ? "" : header.getObject (parent - 1).getName ();
|
||||
String obj2 = sibling == 0 ? "" : header.getObject (sibling - 1).getName ();
|
||||
String obj3 = child == 0 ? "" : header.getObject (child - 1).getName ();
|
||||
|
||||
text.append (String.format ("Parent : %02X (%<3d) %s%n", parent, obj1));
|
||||
text.append (String.format ("Sibling : %02X (%<3d) %s%n", sibling, obj2));
|
||||
|
@ -132,7 +132,7 @@ class ZObject extends AbstractFile implements Comparable<ZObject>
|
|||
public String toString ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return HexFormatter.getHexString (buffer, startPtr, HEADER_SIZE) + " " + name;
|
||||
return HexFormatter.getHexString (buffer, startPtr, HEADER_SIZE) + " " + getName ();
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -200,7 +200,7 @@ class ZObject extends AbstractFile implements Comparable<ZObject>
|
|||
if (propertyNumber >= 19) // directions
|
||||
{
|
||||
ZObject object = getObject ();
|
||||
String objectName = object == null ? "no object" : object.name;
|
||||
String objectName = object == null ? "no object" : object.getName ();
|
||||
|
||||
switch (length)
|
||||
{
|
||||
|
@ -271,8 +271,8 @@ class ZObject extends AbstractFile implements Comparable<ZObject>
|
|||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
int objectId = header.getByte (ptr + i + 1);
|
||||
text.append (
|
||||
String.format ("%s%s", (i == 0 ? "" : ", "), getObject (objectId).name));
|
||||
text.append (String.format ("%s%s", (i == 0 ? "" : ", "),
|
||||
getObject (objectId).getName ()));
|
||||
}
|
||||
}
|
||||
// else
|
||||
|
@ -296,6 +296,6 @@ class ZObject extends AbstractFile implements Comparable<ZObject>
|
|||
public int compareTo (ZObject o)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return this.name.compareTo (o.name);
|
||||
return this.getName ().compareTo (o.getName ());
|
||||
}
|
||||
}
|
|
@ -15,10 +15,8 @@ import com.bytezone.diskbrowser.utilities.Utility;
|
|||
public class WozFile
|
||||
//-----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static final byte[] address16prologue =
|
||||
{ (byte) 0xD5, (byte) 0xAA, (byte) 0x96 };
|
||||
private static final byte[] address13prologue =
|
||||
{ (byte) 0xD5, (byte) 0xAA, (byte) 0xB5 };
|
||||
private static final byte[] address16prologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0x96 };
|
||||
private static final byte[] address13prologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0xB5 };
|
||||
private static final byte[] dataPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0xAD };
|
||||
private static final byte[] epilogue = { (byte) 0xDE, (byte) 0xAA, (byte) 0xEB };
|
||||
// apparently it can be DE AA Ex
|
||||
|
@ -29,9 +27,9 @@ public class WozFile
|
|||
private static final int TRK_SIZE = 0x1A00;
|
||||
private static final int DATA_SIZE = TRK_SIZE - 10;
|
||||
|
||||
private static int[][] interleave =
|
||||
{ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, // 13 sector
|
||||
{ 0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15 } }; // 16 sector
|
||||
private static int[][] interleave = //
|
||||
{ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, // 13 sector
|
||||
{ 0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15 } }; // 16 sector
|
||||
|
||||
public final File file;
|
||||
|
||||
|
@ -146,8 +144,7 @@ public class WozFile
|
|||
{
|
||||
if (info != null)
|
||||
System.out.println (info);
|
||||
throw new DiskNibbleException (
|
||||
String.format ("Invalid chunk name character: %02X%n", val));
|
||||
throw new DiskNibbleException (String.format ("Invalid chunk name character: %02X%n", val));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,9 +299,9 @@ public class WozFile
|
|||
String wozBase2 = home + "Dropbox/Examples/woz test images/WOZ 2.0/";
|
||||
String wozBase3 = home + "Dropbox/Examples/woz test images/WOZ 2.0/3.5/";
|
||||
File[] files = { new File (home + "code/python/wozardry-2.0/bill.woz"),
|
||||
new File (wozBase2 + "DOS 3.3 System Master.woz"),
|
||||
new File (wozBase1 + "DOS 3.3 System Master.woz"),
|
||||
new File (wozBase3 + "Apple IIgs System Disk 1.1.woz") };
|
||||
new File (wozBase2 + "DOS 3.3 System Master.woz"),
|
||||
new File (wozBase1 + "DOS 3.3 System Master.woz"),
|
||||
new File (wozBase3 + "Apple IIgs System Disk 1.1.woz") };
|
||||
try
|
||||
{
|
||||
new WozFile (files[3]);
|
||||
|
@ -369,8 +366,7 @@ public class WozFile
|
|||
String diskTypeText = diskType == 1 ? "5.25" : "3.5";
|
||||
|
||||
text.append (String.format ("Version ............. %d%n", wozVersion));
|
||||
text.append (
|
||||
String.format ("Disk type ........... %d (%s\")%n", diskType, diskTypeText));
|
||||
text.append (String.format ("Disk type ........... %d (%s\")%n", diskType, diskTypeText));
|
||||
text.append (String.format ("Write protected ..... %d%n", writeProtected));
|
||||
text.append (String.format ("Synchronized ........ %d%n", synchronised));
|
||||
text.append (String.format ("Cleaned ............. %d%n", cleaned));
|
||||
|
@ -378,9 +374,8 @@ public class WozFile
|
|||
|
||||
if (wozVersion > 1)
|
||||
{
|
||||
String bootSectorFormatText =
|
||||
bootSectorFormat == 0 ? "Unknown" : bootSectorFormat == 1 ? "16 sector"
|
||||
: bootSectorFormat == 2 ? "13 sector" : "Hybrid";
|
||||
String bootSectorFormatText = bootSectorFormat == 0 ? "Unknown"
|
||||
: bootSectorFormat == 1 ? "16 sector" : bootSectorFormat == 2 ? "13 sector" : "Hybrid";
|
||||
|
||||
text.append (String.format ("%nSides ............... %d%n", sides));
|
||||
text.append (String.format ("Boot sector format .. %d (%s)%n", bootSectorFormat,
|
||||
|
@ -468,8 +463,7 @@ public class WozFile
|
|||
bitCount = val16 (rawBuffer, ptr + DATA_SIZE + 2);
|
||||
|
||||
if (debug1)
|
||||
System.out.println (
|
||||
(String.format ("Bytes: %2d, Bits: %,8d%n%n", bytesUsed, bitCount)));
|
||||
System.out.println ((String.format ("Bytes: %2d, Bits: %,8d%n%n", bytesUsed, bitCount)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -612,10 +606,8 @@ public class WozFile
|
|||
for (Sector sector : sectors)
|
||||
if (sector.dataOffset > 0)
|
||||
{
|
||||
byte[] decodedBuffer =
|
||||
diskReader.decodeSector (newBuffer, sector.dataOffset + 3);
|
||||
int ptr = SECTOR_SIZE
|
||||
* (sector.trackNo * diskSectors + interleave[ndx][sector.sectorNo]);
|
||||
byte[] decodedBuffer = diskReader.decodeSector (newBuffer, sector.dataOffset + 3);
|
||||
int ptr = SECTOR_SIZE * (sector.trackNo * diskSectors + interleave[ndx][sector.sectorNo]);
|
||||
System.arraycopy (decodedBuffer, 0, diskBuffer, ptr, decodedBuffer.length);
|
||||
}
|
||||
}
|
||||
|
@ -627,8 +619,7 @@ public class WozFile
|
|||
{
|
||||
StringBuilder text = new StringBuilder ();
|
||||
if (info.wozVersion == 1)
|
||||
text.append (
|
||||
String.format ("WOZ1: Bytes: %2d, Bits: %,8d%n%n", bytesUsed, bitCount));
|
||||
text.append (String.format ("WOZ1: Bytes: %2d, Bits: %,8d%n%n", bytesUsed, bitCount));
|
||||
else
|
||||
text.append (String.format ("WOZ2: Start: %4d, Blocks: %2d, Bits: %,8d%n%n",
|
||||
startingBlock, blockCount, bitCount));
|
||||
|
@ -728,9 +719,8 @@ public class WozFile
|
|||
String fld = info.diskType == 1 ? "Vol" : info.diskType == 2 ? "Sde" : "???";
|
||||
String dataOffsetText = dataOffset < 0 ? "" : String.format ("%04X", dataOffset);
|
||||
|
||||
return String.format (
|
||||
"%s: %02X Trk: %02X Sct: %02X Chk: %02X Add: %04X Dat: %s", fld, volume,
|
||||
trackNo, sectorNo, checksum, addressOffset, dataOffsetText);
|
||||
return String.format ("%s: %02X Trk: %02X Sct: %02X Chk: %02X Add: %04X Dat: %s", fld,
|
||||
volume, trackNo, sectorNo, checksum, addressOffset, dataOffsetText);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.bytezone.diskbrowser.utilities;
|
||||
package com.bytezone.diskbrowser.nufx;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -10,6 +10,7 @@ import com.bytezone.diskbrowser.prodos.write.DiskFullException;
|
|||
import com.bytezone.diskbrowser.prodos.write.FileAlreadyExistsException;
|
||||
import com.bytezone.diskbrowser.prodos.write.ProdosDisk;
|
||||
import com.bytezone.diskbrowser.prodos.write.VolumeCatalogFullException;
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class Binary2
|
||||
|
@ -19,11 +20,11 @@ public class Binary2
|
|||
"------------------------------------------------------"
|
||||
+ "-----------------------";
|
||||
|
||||
Binary2Header binary2Header;
|
||||
byte[] buffer;
|
||||
List<Binary2Header> headers = new ArrayList<> ();
|
||||
int totalBlocks;
|
||||
String fileName;
|
||||
private Binary2Header binary2Header;
|
||||
private byte[] buffer;
|
||||
private List<Binary2Header> headers = new ArrayList<> ();
|
||||
private int totalBlocks;
|
||||
private String fileName;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public Binary2 (Path path) throws IOException
|
||||
|
@ -31,18 +32,26 @@ public class Binary2
|
|||
{
|
||||
fileName = path.toFile ().getName ();
|
||||
buffer = Files.readAllBytes (path);
|
||||
read (buffer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void read (byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int ptr = 0;
|
||||
|
||||
do
|
||||
{
|
||||
binary2Header = new Binary2Header (buffer, ptr);
|
||||
System.out.println (binary2Header);
|
||||
headers.add (binary2Header);
|
||||
|
||||
ptr += ((binary2Header.eof - 1) / 128 + 2) * 128;
|
||||
if (ptr > buffer.length) // not enough blocks for this file
|
||||
break;
|
||||
|
||||
totalBlocks += binary2Header.totalBlocks;
|
||||
ptr += ((binary2Header.eof - 1) / 128 + 1) * 128 + 128;
|
||||
headers.add (binary2Header);
|
||||
} while (binary2Header.filesToFollow > 0);
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -57,9 +66,19 @@ public class Binary2
|
|||
byte[] dataBuffer = new byte[header.eof]; // this sux
|
||||
System.arraycopy (buffer, header.ptr + 128, dataBuffer, 0, dataBuffer.length);
|
||||
|
||||
disk.addFile (header.fileName, header.fileType, header.auxType, header.created,
|
||||
header.modified, dataBuffer, header.eof);
|
||||
if (header.compressed && dataBuffer[0] == 0x76 && dataBuffer[1] == (byte) 0xFF)
|
||||
{
|
||||
String name = Utility.getCString (dataBuffer, 4);
|
||||
|
||||
Squeeze squeeze = new Squeeze ();
|
||||
byte[] tmp = squeeze.unSqueeze (dataBuffer);
|
||||
|
||||
disk.addFile (name, header.fileType, header.auxType, header.created,
|
||||
header.modified, tmp, tmp.length);
|
||||
}
|
||||
else
|
||||
disk.addFile (header.fileName, header.fileType, header.auxType, header.created,
|
||||
header.modified, dataBuffer, header.eof);
|
||||
}
|
||||
disk.close ();
|
||||
|
||||
|
@ -82,24 +101,11 @@ public class Binary2
|
|||
|
||||
text.append (String.format ("%s%n", UNDERLINE));
|
||||
|
||||
// int totalUncompressedSize = 0;
|
||||
// int totalCompressedSize = 0;
|
||||
|
||||
for (Binary2Header header : headers)
|
||||
{
|
||||
text.append (String.format ("%s%n", header.getLine ()));
|
||||
// totalUncompressedSize += record.getUncompressedSize ();
|
||||
// totalCompressedSize += record.getCompressedSize ();
|
||||
}
|
||||
|
||||
text.append (String.format ("%s%n", UNDERLINE));
|
||||
|
||||
// float pct = 0;
|
||||
// if (totalUncompressedSize > 0)
|
||||
// pct = totalCompressedSize * 100 / totalUncompressedSize;
|
||||
// text.append (String.format (" Uncomp:%7d Comp:%7d %%of orig:%3.0f%%%n%n",
|
||||
// totalUncompressedSize, totalCompressedSize, pct));
|
||||
|
||||
return text.toString ();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.bytezone.diskbrowser.utilities;
|
||||
package com.bytezone.diskbrowser.nufx;
|
||||
|
||||
import static com.bytezone.diskbrowser.prodos.ProdosConstants.fileTypes;
|
||||
|
||||
|
@ -6,16 +6,17 @@ import java.time.LocalDateTime;
|
|||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
import com.bytezone.diskbrowser.prodos.write.ProdosDisk;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class Binary2Header
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
static DateTimeFormatter formatter = DateTimeFormatter.ofPattern ("dd-LLL-yy HH:mm");
|
||||
static String[] osTypes =
|
||||
{ "Prodos", "DOS 3.3", "Reserved", "DOS 3.2 or 3.1", "Pascal", "Macintosh MFS",
|
||||
"Macintosh HFS", "Lisa", "CPM", "Reserved", "MS-DOS", "High Sierra (CD-ROM)",
|
||||
"ISO 9660 (CD-ROM)", "AppleShare" };
|
||||
static String[] osTypes = { "Prodos", "DOS 3.3", "Reserved", "DOS 3.2 or 3.1", "Pascal",
|
||||
"Macintosh MFS", "Macintosh HFS", "Lisa", "CPM", "Reserved", "MS-DOS", "High Sierra (CD-ROM)",
|
||||
"ISO 9660 (CD-ROM)", "AppleShare" };
|
||||
|
||||
int ptr;
|
||||
byte[] buffer;
|
||||
|
@ -87,8 +88,8 @@ public class Binary2Header
|
|||
public String getLine ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return String.format (" %-33s %3s $%04X %s unc %7d", fileName,
|
||||
fileTypes[fileType], auxType, modified.format (formatter), eof);
|
||||
return String.format (" %-33s %3s $%04X %s unc %7d", fileName, fileTypes[fileType],
|
||||
auxType, modified.format (formatter), eof);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -115,12 +116,13 @@ public class Binary2Header
|
|||
text.append (String.format ("Prodos storage type ... %02X%n", prodos16storageType));
|
||||
text.append (String.format ("Prodos total blocks ... %02X%n", prodos16totalBlocks));
|
||||
text.append (String.format ("Prodos eof ............ %06X %<,d%n", prodos16eof));
|
||||
text.append (
|
||||
String.format ("Disk space needed ..... %08X %<,d%n", diskSpaceRequired));
|
||||
text.append (
|
||||
String.format ("OS type ............... %02X %s%n", osType, osTypes[osType]));
|
||||
text.append (String.format ("Disk space needed ..... %08X %<,d%n", diskSpaceRequired));
|
||||
text.append (String.format ("OS type ............... %02X %s%n", osType, osTypes[osType]));
|
||||
text.append (String.format ("Native file type ...... %02X%n", nativeFileType));
|
||||
text.append (String.format ("Data flags ............ %02X%n", dataFlags));
|
||||
text.append (String.format (" compressed .......... %s%n", compressed));
|
||||
text.append (String.format (" encrypted ........... %s%n", encrypted));
|
||||
text.append (String.format (" sparse .............. %s%n", sparsePacked));
|
||||
text.append (String.format ("Version ............... %02X%n", version));
|
||||
text.append (String.format ("Following files ....... %02X%n", filesToFollow));
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
package com.bytezone.diskbrowser.utilities;
|
||||
package com.bytezone.diskbrowser.nufx;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
abstract class LZW
|
||||
// -----------------------------------------------------------------------------------//
|
||||
|
@ -17,7 +19,7 @@ abstract class LZW
|
|||
|
||||
int crc;
|
||||
int crcBase;
|
||||
int v3eof; // LZW/2 calculates the crc sans padding
|
||||
int v3eof; // LZW/2 calculates the crc without padding
|
||||
|
||||
private int byteBuffer; // one character buffer
|
||||
private int bitsLeft; // unused bits left in buffer
|
||||
|
@ -88,7 +90,7 @@ abstract class LZW
|
|||
}
|
||||
|
||||
bitsLeft--;
|
||||
boolean bit = ((byteBuffer << bitsLeft) & 0x80) == 0x80;
|
||||
boolean bit = ((byteBuffer << bitsLeft) & 0x80) != 0;
|
||||
|
||||
return bit;
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
package com.bytezone.diskbrowser.utilities;
|
||||
package com.bytezone.diskbrowser.nufx;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class LZW1 extends LZW
|
|
@ -1,4 +1,6 @@
|
|||
package com.bytezone.diskbrowser.utilities;
|
||||
package com.bytezone.diskbrowser.nufx;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class LZW2 extends LZW
|
161
src/com/bytezone/diskbrowser/nufx/LZW3.java
Normal file
|
@ -0,0 +1,161 @@
|
|||
package com.bytezone.diskbrowser.nufx;
|
||||
|
||||
// DreamGraphix LZW
|
||||
// code ported from CiderPress' DreamGraphix::UnpackDG()
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class LZW3
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
static final int[] bitMasks = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1FF, 0x3FF, 0x7FF, 0xFFF };
|
||||
static final int CLEAR_CODE = 256;
|
||||
static final int EOF_CODE = 257;
|
||||
static final int FIRST_FREE_CODE = 258;
|
||||
|
||||
int nBitMod1;
|
||||
int nBitMask;
|
||||
int finChar;
|
||||
int oldCode;
|
||||
int inCode;
|
||||
int freeCode;
|
||||
int maxCode;
|
||||
int k;
|
||||
|
||||
int bitOffset;
|
||||
|
||||
int[] hashNext = new int[4096];
|
||||
int[] hashChar = new int[4096];
|
||||
|
||||
int ptr = 0;
|
||||
int iCode;
|
||||
int[] stack = new int[32768];
|
||||
int stackIdx = 0;
|
||||
|
||||
byte[] srcBuf;
|
||||
byte[] dstBuf;
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public int unpack (byte[] src, byte[] dst, int max)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
assert max <= dst.length;
|
||||
|
||||
srcBuf = src;
|
||||
dstBuf = dst;
|
||||
|
||||
initTable ();
|
||||
|
||||
int a;
|
||||
int y;
|
||||
|
||||
bitOffset = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (ptr > max)
|
||||
{
|
||||
System.out.println ("LZW3 overrun");
|
||||
return -1;
|
||||
}
|
||||
|
||||
iCode = readCode ();
|
||||
|
||||
if (iCode == EOF_CODE)
|
||||
break;
|
||||
|
||||
if (iCode == CLEAR_CODE)
|
||||
{
|
||||
initTable ();
|
||||
iCode = readCode ();
|
||||
|
||||
oldCode = iCode;
|
||||
k = iCode;
|
||||
finChar = iCode;
|
||||
dstBuf[ptr++] = (byte) iCode;
|
||||
continue;
|
||||
}
|
||||
|
||||
a = inCode = iCode;
|
||||
|
||||
if (iCode >= freeCode)
|
||||
{
|
||||
stack[stackIdx++] = finChar;
|
||||
a = oldCode;
|
||||
}
|
||||
|
||||
while (a >= 256)
|
||||
{
|
||||
y = a;
|
||||
a = hashChar[y];
|
||||
stack[stackIdx++] = a;
|
||||
a = hashNext[y];
|
||||
}
|
||||
|
||||
finChar = a;
|
||||
k = a;
|
||||
y = 0;
|
||||
|
||||
dstBuf[ptr + y++] = (byte) a;
|
||||
|
||||
while (stackIdx > 0)
|
||||
{
|
||||
a = stack[--stackIdx];
|
||||
dstBuf[ptr + y++] = (byte) a;
|
||||
}
|
||||
|
||||
ptr += y;
|
||||
|
||||
addCode ();
|
||||
|
||||
oldCode = inCode;
|
||||
|
||||
if (freeCode < maxCode)
|
||||
continue;
|
||||
|
||||
if (nBitMod1 == 12)
|
||||
continue;
|
||||
|
||||
nBitMod1++;
|
||||
nBitMask = bitMasks[nBitMod1];
|
||||
maxCode <<= 1;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void initTable ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
nBitMod1 = 9;
|
||||
nBitMask = bitMasks[nBitMod1];
|
||||
maxCode = 1 << nBitMod1;
|
||||
freeCode = FIRST_FREE_CODE;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private int readCode ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
int bitIdx = bitOffset & 0x07;
|
||||
int byteIdx = bitOffset >>> 3; // no sign extension
|
||||
|
||||
int iCode = srcBuf[byteIdx] & 0xFF | (srcBuf[byteIdx + 1] & 0xFF) << 8
|
||||
| (srcBuf[byteIdx + 2] & 0xFF) << 16;
|
||||
|
||||
iCode >>>= bitIdx;
|
||||
iCode &= nBitMask;
|
||||
|
||||
bitOffset += nBitMod1;
|
||||
|
||||
return iCode;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
private void addCode ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
hashChar[freeCode] = k;
|
||||
hashNext[freeCode] = oldCode;
|
||||
freeCode++;
|
||||
}
|
||||
}
|
|
@ -1,11 +1,15 @@
|
|||
package com.bytezone.diskbrowser.utilities;
|
||||
package com.bytezone.diskbrowser.nufx;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.DateTime;
|
||||
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class MasterHeader
|
||||
public class MasterHeader
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static final byte[] NuFile =
|
||||
{ 0x4E, (byte) 0xF5, 0x46, (byte) 0xE9, 0x6C, (byte) 0xE5 };
|
||||
private static final byte[] NuFile = { 0x4E, (byte) 0xF5, 0x46, (byte) 0xE9, 0x6C, (byte) 0xE5 };
|
||||
private static final byte[] BIN2 = { 0x0A, 0x47, 0x4C };
|
||||
|
||||
private final int crc;
|
||||
|
@ -30,15 +34,6 @@ class MasterHeader
|
|||
if (Utility.isMagic (buffer, ptr, NuFile))
|
||||
break;
|
||||
|
||||
// internet.shk has 0x2000 bytes of text at the start
|
||||
// if (Utility.isMagic (buffer, 0x2000, NuFile))
|
||||
// {
|
||||
// System.out.println ("found it");
|
||||
// ptr = 0x2000;
|
||||
// bin2 = true;
|
||||
// break;
|
||||
// }
|
||||
|
||||
if (isBin2 (buffer, ptr))
|
||||
{
|
||||
binary2Header = new Binary2Header (buffer, 0);
|
|
@ -1,4 +1,4 @@
|
|||
package com.bytezone.diskbrowser.utilities;
|
||||
package com.bytezone.diskbrowser.nufx;
|
||||
|
||||
import static com.bytezone.diskbrowser.prodos.ProdosConstants.BLOCK_SIZE;
|
||||
|
||||
|
@ -14,6 +14,7 @@ import com.bytezone.diskbrowser.prodos.write.FileAlreadyExistsException;
|
|||
import com.bytezone.diskbrowser.prodos.write.FileEntry;
|
||||
import com.bytezone.diskbrowser.prodos.write.ProdosDisk;
|
||||
import com.bytezone.diskbrowser.prodos.write.VolumeCatalogFullException;
|
||||
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
public class NuFX
|
||||
|
@ -38,13 +39,28 @@ public class NuFX
|
|||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
buffer = Files.readAllBytes (path);
|
||||
volumeName = new VolumeName (path);
|
||||
volumeName = new VolumeName (path.getFileName ().toString ());
|
||||
|
||||
read (buffer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public NuFX (byte[] buffer, String fileName)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
this.buffer = buffer;
|
||||
this.volumeName = new VolumeName (fileName);
|
||||
|
||||
read (buffer);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
void read (byte[] buffer)
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
masterHeader = new MasterHeader (buffer);
|
||||
|
||||
int dataPtr = 48;
|
||||
if (masterHeader.bin2)
|
||||
dataPtr += 128;
|
||||
int dataPtr = masterHeader.bin2 ? 176 : 48;
|
||||
|
||||
if (debug)
|
||||
System.out.printf ("%s%n%n", masterHeader);
|
||||
|
@ -80,6 +96,7 @@ public class NuFX
|
|||
if (record.hasDisk ())
|
||||
++totalDisks;
|
||||
}
|
||||
// System.out.println (toString ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -249,8 +266,8 @@ public class NuFX
|
|||
StringBuilder text = new StringBuilder ();
|
||||
|
||||
text.append (String.format (" %-15.15s Created:%-17s Mod:%-17s Recs:%5d%n%n",
|
||||
volumeName.getFileName (), masterHeader.getCreated2 (),
|
||||
masterHeader.getModified2 (), masterHeader.getTotalRecords ()));
|
||||
volumeName.volumeName, masterHeader.getCreated2 (), masterHeader.getModified2 (),
|
||||
masterHeader.getTotalRecords ()));
|
||||
|
||||
text.append (" Name Type Auxtyp Archived"
|
||||
+ " Fmat Size Un-Length\n");
|
||||
|
@ -287,27 +304,19 @@ public class NuFX
|
|||
|
||||
private String volumeName = "DiskBrowser";
|
||||
private int nameOffset = 0;
|
||||
private Path path;
|
||||
|
||||
// -------------------------------------------------------------------------------//
|
||||
VolumeName (Path path)
|
||||
VolumeName (String name)
|
||||
// -------------------------------------------------------------------------------//
|
||||
{
|
||||
this.path = path;
|
||||
volumeName = getFileName ();
|
||||
int pos = volumeName.lastIndexOf ('.');
|
||||
int pos = name.lastIndexOf ('.');
|
||||
if (pos > 0)
|
||||
volumeName = volumeName.substring (0, pos);
|
||||
if (volumeName.length () > 15)
|
||||
volumeName = volumeName.substring (0, 15);
|
||||
volumeName = volumeName.replace (' ', '.');
|
||||
}
|
||||
name = name.substring (0, pos);
|
||||
if (name.length () > 15)
|
||||
name = name.substring (0, 15);
|
||||
name = name.replace (' ', '.');
|
||||
|
||||
// -------------------------------------------------------------------------------//
|
||||
String getFileName ()
|
||||
// -------------------------------------------------------------------------------//
|
||||
{
|
||||
return path.getFileName ().toString ();
|
||||
this.volumeName = name;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------//
|
|
@ -1,4 +1,4 @@
|
|||
package com.bytezone.diskbrowser.utilities;
|
||||
package com.bytezone.diskbrowser.nufx;
|
||||
|
||||
import static com.bytezone.diskbrowser.prodos.ProdosConstants.fileTypes;
|
||||
|
||||
|
@ -6,18 +6,21 @@ import java.time.LocalDateTime;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.DateTime;
|
||||
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
// -----------------------------------------------------------------------------------//
|
||||
class Record
|
||||
// -----------------------------------------------------------------------------------//
|
||||
{
|
||||
private static final byte[] NuFX = { 0x4E, (byte) 0xF5, 0x46, (byte) 0xD8 };
|
||||
private static String[] fileSystems =
|
||||
{ "", "ProDOS/SOS", "DOS 3.3", "DOS 3.2", "Apple II Pascal", "Macintosh HFS",
|
||||
"Macintosh MFS", "Lisa File System", "Apple CP/M", "", "MS-DOS", "High Sierra",
|
||||
"ISO 9660", "AppleShare" };
|
||||
private static String[] fileSystems = { "", "ProDOS/SOS", "DOS 3.3", "DOS 3.2",
|
||||
"Apple II Pascal", "Macintosh HFS", "Macintosh MFS", "Lisa File System",
|
||||
"Apple CP/M", "", "MS-DOS", "High Sierra", "ISO 9660", "AppleShare" };
|
||||
|
||||
private static String[] storage = { "", "Seedling", "Sapling", "Tree", "", "Extended",
|
||||
"", "", "", "", "", "", "", "Subdirectory" };
|
||||
"", "", "", "", "", "", "", "Subdirectory" };
|
||||
|
||||
private static String[] accessChars = { "D", "R", "B", "", "", "I", "W", "R" };
|
||||
private static String threadFormats[] = { "unc", "sq ", "lz1", "lz2", "", "" };
|
||||
|
@ -250,6 +253,13 @@ class Record
|
|||
return 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
String getThreadFormatText ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
return threadFormats[getThreadFormat ()];
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
int getUncompressedSize ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -279,6 +289,17 @@ class Record
|
|||
return size;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
public float getCompressedPct ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
{
|
||||
float pct = 100;
|
||||
if (getUncompressedSize () > 0)
|
||||
pct = getCompressedSize () * 100 / getUncompressedSize ();
|
||||
|
||||
return pct;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|
||||
byte[] getData ()
|
||||
// ---------------------------------------------------------------------------------//
|
||||
|
@ -309,9 +330,9 @@ class Record
|
|||
if (name.length () > 27)
|
||||
name = ".." + name.substring (name.length () - 25);
|
||||
|
||||
float pct = 100;
|
||||
if (getUncompressedSize () > 0)
|
||||
pct = getCompressedSize () * 100 / getUncompressedSize ();
|
||||
// float pct = 100;
|
||||
// if (getUncompressedSize () > 0)
|
||||
// pct = getCompressedSize () * 100 / getUncompressedSize ();
|
||||
|
||||
String lockedFlag = (access | 0xC3) == 1 ? "+" : " ";
|
||||
String forkedFlag = hasResource () ? "+" : " ";
|
||||
|
@ -319,11 +340,11 @@ class Record
|
|||
if (hasDisk ())
|
||||
return String.format ("%s%-27.27s %-4s %-6s %-15s %s %3.0f%% %7d", lockedFlag,
|
||||
name, "Disk", (getUncompressedSize () / 1024) + "k", archived.format2 (),
|
||||
threadFormats[getThreadFormat ()], pct, getUncompressedSize ());
|
||||
getThreadFormatText (), getCompressedPct (), getUncompressedSize ());
|
||||
|
||||
return String.format ("%s%-27.27s %s%s $%04X %-15s %s %3.0f%% %7d", lockedFlag,
|
||||
name, fileTypes[fileType], forkedFlag, auxType, archived.format2 (),
|
||||
threadFormats[getThreadFormat ()], pct, getUncompressedSize ());
|
||||
getThreadFormatText (), getCompressedPct (), getUncompressedSize ());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------//
|