;***************************************************************
;*                                                             *
;* KBEXT.ASM: extend keyboard functions                        *
;* installs itself in the keyboard interrupt                   *
;* valid for TOS 20/11/1985                                    *
;*                                                             *
;* TOS version dependent (marked with **):                     *
;*     address for kbshifts: A5D (TOS 20.06.85 D)              *
;*                           E1B (TOS 20.11.85 GB)             *
;*                           E1B (TOS 06.02.86 D)              *
;*                                                             *
;* Version for GST-Assembler                                   *
;* THIS PROGRAM IS IN THE PUBLIC DOMAIN                        *
;*                                                             *
;********* Roland Waldi *** 2.00-87/07 *************************

          SECTION   MAIN
          RORG      0
          BRA       install
kbint:
          MOVE.L    TOSvec,A0
          JSR       (A0)           ;* jump to TOS routine
          BRA.S     go
timerint:
          MOVE.W    4(A7),D0
          MOVE.W    D0,-(A7)       ;* copy argument
          MOVE.L    TMRvec,A0
          JSR       (A0)           ;* call etv_timer
          ADDQ.L    #2,A7
go:
          MOVE.L    IOrec,A0
          MOVE.L    (A0),A2        ;* get address of io-buffer
          MOVE.W    8(A0),D1       ;* tail index
          CMP.W     OLDtail,D1     ;* test if changed
          BEQ.S     rturn
          LEA       OLDtail,A1
          MOVE.W    D1,(A1)        ;* save tail index at OLDtail
          MOVE.B    $E1B,D2        ;* get kbshifts (** TOS dependent **)
          BTST      #3,D2          ;* ALT set?
          BEQ.S     rturn          ;* if 0, return
          MOVE.W    0(A2,D1.W),D0  ;*
          AND.W     #$7F,D0        ;* key code
          LEA       ALTtabl,A1     ;* get translation table
          AND.B     #$13,D2        ;* test SHIFT l/r and CapsL
          BEQ.S     goon           ;* if none set
          ADDA.L    #128,A1        ;* use second table (ALT&SHIFT)
goon:
          MOVE.B    0(A1,D0.W),D0  ;* translate
          MOVE.W    D0,2(A2,D1.W)  ;* store char code
rturn:
          RTS
TOSvec:
          DC.L      0
TMRvec:
          DC.L      0
IOrec:
          DC.L      0
OLDtail:
          DC.W      -1
