Created
October 24, 2011 20:57
-
-
Save johngirvin/1310270 to your computer and use it in GitHub Desktop.
Convert KryoFlux "i4" format dump files to DSK format images.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.BufferedInputStream; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileNotFoundException; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.util.ArrayList; | |
import java.util.List; | |
/** | |
* Convert KryoFlux "i4" format dump files to DSK format images. | |
* | |
* Usage: | |
* java KryoFluxDisk [options] [i4_dump_file] [i4_dump_file]... | |
* | |
* Output files are created as the same name as the input files | |
* except with ".dsk" extension. | |
* | |
* Options: | |
* -d create output files in DATA format (default) | |
* -s create output files in SYSTEM format | |
* | |
* Suggested KryoFlux command line to create suitable dump files: | |
* dtc -fdisk_i4_s0.bin -g0 -e39 -l8 -i4 | |
* | |
* @author John Girvin | |
*/ | |
public class KryoFluxDisk { | |
/** | |
* Convert KryoFlux "i4" format dump to DSK. | |
* | |
* @note | |
* Basic implementation. Supports only single sided, 40 track | |
* dumps with 9 x 512 byte sectors per track in non-interleaved | |
* order, and creates only standard DATA or SYSTEM format DSK | |
* images as output. No autodetection of source format. | |
* | |
* @param in - i4 data | |
* @param out - buffer to hold DSK data | |
* @param dataMode - if true, create disk in DATA format, otherwise SYSTEM | |
* | |
*/ | |
private static void i4ToDsk(byte in[], byte[] out, boolean dataMode) { | |
final int TRACK_COUNT = 40; | |
final int SECTOR_COUNT = 9; | |
final int TRACK_SIZE = 512 * SECTOR_COUNT; | |
// DSK "Disk-Info" block | |
final byte diskInfo[] = { | |
0x4D, 0x56, 0x20, 0x2D, 0x20, 0x43, 0x50, 0x43, 0x45, 0x4D, 0x55, 0x20, 0x44, 0x69, 0x73, 0x6B, | |
0x2D, 0x46, 0x69, 0x6C, 0x65, 0x0D, 0x0A, 0x44, 0x69, 0x73, 0x6B, 0x2D, 0x49, 0x6E, 0x66, 0x6F, | |
0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x28, 0x01, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
}; | |
// DSK "Track-Info" block | |
final byte trackInfo[] = { | |
0x54, 0x72, 0x61, 0x63, 0x6B, 0x2D, 0x49, 0x6E, 0x66, 0x6F, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x02, 0x09, 0x4E, (byte)0xE5, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | |
}; | |
int inPos = 0; | |
int outPos = 0; | |
// Initialise Disk-Info block | |
System.arraycopy(diskInfo, 0, out, outPos, 256); | |
out[outPos + 0x30] = TRACK_COUNT; // Track count | |
out[outPos + 0x31] = 1; // Side count | |
out[outPos + 0x32] = 0x00; // Track size including Track-Info block | |
out[outPos + 0x33] = 0x13; | |
outPos += 256; | |
// Initialise tracks | |
for (int track = 0; track < TRACK_COUNT; track++) { | |
// Initialise Track-Info block | |
System.arraycopy(trackInfo, 0, out, outPos, 256); | |
out[outPos + 0x10] = (byte) track; // Track number | |
out[outPos + 0x11] = 0; // Side number | |
out[outPos + 0x14] = 2; // Sector size | |
out[outPos + 0x15] = SECTOR_COUNT; // Sector count | |
out[outPos + 0x16] = 0x4e; // GAP#3 size | |
out[outPos + 0x17] = (byte) 0xe5; // Filler byte | |
// Initialise Track-Info block Sector Information List | |
int sectorInfoPos = outPos + 0x18; | |
for (int sector = 0; sector < SECTOR_COUNT; sector++) { | |
// Initialise sector info entry | |
out[sectorInfoPos + 0x00] = (byte) track; | |
out[sectorInfoPos + 0x01] = 0; | |
out[sectorInfoPos + 0x02] = (byte) (dataMode ? sector + 0xc1 : sector + 0x41); | |
out[sectorInfoPos + 0x03] = 2; | |
sectorInfoPos += 8; | |
} | |
outPos += 256; | |
// Initialise sector data | |
System.arraycopy(in, inPos, out, outPos, TRACK_SIZE); | |
inPos += TRACK_SIZE; | |
outPos += TRACK_SIZE; | |
} | |
} | |
// ======================================================================== | |
// COMMAND LINE WRAPPER | |
public static void main(String [] args) { | |
// Check some arguments have been supplied | |
if (args == null || args.length == 0) { | |
System.exit(5); | |
} | |
// Initialse and parse command line | |
boolean dataMode = true; // create DSK in DATA format | |
List<File> files = new ArrayList<File>(args.length); // source i4 files to read | |
for (String arg: args) { | |
if (arg.startsWith("-")) { | |
// Handle command line option | |
if (arg.equals("-s")) { | |
dataMode = false; | |
} else if (arg.equals("-d")) { | |
dataMode = true; | |
} | |
} else { | |
// Assume this is an input filename and check for validity | |
File file = new File(arg); | |
if (!file.exists() || !file.isFile() || !file.canRead()) { | |
exit("[" + arg + "] is not a valid input file"); | |
} | |
files.add(file); | |
} | |
} | |
// Process files listed on command line | |
for (File inFile: files) { | |
FileInputStream fis = null; | |
BufferedInputStream bis = null; | |
FileOutputStream fos = null; | |
try { | |
// Load the input file to memory | |
fis = new FileInputStream(inFile); | |
bis = new BufferedInputStream(fis); | |
long inFileSize = fis.getChannel().size(); | |
byte inFileData[] = new byte[ (int)inFileSize ]; | |
bis.read(inFileData); | |
// Create buffer for disk image | |
byte outFileData[] = new byte[194816]; | |
// Convert disk image | |
i4ToDsk(inFileData, outFileData, dataMode); | |
// Generate output filename | |
String outFileName = inFile.getName().replaceAll("\\.[^\\.]+$", ".dsk"); | |
if (!outFileName.endsWith(".dsk")) { | |
outFileName += ".dsk"; | |
} | |
// Write output file to disk | |
File outFile = new File(outFileName); | |
fos = new FileOutputStream(outFile); | |
fos.write(outFileData); | |
fos.flush(); | |
} catch (FileNotFoundException e) { | |
exit("FileNotFoundException: " + e.getMessage()); | |
} catch (IOException e) { | |
exit("IOException: " + e.getMessage()); | |
} finally { | |
if (bis != null) { try { bis.close(); } catch (Exception e) { } finally { bis = null; } } | |
if (fis != null) { try { fis.close(); } catch (Exception e) { } finally { bis = null; } } | |
if (fos != null) { try { fos.close(); } catch (Exception e) { } finally { fos = null; } } | |
} | |
} | |
} | |
private static void exit(String msg) { | |
System.err.println(msg); | |
System.exit(5); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See also: http://girv.in/an