1 Отредактировано Voldemar0 (07-04-2018 21:53)

Тема: Баги ИКП-ДОС

Привет!

Ещё этому ДОСу косточки пока не мыли. Бейсику ИКП-шному мыли, но ведь с ним вместе живёт и ДОС.

Про мороку с драйвером файловой системы я писал и писать буду в соседней ветке.

А вот неожиданность: ошибка в драйвере 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 часов работы над такими задачками.
В следующий выходной надо нафиг это всё бросать и в гараж, уже снег стает совсем, выкачу мопедку, поеду весенние говны месить куда нибудь.

2

Re: Баги ИКП-ДОС

Поймал себя на том, что захожу на форум чаще чем обычно именно чтоб посмотреть нет ли продолжения в темах про ДОСы и бейсики....

3

Re: Баги ИКП-ДОС

Voldemar0 пишет:

Привет!

А вот неожиданность: ошибка в драйвере RWTS.
Не частая, не редкая.
Суть в обработке очереди команд.

Вот я чувствовал, что с этими очередями обязательно будут косяки.

4

Re: Баги ИКП-ДОС

USR пишет:

Вот я чувствовал, что с этими очередями обязательно будут косяки.

Решение одной проблемы всегда порождает две новых :)

5 Отредактировано Voldemar0 (10-04-2018 05:43)

Re: Баги ИКП-ДОС

Объехал в итоге этот баг чтением VTOC (17/0) в свой буфер (память дополнительную не нужно, так как для драйвера ФС всё равно нужно выделить два секторных буфера). Запрос делаю без флажка отложенности, так что дочитывает всё из очереди и вроде без внезапных сюрпризов. Сделал это только для команды чтения файла, с записью проблем нет. Тесты проходят.

6 Отредактировано Voldemar0 (04-08-2019 21:03)

Re: Баги ИКП-ДОС

Всё ж хорошо было, и вот опять оно вылезло.

Что делает следующая команда на девятке ?

bload test,A$8000

Она как бы читает файл в область $8000.
Она таки его читает, да.

Вопрос: а где эта область находится в физической памяти ? Мы ж помним - у девятки память сегментирована.
ДОС/Бейсик/Сисмон очень любят её переключать. По поводу и без.

Загрузите ИКП и поглядите одним глазком в эмуляторе: карта памяти во время мигания курсора в командной строке будет простой: 0 1 2 3 4 5 6 7. Т.е. физическая память соответствует логической.
Потом сделайте call-151, и из сисмона выполните, например, команду "L".
Память внезапно переключится  в состояние 0123CD67 (на адресах 8000-BFFF подключает физическая память $18000.$1BFFF).
Это видно только в эмуляторе, потому что сисмон на запрос C100.C17F скажет что всё окей, 01234567.
Это легко проверить: попробуйте переключить банк C14C:0, а потом прочитайте снова C100.C17F - опять
будут лакированные 01234567. Плевать сисмон хотел на ваши переключения, он всё ставит обратно.

Но проблема вот в чём: эти переключения происходят внезапно. Т.е. возврат в бейсик на самом деле не возвращает память в дефолтное состояние. Он помнит какое оно включено  и даже если что-то переключает, всё возвращает обратно. Так же, обычно, поступает и ДОС. И только по команде FP память реально встаёт в состояние 01234567. До следующих фантазий то ли сисмона, то ли кого-то ещё.

Получается, что если вы используете сисмон, бейсик, дос, вы вообще-то не знаете, какой сегмент вам вернётся подключенным. Но bload будет срабатывать именно на текущий выбранный сегмент...

Как-то так. Я вряд ли буду копать эту проблему до причин, скорее всего просто буду подгонять workaround.

--=--

Объясню, почему это может быть важно:
Если бы в доках на систему было чётко заявлено: любые вызовы приводят к случайным переключениям
контроллера ОЗУ, восстаналивайте свою карту памяти - это было бы понятно.
Если бы в доках на систему было чётко заявлено: любые вызовы возвращают состояние памяти (или не изменяют его) - тоже понятно.

Но в доках не сказано вообще ничего.

Тогда начинаем гадать и пробовать. При многих вызовах состояние памяти, обычно, восстанавливается.
Т.е. сама механниках сохранения/восстановления есть.
И это очень правильно: если моя прога, например, выполняется из адресов $8000 или выше, то при несохранённом состоянии возврат управления на этот регион просто попадёт на какой-то мусор, вместо моей программы. Но, как показала практика, срабатывает это восстановление, почему-то не всегда и от чего-то зависит.

Т.е. я , например, в своей программе читаю файл в буфер $6000..$9000, а потом обнаруживаю, что через несколько операций регион 8000-9000 заполнен чем-то не тем, чем надо.
Сам я памятью не управляю, расчитываю на то, что она изначально включена в какое-то фиксированное состояние и почти не трогаю его (за исключением обращения к ИКП-ДОС - она без этого не умеет). Но я широко использую обращения к сисмону, и где-то оно там, видимо , что-то подгаживает. А может это RWTS... А может кто-то ещё.

