Вход

Просмотр полной версии : Старый-Новый Язык Noahsoft PL65



ezswift
18.08.2017, 10:35
Здравствуйте друзья!

В данной теме мне бы хотелось обсуждать давно забытый язык программирования Noahsoft PL65.
Ноасофт в переводе Софт Ноя. (Это тот, кто с ковчегом намыкался.)

Этот язык ничего общего не имеет ни с PL/1, ни PL/65. Просто - другой язык.
В нём, как в Ноевом Ковчеге, сохранены все лучшие возможности таких языков как Алгол, Бейсик, Форт, Лисп, Допотопный Си (ешё до K&R C) и Ассемблер.

Все библиотеки в нём текстовые, их много и они покрывают все потребности/особенности Атари.
Программы компилируются с Диска на Диск, поэтому величина текстов не особенно существенна.
Это полноценная программная среда включающая Редактор, Компилятор и Оболочку среды.

Он пришёл к нам со времени, когда ещё никто не знал какими должны быть языки программирования.
Тем не менее я люблю его, написал для него парочку библиотек и опубликовал парочку видео на ютьюбе.

Вот ссылочки:
https://www.youtube.com/watch?v=oeg5fF398nM&t=323s
https://www.youtube.com/watch?v=4r8ibmREj04&t=38s

Ваш ezswift

ezswift
20.08.2017, 15:40
Здравствуйте, друзья!

Чтобы не быть голословным, предлагаю Вашему вниманию Сниппеты кода, где явно видно необычное применение PL65.

1) В PL65 существуют Абсолютные как в ассемблере целые переменные


BYTE NMIEN=$D40E ! Определение Абсолютного целого
...
NMIEN=$C0 ! Присваивание этому абсолютному адресу значения


2) А вот, следующий код демонстрирует поведение PL65 очень похожее на стэковый язык Форт.


PROC POS(INT col=$55 BYTE row=$54)
BEGIN END

Я имею ввиду, что данные на стэке, полученные из формальных параметров,
которые типизируются прямо в списке формальных параметров как абсолютные целые,
как в форте сразу же из стэка поступают в необходимые ячейки памяти.
Больше ничего делать программе не нужно.

3) А вот этот код по поведению похож на форму Лиспа LAMBDA, где Лямбда это определение функции,
которое может и существовать и вычисляться отдельно от объявления, даже без имени ...


PROC WRTSTR(INT addr,len) FORWARD ! Это объявление процедуры
...
BODY WRTSTR ! А это её определение (что, собственно, она делает) ...
BEGIN ! Как видите, не заданы ранее описанные параметры
PCHAR(0,addr,len) ! Вызов библиотечной процедуры
END


4) ... и даже быть аргументом другой функции ...
Я имею ввиду здесь, что арументы из ранее описанной процедуры POS, при таком её вызове,
не стягиваются со стэка, а напрямую передаются в процедуру PLOT, что экономит машинное время,
затрачиваемое обычно на подготовку стэка для любой процедуры.


PROC PLOT(PROC POS) ! Earlier defined...
BEGIN PUT(6,color) END


5) А это ПРИМАТИВНАЯ(со звёздочкой), от слова Примат, то есть ПРЕДПОЧИТАЕМАЯ,
процедура на встроенном ассемблере.
Это означает, что PL65, убирает прочь свои руки от ассемблирования.
Это просто библиотечная процедура CIO.
Разница с ассемблером в том, что PL65 использует свой собственный программный стэк,
в отличие от аппаратного стэка процессора, применяя свою собственную
внутреннюю переменную STACK и что регистр процессора X используется в PL65 только
для обслуживания программного стэка, а значит до его использования должен быть сохранён
во встроенной переменной XSAVE и после его использования, восстановлен из этой переменной.


PROC CIO*(BYTE iocb BYTE com INT addr,len)
BEGIN
LDA STACK+6,X
ASLA ASLA ASLA ASLA
TAY
LDA STACK+4,X STA ICCOM,Y
LDA STACK+2,X STA ICBAL,Y
LDA STACK+3,X STA ICBAH,Y
LDA STACK,X STA ICBLL,Y
LDA STACK+1,X STA ICBLH,Y
TXA CLC
ADC #8 STA XSAVE
TYA TAX
LDA OCHAR
JSR $E456 BMI ioerr
LDX XSAVE RETURN
:ioerr LDX XSAVE
DEX DEX TYA
STA STACK,X
LDA #0 STA STACK+1,X
ERROR*()
WRTSTR("Error ")
WRITE(ERRNUM)
END


6) Из Бейсика в PL65 сохранены операторы DATA, TRAP NOTRAP ON GOTO.
Как Вы понимаете, я например могу использовать DATA задаваемые в Бейсике
как инлайн код в PL65, задавая таким образом, например шрифт
или сассемблированный код Бейсика, применив лишь незначительные изменения.
заменяя лишь PLA на PULL и PHA на PUSH.

Ну, что? Нравится ?..
ez

PS Я, кстати, добавил ещё видео
https://www.youtube.com/watch?v=NlBwBybF9Us

s_kosorev
20.08.2017, 16:12
А вот этот код по поведению похож на форму Лиспа LAMBDA, где Лямбда это определение функции,
которое может и существовать и вычисляться отдельно от объявления, даже без имени ...
это обычное forward определение функции, лямба чуть другое

var fn = (msg:string) => console.log(msg)
или так
arr.foreach(msg => confole.log(msg))
или совсем так
function getAdder (secondArg:number) { return (firstArg: number) => firstArg + secondArg };

у них есть приколы с замыканием

ezswift
20.08.2017, 17:09
Привет друзьям с Украины!

Я часто у Вас в области отдыхал на Слиянии Оскола и Северского Донца (ст. Букино)

Места НЕЗАБЫВАЕМЫЕ! Правда сейчас там, в Изюме, как я полагаю танки... :(
Однако, ВСЁ проходит!

Соглашусь! ... Да! ...
И ... Не чуть! :)

Просто я программирую только любительски и исключительно для Атари-8.

В Интерлиспе/65 я давно и сурово разочаровался.
Он такой древний, что даже не понимает память 130XE, а большая память для Лиспа - это ВЕЩЬ!

Я хотел спросить, то, что Вы пишете, это какая-то нотация, типа Бэкуса-Наура или реальный язык?
Ну, типа Схема?

И, если Вы теоретик программирования, может, изложите своё представление Лиспа для Атари-130 и далее... (с расширённой памятью)...

Просто, я давно общаюсь с Карстеном Строттманом, который для современного Атари хотел написать Лисп, но упёрся в отсутствие теории.
Ну, нету у него русскоязычных книг, описывающих теорию создания Лиспа с нуля.
Я такие читал, но я, вовсе, не программист и не переводчик.

А вот - определение Факториала на Атарьском Интерлиспе/65.


(DEFINEQ !
(LAMBDA (N)
(COND ((EQ N 0)
1)
(T (* N (! (SUB N 1)))))
)


ez

s_kosorev
21.08.2017, 00:13
Я хотел спросить, то, что Вы пишете, это какая-то нотация, типа Бэкуса-Наура или реальный язык?
Ну, типа Схема?
синтаксис в C# и JavaScript практически один в один

ezswift
23.08.2017, 12:27
Спасибо за Информацию :)

Сегодня хотел бы познакомить Вас с процедурами типа INTERRUPT.

Это обычные процедуры, позволяющие обработку прерываний на языке высокого уровня.
Отметим следующее:
1. Так как программы прерываний не могут быть вызваны из обычной процедуры, то списка параметров вызова в INTERRUPT процедуре не существует!
2. Сама INTERRUPT процедура, тем не менее может вызывать обычные процедуры или функции.
3. INTERRUPT процедуры могут быть описаны как FORWARD процедуры.
4. Так как механизм установки прерываний системозависим, (в разных случаях разный), то нет процедуры высокого уровня для этой цели, но обычно, нужно в правильный адрес занести адрес нашей процедуры, а потом установить флаг инициализации.
5. Ни TRAP, ни ERROR процедуры не рекомендуется использовать в прерываниях, так как в этих случаях прерывается сама процедура прерывания.


! DLI.PRG

INTERRUPT dli()
BYTE COLPF2=$D018 ! Регистр фона экрана
BEGIN COLPF2=30 END ! Задаём другой цвет

PROC setDli()
CONST VDSLST=$0200 ! Системный вектор прерываний DLI
INT SDLSTL=$0230 ! Переменная адреса начала Дисплейного Листа
BYTE NMIEN=$D40E ! Регистр НЕМАСКИРУЕМЫХ прерываний
POINTER ptr ! Указатель общего назначения
BYTE mod BASED ptr
INT vec BASED ptr
BEGIN
ptr=VDSLST vec=.dli ! Задание адреса нашей dli процедуры в векторе
ptr=SDLSTL+16 mod=$82 ! Изменение команды в Дисплейном Листе на 16-й строке (DLI выполняется с 17-й!)
NMIEN=$C0 ! Активация прерывания
END

MAIN()
BEGIN setDli() END


А вот, что вышло...
https://drive.google.com/open?id=0B3ul-RAQNdqjQ1BPVXhiRTlYZXM

ezswift
28.09.2017, 16:28
Сегодня - удивительный день.

Сегодня (я это сегодня увидел...) моё программирование на языке PL65 было занесено на САМУЮ-САМУЮ базу данных Атарьки-8.
На Вики Карстена Строттманна.

Так как это было сделано не по моей просьбе, а по моим заслугам, я счастлив!
zen

Shiny
28.09.2017, 18:52
кстати, а что за программа? я вики изучал только поверхностно.

ezswift
29.09.2017, 10:05
кстати, а что за программа? я вики изучал только поверхностно.

Шынни, Здравствуйте.

Дело в том, что PL65 имеет страшно длинную и занудную, зато подробную и исчерпывающую документацию.

Так как во многом в языке подходы нестандартные, а разбираться сложно, (в то время, даже терминология не устоялась)
то её, собственно никто кроме меня и не читал.
Второй язык, про который только я и читаю - это СС8, а третий Интерлисп/65.
В своё время Интерлисп меня здорово занимал, но его просто не доделали, так как эра Атарек прошла.
Уже были не только 88/86, но уже и 286/386 машины.

Ну, я и написал в форуме AtariAge парочку текстов для примера работы с этими необычностями.
Библиотеку работы с 'Кучей' и библиотеку парсинга контрольных символов клавиатуры.
(Кстати, сегодня покончил с библиотекой прямого доступа к экрану.)

Ну, видать германским товарищам примеры понравились, вот и разместили в википедии.

А меня самого порадовать забыли.
Зато благодарят :)

ezswift
27.09.2018, 10:18
Добавил Видео https://www.youtube.com/watch?v=yIHH0KDo5-c по программированию на встроенном ассемблере PL65.
Надеюсь пригодится.
zen

ezswift
24.10.2019, 03:22
Всем ГОРЯЧИЙ ПРИВЕТ!

Начал создавать библиотеку ассемблерного доступа к экрану.
Вот видео https://www.youtube.com/watch?v=5CHvHxoi78I&t=3476s

Вот коды:

!====================================!
! BLOKS.LIB zenSoft !
! Text Screen !
! Block oriented assembly procedures !
! for PL65 Programming Language !
!------------------------------------!
! Evgeny Zolotarev,(aka 576XE), 2019 !
!====================================!

!= Globals ==========================!
POINTER src,dst
INT SAVMSC=$58,BUFR=$4000

!= Block Oriented Procedures ========!
!- Save Block to Buffer -------------!
PROC saveBlk(BYTE x,y,w,h)
BYTE wid,hei
BEGIN
wid=w hei=h
src=SAVMSC+y*40+x-1 dst=.BUFR
STX XSAVE
LDX #$00
!- Lines treatment ------------------!
:nxtln LDY wid
!- Bytes treatment ------------------!
:nxtby LDA (src),Y STA (dst),Y
LDA #$00 STA (src),Y
DEY
BNE nxtby
!- Line_start plus 40 ---------------!
CLC
LDA src
ADC #40
STA src
LDA src+1
ADC #$00
STA src+1
!- Add wid to Buffer ----------------!
CLC
LDA dst
ADC wid
STA dst
LDA dst+1
ADC #$00
STA dst+1
!- To next Line ... -----------------!
INX
CPX hei
BNE nxtln
LDX XSAVE
END
!- Restore Block from Buffer --------!
PROC restBlk(BYTE x,y,w,h)
BYTE wid,hei
BEGIN
wid=w hei=h
src=.BUFR dst=SAVMSC+y*40+x-1
STX XSAVE
LDX #$00
!- Lines treatment ------------------!
:nxtln LDY wid
!- Bytes treatment ------------------!
:nxtby LDA (src),Y STA (dst),Y
DEY
BNE nxtby
!- Line_start plus 40 ---------------!
CLC
LDA dst
ADC #40
STA dst
LDA dst+1
ADC #$00
STA dst+1
!- Add wid to Buffer ----------------!
CLC
LDA src
ADC wid
STA src
LDA src+1
ADC #$00
STA src+1
!- To next Line ... -----------------!
INX
CPX hei
BNE nxtln
LDX XSAVE
END
!- Invert Screen Block --------------!
PROC invBlok(BYTE x,y,w,h)
BYTE wid,hei
BEGIN
wid=w hei=h src=SAVMSC+y*40+x-1
STX XSAVE
LDX #$00
!- Lines treatment ------------------!
:nxtln LDY wid
!- Bytes treatment ------------------!
:nxtby LDA (src),Y
EOR #$80
STA (src),Y
DEY
BNE nxtby
!- Line_start plus 40 ---------------!
CLC
LDA src
ADC #40
STA src
LDA src+1
ADC #$00
STA src+1
!- To next Line ... -----------------!
INX
CPX hei
BNE nxtln
LDX XSAVE
END
!====================================!
! End of Library
ENDFILE




