Last active
December 26, 2022 00:52
-
-
Save gammy/b6299d14559d1150671d to your computer and use it in GitHub Desktop.
Mount/Read/Write Floppy Emulation USB sticks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # This is a tool to assist in the usage of floppy disk hardware emulators: | |
| # https://en.wikipedia.org/wiki/Floppy_disk_hardware_emulator | |
| # | |
| # Several of these devices (presumably cheaper ones) don't store | |
| # floppy drives as files on an existing file system, but rather just | |
| # store the raw data with a 96K offset. It renders the USB-stick | |
| # useless for any other purposes. | |
| # | |
| # It also means that you need customized software to access the virtual | |
| # floppy disks. What a cheap way to do it! | |
| # | |
| # Anyhow, with the information provided on Gough Lui's blogpost | |
| # http://goughlui.com/2013/04/24/review-unbranded-1-44mb-usb-100-floppy-emulator/ | |
| # | |
| # this script allows you to perform basic operations such as | |
| # - Create or Copy data to a virtual floppy disk | |
| # - Write a floppy disk image to a specific slot (number) | |
| # - Mount any virtual floppy disk image slot | |
| # | |
| # It only uses stock tools such as `dd`, `mkfs.msdos` and `mount`. | |
| # Obtw, the mounting code needs loopback support in your kernel. | |
| # | |
| # By gammy | |
| block_size=1024 | |
| block_count=1440 | |
| disk_padding=96 | |
| deps=(dd mount mkfs.msdos ) | |
| for dep in ${deps[@]}; do | |
| which $dep > /dev/null || exit $? | |
| done | |
| floppy_params="bs=${block_size} count=${block_count}" | |
| let fs_limit="$block_size * $block_count" | |
| function usage() { | |
| local me=$(basename $0) | |
| echo "Mount/Read/Write Floppy Emulation USB sticks" | |
| echo | |
| echo " - USE WITH EXTREME CAUTION - " | |
| echo | |
| echo "Usage: $me <mode> [in] [out] [slot]" | |
| echo | |
| echo "Modes:" | |
| echo "new : Create an empty 1.44M disk image in [out]" | |
| echo "copy : Copy file or directory [in] to floppy image [out]" | |
| echo " (runs 'new [out]' if [out] doesn't exist)" | |
| echo "write: Write [in (floppy image)] to [out (usb image)], slot [slot]" | |
| echo "dump : Write [in], [slot] to [out] *TODO*" | |
| echo "mount: Mount [in], [slot] to [out]" | |
| echo | |
| echo "Example:" | |
| echo " $me copy ~/floppy_disk/ disk1.img" | |
| echo " $me write disk1.img /dev/usb3 1" | |
| echo " $me mount /dev/usb3 1 /mnt/fd" | |
| echo | |
| echo "For some interesting information, see" | |
| echo "http://goughlui.com/2013/04/24/review-unbranded-1-44mb-usb-100-floppy-emulator/" | |
| } | |
| function do_new() { | |
| local out="$1" | |
| if [ -z "$out" ]; then | |
| usage | |
| exit 1 | |
| fi | |
| dd ${floppy_params} if=/dev/zero of="$out" | |
| mkfs.msdos "$out" | |
| if [ $? = 0 ]; then | |
| du -sk "$out" | |
| fi | |
| } | |
| function do_copy() { | |
| if [ "$UID" != "0" ]; then | |
| echo "Sorry, I need root priveleges to mount an image" >&2 | |
| exit 1 | |
| fi | |
| local in="$1" | |
| local out="$2" | |
| if [ -z "$in" -o -z "$out" ]; then | |
| usage | |
| exit 1 | |
| fi | |
| if [ ! -e "$in" ]; then | |
| echo "\"$in\": doesn't exist" >&2 | |
| exit 1 | |
| fi | |
| srcsize=$(du -sk "$in" | cut -f 1) | |
| echo "Source size: ${srcsize}K" | |
| if [ $srcsize -ge $block_count ]; then | |
| echo -n "\"$in\": ${srcsize}K: " | |
| echo "won't fit onto \"$out\" ${block_count}" >&2 | |
| exit 1 | |
| fi | |
| if [ ! -e "$out" ]; then | |
| do_new "$out" | |
| else | |
| echo "Note: \"$out\": already exists" | |
| fi | |
| tmp_mount=$(mktemp --directory) | |
| mount "$out" "$tmp_mount" | |
| ret=$? | |
| if [ "$ret" -ne 0 ]; then | |
| echo "mount \"$out\" \"$tmp_mount\": Failure: $ret" >&2 | |
| exit $ret | |
| fi | |
| if [ -d "$in" ]; then | |
| cp -rv "$in/"* "$tmp_mount/" | |
| else | |
| cp -v "$in" "$tmp_mount/" | |
| fi | |
| umount "$tmp_mount" | |
| rm -rf "$tmp_mount" | |
| } | |
| function do_write() { | |
| local in=$1 | |
| local out=$2 | |
| local slot=$3 | |
| if [ -z "$in" -o -z "$out" -o -z "$slot" ]; then | |
| usage | |
| exit 1 | |
| fi | |
| if [ ! -e "$in" ]; then | |
| echo "\"$in\": doesn't exist" >&2 | |
| exit 1 | |
| fi | |
| if [ -e "$out" ]; then | |
| echo "Note: \"$out\": already exists" >&2 | |
| fi | |
| case "$slot" in | |
| ''|*[!0-9]*) | |
| echo "\"$slot\": Not a number" >&2 | |
| exit 1 | |
| ;; | |
| *) | |
| ;; | |
| esac | |
| let offset="(${block_count} + ${disk_padding}) * $slot" | |
| echo "Copy \"$in\" to \"$out\", slot $slot" | |
| echo dd ${floppy_params} seek="$offset" if="$in" of="$out" | |
| dd ${floppy_params} seek="$offset" if="$in" of="$out" | |
| } | |
| function do_mount() { | |
| if [ "$UID" != "0" ]; then | |
| echo "Sorry, I need root priveleges to mount an image" >&2 | |
| exit 1 | |
| fi | |
| local in=$1 | |
| local out=$2 | |
| local slot=$3 | |
| if [ -z "$in" -o -z "$out" -o -z "$slot" ]; then | |
| usage | |
| exit 1 | |
| fi | |
| if [ ! -e "$in" ]; then | |
| echo "\"$in\": doesn't exist" >&2 | |
| exit 1 | |
| fi | |
| case "$slot" in | |
| ''|*[!0-9]*) | |
| echo "\"$slot\": Not a number" >&2 | |
| exit 1 | |
| ;; | |
| *) | |
| ;; | |
| esac | |
| let offset="$block_size * ($block_count + $disk_padding) * $slot" | |
| echo mount -o loop,offset=${offset},sizelimit=${fs_limit} -t msdos "$in" "$out" | |
| mount -o loop,offset=${offset},sizelimit=${fs_limit} \ | |
| -t msdos \ | |
| "$in" \ | |
| "$out" | |
| ret="$?" | |
| if [ "$ret" = "32" ]; then | |
| echo -n "Failed to mount \"$in\", slot $slot. " | |
| echo "Does that slot exist?" >&2 | |
| return $ret | |
| fi | |
| } | |
| mode=$1 | |
| shift | |
| case "$mode" in | |
| "new") | |
| do_new "$1" | |
| ;; | |
| "copy") | |
| do_copy "$1" "$2" | |
| ;; | |
| "write") | |
| do_write "$1" "$2" "$3" | |
| ;; | |
| "mount") | |
| do_mount "$1" "$3" "$2" | |
| ;; | |
| *) | |
| usage | |
| exit 1 | |
| esac | |
| echo "Finished" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment