Magic Disk 64

home to index to html: MD9006-KURSE-INTERRUPTKURS_TEIL_1.html
MD9006-KURSE-INTERRUPTKURS_TEIL_1.koala.png
     DEN C64'er AUSGEREIZT (Teil 1)     
             INTERRUPTKURS              
             -------------              
 Mehr als 8 Sprites gleichzeitig, Grafi-
ken im Rand des Bildschirms, mehr als 16
Farben, skurrile Verfremdung von Bildern
und eine schier endlos  scheinende  Flut
von phantastischen Spezialeffekten gehö-
ren heutzutage einfach zum Standard  der
Programmierkunst auf dem C'64.          
 Wer hat da nicht schon  einmal  mit dem
Gedanken gespielt, sich  selbst  an  die
Programmierung solcher  Wunderdinge  he-
ranzuwagen.                             
 Nimmt man sich die Zeit,  Laufschriften
von Demos durchzulesen oder lauscht  man
der hitzigen Unterhaltung  eingefleisch-
ter Freaks,so stößt man immer wieder auf
Wörter wie  Raster-Routine,  Sideborder-
Sprites, FLD-, FID-, und  DYSP-ROUTINEN,
die man auch mit der größter Anstrengung
in der angebotenen Fachliteratur einfach
nicht finden kann.                      
 Selbstverständlich gibt es Bücher,  die
sich  mit  Interrupteigenschaften  ihres
Gerätes befassen. Sie werden  allerdings
feststellen,daß die meisten dieses Thema
sehr kurz abhandeln  und  in  der  Regel
ausgerechnet da aufhören, wo es  anfängt
spannend zu werden. Das  völlige  Fehlen
geeigneter Literatur liegt einerseits an
der mangelde Kenntnis des  Sachverhaltes
und andererseits an der  relativ  späten
Entdeckung dieser Fähigkeiten des C'64. 
 Es sei hier noch erwähnt, daß  es  sich
bei einigen Effekten die wir  im   Laufe
dieses Kurses behandeln werden,  nur  um
UNBEABSIGTIGTE Nebeneffekte   der  Chips
handelt,die vom Hersteller nicht geplant
waren und offiziell  auch gar nicht exi-
stieren dürften. Das es sie aber dennoch
gibt,haben wir einzig und allein der Ex-
perimentierfreudigkeit  einiger   Freaks
zu verdanken.                           
Leider muß ich zum Verständnis der abge-
druckten  Programme  Grundkennnisse  der
Hardware, der Maschinensprache  und  Er-
fahrung im Umgang  mit  einem  Assembler
oder einem Monitor voraussetzen, denn   
einen IRQ von BASIC aus zu programmieren
ist prinzipiell nicht möglich.          
 ALLGEMEINES ÜBER DIE INTERRUPTTECHNIK! 
 Was ist ein Interrupt? Wie funktioniert
er und wie kann ich  ihn  in meinen Pro-
grammen einsetzen? Dies sind die Fragen,
die in der ersten Folge  des  Interrupt-
kurses beantwortet werden sollen.       
 Was ein Interrupt ist,läßt sich einfach
beantworten. Ein Interrupt ist eine  ge-
steuerte Unterbrechung und bedeutet, daß
spezielle Chips oder Befehle die  Arbeit
des Rechners jederzeit unterbrechen kön-
nen und ihn dazu zwingen,andere Routinen
auszuführen. Insgesamt gibt es VIER ver-
schiedene IRQ-Möglichkeiten, die in sich
selbst noch unterteilt sind.            
  1-RESET                               
  2-BRK (Break) INTERRUPT               
  3-CIA INTERRUPTS (IRQ-CIA und NMI-CIA)
  4-VIDEO INTERRUPT                     
           DER RESET-INTERRUPT          
           -------------------          
 Dieser Interrupt wird gleich  nach  dem
Einschalten des Computers oder  nach dem
drücken einer Resettaste ausgelöst.  Ich
möchte aber darauf hinweisen,daß es sich
hierbei nicht um eine  Unterbrechung  im
eigentlichen Sinne handelt, sondern  wie
der Name schon sagt:                    
          to reset=zurücksetzen         
um einen totalen ABBRUCH eines laufenden
Programmes, gefolgt  von  einem  neuini-
tialisieren des gesamten  Rechners.  Mit
dem RESET als Unterbrechung  wollen  wir
uns im Laufe dieses  Kurses  auch  nicht
weiter beschäftigen.                    
            DER BRK-INTERRUPT           
            -----------------           
 Als nächstes gibt es  die  Möglichkeit,
