a2cloud/setup/mkpo
T. Joseph Carter 55c53b9c10 Clarify license on script files
As noted, Ivan has agreed to allow these scripts to be relicensed under
CC0.  We have one file under LGPL (a unit file we lifted wholesake from
systemd) and the ADTPro wrapper which I'm pretty sure Ivan wrote, but if
he didn't we need to fix its license to be the same as ADTPro.

Either way, to the best of my knowledge, this resolves the question of
how things are licensed explicitly.  (Closes #21)
2018-06-24 21:48:42 -07:00

169 lines
4.9 KiB
Bash
Executable File

#! /bin/bash
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
# mkpo - create ProDOS disk image
#
# To the extent possible under law, T. Joseph Carter and Ivan Drucker have
# waived all copyright and related or neighboring rights to the a2cloud
# scripts themselves. Software used or installed by these scripts is subject
# to other licenses. This work is published from the United States.
# ID-bashByter routines
function binToDec ()
{
dec=0;
bits=$1;
while (( ${#bits} < 8 )); do
bits="0$bits";
done;
for n in {0..7};
do
(( dec+=( ${bits:$n:1} * ( 2**(7-$n) ) ) ));
done;
echo -n $dec
};
function writecharDec ()
{
[[ -n $1 ]] || return 11;
[[ -n $2 ]] || return 12;
[[ -n $3 ]] || return 13;
[[ -n $4 ]] && return 8;
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) && ( $2 -ge 0 ) ]] || return 22;
[[ ( $(printf %d "$3" 2> /dev/null) == $3 ) && ( $3 -ge 0 ) && ( $3 -lt 255 ) ]] || return 23;
echo -n -e "\x$(printf %02X "$3")" | dd of="$1" bs=1 seek=$(($2)) conv=notrunc 2> /dev/null
};
function writecharsHex ()
{
[[ -n $1 ]] || return 11;
[[ -n $2 ]] || return 12;
[[ -n $3 ]] || return 13;
[[ -n $4 ]] && return 8;
[[ ( $(printf %d "$2" 2> /dev/null) == $2 ) && ( $2 -ge 0 ) ]] || return 22;
p=0;
offset=$2;
len=${#3};
while (( p < len )); do
outByte=${3:$p:2};
[[ $(printf %02X "0x$outByte" 2> /dev/null) == $(echo -n "$outByte" | tr [a-z] [A-Z]) ]] || return 23;
echo -n -e "\x$outByte" | dd of="$1" bs=1 seek=$offset conv=notrunc 2> /dev/null;
(( p += 3 ));
(( offset++ ));
done
};
# mkpo
[[ ! -n $1 ]] && { echo "Usage: mkpo [-b totalBlocks] newImageName [PRODOS.VOL.NAME]"; exit 1; };
[[ -f /usr/local/adtpro/adtpro.sh ]] && adtPath="/usr/local/adtpro" || adtPath=$(ls -1d /Applications/ADTPro* | head -1);
[[ ! -d "$adtPath" ]] && { echo "AppleCommander not found."; exit 1; }
if [[ $1 == "-b" ]]; then
totalBlocks="$2"
shift
shift
fi
[[ -f $1 ]] && { echo "Image '$1' already exists."; exit 1; }
[[ $2 ]] && prodosVolName="$2" || prodosVolName="UNTITLED"
# test ProDOS name legitimacy
prodosVolName=$(tr [:lower:] [:upper:] <<< $prodosVolName )
if [[ ${#prodosVolName} -gt 15 || ! $(grep ^[A-Z][0-9A-Z\.]*$ <<< $prodosVolName) ]]; then
echo "Invalid ProDOS name: $prodosVolName"; exit 1;
fi
# see if nulib2 is available; if so, acmd -convert will create image
# with specified block size
nulib2 &> /dev/null
[[ $? == 2 ]] && nulib2=1 || nulib2=
if [[ $nulib2 ]]; then
if [[ $totalBlocks ]]; then
imageBlocks="$totalBlocks"
else
if [[ $(tr [:upper:] [:lower:] <<< "${1##*.}") == "dsk" ]]; then
imageBlocks=280
else
imageBlocks=1600
fi
fi
rm /tmp/blank.shk &> /dev/null
orig_dir="$PWD"
cd /tmp
rm blank.shk EMPTY &> /dev/null
touch EMPTY
nulib2 -a blank.shk EMPTY &> /dev/null
cd "$orig_dir"
acmd -convert /tmp/blank.shk "$1" $imageBlocks
acmd -d "$1" EMPTY
rm /tmp/blank.shk /tmp/EMPTY
acmd -n "$1" "$prodosVolName"
else
# make the disk image without converting archive
if [[ $totalBlocks || $(tr [:upper:] [:lower:] <<< "${1##*.}") == "dsk" ]]; then
acmd -pro140 "$1" $prodosVolName;
else
acmd -pro800 "$1" $prodosVolName;
fi
fi
# make the disk bootable
if [ -f "$adtPath"/disks/ADTPRO*PO ]; then
dd bs=512 count=1 of="$1" conv=notrunc < "$adtPath"/disks/ADTPRO*PO 2> /dev/null
fi
# change .DSK to DOS-ordered
if [[ ! $totalBlocks && $(tr [:upper:] [:lower:] <<< "${1##*.}") == "dsk" ]]; then
mv "$1" "$1".tmp
for t in {0..34}; do
for s in 0 14 13 12 11 10 9 8 7 6 5 4 3 2 1 15; do
dd bs=256 count=1 if="$1".tmp of="$1" skip=$(( $t*16 + $s )) seek=$(( $t*16 + ( $s==0||$s==15 ? $s : 15-$s ) )) 2> /dev/null;
done;
done
rm "$1".tmp
fi
# if nulib2 isn't available, patch the disk image to use specified block size
if [[ ! $nulib2 && $totalBlocks ]]; then
# change total block count
bcHex=$(printf "%04X" $totalBlocks);
writecharsHex "$1" 1065 "${bcHex:2:2}.${bcHex:0:2}";
# fix FSB
dd if=/dev/zero of="$1" bs=512 seek=280 count=$(( $totalBlocks - 280 )) 2> /dev/null;
dd if="$1" of="$1" bs=1 skip=3073 seek=3107 count=$(( ($totalBlocks / 8) - 35 )) conv=notrunc 2> /dev/null;
bits=$(( $totalBlocks % 8 ));
if (( bits > 0 )); then
usedString="00000000";
freeString=;
for ((b=0; b<$bits; b++))
do
freeString=$freeString"1";
done;
binString=$freeString${usedString:$bits};
writecharDec "$1" $(( ( ($totalBlocks / 8) - 35) + 3107 )) $(binToDec $binString);
fi;
# assign extra blocks to FSB if needed
fsbExtraBlocks=$(( ($totalBlocks-1)/4096 ));
if (( fsbExtraBlocks > 0 )); then
dd if=/dev/zero of="$1" bs=1 seek=3072 count=$(( (fsbExtraBlocks > 8) + 1 )) conv=notrunc 2> /dev/null;
(( fsbExtraBlocks-- ));
fi;
bits=$(( fsbExtraBlocks % 8 ));
if (( bits > 0 )); then
freeString="11111111";
usedString=;
for ((b=0; b<$bits; b++))
do
usedString=$usedString"0";
done;
binString=$usedString${freeString:$bits};
writecharDec "$1" $(( (fsbExtraBlocks>7)+3073 )) $(binToDec $binString);
fi;
fi