1 Отредактировано garnizon (25-04-2024 20:37)

Тема: Применение платы палитр в софте.

Собственно с чего-то надо начинать. Хоть с простой демонстрашки, которая картинки показывает стаями.

Возник вопрос, можно ли, и как, из ИКП-бейсика, обработать хвост графического файла?
http://agatcomp.ru/agat/PCutils/EXIF.shtml

Например, после "bload NAME", исходя из размера загруженного файла, найти сигнатуру "VR", и, если она есть, выдать на экран информацию, в расшифрованном виде.
Прям в текстовой странице: Режим, палитра ну и текст из области комментария конечно.

2

Re: Применение платы палитр в софте.

Насчет этого "хвоста" я вот чего не понимаю: он включается в длину файла или нет?

Просто у меня сложилось впечатление, что этот хвост добавляется именно в "пустую" с точки зрения DOS область файла типа B.
Вот как-то так:

+----------------------------------+-----+--------------------------+
|             Сектор 0             | ... |     Последний сектор     |
+---------+---------+--------------+-----+--------------+-----------+
| Адрес   | Длина   | Данные файла |     | Данные файла | "Хвост"   |
| 2 байта | 2 байта | 252 байта    |     | 4 байта      | 252 байта |
+---------+---------+--------------+-----+--------------+-----------+

То есть, если у нас ч/б картинка 256x256 (МГВР), то в поле "Длина" будет значение $2000.

Если это так, то последние 252 байта с точки зрения DOS не существуют, и доступ к ним стандартными средствами (командой BLOAD) получить нельзя. Их можно будет вычитать только прямыми вызовами RWTS, что плохо.

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

3 Отредактировано Voldemar0 (26-04-2024 06:05)

Re: Применение платы палитр в софте.

Теоретически можно без обращения к RWTS. ДОС читает диск блоками по 256 байт. Я не уверен, но предполагаю (судя по скорости работы команды BLOAD), что те блоки файла, которые должны быть прочитаны целиком, читаются сразу на адреса назначения. Но те, которые нужны не полностью, читаются сперва в промежуточный буфер, а потом часть сектора копируется в регион назначения. Соответственно, если знать адрес этого буфера, после BLOAD можно вытащить "хвост" оттуда. Это потребует привязок к конкретной версии ДОС, но работать должно.

Это не будет работать в Школьнице и её "наследниках": у RWTS есть параметр LAST - сколько байт нужно считать c диска. Там "хвост" будет теряться.

4

Re: Применение платы палитр в софте.

Так примерно (выводит комментарий из VR):

3 REM Этот код работает только в ИКП-Бейсике-9
5 REM Для других версий бейсика нужно подбирать смещение буферов ДОС

7 BUF%=$1F00

10 *$30A:
20 ! LDY $C150
30 ! LDX #0
40 ! STA $C15D
50 ! L:LDA $B107,X ! STA BUF%,X ! INX ! BNE L
80 ! STA $C100,Y
90 ! RTS !:

100 HOME
110 ? "Выберите файл-картинку:"
120 ?:?CHR$(4)"BLOAD?,A$2000"
130 CALL $30A

200 ? CHR$(30+128) : ?
210 IF PEEK(BUF% + 4) <> ASC("V") THEN 900
220 IF PEEK(BUF% + 5) <> ASC("R") THEN 900

300 FOR L = 4 TO 15
310   FOR C = 0 TO 15
320     S% = PEEK(BUF% + L * 16 + C)
330     ? CHR$(S%);
340   NEXT C
350   ?
360 NEXT L
370 STOP

900 ? "В этом файле нет VR-расширения"
910 STOP
Post's attachments

Attachment icon VR.FIL 808 b, 105 downloads since 2024-04-27 

5

Re: Применение платы палитр в софте.

С этим кодом обнаружилась странность.

Последовательность шагов для воспроизведения такая:
1) запускаем программу и загружаем какой-нибудь файл с картинкой и расширением VR
2) запускаем программу еще раз и пытаемся загрузить файл неправильного типа (например, программу на Бейсике). Программа падает с ошибкой "Неверный тип файла"
3) снова запускаем программу. Теперь, какую бы мы картинку не пытались загрузить, программа будет показывать расширение VR от файла, загруженного на шаге 1.

Такое ощущение, что ДОС после ошибки меняет адрес буфера. Я еще подозревал, что меняется банк памяти, но как будто с этим все в порядке.

6

Re: Применение платы палитр в софте.

Я помню, что в dos33 была интересная особенность: сразу после загрузки с Бейсик-60 можно было дать любую ошибочную команду ДОС (например, LOAD с именем несуществующего файла) и ДОС не сообщала о каких-либо ошибках.
Но если дать команду, которая завершится правильно, то на следующие неправильные команды сообщения об ошибках уже появлялись.

Адрес буфера в этом софте вряд ли будет зависеть от большого количества случайностей, как у нынешних систем.
Если его адрес просто так меняется, это может косвенно свидетельствовать о какой-то ошибке управления памятью.
Например, если был запрос неверного типа файла и операция срывается, то какой-то блок памяти забывают освободить. И поэтому выделяют новый.

7

Re: Применение платы палитр в софте.

Voldemar0 пишет:

какой-то блок памяти забывают освободить

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

8 Отредактировано Voldemar0 (12-07-2025 15:40)

Re: Применение платы палитр в софте.

Так если его можно менять через MaxFiles - это и есть динамическая память.

Я помню ошибку с очисткой таких же буферов под Школьницей.
На форуме писал, несколько лет назад.

В ДОС же можно открыть файл и не закрывать его в одной операции. Сколько таких файлов будет - заранее неизвестно. Во всяком случае текстовых - легко. Другие типы - тоже можно, но посложнее (через FileMan).

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

Будет время - я гляну куда там что девается, по описанному тобой сюжету, лишь бы у нас версии ДОС совпали, их же несколько разных.

9

Re: Применение платы палитр в софте.

Voldemar0 пишет:

Так если его можно менять через MaxFiles - это и есть динамическая память.

Динамическая она с некоторой натяжкой. Хоть там и связанный список, но реально выделяется сплошная область памяти с фиксированного адреса. Причем, вся эта динамичность происходит только при запуске ДОС или вызове MAXFILES.
В тот момент, когда происходит ошибка в примере выше - никакая память не выделяется и не освобождается.

Насколько я понимаю, происходит следующее.
При старте ДОС создает набор буферов под 3 одновременно открытых файла. (3 - это настройка MAXFILES по умолчанию.)
Под каждый файл выделяется примерно 600 байт места (буфер данных, буфер TSL, имя файла и что-то еще).
При каждой операции с файлом ДОС выбирает свободный буфер. Если нет других открытых файлов, то этот буфер один и тот же, в данном случае $B107.
Но когда в примере выше происходит ошибка, то ДОС после этого по какой-то непонятной причине в качестве свободного выбирает следующий буфер, с адреса $B35A. И дальше пользуется им.

ДОС, как я понимаю, для освобождения буфера записывает нуль в первый байт имени файла. Как я вижу в эмуляторе, после ошибки имя файла, вызвавшего ошибку, сохраняется (адрес $B334). То есть, кажется файл не закрывается. Но в то же время, если спровоцировать ошибку еще несколько раз, то все продолжает работать, исчерпания количества открытых файлов не происходит. Видимо, проблемы именно с закрытием файла, использующего первый буфер.

Voldemar0 пишет:

лишь бы у нас версии ДОС совпали

Я проверял под ИКП-9.

10

Re: Применение платы палитр в софте.

Видимо, проблемы именно с закрытием файла, использующего первый буфер.

А, нет. Неправильно проверил :)

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

Но если попытаться через BLOAD загрузить 3 разных файла типа A, то буфера тоже будут использоваться разные. И после трех ошибок подряд на очередную попытку загрузки ДОС выдает ошибку "МНОГО ОТКРЫТЫХ ФАЙЛОВ".

Так что BLOAD файла типа A просто оставляет незакрытым файл. Независимо от номера буфера.

11

Re: Применение платы палитр в софте.

короче, надо найти какой-то указатель на последний используемый буфер ?

12 Отредактировано avivanov76 (14-07-2025 00:49)

Re: Применение платы палитр в софте.

