Millfork - средство для погроммирования

 


Один камрад в чятике дал наводку , примеры найдутся тут. С утра посмотрел на это средство программирования.

Первый пример настодоевшей печати(приветствовать мир - это клиника)

// compile with
// java -jar millfork.jar -I ${PATH}/include -t ${platform} ${PATH}/examples/hello_world/hello_world.mfk
import stdio
array hello_world = "Hello world"
void main() {
    ensure_mixedcase()
#if CBM_64 || CBM_264
    set_bg_color(white)
#endif
#if CBM_64 || CBM_264 || ZX_SPECTRUM
    set_border(red)
#endif
    putstr(hello_world, hello_world.length)
    new_line()
    putstrz("Hello world again"z)
#if not(CPM)
    while(true){}
#endif
}

Компиляция(сразу на платформы):

millfork.jar -I d:\8\include\ hello_world.mfk
millfork.jar -I d:\8\include\ -t A8 -s hello_world.mfk
pause


Скомпилировалось и запустилось



раз началось на Atari, то почему бы не попробовать накодить на графику? Смелая задумка пушо возиться с устройствами очень нудно. В примерах нашлось примерчик для Atari, который использовал вызов из ROM:

// idea @ilmenit
// https://demozoo.org/productions/280623
// for 8bit AtariXL, OS Rev 2
alias prev_x = os_OLDCOL.lo
alias cursor_x = os_COLCRS.lo
alias prev_y = os_OLDROW
alias cursor_y = os_ROWCRS
alias color = os_ATACHR
byte i
array(byte) colors = [
  $00,$55,$AA,$FF
]
asm void openmode(byte register(a) m) @ $ef9c extern
asm void drawto() @ $f9c2 extern
void main(){
  openmode(7)
//  os_COLOR4 = 2
  for i,0,to,159 {
os_ATACHR = colors[i&3]
    cursor_x = i
    prev_x = 159-i
    prev_y = 0
    cursor_y = 79
    drawto()
  }
  while true {}
}
Результат работы - скриншот в заголовке. Я долго бился с цветами, которые никак не менялись при вызове. Но потом победил.
Остался последний вопрос - как  вызвать процедуру построения точки? Ответ легко найдется.

Дополнение 30 августа.
Хочешь испортить время и настроение - сядь за код. И вот я засел за построение точек и промаялся весь день.

array(word) sa[192]
array(byte) bw = [$80,$40,$20,$10,8,4,2,1]
pointer sd
asm word call_22b0(byte a,byte c) @ $22b0 extern
void pp(ubyte x,ubyte y)
{
sd=sa[y]+(x>>3)
sd[0] |= bw[x&7]
}
void main() {
byte i
//precalc screen lines adresses
for i,0,to,191
{
sa[word(i)]=call_22b0(i,0)
}
//test plot
for i,0,to,191
{
pp(i,i)
}
    while true {}
}

Для вычисления линейных адресов используется процедура $22B0(это такой грязный хак), но понадобилось, чтобы регистр C=0. вместо ассемблерной вставки использовался такой трюк. но адреса в массив вносились неверно, пришлось извратиться над индексом - word(i)/

Написанная процедура построения точки по координатам не работала - компилятор молча давился на том, что я написал. Оказалось, что для чтения из памяти и записи в память нужно использовать указатель pointer sd.

В общем, оставлю на сладкое кодинг построения окружности Брезенхема, если будет настроение.

Дополнение 1 сентября. Ничто так не бодрит, как попытка накодить программу. Утром засел за алгоритм, и день просто пропал - компиляция не проходила из-за неведомых мне ошибок. Осилил код, но рисовалось невесть что. Сначала накосячил с типом переменных, которые оказались беззнаковыми. Вечером скачал версию 64бит, запустил и слегка офигел от выданных предупреждений. Компилятору не понравилось err+y*2+1, заменил на err=err+y+y+1, и так с другими "неудобными" выражениями. Заработало!
Возможно, найдется простое решение, возможно и нет.
Оставило на утро решение проблем с выводом на экран сообщений компилятора. Решилось, нужно было указать java -jar millfork.jar.Вышло вот что

//Bresenham circle
//http://members.chello.at/easyfilter/bresenham.html
array(word) sa[192]
array(byte) bw = [$80,$40,$20,$10,8,4,2,1]
pointer sd
asm word call_22b0(byte a,byte c) @ $22b0 extern
void pp(ubyte x0,ubyte y0)
{
sd=sa[y0]+(x0>>3)
sd[0] |= bw[x0&7]
}
void inits()
{
 ubyte i
for i,0,to,191
{
sa[word(i)]=call_22b0(i,0)
}
}
void cls()
{
asm
{
// xor a
// ld  b,$18
// call  3652
ld hl,$4000
ld de,$4001
ld bc,6144
ld (hl),l
ldir
ld (hl),$38
ld bc,767
ldir
}
}
void circle(ubyte xm,ubyte ym,ubyte r)
{
sbyte x,y
// ubyte xm,ym,r
unsigned16 err,rr
x=0-r// error with x=-r
y=0
err=2-r-r//2-2*r
do
{
pp(xm-x,ym+y)
pp(xm-y,ym-x)
pp(xm+x,ym-y)
pp(xm+y,ym+x)
rr=err
if (rr<=y) {
y=y+1
err=err+y+y+1//err+y*2+1
}
if (rr>x || err>y) {
x=x+1
err=err+x+x+1//err+x*2+1
}
} while (x<0)
}
void main() {
inits()//precalc screen lines adresses
cls()
circle(128,96,80)
    while true {}
}


Но и на вечер приключения не кончились. Я взял простой Mid-point алгоритм, и получил то ли круг, то ли квадрат, так и не разобрался с причиной. С горя я написал простой хак:


array(byte) bw = [$80,$40,$20,$10,8,4,2,1]
array(word) sa[192]
//pointer sd
asm word call_22b0(byte a,byte c) @ $22b0 extern
void pp(ubyte x0,ubyte y0)
{
pointer sd
sd=sa[y0]+(x0>>3)
 if y0<192
 {
sd[0]^=bw[x0&7]
}
}
void main() {
ubyte i,x,y,yy
word c
//precalc screen lines adresses
for i,0,to,191
{
sa[word(i)]=call_22b0(i,0)
}
c=0
x=0
yy=64
y=yy
    while true
{
x=x-y/2
y=y+x/2
pp(x,y)
c=c+1
if c==20000
{
c=0
yy=yy+1
y=yy
x=0
asm
{
ld hl,$4000
ld de,$4001
ld bc,6143
ld (hl),l
ldir
}
}
}
}

Пока что нельзя сказать, что освоил язык, есть несколько нюансов, которые хотелось бы выяснить, вернусь к записи позже.

Дополнение 05.09 Задали на Atari задачку - печать текста в режиме Бейсика GR.2

array(byte) hello_world = [$30,$31,$32,$33,$9B]
array(byte) nam=[$53,$3a,$9B]
void main() {
asm
 {
lda #18; graphics mode 2+16
       PHA           ; Store on stack
       LDX #$60      ; IOCB6 for screen
       LDA #$C       ; CLOSE command
       STA $0342,X;ICCOM,X   ; in command byte
       JSR $E456;CIOV      ; Do the CLOSE
       LDX #$60      ; The screen again
       LDA #3        ; OPEN command
       STA $0342,X;ICCOM,X   ; in command byte
       LDA #nam&255 ; Name is "S:"
       STA $0344,X;ICBAL,X   ; Low byte
       LDA #nam/256 ; High byte
       STA $0345,X;ICBAH,X
       PLA           ; Get GRAPHICS n
       STA $034B,X;ICAX2,X   ; Graphics mode
       AND #$F0      ; Get high 4 bits
       EOR #$10      ; Flip high bit
       ORA #$C       ; Read or write
       STA $034A,X;ICAX1,X   ; n+16, n+32 etc.
       JSR $E456;CIOV      ; Setup GRAPHICS n
;print #6
lda #2
sta $84
lda #2
sta 85
ldx #$60
lda #hello_world&255
sta $0344,X ; ICBAL
lda #hello_world/256
sta $0345,X ; ICBAL
lda #9
sta $0342,X ; ICCOM
lda #0
sta $0348,X ;ICBLL
lda #$FF
sta $0349,X ;ICBLH
        JSR $E456;CIOV
lda #0
sta 84
lda #2
sta 85
ldx #$60
lda #nam&255
sta $0344,X ; ICBAL
lda #nam/256
sta $0345,X ; ICBAL
lda #9
sta $0342,X ; ICCOM
lda #0
sta $0348,X ;ICBLL
lda #$FF
sta $0349,X ;ICBLH
        JSR $E456;CIOV
 }
//    putstr(hello_world, hello_world.length)
poke(84,5)
poke(85,3)
//    putstr(hello_world, hello_world.length)

    while(true){}
}

Надо почитать доки и изменить код на печать строки без $9b(EOL)

Комментарии