mirror of
https://github.com/RasppleII/a2cloud.git
synced 2024-12-30 03:29:34 +00:00
55c53b9c10
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)
169 lines
4.9 KiB
Bash
Executable File
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
|