7

Re: Баги ИКП-ДОС

Всё, можно выдохнуть...

Это не баг в досе, это просто странное поведение + количество моих костылей стало немного плохо управляемым.

Да, ДОС при обращении к своим процедурах сохраняет и восстанавливает состояние памяти.
Т.е. если у вас сегментная карта 01234567 и вы делаете запрос на чтение в регион 8000..,
то файл прочитается именно в 4й сегмент, несмотря на то, что досу нужен сегмент C в регионе 8000...
Но она  его включит на нужное время и потом, уже при фактическом чтении, выключит.

Тут, вероятно, произошло наложение моих процедур, которые должны выполняться
в конфигурации памяти "пользователь" с процедурами дос, которые работают в своей карте.

Библиотечку поправил, ещё одна новая прога закончена.

Но вылез -то этот сюрприз (и не вылезал до сих пор) именно потому, что, в зависимости
от некоторых действий пользователя (NEW, FP, CALL-151, BLOAD и может быть чего-то ещё)
программа, которую запускают по BRUN, может начать работу в разных конфигурациях памяти.
Я видел нередко варианты 01234567 и 0123CD67, но, вероятно, в каких-то случаях,
могут быть и другие варианты (может, в зависимости от версии ИКП).

Надо либо самому конфигурировать память в начале работы проги (но тогда надо знать, какие сегменты кем используются) или быть очень осторожным.

Провозился с этим багом почти весь день... Отпуск, называется :( Главное - пока не разберешся же - ни на что другое уже переключиться не можешь. Завтра будет расслабон - пойду в гараж, буду маслосъёмные колпачки менять. Там хоть сильно думать не надо :) Мот дымит, как будто стал двухтактным.

8

Re: Баги ИКП-ДОС

Может, не совсем по теме, но - чем отличается FP от NEW? Когда я только начинал баловаться Басиком, мне сразу объяснили, что FP действует круче NEW, лучше очищает память. И я пользовался FP, совершенно не думая о её отличиях от NEW. И вот, увидев упоминание, спустя три десятка лет, решил спросить :)

9 Отредактировано Voldemar0 (06-08-2019 05:15)

Re: Баги ИКП-ДОС

Насколько я могу понять: FP - это сокращение от Float Point - переключение в AppleSoft-бейсик, ну а противоположная команда - INT - переключение в Integer Basic.

Обе команды выполняются DOS'ом.

В то время как команда NEW - это команда бейсика.

Что конкретно они делают - точно не знаю, но предполагаю, что new - это только сброс состояния интерпретатора, в то время как FP и INT - сброс состояния как бейсика так и дос.

В Агате INT выпилен (не следует путать его с функцией "INT(") , причем если в Бейсик-60 сама команда ещё есть, но она даёт загадочную (для Агата), хотя и документированную ошибку "язык не доступен", то в ИКП её уже нет совсем.

А вот FP в ИКП, кроме прочего, проверяет целостность ДОСа и Бейсика в ОЗУ и может выдать ошибку "Система испорчена".

Фактически, FP действительно чистит больше, чем New, причем даже много больше.
Это было заметно и на семёрке, ещё в Бейсик-60.
Например, я столкнулся со следующим приколом в ИКП:
в наследство от эпла ДОС имеет две входных точки: $3D0 и $3D3.
Первая - завершение двоичной программы - в общем-то почти аналогична последнему RTS внутри функции main(). Разве что RTS в ДОСе не всегда срабатывает (в отличие от ДОК и BTK).
Вторая - перезапуск ДОС.

Так вот если программа занимает диапазон памяти от $1900 (регион бейсик- программы) или использует что-то в нулевой странице, то после её завершения по $3D0 бейсик приходит в довольно нестабильное состояние:
например, любая синтаксическая ошибка в командной строке вполне может его убить так, что приходится выключать машину.

А если вернуть управление на $3D3, то стабильность восстанавливается, но, правда, со спецэффектом: судя по всему, ДОС пытается запустить файл "HELLO", так же, как это происходит при загрузке.
Но поскольку у автозапуска имя хардкодед в буфере имени файла, а он меняется любыми командами
RUN/BRUN/LOAD... то получается, что дос пытается запустить последнюю запущенную программу, но
командой RUN. А так как последняя программа имеет тип B - возникает ошибка "ОШ. ТИП ФАЙЛА".

Такие вот пирожки ...
с котятами......
А я теперь раздумываю, какой же выход лучше использовать для своих прог.

Вообще, ИКП - вроде бы развитие от Бейсика-60, но уж очень многое там было приведено в несколько нелогичное состояние. Или добавлено новое, но чуть-чуть недоделано.