Просмотр полной версии : Как лучше всего работать со строками и внешним устройством?
Суть такова: я немного модифицирую эмулятор qaop и могу добавлять различные обработчики к портам, в принципе можно и новые оп-коды к процессору, но не хотелось бы.
Задача примерно такая: некоторому виртуальному устройству (которое сидит на порту 0x1234, например) передать строчку вида "cat /dev/storage/filename.log | tail -n20", а обратно получить ответ в виде текста.
Как это лучше реализовать? Пока вижу что-то вроде RANDOMIZE USR 45000: REM set ram: 47500, cmd cat /dev/storage/...., а потом по адресу 47500 ловить искомый текст. НО! Хотелось бы это как-то красиво с бейсиком подружить, а вот как - не знаю. Есть идеи? Чего бы зачитать на тему такой интеграции?
Есть идеи?
для интеграции с бейсиком может быть полезно сделать такое через потоки ввода вывода, чтобы работать через PRINT #x.
Эм, а где бы зачитать? Спектрум я видел живьем очень давно, забыл все нафиг, был бы рад примерам и какой-то литературе. Алсо, возвратить текст в переменной - это реально? Хотелось бы что-то вроде LET a$=......"cat /dev/storage/file.txt | grep test | tail -n20" и получить ответ, т.е. одной строкой все.
даже не скажу щас где.. или в книжке Родионова и Ларченко "ZX-Spectrum для пользователей и программистов", или в какой инфоркомовской... но где-то я это оч давно видел. смысл такой. если делать PRINT #0, то печатать будет в 2х нижних строках экрана, если #2, то как обычно. так же можно делать и INPUT #x. идея заключается в создании своего собственного канала, например, #3, #4... можно определить подпрограммы, в которые будет поступать строка, и из которой будет получаться строка. как-то так. так что греп на спеке вполне реален.
получить текст в басик почти реально.
Можно сделать
let b_var = usr <xxxx>
тогда b_var будет содержать то, что было в регистровой паре bc.
Для вашей задачи проще было бы вначале сделать print #y "<строка>" и затем делать let b_var = usr <xxxx> - которая вернёт адрес asciiz-строки, которая может быть (если небольшая), например в буфере принтера или в любой другой удобной области.
Вернуть текст напрямую в какую-либо переменную - это много сложнее (там надо писать достаточно сложный обработчик).
Вернуть текст напрямую в какую-либо переменную - это много сложнее (там надо писать достаточно сложный обработчик).
Насколько сложный? Я так понимаю, что надо будет проэмулировать вызов 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.
Некоторый промежуточный итог и ссылки:
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 процедурки (чтения и записи), но вот что мне передадут туда? Я так понимаю, что данные для записи будут уже куда-то записаны и мне останется ловить указатель, но где именно? Аналогично несовсем понятно, как обработать операцию чтения. Завтра еще погуглю, может чего вкусного найду
не уверен, но возможно будешь ловить кучу раз по одному символу.
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 не узнает, что его надо закрыть. Чтобы закрыть поток (а не канал, к которому он присоединен), необходимо опять же, городить что-то свое. При этом поток должен быть удален из области информации о потоках.
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot