IRQ-KURS                
     "Die Hardware ausgetrickst..."     
                (Teil 12)               
 Herzlich  Willkommen  zu  einer  neuen  Folge
 unseres  IRQ-Kurses. In  dieser  Ausgabe
 werden  wir  uns  weiter  mit  der  ESCOS-Routine  des  letzten  Kursteils  beschäftigen. Wir  werden  hierbei  die  Routine  mit
 einem  Movie-Scroller  verbinden, um  so
 einen  bildschirmübergreifenden  Text
 scrollen  zu  lassen. Dies  gestaltet  sich
 ohne  einen  speziellen  Trick  gar  nicht
 mal  so  einfach. . .
1) EINLEITUNG  Wie  Sie  sich  vielleicht  noch  erinnern, so  hatten  wir  in  der  letzten  Folge  des
 IRQ-Kurses  zuletzt  das  Beispielprogramm
" ESCOS2" besprochen. Diese  Raster-IRQ- Routine  öffnete  uns  den  linken  und  rechten, sowie  den  oberen  und  unteren  Bild- schirmrand  und  stellte  dann  alle 21 Rasterzeilen  eine  neue  Reihe  mit  je  acht
 Sprites  auf  dem  Bildschirm  dar. Dadurch
 hatten  wir  insgesamt  vierzehn  Zeilen  zu
 je  acht  Sprites  auf  dem  Bildschirm, die
 alle  nahtlos  aneinandergereiht  fast  den
 gesamten  Bildschirm  überdeckten. Der
 einzige  ungenutzte  Bereich  war  der  von
 Rasterzeile 294 bis 312, der  zu  klein
 war  um  eine  weitere  Spritereihe  darin
 unterzubringen, aber  sowieso  schon  unterhalb  der  für  normale  Monitore  darstellbaren  Grenze  liegt.
 Der  einzige  Unterschied  der  Routine " ES-COS2" zu " ESCOS1" bestand  nun  darin, daß
 erstere  Routine  lediglich  ein  Zeilenoffset- Register  für  den  ersten  auszulösenden  Raster-IRQ  herunterzählte, um  so
 einen  Scroll-Effekt  der  Spritereihen  zu
 erzielen." ESCOS2" ist  also  schon  eine
 Art " Moviescroller" . Der  Grund, warum
 sie  es  nicht  wirklich  ist, liegt  darin, daß  in  jeder  Spritezeile  dieselben  Sprites  auf  dem  Bildschirm  zu  sehen  waren.
 Wie  wir  aber  von  den  Moviescroll-Routinen  wissen, müssen  wir  für  einen
 Scrolltext  das  Aussehen  einer  Spritezeile  ja  individuell  bestimmen  können, damit  auch  wirklich  ein  Text, und  nicht
 immer  dieslbe  Zeile, über  den  Bildschirm
 läuft.
2) DAS  PROBLEM - DIE  LÜSUNG " Kein  Problem" werden  Sie  nun  sagen," einfach  die  Textausgaberoutine  der  Moviescroller- Routinen  vom  IRQ-Kurs  einbauen, und  schon  haben  wir  einen  Scrolltext" . Diese  Feststellung  stimmt  schon, wie  sollte  es  auch  anders  gehen, jedoch
 stellt  sich  uns  dabei  noch  ein  kleines
 Problem  in  den  Weg: dadurch  nämlich, daß
 wir  in  den  ESCOS-Routinen, keine  Zwischenräume  mehr  zwischen  den  einzelnen
 Spritezeilen  haben, gestaltet  es  sich
 als  schwierig, die  Sprite-Pointer  zeitgenau  zu  setzen. Setzen  wir  diese  nämlich  auf  die  neu  einzuscrollende  Sprite- zeile, noch  bevor  die  letzte  Spritezeile
 abgearbeitet  wurde, so  erscheinen  die
 alten  Sprites  schon  im  Aussehen  der
 Neuen. Umgekehrt  können  die  Spritepointer  auch  nicht  nach  Abarbeiten  der  letzten  Spritezeile  gesetzt  werden  da  hier
 ja  schon  die  neuen  Sprites  erscheinen
 müssen. Man  könnte  nun  versuchen, ein
 megagenaues  Timing  zu  programmieren, das  innerhalb  der  ersten  Rasterzeile
 einer  neuen  Spritezeile  exakt  vor  Darstellen  eines  neuen  Sprites  dessen  Pointer  neu  setzt. Dies  gestaltet  sich  jedoch  umso  umständlicher, wenn  wir  beachten  müssen, daß  gleichzeitig  auch  noch
 der  linke  und  rechte  Rand  geöffnet  werden  soll. Da  dieser  ebenfalls  ein  exaktes  Timing  verlangt, würden  wir  mit  dem
 Doppeltiming  in  des  Teufels  Küche  kommen. Aber  keine  Sorge: glücklicherweise
 können  wir  als  IRQ-Magier  wieder  in  die
 Raster-Trickkiste  greifen, und  eine
 weitaus  einfachere  Lösung  des  Problems
 anwenden.
 Wie  Sie  z. B. schon  von  unseren  FLI-Routinen  wissen, hat  man  mit  dem  VIC  die
 Möglichkeit, das  Video-RAM  innerhalb
 seines  Adressbereiches  von 16 KB  zu  verschieben. Der  Speicherbereich, den  der
 Grafikchip  dazu  verwendet, um  den  Inhalt
 des  Textbildschirms  aufzubauen  muß  also
 nicht  zwingenderweise  bei $0400 liegen, wo  er  sonst  nach  dem  Einschalten  des
 Rechners  untergebracht  ist. Durch  die
 Bits 4-7 des  Registers $ D018 können  insgesamt 16 verschiedene  Speicherbereiche
 gewählt  werden, deren  Basisadressen  in
