Это статья написана на основе документации User's manual in english, version 1.11, оригинал
Автор: Nestor Soriano (Konami Man), Декабрь 2004
Nestor Soriano также является автором Nextor
Официальная страница NestorBASIC
Перевод документации выполнил: ATroubleshooter, 2021–2022
Перевод документации NestorBASIC version 1.11 на русский (в работе)
NestorBASIC — это набор подпрограмм(функций, процедур) в машинном коде, интегрированных в один файл, предназначенных для использования в программах, написанных на MSX BASIC. NestorBASIC обеспечивает, без утраты совместимости с MSX X-BASIC, следующую функциональность:
Все имеющиеся функции доступны через один единственный USR и массив целочисленных параметров, следовательно они полностью совместимы с MSX X-BASIC.
Собственно, сам компилятор MSX X-BASIC содержится в файле NBASIC.BIN
, и автоматически загружается при резидентной установке NestorBASIC.
NestorBASIC загружается в сегмент ОЗУ, не используемый MSX BASIC, так что нужен лишь небольшой объем основной памяти MSX BASIC (примерно 500 байт) для программы перехода. Остальная основная память MSX BASIC свободна для программы на Бейсике.
NestorBASIC работает на любой MSX2/2+/Turbo-R с как минимум 128 кБ страничной памяти. В случае с MSX-DOS 2 нужен хотя бы один свободный сегмент ОЗУ в первичном маппере (два, если собираетесь использовать проигрыватели музыки. См. раздел 8 для подробностей).
Файл | Размер (байт) | Контрольная сумма MD5 | Описание |
---|---|---|---|
NestorBASIC 1.11 | 58539 | 42f1a7d5d3fe2281c743f4283fc4f4a9 | оригинал |
Этот архив содержит все исходные файлы для сборки.
Для сборки из исходного текста рекомендуется использовать среду разработки Compass, либо кросс-ассемблер SjAsm на ПК.
Для загрузки NestorBASIC, просто выполните в MSX BASIC команду:
BLOAD"NBASIC.BIN",R
Также можно выполнить вызов из файла автозапуска:
10 BLOAD"NBASIC.BIN",R:NEW
Ни предварительных, ни последующих команд CLEAR
и DEFUSR
не требуется. Если все прошло без ошибок, мы получаем следующее:
USR
[USR0
(параметр) или просто USR
(параметр)] указывает на вышеупомянутую программу перехода — это обработчик вызовов функций NestorBASIC.USR
(функции для работы с файлами и функции обработки строк требуют собственный строковый массив, который нужно объявлять отдельно. См. раздел 4 для подробностей). Первые пять элементов P инициализированы следующим образом:P(0) | Количество доступных сегментов памяти, или код ошибки |
P(1) | Мажорная версия NestorBASIC |
P(2) | Минорная версия NestorBASIC, в формате BCD (должна показываться в шестнадцатеричном формате) |
P(3) | Мажорная версия MSX-DOS |
P(4) | Минорная версия MSX-DOS, в формате BCD (должна показываться в шестнадцатеричном формате) |
Число доступных сегментов ОЗУ всегда будет как минимум 5. Меньшее значение в P(0) будет отражать код ошибки, возникшей при резидентной установке NestorBASIC:
0 | Компьютер не имеет страничной памяти, или в нем только 64кБ страничного ОЗУ |
1 | Дисковая ошибка при чтении NestorBASIC или MSX X-BASIC из файла NBASIC.BIN |
2 | Нет свободных сегментов в первичном маппере. Эта ошибка может появиться только под MSX-DOS 2) |
3 | NestorBASIC уже установлен. Все переменные были переинициализированы |
4 | Не определено в этой версии |
После резидентной загрузки NestorBASIC можно резервировать память для других резидентных подпрограмм в обычном порядке, т. е. использовать команду CLEAR
для установки начала зарезервированной области.
Тем не менее, в связи с тем, что NestorBASIC производит переключения слотов/сегментов в странице 2, и интерпретатор MSX BASIC располагает стек в области памяти ниже области строковых переменных и области, зарезервированной для пользователя, есть нижний предел для адреса, устанавливаемого командой CLEAR
.
А конкретно, нельзя зарезервировать память с адреса меньше, чем определяется
данной формулой:
&HC000 + (MAXFILES+1)*267 + FRE("") + 100
Также, помните, что команда CLEAR
, как и загрузка/очистка/модификация программы
на MSX BASIC стирает все переменные. В этом случае, массив P должен быть переопределён командой DEFINT P:DIM P(15)
, и это должно быть сделано вне блоков компиляции (далее — турбо-блоков). Также, должен быть переопределен массив F, если требуется (см. раздел 4 для подробностей о массиве F). Если нужно объявить массив F внутри турбо-блока, необходимо сделать это в первой строке турбо-блока, чтобы обезопасить использование функций NestorBASIC:
10 'save"autoexec.bas" 20 BLOAD"nbasic.bin",R:IF P(0)<5 THEN PRINT "Error!":END 30 CLEAR 100:DEFINT P:DIM P(15) 40 _TURBO ON(P()) 50 DIM F$(1) 'See section 4 ... 65000 _TURBO OFF 65010 RUN"next.bas" 10 'save"next.bas" 20 DEFINT P:DIM P(15) 30 _TURBO ON(P()) 40 DIM F$(0) 'If F$(1) is not needed. See section 4.1 ... 65000 _TURBO OFF
Также, помните, что нулевой USR
всегда зарезервирован за NestorBASIC как служебный вызов. Вызовы с USR1
по USR9
не заняты.
Страничное ОЗУ компьютеров MSX организовано в сегменты по 16 кБ. Каждый слот ОЗУ содержит определённое число S сегментов (нумеруемых от 0 до S-1), доступных, когда они подключены в адресное пространство активного слота памяти, что контролируется через порты с &HFC по &HFF.
При загрузке NestorBASIC, все имеющиеся слоты сканируются на наличие ОЗУ (всей памяти в случае MSX-DOS 1, всей свободной памяти в случае MSX-DOS 2), и строится таблица сегментов. В этой таблице, все найденные сегменты регистрируются в пары слот-сегмент (под MSX-DOS 2, сегменты сначала выделяются). NestorBASIC идентифицирует каждую из этих пар по порядковому номеру в таблице. Этот номер называется номером логического сегмента, и позволяет пользователю оперировать всей доступной памятью в последовательном виде, не заботясь ни о номерах слотов, ни о номерах физических сегментов, в которых она находится. Например, представим MSX с 128 кБ внутренней RAM (8 сегментов) и маппер на 1024 кБ (64 сегмента) во внешнем слоте. Тогда, после инициализации NestorBASIC, в случае MSX-DOS 1, пользователю будет доступно 72 логических сегмента, под номерами от 0 до 71, и достаточно указать этот номер в соответствующих функциях NestorBASIC для их использования. Номера физических слотов и сегментов уже не потребуются.
Адресное пространство логического сегмента (далее — просто «сегмента») от &H0000 до &H3FFF. Если заданы более высокие адреса при вызове функций NestorBASIC, они будут преобразованы. То есть, адреса &H4000–&H7FFF, &H8000–&HBFFF и &HC000–&HFFFF эквивалентны &H0000–&H3FFF при доступе к сегментам ОЗУ через NestorBASIC.
Все сегменты доступны для чтения и записи, но есть важные ограничения по отношению к первым шести:
Но если используются музыкальные плееры, при инициализации они занимают этот сегмент. См. раздел 8 для подробностей.
Все оставшиеся сегменты — в полном распоряжении программиста.
Внимание: логические сегменты 2 и 4 поменялись ролями при переходе с версии 0.07 на версию 1.00 NestorBASIC. В версии 0.07 и ранее, сегмент 2 был служебным буфером NestorBASIC, а сегмент 4 соответствовал странице 2.
При использовании функций обмена блоками данных, нужно быть осторожным, чтобы сумма адреса назначения и длины пересылаемого блока не превысила адрес &H3FFF (например, не пытайтесь переслать &H2000 байт указывая адрес &H3000 как адрес назначения). В таком случае, сегмент 0 или сегмент 3 будут перезаписаны, и результат будет непредсказуем.
Внимание: с помощью функции 80 можно указать NestorBASIC зарезервировать меньше сегментов памяти, чем суммарно доступно. Это полезно под MSX-DOS 2, когда одновременно используются другие резидентные программы, требующие выделения памяти (например, RAM-диск или NestorMan). Описание функций см. в разделе 10.
NestorBASIC позволяет использовать VRAM для ваших данных, путём эмуляции дополнительных сегментов ОЗУ. Если NestorBASIC показывает, что располагает S сегментами памяти, то номера сегментов с 0 по S-1 соотносятся со страничной RAM, тогда как номера сегментов с S по S+7 (или S+3, в зависимости от объёма видеопамяти, 128 кБ или 64 кБ) соотносятся с VRAM.
Вернёмся к компьютеру из предыдущего примера. После резидентной загрузки NestorBASIC или после вызова функции 1 (см. список функций) получаем P(0)=72. Это значит (предполагая, что у нас 128 кБ видеопамяти), что сегменты с 72 по 79 соотносятся с VRAM.
Соответствие между сегментами и адресами VRAM обратное: сегменты с меньшими номерами соответствуют наибольшим адресам VRAM. Это сделано так для того, чтобы помочь программисту при освобождении сегментов VRAM, соответствующих области отображения: это будет последний сегмент, при работе в текстовом режиме или при использовании лишь одной страницы в графическом режиме.
Вернёмся к предыдущему примеру: компьютеру с 72 сегментами RAM и 128 кБ VRAM. Если программа работает в текстовом режиме, используются только первые 2000 байт VRAM: это видео-ОЗУ соответствует последнему сегменту VRAM, под номером 79. В этом случае, программист может свободно использовать сегменты с 72 по 78, и диапазон доступных сегментов будет 0–78, без необходимости пропускать какой-либо сегмент внутри этой последовательности.
Если программа работает в SCREEN 5
и использует только графическую страницу 0, диапазон сегментов будет с 0 по 77; в SCREEN 7
он будет с 0 по 75, и т.д.
Конечно, NestorBASIC также имеет функции для работы с VRAM напрямую, без эмуляции в ней сегментов RAM. Эти функции позволяют пересылать данные VRAM ↔ RAM и VRAM ↔ файл.
Внимание: сегменты VRAM могут использоваться — как и обычные сегменты RAM — для размещения данных и программ на MSX BASIC, а также для блоковых операций обмена с диском и сегментами RAM. Но учтите, что сегменты VRAM не могут быть использованы для:
Если Вы попытаетесь использовать сегменты VRAM для какой-то из этих целей, функция вернёт ошибку «несуществующий сегмент».
Логический сегмент 255 имеет особое предназначение. Он соотносится не с каким-то конкретным сегментом RAM или VRAM, а с основной памятью MSX BASIC, то есть — c ОЗУ используемым MSX BASIC по адресам &H8000–&HFFFF (к нему не применяются ни ограничения, ни преобразования адресов в диапазон &H0000—&H3FFF, как к другим сегментам). Это удобно использовать для обмена данными между каким–либо сегментом и переменной MSX BASIC или массивом переменных:
1 'Copy 10 bytes from segment 7, begin address &H1000, 2 'to integer array D. 3 '(See section 10 for detailed functions specification) 4 ' 10 DEFINT D:DIM D(4) '5 integer data = 10 bytes 20 P(0)=7 'Source segment 30 P(1)=&H1000 'Source begin address 40 P(2)=255 'Destination segment=BASIC main RAM 50 P(3)=VARPTR(D(0)) 'Destination begin address=D array 60 P(4)=10 'length 70 J=USR(10) 'Call to function 10 (block transfer between segments)
Резюмируя данный раздел, предоставим весь список имеющихся сегментов и их описание. S — это количество сегментов, возвращаемое в P(0) при резидентной загрузке NestorBASIC или при вызове функции USR0(1)
№ | Назначение | |
---|---|---|
0 | Сегмент NestorBASIC | |
1 | Сегмент MSX X-BASIC | |
2 | Основная память MSX BASIC, страница 2 (&H8000–&HBFFF) | |
3 | Основная память MSX BASIC, страница 3 (&HC000–&HFFFF) | |
4 | Сегмент служебного буфера | |
5 по S-1 | Память, доступная программе пользователя (если S>5) Если загружен музыкальный плеер, он находится в сегменте 5. См. раздел 8. |
|
VRAM | VRAM 64 кБ | |
S | &H1C000–&H1FFFF | &HC000–&HFFFF |
S+1 | &H18000–&H1BFFF | &H8000–&HBFFF |
S+2 | &H14000–&H17FFF | &H4000–&H7FFF |
S+3 | &H10000–&H13FFF | &H0000–&H3FFF |
S+4 | &H0C000–&H0FFFF | — |
S+5 | &H08000–&H0BFFF | |
S+6 | &H04000–&H07FFF | |
S+7 | &H00000–&H03FFF | |
S+8 до 254 | Отсутствуют (если S+8<255) | |
255 | Основная память MSX BASIC (&H8000–&HFFFF) |
Все функции доступа к RAM и/или VRAM возвращают код ошибки -1 в следующих случаях:
NestorBASIC включает функции для работы с файлами на диске и доступа к другим возможностям MSX-DOS, а именно:
Функции, доступные только под MSX-DOS 2:
Для передачи имён файлов и директорий, эти функции задействуют массив строковых переменных F$
. Четыре из них — поиск, переименование и перемещение файлов, а также обработка пути файлов требуют двух строковых элементов, для чего нужно, чтобы был объявлен массив F$
из двух элементов DIM F$(1)
. Остальным функциям требуется только одна строка; поэтому, если не будет использоваться ни одна из вышеперечисленных четырех функций, можно объявить массив F$
только из одного элемента DIM F$(0)
. Особенно это рекомендуется в случае использования MSX X-BASIC, потому что внутри турбо-блоков каждая строка занимает 256 байт, независимо от её реальной длины.
Также, нужно иметь в виду, что массив F$
должен объявляться сразу же после начала турбо-блока, следующей строкой:
1000 _TURBO ON(P()) 1010 DIM F$(1) или DIM F$(0) ... 65000 _TURBO OFF
ВАЖНО: Строковые переменные, определенные вне турбо-блока, равно как и другие переменные, не передаются в турбо–блок, и восстанавливаются после его завершения!
Пример.
10 A$="Outside" 20 _TURBO ON 30 A$="Inside":PRINT A$ 40 _TURBO OFF 50 PRINT A$
run Inside Outside
С NestorBASIC это правило по-прежнему верно, но со строками F$()
требуется дополнительная предосторожность. Если массив F$
использовался вне турбо-блока и будет затем объявляться внутри него — следующая строка должна быть помещена перед CALL TURBO ON
:
F$(0)=F$(0)+"":F$(1)=F$(1)+""
Эта строка не нужна, если не требуется сохранять прежнее состояние F$
, или если Вы не будете объявлять F$
внутри турбо–блока.
Ещё одно ограничение F$(0)
и F$(1)
— их длина ограничена 80 символами; остальные
символы будут просто отброшены функциями NestorBASIC, которым эти строки поданы в качестве входных параметров. Все эти ограничения не действуют для индексов выше чем 1, если в массиве F$
больше элементов; то есть, Вы можете объявить F$
из более чем двух элементов, и использовать элементы F$(2), F$(3)
… как обычно.
Помимо ошибки -1, описанной в разделе 3, функции работы с диском имеют собственные коды ошибок.
Следующие ошибки могут появиться только под MSX-DOS 1:
1 | Единый код ошибки MSX-DOS 1. Он может быть вызван следующими причинами:
Под DOS 2, каждая из вышеперечисленных ошибок имеет свой собственный код, никогда не равный 1. |
---|---|
2 | Неверный номер файла (нет открытых файлов с таким номером). |
3 | Слишком много открытых файлов. Максимальное число одновременно открытых файлов можно узнать посредством функции 1. |
Следующие ошибки одинаковы под MSX-DOS 1 и DOS 2, и имеют те же коды ошибок, что и их эквиваленты в MSX BASIC:
60 | Неисправная FAT |
---|---|
62 | Неверный диск (при изменении рабочего диска). |
68 | Диск защищен от записи. |
69 | Физическая ошибка диска. |
70 | Диск отсутствует. |
Специфичные для DOS 2, ошибки:
222 | Не достаточно свободной памяти для создания RAM-диска для открытия файла. |
---|---|
219 | Неверный диск (будучи частью пути или имени файла). |
218 | Неправильное имя файла. |
217 | Неправильный путь. |
215 | Файл не найден. |
214 | Каталог (директория) не найден. |
213 | Корневая директория заполнена. |
212 | Диск заполнен. |
211 | Файл уже существует (при переименовании или перемещении файла). |
210 | Некорректная операция перемещения директорий (каталог не может быть перемещён в один из своих подкаталогов). |
209 | Файл только для чтения (при попытке записи в файл). |
208 | Каталог не пуст (при попытке удаления каталога). |
207 | Некорректные атрибуты (при установке атрибутов файла/директории). |
206 | Некорректная операция с «.» или «..» |
205 | Существует системный файл с таким именем(при создании файла, любой существующий файл с таким именем автоматически удаляется, если только у него не установлен атрибут «системный»). |
204 | Директория с таким именем уже существует (аналогично случаю с системными файлами). |
203 | Файл с таким именем уже существует (при создании каталога). |
202 | Файл открыт (при удалении, переименовании или перемещении файла, или при изменении атрибутов с прямым указанием имени файла). |
199 | Достигнут конец файла (при чтении из файла). |
196 | Слишком много открытых файлов (при открытии файла). |
195 | Неправильный номер файла (больше 63). |
194 | Неверный номер файла (не принадлежит ни одному открытому файлу). |
188 | RAM-диск уже существует (при создании RAM-диска). |
187 | RAM-диск не существует (при удалении RAM-диска). |
NestorBASIC включает функции для сжатия графических данных из VRAM в RAM, и распаковки из RAM в VRAM. Формат сжатия тот же самый, что используется в процедуре вывода логотипа Sunrise, он работает по–байтно по следующему принципу:
Неповторяющиеся байты (до 63) &B00nnnnnn &Hdd .. &Hdd &Bnnnnnn это количество байт, &Hdd это сами байты |
Повторяющиеся байты (до 63 раз): &B01nnnnnn &Hdd &Bnnnnnn это количество повторений байта, &Hdd повторяемый байт |
Повторяющийся байт (до 16383 раз): &B10nnnnnn &Bnnnnnnnn &Hdd &Bnnnnnnnnnnnnnn количество повторений байта, &Hdd повторяемый байт |
Маркер окончания данных: &B11000000 = &HC0 |
(Де)компрессия осуществляется в последовательные сегменты; то есть, после (де)компресии из/в адреса &H3FFF сегмента S, процесс продолжается с адреса &H0000 сегмента S+1.
Функции компрессии/декомпрессии графики могут возвращать следующие коды ошибок:
-1 | Ошибка при сжатии или распаковке. Задан несуществующий сегмент, сегмент VRAM или 255-й. Также, эта ошибка появляется при указании некорректного адреса VRAM в любом из входных параметров. |
---|---|
5 | Ошибка при упаковке. Недостаточно сегментов для сжатия всего изображения. |
6 | Ошибка при распаковке. Найдены некорректные данные, или закончились сегменты, прежде чем встретился маркер окончания данных. |
NestorBASIC включает функции, которые позволяют Вам помещать программы на Бейсике в любой сегмент RAM или VRAM, актуализировать или запускать их, не теряя переменные исходной программы (из которой произведен переход в новую).
ВНИМАНИЕ: Чтобы использовать данные функции, нужно изменить адрес начала Бейсик-программы в основной памяти MSX BASIC с &H8000 на &H8003; это действие должно быть выполнено лишь однократно, и обязательно ПЕРЕД загрузкой NestorBASIC. Это можно сделать двумя способами:
POKE &HF676,4 POKE &H8003,0 NEW
1 'program.bas 10 IF PEEK(&HF676)<>4 THEN POKE &HF676,4:POKE &H8003,0:RUN"program.bas" 20 'From here, you can load NestorBASIC
Когда Вы актуализируете или запускаете программу, размещенную в сегменте, NestorBASIC сохраняет все переменные и массивы в сегменте 4; затем, копируется программа из желаемого сегмента в основную память MSX BASIC, и все ранее сохраненные переменные помещаются после программы, после чего обновляются соответствующие указатели в рабочей области MSX BASIC. И, наконец, будет осуществлено выполнение программы с первой строки, либо переход в интерактивный режим — в зависимости от примененной функции (запуск или актуализация).
Для того, чтобы программу на Бейсике можно было держать в сегменте и, в последствии, актуализировать или запустить, она должна там храниться со специальным заголовком, содержащим информацию о её длине, которая требуется для конкатенации уже существующих переменных с новой программой. Есть функция NestorBASIC, которая позволяет сохранить в файл активную программу с таким заголовком. В дальнейшем, просто загрузите этот файл в какой-нибудь сегмент с помощью дисковой функции, и программа готова к использованию — её можно актуализировать или выполнить в любой момент.
Очевидно, что если исполняется команда или строка, следующая за USR-функцией, которая актуализирует или запускает другую программу на BASIC, то это означает, что мы находимся в состоянии ошибки. Возможна одна из двух ошибок:
-1 | Заданный сегмент не существует. Эти функции поддерживают сегменты VRAM, но не сегмент 255. |
---|---|
-2 | Памяти MSX-BASIC не достаточно для новой программы и переменных. Случается, если актуализируемая/запускаемая программа больше, чем исходная. |
В этой группе собраны функции, предназначенные для:
SCREEN 0
Некоторые из этих функций требуют строковый массив F$ для передачи параметров и возврата результатов, в дополнение к целочисленному массиву P. Больше подробностей о массиве F$ см. в разделе 4.
Некоторые из внутренних процедур NestorBASIC могут вызываться из других машинных подпрограмм пользователя и использоваться прерыванием, определяемым пользователем. См. приложение 2 для детального описания использования этих процедур.
Редактор SEE (sound effects editor) для создания звуковых эффектов под PSG был разработан группой Fuzzy Logic, и использование звуковых эффектов, сделанных в этом редакторе, в коммерческих продуктах подразумевает отчисление небольшой суммы авторам. Больше деталей в приложении 4.
NestorBASIC включает музыкальные проигрыватели Moonblaster 1.4 и Moonblaster Wave для MoonSound версии 1.05
Эти плееры не загружаются автоматически вместе с NestorBASIC: вследствие своего большого размера, они не помещаются в сегмент ОЗУ NestorBASIC, и должны загружаться в отдельный сегмент. Поэтому, чтобы использовать плеер, его нужно загружать директивно. Одновременно может быть загружен лишь один плеер.
Функция 71 загружает и инициализирует желаемый плеер, оставляя его готовым к работе. Эта функция проверяет наличие 5-го сегмента и принадлежность его к первичному мапперу: если это так, то плеер загружается в этот сегмент, после чего сегмент более не доступен для программы пользователя. Если сегмент 5 не существует, или подключён не к первичному мапперу, плеер не будет загружен, и функция выдаст ошибку.
Файл NBASIC.BIN
содержит два варианта проигрывателя Moonblaster Wave: один для MSX2 / 2+ и Turbo-R в режиме Z80, а другой для Turbo-R в режиме R800. Если компьютер это Turbo-R, то NestorBASIC определяет, какой вариант загружать, в соответствии с тем, в каком режиме работает процессор в момент вызова функции 71. Заметьте, что если произведено переключение режима процессора, эту функцию нужно вызвать заново, чтобы загрузить соответствующий плеер: вариант для Z80 не работает в режиме R800, а вариант для R800 привносит ненужное замедление системы в режиме Z80.
После того, как плеер загружен, происходит поиск аудиочипов, и все найденные помечаются как активные. Подробности о включении и отключении аудиочипов см. в описании функции 73.
Как только плеер загружен, он может использоваться функциями NestorBASIC для:
Во время проигрывания музыки, все функции NestorBASIC работают как обычно, включая проигрывание PSG эффектов и использование прерываний, определяемых пользователем. Если NestorBASIC выгрузить из памяти, то воспроизводимая музыка будет автоматически остановлена.
Плеер Moonblaster 1.4 помещается в 4,5 кБ, следовательно — адресное пространство с &H1200 по &H3FFF сегмента 5 остаётся свободно, и может использоваться, например, для хранения воспроизводимой музыки. Это не работает в случае с плеером Moonblaster Wave, который занимает 5 сегмент полностью.
Аудиотреки Moonblaster 1.4 должны помещаться в один сегмент, поэтому их размеры ограничены 16кБ. Мелодии Moonblaster Wave могут занимать несколько сегментов подряд, максимум 3: если при разборе воспроизводимых аудиоданных NestorBASIC доходит до адреса &H3FFF, процесс продолжается с адреса 0 следующего сегмента.
Чтобы загрузить музыкальный трек Moonblaster Wave из файла, можно воспользоваться следующим примером:
1000 'Loading a music through consecutive segments, 1010 'starting in segment S, address A 1020 F$(0)="music.mwm":P(2)=S:P(3)=A 1030 E=USR(31):IF E<>0 THEN 10000 1040 P(4)=&H4000:E=USR(33) 1050 IF (E<>0 AND E<>1 AND E<>199) THEN 10000 1060 IF E=0 THEN P(2)=P(2)+1:P(3)=0:GOTO 1040 1070 E=USR(32):IF E<>0 THEN 10000 ... 10000 'Disk error E handling routine ...
ВНИМАНИЕ: Саундтрек Moonblaster Wave может располагаться, начиная с любого адреса в сегменте, потому что он продолжится в начале следующего сегмента. Тем не менее, как минимум первые 800 байт трека, содержащие таблицу паттернов и различные указатели, должны целиком быть помещены в один, начальный сегмент.
Функции проигрывания музыки могут возвращать следующие коды ошибок:
7 | Возвращается функцией активизации аудио-чипов, функцией паузы и функцией затухания, если если какой-то из входных параметров некорректен. |
---|---|
12 | Возвращается функцией старта воспроизведения и функцией включения аудио-чипов, если плеер не загружен. Остальные функции не выдадут ошибку в этом случае, они просто не сделают ничего |
Следующие ошибки могут произойти при выполнении функции запуска воспроизведения:
-1 | Указанный сегмент не существует, соотносится с VRAM, или это 255 сегмент. |
---|---|
12 | Плеер не загружен. |
13 | Музыка была записана в режиме EDIT и не может быть воспроизведена (плеер Moonblaster 1.4). По данному адресу нет трека Moonblaster Wave, или там находится трек Moonblaster Wave записанный в режиме EDIT (плеер Moonblaster Wave). |
14 | Уже проигрывается другая музыка в этот момент. |
Функция загрузки wavekit для Moonsound, помимо ошибок работы с диском, может вернуть такую ошибку:
15 | По данному смещению в указанном файле нет wavekit для Moonblaster Wave, или там находится wavekit, сохранённый не в режиме USER. |
---|
ВНИМАНИЕ: Плеер Moonblaster 1.4 не умеет различать, являются ли данные по конкретному адресу в действительности саундтреком Moonblaster 1.4, и лишь всецело полагается на первый байт для определения того, что это данные трека, сохранённого в режиме EDIT. Плеер Moonblaster Wave не имеет этой проблемы.
Функция загрузки плеера выдаёт такие же коды ошибок, как и функции для работы с диском, а также код -1 — если сегмент 5 не существует или не принадлежит первичному мапперу.
ДЛЯ СПРАВКИ: Аудиотреки Moonblaster Wave могут быть сохранены в файл в режимах EDIT и USER. Файлы, сохранённые в режиме EDIT, содержат максимум информации о музыкальном треке, и могут быть воспроизведены только в самом трекере (редакторе). Файлы, сохранённые в режиме USER, могут быть проиграны плеерами, и пригодны для встраивания в сторонние программы. Они предельно компактны, из них исключена вся избыточная информация — не задействованные в мелодии паттерны/инструменты/тоны. Названия инструментов и тонов также не сохраняются.
NestorBASIC имеет специальные функции, которые позволяют взаимодействовать с NestorMan (резидентный динамический менеджер памяти для MSX-DOS 2), пакетом InterNestor Suite (стэк TCP/IP для MSX-DOS 2) и InterNestor Lite (стэк TCP/IP для MSX-DOS), если эти программы запущены. Таким образом, возможна разработка приложений на Бейсике, которые используют динамические блоки памяти и связанные списки, а также Internet–приложения. Чтобы узнать, запущен ли NestorMan и InterNestor Suite, можно воспользоваться функцией 81. Процедура проверки наличия загруженного InterNestor Lite детально описана в разделе 9.4.
ВНИМАНИЕ: NestorMan и InterNestor Suite / InterNestor Lite имеют собственную документацию, описывающую их функции и процедуры. Эти программы доступны здесь.
NestorMan реализует систему логических сегментов, очень похожую на ту, что применяется в NestorBASIC. Оба пространства сегментов, NestorBASIC и NestorMan, полностью независимы друг от друга, за несколькими исключениями:
Если NestorMan и/или InterNestor Suite будут использоваться вместе с NestorBASIC, рекомендуется ограничить, с помощью функции 80, количество сегментов RAM, которые будут использоваться NestorBASIC. В противном случае, NestorBASIC зарезервирует для себя все доступные сегменты, и NestorMan не сможет задействовать резервы ОЗУ (необходимые для выделения блоков памяти, создания связанных списков и для отправки/получения данных в/из Интернета).
Для вызова функций NestorMan можно использовать 82-ю функцию; или можно использовать 58-ю функцию, указав хук EXTBIO (&HFFCA) в качестве адреса перехода, занеся &H2202 в регистровую пару DE, и номер функции в регистр C. См. описание функций в разделе 10.
При использовании NestorMan из NestorBASIC, обычно Вам придётся осуществлять передачу данных между сегментом NestorBASIC и сегментом NestorMan. Есть три способа сделать это:
Чтобы прочитать или записать единственный байт данных из/в сегмент NestorMan, проще всего использовать соответствующие функции, которые предоставляет NestorMan (функции 12 и 13).
Помните, что некоторые функции NestorBASIC используют сегмент 4 как служебный буфер для временного размещения данных. См. раздел 10 или приложение 1, чтобы узнать эти функции.
Методика, при использовании InterNestor Suite из NestorBASIC, схожа с той, что применяется для работы с NestorMan. Единственно, нужно иметь в виду следующее:
допускают использование только сегментов TPA как источника/назначения данных или датаграмм. Для этой цели можно использовать последнюю часть сегмента NestorBASIC (сегмент 0) как временный буфер. Это свободное пространство всегда будет, как минимум, размером 600 байт, независимо от используемой версии NestorBASIC.
Этого достаточно для размещения стандартной датаграммы до 576 байт длинной (или для размещения блока данных TCP до 600 байт включительно).
Пример программы TCPCON-S.BAS
(см. здесь), поставляемый с NestorBASIC, иллюстрирует использование NestorBASIC'а совместно с InterNestor Suite.
ВНИМАНИЕ: InterNestor Suite это устаревшее ПО и не рекомендуется к спользованию. Если Вам нужен рабочий стэк TCP/IP, посмотрите в сторону InterNestor Lite.
InterNestor Lite это гораздо более простая программа, чем InterNestor Suite, поэтому использовать её из NestorBASIC также проще. Предоставляется единственная функция (функция 86), которая позволяет выполнять несколько процедур из сегмента кода InterNestor Lite. Чтобы читать или писать в его сегмент данных, необходимо использовать процедуры GET_VAR
, SET_VAR
и COPY_DATA
, которые находятся в сегменте кода.
Чтобы узнать, запущен InterNestor Lite или нет, используйте функцию 58 для вызова хука EXTBIO
(адрес &HFFCA), передав A=0 и DE=&H2203. Если подпрограмма вернула A≠0, значит InterNestor Lite запущен. Больше подробностей в описании функции 86.
Многие из процедур InterNestor Lite используют адреса TPA как источник либо назначение для обмена данными с приложениями. Для таких процедур можно указать адреса выше &H8000, которые соответствуют основной памяти MSX BASIC и рабочей области системы; или адреса ниже &H4000, которые соответствуют сегменту NestorBASIC (сегмент 0).
В конце сегмента NestorBASIC есть свободная область, размер которой варьируется, в зависимости от версии NestorBASIC, но никогда не бывает меньше, чем 600 байт. Эта область может быть использована как временный буфер для обмена данными с InterNestor Lite. Другими словами, можно использовать диапазон от H3DA8 до &H3FFF в качестве TPA области — источника или приёмника для обмена данными между NestorBASIC и InterNestor Lite.
Пример программы TCPCON-L.BAS
(см. здесь), поставляемый с NestorBASIC, иллюстрирует использование NestorBASIC совместно с InterNestor Suite.
Функция 86 (вызов процедуры InterNestor Lite) возвращает ошибку -1, если InterNestor Lite не обнаружен.
Функция 85 (вызов процедуры InterNestor Suite) возвращает ошибку -1, если InterNestor Suite не обнаружен, или если в P(0) указан недействительный номер модуля (действительны номера с 1 по 4).
Функции 83 и 84 (передача блоков данных между сегментом NestorMan и сегментом NestorBASIC) выдаёт ошибку -1, если задан несуществующий сегмент NestorMan или NestorBASIC. Эти функции могут использовать сегменты VRAM и 255-й сегмент.
Функции 80, 81 и 82 никогда не выдают ошибок.
Функции, которые составляют NestorBASIC, обозначаются числом, которое задаётся в качестве операнда команды USR
. Таким образом, чтобы использовать функцию номер F, Вам нужно просто выполнить USR(F)
, имея в виду, что если F — это переменная, то она должна быть целочисленного типа. Параметры для функций должны быть установлены в массиве P (и, в некоторых случаях, в массиве F$) перед вызовом функции. После выполнения, результаты функции записываются в те же массивы, P и/или F.
Элементы массивов P и F$, которые не упоминаются явно в списках результатов каждой функции, возвращаются неизмененными, за исключением адресов в сегменте — они приводятся к диапазону &H0000-&H3FFF (кроме адресов сегмента 255, которые никогда не конвертируются). Если функция возвращает ошибку, выходные параметры будут недействительными (P и F$ остаются неизменны), если иное не сказано в описании функции.
«Блок VRAM» соотносится либо с 64кБ нижней VRAM (блок 0), либо с 64кБ верхней VRAM (блок 1). Адреса VRAM имеют диапазон &H0000-&HFFFF. Если адрес VRAM переходит из &HFFFF в &H0000 путём автоинкремента, блок VRAM также изменяется (c 0 на 1, или с 1 на 0).
Команда USR
возвращает код ошибки, или 0, если ошибок не возникло. Коды ошибок, характерные для каждой группы функций, объяснены в соответствующих разделах.
Приложение 1 содержит полный список функций, который может быть полезен в качестве краткого справочника.
Функции, которые используют 4-й сегмент, имеют метку «(S4)» после их названий.
Это функции: 0, 26-28, 30, 33-41, 55-57, 71, 78, и 79.
Выгрузка NestorBASIC'а из памяти (S4)
Вход | P(0) = 0 | Не освобождать область основной памяти MSX BASIC, зарезервированную NestorBASIC |
---|---|---|
P(0) ≠ 0 | Освободить область основной памяти MSX BASIC, зарезервированную NestorBASIC | |
Выход | — |
Эта функция выгружает NestorBASIC: высвобождает USR
и, в случае MSX-DOS 2, освобождает все выделенные сегменты. Также, останавливаются все процессы, завязанные на прерывания (прерывания, определяемые пользователем, проигрывание звуковых эффектов PSG и музыки). Всегда следует выгружать NestorBASIC прежде чем вернуться в MSX-DOS; в противном случае, все зарезервированные сегменты ОЗУ не будут высвобождены, и, следовательно, не смогут быть использованы до перезагрузки компьютера.
Перед тем как выгрузить NestorBASIC, убедитесь, что не оставили открытых файлов. В противном случае, если в них осуществлялась какая-то запись, во внутренних буферах MSX-DOS могут оставаться несохраненные данные, которые будут потеряны. Вдобавок, в случае с MSX-DOS 2, не высвобождаются дескрипторы открытых файлов (file handles).
Если функции передано P(0)=0, то область основной памяти MSX BASIC, занятая обработчиком вызовов NestorBASIC (примерно 500 байт) не освобождается, что оставляет в силе схему распределения памяти, заданную командами CLEAR
после загрузки NestorBASIC. Если функции передано P(0)≠0, схема распределения ОЗУ возвращается к параметрам, установленным до загрузки NestorBASIC. То есть, FRE(0)
возвращает такое же значение, как до загрузки NestorBASIC. Учтите, что переменные в этом случае инициализируются.
Эта функция никогда не выдаёт ошибки.
Получение общей информации о NestorBASIC и о логическом сегменте.
Вход | P(0) | Номер исследуемого сегмента |
---|---|---|
Выход | P(0) | Число доступных сегментов ОЗУ |
P(1) | мажорная версия NestorBASIC | |
P(2) | минорная версия NestorBASIC, в формате BCD (должна показываться в шестнадцатеричном формате) | |
P(3) | Мажорная версия MSX-DOS | |
P(4) | Минорная версия MSX-DOS, в формате BCD (должна показываться в шестнадцатеричном формате) | |
P(5) | Размер области памяти в основном ОЗУ MSX BASIC, занятой обработчиком USR-вызовов NestorBASIC | |
P(6) | Объем VRAM в кБ (64 или 128) | |
P(7) | Адрес начала свободной области в сегменте 0 ![]() |
|
P(8) | Номер последней вызванной функции | |
P(9) | Число открытых файлов | |
P(10) | Максимальное количество одновременно открытых файлов (действительно только под MSX-DOS 1) | |
P(11) | Слот, которому принадлежит логический сегмент, указанный в P(0) (255, если сегмент не существует, или является сегментом VRAM) | |
P(12) | Номер физического сегмента, соответствующего логическому сегменту, указанному в P(0) | |
F$(0) | Полный путь к файлу NBASIC.BIN |
Под DOS 2, максимальное количество одновременно открытых файлов зависит от состояния внутренней памяти DOS, но не может превышать 63.
Эта функция возвращает ошибку -1 если заданный в P(0) логический сегмент не существует, является сегментом VRAM или 255-м сегментом. Как бы то ни было, даже в этом случае результаты в элементах с P(0) по P(10) будут действительными.
Число, возвращаемое в P(0) этой функцией будет таким же, как число, возвращаемое в P(0) функцией 80; а конкретно — это количество сегментов, зарезервированных для NestorBASIC. По-умолчанию (если функция 80 ещё не вызывалась после загрузки NestorBASIC), NestorBASIC резервирует для себя все свободные сегменты ОЗУ (до 247) во время своей загрузки.
Под MSX-DOS 1, F$(0) будет содержать только букву диска и двоеточие (например A:
),
а под MSX-DOS 2 — имя диска и каталога, заканчивающиеся «\» (например
C:\UTILS\AMAZING\
).
Адрес, возвращаемый в P(7) зависит от версии NestorBASIC, но всегда будет
меньше или равен &H3DA8; то есть, как минимум 600 байт в конце сегмента NestorBASIC всегда будет доступно. Эта область может быть использована, например, как буфер для данных TCP или UDP-датаграмм при использовании InterNestor Suite с NestorBASIC.
ВНИМАНИЕ: Из-за бага в NestorBASIC'е, в P(7) возвращается &H7C60, то есть адрес из страницы 1. Тем не менее, он может быть использован в функциях NestorBASIC'а, так как в них он будет приведен к диапазону &H0000–&H4000, как и другие адреса.
В P(8) содержится номер последней вызванной функции, не считая саму 1 функцию.
Так что если были последовательно вызваны, например, функции 64, 3, 10, 1, 1, 1,
в конечном счёте Вы получите P(8)=10
. Значение ноль будет означать, что ни одной
функции, помимо 1-й, не выполнялось с момента загрузки NestorBASIC.
Прочесть байт из сегмента с автоинкрементом адреса
Вход | P(0) | Сегмент |
---|---|---|
P(1) | Адрес | |
Выход | P(2) | Полученный байт P(1) = P(1) + 1 |
Прочесть целое число (2 байта) из сегмента
Вход | P(0) | Сегмент |
---|---|---|
Выход | P(2) | Полученное целое число |
Младший байт берётся из адреса P(1), а старший байт из адреса P(1)+1.
Прочесть целое число (2 байта) из сегмента с автоинкрементом адреса
Вход | P(0) | Сегмент |
---|---|---|
P(1) | Адрес | |
Выход | P(2) | Полученное целое число P(1) = P(1) + 2 |
Младший байт берётся из адреса P(1), а старший байт из адреса P(1)+1.
Записать байт в сегмент с автоинкрементом адреса
Вход | P(0) | Сегмент |
---|---|---|
P(1) | Адрес | |
P(2) | Записываемый байт | |
Выход | P(1) = P(1) + 1 |
Записать целое число (2 байта) в сегмент
Вход | P(0) | Сегмент |
---|---|---|
P(1) | Адрес | |
P(2) | Записываемое целое число | |
Выход | — |
Младший байт записывается в адрес P(1), а старший байт в адрес P(1)+1.
Записать целое число (2 байта) в сегмент с автоинкрементом адреса
Вход | P(0) | Сегмент |
---|---|---|
P(1) | Адрес | |
P(2) | Записываемое целое число | |
Выход | P(1) = P(1) + 2 |
Младший байт записывается в адрес P(1), а старший байт в адрес P(1)+1.
Блочная пересылка данных между сегментами
Вход | P(0) | Сегмент источника |
---|---|---|
P(1) | Адрес начала источника | |
P(2) | Сегмент назначения | |
P(3) | Адрес начала назначения | |
P(4) | Длина блока | |
P(5)<> 0 → Автоинкремент P(1) | ||
P(6)<> 0 → Автоинкремент P(3) | ||
Выход | P(1) = P(1) + P(4) если P(5)<>0 | |
P(3) = P(3) + P(4) если P(6)<>0 |
P(3)+P(4) должно быть меньше &H4000, иначе результат непредсказуем.
Заполнить область ОЗУ байтом
Вход | P(0) | Сегмент |
---|---|---|
P(1) | Начальный адрес | |
P(2) | Байт | |
P(3) | Длина области | |
Выход | — |
P(3)+P(4) должно быть меньше &H4000, иначе результат непредсказуем.
Заполнить область ОЗУ байтом с автоинкрементом адреса.
Вход | P(0) | Сегмент |
---|---|---|
P(1) | Начальный адрес | |
P(2) | Байт | |
P(3) | Длина области | |
Выход | P(1) = P(1) + P(3) |
P(3)+P(4) должно быть меньше &H4000, иначе результат непредсказуем.
Прочесть байт из VRAM с автоинкрементом адреса
Вход | P(0) | Блок VRAM |
---|---|---|
P(1) | Адрес | |
Выход | P(2) | Полученный байт P(0):P(1) = P(0):P(1) + 1 |
Прочесть целое число (2 байта) из VRAM
Вход | P(0) | Блок VRAM |
---|---|---|
P(1) | Адрес | |
Выход | P(2) | Полученный байт |
Младший байт берётся из адреса P(1), а старший байт из адреса P(1)+1.
Прочесть целое число (2 байта) из VRAM с автоинкрементом адреса
Вход | P(0) | Блок VRAM |
---|---|---|
P(1) | Адрес | |
Выход | P(2) | Полученное целое число P(0):P(1) = P(0):P(1) + 2 |
Младший байт берётся из адреса P(1), а старший байт из адреса P(1)+1.
Записать байт в VRAM с автоинкрементом адреса
Вход | P(0) | Блок VRAM |
---|---|---|
P(1) | Адрес | |
P(2) | Записываемый байт | |
Выход | P(0):P(1) = P(0):P(1) + 1 |
Записать целое число (2 байта) в VRAM
Вход | P(0) | Блок VRAM |
---|---|---|
P(1) | Адрес | |
P(2) | Записываемое целое число | |
Выход | — |
Младший байт записывается в адрес P(1), а старший байт в адрес P(1)+1.
Записать целое число (2 байта) в VRAM с автоинкрементом адреса
Вход | P(0) | Блок VRAM |
---|---|---|
P(1) | Адрес | |
P(2) | Записываемое целое число | |
Выход | P(0):P(1) = P(0):P(1) + 2 |
Младший байт записывается в адрес P(1), а старший байт в адрес P(1)+1.
Блочная пересылка данных из VRAM в RAM
Вход | P(0) | Блок VRAM источника |
---|---|---|
P(1) | Начальный адрес источника (VRAM) | |
P(2) | Сегмент назначения | |
P(3) | Начальный адрес назначения (RAM) | |
P(4) | Количество пересылаемых байт | |
P(5)<> 0 → Автоинкремент P(1) | ||
P(6)<> 0 → Автоинкремент P(3) | ||
Выход | P(1) = P(1) + P(4) если P(5)<>0 | |
P(2):P(3) = P(2):P(3) + P(4) если P(6)<>0 |
P(3)+P(4) должно быть меньше &H4000, иначе результат непредсказуем.
Пакетная пересылка данных из RAM в VRAM
Вход | P(0) | Сегмент источника |
---|---|---|
P(1) | Начальный адрес источника (RAM) | |
P(2) | Блок VRAM назначения | |
P(3) | Начальный адрес назначения (VRAM) | |
P(4) | Количество пересылаемых байт | |
P(5)<> 0 → Автоинкремент P(1) | ||
P(6)<> 0 → Автоинкремент P(3) | ||
Выход: | P(1) = P(1) + P(4) если P(5)<>0 | |
P(2):P(3) = P(2):P(3) + P(4) если P(6)<>0 |
Пакетная пересылка данных в пределах VRAM
Вход | P(0) | Блок VRAM источника |
---|---|---|
P(1) | Начальный адрес источника | |
P(2) | Блок VRAM назначения | |
P(3) | Начальный адрес назначения | |
P(4) | Количество пересылаемых байт (максимум &H4000) | |
P(5)<> 0 → Автоинкремент P(1) | ||
P(6)<> 0 → Автоинкремент P(3) | ||
Выход | P(0):P(1) = P(0):P(1) + P(4) если P(5)<>0 | |
P(2):P(3) = P(2):P(3) + P(4) если P(6)<>0 |
Если P(4) больше &H4000, только &H4000 байт будет переслано, и инкремент адреса тоже будет ограничен &H4000, но P(4) не будет модифицирован. Таким образом, для пересылки больших блоков (до 64Кб) простым способом Вы можете выполнить примерно следующее:
10 'P(0) to P(3) already set. Data block length set in L. 20 P(5)=1:P(6)=1 30 P(4)=VAL("&H"+HEX$(L)):J=USR(23):L=L-&H4000:IF L>0 THEN 30
Преобразование L из десятичного в шестнадцатиричный формат, а потом обратно — требуется из-за того, что целочисленные переменные в MSX BASIC имеют диапазон значений от -32768 до 32767; если большее значение непосредственно занести в P(4), случится ошибка переполнения.
Так как MSX X-BASIC работает с вещественными переменными особым способом, то, если применять этот приём внутри турбо-блока, L должно быть целым, кратным 256.
Заполнить область VRAM байтом
Вход | P(0) | Блок VRAM |
---|---|---|
P(1) | Начальный адрес | |
P(2) | Записываемый байт | |
P(3) | Длина области (максимум 16кБ) | |
Выход | — |
Чтобы заполнить область, размером больше 16кБ, используйте метод, описанный в функции 23.
Заполнить область VRAM байтом с автоинкрементом адреса
Вход | P(0) | Блок VRAM |
---|---|---|
P(1) | Начальный адрес | |
P(2) | Записываемый байт | |
P(3) | Длина области (максимум 16кБ) | |
Выход: | P(0):P(1) = P(0):P(1) + P(3) |
Чтобы заполнить область, размером больше 16кБ, используйте метод, описанный в функции 23.
Поиск файла (S4)
Вход | F$(1) | Маска поиска (пустая строка=«*.*») |
---|---|---|
P(0) = 0 | Поиск первого файла, соответствующего маске | |
P(0) = 1 | Поиск последующих файлов, соответствующих маске | |
P(1) | Атрибуты поиска: 2*H + 4*S + 8*V + 16*D
|
|
Выход | F$(0) | Имя найденного файла |
P(0) = 1 | ||
P(1) | Атрибуты файла (всегда 0 под MSX-DOS 1): R + 2*H + 4*S + 8*V + 16*D + 32*A
|
|
P(2) | Час создания/последней модификации (0–23) | |
P(3) | Минута создания/последней модификации (0–59) | |
P(4) | День создания/последней модификации (1–31) | |
P(5) | Месяц создания/последней модификации (1–12) | |
P(6) | Год создания/последней модификации (1980–2079) | |
P(7) | Первый кластер (2–4095) | |
P(8) | Логический диск (0=A:,…,7=H:) | |
P(9) | Длина файла (младшее слово) | |
P(10) | Длина файла (старшее слово) | |
P(11) |
0, если ничего не найдено при первоначальном поиске
|
F$(1) может включать букву диска и, в случае MSX-DOS 2, путь; F$(0) будет содержать только имя найденного файла.
P(0) должен быть установлен в 0, чтобы искать первое встретившееся совпадение с заданной маской, и оставлен равным 1, чтобы искать следующие файлы. Это то, что функция делает автоматически (всегда устанавливает P(0) в 1). Кроме того, P(11) устанавливается в 1 при первоначальном поиске файла (0 если ничего не найдено), и инкрементируется автоматически на каждой последующей итерации. Поэтому, чтобы найти соответствующие маске файлы, можно использовать цикл вроде этого:
10 'Search of all the filenames in drive B: (default directory) 20 F$(1)="B:":P(0)=0:P(1)=2+16 'Include directories and hidden files 30 IF USR(26)<>0 THEN PRINT:PRINT"Total found:";P(11):END 40 PRINT F$(0),CHR$(-ASC("h")*((P(1)AND2)<>0)); CHR$(-ASC("d")*((P(1)AND16)<>0)); CHR$(-ASC("a")*((P(1)AND32)<>0)):GOTO 30
Если больше не осталось совпадающих с маской файлов/директорий, функция вернёт ошибку «Файл не найден». Под MSX-DOS 1, ошибка при поиске первого файла может означать также, что диск не существует или имя файла задано некорректно (под MSX-DOS 2 эти ошибки имеют свой собственный код).
Чтобы получить длину файла, можно использовать формулу P(9)+65536*P(10). При выводе на экран этих длин, помните, что представление числовых переменных различается в MSX BASIC и MSX X-BASIC для больших чисел; лучше всего отображать размер файлов сразу в килобайтах: INT(P(9)/1024)+64*P(10).
Переименование файла (S4)
Вход | F$(0) | Имя файла |
---|---|---|
F$(1) | Новое имя файла | |
Выход | — |
F$(0) может также включать имя диска и, в случае с MSX-DOS 2, путь; F$(1) должен содержать только новое имя файла. Под MSX-DOS 1 можно переименовывать несколько файлов за один раз, используя маски; под MSX-DOS 2 можно переименовать только один файл за раз.
Удаление файла
Вход | F$(0) | Имя файла |
---|---|---|
Выход | — |
F$(0) может также включать имя диска и, в случае с MSX-DOS 2, путь. Под MSX-DOS 2 эта функция выдаст ошибку, если Вы попытаетесь удалить открытый файл. Под MSX-DOS 1 можно удалить открытые файлы, но это не рекомендуется, потому что последующие попытки доступа у этим файлам могут привести к непредсказуемым результатам.
Под MSX-DOS 1 можно удалять несколько файлов за один раз, используя маски; под MSX-DOS 2 можно удалить только один файл за раз.
Перемещение файла (MSX-DOS 2)
Вход | F$(0) | Имя файла |
---|---|---|
F$(1) | Новое расположение файла | |
Выход | — |
Эта функция доступна только под MSX-DOS 2. Под MSX-DOS 1 всегда возвращает ошибку 1.
F$(0) может также включать имя диска и путь. F$(1) не должен содержать ни имени файла (файл при перемещении сохраняет то же имя), ни буквы диска (файл может быть перемещен только в другой каталог на том же диске). Если задать каталог вместо файла в F$(0), все его подкаталоги и содержащиеся в нём файлы тоже будут перемещены.
Создание файла или директории
Вход | F$(0) | Имя файла или директории |
---|---|---|
P(0) | Атрибуты при создании (игнорируются под MSX-DOS 1):
|
F$(0) может также включать имя диска и путь. Файл будет создан с нулевой длиной и не останется открытым: для доступа к файлу, его нужно будет предварительно явно открыть (функция 31).
Под MSX-DOS 1 можно создавать только файлы, и P(0) игнорируется. Под MSX-DOS 2 файлы всегда создаются с установленным атрибутом «Архивный», в дополнение к атрибутам, заданным в P(0).
Открытие файла
Вход | F$(0) | Имя файла |
---|---|---|
Выход | P(0) | Номер, назначенный файлу |
F$(0) может содержать букву диска и, в случае с DOS 2, путь. Число, возвращаемое в P(0), идентифицирует файл, и будет указываться при последующих вызовах дисковых функций. Конкретное значение этого числа зависит от версии MSX-DOS и того, сколько файлов было открыто и закрыто ранее; не нужно воспринимать это значение как показатель текущего количества открытых файлов (используйте для этого функцию 1).
Под MSX-DOS 1, если превысить допустимое число одновременно открытых файлов, возникнет ошибка 3. Максимальное число одновременно открытых файлов под MSX-DOS 1 можно узнать посредством 1-й функции.
Закрытие файла
Вход | P(0) | Номер файла |
---|---|---|
Выход | — |
Очень важно закрывать файлы, которые уже не будут использоваться: иначе, если в них осуществлялась какая–то запись, во внутренних буферах MSX-DOS могут оставаться несохраненные данные, которые будут потеряны; к тому же, в этом случае, элемент каталога для этого файла не будет обновлён.
Чтение из файла (S4)
Вход | P(0) | Номер файла |
---|---|---|
P(2) | Сегмент назначения | |
P(3) | Начальный адрес назначения | |
P(4) | Сколько байт прочитать | |
P(6) | Увеличить P(3) если ≠0 | |
Выход | P(7) | Число фактически прочитанных байт |
P(3) | P(3)+P(4) если P(6)≠0 |
P(3)+P(4) должно быть меньше &H4000, иначе результат непредсказуем.
Файл читается с позиции, на которую указывает файловый указатель; этот указатель автоматически увеличивается после чтения. Чтобы узнать или изменить этот указатель, используйте функцию 42.
Чтобы прочитать файл до конца, или прочитать весь файл, если он короче 16кБ, проще всего попытаться прочесть 16кБ (установить P(4)=&H4000) и игнорировать ошибку с кодом 1 или 199: для данной функции, эти ошибки означают лишь то, что был достигнут конец файла.
Если конец файла был достигнут до прочтения P(4) байт, будет выдана ошибка. Чтобы узнать число прочитанных байт, смотрите в P(7). Если нет ошибки, то в P(7) будет то же значение, что и в P(4); в случае физической ошибки (неисправная FAT, физическая ошибка диска или диск не вставлен), в P(7) всегда будет 0.
Чтение из файла в VRAM (S4)
Вход | P(0) | Номер файла |
---|---|---|
P(2) | Блок VRAM назначения | |
P(3) | Начальный адрес назначения | |
P(4) | Сколько байт прочитать (максимум &H4000) | |
P(6) | Увеличить P(3) если ≠0 | |
Выход | P(7) | Число фактически прочитанных байт P(2):P(3) = P(2):P(3)+P(4) если P(6)≠0 |
Если P(4) больше &H4000, только &H4000 байт будет прочитано, и приращение адреса также будет ограничено &H4000, но P(4) не будет изменено. Поэтому, чтобы читать более крупные куски (до 64кБ), можно использовать приём, описанный в функции 23.
Для этой функции также действительны замечания насчет файлового указателя и значения P(7), сделанные в описании функции 33.
Чтение секторов диска (S4)
Вход | P(0) | Привод (0=A:,…,7=H:) |
---|---|---|
P(1) | Номер начального сектора | |
P(2) | Сегмент назначения | |
P(3) | Начальный адрес назначения | |
P(4) | Сколько секторов прочитать (максимум 32) | |
P(6) | Увеличить P(3) если ≠0 | |
Выход | P(7) | P(4)*512 (0 в случае ошибки) |
P(3) | P(3)+P(4)*512 если P(6)≠0 |
P(3)+P(4)×512 должно быть меньше &H4000, иначе результат непредсказуем.
Эта функция не поддерживает частичное чтение: если не возникло ошибки, тогда P(7) будет содержать число прочитанных байт, то есть P(4)×512; но в случае ошибки в P(7) будет 0. Если P(6)≠0, P(3) будет увеличен на число прочитанных байт (P(7) или 0).
Чтение секторов диска в VRAM (S4)
Вход | P(0) | Привод (0=A:,…,7=H:) |
---|---|---|
P(1) | Номер начального сектора | |
P(2) | Блок VRAM назначения | |
P(3) | Начальный адрес назначения | |
P(4) | Сколько секторов прочитать (максимум 32) | |
P(6) | Увеличить P(3) если ≠0 | |
Выход | P(7) | P(4)×512 (0 в случае ошибки) |
P(3) | P(3)+P(4)×512 если P(6)≠0 |
Если P(4) больше, чем 32 — только 32 сектора (&H4000 байт) будет прочитано, и приращение адреса также будет ограничено &H4000, но P(4) не будет изменено. Поэтому, чтобы читать более крупные куски (до 64кБ), можно использовать прием, описанный в функции 23.
Для этой функции также действительны соображения относительно значения P(7), сделанные в описании функции 35.
Запись в файл (S4)
Вход | P(0) | Номер файла |
---|---|---|
P(2) | Сегмент источника | |
P(3) | Начальный адрес источника | |
P(4) | Сколько байт записать | |
P(6) | Увеличить P(3) если ≠0 | |
Выход | P(7) | Число фактически записанных байт |
P(3) | P(3)+P(4) если P(6)≠0 |
P(3)+P(4) должно быть меньше &H4000, иначе данные, записанные в файл, будут непредсказуемыми.
Данные записываются в файл с позиции, на которую указывает файловый указатель; этот указатель автоматически увеличивается после чтения. Чтобы узнать или изменить этот указатель, используйте функцию 42. В случае физической ошибки (неисправная FAT, физическая ошибка диска или диск не вставлен), в P(7) всегда будет 0.
Запись в файл из VRAM (S4)
Вход | P(0) | Номер файла |
---|---|---|
P(2) | Блок VRAM источника | |
P(3) | Начальный адрес источника | |
P(4) | Сколько байт записать (максимум &H4000) | |
P(6) | Увеличить P(3) если ≠0 | |
Выход | P(7) | Число фактически записанных байт |
P(2):P(3) | P(2):P(3)+P(4) если P(6)≠0 |
Если P(4) больше &H4000, только &H4000 байт будет записано, и приращение адреса также будет ограничено &H4000, но P(4) не будет изменено. Поэтому, чтобы записывать более крупные куски (до 64кБ), можно использовать прием, описанный в функции 23.
Для этой функции также справедливы замечания касательно файлового указателя, сделанные в описании функции 37.
Запись в сектора диска (S4)
Вход | P(0) | Привод (0=A:,…,7=H:) |
---|---|---|
P(1) | Номер начального сектора | |
P(2) | Сегмент источника | |
P(3) | Начальный адрес источника | |
P(4) | Сколько секторов записать (максимум 32) | |
P(6) | Увеличить P(3) если ≠0 | |
Выход | P(7) | P(4)*512 (0 в случае ошибки) |
P(3) | P(3)+P(4)×512 если P(6)≠0 |
P(3)+P(4)×512 должно быть меньше &H4000, иначе данные, записанные в файл, будут непредсказуемыми.
Эта функция не поддерживает частичную запись: если не возникло ошибки, тогда P(7) будет содержать число записанных байт, то есть P(4)×512; но в случае ошибки в P(7) будет 0. Если P(6)≠0, P(3) будет увеличен на число записанных байт (P(7) или 0).
Запись в сектора диска из VRAM (S4)
Вход | P(0) | Привод (0=A:,…,7=H:) |
---|---|---|
P(1) | Номер начального сектора | |
P(2) | Блок VRAM источника | |
P(3) | Начальный адрес источника | |
P(4) | Сколько секторов записать (максимум 32) | |
P(6) | Увеличить P(3) если ≠0 | |
Выход | P(7) | P(4)×512 (0 в случае ошибки) |
P(3) | P(3)+P(4)×512 если P(6)≠0 |
Если P(4) больше, чем 32 — только 32 сектора (&H4000 байт) будет записано, и приращение адреса также будет ограничено &H4000, но P(4) не будет изменено. Поэтому, чтобы записывать более крупные куски (до 64кБ), можно использовать прием, описанный в функции 23.
Для этой функции также справедливы замечания, касающиеся значения P(7), представленные в описании функции 39.
Заполнение файла байтом (S4)
Вход | P(0) | Номер файла |
---|---|---|
P(1) | Байт | |
P(4) | Сколько байт записать (максимум &H4000) | |
Выход | P(7) | Число фактически записанных байт |
Эта функция просто записывает P(4) байт, равных содержимому P(1), в сегмент 4, начиная с адреса 0, и затем вызывает функцию 37 с P(2)=4 и P(3)=0. Поэтому, все замечания, сделанные в функции 37, будут также справедливы и здесь.
Перемещение файлового указателя
Вход | P(0) | Номер файла |
---|---|---|
P(1) | База для смещения:
|
|
P(2) | Знаковое смещение (младшее слово) | |
P(3) | Знаковое смещение (старшее слово) | |
Выход | P(4) | Новое положение файлового указателя (младшее слово) |
P(5) | Новое положение файлового указателя (старшее слово) |
Чтобы установить в P(2) и P(3) смещение D большее, чем 32768 или меньшее, чем 0, нужно использовать следующую формулу:
P(3)=INT(D/65536) P(2)=VAL("&H"+HEX$(D-(P(2)*65536)))
а чтобы восстановить полученный новый указатель в переменную P, следующую:
P=P(4)-(65536*(P(4)<0))+65536!*P(5)
Так как MSX X-BASIC работает с вещественными переменными особым способом, то, если применять этот приём внутри турбо-блока, D должно быть целым, кратным 256.
Чтобы узнать текущую позицию файлового указателя, просто используйте эту функцию с параметрами P(1)=1, P(2)=0 и P(3)=0; чтобы узнать длину файла, вызовите её с параметрами P(1)=2, P(2)=0 и P(3)=0. В первом случае указатель файла остаётся неизменным.
При использовании данной функции, помните, что смещение интерпретируется со знаком. Поэтому:
Узнать текущий диск и вектор доступных дисков (login vector)
Вход | — | |
---|---|---|
Выход | P(0) | Текущий диск (0=A:,…,7=H:) |
P(1) | Вектор доступных дисков |
Вектор доступных дисков это байт, который содержит, в каждом бите, информацию о наличии или отсутствии (бит=1: присутствует, bit=0: отсутствует); младший бит соответствует диску A: а старший - диску H:. Например, если функция возвращает P(1)=&B01000011
, значит присутствуют диски A:, B: и G:
Установить текущий диск
Вход | P(0) | Номер диска (0=A:,…,7=H:) |
---|---|---|
Выход | — |
Эта функция выдаст ошибку 62 если попытаться установить текущим неверный диск (отсутствующий, или выше, чем 7).
Информация о дисковом пространстве
Вход | P(0) | Привод (0=Текущий рабочий диск, 1=A:,…,8=H:) |
---|---|---|
Выход | P(1) | Секторов на кластер |
P(2) | Всего кластеров (максимум 4096) | |
P(3) | Количество свободных кластеров |
Свободное пространство в байтах можно вычислить по формуле P(1)*P(3)*512, или в килобайтах по формуле P(1)*P(3)/2; и то же самое с общим размером диска, используя P(2) вместо P(3).
Эта функция выдаст ошибку 62 если попытаться получить информацию о неверном диске (отсутствующий, или выше, чем 8).