                          - SEPTIC'S DEMOSKOLA -

                                 Lektion 3
                                 ¯¯¯¯¯¯¯¯¯
                        Skriven av Vicious / Septic

                                 07 Maj 93



                                 Inledning
                                 ¯¯¯¯¯¯¯¯¯
Äntligen dags att visa bilder! Det är väl nu det börjar bli lite mer
intressant...I den här delen ska jag gå igenom hur bitplansgrafik fungerar
och hur man visar en enkel 32-färgers bild.
  De två första lektionerna verkar inte ha varit några större problem. I
alla fall har jag inte fått en enda fråga om något där, och det är ju bara
bra, för det måste betyda att jag lär ut allt mycket bra! (Eller?)
  Jag inför också en ny överskrift (som följer direkt här under) som kommer
att behandla det vi gör i teorin. Hitills har allt varit ganska självklart
men i fortsättningen kan det bli lite knepigare, och en viktig sak för att
man ska kunna programmera en sak är att man förstår hur den fungerar.


                                   Teori
                                   ¯¯¯¯¯
Ett demo skulle inte vara mycket att ha om inte bitplansgrafik fanns. Det
skulle inte finnas några texter, inga stillbilder eller rörliga bilder
(bobs, vektorer, etc...). Det skulle kort och gott bara finnas musik och i
bästa fall ett par copperbars! Därför måste vi vara evigt tacksamma för att
vi kan visa grafik, och det mycket simpelt också! Detta är Amiga, och vi
behöver knappt anstränga oss det minsta för att visa en liten bild.
  Men, först och främst, vad är en bild? - Som bekant förstår datorn
egentligen bara ettor och nollor. Kombinerar vi dessa får vi binära tal,
som kan representera decimala eller hexadecimala tal, som vi tycker är
enklare att handskas med. I grafik-sammanhang är det dock enklare att prata
om binära tal istället för decimala eller hexadecimala. I en bild motsvarar
nollan en tom pixel och ettan en satt pixel. En rad med ettor i minnet ger
alltså en lång rak linje på bilden.
  Nu kanske du undrar hur bara nollor och ettor kan åstadkomma så många
färger som Amigan kan prestera. Då inför vi ett nytt begrepp som kanske
låter bekant -> bitplan! Med hjälp av flera bitplan kan vi kombinera våra
ettor och nollor så att de kan representera pixlar med olika färger.
  Detta kan te sig lite mystiskt innan man förstår hur det fungerar, men
det hela bygger på en ganska lätt princip.
  Den enklaste formen av bild är 2-färgers bilden. Där har man bara ETT
bitplan innehållande ettor och nollor, där nollan representerar
bakgrundsfärgen, och ettan motsvarar färg 1.
  Om vi nu lägger till ett bitplan så att vi har två bitplan i vår bild kan
vi plötsligt rita med FYRA färger. Detta beror på att vi kan få ut fyra
olika kombinationer med våra bitplan.
  Om vi t.ex. tittar på pixeln längst upp till vänster på vår bild så ser
vi att det är en etta i första bitplanet och så tittar vi på pixeln längst
upp till vänster i andra bitplanet och ser ännu en etta. En etta på båda
ställena ger färg tre!
  Lägger vi till ännu ett bitplan med en etta där har vi plötsligt färg
SJU!
  Hur bitplanen kombineras för att ge olika färger kan enkelt kontrolleras
genom att man ger varje bitplan ett speciellt värde. Bitplan 1 får värdet
1, bitplan 2 får värdet 2, bitplan 3 värdet 4 osv:

           BITPLAN    VÄRDE
           -------    -----
              1         1
              2         2
              3         4
              4         8
              5         16

  När man sen ska ta reda på vilken färg det blir kikar man bara i tur och
ordning på varje bitplan och lägger till dess VÄRDE bara om biten är satt.
Så om en bit är satt i bitplan 3 och bitplan 5 bara, blir sammanlagda
värdet: 4+16 = 20   Alltså, färg 20! Om vi tar ett annat exempel, där en
bit är satt i bitplan 1, en i bitplan 4 och en i bitplan 5: 1+8+16 = 25
Färg 25! Väldigt enkelt när man väl kan det...Om man tar 2 upphöjt i antal
bitplan så får man även max antal färger. Det kan kanske vara bra att
veta...

  Det kan vara väldigt svårt att förstå hur bitplan och sånt hänger ihop i
början...Oftast förstår man inte det förrän längre fram, och till att börja
med räcker det att veta hur man visar bilder, inte hur de är uppbyggda.
  Hoppas du förstått ungefär hur det fungerar, för nu hoppar vi vidare till
registren vi behöver för att visa en bild...


                                 Register
                                 ¯¯¯¯¯¯¯¯
För att visa en bild behöver man egentligen bara slå på BITPLANS-DMA i
DMACON ($dff096). Amigan kommer då glatt att visa vad den känner för (tja,
nästan i alla fall, men det är inte vackert...) eftersom den inte har fått
några uppgifter alls om vår bild.
  Vad vi behöver göra är alltså att peka på vår bild, ge Amigan de rätta
färgerna och måtten på bilden och sen är det klart!
  Precis som allt annat DMA-relaterat shit måste all grafik ligga i
CHIP-mem för att kunna visas. Det gör man enklast genom kommandot SECTION
DATA,DATA_C, så slipper man allt jobbigt minnesallokerande.
  Först måste vi tala om var vi har vår bild. Man måste ange var varje
bitplan ligger och skriva in alla addresser i registren BPLxPTH
($DFF0E0-$DFF0F4). Precis som alla DMA-pekare måste den uppdateras varje
vertical blanking, så givetvis låter vi coppern sköta det.
  Vi måste också ange i vilken skärmmode vi vill visa bilden. Det gör vi i
registret BPLCON0 ($DFF100). Det ser ut så här:

   BIT#   BPLCON0   Beskrivning
   ----   -------   -----------
    15    HIRES     Högupplösning, 640 pixlar bredd.
    14    BPU2      De här tre bitarna anger antalet bitplan
    13    BPU1        som ska användas när bilden visas. De kan
    12    BPU0        innehålla allt från värdet 0 till 6.
    11    HOMOD     HAM-mode! Om du ska visa en HAM-bild ska den här
                    biten vara satt! (Annars blir bilden fuuuul...:-)
    10    DBLPF     Dubbla playfields, kan användas för att göra
                    parallax-scroll väldigt lätt.
    09    COLOR     Composite Color på. (För genlocks-färg, har jag för mig
                    eller ngt sånt...Jag brukar alltid ha den på!)
    08    GAUD      Genlock på. Gör det möjligt för dem med genlock att
                    köra en TV-bild på bakgrundsfärgen.
    07     X        Ej använda.
    06     X
    05     X
    04     X
    03    LPEN      För användning av ljuspenna.
    02    LACE      Interlace läge.
    01    ERSY      External resync. Bäst att inte röra...
    00     X

Efter att vi specificerat skärmmoden ska vi ange den horisontella
scrollkoden, i register BPLCON1 ($DFF102).
  Om man ska hårdvaru scrolla sin skärm använder man det här registret för
att flytta skärmen 1-16 steg. Vi ska dock bara visa en stilla bild, så vi
sätter BPLCON1 till dess normala värde, 0.
  Registret ser ut som följer:

   BIT#   BPLCON1   Beskrivning
   ----   -------   -----------
    15       X      Används ej.
    14       X
    13       X
    12       X
    11       X
    10       X
    09       X
    08       X
    07     PF2H3    Horisontell scrollcode för jämna bitplan.
    06     PF2H2        "           "       "    "       "
    05     PF2H1        "           "       "    "       "
    04     PF2H0        "           "       "    "       "
    03     PF1H3    Horisontell scrollcode för udda bitplan.
    02     PF1H2        "           "       "    "     "
    01     PF1H1        "           "       "    "     "
    00     PF1H0        "           "       "    "     "

Som ni ser kan udda och jämna bitplan ha olika scrollcoder, och det är på
det sättet man kan få en svajande bild att dela på sig. Jag ska i nästa
lektion gå in mer på hur det här registret används och göra ett program-
exempel som visar hur det går till praktiskt.
  Det ytterligare ett liknande register, kallat BPLCON2 ($DFF104). Det
sköter om prioriteten mellan bitplan och sprites, och även bitplan/bitplan,
men det behöver vi inte använda (än) så det besparar jag er en genomgång
av. Vi sätter den bara till noll.
  Nu är det dax att tala om hur bred skärmen är. Det gör vi genom att ange