!====================================!
! BLOKS.PRG zenSoft !
! PL65 Programming Language !
!------------------------------------!
! Evgeny Zolotarev,(aka 576XE), 2019 !
!====================================!

CONST void=$FF,esc=$1C
BYTE CH=$02FC
INCLUDE BLOKS.LIB

!= Miscellaneous Proces & Funcs =====!
FUNC readKey()
BYTE chr
BEGIN
WHILE CH=void DO ENDWHILE ! wait...
chr=CH CH=void
END chr

MAIN()
BYTE x,y,w,h,c
BEGIN
x=3 y=3 w=20 h=10
REPEAT
c=readKey()
IF c=esc THEN RETURN ENDIF
invBlok(x,y,w,h)
c=readKey()
IF c=esc THEN RETURN ENDIF
invBlok(x,y,w,h)
c=readKey()
IF c=esc THEN RETURN ENDIF
saveBlk(x,y,w,h)
c=readKey()
IF c=esc THEN RETURN ENDIF
restBlk(x,y,w,h)
FOREVER
END

Надеюсь кому пригодится...
zen

nihirash
24.10.2019, 13:38
Ох уж этот модула-пободный синтаксис.

Меня Amiga E коробит исключительно этим.

bigral
25.10.2019, 15:45
Mда синтаксис содран с алгола, ну и потому похож на pascal, modula. В принципе обкатанный синтаксис легко воспринимаемый студентами. В совдепии был "алгоритмический язык" тоже самое примерно что и тут, только сокращения с русского языка ЕСЛИ ... ТО ... ИНАЧЕ ... ВСЕ

Oleg N. Cher
27.10.2019, 21:06
А язычок-то смотрится поприятнее, чем PL/M.

andrews
27.10.2019, 21:50
Еще есть Action! https://en.wikipedia.org/wiki/Action!_(programming_language) Описание, примеры, доступен в исходниках

ezswift
28.10.2019, 14:14
Здравствуйте ВСЕ!!!

2Oleg N. Cher :)
Pl65 даже приятнее, чем я думал, когда изменил ему ради Паскаля... Скорблю!

У него, ПАРДОН, Атарьское распределение Памяти. (Sic!)

Я ведь, не зря прячу окна по адресу $4000!
Надеюсь, когда-то, разродится всё - работой на Куче.

Об этом видео запилю... "Славься Кей!..."

Очень страдаю от отсутствия 8-bit алгоритмов... Разных... Рою интернет как ломовая лошадь!
А Гуголь - не Гоголь. Он покруче муть выдаёт!!!

В общем, с Паскалем (Прости, Блез) я распрощался на время...

Сейчас вошкаюсь по теме вертикальная линия на Ассемблере PL65
Ну, не устраивает меня скорость её прорисовки в нативе !!!
Я пробовал внутренние процедуры FILL и MOVE.
Они и вправду эффективны и быстры, но их вызов(ы) безумно медленный(е).
Как только ВСЁ ЭТО попадает в цикл Вы видете, что линия РИСУЕТСЯ, а отнюдь не ВОЗНИКАЕТ!

Надо на ассемблере...

С Паскалем - не справляюсь, с PL65 пжалста!

Я не гоню на Паскаль!
Любой Язык Высокого Уровня Ущербен Изначально!
Так как вынужден применять ДОПУЩЕНИЯ.

Но, на ассемблере сами возИтесь! Кто мешает?

Теперь про ACTION!
Это - Стопроцентно Атарьский язык!!!
Но, с ним работать, как в лужу пукать.
Эффектно (Effectus), но мокро и муторно.

Это - просто ПЕРЕХОДНЫЙ язык.
Ему надо ВЗРОСЛЕТЬ!

И PL65 - просто его старший брат.
zen

ezswift
29.10.2019, 10:48
[QUOTE=pinny;1031144]Ох уж этот модула-пободный синтаксис. :)

Ну НЕТ у Атари фигурных скобок !!! Матчасть!
zen

nihirash
29.10.2019, 13:32
Ну НЕТ у Атари фигурных скобок !!! Матчасть!

Я затупил, что это не кросскомпилятор.

Да и на атари я только играю)

ezswift
29.10.2019, 16:46
2pinny :)
Атари - интересная машинка - факт.

Её подсистемы при должном развитии плавно перешли к Северному и Южному мостам, USB и одноплатному конструктиву.
Более того, система обработки картриджей позволяет такое, что и не снилось никаким PC.
Вставил картридж и заменил системный БИОС... Где такой слот у Писюка?

Ну, я не маньячу, хотя похоже...
Я просто ЛЮЛЮ Атари.
Пытаюсь сделать для неё что-то и пр.
zen

ezswift
20.12.2020, 09:12
Здравствуйте, друзья!

Вот как раз к Новому году написал на PL65 программульку доступа ко всей расширеной памяти Атари.
В эмуляторах глючит.
На реальной машине всё OK :)

Вот код: (Пока подождите. Выловил какие-то глюки при исправной IMHO программе)

ezswift
22.12.2020, 12:23
Я, конечно огорчён, что программулька не работает гладко, но на Real HW ВСЕ работает !!!
Вот изящный код.


!====================================!
! BANKS.PRG !
! Using 130XE Extended Banks in !
! PL65 Programming Language !
!------------------------------------!
! Evgeny Zolotarev,(aka 576XE), 2020 !
!====================================!
INCLUDE TERMINAL.LIB

!- CONSTANTS & VARIABLES:
CONST bkMask=%10010001
BYTE PORTB=$D301,NMIEN=$D40E,bkTag
INT bkNum

!- DUMMY array representing ---------!
!- selected BANK's slice ------------!
BYTE bkMem[$4000]=$4000

!- Bank Selector Values 576XE -------!
!- Atari800WinPlus/Altirra (Rambo) --!
BYTE bkSel[33]
DATA $91,
$81,$83,$85,$87,$89,$8B,$8D,$8F,
$A1,$A3,$A5,$A7,$A9,$AB,$AD,$AF,
$C1,$C3,$C5,$C7,$C9,$CB,$CD,$CF,
$E1,$E3,$E5,$E7,$E9,$EB,$ED,$EF;

! String VAR to store in all BANKS
STRING inp$[4+27]
DATA " => User DATA from Bank #00";

! Set string as VAR for appending
STRING out$[4+27]
DATA " ";

!- PROCEDURES:
!- Clear Screen Procedure -----------!
PROC clrScr()
CONST clr=255
BEGIN WRTSTR(CHR$(125)) END

!- Wait for Any Key Pressed ---------!
PROC anyKey()
CONST none=255
BYTE CH=764
BEGIN
WRTSTR("Wait for a Key...") CR()
WHILE CH=none DO ENDWHILE
CH=none
END

!- Place bkSel Tags into PORTB ------!
PROC setBk*(BYTE bkTag)
BEGIN
!- Wrapper STOPs/STARTs IRQ & NMI ---!
SEI LDA #$00 STA NMIEN
LDA PORTB
AND bkMask OR bkTag
STA PORTB
LDA #$40 STA NMIEN CLI
END

!- Send bkNum to setBk subroutine ---!
PROC setBank(INT bkNum)
BEGIN
bkTag=bkSel[bkNum]
setBk*(bkTag)
END

!- Writes to Bank -------------------!
PROC writBk()
BEGIN
FOR bkNum=0 TO 32 DO
WRTSTR("Writing to BANK #") WRITE(bkNum) CR()
IF bkNum<10 THEN
inp$[25,25]=STR$(0) inp$[26,26]=STR$(bkNum)
ELSE inp$[25]=STR$(bkNum) ENDIF
out$=inp$
setBank(bkNum)
MOVE(.out,LEN(out$),.bkMem)
NEXT
END

!- Reads from Bank ------------------!
PROC readBk()
BEGIN
FOR bkNum=0 TO 32 DO
WRTSTR("Reading BANK #") WRITE(bkNum) CR()
setBank(bkNum)
MOVE(.bkMem,LEN(out$),.out)
WRTSTR(out$) CR()
NEXT
END

!------------------------------------!
MAIN()
BYTE PORT
BEGIN
LDA PORTB STA PORT
clrScr() anyKey() writBk()
anyKey() clrScr() readBk()
LDA PORT STA PORTB
END
! >>> EOF <<< !


Проблемы возникают только при переходе от 0-го (основного) банка памяти к расширенной памяти.
Что интересно, данные заносятся и в основную память. Проверял в мониторе.
При работе только с расширенной памятью(bkNum от 1 to 32) их нет! Что-то в эмулях !!!

zen

ezswift
24.12.2020, 12:37
Ну, значит, продолжение истории...
Связался я с Avery Lee - создатель Алтирры и он тут же намекнул в чём проблема кода.
Почему намекнул, а потому, что он же не знал как именно я включаю реальную Атарьку.

В общем, располагая данными программки XRAM, я отмаскировал все биты в PORTB, которые нас не могли интересовать и получил значение включённого нулевого(main) фрейма как $91. Здесь, почти ВСЁ было правильно, кроме первого(второй по счёту справа) бита.
Для PORTB он работает инверсно по отношению к остальным.

То есть когда я обнулял его программно, ОН ВКЛЮЧАЛ БЕЙСИК, а бейсик при загрузке вызывал GR. 0, то есть, переносил память и инициализировал новый экран, что и портило мою программку.

Вот рабочий код:


!====================================!
! BANKS.PRG !
! Using 130XE Extended Banks in !
! PL65 Programming Language !
!------------------------------------!
! Evgeny Zolotarev,(aka 576XE), 2020 !
!====================================!
INCLUDE TERMINAL.LIB

!- CONSTANTS & VARIABLES:
CONST bkMask=%10010001
BYTE PORTB=$D301,NMIEN=$D40E,bkTag
INT bkNum

!- DUMMY array representing ---------!
!- selected BANK's slice ------------!
BYTE bkMem[$4000]=$4000

!- Bank Selector Values -------------!
!- Atari800WinPlus 576XE ------------!
BYTE bkSel[33]
DATA $93,
$81,$83,$85,$87,$89,$8B,$8D,$8F,
$A1,$A3,$A5,$A7,$A9,$AB,$AD,$AF,
$C1,$C3,$C5,$C7,$C9,$CB,$CD,$CF,
$E1,$E3,$E5,$E7,$E9,$EB,$ED,$EF;

!- Bank Selector Values -------------!
!- Altirra 576XE Compy scheme -------!
! BYTE bkSel[33]
! DATA $33,
! $21,$23,$25,$27,$29,$2B,$2D,$2F,
! $61,$63,$65,$67,$69,$6B,$6D,$6F,
! $A1,$A3,$A5,$A7,$A9,$AB,$AD,$AF,
! $E1,$E3,$E5,$E7,$E9,$EB,$ED,$EF;

! String VAR to store in all BANKS
STRING inp$[4+27]
DATA "==> User DATA from Bank #00";

! Set string as VAR for appending
STRING out$[4+27]
DATA " ";

!- PROCEDURES:
!- Clear Screen Procedure -----------!
PROC clrScr()
CONST clr=255
BEGIN WRTSTR(CHR$(125)) END

!- Wait for Any Key Pressed ---------!
PROC anyKey()
CONST none=255
BYTE CH=764
BEGIN
WRTSTR("Wait for a Key...") CR()
WHILE CH=none DO ENDWHILE
CH=none
END

!- Place bkSel Tags into PORTB ------!
PROC setBk*(BYTE bkTag)
BEGIN
!- Wrapper STOPs/STARTs IRQ & NMI ---!
SEI LDA #$00 STA NMIEN
LDA PORTB
AND bkMask OR bkTag
STA PORTB
LDA #$40 STA NMIEN CLI
END

!- Send bkNum to setBk subroutine ---!
PROC setBank(INT bkNum)
BEGIN
bkTag=bkSel[bkNum]
setBk*(bkTag)
END

!- Writes to Bank -------------------!
PROC writBk()
BEGIN
FOR bkNum=0 TO 32 DO
WRTSTR("Writing to BANK #") WRITE(bkNum) CR()
IF bkNum<10 THEN
inp$[25,25]=STR$(0) inp$[26,26]=STR$(bkNum)
ELSE inp$[25]=STR$(bkNum) ENDIF
out$=inp$
setBank(bkNum)
MOVE(.out,LEN(out$),.bkMem)
NEXT
END

!- Reads from Bank ------------------!
PROC readBk()
BEGIN
FOR bkNum=0 TO 32 DO
WRTSTR("Reading BANK #") WRITE(bkNum) CR()
setBank(bkNum)
MOVE(.bkMem,LEN(out$),.out)
WRTSTR(out$) CR()
NEXT
END