mit der Hilfe des Assemblerbefehls 'BRK'
einen  Interrupt  durch  den   Prozessor
selbst auszulösen. Dieser Interrupt wird
auch als Software-IRQ bezeichnet.  Da es
sich hierbei gleichzeitig um  einen  der
einfachsten Unterbrechungsarten handelt,
ist sie wie geschaffen, um an einem ein-
fachen Programmbeispiel den gewöhnlichen
Verlauf eines Interrupts zu  demonstrie-
ren. Für den  BRK  sind   die  folgenden
Adressen von Bedeutung.                 
     $0316 Lo-Byte des BREAK-Vektors    
     $0317 Hi-Byte des BREAK-Vektors    
 Diese Register befinden sich im RAM und
sind somit veränderbar.Das folgende Pro-
grammbeispiel soll dies verdeutlichen.  
BRK-Demo:                               
 1000 LDA #$17  Lo-Byte des BRK-Vektors 
 1002 STA $0316 umstellen.              
 1005 LDA #$10  Hi-Byte des BRK-Vektors 
 1007 STA $0317 umstellen.              
 100A BRK       Starten des IRQ         
 --------------------                   
 100B NOP                               
 100C LDA #$0E  Rahmenfarbe rücksetzen  
 100E STA $D020 rücksetzen              
 1011 LDA #$06  Hintergrundfarbe        
 1013 STA $D021 rücksetzen              
 1016 RTS       Rücksprung zu Basic     
 1017 INC $D020 Rahmenfarbe ändern      
 101A LDA $DC01 PORT B auslesen         
 101D CMP #$EF  prüfen ob SPACE gedrückt
 101F BNE LOOP  Nein ?? dann $1017      
 1021 PLA       Y-Reg. vom Stack holen  
 1022 TAY                               
 1023 PLA       X-Reg. vom Stack holen  
 1024 TAX                               
 1025 PLA       Akku vom Stack holen    
 1026 RTI       Interrupt verlassen     
 Wird dieses Programm mit  'SYS  4096'  
gestartet, beginnt sich  die Rahmenfarbe
fortlaufend zu ändern.  Drückt  man  an-
schließend die  SPACE-Taste,  so  meldet
sich der Rechner mit 'READY' wieder.    
Nachdem  wir  unsere  Routine  gestartet
haben, wird als erstes Lo-  und  Hi-Byte
des Break-Vektors (welche Bedeutung jene
Register  im  einzelnen  haben, wird an-
schließend geklärt)auf die Adresse $1017
gerichtet. Der Interrupt wird ausgelöst,
sobald der Prozessor auf  den BRK Befehl
stößt. Was dabei im Rechner vorgeht,läßt
sich in vier Punkte gliedern:           
1.Als erstes wird im STATUSREGISTER  das
  BREAK-FLAG gesetzt, um  dem  Prozessor
  die Art des Interrups mitzuteilen. An-
  schließend wird  Hi- und Lo-Byte   des
  PROGRAMMCOUNTERS  auf den  Stack abge-
  legt, d.h.der Prozessor merkt sich die
  Adresse, an der er den letzten  Befehl
  ausgeführt hat. Das Gleiche  geschieht
  übrigens auch bei einem 'JSR'  Befehl.
  Dies ist sehr wichtig,denn nur so kann
  der Rechner seine Arbeit nach  Beendi-
  gung des Interrups wieder  fortsetzen.
  In unserem Beispiel merkt er sich also
  die Adresse: $100A+$0002=$100C.       
  Das zu der  aktuellen  Unterbrechungs-
  adresse noch der Wert $02  dazuaddiert
  wird,ist eine Außnahme,die bei anderen
  Unterbrechungen nicht vorkommt.       
2.Um die FLAGS zu retten,wird zusätzlich
  noch das komplette STATUSREGISTER  auf
  dem Stack abgelegt.                   
3.Anschließend verzweigt der Rechner in-
  direkt über die Adressen   $FFFE/$FFFF
  in die ROM-Routine bei $FF48.An dieser
  Stelle findet man  folgendes  Programm
  vor.                                  