Надо бы Игоря спросить, какой ему нужен результат.
Есть несколько вариантов что с этой ошибкой делать:
1) с кодом ничего не делать, просто повесить предупреждение, что при попытке загружать вместо картинок какие-то другие файлы программа сломается вдребезги пополам, поэтому лучше и не пытаться. Самый простой вариант.

2) попытаться найти указатель на последний используемый буфер. Мне этот вариант не очень нравится, потому что ошибочно выбранный файл остается открытым. А если пользователь три раза ошибется, то программа все равно сломается.

3) попробовать обработать ошибку и закрыть файл. Как оказалось, команда MAXFILES принудительно закрывает все открытые файлы, поэтому можно добавить такой обработчик ошибок:

96 ONERR GOTO 5000

5000 ER = PEEK(222)
5010 IF ER = 6 THEN STOP
5020 IF ER <> 13 THEN GOTO 5050
5030 PRINT "НЕВЕРНЫЙ ТИП ФАЙЛА": GET A$
5040 PRINT: PRINT CHR$(4)"MAXFILES 3"
5050 RESUME

В ячейке 222 лежит код ошибки ДОС. В строке 5010 сделана проверка на код ошибки "файл не найден". Я сделал тут выход из программы если вместо выбора файла нажали "РЕД". Если такая проверка не нужна, можно эту строку убрать.
В строке 5020 сделана проверка на код ошибки "Неверный тип файла", в строке 5030 вывод текста ошибки, а в строке 5040 - собственно выполнение команды MAXFILES.

Понятно, что костыль, и лучше бы исправить ДОС, но это уж очень тяжелый вариант.

Вообще, пора уже как у Майкрософта базу знаний багов заводить (Knowledge Base). И все ошибки туда под номерами складывать, а то информация растекается по разным темам форума и фиг ее потом найдешь.

13 Отредактировано Voldemar0 (14-07-2025 11:42)

Re: Применение платы палитр в софте.

Значит надо порыться и посмотреть, во всех ли версиях Бейсик-ИКП-9 есть эта ошибка.
А заодно и по другим архитектурам и НЕ-ИКП тоже пошерстить.
Даже, наверное, стоило бы начать от эпловского бейсика/ДОСа.
Может к ним есть упоминание такой проблемы ?

14

Re: Применение платы палитр в софте.

Баг, похоже, застарелый :)
Он есть в Apple DOS 3.3, он есть в ДОС, который идет с Бейсик-60, он есть в ALV DOS, ИКП-7, ИКП-9 и ИКП-90 (который с поддержкой сети).

15 Отредактировано Voldemar0 (15-07-2025 06:20)

Re: Применение платы палитр в софте.

Возможно, где-то в ДОСе есть код, который называется как-то вроде "вывод сообщения об ошибке и завершение операции". И после любого IF с проверкой ошибочной ситуации стоит просто LDA#<код ошибки> / JMP на эту точку. В результате рессурсы, которые должны были быть освобождены при нормальном завершении, остаются брошенными.

Если так, то не только ошибка "Mismatch type file" будет приводить к незакрытым файлам, но и другие, связанные с открытием/закрытием файлов. LOAD, RUN, OPEN, READ, WRITE...

Но, в рамках топика, это всё равно возвращает к тому, что нужно выкопать указатель на последний выделенный блок и работать от него. Либо воткнуть в начало проги "MAXFILES 3".

16

Re: Применение платы палитр в софте.

Voldemar0 пишет:

И после любого IF с проверкой ошибочной ситуации стоит просто LDA#<код ошибки> / JMP на эту точку.

Кажется, все сложнее. Например, в коде LOAD есть принудительное закрытие всех открытых файлов, поэтому RUN и LOAD будут работать корректно.

К своему стыду обнаружил, что никогда не читал файлы на Агатовском Бейсике :) Пришлось повозиться с написанием тестовой программки, которая открывает 4 файла неправильных типов. Без ONERR GOTO этого не сделать (программа вылетает), но RESUME передает управление в то место, где возникла ошибка, поэтому файл начинает открываться до бесконечности. Плюс, у ONERR GOTO какие-то странные отношения с циклом FOR. Но ничего, выкрутился. Программка тоже отработала корректно - открытые файлы не накапливаются. По крайней мере, у OPEN проблем нет.

