; ---------------------------------------------------------------------
;
;      The official Kickstart-game, part one !
;
;      Code and Comments by Martin Silbernagl 29/04/1988.
;
; ---------------------------------------------------------------------


INTREQ         EQU     $DFF09C         ; ab hier Hardware Register
INTENA         EQU     $DFF09A
INTENAR        EQU     $DFF01C
COLOR00        EQU     $DFF180
VHPOSR         EQU     $DFF006

CIAA_PRA       EQU     $BFE001
CIAA_SDR       EQU     $BFEC01
CIAA_ICR       EQU     $BFED01
CIAA_CRA       EQU     $BFEE01
CIAA_CRB       EQU     $BFEF01

CIAB_CRA       EQU     $BFDE00
CIAB_CRB       EQU     $BFDF00


START:
       MOVEM.L D0-D7/A0-A6,-(A7)       ; Alle Register auf den Stack legen

       MOVEQ   #61,D0                  ; Schleife 62 mal durchlaufen
       LEA     PAGE0,A0                ; Basis des Zwischenspeichers nach A0
       LEA     8,A1                    ; Basis der Vektorentabelle nach A1
LOOP1: MOVE.L  (A1)+,(A0)+             ; jeweils einen Vektor kopieren
       DBRA    D0,LOOP1                ; D0=-1? Wenn nicht, dann loop1

MAIN:
       MOVE.L  #MAIN,$0020             ; MAIN to Priv._Viol._Vektor
       MOVE.W  #$2700,SR               ; Supervisor=1, Interruptlevel=7
       ADDA.L  #6,A7                   ; A7 auf alten Inhalt zuruecksetzen

       MOVE.L  A7,ADR7                 ; Inhalt von A7 zwischenspeichern
       LEA     STACK,A7                ; Supervisor-Stackptr. neu setzten

       MOVE.L  #PORTS,$68              ; Vektor Int.-Level 2 auf PORTS umbiegen
       MOVE.W  INTENAR,INTENA_BUF      ; Interrrupt-Register zwischenspeichern
       MOVE.W  #$7fff,INTENA           ; Alle Ints. ausschalten
       MOVE.W  #$C008,INTENA           ; PORTS-Int. erlauben
       MOVE.B  #$88,CIAA_ICR           ; SP Interrupt des CIA_A erlaubt
       MOVE.W  #$2000,SR               ; Supervisor=1, Interruptlevel=0

MAIN_LOOP:
       MOVE.W  VHPOSR,COLOR00          ; Hier steht spaeter das Hauptpgm.
MAIN_JMP:
       JMP     MAIN_LOOP               ; Hauptschleife



; ---------------------------------------------------------------------
;
; Ab hier wird das Betriebssystem (exec usw.) wieder eingeschaltet.
;
; ---------------------------------------------------------------------

ENDING:
       MOVE.W  #$2700,SR               ; auf hoechste Int. Ebene setzen
       ORI.W   #$8000,INTENA_BUF       ; Set-Bit im Zwischenspeicher setzen
       MOVE.W  #$7fff,INTENA           ; alle Ints. verbieten
       MOVE.W  INTENA_BUF,INTENA       ; alte Interrupts setzen

       MOVEQ   #61,D0                  ; 62 Werte kopieren
       LEA     PAGE0,A0                ; Basis des Zwischenspeichers nach A0
       LEA     8,A1                    ; Basis der Vektorentabelle nach A1
LOOP2:
       MOVE.L  (A0)+,(A1)+             ; jeweils einen Vektor kopieren
       DBRA    D0,LOOP2                ; D0=-1? Wenn nicht, dann loop2

       MOVEA.L ADR7,A7                 ; alten Stackpointer wieder holen

       MOVE.W  #$0000,SR               ; Supervisor=0, Interruptlevel=0
       MOVEM.L (A7)+,D0-D7/A0-A6       ; Alle Register vom Stack
       RTS                             ; Und das Pgm beenden



