Тема: Баги ИКП-ДОС
Привет!
Ещё этому ДОСу косточки пока не мыли. Бейсику ИКП-шному мыли, но ведь с ним вместе живёт и ДОС.
Про мороку с драйвером файловой системы я писал и писать буду в соседней ветке.
А вот неожиданность: ошибка в драйвере RWTS.
Не частая, не редкая.
Суть в обработке очереди команд.
Логика различных агатовских драйверов с отложенным исполнением, обычно, похожа. Очередной запрос проверяется на следующее:
1) Есть ли задания в очереди ?
2) Касается ли этот запрос текущего трека (того, над которым сейчас висит головка) ?
3) Является ли запрос отложенным ?
4) Был ли уже отложенный запрос на данный сектор ?
Если запрос касается трека очереди либо очередь пуста, запрос ставится в очередь.
Если нет - то очередь уходит на исполнение, очищается и запрос добавляется к пустой очереди.
Косяк в пункте 4: он проверяется тут:
0FA9 - A0 05 .. " ." LDY #05
0FAB - B1 48 .. "1h" LDA (48), Y
0FAD - AA .. .. "*" TAX
0FAE - BD 00 07 "=.." LDA 0700, X
0FB1 - F0 05 .. "ð." BEQ 0FB8
0FB3 - 20 82 0C "..." JSR 0C82
по адресу (48),5 задаётся номер сектора, а в таблице по адресу 700 лежит массив операций, которые нужно выполнить для каждого сектора. Если для запрошенного сектора не было отложенных запросов - всё хорошо. Иначе запускается процедура 0C82. А косяк в том, что она в регистре X ожидает номер слоты, умноженный на $10. А вовсе не номер сектора. Дальше залип и завис.
Обычно, такой ситуации не бывает: всякие дисковые редакторы не запрашивают отложенных операций, а внутри файлового драйвера отложенные операции вызываются только для не-последнего сектора файла (но об этом чуть позже). Поэтому эту ошибку не заметили.
Проверить просто: постройте файл, у которого в TSL будет указан несколько раз один и тот же сектор. BLOAD/LOAD в ИКП зависнет либо будут какие-нибудь непредсказуемости. Учтите, что число секторов в каталоге должно быть больше или соответствовать числу секторов в TSL.
-=-
А как на неё вышел я?
Тут дело в логике работы стандартного процессора комстроки и моего врапера:
- стандартный процессор на операции чтения файла LOAD/BLOAD выполняет такую последовательность вызовов (для B-типа, например):
1) fopen, fclose. Здесь проверяется тип файла (соответствие запрошенному B).
2) fopen, fread(2 байта) - смещение, fread(2 байта) - размер, fread(размер), fclose.
Т.е. процессор знает размер файла и запрашивает только нужное число байт.
- у меня враппер действует по другому:
fopen, fread($FF00 байт), fclose.
fread даёт ошибку "чтение после конца данных", но меня это не колышет, я могу узнать фактическое число прочитанных байт из возвращаемого file control block.
Проблема в том, что в file driver есть некоторый косячок: он все запросы к RWTS на чтение блоков данных файла посылает с флагом "отложенный". Кроме последнего запроса, который считается последним исходя из _запрошенного_ объёма данных. И не учитывает, что TSL-то уже закончился, т.е. достигнут EOF. Ну а в fclose никто и не подумал вызвать закрытие очереди (а зачем ?).
Хотел объехать это, просто вызвав сброс очереди перед fclose, но, похоже, явной команды для этого RWTS не предусматривает и, в любом случае, проверяет поле номера сектора. А дальше срабатывает ошибка в RWTS и он зависает. Можно попробовать менять номер сектора на любой другой или вообще запрашивать другой трек, но костыль-то получается знатный...
PS Я прям чувствую, как мозги теплеют после 4-8 часов работы над такими задачками.
В следующий выходной надо нафиг это всё бросать и в гараж, уже снег стает совсем, выкачу мопедку, поеду весенние говны месить куда нибудь.