NAME
D64::Disk::Image - Perl interface to Per Olofsson's "diskimage.c", an ANSI C library for manipulating Commodore disk images
SYNOPSIS
use D64::Disk::Image qw(:all);
# Create an empty image:
my $d64 = D64::Disk::Image->create_image('image.d64');
# Format the image:
my $rawname = $d64->rawname_from_name('title');
my $rawid = $d64->rawname_from_name('id');
$d64->format($rawname, $rawid);
# Write the image to disk:
$d64->free_image();
# Load an image from disk:
my $d64 = D64::Disk::Image->load_image('image.d64');
# Open a file for writing:
my $rawname = $d64->rawname_from_name('filename');
my $prg = $d64->open($rawname, T_PRG, F_WRITE);
# Write data to file:
my $counter = $prg->write($buffer);
# Close a file:
$prg->close();
# Open a file for reading:
my $rawname = $d64->rawname_from_name('filename');
my $prg = $d64->open($rawname, T_PRG, F_READ);
# Read data from file:
my ($counter, $buffer) = $prg->read();
# Close a file:
$prg->close();
# Free an image in memory:
$d64->free_image();
DESCRIPTION
Per Olofsson's "diskimage.c" is an ANSI C library for manipulating Commodore disk images. In Perl the following operations are implemented via D64::Disk::Image
package:
Open file ('$' reads directory)
Delete file
Rename file
Format disk
Allocate sector
Deallocate sector
Additionally, the following operations are implemented via accompanying D64::Disk::Image::File
package:
Read file
Write file
Close file
The following formats are supported:
D64 (single-sided 1541 disk image, with optional error info, which is currently ignored)
D71 (double-sided 1571 disk image)
D81 (3,5" 1581 disk image, however only root directory)
METHODS
new / load_image
Create new D64::Disk::Image
object and load existing D64/D71/D81 image file from disk:
my $d64DiskImageObj = D64::Disk::Image->new($name);
my $d64DiskImageObj = D64::Disk::Image->load_image($name);
new / create_image
Create new D64::Disk::Image
object and create new D64/D71/D81 image file on disk:
my $d64DiskImageObj = D64::Disk::Image->new($name, $imageType);
my $d64DiskImageObj = D64::Disk::Image->create_image($name, $imageType);
The following image type constants are available: D64, D71, D81 (image type D64 is used by default when executed as "create_image"). Each disk created needs to be formatted first before it can be used.
free_image
Free an image in memory (each opened disk needs to be subsequently freed to avoid memory leaks):
$d64DiskImageObj->free_image();
If the image has been modified, the changes will be written to disk.
sync
Write the image to disk:
$d64DiskImageObj->sync();
status
Get the drive status:
my ($numstatus, $status) = $d64DiskImageObj->status();
Numerical status is returned first, textual content of a status message is copied to the second return value.
open
Open a file for reading or writing:
my $imageFileObj = $d64DiskImageObj->open($rawname, $fileType, $mode);
The following file type constants are available: T_DEL, T_SEQ, T_PRG, T_USR, T_REL, T_CBM, T_DIR (by default file type T_PRG is used)
There are two open modes available: F_READ for reading, F_WRITE for writing (by default file is opened in F_READ mode)
Opening, reading, writing, and closing files is described in detail in D64::Disk::Image::File
format
Format the image:
my $numstatus = $d64DiskImageObj->format($rawname, $rawid);
If $rawid is given, a full format is performed.
my $numstatus = $d64DiskImageObj->format($rawname);
If no $rawid is given, a quick format is performed.
delete
Delete files matching the pattern:
my $numstatus = $d64DiskImageObj->delete($rawPattern, $fileType);
rename
Rename a file:
my $numstatus = $d64DiskImageObj->rename($oldRawName, $newRawName, $fileType);
sectors_per_track
Get the number of sectors in a given track:
my $sectors = D64::Disk::Image->sectors_per_track($imageType, $track);
my $sectors = $d64DiskImageObj->sectors_per_track($imageType, $track);
tracks
Get the number of tracks in the image:
my $tracks = D64::Disk::Image->tracks($imageType);
my $tracks = $d64DiskImageObj->tracks($imageType);
title
Get the disk title and id in the BAM:
my ($title, $id) = $d64DiskImageObj->title();
track_blocks_free
Get the number of free sectors in a given track:
my $track_blocks_free = $d64DiskImageObj->track_blocks_free($track);
is_ts_free
Get non-zero if the given track and sector is free, and zero if it's allocated:
my $is_ts_free = $d64DiskImageObj->is_ts_free($track, $sector);
alloc_ts
Allocate a given track and sector:
$d64DiskImageObj->alloc_ts($track, $sector);
free_ts
Free a given track and sector:
$d64DiskImageObj->free_ts($track, $sector);
rawname_from_name
Convert a NULL-terminated string to 16-byte 0xA0 padding:
my $rawname = D64::Disk::Image->rawname_from_name($name);
my $rawname = $d64DiskImageObj->rawname_from_name($name);
name_from_rawname
Converts a 0xA0 padded string to a NULL-terminated string:
my $name = D64::Disk::Image->name_from_rawname($rawname);
my $name = $d64DiskImageObj->name_from_rawname($rawname);
blocksfree
Get number of blocks free:
my $blocksFree = $d64DiskImageObj->blocksfree();
type
Get image type:
my $imageType = $d64DiskImageObj->type();
ascii_to_petscii
Convert an ASCII string to a PETSCII string:
my $petscii_string = D64::Disk::Image->ascii_to_petscii($ascii_string);
my $petscii_string = $d64DiskImageObj->ascii_to_petscii($ascii_string);
petscii_to_ascii
Convert a PETSCII string to an ASCII string:
my $ascii_string = D64::Disk::Image->petscii_to_ascii($petscii_string);
my $ascii_string = $d64DiskImageObj->petscii_to_ascii($petscii_string);
EXAMPLES
Print out the BAM:
# Load image into RAM:
my $d64 = D64::Disk::Image->load_image('image.d64');
# Get image type:
my $imageType = $d64->type();
# Print BAM:
print "TRK FREE MAP\n";
for (my $track = 1; $track <= $d64->tracks($imageType); $track++) {
my $sectors = $d64->sectors_per_track($imageType, $track);
printf "%3d: %2d/%d ", $track, $d64->track_blocks_free($track), $sectors;
for (my $sector = 0; $sector < $sectors; $sector++) {
printf "%d", $d64->is_ts_free($track, $sector);
}
print "\n";
}
print "\n";
# Print number of blocks free:
my $blocksFree = $d64->blocksfree();
printf "%d blocks free\n", $blocksFree;
# Release image:
$d64->free_image();
List the directory:
my @file_types = qw/del seq prg usr rel cbm dir ???/;
# Load image into RAM:
my $d64 = D64::Disk::Image->load_image('image.d64');
# Open directory for reading:
my $dir = $d64->open('$', T_PRG, F_READ);
# Convert title to ASCII:
my ($title, $id) = $d64->title();
$title = $d64->name_from_rawname($title);
$title = $d64->petscii_to_ascii($title);
# Convert ID to ASCII:
$id = $d64->name_from_rawname($id);
$id = $d64->petscii_to_ascii($id);
# Print title and disk ID:
printf "0 \"%-16s\" %s\n", $title, $id;
# Read first block into buffer:
my ($counter, $buffer) = $dir->read(254);
die 'BAM read failed' if $counter != 254;
# Read directory blocks:
while (1) {
my ($counter, $buffer) = $dir->read(254);
last unless $counter == 254;
for (my $offset = -2; $offset < 254; $offset += 32) {
# If file type != 0:
my $file_type = ord (substr $buffer, $offset + 2, 1);
if ($file_type != 0) {
my $rawname = substr $buffer, $offset + 5;
my $name = $d64->name_from_rawname($rawname);
my $type = $file_type & 7;
my $closed = $file_type & 0x80;
my $locked = $file_type & 0x40;
my $size = ord (substr $buffer, $offset + 31, 1) << 8 | ord (substr $buffer, $offset + 30, 1);
# Convert to ASCII and add quotes:
$name = $d64->petscii_to_ascii($name);
my $quotename = sprintf "\"%s\"", $name;
# Print directory entry:
printf "%-4d %-18s%c%s%c\n", $size, $quotename, $closed ? ord ' ' : ord '*', $file_types[$type], $locked ? ord '<' : ord ' ';
}
}
}
# Print number of blocks free:
my $blocksFree = $d64->blocksfree();
printf "%d blocks free\n", $blocksFree;
# Close directory:
$dir->close();
# Release image:
$d64->free_image();
Copy a file from a disk image:
# Load image into RAM:
my $d64 = D64::Disk::Image->load_image('image.d64');
# Convert filename:
my $name = 'filename';
my $rawname = $d64->rawname_from_name($d64->ascii_to_petscii($name));
# Open file for reading:
my $prg = $d64->open($rawname, T_PRG, F_READ);
# Open file for writing:
die "$name file already exists" if -e $name;
open PRG, '>:bytes', $name or die "Couldn't open $name file for writing";
# Read data from file:
my ($size, $buffer) = $prg->read();
print PRG $buffer;
printf "Read %d bytes from %s\n", $size, $disk;
# Close files:
close PRG;
$prg->close();
# Release image:
$d64->free_image();
Copy a file to a disk image:
# Load image into RAM:
my $d64 = D64::Disk::Image->load_image('image.d64');
# Convert filename:
my $name = 'filename';
my $rawname = $d64->rawname_from_name($d64->ascii_to_petscii($name));
# Open file for writing:
my $prg = $d64->open($rawname, T_PRG, F_WRITE);
# Open file for reading:
die "$name file does not exist" unless -e $name;
open PRG, '<:bytes', $name or die "Couldn't open $name file for reading";
# Write data to file:
my $buffer;
my $filesize = (stat($name))[7];
sysread PRG, $buffer, $filesize;
my $size = $prg->write($buffer);
printf "Wrote %d bytes to %s\n", $size, $disk_3;
# Close files:
close PRG;
$prg->close();
# Release image:
$d64->free_image();
Create an empty disk image:
# Create an empty image:
my $d64 = D64::Disk::Image->create_image('image.d64', D64);
# Convert title:
my $name = 'title';
my $rawname = $d64->rawname_from_name($d64->ascii_to_petscii($name));
# Convert ID:
my $id = 'id';
my $rawid = $d64->rawname_from_name($d64->ascii_to_petscii($id));
# Format the image:
$d64->format($rawname, $rawid);
# Release image:
$d64->free_image();
BUGS
There are no known bugs at the moment. Please report any bugs or feature requests.
EXPORT
D64::Disk::Image
exports nothing by default.
You may request the import of image type constants (D64, D71, and D81), and file type constants (T_DEL
, T_SEQ
, T_PRG
, T_USR
, T_REL
, T_CBM
, and T_DIR
). All of these constants can be explicitly imported from D64::Disk::Image
by using it with ":types" tag. You may also request the import of open mode constants (F_READ
, and F_WRITE
). Both these constants can be explicitly imported from D64::Disk::Image
by using it with ":modes" tag. All constants can be explicitly imported from D64::Disk::Image
by using it with ":all" tag.
SEE ALSO
AUTHOR
Pawel Krol, <pawelkrol@cpan.org>.
VERSION
Version 0.05 (2018-12-01)
COPYRIGHT AND LICENSE
diskimage.c is released under a slightly modified BSD license.
Copyright (c) 2003-2006, Per Olofsson All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diskimage.c website: https://paradroid.automac.se/diskimage/