mirror of
https://github.com/badvision/jace.git
synced 2024-11-28 10:52:33 +00:00
Fixed bugs in the mass-storage implementation. Directories can be mounted via drag/drop, file information is now property reported including dates, and now large files >128k work correctly.
This commit is contained in:
parent
cf87f30e35
commit
4021af3ac6
@ -123,7 +123,7 @@ public class JaceUIController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (File f : files) {
|
for (File f : files) {
|
||||||
if (f.isFile()) return f;
|
if (f.exists()) return f;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,14 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Prodos directory node
|
* Prodos directory node
|
||||||
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
*
|
||||||
|
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
||||||
*/
|
*/
|
||||||
public class DirectoryNode extends DiskNode implements FileFilter {
|
public class DirectoryNode extends DiskNode implements FileFilter {
|
||||||
// public static int FILE_ENTRY_SIZE = 38;
|
// public static int FILE_ENTRY_SIZE = 38;
|
||||||
|
|
||||||
public static int FILE_ENTRY_SIZE = 0x027;
|
public static int FILE_ENTRY_SIZE = 0x027;
|
||||||
|
|
||||||
public DirectoryNode(ProdosVirtualDisk ownerFilesystem, File physicalDir, int baseBlock) throws IOException {
|
public DirectoryNode(ProdosVirtualDisk ownerFilesystem, File physicalDir, int baseBlock) throws IOException {
|
||||||
setBaseBlock(baseBlock);
|
setBaseBlock(baseBlock);
|
||||||
init(ownerFilesystem, physicalDir);
|
init(ownerFilesystem, physicalDir);
|
||||||
@ -44,7 +47,6 @@ public class DirectoryNode extends DiskNode implements FileFilter {
|
|||||||
init(ownerFilesystem, physicalDir);
|
init(ownerFilesystem, physicalDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void init(ProdosVirtualDisk ownerFilesystem, File physicalFile) throws IOException {
|
private void init(ProdosVirtualDisk ownerFilesystem, File physicalFile) throws IOException {
|
||||||
setPhysicalFile(physicalFile);
|
setPhysicalFile(physicalFile);
|
||||||
setType(EntryType.SUBDIRECTORY);
|
setType(EntryType.SUBDIRECTORY);
|
||||||
@ -78,7 +80,8 @@ public class DirectoryNode extends DiskNode implements FileFilter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
/**
|
/**
|
||||||
* Checks contents of subdirectory for changes as well as directory itself (super class)
|
* Checks contents of subdirectory for changes as well as directory itself
|
||||||
|
* (super class)
|
||||||
*/
|
*/
|
||||||
public boolean checkFile() throws IOException {
|
public boolean checkFile() throws IOException {
|
||||||
boolean success = true;
|
boolean success = true;
|
||||||
@ -90,7 +93,7 @@ public class DirectoryNode extends DiskNode implements FileFilter {
|
|||||||
for (File f : realFileList) {
|
for (File f : realFileList) {
|
||||||
realFiles.add(f.getName());
|
realFiles.add(f.getName());
|
||||||
}
|
}
|
||||||
for (Iterator<DiskNode> i = getChildren().iterator(); i.hasNext(); ) {
|
for (Iterator<DiskNode> i = getChildren().iterator(); i.hasNext();) {
|
||||||
DiskNode node = i.next();
|
DiskNode node = i.next();
|
||||||
if (realFiles.contains(node.getPhysicalFile().getName())) {
|
if (realFiles.contains(node.getPhysicalFile().getName())) {
|
||||||
realFiles.remove(node.getPhysicalFile().getName());
|
realFiles.remove(node.getPhysicalFile().getName());
|
||||||
@ -119,14 +122,15 @@ public class DirectoryNode extends DiskNode implements FileFilter {
|
|||||||
checkFile();
|
checkFile();
|
||||||
if (block == 0) {
|
if (block == 0) {
|
||||||
generateHeader(buffer);
|
generateHeader(buffer);
|
||||||
for (int i=0; i < 12 && i < children.size(); i++)
|
for (int i = 0; i < 12 && i < children.size(); i++) {
|
||||||
generateFileEntry(buffer, 4 + (i+1) * FILE_ENTRY_SIZE, i);
|
generateFileEntry(buffer, 4 + (i + 1) * FILE_ENTRY_SIZE, i);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
int start = (block * 13) - 1;
|
int start = (block * 13) - 1;
|
||||||
int end = start + 13;
|
int end = start + 13;
|
||||||
int offset = 4;
|
int offset = 4;
|
||||||
|
|
||||||
for (int i=start; i < end && i < children.size(); i++) {
|
for (int i = start; i < end && i < children.size(); i++) {
|
||||||
// TODO: Add any parts that are not file entries.
|
// TODO: Add any parts that are not file entries.
|
||||||
generateFileEntry(buffer, offset, i);
|
generateFileEntry(buffer, offset, i);
|
||||||
offset += FILE_ENTRY_SIZE;
|
offset += FILE_ENTRY_SIZE;
|
||||||
@ -136,7 +140,9 @@ public class DirectoryNode extends DiskNode implements FileFilter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean accept(File file) {
|
public boolean accept(File file) {
|
||||||
if (file.getName().endsWith("~")) return false;
|
if (file.getName().endsWith("~")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
char c = file.getName().charAt(0);
|
char c = file.getName().charAt(0);
|
||||||
if (c == '.' || c == '~') {
|
if (c == '.' || c == '~') {
|
||||||
return false;
|
return false;
|
||||||
@ -146,24 +152,27 @@ public class DirectoryNode extends DiskNode implements FileFilter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the directory header found in the base block of a directory
|
* Generate the directory header found in the base block of a directory
|
||||||
|
*
|
||||||
* @param buffer where to write data
|
* @param buffer where to write data
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("static-access")
|
@SuppressWarnings("static-access")
|
||||||
private void generateHeader(byte[] buffer) {
|
private void generateHeader(byte[] buffer) {
|
||||||
// System.out.println("Generating directory header");
|
// System.out.println("Generating directory header");
|
||||||
// Previous block = 0
|
// Previous block = 0
|
||||||
generateWord(buffer, 0,0);
|
generateWord(buffer, 0, 0);
|
||||||
// Next block
|
// Next block
|
||||||
int nextBlock = 0;
|
int nextBlock = 0;
|
||||||
if (!additionalNodes.isEmpty())
|
if (!additionalNodes.isEmpty()) {
|
||||||
nextBlock = additionalNodes.get(0).baseBlock;
|
nextBlock = additionalNodes.get(0).baseBlock;
|
||||||
|
}
|
||||||
generateWord(buffer, 0x02, nextBlock);
|
generateWord(buffer, 0x02, nextBlock);
|
||||||
// Directory header + name length
|
// Directory header + name length
|
||||||
// Volumme header = 0x0f0; Subdirectory header = 0x0e0
|
// Volumme header = 0x0f0; Subdirectory header = 0x0e0
|
||||||
buffer[4]= (byte) ((baseBlock == 0x02 ? 0x0f0 : 0x0E0) + getName().length());
|
buffer[4] = (byte) ((baseBlock == 0x02 ? 0x0f0 : 0x0E0) + getName().length());
|
||||||
generateName(buffer, 5, this);
|
generateName(buffer, 5, this);
|
||||||
for (int i=0x014 ; i <= 0x01b; i++)
|
for (int i = 0x014; i <= 0x01b; i++) {
|
||||||
buffer[i] = 0;
|
buffer[i] = 0;
|
||||||
|
}
|
||||||
generateTimestamp(buffer, 0x01c, getPhysicalFile().lastModified());
|
generateTimestamp(buffer, 0x01c, getPhysicalFile().lastModified());
|
||||||
// Prodos 1.9
|
// Prodos 1.9
|
||||||
buffer[0x020] = 0x019;
|
buffer[0x020] = 0x019;
|
||||||
@ -185,6 +194,7 @@ public class DirectoryNode extends DiskNode implements FileFilter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the entry of a directory
|
* Generate the entry of a directory
|
||||||
|
*
|
||||||
* @param buffer where to write data
|
* @param buffer where to write data
|
||||||
* @param offset starting offset in buffer to write
|
* @param offset starting offset in buffer to write
|
||||||
* @param fileNumber number of file (indexed in Children array) to write
|
* @param fileNumber number of file (indexed in Children array) to write
|
||||||
@ -192,17 +202,17 @@ public class DirectoryNode extends DiskNode implements FileFilter {
|
|||||||
private void generateFileEntry(byte[] buffer, int offset, int fileNumber) throws IOException {
|
private void generateFileEntry(byte[] buffer, int offset, int fileNumber) throws IOException {
|
||||||
// System.out.println("Generating entry for "+children.get(fileNumber).getName());
|
// System.out.println("Generating entry for "+children.get(fileNumber).getName());
|
||||||
DiskNode child = children.get(fileNumber);
|
DiskNode child = children.get(fileNumber);
|
||||||
|
child.allocate();
|
||||||
// Entry Type and length
|
// Entry Type and length
|
||||||
buffer[offset] = (byte) ((child.getType().code << 4) + child.getName().length());
|
buffer[offset] = (byte) ((child.getType().code << 4) + child.getName().length());
|
||||||
// Name
|
// Name
|
||||||
generateName(buffer, offset+1, child);
|
generateName(buffer, offset + 1, child);
|
||||||
// File type
|
// File type
|
||||||
buffer[offset + 0x010] = (byte) ((child instanceof DirectoryNode) ? 0x0f : ((FileNode) child).fileType);
|
buffer[offset + 0x010] = (byte) ((child instanceof DirectoryNode) ? 0x0f : ((FileNode) child).fileType);
|
||||||
// Key pointer
|
// Key pointer
|
||||||
generateWord(buffer, offset + 0x011, child.getBaseBlock());
|
generateWord(buffer, offset + 0x011, child.getBaseBlock());
|
||||||
// Blocks used -- will report only one unless file is actually allocated
|
// Blocks used -- will report only one unless file is actually allocated
|
||||||
// child.allocate();
|
generateWord(buffer, offset + 0x013, child.additionalNodes.size());
|
||||||
generateWord(buffer, offset + 0x013, 1 + child.additionalNodes.size());
|
|
||||||
// EOF
|
// EOF
|
||||||
// TODO: Verify this is the right thing to do -- is EOF total length or a modulo?
|
// TODO: Verify this is the right thing to do -- is EOF total length or a modulo?
|
||||||
int length = ((int) child.physicalFile.length()) & 0x0ffffff;
|
int length = ((int) child.physicalFile.length()) & 0x0ffffff;
|
||||||
@ -214,11 +224,12 @@ public class DirectoryNode extends DiskNode implements FileFilter {
|
|||||||
buffer[offset + 0x01c] = 0x19;
|
buffer[offset + 0x01c] = 0x19;
|
||||||
// Minimum version = 0
|
// Minimum version = 0
|
||||||
buffer[offset + 0x01d] = 0;
|
buffer[offset + 0x01d] = 0;
|
||||||
// Access = all granted
|
// Access = Read-only
|
||||||
buffer[offset + 0x01e] = (byte) 0x0ff;
|
buffer[offset + 0x01e] = (byte) 0x001;
|
||||||
// AUX type
|
// AUX type
|
||||||
if (child instanceof FileNode)
|
if (child instanceof FileNode) {
|
||||||
generateWord(buffer, offset + 0x01f, ((FileNode) child).loadAddress);
|
generateWord(buffer, offset + 0x01f, ((FileNode) child).loadAddress);
|
||||||
|
}
|
||||||
// Modification date
|
// Modification date
|
||||||
generateTimestamp(buffer, offset + 0x021, child.physicalFile.lastModified());
|
generateTimestamp(buffer, offset + 0x021, child.physicalFile.lastModified());
|
||||||
// Key pointer for directory
|
// Key pointer for directory
|
||||||
@ -231,26 +242,22 @@ public class DirectoryNode extends DiskNode implements FileFilter {
|
|||||||
|
|
||||||
// yyyyyyym mmmddddd - Byte 0,1
|
// yyyyyyym mmmddddd - Byte 0,1
|
||||||
// ---hhhhh --mmmmmm - Byte 2,3
|
// ---hhhhh --mmmmmm - Byte 2,3
|
||||||
// buffer[offset+1] = (byte) (((c.get(Calendar.YEAR) - 1990) << 1) + ((c.get(Calendar.MONTH)>> 3) & 1));
|
buffer[offset+1] = (byte) (((c.get(Calendar.YEAR) - 2000) << 1) | ((c.get(Calendar.MONTH)+1)>> 3));
|
||||||
buffer[offset+0] = 0;
|
|
||||||
buffer[offset+1] = 0;
|
|
||||||
buffer[offset+2] = 0;
|
|
||||||
buffer[offset+3] = 0;
|
|
||||||
// buffer[offset+2] = (byte) ((c.get(Calendar.MONTH)>> 3) & 1);
|
// buffer[offset+2] = (byte) ((c.get(Calendar.MONTH)>> 3) & 1);
|
||||||
// buffer[offset+3] = (byte) (((c.get(Calendar.MONTH)&7) + c.get(Calendar.DAY_OF_MONTH)) & 0x0ff);
|
buffer[offset+0] = (byte) (((((c.get(Calendar.MONTH)+1)&7)<<5) | c.get(Calendar.DAY_OF_MONTH)) & 0x0ff);
|
||||||
// buffer[offset+0] = (byte) c.get(Calendar.HOUR_OF_DAY);
|
buffer[offset+3] = (byte) c.get(Calendar.HOUR_OF_DAY);
|
||||||
// buffer[offset+1] = (byte) c.get(Calendar.MINUTE);
|
buffer[offset+2] = (byte) c.get(Calendar.MINUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateWord(byte[] buffer, int i, int value) {
|
private void generateWord(byte[] buffer, int i, int value) {
|
||||||
// Little endian format
|
// Little endian format
|
||||||
buffer[i] = (byte) (value & 0x0ff);
|
buffer[i] = (byte) (value & 0x0ff);
|
||||||
buffer[i+1] = (byte) ((value >> 8) & 0x0ff);
|
buffer[i + 1] = (byte) ((value >> 8) & 0x0ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateName(byte[] buffer, int offset, DiskNode node) {
|
private void generateName(byte[] buffer, int offset, DiskNode node) {
|
||||||
for (int i=0; i < node.getName().length(); i++) {
|
for (int i = 0; i < node.getName().length(); i++) {
|
||||||
buffer[offset+i] = (byte) node.getName().charAt(i);
|
buffer[offset + i] = (byte) node.getName().charAt(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ public abstract class DiskNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh() {
|
public void refresh() throws IOException {
|
||||||
ownerFilesystem.deallocateEntry(this);
|
ownerFilesystem.deallocateEntry(this);
|
||||||
doRefresh();
|
doRefresh();
|
||||||
allocationTime = System.currentTimeMillis();
|
allocationTime = System.currentTimeMillis();
|
||||||
|
@ -21,6 +21,7 @@ package jace.hardware.massStorage;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of a prodos file with a known file type and having a known
|
* Representation of a prodos file with a known file type and having a known
|
||||||
@ -81,16 +82,18 @@ public class FileNode extends DiskNode {
|
|||||||
} else if (fileSize <= SAPLING_MAX_SIZE) {
|
} else if (fileSize <= SAPLING_MAX_SIZE) {
|
||||||
setType(EntryType.SAPLING);
|
setType(EntryType.SAPLING);
|
||||||
return EntryType.SAPLING;
|
return EntryType.SAPLING;
|
||||||
|
} else {
|
||||||
|
setType(EntryType.TREE);
|
||||||
|
return EntryType.TREE;
|
||||||
}
|
}
|
||||||
setType(EntryType.TREE);
|
|
||||||
return EntryType.TREE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
String[] parts = name.split("\\.");
|
String[] parts = name.replaceAll("[^A-Za-z0-9]", ".").split("\\.");
|
||||||
FileType t = null;
|
FileType t = FileType.UNKNOWN;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
String prodosName = name;
|
||||||
if (parts.length > 1) {
|
if (parts.length > 1) {
|
||||||
String extension = parts[parts.length - 1].toUpperCase();
|
String extension = parts[parts.length - 1].toUpperCase();
|
||||||
String[] extParts = extension.split("#");
|
String[] extParts = extension.split("#");
|
||||||
@ -103,17 +106,14 @@ public class FileNode extends DiskNode {
|
|||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
System.out.println("Not sure what extension " + extension + " is!");
|
System.out.println("Not sure what extension " + extension + " is!");
|
||||||
}
|
}
|
||||||
name = "";
|
prodosName = "";
|
||||||
for (int i = 0; i < parts.length - 1; i++) {
|
for (int i = 0; i < parts.length - 1; i++) {
|
||||||
name += (i > 0 ? "." + parts[i] : parts[i]);
|
prodosName += (i > 0 ? "." + parts[i] : parts[i]);
|
||||||
}
|
}
|
||||||
if (extParts[extParts.length - 1].equals("SYSTEM")) {
|
if (extParts[extParts.length - 1].equals("SYSTEM")) {
|
||||||
name += ".SYSTEM";
|
prodosName += ".SYSTEM";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (t == null) {
|
|
||||||
t = FileType.UNKNOWN;
|
|
||||||
}
|
|
||||||
if (offset == 0) {
|
if (offset == 0) {
|
||||||
offset = t.defaultLoadAddress;
|
offset = t.defaultLoadAddress;
|
||||||
}
|
}
|
||||||
@ -121,12 +121,13 @@ public class FileNode extends DiskNode {
|
|||||||
loadAddress = offset;
|
loadAddress = offset;
|
||||||
|
|
||||||
// Pass usable name (stripped of file extension and other type info) as name
|
// Pass usable name (stripped of file extension and other type info) as name
|
||||||
super.setName(name);
|
super.setName(prodosName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileNode(ProdosVirtualDisk ownerFilesystem, File file) throws IOException {
|
public FileNode(ProdosVirtualDisk ownerFilesystem, File file) throws IOException {
|
||||||
setOwnerFilesystem(ownerFilesystem);
|
setOwnerFilesystem(ownerFilesystem);
|
||||||
setPhysicalFile(file);
|
setPhysicalFile(file);
|
||||||
|
setName(file.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -135,16 +136,19 @@ public class FileNode extends DiskNode {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doAllocate() throws IOException {
|
public void doAllocate() throws IOException {
|
||||||
int dataBlocks = (int) ((getPhysicalFile().length() / ProdosVirtualDisk.BLOCK_SIZE) + 1);
|
int dataBlocks = (int) ((getPhysicalFile().length()+ProdosVirtualDisk.BLOCK_SIZE-1) / ProdosVirtualDisk.BLOCK_SIZE);
|
||||||
int treeBlocks;
|
int treeBlocks =(((dataBlocks * 2) + (ProdosVirtualDisk.BLOCK_SIZE-2)) / ProdosVirtualDisk.BLOCK_SIZE);
|
||||||
if (dataBlocks > 1 && dataBlocks < 257) {
|
if (treeBlocks > 1) treeBlocks++;
|
||||||
treeBlocks = 1;
|
// if (dataBlocks > 1 && (dataBlocks*2) < ProdosVirtualDisk.BLOCK_SIZE) {
|
||||||
} else {
|
// treeBlocks = 1;
|
||||||
treeBlocks = 1 + (dataBlocks / 256);
|
// } else {
|
||||||
}
|
// treeBlocks = 1 + (dataBlocks * 2 / ProdosVirtualDisk.BLOCK_SIZE);
|
||||||
for (int i = 1; i < dataBlocks + treeBlocks; i++) {
|
// }
|
||||||
SubNode subNode = new SubNode(i, this);
|
System.out.println("Allocating "+(dataBlocks + treeBlocks)+" blocks for file "+getName()+"; data "+dataBlocks+"; tree "+treeBlocks);
|
||||||
|
for (int i = 0; i < dataBlocks + treeBlocks; i++) {
|
||||||
|
new SubNode(i, this);
|
||||||
}
|
}
|
||||||
|
setBaseBlock(additionalNodes.get(0).getBaseBlock());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -154,6 +158,9 @@ public class FileNode extends DiskNode {
|
|||||||
@Override
|
@Override
|
||||||
public void readBlock(int block, byte[] buffer) throws IOException {
|
public void readBlock(int block, byte[] buffer) throws IOException {
|
||||||
// System.out.println("Read block "+block+" of file "+getName());
|
// System.out.println("Read block "+block+" of file "+getName());
|
||||||
|
int dataBlocks = (int) ((getPhysicalFile().length()+ProdosVirtualDisk.BLOCK_SIZE-1) / ProdosVirtualDisk.BLOCK_SIZE);
|
||||||
|
int treeBlocks =(((dataBlocks * 2) + (ProdosVirtualDisk.BLOCK_SIZE-2)) / ProdosVirtualDisk.BLOCK_SIZE);
|
||||||
|
if (treeBlocks > 1) treeBlocks++;
|
||||||
switch (this.getType()) {
|
switch (this.getType()) {
|
||||||
case SEEDLING:
|
case SEEDLING:
|
||||||
readFile(buffer, 0);
|
readFile(buffer, 0);
|
||||||
@ -163,20 +170,20 @@ public class FileNode extends DiskNode {
|
|||||||
readFile(buffer, (block - 1));
|
readFile(buffer, (block - 1));
|
||||||
} else {
|
} else {
|
||||||
// Generate seedling index block
|
// Generate seedling index block
|
||||||
generateIndex(buffer, 0, 256);
|
generateIndex(buffer, 0, dataBlocks);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TREE:
|
case TREE:
|
||||||
int dataBlocks = (int) ((getPhysicalFile().length() / ProdosVirtualDisk.BLOCK_SIZE) + 1);
|
|
||||||
int treeBlocks = (dataBlocks / 256);
|
|
||||||
if (block == 0) {
|
if (block == 0) {
|
||||||
generateIndex(buffer, 0, treeBlocks);
|
System.out.println("Reading index for "+getName());
|
||||||
} else if (block < treeBlocks) {
|
generateIndex(buffer, 1, treeBlocks);
|
||||||
int start = treeBlocks + (block - 1 * 256);
|
} else if (block <= treeBlocks) {
|
||||||
int end = Math.min(start + 256, treeBlocks);
|
System.out.println("Reading tree block "+block+" for "+getName());
|
||||||
generateIndex(buffer, treeBlocks, end);
|
int start = treeBlocks + ((block - 1) * 256);
|
||||||
|
int end = treeBlocks + dataBlocks;
|
||||||
|
generateIndex(buffer, start, end);
|
||||||
} else {
|
} else {
|
||||||
readFile(buffer, (block - treeBlocks));
|
readFile(buffer, (block - treeBlocks - 1));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -190,10 +197,22 @@ public class FileNode extends DiskNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateIndex(byte[] buffer, int indexStart, int indexLimit) {
|
private void generateIndex(byte[] buffer, int indexStart, int indexLimit) {
|
||||||
int pos = 0;
|
System.out.println("Index block contents:");
|
||||||
for (int i = indexStart; pos < 256 && i < indexLimit && i < additionalNodes.size(); i++, pos++) {
|
Arrays.fill(buffer, (byte) 0);
|
||||||
buffer[pos] = (byte) (additionalNodes.get(i).baseBlock & 0x0ff);
|
for (int i = indexStart, count=0; count < 256 && i < indexLimit && i < additionalNodes.size(); i++, count++) {
|
||||||
buffer[pos + 256] = (byte) ((additionalNodes.get(i).baseBlock >> 8) & 0x0ff);
|
int base = additionalNodes.get(i).baseBlock;
|
||||||
|
System.out.print(Integer.toHexString(base)+":");
|
||||||
|
buffer[count] = (byte) (base & 0x0ff);
|
||||||
|
buffer[count + 256] = (byte) (base >> 8);
|
||||||
}
|
}
|
||||||
|
System.out.println();
|
||||||
|
for (int i=0; i < 256; i++) {
|
||||||
|
System.out.printf("%02X ",buffer[i]&0x0ff);
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
for (int i=256; i < 512; i++) {
|
||||||
|
System.out.printf("%02X ",buffer[i]&0x0ff);
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -38,7 +38,7 @@ import java.util.logging.Logger;
|
|||||||
* is a folder and not a disk image. FreespaceBitmap and the various Node
|
* is a folder and not a disk image. FreespaceBitmap and the various Node
|
||||||
* classes are used to represent the filesystem structure.
|
* classes are used to represent the filesystem structure.
|
||||||
*
|
*
|
||||||
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
||||||
*/
|
*/
|
||||||
public class ProdosVirtualDisk implements IDisk {
|
public class ProdosVirtualDisk implements IDisk {
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ public class ProdosVirtualDisk implements IDisk {
|
|||||||
DiskNode node = physicalMap.get(block);
|
DiskNode node = physicalMap.get(block);
|
||||||
Arrays.fill(ioBuffer, (byte) (block & 0x0ff));
|
Arrays.fill(ioBuffer, (byte) (block & 0x0ff));
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
System.out.println("Reading unknown block?!");
|
System.out.println("Reading unknown block " + Integer.toHexString(block));
|
||||||
for (int i = 0; i < BLOCK_SIZE; i++) {
|
for (int i = 0; i < BLOCK_SIZE; i++) {
|
||||||
memory.write(bufferAddress + i, (byte) 0, false, false);
|
memory.write(bufferAddress + i, (byte) 0, false, false);
|
||||||
}
|
}
|
||||||
@ -132,11 +132,15 @@ public class ProdosVirtualDisk implements IDisk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mark space occupied by node
|
// Mark space occupied by node
|
||||||
public void allocateEntry(DiskNode node) {
|
public void allocateEntry(DiskNode node) throws IOException {
|
||||||
physicalMap.put(node.baseBlock, node);
|
physicalMap.put(node.baseBlock, node);
|
||||||
node.additionalNodes.stream().forEach((sub) -> {
|
|
||||||
physicalMap.put(sub.getBaseBlock(), sub);
|
for (DiskNode subnode : node.additionalNodes) {
|
||||||
});
|
int blockNum = getNextFreeBlock();
|
||||||
|
System.out.println("Allocating block " + Integer.toHexString(blockNum) + " for " + subnode.getName());
|
||||||
|
subnode.setBaseBlock(blockNum);
|
||||||
|
physicalMap.put(blockNum, subnode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark space occupied by nodes as free (remove allocation mapping)
|
// Mark space occupied by nodes as free (remove allocation mapping)
|
||||||
@ -145,11 +149,11 @@ public class ProdosVirtualDisk implements IDisk {
|
|||||||
if (physicalMap.get(node.baseBlock) != null && physicalMap.get(node.baseBlock).equals(node)) {
|
if (physicalMap.get(node.baseBlock) != null && physicalMap.get(node.baseBlock).equals(node)) {
|
||||||
physicalMap.remove(node.baseBlock);
|
physicalMap.remove(node.baseBlock);
|
||||||
}
|
}
|
||||||
node.additionalNodes.stream().filter((sub) ->
|
node.additionalNodes.stream().filter((sub)
|
||||||
(physicalMap.get(sub.getBaseBlock()) != null && physicalMap.get(sub.baseBlock).equals(sub))).
|
-> (physicalMap.get(sub.getBaseBlock()) != null && physicalMap.get(sub.baseBlock).equals(sub))).
|
||||||
forEach((sub) -> {
|
forEach((sub) -> {
|
||||||
physicalMap.remove(sub.getBaseBlock());
|
physicalMap.remove(sub.getBaseBlock());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is the specified block in use?
|
// Is the specified block in use?
|
||||||
@ -200,7 +204,6 @@ public class ProdosVirtualDisk implements IDisk {
|
|||||||
freespaceBitmap = new FreespaceBitmap(this, FREESPACE_BITMAP_START);
|
freespaceBitmap = new FreespaceBitmap(this, FREESPACE_BITMAP_START);
|
||||||
allocateEntry(freespaceBitmap);
|
allocateEntry(freespaceBitmap);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -31,7 +31,6 @@ import java.io.IOException;
|
|||||||
public class SubNode extends DiskNode {
|
public class SubNode extends DiskNode {
|
||||||
|
|
||||||
int sequenceNumber;
|
int sequenceNumber;
|
||||||
private int seq;
|
|
||||||
|
|
||||||
public SubNode(int seq, DiskNode parent) throws IOException {
|
public SubNode(int seq, DiskNode parent) throws IOException {
|
||||||
init(seq, parent);
|
init(seq, parent);
|
||||||
@ -49,6 +48,11 @@ public class SubNode extends DiskNode {
|
|||||||
parent.additionalNodes.add(this);
|
parent.additionalNodes.add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return parent.getName() + "; block "+sequenceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doDeallocate() {
|
public void doDeallocate() {
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ public enum DiskType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static public DiskType determineType(File file) {
|
static public DiskType determineType(File file) {
|
||||||
if (!file.exists()) return null;
|
if (file == null || !file.exists()) return null;
|
||||||
if (file.isDirectory()) return VIRTUAL;
|
if (file.isDirectory()) return VIRTUAL;
|
||||||
if (file.getName().toLowerCase().endsWith("hdv")) {
|
if (file.getName().toLowerCase().endsWith("hdv")) {
|
||||||
return LARGE;
|
return LARGE;
|
||||||
|
Loading…
Reference in New Issue
Block a user