#!/bin/bash
# make_hdd.sh OUT.chd FILE1 [FILE2 ...]
#
# Собирает 32 МБ RAW-образ жёсткого диска (MBR + один раздел FAT16) с
# указанными файлами в корне и конвертит его в CHD для MAME (монтируется
# как -hard2).  Быстрая альтернатива floppy (mc.img): MAME эмулирует FDD
# с реальной черепашьей скоростью, HDD — в разы быстрее.
#
# Требует: mtools (mpartition/mformat/mcopy) + chdman (из MAME).
# Sprinter DSS штатно монтирует стандартный MBR+FAT16 (подтверждено).
#
# Использование:
#   toolchain/make_hdd.sh mame/v306/IMG/test_hdd.chd prog.exe data1 data2 ...
#   toolchain/make_hdd.sh out.chd prog.exe KID:kid0.atl GUARD:g0.atl ...
#     — аргумент вида КАТАЛОГ:файл кладёт файл в подкаталог образа
#       (каталог создаётся); без префикса файл идёт в корень.
set -e

if [ $# -lt 2 ]; then
  echo "usage: $0 OUT.chd FILE1 [FILE2 ...]" >&2
  exit 1
fi

OUT_CHD="$1"; shift

# Геометрия: 128*16*32*512 = 32 МБ.  BPS=512.
CYLS=128; HEADS=16; SECS=32
SECTORS=$((CYLS * HEADS * SECS))          # 65536

# macOS mktemp требует X'ы в КОНЦЕ шаблона.
RAW=$(mktemp /tmp/sphdd.raw.XXXXXX)
MTC=$(mktemp /tmp/sphdd.mtc.XXXXXX)
trap 'rm -f "$RAW" "$MTC"' EXIT

dd if=/dev/zero of="$RAW" bs=512 count=$SECTORS status=none

# mtools-диск z: = раздел 1 нашего RAW-образа.
printf 'drive z: file="%s" partition=1\n' "$RAW" > "$MTC"
export MTOOLSRC="$MTC" MTOOLS_SKIP_CHECK=1

# mtools собран с enable-raw-term и, когда ему нужно что-то спросить,
# открывает УПРАВЛЯЮЩИЙ ТЕРМИНАЛ напрямую (/dev/tty) — в обход stdin.
# Поэтому ни `< /dev/null`, ни перенаправление stdio не спасают: из
# терминала сборка молча вставала навсегда на `mmd z:/BG` (подтверждено
# lsof: fd 0 = /dev/null, fd 4 = /dev/tty, процесс спит).  Лечится только
# отсутствием управляющего терминала — запускаем mtools в новой сессии,
# тогда открыть /dev/tty нечего и mtools идёт неинтерактивным путём.
#
# setsid(1) в macOS нет, поэтому делаем то же самое питоном.
# Каналов, откуда mtools может ждать ответ, ДВА, и закрывать надо оба:
#   /dev/tty  — убирается новой сессией (os.setsid);
#   stdin     — убирается перенаправлением из /dev/null.
# Закрыть только один недостаточно: с одним лишь setsid mmd переключался на
# stdin и вис уже на нём (lsof: fd 0 = /dev/ttys002).
mt() {
  python3 -c 'import os,sys; os.setsid(); os.execvp(sys.argv[1], sys.argv[1:])' \
      "$@" < /dev/null
}

# MBR + раздел 1 на весь диск (тип FAT16), затем формат FAT16.
echo "--- разметка и формат образа ---"
mt mpartition -I -c -t $CYLS -h $HEADS -s $SECS z:
mt mformat z:

echo "--- копирование файлов ---"

# Аргумент может быть либо файлом (кладём в корень), либо парой
# КАТАЛОГ:файл — тогда каталог создаётся на образе и файл кладётся туда.
# Имена на Sprinter/DSS — 8.3, каталоги тоже (KID, GUARD, BG, LEVELS...).
for f in "$@"; do
  case "$f" in
    *:*) dir="${f%%:*}"; src="${f#*:}"
         # Каталог может уже быть — это не ошибка; stderr НЕ прячем, иначе
         # непрошедший вопрос mtools снова окажется невидимым.
         mt mmd "z:/$dir" >/dev/null 2>&1 || true
         mt mcopy -o "$src" "z:/$dir/" ;;
    *)   mt mcopy -o "$f" z: ;;
  esac
done

echo "--- содержимое образа ---"
mt mdir -/ z:

# RAW -> CHD (без сжатия = быстро; та же геометрия).
echo "--- конвертация RAW -> CHD ---"
chdman createhd -i "$RAW" -o "$OUT_CHD" -c none \
  -chs $CYLS,$HEADS,$SECS -ss 512 -f
echo "готово: $OUT_CHD"
