This commit is contained in:
Denis Molony
2017-02-02 08:15:30 +11:00
parent adf22d8894
commit 286a7d5d98
7 changed files with 150 additions and 166 deletions

View File

@@ -359,13 +359,33 @@ public abstract class HiResImage extends AbstractFile
return true;
}
// http://www.daubnet.com/en/file-format-bmp
public static boolean isBmp (byte[] buffer)
{
if (buffer.length < 2)
if (buffer.length < 26)
return false;
String text = new String (buffer, 0, 2);
return text.equals ("BM");
int size = HexFormatter.unsignedLong (buffer, 2);
if (false)
{
int empty = HexFormatter.unsignedLong (buffer, 6);
int offset = HexFormatter.unsignedLong (buffer, 10);
int header = HexFormatter.unsignedLong (buffer, 14);
int width = HexFormatter.unsignedLong (buffer, 18);
int height = HexFormatter.unsignedLong (buffer, 22);
System.out.println (buffer.length);
System.out.println (size);
System.out.println (empty);
System.out.println (offset);
System.out.println (header);
System.out.println (width);
System.out.println (height);
}
return text.equals ("BM") && size <= buffer.length;
}
public static PaletteFactory getPaletteFactory ()
@@ -408,7 +428,7 @@ public abstract class HiResImage extends AbstractFile
StringBuilder text = new StringBuilder ();
text.append (String.format (" %X", id));
text.append (String.format ("%02X", id));
for (int i = 0; i < 16; i++)
text.append (String.format (" %04X", entries[i].value));

View File

@@ -7,6 +7,7 @@ public class MerlinSource extends AbstractFile
private static int TAB_POS = tabs[2];
private final int recordLength;
private final int eof;
private boolean prodosFile;
// Source : Prodos text file
public MerlinSource (String name, byte[] buffer, int recordLength, int eof)
@@ -14,6 +15,7 @@ public class MerlinSource extends AbstractFile
super (name, buffer);
this.eof = eof;
this.recordLength = recordLength;
prodosFile = true;
}
// Source : Dos binary file
@@ -29,14 +31,14 @@ public class MerlinSource extends AbstractFile
{
StringBuilder text = new StringBuilder ();
text.append ("Name : " + name + "\n");
if (recordLength > 0) // a prodos text file
text.append ("Merlin source : " + name + "\n");
if (prodosFile)
{
text.append (String.format ("Record length : %,8d%n", recordLength));
text.append (String.format ("End of file : %,8d%n", eof));
text.append (String.format ("EOF (aux) : %,8d%n", eof));
}
else
text.append (String.format ("End of file : %,8d%n", buffer.length));
text.append (String.format ("Buffer size : %,8d%n", buffer.length));
text.append ("\n");
ptr = 0;

View File

@@ -4,6 +4,7 @@ import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Map;
@@ -42,7 +43,6 @@ public class QuickDrawFont extends AbstractFile
private final int totalCharacters;
private final String[] imageLines;
private final byte[] bitImage;
private final byte[] locationTable;
private final byte[] offsetWidthTable;
@@ -51,6 +51,8 @@ public class QuickDrawFont extends AbstractFile
private final int locationTableOffset;
private final int offsetWidthTableOffset;
private final BitSet[] strike;
public QuickDrawFont (String name, byte[] buffer, int fileType, int auxType)
{
super (name, buffer);
@@ -99,18 +101,13 @@ public class QuickDrawFont extends AbstractFile
totalCharacters = lastChar - firstChar + 2; // includes missing character
bitImage = new byte[rowWords * 2 * fRectHeight]; // should use java bits
strike = new BitSet[fRectHeight];
for (int i = 0; i < fRectHeight; i++)
strike[i] = new BitSet (rowWords * 16);
locationTable = new byte[(totalCharacters + 1) * 2];
offsetWidthTable = new byte[(totalCharacters + 1) * 2];
if (false)
{
System.out.printf ("Buffer length : %d%n", buffer.length);
System.out.printf ("Total chars : %d%n", totalCharacters);
System.out.printf ("owtable offset : %d%n", offsetWidthTableOffset);
System.out.printf ("owtable size : %d%n", offsetWidthTable.length);
}
if (offsetWidthTableOffset + offsetWidthTable.length > buffer.length)
{
System.out.println ("*********** Bad ow length");
@@ -118,27 +115,24 @@ public class QuickDrawFont extends AbstractFile
return;
}
System.arraycopy (buffer, bitImageOffset, bitImage, 0, bitImage.length);
// convert image data to bitset
int rowLenBits = rowWords * 16; // # bits in each row
int rowLenBytes = rowWords * 2; // # bytes in each row
for (int row = 0; row < fRectHeight; row++) // for each row
for (int j = 0; j < rowLenBits; j++) // for each bit in the row
{
int b = buffer[bitImageOffset + row * rowLenBytes + j / 8] & 0xFF;
strike[row].set (j, ((b & (0x80 >>> (j % 8))) != 0));
}
System.arraycopy (buffer, locationTableOffset, locationTable, 0,
locationTable.length);
System.arraycopy (buffer, offsetWidthTableOffset, offsetWidthTable, 0,
offsetWidthTable.length);
for (int i = 0; i < fRectHeight; i++)
{
int rowOffset = i * rowWords * 2;
StringBuilder bits = new StringBuilder ();
for (int j = rowOffset; j < rowOffset + rowWords * 2; j++)
bits.append (HexFormatter.getBitString (bitImage[j]));
imageLines[i] = bits.toString ().replaceAll ("1", "#");
}
for (int i = 0, max = totalCharacters + 1; i < max; i++)
{
int location = HexFormatter.unsignedShort (locationTable, i * 2);
// int offset = offsetWidthTable[i * 2] & 0xFF;
// int width = offsetWidthTable[i * 2 + 1] & 0xFF;
int j = i + 1;
if (j < max)
@@ -157,45 +151,41 @@ public class QuickDrawFont extends AbstractFile
}
}
if (true)
int base = 10;
int spacing = 5;
int charsWide = (int) (Math.sqrt (totalCharacters) + .5);
int charsHigh = (totalCharacters - 1) / charsWide + 1;
image = new BufferedImage (charsWide * (widMax + spacing) + base * 2,
charsHigh * (fRectHeight + spacing) + base * 2, BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g2d = image.createGraphics ();
g2d.setComposite (AlphaComposite.getInstance (AlphaComposite.SRC_OVER, (float) 1.0));
int x = base;
int y = base;
int count = 0;
for (int i = 0; i < totalCharacters + 1; i++)
{
int base = 10;
int spacing = 5;
Character character;
if (characters.containsKey (i))
character = characters.get (i);
else
character = characters.get (lastChar + 1);
int charsWide = (int) (Math.sqrt (totalCharacters) + .5);
int charsHigh = (totalCharacters - 1) / charsWide + 1;
if (character != null)
g2d.drawImage (character.image, x, y, null);
image = new BufferedImage (charsWide * (widMax + spacing) + base * 2,
charsHigh * (fRectHeight + spacing) + base * 2, BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g2d = image.createGraphics ();
g2d.setComposite (
AlphaComposite.getInstance (AlphaComposite.SRC_OVER, (float) 1.0));
int x = base;
int y = base;
int count = 0;
for (int i = 0; i < totalCharacters + 1; i++)
x += widMax + spacing;
if (++count % charsWide == 0)
{
Character character;
if (characters.containsKey (i))
character = characters.get (i);
else
character = characters.get (lastChar + 1);
if (character != null)
g2d.drawImage (character.image, x, y, null);
x += widMax + spacing;
if (++count % charsWide == 0)
{
x = base;
y += fRectHeight + spacing;
}
x = base;
y += fRectHeight + spacing;
}
g2d.dispose ();
}
g2d.dispose ();
}
@Override
@@ -248,52 +238,6 @@ public class QuickDrawFont extends AbstractFile
text.append (String.format (
"Char %3d, location %,5d, pixelWidth %2d. offset %,5d, width %,5d%n", i,
location, pixelWidth, offset, width));
if (pixelWidth > 0 && location + pixelWidth < imageLines[0].length ())
for (int j = 0; j < fRectHeight; j++)
{
for (int w = 0; w < offset; w++)
text.append (' ');
text.append (imageLines[j].substring (location, location + pixelWidth));
text.append ("\n");
}
}
if (false)
{
text.append ("\n\n");
for (int i = 0; i < fRectHeight; i++)
{
text.append (String.format ("Row: %d%n", i));
int rowOffset = i * rowWords * 2;
String line = HexFormatter.format (bitImage, rowOffset, rowWords * 2,
bitImageOffset + rowOffset);
text.append (line);
text.append ("\n\n");
}
text.append ("\n\n");
text.append (HexFormatter.format (locationTable, 0, locationTable.length,
locationTableOffset));
text.append ("\n\n");
text.append (HexFormatter.format (offsetWidthTable, 0, offsetWidthTable.length,
offsetWidthTableOffset));
text.append ("\n\n");
for (int i = 0; i < totalCharacters; i++)
{
int location = HexFormatter.unsignedShort (locationTable, i * 2);
text.append (String.format ("%3d %04X %,7d%n", i, location, location));
}
text.append ("\n\n");
for (int i = 0; i < totalCharacters; i++)
{
int offset = offsetWidthTable[i * 2] & 0xFF;
int width = offsetWidthTable[i * 2 + 1] & 0xFF;
text.append (String.format ("%3d %02X %02X%n", i, offset, width));
}
}
return text.toString ();
@@ -302,30 +246,16 @@ public class QuickDrawFont extends AbstractFile
class Character
{
private final BufferedImage image;
private final int location;
private final int pixelWidth;
// offset - where to start drawing relative to current pen location
// width - how far to move the current pen location after drawing
// location - index into imageLines[]
// pixelWidth - number of pixels to copy from imageLines[]
public Character (int location, int pixelWidth)
public Character (int offset, int width)
{
this.location = location;
this.pixelWidth = pixelWidth;
image = new BufferedImage (pixelWidth, fRectHeight, BufferedImage.TYPE_BYTE_GRAY);
image = new BufferedImage (width, fRectHeight, BufferedImage.TYPE_BYTE_GRAY);
DataBuffer dataBuffer = image.getRaster ().getDataBuffer ();
if (pixelWidth > 0 && location + pixelWidth < imageLines[0].length ())
for (int i = 0; i < fRectHeight; i++)
{
int element = i * pixelWidth; // start of row
String row = imageLines[i].substring (location, location + pixelWidth);
for (char c : row.toCharArray ())
dataBuffer.setElem (element++, c == '.' ? 0 : 255);
}
int element = 0;
for (int row = 0; row < fRectHeight; row++)
for (int j = offset; j < offset + width; j++)
dataBuffer.setElem (element++, strike[row].get (j) ? 255 : 0);
}
}
}

View File

@@ -4,11 +4,12 @@ import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import com.bytezone.diskbrowser.prodos.ProdosConstants;
import com.bytezone.diskbrowser.utilities.HexFormatter;
public class SHRPictureFile2 extends HiResImage
{
ColorTable[] colorTables;
byte[] scb;
byte[] scb; // 0xC1 aux=0
public SHRPictureFile2 (String name, byte[] buffer, int fileType, int auxType, int eof)
{
@@ -36,7 +37,7 @@ public class SHRPictureFile2 extends HiResImage
auxType = 0;
}
if (auxType == 0)
if (auxType == 0) // 32,768
{
scb = new byte[200];
System.arraycopy (buffer, 32000, scb, 0, scb.length);
@@ -49,7 +50,7 @@ public class SHRPictureFile2 extends HiResImage
{
System.out.println ("0xC1 aux 1 not written");
}
else if (auxType == 2) // Brooks
else if (auxType == 2) // Brooks 38,400
{
colorTables = new ColorTable[200];
for (int i = 0; i < colorTables.length; i++)
@@ -118,11 +119,27 @@ public class SHRPictureFile2 extends HiResImage
}
if (colorTables != null)
{
text.append ("Color Table\n\n #");
for (int i = 0; i < 16; i++)
text.append (String.format (" %02X ", i));
text.append ("\n--");
for (int i = 0; i < 16; i++)
text.append (" ----");
text.append ("\n");
for (ColorTable colorTable : colorTables)
{
text.append (colorTable);
text.append ("\n\n");
text.append (colorTable.toLine ());
text.append ("\n");
}
}
text.append ("\nScreen lines\n\n");
for (int i = 0; i < 200; i++)
{
text.append (HexFormatter.format (buffer, i * 160, 160));
text.append ("\n\n");
}
text.deleteCharAt (text.length () - 1);
text.deleteCharAt (text.length () - 1);

View File

@@ -6,28 +6,31 @@ import com.bytezone.diskbrowser.utilities.HexFormatter;
public class TextFile extends AbstractFile
{
private int recordLength;
private List<TextBuffer> buffers; // only used if it is a Prodos text file
private int recordLength; // prodos aux
private List<TextBuffer> buffers; // only used if it is a Prodos text file
private int eof;
private boolean prodosFile;
public TextFile (String name, byte[] buffer)
{
super (name, buffer);
}
public TextFile (String name, byte[] buffer, int recordLength, int eof)
public TextFile (String name, byte[] buffer, int auxType, int eof)
{
this (name, buffer);
this.eof = eof;
this.recordLength = recordLength;
recordLength = auxType;
prodosFile = true;
}
public TextFile (String name, List<TextBuffer> buffers, int recordLength, int eof)
public TextFile (String name, List<TextBuffer> buffers, int auxType, int eof)
{
super (name, null);
this.buffers = buffers;
this.eof = eof;
this.recordLength = recordLength;
recordLength = auxType;
prodosFile = true;
}
@Override
@@ -54,7 +57,7 @@ public class TextFile extends AbstractFile
StringBuilder text = new StringBuilder ();
text.append ("Name : " + name + "\n");
if (recordLength > 0) // a prodos text file
if (prodosFile)
{
text.append (String.format ("Record length : %,8d%n", recordLength));
text.append (String.format ("End of file : %,8d%n", eof));
@@ -72,7 +75,8 @@ public class TextFile extends AbstractFile
return unknownLength (text);
text.append ("Offset Record Text values\n");
text.append ("------ ------- -------------------------------------------------------\n");
text.append (
"------ ------- -------------------------------------------------------\n");
return knownLength (text, 0).toString ();
}
@@ -102,7 +106,7 @@ public class TextFile extends AbstractFile
bytes--;
text.append (String.format ("%,6d %,8d %s%n", ptr, recNo++,
HexFormatter.getString (buffer, ptr, bytes)));
HexFormatter.getString (buffer, ptr, bytes)));
}
return text;
}
@@ -119,7 +123,7 @@ public class TextFile extends AbstractFile
{
text.append ("Offset Text values\n");
text.append ("------ -------------------------------------------------------"
+ "-------------------\n");
+ "-------------------\n");
if (size == 0)
return text.toString ();

