Since @user310346's answer proved particularly tricky and fragile to adapt for producing FAT16 filesystems for use in Box86, I spent a while wrestling with it and came up with three useful things to say:
First, most of that boilerplate in user310346's answer is for allowing you to specify an arbitrary partition size in bytes and then calculate the drive size from it, with appropriate rounding. If you're willing to specify an image/drive size (which I need to do because I'm trying to match a CHS preset from Box86), then parted can automate deriving the rest from it.
Second, though it apparently requires a version newer than what comes with Kubuntu Linux 20.04 LTS, the Parted manual from 2002 lists mkfs and mkpartfs commands that should theoretically be able to boil my use-case down todo this and yours to not much more:
diskimg=hard_drive.img
size=260M
truncate -s "${size}" "${diskimg}"
parted --machine --script --align optimal "${diskimg}" \
mklabel msdos \
mkpartfs primary fat16 1 '100%' \
set 1 lba off
(set 1 lba off changessort of thing, so it'd be worth looking through the partition type byte from 0x0e W95 FAT16 (LBA)changelogs to 0x06 FAT16)see what became of them. Maybe they just morphed into something more obscure but still not requiring root permissions.
Third, thanks to the Bochs manual, I discovered that, if you're going to use mtools, it's easier to get a working filesystem if you have it do all the work.
#!/bin/sh
cd "$(dirname "$(readlink -f "$0")")" || exit
SRC_DIR="combined_disk"
IMG_NAME="combined_disk.img"
# Size for the hard drive image
# (Here's a big one that's recognized in 86Box's CHS presets)
CYLINDERS=1036
HEADS=16
SECTORS=63
# Work around partition=1 not being possible on the command-line AFAIK
mtools_tmp="$(mktemp -d --tmpdir make_disk.XXXXXXXXXX)"
mtools_conf="${mtools_tmp}/mtoolsrc"
echo "drive c: file=\"${IMG_NAME}\" partition=1" >"$mtools_conf"
export MTOOLSRC="${mtools_conf}"
cleanup() {
rm -rf "${mtools_tmp}"
}
trap cleanup EXIT
rm -f "${IMG_NAME}.img"
truncate -s "$((CYLINDERS * HEADS * SECTORS * 512))" "$IMG_NAME"
mpartition -I -t "$CYLINDERS" -h "$HEADS" -s "$SECTORS" c: 2>&1
mpartition -c -T 6 -t "$CYLINDERS" -h "$HEADS" -s "$SECTORS" c:
mformat c:
mcopy -s "$SRC_DIR"/* c: