Skip to content

Latest commit

 

History

History
334 lines (242 loc) · 14.9 KB

vdp_cursus_11.md

File metadata and controls

334 lines (242 loc) · 14.9 KB
             M S X 2 / 2 +   V D P   C U R S U S   ( 1 1  )
                                                            
      
                          P A L E T S P L I T 
      
      We   gaan  deze   keer  een  voorbeeld  van  een  zogenaamde 
      paletsplit behandelen.  Dit is  een screensplit, waarbij het 
      palet wordt veranderd bij de screensplit. Hierdoor kunnen er 
      dan bijvoorbeeld 32 kleuren tegelijk op het scherm in SCREEN 
      5. Eerst maar even wat theorie.
      
      
                     P A L E T   A A N S T U R E N 
      
      De VDP heeft 16 paletregisters, die worden aangeduid met P#0 
      t/m  P#15.  Deze  paletregisters kunnen  niet direct  worden 
      beschreven,  en  het  is  helemaal  niet mogelijk  om palet- 
      registers uit te lezen.
      
      De paletregisters  kunnen alleen indirect worden beschreven, 
      en  wel door  eerst het  palet te selecteren door het nummer 
      naar R#16  te schrijven en vervolgens de paletdata naar Port 
      #2 te sturen (I/O poort &H9A).
      
      De  paletdata bestaat uit twee bytes, waarvan slechts 9 bits 
      van belang  zijn. Drie  bits voor rood, drie bits voor blauw 
      en  drie bits  voor groen.  De twee bytes met paletdata zijn 
      als volgt opgebouwd:
      
      MSB   7   6   5   4   3   2   1   0   LSB
            0   ----R----   0   ----B----             1e byte
            0   0   0   0   0   ----G----             2e byte
      
      Let  op, want  de volgorde is niet R,G,B zoals bij de COLOR= 
      instructie  in  BASIC maar  R,B,G. De  handigste notatie  om 
      paletbytes weer  te geven  is door  de eerste byte in hex te 
      zetten en de tweede gewoon in decimaal, dus zo:
      
      &HRB,G
      
      Waarbij  R, B  en G  zoals we  gewend zijn lopen van 0-7. De 
      kleur met R=3, B=7 en G=1 wordt dus:
      
      &H37,1
      
      Tot slot  geef ik  nog even  een voorbeeld  van de  complete 
      procedure  die moet  worden gevolgd  om de  BASIC instructie 
      COLOR=(13,7,2,5) in ML te maken:
      
              DI
              LD      A,13
              OUT     (&H99),A
              LD      A,16+128
              OUT     (&H99),A        ; selecteer P#13
              EI
              LD      A,&H75          ; R=7, B=5
              OUT     (&H9A),A
              LD      A,2             ; G=2
              OUT     (&H9A),A
      
      De  DI  en  EI  instructies zijn  nodig omdat  de interrupts 
      altijd  uit  moeten  staan  als  we  naar  een  VDP register 
      schrijven. Bij  het schrijven  van de  paletregisters is dit 
      alleen  nodig  als  er  op  de  interrupt  ook  iets  met de 
      paletregisters  zou kunnen  worden gedaan. In dat geval moet 
      de EI verhuizen naar het einde van de routine.
      
      Tot  slot  moeten we  nog weten  dat de  paletpointer (R#16) 
      automatisch wordt  verhoogd na  het ontvangen van twee palet 
      bytes  van Port  #2 en  daarbij na P#15 weer verder gaat bij 
      P#0. Als  we bij  bovenstaand voorbeeld dus ook nog kleur 14 
      zouden   willen  veranderen,  kunnen  we  volstaan  met  het 
      schrijven van de twee paletbytes naar &H9A.
      
      
                         S C R E E N S P L I T 
      
      De theorie over het palet is nu in voldoende mate behandeld, 
      maar  voor  een  paletsplit  hebben we  ook een  screensplit 
      nodig. Ik prefereer de zogenaamde "polling screensplit". Dit 
      zegt  u  waarschijnlijk  weinig,  tenzij  u  de  tekst  over 
      Interrupt  Service  Routines  op  Sunrise  Special  #2  hebt 
      gelezen. Daar wordt namelijk uitgelegd wat polling is.
      
      Er zijn  twee manieren  om een screensplit te detecteren. De 
      eerste  manier  is  door  de  VDP de  opdracht te  geven een 
      interrupt  te genereren zodra hij bij een bepaalde beeldlijn 
      is bij de schermopbouw. De computer springt bij de interrupt 
      naar  adres  &H38  en  komt zo  vanzelf bij  de hook  &HFD9A 
      terecht. Als je die hook afbuigt met je eigen routine kun je 
      de screensplit verder afhandelen.
      
      Er is echter een veel simpeler manier, die bovendien sneller 
      reageert op  de screensplit,  en dat is polling. Bij polling 
      wacht  je  gewoon  totdat  de  VDP  bij  de  juiste  lijn is 
      aangeland  met de  schermopbouw. Als  je dit een beetje slim 
      uitkient  neemt  het ook  nog eens  minder processortijd  in 
      beslag  dan  de  interruptmethode.  Bij de  interruptmethode 
      worden namelijk alle registers op de stack gePUSHt, en wordt 
      er flink  wat heen  en weer  gesprongen voordat  de computer 
      eindelijk bij jouw screensplitroutine is. Bij polling is dat 
      allemaal niet nodig.
      
      
             S C R E E N S P L I T   M E T   P O L L I N G 
      
      Hoe  werkt nu  zo'n screensplit met polling. Vrij eenvoudig. 
      Je moet  het programma  zo programmeren dat je per interrupt 
      werkt. Aan het begin zet je een HALT neer. Een HALT wacht op 
      een  interrupt. Dit  is normaal gesproken altijd de 50 of 60 
      Hz interrupt,  die optreedt  als de  VDP met de schermopbouw 
      bij  lijn 212  is aangeland.  HALT laat  die interrupt eerst 
      uitvoeren,  en   daarna  wordt  er  verder  gegaan  met  het 
      hoofdprogramma.
      
      Heb  je  bijvoorbeeld de  replayroutine van  MoonBlaster aan 
      &HFD9F hangen,  dan wordt de muziek dus eerst afgespeeld. Na 
      de  HALT  doe  je  de  scherminstellingen voor  het bovenste 
      gedeelte van het scherm. In dit geval is dat dus het naar de 
      VDP sturen van het palet voor het bovenste gedeelte.
      
      Vervolgens  ga  je  andere  dingen  doen  (bijvoorbeeld  het 
      toetsenbord uitlezen,  berekeningen doen,  etc.), en je mikt 
      het  ongeveer zo uit dat de computer daarmee klaar is als de 
      VDP met de beeldopbouw bij de screensplit is aangeland.
      
      Nu zet je de lijn voor de screensplit in R#19. De VDP zal nu 
      bit 0  van S#1  zetten zodra  hij bij die lijn is. Je checkt 
      dus  bit 0  van S#1  net zolang totdat het op 1 springt. Dan 
      stuur je  het palet  voor de  onderste helft  van het scherm 
      naar  de VDP. Vervolgens heb je nog tijd om andere dingen te 
      doen. Als je er maar voor zorgt dat de computer weer op tijd 
      bij de HALT is.
      
      
               M E E R D E R E   S C R E E N S P L I T S 
      
      Het  grote   voordeel  van  deze  methode  is  dat  meerdere 
      screensplits  geen enkel  probleem zijn. Gewoon nog een keer 
      het screensplitroutinetje  erin zetten,  alleen dan  met een 
      andere lijn.
      
      Bij  de interruptmethode wordt dit toch ingewikkelder, omdat 
      de computer  bij elke interrupt (ook de 50/60 Hz interrupt!) 
      naar  &HFD9A springt,  zodat je  in die  routine eerst  moet 
      uitzoeken welke screensplit het eigenlijk is.
      
      Genoeg  theorie, we gaan gauw verder met het voorbeeld. Hier 
      komt   de   assemblerlisting,  zoals   gewoonlijk  rijkelijk 
      voorzien van uitleg.
      
      
      ; PALSPLIT.ASM
      ; Voorbeeld paletsplit: 32 kleuren op het scherm
      ; VDP Cursus Sunrise Magazine #6
      ; Stefan Boer 18/01/93
      ; (c) Ectry 1993
      
      LINE:   EQU   106
      
              ORG   &HD000
              DI
              XOR   A
              OUT   (&H99),A
              LD    A,16+128
              OUT   (&H99),A        ; P#0 selecteren
      
      
      Hier wordt  P#0 geselecteerd. Dit hoeven we slechts ��n keer 
      te  doen, omdat  we toch  elke keer  alle 16  paletregisters 
      beschrijven. Na afloop staat de paletpointer dan immers toch 
      weer op 0. Hierna begint de hoofdlus:
      
      
      UPPER:  EI
              XOR   A
              CALL  &HD8            ; spatiebalk testen
              RET   NZ
      
      
      Door de  routine GTTRIG  op adres  &HD8 aan te roepen met de 
      waarde  0  in  het A  register vragen  we de  status van  de 
      spatiebalk  op.  Als  de  spatiebalk  is ingedrukt  wordt de 
      routine be�indigd.
      
      
              HALT                  ; wacht op interrupt
      
      
      Hier   wordt  op   de  interrupt  gewacht,  dit  is  dus  de 
      'screensplit' op lijn 212.
      
      
              DI
              LD    HL,PALET1       ; palet voor bovenste helft
              LD    BC,&H209A       ; 32 bytes naar poort &H9A
              OTIR                  ; stuur palet naar VDP
      
      
      De  interrupts  worden  uitgezet, al  is dat  eigenlijk niet 
      nodig omdat er in de praktijk toch geen interrupts optreden. 
      Vervolgens  wordt het  palet met een OTIR instructie naar de 
      VDP gestuurd. Omdat we in dit voorbeeld verder toch niets te 
      doen hebben gaan we gelijk verder met de screensplitroutine.
      
      
              LD    A,LINE
              OUT   (&H99),A
              LD    A,19+128
              OUT   (&H99),A        ; lijn voor screensplit
      
      
      Hier wordt de lijn voor de screensplit naar R#19 geschreven. 
      LINE is  aan het  begin van  de listing  met een  EQU op 106 
      gezet,  dat is  het midden  van het  scherm (want dat is 212 
      lijnen).
      
      
              LD    A,1
              OUT   (&H99),A
              LD    A,15+128
              OUT   (&H99),A        ; S#1 selecteren
              NOP
              NOP                   ; geef VDP tijd om data klaar
                                    ; te zetten
      LOWER:  IN    A,(&H99)        ; lees S#1
              BIT   0,A             ; test op screensplit
              JP    Z,LOWER         ; lijn nog niet bereikt
      
      
      We selecteren eerst S#1, zodat we die kunnen lezen door Port 
      #1 (poort  &H99) te  lezen. De  twee NOPjes zijn nodig om de 
      VDP  de kans  te geven  de juiste  data op  &H99 te  zetten. 
      Vervolgens wachten  we tot  bit 0  van S#1 op 1 springt. Dan 
      weten we dat de VDP bij lijn 106 is aangeland.
      
      
              LD    HL,PALET2       ; palet voor onderste helft
              LD    BC,&H209A       ; 32 bytes naar poort &H9A
              OTIR                  ; stuur palet naar VDP
      
      
      We  sturen op  de inmiddels  bekende wijze het palet naar de 
      VDP.
      
      
              XOR   A
              OUT   (&H99),A
              LD    A,15+128
              OUT   (&H99),A        ; weer S#0 voor BIOS
      
      
      Dit  is  belangrijk,  voor  de  BIOS  moet  S#0  altijd zijn 
      geselecteerd. Om  het BIOS  zo snel mogelijk te houden wordt 
      er namelijk simpelweg IN A,(&H99) gebruikt om S#0 te lezen.
      
      
              JP    UPPER
      
      
      En  tot slot  springen we weer naar de bovenste screensplit, 
      waar eerst  nog even  op de spatie wordt gecheckt. Nu nog de 
      paletten invullen:
      
      
      ; palet voor bovenste helft van scherm
      
      PALET1: DB    &H00,0,&H11,1,&H22,2,&H33,3
              DB    &H44,4,&H55,5,&H66,6,&H77,7
              DB    &H10,0,&H20,0,&H30,0,&H40,0
              DB    &H50,0,&H60,0,&H70,0,&H77,0
      
      ; palet voor onderste helft van scherm
      
      PALET2: DB    &H00,0,&H01,0,&H02,0,&H03,0
              DB    &H04,0,&H05,0,&H06,0,&H07,0
              DB    &H00,1,&H00,2,&H00,3,&H00,4
              DB    &H00,5,&H00,6,&H00,7,&H07,7
      
      
      De  hier gegeven data is natuurlijk volslagen willekeurig, u 
      kunt hier  zelf invullen  wat u  wilt. Deze  assmblerlisting 
      staat  als PALSPLIT.ASC  op de diskette, geassembleerd onder 
      de naam PALSPLIT.BIN.
      
      
                           V O O R B E E L D 
      
      In PALSPLIT.PMA zit het voorbeeldprogramma PALSPLIT.BAS, dit 
      programma  tekent 2  maal 15 verticale balken in SCREEN 5 om 
      de  routine  uit  te  testen.  Er  zijn dan  dus 31  kleuren 
      tegelijk  op  het  scherm  (30 balken  + achtergrondkleur  = 
      zwart).
      
      
                    N E T T E   P A L E T S P L I T 
      
      U  zult  bij  het  voorbeeld  helemaal niets  merken van  de 
      paletsplit. Dit komt omdat de split ergens bij lijn 106 zit, 
      en  daar zit alleen kleur 0. Ik heb kleur 0 express in beide 
      paletten hetzelfde  gehouden, zodat de overgang niet te zien 
      is.
      
      Kijk maar eens wat er gebeurt als u kleur 0 wel verschillend 
      maakt,  dan kun  je duidelijk de screensplit zien zitten. Je 
      ziet ook dat hij trilt.
      
      Bij andere  screensplits kun  je de  split wegwerken door op 
      een  bit van  een statusregister te checken dat aangeeft dat 
      de VDP  begint met  het opbouwen van de lijn. Omdat dat niet 
      precies  klopt  moet  er  dan  ook nog  een wachtlusje  bij. 
      Waarschijnlijk  kom ik  daar in  een later  deel van  de VDP 
      cursus nog wel eens op terug.
      
      Bij een  paletsplit is  de hier  gebruikte oplossing  echter 
      beter,  het kost  vrijwel geen  moeite en  je ziet  de split 
      absoluut niet.  Zorg dus  dat kleuren  die in  het overloop- 
      gebied  voorkomen in  beide paletten hetzelfde zijn, dan zie 
      je niets van de paletsplit.
      
      
                         5 1 2   K L E U R E N 
      
      Ik denk  dat het  mogelijk is om met behulp van deze routine 
      alle  512 kleuren tegelijkertijd op het scherm te krijgen in 
      SCREEN 5,  door gewoon  het screensplitstuk een flink aantal 
      keren  achter elkaar  te zetten  en voldoende  verschillende 
      paletten toe te voegen. Ik heb het zelf nog niet geprobeerd, 
      misschien een andere keer.
      
      Veel succes  met het  experimenteren met deze routine en tot 
      de volgende keer.
      
                                                      Stefan Boer