mirror of https://github.com/badvision/jace.git
200 lines
6.6 KiB
Java
200 lines
6.6 KiB
Java
/*
|
|
* Copyright (C) 2012 Brendan Robert (BLuRry) brendan.robert@gmail.com.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301 USA
|
|
*/
|
|
package jace.hardware.massStorage;
|
|
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.IOException;
|
|
|
|
/**
|
|
* Representation of a prodos file with a known file type and having a known
|
|
* size (either seedling, sapling or tree)
|
|
*
|
|
* @author Brendan Robert (BLuRry) brendan.robert@gmail.com
|
|
*/
|
|
public class FileNode extends DiskNode {
|
|
|
|
public enum FileType {
|
|
|
|
UNKNOWN(0x00, 0x0000),
|
|
ADB(0x019, 0x0000),
|
|
AWP(0x01a, 0x0000),
|
|
ASP(0x01b, 0x0000),
|
|
BAD(0x01, 0x0000),
|
|
BIN(0x06, 0x0300),
|
|
CLASS(0xED, 0x0000),
|
|
BAS(0xfc, 0x0801),
|
|
CMD(0x0f0, 0x0000),
|
|
INT(0xfa, 0x0801),
|
|
IVR(0xfb, 0x0000),
|
|
PAS(0xef, 0x0000),
|
|
REL(0x0Fe, 0x0000),
|
|
SHK(0x0e0, 0x08002),
|
|
SDK(0x0e0, 0x08002),
|
|
SYS(0x0ff, 0x02000),
|
|
SYSTEM(0x0ff, 0x02000),
|
|
TXT(0x04, 0x0000),
|
|
U01(0x0f1, 0x0000),
|
|
U02(0x0f2, 0x0000),
|
|
U03(0x0f3, 0x0000),
|
|
U04(0x0f4, 0x0000),
|
|
U05(0x0f5, 0x0000),
|
|
U06(0x0f6, 0x0000),
|
|
U07(0x0f7, 0x0000),
|
|
U08(0x0f8, 0x0000),
|
|
VAR(0x0FD, 0x0000);
|
|
public int code = 0;
|
|
public int defaultLoadAddress = 0;
|
|
|
|
FileType(int code, int addr) {
|
|
this.code = code;
|
|
this.defaultLoadAddress = addr;
|
|
}
|
|
}
|
|
public int fileType = 0x00;
|
|
public int loadAddress = 0x00;
|
|
public static int SEEDLING_MAX_SIZE = ProdosVirtualDisk.BLOCK_SIZE;
|
|
public static int SAPLING_MAX_SIZE = ProdosVirtualDisk.BLOCK_SIZE * 128;
|
|
|
|
@Override
|
|
public EntryType getType() {
|
|
long fileSize = getPhysicalFile().length();
|
|
if (fileSize <= SEEDLING_MAX_SIZE) {
|
|
setType(EntryType.SEEDLING);
|
|
return EntryType.SEEDLING;
|
|
} else if (fileSize <= SAPLING_MAX_SIZE) {
|
|
setType(EntryType.SAPLING);
|
|
return EntryType.SAPLING;
|
|
}
|
|
setType(EntryType.TREE);
|
|
return EntryType.TREE;
|
|
}
|
|
|
|
@Override
|
|
public void setName(String name) {
|
|
String[] parts = name.split("\\.");
|
|
FileType t = null;
|
|
int offset = 0;
|
|
if (parts.length > 1) {
|
|
String extension = parts[parts.length - 1].toUpperCase();
|
|
String[] extParts = extension.split("#");
|
|
if (extParts.length == 2) {
|
|
offset = Integer.parseInt(extParts[1], 16);
|
|
extension = extParts[0];
|
|
}
|
|
try {
|
|
t = FileType.valueOf(extension);
|
|
} catch (IllegalArgumentException ex) {
|
|
System.out.println("Not sure what extension " + extension + " is!");
|
|
}
|
|
name = "";
|
|
for (int i = 0; i < parts.length - 1; i++) {
|
|
name += (i > 0 ? "." + parts[i] : parts[i]);
|
|
}
|
|
if (extParts[extParts.length - 1].equals("SYSTEM")) {
|
|
name += ".SYSTEM";
|
|
}
|
|
}
|
|
if (t == null) {
|
|
t = FileType.UNKNOWN;
|
|
}
|
|
if (offset == 0) {
|
|
offset = t.defaultLoadAddress;
|
|
}
|
|
fileType = t.code;
|
|
loadAddress = offset;
|
|
|
|
// Pass usable name (stripped of file extension and other type info) as name
|
|
super.setName(name);
|
|
}
|
|
|
|
public FileNode(ProdosVirtualDisk ownerFilesystem, File file) throws IOException {
|
|
setOwnerFilesystem(ownerFilesystem);
|
|
setPhysicalFile(file);
|
|
}
|
|
|
|
@Override
|
|
public void doDeallocate() {
|
|
}
|
|
|
|
@Override
|
|
public void doAllocate() throws IOException {
|
|
int dataBlocks = (int) ((getPhysicalFile().length() / ProdosVirtualDisk.BLOCK_SIZE) + 1);
|
|
int treeBlocks = 0;
|
|
if (dataBlocks > 1 && dataBlocks < 257) {
|
|
treeBlocks = 1;
|
|
} else {
|
|
treeBlocks = 1 + (dataBlocks / 256);
|
|
}
|
|
for (int i = 1; i < dataBlocks + treeBlocks; i++) {
|
|
new SubNode(i, this);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void doRefresh() {
|
|
}
|
|
|
|
@Override
|
|
public void readBlock(int block, byte[] buffer) throws IOException {
|
|
// System.out.println("Read block "+block+" of file "+getName());
|
|
switch (this.getType()) {
|
|
case SEEDLING:
|
|
readFile(buffer, 0);
|
|
break;
|
|
case SAPLING:
|
|
if (block > 0) {
|
|
readFile(buffer, (block - 1));
|
|
} else {
|
|
// Generate seedling index block
|
|
generateIndex(buffer, 0, 256);
|
|
}
|
|
break;
|
|
case TREE:
|
|
int dataBlocks = (int) ((getPhysicalFile().length() / ProdosVirtualDisk.BLOCK_SIZE) + 1);
|
|
int treeBlocks = (dataBlocks / 256);
|
|
if (block == 0) {
|
|
generateIndex(buffer, 0, treeBlocks);
|
|
} else if (block < treeBlocks) {
|
|
int start = treeBlocks + (block - 1 * 256);
|
|
int end = Math.min(start + 256, treeBlocks);
|
|
generateIndex(buffer, treeBlocks, end);
|
|
} else {
|
|
readFile(buffer, (block - treeBlocks));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void readFile(byte[] buffer, int start) throws IOException {
|
|
FileInputStream f = new FileInputStream(physicalFile);
|
|
f.skip(start * ProdosVirtualDisk.BLOCK_SIZE);
|
|
f.read(buffer, 0, ProdosVirtualDisk.BLOCK_SIZE);
|
|
f.close();
|
|
}
|
|
|
|
private void generateIndex(byte[] buffer, int indexStart, int indexLimit) {
|
|
int pos = 0;
|
|
for (int i = indexStart; pos < 256 && i < indexLimit && i < additionalNodes.size(); i++, pos++) {
|
|
buffer[pos] = (byte) (additionalNodes.get(i).baseBlock & 0x0ff);
|
|
buffer[pos + 256] = (byte) ((additionalNodes.get(i).baseBlock >> 8) & 0x0ff);
|
|
}
|
|
}
|
|
}
|