Skip to content

Instantly share code, notes, and snippets.

@johngirvin
Created October 24, 2011 20:57
Show Gist options
  • Save johngirvin/1310270 to your computer and use it in GitHub Desktop.
Save johngirvin/1310270 to your computer and use it in GitHub Desktop.
Convert KryoFlux "i4" format dump files to DSK format images.
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);
}
}
@johngirvin
Copy link
Author

See also: http://girv.in/an

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment