                          - SEPTIC'S DEMOSKOLA -

                                 Lektion 1
                                 
                        Skriven av Vicious / Septic

                                 13 Apr 93



                                 Inledning
                                 
Vlkommen till frsta lektionen i denna utomordentliga demoskola. Hr
kommer du att f mjlighet att lra dig allt du gtt och drmt om att
kunna, men inte lyckats/haft tid med. Vi kommer trska igenom allt tnkbart
inom demovrlden, s som copperbars, sprites, bobs, textscrollar, linje-
ritning, vektorer, cirklar och mycket mer skojigt som man kan ha nytta av i
sin framtida demoprogrammering.
  Jag frutstter att grundkunskaper i assemblerprogrammering finns innan
ni brjar lsa, fr detta r enbart en Demoskola, som ska lra ut demo-
programmering, inte en assemblerskola. Exempelprogrammen r skrivna i
AsmOne, men om du anvnder en annan assembler s br det inte vara s stora
problem att anpassa sourcen efter den.
  Kursen kommer att i viss mn strida mot allt vad Commodore fresprkar om
systemvnlig programmering, men jag anser att det r en ndvndighet
inom demoprogrammering att skriva sina egna "quick-and-dirty" rutiner fr
att pressa ut det maximala av Amigan. Anvnder man Commodores egna
libraryrutiner s blir allt alldeles fr segt, och dessutom fr man inte
den rtta kontrollen ver programmet.
  Om du inte delar den uppfattningen, utan enbart vill gra program som
garanterat kommer fungera p alla kommande Amigor s rekommenderar jag dig
att sluta lsa nu.
  Sdr, d var vi frbi formaliteterna och kan raskt kasta oss ver
vsentligheterna...


                                 Register
                                 
Under den hr rubriken (som ni s smningom kommer att vara ganska bekanta
med) ska jag i varje Lektion g igenom olika register vi behver fr att
stadkomma vra effekter. Alla dessa register finns utfrligt frklarade i
Commodores Hardware Reference Manual och jag rekommenderar att du skaffar
den boken om du inte har den, fr den r varje demoprogrammerares bibel.
Jag kommer dock frklara de register jag anvnder, vad de r bra fr och
hur de anvnds.
  Till att brja med kanske jag ska frklara lite runtom dessa omtalade
hrdvaru register. Genom att lsa eller skriva till ett hrdvaru register
kan man kommunicera direkt med hrdvaran i Amigan. Commodore sger att man
inte br programmera dem direkt utan g via resources eller libraries, men
det allra bsta r att inte gra det, fr att spara rastertid. Man kan till
exempel lsa av var videostrlen befinner sig p fr rasterrad och synca en
rutin direkt efter den, eller byta bakgrundsfrg fr varje rasterrad och
skapa vackra coppereffekter. Allt det hr blir smidigare (nr man vl kan
det) och framfr allt snabbare om man anvnder hrdvaran direkt.
  Ett mycket viktigt register som vi ska brja med r DMACON ($dff096). Det
styr Amigans DMA, dvs vi kan reglera vad vi vill anvnda och vad vi inte
behver. De saker man styr med registret r:

   * Blitter prioritet ver DMA
   * Bitplans DMA (s att man kan visa grafik)
   * Copper DMA
   * Blitter DMA
   * Sprite DMA
   * Disk DMA
   * Ljud DMA

Som ni ser s r det ungefr allt vad man kan tnka sig ha med i ett demo,
och det hr registret styr vad som ska synas. Precis som de flesta andra
registren r DMACON ($dff096) ett WRITE ONLY register, dvs man kan bara
skriva till det. Vill man lsa av nuvarande DMA fr man lsa frn DMACON's
motsvarighet, DMACONR ($dff002). De register som innehller intressant
information har oftast en READ ONLY-motsvarighet.
  Nr man gr ett demo ska man alltid planera i frvg vad man egentligen
ska gra, hur det ska se ut och s vidare...D blir det ocks ltt att
avgra vad man ska stta fr DMA. Behver man tex inte sprites i sitt demo
ska man sl av Sprite DMA, fr att slippa "spriteflimmer" och att ondig
DMA-tid gr till sprites som inte visas.
  Vi ska nu titta p hur registret r uppbyggt. Det r ett WORD-register,
vilket allts betyder att det innehller 16 bitar. Dess uppbyggnad r
mycket vanlig och terkommer i mnga andra register. Bitarna lyder som
fljer:

 BIT   FUNKTION   BESKRIVNING
       
 15    SET/CLR    Anger om bitar med en 1 ska rensas eller sttas.
 14    BBUSY      Anger om blittern arbetar eller r ledig. (Read Only)
 13    BZERO      Talar om ifall en blitteroperation resulterade i
                  en destination med bara nollor.
 12    X
 11    X
 10    BLTPRI     Blittern prioriteras fre processorn, vilket gr att
                  processorn inte kan stjla ngra cyklar frn blitter DMA.
 09    DMAEN      Tillter nedanstende DMA.
 08    BPLEN      Bitplans DMA pslagen.
 07    COPEN      Copper pslagen.
 06    BLTEN      Blitter pslagen.
 05    SPREN      Sprite DMA pslagen.
 04    DSKEN      Disk DMA pslagen.
 03    AUD3EN     Ljud kanal 3 DMA pslagen.
 02    AUD2EN      "    " "  2  "   "   "
 01    AUD1EN      "    " "  1  "   "   "
 00    AUD0EN      "    " "  0  "   "   "

Frst och frmst i ett program, br man spara den gamla DMA-instllningen
(om man ska tervnda till systemet) innan man stter sin egen. Det grs
enkelt genom att plocka ett WORD frn DMACONR ($dff002) och spara det tills
man avslutar sitt program. Man mste dock stta bit 15 innan man skriver
tillbaka till DMACON ($dff096) fr att bitarna ska sttas.
  Nr man sparat den gamla instllningen brukar man rensa alla bitarna,
vilket man gr genom att skriva #$7fff till DMACON ($dff096). Detta gr att
alla bitar rensas (eftersom bit 15 r 0). Nr man rensat allt r det dags
att komponera ihop sin egna DMA och skriva den till DMACON ($dff096).
(Detta kan du se i demonstrations programmet Lekt1.s om ngot r oklart.)

Efter allt prat om DMA ska vi ta upp coppern en smula. Innan man
installerar sin egen copperlista br man ocks hr (likt DMA) spara undan
den gamla copperaddressen (om man ska tervnda till systemet) fr att
kunna terstlla den gamla copperlistan vid programmets slut.
  Att hmta systemets copperlista r inte lika enkelt som att hmta gammal
DMA, eftersom det inte finns ngot READ-register fr copperaddressen. Man
fr istllet g via graphics.library (trots att jag inte gillar att anvnda
libraries :-) s blir man tvungen ibland...). Genom att ppna
graphics.library och hmta vrdet som ligger p $26+gfxlib-startaddressen.
Efter att ha sparat den addressen kan vi lugnt skriva in vr egen
copperlista i COP1LC ($dff080). (OBS! Copperlistan mste ligga i CHIPMEM!)
Vrdet skrivs in som ett LONGWORD. Efter det ska man helst skriva ett WORD
till COPJMP1 ($dff088) fr att tvinga Amigan att brja anvnda din egen
copperlista. COPJMP1 ($dff088) r ett s kallat strobe-register, som inte
bryr sig om vilket vrde som skrivs, utan bara att man skrivit till det.
Meningen med COPJMP1 ($dff088) och COPJMP2 ($dff08a) r att man kan ha tv
copperlistor samtidigt p COP1LC ($dff080) och COP2LC ($dff084) som kan
hoppa mellan varandra.
  Om vi nu skulle ta och beskriva copperlistor. Coppern r ju som bekant en
coprocessor som arbetar helt oberoende av MC68000 processorn. Copper r en
mycket effektiv liten medhjlpare, som ligger bakom mycket av Amigans
grafikmjligheter. Exempelvis kan man p ett enkelt stt byta frger, DMA,
trigga interrupt eller till och med byta upplsning var som helst p
skrmen. Eftersom copperlistan krs om varje vertical blanking s frenklar
den register-uppdatering, p exempelvis bitplanspekare som mste sttas
varje vbl (vertical blanking), avsevrt. Man kan ven kontrollera blittern
med den, och uppdatera sprites, osv osv...Kort sagt, coppern r mycket
anvnbar, men nd ganska enkel att anvnda!
  Dess enkelhet ligger i att den endast har tre (3) instruktioner. WAIT,
