Add image utility scripts to archive

This commit is contained in:
T. Joseph Carter 2015-10-28 16:36:05 -07:00
parent 7eeed445e5
commit a2809e85e9
5 changed files with 539 additions and 0 deletions

151
docs/ivanx/setup/acmd.txt Normal file
View File

@ -0,0 +1,151 @@
#!/bin/bash
decToHex () {
# converts single-byte decimal value to hexadecimal equivalent
# arg: decimal value from 0-255
# out: two-digit hex value from 00-FF
#exit: 8=extraneous arg, 11=missing arg, 21=invalid arg
[[ $arg1 ]] || return 11
[[ $2 ]] && return 8
[[ ( $(printf %d "$arg1" 2> /dev/null) == $arg1 ) \
&& ( $arg1 -ge 0 ) && ( $arg1 -le 255 ) ]] || return 21
# args are valid
printf %02X "$arg1"
}
echoerr() {
echo "$@" 1>&2;
}
helpExit () {
if [[ -s $acmdStdErr ]]; then
if [[ $(grep CommandLineHelp $acmdStdErr) ]]; then
grep -v ^-[pge][[:space:]] $acmdStdErr | grep -v '^ or' | grep -v 0x2000 1>&2
echoerr "-g <imagename> <filename> [<outputFilename>] copy filename out of any"
echoerr " disk image. Using - for outputFilename will copy to stdout."
echoerr "-e <imagename> <filename> [<outputFilename>] like -g, with conversion"
echoerr " to modern file format if possible."
echoerr "-p <imagename> <filename> [[$|0x]<type>] [[$|0x]<auxtype>] copy filename"
echoerr " into ProDOS disk image. <type> is either three-letter or numeric"
echoerr " ProDOS file type (BIN if omitted). Will read from stdin if supplied."
echoerr " ProDOS subdirectories in <filename> will be created if needed."
echoerr "-c <filename> <imagename> [[$|0x]<type>] [[$|0x]<auxtype>] synonym for -p"
echoerr " with filename and imagename reversed."
else
cat $acmdStdErr
fi
if [[ $arg1 == "-h" ]]; then
exitVal=0
else
exitVal=1
fi
else
if [[ $vsd1_md5 && ( "$vsd1_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual.po)" || "$vsd2_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual2.po)" ) ]]; then
if [[ "$vsd1_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual.po)" || "$vsd2_md5" != "$(md5sum /usr/local/adtpro/disks/Virtual2.po)" ]]; then
echoerr "One of the virtual drive image files has changed while ADTPro server is active."
echoerr " If using VSDRIVE, type 'vsdsync' now to see changes and prevent corruption."
fi
fi
exitval=0
fi
rm $acmdStdErr &> /dev/null
exit $exitVal
}
arg1=$1
acmdStdErr="/tmp/acmd_$RANDOM$RANDOM"
[[ -f /usr/local/adtpro/adtpro.sh ]] && adtPath="/usr/local/adtpro" || adtPath=$(ls -1d /Applications/ADTPro* | head -1);
if [[ ! $2 || $arg1 == "-h" ]]; then
java -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar 2> $acmdStdErr
[[ $? -eq 127 ]] && exit 127 || helpExit $arg1
fi
if [[ $arg1 != "-i" && $arg1 != "-ls" && $arg1 != "-l" && $arg1 != "-ll" && $arg1 != "-x" && $arg1 != "-g" && $arg1 != "-e" && $(ps aux | grep [A]DTPro) ]]; then
vsd1_md5="$(md5sum /usr/local/adtpro/disks/Virtual.po)"
vsd2_md5="$(md5sum /usr/local/adtpro/disks/Virtual2.po)"
fi
if [[ ( $arg1 == "-p" || $arg1 == "-c" || $arg1 == "-g" || $arg1 == "-e" ) && $2 && $3 ]]; then
getArg=
if [[ $arg1 == "-p" ]]; then
prodosArg="$3"
imageArg="$2"
elif [[ $arg1 == "-c" ]]; then
prodosArg="$2"
imageArg="$3"
elif [[ $arg1 == "-g" || $arg1 == "-e" ]]; then
fileArg="$3"
imageArg="$2"
getArg="$arg1"
else
exit 2;
fi
shift
if [[ $getArg ]]; then # get file
outFile=
[[ $3 && $3 != "-" ]] && outFile="$3"
[[ ! $3 ]] && outFile="${2##*/}"
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar $getArg "$imageArg" "$fileArg" $outFile 2> $acmdStdErr
else # put file
# test ProDOS name legitimacy
prodosPath=$(tr [:lower:] [:upper:] <<< $prodosArg )
IFS_orig="$IFS"; IFS="/";
prodosPathParts="$prodosPath"
for thisProdosPathPart in $prodosPathParts; do
if [[ ${#thisProdosPathPart} -gt 15 || ! $(grep ^[A-Z][0-9A-Z\.]*$ <<< $thisProdosPathPart) ]]; then
echoerr "Invalid ProDOS name: $prodosPath"; exit 1;
fi
done
IFS="$IFS_orig"
# process filetype
[[ ${3:0:2} == "0x" ]] && ftArg="\$${3:2}" || ftArg="$3"
auxType="$4"
# assume BIN/$2000 if filetype omitted
if [[ ! $ftArg ]]; then
ft="BIN"
auxType="\$2000"
# accept hex or decimal number for file type
elif [[ ( ${ftArg:0:1} == '$' && ${#ftArg} -eq 3 ) || $(grep [0-9] <<< ${ftArg:0:1}) ]]; then
if [[ ${ftArg:0:1} == '$' ]]; then
fc=$(tr [:upper:] [:lower:] <<< ${ftArg:1:2})
else
fc=$(decToHex $ftArg | tr [:upper:] [:lower:])
fi
P_00=UNK; P_01=BAD; P_02=PCD; P_03=PTX; P_04=TXT; P_05=PDA; P_06=BIN; P_07=FNT; P_08=FOT; P_09=BA3; P_0a=DA3; P_0b=WPF; P_0c=SOS; P_0f=DIR; P_10=RPD; P_11=RPI; P_12=AFD; P_13=AFM; P_14=AFR; P_15=SCL; P_16=PFS; P_19=ADB; P_1a=AWP; P_1b=ASP; P_20=TDM; P_21=IPS; P_22=UPV; P_29=3SD; P_2a=8SC; P_2b=8OB; P_2c=8IC; P_2d=8LD; P_2e=P8C; P_41=OCR; P_42=FTD; P_50=GWP; P_51=GSS; P_52=GDB; P_53=DRW; P_54=GDP; P_55=HMD; P_56=EDU; P_57=STN; P_58=HLP; P_59=COM; P_5a=CFG; P_5b=ANM; P_5c=MUM; P_5d=ENT; P_5e=DVU; P_60=PRE; P_6b=BIO; P_6d=DVR; P_6e=PRE; P_6f=HDV; P_80=GEZ; P_81=GE1; P_82=GEO; P_83=GE3; P_84=GE4; P_85=GE5; P_86=GE6; P_87=GE7; P_88=GE8; P_89=GE9; P_8a=GEA; P_8b=GEB; P_8c=GEC; P_8d=GED; P_8e=GEE; P_8f=GEF; P_a0=WP_; P_ab=GSB; P_ac=TDF; P_ad=BDF; P_b0=SRC; P_b1=OBJ; P_b2=LIB; P_b3=S16; P_b4=RTL; P_b5=EXE; P_b6=STR; P_b7=TSF; P_b8=NDA; P_b9=CDA; P_ba=TOL; P_bb=DRV; P_bc=LDF; P_bd=FST; P_bf=DOC; P_c0=PNT; P_c1=PIC; P_c2=ANI; P_c3=PAL; P_c5=OOG; P_c6=SCR; P_c7=CDV; P_c8=FON; P_c9=FND; P_ca=ICN; P_d5=MUS; P_d6=INS; P_d7=MDI; P_d8=SND; P_db=DBM; P_e0=SHK; P_e2=DTS; P_ee=R16; P_ef=PAS; P_f0=CMD; P_f9=P16; P_fa=INT; P_fb=IVR; P_fc=BAS; P_fd=VAR; P_fe=REL; P_ff=SYS;
ftVar="P_$fc";
[[ ${!ftVar} ]] && ft=${!ftVar} || ft="\$$fc";
else
ft="$ftArg"
fi
# set auxtype to $0801 for Applesoft programs if not specified
[[ $ft == "BAS" && ! $auxType ]] && auxType="\$0801"
# test for absence of stdin [[ -t 0 ]] and if absent use ProDOS name
if [[ -t 0 ]]; then
[[ ! -f $prodosArg ]] && { echoerr "$prodosArg not found."; exit 1; }
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar -d "$imageArg" $prodosPath &> /dev/null
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar -p "$imageArg" $prodosPath $ft $auxType < $prodosArg 2> $acmdStdErr
else
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar -d "$imageArg" $prodosPath &> /dev/null
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar -p "$imageArg" $prodosPath $ft $auxType 2> $acmdStdErr
fi
fi
else
imageArg="$2"
java -Xmx128m -jar "$adtPath"/lib/AppleCommander/AppleCommander-ac.jar "$@" 2> $acmdStdErr
fi
helpExit

80
docs/ivanx/setup/dopo.txt Normal file
View File

@ -0,0 +1,80 @@
#!/bin/bash
# follows gzip syntax -- acts in place if filename provided, outputs to
# stdout with -c, accepts stdin and outputs to stdout if filename is - or absent
# output to stdout?
if [[ "$1" == "-c" ]]; then
shift;
stdout=1;
else
stdout=
fi
# use stdin?
if [[ ! $1 || "$1" == "-" ]]; then
stdin=1
stdout=1
elif [[ $1 && ! -f "$1" ]]; then
echo "usage: dopo [-c] [-|140KdiskImageFilename] 1>&2";
exit 1;
else
stdin=
fi
if [[ ! $stdout ]]; then
#get filename extension, in lowercase
f="$(tr [:upper:] [:lower:] <<< ${1##*.})";
#if it's dsk/do/po, get name without extension
[[ "$f" == "dsk" || "$f" == "do" || "$f" == "po" ]] && of="${1%.*}" || of="$1";
#if name had .po extension, append .dsk to outfile name, otherwise append .po
[[ "$f" == "po" ]] && of="$of.dsk" || of="$of.po"
# set outfile param for dd
ofile="$of"
else
ofile="/tmp/$$.dopo_out"
fi
if [[ ! $stdin ]]; then
# set infile param for dd
ifile="$1"
elif [[ -t 0 ]]; then
echo "usage: dopo [-c] [-|140KdiskImageFilename]" 1>&2; exit 1;
else
ifile="/tmp/$$.dopo_in"
cat > "$ifile"
fi
# verify file is 140K by successfully reading 140K'th byte, and failing to read the one past
[[ $(dd if="$ifile" of=/dev/null bs=1 skip=143359 2>&1 | tail -1 | cut -d ' ' -f 1) -ne 1 || $(dd if="$ifile" of=/dev/null bs=1 skip=143360 2>&1 | tail -1 | cut -d ' ' -f 1) -ne 0 ]] && badInput=1 || badInput=
if [[ $badInput ]]; then
if [[ ! $stdin ]]; then
echo -n "$1 doesn't appear to be a 140K image. Continue? " 1>&2;
read
[[ ${REPLY:0:1} == "y" || ${REPLY:0:1} == "Y" ]] || exit 1;
else
echo "warning: Input file doesn't appear to be a 140K image." 1>&2
echo " Output file is likely to be useless." 1>&2
fi
fi
# for each track
for t in {0..34}; do
# read each sector in the right sequence to make (or unmake)
# valid ProDOS blocks (sector pairs)
for s in 0 14 13 12 11 10 9 8 7 6 5 4 3 2 1 15; do
# copy the sector from the old file to the new one
dd if="$ifile" of="$ofile" bs=256 count=1 skip=$(( t*16 + s )) seek=$(( t*16 + (s==0 || s==15 ? s : 15-s) )) 2> /dev/null
done
done
# remove the old one
[[ ! $stdin && ! $stdout ]] && rm "$1" &> /dev/null
# dump to stdout if -c or stdin used
[[ $stdout ]] && { cat $ofile; rm $ofile &> /dev/null; }
[[ $stdin ]] && rm $ifile &> /dev/null;

View File

@ -0,0 +1,124 @@
#!/bin/bash
readcharDec () {
# read one character from file & convert to equivalent decimal value
# arg1: filename
# arg2: (optional) offset (# of bytes to skip before reading)
# out: decimal value from 0-255
# exit: 8=extraneous arg, 11=missing arg1,
# 21=invalid arg1, 22=invalid arg2
[[ $1 ]] || return 11
[[ $3 ]] && return 8
[[ -f $1 ]] || return 21
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
&& ( $2 -ge 0 ) ]] || return 22; }
# args are valid
charX="$(dd if="$1" bs=1 skip=$(($2)) \
count=1 2> /dev/null; echo -n X)"
[[ ${#charX} -gt 1 ]] || { echo -n 0; return 0; }
echo -n "${charX:0:1}" | od -t u1 | \
head -1 | sed 's/[0\ ]*//' | tr -d ' \n'
}
readcharHex () {
# read one character from file & convert to corresponding hex value
# arg1: filename
# arg2: (optional) offset (# of bytes to skip before reading)
# out: two-digit hex value from 00-FF
# exit: 8=extraneous arg, 11=missing arg1,
# 21=invalid arg1, 22=invalid arg2
[[ $1 ]] || return 11
[[ $3 ]] && return 8
[[ -f $1 ]] || return 21
[[ $2 ]] && { [[ ( $(printf %d "$2" 2> /dev/null) == $2 ) \
&& ( $2 -ge 0 ) ]] || return 22; }
# args are valid
charX="$(dd if="$1" bs=1 skip=$(($2)) \
count=1 2> /dev/null; echo -n X)"
[[ ${#charX} -gt 1 ]] || { echo -n "00"; return 0; }
printf %02X $(echo -n "${charX:0:1}" | od -t u1 | \
head -1 | sed 's/[0\ ]*//' | tr -d ' \n')
}
### start
usage () {
echo "Usage:"
echo "all files: dos2pro dosImageName"
echo "one file : dos2pro dosImageName DOSFILE"
echo "notes:"
echo " Wildcard matching (*) is not supported."
echo " Illegal prodos characters will be made into periods, and names"
echo " will be truncated at 15 characters and possibly overwrite"
echo " other files if they match a previous name conversion."
exit 1
}
[[ $1 == "-h" || $1 == "--help" || ! $1 || ! -f "$1" ]] && usage
dosImage="$1"
fileName="$2"
dosImageBasename=$(basename "$dosImage")
proImage="${dosImageBasename%.*}_prodos.po"
if [[ ! -f "$proImage" ]]; then
echo "Creating $proImage..."
mkpo -b 280 "$proImage"
else
echo "Found $proImage..."
fi
if [[ ! $(acmd -i "$dosImage" 2> /dev/null | grep "Disk Format: DOS 3.3") ]]; then
echo "The file '$dosImage' doesn't appear to be a DOS 3.3 disk image."
exit 2
fi
dosLines=$(acmd -ll "$dosImage")
IFS=''
while read thisLine; do
if [[ ${thisLine:0:2} == "* " || ${thisLine:0:2} == " " ]]; then
dosName=$(cut -c 5- <<< $thisLine | rev | sed 's/^[^ ]* [^ ]* [^ ]* [^ ]* [^ ]* \(.*$\)/\1/' | rev)
if [[ ! $fileName || "$fileName" == "$dosName" ]]; then
dosType=$(cut -c 3 <<< $thisLine)
if [[ $dosType == "A" ]]; then
proType="BAS"
binAddr="0801"
elif [[ $dosType == "I" ]]; then
proType="INT"
elif [[ $dosType == "T" ]]; then
proType="TXT"
elif [[ $dosType == "B" ]]; then
proType="BIN"
sector=$(rev <<< $thisLine | cut -f2 -d ' ' | rev | cut -c 2-)
track=$(rev <<< $thisLine | cut -f3 -d ' ' | rev | cut -c 2-)
offset=$(( (track * 16 + sector) * 256 + 12 ))
track=$(readcharDec "$dosImage" $offset)
sector=$(readcharDec "$dosImage" $((offset+1)))
offset=$(( (track * 16 + sector) * 256 ))
binAddr=$(readcharHex "$dosImage" $((offset+1)))$(readcharHex "$dosImage" $offset)
else
echo "Error: Unknown DOS 3.3 file type."
exit 2
fi
proName=$(sed 's/^[^A-Za-z]/A/' <<< $dosName | sed 's/[^A-Za-z0-9\.]/./g')
auxType=
[[ $binAddr ]] && auxType="\$$binAddr"
echo "Copying '$dosName' to '$proName'"
acmd -g "$dosImage" "$dosName" - | acmd -p "$proImage" "$proName" "$proType" "$auxType"
filesCopied=1
fi
fi
done <<< $dosLines
if [[ ! $filesCopied ]]; then
if [[ $fileName ]]; then
echo "File '$fileName' not found on DOS 3.3 disk image."
else
echo "No files copied."
fi
fi

160
docs/ivanx/setup/mkpo.txt Normal file
View File

@ -0,0 +1,160 @@
#!/bin/bash
# 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

View File

@ -0,0 +1,24 @@
#!/bin/bash
origDir="$PWD"
[[ ! -n $1 || ! -n $2 ]] && { echo "Usage: shk2image archiveFileName imageFileName [PRODOS.DIR.NAME]"; exit 1; };
imageFileName="$2";
prodosDir="$3";
[[ ! -f "$1" ]] && { echo "Archive file '$1' was not found."; exit 1; };
[[ ! -f "$imageFileName" ]] && mkpo "$imageFileName";
[[ -n $prodosDir ]] && dirName="$prodosDir/" || dirName=;
IFS="";
[[ ${1:0:1} == "/" ]] && archiveFile="$1" || archiveFile="$origDir/$1"
mkdir -p /tmp/shk2image_temp
cd /tmp/shk2image_temp
shkFiles=$(nulib2 -xse "$archiveFile" | tr "\r" "~" | cut -d "~" -f 2 | cut -c 18-);
cd "$origDir"
while read thisFile; do
fileName=${thisFile%%#*};
fileType=${thisFile##*#};
echo "extracting $fileName...";
acmd -d "$imageFileName" $dirName$fileName &>/dev/null;
acmd -p "$imageFileName" $dirName$fileName \$${fileType:0:2} \$${fileType:2:4} < /tmp/shk2image_temp/"$thisFile"
rm /tmp/shk2image_temp/"$thisFile"
done <<< $shkFiles
rm -r /tmp/shk2image_temp