start och slut på skärmen i registren DDFSTRT ($DFF092) och DDFSTOP
($DFF094).
  De översta 8 bitarna i de bägge registren används ej, och inte heller de
två lägsta, bit 0 och 1, så dem ska ni inte pilla på :-).
  Det finns en enkel tabell som är bra att följa när man ska specificera
sin skärmbredd:

   DDFSTRT (Vänster startposition)
   -------------------------------
   Mode     Bitar-> H7 H6 H5 H4 H3 H2 H1 H0
   ----------------------------------------
   Extra wide (max)  0  0  1  0  1  0  X  X   =   $28
   Wide              0  0  1  1  0  0  X  X   =   $30
   Normal            0  0  1  1  1  0  X  X   =   $38
   Narrow            0  1  0  0  0  0  X  X   =   $40

   DDFSTOP (Höger stopposition)
   ----------------------------
   Mode     Bitar-> H7 H6 H5 H4 H3 H2 H1 H0
   ----------------------------------------
   Narrow            1  1  0  0  1  0  X  X   =   $C8
   Normal            1  1  0  1  0  0  X  X   =   $D0
   Wide (max)        1  1  0  1  1  0  X  X   =   $D8

  Väljer man Normal på bägge ställena så får vi en 320 pixlar bred skärm.
Väljer vi Extra wide och Wide får vi 368 pixlars bredd, alltså overscan.
Tänk er att Normal är 320 pixlar och lägg sen till (eller dra ifrån) 16
pixlar för varje 8 som ni lägger till (eller drar ifrån) på start eller
slutpositionen...Alltså om vi har Normal, $38 och $D0, vilket är 320 pixlar
brett, och vi vill öka skärmbredden med 32 pixlar, då ökar vi
startpositionen med 8 och slutpositionen med 8 och så har vi en skärm på
352 pixlars bredd.
  Sen måste vi också tala om hur mycket vi vill visa av skärmen. Det gör vi
i registren DIWSTRT ($DFF08E) och DIWSTOP ($DFF090). De högsta 8 bitarna är
den vertikala positionen och den 8 lägsta är den horisontala. På en normal
skärm brukar man sätta vertikala startpositionen till $2C och horisontala
startpositionen till $81, vilket när man slår ihop dem blir $2C81. Den
normala vertikala slutpositionen brukar vara $12C, men eftersom vi bara har
8 bitar så är det ju inte så lyckat, eftersom vi bara klarar värden upp
till $100. Ingen fara, i den vertikala slutpositionen agerar Amigan alltid
som om den nionde biten var satt, så vi behöver bara ange talet $2C, så
blir det automatiskt $12C! (Det dumma med detta är att vi inte kan
specificera slutpositioner under $80, alltså ungefär på översta halvan av
skärmen...)
  Den normala horisontala slutpositionen brukar vara $C1, och de två talen
tillsammans blir $2CC1.
  Om ni vill kan ni leka med de här talen lite i copperlistan för att se
hur det funkar, och hur bilden påverkas.
  Så, nu var det bara en liten grej kvar - MODULO!
  Säg att vi har ritat en jättefin bild som är 512 pixlar bred i
lågupplösning och vill visa den i vårt jätteskojiga demo. Vi tittar på
DDFSTRT och DDFSTOP och finner att den maximala skärmbredden endast är 368
pixlar! Hu, va hemskt! - Men, vilken tur att vi har MODULO då! Modulon
talar nämligen om hur mycket Amigan ska hoppa över i slutet på en rad för
att komma till början på nästa!
  Om vi tar vår lilla bild, 512 pixlar bred, vilket är 512/8=64 bytes (vi
räknar nästan alltid i bytes, inte pixlar) brett. Vi sätter vår skärm till
bredden 368 pixlar, vilket är 368/8=46 bytes. Det är nu modulon kommer in,
och ska ange hur mycket vi ska hoppa över. Vi har läst 46 bytes nu och
kommit till slutet på skärmen, men det finns fortfarande kvar en del på vår
bild som var 64 bytes bred. För att komma till nästa rad måste vi alltså
hoppa över de bytes som är kvar, helt enkelt 64 bytes minus 46 bytes = 18
bytes. Vi har alltså en modulo på 18 bytes.
  Modulon skrivs in i registren BPL1MOD ($DFF108) för udda bitplan och