FF48 PHA         Akku auf Stack retten  
FF49 TXA                                
FF4A PHA         X-Reg.auf Stack retten 
FF4B TYA                                
FF4C PHA         Y-Reg.auf Stack retten 
FF4D TSX         Stackpointer ins X-Reg.
FF4E LDA $0104,X Statusregister in Akku 
FF51 AND #$10    BREAK-Flag prüfen      
FF53 BEQ FF58    nicht gesetzt?Dann FF58
FF55 JMP ($0316) sonst Break-INTERRUPT  
FF58 JMP ($0314) Timer-IRQ              
  Diese Routine entscheidet, ob es  sich
  bei der Art des   Interrups  um  einen
  TIMER- oder, wie in  unserem  Fall, um
  einen BREAK-INTERRUPT handelt. Handelt
  es sich um den Letzteren, dann wird zu
  der Routine verzweigt, auf welche  die
  Register $0316/$0317 zeigen.Da wir nun
  zuvor beide Register auf  die  Adresse
  $1017 gerichtet haben, wird nun unsere
  eigene IRQ-Routine angesprungen. Diese
  macht sich auch  augenblicklich  durch
  ändern der Rahmenfarbe  bemerkbar.    
4.Um das  Interruptprogramm  wieder   zu
  verlassen,  drücken  wir  einfach  die
  Space- Taste. Als erstes  werden   die
  Werte für Akku und die beiden Register
  X und Y vom Stack geholt. Um   den In-
  terrupt endgültig zu beenden, gibt  es
  den Befehl RTI(Return from Interrupt),
  was zu deutsch ungefähr soviel  bedeu-
  tet wie  'Verlassen der Unterbrechung-
  sebene'. Trifft der Prozessor  nun auf
  einen 'RTI' Befehl,  dann  werden  als
  erstes   STATUSREGISTER  und  PROGRMM-
  COUNTER von Stack geholt und  der Pro-
  grammablauf kann an der Adresse  $100c
  fortgesetzt werden.                   
 Im Gegensatz zu anderen IRQ-Arten, bie-
tet der  BRK-INTERRUPT in der Praxis re-
lativ wenige Anwendunggebiete.Man könnte
ihn eigentlich problemlos als Unterpro- 
grammbefehl  einsetzen,  allerdings  ist
dafür der 'JSR' Befehl wesentlich besser
geeignet, da seine Handhabung  nicht  so
umständlich ist. Eine wesentliche  Rolle
spielt der BRK bei Software-Instrumenten
wie z.B. Maschinensprachemonitore.  Hier
werden die beiden  Adressen  $0316/$0317
so umgestellt, daß  sie   als  Register-
Indikatoren dienen.                     
           DER CIA-INTERRUPT            
           -----------------            
 Die folgenden  Interrupt-Typen  sind da
schon wesentlich interresanter.  Hierbei
handelt  es  sich  um sogenannte EXTERNE
Unterbrechungen.   In ihrem C-64 gibt es
drei spezielle Chips,  die aus einem be-
stimmten Grund den Prozessor zwingen die
augenblickliche   Tätigkeit  zu   unter-
brechen  und  eine andere Aufgabe auszu-
führen.  Hierzu gehören die beiden  CIA-
Chips und der Video-Chip.               
 Selbstverständlich geschehen  diese Un-
terbrechungen nicht einfach aus heiterem
Himmel, sondern können vom Programmierer
kontrolliert   und  gezielt   eingesetzt
werden.                                 
   Beim BRK-IRQ konnten wir die Adresse,
an der ein IRQ ausgelöst wird,ganz genau
festlegen. Beim Timer-IRQ ist dies nicht
ganz so einfach, weil  hier  die  Unter-
brechung nicht mehr vom Prozessor selbst
eingeleitet wird sondern von einem Chip,
der gleich zweimal vorhanden ist.Gemeint
ist der 'Complex Interface Adapter',auch
unter der Kurzform CIA bekannt.         
 Der erste der beiden CIAs wird auch als
'IRQ-TIMER' oder'IRQ-CIA' bezeichnet. Er
besitzt die Basisadresse $DC00 und  wird
in erster Linie zur  Verwaltung  einiger
Vorgänge im Betriebsystem benutzt.      
 Den  zweiten  CIA  bezeichnet  man  als
'NMI-TIMER'. Er besitzt die Basisadresse
$DD00  und  wird  außer  zur  Verwaltung
einer event. vorhandenen  RS232 Schnitt-
stelle vom Betriebsystem für  keine  be-
stimmte Aufgabe vorgesehen.             
  Jeder CIA besitzt zwei Intervalltimer,
die aus einem 16-Bit  Zähler (read only)
und einem 16-Bit Zwischenspeicher (write
only) bestehen. Daten, die  in den Timer
geschieben  werden,  landen im Zwischen-
speicher,  während  die  Lesedaten   den
augenblicklichen  Stand  des Zählers an-
geben.  Die  beiden  Timer können sowohl
unabhängig von einander, als auch im Zu-
sammenhang benutzt werden. Die verschie-
denen  Betriebsarten  erlauben  das  Er-
zeugen variabler Zeitverzögerungen.     
 Ein Intervalltimer  ist mit einem Zeit-
