Инструменты пользователя

Инструменты сайта


msx:nestor_basic:nestor_basic

NestorBASIC

FIXME

Это статья написана на основе документации User's manual in english, version 1.11, оригинал
Автор: Nestor Soriano (Konami Man), Декабрь 2004

Nestor Soriano также является автором Nextor

Официальная страница NestorBASIC

Перевод документации выполнил: ATroubleshooter, 2021–2022
Перевод документации NestorBASIC version 1.11 на русский (в работе)

Содержание

1. Что такое NestorBASIC ?

NestorBASIC — это набор подпрограмм(функций, процедур) в машинном коде, интегрированных в один файл, предназначенных для использования в программах, написанных на MSX BASIC. NestorBASIC обеспечивает, без утраты совместимости с MSX X-BASIC, следующую функциональность:

  • Полный доступ ко всей страничной оперативной памяти компьютера(всей памяти, в случае MSX-DOS 1, всей свободной памяти в случае MSX-DOS 2), вплоть до 4 Мб.
  • Доступ ко всей видеопамяти(VRAM), с возможностью пересылки блоков данных как в пределах VRAM, так и между VRAM и RAM.
  • Размещение программ MSX BASIC в страничной памяти, с возможностью выполнять переход из одной программы в другую с сохранением переменных.
  • Доступ к файлам на диске и непосредственно к физическим секторам, с возможностью чтения/записи напрямую в/из страничной RAM и VRAM. Поиск файлов, работа с директориями.
  • Сжатие и распаковка графики.
  • Проигрывание Moonblaster-музыки. Подгрузка samplekit'ов.
  • Воспроизведение звуковых эффектов на PSG(AY-3-8910).
  • Вызов подпрограмм в машинном коде, находящихся в BIOS, Sub-BIOS, в основной области памяти MSX BASIC, рабочей области системы, или в сегменте страничного ОЗУ.
  • Вызов функций NestorMan, процедур InterNestor Suite и InterNestor Lite.

Все имеющиеся функции доступны через один единственный USR и массив целочисленных параметров, следовательно они полностью совместимы с MSX X-BASIC.

Собственно, сам компилятор MSX X-BASIC содержится в файле NBASIC.BIN, и автоматически загружается при резидентной установке NestorBASIC.

NestorBASIC загружается в сегмент ОЗУ, не используемый MSX BASIC, так что нужен лишь небольшой объем основной памяти MSX BASIC (примерно 500 байт) для программы перехода. Остальная основная память MSX BASIC свободна для программы на Бейсике.

2. Системные требования. Загрузка NestorBASIC

NestorBASIC работает на любой MSX2/2+/Turbo-R с как минимум 128 кБ страничной памяти. В случае с MSX-DOS 2 нужен хотя бы один свободный сегмент ОЗУ в первичном маппере (два, если собираетесь использовать проигрыватели музыки. См. раздел 8 для подробностей).

Файл Размер
(байт)
Контрольная сумма
MD5
Описание
NestorBASIC 1.115853942f1a7d5d3fe2281c743f4283fc4f4a9оригинал

Этот архив содержит все исходные файлы для сборки.

Для сборки из исходного текста рекомендуется использовать среду разработки Compass, либо кросс-ассемблер SjAsm на ПК.

Для загрузки NestorBASIC, просто выполните в MSX BASIC команду:

BLOAD"NBASIC.BIN",R

Также можно выполнить вызов из файла автозапуска:

AUTOEXEC.BAS
10 BLOAD"NBASIC.BIN",R:NEW

Ни предварительных, ни последующих команд CLEAR и DEFUSR не требуется. Если все прошло без ошибок, мы получаем следующее:

  1. NestorBASIC и MSX X-BASIC загружены, каждый в свой сегмент ОЗУ, и готовы к работе.
  2. Размер свободной основной памяти MSX BASIC уменьшился примерно на 500 байт, которые были заняты программой, осуществляющей переход в сегмент NestorBASIC.
  3. Первый USR [USR0(параметр) или просто USR(параметр)] указывает на вышеупомянутую программу перехода — это обработчик вызовов функций NestorBASIC.
  4. Создан целочисленный массив параметров P. Этот массив используется для передачи параметров в функции 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)
3NestorBASIC уже установлен. Все переменные были переинициализированы
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 не заняты.

3. Логические сегменты

3.1. Что такое логический сегмент?

Страничное ОЗУ компьютеров 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.

Все сегменты доступны для чтения и записи, но есть важные ограничения по отношению к первым шести:

  1. Сегмент 0 содержит собственно NestorBASIC, и лишь небольшая область ОЗУ остаётся доступной для пользователя в конце него. Используйте функцию 1 чтобы получить начальный адрес этой области (описание функции см. в разделе 10).
  2. Сегмент 1 содержит компилятор MSX X-BASIC. Можно перезаписать этот сегмент только в том случае, если Вы не собираетесь использовать компилятор.
  3. Сегмент 2 всегда подключён к 2 странице (адреса &H8000–&HBFFF), и содержит исполняемую программу на MSX BASIC и часть её переменных.
  4. Сегмент 3 всегда подключён к странице 3 (адреса &HC000–&HFFFF), и содержит рабочую область системы и часть переменных программы на MSX BASIC. Будьте внимательны при записи сюда.
  5. Сегмент 4 используется как служебный буфер некоторыми функциями NestorBASIC. Вы можете использовать этот сегмент для ваших данных, если Вы не обращаетесь к этим функциям NestorBASIC. См. раздел 10 или приложение 1 чтобы узнать, какие функции используют этот сегмент.
  6. Сегмент 5, если он есть, изначально свободен, и не используется 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.

3.2. Использование VRAM в качестве логических сегментов

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. Эти функции позволяют пересылать данные VRAMRAM и VRAM ↔ файл.

Внимание: сегменты VRAM могут использоваться — как и обычные сегменты RAM — для размещения данных и программ на MSX BASIC, а также для блоковых операций обмена с диском и сегментами RAM. Но учтите, что сегменты VRAM не могут быть использованы для:

  • Сжатия/распаковки графики
  • Исполнения программ в машинном коде
  • Исполнения прерываний, определяемых пользователем.
  • Воспроизведения звуковых эффектов на PSG(AY-3-8910)
  • Воспроизведения музыки

Если Вы попытаетесь использовать сегменты VRAM для какой-то из этих целей, функция вернёт ошибку «несуществующий сегмент».

3.3. Сегмент 255

Логический сегмент 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)

3.4. Карта сегментов

Резюмируя данный раздел, предоставим весь список имеющихся сегментов и их описание. 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.
VRAMVRAM 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)

3.5. Ошибки

Все функции доступа к RAM и/или VRAM возвращают код ошибки -1 в следующих случаях:

  • указан номер отсутствующего сегмента памяти;
  • попытка доступа к адресу VRAM выше &HFFFF в компьютерах с 64 кБ VRAM;
  • указан сегмент VRAM или 255-й сегмент в функциях, которые поддерживают только обычные сегменты RAM.

4. Доступ к диску

NestorBASIC включает функции для работы с файлами на диске и доступа к другим возможностям MSX-DOS, а именно:

  • создание/удаление/переименование/поиск файлов;
  • чтение/запись файлов в/из любого сегмента или области VRAM;
  • чтение/запись секторов в/из любого сегмента или области VRAM;
  • определение ёмкости диска, свободного пространства.

Функции, доступные только под MSX-DOS 2:

  • перемещение файлов, чтение/установка атрибутов файла;
  • получение/смена текущего рабочего диска/каталога (директории);
  • определение ёмкости/создание RAM-диска.

4.1. Массив F$

Для передачи имён файлов и директорий, эти функции задействуют массив строковых переменных 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

ВАЖНО: Строковые переменные, определенные вне турбо-блока, равно как и другие переменные, не передаются в турбо–блок, и восстанавливаются после его завершения!

Пример.

41.bas
10 A$="Outside"
20 _TURBO ON
30 A$="Inside":PRINT A$
40 _TURBO OFF
50 PRINT A$
run
Inside
Outside

Запустить в WebMSX

С 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)… как обычно.

4.2. Ошибки

Помимо ошибки -1, описанной в разделе 3, функции работы с диском имеют собственные коды ошибок.

Следующие ошибки могут появиться только под MSX-DOS 1:

1Единый код ошибки MSX-DOS 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Неверный номер файла (не принадлежит ни одному открытому файлу).
188RAM-диск уже существует (при создании RAM-диска).
187RAM-диск не существует (при удалении RAM-диска).

5. Сжатие и распаковка графики

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.

5.1 Ошибки

Функции компрессии/декомпрессии графики могут возвращать следующие коды ошибок:

-1Ошибка при сжатии или распаковке. Задан несуществующий сегмент, сегмент VRAM или 255-й. Также, эта ошибка появляется при указании некорректного адреса VRAM в любом из входных параметров.
5Ошибка при упаковке. Недостаточно сегментов для сжатия всего изображения.
6Ошибка при распаковке. Найдены некорректные данные, или закончились сегменты, прежде чем встретился маркер окончания данных.

6. Размещение программ на Бейсике в ОЗУ и их запуск

NestorBASIC включает функции, которые позволяют Вам помещать программы на Бейсике в любой сегмент RAM или VRAM, актуализировать или запускать их, не теряя переменные исходной программы (из которой произведен переход в новую).

ВНИМАНИЕ: Чтобы использовать данные функции, нужно изменить адрес начала Бейсик-программы в основной памяти MSX BASIC с &H8000 на &H8003; это действие должно быть выполнено лишь однократно, и обязательно ПЕРЕД загрузкой NestorBASIC. Это можно сделать двумя способами:

  • В интерактивном режиме, напечатав следующие команды:
    POKE &HF676,4
    POKE &H8003,0
    NEW
  • Из программы на Бейсике. Этот способ лучше, так как в этой же программе можно, следом, загрузить NestorBASIC. Первая строка программы должна быть такой:
    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, которая позволяет сохранить в файл активную программу с таким заголовком. В дальнейшем, просто загрузите этот файл в какой-нибудь сегмент с помощью дисковой функции, и программа готова к использованию — её можно актуализировать или выполнить в любой момент.

6.1 Ошибки

Очевидно, что если исполняется команда или строка, следующая за USR-функцией, которая актуализирует или запускает другую программу на BASIC, то это означает, что мы находимся в состоянии ошибки. Возможна одна из двух ошибок:

-1Заданный сегмент не существует. Эти функции поддерживают сегменты VRAM, но не сегмент 255.
-2Памяти MSX-BASIC не достаточно для новой программы и переменных. Случается, если актуализируемая/запускаемая программа больше, чем исходная.

7. Различные прочие функции

В этой группе собраны функции, предназначенные для:

  • Вызова подпрограмм в машинном коде, находящихся в BIOS, Sub-BIOS, в основной памяти Бейсик, рабочей области системы или в сегменте ОЗУ (так называемые «пользовательские подпрограммы»).
  • Размещения строковых переменных в сегментах RAM и извлечения их оттуда.
  • Вывода на экран строковых переменных в графическом режиме.
  • Управления миганием (blink mode) в SCREEN 0
  • Назначения пользовательских прерываний (программы в машинном коде, находящиеся в сегменте RAM, выполняемые каждое прерывание по таймеру 50/60 Гц).
  • Воспроизведения звуковых эффектов на PSG(AY-3-8910), созданных в SEE версий 3.xx

Некоторые из этих функций требуют строковый массив F$ для передачи параметров и возврата результатов, в дополнение к целочисленному массиву P. Больше подробностей о массиве F$ см. в разделе 4.

Некоторые из внутренних процедур NestorBASIC могут вызываться из других машинных подпрограмм пользователя и использоваться прерыванием, определяемым пользователем. См. приложение 2 для детального описания использования этих процедур.

Редактор SEE (sound effects editor) для создания звуковых эффектов под PSG был разработан группой Fuzzy Logic, и использование звуковых эффектов, сделанных в этом редакторе, в коммерческих продуктах подразумевает отчисление небольшой суммы авторам. Больше деталей в приложении 4.

8. Воспроизведение музыки

8.1. Инициализация музыкального плеера

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.

8.2. Возможности плеера

Как только плеер загружен, он может использоваться функциями NestorBASIC для:

  • Начала проигрывания музыки, предварительно загруженной в сегмент RAM (сегменты VRAM не поддерживаются).
  • Остановки воспроизведения музыки.
  • Паузы/продолжения воспроизведения музыки.
  • Постепенного затухания музыки, с выбором скорости затухания.
  • Получения информации о воспроизводимой музыке (сегмент и начальный адрес, по которому она находится, название мелодии, набор сэмплов (samplekit) или набор PCM-инструментов (wavekit), текущая позиция и темп).
  • Получения сведений о обнаруженных аудиочипах.
  • Отключения аудиочипов, чтобы они не задействовались, несмотря на то, что были обнаружены.
  • Загрузки samplekit музыкального трека или wavekit для Moonsound из файла.

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

8.3 Ошибки

Функции проигрывания музыки могут возвращать следующие коды ошибок:

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, могут быть проиграны плеерами, и пригодны для встраивания в сторонние программы. Они предельно компактны, из них исключена вся избыточная информация — не задействованные в мелодии паттерны/инструменты/тоны. Названия инструментов и тонов также не сохраняются.

9. Взаимодействие с NestorMan и InterNestor Suite/Lite

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 имеют собственную документацию, описывающую их функции и процедуры. Эти программы доступны здесь.


TCPCON, оригинал

9.1. Сегменты NestorBASIC и сегменты NestorMan

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

  • Сегменты 0, 1, 2 и 3 являются общими для NestorBASIC и NestorMan (в документации к NestorMan эти сегменты называются «TPA segments»).
  • Если, при резидентной загрузке NestorBASIC, NestorMan запущен — тогда логический сегмент 4 NestorBASIC выделяется не с использованием механизмов MSX-DOS 2, как остальные сегменты. Вместо этого, используется функция 7 NestorMan; таким образом, 4-му сегменту NestorBASIC присваивается, в свою очередь, номер сегмента NestorMan (этот номер можно узнать посредством 81-й функции NestorBASIC). Этот сегмент зарезервирован установкой атрибута «exclusive», и поэтому не используется NestorMan для выделения блоков памяти.

Если NestorMan и/или InterNestor Suite будут использоваться вместе с NestorBASIC, рекомендуется ограничить, с помощью функции 80, количество сегментов RAM, которые будут использоваться NestorBASIC. В противном случае, NestorBASIC зарезервирует для себя все доступные сегменты, и NestorMan не сможет задействовать резервы ОЗУ (необходимые для выделения блоков памяти, создания связанных списков и для отправки/получения данных в/из Интернета).

Для вызова функций NestorMan можно использовать 82-ю функцию; или можно использовать 58-ю функцию, указав хук EXTBIO (&HFFCA) в качестве адреса перехода, занеся &H2202 в регистровую пару DE, и номер функции в регистр C. См. описание функций в разделе 10.

9.2. Обмен данными между NestorBASIC и NestorMan

