;// mike.dld [

VKEY_LSHIFT   = 0000000000000001b
VKEY_RSHIFT   = 0000000000000010b
VKEY_LCONTROL = 0000000000000100b
VKEY_RCONTROL = 0000000000001000b
VKEY_LALT     = 0000000000010000b
VKEY_RALT     = 0000000000100000b
VKEY_CAPSLOCK = 0000000001000000b
VKEY_NUMLOCK  = 0000000010000000b
VKEY_SCRLOCK  = 0000000100000000b

VKEY_SHIFT    = 0000000000000011b
VKEY_CONTROL  = 0000000000001100b
VKEY_ALT      = 0000000000110000b

uglobal
  align 4
  kb_state      dd 0
  ext_code      db 0

  keyboard_mode db 0
  keyboard_data db 0

  altmouseb     db 0
  ctrl_alt_del  db 0

  kb_lights     db 0

align 4
        hotkey_scancodes        rd      256     ; we have 256 scancodes
        hotkey_list             rd      256*4   ; max 256 defined hotkeys
        hotkey_buffer           rd      120*2   ; buffer for 120 hotkeys
endg

iglobal
hotkey_tests    dd      hotkey_test0
                dd      hotkey_test1
                dd      hotkey_test2
                dd      hotkey_test3
                dd      hotkey_test4
hotkey_tests_num = 5
endg

hotkey_test0:
        test    al, al
        setz    al
        ret
hotkey_test1:
        test    al, al
        setnp   al
        ret
hotkey_test2:
        cmp     al, 3
        setz    al
        ret
hotkey_test3:
        cmp     al, 1
        setz    al
        ret
hotkey_test4:
        cmp     al, 2
        setz    al
        ret

hotkey_do_test:
        push    eax
        mov     edx, [kb_state]
        shr     edx, cl
        add     cl, cl
        mov     eax, [eax+4]
        shr     eax, cl
        and     eax, 15
        cmp     al, hotkey_tests_num
        jae     .fail
        xchg    eax, edx
        and     al, 3
        call    [hotkey_tests + edx*4]
        cmp     al, 1
        pop     eax
        ret
.fail:
        stc
        pop     eax
        ret

align 4
irq1:
;       save_ring3_context
;       mov   ax, os_data
;       mov   ds, ax
;       mov   es, ax

       movzx eax,word[0x3004] ; top window process
       movzx eax,word[0xC400+eax*2]
       shl   eax,8
       mov   al,[0x80000+eax+APPDATA.keyboard_mode]
       mov   [keyboard_mode],al

       in    al,0x60
       mov   [keyboard_data],al

; ch = scancode
; cl = ext_code
; bh = 0 - normal key
; bh = 1 - modifier (Shift/Ctrl/Alt)
; bh = 2 - extended code

       mov   ch,al
       cmp   al,0xE0
       je    @f
       cmp   al,0xE1
       jne   .normal_code
   @@:
        mov     bh, 2
        mov     [ext_code], al
        jmp     .writekey
   .normal_code:
        mov     cl, 0
        xchg    cl, [ext_code]
       and   al,0x7F
        mov     bh, 1
   @@: cmp   al,0x2A
       jne   @f
       cmp   cl,0xE0
       je    .writekey
       mov   eax,VKEY_LSHIFT
       jmp   .modifier
   @@: cmp   al,0x36
       jne   @f
       cmp   cl,0xE0
       je    .writekey
       mov   eax,VKEY_RSHIFT
       jmp   .modifier
   @@: cmp   al,0x38
       jne   @f
        mov     eax, VKEY_LALT
        test    cl, cl
        jz      .modifier
        mov     al, VKEY_RALT
        jmp     .modifier
   @@: cmp   al,0x1D
       jne   @f
        mov     eax, VKEY_LCONTROL
        test    cl, cl
        jz      .modifier
        mov     al, VKEY_RCONTROL
        cmp     cl, 0xE0
        jz      .modifier
        mov     [ext_code], cl
        jmp     .writekey
   @@: cmp   al,0x3A
       jne   @f
       mov   bl,4
       mov   eax,VKEY_CAPSLOCK
       jmp   .no_key.xor
   @@: cmp   al,0x45
       jne   @f
        test    cl, cl
        jnz     .writekey
       mov   bl,2
       mov   eax,VKEY_NUMLOCK
       jmp   .no_key.xor
   @@: cmp   al,0x46
       jne   @f
       mov   bl,1
       mov   eax,VKEY_SCRLOCK
       jmp   .no_key.xor
   @@:
       test  ch,ch
       js    .writekey
       movzx eax,ch              ; plain key
       mov   bl,[keymap+eax]
       mov   edx,[kb_state]
       test  dl,VKEY_CONTROL     ; ctrl alt del
       jz    .noctrlaltdel
       test  dl,VKEY_ALT
       jz    .noctrlaltdel
       cmp   ch,53h
       jne   .noctrlaltdel
       mov   [ctrl_alt_del],1
   .noctrlaltdel:
       test  dl,VKEY_CONTROL     ; ctrl on ?
       jz    @f
       sub   bl,0x60
   @@: test  dl,VKEY_SHIFT       ; shift on ?
       jz    @f
       mov   bl,[keymap_shift+eax]
   @@: test  dl,VKEY_ALT         ; alt on ?
       jz    @f
       mov   bl,[keymap_alt+eax]
   @@:
        mov     bh, 0
        jmp     .writekey
.modifier:
        test    ch, ch
        js      .modifier.up
        or      [kb_state], eax
        jmp     .writekey
.modifier.up:
        not     eax
        and     [kb_state], eax
        jmp     .writekey
.no_key.xor:
        mov     bh, 0
        test    ch, ch
        js      .writekey
        xor     [kb_state], eax
        xor     [kb_lights], bl
        call    set_lights

.writekey:
; test for system hotkeys
        movzx   eax, ch
        cmp     bh, 1
        ja      .nohotkey
        jb      @f
        xor     eax, eax
@@:
        mov     eax, [hotkey_scancodes + eax*4]
.hotkey_loop:
        test    eax, eax
        jz      .nohotkey
        mov     cl, 0
        call    hotkey_do_test
        jc      .hotkey_cont
        mov     cl, 2
        call    hotkey_do_test
        jc      .hotkey_cont
        mov     cl, 4
        call    hotkey_do_test
        jnc     .hotkey_found
.hotkey_cont:
        mov     eax, [eax]
        jmp     .hotkey_loop
.hotkey_found:
        mov     eax, [eax+8]
; put key in buffer for process in slot eax
        mov     edi, hotkey_buffer
@@:
        cmp     dword [edi], 0
        jz      .found_free
        add     edi, 8
        cmp     edi, hotkey_buffer+120*8
        jb      @b
; no free space - replace first entry
        mov     edi, hotkey_buffer
.found_free:
        mov     [edi], eax
        movzx   eax, ch
        cmp     bh, 1
        jnz     @f
        xor     eax, eax
@@:
        mov     [edi+4], ax
        mov     eax, [kb_state]
        mov     [edi+6], ax
        jmp     .exit.irq1
.nohotkey:
       cmp   [keyboard_mode],0 ; return from keymap
       jne   .scancode
        test    bh, bh
        jnz     .exit.irq1
        test    bl, bl
        jz      .exit.irq1
        jmp     .dowrite
.scancode:
        mov     bl, ch
.dowrite:
       movzx eax,byte[0xF400]
       cmp   al,120
       jae   .exit.irq1
       inc   eax
       mov   [0xF400],al
       mov   [0xF400+eax],bl

   .exit.irq1:
       mov   [check_idle_semaphore],5

;       mov   al,0x20                  ; ready for next irq
;       out   0x20,al

;       restore_ring3_context
;       iret
        ret

set_lights:
       mov   al,0xED
       call  kb_write
       mov   al,[kb_lights]
       call  kb_write
       ret

;// mike.dld ]