MOVE och SKIP. Copperinstruktionerna bestr av ett LONGWORD, eller tv
WORDS.
  Om vi brjar med instruktionen WAIT. Med den kan man vnta p att video-
strlen ska n en viss position p skrmen och dr tex ndra palette eller
ngot annat skojigt. De tv WORDen ser ut s hr:

                                  WORD 1

Bit 0    - Alltid satt till 1 (detta plus bit 0 i word 2 r den egentliga
           instruktions identifieraren).
Bit 1-7  - Horisontell strlposition att vnta p.
Bit 8-15 - Vertikal strlposition att vnta p.

                                  WORD 2

Bit 0    - Alltid satt till 0.
Bit 1-7  - Anger vilka bitar som mste stmma med det horisontella
           strlpositions vrdet.
Bit 8-14 - Anger vilka bitar som mste stmma med det vertikala strl-
           positions vrdet.
Bit 15   - Normalt satt till 1. (Se Hardware Reference Manual fr mer
           information.)

Om vi tar ett exempel p en WAIT-instruktion s kan den se ut s hr:

   DC.W   $8007,$FF00

Det hr WAIT-kommandot vntar p den vertikala raden $80, medan
horisontella postitionen $07 ignoreras eftersom dess bitar r noll i WORD 2
($FF00).

   DC.W   $A019,$FFFE

Hr har vi dremot ett WAIT-kommando dr den horisontella positionen $19
inte ignoreras. Hr vntar vi tills positionen $A0 vertikalt och $19
horis. r uppndd (eller verstigen) innan nsta instruktion utfrs.
  Notera att det horisontella vrdet mste vara udda! Annars tolkas det som
ett MOVE-kommando. Det mste ocks ligga inom $0-$e2.

Ett MOVE-kommando flyttar ett WORD till ett hrdvaru register. Det kan till
exempel vara ett frgbyte eller en bitplans uppdatering. Hr kommer MOVE-
kommandots utseende:

                                  WORD 1

Bit 0    - Alltid 0.
Bit 1-8  - Register destination.
Bit 9-15 - Oanvnda. Stt till 0.

                                  WORD 2

Bit 0-15 - 16 bitar som ska flyttas till hrdvaru registret.

MOVE kan skriva till alla register ver $dff020. Om man har satt copperns
DANGER bit i COPCON ($dff02e) kan man ven skriva till registren mellan
$dff010 och $dff020.
  Fr att byta bakgrundsfrg till vit skriver vi till COLOR00 ($dff180). Om
man gjorde det med processorn skulle det se ut s hr:

   MOVE.W   #$FFF,$DFF180

Men med copperns MOVE blir det:

   DC.W   $0180,$0FFF

Till sist har vi SKIP-kommandot. Det anvnds inte s vrst mycket men fr
den sakens skull behver vi ju inte hoppa ver det.
  SKIP r ganska likt WAIT. Den kollar ocks var videostrlen befinner sig,
och om positionen r lika eller mer hoppas nsta instruktion ver.

                                  WORD 1

Bit 0    - Alltid satt till 1.
Bit 1-7  - Horisontell strlposition att vnta p.
Bit 8-15 - Vertikal strlposition att vnta p.

                                  WORD 2

Bit 0    - Alltid 1.
Bit 1-7  - Anger vilka bitar som mste stmma med det horisontella
           strlpositions vrdet.
Bit 8-14 - Anger vilka bitar som mste stmma med det vertikala strl-
           positions vrdet.
Bit 15   - Normalt satt till 1. (Se Hardware Reference Manual fr mer
           information.)

SKIP kan tex anvndas fr att skippa en strobe-skrivning till COPJMP2 som
gr att copperlista 2 brjar anvndas. r man sdr haj p hur det funkar
kan man skapa snitsiga copperloopar fr roliga effekter. Det kommer jag
dock inte g in p nrmare hr.
  Om du fortfarande inte riktigt frstr hur copperlistan r uppbyggd kan