; ---------------------------------------------------------------------
;
; Die Routine Ports wird angesprungen, wenn der CIA_A einen Interrupt
; fordert. Dies kann unter anderem dann geschehen, wenn von der Tas-
; tatur ein Byte gesendet wird.
;
; ---------------------------------------------------------------------

PORTS:                                 ; Server von Interrupt-Level 2
       MOVE.W  #$0008,INTREQ           ; Interrupt-Bit wieder zuruecksetzen
       MOVEM.L D0-D2/A0,-(A7)          ; D0-D2 und A0 auf den Stack

       MOVE.B  CIAA_ICR,D2             ; Inhalt des Interrupt Controllers
       BTST    #3,D2                   ; SP Bit gesetzt ?
       BEQ     END_PORTS               ; wenn nicht, kein Interrupt fuer uns
       MOVE.B  CIAA_SDR,D0             ; Inhalt Serielles Datenregister
       ORI.B   #64,CIAA_CRA            ; Serial-Port auf Output setzen
       MOVEQ   #60,D1                  ; Schleife 60 mal durchlaufen
KBRD_LOW:
       CLR.B   CIAA_SDR                ; Auf Null setzen
       DBRA    D1,KBRD_LOW             ; Schleife machen
       NOT.B   D0                      ; Erhaltene Daten invertieren
       ROR.B   #1,D0                   ; Bits in richtige Reihenfolge bringen
       AND.B   #$BF,CIAA_CRA           ; Serial-Port auf Input setzen

       CMP.B   #$F9,D0                 ; Letzter Keycode schlecht ?
       BNE.S   LAST_GOOD               ; wenn nicht, dann nach last_good
       BRA     END_PORTS               ; sonst den Interrupt beenden
LAST_GOOD:

       TST.B   PASS_CNT                ; Password schon eingegeben ?
       BEQ.S   PLUS_PASS               ; wenn ja, dann nach plus_pass
       CMP.B   #$7f,D0                 ; Eine losgelassene Taste ?
       BHI     REGULAR_KEYS            ; wenn ja, dann nach regular_keys
       MOVEA.L PASS_PTR,A0             ; Zeiger auf akt. Buchstaben
       CMP.B   (A0)+,D0                ; gedr. Taste gleich (A0) ?
       BEQ.S   NEXT_OK                 ; wenn ja, dann nach next_ok
       MOVE.B  #14,PASS_CNT            ; wenn nicht, Zaehler zuruecksetzen
       MOVE.L  #PASS_WORD,PASS_PTR     ; Zeiger zuruecksetzen
       BRA     REGULAR_KEYS            ; und beenden
NEXT_OK:
       MOVE.L  A0,PASS_PTR             ; neue Adr. zurueckschreiben
       SUBQ.B  #1,PASS_CNT             ; Zaehler erniedrigen
       BNE     END_PORTS               ; Zaehler versch. Null -> end_ports

PLUS_PASS:
       LEA     PASS_KEY_TABLE,A0       ; Adresse der Sprungtabelle nach A0
       MOVEQ   #0,D1                   ; D1 auf 32-Bit 0 setzen
       MOVE.B  D0,D1                   ; Key-Code kopieren
       LSL.W   #2,D1                   ; Inhalt von D1 vervierfachen
       MOVEA.L 0(A0,D1),A0             ; Zeiger auf Adresse der Routine
       JMP     (A0)                    ; zur berechneten Key-Routine springen

L:                                     ; kuerzeres Label fuer REGULAR_KEYS
       NOP                             ; steht nur zur Zierde hier
REGULAR_KEYS:
       LEA     KEY_TABLE,A0            ; Adresse der Sprungtabelle nach A0
       MOVEQ   #0,D1                   ; D1 auf 32-Bit 0 setzen
       MOVE.B  D0,D1                   ; Key-Code kopieren
       LSL.W   #2,D1                   ; Inhalt von D1 vervierfachen
       MOVEA.L 0(A0,D1),A0             ; Zeiger auf Adresse der Routine
       JMP     (A0)                    ; zur berechneten Key-Routine springen