$0400- Schritten  von $0000-$3 C00 gehen.
 Nun  werden  Sie  fragen, was  denn  das  Video- RAM  mit  unserer  ESCOS-Routine  zu  tun
 hat, zumal  wir  die  Bildschirmdarstellung
 doch  sowieso  abgeschaltet  haben, und
 keinen  Text  auf  dem  Bildschirm  haben?
 Nun, ganz  einfach: wo  befinden  sich  denn
 die  Register  der  Spritepointer  normalerweise? Natürlich  in  den  Adressen  von
$07 F8-$07 FF. Und  genau  diese  Adresse liegen  am  Ende  des  Video-RAMs. Verschiebt  man  nun  das  Video-RAM  an  eine
 andere  Adresse, so  verschiebt  man  automatisch  auch  die  Registeradressen  der
 Spritepointer! Wird  das  Video-RAM  also
 beispielsweise  um $0400 Bytes  nach $0800 verschoben, so  bewegen  sich  die  Spritepointer- Register  ebenfalls  um $0400- Bytes  nach  vorne. Um  nun  also  das  Aussehen  der  acht  Sprites  zu  definieren, müssen  die  Adressen $0 BF8-$0 BFF  beschrieben
 werden. Und  genau  das  ist  die  Lösung
 unseres  Problems. Da  es  während  des
 Spriteaufbaus  zu  lange  dauert, alle  acht
 Spritepointer  in  den  Akku  zu  laden  und
 in  die  Register  zu  schreiben, soll  das
 die  Initialisierungsroutine  des  Moviescrollers  übernehmen. Hierbei  schreibt
 letztere  die  benötigten  Werte  für  eine
 Spritezeile  in  die  Pointerregister  eines
 verschobenen  Video-RAMs. Während  der
 Darstellung  brauchen  wir  nun  nur  noch
 durch  Schreiben  eines  einzigen  Bytes, nämlich  des  ensprechenden  Wertes  für  ein neues  Video-RAM  in $ D018, auf  selbiges
 umzuschalten. Dadurch, daß  der  VIC  für
 die  neue  Spritezeile  nun  in  einem  ganz
 anderen  Video-RAM  arbeitet, holt  er  sich
 auch  die  Spritepointer  aus  den  neuen
 Adressen, womit  wir  alle  acht  Spritepointer  mit  nur  einem  Schreibzugriff
 umgeschaltet  hätten!
 Die  Umsetzung  dieser  Lösung  in  die  Praxis  gestaltet  sich  für  uns  sehr  einfach.
 Sinnigerweise  haben  wir  nämlich  in  den
 Routinen " ESCOS1" und " ESCOS2" schon
 Platz  für  diese  Änderung  gelassen. Wie
 Sie  sich  vielleicht  erinnern, hatten  wir
 zur  Darstellung  der  Sprites  innerhalb
 der  IRQ-Routine  dieser  beiden  Beispielprogramme  die  Unterroutine " OPEN21" vierzehnmal  aufgerufen. Sie  wird  immer
 in  der  ersten  Rasterzeile  einer  neuen
 Spritezeile  angesprungen, und  übernimmt
 das  Neusetzen  der  Y-Koordinaten  aller
 Sprites, sowie  das  Üffnen  des  Sideborders  in  den  folgenden 21 Rasterzeilen.
 So  sah  der  Aufruf  in  den  beiden  Bei- spielprogrammen  aus:
 nop  ; Diese  Befehlsfolge  wird  jsr  open21 ; insgesamt 14 x  aufgerufen 