Интересный момент - это то, что в тексте кода BLOAD есть комментарий "(CHANGED 11/1/78 FOR TYPE MISMATCH)". Дело в том, что к 1 ноября 1978 разработчик ДОС над ней больше работал - он еще летом передал код Apple. То есть, эту проверку типов добавляли программисты Apple. И, видно, что-то пошло не так :)

И еще два наблюдения навеянные этой багой:
1) Если в современных операционках написать программу на C, которая открывает два раза один и тот же файл, то получится два разных дескриптора. Используя их, можно, например, читать файл из разных точек. Но если попытаться то же самое сделать в ДОС (например, через вызовы файлового менеджера), то в момент второго вызова OPEN ранее открытый файл закроется и первый дескриптор станет недействителен. То есть в ДОС в принципе другой подход (один файл - один дескриптор).

2) Файл-менеджер для ИКП явно переделывали - структуры данных для открытых файлов больше по размеру и устроены иначе. То есть, исходники у разработчиков были достаточно подробные и поправить баг они в теории могли.

17 Отредактировано Voldemar0 (18-07-2025 08:26)

Re: Применение платы палитр в софте.

> ONERR GOTO

У этой штуки очень много приколов и хитростей (один только доступ к статусам через PEEK чего стоят). Про неё уже где-то писали интересное, в 90-х (возможно, у Волкова или у Серкова).

п1 как бы даже не удивляет. Не тот уровень разработки, а виласапет новый.
"Танк секретный, физики могли не знать" :)

п2 ... так же как и добавить новых багов.

Понятно, что раз они перетаскивали всё на новые адреса, исходники у них были.
И мы даже примерно представляем себе - какие.
Не то, чтобы подробные, но это не мешало их править во все стороны.

В ИКП, например, команда BLOAD умеет читать текстовые файлы. В DOS3.3 такое даже вообразить невозможно было.

----

Однажды, когда нибудь, я причешу все эти исходники и разберу их по частям.
Но не в этом десятилетии, видимо :(

18

Re: Применение платы палитр в софте.

А может быть вообще по другому зайти: когда читается файл, последним будет прочитан этот последний сектор. Значит в таблице параметров RWTS будет его адрес (как Т/С так и адрес в ОЗУ). Адрес таблицы параметров RWTS в любом ДОСе из числа DOS3.3 и его наследников можно узнать через вектора в регионе $3Fx.

19

Re: Применение платы палитр в софте.

Т.е. после загрузки файла еще одно обращение к диску для чтения хвоста?

20 Отредактировано Voldemar0 (21-08-2025 17:36)

Re: Применение платы палитр в софте.

Вот как-то так:

5 BUF%=$1F00

100 *$30A:

REM   Получаем адрес таблицы параметров RWTS
110 ! JSR $3E3
120 ! STA $E1
130 ! STY $E0

REM   Сохраняем состояние 5 сегмента ОЗУ
140 ! LDX $C150

REM   Вытаскиваем из таблицы параметров адрес последнего сектора, запрошенного у RWTS
150 ! LDY #8
160 ! LDA ($E0),Y
170 ! PHA
180 ! INY
190 ! LDA ($E0),Y
200 ! STA $E1
210 ! PLA
220 ! STA $E0

REM   Переливаем последний прочитанный сектор в BUF%
230 ! LDY #0
240 ! STA $C15D
250 ! L:LDA ($E0),Y
260 ! STA BUF%,Y
270 ! INY
280 ! BNE L

REM   Восстанавливаем состояние 5 сегмента ОЗУ
290 ! STA $C100,X

REM   Fin
300 ! RTS
310 !:

500 HOME
510 ? "Выберите файл-картинку:"
520 ?:?CHR$(4)"BLOAD?,A$2000"
530 CALL $30A

600 ? CHR$(30+128) : ?
610 IF PEEK(BUF% + 4) <> ASC("V") THEN 900
620 IF PEEK(BUF% + 5) <> ASC("R") THEN 900

700 FOR L = 4 TO 15
710   FOR C = 0 TO 15
720     S% = PEEK(BUF% + L * 16 + C)
730     ? CHR$(S%);
740   NEXT C
750   ?
760 NEXT L
770 STOP

900 ? "В этом файле нет VR-расширения"
910 STOP