BPL2MOD ($DFF10A) för jämna bitplan.
  En liten parentes: Tidigare har vi bara använt bakgrundsfärgs-registret
COLOR00 ($DFF180). För att sätta de andra 31 färgerna använder man de
efterföljande registrena: $DFF182-$DFF1BE.
  Tja, det var alla register vi behöver för att få fram en bild.


                              Programexemplet
                              ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Ett mycket simpelt program den här gången. Visar den enklaste typen av
bild, en 320 pixlar bred, 256 pixlar hög lågupplösningsbild, inte helt
okänd, utan faktiskt den vinnande bilden från The Party II i Aars. Tyckte
den passade bättre än någon bild som jag skulle kunna rita själv ;-)
  Det vanligaste bildformatet är IFF, tex sparar Deluxe Paint alla sina
bilder i IFF, men det formatet fattar egentligen inte Amigan ett dugg av.
Ska man visa det på skärmen måste det vara konverterat till RAW-format. Det
kan man göra med något av den uppsjö program som klarar av det...Tex,
Kefrens IFF-Converter, IFF-Master, PixMate m.m.....
  Om ni vill ha ett program som konverterar IFF -> RAW så skriv ett litet
brev till mig (för jag tänker inte sitta och uploada om ingen behöver
programmet ändå!).
  De två nya rutinerna i programmet gör två enkla grejor. Den ena rutinen
ställer in pekarna på varje bitplan i bilden, och den andra sätter rätt
färger.
  Om vi börjar med den första rutinen, SetBplPtr. Där ställer vi först in
A0 så att det pekar på bildens början, och flyttar sen in den addressen i
D0. Detta måste vi göra för att kunna använda kommandot SWAP.
  Sen pekar vi på bitplanspekarna i copperlistan, där vi ska skriva in
bitplanens startaddresser.
  Eftersom coppern bara kan flytta ett word, 16 bitar, åt gången och vår
address till bitplanet är 32 bitar, måste coppern göra uppdateringen av
bitplanspekaren i två steg. Det är därför vi först flyttar in de 16 lägsta
bitarna och sen, med kommandot SWAP, byter de 16 översta bitarna mot de
16 lägsta i D0 och skriver in de högsta 16 bitarna i copperlistan.
  Efter det lägger vi till hela bitplanets storlek till D0, alltså bredden
i bytes gånger höjden.
  Sen ökar vi på A1 med 8 för att komma till nästa ställe i copperlistan
och så loopar vi tillbaka.
  Den andra rutinen, SetColours, baseras på att vi sparat IFF-bilden som
RAW med paletten efter. Då kan vi läsa 32 words där, eftersom vår bild har
32 färger, och i tur och ordning föra in dem i copperlistan.
  Om vi då tittar lite längre ner i sourcen, på copperlistan, så ser ni hur
jag satt upp de olika registren som jag gick igenom i Register-kapitlet.
  Först sätter jag DIWSTRT till $2C81 och DIWSTOP till $2CC1. Sen sätter
jag de normala DDFSTRT och DFFSTOP värdena, $38 och $D0. Efter det talar
jag om hur många färger bilden har, 32 färger, alltså 5 bitplan. Tvåan i
$5200 anger att jag vill ha COLOR mode på.
  Sen nollställer jag både BPLCON1 och BPLCON2 och sätter både jämn och
udda modulo till noll, eftersom vi har en 320 pixlar bred skärm och vår
bild precis är 320 pixlar.
  Sen följer de fem bitplanspekarna, och där gör jag så att jag skriver in
de 16 högsta bitarna först och sen de 16 lägsta, eftersom coppern ju inte
kan flytta mer än ett word med sitt MOVE-kommando.
  Efter det kommer 32 stycken MOVE-kommando som sätter alla 32 färgerna
till noll. Det är här jag skriver in de riktiga färgerna i rutinen
SetColours.
  Det var de enda nya sakerna i programväg som jag inte tagit upp innan.
Nästa gång ska vi ta upp lite mer skojiga saker om bitplansgrafik, så håll
er till tåls!
