mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2024-06-08 04:29:35 +00:00
Compare commits
33 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2bc330e377 | ||
|
6c81bcc93b | ||
|
171fd66ba1 | ||
|
aa77ec1cd4 | ||
|
8f95988596 | ||
|
8cb682f068 | ||
|
dfc7a68580 | ||
|
4b476457d3 | ||
|
3bf972a761 | ||
|
fd5bee6e5c | ||
|
0af6714119 | ||
|
22dfaf65c6 | ||
|
f4a6465b04 | ||
|
64d5ce9ee2 | ||
|
4e48437adc | ||
|
e2abdcabc9 | ||
|
bc0993e9d3 | ||
|
9fba3893ba | ||
|
09c4542118 | ||
|
af3ead0441 | ||
|
c12392200b | ||
|
794fef8610 | ||
|
2ec0e10c5e | ||
|
668ed719fa | ||
|
23b95675cf | ||
|
b98ecbed8d | ||
|
82381a6a47 | ||
|
3f2f1bfbca | ||
|
a7119528a6 | ||
|
6f943ae8c2 | ||
|
5add6c0729 | ||
|
921c946ab5 | ||
|
898587b23b |
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,4 +0,0 @@
|
||||||
/bin/
|
|
||||||
.project
|
|
||||||
.classpath
|
|
||||||
build.xml
|
|
|
@ -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
|
||||||
|
|
40
build.xml
Normal file
40
build.xml
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project name="DiskBrowser" default="jar" basedir=".">
|
||||||
|
|
||||||
|
<property name="srcDir" location="src" />
|
||||||
|
<property name="binDir" location="bin" />
|
||||||
|
<property name="jarDir" location="${user.home}/Dropbox/Java" />
|
||||||
|
<property name="jarFile" location="${jarDir}/DiskBrowser.jar" />
|
||||||
|
|
||||||
|
<target name="version">
|
||||||
|
<echo>DiskBrowser.jar</echo>
|
||||||
|
<echo>${ant.version}</echo>
|
||||||
|
<echo>Java/JVM version: ${ant.java.version}</echo>
|
||||||
|
<echo>Java/JVM detail version: ${java.version}</echo>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="init" depends="version">
|
||||||
|
<delete file="${binDir}/*.class" />
|
||||||
|
<delete file="${jarFile}" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="compile" depends="init">
|
||||||
|
<javac debug="on" srcdir="${srcDir}" destdir="${binDir}" includeantruntime="false">
|
||||||
|
<classpath>
|
||||||
|
<pathelement location="." />
|
||||||
|
</classpath>
|
||||||
|
</javac>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="jar" depends="compile">
|
||||||
|
<jar destfile="${jarFile}">
|
||||||
|
<fileset dir="${binDir}" />
|
||||||
|
<zipfileset src="${jarDir}/InputPanel.jar" />
|
||||||
|
<manifest>
|
||||||
|
<attribute name="Main-Class" value="com.bytezone.diskbrowser.gui.DiskBrowser" />
|
||||||
|
</manifest>
|
||||||
|
</jar>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
</project>
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -16,9 +16,10 @@ import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
public abstract class HiResImage extends AbstractFile
|
public abstract class HiResImage extends AbstractFile
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
static final String[] auxTypes = { "Paintworks Packed SHR Image", "Packed Super Hi-Res Image",
|
static final String[] auxTypes =
|
||||||
"Super Hi-Res Image (Apple Preferred Format)", "Packed QuickDraw II PICT File",
|
{ "Paintworks Packed SHR Image", "Packed Super Hi-Res Image",
|
||||||
"Packed Super Hi-Res 3200 color image", "DreamGraphix" };
|
"Super Hi-Res Image (Apple Preferred Format)", "Packed QuickDraw II PICT File",
|
||||||
|
"Packed Super Hi-Res 3200 color image", "DreamGraphix" };
|
||||||
|
|
||||||
static final int COLOR_TABLE_SIZE = 32;
|
static final int COLOR_TABLE_SIZE = 32;
|
||||||
static final int COLOR_TABLE_OFFSET_AUX_0 = 32_256;
|
static final int COLOR_TABLE_OFFSET_AUX_0 = 32_256;
|
||||||
|
@ -115,7 +116,8 @@ public abstract class HiResImage extends AbstractFile
|
||||||
|
|
||||||
static PaletteFactory paletteFactory = new PaletteFactory ();
|
static PaletteFactory paletteFactory = new PaletteFactory ();
|
||||||
|
|
||||||
static final byte[] pngHeader = { (byte) 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };
|
static final byte[] pngHeader =
|
||||||
|
{ (byte) 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };
|
||||||
|
|
||||||
static boolean colourQuirks;
|
static boolean colourQuirks;
|
||||||
static boolean monochrome;
|
static boolean monochrome;
|
||||||
|
@ -275,8 +277,8 @@ public abstract class HiResImage extends AbstractFile
|
||||||
{
|
{
|
||||||
String auxText = "";
|
String auxText = "";
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
text.append (String.format ("Image File : %s%nFile type : $%02X %s%n", name, fileType,
|
text.append (String.format ("Image File : %s%nFile type : $%02X %s%n", name,
|
||||||
ProdosConstants.fileTypes[fileType]));
|
fileType, ProdosConstants.fileTypes[fileType]));
|
||||||
|
|
||||||
switch (fileType)
|
switch (fileType)
|
||||||
{
|
{
|
||||||
|
@ -393,7 +395,8 @@ public abstract class HiResImage extends AbstractFile
|
||||||
{
|
{
|
||||||
if (dataBuffer.getSize () < rgbList.length + element)
|
if (dataBuffer.getSize () < rgbList.length + element)
|
||||||
{
|
{
|
||||||
System.out.printf ("Bollocks: %d %d %d%n", dataBuffer.getSize (), rgbList.length, element);
|
System.out.printf ("Bollocks: %d %d %d%n", dataBuffer.getSize (), rgbList.length,
|
||||||
|
element);
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,12 +465,13 @@ public abstract class HiResImage extends AbstractFile
|
||||||
int type = (buffer[ptr] & 0xC0) >>> 6; // 0-3
|
int type = (buffer[ptr] & 0xC0) >>> 6; // 0-3
|
||||||
int count = (buffer[ptr++] & 0x3F) + 1; // 1-64
|
int count = (buffer[ptr++] & 0x3F) + 1; // 1-64
|
||||||
|
|
||||||
text.append (String.format ("%04X/%04d: %02X (%d,%2d) ", ptr - 1, size, buffer[ptr - 1],
|
text.append (String.format ("%04X/%04d: %02X (%d,%2d) ", ptr - 1, size,
|
||||||
type, count));
|
buffer[ptr - 1], type, count));
|
||||||
|
|
||||||
if (type == 0)
|
if (type == 0)
|
||||||
{
|
{
|
||||||
text.append (String.format ("%s%n", HexFormatter.getHexString (buffer, ptr, count)));
|
text.append (
|
||||||
|
String.format ("%s%n", HexFormatter.getHexString (buffer, ptr, count)));
|
||||||
ptr += count;
|
ptr += count;
|
||||||
size += count;
|
size += count;
|
||||||
}
|
}
|
||||||
|
@ -651,8 +655,8 @@ public abstract class HiResImage extends AbstractFile
|
||||||
if (buffer.length < 4)
|
if (buffer.length < 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return buffer[0] == (byte) 0xC1 && buffer[1] == (byte) 0xD0 && buffer[2] == (byte) 0xD0
|
return buffer[0] == (byte) 0xC1 && buffer[1] == (byte) 0xD0
|
||||||
&& buffer[3] == 0;
|
&& buffer[2] == (byte) 0xD0 && buffer[3] == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
|
|
@ -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,28 +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);
|
while (buffer[ptr] != 0x0D)
|
||||||
text.append (line + "\n");
|
text.append ((char) buffer[ptr++]);
|
||||||
ptr += line.length () + 1;
|
|
||||||
|
text.append ("\n");
|
||||||
|
ptr++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (text.length () > 0)
|
if (text.length () > 0)
|
||||||
|
@ -45,16 +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 ();
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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,9 +16,11 @@ 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 = "----------------------------------------------------\n";
|
static final String UNDERLINE =
|
||||||
|
"----------------------------------------------------\n";
|
||||||
|
|
||||||
private static final String NO_DATE = "<NO DATE>";
|
private static final String NO_DATE = "<NO DATE>";
|
||||||
|
|
||||||
|
@ -27,8 +30,8 @@ public class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||||
private final int usedBlocks;
|
private final int usedBlocks;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
public ProdosDirectory (FormattedDisk parent, String name, byte[] buffer, int totalBlocks,
|
public ProdosDirectory (FormattedDisk parent, String name, byte[] buffer,
|
||||||
int freeBlocks, int usedBlocks)
|
int totalBlocks, int freeBlocks, int usedBlocks)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (name, buffer);
|
super (name, buffer);
|
||||||
|
@ -109,8 +112,10 @@ public class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||||
LocalDateTime createdDate = Utility.getAppleDate (buffer, i + 24);
|
LocalDateTime createdDate = Utility.getAppleDate (buffer, i + 24);
|
||||||
LocalDateTime modifiedDate = Utility.getAppleDate (buffer, i + 33);
|
LocalDateTime modifiedDate = Utility.getAppleDate (buffer, i + 33);
|
||||||
|
|
||||||
String dateC = createdDate == null ? NO_DATE : createdDate.format (df).toUpperCase ();
|
String dateC =
|
||||||
String dateM = modifiedDate == null ? NO_DATE : modifiedDate.format (df).toUpperCase ();
|
createdDate == null ? NO_DATE : createdDate.format (df).toUpperCase ();
|
||||||
|
String dateM =
|
||||||
|
modifiedDate == null ? NO_DATE : modifiedDate.format (df).toUpperCase ();
|
||||||
|
|
||||||
String timeC = createdDate == null ? "" : createdDate.format (tf);
|
String timeC = createdDate == null ? "" : createdDate.format (tf);
|
||||||
String timeM = modifiedDate == null ? "" : modifiedDate.format (tf);
|
String timeM = modifiedDate == null ? "" : modifiedDate.format (tf);
|
||||||
|
@ -144,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 %04X%n",
|
text.append (
|
||||||
locked, filename, ProdosConstants.fileTypes[type], forkFlag, blocks, dateM, timeM,
|
String.format ("%s%-15s %3s%s %5d %9s %5s %9s %5s %8d %7s %04X%n",
|
||||||
dateC, timeC, eof, subType, aux));
|
locked, filename, ProdosConstants.fileTypes[type], forkFlag, blocks,
|
||||||
|
dateM, timeM, dateC, timeC, eof, subType, aux));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -154,8 +160,9 @@ public class ProdosDirectory extends AbstractFile implements ProdosConstants
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
text.append (String.format ("%nBLOCKS FREE:%5d BLOCKS USED:%5d TOTAL BLOCKS:%5d%n",
|
text.append (
|
||||||
freeBlocks, usedBlocks, totalBlocks));
|
String.format ("%nBLOCKS FREE:%5d BLOCKS USED:%5d TOTAL BLOCKS:%5d%n",
|
||||||
|
freeBlocks, usedBlocks, totalBlocks));
|
||||||
|
|
||||||
return text.toString ();
|
return text.toString ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,7 +243,7 @@ public class SHRPictureFile1 extends HiResImage
|
||||||
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
|
colorTables[i] = new ColorTable (i, 0x00); // default empty table !! not
|
||||||
// finished
|
// finished
|
||||||
ptr += 32;
|
ptr += 32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -16,6 +16,7 @@ import com.bytezone.diskbrowser.disk.SectorType;
|
||||||
import com.bytezone.diskbrowser.gui.DataSource;
|
import com.bytezone.diskbrowser.gui.DataSource;
|
||||||
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
import com.bytezone.diskbrowser.utilities.HexFormatter;
|
||||||
|
|
||||||
|
// https://www.retrotechnology.com/dri/howto_cpm.html
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
public class CPMDisk extends AbstractFormattedDisk
|
public class CPMDisk extends AbstractFormattedDisk
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
|
@ -88,7 +89,7 @@ public class CPMDisk extends AbstractFormattedDisk
|
||||||
if (b1 > 31 && b1 != EMPTY_BYTE_VALUE)
|
if (b1 > 31 && b1 != EMPTY_BYTE_VALUE)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (b2 < 32 || (b2 > 126 && b2 != EMPTY_BYTE_VALUE))
|
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)
|
||||||
|
@ -99,7 +100,7 @@ public class CPMDisk extends AbstractFormattedDisk
|
||||||
if (b1 == EMPTY_BYTE_VALUE) // deleted file??
|
if (b1 == EMPTY_BYTE_VALUE) // deleted file??
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (b2 < 32 || (b2 > 126 && b2 != EMPTY_BYTE_VALUE))
|
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);
|
||||||
|
@ -188,9 +189,8 @@ public class CPMDisk extends AbstractFormattedDisk
|
||||||
public AppleFileSource getCatalog ()
|
public AppleFileSource getCatalog ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
String line =
|
String line = "---- --------- --- - - -- -- -- -- ----------------------------"
|
||||||
"---- --------- --- - - -- -- -- -- ----------------------------"
|
+ "-------------------\n";
|
||||||
+ "-------------------\n";
|
|
||||||
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\n");
|
text.append ("User Name Typ R S Ex S2 S1 RC Blocks\n");
|
||||||
|
|
|
@ -139,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 ();
|
||||||
|
|
||||||
|
@ -218,14 +217,13 @@ class DirectoryEntry implements AppleFileSource
|
||||||
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) || "COB".equals (type)
|
else if ("ASM".equals (type) || "DOC".equals (type) || "COB".equals (type)
|
||||||
|| "HLP".equals (type) || "TXT".equals (type) || "LET".equals (type)
|
|| "HLP".equals (type) || "TXT".equals (type) || "LET".equals (type) || "ALX".equals (type)
|
||||||
|| "ALX".equals (type) || "SRC".equals (type) || "H".equals (type)
|
|| "SRC".equals (type) || "H".equals (type) || exactBuffer[len - 1] == 0x1A)
|
||||||
|| exactBuffer[len - 1] == 0x1A)
|
|
||||||
appleFile = new CPMTextFile (name, exactBuffer);
|
appleFile = new CPMTextFile (name, exactBuffer);
|
||||||
else if ("BAS".equals (type))
|
else if ("BAS".equals (type))
|
||||||
appleFile = new CPMBasicFile (name, exactBuffer);
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -733,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));
|
||||||
|
|
|
@ -148,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 **");
|
||||||
|
@ -156,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)
|
||||||
|
@ -173,7 +177,7 @@ public class DiskFactory
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// e.printStackTrace ();
|
// e.printStackTrace ();
|
||||||
if (e.getMessage () == null)
|
if (e.getMessage () == null)
|
||||||
System.out.println (e);
|
System.out.println (e);
|
||||||
else
|
else
|
||||||
|
@ -183,10 +187,10 @@ public class DiskFactory
|
||||||
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 ());
|
||||||
|
@ -414,7 +418,8 @@ public class DiskFactory
|
||||||
|
|
||||||
if (length != DISK_143K) // 16 sector floppy disk
|
if (length != DISK_143K) // 16 sector floppy disk
|
||||||
{
|
{
|
||||||
System.out.printf ("%s: invalid file length : %,d%n", file.getName (), file.length ());
|
System.out.printf ("%s: invalid file length : %,d%n", file.getName (),
|
||||||
|
file.length ());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,8 +579,8 @@ public class DiskFactory
|
||||||
disk = new DataDisk (appleDisk256);
|
disk = new DataDisk (appleDisk256);
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
System.out
|
System.out.println (
|
||||||
.println ("Factory creating disk : " + disk.getDisk ().getFile ().getAbsolutePath ());
|
"Factory creating disk : " + disk.getDisk ().getFile ().getAbsolutePath ());
|
||||||
|
|
||||||
if (disk != null && compressed)
|
if (disk != null && compressed)
|
||||||
disk.setOriginalPath (originalPath);
|
disk.setOriginalPath (originalPath);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -15,27 +15,21 @@ import com.bytezone.diskbrowser.utilities.DefaultAction;
|
||||||
public abstract class AbstractSaveAction extends DefaultAction
|
public abstract class AbstractSaveAction extends DefaultAction
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
private JFileChooser fileChooser;
|
protected JFileChooser fileChooser = new JFileChooser ();
|
||||||
private String dialogTitle;
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
public AbstractSaveAction (String menuText, String tip, String dialogTitle)
|
public AbstractSaveAction (String menuText, String tip, String dialogTitle)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (menuText, tip);
|
super (menuText, tip);
|
||||||
this.dialogTitle = dialogTitle;
|
|
||||||
|
fileChooser.setDialogTitle (dialogTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
void setSelectedFile (File file)
|
void setSelectedFile (File file)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
if (fileChooser == null)
|
|
||||||
{
|
|
||||||
fileChooser = new JFileChooser ();
|
|
||||||
fileChooser.setDialogTitle (dialogTitle);
|
|
||||||
}
|
|
||||||
|
|
||||||
fileChooser.setSelectedFile (file);
|
fileChooser.setSelectedFile (file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,26 +37,22 @@ public abstract class AbstractSaveAction extends DefaultAction
|
||||||
void saveBuffer (byte[] buffer)
|
void saveBuffer (byte[] buffer)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
if (fileChooser.showSaveDialog (null) != JFileChooser.APPROVE_OPTION)
|
|
||||||
return;
|
|
||||||
|
|
||||||
File file = fileChooser.getSelectedFile ();
|
File file = fileChooser.getSelectedFile ();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Files.write (file.toPath (), buffer, StandardOpenOption.CREATE_NEW);
|
Files.write (file.toPath (), buffer, StandardOpenOption.CREATE_NEW);
|
||||||
JOptionPane.showMessageDialog (null,
|
JOptionPane.showMessageDialog (null, String.format ("File %s saved", file.getName ()));
|
||||||
String.format ("File %s saved", file.getName ()));
|
|
||||||
}
|
}
|
||||||
catch (FileAlreadyExistsException e)
|
catch (FileAlreadyExistsException e)
|
||||||
{
|
{
|
||||||
JOptionPane.showMessageDialog (null, "File " + file.getName () + " already exists",
|
JOptionPane.showMessageDialog (null, "File " + file.getName () + " already exists", "Failed",
|
||||||
"Failed", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace ();
|
e.printStackTrace ();
|
||||||
JOptionPane.showMessageDialog (null, "File failed to save - " + e.getMessage (),
|
JOptionPane.showMessageDialog (null, "File failed to save - " + e.getMessage (), "Failed",
|
||||||
"Failed", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.bytezone.diskbrowser.gui;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.disk.AppleDisk;
|
import com.bytezone.diskbrowser.disk.AppleDisk;
|
||||||
|
@ -40,7 +41,9 @@ class SaveDiskAction extends AbstractSaveAction implements DiskSelectionListener
|
||||||
String suffix = blocks <= 560 ? ".dsk" : ".hdv";
|
String suffix = blocks <= 560 ? ".dsk" : ".hdv";
|
||||||
|
|
||||||
setSelectedFile (new File (formattedDisk.getName () + suffix));
|
setSelectedFile (new File (formattedDisk.getName () + suffix));
|
||||||
saveBuffer (appleDisk.getBuffer ());
|
|
||||||
|
if (fileChooser.showSaveDialog (null) == JFileChooser.APPROVE_OPTION)
|
||||||
|
saveBuffer (appleDisk.getBuffer ());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
System.out.println ("Not an AppleDisk"); // impossible
|
System.out.println ("Not an AppleDisk"); // impossible
|
||||||
|
|
|
@ -1,9 +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 javax.swing.Action;
|
||||||
|
import javax.swing.JCheckBox;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@ -12,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", "Save 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -31,8 +42,18 @@ class SaveFileAction extends AbstractSaveAction implements FileSelectionListener
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setSelectedFile (new File (appleFileSource.getUniqueName () + ".bin"));
|
if (formatted.isSelected ())
|
||||||
saveBuffer (appleFileSource.getDataSource ().getBuffer ());
|
setSelectedFile (new File (appleFileSource.getUniqueName () + ".txt"));
|
||||||
|
else
|
||||||
|
setSelectedFile (new File (appleFileSource.getUniqueName () + ".bin"));
|
||||||
|
|
||||||
|
if (fileChooser.showSaveDialog (null) != JFileChooser.APPROVE_OPTION)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (formatted.isSelected ())
|
||||||
|
saveBuffer (appleFileSource.getDataSource ().getText ().getBytes ());
|
||||||
|
else
|
||||||
|
saveBuffer (appleFileSource.getDataSource ().getBuffer ());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -41,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import java.awt.event.ActionEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
import com.bytezone.diskbrowser.disk.Disk;
|
import com.bytezone.diskbrowser.disk.Disk;
|
||||||
|
@ -41,7 +42,9 @@ class SaveSectorsAction extends AbstractSaveAction implements SectorSelectionLis
|
||||||
blocks.size () == 1 ? disk.readBlock (blocks.get (0)) : disk.readBlocks (blocks);
|
blocks.size () == 1 ? disk.readBlock (blocks.get (0)) : disk.readBlocks (blocks);
|
||||||
|
|
||||||
setSelectedFile (new File ("SavedSectors.bin"));
|
setSelectedFile (new File ("SavedSectors.bin"));
|
||||||
saveBuffer (buffer);
|
|
||||||
|
if (fileChooser.showSaveDialog (null) == JFileChooser.APPROVE_OPTION)
|
||||||
|
saveBuffer (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
|
|
@ -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
|
||||||
|
@ -43,13 +44,14 @@ public class Binary2
|
||||||
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -64,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 ();
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,9 @@ 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;
|
||||||
|
@ -89,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -117,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));
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,7 @@ import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
public 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;
|
||||||
|
@ -35,15 +34,6 @@ public 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);
|
||||||
|
|
|
@ -40,6 +40,7 @@ public class NuFX
|
||||||
{
|
{
|
||||||
buffer = Files.readAllBytes (path);
|
buffer = Files.readAllBytes (path);
|
||||||
volumeName = new VolumeName (path.getFileName ().toString ());
|
volumeName = new VolumeName (path.getFileName ().toString ());
|
||||||
|
|
||||||
read (buffer);
|
read (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +96,7 @@ public class NuFX
|
||||||
if (record.hasDisk ())
|
if (record.hasDisk ())
|
||||||
++totalDisks;
|
++totalDisks;
|
||||||
}
|
}
|
||||||
|
// System.out.println (toString ());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
|
|
@ -15,13 +15,12 @@ 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", "", "" };
|
||||||
|
@ -254,6 +253,13 @@ class Record
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
String getThreadFormatText ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
return threadFormats[getThreadFormat ()];
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
int getUncompressedSize ()
|
int getUncompressedSize ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -283,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 ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -313,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 () ? "+" : " ";
|
||||||
|
@ -323,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 ());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
|
125
src/com/bytezone/diskbrowser/nufx/Squeeze.java
Normal file
125
src/com/bytezone/diskbrowser/nufx/Squeeze.java
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
package com.bytezone.diskbrowser.nufx;
|
||||||
|
|
||||||
|
import com.bytezone.diskbrowser.utilities.FileFormatException;
|
||||||
|
import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
|
|
||||||
|
// see http://fileformats.archiveteam.org/wiki/Squeeze
|
||||||
|
// see http://fileformats.archiveteam.org/wiki/RLE90
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
|
public class Squeeze
|
||||||
|
// -----------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
private static final byte[] Squeeze = { 0x76, (byte) 0xFF };
|
||||||
|
private static int RLE_DELIMITER = 0x90;
|
||||||
|
private static int EOF_TOKEN = 0x100;
|
||||||
|
|
||||||
|
private int bits;
|
||||||
|
private int bitPos = 7; // trigger the first read
|
||||||
|
private int ptr;
|
||||||
|
private byte[] buffer;
|
||||||
|
private Node[] nodes;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
public byte[] unSqueeze (byte[] buffer)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
if (!Utility.isMagic (buffer, 0, Squeeze))
|
||||||
|
throw new FileFormatException ("Not Squeeze format");
|
||||||
|
|
||||||
|
byte[] uncompressed = new byte[buffer.length * 3];
|
||||||
|
int uncPtr = 0;
|
||||||
|
|
||||||
|
int fileChecksum = Utility.getShort (buffer, 2);
|
||||||
|
String fileName = Utility.getCString (buffer, 4);
|
||||||
|
|
||||||
|
ptr = fileName.length () + 5;
|
||||||
|
int nodeCount = Utility.getShort (buffer, ptr);
|
||||||
|
ptr += 2;
|
||||||
|
|
||||||
|
nodes = new Node[nodeCount];
|
||||||
|
this.buffer = buffer;
|
||||||
|
|
||||||
|
for (int i = 0; i < nodes.length; i++)
|
||||||
|
{
|
||||||
|
int left = Utility.getSignedShort (buffer, ptr);
|
||||||
|
int right = Utility.getSignedShort (buffer, ptr + 2);
|
||||||
|
nodes[i] = new Node (left, right);
|
||||||
|
ptr += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean repeating = false;
|
||||||
|
int lastVal = 0;
|
||||||
|
int sum = 0;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
int val = decodeSymbol ();
|
||||||
|
if (val == EOF_TOKEN)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (repeating)
|
||||||
|
{
|
||||||
|
repeating = false;
|
||||||
|
|
||||||
|
if (val == 0) // flag indicating a single RLE_DELIMITER
|
||||||
|
{
|
||||||
|
lastVal = RLE_DELIMITER;
|
||||||
|
val = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (--val != 0)
|
||||||
|
{
|
||||||
|
sum += lastVal;
|
||||||
|
uncompressed[uncPtr++] = (byte) lastVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (val == RLE_DELIMITER)
|
||||||
|
repeating = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastVal = val;
|
||||||
|
sum += lastVal;
|
||||||
|
uncompressed[uncPtr++] = (byte) lastVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((sum & 0xFFFF) != fileChecksum)
|
||||||
|
System.out.printf ("Checksum mismatch : %04X %04X%n", fileChecksum, sum & 0xFFFF);
|
||||||
|
|
||||||
|
byte[] uncompressedBuffer = new byte[uncPtr];
|
||||||
|
System.arraycopy (uncompressed, 0, uncompressedBuffer, 0, uncompressedBuffer.length);
|
||||||
|
|
||||||
|
return uncompressedBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
private int decodeSymbol ()
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
int val = 0;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (++bitPos > 7)
|
||||||
|
{
|
||||||
|
bits = buffer[ptr++];
|
||||||
|
bitPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = (bits & 1) == 0 ? nodes[val].left : nodes[val].right;
|
||||||
|
bits >>>= 1;
|
||||||
|
|
||||||
|
if (val < 0)
|
||||||
|
return -++val; // increment and make positive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
record Node (int left, int right)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package com.bytezone.diskbrowser.pascal;
|
package com.bytezone.diskbrowser.pascal;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.format.FormatStyle;
|
import java.time.format.FormatStyle;
|
||||||
|
@ -30,8 +29,8 @@ public class PascalDisk extends AbstractFormattedDisk
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
static final int CATALOG_ENTRY_SIZE = 26;
|
static final int CATALOG_ENTRY_SIZE = 26;
|
||||||
private final DateFormat df = DateFormat.getDateInstance (DateFormat.SHORT);
|
private final DateTimeFormatter dtf =
|
||||||
private final DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDate (FormatStyle.SHORT);
|
DateTimeFormatter.ofLocalizedDate (FormatStyle.SHORT);
|
||||||
private final VolumeEntry volumeEntry;
|
private final VolumeEntry volumeEntry;
|
||||||
private final PascalCatalogSector diskCatalogSector;
|
private final PascalCatalogSector diskCatalogSector;
|
||||||
|
|
||||||
|
@ -50,8 +49,8 @@ public class PascalDisk extends AbstractFormattedDisk
|
||||||
SectorType fotoSector = new SectorType ("Foto", Color.gray);
|
SectorType fotoSector = new SectorType ("Foto", Color.gray);
|
||||||
SectorType badSector = new SectorType ("Bad", Color.darkGray);
|
SectorType badSector = new SectorType ("Bad", Color.darkGray);
|
||||||
|
|
||||||
SectorType[] sectors = { catalogSector, badSector, codeSector, textSector, infoSector, dataSector,
|
SectorType[] sectors = { catalogSector, badSector, codeSector, textSector, infoSector,
|
||||||
grafSector, fotoSector };
|
dataSector, grafSector, fotoSector };
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
public PascalDisk (Disk disk)
|
public PascalDisk (Disk disk)
|
||||||
|
@ -102,7 +101,8 @@ public class PascalDisk extends AbstractFormattedDisk
|
||||||
freeBlocks.set (i, false);
|
freeBlocks.set (i, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
diskCatalogSector = new PascalCatalogSector (disk, disk.readBlocks (sectors), sectors);
|
diskCatalogSector =
|
||||||
|
new PascalCatalogSector (disk, disk.readBlocks (sectors), sectors);
|
||||||
|
|
||||||
// read the catalog
|
// read the catalog
|
||||||
List<DiskAddress> addresses = new ArrayList<> ();
|
List<DiskAddress> addresses = new ArrayList<> ();
|
||||||
|
@ -235,7 +235,6 @@ public class PascalDisk extends AbstractFormattedDisk
|
||||||
}
|
}
|
||||||
|
|
||||||
int lastByte = Utility.getShort (buffer, ptr + 22);
|
int lastByte = Utility.getShort (buffer, ptr + 22);
|
||||||
// GregorianCalendar date = Utility.getPascalDate (buffer, 24);
|
|
||||||
LocalDate localDate = Utility.getPascalLocalDate (buffer, 24);
|
LocalDate localDate = Utility.getPascalLocalDate (buffer, 24);
|
||||||
String dateString = localDate == null ? ""
|
String dateString = localDate == null ? ""
|
||||||
: localDate.format (DateTimeFormatter.ofLocalizedDate (FormatStyle.SHORT));
|
: localDate.format (DateTimeFormatter.ofLocalizedDate (FormatStyle.SHORT));
|
||||||
|
@ -300,16 +299,18 @@ public class PascalDisk extends AbstractFormattedDisk
|
||||||
{
|
{
|
||||||
String newLine = String.format ("%n");
|
String newLine = String.format ("%n");
|
||||||
String newLine2 = newLine + newLine;
|
String newLine2 = newLine + newLine;
|
||||||
String line =
|
String line = "---- --------------- ---- -------- ------- ---- ---- ----"
|
||||||
"---- --------------- ---- -------- ------- ---- ---- ----" + newLine;
|
+ newLine;
|
||||||
|
|
||||||
String date = volumeEntry.localDate == null ? "--" : volumeEntry.localDate.format (dtf);
|
String date =
|
||||||
|
volumeEntry.localDate == null ? "--" : volumeEntry.localDate.format (dtf);
|
||||||
|
|
||||||
StringBuilder text = new StringBuilder ();
|
StringBuilder text = new StringBuilder ();
|
||||||
text.append ("File : " + getDisplayPath () + newLine2);
|
text.append ("File : " + getDisplayPath () + newLine2);
|
||||||
text.append ("Volume : " + volumeEntry.name + newLine);
|
text.append ("Volume : " + volumeEntry.name + newLine);
|
||||||
text.append ("Date : " + date + newLine2);
|
text.append ("Date : " + date + newLine2);
|
||||||
text.append ("Blks Name Type Date Length Frst Last Blks\n");
|
text.append (
|
||||||
|
"Blks Name Type Date Length Frst Last Blks\n");
|
||||||
text.append (line);
|
text.append (line);
|
||||||
|
|
||||||
int usedBlocks = 6;
|
int usedBlocks = 6;
|
||||||
|
@ -322,15 +323,16 @@ public class PascalDisk extends AbstractFormattedDisk
|
||||||
date = ce.localDate == null ? "--" : ce.localDate.format (dtf);
|
date = ce.localDate == null ? "--" : ce.localDate.format (dtf);
|
||||||
|
|
||||||
int bytes = (size - 1) * 512 + ce.bytesUsedInLastBlock;
|
int bytes = (size - 1) * 512 + ce.bytesUsedInLastBlock;
|
||||||
String fileType =
|
String fileType = ce.fileType < 0 || ce.fileType >= fileTypes.length ? "????"
|
||||||
ce.fileType < 0 || ce.fileType >= fileTypes.length ? "????" : fileTypes[ce.fileType];
|
: fileTypes[ce.fileType];
|
||||||
text.append (String.format ("%4d %-15s %-6s %8s %,8d $%03X $%03X $%03X%n", size,
|
text.append (String.format ("%4d %-15s %-6s %8s %,8d $%03X $%03X $%03X%n",
|
||||||
ce.name, fileType, date, bytes, ce.firstBlock, ce.lastBlock, size));
|
size, ce.name, fileType, date, bytes, ce.firstBlock, ce.lastBlock, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
text.append (line);
|
text.append (line);
|
||||||
text.append (String.format ("Blocks free : %3d Blocks used : %3d Total blocks : %3d%n",
|
text.append (
|
||||||
(volumeEntry.totalBlocks - usedBlocks), usedBlocks, volumeEntry.totalBlocks));
|
String.format ("Blocks free : %3d Blocks used : %3d Total blocks : %3d%n",
|
||||||
|
(volumeEntry.totalBlocks - usedBlocks), usedBlocks, volumeEntry.totalBlocks));
|
||||||
|
|
||||||
return new DefaultAppleFileSource (volumeEntry.name, text.toString (), this);
|
return new DefaultAppleFileSource (volumeEntry.name, text.toString (), this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@ import com.bytezone.diskbrowser.utilities.Utility;
|
||||||
abstract class CatalogEntry implements AppleFileSource
|
abstract class CatalogEntry implements AppleFileSource
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
static String[] storageTypes =
|
static String[] storageTypes = { "Del", "Sdl", "Sap", "Tre", "Pas", "Ext", "", "", "",
|
||||||
{ "Del", "Sdl", "Sap", "Tre", "Pas", "Ext", "", "", "", "", "", "", "", "DIR", "SDH", "VDH" };
|
"", "", "", "", "DIR", "SDH", "VDH" };
|
||||||
Disk disk;
|
Disk disk;
|
||||||
ProdosDisk parentDisk;
|
ProdosDisk parentDisk;
|
||||||
|
|
||||||
|
|
|
@ -72,8 +72,8 @@ class FileEntry extends CatalogEntry implements ProdosConstants
|
||||||
private FileEntry link;
|
private FileEntry link;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
FileEntry (ProdosDisk fDisk, byte[] entryBuffer, DirectoryHeader parent, int parentBlock,
|
FileEntry (ProdosDisk fDisk, byte[] entryBuffer, DirectoryHeader parent,
|
||||||
int entryNo)
|
int parentBlock, int entryNo)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (fDisk, entryBuffer, parentBlock, entryNo);
|
super (fDisk, entryBuffer, parentBlock, entryNo);
|
||||||
|
@ -101,7 +101,6 @@ class FileEntry extends CatalogEntry implements ProdosConstants
|
||||||
|
|
||||||
case GSOS_EXTENDED_FILE:
|
case GSOS_EXTENDED_FILE:
|
||||||
readForks ();
|
readForks ();
|
||||||
// System.out.printf ("%s has forks%n", getUniqueName ());
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SUBDIRECTORY:
|
case SUBDIRECTORY:
|
||||||
|
@ -351,7 +350,8 @@ class FileEntry extends CatalogEntry implements ProdosConstants
|
||||||
file = new DoubleHiResImage (name, outBuffer);
|
file = new DoubleHiResImage (name, outBuffer);
|
||||||
break;
|
break;
|
||||||
case 0x8000:
|
case 0x8000:
|
||||||
file = new SHRPictureFile2 (name, outBuffer, FILE_TYPE_PIC, 0x2000, 0x8000);
|
file =
|
||||||
|
new SHRPictureFile2 (name, outBuffer, FILE_TYPE_PIC, 0x2000, 0x8000);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
file = new AssemblerProgram (name, exactBuffer, auxType);
|
file = new AssemblerProgram (name, exactBuffer, auxType);
|
||||||
|
@ -371,8 +371,8 @@ class FileEntry extends CatalogEntry implements ProdosConstants
|
||||||
}
|
}
|
||||||
// else if (name.endsWith (".PIC")) // 0091 X-BASIC../../XBASIC.PIC
|
// else if (name.endsWith (".PIC")) // 0091 X-BASIC../../XBASIC.PIC
|
||||||
// file = new SHRPictureFile2 (name, exactBuffer, fileType, auxType, endOfFile);
|
// file = new SHRPictureFile2 (name, exactBuffer, fileType, auxType, endOfFile);
|
||||||
else if ((name.equals ("DOS.3.3") || name.equals ("DDOS.3.3")) && endOfFile == 0x2800
|
else if ((name.equals ("DOS.3.3") || name.equals ("DDOS.3.3"))
|
||||||
&& DosMasterFile.isDos33 (parentDisk, exactBuffer))
|
&& endOfFile == 0x2800 && DosMasterFile.isDos33 (parentDisk, exactBuffer))
|
||||||
{
|
{
|
||||||
file = new DosMasterFile (name, exactBuffer);
|
file = new DosMasterFile (name, exactBuffer);
|
||||||
}
|
}
|
||||||
|
@ -415,8 +415,8 @@ class FileEntry extends CatalogEntry implements ProdosConstants
|
||||||
|
|
||||||
case FILE_TYPE_DIRECTORY:
|
case FILE_TYPE_DIRECTORY:
|
||||||
VolumeDirectoryHeader vdh = parentDisk.getVolumeDirectoryHeader ();
|
VolumeDirectoryHeader vdh = parentDisk.getVolumeDirectoryHeader ();
|
||||||
file = new ProdosDirectory (parentDisk, name, buffer, vdh.totalBlocks, vdh.freeBlocks,
|
file = new ProdosDirectory (parentDisk, name, buffer, vdh.totalBlocks,
|
||||||
vdh.usedBlocks);
|
vdh.freeBlocks, vdh.usedBlocks);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_TYPE_APPLESOFT_BASIC_VARS:
|
case FILE_TYPE_APPLESOFT_BASIC_VARS:
|
||||||
|
@ -549,6 +549,8 @@ class FileEntry extends CatalogEntry implements ProdosConstants
|
||||||
case FILE_TYPE_NON:
|
case FILE_TYPE_NON:
|
||||||
if (name.endsWith (".TIFF") && HiResImage.isTiff (exactBuffer))
|
if (name.endsWith (".TIFF") && HiResImage.isTiff (exactBuffer))
|
||||||
file = new OriginalHiResImage (name, exactBuffer, auxType);
|
file = new OriginalHiResImage (name, exactBuffer, auxType);
|
||||||
|
else if (name.endsWith (".JAVA"))
|
||||||
|
file = new BasicTextFile (name, exactBuffer, auxType, endOfFile);
|
||||||
else
|
else
|
||||||
file = new DefaultAppleFile (name, exactBuffer);
|
file = new DefaultAppleFile (name, exactBuffer);
|
||||||
break;
|
break;
|
||||||
|
@ -625,7 +627,8 @@ class FileEntry extends CatalogEntry implements ProdosConstants
|
||||||
if (addresses.size () > 0)
|
if (addresses.size () > 0)
|
||||||
{
|
{
|
||||||
byte[] tempBuffer = disk.readBlocks (addresses);
|
byte[] tempBuffer = disk.readBlocks (addresses);
|
||||||
buffers.add (new TextBuffer (tempBuffer, auxType, logicalBlock - addresses.size ()));
|
buffers.add (
|
||||||
|
new TextBuffer (tempBuffer, auxType, logicalBlock - addresses.size ()));
|
||||||
addresses.clear ();
|
addresses.clear ();
|
||||||
}
|
}
|
||||||
logicalBlock += 256;
|
logicalBlock += 256;
|
||||||
|
@ -725,8 +728,8 @@ class FileEntry extends CatalogEntry implements ProdosConstants
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
private int readIndexBlock (int indexBlock, List<DiskAddress> addresses, List<TextBuffer> buffers,
|
private int readIndexBlock (int indexBlock, List<DiskAddress> addresses,
|
||||||
int logicalBlock)
|
List<TextBuffer> buffers, int logicalBlock)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
byte[] indexBuffer = disk.readBlock (indexBlock);
|
byte[] indexBuffer = disk.readBlock (indexBlock);
|
||||||
|
@ -738,7 +741,8 @@ class FileEntry extends CatalogEntry implements ProdosConstants
|
||||||
else if (addresses.size () > 0)
|
else if (addresses.size () > 0)
|
||||||
{
|
{
|
||||||
byte[] tempBuffer = disk.readBlocks (addresses);
|
byte[] tempBuffer = disk.readBlocks (addresses);
|
||||||
buffers.add (new TextBuffer (tempBuffer, auxType, logicalBlock - addresses.size ()));
|
buffers
|
||||||
|
.add (new TextBuffer (tempBuffer, auxType, logicalBlock - addresses.size ()));
|
||||||
addresses.clear ();
|
addresses.clear ();
|
||||||
}
|
}
|
||||||
logicalBlock++;
|
logicalBlock++;
|
||||||
|
@ -809,13 +813,14 @@ class FileEntry extends CatalogEntry implements ProdosConstants
|
||||||
String locked = (access == 0x00) ? "*" : " ";
|
String locked = (access == 0x00) ? "*" : " ";
|
||||||
|
|
||||||
if (true)
|
if (true)
|
||||||
return String.format ("%s %03d %s", ProdosConstants.fileTypes[fileType], blocksUsed, locked)
|
return String.format ("%s %03d %s", ProdosConstants.fileTypes[fileType],
|
||||||
+ name;
|
blocksUsed, locked) + name;
|
||||||
|
|
||||||
String timeC = created == null ? "" : created.format (ProdosDisk.df);
|
String timeC = created == null ? "" : created.format (ProdosDisk.df);
|
||||||
String timeF = modified == null ? "" : modified.format (ProdosDisk.df);
|
String timeF = modified == null ? "" : modified.format (ProdosDisk.df);
|
||||||
|
|
||||||
return String.format ("%s %s%-30s %3d %,10d %15s %15s", ProdosConstants.fileTypes[fileType],
|
return String.format ("%s %s%-30s %3d %,10d %15s %15s",
|
||||||
locked, parentDirectory.name + "/" + name, blocksUsed, endOfFile, timeC, timeF);
|
ProdosConstants.fileTypes[fileType], locked, parentDirectory.name + "/" + name,
|
||||||
|
blocksUsed, endOfFile, timeC, timeF);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.swing.tree.DefaultMutableTreeNode;
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
import javax.swing.tree.DefaultTreeModel;
|
import javax.swing.tree.DefaultTreeModel;
|
||||||
|
@ -31,7 +32,8 @@ public class ProdosDisk extends AbstractFormattedDisk
|
||||||
{
|
{
|
||||||
static ProdosPreferences prodosPreferences; // set by MenuHandler
|
static ProdosPreferences prodosPreferences; // set by MenuHandler
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
final SectorType dosSector = new SectorType ("Bootstrap Loader", Color.lightGray);
|
final SectorType dosSector = new SectorType ("Bootstrap Loader", Color.lightGray);
|
||||||
|
|
|
@ -5,6 +5,10 @@ import static com.bytezone.diskbrowser.prodos.ProdosConstants.SAPLING;
|
||||||
import static com.bytezone.diskbrowser.prodos.ProdosConstants.SEEDLING;
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.SEEDLING;
|
||||||
import static com.bytezone.diskbrowser.prodos.ProdosConstants.TREE;
|
import static com.bytezone.diskbrowser.prodos.ProdosConstants.TREE;
|
||||||
|
|
||||||
|
// Assumptions:
|
||||||
|
// - file does not already exist
|
||||||
|
// - disk is not interleaved
|
||||||
|
// - blocks are 512 contiguous bytes
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
public class FileWriter
|
public class FileWriter
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
|
@ -37,8 +41,7 @@ public class FileWriter
|
||||||
|
|
||||||
while (dataPtr < this.eof)
|
while (dataPtr < this.eof)
|
||||||
{
|
{
|
||||||
int actualBlockNo = allocateNextBlock ();
|
int actualBlockNo = register (dataPtr / BLOCK_SIZE);
|
||||||
map (dataPtr / BLOCK_SIZE, actualBlockNo);
|
|
||||||
|
|
||||||
int bufferPtr = actualBlockNo * BLOCK_SIZE;
|
int bufferPtr = actualBlockNo * BLOCK_SIZE;
|
||||||
int transfer = Math.min (remaining, BLOCK_SIZE);
|
int transfer = Math.min (remaining, BLOCK_SIZE);
|
||||||
|
@ -53,8 +56,7 @@ public class FileWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
void writeRecord (int recordNo, byte[] dataBuffer, int recordLength)
|
void writeRecord (int recordNo, byte[] dataBuffer, int recordLength) throws DiskFullException
|
||||||
throws DiskFullException
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
assert recordLength > 0;
|
assert recordLength > 0;
|
||||||
|
@ -98,33 +100,23 @@ public class FileWriter
|
||||||
private int getActualBlockNo (int logicalBlockNo) throws DiskFullException
|
private int getActualBlockNo (int logicalBlockNo) throws DiskFullException
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
int actualBlockNo = 0;
|
|
||||||
|
|
||||||
switch (storageType)
|
switch (storageType)
|
||||||
{
|
{
|
||||||
case TREE:
|
case TREE:
|
||||||
actualBlockNo = masterIndexBlock.get (logicalBlockNo / 0x100)
|
return masterIndexBlock.get (logicalBlockNo / 0x100).getPosition (logicalBlockNo % 0x100);
|
||||||
.getPosition (logicalBlockNo % 0x100);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SAPLING:
|
case SAPLING:
|
||||||
if (logicalBlockNo < 0x100)
|
if (logicalBlockNo < 0x100)
|
||||||
actualBlockNo = indexBlock.getPosition (logicalBlockNo);
|
return indexBlock.getPosition (logicalBlockNo);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SEEDLING:
|
case SEEDLING:
|
||||||
if (logicalBlockNo == 0)
|
if (logicalBlockNo == 0)
|
||||||
actualBlockNo = keyPointer;
|
return keyPointer;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actualBlockNo == 0)
|
return register (logicalBlockNo);
|
||||||
{
|
|
||||||
actualBlockNo = allocateNextBlock ();
|
|
||||||
map (logicalBlockNo, actualBlockNo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return actualBlockNo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -138,14 +130,17 @@ public class FileWriter
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
private void map (int logicalBlockNo, int actualBlockNo) throws DiskFullException
|
private int register (int logicalBlockNo) throws DiskFullException
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
|
int nextBlockNo = allocateNextBlock ();
|
||||||
|
|
||||||
if (logicalBlockNo >= 0x100) // potential TREE
|
if (logicalBlockNo >= 0x100) // potential TREE
|
||||||
{
|
{
|
||||||
if (storageType != TREE)
|
if (storageType != TREE)
|
||||||
{
|
{
|
||||||
masterIndexBlock = new MasterIndexBlock (allocateNextBlock ());
|
masterIndexBlock = new MasterIndexBlock (nextBlockNo);
|
||||||
|
nextBlockNo = allocateNextBlock ();
|
||||||
|
|
||||||
if (storageType == SAPLING) // sapling -> tree
|
if (storageType == SAPLING) // sapling -> tree
|
||||||
{
|
{
|
||||||
|
@ -153,7 +148,9 @@ public class FileWriter
|
||||||
}
|
}
|
||||||
else if (storageType == SEEDLING) // seedling -> sapling -> tree
|
else if (storageType == SEEDLING) // seedling -> sapling -> tree
|
||||||
{
|
{
|
||||||
indexBlock = new IndexBlock (allocateNextBlock ());
|
indexBlock = new IndexBlock (nextBlockNo);
|
||||||
|
nextBlockNo = allocateNextBlock ();
|
||||||
|
|
||||||
indexBlock.setPosition (0, keyPointer);
|
indexBlock.setPosition (0, keyPointer);
|
||||||
masterIndexBlock.set (0, indexBlock);
|
masterIndexBlock.set (0, indexBlock);
|
||||||
}
|
}
|
||||||
|
@ -163,48 +160,51 @@ public class FileWriter
|
||||||
indexBlock = null;
|
indexBlock = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getIndexBlock (logicalBlockNo / 0x100).setPosition (logicalBlockNo % 0x100,
|
getIndexBlock (logicalBlockNo / 0x100).setPosition (logicalBlockNo % 0x100, nextBlockNo);
|
||||||
actualBlockNo);
|
|
||||||
}
|
}
|
||||||
else if (logicalBlockNo > 0) // potential SAPLING
|
else if (logicalBlockNo > 0) // potential SAPLING
|
||||||
{
|
{
|
||||||
if (storageType == TREE) // already a tree
|
if (storageType == TREE) // already a tree
|
||||||
{
|
{
|
||||||
getIndexBlock (0).setPosition (logicalBlockNo, actualBlockNo);
|
getIndexBlock (0).setPosition (logicalBlockNo, nextBlockNo);
|
||||||
}
|
}
|
||||||
else if (storageType == SAPLING) // already a sapling
|
else if (storageType == SAPLING) // already a sapling
|
||||||
{
|
{
|
||||||
indexBlock.setPosition (logicalBlockNo, actualBlockNo);
|
indexBlock.setPosition (logicalBlockNo, nextBlockNo);
|
||||||
}
|
}
|
||||||
else // new file or already a seedling
|
else // new file or already a seedling
|
||||||
{
|
{
|
||||||
indexBlock = new IndexBlock (allocateNextBlock ());
|
indexBlock = new IndexBlock (nextBlockNo);
|
||||||
|
nextBlockNo = allocateNextBlock ();
|
||||||
|
|
||||||
if (storageType == SEEDLING) // seedling -> sapling
|
if (storageType == SEEDLING) // seedling -> sapling
|
||||||
indexBlock.setPosition (0, keyPointer);
|
indexBlock.setPosition (0, keyPointer);
|
||||||
|
|
||||||
keyPointer = indexBlock.blockNo;
|
keyPointer = indexBlock.blockNo;
|
||||||
storageType = SAPLING;
|
storageType = SAPLING;
|
||||||
indexBlock.setPosition (logicalBlockNo, actualBlockNo);
|
indexBlock.setPosition (logicalBlockNo, nextBlockNo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (logicalBlockNo == 0) // potential SEEDLING
|
else if (logicalBlockNo == 0) // potential SEEDLING
|
||||||
{
|
{
|
||||||
if (storageType == TREE) // already a tree
|
if (storageType == TREE) // already a tree
|
||||||
{
|
{
|
||||||
getIndexBlock (0).setPosition (0, actualBlockNo);
|
getIndexBlock (0).setPosition (0, nextBlockNo);
|
||||||
}
|
}
|
||||||
else if (storageType == SAPLING) // already a sapling
|
else if (storageType == SAPLING) // already a sapling
|
||||||
{
|
{
|
||||||
indexBlock.setPosition (0, actualBlockNo);
|
indexBlock.setPosition (0, nextBlockNo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
keyPointer = actualBlockNo;
|
keyPointer = nextBlockNo;
|
||||||
storageType = SEEDLING;
|
storageType = SEEDLING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
System.out.println ("Error: " + logicalBlockNo);
|
System.out.println ("Error: " + logicalBlockNo);
|
||||||
|
|
||||||
|
return nextBlockNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.bytezone.diskbrowser.utilities;
|
package com.bytezone.diskbrowser.utilities;
|
||||||
|
|
||||||
|
import java.time.DateTimeException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
@ -7,12 +8,11 @@ import java.time.format.DateTimeFormatter;
|
||||||
public class DateTime
|
public class DateTime
|
||||||
// -----------------------------------------------------------------------------------//
|
// -----------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
private static String[] months = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
|
private static String[] months =
|
||||||
"Aug", "Sep", "Oct", "Nov", "Dec" };
|
{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||||
private static String[] days = { "", "Sunday", "Monday", "Tuesday", "Wednesday",
|
private static String[] days =
|
||||||
"Thursday", "Friday", "Saturday" };
|
{ "", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
|
||||||
private static final DateTimeFormatter dtf =
|
private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern ("dd-LLL-yy HH:mm");
|
||||||
DateTimeFormatter.ofPattern ("dd-LLL-yy HH:mm");
|
|
||||||
|
|
||||||
private final int second;
|
private final int second;
|
||||||
private final int minute;
|
private final int minute;
|
||||||
|
@ -40,8 +40,8 @@ public class DateTime
|
||||||
public String format ()
|
public String format ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
return String.format ("%02d:%02d:%02d %s %d %s %d", hour, minute, second,
|
return String.format ("%02d:%02d:%02d %s %d %s %d", hour, minute, second, days[weekDay], day,
|
||||||
days[weekDay], day, months[month], year);
|
months[month], year);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -56,10 +56,15 @@ public class DateTime
|
||||||
public LocalDateTime getLocalDateTime ()
|
public LocalDateTime getLocalDateTime ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
int adjustedYear = year + (year > 70 ? 1900 : 2000);
|
try
|
||||||
if (day < 0 || day > 30)
|
{
|
||||||
|
int adjustedYear = year + (year > 70 ? 1900 : 2000);
|
||||||
|
return LocalDateTime.of (adjustedYear, month + 1, day + 1, hour, minute);
|
||||||
|
}
|
||||||
|
catch (DateTimeException e)
|
||||||
|
{
|
||||||
return null;
|
return null;
|
||||||
return LocalDateTime.of (adjustedYear, month + 1, day + 1, hour, minute);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -67,8 +72,7 @@ public class DateTime
|
||||||
public String toString ()
|
public String toString ()
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
return "DateTime [second=" + second + ", minute=" + minute + ", hour=" + hour
|
return "DateTime [second=" + second + ", minute=" + minute + ", hour=" + hour + ", year=" + year
|
||||||
+ ", year=" + year + ", day=" + day + ", month=" + month + ", weekDay=" + weekDay
|
+ ", day=" + day + ", month=" + month + ", weekDay=" + weekDay + "]";
|
||||||
+ "]";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,6 +17,7 @@ public abstract class DefaultAction extends AbstractAction
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (text);
|
super (text);
|
||||||
|
|
||||||
this.baseURL = null;
|
this.baseURL = null;
|
||||||
putValue (Action.SHORT_DESCRIPTION, tip);
|
putValue (Action.SHORT_DESCRIPTION, tip);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +27,7 @@ public abstract class DefaultAction extends AbstractAction
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
super (text);
|
super (text);
|
||||||
|
|
||||||
this.baseURL = baseURL;
|
this.baseURL = baseURL;
|
||||||
putValue (Action.SHORT_DESCRIPTION, tip);
|
putValue (Action.SHORT_DESCRIPTION, tip);
|
||||||
}
|
}
|
||||||
|
@ -39,6 +41,7 @@ public abstract class DefaultAction extends AbstractAction
|
||||||
System.out.println ("Base URL not set");
|
System.out.println ("Base URL not set");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
URL url = this.getClass ().getResource (baseURL + iconName);
|
URL url = this.getClass ().getResource (baseURL + iconName);
|
||||||
if (url != null)
|
if (url != null)
|
||||||
putValue (iconType, new ImageIcon (url));
|
putValue (iconType, new ImageIcon (url));
|
||||||
|
|
|
@ -40,8 +40,8 @@ public final class Utility
|
||||||
private static MathContext mathContext4 = new MathContext (6);
|
private static MathContext mathContext4 = new MathContext (6);
|
||||||
private static MathContext mathContext8 = new MathContext (15);
|
private static MathContext mathContext8 = new MathContext (15);
|
||||||
|
|
||||||
private static final List<String> suffixes = Arrays.asList ("po", "dsk", "do", "hdv", "2mg",
|
private static final List<String> suffixes = Arrays.asList ("po", "dsk", "do", "hdv",
|
||||||
"d13", "sdk", "shk", "bxy", "bny", "woz", "img", "dimg");
|
"2mg", "d13", "sdk", "shk", "bxy", "bny", "bqy", "woz", "img", "dimg");
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
private Utility ()
|
private Utility ()
|
||||||
|
@ -255,7 +255,8 @@ public final class Utility
|
||||||
}
|
}
|
||||||
catch (DateTimeException e)
|
catch (DateTimeException e)
|
||||||
{
|
{
|
||||||
System.out.printf ("Bad date/time: %d %d %d %d %d %n", year, month, day, hour, minute);
|
System.out.printf ("Bad date/time: %d %d %d %d %d %n", year, month, day, hour,
|
||||||
|
minute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +316,8 @@ public final class Utility
|
||||||
public static int readTriple (byte[] buffer, int ptr)
|
public static int readTriple (byte[] buffer, int ptr)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
return (buffer[ptr] & 0xFF) | (buffer[ptr + 1] & 0xFF) << 8 | (buffer[ptr + 2] & 0xFF) << 16;
|
return (buffer[ptr] & 0xFF) | (buffer[ptr + 1] & 0xFF) << 8
|
||||||
|
| (buffer[ptr + 2] & 0xFF) << 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -384,8 +386,8 @@ public final class Utility
|
||||||
if (exponent == 0)
|
if (exponent == 0)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|
||||||
int mantissa =
|
int mantissa = (buffer[ptr + 2] & 0x7F) << 16 | (buffer[ptr + 1] & 0xFF) << 8
|
||||||
(buffer[ptr + 2] & 0x7F) << 16 | (buffer[ptr + 1] & 0xFF) << 8 | (buffer[ptr] & 0xFF);
|
| (buffer[ptr] & 0xFF);
|
||||||
boolean negative = (buffer[ptr + 2] & 0x80) != 0;
|
boolean negative = (buffer[ptr + 2] & 0x80) != 0;
|
||||||
double value = 0.5;
|
double value = 0.5;
|
||||||
|
|
||||||
|
@ -408,9 +410,10 @@ public final class Utility
|
||||||
if (exponent == 0)
|
if (exponent == 0)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|
||||||
long mantissa = (long) (buffer[ptr + 6] & 0x7F) << 48 | (long) (buffer[ptr + 5] & 0xFF) << 40
|
long mantissa = (long) (buffer[ptr + 6] & 0x7F) << 48
|
||||||
| (long) (buffer[ptr + 4] & 0xFF) << 32 | (long) (buffer[ptr + 3] & 0xFF) << 24
|
| (long) (buffer[ptr + 5] & 0xFF) << 40 | (long) (buffer[ptr + 4] & 0xFF) << 32
|
||||||
| (buffer[ptr + 2] & 0xFF) << 16 | (buffer[ptr + 1] & 0xFF) << 8 | (buffer[ptr] & 0xFF);
|
| (long) (buffer[ptr + 3] & 0xFF) << 24 | (buffer[ptr + 2] & 0xFF) << 16
|
||||||
|
| (buffer[ptr + 1] & 0xFF) << 8 | (buffer[ptr] & 0xFF);
|
||||||
boolean negative = (buffer[ptr + 6] & 0x80) != 0;
|
boolean negative = (buffer[ptr + 6] & 0x80) != 0;
|
||||||
double value = 0.5;
|
double value = 0.5;
|
||||||
|
|
||||||
|
@ -454,6 +457,19 @@ public final class Utility
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
public static String getCString (byte[] buffer, int offset)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
int length = 0;
|
||||||
|
int ptr = offset;
|
||||||
|
|
||||||
|
while (buffer[ptr++] != 0)
|
||||||
|
++length;
|
||||||
|
|
||||||
|
return new String (buffer, offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
public static int getWizLong (byte[] buffer, int offset)
|
public static int getWizLong (byte[] buffer, int offset)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -507,11 +523,13 @@ public final class Utility
|
||||||
int[] val = new int[6];
|
int[] val = new int[6];
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
val[i] = Integer.parseInt (String.format ("%02X", buffer[ptr + i] & 0xFF));
|
val[i] = Integer.parseInt (String.format ("%02X", buffer[ptr + i] & 0xFF));
|
||||||
|
// val[i] = buffer[ptr + i] & 0xFF;
|
||||||
|
|
||||||
LocalDateTime date = LocalDateTime.of (val[3] + 2000, val[5], val[4], val[2], val[1], val[0]);
|
LocalDateTime date =
|
||||||
|
LocalDateTime.of (val[3] + 2000, val[5], val[4], val[2], val[1], val[0]);
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
catch (DateTimeException | NumberFormatException e)
|
catch (DateTimeException e)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -551,6 +569,23 @@ public final class Utility
|
||||||
return suffixes.contains (getSuffix (filename));
|
return suffixes.contains (getSuffix (filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
public static String getShortPath (String path)
|
||||||
|
// ---------------------------------------------------------------------------------//
|
||||||
|
{
|
||||||
|
String home = System.getProperty ("user.home");
|
||||||
|
if (path.startsWith (home))
|
||||||
|
path = "~" + path.substring (home.length ());
|
||||||
|
else if (path.startsWith ("/Volumes/"))
|
||||||
|
{
|
||||||
|
int pos = path.indexOf (home);
|
||||||
|
if (pos > 0)
|
||||||
|
path = "~" + path.substring (home.length () + pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
public static void reverse (byte[] buffer)
|
public static void reverse (byte[] buffer)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
@ -599,7 +634,8 @@ public final class Utility
|
||||||
public static boolean isPossibleVariable (byte value)
|
public static boolean isPossibleVariable (byte value)
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
{
|
{
|
||||||
return isDigit (value) || isLetter (value) || value == ASCII_DOLLAR || value == ASCII_PERCENT;
|
return isDigit (value) || isLetter (value) || value == ASCII_DOLLAR
|
||||||
|
|| value == ASCII_PERCENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------//
|
// ---------------------------------------------------------------------------------//
|
||||||
|
|
Loading…
Reference in New Issue
Block a user