View File

@@ -205,8 +205,12 @@ abstract class AbstractCatalogEntry implements AppleFileSource
appleFile = new ShapeTable (name, exactBuffer);
else if (name.endsWith (".S"))
appleFile = new MerlinSource (name, exactBuffer);
else if (HiResImage.isGif (exactBuffer))
else if (HiResImage.isGif (exactBuffer)) // buffer?
appleFile = new OriginalHiResImage (name, exactBuffer, loadAddress);
else if (HiResImage.isPng (exactBuffer)) // buffer?
appleFile = new OriginalHiResImage (name, exactBuffer, loadAddress);
else if (name.endsWith (".BMP") && HiResImage.isBmp (buffer))
appleFile = new OriginalHiResImage (name, buffer, loadAddress);
else if (name.endsWith (".PAC"))
appleFile = new DoubleHiResImage (name, exactBuffer);
else if (link != null)

View File

@@ -242,22 +242,8 @@ class FileEntry extends CatalogEntry implements ProdosConstants
return file;
}
/*
* Text files with reclen > 0 are random access, possibly with gaps between
* records, so they need to be handled separately.
*/
if (fileType == FILE_TYPE_TEXT && auxType > 0)
{
switch (storageType)
{
case TYPE_TREE:
return getTreeTextFile ();
case TYPE_SAPLING:
return getSaplingTextFile ();
case TYPE_SEEDLING:
return getSeedlingTextFile ();
}
}
if (fileType == FILE_TYPE_TEXT && auxType > 0) // random access file
return getRandomAccessTextFile ();
byte[] buffer = isGEOSFile () ? getGEOSBuffer () : getBuffer ();
byte[] exactBuffer = getExactBuffer (buffer);
@@ -410,6 +396,25 @@ class FileEntry extends CatalogEntry implements ProdosConstants
return exactBuffer;
}
private DataSource getRandomAccessTextFile ()
{
// Text files with aux (reclen) > 0 are random access, possibly with
// non-contiguous records, so they need to be handled differently
switch (storageType)
{
case TYPE_TREE:
return getTreeTextFile ();
case TYPE_SAPLING:
return getSaplingTextFile ();
case TYPE_SEEDLING:
return getSeedlingTextFile ();
default:
System.out.println ("Impossible: text file: " + storageType);
return null;
}
}
private DataSource getTreeTextFile ()
{
List<TextBuffer> buffers = new ArrayList<TextBuffer> ();
@@ -477,11 +482,9 @@ class FileEntry extends CatalogEntry implements ProdosConstants
case TYPE_SAPLING:
case TYPE_TREE:
return disk.readSectors (dataBlocks);
case TYPE_GSOS_EXTENDED_FILE:
// this will return the data fork and the resource fork concatenated
return disk.readSectors (dataBlocks);
case TYPE_SUBDIRECTORY:
byte[] fullBuffer = new byte[dataBlocks.size () * BLOCK_ENTRY_SIZE]; // 39 * 13 = 507
byte[] fullBuffer = new byte[dataBlocks.size () * BLOCK_ENTRY_SIZE];
int offset = 0;
for (DiskAddress da : dataBlocks)
{
@@ -490,6 +493,10 @@ class FileEntry extends CatalogEntry implements ProdosConstants
offset += BLOCK_ENTRY_SIZE;
}
return fullBuffer;
case TYPE_GSOS_EXTENDED_FILE:
return disk.readSectors (dataBlocks); // data and resource forks concatenated
default:
System.out.println ("Unknown storage type in getBuffer : " + storageType);
return new byte[512];
@@ -501,7 +508,7 @@ class FileEntry extends CatalogEntry implements ProdosConstants
switch (storageType)
{
case TYPE_SEEDLING:
System.out.println ("Seedling GEOS file : " + name); // not sure if this is possible
System.out.println ("Seedling GEOS file : " + name); // not sure if possible
return disk.readSectors (dataBlocks);
case TYPE_SAPLING:
return getIndexFile (keyPtr);