Compare commits

...

154 Commits
1.59 ... master

Author SHA1 Message Date
Denis Molony
2bc330e377 tidying 2024-05-07 08:34:02 +10:00
Denis Molony
6c81bcc93b allow dos 4.5 2024-05-07 08:28:33 +10:00
Denis Molony
171fd66ba1 tidying 2024-05-02 12:38:45 +10:00
Denis Molony
aa77ec1cd4 fixed catalog date display problem 2024-04-29 18:26:31 +10:00
Denis Molony
8f95988596 link to DiskBrowserApp 2024-04-06 16:33:53 +10:00
Denis Molony
8cb682f068 added C1/4100 2024-03-12 17:37:13 +10:00
Denis Molony
dfc7a68580 renamed jarFolder 2023-09-30 23:55:41 +10:00
Denis Molony
4b476457d3 added ant build.xml 2023-09-28 15:27:27 +10:00
Denis Molony
3bf972a761 tidying 2023-09-16 06:51:31 +10:00
Denis Molony
fd5bee6e5c tidying 2023-04-07 19:50:02 +10:00
Denis Molony
0af6714119 tidying 2023-03-16 09:00:31 +10:00
Denis Molony
22dfaf65c6 spacing 2023-03-11 16:35:48 +10:00
Denis Molony
f4a6465b04 shorten absolute path 2023-02-24 12:33:21 +10:00
Denis Molony
64d5ce9ee2 allow 2img length = 0 2023-02-20 13:02:53 +10:00
Denis Molony
4e48437adc tidying 2023-02-15 20:30:34 +10:00
Denis Molony
e2abdcabc9 added comment 2023-01-16 13:08:46 +10:00
Denis Molony
bc0993e9d3 better pascal TEXT handling 2022-12-15 20:35:26 +10:00
Denis Molony
9fba3893ba tidying 2022-12-11 01:59:44 +10:00
Denis Molony
09c4542118 Merge branch 'master' of https://github.com/dmolony/DiskBrowser.git 2022-12-11 01:56:35 +10:00
Denis Molony
af3ead0441 tidying 2022-12-11 01:54:00 +10:00
Denis Molony
c12392200b
Merge pull request #24 from frankmilliron/master
Add some new equates
2022-11-27 04:53:01 +10:00
frankmilliron
794fef8610
Add some new equates 2022-11-26 10:31:06 -08:00
frankmilliron
2ec0e10c5e
Add some new equates 2022-11-26 10:27:06 -08:00
Denis Molony
668ed719fa tidying 2022-09-16 06:26:52 +10:00
Denis Molony
23b95675cf tidying 2022-08-22 16:55:32 +10:00
Denis Molony
b98ecbed8d allow truncated bin2 files 2022-08-10 21:01:21 +10:00
Denis Molony
82381a6a47 fixed DateTime bug 2022-08-10 18:06:43 +10:00
Denis Molony
3f2f1bfbca stupid eclipse 2022-08-10 15:10:16 +10:00
Denis Molony
a7119528a6 reorder block allocations 2022-08-10 15:08:10 +10:00
Denis Molony
6f943ae8c2 tidying 2022-07-31 10:08:15 +10:00
Denis Molony
5add6c0729 tidying 2022-07-31 09:58:00 +10:00
Denis Molony
921c946ab5 Added Squeeze format (BQY) 2022-07-31 09:21:52 +10:00
Denis Molony
898587b23b Added a formatted checkbox to the save dialog 2022-07-31 07:13:59 +10:00
Denis Molony
37c489f252 Fixed Pascal bug with invalid dates 2022-07-29 23:00:30 +10:00
Denis Molony
036e47b9b1 tidying 2022-07-09 08:13:05 +10:00
Denis Molony
250c1a9bd9 more spell code 2022-06-21 13:59:42 +10:00
Denis Molony
b19e89d7cf fixed bug in known spells 2022-06-21 12:51:43 +10:00
Denis Molony
d71cabb754 tidying 2022-06-17 18:24:43 +10:00
Denis Molony
848b2469ae refactoring Character 2022-06-11 15:52:58 +10:00
Denis Molony
989b1d5ab9 fixed link to WizardryApp 2022-06-10 15:59:47 +10:00
Denis Molony
e0a2c50d5b fixed attributes bug 2022-06-10 15:56:48 +10:00
Denis Molony
8765299cf4 tidying 2022-06-09 16:14:52 +10:00
Denis Molony
97fe58d94d refactoring getWizLong and getSignedShort 2022-06-06 10:15:14 +10:00
Denis Molony
7d4d8c75e6 adjusted huffman decode routine 2022-06-04 13:06:20 +10:00
Denis Molony
f5664a9ce9 Updated Item 2022-05-31 17:44:41 +10:00
Denis Molony
9d8cdcd67b explained wiz4 naming convention 2022-05-29 19:58:12 +10:00
Denis Molony
12b74f9d21 Wizardry IV screen 2022-05-29 19:51:19 +10:00
Denis Molony
1b405c6f38 tidying 2022-05-29 18:53:08 +10:00
Denis Molony
66d6910f91 started combining CharacterV1 and CharacterV4 2022-05-29 16:21:20 +10:00
Denis Molony
572ee8c3a1 added possessions to characters 2022-05-29 15:16:11 +10:00
Denis Molony
2a14b7baad display attributes and spells 2022-05-29 12:52:42 +10:00
Denis Molony
a633e28ed3 added character parties 2022-05-29 10:43:10 +10:00
Denis Molony
ca11e8ee68 improved group routine 2022-05-28 19:15:32 +10:00
Denis Molony
ce52253f5d found how to group characters 2022-05-28 18:54:06 +10:00
Denis Molony
e408aa3d62 tidying 2022-05-28 16:19:37 +10:00
Denis Molony
c4b4d17f52 Items and Monsters for Wizardry IV 2022-05-28 12:59:25 +10:00
Denis Molony
0b72f1a37d Added characters to Wiz4 2022-05-27 18:30:30 +10:00
Denis Molony
1b86b31233 removed GregorianCalendar 2022-05-11 10:09:27 +10:00
Denis Molony
1b9e9d47ac checking Wiz4 disks 2022-05-03 15:36:37 +10:00
Denis Molony
decc781572 tidying 2022-04-13 09:51:17 +10:00
Denis Molony
16ccc2632a allow woz disks to be saved as converted disk images 2022-04-09 18:25:02 +10:00
Denis Molony
40c2afbd48 tidying 2022-04-06 18:05:37 +10:00
Denis Molony
f9038810d2 wrong picture 2022-03-31 12:06:39 +10:00
Denis Molony
3435e825df use stored experience points 2022-03-31 12:04:23 +10:00
Denis Molony
ff7c6fd126 found bug in Wizardry exp points calculation 2022-03-29 18:00:32 +10:00
Denis Molony
91846d8563 later screen 2022-03-28 18:36:17 +10:00
Denis Molony
19b6339ac5 calculate experience points correctly 2022-03-28 17:02:01 +10:00
Denis Molony
db4953618c allow woz format pascal disks 2022-03-28 13:55:49 +10:00
Denis Molony
c1deee56a0 tidying 2022-03-26 21:37:41 +10:00
Denis Molony
b1ed1a74ba tidying 2022-03-26 18:07:17 +10:00
Denis Molony
cf0cfd278b added Message 2022-03-18 19:22:07 +10:00
Denis Molony
48aca6e1eb tidying 2022-03-14 08:46:56 +10:00
Denis Molony
d83ac3afda changed Maze hex output to debug screen 2022-03-10 21:06:52 +10:00
Denis Molony
2270b1f6db tidying 2022-03-10 19:04:52 +10:00
Denis Molony
da67dbe0d7 more details on maze levels 2022-03-10 16:21:18 +10:00
Denis Molony
133352ba31 various 2022-02-07 15:28:22 +10:00
Denis Molony
761c43dc3d changed award function 2022-02-07 15:26:42 +10:00
Denis Molony
d03de97247 fixed stack overflow bug 2022-02-07 15:26:17 +10:00
Denis Molony
e67bbeaf8b made some functions visible for Wizardry Disk Browser 2022-01-27 13:14:07 +10:00
Denis Molony
6dfc72b2d2 adding new instanceof pattern 2021-09-28 19:17:10 +10:00
Denis Molony
fb748df4ae tidying 2021-09-19 17:09:34 +10:00
Denis Molony
4a03c411fc renamed DataPanel to OutputPanel 2021-09-18 23:44:48 +10:00
Denis Molony
54db7d95d6 replaced pascal screen 2021-09-18 23:28:48 +10:00
Denis Molony
59b22be2bd tidying 2021-09-16 18:24:13 +10:00
Denis Molony
47a07f5cfe added second pascal screen 2021-09-15 14:30:28 +10:00
Denis Molony
bca12f0738 tidying 2021-09-15 10:51:45 +10:00
Denis Molony
27100ad38e DreamGraphix 3200 2021-08-30 16:56:43 +10:00
Denis Molony
2a6fd74013 tidying 2021-08-20 20:04:53 +10:00
Denis Molony
4767c317d0 fixed bad prodos date 2021-07-30 19:33:03 +10:00
Denis Molony
068f382c87 tidying 2021-07-30 06:03:40 +10:00
Denis Molony
e7d8c4ebc2 tidying 2021-07-29 13:18:13 +10:00
Denis Molony
9ef0f82dea tidying 2021-07-29 13:17:36 +10:00
Denis Molony
fba8c07142 tidying 2021-07-29 09:35:07 +10:00
Denis Molony
4aefc8b695 abandoned load address indexing 2021-07-29 09:33:41 +10:00
Denis Molony
a8574d24f8 moved code to Utility 2021-07-29 06:32:22 +10:00
Denis Molony
449e6c0e9a tidying 2021-07-28 17:19:32 +10:00
Denis Molony
09b6f66855 MS floating point 2021-07-28 14:42:28 +10:00
Denis Molony
f30fe1a78a debugged bug in debug 2021-07-27 17:58:39 +10:00
Denis Molony
0e40e25710 debug for CP/M basic 2021-07-27 17:55:19 +10:00
Denis Molony
f02c932d91 tidying 2021-07-27 15:57:46 +10:00
Denis Molony
c18cfe9ed7 more CP/M basic tokens 2021-07-27 11:58:43 +10:00
Denis Molony
dcb3e32845 more CP/M basic 2021-07-26 21:39:05 +10:00
Denis Molony
08d6d1b136 better CP/M basic 2021-07-26 15:42:40 +10:00
Denis Molony
954b0c0bd8 more CP/M basic 2021-07-26 12:02:52 +10:00
Denis Molony
f22b4dcd46 tidying 2021-07-25 21:11:50 +10:00
Denis Molony
c42481637e oops 2021-07-25 18:31:02 +10:00
Denis Molony
7ca8160d13 initial CP/M basic 2021-07-25 18:30:22 +10:00
Denis Molony
26316a82a9 better CP/M format checker 2021-07-24 20:59:00 +10:00
Denis Molony
5f29cfcd09 removed protected from AbstractFile.name 2021-07-24 18:08:40 +10:00
Denis Molony
7f2e963689 tidying 2021-07-22 19:40:52 +10:00
Denis Molony
8ea18c8cc1 resource fork in DefaultAppleFile 2021-07-21 21:17:43 +10:00
Denis Molony
f92fe5b57e edit 2021-07-02 20:36:59 +10:00
Denis Molony
bb4dcbdd7c edit 2021-07-02 20:33:10 +10:00
Denis Molony
8aec65449e edit 2021-07-02 20:31:31 +10:00
Denis Molony
ff273e7df9 edit 2021-07-02 20:26:59 +10:00
Denis Molony
1a1f9df93f edit 2021-07-02 16:33:12 +10:00
Denis Molony
80a07c0496 edit 2021-07-02 16:11:53 +10:00
Denis Molony
8369e4a788 edit 2021-07-02 16:09:37 +10:00
Denis Molony
bfeab1477c edit 2021-07-02 16:04:42 +10:00
Denis Molony
ad8464c6c2 edit 2021-07-02 16:03:31 +10:00
Denis Molony
b1ff2f7740 edit 2021-07-02 16:01:45 +10:00
Denis Molony
4040238bbf edit 2021-07-02 15:59:50 +10:00
Denis Molony
70f21070d5 edit 2021-07-02 15:58:19 +10:00
Denis Molony
91693bbc37 edit 2021-07-02 15:56:54 +10:00
Denis Molony
8a9b824302 edit 2021-07-02 15:53:09 +10:00
Denis Molony
06f4713baa edit 2021-07-02 15:49:55 +10:00
Denis Molony
e7ded68b03 extra screen 2021-07-02 15:48:30 +10:00
Denis Molony
58cec66535 edited 2021-07-02 15:45:07 +10:00
Denis Molony
c105d07e60 doco for applesoft formatting 2021-07-02 15:43:17 +10:00
Denis Molony
3e32b3caf0 fixed bolloxed pascal date format 2021-06-25 19:04:20 +10:00
Denis Molony
7aa80b8b5e date format fix 2021-06-19 19:46:59 +10:00
Denis Molony
5e053872a9 CPM fixes 2021-06-18 10:48:38 +10:00
Denis Molony
7d162a4baf more listeners, recognise deleted CPM files 2021-06-14 15:55:35 +10:00
Denis Molony
83d5be3f9f more PropertyChangeListeners 2021-06-06 16:27:30 +10:00
Denis Molony
ea0a827331 fixed the hide panel actions 2021-06-04 16:53:04 +10:00
Denis Molony
dc551285bb tidying 2021-06-03 18:11:44 +10:00
Denis Molony
95538f5282 Extracted AnimationWorker from DataPanel 2021-06-03 14:59:13 +10:00
Denis Molony
9d706d62ef extracted ImagePanel from DataPanel 2021-06-03 14:52:10 +10:00
Denis Molony
63fc59accc using PropertyChangeListeners 2021-06-02 11:48:57 +10:00
Denis Molony
beb0830c25 created more listeners 2021-06-01 20:29:34 +10:00
Denis Molony
ae1188ae27 tidying 2021-06-01 20:21:21 +10:00
Denis Molony
1b27ea02e7 tidying 2021-05-22 20:15:20 +10:00
Denis Molony
c2f2277717 use both 2021-05-22 11:10:59 +10:00
Denis Molony
79ccd6793c https://jdk.java.net/16/ 2021-05-22 11:02:49 +10:00
Denis Molony
5be0236845 changed to https://jdk.java.net 2021-05-22 10:55:19 +10:00
Denis Molony
59bf768d14 more descriptions 2021-05-22 10:41:04 +10:00
Denis Molony
566479450a added duplicates screenshot 2021-05-22 10:31:33 +10:00
Denis Molony
b45e7d7e54 new disk list image 2021-05-22 09:59:06 +10:00
Denis Molony
9dddd2be3e combined file and buffer saves 2021-05-21 14:36:44 +10:00
Denis Molony
d3f21e0d49 better save error dialogs 2021-05-21 13:34:33 +10:00
Denis Molony
af706e03c7 tidying 2021-05-21 12:59:54 +10:00
Denis Molony
b6496e9c87 created nufx package 2021-05-21 12:57:03 +10:00
Denis Molony
a33aedd750 tidying 2021-05-21 12:50:23 +10:00
Denis Molony
13647213c6 refactoring 2021-05-20 20:13:06 +10:00
149 changed files with 5034 additions and 2777 deletions

4
.gitignore vendored
View File

@ -1,4 +0,0 @@
/bin/
.project
.classpath
build.xml

View File

@ -1,5 +1,6 @@
# Apple II Disk Browser # Apple II Disk Browser
### Alternative
There is a new release of [DiskBrowser2](https://github.com/dmolony/diskbrowser2) available.
### Features ### Features
- Cross-platform (Windows, MacOS, Linux) - Cross-platform (Windows, MacOS, Linux)
- Disk formats - Disk formats
@ -30,7 +31,7 @@
* [Usage](resources/usage.md) * [Usage](resources/usage.md)
### Installation ### 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. * 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. * 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). * 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
![Graphics](resources/graphics.png?raw=true "Graphics") ![Graphics](resources/graphics.png?raw=true "Graphics")
#### Applesoft Formatting and Analysis #### 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") ![Applesoft](resources/basic.png?raw=true "Applesoft")
#### Pascal code #### 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
![Infocom](resources/zork.png?raw=true "Infocom") ![Infocom](resources/zork.png?raw=true "Infocom")
#### Wizardry #### 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") ![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 #### Visicalc
DiskBrowser has an inbuilt Visicalc processor which will evaluate the sheet and display the results.
![Visicalc](resources/visicalc.png?raw=true "Visicalc") ![Visicalc](resources/visicalc.png?raw=true "Visicalc")
#### Complete Disk List #### 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") ![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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 KiB

BIN
resources/basic1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

BIN
resources/basic2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
resources/basic3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

BIN
resources/basic4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
resources/basic5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 784 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
resources/duplicates.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 788 KiB

BIN
resources/pascal1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

BIN
resources/pascal2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 642 KiB

After

Width:  |  Height:  |  Size: 1.0 MiB

BIN
resources/wizardry4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

View File

@ -17,9 +17,9 @@ public abstract class AbstractFile implements DataSource
protected String name; protected String name;
public byte[] buffer; public byte[] buffer;
protected AssemblerProgram assembler; AssemblerProgram assembler;
protected BufferedImage image; protected BufferedImage image;
protected int loadAddress; int loadAddress;
ResourceFork resourceFork; ResourceFork resourceFork;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -30,12 +30,29 @@ public abstract class AbstractFile implements DataSource
this.buffer = buffer; this.buffer = buffer;
} }
// ---------------------------------------------------------------------------------//
public void setName (String name)
// ---------------------------------------------------------------------------------//
{
this.name = name; // Infocom ZObject uses this - but it sucks
}
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@Override @Override
public String getText () // Override this to get a tailored text representation 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 ();
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//

View File

@ -10,7 +10,7 @@ public class ApplesoftBasicProgram extends BasicProgram implements ApplesoftCons
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private final List<SourceLine> sourceLines = new ArrayList<> (); 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 UserBasicFormatter userBasicFormatter;
private final AppleBasicFormatter appleBasicFormatter; private final AppleBasicFormatter appleBasicFormatter;
@ -78,13 +78,6 @@ public class ApplesoftBasicProgram extends BasicProgram implements ApplesoftCons
return sourceLines; return sourceLines;
} }
// ---------------------------------------------------------------------------------//
// byte[] getBuffer ()
// // ---------------------------------------------------------------------------------//
// {
// return buffer;
// }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
int getEndPtr () int getEndPtr ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//

View File

@ -8,8 +8,8 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
public class BasicTextFile extends TextFile public class BasicTextFile extends TextFile
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private static String underline = "------------------------------------------" private static String underline =
+ "------------------------------------\n"; "------------------------------------------" + "------------------------------------\n";
private static String fullUnderline = "---------- ------- " + underline; private static String fullUnderline = "---------- ------- " + underline;
private int recordLength; // prodos aux private int recordLength; // prodos aux
private List<TextBuffer> buffers; // only used if it is a Prodos text file 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); super (name, buffer);
this.eof = eof; this.eof = eof;
recordLength = auxType; recordLength = auxType;
prodosFile = true; prodosFile = true;
} }
@ -42,6 +43,7 @@ public class BasicTextFile extends TextFile
this.buffers = buffers; this.buffers = buffers;
this.eof = eof; this.eof = eof;
recordLength = auxType; recordLength = auxType;
prodosFile = true; prodosFile = true;
} }
@ -167,8 +169,7 @@ public class BasicTextFile extends TextFile
if (textPreferences.showTextOffsets) if (textPreferences.showTextOffsets)
{ {
line = line.replaceAll ("\\n", "\n "); line = line.replaceAll ("\\n", "\n ");
text.append ( text.append (String.format ("%,10d %,8d %s%n", recNo * recordLength, recNo, line));
String.format ("%,10d %,8d %s%n", recNo * recordLength, recNo, line));
} }
else else
text.append (String.format ("%s%n", line)); text.append (String.format ("%s%n", line));

View 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);
}
}

View File

@ -26,7 +26,10 @@ public class CPMTextFile extends TextFile
{ {
String line = getLine (ptr); String line = getLine (ptr);
text.append (line + "\n"); 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) while (ptr < buffer.length && buffer[ptr] == 0)
++ptr; ++ptr;
} }
@ -43,8 +46,8 @@ public class CPMTextFile extends TextFile
{ {
StringBuilder line = new StringBuilder (); StringBuilder line = new StringBuilder ();
int max = buffer.length - 1; // int max = buffer.length - 1;
while (ptr < max && buffer[ptr] != 0x0D && buffer[ptr + 1] != 0x0A) while (ptr < buffer.length && buffer[ptr] != 0x0D && buffer[ptr] != 0x0A)
line.append ((char) (buffer[ptr++] & 0x7F)); line.append ((char) (buffer[ptr++] & 0x7F));
return line.toString (); return line.toString ();

View File

@ -18,6 +18,7 @@ public class DefaultAppleFile extends AbstractFile
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super (name, buffer); super (name, buffer);
this.text = "Name : " + name + "\n\n" + text; this.text = "Name : " + name + "\n\n" + text;
} }
@ -35,8 +36,10 @@ public class DefaultAppleFile extends AbstractFile
{ {
if (text != null) if (text != null)
return text; return text;
if (buffer == null) if (buffer == null)
return "Invalid file : " + name; return "Invalid file : " + name;
return super.getText (); return super.getText ();
} }
} }

View File