!------------------------------------!
MAIN()
BEGIN
clrScr() anyKey() writBk()
anyKey() clrScr() readBk()
END
! >>> EOF <<< !


Заметьте, что я оставил маску ПРЕЖНЕЙ (Маска просто сохраняет от стирания системные данные в PORTB), зато значение нулевого тэга поменял. Можно ещё в конце MAIN добавить восстановление PORTB, но мне не это было нужно, а работа с EXTMEM. :)

zen

- - - Добавлено - - -

Ну, хотелось бы прояснить как с этим можно работать.

Раз у нас есть доступ ко всей памяти, мы можем исключить из списка основную память - $93, 130XE память - ($E3,$E7,$EB,$EF), например для рамдиска или программ её использующих (MAE assembler, CLSN Pascal etc.), зато остальную память отдать программной Куче. :)

zen

Lethargeek
24.12.2020, 12:46
Ну НЕТ у Атари фигурных скобок !!! Матчасть!
где-то и квадратных нету еще - а паскаль и си есть, однако
матчасть не мешает применять диграфы, не аргумент

ezswift
24.12.2020, 13:04
:)

Я знаю даже то, что некоторые диалекты Си способны воспринимать Пики да Буби как замену всяким Диграфам и Трезубам.
Но я не этим занят...

Например одна и та же стэндэлонная программка на Си вдвое больше по размеру, чем на PL65 и, что характерно, я для этой программки НЕ ТРОГАЛ родную библиотеку TERMINAL.LIB, а можно было бы её подчистить (выкинуть ненужные функции).

zen

ezswift
12.11.2022, 07:58
Увертюра...

В 2014 г. на AtariAge появилась тема "PL65 Problem - WRTSTR/WRTLN" весьма уважаемого пользователя с ником MrFish.

Речь шла о том, что PL65 неверно передаёт строковые параметры в процедуры.
Занимались этой проблемой весьма серьёзные люди - FJC, например...
Склонялись, что что-то портит стек.
...
Так вот, вчера мне удалось понять что происходит и я даже начал писать TEXT.LIB - библиотеку строковых функций, над которой мучился уже полгода.

Смысл был в том, что подробнейшая и полнейшая документация НЕСИСТЕМАТИЗИРОВАНА и несмотря на то, что описано ВСЁ, искать по всему тексту - сплошное мучение. Кроме этого понимание затруднялось неустоявшейся терминологией и наличием "Умолчаний" в документации.

Прошло 8 лет и Вуаля!
Оказалось, что по факту, в языке одновременно существуют два представления строк:

1. Для программиста (для объявления переменной)
объявление -
STRING strg$[255]
инициализация -
DATA "It is simply a String";

2. Для компилятора (для расчётов)

FUNC pos(INT adr,len,adr1,len1)

Теперь-то понятно, что компилятор просто не может прожевать полностью
бессмысленое определение:


FUNC pos(STRING stg$[255],stg2[255])

так как не расшифровывает определения предназначенного только для программиста.

zen

ezswift
19.04.2023, 09:32
Здравствуйте, друзья!

Мне удалось на днях закончить написание Библиотеки обработки текстов для PL65 :)

Я опубликовал соответствующее видео на Youtube.
Вот ссылка:
https://www.youtube.com/playlist?list=PLNR3VBeLxQX9yK-qWnrxcsQqkHaMotUB4

Код Библиотеки:

