mirror of
https://github.com/RasppleII/a2cloud.git
synced 2024-12-22 13:30:27 +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)
133 lines
4.1 KiB
Bash
Executable File
133 lines
4.1 KiB
Bash
Executable File
#! /bin/bash
|
|
# vim: set tabstop=4 shiftwidth=4 noexpandtab filetype=sh:
|
|
|
|
# dos2pro - extract files from DOS 3.3 image and convert to ProDOS
|
|
#
|
|
# 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.
|
|
|
|
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
|