ASCII X-Basic (он же Kun Basic)
Стандартный MSX-Basic, имеет очень богатый функционал возможностей, и тем более, позволяет напрямую обращаться к видеопроцессору, для вызова аппаратных функций.
Тем не менее, он очень медленно интерпретируется, что является его самым главным недостатком.
Поэтому компания ASCII, решила устранить этот недостаток практически сразу, а именно: в 1986 году, вместе с выходом стандарта MSX2.
Они не стали изобретать велосипед, и переписывать MSX-Basic (который к слову и так претерпел кардинальные изменения), и решили поступить проще:
создали реалтаймовый компилятор кода, и расширили стандартный набор команд MSX-Basic'а, командами и опциями управления компилятором.
Команд всего три:
Первая команда, предназначена для запуска всей программы, в режиме компиляции. И если в коде нет не поддерживаемых функций (об этом чуть позже), то программа перед стартом компилируется и запускается. При этом производительность увеличивается на порядки (от 140%-10000%, по оценкам NYYRIKKI)!Код:_RUN (CALL RUN) _TURBO ON (CALL TURBO ON) _TURBO OFF (CALL TURBO OFF)
Необходимо сразу отметить, что CTRL-STOP, в этом режиме не обрабатывается, поэтому при отладке, необходимо модифицировать программу так, чтобы она содержала обработчик условного перехода по заранее подготовленным условиям, на выход из программы, в противном случае, программа будет выполнена от начала и до конца.
И если программа зациклена в бесконечном цикле, то вы из нее никогда не выйдите.
Вторая и третья команды, предназначены для определения блока в теле программы, который будет компилироваться при выполнении.
Таким образом, вся программа будет работать в штатном режиме интерпретации, а выделенный блок будет откомпилирован для ускорения вычислений или вывода графики.
Здесь сразу возникает первое и фундаментальное соглашение синтаксиса:
Вместе с этими командами ЗАПРЕЩЕНО использовать другие в одной строке программы.
то есть если используется определение блока компиляции, то блок может быть описан только следующим образом:
Никаких комментариев, операторов через двоеточие, с этими командами использоваться не могут.Код:10 _TURBO ON 20 ... 30 ... 90 _TURBO OFF 100 END
А дальше, соглашений становится все больше и больше, но запомнить эти правила несложно, а если вы умеете писать на ассемблере или машинном коде, то они становятся очевидными и понятными.
Итак:
1. Переменные внутри блока компиляции имеют внутреннюю область определения.
Это значит, что они не доступны основной программе и наоборот.
Например:
Выведет на экран следующий результат:Код:10 A=10: ? A 20 _TURBO ON 30 ? A 40 _TURBO OFF
Код:10 0 Ok
Здесь очевидны несколько вариантов решения проблемы: можно передавать параметры через память или видеопамять, используя POKE/VPOKE (PEEK/VPEEK), не использовать общие пространства определений, либо прибегнуть к способу передачи параметров, которые непосредственно поддерживает сам оператор _TURBO ON
Выведет на экран следующий результат:Код:10 A=10: ? A 20 _TURBO ON (A) 30 ? A 40 _TURBO OFF
Да, все вот так просто, переменные можно передавать внутрь блока, разделяя имена переменных запятыми,Код:10 10 Ok
а самое главное, что изменение, переданных таким образов переменных, внутри блока компиляции будет происходить глобально.
Передаваемые переменные должны иметь тип INT, можно так же передавать строковые переменные.
А еще, точно так же можно передавать и массивы, но здесь вступает в силу еще одно ограничение и соглашение:
2. Передаваемые массивы внутрь блока компиляции, должны быть определены как Array of Int
То есть такой код:
Код:10 DIM A(10) 20 _TURBO ON (A()) 30 ... 40 _TURBO OFF
Выдаст сообщение об ошибке.
Чтобы правильно определить тип, нужно добавить строку:
И массив будет передан корректно.Код:10 DEFINTA 20 DIM A(10) 30 _TURBO ON (A()) 40 ... 50 _TURBO OFF
Ну и теперь, самая смачная ложка дёгтя в этом компоте:
Не все стандартные операторы MSX-Basic могут быть включены в блок компиляции.
Вот перечень не поддерживаемых:
Код:AUTO, BASE, BLOAD, BSAVE, CALL, CDBL, CINT, CLEAR, CLOAD, CLOAD?, CLOSE, CONT, CSAVE, CSNG, CVD, CVI, CVS, DEFFN, DELETE, DRAW, DSKF, EOF, ERASE, ERL, ERR, ERROR, EQV, FIELD, FILES, FPOS, FRE, GET, IMP, INPUT#, KEY LIST, LFILES, LINEINPUT#, LIST, LLIST, LOAD, LOC, LOF, LPRINT USING, LSET, MAXFILES, MERGE, MOTOR, MKD$, MKI$, MKS$, NAME, NEW, ON ERROR GOTO, ON INTERVAL GOSUB (due to a bug), OPEN, PLAY, PRINT#, PRINT USING, PUT KANJI, RENUM, RESUME, RSET, SAVE, SPC, TAB, TRON, TROFF, WIDTH.
Это справедливо для версии X-Basic от 1989 года (Kun-Basic 2.0)
Как можно заметить, это все операции дискового ввода/вывода, и частично экранного I/O.
А так же все операторы, которые используют строковый парсер.
В добавок к этому, следующие команды могут быть использованы с частичными ограничениями:
Код:CIRCLE: Только окружности, никаких дуг или эллипсов. COPY: Только пересылки в видеопамяти. DEFDBL: То же что и DEFSNG. DIM: Должен определяться только вначале программы либо внутри блока компиляции. INPUT: Может принимать только одну переменную. KEY: Только для ON KEY GOSUB, KEY(n) ON/OFF. LOCATE: Обе координаты должны быть определены. Параметр переключения курсора недоступен. NEXT: Имя переменной цикла после NEXT не может быть опущено. ON: ON STOP GOSUB, ON INTERVAL GOSUB не доступны. PRINT: Разделители обрабатываются иначе. Нет выравнивания для цифр. PUT: Только PUT SPRITE. RUN: Переменные не инициализируются. SCREEN: Только номер режима и размер спрайтов. SET: Только SET PAGE. STOP: Такое же поведение как у END. USR: Параметром может быть только Int. VARPTR: Дескриптор файла не может быть передан в качестве параметра.
На первый взгляд, никакой пользы от такой компиляции. Тем не менее, это только первое впечатление от прочитанного!
К тому же, все эти команды, и команды из первого списка, остаются доступными за пределами блока компиляции.
В дополнении, с версии 2.0, доступны еще несколько нововведений:
Здесь, строки 120 и 130, означают следующее:Код:#I - Команда включения INLINE машинного кода в тело программы: 100 DEFINT A-Z 110 K=1 120 '#I &H2A,K 130 '#I &HF3,&HCD,@150,&HFB 140 END 150 'SUB 160 RETURN
Код:LD HL,(K); (где переменная K должна быть типа INT) DI CALL @150; (Здесь указан вызов подпрограммы бейсика по адресу строки 150. Строка вызова должна входить в блок компиляции!) EI
Таким образом, упрощается само использование машинных подпрограмм в коде, не нужно тратить ресурсо-емкий оператор DATA.
В качестве полезного примера, приведу такой:
Так как в графических режимах запрещен вывод текста в блоке компиляции, я написал простой код:
Подпрограмма вывода строк находится по адресам: 70-110 (Выделено зеленым цветом).Код:10 DEFINTA-Z 20 SCREEN 7,0,0:COLOR 15,0,0:CLS:PSET(0,0),0,TPSET 30 _TURBO ON 40 CN=500:TIME=0:A$="New String Here (Нoвая строка хере)" 50 X=RND(1)*(512-LEN(A$)*8):Y=RND(1)*200:C=RND(1)*8+8:GOSUB 70 60 IF STRIG(0) OR CN=0 GOTO 120 ELSE CN=CN-1:GOTO 50 70 ' SUB Put_String(a$,x,y,c) 80 COLOR C:PRESET(X,Y):FOR I=1 TO LEN(A$):K=ASC(MID$(A$,I,1)) 90 '#I &h3A,K 100 '#I &HCD,&H8D,&H00 110 NEXT I:RETURN 120 SCREEN 0:PRINTTIME/60;" Seconds" 130 _TURBO OFF 140 END
Код выводит в рандомных координатах (с учетом длины строки), 500 строк рандомным цветом на экран,
с логической операцией TPSET (вывод только ненулевых пикселей),и считает время вывода.
Ярким синим выделен оператор PSET вначале, чтобы показать, что переопределение логики вывода, так же должно находиться за блоком компиляции, ввиду того, что переменная MSX-Basic'a, которая хранит логику вывода, изменяется только в своей области видимости.
Очевидно, что можно писать в эту переменную напрямую по адресу, но я не помню ее адрес
Аналогичная программа в штатном бейсике выглядит так:
Здесь подпрограмма находится по адресам 50-70, красным выделены запрещенные операторы в X-Basic.Код:10 DEFINTA-Z:SCREEN 7,0,0:COLOR 15,0,0:CLS:CN=500:TIME=0 20 OPEN"grp:" FOR OUTPUT AS#1:A$="New String Here (Нoвая строка хере)" 30 X=RND(1)*(512-LEN(A$)*8):Y=RND(1)*200:C=RND(1)*8+8:GOSUB 50 40 IF STRIG(0) OR CN=0 GOTO 80 ELSE CN=CN-1:GOTO 30 50 ' SUB Put_String(a$,x,y,c) 60 COLOR C,0:PRESET(X,Y),0,TPSET 70 PRINT#1, A$:RETURN 80 SCREEN 0:PRINT INT(TIME/60);" Seconds" 90 END
Сравним время вывода 500 строк на экран?
Вывод штатными графическими средствами MSX-Basic 2.1: 128.66 секунд
Вывод машинным кодом в блоке компиляции X-Basic 2.1: 84.17 секунд
(ради эксперимента, проверил так же подпрограмму, где весь цикл вывода строки написан в кодах, получил доп.выигрыш +3 секунды)
Ну и как вам такое? При этом код на X-Basic'е занял меньше памяти!
Оставшиеся две опции управления блоком компиляции такие:
Код:#C - Опция включает/отключает графический клипер. Доступно в режимах 5-8 (кроме операторов PAINT, и CIRCLE). 10 SCREEN 8 20 '#C- 30 LINE(0,0)-(255,255) 'Y CLIPPED 40 IF INKEY$="" THEN 40 50 '#C+ 60 LINE(0,0)-(255,255) 'NOT CLIPPED 70 IF INKEY$="" THEN 70Код:#N - Опция включает/отключает проверку переполнения переменной условия: 10 FOR I%=0 TO &H7FFF 20 NEXT I%
В штатном MSX-Basic, такой цикл выдаст ошибку переполнения. И если включить его в блок компиляции, то такой цикл становится бесконечным.
Если указана опция #N+, то проверка будет выполнена, и цикл отработает корректно.
Это несомненно снижает эффективность кода, и поэтому лучше не использовать эту опцию, кроме тех случаев, когда это действительно необходимо.
Опция #N-, отключает проверку.
Взять ROM Kun-Basic-2.1 можно на http://www.planetemu.net
Существует BIN - версия, но я ее не держу в арсенале, и 2.1 в таком виде не видел.
Меня самого, шокировало прежде всего то, что я ничего не знал о таком великолепном инструменте в свое время,
а когда проверил быстродействие то и вовсе был сражен наповал!
В заключении, хочу добавить, что если внутри блока компиляции стоит переход на несуществующую строку, то при запуске вы получите сообщение об ошибке, что какая-то строка не найдена, но вот где, и какая конкретно - придется искать, потому что компилятор не видит номера строк.
И последнее: при использовании компилятора, объем используемой памяти сильно расходуется.
Так например передача параметров, увеличивает требуемую область данных, а в среднем доступно около 10кб для кода.
Эти недостатки были устранены в следующем, еще более мощном инструменте, созданном Нестором Сориано (Nestor Soriano),
который тотально расширил возможности X-Basic'а, просто взгляните на них:
Nestor-Basic from Nestor SorianoAccess to all the mapped memory available on the computer (all the free memory when using DOS 2), up to 4 Mb.
Full access to VRAM, including data blocks exchange between RAM and VRAM.
BASIC programs storage in mapped memory, it is possible to switch from one to another without losing the existing variables.
Disk files and sectors access, it is possible to directly read/write to/from mapped memory and VRAM. File searching, directories management.
Graphic compression/decompresion.
MoonBlaster music replay. Samplekit and wavekit load.
PSG sound effects replay.
Machine code routines execution; routines placed in BIOS, in a mapped memory segment or in BASIC main memory (including system work area) can be executed directly or using interrupts.
NestorMan functions, InterNestor Suite and InterNestor Lite routines execution.
Таким образом Nestor-Basic, это развитие Kun-Basic'a, в котором появилась возможность создавать программы, не ограниченные объемом штатного MSX-Basic'а, а код можно вызывать из других слотов и даже видеопамяти!
Плейеры MoonBlaster и PSG, полноценные низкоуровневые дисковые операции, компрессор/декомпрессор графики, и многое другое!
Надеюсь у вас уже зачесались руки, проверить все описанное выше в действии.
А если нет, добавлю сюда еще примеров моих извращений над бейсиком, которые красноречиво показывают, насколько X-Basic, делает MSX-Basic круче:
1. Standart MSX2 Basic v2.1
2. MSX2 Basic v2.1 + X-Basic-2.1 extention:
На обоих видео один и тот же код, только во втором, добавлены команды определения блока компиляции.
И последний показательный пример:
В котором я взял файл PSG, запихуил его в видеопамять, и проиграл, тем самым оценив всю непревзойденную мощь X-Basic-2.1.
Успешных начинаний, всех с наступившей весной!