Files
Sprinter-SDCC/toolchain/make_hdd.sh
T
snark13 59e51f7e83 toolchain: make_hdd.sh не виснет при запуске из терминала
Симптом: сборка образа молча вставала навсегда сразу после эхо-строки
команды.  Появилось не «само» — ровно тогда, когда образ разложили по
подкаталогам (BG/KID/GUARD/LEVELS) и в скрипте появился mmd.

Диагноз по артефакту, а не по догадке: зависший процесс — `mmd z:/BG`,
и lsof показал fd 0 = /dev/null, fd 4 = /dev/tty.  То есть mtools (собран
с enable-raw-term) для интерактивного вопроса открывает УПРАВЛЯЮЩИЙ
ТЕРМИНАЛ напрямую, в обход stdin — поэтому ни `< /dev/null`, ни
перенаправления stdio не помогают.  А `2>/dev/null` на mmd прятал сам
вопрос, из-за чего это выглядело как зависание на пустом месте.
Из НЕинтерактивного запуска (CI, фоновая задача) терминала нет, вопрос не
задаётся, и баг не воспроизводится — потому и жил незамеченным.

Лечение: все вызовы mtools идут через обёртку mt(), которая запускает их в
НОВОЙ СЕССИИ (os.setsid + exec питоном; setsid(1) в macOS нет).  Без
управляющего терминала открывать /dev/tty нечего, и mtools выбирает
неинтерактивный путь.

Заодно добавлены отметки этапов («разметка и формат», «копирование
файлов», «конвертация RAW -> CHD»): если что-то встанет снова, будет сразу
видно где, а не после последнего аргумента команды.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 21:57:39 +03:00

83 lines
4.0 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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 нет, поэтому делаем то же самое питоном.
mt() {
python3 -c 'import os,sys; os.setsid(); os.execvp(sys.argv[1], sys.argv[1:])' "$@"
}
# 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"