                          - SEPTIC'S DEMOSKOLA -

                                 Lektion 7
                                 
                        Skriven av Vicious / Septic

                                 24 Jul 93



                                 Inledning
                                 
Stora vlanimerade bobs, hga sinusscrollers och snabba fyllda vectorer har
en sak gemensamt. De anvnder den kraftfulla saken i Amigan som kallas
BLITTER. I den hr lektionen ska vi ntligen brja rota lite i blitterns
mjligheter och lra oss hur den ska hanteras.


                                   Teori
                                   
I frsta hand ska vi tnka p blittern som en kopierare. Processorn r dess
arbetsgivare, och har inte processorn sagt till den att jobba s ligger den
bara i ett hrn och latar sig.
  Men, blittern r inte ngon latmask, utan vldigt effektiv. S fort
processorn talat om fr den vad den ska kopiera s stter den igng med
rasande fart. Under tiden kan processorn utfra berkningar och annat smtt
och gott medan den vntar p att blittern ska bli klar.
  Blittern kan anvndas till att kopiera helt vanligt frn klla till
destination, men den kan ocks kombinera olika kllor fr att uppn
intressanta resultat, inte minst inom grafikbehandling. Ett exempel r ju
bobs, som jag kommer att ta upp nsta gng.


                                 Register
                                 
Innan vi brjar ge blittern order med processorn r det viktigt att kolla
om den r klar. Annars kan det hnda att kopieringen den just fr
tillfllet hller p med gr t skogen.
  Att titta om den r klar kan man p ett enkelt stt gra genom att testa
bit #14 (BBUSY) i DMACONR ($dff002). Om den r satt s vet man att blittern
hller p fr fullt och har inte tid med en ny kopiering n.
  Nr man s har kollat om den r frdig och ftt klartecken s kan man
brja initialisera de olika registren som blittern anvnder.
  Till att brja med brukar jag specificera hurdan kopiering jag ska gra
och det gr man i BLTCON0 ($dff040) och BLTCON1 ($dff042). De bgge
registren ser ut som fljer (ej i line draw mode):

   BIT#   BLTCON0   BLTCON1
   ----   -------   -------
    15    ASH3      BSH3
    14    ASH2      BSH2
    13    ASH1      BSH1
    12    ASH0      BSH0
    11    USEA       x
    10    USEB       x
    09    USEC       x
    08    USED       x
    07    LF7        x
    06    LF6        x
    05    LF5        x
    04    LF4       EFE
    03    LF3       IFE
    02    LF2       FCI
    01    LF1       DESC
    00    LF0       LINE

ASH0-3 - Anger skiftvrde fr klla A.
BSH0-3 - Anger skiftvrde fr klla B.
USEA-D - Talar om vilka blitter kanaler man vill anvnda.
LF7-0  - Logisk minterm funktion.
EFE    - Fyll exklusivt.
IFE    - Fyll inklusivt.
FCI    - Fill Carry Input
DESC   - Descending mode (Kopiera nerifrn och upp istllet fr tvrtom).
LINE   - Slr p line mode.

Fyllbitarna och linemode biten ska jag ta upp i senare lektioner. Just nu
ska vi koncentrera oss p BLTCON0 och enbart nollstlla BLTCON1.
  De som inte r helt bakom fltet - eh, urskta - har vl vid det hr
laget (om ni lst ordentligt) mrkt att blittern har 4 (fyra) kanaler. De
tre frsta, A, B och C r kllkanaler och den sista, som har beteckningen
D, r en destinationskanal.
  Vi ska den hr gngen bara anvnda oss utav klla A och destination D,
eftersom vr kopiering r av enkel typ. Allts vljer vi bara bit #11 och
bit #8 (USEA och USED).
  Du kanske undrar vad skiftningen r till fr? Jo, blittern jobbar alltid