@ -18,98 +18,101 @@ public abstract class HiResImage extends AbstractFile
{ {
static final String[] auxTypes = static final String[] auxTypes =
{ "Paintworks Packed SHR Image", "Packed Super Hi-Res Image", { "Paintworks Packed SHR Image", "Packed Super Hi-Res Image",
"Super Hi-Res Image (Apple Preferred Format)", "Packed QuickDraw II PICT File", "Super Hi-Res Image (Apple Preferred Format)", "Packed QuickDraw II PICT File",
"Packed Super Hi-Res 3200 color image" }; "Packed Super Hi-Res 3200 color image", "DreamGraphix" };
static final int COLOR_TABLE_SIZE = 32; static final int COLOR_TABLE_SIZE = 32;
static final int COLOR_TABLE_OFFSET_AUX_0 = 32_256; static final int COLOR_TABLE_OFFSET_AUX_0 = 32_256;
static final int COLOR_TABLE_OFFSET_AUX_2 = 32_000; static final int COLOR_TABLE_OFFSET_AUX_2 = 32_000;
public static final int FADDEN_AUX = 0x8066; public static final int FADDEN_AUX = 0x8066;
private byte[] fourBuf = new byte[4]; private byte[] fourBuf = new byte[4];
private ColorTable defaultColorTable320 = new ColorTable (0, 0x00); private ColorTable defaultColorTable320 = new ColorTable (0, 0x00);
private ColorTable defaultColorTable640 = new ColorTable (0, 0x80); private ColorTable defaultColorTable640 = new ColorTable (0, 0x80);
// ---- ---- ------ -------------------------------------- ------------------------ // ---- ---- ------ -------------------------------------- ------------------------
// File Type Aux Name Description // File Type Aux Name Description
// ---- ---- ------ -------------------------------------- ------------------------ // ---- ---- ------ -------------------------------------- ------------------------
// $06 BIN isGif() OriginalHiResImage // $06 BIN isGif() OriginalHiResImage
// $06 BIN isPng() OriginalHiResImage // $06 BIN isPng() OriginalHiResImage
// $06 BIN .BMP isBmp() OriginalHiResImage // $06 BIN .BMP isBmp() OriginalHiResImage
// $06 BIN .AUX DoubleHiResImage // $06 BIN .AUX DoubleHiResImage
// $06 BIN .PAC DoubleHiResImage // $06 BIN .PAC DoubleHiResImage
// $06 BIN .A2FC DoubleHiResImage // $06 BIN .A2FC DoubleHiResImage
// $06 BIN $2000 eof $4000 DoubleHiResImage // $06 BIN $2000 eof $4000 DoubleHiResImage
// $06 BIN $1FFF eof $1FF8/$1FFF/$2000/$4000 OriginalHiResImage // $06 BIN $1FFF eof $1FF8/$1FFF/$2000/$4000 OriginalHiResImage
// $06 BIN $2000 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 $1FF8/$1FFF/$2000/$4000 OriginalHiResImage (?)
// $06 BIN $4000 eof $4000 DoubleHiResImage (?) // $06 BIN $4000 eof $4000 DoubleHiResImage (?)
// $06 BIN .3200 SHRPictureFile2 // $06 BIN .3200 SHRPictureFile2
// $06 BIN .3201 SHRPictureFile2 packed // $06 BIN .3201 SHRPictureFile2 packed
// ---- ---- ------ -------------------------------------- ------------------------ // ---- ---- ------ -------------------------------------- ------------------------
// $08 FOT <$4000 Apple II Graphics File OriginalHiResImage // $08 FOT <$4000 Apple II Graphics File OriginalHiResImage
// $08 FOT $4000 Packed Hi-Res file ??? // $08 FOT $4000 Packed Hi-Res file ???
// $08 FOT $4001 Packed Double Hi-Res file ??? // $08 FOT $4001 Packed Double Hi-Res file ???
// $08 FOT $8066 Fadden Hi-res FaddenHiResImage // $08 FOT $8066 Fadden Hi-res FaddenHiResImage
// ---- ---- ------ -------------------------------------- ------------------------ // ---- ---- ------ -------------------------------------- ------------------------
// * $C0 PNT $0000 Paintworks Packed Super Hi-Res SHRPictureFile2 // * $C0 PNT $0000 Paintworks Packed Super Hi-Res SHRPictureFile2
// * $C0 PNT $0001 Packed IIGS Super Hi-Res Image SHRPictureFile2 // * $C0 PNT $0001 Packed IIGS Super Hi-Res Image SHRPictureFile2
// * $C0 PNT $0002 IIGS Super Hi-Res Picture File (APF) SHRPictureFile1 // * $C0 PNT $0002 IIGS Super Hi-Res Picture File (APF) SHRPictureFile1
// $C0 PNT $0003 Packed IIGS QuickDraw II PICT File SHRPictureFile2 * // $C0 PNT $0003 Packed IIGS QuickDraw II PICT File SHRPictureFile2 *
// * $C0 PNT $0004 Packed Super Hi-Res 3200 (Brooks) SHRPictureFile2 .3201 // * $C0 PNT $0004 Packed Super Hi-Res 3200 (Brooks) SHRPictureFile2 .3201
// $C0 PNT $1000 // $C0 PNT $1000
// $C0 PNT $8000 Drawplus? Paintworks Gold? // $C0 PNT $8000 Drawplus? Paintworks Gold?
// $C0 PNT $8001 GTv background picture // $C0 PNT $8001 GTv background picture
// $C0 PNT $8005 DreamGraphix document // $C0 PNT $8005 DreamGraphix document SHRPictureFile2
// $C0 PNT $8006 GIF // $C0 PNT $8006 GIF
// ---- ---- ------ -------------------------------------- ------------------------ // ---- ---- ------ -------------------------------------- ------------------------
// * $C1 PIC $0000 IIGS Super Hi-Res Image SHRPictureFile2 // * $C1 PIC $0000 IIGS Super Hi-Res Image SHRPictureFile2
// $C1 PIC $0001 IIGS QuickDraw II PICT File SHRPictureFile2 * // $C1 PIC $0001 IIGS QuickDraw II PICT File SHRPictureFile2 *
// * $C1 PIC $0002 Super Hi-Res 3200 (Brooks) SHRPictureFile2 .3200 // * $C1 PIC $0002 Super Hi-Res 3200 (Brooks) SHRPictureFile2 .3200
// $C1 PIC $2000 = $C1/0000 // $C1 PIC $2000 = $C1/0000
// $C1 PIC $4100 = $C1/0000 // $C1 PIC $4100 = $C1/0000
// $C1 PIC $4950 = $C1/0000 // $C1 PIC $4950 = $C1/0000
// $C1 PIC $8001 Allison raw image // $C1 PIC $8001 Allison raw image
// $C1 PIC $8002 Thunderscan // $C1 PIC $8002 Thunderscan
// $C1 PIC $8003 DreamGraphix // $C1 PIC $8003 DreamGraphix
// ---- ---- ------ -------------------------------------- ------------------------ // ---- ---- ------ -------------------------------------- ------------------------
// $C2 ANI Paintworks animation // $C2 ANI Paintworks animation
// $C3 PAL Paintworks palette // $C3 PAL Paintworks palette
// ---- ---- ------ -------------------------------------- ------------------------ // ---- ---- ------ -------------------------------------- ------------------------
// packed unpacked // packed unpacked
// $06.3200 1 // $06.3200 1
// $06.3201 . // $06.3201 .
// $08 0000 . // $08 0000 .
// $08 4000 . // $08 4000 .
// $08 4001 . // $08 4001 .
// $08 8066 3 // $08 8066 3
// $C0 0000 1 // $C0 0000 1
// $C0 0001 $C1 0000 2 1 // $C0 0001 $C1 0000 2 1
// $C0 0002 1,5 // $C0 0002 1,5
// $C0 0003 $C1 0001 . . // $C0 0003 $C1 0001 . .
// $C0 0004 $C1 0002 . 1 // $C0 0004 $C1 0002 . 1
// $C0 1000 . // $C0 1000 .
// $C0 8000 . // $C0 8000 .
// $C0 8001 . // $C0 8001 .
// $C0 8005 . // $C0 8005 6
// $C0 8006 . // $C0 8006 .
// $C1 0042 4 // $C1 0042 4
// $C1 0043 4 // $C1 0043 4
// $C1 2000 . // $C1 2000 .
// $C1 4100 1 // $C1 4100 1
// $C1 4950 . // $C1 4950 .
// $C1 8001 . // $C1 8001 .
// $C1 8002 . // $C1 8002 .
// $C1 8003 . // $C1 8003 .
// 1 Graphics & Animation.2mg // 1 Graphics & Animation.2mg
// 2 0603 Katie's Farm - Disk 2.po // 2 0603 Katie's Farm - Disk 2.po
// 3 CompressedSlides.do // 3 CompressedSlides.do
// 4 System Addons.hdv // 4 System Addons.hdv
// 5 gfx.po // 5 gfx.po
// // 6 Dream Grafix v1.02.po
// see also - https://docs.google.com/spreadsheets/d // 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 (); static PaletteFactory paletteFactory = new PaletteFactory ();
@ -297,7 +300,10 @@ public abstract class HiResImage extends AbstractFile
break; break;
case ProdosConstants.FILE_TYPE_PNT: // 0xC0 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; break;
case ProdosConstants.FILE_TYPE_PIC: // 0xC1 case ProdosConstants.FILE_TYPE_PIC: // 0xC1
@ -495,7 +501,7 @@ public abstract class HiResImage extends AbstractFile
int calculateBufferSize (byte[] buffer, int ptr) int calculateBufferSize (byte[] buffer, int ptr)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
// int ptr = 0; // int ptr = 0;
int size = 0; int size = 0;
while (ptr < buffer.length) while (ptr < buffer.length)
{ {

View File

@ -70,6 +70,8 @@ public class OriginalHiResImage extends HiResImage
for (int ptr = base; ptr < max; ptr++) for (int ptr = base; ptr < max; ptr++)
{ {
int value = buffer[ptr] & 0x7F; 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++) for (int px = 0; px < 7; px++)
{ {
int val = (value >> px) & 0x01; int val = (value >> px) & 0x01;

View File

@ -4,6 +4,8 @@ package com.bytezone.diskbrowser.applefile;
public class PascalText extends TextFile public class PascalText extends TextFile
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private final static int PAGE_SIZE = 1024;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public PascalText (String name, byte[] buffer) public PascalText (String name, byte[] buffer)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -16,26 +18,34 @@ public class PascalText extends TextFile
public String getText () public String getText ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
// Text files are broken up into 1024-byte pages.
// [DLE] [indent] [text] [CR] ... [nulls]
StringBuilder text = new StringBuilder (getHeader ()); StringBuilder text = new StringBuilder (getHeader ());
int ptr = 0x400; int ptr = PAGE_SIZE; // skip text editor header
while (ptr < buffer.length) 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; 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) while (tab-- > 0)
text.append (" "); text.append (" ");
ptr += 2; ptr += 2;
} }
String line = getLine (ptr);
text.append (line + "\n"); while (buffer[ptr] != 0x0D)
ptr += line.length () + 1; text.append ((char) buffer[ptr++]);
text.append ("\n");
ptr++;
} }
if (text.length () > 0) if (text.length () > 0)
@ -43,14 +53,4 @@ public class PascalText extends TextFile
return text.toString (); return text.toString ();
} }
// ---------------------------------------------------------------------------------//
private String getLine (int ptr)
// ---------------------------------------------------------------------------------//
{
StringBuilder line = new StringBuilder ();
while (buffer[ptr] != 0x0D)
line.append ((char) buffer[ptr++]);
return line.toString ();
}
} }

View File

@ -3,6 +3,7 @@ package com.bytezone.diskbrowser.applefile;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
import java.util.Locale;
import com.bytezone.diskbrowser.disk.FormattedDisk; import com.bytezone.diskbrowser.disk.FormattedDisk;
import com.bytezone.diskbrowser.prodos.DirectoryHeader; import com.bytezone.diskbrowser.prodos.DirectoryHeader;
@ -15,7 +16,8 @@ import com.bytezone.diskbrowser.utilities.Utility;
public class ProdosDirectory extends AbstractFile implements ProdosConstants 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 DateTimeFormatter tf = DateTimeFormatter.ofPattern ("H:mm");
static final String UNDERLINE = static final String UNDERLINE =
"----------------------------------------------------\n"; "----------------------------------------------------\n";
@ -86,7 +88,6 @@ public class ProdosDirectory extends AbstractFile implements ProdosConstants
int nameLength = buffer[i] & 0x0F; int nameLength = buffer[i] & 0x0F;
String filename = HexFormatter.getString (buffer, i + 1, nameLength); String filename = HexFormatter.getString (buffer, i + 1, nameLength);
String subType = ""; String subType = "";
String locked;
switch (storageType) 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 eof = Utility.intValue (buffer[i + 21], buffer[i + 22], buffer[i + 23]);
int fileType = buffer[i + 16] & 0xFF; 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) switch (fileType)
{ {
case FILE_TYPE_TEXT: case FILE_TYPE_TEXT:
int aux = Utility.getShort (buffer, i + 31);
subType = String.format ("R=%5d", aux); subType = String.format ("R=%5d", aux);
break; break;
@ -134,14 +135,13 @@ public class ProdosDirectory extends AbstractFile implements ProdosConstants
case FILE_TYPE_PNT: case FILE_TYPE_PNT:
case FILE_TYPE_PIC: case FILE_TYPE_PIC:
case FILE_TYPE_FOT: case FILE_TYPE_FOT:
aux = Utility.getShort (buffer, i + 31);
subType = String.format ("A=$%4X", aux); subType = String.format ("A=$%4X", aux);
break; break;
case FILE_TYPE_AWP: case FILE_TYPE_AWP:
aux = Utility.intValue (buffer[i + 32], buffer[i + 31]); // backwards! int flags = Utility.intValue (buffer[i + 32], buffer[i + 31]); // aux backwards!
if (aux != 0) if (flags != 0)
filename = convert (filename, aux); filename = convert (filename, flags);
break; break;
default: default:
@ -149,9 +149,10 @@ public class ProdosDirectory extends AbstractFile implements ProdosConstants
} }
String forkFlag = storageType == 5 ? "+" : " "; String forkFlag = storageType == 5 ? "+" : " ";
text.append (String.format ("%s%-15s %3s%s %5d %9s %5s %9s %5s %8d %7s%n", text.append (
locked, filename, ProdosConstants.fileTypes[type], forkFlag, blocks, dateM, String.format ("%s%-15s %3s%s %5d %9s %5s %9s %5s %8d %7s %04X%n",
timeM, dateC, timeC, eof, subType)); locked, filename, ProdosConstants.fileTypes[type], forkFlag, blocks,
dateM, timeM, dateC, timeC, eof, subType, aux));
break; break;
default: default:

View File

@ -88,8 +88,8 @@ public class QuickDrawFont extends CharacterList
firstChar = Utility.getShort (buffer, ptr + 2); firstChar = Utility.getShort (buffer, ptr + 2);
lastChar = Utility.getShort (buffer, ptr + 4); lastChar = Utility.getShort (buffer, ptr + 4);
widMax = Utility.getShort (buffer, ptr + 6); widMax = Utility.getShort (buffer, ptr + 6);
kernMax = Utility.signedShort (buffer, ptr + 8); kernMax = Utility.getSignedShort (buffer, ptr + 8);
nDescent = Utility.signedShort (buffer, ptr + 10); nDescent = Utility.getSignedShort (buffer, ptr + 10);
fRectWidth = Utility.getShort (buffer, ptr + 12); fRectWidth = Utility.getShort (buffer, ptr + 12);
fRectHeight = Utility.getShort (buffer, ptr + 14); fRectHeight = Utility.getShort (buffer, ptr + 14);

View File

@ -141,7 +141,7 @@ public class SHRPictureFile1 extends HiResImage
int lo = dirEntry.mode & 0x00FF; // mode bit if hi == 0 int lo = dirEntry.mode & 0x00FF; // mode bit if hi == 0
boolean fillMode = (dirEntry.mode & 0x20) != 0; boolean fillMode = (dirEntry.mode & 0x20) != 0;
// assert fillMode == false; // assert fillMode == false;
if (hi != 0) if (hi != 0)
System.out.println ("hi not zero"); System.out.println ("hi not zero");
@ -242,7 +242,8 @@ public class SHRPictureFile1 extends HiResImage
if (ptr < data.length - 32) if (ptr < data.length - 32)
colorTables[i] = new ColorTable (i, data, ptr); colorTables[i] = new ColorTable (i, data, ptr);
else 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; ptr += 32;
} }
} }
@ -332,11 +333,11 @@ public class SHRPictureFile1 extends HiResImage
ptr = 0; ptr = 0;
for (int line = 0; line < numScanLines; line++) for (int line = 0; line < numScanLines; line++)
{ {
// if (isOddAndEmpty (packedScanLines[line])) // if (isOddAndEmpty (packedScanLines[line]))
// { // {
// System.out.println ("Odd number of bytes in empty buffer in " + name); // System.out.println ("Odd number of bytes in empty buffer in " + name);
// break; // break;
// } // }
int bytesUnpacked = unpack (packedScanLines[line], 0, int bytesUnpacked = unpack (packedScanLines[line], 0,
packedScanLines[line].length, unpackedBuffer, ptr); packedScanLines[line].length, unpackedBuffer, ptr);
@ -352,16 +353,17 @@ public class SHRPictureFile1 extends HiResImage
} }
// -------------------------------------------------------------------------------// // -------------------------------------------------------------------------------//
// private boolean isOddAndEmpty (byte[] buffer) // private boolean isOddAndEmpty (byte[] buffer)
// // -------------------------------------------------------------------------------// // //
// { // -------------------------------------------------------------------------------//
// if (buffer.length % 2 == 0) // {
// return false; // if (buffer.length % 2 == 0)
// for (byte b : buffer) // return false;
// if (b != 0) // for (byte b : buffer)
// return false; // if (b != 0)
// return true; // return false;
// } // return true;
// }
// -------------------------------------------------------------------------------// // -------------------------------------------------------------------------------//
@Override @Override

View File

@ -5,6 +5,7 @@ import java.awt.image.DataBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.bytezone.diskbrowser.nufx.LZW3;
import com.bytezone.diskbrowser.prodos.ProdosConstants; import com.bytezone.diskbrowser.prodos.ProdosConstants;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
import com.bytezone.diskbrowser.utilities.Utility; import com.bytezone.diskbrowser.utilities.Utility;
@ -144,6 +145,36 @@ public class SHRPictureFile2 extends HiResImage
break; 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: default:
System.out.printf ("%s: PNT unknown aux: %04X%n", name, auxType); System.out.printf ("%s: PNT unknown aux: %04X%n", name, auxType);
failureReason = "unknown PNT aux"; failureReason = "unknown PNT aux";

View File

@ -1,16 +1,40 @@
package com.bytezone.diskbrowser.applefile; package com.bytezone.diskbrowser.applefile;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
public class SegmentDictionary public class SegmentDictionary
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private final boolean isValid; 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) public SegmentDictionary (String name, byte[] buffer)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
isValid = !name.equals ("SYSTEM.INTERP"); // temporary 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]);
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//

View File

@ -52,7 +52,7 @@ public class StoredVariables extends AbstractFile
else if (suffix == '%') else if (suffix == '%')
{ {
intValue = Utility.intValue (buffer[ptr + 3], buffer[ptr + 2]); // backwards! intValue = Utility.intValue (buffer[ptr + 3], buffer[ptr + 2]); // backwards!
if ((buffer[ptr + 2] & 0x80) > 0) if ((buffer[ptr + 2] & 0x80) != 0)
intValue -= 65536; intValue -= 65536;
text.append (" = " + intValue); text.append (" = " + intValue);
} }
@ -60,7 +60,7 @@ public class StoredVariables extends AbstractFile
{ {
if (hasValue (ptr + 2)) if (hasValue (ptr + 2))
{ {
String value = HexFormatter.floatValue (buffer, ptr + 2) + ""; String value = Utility.floatValue (buffer, ptr + 2) + "";
if (value.endsWith (".0")) if (value.endsWith (".0"))
text.append (" = " + value.substring (0, value.length () - 2)); text.append (" = " + value.substring (0, value.length () - 2));
else else
@ -101,7 +101,7 @@ public class StoredVariables extends AbstractFile
suffix = ' '; suffix = ' ';
} }
StringBuffer variableName = new StringBuffer (); StringBuilder variableName = new StringBuilder ();
variableName.append (c1); variableName.append (c1);
if (c2 > 32) if (c2 > 32)
variableName.append (c2); variableName.append (c2);
@ -116,12 +116,14 @@ public class StoredVariables extends AbstractFile
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
StringBuilder text = new StringBuilder ("("); StringBuilder text = new StringBuilder ("(");
for (int i = 0; i < values.length; i++) for (int i = 0; i < values.length; i++)
{ {
text.append (values[i]); text.append (values[i]);
if (i < values.length - 1) if (i < values.length - 1)
text.append (','); text.append (',');
} }
return text.append (')').toString (); return text.append (')').toString ();
} }
@ -178,7 +180,7 @@ public class StoredVariables extends AbstractFile
else if (elementSize == 5) else if (elementSize == 5)
{ {
if (hasValue (p)) if (hasValue (p))
text.append (HexFormatter.floatValue (buffer, p)); text.append (Utility.floatValue (buffer, p));
text.append ("\n"); text.append ("\n");
} }
p += elementSize; p += elementSize;
@ -201,6 +203,7 @@ public class StoredVariables extends AbstractFile
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
if (buffer[p + i] != 0) if (buffer[p + i] != 0)
return true; return true;
return false; return false;
} }

View File

@ -202,7 +202,7 @@ public class SubLine implements ApplesoftConstants
private void checkFunction (String var, byte terminator) private void checkFunction (String var, byte terminator)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
assert terminator == ASCII_LEFT_BRACKET; // assert terminator == ASCII_LEFT_BRACKET;
if (!functions.contains (var)) if (!functions.contains (var))
functions.add (var); functions.add (var);

View File