;*
;* here are the keyboard tables for normal, SHIFT,
;*                                  and normal with CAPS LOCK
;*                                  ALT, ALT&SHIFT
;*
;* to change the keyboard layout, use the "normal" table as a
;* guide for the keys (the layout is for a UK keyboard)
;* and insert the ATARI/ASCII codes of the characters you want.
;* NOTE:
;* with ALT, the positions 02 ('1') ... 09 ('8') move to
;* 78 ... 7F,
;* and 0A ('9') ... 0D ('=') to 00 ... 03 (actually 80 ... 83)
;* these rearrangements are done BY THE PROGRAM
;*
normal:
          DC.B      $00,$1B,'1','2','3','4','5','6' ;* 00 Esc
          DC.B      '7','8','9','0','-','=',$08,$09 ;* 08 BS,TAB
          DC.B      'q','w','e','r','t','y','u','i' ;* 10
          DC.B      'o','p',$5B,$5D,$0D,$00,'a','s' ;* 18 brackets,CR
          DC.B      'd','f','g','h','j','k','l',';' ;* 20
          DC.B      $27,'`',$00,'#','z','x','c','v' ;* 28 '
          DC.B      'b','n','m',',','.','/',$00,$00 ;* 30
          DC.B      $00,' ',$00,$00,$00,$00,$00,$00 ;* 38
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 40
          DC.B      $00,$00,'-',$00,$00,$00,'+',$00 ;* 48
          DC.B      $00,$00,$00,$7F,$00,$00,$00,$00 ;* 50 DEL
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 58
          DC.B      $5C,$00,$00,'(',')','/','*','7' ;* 60 \
          DC.B      '8','9','4','5','6','1','2','3' ;* 68
          DC.B      '0','.',$0D,$00,$00,$00,$00,$00 ;* 70 Enter
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 78
shiftblk:
          DC.B      $00,$1B,'!','@','#','$','%','^' ;* 00
          DC.B      '&','*','(',')','_','+',$08,$09 ;* 08
          DC.B      'Q','W','E','R','T','Y','U','I' ;* 10
          DC.B      'O','P','{','}',$0D,$00,'A','S' ;* 18
          DC.B      'D','F','G','H','J','K','L',':' ;* 20
          DC.B      '"',$BA,$00,'~','Z','X','C','V' ;* 28
          DC.B      'B','N','M','<','>','?',$00,$00 ;* 30
          DC.B      $00,' ',$00,$00,$00,$00,$00,$00 ;* 38
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 40
          DC.B      $00,$00,'-',$00,$00,$00,'+',$00 ;* 48
          DC.B      $00,$00,$00,$7F,$00,$00,$00,$00 ;* 50
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 58
          DC.B      '|',$00,$00,'(',')','/','*','7' ;* 60
          DC.B      '8','9','4','5','6','1','2','3' ;* 68
          DC.B      '0','.',$0D,$00,$00,$00,$00,$00 ;* 70
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 78
capslock:
          DC.B      $00,$1B,'1','2','3','4','5','6' ;* 00
          DC.B      '7','8','9','0','-','=',$08,$09 ;* 08
          DC.B      'Q','W','E','R','T','Y','U','I' ;* 10
          DC.B      'O','P',$5B,$5D,$0D,$00,'A','S' ;* 18
          DC.B      'D','F','G','H','J','K','L',';' ;* 20
          DC.B      $27,'`',$00,'#','Z','X','C','V' ;* 28
          DC.B      'B','N','M',',','.','/',$00,$00 ;* 30
          DC.B      $00,' ',$00,$00,$00,$00,$00,$00 ;* 38
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 40
          DC.B      $00,$00,'-',$00,$00,$00,'+',$00 ;* 48
          DC.B      $00,$00,$00,$7F,$00,$00,$00,$00 ;* 50
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 58
          DC.B      $5C,$00,$00,'(',')','/','*','7' ;* 60
          DC.B      '8','9','4','5','6','1','2','3' ;* 68
          DC.B      '0','.',$0D,$00,$00,$00,$00,$00 ;* 70
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 78
ALTtabl:
          DC.B      $00,$1B,$BB,$AB,$9C,$AC,$BF,$A9 ;* 78
          DC.B      $BD,$F9,$F8,$B2,$9E,$F0,$00,$00 ;* 00
          DC.B      $91,$C2,$89,$D5,$E7,$98,$81,$8B ;* 10
          DC.B      $94,$E3,$C7,$F5,$00,$00,$84,$9E ;* 18
          DC.B      $EB,$9F,$C4,$C6,$C0,$CC,$CD,$C8 ;* 20
          DC.B      $CA,$CB,$00,$86,$B0,$B1,$87,$DE ;* 28
          DC.B      $C3,$A4,$E6,$DB,$DC,$B3,$00,$00 ;* 30
          DC.B      $00,$20,$00,$00,$00,$00,$00,$00 ;* 38
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 40
          DC.B      $00,$00,$D9,$00,$00,$00,$D8,$00 ;* 48
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 50
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 58
          DC.B      $B4,$00,$00,$E0,$E1,$ED,$EF,$A1 ;* 60
          DC.B      $8C,$8D,$A0,$83,$85,$82,$88,$8A ;* 68
          DC.B      $E9,$E5,$00,$00,$00,$00,$00,$00 ;* 70
          DC.B      $BB,$AB,$9C,$AC,$BF,$A9,$BD,$F9 ;* 78
;* ALT & SHIFT
          DC.B      $00,$1B,$AD,$B9,$DD,$9B,$F6,$AA ;* 00
          DC.B      $BE,$FA,$A6,$A7,$F7,$F1,$00,$00 ;* 08
          DC.B      $92,$D6,$EE,$D4,$D3,$9D,$9A,$EC ;* 10
          DC.B      $99,$BC,$CF,$F4,$00,$00,$8E,$E4 ;* 18
          DC.B      $C5,$CE,$E2,$C9,$C1,$D1,$D2,$D3 ;* 20
          DC.B      $D4,$FF,$00,$8F,$B7,$B8,$80,$FB ;* 28
          DC.B      $DF,$A5,$D0,$F3,$F2,$A8,$00,$00 ;* 30
          DC.B      $00,$20,$00,$00,$00,$00,$00,$00 ;* 38
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 40
          DC.B      $00,$00,$DA,$00,$00,$00,$D7,$00 ;* 48
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 50
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 58
          DC.B      $B5,$00,$00,$AE,$AF,$E8,$B6,$A2 ;* 60
          DC.B      $93,$95,$A3,$96,$97,$90,$FD,$FE ;* 68
          DC.B      $EA,$FC,$00,$00,$00,$00,$00,$00 ;* 70
          DC.B      $00,$00,$00,$00,$00,$00,$00,$00 ;* 78
pglength:
          DC.L      0
install:
          MOVEA.L   4(A7),A5       ;* basepage
          LEA       pglength(PC),A0
          LEA       install(PC),A1
          MOVE.L    A1,D0
          SUB.L     A5,D0          ;* calculate length
          MOVE.L    D0,(A0)
          MOVE.L    D0,-(A7)       ;* length
          MOVE.L    A5,-(A7)       ;* start
          CLR.W     -(A7)
          MOVE.W    #$4A,-(A7)
          TRAP      #1             ;* SETBLOCK, reserve storage
          LEA       12(A7),A7
          CLR.W     -(A7)          ;* read file DEFAULT.KBD
          PEA       file1(PC)
          MOVE.W    #$3D,-(A7)     ;* open
          TRAP      #1
          ADDQ.L    #8,A7
          TST.W     D0
          BMI.S     nodefault
          PEA       normal(PC)     ;* table address for read
          MOVE.L    #384,-(A7)     ;* length
          MOVE.W    D0,-(A7)       ;* handle 
          MOVE.W    #$3F,-(A7)     ;* read
          TRAP      #1
          LEA       12(A7),A7
          MOVE.W    handle(PC),-(A7)
          MOVE.W    #$3E,-(A7)     ;* close
          TRAP      #1
          ADDQ.L    #4,A7
nodefault:
          CLR.W     -(A7)          ;* read file ALT.KBD
          PEA       file2(PC)
          MOVE.W    #$3D,-(A7)     ;* open
          TRAP      #1
          ADDQ.L    #8,A7
          TST.W     D0
          BMI.S     noaltfile
          LEA       handle(PC),A0  ;* file handle
          MOVE.W    D0,(A0)
          PEA       ALTtabl(PC)    ;* table address for read
          MOVE.L    #256,-(A7)     ;* length
          MOVE.W    D0,-(A7)       ;* handle 
          MOVE.W    #$3F,-(A7)     ;* read
          TRAP      #1
          LEA       12(A7),A7
          MOVE.W    handle(PC),-(A7)
          MOVE.W    #$3E,-(A7)     ;* close
          TRAP      #1
          ADDQ.L    #4,A7
noaltfile:
          LEA       ALTtabl(PC),A0 ;* rearrange ALT-Codes
          MOVE.L    $02(A0),$78(A0)
          MOVE.L    $06(A0),$7C(A0)
          MOVE.L    $0A(A0),$00(A0)
          MOVE.L    $082(A0),$0F8(A0) ;* same for ALFT SHIFT
          MOVE.L    $086(A0),$0FC(A0)
          MOVE.L    $08A(A0),$080(A0)
          MOVE.W    #1,-(A7)
          MOVE.W    #14,-(A7)
          TRAP      #14            ;* get iorec(1)
          ADDQ.L    #4,A7
          LEA       IOrec(PC),A0
          MOVE.L    D0,(A0)        ;* save pointer to kbd-iorec
          PEA       capslock(PC)   ;* CapsL
          PEA       shiftblk(PC)   ;* shifted
          PEA       normal         ;* unshifted
          MOVE.W    #16,-(A7)
          TRAP      #14            ;* XBIOS keytbl(,,)
          ADDA.L    #14,A7
          MOVE.W    #34,-(A7)
          TRAP      #14            ;* Kbdvbase()
          ADDQ.L    #2,A7
          MOVE.L    D0,A1          ;* A1 = addr(kbdvbase)
          LEA       TOSvec,A0
          MOVE.L    32(A1),(A0)    ;* save interrupt routine address
          LEA       kbint,A0
          MOVE.L    A0,32(A1)      ;* install new interrupt vector
          CLR.L     -(A7)
          MOVE.W    #$20,-(A7)
          TRAP      #1             ;* Super
          ADDQ.L    #6,A7
          LEA       TMRvec,A0
          MOVE.L    $400,(A0)      ;* save etv_timer routine address
          LEA       timerint,A0
          MOVE.L    A0,$400        ;* install new interrupt vector
          MOVE.L    D0,-(A7)
          MOVE.W    #$20,-(A7)
          TRAP      #1
          ADDQ.L    #6,A7
          CLR.W     -(A7)          ;* return code
          MOVE.L    pglength,-(A7) ;* program length
          MOVE.W    #$31,-(A7)     ;* Ptermres
          TRAP      #1             ;* reserve storage and end
          RTS                      ;* never reached
handle:   DC.W      0
file1:    DC.B      $5C,'A','U','T','O',$5C
          DC.B      'D','E','F','A','U','L','T','.'
          DC.B      'K','B','D',$00
file2:    DC.B      $5C,'A','U','T','O',$5C
          DC.B      'A','L','T','.'
          DC.B      'K','B','D',$00
          END