bara med hela WORDS, vilket allts r var sextonde pixel (titta tillbaka p
lektionen om bitplan om du inte minns!) och att flytta ett objekt p enbart
jmna sextonpixels koordinater i X-led skulle inte vara s snyggt. Det r
hr skiftningen kommer in. Man skiftar helt enkelt datan upp till femton
steg inom det wordet man kopierat till och vips, s kan man lta ett
grafisk objekt glida fram en pixel i taget.
  Man kan dock anvnda skiftningen till annat ocks. Nmligen nr man
scrollar en text! Programexemplet fr den hr gngen anvnder skiftnings-
tekniken fr att kunna scrolla texten fyra pixlar t gngen.
  Bitarna 7 till 0 (LF7-0) i BLTCON0 anger den logiska mintermen, vilken r
en mycket kraftfull liten sak som talar om fr blittern hur de tre kllorna
ska kombineras fr att n en speciell effekt. Dess komplexitet gr den
ocks ganska svr att frst, s f inte kronisk hjrnbldning nu om ni
inte fattar min frklaring.
  Man kan allts kombinera de tre kllorna A, B och C p upp till 256 olika
stt med den hr funktionsgeneratorn. Varje enskild bit i det man kopierar
kommer att testas och pverkas olika, beroende p hurdan minterm man valt.
  Man kan skdliggra det med en sanningstabell (som de gjort i Hardware
Manualen, dr sm bokstver betyder NOT):

   A   B   C   D   BLTCON0 bit   MINTERM
   -   -   -   -   -----------   -------
   0   0   0   ?        0          abc (=not A and not B and not C)
   0   0   1   ?        1          abC (=not A and not B and C)
   0   1   0   ?        2          aBc etc etc...
   0   1   1   ?        3          aBC
   1   0   0   ?        4          Abc
   1   0   1   ?        5          AbC
   1   1   0   ?        6          ABc
   1   1   1   ?        7          ABC

Sedan lser man bara i tabellen beroende p hur man vill kombinera
kllorna. Om vi till exempel vill stta alla bitar i destionationen nr A
eller B r 1, tittar vi i tabellen och ser efter p vilka bitpositioner som
A r 1, vilket r p position 4 till 7, och sedan p vilka positioner som B
r 1, och det r ju position 2 och 3 samt 6 och 7.
  Sedan tittar vi bara p vilka bitar vi satt, nmligen 2 till och med 7
och ser att vi ftt talet %11111100, vilket r $FC hexadecimalt.
  Vi ser nu ocks vilken enkel typ av kopiering vi ska anvnda till
scrolltexten, eftersom vi bara ska flytta frn A till D utan krusiduller.
Vi stter bara alla bitar som har A-biten satt, nmligen bit 4-7, och fr
talet %11110000, som r $F0 i hex.
  Men, tyvrr r det inte s hr enkelt bara. Fr nr man ska konstruera
svrare operationer (nsta gng ska vi kika p hur man gr BOBS) krvs ven
lite logiska ekvationer.
  Ett exempel:

   D=Ac + B

Bokstver som sitter ihop lses som AND och ett plus anger OR. Sm
bokstver har NOT framfr sig. Uttrycket ovan utlses allts som "A and not
C or B". Detta betyder att D-biten bara stts nr A r satt och C r 0
eller nr B r 1.
  Att rkna ut siffror fr det hr r bde jobbigt och svrt, s drfr har
jag inkluderat variabler i slutet av programexemplet som gr anvndningen
av minterms mycket enklare. Vi skall dock inte titta mer p dem frrn i
nsta avsnitt.

Sdr, det var lite om BLTCON! Efter att vi talat om fr den ivrige
kopieraren hur han ska kopiera, mste vi ange varifrn han ska hmta data
och var det ska hamna.
  Klla A har sin pekare i BLTPTA ($dff050) och destinationen D BLTPTD
($dff054). Bgge adresserna kan skrivas in som longwords men tnk p att
det mste vara inom CHIP mem.

Precis som med bitplan, kan blittern addera ett modulo vrde efter varje
rad den kopierat. Detta gr det enklare om man kopierar data som r mindre
n skrmen r bred. Man kan d tex flytta en bob som bara r 32 pixlar bred
p en 320-skrm och inte behva krngla med att kopiera en rad i taget och
sen addera ett breddvrde fr att spara tid, utan kan initiera blittern
till att skta det helt automagiskt.
  Modulovrdet fr klla A finns i BLTAMOD ($dff064) och fr destination D
i BLTDMOD ($dff066).

Det finns ocks ett maskregister i blittern, som mjliggr logisk AND i
brjan och i slutet p en kopierad rad. Man kan p s stt rensa bort
pixlar man inte vill ha med i ett objekt som inte riktigt fyller upp ett
helt jmnt word. Tills vidare lter vi de registren vara $ffff, eftersom vi
inte vill maska bort ngot n. (Mer om dess anvndning nsta gng, s hll
er till tls...)

Nu r det bara att stta igng blittern! Och hur gr man det d? Jo, det
gr man genom att ange kopieringens storlek! S fort blittern ftt tag i
storleken p datafltet den ska kopiera s stter den igng, s drfr ska
man ALLTID ge storleken sist, efter det att man satt alla andra blitter-
register till rtt vrden.
  Blittern tar emot storleken som bredd i words och hjd i antal rader.
Registret man ska skriva in allt detta i r BLTSIZE ($dff058).
  Bitarna i BLTSIZE ligger s att hjden anges i bit 6 till 15 och bredden
i bit 0 till 5. Enkelt sett r det bara att multiplicera hjden med 64 fr
att tvinga upp den i bitarna 6 och uppt, och sen addera bredden.
  Ett block p 128*32 pixlar fr allts storleken (32*64)+(128/16)=2056
($808). Hjden 32 multipliceras allts med 64, och sen lgger man till
bredden i words, vilket ju r 128 pixlar dividerat med 16 = 8 words.

Sdr ja! Det var en liten flukt p vad man kan gra enbart inom enkel
kopiering med blittern. Nu kan vi kasta oss vidare p programexemplet.


                              Programexemplet
                              
Scrolltexter kan tyckas enormt trkiga eftersom de verkar ha funnits sen
urminnes tider (ja, tminstone sen 64:an brjade sitt triumftg vrlden
ver) men de visar p ett bra stt hur "fyrkantig" kopiering gr till.
  Vad man gr nr man scrollar r helt enkelt att kopiera en hel fyrkantig
area, dr texten finns, till en ny position i X-led, ngra pixlar t
vnster (eller hger :-) om ni sett mitt Slipstro...) I mitt program
scrollar jag, p en 384*32 skrm, en 32*32 font med lite poetisk text.
Skrmen r 384 pixlar bred fr att undvika fula kanter dr scrollen bara
huggs av, och fr att dlja att vra nya bokstver ploppar ut p skrmen
istllet fr att glida in lugnt och mjukt. Att den r 32 hg bara, r helt
enkelt fr att det inte behvdes mer, nr fonten inte vara hgre n 32.
  Jag har dessutom lagt till en liten spegeleffekt p scrollen, som r 16
pixlar extra, men denna har inget med den riktiga skrmen (som ju bara r
32 hg) att gra, utan r bara en uppochnervnd kopia som stadkommits med
negativ modulo.
  Men, i alla fall s kanske det r bst att jag gr igenom programmet steg
fr steg som jag brukar.
  Frst och frmst har vi den gamla hederliga startupen (hmmm?! den har
hngt med sen lektion 1 och ingen har protesterat, men funkar den verkligen
p A1200?!?!?) som vi studerat tidigare och inte behver mala vidare p.
Sen kommer DMA-sttningen, och hr kan ni se att jag slagit p blitter-DMAn
och ven BLITTER NASTY-biten, som ger blittern full prioritet ver
processorn, s att blittern fr mer tid och kopieringen gr fortare. Ett
optimalt stt (som jag sett att Hannibal/Lemon. anvnder) borde egentligen
vara att endast sl p BLITTER NASTY nr man vntar p att blittern ska bli
frdig, men jag har inte orkat gra det hr.
  Efter det stter vi copperlistan och sen kommer mainrutinen. Hr ser vi
att jag frst anvnder en sync-rutin fr att synka scrollen med
rasterstrlen (prova att plocka bort sync-rutinen fr att se skillnaden)
och f det hela att flyta fint.
  Sen hoppar jag till scrolltext-rutinen och d ska vi ta och kika p vad
jag gr dr.
  Frst av allt subtraherar jag frn en ScrollCounter. Detta gr jag fr
att kunna veta nr nya bokstver ska skrivas ut.
  Om inte ScrollCountern r noll hoppar vi till .NoNewChar men om den
dremot R noll stter vi den till 8. Hmmm, TTA? Kanske du undrar, och det
kan jag frst. Det riktiga talet borde ju egentligen vara 32! Men, om
vrdet skulle vara 32 skulle vi ocks f scrolla texten en pixel varje synk
bara, och det r ganska sakta. Jag scrollar nu texten 4 pixlar t vnster
varje sync, och drfr blir det bara vrdet 32/4=8 i ScrollCountern. Testa
grna att skriva in hgre och lgre vrden p den hr raden s kommer ni
att mrka att bokstverna kommer nrmare eller lngre frn varandra.
  Sedan hoppar jag till rutinen NewChar, och d r det lika bra att vi
kikar p den ocks med en gng.
  I NewChar hmtar jag frst en pekare som anger var i texten vi befinner
oss, allts vilket tecken vi nu skall putta ut p skrmen. Efter att ha
nollstllt D0 (egentligen inte ndvndigt, men en skerhetstgrd fr
divideringen senare) hmtar jag tecknet och hoppar om det inte r noll. r
det noll, brjar vi bara om frn brjan p texten igen och frsker p
nytt.
  Sedan sparar jag textpekaren igen (nu pekar den p nsta bokstav som vi
ska skriva ut nsta gng) och subtraherar 32 frn D0. Om ni tittat i en
ASCII-tabell ngon gng (och det hoppas jag, annars ska ni gra det
omedelbums!) s har ni frhoppningsvis mrkt att de frsta 32 bokstverna
bara r kontrolltecken. Dessa tecken behver inte vi i vr scrolltext, och
vi har heller inte dem representerade i vr font, s drfr gr vi helt
enkelt om tabellen s att mellanslag fr vrdet 0 istllet fr 32 och
utropstecken blir 1 istllet fr 33 osv...Titta p fontbilden s ser du hur
tecknen r uppstllda. (,  och  finns ocks med p bilden fast p ganska
galna positioner, nmligen &, % och +, s bli inte frvnad om det inte
stmmer riktigt med en ASCII-tabell!)
  Sedan - om vi gr tillbaka till programmet igen - nollstller jag D1
(skerhet igen, annars kan det bugga ur...) och dividerar D0, allts
bokstavsnumret, med 10 eftersom det finns 10 tecken p varje rad i
fontbilden. Nr jag gr detta fr jag ett svar som anger p vilket rad
tecknet str och en rest (i de hgre 16 bitarna) som talar om p vilken
position i sidled.
  Jag flyttar de lga 16 bitarna, allts radnumret till D1 och
multiplicerar det med en bokstavs-radhjd i fontbilden, som r 320 pixlar
bred, vilket allts blir 320/8 bytes=40 gnger 32 pixlar hg.
  Efter det rensar jag de lga bitarna i D0 och flyttar ner divisions-