При использовании NestorMan из NestorBASIC, обычно Вам придётся осуществлять передачу данных между сегментом NestorBASIC и сегментом NestorMan. Есть три способа сделать это:

  1. Если сегмент источника или назначения — это сегмент TPA (номер сегмента от 0 до 3), достаточно использовать соответствующую функцию NestorMan для передачи блока данных (функция 14), поскольку NestorMan и так видит эти сегменты.
  2. Можно использовать сегмент 4 NestorBASIC как промежуточный буфер для пересылки. Например, предположим пересылку из NestorBASIC в NestorMan. S1 это источник — сегмент NestorBASIC, S2 это назначение — сегмент NestorMan, и S3 это номер сегмента NestorMan, соответствующий 4 сегменту NestorBASIC. Тогда, сначала делается пересылка S1→4 с помощью функции NestorBASIC (функция 10), и затем делается пересылка S3→S2 с использованием функции NestorMan (функция 14).
  3. Функции 83 и 84 NestorBASIC осуществляют блочное копирование данных из сегмента NestorMan в сегмент NestorBASIC и наоборот.

Чтобы прочитать или записать единственный байт данных из/в сегмент NestorMan, проще всего использовать соответствующие функции, которые предоставляет NestorMan (функции 12 и 13).

Помните, что некоторые функции NestorBASIC используют сегмент 4 как служебный буфер для временного размещения данных. См. раздел 10 или приложение 1, чтобы узнать эти функции.

9.3. Использование InterNestor Suite

Методика, при использовании InterNestor Suite из NestorBASIC, схожа с той, что применяется для работы с NestorMan. Единственно, нужно иметь в виду следующее:

  • Функция 85 позволяет исполнять процедуры InterNestor Suite.
  • Чтобы читать и записывать данные в сегменты InterNestor Suite (константы конфигурации и переменные), сначала нужно, используя функцию 81, выяснить номера сегментов модулей InterNestor Suite (каждый модуль занимает сегмент NestorMan), а далее, использовать методы обмена данными, описанные в предыдущем разделе.
  • Процедуры InterNestor Suite для чтения/записи данных TCP или датаграмм UDP

допускают использование только сегментов TPA как источника/назначения данных или датаграмм. Для этой цели можно использовать последнюю часть сегмента NestorBASIC (сегмент 0) как временный буфер. Это свободное пространство всегда будет, как минимум, размером 600 байт, независимо от используемой версии NestorBASIC.
Этого достаточно для размещения стандартной датаграммы до 576 байт длинной (или для размещения блока данных TCP до 600 байт включительно).

Пример программы TCPCON-S.BAS (см. здесь), поставляемый с NestorBASIC, иллюстрирует использование NestorBASIC'а совместно с InterNestor Suite.

ВНИМАНИЕ: InterNestor Suite это устаревшее ПО и не рекомендуется к спользованию. Если Вам нужен рабочий стэк TCP/IP, посмотрите в сторону InterNestor Lite.

9.4. Использование 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.

9.5. Ошибки

Функция 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 никогда не выдают ошибок.

10. Функции NestorBASIC

10.1. Общее описание

FIXME

Функции, которые составляют 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.

10.2. Общие функции

FIXME

Функция 0

Выгрузка 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. Учтите, что переменные в этом случае инициализируются.

Эта функция никогда не выдаёт ошибки.

Функция 1

Получение общей информации о 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 FIXME(&H3DA8 как максимум)
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, но всегда будет меньше или равен FIXME &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.

10.3. Функции для доступа к логическим сегментам

Функция 2

Прочесть байт из сегмента

ВходP(0)Сегмент
P(1)Адрес
ВыходP(2)Полученный байт

Функция 3

Прочесть байт из сегмента с автоинкрементом адреса

ВходP(0)Сегмент
P(1)Адрес
ВыходP(2)Полученный байт
P(1) = P(1) + 1

Функция 4

Прочесть целое число (2 байта) из сегмента

ВходP(0)Сегмент
ВыходP(2)Полученное целое число

Младший байт берётся из адреса P(1), а старший байт из адреса P(1)+1.

Функция 5

Прочесть целое число (2 байта) из сегмента с автоинкрементом адреса

ВходP(0)Сегмент
P(1)Адрес
ВыходP(2)Полученное целое число
P(1) = P(1) + 2

Младший байт берётся из адреса P(1), а старший байт из адреса P(1)+1.