laufwerk  vergleichbar,  das kontinuier-
lich rückwärts zählt.  Ist der COUNTDOWN
dieses Zählers abgelaufen,d.h.der Zähler
ist beim Wert Null angelangt,so wird ein
Interrupt ausgelöst.  Diese  Möglichkeit
wird beispielsweise  vom  Betriebssystem
gezielt eingesetzt, um  in  regelmäßigen
Abständen  (jede 1/60 Sekunde)  den nor-
malen Programmablauf zu unterbrechen und
indirekt über die Adressen   $0314/$0315
in eine  ROM-Routine  zu springen.   Auf
diese  Weise  wird die interne Uhr (TI$)
gestellt, die Tastatur abgefragt und das
Blinken des Cursors erzeugt.            
 Da der C64 zwei CIA-Chips besitz,  gibt
es  also insgesammt vier Intervalltimer,
die man völlig unabhängig  von  einander
oder im Zusammenhang einsetzen kann.    
 Das folgende Beispielprogramm  soll die
Arbeitsweise einer  Timer-Unterbrechung,
anhand einer nützlichen  Anwendung  ver-
deutlichen. Wir  wollen  einfach mit dem
Joy-Stick in Port 2 ein  Sprite über den
Bildschirm bewegen. Allerdings soll dies
ausschließlich im Interrupt geschehen.  
1000 SEI       ;IRQ-sperren             
1001 LDX #$01  ;SPRITE Nr.1             
1003 STX $D015 ;einschalten             
1006 STX $D027 ;Farbe = weiß            
1009 LDA #$3F  ;SPRITE DATAS            
100b STA $07F8 ;von $3F*64 = $0FC0 holen
100e LDA #$64  ;X-,und Y-Position von   
1010 STA $D000 ;Sprite Nr.1 auf $64     
1013 STA $D001 ;setzen                  
1016 LDX #$0E  ;Rahmen und              
1008 LDY #$06  ;Hintergrund             
101a STX $D020 ;auf 'blau' setzen       
101d STY $D021                          
1020 LDX #$36  ;Lo-und Hi-byte          
1022 LDY #$10  ;des IRQ-Vektors auf die 
1024 STX $0314 ;Interrupt-Routine       
1027 STY $0315 ;richten                 
102a LDX #$25  ;Lo-und Hi-Byte          
102c LDY #$40  ;von Intervalltimer A    
102e STX $DC04 ;setzen                  
1031 STY $DC05                          
1034 CLI       ;Interrupt erlauben      
1035 RTS       ;Rücksprung zu Basic     
1036 LDA $DC00 ;Joy-Stick Register 2    
1039 LSR       ;prüfen ob Bit 1 gelöscht
103A BCS $103F ;Nein? Dann verzweigen!  
103C DEC $D001 ;sonst Sprite aufwärts   
103F LSR       ;prüfen ob Bit 2 gelöscht
1040 BCS $1045 ;Nein? Dann verzweigen!  
1042 INC $D001 ;sonst Sprite abwärts    
1045 LSR       ;prüfen ob Bit 3 gelöscht
1046 BCS $104B ;Nein? Dann verzweigen!  
1048 DEC $D000 ;sonst Sprite nach links 
104B LSR       ;prüfen ob Bit 4 gelöscht
104C BCS $1051 ;Nein? Dann verzweigen!  
104E INC $D000 ;sonst Sprite nach rechts
1051 JMP $EA31 ;Sprung zum IRQ-Ende!    
 Starten   sie  dieses   Programm    mit
'SYS 4096',  dann  erscheint  ein Sprite
links im Bildschirm und der Rechner mel-
det sich mit 'READY'und einem blinkendem
Cursor wieder.  Außer  einem  Sprite und
einem blauen Bildschirm  läßt  sich  auf
den ersten Blick auch  nichts  ungewöhn-
liches erkennen.  Was  man  jedoch  noch
nicht sehen kann, ist, daß analog zu den
Standardfunktionen  eine  kleine Routine
im  Interrupt  abläuft,  die nur auf ein
Signal vom Joy-Stick wartet.            
 Bewegen Sie einfach mal den Steuerknüp-
pel und Sie werden merken, daß sich  das
Sprite in alle Richtungen  steuern läßt.
Was sie hier sehen  ist, eine  typische,
kontrollierte Unterbrechung, wie  sie zu
Beginn  des  Artikels beschrienen wurde.
Man hat den Eindruck, daß  Eingaben über
die Tastatur und die  Joy-Stick Abfrage,
quasi gleichzeitig ablaufen.  Daß   dies
nicht  der  Fall ist,  werden wir gleich
erkennen.                               
 Die ersten Befehle, bis  einschließlich