!====================================!
! TEXT.LIB !
! Text Functions Library for PL65 !
! Programming Language !
!------------------------------------!
! Evgeny Zolotarev,(aka 576XE), 2023 !
!====================================!
POINTER sP BYTE sV BASED sP
BYTE wV BASED sP
!====================================!
FUNC Left$(INT sA,sL,n)
STRING out$[256] INT i
BEGIN
FOR i=0 TO n DO
sP=sA+i out$[i,i]=CHR$(sV)
NEXT
END out$
!------------------------------------!
FUNC Mid$(INT sA,sL,m,n)
STRING out$[256] INT i
BEGIN
sA=sA+m-1
FOR i=0 TO n DO
sP=sA+i out$[i,i]=CHR$(sV)
NEXT
END out$
!------------------------------------!
FUNC Right$(INT sA,sL,n)
STRING out$[256] INT i
BEGIN
sA=sA+sL-n
FOR i=0 TO n DO
sP=sA+i out$[i,i]=CHR$(sV)
NEXT
END out$
!------------------------------------!
FUNC Pos(INT pA,pL,sA,sL)
POINTER pP BYTE pV BASED pP
INT i,j,psn BYTE f
BEGIN
IF pL<=sL THEN
sL=sL-pL+1
i=0 j=0
! While Fail ...
! Repeating along the String
REPEAT
f=$FF
! If Success...
! Indexing along the Pattern
FOR j=0 TO pL-1 DO
sP=sA+i+j pP=pA+j
IF sV<>pV THEN f=0 ENDIF
NEXT
i=i+1
UNTIL (i=sL OR f<>0)
IF f<>0 THEN psn=i ELSE psn=0
ENDIF
ELSE psn=0 ENDIF
END psn
!------------------------------------!
FUNC Conc$(INT sA,sL,pA,pL)
STRING out$[256] INT i,j
BEGIN
FOR i=0 TO sL DO
sP=sA+i out$[i,i]=CHR$(sV)
NEXT
FOR j=0 TO pL DO
sP=pA+j out$[i+j,i+j]=CHR$(sV)
NEXT
i=sL out$[i,i]=" "
END out$
!------------------------------------!
FUNC Ins$(INT pA,pL,sA,sL,m)
STRING out$[256],a$[256],b$[256]
INT n
BEGIN
a$=Left$(sA,sL,m) b$=Right$(sA,sL,sL-m-1)
n=LEN(a$)+pL+1
a$=Conc$(a$,pA,pL)
out$=Conc$(a$,b$)
END out$
!------------------------------------!
FUNC Del$(INT sA,sL,m,n)
STRING a$[256],b$[256],out$[256] INT i
BEGIN
a$=Left$(sA,sL,m) b$=Right$(sA,sL,sL-m-n)
out$=Conc$(a$,b$)
i=LEN(a$) out$[i,i]=" "
sP=.out-2 wV=sL-n+1
END out$
!------------------------------------!
FUNC Inv$(INT sA,sL,m,n)
STRING out$[256] INT i
BEGIN
out$=Mid$(sA,sL,1,sL)
FOR i=0 TO n-1 DO
sP=.out+m-1+i sV=sV+128
NEXT
END out$
!------------------------------------!
FUNC Upper$(INT sA,sL,m,n)
STRING out$[256] INT i
BEGIN
out$=Mid$(sA,sL,1,sL)
FOR i=0 TO n-1 DO
sP=.out+m-1+i
IF sV>$60 AND sV<$7B
THEN sV=sV-$20 ENDIF
NEXT
END out$
!------------------------------------!
FUNC Lower$(INT sA,sL,m,n)
STRING out$[256] INT i
BEGIN
out$=Mid$(sA,sL,1,sL)
FOR i=0 TO n-1 DO
sP=.out+m-1+i
IF sV>$40 AND sV<$5B
THEN sV=sV+$20 ENDIF
NEXT
END out$
!====================================!
ENDFILE

Вот код проверочной программы:


!====================================!
! TEXT.PRG !
! Text Functions Program for PL65 !
! Programming Language !
!------------------------------------!
! Evgeny Zolotarev,(aka 576XE), 2023 !
!====================================!
INCLUDE TERMINAL.LIB
INCLUDE TEXT.LIB
!====================================!
MAIN()
STRING s$[256],p$[256],a$[256],out$[256] INT psn,m,n
BEGIN
s$="Moscow Alma-Ata Petersburg Evpatoria Feodosia Simeiz Konakovo"
p$="Alma-Ata" a$="Syktyvkar"
m=15 n=12
CR()
WRTSTR("Left$ - ") WRTLN(Left$(s$,6))
WRTSTR("Mid$ - ") WRTLN(Mid$(s$,8,8))
WRTSTR("Right$ - ") WRTLN(Right$(s$,8))
CR()
psn=Pos(p$,s$) WRTSTR("Pos - ") WRITE(psn) CR()
CR()
WRTSTR("Conc$ - ") WRTLN(Conc$(p$,a$))
out$=Ins$(a$,s$,m) WRTSTR("Ins$ -") WRTLN(out$)
out$=Del$(s$,m,n) WRTSTR("Del$ -") WRTLN(out$)
m=17 n=10
CR()
WRTSTR("Inv$ - ") WRTLN(Inv$(s$,m,n))
WRTSTR("Upper$ - ") WRTLN(Upper$(s$,m,n))
WRTSTR("Lower$ - ") WRTLN(Lower$(s$,m,n))
END
!====================================!

78787
Пользуйтесь наздоровье :)
zen