du kika i exempel-sourcen. Dr finns en copperlista vl dokumenterad.

Detta var vad jag tnkte ta upp i registervg hr i Lektion 1. Som jag sa
frut finns alla hrdvaru register vl dokumenterade i Hardware Reference
Manual, och den BR du ha om du vill bekanta dig med Amigans mjligheter
inom demoprogrammering.


                                   Setup
                                   
Programexemplet till den hr lektionen r vldigt simpelt, men jag tyckte
jag skulle brja frn grunden, s att alla hnger med ordentligt.
  Kort sagt stter programmet bara upp demots "interface", dvs att det
stnger av Amigans multitasking system och byter till en egen skrm.
  Vad jag gr i min INIT rutin r fljande -> Frst hmtar jag ngot som
kallas VBR (Vector Base Register). VBR finns inte p vanliga 68000
processorer utan bara p 68010 och uppt. Det r en offset till datorns
interrupt- och undantagsregister som p en 68000 ligger i brjan p minnet.
Meningen med VBR r att man ska kunna flytta dessa interrupt- och
undantagsregister till FAST MEM fr att datorn skall bli snabbare. Drfr
r det viktigt att man i sitt program inte antar att exempelvis vertical
blanking interruptet ligger p adress $6c utan att man kollar vad VBR-
registret r instllt p och lser relativt frn den addressen plus $6c.
Om ni tycker detta verkar krngligt s r det inte s farligt. Lr er bara
att man ska hmta VBR i sitt program fr att det ska funka.
  Nsta steg r att stnga av multitaskingen. Inget att orda om. Vill man
gra de hftigaste rutinerna mste man tyvrr sno all processortid
sjlv....
  Efter det kommer en liten villkorlig rutinsnutt (som du sjlv vljer om
du vill ha med genom att ndra variabeln DisableCache i brjan av
programmet). Rutinen stnger av cache p datorer som har det (dock ej p
maskiner med KS1.3 eller lgre...) och varfr ska man gra det d? Tja,
instruktionscache kan strula till det ibland vid decrunching, likas
datacache, s det bsta r vl att stnga av det, om man inte utnyttjar
dess snabbhet i programmet.
  Efter det ppnar jag graphics.library och kr OwnBlitter() fr att ta
ver blittern frn systemet. Sen kr vi WaitBlit() fr att vnta tills vi
ftt den. Efter det gr vi en LoadView(0) s att vi kan stta in vr egen
copperlista. Fr skerhets skull vntar vi ocks med WaitTOF (tv gnger
ifall usern kr i interlace...).
  Eftersom vi inte har ngra interrupt p den hr gngen s rensas bara
interrupt-kontroll registret. Vi rensar ocks DMAn (men den stter vi
lngre fram...)
  Nu kommer det nnu en villkorlig del, DisableMotor. En irriterande grej
nr man stnger av interrupt och multitasking r att drivelampan ibland kan
fortstta att lysa nr demot kr. Den hr rutinen slcker den genom att
stnga av motorn.
  Nr vi nu tervnder frn INIT-rutinen stter jag den DMA jag vill ha.
Fr enkelhetens skull har jag skrivit dit (vertikalt) vad de olika bitarna
str fr s att det ska bli enklare att se. Vad jag gr r att stta p
endast COPPER DMA.
  Sen stter jag dit min egen copperlista och skriver till strobe registret
som jag berttade om i brjan, COPJMP1 ($dff088).
  Mainloopen innehller bara en liten nonsensrutin som byter bakgrundsfrg.
Den loopar tills du trycker vnster musknapp.
  Efter det krs min UnInit-rutin. Man kan sga att den gr precis tvrtom
vad INIT-rutinen gr. Frst terstller vi gamla interupt och DMA, sen ger
vi tillbaka blittern till systemet och efter det fixar vi tillbaka den
gamla viewporten och de tv copperlistorna som anvnds av systemet.
  Nu r det bara att stnga intuition.library + graphics.library och (ifall
vi stngde av det) sen terstller vi cacheminnet.
  Allra sist slr vi p multitaskingen igen.
  Mycket mer finns det inte att sga om det enkla programmet. Studera det
noga och titta hur det fungerar.

