Maj 17, 2013

Action!: Finescroll w VBLKD.

Poprzednie przykłady z “Poradnika programisty” brzydko się rwały przy przesuwaniu, zwłaszcza na prawdziwym Atari. Na podstawie różnych “odkryć i znalezisk” powstał poniższy przykład w Action! wykorzystujący Vertical Blank Interrupt. A tutaj analogiczny przykład, który robi to samo w zwykłej pętli i synchronizuje się z VBLANK interrupt za pomocą zegara systemowego.

int j=[0], k=[0]
byte hscrol=54276
card pointer pc
card tmp

include "H1:RUNTIME.ACT"

proc scroll()
 hscrol=j
 j==+1
 if j=17 then
  j=0 pc^==-2 k==+1
  if k=14 then
   pc^=tmp k=0
  fi
 fi
[$4C $E462] ;jmp xitvbv

proc main()
 int i card savmsc=88
 byte clock=$14
 byte nmien=$D40E
 byte array ndl = [112 112 112 66 64 156 2 2 2 2 2 2 2 2 2 2
                   2 2 2 2 2 2 2 2 2 2 2 86 216 159 65 32 156]
 card dlist=560
 card vvblkd=$0224
 byte col0=708
 byte col1=709

 graphics(0)
 dlist=ndl
 savmsc=40000
 col0=14 col1=14

 for i=1 to 23 do
  printf("line: %i%E", i)
 od

 print("Action!")

 pc=dlist+28
 tmp=pc^+6
 i=clock
 while clock=i do od
 nmien=0
 vvblkd=scroll
 nmien=$40
 do od
return

scroll() dodałem jako część opóźnioną procedury obsługi przerwania. Wg Tajemnic Atari powinno się ustawiać vvblkd po “cyknięciu” zegara, żeby się nie okazało, że nie starczy czasu. Tak też zrobiłem. Nie jestem przekonany czy to jest konieczne.

Maj 7, 2013

Tremolo locker.

Mój najlepszy kolega Krzyś zrobił mi dziś blokadę tremolo wykorzystując co wpadnie w ręce w naszym firmowym warsztacie.

Tym sposobem Cort  ma w końcu “stały mostek” i znacznie dłuższy sustain. Mostek jest zdecydowanie lepiej ustawiony i krawędź mocniej “siedzi” na śrubach. Mam tylko jedno spostrzeżenie: większość ludzi sugeruje montaż przy “zbalansowanym” mostku idealnie równoległym do deski gitary. Wydaje mi się to o tyle niekorzystne, że gdy mostek jest idealnie równolegle, blok nie dociska do tremlockera. Ja postanowiłem przeciągnąć nieco mostek naprężając mocniej sprężyny. Dzięki temu idealną pozycję mostka reguluję śrubką na tremlockerze i dzięki sile naciągu sprężyn nie ma “stuków puków” bloku o tremlockera np jak położę rękę na mostku.

Maj 3, 2013

Madsowy “Hello World!”

Czytam powoli “Atari Roots” i przy trybach adresowania wymyśliłem sobie “Hello World” z wykorzystaniem madsowego .sb. Pomysł jest taki: pobieramy adres pamięci tekstu z adresu 660 i 661. Jest to trzecia od dołu linijka ekranu (pewnie dlatego, żeby print w basicu był prosty i obsługiwał tryby graficzne z “okienkiem tekstowym”). Odejmujemy odpowiednią magiczną liczbę (20 linii = 800 bajtów, LSB i MSB łatwo przeliczyć).

hello

Niespodzianka polega na tym, że opis .sb mówi: “it will convert all bytes into ATASCII screen codes before storing them”. Konwersja wykonywana jest do kodów ekranowych, stąd porównanie cmp #$db już po konwersji, zamiast #$9b.

     org $600
     cld
     sec
     lda 660
     sbc #32
     sta $cb
     lda 661
     sbc #3
     sta $cc
     ldy #0
     ldx #0
loop lda txt,y
     cmp #$db
     beq nxtl
     sta ($cb),y
     iny
     jmp loop
nxtl clc
     ldy #0
     lda $cb
     adc #54
     sta $cb
     lda $cc
     adc #0
     sta $cc
     inx
     cpx #24
     bne loop
rbow lda $d20a
     sta $d018
     lda #0
     sta $2c5
     sta $d40a
     jmp rbow
txt  .sb 'Hello World!' $9b

W “promocji” namalujemy na końcu losową tęczę :) . Możliwości generowania obrazu tego małego komputerka zawsze mnie fascynowały.

Tabela mapowania ATASCII na kody ekranowe tutaj. Jak zauważył xxl na forum atarionline.pl przy napisie dłuższym niż 255 bajtów rejestr y się przekręci. W “Hello World!” nam to nie grozi, niech więc póki co zostanie tak jak jest.

Następny przystanek: plot/drawto.

Tagi: ,
Kwiecień 21, 2013

Netctl

Dziś będzie krótko: netctl rządzi. Chyba zostałem fanboyem systemd…

Tagi: ,
Marzec 25, 2013

Finescroll.

Czasem moje eksperymenty przenoszą się na godziny późno-nocne :) Tym razem przemyślenia w temacie “finescroll poziomy”. Synchronizacja nie powinna uciekać, bo przed przesunięciem łapiemy ramkę sprawdzając czy zegar “tyknął”, a dzieje się tak podczas VBLANK interrupt 50 razy na sekundę. W tym wpisie analogiczny przykład z VBI, przy okazji którego pojawił się pomysł uzupełnienia tej procedury o i=time while time=i do od.


include "H1:RUNTIME.ACT"

proc main()
 int i=[0], j=[0], k=[0]
 card dlist=560
 byte hscrol=54276
 card pointer pc
 card savmsc=88
 card tmp
 byte col0=708
 byte col1=709
 byte time=$14

 byte array ndl = [112 112 112 66 64 156 2 2 2 2 2 2 2 2 2 2
                   2 2 2 2 2 2 2 2 2 2 2 86 216 159 65 32 156]
;                  64 + 6 (GR.1) + 16 (hscrol on) = 86
 graphics(0)
 savmsc=40000
 dlist=ndl
 col0=14
 col1=14

 for i=1 to 23 do
 printf("line: %i%E", i)
 od

 print("Action!")

 pc=dlist+28
 tmp=pc^+6
 do
  i=time while time=i do od
  hscrol=j
  j==+1
  if j=17 then
   j=0 pc^==-2 k==+1
   if k=14 then
    pc^=tmp k=0
   fi
  fi
od
return
Marzec 23, 2013

Scroll poziomy.

Tamtego wieczoru się nie udało, ale dziś, jak wszyscy już śpią, mogę chwilę się pobawić. Przykłady w książkach Ziętary być może nie były bezpośrednio jego autorstwa, ale jednak były bardzo fajne.

Poniżej przykład scrollowania poziomego i coś podobnego w Action!

100 POKE 82,0:GRAPHICS 0:FOR I=1 TO 92:? I,"   ";:NEXT I
110 DL=PEEK(560)+256*PEEK(561)
120 POKE 54276,7
130 FOR I=DL+10 TO DL+20:POKE I,PEEK(I)+16:NEXT I
140 FOR K=1 TO 10:FOR J=7 TO 0 STEP -1
150 POKE 54276,J:GOSUB 300
160 NEXT J:NEXT K
170 FOR K=1 TO 20:FOR J=7 TO 0 STEP -1
180 POKE 54276,J
190 NEXT J:NEXT K:J=7
200 POKE 54276,J:J=J-1
210 IF J>=0 THEN 200
220 J=7:L=PEEK(DL+4):H=PEEK(DL+5):L=L+2
230 IF L>255 THEN L=L-256:H=H+1
240 IF H>255 THEN POKE 82,2:GRAPHICS 0:END
250 POKE DL+4,L:POKE DL+5,H:GOTO 200
300 FOR I=1 TO 100:NEXT I:RETURN

 

proc delay()
 int i for i=0 to 500 do od
 return

proc main()

byte lmarg=82
int i, j, k
card dl=560, hscrol=54276
byte pointer ptr
card pointer p

lmarg=0 graphics(0)

for i=10 to 92 do
 printf("%I         ", i)
od

hscrol=7
ptr=dl+10

for i=10 to 20 do
 ptr^==+16
 ptr==+1
od

for k=1 to 10 do
 for j=7 to 0 step -1 do
  hscrol=j delay()
 od
od

for k=1 to 20 do
 for j=7 to 0 step -1 do
  hscrol=j
 od
od

j=7 p=dl+4
do
 hscrol=j
 j==-1
 if j<0 then
  j=7
  p^==+2
  if p^ > 65530 then
   lmarg=2 graphics(0)
   main()
  fi
 fi
delay()
od
return
Marzec 21, 2013

Action!zmy i Scrolle.

Grafikę graczy i pocisków na razie odpuszczam :) ale tylko na chwilę, bo zawsze chciałem ogarnąć temat scrollowania. Przerabiam więc przykłady z “Poradnika Programisty” Ziętary na Action! Oto pierwszy z nich. Jak widać, tak jak chciałem display listę zmieniam wskaźnikiem, bez peeków i poków.

Listing w Basicu:

100 POKE 82,0:GRAPHICS 0:FOR I=1 TO 92:? I,:NEXT I
110 DL=PEEK(560)+256*PEEK(561)
120 POKE 54377,0
130 FOR I=DL+10 TO DL+27:POKE I,PEEK(I)+32:NEXT I
140 FOR K=1 TO 10:FOR J=0 TO 7
150 POKE 54277,J:GOSUB 300
160 NEXT J:NEXT K:J=0
170 FOR K=1 TO 20:FOR J=0 TO 7
180 POKE 54277,J
190 NEXT J:NEXT K
200 POKE 54277,J:J=J+1
210 IF J<8 THEN 200
220 J=0:L=PEEK(DL+4):H=PEEK(DL+5):L=L+40
230 IF L>255 THEN L=L-256:H=H+1
240 IF H>255 THEN POKE 82,2:GRAPHICS 0:END
250 POKE DL+4,L:POKE DL+5,H:GOTO 200
300 FOR I=1 TO 100:NEXT I:RETURN

I zbliżony kod w Action (zbliżony, bo pisany na szybko i nie chce mi się pisać
printa z tabulatorem):

include "H1:RUNTIME.ACT";

proc delay()
 int i for i=0 to 500 do od
 return

proc main()

byte i, j, k, lmarg=82, vscrol=54277
card dl=560
byte pointer ptr
card pointer p

lmarg=0 graphics(0)

for i=10 to 92 do
  printf("%I         ", i)
od

vscrol=0
ptr=dl+10
for i=0 to 17 do
 ptr^==+32
 ptr==+1
od

for k=1 to 10 do
 for j=0 to 7 do
  vscrol=j delay()
 od
od

for k=1 to 20 do
 for j=0 to 7 do
  vscrol=j
 od
od

do
 while j<8 do
   vscrol=j
   j==+1
   delay()
 od
 p=dl+4
 j=0 p^==+40

 if p>=65495 then
  lmarg=2 graphics(0)
  main()
 fi
 delay()
od

return

Dziś wieczorem eksperymenta ze scrollem poziomym.

Luty 25, 2013

Popsułem U1MB.

Niestety. Flashowanie za pomocą kabla SIO2PC via przelotka USB na Prolificu zdechło i U1MB zapadło na niepamięć. Problem chyba na 100% wynika z ostatnich zmian w kodzie USB kernela. I nie powiem żebym się z tego powodu cieszył… Zamówiłem więc u Lotharka dwa zaprogramowane AM29F0408 i oczywiście je też popsułem. Całe szczęście w Monster Elektronik programowanie pamięci kosztuje 5zł/szt.

Żeby wyeliminować potencjalne problemy z usb / przelotką / aspeqt, przetestowałem odpalanie flashera po zamontowaniu go w SDX za pomocą MATR. Działa, choć do końca tego nie przetestowałem bo flashowanie SST się jeszcze wywala. Dzieki temu wygenerowany w U1MB Rom Generatorze flasher będzie można skopiować na partycję FAT na karcie CF i bezpośrednio stamtąd zamontować  i uruchomić. Czekam tylko na info od Truba , który obiecał dodać do flashera z SDX obsługę pamięci SST, które mają 4kB klastry (i dlatego je sobie tak szybko popsułem, AMI ma 64kB).

Więcej tutaj.

Luty 19, 2013

Action! Własne Graphics(), Position(), Plot(), Drawto() i Print().

Nie znam asm, ale na podstawie tego co można znaleźć w kilku moich ulubionych książkach udało mi się stworzyć procedurki do rysowania i pisania na ekranie. Dumny jestem z printa, który wykorzystuje feature Actionowego “string constant”, czyli fakt, że element zerowy łańcucha napisu zawiera długość napisu, którą wydłubujemy w asm i podajemy w ICBLL, określając długość bufora.

MYGR.ACT

include "H1:ASMINC.ACT"
proc main()
int r
card savmsc=88
card textaddr=660
byte bkg=710
byte array dltb=[ 112 112 112 66 96 159 72
112 158 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8
8 8 8 8 65 78 158 ]
card dlist=560
graphics(3)
bkg=0
dlist=dltb
textaddr=40800
savmsc=40560
print("ACTION! rules")
for r=0 to 18 step 2 do
 plot(0+r,0+r) drawto(0+r,10+r)
 plot(0+r,10+r) drawto(10+r,10+r)
 plot(10+r,10+r) drawto(10+r,0+r)
 plot(10+r,0+r) drawto(0+r,0+r)
od
do od

MYLIB.ASM

           org $600
graphics   pha
           ldx #$60
           lda #close
           sta iccom,x
           jsr ciov
           lda #open
           sta iccom,x
           lda <fname
           sta icbal,x
           lda >fname
           sta icbah,x
           pla
           sta icaux2,x
           and #$f0
           eor #$10
           ora #opnino
           sta icaux1,x
           jmp ciov
           rts

;          org $62b
position   sty colcrs
           stx colcrs+1
           sta rowcrs
           rts

;          org $632
plot       jsr position
           ldx #$60
           lda #putchr
           sta iccom,x
           lda #$0
           sta icbll,x
           sta icblh,x
           lda color
           jmp ciov
           rts

;          org $64b
drawto     jsr position
           lda color
           sta atachr
           ldx #$60
           lda #drawln
           sta iccom,x
           lda #opnino
           sta icaux1, x
           lda #$0
           sta icaux2, x
           jmp ciov
           rts

;          org $669
print      clc
           sta $d4
           stx $d5
           ldx #0
           adc #1      ;leave 0-th element
           sta icbal,x
           lda #putrec
           sta iccom,x
           lda $d5
           sta icbah,x
           lda #0
           sta icblh,x
           ldy #0
           lda ($d4),y  ;buflen from string
           sta icbll,x  ;constant's 0-th element
           jsr ciov
           rts

atachr     equ $2fb
drawln     equ $11
opnino     equ $c
icaux1     equ $34a
icaux2     equ $34b
fname      dta c 'S:'
colcrs     equ $55
rowcrs     equ $54
putchr     equ $0b
icbal      equ $344
icbah      equ $345
iccom      equ $342
icbll      equ $348
icblh      equ $349
color      .db 1
ciov       equ $e456
putrec     equ $9
getrec     equ $5
open       equ $03
close      equ $0c

Przy tego typu łączeniu kodu asm z Action! adresy procedur najbezpieczniej wziąć z listingu wygenerowanego madsem (opcja -l:ASMINC.lst).

ASMINC.ACT

proc graphics=$600(byte m)
proc position=$62B(card c, byte r)
proc plot=$632(card c, byte r)
proc drawto=$64B(card c, byte r)
proc print=$669(card msg)

Wiem że da się to zrobić lepiej ale i tak jestem z siebie dumny :)

Jak widać Action przekazuje parametry procedur przez akumulator i rejestry X i Y (a jeśli jest ich więcej, również przez stronę zerową). W print() adres napisu maglujemy w postaci LSB,MSB. MYLIB.ASM madsujemy i cat-ujemy MYLIB.OBX z binarką MGR.XEX.

Ciekawe jest to, że powyższy przykład w Action! po kompilacji z Runtime Action! albo uruchomieniu z cartem się wykrzacza, a działa po “zlinkowaniu” z ASMLIB.obx. Domyślam się, że chodzi o współrzędne podawane plot() i drawto(). Zapewne w przypadku procedur z carta i runtime generują one coś w stylu error 141, a procedurki w asm nie sprawdzają zakresu współrzędnych i jadą dalej poza pamięcią obrazu… Na chwilę obecną nie jestem w stanie tego lepiej wytłumaczyć. Ważne że działa.

Konwertować do bloków kodu [] mi się tego póki co nie chce, ale pewnie niebawem i to przetrenuje.

Kolejny, ważniejszy krok, to stworzenie procedur piszących bezpośrednio do pamięci ekranu danego trybu graficznego. JHusak kiedyś wspominał o szybkim plot(), jest nawet o tym wzmianka w FAQ o Action! atarionline.pl, ale od jakiegoś czasu ten link się zapętla.

Luty 12, 2013

EnvisionPCreborn

EnvisionPCreborn to świetny program do edycji zestawów znaków i map do gier. Jak dla mnie interfejs tego programu to po prostu rewelacja i chciałbym aby więcej programów dla Atari na PC powstawało z takimi założeniami dla GUI.

epc

Pomimo, że program od dawna nie był aktualizowany, kompiluje się pod Linuksem bez większych problemów po małej modyfikacji Makefile.linux: trzeba dodać undo.c do listy plików w SOURCE.

No i jeszcze jeden brzydki przykład w Action!

include "H1:RUNTIME.ACT"
proc main()

card chrom, chram, start
card charp=756
int i
byte cur=752
byte bkg=710

byte array chrs1 = [0 0 0 24 24 0 0 0
0 0 0 24 24 0 0 0
0 0 0 0 31 63 96 192
0 0 0 0 248 252 6 3]

byte array chrs2 = [0 0 0 0 192 127 63 0
0 0 0 0 3 254 252 0
0 0 0 24 24 0 0 0
0 0 0 24 24 0 0 0]

graphics(0)

bkg=0
cur=1

chrom=charp*256
chram=16384
moveblock(chram, chrom, 1024)
chram=16384+1024
moveblock(chram, chrom, 1024)
start=16384+776
moveblock(start, chrs1, 32)
start=16384+776+1024
moveblock(start, chrs2, 32)

charp=64

for i=1 to 7 do
 printe("ab ab ab ab ab ab ab ab ab")
 printe("cd cd cd cd cd cd cd cd cd")
 printe("")
od

do
 for i=0 to 15000 do od
 charp=68
 for i=0 to 15000 do od
 charp=64
od

return
Follow

Otrzymuj każdy nowy wpis na swoją skrzynkę e-mail.