... ; um je 21 Zeilen zu öffnen nop ;Sprite Line 14 jsr open21
 Die " NOP"- Befehle  dienten  dabei  nur  der
 Verzögerung  um  zwei  Taktzyklen, damit
 die  Änderung  zum  richtigen  Zeitpunkt
 eintritt. Wir  können  diese  Befehle  mit
 jedem  anderen  Befehl  ersetzen, der  nur 2 Takte  in  Anspruch  nimmt. Diese  Tatsache
 machen  wir  uns  für  den  Moviescroller
 zunutze. Wir  ersetzen  die  NOPs  mit  LDA-Befehlen, wobei  der  Wert, der  in  den
 Akku  geladen  wird, dem  Wert  entspricht, der  in  Register $ D018 geschrieben  werden
 muß, um  auf  das  neue  Video-RAM  umzuschalten. Er  dient  quasi  als  Parameter
 für  die " OPEN21"- Routine. Demnach  sieht
 der  Aufruf  dieser  Routine, aus  dem  Raster- IRQ  heraus, nun  folgendermaßen  aus:
 v00 : lda #$00*$10 ; Code  für  Scr0($0000) jsr  open21 ;21 Rasterzeilen  öffnen
 v01 : lda #$01*$10 ; Code  für  Scr0($0400) jsr  open21 ;21 Rasterzeilen  öffnen
 v02 : lda #$02*$10 ; Code  für  Scr0($0800) jsr  open21 ;21 Rasterzeilen  öffnen
    ...                                 
v0d:lda #$0d*$10 ;Code für Scr13 ($3400)
    jsr open21   ;21 Rasterzeilen öffnen
 Wie  schon  in  den  ESCOS-Beispielen, so
 wiederholt  sich  auch  hier  die  LDA-JSR- Befehlsfolge 14 Mal, wobei  jeweils  der
 nächste  Video-RAM- Bereich  als  Parameter
 im  Akku  übergeben  wird. Timingmässig  hat
 sich  nichts  geändert, da  der  NOP-Befehl
 genausolange  braucht  wie  der  LDA-Befehl.
 Eine  ähnliche  Modifikation  haben  wir  nun
 für  das  Schreiben  dieses  Akku-Wertes  in
 Register $ D018 vorgenommen. Diese  Aufgabe  soll  von  der  Routine " OPEN21" durchgeführt  werden. Hier  ein  Auszug  der  er- sten  Zeilen  dieser  Routine  aus  dem  Beispiel " ESCOS2" :
 open21 :
nop ;Verzögern bis rechter nop ; Rand erreicht dec $d016 ;38 Spalten (Rand inc $d016 ;40 Spalten öffnen) lda $1500,y ;$D011-Wert aus Tabelle sta $d011 ; lesen und eintragen iny ;Tabellen-Index+1 jsr cycles+5;24 Zyklen verzögern
 . . .
 Wie  Sie  sehen, stehen  hier  ebenfalls
 zwei  NOP-Befehle  am  Anfang  der  Routine.
 Sie  benötigen 4 Taktzyklen, was  für  einen " STA $ XXXX"- Befehl  ebenfalls  zutrifft. Die  zwei  NOPs  wurden  für  den
 Moviescroller  nun  mit  einem " STA $ D018" ersetzt:
 open21 :
 sta $ d018 ; VRAM  f. SprPtrs. versch.
dec $d016 ;38 Spalten (Rand inc $d016 ;40 Spalten öffnen) lda $1500,y ;$D011-Wert aus Tabelle sta $d011 ; lesen und eintragen iny ;Tabellen-Index+1 jsr cycles+5;24 Zyklen verzögern
 . . .
 Damit  hätten  wir  also  die  ESCOS-Routine
 so  umprogrammiert, daß  Sie  uns  in  jeder
 der 14 Spritezeilen  auch  neue  Spritepointer  setzt. Es  müssen  nun  noch  zwei
 weitere  Änderungen  gemacht  werden, damit
 der  Moviescroller  auch  voll  funktionstüchtig  ist.
 Zunächst  einmal  muß  die  Initialierungsroutine  erweitert  werden. Sie  soll  uns
 die  Spritepointer  der  benutzten  Video-RAM- Adressen  auf  bestimmte  Sprites  vorinitialisieren, so  daß  später  zur  Darstellung  einer  bestimmten  Spritereihe
 nur  noch  die  Nummer  des  zu  benutzenden
 Video-RAMs  in  den  Labeln " V00" bis " V0 D" der  Raster-IRQ- Routine ( siehe  oben) ein- getragen  werden  muß, und  die  Routine
 somit  automatisch  den  richtigen  Bildschirm  zur  korrekten  Darstellung  der
 entsprechenden  Spritezeile  wählt.
 Zunächst  einmal  wollen  wir  vereinbaren, daß  wir  den 16 K-Adressbereich  des  VICs
 von $0000-$3 FFF  um  eins  nach  oben  in  den
 Bereich  von $4000-$7 FFF  verschieben.
 Dadurch  stört  uns  die  Zeropage, die  normalerweise  ja  auch  im  Bereich  des  VICs
 liegt, nicht  mehr, und  wir  haben  volle