Функция 6

Записать байт в сегмент

ВходP(0)Сегмент
P(1)Адрес
P(2)Записываемый байт
Выход

Функция 7

Записать байт в сегмент с автоинкрементом адреса

ВходP(0)Сегмент
P(1)Адрес
P(2)Записываемый байт
ВыходP(1) = P(1) + 1

Функция 8

Записать целое число (2 байта) в сегмент

ВходP(0)Сегмент
P(1)Адрес
P(2)Записываемое целое число
Выход

Младший байт записывается в адрес P(1), а старший байт в адрес P(1)+1.

Функция 9

Записать целое число (2 байта) в сегмент с автоинкрементом адреса

ВходP(0)Сегмент
P(1)Адрес
P(2)Записываемое целое число
ВыходP(1) = P(1) + 2

Младший байт записывается в адрес P(1), а старший байт в адрес P(1)+1.

Функция 10

Блочная пересылка данных между сегментами

Вход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, иначе результат непредсказуем.

Функция 11

Заполнить область ОЗУ байтом

ВходP(0)Сегмент
P(1)Начальный адрес
P(2)Байт
P(3)Длина области
Выход

P(3)+P(4) должно быть меньше &H4000, иначе результат непредсказуем.

Функция 12

Заполнить область ОЗУ байтом с автоинкрементом адреса.

ВходP(0)Сегмент
P(1)Начальный адрес
P(2)Байт
P(3)Длина области
ВыходP(1) = P(1) + P(3)

P(3)+P(4) должно быть меньше &H4000, иначе результат непредсказуем.

10.4. Функции доступа к VRAM

Функция 13

Прочесть байт из VRAM

ВходP(0)Блок VRAM
P(1)Адрес
ВыходP(2)Полученный байт

Функция 14

Прочесть байт из VRAM с автоинкрементом адреса

ВходP(0)Блок VRAM
P(1)Адрес
ВыходP(2)Полученный байт
P(0):P(1) = P(0):P(1) + 1

Функция 15

Прочесть целое число (2 байта) из VRAM

ВходP(0)Блок VRAM
P(1)Адрес
ВыходP(2)Полученный байт

Младший байт берётся из адреса P(1), а старший байт из адреса P(1)+1.

Функция 16

Прочесть целое число (2 байта) из VRAM с автоинкрементом адреса

ВходP(0)Блок VRAM
P(1)Адрес
ВыходP(2)Полученное целое число
P(0):P(1) = P(0):P(1) + 2

Младший байт берётся из адреса P(1), а старший байт из адреса P(1)+1.

Функция 17

Записать байт в VRAM

ВходP(0)Блок VRAM
P(1)Адрес
P(2)Записываемый байт
Выход

Функция 18

Записать байт в VRAM с автоинкрементом адреса

ВходP(0)Блок VRAM
P(1)Адрес
P(2)Записываемый байт
ВыходP(0):P(1) = P(0):P(1) + 1

Функция 19

Записать целое число (2 байта) в VRAM

ВходP(0)Блок VRAM
P(1)Адрес
P(2)Записываемое целое число
Выход

Младший байт записывается в адрес P(1), а старший байт в адрес P(1)+1.

Функция 20

Записать целое число (2 байта) в VRAM с автоинкрементом адреса

ВходP(0)Блок VRAM
P(1)Адрес
P(2)Записываемое целое число
ВыходP(0):P(1) = P(0):P(1) + 2

Младший байт записывается в адрес P(1), а старший байт в адрес P(1)+1.

Функция 21

Блочная пересылка данных из 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, иначе результат непредсказуем.

Функция 22

Пакетная пересылка данных из 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

Функция 23

Пакетная пересылка данных в пределах 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.

Функция 24

Заполнить область VRAM байтом

ВходP(0)Блок VRAM
P(1)Начальный адрес
P(2)Записываемый байт
P(3)Длина области (максимум 16кБ)
Выход

Чтобы заполнить область, размером больше 16кБ, используйте метод, описанный в функции 23.

Функция 25

Заполнить область VRAM байтом с автоинкрементом адреса

ВходP(0)Блок VRAM
P(1)Начальный адрес
P(2)Записываемый байт
P(3)Длина области (максимум 16кБ)
Выход:P(0):P(1) = P(0):P(1) + P(3)

Чтобы заполнить область, размером больше 16кБ, используйте метод, описанный в функции 23.

10.5. Функции для работы с диском

Функция 26

Поиск файла (S4)

ВходF$(1)Маска поиска (пустая строка=«*.*»)
P(0) = 0 Поиск первого файла, соответствующего маске
P(0) = 1Поиск последующих файлов, соответствующих маске
P(1)Атрибуты поиска: 2*H + 4*S + 8*V + 16*D
  • H = 1 → Включить скрытые файлы в поиск
  • S = 1 → Включить системные файлы в поиск
  • V = 1 → Искать только метку тома
  • D = 1 → Включить подкаталоги в поиск
ВыходF$(0)Имя найденного файла
P(0) = 1
P(1)Атрибуты файла (всегда 0 под MSX-DOS 1):

R + 2*H + 4*S + 8*V + 16*D + 32*A
  • R = 1 → Только для чтения
  • H = 1 → Скрытый
  • S = 1 → Системный
  • V = 1 → Метка тома
  • D = 1 → Директория
  • A = 1 → Архивный
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, если ничего не найдено при первоначальном поиске
1, если при первоначальном поиске найден файл
P(11), если при дальнейшем поиске ничего не найдено
P(11)+1, если при дальнейшем поиске файл найден

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).

Функция 27

Переименование файла (S4)

ВходF$(0)Имя файла
F$(1)Новое имя файла
Выход

F$(0) может также включать имя диска и, в случае с MSX-DOS 2, путь; F$(1) должен содержать только новое имя файла. Под MSX-DOS 1 можно переименовывать несколько файлов за один раз, используя маски; под MSX-DOS 2 можно переименовать только один файл за раз.

Функция 28

Удаление файла

ВходF$(0)Имя файла
Выход

F$(0) может также включать имя диска и, в случае с MSX-DOS 2, путь. Под MSX-DOS 2 эта функция выдаст ошибку, если Вы попытаетесь удалить открытый файл. Под MSX-DOS 1 можно удалить открытые файлы, но это не рекомендуется, потому что последующие попытки доступа у этим файлам могут привести к непредсказуемым результатам.

Под MSX-DOS 1 можно удалять несколько файлов за один раз, используя маски; под MSX-DOS 2 можно удалить только один файл за раз.

Функция 29

Перемещение файла (MSX-DOS 2)

ВходF$(0)Имя файла
F$(1)Новое расположение файла
Выход

Эта функция доступна только под MSX-DOS 2. Под MSX-DOS 1 всегда возвращает ошибку 1.

F$(0) может также включать имя диска и путь. F$(1) не должен содержать ни имени файла (файл при перемещении сохраняет то же имя), ни буквы диска (файл может быть перемещен только в другой каталог на том же диске). Если задать каталог вместо файла в F$(0), все его подкаталоги и содержащиеся в нём файлы тоже будут перемещены.

Функция 30

Создание файла или директории

ВходF$(0)Имя файла или директории
P(0)Атрибуты при создании (игнорируются под MSX-DOS 1):
  • R + 2*H + 4*S для файлов;
  • 2*H + 16 для директорий.
  • R = 1 → Только для чтения
  • H = 1 → Скрытый
  • S = 1 → Системный

F$(0) может также включать имя диска и путь. Файл будет создан с нулевой длиной и не останется открытым: для доступа к файлу, его нужно будет предварительно явно открыть (функция 31).

Под MSX-DOS 1 можно создавать только файлы, и P(0) игнорируется. Под MSX-DOS 2 файлы всегда создаются с установленным атрибутом «Архивный», в дополнение к атрибутам, заданным в P(0).