@ -47,8 +47,8 @@ public class UserBasicFormatter extends BasicFormatter
{ {
StringBuilder text = new StringBuilder (String.format ("%5d", (line.lineNumber))); StringBuilder text = new StringBuilder (String.format ("%5d", (line.lineNumber)));
int indentLevel = loopVariables.size (); // each full line starts at the loop indent int indentLevel = loopVariables.size (); // each full line starts at the loop indent
int ifIndent = 0; // IF statement(s) limit back indentation by NEXT int ifIndent = 0; // IF statement(s) limit back indentation by NEXT
for (SubLine subline : line.sublines) for (SubLine subline : line.sublines)
{ {
@ -107,7 +107,7 @@ public class UserBasicFormatter extends BasicFormatter
String lineText = alignment.getAlignedText (subline); String lineText = alignment.getAlignedText (subline);
if (subline.is (TOKEN_DATA) && basicPreferences.deleteExtraDataSpace) 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 // Check for a wrappable REM/DATA/DIM statement
// (see SEA BATTLE on DISK283.DSK) // (see SEA BATTLE on DISK283.DSK)

View File

@ -22,10 +22,19 @@
0035 YSAV1 0035 YSAV1
0036 CSWL 0036 CSWL
0037 CSHW 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 004E RND-LO
004F RND-HI 004F RND-HI
0050 LINNUM 0050 LINNUM line number, unsigned word
0067 Basic program address LO 0067 Basic program address LO
0068 Basic program address HI 0068 Basic program address HI
0069 Basic variables address LO 0069 Basic variables address LO
@ -52,8 +61,48 @@
0200 Input buffer 0200 Input buffer
03D0 Applesoft warm start 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 * C000 80STOREOFF Allow page2 to switch video page1 page2
C001 80STOREON Allow page2 to switch main & aux video memory 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 C00A SLOTC3ROMOFF Enable main ROM from $C300-$C3FF
C00B SLOTC3ROMON Enable slot ROM from $C300-$C3FF C00B SLOTC3ROMON Enable slot ROM from $C300-$C3FF
C000 KYBD - last key pressed C000 KBD - Last key pressed
C010 STROBE - Clear KYBD 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 C050 TXTCLR - Display Graphics
C051 TXTSET - Display Text C051 TXTSET - Display Text
C052 MIXCLR - Display Full Screen 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 C055 TXTPAGE2 - If 80STORE Off: Display Page 2, If 80STORE On: Read/Write Aux Display Mem
C056 LORES - Display LoRes Graphics C056 LORES - Display LoRes Graphics
C057 HIRES - Display HiRes 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 C080 Read RAM bank 2; no write
C081 ROMIN - Read ROM; write RAM bank 2 C081 ROMIN - Read ROM; write RAM bank 2
@ -96,6 +158,9 @@ C08D Read ROM; write RAM bank 1
C08E Read ROM; no write C08E Read ROM; no write
C08F Read/write RAM bank 1 C08F Read/write RAM bank 1
C600 BOOT0 - Disk II controller ROM
0801 BOOT1 - Disk II bootstrap RAM
D52C INLIN numeric input D52C INLIN numeric input
DB3A STROUT - output a string DB3A STROUT - output a string
DB5C output a character DB5C output a character
@ -106,6 +171,7 @@ DEC0 SYNCHR
DEC9 syntax error DEC9 syntax error
DFE3 PTRGET DFE3 PTRGET
E000 Applesoft BASIC entry
E053 find a variable E053 find a variable
E10C convert FP to INT E10C convert FP to INT
E2F2 GIVAYF - convert (A,Y) to FP E2F2 GIVAYF - convert (A,Y) to FP
@ -177,15 +243,16 @@ F941 PRINTAX - print AX registers in hex
F948 PRBLNK - print 3 spaces F948 PRBLNK - print 3 spaces
F94A PRBL2 - print X blank spaces F94A PRBL2 - print X blank spaces
FAA6 reboot DOS FAA6 PWRUP - reboot
FAFF 0 = Autostart ROM, 1 = Old Monitor FAFF 0 = Autostart ROM, 1 = Old Monitor
FB1E PREAD - read game paddle FB1E PREAD - read game paddle
FB2F initialise text screen FB2F INIT - initialise text screen
FB39 text mode - SETTXT FB39 text mode - SETTXT
FB40 SETGR FB40 SETGR
FB5B TABV - monitor tab routine 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 FBC1 BASCALC - calculate video address
FBDD BELL1 - beep speaker FBDD BELL1 - beep speaker
FBF4 CURSRIT - move cursor right FBF4 CURSRIT - move cursor right
@ -193,6 +260,7 @@ FBF4 CURSRIT - move cursor right
FC10 CURSLFT - move cursor left FC10 CURSLFT - move cursor left
FC1A CURSUP - move cursor up FC1A CURSUP - move cursor up
FC22 VTAB FC22 VTAB
FC24 VTABZ
FC42 CLREOP - clear to end of page FC42 CLREOP - clear to end of page
FC58 HOME - clear screen FC58 HOME - clear screen
FC62 CR FC62 CR
@ -215,12 +283,13 @@ FDE3 PRHEX - print a hex digit
FDED COUT - print a character (in Acc) FDED COUT - print a character (in Acc)
FDF0 COUT1 - print character to screen 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 FE80 SETINV - set inverse mode
FE84 SETNORM - set normal mode FE84 SETNORM - set normal mode
FE89 disconnect DOS from I/O links FE89 SETKBD - disconnect DOS from I/O links
FE8B INPORT FE8B INPORT
FE93 disconnect DOS from I/O links FE93 SETVID - disconnect DOS from I/O links
FE95 OUTPORT FE95 OUTPORT
FECD WRITE FECD WRITE
FEFD READ FEFD READ
@ -231,6 +300,14 @@ FF3A BELL
FF3F IOREST - restore all registers FF3F IOREST - restore all registers
FF4A IOSAVE - save all registers FF4A IOSAVE - save all registers
FF58 RTS - jump to <address on stack> + 1 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 FFA7 GETNUM - move num to A2L.A2H
FFC7 ZMODE - monitor get ASCII return FFC7 ZMODE - monitor get ASCII return
FFFA NMI_VECTOR
FFFB NMI_VECTOR
FFFC RESET_VECTOR
FFFD RESET_VECTOR
FFFE IRQ_VECTOR
FFFF IRQ_VECTOR

View File

@ -139,7 +139,7 @@ public class AppleworksWPFile extends AbstractFile
break; break;
default: 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; ptr += 2;
} }

View File

@ -26,23 +26,28 @@ class CPMCatalogSector extends AbstractSector
for (int i = 0; i <= 255; i += CATALOG_ENTRY_SIZE) 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; break;
boolean readOnly = (buffer[i + 9] & 0x80) != 0; boolean readOnly = (buffer[i + 9] & 0x80) != 0;
boolean systemFile = (buffer[i + 10] & 0x80) != 0; boolean systemFile = (buffer[i + 10] & 0x80) != 0;
boolean unknown = (buffer[i + 11] & 0x80) != 0;
String type; String type;
String extra; String extra;
if (readOnly || systemFile) if (readOnly || systemFile || unknown)
{ {
byte[] typeBuffer = new byte[3]; byte[] typeBuffer = new byte[3];
typeBuffer[0] = (byte) (buffer[i + 9] & 0x7F); typeBuffer[0] = (byte) (buffer[i + 9] & 0x7F);
typeBuffer[1] = (byte) (buffer[i + 10] & 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 (); type = new String (typeBuffer).trim ();
extra = String.format (" (%s%s)", readOnly ? "read only" : "", extra = String.format (" (%s%s%s)", readOnly ? "read only" : "",
systemFile ? "system file" : ""); systemFile ? "system file" : "", unknown ? "unknown" : "");
} }
else else
{ {
@ -50,8 +55,14 @@ class CPMCatalogSector extends AbstractSector
extra = ""; extra = "";
} }
addText (text, buffer, i, 1, "User number"); if (buffer[i] == (byte) 0xE5)
addText (text, buffer, i + 1, 4, "File name : " + new String (buffer, i + 1, 8)); 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 + 5, 4, "");
addText (text, buffer, i + 9, 3, "File type : " + type + extra); addText (text, buffer, i + 9, 3, "File type : " + type + extra);
addText (text, buffer, i + 12, 1, "Extent counter LO"); addText (text, buffer, i + 12, 1, "Extent counter LO");

View File

@ -1,6 +1,7 @@
package com.bytezone.diskbrowser.cpm; package com.bytezone.diskbrowser.cpm;
import java.awt.Color; import java.awt.Color;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.tree.DefaultMutableTreeNode; 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.DiskAddress;
import com.bytezone.diskbrowser.disk.SectorType; import com.bytezone.diskbrowser.disk.SectorType;
import com.bytezone.diskbrowser.gui.DataSource; 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 public class CPMDisk extends AbstractFormattedDisk
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private static final int EMPTY_BYTE_VALUE = 0xE5;
private final Color green = new Color (0, 200, 0); private final Color green = new Color (0, 200, 0);
public final SectorType catalogSector = new SectorType ("Catalog", green); public final SectorType catalogSector = new SectorType ("Catalog", green);
@ -50,7 +55,7 @@ public class CPMDisk extends AbstractFormattedDisk
sectorTypesList.add (macSector); sectorTypesList.add (macSector);
sectorTypesList.add (otherSector); sectorTypesList.add (otherSector);
setEmptyByte ((byte) 0xE5); setEmptyByte ((byte) EMPTY_BYTE_VALUE);
// search for the version string // search for the version string
for (int i = 8; i >= 4; i -= 2) for (int i = 8; i >= 4; i -= 2)
@ -74,22 +79,28 @@ public class CPMDisk extends AbstractFormattedDisk
sectorTypes[da.getBlockNo ()] = catalogSector; sectorTypes[da.getBlockNo ()] = catalogSector;
byte[] buffer = disk.readBlock (da); byte[] buffer = disk.readBlock (da);
int b1 = buffer[0] & 0xFF; int b1 = buffer[0] & 0xFF;
int b2 = buffer[1] & 0xFF; int b2 = buffer[1] & 0xFF;
if (b1 == 0xE5)
if (b1 == EMPTY_BYTE_VALUE && (b2 == EMPTY_BYTE_VALUE || b2 == 0))
continue; continue;
if (b1 > 31)
if (b1 > 31 && b1 != EMPTY_BYTE_VALUE)
break; break;
if (b2 < 32 || (b2 > 126 && b2 != 0xE5))
if (b2 <= 32 || (b2 > 126 && b2 != EMPTY_BYTE_VALUE))
break; break;
for (int i = 0; i < buffer.length; i += 32) for (int i = 0; i < buffer.length; i += 32)
{ {
b1 = buffer[i] & 0xFF; b1 = buffer[i] & 0xFF;
b2 = buffer[i + 1] & 0xFF; b2 = buffer[i + 1] & 0xFF;
if (b1 == 0xE5)
break; if (b1 == EMPTY_BYTE_VALUE) // deleted file??
if (b2 < 32 || (b2 > 126 && b2 != 0xE5)) continue;
if (b2 <= 32 || (b2 > 126 && b2 != EMPTY_BYTE_VALUE))
break; break;
DirectoryEntry entry = new DirectoryEntry (this, buffer, i); 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 ()); volumeNode.setUserObject (getCatalog ());
makeNodeVisible (volumeNode.getFirstLeaf ()); makeNodeVisible (volumeNode.getFirstLeaf ());
} }
@ -147,6 +155,7 @@ public class CPMDisk extends AbstractFormattedDisk
{ {
if (fileEntries.size () > 0 && fileEntries.size () > fileNo) if (fileEntries.size () > 0 && fileEntries.size () > fileNo)
return fileEntries.get (fileNo).getSectors (); return fileEntries.get (fileNo).getSectors ();
return null; return null;
} }
@ -180,19 +189,17 @@ public class CPMDisk extends AbstractFormattedDisk
public AppleFileSource getCatalog () public AppleFileSource getCatalog ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
String newLine = String.format ("%n"); String line = "---- --------- --- - - -- -- -- -- ----------------------------"
String line = + "-------------------\n";
"---- --------- --- - - -- -- -- -- ----------------------------"
+ "-------------------" + newLine;
StringBuilder text = new StringBuilder (); StringBuilder text = new StringBuilder ();
text.append (String.format ("File : %s%n%n", getDisplayPath ())); 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); text.append (line);
for (AppleFileSource entry : fileEntries) for (AppleFileSource entry : fileEntries)
{ {
text.append (((DirectoryEntry) entry).line ()); text.append (((DirectoryEntry) entry).line ());
text.append (newLine); text.append ("\n");
} }
text.append (line); text.append (line);
if (version != 0) if (version != 0)
@ -204,6 +211,64 @@ public class CPMDisk extends AbstractFormattedDisk
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public static boolean isCorrectFormat (AppleDisk disk) 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); disk.setInterleave (3);
@ -222,26 +287,60 @@ public class CPMDisk extends AbstractFormattedDisk
for (int sector = 0; sector < 8; sector++) for (int sector = 0; sector < 8; sector++)
{ {
byte[] buffer = disk.readBlock (3, sector); byte[] buffer = disk.readBlock (3, sector);
System.out.println (HexFormatter.format (buffer));
// check if entire sector is empty (everything == 0xE5) // 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; break;
for (int i = 0; i < buffer.length; i += 32) for (int i = 0; i < buffer.length; i += 32)
{ {
int val = buffer[i] & 0xFF; b1 = buffer[i] & 0xFF;
if (val == 0xE5) b2 = buffer[i + 1] & 0xFF;
break;
if (val > 31) if (b1 == EMPTY_BYTE_VALUE) // deleted file??
continue;
if (b2 < 32 || (b2 > 126 && b2 != EMPTY_BYTE_VALUE))
return false; return false;
for (int j = 1; j <= 8; j++) // int val = buffer[i] & 0xFF;
{ // if (val == EMPTY_BYTE_VALUE)
val = buffer[i + j] & 0xFF; // {
if (val < 32 || (val > 126 && val != 0xE5)) // if (debug)
return false; // 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;
// }
// }
} }
} }

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.bytezone.diskbrowser.applefile.AppleFileSource; import com.bytezone.diskbrowser.applefile.AppleFileSource;
import com.bytezone.diskbrowser.applefile.CPMBasicFile;
import com.bytezone.diskbrowser.applefile.CPMTextFile; import com.bytezone.diskbrowser.applefile.CPMTextFile;
import com.bytezone.diskbrowser.applefile.DefaultAppleFile; import com.bytezone.diskbrowser.applefile.DefaultAppleFile;
import com.bytezone.diskbrowser.disk.AppleDiskAddress; import com.bytezone.diskbrowser.disk.AppleDiskAddress;
@ -54,7 +55,11 @@ class DirectoryEntry implements AppleFileSource
type = new String (typeBuffer).trim (); type = new String (typeBuffer).trim ();
userNumber = buffer[offset] & 0xFF; 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; extent = buffer[offset + 12] & 0xFF;
s2 = buffer[offset + 13] & 0xFF; s2 = buffer[offset + 13] & 0xFF;
s1 = buffer[offset + 14] & 0xFF; s1 = buffer[offset + 14] & 0xFF;
@ -77,9 +82,6 @@ class DirectoryEntry implements AppleFileSource
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
blocks.add (new AppleDiskAddress (disk, blockNumber + 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) for (DiskAddress sector : blocks)
if (sector.matches (da)) if (sector.matches (da))
return true; return true;
return false; return false;
} }
@ -136,9 +139,8 @@ class DirectoryEntry implements AppleFileSource
char ro = readOnly ? '*' : ' '; char ro = readOnly ? '*' : ' ';
char sf = systemFile ? '*' : ' '; char sf = systemFile ? '*' : ' ';
String text = String text = String.format ("%3d %-8s %-3s %s %s %02X %02X %02X %02X %s",
String.format ("%3d %-8s %-3s %s %s %02X %02X %02X %02X %s", userNumber, name, type, ro, sf, extent, s2, s1, recordsUsed, bytes);
userNumber, name, type, ro, sf, extent, s2, s1, recordsUsed, bytes);
for (DirectoryEntry entry : entries) for (DirectoryEntry entry : entries)
text = text + "\n" + entry.line (); text = text + "\n" + entry.line ();
@ -210,23 +212,18 @@ class DirectoryEntry implements AppleFileSource
byte[] exactBuffer = new byte[len]; byte[] exactBuffer = new byte[len];
System.arraycopy (buffer, 0, exactBuffer, 0, 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)) if ("COM".equals (type))
appleFile = new DefaultAppleFile (name, exactBuffer, "COM File"); appleFile = new DefaultAppleFile (name, exactBuffer, "COM File");
else if ("DVR".equals (type)) else if ("DVR".equals (type))
appleFile = new DefaultAppleFile (name, exactBuffer, "DVR File"); appleFile = new DefaultAppleFile (name, exactBuffer, "DVR File");
else if ("ASM".equals (type) || "DOC".equals (type) || "TXT".equals (type) else if ("ASM".equals (type) || "DOC".equals (type) || "COB".equals (type)
|| count > 2) || "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); appleFile = new CPMTextFile (name, exactBuffer);
else if ("BAS".equals (type))
appleFile = new CPMBasicFile (name, exactBuffer);
else else
appleFile = new DefaultAppleFile (name, exactBuffer, "CPM File : " + type); appleFile = new DefaultAppleFile (name, exactBuffer, "CPM File : " + name + "." + type);
return appleFile; return appleFile;
} }

View File

@ -206,8 +206,7 @@ public abstract class AbstractFormattedDisk implements FormattedDisk
DefaultMutableTreeNode root = getCatalogTreeRoot (); DefaultMutableTreeNode root = getCatalogTreeRoot ();
if (root.getUserObject () == null) if (root.getUserObject () == null)
root.setUserObject ( root.setUserObject (new DefaultAppleFileSource (getName (), disk.toString (), this));
new DefaultAppleFileSource (getName (), disk.toString (), this));
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -234,15 +233,15 @@ public abstract class AbstractFormattedDisk implements FormattedDisk
public String getDisplayPath () public String getDisplayPath ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
// if (originalPath != null)
// return originalPath.toString ();
String home = System.getProperty ("user.home"); String home = System.getProperty ("user.home");
String path = originalPath != null ? originalPath.toString () String path =
: disk.getFile ().getAbsolutePath (); originalPath != null ? originalPath.toString () : disk.getFile ().getAbsolutePath ();
if (path.startsWith (home))
return "~" + path.substring (home.length ()); int pos = path.indexOf (home);
if (pos == 0 || (path.startsWith ("/Volumes/") && pos > 0))
return "~" + path.substring (home.length () + pos);
return disk.getFile ().getAbsolutePath (); return disk.getFile ().getAbsolutePath ();
} }
@ -327,8 +326,7 @@ public abstract class AbstractFormattedDisk implements FormattedDisk
if (children != null) if (children != null)
while (children.hasMoreElements ()) while (children.hasMoreElements ())
{ {
DefaultMutableTreeNode childNode = DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) children.nextElement ();
(DefaultMutableTreeNode) children.nextElement ();
if (childNode.getUserObject ().toString ().indexOf (name) > 0) if (childNode.getUserObject ().toString ().indexOf (name) > 0)
return childNode; return childNode;
} }

View File

@ -8,14 +8,12 @@ import javax.swing.JPanel;
import com.bytezone.diskbrowser.applefile.AssemblerProgram; import com.bytezone.diskbrowser.applefile.AssemblerProgram;
import com.bytezone.diskbrowser.gui.DataSource; import com.bytezone.diskbrowser.gui.DataSource;
import com.bytezone.diskbrowser.utilities.HexFormatter; import com.bytezone.diskbrowser.utilities.HexFormatter;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
public abstract class AbstractSector implements DataSource public abstract class AbstractSector implements DataSource
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private static String newLine = String.format ("%n");
private static String newLine2 = newLine + newLine;
final public byte[] buffer; final public byte[] buffer;
protected Disk disk; protected Disk disk;
protected DiskAddress diskAddress; protected DiskAddress diskAddress;
@ -90,10 +88,11 @@ public abstract class AbstractSector implements DataSource
{ {
StringBuilder text = new StringBuilder (); StringBuilder text = new StringBuilder ();
text.append (title + newLine2); text.append (title + "\n\n");
text.append ("Offset Value Description" + newLine); text.append ("Offset Value Description\n");
text.append ("======= =========== " text.append ("======= =========== "
+ "===============================================================" + newLine); + "===============================================================\n");
return text; return text;
} }
@ -143,14 +142,13 @@ public abstract class AbstractSector implements DataSource
String desc) String desc)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
if (size == 1) desc += switch (size)
desc += " (" + (b[offset] & 0xFF) + ")"; {
else if (size == 2) case 1 -> " (" + (b[offset] & 0xFF) + ")";
desc += case 2 -> String.format (" (%,d)", Utility.getShort (b, offset));
String.format (" (%,d)", ((b[offset + 1] & 0xFF) * 256 + (b[offset] & 0xFF))); case 3 -> String.format (" (%,d)", Utility.readTriple (b, offset));
else if (size == 3) default -> "";
desc += String.format (" (%,d)", ((b[offset + 2] & 0xFF) * 65536) };
+ ((b[offset + 1] & 0xFF) * 256) + (b[offset] & 0xFF));
addText (text, b, offset, size, desc); addText (text, b, offset, size, desc);
} }

View File