Adresse'$101D' initialisieren Sprite und
Hintergrundfarbe und dürften  uns  keine
Schwierigkeit  bereiten.  Gleich  darauf
werden die Vektoren  des Timer-Interrups
umgestellt. Waren bei der Programmierung
des BRK-Interrupts  die  Adressen  $0316
und $0317 von großer Bedeutung,  so sind
es  beim  Timer-Interrupt  die  Adressen
$0314 und $0315.                        
 In unserem  Demo-Programm  richten  wir
diesen Vektor  auf  Adresse  $1036.  Auf
diese  Weise können wir unsere Joy-Stick
Abfrage  einfach in den normalen Verlauf
des Betriebsystems einbinden.           
 Der voreingestellte Wert in $0314/$0315
ist $EA31.  An  dieser  Adresse befindet
sich  eine  Routine,  die  im Normalfall
60mal pro Sekunde angesprungen wird,  um
die Uhr weiterzustellen und die Tastatur
abzufragen. Aus diesem Grund  sollte zum
Abschluß  einer  'seriösen'  IRQ-Routine
ein Sprung nach $EA31 folgen.           
  Somit hätten wir alles geklärt bis auf
die Funktion  der  beiden  CIA  Register
$DC04/$DC05.Zuvor haben wir einiges über
Intervalltimer erfahren  und angedeutet,
daß man damit Zeitverzögerungen erzeugen
kann.                                   
 Gemeint  war  damit,  daß  man die Zeit
zwischen den Interruptanforderungen  be-
liebig verändern kann.                  
 Wem  die  Joy-Stick  Abfrage  bisher zu
langsam war,  der  sollte  einfach einen
kleineren Wert ausprobieren.            
        z.B. $1025 (statt $4025)        
 Nun  ist  die  Joy-Stick  Abfrage  viel
flotter. Alle anderen Funktionen  wurden
aber ebenfalls  beschleunigt  und   dies
ist  in  Bezug  auf die Cursor Steuerung
eher negativ, da man nicht mehr so genau
schreiben kann.                         
 Der Grund für dieses allgemeine  'Speed
up' liegt  daran,  daß  Intervalltimer A
bereits vom Betriebsystem benutzt wird. 
 Nun gibt es  aber die Möglichkeit,  die
Joy-Stick  Abfrage  von  einem   anderem
Intervalltimer  abarbeiten  zu   lassen.
Gleich zu  Beginn haben wir erfahren,das
der  C64  mit  Intervalltimer  reichlich
bestückt  ist,  denn  immerhin  gibt  es
gleich vier verschliedene davon.        
 Weitere  Routinen  finden  Sie  auf der
Rückseite der MAGIC-DISK,    die man mit
Hilfe eines MONITORS einladen kann.     
 "TIMER-DEMO 2"  ist  identisch  mit dem
zuletzt  besprochenen  Listing,  nur das
der  Joy-Stick über Intervalltimer B ab-
gefragt wird.    Zu diesem Zweck, mußten
folgende Befehle hinzugefügt werden.    
 1034 LDX #$80       ;Lo-und Hi-Byte von
 1036 LDY #$10       ;Intervalltimer B  
 1038 STX $DC06      ;setzen            
 103B STY $DC07                         
 103E LDA #%10000011 ;IRQ-Quelle        
 1040 STA $DC0D      ;In ICR schreiben  
 1043 LDA #%00010001 ;Intervalltimer B  
 1045 STA $DC0F      ;starten           
 Im  "TIMER-DEMO 3" haben wir die letzte
Routine  nochmals  erweitert. Intervall-
timer A des  NMI-Timers wurde als dritte
Unterbrechungsanforderung  hinzugezogen,
um ein Musikstück im Interrupt abspielen
zu lassen.  Sie sehen das die Interrupt-
programmierung  eine  Fülle von Möglich-
keiten bietet,  die  wir  für uns nutzen
können.  Wenn  sie  auch noch etwas Zeit
zum Tüfteln investieren,  finden Sie be-
stimmt noch eine Menge weiterer Möglich-
keiten.                                 
 Damit  schließen  wir  zunächst mal die
Einführung  in   die  Unterbrechungspro-
grammierung ab.  Da  wir in  diesen Teil
schon fast alle  IRQ-Arten  angesprochen
haben,  wollen  wir  uns in der nächsten
und allen weiteren Ausgaben nur noch mit
dem   wichtigsten  Typ  des   Interrupts
befassen: dem RASTER-Interrupt.         
                            (IVO HERZEG)



Valid HTML 4.0 Transitional Valid CSS!