The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Archive::ByteBoozer - Perl interface to David Malmborg's "ByteBoozer", a data cruncher for Commodore files

SYNOPSIS

  use Archive::ByteBoozer qw/crunch/;

  # Read file, crunch data, write crunched data into a file:
  my $original = new IO::File "original.prg", "r";
  my $crunched = new IO::File "crunched.prg", "w";
  crunch(source => $original, target => $crunched);

  # Read scalar, crunch data, write crunched data into a scalar:
  my @data = (0x00, 0x10, 0x01, 0x02, 0x03, 0x04, 0x05);
  my $original = join '', map { chr $_ } @data;
  my $crunched = new IO::Scalar;
  crunch(source => $original, target => $crunched);

  # Crunch data preceding it with the given initial address first:
  my $initial_address = 0x2000;
  crunch(source => $original, target => $crunched, precede_initial_address => $initial_address);

  # Crunch data replacing the first two bytes with the new initial address first:
  my $initial_address = 0x4000;
  crunch(source => $original, target => $crunched, replace_initial_address => $initial_address);

  # Attach decruncher with the given execute program address:
  my $program_address = 0x0c00;
  crunch(source => $original, target => $crunched, attach_decruncher => $program_address);

  # Relocate compressed data to the given start address:
  my $start_address = 0x0800;
  crunch(source => $original, target => $crunched, relocate_output => $start_address);

  # Relocate compressed data to the given end address:
  my $end_address = 0x2800;
  crunch(source => $original, target => $crunched, relocate_output_up_to => $end_address);

  # Enable verbose output while crunching data:
  my $verbose = 1;
  crunch(source => $original, target => $crunched, verbose => $verbose);

DESCRIPTION

David Malmborg's "ByteBoozer" is a data cruncher for Commodore files written in C. In Perl the following operations are implemented via Archive::ByteBoozer package:

  • Reading data from any given IO:: interface (including files, scalars, etc.)

  • Packing data using the compression algorithm implemented via ByteBoozer

  • Writing data into any given IO:: interface (including files, scalars, etc.)

METHODS

crunch

In order to crunch the data, you are required to provide source and target IO:: interfaces:

  my $original = new IO::File "original.prg", "r";
  my $crunched = new IO::File "crunched.prg", "w";
  crunch(source => $original, target => $crunched);

Upon writing the data into the target IO:: interface current position in the stream will be reset to the initial position acquired before the subroutine call, which enables immediate access to the compressed data without the necessity of seeking to the right position in the stream. The same comment applies to the source IO:: interface.

In addition to the source and target IO:: interfaces, which are mandatory arguments to the crunch subroutine call, the following parameters are recognized:

attach_decruncher

attach_decruncher enables to attach decruncher procedure with the given program start address:

  my $program_address = 0x0c00;
  crunch(source => $in, target => $out, attach_decruncher => $program_address);

This will create an executable BASIC file that is by default loaded into the memory area beginning at $0801 (assuming no output relocation has been requested), and jumping directly to the given execute program address of $0c00 upon completion of the decrunching process.

make_executable

make_executable is an alias for attach_decruncher:

  my $program_address = 0x3600;
  crunch(source => $in, target => $out, make_executable => $program_address);

relocate_output

relocate_output is used for setting up a new start address of the compressed data (by default data is shifted and aligned to fill in the memory up to the address of $fff9):

    my $start_address = 0x0800;
    crunch(source => $in, target => $out, relocate_output => $start_address);

This will relocate compressed data to the given start address of $0800 by writing an appropriate information in the output stream.

relocate_output_up_to

relocate_output_up_to is used for setting up a new start address of the compressed data by shifting it up to the given end address (by default data is shifted and aligned to fill in the memory up to the address of $fff9, however you might want to align your data to a different end address - it is where this option becomes handy):

  my $end_address = 0x2800;
  crunch(source => $original, target => $crunched, relocate_output_up_to => $end_address);

This will relocate compressed data to some address below $2800 by writing an appropriate information in the output stream.

In the above example the following assumptions are true: your source code or other used data begins at $2800 and you want to load your compressed soundtrack file somewhere between $1000 and $2800, however you may still want to execute your decrunching routine later. This will not work if you load your compressed file at $1000, because uncompressed data would begin to overwrite your loaded data shortly after you invoked decruncher routine, leading to data corruption and truly unpredictable results. What you want to do is to load your file at any address that will provide data safety. relocate_output_up_to parameter ensures that.

relocate_output_up_to and relocate_output parameters are mutually exclusive. relocate_output_up_to always takes precedence over relocate_output.

precede_initial_address

precede_initial_address adds given initial address at the beginning of an input stream, so this option can be used for setting up start address on the target device upon decrunching compressed data. If you are targetting a raw stream of bytes without providing initial memory address within it, decruncher routine will not be able to properly determine the right memory address, where your data should get unpacked to. Therefore it is essential to precede your input stream with the initial address, telling ByteBoozer what the target address of the uncompressed data is going to be:

    my $initial_address = 0x2000;
    crunch(source => $in, target => $out, precede_initial_address => $initial_address);

Before crunching algorithm is applied, data will be here prepended with the given initial address of $2000 first. This given initial address should be understood as the start address of the unpacked data (this is exactly where your compressed data is going to be uncrunched to).

Please note that this option and replace_initial_address are mutually exclusive. This option is expected to be applied to a raw stream of bytes, while the latter one is not supposed to handle raw byte streams.

replace_initial_address

replace_initial_address replaces the original initial address that is found at the beginning of an input stream with the new initial address first, even before the whole crunching process begins. This option is therefore used the same like precede_initial_address for setting up a start address on the target device upon decrunching compressed data, however the initial address is not preceding the data, so that length of data remains unchanged, only its first two bytes get altered. This will tell ByteBoozer what is the new target address of the uncompressed data:

    my $initial_address = 0x4000;
    crunch(source => $in, target => $out, replace_initial_address => $initial_address);

Before crunching algorithm is applied, first two data bytes will be here replaced with the given initial address of $4000 first. This given initial address should be understood as the start address of the unpacked data (this is exactly where your compressed data is going to be uncrunched to).

Please note that this option and precede_initial_address are mutually exclusive. This option is expected to be applied to a regular stream of C64 file data, while the latter one is not supposed to handle regular C64 data files.

verbose

verbose indicates display of the compression result:

    my $verbose = 1;
    crunch(source => $in, target => $out, verbose => $verbose);

When set to 1 a similar informative message will be written to the standard output: ByteBoozer: compressed 174 bytes into 121 bytes.

EXAMPLES

Compress a PRG file named "part-1.prg", replace its start address with $2000 (this is where the data will be uncompressed to), move all packed bytes to $f000 (this will be written into loading address of the output file), and save crunched data into a PRG file name "part-1.crunched.prg":

  use Archive::ByteBoozer qw/crunch/;

  my $source            = new IO::File "part-1.prg", "r";
  my $target            = new IO::File "part-1.crunched.prg", "w";
  my $unpacking_address = 0x2000;
  my $relocate_address  = 0xf000;

  crunch(
    source                  => $source,
    target                  => $target,
    replace_initial_address => $unpacking_address,
    relocate_output         => $relocate_address,
  );

BUGS

There are no known bugs at the moment. Please report any bugs or feature requests.

EXPORT

Archive::ByteBoozer exports nothing by default.

You are allowed to explicitly import the crunch subroutine into the caller's namespace either by specifying its name in the import list (crunch) or by using the module with the :crunch tag.

SEE ALSO

IO::File, IO::Scalar

AUTHOR

Pawel Krol, <djgruby@gmail.com>.

VERSION

Version 0.10 (2018-11-26)

COPYRIGHT AND LICENSE

ByteBoozer cruncher/decruncher:

Copyright (C) 2004-2006, 2008-2009, 2012 David Malmborg.

Archive::ByteBoozer Perl interface:

Copyright (C) 2012-2013, 2016, 2018 by Pawel Krol.

This library is free open source software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.6 or, at your option, any later version of Perl 5 you may have available.

PLEASE NOTE THAT IT COMES WITHOUT A WARRANTY OF ANY KIND!