@ -16,9 +16,9 @@ import java.util.zip.Checksum;
import com.bytezone.diskbrowser.nib.NibFile; import com.bytezone.diskbrowser.nib.NibFile;
import com.bytezone.diskbrowser.nib.V2dFile; import com.bytezone.diskbrowser.nib.V2dFile;
import com.bytezone.diskbrowser.nib.WozFile; 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.FileFormatException;
import com.bytezone.diskbrowser.utilities.NuFX;
import com.bytezone.diskbrowser.utilities.Utility; import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
@ -48,11 +48,11 @@ public class AppleDisk implements Disk
private int interleave = 0; private int interleave = 0;
private static int[][] interleaveSector = // 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, { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, //
22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }, // None 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, 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, 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, 6, 12, 3, 9, 15, 14, 5, 11, 2, 8, 7, 13, 4, 10, 1 } }; // CPM
// Physical disk interleave: // Physical disk interleave:
// Info from http://www.applelogic.org/TheAppleIIEGettingStarted.html // 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) public AppleDisk (File file, int tracks, int sectors, int skip) throws FileFormatException
throws FileFormatException
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
assert (file.exists ()) : "No such path :" + file.getAbsolutePath (); assert (file.exists ()) : "No such path :" + file.getAbsolutePath ();
@ -158,7 +157,7 @@ public class AppleDisk implements Disk
tracks = blocks / 8; // change parameter! tracks = blocks / 8; // change parameter!
sectors = 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 || (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 //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.sectorSize = 512;
this.trackSize = sectors * sectorSize; 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.blocks = tracks * sectors;
this.sectorSize = 512; this.sectorSize = 512;
@ -363,7 +362,6 @@ public class AppleDisk implements Disk
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
this.dosVersion = version; this.dosVersion = version;
// System.out.printf ("DOS version %02X%n", version);
} }
/* /*
@ -469,6 +467,7 @@ public class AppleDisk implements Disk
readBuffer (da, buffer, ptr); readBuffer (da, buffer, ptr);
ptr += sectorSize; ptr += sectorSize;
} }
return buffer; return buffer;
} }
@ -557,8 +556,7 @@ public class AppleDisk implements Disk
{ {
if (!isValidAddress (block)) if (!isValidAddress (block))
{ {
System.out.printf ("getDiskAddress: Invalid block : %d of %d%n", block, System.out.printf ("getDiskAddress: Invalid block : %d of %d%n", block, this.blocks);
this.blocks);
return null; return null;
// return new AppleDiskAddress (this, 0); // this was looping 26/07/2016 // 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 da.getDisk () == this : "Disk address not applicable to this disk";
assert sectorSize == SECTOR_SIZE assert sectorSize == SECTOR_SIZE || sectorSize == BLOCK_SIZE : "Invalid sector size : "
|| sectorSize == BLOCK_SIZE : "Invalid sector size : " + sectorSize; + sectorSize;
assert interleave >= 0 && interleave <= MAX_INTERLEAVE : "Invalid interleave : " assert interleave >= 0 && interleave <= MAX_INTERLEAVE : "Invalid interleave : " + interleave;
+ interleave;
if (sectorSize == SECTOR_SIZE) if (sectorSize == SECTOR_SIZE)
{ {
@ -640,8 +637,7 @@ public class AppleDisk implements Disk
System.arraycopy (diskBuffer, diskOffset, buffer, bufferOffset, SECTOR_SIZE); System.arraycopy (diskBuffer, diskOffset, buffer, bufferOffset, SECTOR_SIZE);
diskOffset = getBufferOffset (da, 1); diskOffset = getBufferOffset (da, 1);
System.arraycopy (diskBuffer, diskOffset, buffer, bufferOffset + SECTOR_SIZE, System.arraycopy (diskBuffer, diskOffset, buffer, bufferOffset + SECTOR_SIZE, 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 da.getDisk () == this : "Disk address not applicable to this disk";
assert sectorSize == SECTOR_SIZE assert sectorSize == SECTOR_SIZE || sectorSize == BLOCK_SIZE : "Invalid sector size : "
|| sectorSize == BLOCK_SIZE : "Invalid sector size : " + sectorSize; + sectorSize;
assert interleave >= 0 && interleave <= MAX_INTERLEAVE : "Invalid interleave : " assert interleave >= 0 && interleave <= MAX_INTERLEAVE : "Invalid interleave : " + interleave;
+ interleave;
if (sectorSize == SECTOR_SIZE) if (sectorSize == SECTOR_SIZE)
{ {
@ -670,6 +665,13 @@ public class AppleDisk implements Disk
} }
} }
// ---------------------------------------------------------------------------------//
public byte[] getBuffer ()
// ---------------------------------------------------------------------------------//
{
return diskBuffer;
}
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
private int getBufferOffset (DiskAddress da) private int getBufferOffset (DiskAddress da)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -731,12 +733,8 @@ public class AppleDisk implements Disk
{ {
StringBuilder text = new StringBuilder (); StringBuilder text = new StringBuilder ();
String path = file.getAbsolutePath (); text.append (
String home = System.getProperty ("user.home"); String.format ("Path ......... %s%n", Utility.getShortPath (file.getAbsolutePath ())));
if (path.startsWith (home))
path = "~" + path.substring (home.length ());
text.append (String.format ("Path ......... %s%n", path));
text.append (String.format ("File name .... %s%n", file.getName ())); text.append (String.format ("File name .... %s%n", file.getName ()));
text.append (String.format ("File size .... %,d%n", file.length ())); text.append (String.format ("File size .... %,d%n", file.length ()));
text.append (String.format ("Tracks ....... %d%n", tracks)); text.append (String.format ("Tracks ....... %d%n", tracks));

View File

@ -49,8 +49,8 @@ public class DefaultAppleFileSource implements AppleFileSource
{ {
this (title, file, owner); this (title, file, owner);
this.blocks = blocks; this.blocks = blocks;
if (file instanceof DefaultDataSource) if (file instanceof DefaultDataSource dds)
((DefaultDataSource) file).buffer = owner.getDisk ().readBlocks (blocks); dds.buffer = owner.getDisk ().readBlocks (blocks);
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -58,8 +58,8 @@ public class DefaultAppleFileSource implements AppleFileSource
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
this.blocks = blocks; this.blocks = blocks;
if (file instanceof DefaultDataSource) if (file instanceof DefaultDataSource dds)
((DefaultDataSource) file).buffer = owner.getDisk ().readBlocks (blocks); dds.buffer = owner.getDisk ().readBlocks (blocks);
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//

View File

@ -1,5 +1,6 @@
package com.bytezone.diskbrowser.disk; package com.bytezone.diskbrowser.disk;
import java.io.BufferedInputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; 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.NibFile;
import com.bytezone.diskbrowser.nib.V2dFile; import com.bytezone.diskbrowser.nib.V2dFile;
import com.bytezone.diskbrowser.nib.WozFile; 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.pascal.PascalDisk;
import com.bytezone.diskbrowser.prodos.ProdosDisk; import com.bytezone.diskbrowser.prodos.ProdosDisk;
import com.bytezone.diskbrowser.utilities.Binary2;
import com.bytezone.diskbrowser.utilities.FileFormatException; 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.utilities.Utility;
import com.bytezone.diskbrowser.wizardry.Wizardry4BootDisk; import com.bytezone.diskbrowser.wizardry.Wizardry4BootDisk;
import com.bytezone.diskbrowser.wizardry.WizardryScenarioDisk; import com.bytezone.diskbrowser.wizardry.WizardryScenarioDisk;
@ -32,6 +34,7 @@ public class DiskFactory
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private static boolean debug = false; private static boolean debug = false;
private static final int DISK_800K = 819200; private static final int DISK_800K = 819200;
private static final int DISK_143K = 143360; private static final int DISK_143K = 143360;
private static final int DISK_116K = 116480; private static final int DISK_116K = 116480;
@ -145,7 +148,7 @@ public class DiskFactory
if ("sdk".equals (suffix) // NuFX disk if ("sdk".equals (suffix) // NuFX disk
|| "shk".equals (suffix) // NuFX files or disk || "shk".equals (suffix) // NuFX files or disk
|| "bxy".equals (suffix)) // NuFX in Binary2 || "bxy".equals (suffix)) // NuFX in Bin2
{ {
if (debug) if (debug)
System.out.println (" ** sdk/shk/bxy **"); System.out.println (" ** sdk/shk/bxy **");
@ -153,7 +156,11 @@ public class DiskFactory
{ {
nuFX = new NuFX (file.toPath ()); nuFX = new NuFX (file.toPath ());
if (nuFX.getTotalDisks () == 0 && nuFX.getTotalFiles () == 0) if (nuFX.getTotalDisks () == 0 && nuFX.getTotalFiles () == 0)
{
if (debug)
System.out.println ("Empty NuFX file");
return null; return null;
}
byte[] diskBuffer = nuFX.getDiskBuffer (); byte[] diskBuffer = nuFX.getDiskBuffer ();
if (diskBuffer == null) if (diskBuffer == null)
@ -176,14 +183,14 @@ public class DiskFactory
else else
System.out.println (e.getMessage ()); System.out.println (e.getMessage ());
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ()); System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
// System.out.println (nuFX); // System.out.println (nuFX);
return null; return null;
} }
} }
else if ("bny".equals (suffix)) // Binary2 uncompressed files else if ("bny".equals (suffix) || "bqy".equals (suffix)) // Binary2 uncompressed files
{ {
if (debug) if (debug)
System.out.println (" ** bny **"); System.out.println (" ** bny/bqy **");
try try
{ {
binary2 = new Binary2 (file.toPath ()); binary2 = new Binary2 (file.toPath ());
@ -201,13 +208,21 @@ public class DiskFactory
} }
catch (Exception e) catch (Exception e)
{ {
// e.printStackTrace (); // e.printStackTrace ();
System.out.println (e.getMessage ()); System.out.println (e.getMessage ());
System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ()); System.out.printf ("Error unpacking: %s%n", file.getAbsolutePath ());
// System.out.println (binary2); // System.out.println (binary2);
return null; 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 disk = null;
FormattedDisk disk2 = null; FormattedDisk disk2 = null;
@ -268,7 +283,7 @@ public class DiskFactory
} }
if (debug) 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); disk = checkHardDisk (file);
if (disk != null) if (disk != null)
@ -335,9 +350,10 @@ public class DiskFactory
{ {
if (debug) if (debug)
System.out.println (" --> PRODOS hard disk"); System.out.println (" --> PRODOS hard disk");
return new ProdosDisk (disk800); disk = new ProdosDisk (disk800);
} }
disk = new DataDisk (disk800); else
disk = new DataDisk (disk800);
} }
else else
{ {
@ -345,11 +361,15 @@ public class DiskFactory
disk = checkDos (appleDisk256); disk = checkDos (appleDisk256);
if (disk == null) if (disk == null)
disk = checkProdos (new AppleDisk (wozFile, 35, 8)); disk = checkProdos (new AppleDisk (wozFile, 35, 8));
if (disk == null)
disk = checkPascalDisk (new AppleDisk (wozFile, 35, 8));
if (disk == null) if (disk == null)
disk = new DataDisk (appleDisk256); disk = new DataDisk (appleDisk256);
} }
} }
disk.setOriginalPath (originalPath); // allow Save converted disk...
return disk; return disk;
} }
catch (Exception e) catch (Exception e)
@ -408,7 +428,7 @@ public class DiskFactory
if (true) if (true)
{ {
// long checksum = appleDisk256.getBootChecksum (); // long checksum = appleDisk256.getBootChecksum ();
long checksum = 0; long checksum = 0;
if (checksum == 227968344L) // empty boot sector if (checksum == 227968344L) // empty boot sector
@ -433,7 +453,7 @@ public class DiskFactory
if (debug) if (debug)
System.out.println (" known DOS checksum : " + checksum); System.out.println (" known DOS checksum : " + checksum);
disk = checkDos (appleDisk256); 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 (disk2 != null && disk != null) // should be impossible
{ {
if (debug) if (debug)
@ -479,11 +499,11 @@ public class DiskFactory
else if (debug) else if (debug)
System.out.println (" unknown checksum : " + checksum); System.out.println (" unknown checksum : " + checksum);
// else if (checksum == 1212926910L || checksum == 1365043894L // else if (checksum == 1212926910L || checksum == 1365043894L
// || checksum == 2128073918L) // || checksum == 2128073918L)
// disk = checkCPMDisk (file); // disk = checkCPMDisk (file);
// System.out.println (checksum); // System.out.println (checksum);
if (disk != null) if (disk != null)
{ {
@ -572,7 +592,7 @@ public class DiskFactory
private static FormattedDisk check (FormattedDisk disk) private static FormattedDisk check (FormattedDisk disk)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
if (disk.getDisk ()instanceof AppleDisk appleDisk) if (disk.getDisk () instanceof AppleDisk appleDisk)
{ {
if (nuFX != null) if (nuFX != null)
appleDisk.setNuFX (nuFX); appleDisk.setNuFX (nuFX);
@ -597,7 +617,7 @@ public class DiskFactory
if (debug) if (debug)
System.out.println (" --> DOS"); System.out.println (" --> DOS");
DosDisk dosDisk = new DosDisk (disk); DosDisk dosDisk = new DosDisk (disk);
// disk.setDosVersion (dosDisk.getVersion ()); // disk.setDosVersion (dosDisk.getVersion ());
return dosDisk; return dosDisk;
} }
@ -666,7 +686,7 @@ public class DiskFactory
{ {
if (debug) 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 blocks : %f%n", (float) file.length () / 512);
System.out.printf ("Total tracks : %f%n", (float) file.length () / 4096); System.out.printf ("Total tracks : %f%n", (float) file.length () / 4096);
System.out.printf ("File length : %d%n", file.length ()); System.out.printf ("File length : %d%n", file.length ());
@ -690,10 +710,10 @@ public class DiskFactory
System.out.println ("*** extended ***"); // System Addons.hdv System.out.println ("*** extended ***"); // System Addons.hdv
} }
AppleDisk disk; AppleDisk disk;
// if (nuFX == null) // if (nuFX == null)
disk = new AppleDisk (file, tracks, 8); disk = new AppleDisk (file, tracks, 8);
// else // else
// disk = new AppleDisk (file, tracks, 8, nuFX); // disk = new AppleDisk (file, tracks, 8, nuFX);
if (ProdosDisk.isCorrectFormat (disk)) if (ProdosDisk.isCorrectFormat (disk))
{ {
@ -701,6 +721,7 @@ public class DiskFactory
System.out.println (" --> PRODOS hard disk"); System.out.println (" --> PRODOS hard disk");
return new ProdosDisk (disk); return new ProdosDisk (disk);
} }
if (PascalDisk.isCorrectFormat (disk, debug)) if (PascalDisk.isCorrectFormat (disk, debug))
{ {
if (debug) if (debug)
@ -716,7 +737,7 @@ public class DiskFactory
} }
if (debug) if (debug)
System.out.println (" not a Prodos hard disk\n"); System.out.println (" not a Prodos/Pascal hard disk\n");
return null; return null;
} }
@ -841,11 +862,16 @@ public class DiskFactory
if (Wizardry4BootDisk.isWizardryIVorV (disk, debug)) if (Wizardry4BootDisk.isWizardryIVorV (disk, debug))
{ {
if (debug)
System.out.println ("checking Wizardry IV or V");
String fileName = file.getAbsolutePath ().toLowerCase (); String fileName = file.getAbsolutePath ().toLowerCase ();
int pos = file.getAbsolutePath ().indexOf ('.'); int pos = fileName.lastIndexOf ('.');
char c = fileName.charAt (pos - 1); char c = fileName.charAt (pos - 1); // '1' (wiz4) or 'a' (wiz5)
// String suffix = fileName.substring (pos + 1); int requiredDisks = c == '1' ? 7 : c == 'a' ? 10 : 0;
int requiredDisks = c == '1' ? 6 : c == 'a' ? 10 : 0;
if (debug)
System.out.printf ("Required disks: %d%n", requiredDisks);
if (requiredDisks > 0) if (requiredDisks > 0)
{ {
@ -866,7 +892,7 @@ public class DiskFactory
} }
} }
if (debug) 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); PascalDisk pascalDisk = new PascalDisk (disk);
return pascalDisk; return pascalDisk;
@ -876,6 +902,9 @@ public class DiskFactory
private static boolean collectDataDisks (String fileName, int dotPos, AppleDisk[] disks) private static boolean collectDataDisks (String fileName, int dotPos, AppleDisk[] disks)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
if (debug)
System.out.println ("Collecting Wizardry disks");
char c = fileName.charAt (dotPos - 1); char c = fileName.charAt (dotPos - 1);
String suffix = fileName.substring (dotPos + 1); String suffix = fileName.substring (dotPos + 1);
@ -883,14 +912,16 @@ public class DiskFactory
{ {
String old = new String (c + "." + suffix); String old = new String (c + "." + suffix);
String rep = new String ((char) (c + i - 1) + "." + suffix); String rep = new String ((char) (c + i - 1) + "." + suffix);
File f = new File (fileName.replace (old, rep)); File f = new File (fileName.replace (old, rep));
if (debug)
System.out.println (f);
if (!f.exists () || !f.isFile ()) if (!f.exists () || !f.isFile ())
return false; return false;
AppleDisk dataDisk = new AppleDisk (f, 35, 8); disks[i] = new AppleDisk (f, 35, 8);
dataDisk.setInterleave (1); disks[i].setInterleave (1);
disks[i] = dataDisk;
} }
return true; return true;
@ -931,4 +962,22 @@ public class DiskFactory
return null; 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;
}
} }

View File

@ -51,6 +51,9 @@ public class Prefix2mg
if (format == 0 && flagsVolume == 0) if (format == 0 && flagsVolume == 0)
flagsVolume = 254; flagsVolume = 254;
if (length == 0)
length = 512 * blocks;
// see /Asimov disks/images/gs/os/prodos16/ProDOS 16v1_3.2mg // see /Asimov disks/images/gs/os/prodos16/ProDOS 16v1_3.2mg
// System.out.println (this); // System.out.println (this);
} }

View File

@ -17,8 +17,7 @@ public class SectorListConverter
sectors = new ArrayList<> (); sectors = new ArrayList<> ();
sectorText = text; sectorText = text;
String[] blocks = text.split (";"); for (String s : text.split (";"))
for (String s : blocks)
{ {
int pos = s.indexOf ('-'); int pos = s.indexOf ('-');
if (pos > 0) if (pos > 0)

View File

@ -89,8 +89,8 @@ abstract class AbstractCatalogEntry implements AppleFileSource
lastModified = Utility.getDateTime (entryBuffer, 0x1B); lastModified = Utility.getDateTime (entryBuffer, 0x1B);
// CATALOG command only formats the LO byte - see Beneath Apple DOS pp4-6 // CATALOG command only formats the LO byte - see Beneath Apple DOS pp4-6
String base = String.format ("%s%s %03d ", locked ? "*" : " ", getFileType (), String base =
reportedSize & 0xFF); String.format ("%s%s %03d ", locked ? "*" : " ", getFileType (), reportedSize & 0xFF);
catalogName = getName (base, entryBuffer); catalogName = getName (base, entryBuffer);
displayName = getDisplayName (entryBuffer); displayName = getDisplayName (entryBuffer);
} }
@ -235,18 +235,28 @@ abstract class AbstractCatalogEntry implements AppleFileSource
case IntegerBasic: case IntegerBasic:
reportedLength = Utility.getShort (buffer, 0); reportedLength = Utility.getShort (buffer, 0);
exactBuffer = new byte[reportedLength]; if (reportedLength > 0)
System.arraycopy (buffer, 2, exactBuffer, 0, reportedLength); {
appleFile = new IntegerBasicProgram (name, exactBuffer); exactBuffer = new byte[reportedLength];
System.arraycopy (buffer, 2, exactBuffer, 0, reportedLength);
appleFile = new IntegerBasicProgram (name, exactBuffer);
}
else
appleFile = new DefaultAppleFile (name, buffer);
break; break;
case ApplesoftBasic: case ApplesoftBasic:
reportedLength = Utility.getShort (buffer, 0); reportedLength = Utility.getShort (buffer, 0);
exactBuffer = new byte[reportedLength]; if (reportedLength > 0)
if (reportedLength > buffer.length) {
reportedLength = buffer.length - 2; exactBuffer = new byte[reportedLength];
System.arraycopy (buffer, 2, exactBuffer, 0, reportedLength); if (reportedLength > buffer.length)
appleFile = new ApplesoftBasicProgram (name, exactBuffer); reportedLength = buffer.length - 2;
System.arraycopy (buffer, 2, exactBuffer, 0, reportedLength);
appleFile = new ApplesoftBasicProgram (name, exactBuffer);
}
else
appleFile = new DefaultAppleFile (name, buffer);
break; break;
case Binary: // binary file case Binary: // binary file
@ -256,8 +266,8 @@ abstract class AbstractCatalogEntry implements AppleFileSource
reportedLength = Utility.getShort (buffer, 2); reportedLength = Utility.getShort (buffer, 2);
if (reportedLength == 0) if (reportedLength == 0)
{ {
System.out.println (name.trim () + " reported length : 0 - reverting to " System.out.println (
+ (buffer.length - 4)); name.trim () + " reported length : 0 - reverting to " + (buffer.length - 4));
reportedLength = 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 exactBuffer = new byte[buffer.length - 4]; // reported length is too long
System.arraycopy (buffer, 4, exactBuffer, 0, exactBuffer.length); System.arraycopy (buffer, 4, exactBuffer, 0, exactBuffer.length);
if ((name.endsWith (".FONT") || name.endsWith (" FONT") if ((name.endsWith (".FONT") || name.endsWith (" FONT") || name.endsWith (".SET")
|| name.endsWith (".SET") || name.startsWith ("ASCII.")) || name.startsWith ("ASCII.")) && FontFile.isFont (exactBuffer))
&& FontFile.isFont (exactBuffer))
appleFile = new FontFile (name, exactBuffer, loadAddress); appleFile = new FontFile (name, exactBuffer, loadAddress);
else if (name.endsWith (".MW")) else if (name.endsWith (".MW"))
appleFile = new MagicWindowText (name, exactBuffer); appleFile = new MagicWindowText (name, exactBuffer);
@ -305,8 +314,7 @@ abstract class AbstractCatalogEntry implements AppleFileSource
appleFile = new AssemblerProgram (name, exactBuffer, loadAddress); appleFile = new AssemblerProgram (name, exactBuffer, loadAddress);
} }
else if (reportedLength == 0x240 // else if (reportedLength == 0x240 //
&& (loadAddress == 0x5800 || loadAddress == 0x6000 && (loadAddress == 0x5800 || loadAddress == 0x6000 || loadAddress == 0x7800))
|| loadAddress == 0x7800))
appleFile = new PrintShopGraphic (name, exactBuffer); appleFile = new PrintShopGraphic (name, exactBuffer);
else if (isRunCommand (exactBuffer)) else if (isRunCommand (exactBuffer))
{ {
@ -319,8 +327,8 @@ abstract class AbstractCatalogEntry implements AppleFileSource
{ {
appleFile = new AssemblerProgram (name, exactBuffer, loadAddress); appleFile = new AssemblerProgram (name, exactBuffer, loadAddress);
if ((exactBuffer.length + 4) < buffer.length) if ((exactBuffer.length + 4) < buffer.length)
((AssemblerProgram) appleFile).setExtraBuffer (buffer, ((AssemblerProgram) appleFile).setExtraBuffer (buffer, exactBuffer.length + 4,
exactBuffer.length + 4, buffer.length - (exactBuffer.length + 4)); buffer.length - (exactBuffer.length + 4));
} }
break; break;
@ -362,8 +370,8 @@ abstract class AbstractCatalogEntry implements AppleFileSource
int reportedLength = Utility.getShort (buffer, 2); int reportedLength = Utility.getShort (buffer, 2);
if (reportedLength == 0) if (reportedLength == 0)
{ {
System.out.println ( System.out
name.trim () + " reported length : 0 - reverting to " + (buffer.length - 4)); .println (name.trim () + " reported length : 0 - reverting to " + (buffer.length - 4));
reportedLength = buffer.length - 4; reportedLength = buffer.length - 4;
} }

View File

@ -326,6 +326,8 @@ public class DosDisk extends AbstractFormattedDisk
return "4.2"; return "4.2";
case 0x43: case 0x43:
return "4.3"; return "4.3";
case 0x45:
return "4.5";
default: default:
return "??"; return "??";
} }
@ -376,7 +378,7 @@ public class DosDisk extends AbstractFormattedDisk
int version = buffer[3] & 0xFF; int version = buffer[3] & 0xFF;
if (debug) if (debug)
System.out.printf ("Version: %02X%n", buffer[3]); System.out.printf ("Version: %02X%n", buffer[3]);
if (version == 0 || (version > 0x43 && version != 0xFF)) if (version == 0 || (version > 0x45 && version != 0xFF))
{ {
if (debug) if (debug)
System.out.printf ("Bad version : %02X%n", version); System.out.printf ("Bad version : %02X%n", version);

View File

@ -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); setDefaultCloseOperation (HIDE_ON_CLOSE);
deleteWindow = new DeleteWindow (rootFolderData); deleteWindow = new DeleteWindow (rootFolderData);

View File

@ -8,6 +8,8 @@ import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -20,11 +22,10 @@ import javax.swing.JFrame;
import javax.swing.JPanel; import javax.swing.JPanel;
import com.bytezone.diskbrowser.gui.DuplicateAction.DiskTableSelectionListener; import com.bytezone.diskbrowser.gui.DuplicateAction.DiskTableSelectionListener;
import com.bytezone.diskbrowser.gui.RootDirectoryChangeListener;
import com.bytezone.diskbrowser.utilities.Utility; import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
public class RootFolderData implements RootDirectoryChangeListener public class RootFolderData implements PropertyChangeListener
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private static final String header = 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) if (pos >= 0)
{ {
int cmp = 0; int cmp = fileName.endsWith (".zip") ? 2 : fileName.endsWith (".gz") ? 1 : 0;
if (filename.endsWith (".gz"))
cmp = 1;
else if (filename.endsWith (".zip"))
cmp = 2;
typeTotals[cmp][pos]++; typeTotals[cmp][pos]++;
typeTotals[3][pos]++; typeTotals[3][pos]++;
++totalDisks; ++totalDisks;
} }
else 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); 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)) if (fileNameMap.containsKey (fileName))
fileNameMap.get (filename).addDuplicateName (diskDetails); fileNameMap.get (fileName).addDuplicateName (diskDetails);
else else
fileNameMap.put (filename, diskDetails); fileNameMap.put (fileName, diskDetails);
if (doChecksums) if (doChecksums)
{ {
@ -277,8 +275,7 @@ public class RootFolderData implements RootDirectoryChangeListener
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@Override private void rootDirectoryChanged (File oldRootFolder, File newRootFolder)
public void rootDirectoryChanged (File oldRootFolder, File newRootFolder)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
rootFolder = newRootFolder; rootFolder = newRootFolder;
@ -286,6 +283,15 @@ public class RootFolderData implements RootDirectoryChangeListener
disksWindow = null; // force a recount disksWindow = null; // force a recount
} }
// ---------------------------------------------------------------------------------//
@Override
public void propertyChange (PropertyChangeEvent evt)
// ---------------------------------------------------------------------------------//
{
if (evt.getPropertyName ().equals ("RootDirectory"))
rootDirectoryChanged ((File) evt.getOldValue (), (File) evt.getNewValue ());
}
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@Override @Override
public String toString () public String toString ()
@ -326,16 +332,16 @@ public class RootFolderData implements RootDirectoryChangeListener
int grandTotal[] = new int[4]; int grandTotal[] = new int[4];
for (int i = 0; i < typeTotals[0].length; i++) for (int i = 0; i < typeTotals[0].length; i++)
{ if (typeTotals[3][i] > 0)
line = String.format ("%14.14s %,7d %,7d %,7d %,7d", {
Utility.getSuffix (i) + " ...........", typeTotals[0][i], typeTotals[1][i], line = String.format ("%14.14s %,7d %,7d %,7d %,7d",
typeTotals[2][i], typeTotals[3][i]); Utility.getSuffix (i) + " ...........", typeTotals[0][i], typeTotals[1][i],
g.drawString (line, x, y); typeTotals[2][i], typeTotals[3][i]);
for (int j = 0; j < typeTotals.length; j++) g.drawString (line, x, y);
grandTotal[j] += typeTotals[j][i]; for (int j = 0; j < typeTotals.length; j++)
grandTotal[j] += typeTotals[j][i];
y += lineHeight; y += lineHeight;
} }
line = String.format ("Total %,7d %,7d %,7d %,7d%n%n", grandTotal[0], line = String.format ("Total %,7d %,7d %,7d %,7d%n%n", grandTotal[0],
grandTotal[1], grandTotal[2], grandTotal[3]); grandTotal[1], grandTotal[2], grandTotal[3]);

View File

@ -1,6 +1,13 @@
package com.bytezone.diskbrowser.gui; 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.JFileChooser;
import javax.swing.JOptionPane;
import com.bytezone.diskbrowser.utilities.DefaultAction; import com.bytezone.diskbrowser.utilities.DefaultAction;
@ -8,13 +15,44 @@ import com.bytezone.diskbrowser.utilities.DefaultAction;
public abstract class AbstractSaveAction extends 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);
}
}
} }

View 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 ();
}
}

View File

@ -158,9 +158,9 @@ class AppleDiskTab extends AbstractTab
// check for multi-volume disk (only search the current branch) // check for multi-volume disk (only search the current branch)
FormattedDisk fd = ((AppleFileSource) rootNode.getUserObject ()).getFormattedDisk (); 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); rootNode = (DefaultMutableTreeNode) rootNode.getChildAt (volume);
} }
@ -169,8 +169,8 @@ class AppleDiskTab extends AbstractTab
{ {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) children.nextElement (); DefaultMutableTreeNode node = (DefaultMutableTreeNode) children.nextElement ();
Object userObject = node.getUserObject (); Object userObject = node.getUserObject ();
if (userObject instanceof AppleFileSource if (userObject instanceof AppleFileSource afs
&& nodeName.equals (((AppleFileSource) userObject).getUniqueName ())) && nodeName.equals (afs.getUniqueName ()))
return node; return node;
} }
return null; return null;

View File

@ -10,6 +10,8 @@ import java.awt.Dimension;
import java.awt.Font; import java.awt.Font;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EventObject; import java.util.EventObject;
@ -36,9 +38,8 @@ import com.bytezone.diskbrowser.gui.RedoHandler.RedoListener;
import com.bytezone.diskbrowser.gui.TreeBuilder.FileNode; import com.bytezone.diskbrowser.gui.TreeBuilder.FileNode;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
class CatalogPanel extends JTabbedPane class CatalogPanel extends JTabbedPane implements RedoListener, SectorSelectionListener,
implements RedoListener, SectorSelectionListener, QuitListener, FontChangeListener, QuitListener, FontChangeListener, DiskTableSelectionListener, PropertyChangeListener
RootDirectoryChangeListener, DiskTableSelectionListener
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private static final String prefsLastDiskUsed = "Last disk used"; private static final String prefsLastDiskUsed = "Last disk used";
@ -66,8 +67,7 @@ class CatalogPanel extends JTabbedPane
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@Override private void rootDirectoryChanged (File oldRootFolder, File newRootFolder)
public void rootDirectoryChanged (File oldRootFolder, File newRootFolder)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
rootFolder = newRootFolder; rootFolder = newRootFolder;
@ -82,6 +82,18 @@ class CatalogPanel extends JTabbedPane
setSelectedIndex (0); 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) private void insertFileSystemTab (DiskSelectedEvent diskEvent)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -146,11 +158,10 @@ class CatalogPanel extends JTabbedPane
tab.refresh (); tab.refresh ();
// Any newly created disk needs to appear in the FileSystemTab's tree // Any newly created disk needs to appear in the FileSystemTab's tree
if (tab instanceof AppleDiskTab) if (tab instanceof AppleDiskTab appleDiskTab)
fileTab.replaceDisk (((AppleDiskTab) tab).disk); fileTab.replaceDisk (appleDiskTab.disk);
} }
// called from CloseTabAction
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public void closeCurrentTab () public void closeCurrentTab ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -174,10 +185,7 @@ class CatalogPanel extends JTabbedPane
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
Tab tab = (Tab) getSelectedComponent (); Tab tab = (Tab) getSelectedComponent ();
if (diskTabs.size () > 1 && tab instanceof AppleDiskTab) closeTabAction.setEnabled (diskTabs.size () > 1 && tab instanceof AppleDiskTab);
closeTabAction.setEnabled (true);
else
closeTabAction.setEnabled (false);
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -213,8 +221,8 @@ class CatalogPanel extends JTabbedPane
FormattedDisk fd = ((AppleDiskTab) selectedTab).disk; FormattedDisk fd = ((AppleDiskTab) selectedTab).disk;
prefs.put (prefsLastDiskUsed, fd.getAbsolutePath ()); prefs.put (prefsLastDiskUsed, fd.getAbsolutePath ());
if (fd instanceof HybridDisk) if (fd instanceof HybridDisk hybridDisk)
prefs.putInt (prefsLastDosUsed, ((HybridDisk) fd).getCurrentDiskNo ()); prefs.putInt (prefsLastDosUsed, hybridDisk.getCurrentDiskNo ());
else else
prefs.putInt (prefsLastDosUsed, -1); prefs.putInt (prefsLastDosUsed, -1);
@ -223,16 +231,16 @@ class CatalogPanel extends JTabbedPane
{ {
EventObject event = redoEvent.value; 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 (prefsLastFileUsed, afs == null ? "" : afs.getUniqueName ());
prefs.put (prefsLastSectorsUsed, ""); prefs.put (prefsLastSectorsUsed, "");
} }
else if (event instanceof SectorSelectedEvent) else if (event instanceof SectorSelectedEvent sectorSelectedEvent)
{ {
prefs.put (prefsLastFileUsed, ""); 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) if (diskEvent != null)
{ {
fd1 = diskEvent.getFormattedDisk (); fd1 = diskEvent.getFormattedDisk ();
if (lastDosUsed >= 0 && fd1 instanceof HybridDisk) if (lastDosUsed >= 0 && fd1 instanceof HybridDisk hybridDisk)
((HybridDisk) fd1).setCurrentDiskNo (lastDosUsed); hybridDisk.setCurrentDiskNo (lastDosUsed);
} }
} }
else else
@ -321,6 +329,14 @@ class CatalogPanel extends JTabbedPane
selector.addDiskSelectionListener (listener); selector.addDiskSelectionListener (listener);
} }
// ---------------------------------------------------------------------------------//
public void addDiskSelectionListener (DiskSelectionListener... listeners)
// ---------------------------------------------------------------------------------//
{
for (DiskSelectionListener diskSelectionListener : listeners)
selector.addDiskSelectionListener (diskSelectionListener);
}
// Pass through to DiskSelector // Pass through to DiskSelector
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public void addFileSelectionListener (FileSelectionListener listener) public void addFileSelectionListener (FileSelectionListener listener)
@ -329,6 +345,14 @@ class CatalogPanel extends JTabbedPane
selector.addFileSelectionListener (listener); selector.addFileSelectionListener (listener);
} }
// ---------------------------------------------------------------------------------//
public void addFileSelectionListener (FileSelectionListener... listeners)
// ---------------------------------------------------------------------------------//
{
for (FileSelectionListener fileSelectionListener : listeners)
selector.addFileSelectionListener (fileSelectionListener);
}
// Pass through to DiskSelector // Pass through to DiskSelector
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public void addFileNodeSelectionListener (FileNodeSelectionListener listener) public void addFileNodeSelectionListener (FileNodeSelectionListener listener)
@ -337,6 +361,14 @@ class CatalogPanel extends JTabbedPane
selector.addFileNodeSelectionListener (listener); selector.addFileNodeSelectionListener (listener);
} }
// ---------------------------------------------------------------------------------//
public void addFileNodeSelectionListener (FileNodeSelectionListener... listeners)
// ---------------------------------------------------------------------------------//
{
for (FileNodeSelectionListener fileNodeSelectionListener : listeners)
selector.addFileNodeSelectionListener (fileNodeSelectionListener);
}
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
private class TabChangeListener implements ChangeListener private class TabChangeListener implements ChangeListener
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -367,13 +399,13 @@ class CatalogPanel extends JTabbedPane
{ {
case "DiskEvent": case "DiskEvent":
case "FileNodeEvent": case "FileNodeEvent":
if (tab instanceof FileSystemTab) if (tab instanceof FileSystemTab fileSystemTab)
((FileSystemTab) tab).redoEvent (event); fileSystemTab.redoEvent (event);
break; break;
case "FileEvent": case "FileEvent":
if (tab instanceof AppleDiskTab) if (tab instanceof AppleDiskTab appleDiskTab)
((AppleDiskTab) tab).redoEvent (event); appleDiskTab.redoEvent (event);
break; break;
case "SectorEvent": case "SectorEvent":
@ -394,8 +426,8 @@ class CatalogPanel extends JTabbedPane
{ {
// user has clicked in the DiskLayoutPanel, so turn off any current file selection // user has clicked in the DiskLayoutPanel, so turn off any current file selection
Tab tab = (Tab) getSelectedComponent (); Tab tab = (Tab) getSelectedComponent ();
if (tab instanceof AppleDiskTab) if (tab instanceof AppleDiskTab appleDiskTab)
((AppleDiskTab) tab).tree.setSelectionPath (null); appleDiskTab.tree.setSelectionPath (null);
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -430,7 +462,7 @@ class CatalogPanel extends JTabbedPane
FileNode node = (FileNode) selectedNode.getUserObject (); FileNode node = (FileNode) selectedNode.getUserObject ();
if (node.file.isDirectory ()) if (node.file.isDirectory ())
{ {
// lister.catalogLister.setNode (selectedNode); // lister.catalogLister.setNode (selectedNode);
} }
else if (e.getClickCount () == 2) else if (e.getClickCount () == 2)
addDiskPanel (node.getFormattedDisk (), true); addDiskPanel (node.getFormattedDisk (), true);

View File

@ -19,6 +19,7 @@ public class CloseTabAction extends AbstractAction
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super ("Close Tab"); super ("Close Tab");
putValue (Action.SHORT_DESCRIPTION, "Close the current disk tab"); putValue (Action.SHORT_DESCRIPTION, "Close the current disk tab");
// putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("ctrl W")); // putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("ctrl W"));
int mask = Toolkit.getDefaultToolkit ().getMenuShortcutKeyMaskEx (); int mask = Toolkit.getDefaultToolkit ().getMenuShortcutKeyMaskEx ();

View File

@ -12,17 +12,15 @@ import javax.swing.KeyStroke;
public class ColourQuirksAction extends AbstractAction public class ColourQuirksAction extends AbstractAction
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private final DataPanel owner;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public ColourQuirksAction (DataPanel owner) public ColourQuirksAction ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super ("Smear HGR"); super ("Smear HGR");
putValue (Action.SHORT_DESCRIPTION, "Display pixels like a TV screen"); putValue (Action.SHORT_DESCRIPTION, "Display pixels like a TV screen");
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt Q")); putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt Q"));
putValue (Action.MNEMONIC_KEY, KeyEvent.VK_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) public void actionPerformed (ActionEvent e)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
owner.setColourQuirks (((JMenuItem) e.getSource ()).isSelected ()); firePropertyChange (e.getActionCommand (), null,
((JMenuItem) e.getSource ()).isSelected ());
} }
} }

View File

@ -11,16 +11,14 @@ import javax.swing.KeyStroke;
public class DebuggingAction extends AbstractAction public class DebuggingAction extends AbstractAction
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private final DataPanel owner;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public DebuggingAction (DataPanel owner) public DebuggingAction ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super ("Debugging"); super ("Debugging");
putValue (Action.SHORT_DESCRIPTION, "Show debugging information"); putValue (Action.SHORT_DESCRIPTION, "Show debugging information");
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("meta D")); 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) public void actionPerformed (ActionEvent e)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
owner.setDebug (((JMenuItem) e.getSource ()).isSelected ()); firePropertyChange (e.getActionCommand (), null,
((JMenuItem) e.getSource ()).isSelected ());
} }
} }

View File

@ -6,6 +6,8 @@ import java.awt.Desktop;
import java.awt.EventQueue; import java.awt.EventQueue;
import java.awt.event.WindowAdapter; import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
@ -22,7 +24,8 @@ import javax.swing.UIManager;
import com.bytezone.diskbrowser.duplicates.RootFolderData; 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; private static String[] args;
@ -35,13 +38,21 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
private final RootFolderData rootFolderData = new RootFolderData (); 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 () public DiskBrowser ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super (windowTitle); 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])) if (args.length > 0 && "-reset".equals (args[0]))
new WindowState (prefs).clear (); new WindowState (prefs).clear ();
@ -59,65 +70,56 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
// create and add the left-hand catalog panel // create and add the left-hand catalog panel
CatalogPanel catalogPanel = new CatalogPanel (redoHandler); 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 // create and add the centre output panel
DataPanel dataPanel = new DataPanel (menuHandler); OutputPanel dataPanel = new OutputPanel (menuHandler);
addPanel (dataPanel, "Output", BorderLayout.CENTER); addPanel (dataPanel, "Output", BorderLayout.CENTER);
// create and add the right-hand disk layout panel // create and add the right-hand disk layout panel
DiskLayoutPanel diskLayoutPanel = new DiskLayoutPanel (); DiskLayoutPanel diskLayoutPanel = new DiskLayoutPanel ();
JPanel layoutBorderPanel = layoutBorderPanel = addPanel (diskLayoutPanel, "Disk layout", BorderLayout.EAST);
addPanel (diskLayoutPanel, "Disk layout", BorderLayout.EAST);
// create actions // create actions
DuplicateAction duplicateAction = new DuplicateAction (rootFolderData); DuplicateAction duplicateAction = new DuplicateAction (rootFolderData);
RootDirectoryAction rootDirectoryAction = new RootDirectoryAction (); RootDirectoryAction rootDirectoryAction = new RootDirectoryAction ();
RefreshTreeAction refreshTreeAction = new RefreshTreeAction (catalogPanel); RefreshTreeAction refreshTreeAction = new RefreshTreeAction (catalogPanel);
// PreferencesAction preferencesAction = new PreferencesAction (this, prefs); // PreferencesAction preferencesAction = new PreferencesAction (this, prefs);
AbstractAction print = new PrintAction (dataPanel); AbstractAction print = new PrintAction (dataPanel);
// AboutAction aboutAction = new AboutAction (); // AboutAction aboutAction = new AboutAction ();
HideCatalogAction hideCatalogAction = // HideLayoutAction hideLayoutAction = new HideLayoutAction (this, layoutBorderPanel);
new HideCatalogAction (this, catalogBorderPanel); ShowFreeSectorsAction showFreeAction = new ShowFreeSectorsAction ();
HideLayoutAction hideLayoutAction = new HideLayoutAction (this, layoutBorderPanel);
ShowFreeSectorsAction showFreeAction =
new ShowFreeSectorsAction (menuHandler, diskLayoutPanel);
CloseTabAction closeTabAction = new CloseTabAction (catalogPanel); CloseTabAction closeTabAction = new CloseTabAction (catalogPanel);
// closeTabAction.addPropertyChangeListener (catalogPanel);
hideCatalogAction.addPropertyChangeListener (this);
hideLayoutAction.addPropertyChangeListener (this);
// add action buttons to toolbar // add action buttons to toolbar
toolBar.add (rootDirectoryAction); toolBar.add (rootDirectoryAction);
toolBar.add (refreshTreeAction); toolBar.add (refreshTreeAction);
// toolBar.add (preferencesAction); // toolBar.add (preferencesAction);
toolBar.add (duplicateAction); toolBar.add (duplicateAction);
toolBar.add (print); toolBar.add (print);
// toolBar.add (aboutAction); // toolBar.add (aboutAction);
// set the listeners // set the listeners
rootDirectoryAction.addListener (rootFolderData); rootDirectoryAction.addPropertyChangeListener (rootFolderData);
rootDirectoryAction.addListener (catalogPanel); rootDirectoryAction.addPropertyChangeListener (catalogPanel);
rootDirectoryAction.addListener (duplicateAction); rootDirectoryAction.addPropertyChangeListener (duplicateAction);
catalogPanel.addDiskSelectionListener (this); catalogPanel.addDiskSelectionListener (this, dataPanel, diskLayoutPanel, redoHandler,
catalogPanel.addDiskSelectionListener (dataPanel); menuHandler, menuHandler.saveDiskAction);
catalogPanel.addDiskSelectionListener (diskLayoutPanel);
catalogPanel.addDiskSelectionListener (redoHandler);
catalogPanel.addDiskSelectionListener (menuHandler);
catalogPanel.addDiskSelectionListener (menuHandler.saveDiskAction);
catalogPanel.addFileSelectionListener (dataPanel); catalogPanel.addFileSelectionListener (dataPanel, diskLayoutPanel, redoHandler, menuHandler,
catalogPanel.addFileSelectionListener (diskLayoutPanel); menuHandler.saveFileAction);
catalogPanel.addFileSelectionListener (redoHandler);
catalogPanel.addFileSelectionListener (menuHandler);
catalogPanel.addFileSelectionListener (menuHandler.saveFileAction);
catalogPanel.addFileNodeSelectionListener (dataPanel); catalogPanel.addFileNodeSelectionListener (dataPanel, redoHandler);
catalogPanel.addFileNodeSelectionListener (redoHandler);
diskLayoutPanel.addSectorSelectionListener (dataPanel); diskLayoutPanel.addSectorSelectionListener (dataPanel, redoHandler, catalogPanel,
diskLayoutPanel.addSectorSelectionListener (redoHandler); menuHandler.saveSectorsAction);
diskLayoutPanel.addSectorSelectionListener (catalogPanel);
diskLayoutPanel.addSectorSelectionListener (menuHandler.saveSectorsAction);
duplicateAction.addTableSelectionListener (catalogPanel); duplicateAction.addTableSelectionListener (catalogPanel);
@ -130,12 +132,10 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
menuHandler.fontAction.addFontChangeListener (dataPanel); menuHandler.fontAction.addFontChangeListener (dataPanel);
menuHandler.fontAction.addFontChangeListener (catalogPanel); menuHandler.fontAction.addFontChangeListener (catalogPanel);
// menuHandler.fontAction.addFontChangeListener (diskLayoutPanel); // menuHandler.fontAction.addFontChangeListener (diskLayoutPanel);
// set the MenuItem Actions // set the MenuItem Actions
menuHandler.printItem.setAction (print); menuHandler.printItem.setAction (print);
// menuHandler.addHelpMenuAction (preferencesAction, "prefs");
// menuHandler.addHelpMenuAction (aboutAction, "about");
menuHandler.refreshTreeItem.setAction (refreshTreeAction); menuHandler.refreshTreeItem.setAction (refreshTreeAction);
menuHandler.rootItem.setAction (rootDirectoryAction); menuHandler.rootItem.setAction (rootDirectoryAction);
menuHandler.showCatalogItem.setAction (hideCatalogAction); menuHandler.showCatalogItem.setAction (hideCatalogAction);
@ -144,10 +144,12 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
menuHandler.duplicateItem.setAction (duplicateAction); menuHandler.duplicateItem.setAction (duplicateAction);
menuHandler.closeTabItem.setAction (closeTabAction); menuHandler.closeTabItem.setAction (closeTabAction);
addQuitListener (rootDirectoryAction); showFreeAction.addPropertyChangeListener (diskLayoutPanel);
addQuitListener (menuHandler);
addQuitListener (catalogPanel); quitListeners.add (rootDirectoryAction);
addQuitListener (this); quitListeners.add (menuHandler);
quitListeners.add (catalogPanel);
quitListeners.add (this);
if (Desktop.isDesktopSupported ()) if (Desktop.isDesktopSupported ())
{ {
@ -158,14 +160,14 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
"Author - Denis Molony\nGitHub - https://github.com/dmolony/DiskBrowser", "Author - Denis Molony\nGitHub - https://github.com/dmolony/DiskBrowser",
"About DiskBrowser", JOptionPane.INFORMATION_MESSAGE)); "About DiskBrowser", JOptionPane.INFORMATION_MESSAGE));
if (desktop.isSupported (Desktop.Action.APP_PREFERENCES) && false) // if (desktop.isSupported (Desktop.Action.APP_PREFERENCES) && false)
desktop.setPreferencesHandler ( // desktop.setPreferencesHandler (
e -> JOptionPane.showMessageDialog (null, "Preferences dialog")); // e -> JOptionPane.showMessageDialog (null, "Preferences dialog"));
if (desktop.isSupported (Desktop.Action.APP_QUIT_HANDLER)) if (desktop.isSupported (Desktop.Action.APP_QUIT_HANDLER))
desktop.setQuitHandler ( (e, r) -> fireQuitEvent ()); desktop.setQuitHandler ( (e, r) -> fireQuitEvent ()); // needed for cmd-Q
// else // else
setQuitHandler (); setQuitHandler (); // needed for the close button
} }
else else
{ {
@ -185,9 +187,9 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
// Remove the two optional panels if they were previously hidden // Remove the two optional panels if they were previously hidden
if (!menuHandler.showLayoutItem.isSelected ()) if (!menuHandler.showLayoutItem.isSelected ())
hideLayoutAction.set (false); setLayoutPanel (false);
if (!menuHandler.showCatalogItem.isSelected ()) if (!menuHandler.showCatalogItem.isSelected ())
hideCatalogAction.set (false); setCatalogPanel (false);
menuHandler.addBasicPreferencesListener (dataPanel); menuHandler.addBasicPreferencesListener (dataPanel);
menuHandler.addAssemblerPreferencesListener (dataPanel); menuHandler.addAssemblerPreferencesListener (dataPanel);
@ -209,7 +211,6 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
fireQuitEvent (); fireQuitEvent ();
} }
}); });
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -224,13 +225,47 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
return panel; 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 @Override
public void diskSelected (DiskSelectedEvent e) public void diskSelected (DiskSelectedEvent e)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
setTitle (windowTitle + e.getFormattedDisk () == null ? "" setTitle (windowTitle + e.getFormattedDisk () == null ? "" : e.getFormattedDisk ().getName ());
: e.getFormattedDisk ().getName ());
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -250,31 +285,15 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
windowSaver.restoreWindow (); 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 () private static void setLookAndFeel ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
// FlatLightLaf.install (); // FlatLightLaf.install ();
try try
{ {
UIManager.setLookAndFeel (UIManager.getSystemLookAndFeelClassName ()); UIManager.setLookAndFeel (UIManager.getSystemLookAndFeelClassName ());
// UIManager.setLookAndFeel (new FlatLightLaf ()); // UIManager.setLookAndFeel (new FlatLightLaf ());
if (MAC) if (MAC)
System.setProperty ("apple.laf.useScreenMenuBar", "true"); 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 () private void fireQuitEvent ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -317,4 +320,20 @@ public class DiskBrowser extends JFrame implements DiskSelectionListener, QuitLi
for (QuitListener listener : quitListeners) for (QuitListener listener : quitListeners)
listener.restore (prefs); 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);
}
});
}
} }

View File

@ -97,9 +97,10 @@ class DiskLayoutImage extends DiskPanel implements Scrollable, RedoListener
selectionHandler.setSelection (sectors); selectionHandler.setSelection (sectors);
if (sectors != null && sectors.size () > 0) if (sectors != null && sectors.size () > 0)
{ {
DiskAddress da = sectors.size () == 1 ? sectors.get (0) : sectors.get (1); // DiskAddress da = sectors.size () == 1 ? sectors.get (0) : sectors.get (1);
if (da != null) // if (da != null)
scrollRectToVisible (layoutDetails.getLocation (da)); // scrollRectToVisible (layoutDetails.getLocation (da));
scrollRectToVisible (layoutDetails.getLocation (sectors.get (0)));
} }
repaint (); repaint ();
} }

View File

@ -12,6 +12,8 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JPanel; import javax.swing.JPanel;
@ -19,14 +21,14 @@ import javax.swing.JScrollPane;
import com.bytezone.diskbrowser.disk.Disk; import com.bytezone.diskbrowser.disk.Disk;
import com.bytezone.diskbrowser.disk.DiskAddress; import com.bytezone.diskbrowser.disk.DiskAddress;
import com.bytezone.diskbrowser.disk.HybridDisk;
import com.bytezone.diskbrowser.disk.FormattedDisk; 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.RedoEvent;
import com.bytezone.diskbrowser.gui.RedoHandler.RedoListener; import com.bytezone.diskbrowser.gui.RedoHandler.RedoListener;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
class DiskLayoutPanel extends JPanel class DiskLayoutPanel extends JPanel implements DiskSelectionListener,
implements DiskSelectionListener, FileSelectionListener, RedoListener FileSelectionListener, RedoListener, PropertyChangeListener
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private static final int SIZE = 15; // basic unit of a display block private static final int SIZE = 15; // basic unit of a display block
@ -134,6 +136,14 @@ class DiskLayoutPanel extends JPanel
diskLayoutImage.setShowFreeSectors (free); diskLayoutImage.setShowFreeSectors (free);
} }
// ---------------------------------------------------------------------------------//
@Override
public void propertyChange (PropertyChangeEvent evt)
// ---------------------------------------------------------------------------------//
{
setFree ((Boolean) evt.getNewValue ());
}
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public void addSectorSelectionListener (SectorSelectionListener listener) public void addSectorSelectionListener (SectorSelectionListener listener)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -141,6 +151,14 @@ class DiskLayoutPanel extends JPanel
diskLayoutImage.addSectorSelectionListener (listener); diskLayoutImage.addSectorSelectionListener (listener);
} }
// ---------------------------------------------------------------------------------//
public void addSectorSelectionListener (SectorSelectionListener... listeners)
// ---------------------------------------------------------------------------------//
{
for (SectorSelectionListener sectorSelectionListener : listeners)
diskLayoutImage.addSectorSelectionListener (sectorSelectionListener);
}
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public void removeSectorSelectionListener (SectorSelectionListener listener) public void removeSectorSelectionListener (SectorSelectionListener listener)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -244,8 +262,8 @@ class DiskLayoutPanel extends JPanel
private void checkCorrectDisk (FormattedDisk newDisk) private void checkCorrectDisk (FormattedDisk newDisk)
{ {
if (newDisk instanceof HybridDisk) if (newDisk instanceof HybridDisk hybridDisk)
newDisk = ((HybridDisk) newDisk).getCurrentDisk (); // never set to a Dual-dos disk newDisk = hybridDisk.getCurrentDisk (); // never set to a hybrid disk
if (newDisk != diskLayoutImage.getDisk ()) if (newDisk != diskLayoutImage.getDisk ())
{ {
LayoutDetails layout = new LayoutDetails (newDisk); LayoutDetails layout = new LayoutDetails (newDisk);

View File

@ -157,6 +157,7 @@ class DiskLayoutSelection implements Iterable<DiskAddress>
for (DiskAddress selection : highlights) for (DiskAddress selection : highlights)
if (selection != null && da.matches (selection)) if (selection != null && da.matches (selection))
return true; return true;
return false; return false;
} }

View File

@ -85,14 +85,13 @@ class DiskLegendPanel extends DiskPanel
int val = formattedDisk.falseNegativeBlocks (); int val = formattedDisk.falseNegativeBlocks ();
if (val > 0) if (val > 0)
{ {
g.drawString ( g.drawString (val + " unused sector" + (val == 1 ? "" : "s") //
val + " unused sector" + (val == 1 ? "" : "s") + " marked as unavailable", 10, + " marked as unavailable", 10, y);
y);
y += lineHeight; y += lineHeight;
} }
val = formattedDisk.falsePositiveBlocks (); val = formattedDisk.falsePositiveBlocks ();
if (val > 0) if (val > 0)
g.drawString (val + " used sector" + (val == 1 ? "" : "s") + " marked as available", g.drawString (val + " used sector" + (val == 1 ? "" : "s") //
10, y); + " marked as available", 10, y);
} }
} }

View File

@ -13,6 +13,7 @@ public class DiskPanel extends JPanel
{ {
FormattedDisk formattedDisk; FormattedDisk formattedDisk;
LayoutDetails layoutDetails; LayoutDetails layoutDetails;
int blockWidth = 30; // default int blockWidth = 30; // default
int blockHeight = 15; // default int blockHeight = 15; // default
int centerOffset; int centerOffset;
@ -20,11 +21,11 @@ public class DiskPanel extends JPanel
Color backgroundColor = new Color (0xE0, 0xE0, 0xE0); Color backgroundColor = new Color (0xE0, 0xE0, 0xE0);
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public void setDisk (FormattedDisk disk, LayoutDetails details) public void setDisk (FormattedDisk formattedDisk, LayoutDetails layoutDetails)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
formattedDisk = disk; this.formattedDisk = formattedDisk;
layoutDetails = details; this.layoutDetails = layoutDetails;
blockWidth = layoutDetails.block.width; blockWidth = layoutDetails.block.width;
blockHeight = layoutDetails.block.height; blockHeight = layoutDetails.block.height;

View File

@ -9,7 +9,7 @@ import com.bytezone.diskbrowser.disk.FormattedDisk;
class DiskSelectedEvent extends EventObject class DiskSelectedEvent extends EventObject
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private final FormattedDisk owner; private final FormattedDisk formattedDisk;
boolean redo; boolean redo;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -17,14 +17,14 @@ class DiskSelectedEvent extends EventObject
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super (source); super (source);
this.owner = disk; this.formattedDisk = disk;
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public FormattedDisk getFormattedDisk () public FormattedDisk getFormattedDisk ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
return owner; return formattedDisk;
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -32,14 +32,14 @@ class DiskSelectedEvent extends EventObject
public String toString () public String toString ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
return owner.getDisk ().getFile ().getAbsolutePath (); return formattedDisk.getDisk ().getFile ().getAbsolutePath ();
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public String toText () public String toText ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
return owner.getAbsolutePath (); return formattedDisk.getAbsolutePath ();
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//

View File

@ -3,6 +3,8 @@ package com.bytezone.diskbrowser.gui;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File; import java.io.File;
import javax.swing.Action; import javax.swing.Action;
@ -14,7 +16,7 @@ import com.bytezone.diskbrowser.duplicates.RootFolderData;
import com.bytezone.diskbrowser.utilities.DefaultAction; import com.bytezone.diskbrowser.utilities.DefaultAction;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
public class DuplicateAction extends DefaultAction implements RootDirectoryChangeListener public class DuplicateAction extends DefaultAction implements PropertyChangeListener
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
RootFolderData rootFolderData; RootFolderData rootFolderData;
@ -36,14 +38,22 @@ public class DuplicateAction extends DefaultAction implements RootDirectoryChang
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@Override private void rootDirectoryChanged (File oldRootFolder, File newRootFolder)
public void rootDirectoryChanged (File oldRootFolder, File newRootFolder)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
assert rootFolderData.getRootFolder () == newRootFolder; assert rootFolderData.getRootFolder () == newRootFolder;
setEnabled (rootFolderData.getRootFolder () != null); setEnabled (rootFolderData.getRootFolder () != null);
} }
// ---------------------------------------------------------------------------------//
@Override
public void propertyChange (PropertyChangeEvent evt)
// ---------------------------------------------------------------------------------//
{
if (evt.getPropertyName ().equals ("RootDirectory"))
rootDirectoryChanged ((File) evt.getOldValue (), (File) evt.getNewValue ());
}
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@Override @Override
public void actionPerformed (ActionEvent arg0) public void actionPerformed (ActionEvent arg0)

View File

@ -3,8 +3,8 @@ package com.bytezone.diskbrowser.gui;
import java.util.EventObject; import java.util.EventObject;
import com.bytezone.diskbrowser.applefile.AppleFileSource; import com.bytezone.diskbrowser.applefile.AppleFileSource;
import com.bytezone.diskbrowser.disk.HybridDisk;
import com.bytezone.diskbrowser.disk.FormattedDisk; import com.bytezone.diskbrowser.disk.FormattedDisk;
import com.bytezone.diskbrowser.disk.HybridDisk;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
class FileSelectedEvent extends EventObject class FileSelectedEvent extends EventObject
@ -21,8 +21,9 @@ class FileSelectedEvent extends EventObject
super (source); super (source);
this.appleFileSource = appleFileSource; this.appleFileSource = appleFileSource;
// If a file is selected from a disk which is contained in a Dual-dos disk, then the DDS // If a file is selected from a disk which is part of a hybrid disk, then the
// must be told so that it can ensure its internal currentDisk is set correctly // parent must be told so that it can ensure its internal currentDisk is set
// correctly
FormattedDisk fd = appleFileSource.getFormattedDisk (); FormattedDisk fd = appleFileSource.getFormattedDisk ();
HybridDisk ddd = (HybridDisk) fd.getParent (); HybridDisk ddd = (HybridDisk) fd.getParent ();
if (ddd != null) if (ddd != null)

View File

@ -36,6 +36,7 @@ public class FontAction extends DefaultAction implements QuitListener
{ {
super ("Set Font...", "Set display to a different font or font size", super ("Set Font...", "Set display to a different font or font size",
"/com/bytezone/loadlister/"); "/com/bytezone/loadlister/");
int mask = Toolkit.getDefaultToolkit ().getMenuShortcutKeyMaskEx (); int mask = Toolkit.getDefaultToolkit ().getMenuShortcutKeyMaskEx ();
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke (KeyEvent.VK_F, mask)); 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); FontChangeEvent fontChangeEvent = new FontChangeEvent (font);
FontChangeListener[] listeners = FontChangeListener[] listeners = (listenerList.getListeners (FontChangeListener.class));
(listenerList.getListeners (FontChangeListener.class));
for (FontChangeListener listener : listeners) for (FontChangeListener listener : listeners)
listener.changeFont (fontChangeEvent); listener.changeFont (fontChangeEvent);
} }

View File

@ -47,6 +47,7 @@ public class FontFrame extends JFrame
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super ("Font Selection"); super ("Font Selection");
this.fontAction = fontAction; this.fontAction = fontAction;
buildLayout (); buildLayout ();
getFonts (); getFonts ();
@ -96,8 +97,7 @@ public class FontFrame extends JFrame
public String getSelectedValue () public String getSelectedValue ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
String fontName = fontList.getSelectedValue (); return fontList.getSelectedValue ();
return fontName;
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -112,8 +112,7 @@ public class FontFrame extends JFrame
public String getSelectedSize () public String getSelectedSize ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
String fontSize = fontSizePanel.getSelectedText (); return fontSizePanel.getSelectedText ();
return fontSize;
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -146,7 +145,6 @@ public class FontFrame extends JFrame
int ptr = 0; int ptr = 0;
for (String fontName : fonts) for (String fontName : fonts)
{
while (ptr < pf.length) while (ptr < pf.length)
{ {
int result = fontName.compareToIgnoreCase (pf[ptr]); int result = fontName.compareToIgnoreCase (pf[ptr]);
@ -159,7 +157,6 @@ public class FontFrame extends JFrame
} }
break; break;
} }
}
fontList.setSelectedValue (initialFont, true); fontList.setSelectedValue (initialFont, true);
} }
@ -254,13 +251,14 @@ public class FontFrame extends JFrame
private Font getCurrentFont () private Font getCurrentFont ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
String fontName = getSelectedValue ();
String fontSize = getSelectedSize (); String fontSize = getSelectedSize ();
if (fontSize.isEmpty ()) if (fontSize.isEmpty ())
return null; return null;
int pos = fontSize.indexOf (' '); int pos = fontSize.indexOf (' ');
int size = Integer.parseInt (fontSize.substring (0, pos)); 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 (); initialFont = getSelectedValue ();
initialSize = getSelectedSize (); initialSize = getSelectedSize ();
int pos = initialSize.indexOf (' '); int pos = initialSize.indexOf (' ');
int size = Integer.parseInt (initialSize.substring (0, pos)); int size = Integer.parseInt (initialSize.substring (0, pos));
Font font = new Font (initialFont, Font.PLAIN, size); Font font = new Font (initialFont, Font.PLAIN, size);
fontAction.fireFontChangeEvent (font); fontAction.fireFontChangeEvent (font);
} }

View File

@ -1,33 +1,26 @@
package com.bytezone.diskbrowser.gui; package com.bytezone.diskbrowser.gui;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke; import javax.swing.KeyStroke;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
class HideCatalogAction extends AbstractAction class HideCatalogAction extends AbstractAction
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
JFrame owner;
JPanel catalogPanel;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public HideCatalogAction (JFrame owner, JPanel catalogPanel) public HideCatalogAction ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super ("Show catalog panel"); super ("Show catalog panel");
putValue (Action.SHORT_DESCRIPTION, "Show/hide the catalog panel"); putValue (Action.SHORT_DESCRIPTION, "Show/hide the catalog panel");
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt C")); putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt C"));
putValue (Action.MNEMONIC_KEY, KeyEvent.VK_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) public void actionPerformed (ActionEvent e)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
set (((JMenuItem) e.getSource ()).isSelected ()); firePropertyChange (e.getActionCommand (), null,
} ((JMenuItem) e.getSource ()).isSelected ());
// ---------------------------------------------------------------------------------//
public void set (boolean show)
// ---------------------------------------------------------------------------------//
{
if (show)
{
owner.add (catalogPanel, BorderLayout.WEST);
owner.validate ();
}
else
{
owner.remove (catalogPanel);
owner.validate ();
}
} }
} }

View File

@ -1,33 +1,26 @@
package com.bytezone.diskbrowser.gui; package com.bytezone.diskbrowser.gui;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.KeyStroke; import javax.swing.KeyStroke;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
class HideLayoutAction extends AbstractAction class HideLayoutAction extends AbstractAction
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
JFrame owner;
JPanel layoutPanel;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public HideLayoutAction (JFrame owner, JPanel layoutPanel) public HideLayoutAction ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super ("Show disk layout panel"); super ("Show disk layout panel");
putValue (Action.SHORT_DESCRIPTION, "Show/hide the disk layout panel"); putValue (Action.SHORT_DESCRIPTION, "Show/hide the disk layout panel");
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt D")); putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt D"));
putValue (Action.MNEMONIC_KEY, KeyEvent.VK_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) public void actionPerformed (ActionEvent e)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
set (((JMenuItem) e.getSource ()).isSelected ()); firePropertyChange (e.getActionCommand (), null,
} ((JMenuItem) e.getSource ()).isSelected ());
// ---------------------------------------------------------------------------------//
public void set (boolean show)
// ---------------------------------------------------------------------------------//
{
if (show)
{
owner.add (layoutPanel, BorderLayout.EAST);
owner.validate ();
}
else
{
owner.remove (layoutPanel);
owner.validate ();
}
} }
} }

View 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);
}
}
}

View File

@ -2,45 +2,33 @@ package com.bytezone.diskbrowser.gui;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JTextArea;
import javax.swing.KeyStroke; import javax.swing.KeyStroke;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
class LineWrapAction extends AbstractAction class LineWrapAction extends AbstractAction
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
List<JTextArea> listeners = new ArrayList<> ();
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public LineWrapAction () public LineWrapAction ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super ("Line wrap"); 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.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt W"));
putValue (Action.MNEMONIC_KEY, KeyEvent.VK_W); putValue (Action.MNEMONIC_KEY, KeyEvent.VK_W);
} }
// ---------------------------------------------------------------------------------//
public void addListener (JTextArea listener)
// ---------------------------------------------------------------------------------//
{
if (!listeners.contains (listener))
listeners.add (listener);
}
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@Override @Override
public void actionPerformed (ActionEvent e) public void actionPerformed (ActionEvent e)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
for (JTextArea listener : listeners) firePropertyChange (e.getActionCommand (), null,
listener.setLineWrap (((JMenuItem) e.getSource ()).isSelected ()); ((JMenuItem) e.getSource ()).isSelected ());
} }
} }

View File

@ -76,7 +76,6 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
private static final String PREFS_PALETTE = "palette"; private static final String PREFS_PALETTE = "palette";
FormattedDisk currentDisk;
final SaveDiskAction saveDiskAction = new SaveDiskAction (); final SaveDiskAction saveDiskAction = new SaveDiskAction ();
final SaveFileAction saveFileAction = new SaveFileAction (); final SaveFileAction saveFileAction = new SaveFileAction ();
final SaveSectorsAction saveSectorsAction = new SaveSectorsAction (); final SaveSectorsAction saveSectorsAction = new SaveSectorsAction ();
@ -186,6 +185,8 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
ButtonGroup paletteGroup = new ButtonGroup (); ButtonGroup paletteGroup = new ButtonGroup ();
FormattedDisk currentDisk;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
MenuHandler () MenuHandler ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -211,7 +212,7 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
addLauncherMenu (); addLauncherMenu ();
fileMenu.add (printItem); fileMenu.add (printItem);
// fileMenu.addSeparator (); // fileMenu.addSeparator ();
fileMenu.add (closeTabItem); fileMenu.add (closeTabItem);
JMenuItem fontItem = new JMenuItem (fontAction); JMenuItem fontItem = new JMenuItem (fontAction);
@ -270,13 +271,13 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
applesoftMenu.add (splitRemarkItem); applesoftMenu.add (splitRemarkItem);
applesoftMenu.add (splitDimItem); applesoftMenu.add (splitDimItem);
applesoftMenu.add (alignAssignItem); applesoftMenu.add (alignAssignItem);
// applesoftMenu.add (showBasicTargetsItem); // applesoftMenu.add (showBasicTargetsItem);
// applesoftMenu.add (onlyShowTargetLinesItem); // applesoftMenu.add (onlyShowTargetLinesItem);
applesoftMenu.add (showCaretItem); applesoftMenu.add (showCaretItem);
applesoftMenu.add (showThenItem); applesoftMenu.add (showThenItem);
applesoftMenu.add (blankAfterReturnItem); applesoftMenu.add (blankAfterReturnItem);
applesoftMenu.add (formatRemItem); applesoftMenu.add (formatRemItem);
// applesoftMenu.add (deleteExtraRemSpace); // applesoftMenu.add (deleteExtraRemSpace);
applesoftMenu.add (deleteExtraDataSpace); applesoftMenu.add (deleteExtraDataSpace);
applesoftMenu.addSeparator (); applesoftMenu.addSeparator ();
applesoftMenu.add (showXrefItem); applesoftMenu.add (showXrefItem);
@ -284,7 +285,7 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
applesoftMenu.add (showSymbolsItem); applesoftMenu.add (showSymbolsItem);
applesoftMenu.add (showFunctionsItem); applesoftMenu.add (showFunctionsItem);
applesoftMenu.add (showConstantsItem); applesoftMenu.add (showConstantsItem);
// applesoftMenu.add (listStringsItem); // applesoftMenu.add (listStringsItem);
applesoftMenu.add (showDuplicateSymbolsItem); applesoftMenu.add (showDuplicateSymbolsItem);
assemblerMenu.add (showAssemblerHeaderItem); assemblerMenu.add (showAssemblerHeaderItem);
@ -347,6 +348,7 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
showAllFormatItem.addActionListener (basicPreferencesAction); showAllFormatItem.addActionListener (basicPreferencesAction);
showAllXrefItem.addActionListener (basicPreferencesAction); showAllXrefItem.addActionListener (basicPreferencesAction);
appleLineWrapItem.addActionListener (basicPreferencesAction); appleLineWrapItem.addActionListener (basicPreferencesAction);
for (JMenuItem item : applesoftFormatItems) for (JMenuItem item : applesoftFormatItems)
item.addActionListener (basicPreferencesAction); item.addActionListener (basicPreferencesAction);
for (JMenuItem item : applesoftXrefItems) for (JMenuItem item : applesoftXrefItems)
@ -374,10 +376,12 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
sectorGroup.add (sector256Item); sectorGroup.add (sector256Item);
sectorGroup.add (sector512Item); sectorGroup.add (sector512Item);
interleaveGroup.add (interleave0Item); interleaveGroup.add (interleave0Item);
interleaveGroup.add (interleave1Item); interleaveGroup.add (interleave1Item);
interleaveGroup.add (interleave2Item); interleaveGroup.add (interleave2Item);
interleaveGroup.add (interleave3Item); interleaveGroup.add (interleave3Item);
scaleGroup.add (scale1Item); scaleGroup.add (scale1Item);
scaleGroup.add (scale2Item); scaleGroup.add (scale2Item);
scaleGroup.add (scale3Item); scaleGroup.add (scale3Item);
@ -546,6 +550,7 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
openSupported = true; openSupported = true;
break; break;
} }
if (!openSupported) if (!openSupported)
return; return;
@ -554,60 +559,6 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
fileMenu.addSeparator (); 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 @Override
public void restore (Preferences prefs) public void restore (Preferences prefs)
@ -697,6 +648,60 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
fontAction.restore (prefs); 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 @Override
public void diskSelected (DiskSelectedEvent event) public void diskSelected (DiskSelectedEvent event)
@ -733,7 +738,7 @@ class MenuHandler implements DiskSelectionListener, FileSelectionListener, QuitL
interleave3Item.setSelected (disk.getDisk ().getInterleave () == 3); interleave3Item.setSelected (disk.getDisk ().getInterleave () == 3);
} }
boolean isDataDisk = (disk instanceof DataDisk); boolean isDataDisk = disk instanceof DataDisk;
sector256Item.setEnabled (isDataDisk); sector256Item.setEnabled (isDataDisk);
sector512Item.setEnabled (isDataDisk); sector512Item.setEnabled (isDataDisk);

View File

@ -12,17 +12,15 @@ import javax.swing.KeyStroke;
class MonochromeAction extends AbstractAction class MonochromeAction extends AbstractAction
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private final DataPanel owner;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
MonochromeAction (DataPanel owner) MonochromeAction ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super ("Monochrome"); super ("Monochrome");
putValue (Action.SHORT_DESCRIPTION, "Display image in monochrome or color"); putValue (Action.SHORT_DESCRIPTION, "Display image in monochrome or color");
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt M")); putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt M"));
putValue (Action.MNEMONIC_KEY, KeyEvent.VK_M); putValue (Action.MNEMONIC_KEY, KeyEvent.VK_M);
this.owner = owner;
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -30,6 +28,7 @@ class MonochromeAction extends AbstractAction
public void actionPerformed (ActionEvent e) public void actionPerformed (ActionEvent e)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
owner.setMonochrome (((JMenuItem) e.getSource ()).isSelected ()); firePropertyChange (e.getActionCommand (), null,
((JMenuItem) e.getSource ()).isSelected ());
} }
} }

View File

@ -17,11 +17,11 @@ import com.bytezone.diskbrowser.applefile.PaletteFactory.CycleDirection;
class NextPaletteAction extends AbstractAction class NextPaletteAction extends AbstractAction
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private final DataPanel owner; private final OutputPanel owner;
private final ButtonGroup buttonGroup; private final ButtonGroup buttonGroup;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
NextPaletteAction (DataPanel owner, ButtonGroup buttonGroup) NextPaletteAction (OutputPanel owner, ButtonGroup buttonGroup)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super ("Next Palette"); super ("Next Palette");

View File

@ -1,27 +1,21 @@
package com.bytezone.diskbrowser.gui; package com.bytezone.diskbrowser.gui;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font; import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets; import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List; import java.util.List;
import javax.swing.AbstractButton; import javax.swing.AbstractButton;
import javax.swing.ButtonGroup; import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem; import javax.swing.JCheckBoxMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
import javax.swing.JTabbedPane; import javax.swing.JTabbedPane;
import javax.swing.JTextArea; import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants; import javax.swing.ScrollPaneConstants;
import javax.swing.SwingConstants; import javax.swing.SwingConstants;
import javax.swing.SwingWorker;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; 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.disk.SectorList;
import com.bytezone.diskbrowser.gui.FontAction.FontChangeEvent; import com.bytezone.diskbrowser.gui.FontAction.FontChangeEvent;
import com.bytezone.diskbrowser.gui.FontAction.FontChangeListener; 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, implements DiskSelectionListener, FileSelectionListener, SectorSelectionListener,
FileNodeSelectionListener, FontChangeListener, BasicPreferencesListener, FileNodeSelectionListener, FontChangeListener, BasicPreferencesListener,
AssemblerPreferencesListener, TextPreferencesListener AssemblerPreferencesListener, TextPreferencesListener, PropertyChangeListener
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private static final int TEXT_WIDTH = 65; private static final int TEXT_WIDTH = 65;
private static final int BACKGROUND = 245;
// final MenuHandler menuHandler;
private final JTextArea formattedText; private final JTextArea formattedText;
private final JTextArea hexText; private final JTextArea hexText;
private final JTextArea disassemblyText; private final JTextArea disassemblyText;
@ -57,41 +52,42 @@ public class DataPanel extends JTabbedPane
// these two panes are interchangeable // these two panes are interchangeable
private final JScrollPane formattedPane; private final JScrollPane formattedPane;
private final JScrollPane imagePane; private final JScrollPane imagePane;
private boolean imageVisible = false; private boolean imageVisible = false;
private final ImagePanel imagePanel; // internal class private final ImagePanel imagePanel = new ImagePanel ();
private AnimationWorker animation;
private boolean debugMode; private boolean debugMode;
private DataSource currentDataSource;
// used to determine whether the text has been set // used to determine whether the text has been set
boolean formattedTextValid; private boolean formattedTextValid;
boolean hexTextValid; private boolean hexTextValid;
boolean assemblerTextValid; private boolean assemblerTextValid;
DataSource currentDataSource;
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; private enum TabType
enum TabType
{ {
FORMATTED, HEX, DISASSEMBLED FORMATTED, HEX, DISASSEMBLED
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public DataPanel (MenuHandler mh) public OutputPanel (MenuHandler menuHandler)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
this.menuHandler = mh;
setTabPlacement (SwingConstants.BOTTOM); setTabPlacement (SwingConstants.BOTTOM);
formattedText = new JTextArea (10, TEXT_WIDTH); formattedText = new JTextArea (10, TEXT_WIDTH);
formattedPane = setPanel (formattedText, "Formatted"); 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 " formattedText.setText ("Please use the 'File->Set HOME folder...' command to "
+ "\ntell DiskBrowser where your Apple disks are located." + "\ntell DiskBrowser where your Apple disks are located."
+ "\n\nTo see the contents of a disk in more detail, double-click" + "\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 " + "\nthe disk. You will then be able to select individual files to " + "view them.");
+ "view completely.");
hexText = new JTextArea (10, TEXT_WIDTH); hexText = new JTextArea (10, TEXT_WIDTH);
setPanel (hexText, "Hex dump"); setPanel (hexText, "Hex dump");
@ -99,10 +95,8 @@ public class DataPanel extends JTabbedPane
disassemblyText = new JTextArea (10, TEXT_WIDTH); disassemblyText = new JTextArea (10, TEXT_WIDTH);
setPanel (disassemblyText, "Disassembly"); setPanel (disassemblyText, "Disassembly");
imagePanel = new ImagePanel (); imagePane = new JScrollPane (imagePanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
imagePane = ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
new JScrollPane (imagePanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
imagePane.setBorder (null); imagePane.setBorder (null);
@ -126,6 +120,7 @@ public class DataPanel extends JTabbedPane
formattedTextValid = true; formattedTextValid = true;
} }
break; break;
case 1: // Hex case 1: // Hex
if (!hexTextValid) if (!hexTextValid)
{ {
@ -136,6 +131,7 @@ public class DataPanel extends JTabbedPane
hexTextValid = true; hexTextValid = true;
} }
break; break;
case 2: // Assembler case 2: // Assembler
if (!assemblerTextValid) if (!assemblerTextValid)
{ {
@ -146,19 +142,24 @@ public class DataPanel extends JTabbedPane
assemblerTextValid = true; assemblerTextValid = true;
} }
break; break;
default: 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); menuHandler.lineWrapItem.setAction (lineWrapAction);
lineWrapAction.addListener (formattedText); lineWrapAction.addPropertyChangeListener (this);
menuHandler.colourQuirksItem.setAction (new ColourQuirksAction (this)); colourQuirksAction.addPropertyChangeListener (this);
menuHandler.monochromeItem.setAction (new MonochromeAction (this)); menuHandler.colourQuirksItem.setAction (colourQuirksAction);
menuHandler.debuggingItem.setAction (new DebuggingAction (this));
monochromeAction.addPropertyChangeListener (this);
menuHandler.monochromeItem.setAction (monochromeAction);
debuggingAction.addPropertyChangeListener (this);
menuHandler.debuggingItem.setAction (debuggingAction);
// fill in the placeholders created by the MenuHandler // fill in the placeholders created by the MenuHandler
List<Palette> palettes = HiResImage.getPalettes (); List<Palette> palettes = HiResImage.getPalettes ();
@ -170,6 +171,7 @@ public class DataPanel extends JTabbedPane
JCheckBoxMenuItem item = (JCheckBoxMenuItem) enumeration.nextElement (); JCheckBoxMenuItem item = (JCheckBoxMenuItem) enumeration.nextElement ();
item.setAction (new PaletteAction (this, palettes.get (ndx++))); item.setAction (new PaletteAction (this, palettes.get (ndx++)));
} }
menuHandler.nextPaletteItem.setAction (new NextPaletteAction (this, buttonGroup)); menuHandler.nextPaletteItem.setAction (new NextPaletteAction (this, buttonGroup));
menuHandler.prevPaletteItem.setAction (new PreviousPaletteAction (this, buttonGroup)); menuHandler.prevPaletteItem.setAction (new PreviousPaletteAction (this, buttonGroup));
} }
@ -179,9 +181,8 @@ public class DataPanel extends JTabbedPane
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
HiResImage.getPaletteFactory ().setCurrentPalette (palette); HiResImage.getPaletteFactory ().setCurrentPalette (palette);
if (currentDataSource instanceof HiResImage) if (currentDataSource instanceof HiResImage image)
{ {
HiResImage image = (HiResImage) currentDataSource;
image.setPalette (); image.setPalette ();
imagePanel.setImage (image.getImage ()); imagePanel.setImage (image.getImage ());
} }
@ -192,15 +193,29 @@ public class DataPanel extends JTabbedPane
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
Palette palette = HiResImage.getPaletteFactory ().cyclePalette (direction); Palette palette = HiResImage.getPaletteFactory ().cyclePalette (direction);
if (currentDataSource instanceof HiResImage) if (currentDataSource instanceof HiResImage image)
{ {
HiResImage image = (HiResImage) currentDataSource;
image.setPalette (); image.setPalette ();
imagePanel.setImage (image.getImage ()); imagePanel.setImage (image.getImage ());
} }
return palette; 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) void setLineWrap (boolean lineWrap)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -212,9 +227,8 @@ public class DataPanel extends JTabbedPane
public void setColourQuirks (boolean value) public void setColourQuirks (boolean value)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
if (currentDataSource instanceof HiResImage) if (currentDataSource instanceof HiResImage image)
{ {
HiResImage image = (HiResImage) currentDataSource;
image.setColourQuirks (value); image.setColourQuirks (value);
imagePanel.setImage (image.getImage ()); imagePanel.setImage (image.getImage ());
} }
@ -224,9 +238,8 @@ public class DataPanel extends JTabbedPane
public void setMonochrome (boolean value) public void setMonochrome (boolean value)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
if (currentDataSource instanceof HiResImage) if (currentDataSource instanceof HiResImage image)
{ {
HiResImage image = (HiResImage) currentDataSource;
image.setMonochrome (value); image.setMonochrome (value);
imagePanel.setImage (image.getImage ()); imagePanel.setImage (image.getImage ());
} }
@ -237,22 +250,16 @@ public class DataPanel extends JTabbedPane
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
imagePanel.setScale (scale); imagePanel.setScale (scale);
if (currentDataSource instanceof HiResImage) if (currentDataSource instanceof HiResImage image)
{
HiResImage image = (HiResImage) currentDataSource;
imagePanel.setImage (image.getImage ()); imagePanel.setImage (image.getImage ());
}
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public void update () public void update ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
if (currentDataSource instanceof HiResImage) if (currentDataSource instanceof HiResImage image)
{
HiResImage image = (HiResImage) currentDataSource;
imagePanel.setImage (image.getImage ()); imagePanel.setImage (image.getImage ());
}
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -264,9 +271,10 @@ public class DataPanel extends JTabbedPane
AbstractFile.setDebug (value); AbstractFile.setDebug (value);
setText (formattedText, currentDataSource.getText ()); setText (formattedText, currentDataSource.getText ());
if (currentDataSource instanceof HiResImage if (currentDataSource instanceof HiResImage //
|| currentDataSource instanceof MazeLevel // Wizardry
|| currentDataSource instanceof QuickDrawFont) || currentDataSource instanceof QuickDrawFont)
setDataSource (currentDataSource); // toggles text/image setDataSource (currentDataSource); // toggles text/image
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -298,6 +306,7 @@ public class DataPanel extends JTabbedPane
JScrollPane outputScrollPane = JScrollPane outputScrollPane =
new JScrollPane (outputPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, new JScrollPane (outputPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
outputScrollPane.setBorder (null); // remove the ugly default border outputScrollPane.setBorder (null); // remove the ugly default border
add (outputScrollPane, tabName); add (outputScrollPane, tabName);
return outputScrollPane; return outputScrollPane;
@ -355,15 +364,15 @@ public class DataPanel extends JTabbedPane
removeImage (); removeImage ();
else else
{ {
if (dataSource instanceof HiResImage) if (dataSource instanceof HiResImage hri)
{ {
((HiResImage) dataSource).checkPalette (); hri.checkPalette ();
image = dataSource.getImage (); image = dataSource.getImage ();
if (((HiResImage) dataSource).isAnimation ()) if (((HiResImage) dataSource).isAnimation ())
{ {
if (animation != null) if (animation != null)
animation.cancel (); animation.cancel ();
animation = new Worker ((SHRPictureFile2) dataSource); animation = new AnimationWorker (this, (SHRPictureFile2) dataSource);
animation.execute (); animation.execute ();
} }
} }
@ -411,71 +420,6 @@ public class DataPanel extends JTabbedPane
textArea.setCaretPosition (0); 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 @Override
public void diskSelected (DiskSelectedEvent event) public void diskSelected (DiskSelectedEvent event)
@ -483,6 +427,7 @@ public class DataPanel extends JTabbedPane
{ {
setSelectedIndex (0); setSelectedIndex (0);
setDataSource (null); setDataSource (null);
if (event.getFormattedDisk () != null) if (event.getFormattedDisk () != null)
setDataSource (event.getFormattedDisk ().getCatalog ().getDataSource ()); setDataSource (event.getFormattedDisk ().getCatalog ().getDataSource ());
else else
@ -524,7 +469,6 @@ public class DataPanel extends JTabbedPane
{ {
setSelectedIndex (0); setSelectedIndex (0);
setDataSource (event.getFileNode ()); setDataSource (event.getFileNode ());
// FileNode node = event.getFileNode ();
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -549,8 +493,7 @@ public class DataPanel extends JTabbedPane
public void setAssemblerPreferences (AssemblerPreferences assemblerPreferences) public void setAssemblerPreferences (AssemblerPreferences assemblerPreferences)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
if (currentDataSource instanceof AssemblerProgram if (currentDataSource instanceof AssemblerProgram || currentDataSource instanceof BootSector)
|| currentDataSource instanceof BootSector)
setDataSource (currentDataSource); setDataSource (currentDataSource);
} }
@ -562,49 +505,4 @@ public class DataPanel extends JTabbedPane
if (currentDataSource instanceof BasicTextFile) if (currentDataSource instanceof BasicTextFile)
setDataSource (currentDataSource); 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 ();
}
}
} }

View File

@ -12,10 +12,10 @@ class PaletteAction extends AbstractAction
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private final Palette palette; 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 ()); super (palette.getName ());

View File

@ -17,11 +17,11 @@ import com.bytezone.diskbrowser.applefile.PaletteFactory.CycleDirection;
class PreviousPaletteAction extends AbstractAction class PreviousPaletteAction extends AbstractAction
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private final DataPanel owner; private final OutputPanel owner;
private final ButtonGroup buttonGroup; private final ButtonGroup buttonGroup;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
PreviousPaletteAction (DataPanel owner, ButtonGroup buttonGroup) PreviousPaletteAction (OutputPanel owner, ButtonGroup buttonGroup)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super ("Previous Palette"); super ("Previous Palette");

View File

@ -16,10 +16,10 @@ import com.bytezone.diskbrowser.utilities.DefaultAction;
class PrintAction extends 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", super ("Print...", "Print the contents of the output panel",

View File

@ -3,8 +3,6 @@ package com.bytezone.diskbrowser.gui;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
import javax.swing.Action; import javax.swing.Action;
@ -18,7 +16,7 @@ class RootDirectoryAction extends DefaultAction implements QuitListener
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private static final String prefsRootDirectory = "Root directory"; private static final String prefsRootDirectory = "Root directory";
private final List<RootDirectoryChangeListener> listeners = new ArrayList<> ();
private File rootFolder; 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", super ("Set HOME folder...", "Defines root folder where the disk images are kept",
"/com/bytezone/diskbrowser/icons/"); "/com/bytezone/diskbrowser/icons/");
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt H")); putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt H"));
putValue (Action.MNEMONIC_KEY, KeyEvent.VK_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 @Override
public void quit (Preferences prefs) public void quit (Preferences prefs)
@ -78,9 +69,7 @@ class RootDirectoryAction extends DefaultAction implements QuitListener
public void restore (Preferences prefs) public void restore (Preferences prefs)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
String rootDirectory = prefs.get (prefsRootDirectory, ""); File rootDirectoryFile = new File (prefs.get (prefsRootDirectory, ""));
File rootDirectoryFile = new File (rootDirectory);
if (!rootDirectoryFile.exists () || !rootDirectoryFile.isDirectory ()) if (!rootDirectoryFile.exists () || !rootDirectoryFile.isDirectory ())
{ {
@ -96,7 +85,7 @@ class RootDirectoryAction extends DefaultAction implements QuitListener
{ {
File oldRootFolder = rootFolder; File oldRootFolder = rootFolder;
rootFolder = newRootFolder; rootFolder = newRootFolder;
for (RootDirectoryChangeListener listener : listeners)
listener.rootDirectoryChanged (oldRootFolder, newRootFolder); firePropertyChange ("RootDirectory", oldRootFolder, newRootFolder);
} }
} }

View File

@ -1,10 +0,0 @@
package com.bytezone.diskbrowser.gui;
import java.io.File;
// -----------------------------------------------------------------------------------//
public interface RootDirectoryChangeListener
// -----------------------------------------------------------------------------------//
{
public void rootDirectoryChanged (File oldRootFolder, File newRootFolder);
}

View File

@ -2,25 +2,25 @@ package com.bytezone.diskbrowser.gui;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import javax.swing.JFileChooser; import javax.swing.JFileChooser;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import com.bytezone.diskbrowser.disk.AppleDisk;
import com.bytezone.diskbrowser.disk.Disk;
import com.bytezone.diskbrowser.disk.FormattedDisk; import com.bytezone.diskbrowser.disk.FormattedDisk;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
class SaveDiskAction extends AbstractSaveAction implements DiskSelectionListener class SaveDiskAction extends AbstractSaveAction implements DiskSelectionListener
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
FormattedDisk disk; FormattedDisk formattedDisk;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
SaveDiskAction () 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) public void actionPerformed (ActionEvent evt)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
if (disk == null) if (formattedDisk == null)
{ {
JOptionPane.showMessageDialog (null, "No disk selected"); JOptionPane.showMessageDialog (null, "No disk selected");
return; return;
} }
if (fileChooser == null) Disk disk = formattedDisk.getDisk ();
if (disk instanceof AppleDisk appleDisk)
{ {
fileChooser = new JFileChooser (); int blocks = disk.getTotalBlocks ();
fileChooser.setDialogTitle ("Save converted disk"); 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) if (fileChooser.showSaveDialog (null) == JFileChooser.APPROVE_OPTION)
{ saveBuffer (appleDisk.getBuffer ());
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");
}
} }
else
System.out.println ("Not an AppleDisk"); // impossible
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -64,7 +54,7 @@ class SaveDiskAction extends AbstractSaveAction implements DiskSelectionListener
public void diskSelected (DiskSelectedEvent event) public void diskSelected (DiskSelectedEvent event)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
this.disk = event.getFormattedDisk (); formattedDisk = event.getFormattedDisk ();
setEnabled (disk != null && disk.isTempDisk ()); setEnabled (formattedDisk != null && formattedDisk.isTempDisk ());
} }
} }

View File

@ -1,13 +1,15 @@
package com.bytezone.diskbrowser.gui; package com.bytezone.diskbrowser.gui;
import java.awt.Toolkit;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File; 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.JFileChooser;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import com.bytezone.diskbrowser.applefile.AppleFileSource; import com.bytezone.diskbrowser.applefile.AppleFileSource;
@ -16,12 +18,17 @@ class SaveFileAction extends AbstractSaveAction implements FileSelectionListener
//-----------------------------------------------------------------------------------// //-----------------------------------------------------------------------------------//
{ {
AppleFileSource appleFileSource; AppleFileSource appleFileSource;
private JCheckBox formatted = new JCheckBox ("Formatted");
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
SaveFileAction () 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; return;
} }
if (fileChooser == null) if (formatted.isSelected ())
{ setSelectedFile (new File (appleFileSource.getUniqueName () + ".txt"));
fileChooser = new JFileChooser (); else
fileChooser.setDialogTitle ("Save File"); 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) if (formatted.isSelected ())
{ saveBuffer (appleFileSource.getDataSource ().getText ().getBytes ());
File file = fileChooser.getSelectedFile (); else
try saveBuffer (appleFileSource.getDataSource ().getBuffer ());
{
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");
}
}
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -67,8 +62,8 @@ class SaveFileAction extends AbstractSaveAction implements FileSelectionListener
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
this.appleFileSource = event.appleFileSource; this.appleFileSource = event.appleFileSource;
setEnabled (
event.appleFileSource != null && event.appleFileSource.getDataSource () != null setEnabled (appleFileSource != null && appleFileSource.getDataSource () != null
&& event.appleFileSource.getDataSource ().getBuffer () != null); && appleFileSource.getDataSource ().getBuffer () != null);
} }
} }

View File

@ -2,13 +2,14 @@ package com.bytezone.diskbrowser.gui;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.io.File; import java.io.File;
import java.io.IOException; import java.util.List;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import javax.swing.JFileChooser; import javax.swing.JFileChooser;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import com.bytezone.diskbrowser.disk.Disk;
import com.bytezone.diskbrowser.disk.DiskAddress;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
class SaveSectorsAction extends AbstractSaveAction implements SectorSelectionListener class SaveSectorsAction extends AbstractSaveAction implements SectorSelectionListener
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
@ -19,7 +20,7 @@ class SaveSectorsAction extends AbstractSaveAction implements SectorSelectionLis
SaveSectorsAction () SaveSectorsAction ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super ("Save sectors...", "Save currently selected sectors"); super ("Save sectors...", "Save currently selected sectors", "Save sectors");
this.setEnabled (false); this.setEnabled (false);
} }
@ -34,31 +35,16 @@ class SaveSectorsAction extends AbstractSaveAction implements SectorSelectionLis
return; return;
} }
if (fileChooser == null) // block 0 will not read when it is the only DiskAddress in the list
{ List<DiskAddress> blocks = event.getSectors ();
fileChooser = new JFileChooser (); Disk disk = event.getFormattedDisk ().getDisk ();
fileChooser.setDialogTitle ("Save sectors"); 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) if (fileChooser.showSaveDialog (null) == JFileChooser.APPROVE_OPTION)
{ saveBuffer (buffer);
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");
}
}
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//

View File

@ -10,11 +10,11 @@ import javax.swing.KeyStroke;
public class ScaleAction extends AbstractAction public class ScaleAction extends AbstractAction
{ {
private final DataPanel owner; private final OutputPanel owner;
private double scale; private double scale;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public ScaleAction (DataPanel owner, double scale, int menu) public ScaleAction (OutputPanel owner, double scale, int menu)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super ("Scale " + scale); super ("Scale " + scale);

View File

@ -29,14 +29,14 @@ class ScrollRuler extends JComponent
private boolean isHex = true; private boolean isHex = true;
private boolean isTrackMode = true; private boolean isTrackMode = true;
private LayoutDetails layoutDetails; 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.orientation = orientation;
this.image = image; this.diskLayoutImage = diskLayoutImage;
// set defaults until setLayout is called // set defaults until setLayout is called
if (orientation == HORIZONTAL) 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 // Must match the preferred size of DiskLayoutImage
if (orientation == HORIZONTAL) if (orientation == HORIZONTAL)
setPreferredSize ( setPreferredSize (new Dimension (
new Dimension (layout.block.width * layout.grid.width + 1, HEIGHT)); layoutDetails.block.width * layoutDetails.grid.width + 1, HEIGHT));
else else
setPreferredSize ( setPreferredSize (new Dimension (WIDTH,
new Dimension (WIDTH, layout.block.height * layout.grid.height + 1)); 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 start = (clipRect.x / width);
int end = start + clipRect.width / 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; String format;
int offset; int offset;
@ -131,7 +131,7 @@ class ScrollRuler extends JComponent
{ {
int start = (clipRect.y / height); int start = (clipRect.y / height);
int end = start + clipRect.height / 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"; String format = isHex ? "%04X" : "%04d";

View File

@ -12,7 +12,7 @@ class SectorSelectedEvent extends EventObject
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private final List<DiskAddress> sectors; private final List<DiskAddress> sectors;
private final FormattedDisk owner; private final FormattedDisk owner; // for dual-format disks
boolean redo; boolean redo;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -20,6 +20,7 @@ class SectorSelectedEvent extends EventObject
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super (source); super (source);
this.sectors = sectors; this.sectors = sectors;
// always store the parent if this disk is part of a dual-dos disk // always store the parent if this disk is part of a dual-dos disk
this.owner = owner.getParent () == null ? owner : owner.getParent (); this.owner = owner.getParent () == null ? owner : owner.getParent ();
@ -44,8 +45,10 @@ class SectorSelectedEvent extends EventObject
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
StringBuilder text = new StringBuilder (); 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 (); return text.toString ();
} }

View File

@ -5,26 +5,23 @@ import java.awt.event.KeyEvent;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.JMenuItem;
import javax.swing.KeyStroke; import javax.swing.KeyStroke;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
class ShowFreeSectorsAction extends AbstractAction class ShowFreeSectorsAction extends AbstractAction
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
DiskLayoutPanel panel;
MenuHandler mh;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
ShowFreeSectorsAction (MenuHandler mh, DiskLayoutPanel panel) ShowFreeSectorsAction ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
super ("Show free sectors"); super ("Show free sectors");
putValue (Action.SHORT_DESCRIPTION, putValue (Action.SHORT_DESCRIPTION,
"Display which sectors are marked free in the disk layout panel"); "Display which sectors are marked free in the disk layout panel");
putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt F")); putValue (Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke ("alt F"));
putValue (Action.MNEMONIC_KEY, KeyEvent.VK_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) public void actionPerformed (ActionEvent e)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
panel.setFree (mh.showFreeSectorsItem.isSelected ()); firePropertyChange (e.getActionCommand (), null,
((JMenuItem) e.getSource ()).isSelected ());
} }
} }

View File

@ -23,7 +23,7 @@ import com.bytezone.diskbrowser.utilities.Utility;
class TreeBuilder 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 FileComparator fileComparator = new FileComparator ();
private final JTree tree; private final JTree tree;
@ -219,8 +219,7 @@ class TreeBuilder
String type = pos > 0 && !f.isDirectory () ? name.substring (pos) : ""; String type = pos > 0 && !f.isDirectory () ? name.substring (pos) : "";
String size = f.isDirectory () ? "" : String.format ("%,14d", f.length ()); String size = f.isDirectory () ? "" : String.format ("%,14d", f.length ());
text.append (String.format ("%s %-40.40s %s %-14s %s%n", text.append (String.format ("%s %-40.40s %s %-14s %s%n",
f.isDirectory () ? "D" : " ", name, sdf.format (d).replace (".", ""), size, f.isDirectory () ? "D" : " ", name, sdf.format (d), size, type));
type));
} }
} }

View File

@ -57,7 +57,7 @@ class ZObject extends AbstractFile implements Comparable<ZObject>
propertyTablePtr = header.getWord (offset + 7); propertyTablePtr = header.getWord (offset + 7);
int ptr = propertyTablePtr; int ptr = propertyTablePtr;
int nameLength = header.getByte (ptr) * 2; 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; ptr += nameLength;
// read each property // read each property
@ -84,11 +84,11 @@ class ZObject extends AbstractFile implements Comparable<ZObject>
{ {
StringBuilder text = new StringBuilder (); 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 obj1 = parent == 0 ? "" : header.getObject (parent - 1).getName ();
String obj2 = sibling == 0 ? "" : header.getObject (sibling - 1).name; String obj2 = sibling == 0 ? "" : header.getObject (sibling - 1).getName ();
String obj3 = child == 0 ? "" : header.getObject (child - 1).name; String obj3 = child == 0 ? "" : header.getObject (child - 1).getName ();
text.append (String.format ("Parent : %02X (%<3d) %s%n", parent, obj1)); text.append (String.format ("Parent : %02X (%<3d) %s%n", parent, obj1));
text.append (String.format ("Sibling : %02X (%<3d) %s%n", sibling, obj2)); 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 () 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 if (propertyNumber >= 19) // directions
{ {
ZObject object = getObject (); ZObject object = getObject ();
String objectName = object == null ? "no object" : object.name; String objectName = object == null ? "no object" : object.getName ();
switch (length) switch (length)
{ {
@ -271,8 +271,8 @@ class ZObject extends AbstractFile implements Comparable<ZObject>
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
{ {
int objectId = header.getByte (ptr + i + 1); int objectId = header.getByte (ptr + i + 1);
text.append ( text.append (String.format ("%s%s", (i == 0 ? "" : ", "),
String.format ("%s%s", (i == 0 ? "" : ", "), getObject (objectId).name)); getObject (objectId).getName ()));
} }
} }
// else // else
@ -296,6 +296,6 @@ class ZObject extends AbstractFile implements Comparable<ZObject>
public int compareTo (ZObject o) public int compareTo (ZObject o)
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
return this.name.compareTo (o.name); return this.getName ().compareTo (o.getName ());
} }
} }

View File

@ -15,10 +15,8 @@ import com.bytezone.diskbrowser.utilities.Utility;
public class WozFile public class WozFile
//-----------------------------------------------------------------------------------// //-----------------------------------------------------------------------------------//
{ {
private static final byte[] address16prologue = private static final byte[] address16prologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0x96 };
{ (byte) 0xD5, (byte) 0xAA, (byte) 0x96 }; private static final byte[] address13prologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0xB5 };
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[] dataPrologue = { (byte) 0xD5, (byte) 0xAA, (byte) 0xAD };
private static final byte[] epilogue = { (byte) 0xDE, (byte) 0xAA, (byte) 0xEB }; private static final byte[] epilogue = { (byte) 0xDE, (byte) 0xAA, (byte) 0xEB };
// apparently it can be DE AA Ex // 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 TRK_SIZE = 0x1A00;
private static final int DATA_SIZE = TRK_SIZE - 10; private static final int DATA_SIZE = TRK_SIZE - 10;
private static int[][] interleave = private static int[][] interleave = //
{ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, // 13 sector { { 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 { 0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15 } }; // 16 sector
public final File file; public final File file;
@ -146,8 +144,7 @@ public class WozFile
{ {
if (info != null) if (info != null)
System.out.println (info); System.out.println (info);
throw new DiskNibbleException ( throw new DiskNibbleException (String.format ("Invalid chunk name character: %02X%n", val));
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 wozBase2 = home + "Dropbox/Examples/woz test images/WOZ 2.0/";
String wozBase3 = home + "Dropbox/Examples/woz test images/WOZ 2.0/3.5/"; 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"), File[] files = { new File (home + "code/python/wozardry-2.0/bill.woz"),
new File (wozBase2 + "DOS 3.3 System Master.woz"), new File (wozBase2 + "DOS 3.3 System Master.woz"),
new File (wozBase1 + "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 (wozBase3 + "Apple IIgs System Disk 1.1.woz") };
try try
{ {
new WozFile (files[3]); new WozFile (files[3]);
@ -369,8 +366,7 @@ public class WozFile
String diskTypeText = diskType == 1 ? "5.25" : "3.5"; String diskTypeText = diskType == 1 ? "5.25" : "3.5";
text.append (String.format ("Version ............. %d%n", wozVersion)); text.append (String.format ("Version ............. %d%n", wozVersion));
text.append ( text.append (String.format ("Disk type ........... %d (%s\")%n", diskType, diskTypeText));
String.format ("Disk type ........... %d (%s\")%n", diskType, diskTypeText));
text.append (String.format ("Write protected ..... %d%n", writeProtected)); text.append (String.format ("Write protected ..... %d%n", writeProtected));
text.append (String.format ("Synchronized ........ %d%n", synchronised)); text.append (String.format ("Synchronized ........ %d%n", synchronised));
text.append (String.format ("Cleaned ............. %d%n", cleaned)); text.append (String.format ("Cleaned ............. %d%n", cleaned));
@ -378,9 +374,8 @@ public class WozFile
if (wozVersion > 1) if (wozVersion > 1)
{ {
String bootSectorFormatText = String bootSectorFormatText = bootSectorFormat == 0 ? "Unknown"
bootSectorFormat == 0 ? "Unknown" : bootSectorFormat == 1 ? "16 sector" : bootSectorFormat == 1 ? "16 sector" : bootSectorFormat == 2 ? "13 sector" : "Hybrid";
: bootSectorFormat == 2 ? "13 sector" : "Hybrid";
text.append (String.format ("%nSides ............... %d%n", sides)); text.append (String.format ("%nSides ............... %d%n", sides));
text.append (String.format ("Boot sector format .. %d (%s)%n", bootSectorFormat, 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); bitCount = val16 (rawBuffer, ptr + DATA_SIZE + 2);
if (debug1) if (debug1)
System.out.println ( System.out.println ((String.format ("Bytes: %2d, Bits: %,8d%n%n", bytesUsed, bitCount)));
(String.format ("Bytes: %2d, Bits: %,8d%n%n", bytesUsed, bitCount)));
} }
else else
{ {
@ -612,10 +606,8 @@ public class WozFile
for (Sector sector : sectors) for (Sector sector : sectors)
if (sector.dataOffset > 0) if (sector.dataOffset > 0)
{ {
byte[] decodedBuffer = byte[] decodedBuffer = diskReader.decodeSector (newBuffer, sector.dataOffset + 3);
diskReader.decodeSector (newBuffer, sector.dataOffset + 3); int ptr = SECTOR_SIZE * (sector.trackNo * diskSectors + interleave[ndx][sector.sectorNo]);
int ptr = SECTOR_SIZE
* (sector.trackNo * diskSectors + interleave[ndx][sector.sectorNo]);
System.arraycopy (decodedBuffer, 0, diskBuffer, ptr, decodedBuffer.length); System.arraycopy (decodedBuffer, 0, diskBuffer, ptr, decodedBuffer.length);
} }
} }
@ -627,8 +619,7 @@ public class WozFile
{ {
StringBuilder text = new StringBuilder (); StringBuilder text = new StringBuilder ();
if (info.wozVersion == 1) if (info.wozVersion == 1)
text.append ( text.append (String.format ("WOZ1: Bytes: %2d, Bits: %,8d%n%n", bytesUsed, bitCount));
String.format ("WOZ1: Bytes: %2d, Bits: %,8d%n%n", bytesUsed, bitCount));
else else
text.append (String.format ("WOZ2: Start: %4d, Blocks: %2d, Bits: %,8d%n%n", text.append (String.format ("WOZ2: Start: %4d, Blocks: %2d, Bits: %,8d%n%n",
startingBlock, blockCount, bitCount)); startingBlock, blockCount, bitCount));
@ -728,9 +719,8 @@ public class WozFile
String fld = info.diskType == 1 ? "Vol" : info.diskType == 2 ? "Sde" : "???"; String fld = info.diskType == 1 ? "Vol" : info.diskType == 2 ? "Sde" : "???";
String dataOffsetText = dataOffset < 0 ? "" : String.format ("%04X", dataOffset); String dataOffsetText = dataOffset < 0 ? "" : String.format ("%04X", dataOffset);
return String.format ( return String.format ("%s: %02X Trk: %02X Sct: %02X Chk: %02X Add: %04X Dat: %s", fld,
"%s: %02X Trk: %02X Sct: %02X Chk: %02X Add: %04X Dat: %s", fld, volume, volume, trackNo, sectorNo, checksum, addressOffset, dataOffsetText);
trackNo, sectorNo, checksum, addressOffset, dataOffsetText);
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//

View File

@ -1,4 +1,4 @@
package com.bytezone.diskbrowser.utilities; package com.bytezone.diskbrowser.nufx;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; 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.FileAlreadyExistsException;
import com.bytezone.diskbrowser.prodos.write.ProdosDisk; import com.bytezone.diskbrowser.prodos.write.ProdosDisk;
import com.bytezone.diskbrowser.prodos.write.VolumeCatalogFullException; import com.bytezone.diskbrowser.prodos.write.VolumeCatalogFullException;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
public class Binary2 public class Binary2
@ -19,11 +20,11 @@ public class Binary2
"------------------------------------------------------" "------------------------------------------------------"
+ "-----------------------"; + "-----------------------";
Binary2Header binary2Header; private Binary2Header binary2Header;
byte[] buffer; private byte[] buffer;
List<Binary2Header> headers = new ArrayList<> (); private List<Binary2Header> headers = new ArrayList<> ();
int totalBlocks; private int totalBlocks;
String fileName; private String fileName;
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
public Binary2 (Path path) throws IOException public Binary2 (Path path) throws IOException
@ -31,18 +32,26 @@ public class Binary2
{ {
fileName = path.toFile ().getName (); fileName = path.toFile ().getName ();
buffer = Files.readAllBytes (path); buffer = Files.readAllBytes (path);
read (buffer);
}
// ---------------------------------------------------------------------------------//
private void read (byte[] buffer)
// ---------------------------------------------------------------------------------//
{
int ptr = 0; int ptr = 0;
do do
{ {
binary2Header = new Binary2Header (buffer, ptr); 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; totalBlocks += binary2Header.totalBlocks;
ptr += ((binary2Header.eof - 1) / 128 + 1) * 128 + 128; headers.add (binary2Header);
} while (binary2Header.filesToFollow > 0); } while (binary2Header.filesToFollow > 0);
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -57,9 +66,19 @@ public class Binary2
byte[] dataBuffer = new byte[header.eof]; // this sux byte[] dataBuffer = new byte[header.eof]; // this sux
System.arraycopy (buffer, header.ptr + 128, dataBuffer, 0, dataBuffer.length); System.arraycopy (buffer, header.ptr + 128, dataBuffer, 0, dataBuffer.length);
disk.addFile (header.fileName, header.fileType, header.auxType, header.created, if (header.compressed && dataBuffer[0] == 0x76 && dataBuffer[1] == (byte) 0xFF)
header.modified, dataBuffer, header.eof); {
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 (); disk.close ();
@ -82,24 +101,11 @@ public class Binary2
text.append (String.format ("%s%n", UNDERLINE)); text.append (String.format ("%s%n", UNDERLINE));
// int totalUncompressedSize = 0;
// int totalCompressedSize = 0;
for (Binary2Header header : headers) for (Binary2Header header : headers)
{
text.append (String.format ("%s%n", header.getLine ())); text.append (String.format ("%s%n", header.getLine ()));
// totalUncompressedSize += record.getUncompressedSize ();
// totalCompressedSize += record.getCompressedSize ();
}
text.append (String.format ("%s%n", UNDERLINE)); 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 (); return text.toString ();
} }
} }

View File

@ -1,4 +1,4 @@
package com.bytezone.diskbrowser.utilities; package com.bytezone.diskbrowser.nufx;
import static com.bytezone.diskbrowser.prodos.ProdosConstants.fileTypes; import static com.bytezone.diskbrowser.prodos.ProdosConstants.fileTypes;
@ -6,16 +6,17 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import com.bytezone.diskbrowser.prodos.write.ProdosDisk; import com.bytezone.diskbrowser.prodos.write.ProdosDisk;
import com.bytezone.diskbrowser.utilities.HexFormatter;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
public class Binary2Header public class Binary2Header
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
static DateTimeFormatter formatter = DateTimeFormatter.ofPattern ("dd-LLL-yy HH:mm"); static DateTimeFormatter formatter = DateTimeFormatter.ofPattern ("dd-LLL-yy HH:mm");
static String[] osTypes = static String[] osTypes = { "Prodos", "DOS 3.3", "Reserved", "DOS 3.2 or 3.1", "Pascal",
{ "Prodos", "DOS 3.3", "Reserved", "DOS 3.2 or 3.1", "Pascal", "Macintosh MFS", "Macintosh MFS", "Macintosh HFS", "Lisa", "CPM", "Reserved", "MS-DOS", "High Sierra (CD-ROM)",
"Macintosh HFS", "Lisa", "CPM", "Reserved", "MS-DOS", "High Sierra (CD-ROM)", "ISO 9660 (CD-ROM)", "AppleShare" };
"ISO 9660 (CD-ROM)", "AppleShare" };
int ptr; int ptr;
byte[] buffer; byte[] buffer;
@ -87,8 +88,8 @@ public class Binary2Header
public String getLine () public String getLine ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
return String.format (" %-33s %3s $%04X %s unc %7d", fileName, return String.format (" %-33s %3s $%04X %s unc %7d", fileName, fileTypes[fileType],
fileTypes[fileType], auxType, modified.format (formatter), eof); 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 storage type ... %02X%n", prodos16storageType));
text.append (String.format ("Prodos total blocks ... %02X%n", prodos16totalBlocks)); text.append (String.format ("Prodos total blocks ... %02X%n", prodos16totalBlocks));
text.append (String.format ("Prodos eof ............ %06X %<,d%n", prodos16eof)); text.append (String.format ("Prodos eof ............ %06X %<,d%n", prodos16eof));
text.append ( text.append (String.format ("Disk space needed ..... %08X %<,d%n", diskSpaceRequired));
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 ("OS type ............... %02X %s%n", osType, osTypes[osType]));
text.append (String.format ("Native file type ...... %02X%n", nativeFileType)); text.append (String.format ("Native file type ...... %02X%n", nativeFileType));
text.append (String.format ("Data flags ............ %02X%n", dataFlags)); 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 ("Version ............... %02X%n", version));
text.append (String.format ("Following files ....... %02X%n", filesToFollow)); text.append (String.format ("Following files ....... %02X%n", filesToFollow));

View File

@ -1,9 +1,11 @@
package com.bytezone.diskbrowser.utilities; package com.bytezone.diskbrowser.nufx;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
abstract class LZW abstract class LZW
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
@ -17,7 +19,7 @@ abstract class LZW
int crc; int crc;
int crcBase; 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 byteBuffer; // one character buffer
private int bitsLeft; // unused bits left in buffer private int bitsLeft; // unused bits left in buffer
@ -88,7 +90,7 @@ abstract class LZW
} }
bitsLeft--; bitsLeft--;
boolean bit = ((byteBuffer << bitsLeft) & 0x80) == 0x80; boolean bit = ((byteBuffer << bitsLeft) & 0x80) != 0;
return bit; return bit;
} }

View File

@ -1,4 +1,6 @@
package com.bytezone.diskbrowser.utilities; package com.bytezone.diskbrowser.nufx;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
class LZW1 extends LZW class LZW1 extends LZW

View File

@ -1,4 +1,6 @@
package com.bytezone.diskbrowser.utilities; package com.bytezone.diskbrowser.nufx;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
class LZW2 extends LZW class LZW2 extends LZW

View 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++;
}
}

View File

@ -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 = private static final byte[] NuFile = { 0x4E, (byte) 0xF5, 0x46, (byte) 0xE9, 0x6C, (byte) 0xE5 };
{ 0x4E, (byte) 0xF5, 0x46, (byte) 0xE9, 0x6C, (byte) 0xE5 };
private static final byte[] BIN2 = { 0x0A, 0x47, 0x4C }; private static final byte[] BIN2 = { 0x0A, 0x47, 0x4C };
private final int crc; private final int crc;
@ -30,15 +34,6 @@ class MasterHeader
if (Utility.isMagic (buffer, ptr, NuFile)) if (Utility.isMagic (buffer, ptr, NuFile))
break; 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)) if (isBin2 (buffer, ptr))
{ {
binary2Header = new Binary2Header (buffer, 0); binary2Header = new Binary2Header (buffer, 0);

View File

@ -1,4 +1,4 @@
package com.bytezone.diskbrowser.utilities; package com.bytezone.diskbrowser.nufx;
import static com.bytezone.diskbrowser.prodos.ProdosConstants.BLOCK_SIZE; 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.FileEntry;
import com.bytezone.diskbrowser.prodos.write.ProdosDisk; import com.bytezone.diskbrowser.prodos.write.ProdosDisk;
import com.bytezone.diskbrowser.prodos.write.VolumeCatalogFullException; import com.bytezone.diskbrowser.prodos.write.VolumeCatalogFullException;
import com.bytezone.diskbrowser.utilities.FileFormatException;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
public class NuFX public class NuFX
@ -38,13 +39,28 @@ public class NuFX
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
{ {
buffer = Files.readAllBytes (path); 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); masterHeader = new MasterHeader (buffer);
int dataPtr = 48; int dataPtr = masterHeader.bin2 ? 176 : 48;
if (masterHeader.bin2)
dataPtr += 128;
if (debug) if (debug)
System.out.printf ("%s%n%n", masterHeader); System.out.printf ("%s%n%n", masterHeader);
@ -80,6 +96,7 @@ public class NuFX
if (record.hasDisk ()) if (record.hasDisk ())
++totalDisks; ++totalDisks;
} }
// System.out.println (toString ());
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -249,8 +266,8 @@ public class NuFX
StringBuilder text = new StringBuilder (); StringBuilder text = new StringBuilder ();
text.append (String.format (" %-15.15s Created:%-17s Mod:%-17s Recs:%5d%n%n", text.append (String.format (" %-15.15s Created:%-17s Mod:%-17s Recs:%5d%n%n",
volumeName.getFileName (), masterHeader.getCreated2 (), volumeName.volumeName, masterHeader.getCreated2 (), masterHeader.getModified2 (),
masterHeader.getModified2 (), masterHeader.getTotalRecords ())); masterHeader.getTotalRecords ()));
text.append (" Name Type Auxtyp Archived" text.append (" Name Type Auxtyp Archived"
+ " Fmat Size Un-Length\n"); + " Fmat Size Un-Length\n");
@ -287,27 +304,19 @@ public class NuFX
private String volumeName = "DiskBrowser"; private String volumeName = "DiskBrowser";
private int nameOffset = 0; private int nameOffset = 0;
private Path path;
// -------------------------------------------------------------------------------// // -------------------------------------------------------------------------------//
VolumeName (Path path) VolumeName (String name)
// -------------------------------------------------------------------------------// // -------------------------------------------------------------------------------//
{ {
this.path = path; int pos = name.lastIndexOf ('.');
volumeName = getFileName ();
int pos = volumeName.lastIndexOf ('.');
if (pos > 0) if (pos > 0)
volumeName = volumeName.substring (0, pos); name = name.substring (0, pos);
if (volumeName.length () > 15) if (name.length () > 15)
volumeName = volumeName.substring (0, 15); name = name.substring (0, 15);
volumeName = volumeName.replace (' ', '.'); name = name.replace (' ', '.');
}
// -------------------------------------------------------------------------------// this.volumeName = name;
String getFileName ()
// -------------------------------------------------------------------------------//
{
return path.getFileName ().toString ();
} }
// -------------------------------------------------------------------------------// // -------------------------------------------------------------------------------//

View File

@ -1,4 +1,4 @@
package com.bytezone.diskbrowser.utilities; package com.bytezone.diskbrowser.nufx;
import static com.bytezone.diskbrowser.prodos.ProdosConstants.fileTypes; import static com.bytezone.diskbrowser.prodos.ProdosConstants.fileTypes;
@ -6,18 +6,21 @@ import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.bytezone.diskbrowser.utilities.DateTime;
import com.bytezone.diskbrowser.utilities.FileFormatException;
import com.bytezone.diskbrowser.utilities.Utility;
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
class Record class Record
// -----------------------------------------------------------------------------------// // -----------------------------------------------------------------------------------//
{ {
private static final byte[] NuFX = { 0x4E, (byte) 0xF5, 0x46, (byte) 0xD8 }; private static final byte[] NuFX = { 0x4E, (byte) 0xF5, 0x46, (byte) 0xD8 };
private static String[] fileSystems = private static String[] fileSystems = { "", "ProDOS/SOS", "DOS 3.3", "DOS 3.2",
{ "", "ProDOS/SOS", "DOS 3.3", "DOS 3.2", "Apple II Pascal", "Macintosh HFS", "Apple II Pascal", "Macintosh HFS", "Macintosh MFS", "Lisa File System",
"Macintosh MFS", "Lisa File System", "Apple CP/M", "", "MS-DOS", "High Sierra", "Apple CP/M", "", "MS-DOS", "High Sierra", "ISO 9660", "AppleShare" };
"ISO 9660", "AppleShare" };
private static String[] storage = { "", "Seedling", "Sapling", "Tree", "", "Extended", private static String[] storage = { "", "Seedling", "Sapling", "Tree", "", "Extended",
"", "", "", "", "", "", "", "Subdirectory" }; "", "", "", "", "", "", "", "Subdirectory" };
private static String[] accessChars = { "D", "R", "B", "", "", "I", "W", "R" }; private static String[] accessChars = { "D", "R", "B", "", "", "I", "W", "R" };
private static String threadFormats[] = { "unc", "sq ", "lz1", "lz2", "", "" }; private static String threadFormats[] = { "unc", "sq ", "lz1", "lz2", "", "" };
@ -250,6 +253,13 @@ class Record
return 0; return 0;
} }
// ---------------------------------------------------------------------------------//
String getThreadFormatText ()
// ---------------------------------------------------------------------------------//
{
return threadFormats[getThreadFormat ()];
}
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
int getUncompressedSize () int getUncompressedSize ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -279,6 +289,17 @@ class Record
return size; return size;
} }
// ---------------------------------------------------------------------------------//
public float getCompressedPct ()
// ---------------------------------------------------------------------------------//
{
float pct = 100;
if (getUncompressedSize () > 0)
pct = getCompressedSize () * 100 / getUncompressedSize ();
return pct;
}
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
byte[] getData () byte[] getData ()
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//
@ -309,9 +330,9 @@ class Record
if (name.length () > 27) if (name.length () > 27)
name = ".." + name.substring (name.length () - 25); name = ".." + name.substring (name.length () - 25);
float pct = 100; // float pct = 100;
if (getUncompressedSize () > 0) // if (getUncompressedSize () > 0)
pct = getCompressedSize () * 100 / getUncompressedSize (); // pct = getCompressedSize () * 100 / getUncompressedSize ();
String lockedFlag = (access | 0xC3) == 1 ? "+" : " "; String lockedFlag = (access | 0xC3) == 1 ? "+" : " ";
String forkedFlag = hasResource () ? "+" : " "; String forkedFlag = hasResource () ? "+" : " ";
@ -319,11 +340,11 @@ class Record
if (hasDisk ()) if (hasDisk ())
return String.format ("%s%-27.27s %-4s %-6s %-15s %s %3.0f%% %7d", lockedFlag, return String.format ("%s%-27.27s %-4s %-6s %-15s %s %3.0f%% %7d", lockedFlag,
name, "Disk", (getUncompressedSize () / 1024) + "k", archived.format2 (), 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, return String.format ("%s%-27.27s %s%s $%04X %-15s %s %3.0f%% %7d", lockedFlag,
name, fileTypes[fileType], forkedFlag, auxType, archived.format2 (), name, fileTypes[fileType], forkedFlag, auxType, archived.format2 (),
threadFormats[getThreadFormat ()], pct, getUncompressedSize ()); getThreadFormatText (), getCompressedPct (), getUncompressedSize ());
} }
// ---------------------------------------------------------------------------------// // ---------------------------------------------------------------------------------//

Some files were not shown because too many files have changed in this diff Show More