From 20724b4a70e52d6ee8463345d089f4141b18d697 Mon Sep 17 00:00:00 2001 From: "T. Joseph Carter" Date: Fri, 30 Oct 2015 04:04:28 -0700 Subject: [PATCH] Add mkpo to source tree --- setup/mkpo.txt | 160 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 setup/mkpo.txt diff --git a/setup/mkpo.txt b/setup/mkpo.txt new file mode 100644 index 0000000..0aee1d5 --- /dev/null +++ b/setup/mkpo.txt @@ -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