Функция 31

Открытие файла

ВходF$(0)Имя файла
ВыходP(0)Номер, назначенный файлу

F$(0) может содержать букву диска и, в случае с DOS 2, путь. Число, возвращаемое в P(0), идентифицирует файл, и будет указываться при последующих вызовах дисковых функций. Конкретное значение этого числа зависит от версии MSX-DOS и того, сколько файлов было открыто и закрыто ранее; не нужно воспринимать это значение как показатель текущего количества открытых файлов (используйте для этого функцию 1).

Под MSX-DOS 1, если превысить допустимое число одновременно открытых файлов, возникнет ошибка 3. Максимальное число одновременно открытых файлов под MSX-DOS 1 можно узнать посредством 1-й функции.

Функция 32

Закрытие файла

ВходP(0)Номер файла
Выход

Очень важно закрывать файлы, которые уже не будут использоваться: иначе, если в них осуществлялась какая–то запись, во внутренних буферах MSX-DOS могут оставаться несохраненные данные, которые будут потеряны; к тому же, в этом случае, элемент каталога для этого файла не будет обновлён.

Функция 33

Чтение из файла (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.

Функция 34

Чтение из файла в 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.

Функция 35

Чтение секторов диска (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).

Функция 36

Чтение секторов диска в 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.

Функция 37

Запись в файл (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.

Функция 38

Запись в файл из 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.

Функция 39

Запись в сектора диска (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).

Функция 40

Запись в сектора диска из 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.

Функция 41

Заполнение файла байтом (S4)

ВходP(0)Номер файла
P(1)Байт
P(4)Сколько байт записать (максимум &H4000)
ВыходP(7)Число фактически записанных байт

Эта функция просто записывает P(4) байт, равных содержимому P(1), в сегмент 4, начиная с адреса 0, и затем вызывает функцию 37 с P(2)=4 и P(3)=0. Поэтому, все замечания, сделанные в функции 37, будут также справедливы и здесь.

Функция 42

Перемещение файлового указателя

ВходP(0)Номер файла
P(1)База для смещения:
  • 0 — Относительно начала файла
  • 1 — Относительно текущей позиции указателя
  • 2 — Относительно конца файла
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. В первом случае указатель файла остаётся неизменным.

При использовании данной функции, помните, что смещение интерпретируется со знаком. Поэтому:

  • Если Вы вызываете функцию с P(1)=0, смещение должно быть положительным. Иначе, при последующем доступе к файлу, результат будет непредсказуемым.
  • Если Вы вызываете функцию с P(1)=1, положительное смещение передвинет файловый указатель вперёд; отрицательное смещение передвинет файловый указатель назад.
  • Если Вы вызываете функцию с P(1)=2, смещение должно быть отрицательным; в противном случае, файловый указатель будет помещён после конца файла. В таком случае, дальнейшее чтение файла вызовет ошибку «End of file» (будет прочитано 0 байт), а запись в файл приведёт к тому, что пространство между концом файла и указателем будет заполнено нулями.

Функция 43

Узнать текущий диск и вектор доступных дисков (login vector)

Вход
ВыходP(0)Текущий диск (0=A:,…,7=H:)
P(1)Вектор доступных дисков

Вектор доступных дисков это байт, который содержит, в каждом бите, информацию о наличии или отсутствии (бит=1: присутствует, bit=0: отсутствует); младший бит соответствует диску A: а старший - диску H:. Например, если функция возвращает P(1)=&B01000011, значит присутствуют диски A:, B: и G:

Функция 44

Установить текущий диск

ВходP(0)Номер диска (0=A:,…,7=H:)
Выход

Эта функция выдаст ошибку 62 если попытаться установить текущим неверный диск (отсутствующий, или выше, чем 7).

Функция 45

Информация о дисковом пространстве

Вход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).

Ссылки

msx/nestor_basic/nestor_basic.txt · Последние изменения: 2022-05-15 19:14 — GreyWolf