16 KB  zur  Speicherung  von  Sprites  und
 Spritepointer-Video- RAM  zur  Verfügung.
 Die  Verschiebung  wird  durch  Schreiben
 des  Wertes 2 in  das  Portregister  A  von
 CIA-B  erreicht. Innerhalb  der  Initialsierung  wurde  also  folgende  Befehlssequenz  hinzugefügt:
LDA #$02 STA $DD00
 Damit  befindet  sich  der  Datenbereich  für
 den  VIC  nun  im  Bereich  von $4000-$7 FFF.
 Beachten  Sie  bitte  auch, daß  nun  der
 Bytewert, den  der  VIC  in " ausgetricksten" Rasterzeilen  darstellt, nicht  mehr
 in $3 FFF, sondern  in $7 FFF  abgelegt  werden  muß ( im  Beispielprogramm  enthält  er
 den  Wert $81, womit  vertikale  Lininen
 hinter  dem  Scrolltext  erscheinen) . Nun
 folgt  der  Teil, der  die  Spritepointer
 setzt. Hier  treffen  wir  die  Konvention, daß  die  Sprites, die  durch  die  Pointer
 einer  Video-RAM- Bereichs  dargestellt
 werden  auch  innerhalb  dieses  Video-RAMs
 unterbracht  werden  sollen. Liegt  dieses
 also  Beispielsweise  bei $4400, so  soll
 Spritepointer 0 auf  das  Sprite  bei $4400( Blocknr.16), Spritepointer 1 auf  das
 Sprite  bei $4440( Blocknr.17), usw., zeigen. Dies  bewerkstelligt  nun  der  folgende  Teil  der  Init-Routine:
lda #$f8 ;ZP-Zgr. $02/03 mit sta $02 ; $43F8 init. lda #$43 sta $03
 lda #($0000/64) ; Ptr. f. Sprite-Line01 jsr  setpoint  ; setzen  lda #($0400/64) ; Ptr. f. Sprite-Line02 jsr  setpoint  ; setzen  lda #($0800/64) ; Ptr. f. Sprite-Line03 jsr  setpoint  ; setzen 
 . . .
 lda #($3000/64) ; Ptr. f. Sprite  Line13 jsr  setpoint  ; setzen  lda #($3400/64) ; Ptr. f. Sprite  Line14 jsr  setpoint  ; setzen 
 Wie  Sie  sehen  wird  lediglich  ein  Adressierungszeiger  in  der  Zeropage  initialisiert, und  dann 14 Mal  die  Unterroutine
" SETPOINT" aufgerufen, wobei  im  Akku  der
 Inhalt  für  den  jeweils  ersten  Spritepointer  übergeben  wird. Hier  nun  die
 Routine " SETPOINT", die  die  eigentlichen
 Werte  in  die  Pointerregister  schreibt:
 SETPOINT:
 ldy #$00 ; Index-Reg. init.
 sta ($02), y; SprPtr0 ablegen 
clc ;Akku=Akku+1 adc #$01 iny ;Index=Index+1 sta ($02),y;SprPtr1 ablegen clc ;Akku=Akku+1 adc #$01 iny ;Index=Index+1 sta ($02),y;SprPtr2 ablegen ... clc ;Akku=Akku+1 adc #$01 iny ;Index=Index+1 sta ($02),y;SprPtr7 ablegen clc ;Auf Hi-Byte des $02/$03 lda $03 ; Zeigers den Wert 4 add. adc #$04 ; um auf nächstes VRAM zu sta $03 ; positonieren rts
 Wie  Sie  sehen, so  wird  vom  Basiswert  des
 ersten  Spritepointers  an, acht  Mal  jeweils  um  eins  hochgezählt  und  das  Ergebnis  über  den  Vektor  bei $02/$03 in  die entsprechende  Sprite-Pointer- Adresse
 geschrieben. Beim  ersten  Durchlauf  zeigt
 dieser  Vektor  auf  Adresse $43 F8, wo  sich
 die  Spritepointer  des  ersten  Video-RAM- Bereichs  befinden. Am  Ende  der  Pointerinitialisierung  wird  die  Vektoradresse
 nun  um $0400 erhöht ( auf  Hi-Byte  wird
$04 addiert), damit  beim  nächsten  Durchlauf  die  Zeiger  des  nächsten  Video-RAM- Bereichs  gesetzt  werden.
( Anm. d. Red. : Bitte  wählen  Sie  jetzt  den
 zweiten  Teil  des  IRQ-Kurses  aus  dem  Textmenu)