Вход

Просмотр полной версии : Как лучше всего работать со строками и внешним устройством?



Uporot
09.04.2010, 07:37
Суть такова: я немного модифицирую эмулятор qaop и могу добавлять различные обработчики к портам, в принципе можно и новые оп-коды к процессору, но не хотелось бы.

Задача примерно такая: некоторому виртуальному устройству (которое сидит на порту 0x1234, например) передать строчку вида "cat /dev/storage/filename.log | tail -n20", а обратно получить ответ в виде текста.

Как это лучше реализовать? Пока вижу что-то вроде RANDOMIZE USR 45000: REM set ram: 47500, cmd cat /dev/storage/...., а потом по адресу 47500 ловить искомый текст. НО! Хотелось бы это как-то красиво с бейсиком подружить, а вот как - не знаю. Есть идеи? Чего бы зачитать на тему такой интеграции?

psb
09.04.2010, 08:13
Есть идеи?
для интеграции с бейсиком может быть полезно сделать такое через потоки ввода вывода, чтобы работать через PRINT #x.

Uporot
09.04.2010, 19:54
Эм, а где бы зачитать? Спектрум я видел живьем очень давно, забыл все нафиг, был бы рад примерам и какой-то литературе. Алсо, возвратить текст в переменной - это реально? Хотелось бы что-то вроде LET a$=......"cat /dev/storage/file.txt | grep test | tail -n20" и получить ответ, т.е. одной строкой все.

psb
09.04.2010, 20:15
даже не скажу щас где.. или в книжке Родионова и Ларченко "ZX-Spectrum для пользователей и программистов", или в какой инфоркомовской... но где-то я это оч давно видел. смысл такой. если делать PRINT #0, то печатать будет в 2х нижних строках экрана, если #2, то как обычно. так же можно делать и INPUT #x. идея заключается в создании своего собственного канала, например, #3, #4... можно определить подпрограммы, в которые будет поступать строка, и из которой будет получаться строка. как-то так. так что греп на спеке вполне реален.

GriV
09.04.2010, 23:14
получить текст в басик почти реально.
Можно сделать
let b_var = usr <xxxx>
тогда b_var будет содержать то, что было в регистровой паре bc.

Для вашей задачи проще было бы вначале сделать print #y "<строка>" и затем делать let b_var = usr <xxxx> - которая вернёт адрес asciiz-строки, которая может быть (если небольшая), например в буфере принтера или в любой другой удобной области.
Вернуть текст напрямую в какую-либо переменную - это много сложнее (там надо писать достаточно сложный обработчик).

Uporot
10.04.2010, 01:29
Вернуть текст напрямую в какую-либо переменную - это много сложнее (там надо писать достаточно сложный обработчик).

Насколько сложный? Я так понимаю, что надо будет проэмулировать вызов LET R$="_200 байт_", получить указатель на сегмент памяти этой строки, после чего по print #123/usr 45123 сделать запись в эту строчку на уровне самой виртуальной машины, не? Вот только учебника по бейсику у меня нету, где и чего он там хранит и как выделяет память под строчки. Например, насколько сложно будет строчку "123" переделать в "12345".

Barmaley_m
12.04.2010, 16:05
Вернуть текст напрямую в какую-либо переменную - это много сложнее (там надо писать достаточно сложный обработчик).
Да ничего сложного, нужно пользоваться командой INPUT #x или INKEY$ #x.

Например
10 INPUT #3, a$
вернет строку, если канал 3 открыт на нужный поток.
или
20 INPUT #3, LINE a$
вернет строку, но без необходимости заключать ее в кавычки для устройства, формирующего ее.
или
30 LET b$ = INKEY$ #3
вернет один символ из потока.

Все это сделано в TR-DOS, там организован текстовый ввод и вывод в файлы. Изучайте исходники TR-DOS, чтобы понять, как это сделать лучше всего.

Аналогично реализовано в ZX Interface 1, там тоже есть ввод и вывод в файлы на микродрайве и ввод/вывод по локальной сети. Можно изучить исходники ZX Interface 1 ROM (где-то в сети валяется полный дизассемблер с комментариями). Но Interface 1 для нашей страны экзотика, так что лучше все-таки поизучать TR-DOS, тем более что тут на форуме дизассемблер с русскими комментариями даже пробегал.

Но это что касается реализации - то нужно изучать исходники, а для того, чтобы изучить, как пользоваться "родными" функциями бейсика вроде PRINT#, INPUT#, INKEY$ #, в частности - для ввода/вывода в файлы или по локалке - это нужно читать какое-нибудь описание бейсика и TR-DOS для пользователей - вроде книги Ларченко/Родионова. Или английский мануал к Interface 1.

Uporot
14.04.2010, 01:20
Некоторый промежуточный итог и ссылки:

The INPUT # statement is slightly more complicated in that is can both read and write data, as in INPUT "What is your name? "; A$. In fact each stream really has two components, an input stream and an output stream.

Т.е. можно отправлять запрос и читать ответ 1 простой командой, как я и хотел.

http://www.worldofspectrum.org/ZXBasicManual/zxmanchap24.html - карта памяти, где чего лежит
http://www.worldofspectrum.org/ZXBasicManual/zxmanchap25.html - системные переменные с указателями
http://www.worldofspectrum.org/faq/reference/48kreference.htm - хорошая статья о каналах

Я так понял, что: пишу 5 байт недалеко от начала CHANS (а почему в асмовой вставке от конца?), указывающие на 2 процедурки (чтения и записи), но вот что мне передадут туда? Я так понимаю, что данные для записи будут уже куда-то записаны и мне останется ловить указатель, но где именно? Аналогично несовсем понятно, как обработать операцию чтения. Завтра еще погуглю, может чего вкусного найду

psb
14.04.2010, 09:12
не уверен, но возможно будешь ловить кучу раз по одному символу.

Barmaley_m
15.04.2010, 15:24
Чтобы добавить новый тип потока в область информации о потоках, необходимо "расширить" эту область, ведь она уже забита. Для этого в ПЗУ бейсика есть процедура MAKE_ROOM (адрес не помню) - она раздвигает все бейсиковские структуры памяти, модифицирует системные переменные и т.д. Освобождение памяти - процедура RECLAIM2.

В таблицу добавляется новый поток с какой-нибудь буквой. Туда же помещаются адреса двух процедур - ввода символа и вывода символа. Если поток работает только в одном направлении, то процедура ввода/вывода в противоположном направлении должна указывать на подпрограмму печати сообщения об ошибке J Invalid I/O device. Адрес этой подпрограммы хранится в информации о потоках для потоков S и P, например, потому что из них невозможен ввод.

К сожалению, открывать каналы штатной командой Бейсика OPEN # не получится, из-за бага в бейсике. Поэтому реализация тех функций, которые должна была выполнять эта команда, возлагаются на пользовательскую программу. Все это сделано в TR-DOS и Interface 1 ROM, можно исходники изучать.

Закрывать каналы командой Бейсика CLOSE# возможно, но при этом поток не будет уведомлен о закрытии, т.е. если это файл на диске - то TR-DOS не узнает, что его надо закрыть. Чтобы закрыть поток (а не канал, к которому он присоединен), необходимо опять же, городить что-то свое. При этом поток должен быть удален из области информации о потоках.