K:                                     ; kuerzeres Label fuer END_PORTS
       NOP                             ; steht auch hier nur zur Zierde
END_PORTS:
       MOVEM.L (A7)+,D0-D2/A0          ; D0-D2 und A0 vom Stack holen
       RTE                             ; return to where we came from

PASS_PTR:      DC.L    PASS_WORD
PASS_CNT:      DC.B    14
SHIFT:         DC.B    0
PASS_WORD:
       DC.B    $13,$12,$20,$22,$40,$27,$17,$33,$27,$21,$14,$20,$13,$14
               ; r   e   a   d       k   i   c   k   s   t   a   r   t
       ALIGN
PASS_KEY_TABLE:
       DC.L    L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L ;  0-23
       DC.L    L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L ; 24-47
       DC.L    L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L ; 48-71
       DC.L    L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,Z ; 72-95
       DC.L    L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L ; 96-119
       DC.L    L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L ;120-143
       DC.L    L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L ;144-167
       DC.L    L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L ;168-191
       DC.L    L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L ;192-215
       DC.L    L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L ;216-239
       DC.L    L,L,L,L,L,L,L,L,L,L,L,L,L,L,L,L                 ;240-255
KEY_TABLE:
       DC.L    K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K ;  0-23
       DC.L    K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K ; 24-47
       DC.L    K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,T,K,K ; 48-71
       DC.L    K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K ; 72-95
       DC.L    R,R,R,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K ; 96-119
       DC.L    K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K ;120-143
       DC.L    K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K ;144-167
       DC.L    K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K ;168-191
       DC.L    K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K ;192-215
       DC.L    K,K,K,K,K,K,K,K,U,U,U,K,K,K,K,K,K,K,K,K,K,K,K,K ;216-239
       DC.L    K,K,K,K,K,K,K,K,K,K,K,K,K,K,K,K                 ;240-255



; ---------------------------------------------------------------------
;
; Ab hier stehen die Routinen, die durch einen Tastendruck aufgerufen
; werden, auch wenn noch kein Password eingegeben wurde.
;
; ---------------------------------------------------------------------

T:                                     ; Wird bei esc (=$45) aufgerufen
       MOVE.L  #ENDING,MAIN_JMP+2      ; Main_loop umbiegen
       JMP     END_PORTS               ; und beenden

R:                                     ; Wird bei Shift down aufgerufen
       ADDQ.B  #1,SHIFT                ; Shift-Zaehler um eins erhoehen
       JMP     END_PORTS               ; und zurueck

U:                                     ; Wird bei Shift release aufgerufen
       SUBQ.B  #1,SHIFT                ; Shift-Zaehler um eins erniedrigen
       JMP     END_PORTS               ; und zurueck



; ---------------------------------------------------------------------
;
; Ab hier stehen die Routinen, die durch einen Tastendruck aufgerufen
; werden, aber nur wenn das Password eingegeben wurde.
;
; ---------------------------------------------------------------------

Z:                                     ; wird durch Help down aufgerufen
       BCHG    #1,CIAA_PRA             ; Led-Status umschalten
       JMP     END_PORTS               ; Ruecksprung



; ---------------------------------------------------------------------
;
; Ab hier stehen der Stack, unsere Variablen und Zwischenspeicher (Buffer)
;
; ---------------------------------------------------------------------

STACK_END:     DS.W    2048            ; neuer Stack-Speicher
STACK:         DC.W    0               ; oberes Stack-Ende
ADR7:          DC.L    0               ; Zwischenspeicher fuer A7
PAGE0:         DS.L    62              ; Zwischenspeicher der "Zeropage"
INTENA_BUF:    DC.W    0               ; Zwischenspeicher des Int.-Registers

       END