resten dit. Efter det utfr jag en aritmetisk skift t vnster tv steg,
vilket r samma sak som att multiplicera med 4 (fast skiftning gr
snabbare), och det gr jag fr att f korrekt tecken position i X-led.
Varje bokstav r ju 32 pixlar bred, och det r ju som bekant FYRA bytes!
S, om tecknet hade position 2 s multiplicerar vi det med 4 och fr 8, och
det betyder allts att grafiken fr bokstav nr 2 finns 8 bytes in p
fontbilden.
  Vad gr jag sen? Jo, nu har vi alla offseter vi behver, s nu pekar jag
p var fontbilden ligger i minnet och adderar sedan s att A0 till slut
pekar p rtt bokstav, allts den vi ska skriva ut p skrmen.
  Sen pekar jag p skrmen, 46 bytes in, eftersom vi ska skriva tecknet
lngt ute till hger och s brjar jag flytta data.
  Det behvs tv loopar fr det hela. En som gr runt 32 gnger (d vi
kopierar rad fr rad i bokstavsgrafiken) och s en som gr runt 4 gnger
(eftersom fonten har fyra bitplan).
  Jag flyttar grafiken med move.l fr att det r precis 32 pixlar och sen
adderar jag skrmbredden (s att vi kommer till nsta rad, rakt under den
frra) till bde fontbilden och den riktiga skrmen. (Fonten r 320 pixlar
bred, vilket r 40 bytes, och skrmen r 384/8=48...)
  Nr jag har kopierat en hel bokstav i ett bitplan gr jag till nsta
bitplan. Eftersom skrmen bara r 32 pixlar hg behver jag inte addera
ngot till den, men till fontbilden adderar jag dess bitplanstorlek
(40*192) minus ett teckens hjd (40*32), s hamnar jag p rtt stlle.
  Sdr, det var NewChar-rutinen. D hoppar vi tillbaka till dr vi var, i
ScrollText-rutinen.
  Hr hoppar vi till sjlva blitter-scroll-rutinen, ScrollIt.
  I ScrollIt gr vi det som man alltid frst mste gra innan man anvnder
blittern. Man testar om den r klar! Jag gr hr en busywait (detta e
demokodning, s who carez?!).
  Sedan lgger jag in source och destination i A0 och A1. Att sourcen r
screen+2 (allts 16 pixlar t hger) beror p att blittern skiftar t hger
(utom i descending mode, men det r en annan historia jag ska ta upp i en
senare lektion). S, vad vi gr r allts att flytta 16 pixlar t vnster
och sen skifta t hger fr att f hastigheten 16-skiftvrde.
  Vilket skiftvrde jag har ser ni p nsta rad, dr jag skriver till
BLTCON0. Det r $c000, men bara de tre hgsta bitarna rknas, s det blir
$c, allts 12. Scrollhastigheten blir sledes 16-12=4, och det knner vi ju
igen frn ovan!
  Sedan str det ocks +srca!dest!a och det r minterms-frenklingarna som
jag pratade om innan, som gr det lttare att kombinera funktioner. Srca
och Dest str fr USEA och USED, allts att bara A och D ska vara pslagna,
och A:et som fljer talar om fr blittern att den ska kopiera allt frn A
till D utan ngra som helst modifikationer.
  Sen nollstller jag BLTCON1 (kan egentligen gras genom att skriva ett
longword till BLTCON0, men jag ville f det hela verskdligt fr de som r
nybrjare :-)) och skriver $ffffffff till BLTAxWM som r de bgge
maskregistren.
  I BLTAPT och BLTDPT skriver jag s in klla och destination och sen
skriver jag noll till bda modulo-registren.
  Nu, sist men absolut inte minst, skriver jag storleken till BLTSIZE. 32
raders hjd gnger 4 bitplan plus 8 extra rader och s 23 words bredd.

Det var allt om programmet den hr gngen. Fr att enklare flja det hela
kan ni ju printa ut den hr textfilen och lsa den samtidigt som ni tittar
p programmet, eller s kan ni ladda in det i ngon texteditor som klarar
av flera filer t gngen i olika fnster (typ Cygnus Ed, yeah!) som jag
sjlv anvnder.
