interrupt KeyboardInterrupt()
{
 jmp short $+5
 DB 'D','I','N'

 // Эмулируем прерывание
 $pushf
 $CS:
 CALL FAR OldKeyboardInterrupt

 // Сохраняем флаги
 $pushf
  // Сохраняем все регистыры
  $pushad
   // Сохраняем сегмент данных DS
   push DS
    // Устанавливаем DS на CS для адресации
    DS=CS;

    // Если расширенный скан-код 0E1h, то надо считать вордовское значение
    // из порта 60h
    IF (ExtendedKey==0E1h) in AX,60h
    // Считываем сканкод из порта клавы
    in AL,60h

    IF (ExtendedKey!=0)&&(ExtendedSwitch==FALSE) ExtendedKey=0;
    ELSE{
       IF (AL==0E0h)||(AL==0E1h) ExtendedKey=AL;
       ELSE{
          BL=ExtendedSwitch;
          IF (ExtendedKey==BL){
             IF (AL==sw)&&(downed==FALSE){
                push ES
                 ES=0;
                 tics=ESDWORD[46ch];
                 downed=TRUE;
                pop ES
             }
             ELSE IF (AL-128==sw){
                push ES
                 ES=0;
                 EAX=ESDWORD[46ch]-tics;
                pop ES
                IF (EAX<=2) rus=1-rus; //AL=rus+48; int 29h;}
                // Установка цвета бордюра
                IF (rus==TRUE) BH=BorderColor; ELSE BH=0; AX=1001h; int 10h
                downed=FALSE;
             }
          }
          ExtendedKey=0;
       }
    }

   // Восстанавливаем сегмент данных
   pop DS
  // Восстанавливаем регистры
  $popad
 // Восстанавливаем флаги
 $popf
}

interrupt Clicker()
{
 // Сохраняем флаги
 $pushf
 IF (AH==10h)||(AH==0){
    // Восстанавливаем флаги
    $popf
    // Эмулируем прерывание
    $pushf
    $CS:
    call far OldInt16h
 }
 ELSE{
    // Восстанавливаем флаги
    $popf
    // Прыгаем на старый вектор прерывания, флаги сохранять не надо
    $CS:
    jmp far OldInt16h
 }
 // Сохраняем флаги
 $pushf
  // Сохраняем сегмент данных DS
  push DS
   // Сохраняем ES
   push ES
   // Устанавливаем DS на CS
   push CS pop DS
    // Сохраняем SI
    push SI
     IF (rus==TRUE){
        SI=AH;
         ES=40h;
         IF (SI>=71)&&(SI<=83);
         ELSE IF (AL>=' ')&&(AL<='~'){
            push BX
             BX=ESWORD[17h];
             IF (BX&1!=0)||(BX&2!=0) AL=shiftkey[SI];
             ELSE IF (BX&40h!=0){
                IF (AL>='>')&&(AL<='}') AL=shiftkey[SI];
                ELSE IF (AL==',')||(AL=='.')||(AL==';')||(AL==39) AL=shiftkey[SI];
                ELSE AL=key[SI];
             }
             ELSE AL=key[SI];
            pop BX
            AH=0;
         }
     }
     ELSE{push AX,BX AX=1001h; BH=0; int 10h pop BX,AX}
    // Восстанавливаем SI
    pop SI
   // Восстанавливаем ES
   pop ES
  // Восстанавливаем сегмент данных DS
  pop DS
 // Восстанавливаем флаги
 $popf
}

interrupt VideoFont()
{
 // Сохраняем флаги
 $pushf
 IF (AH==0)/*||(AH==12h)*/||(AX==1C02h){
    // Восстанавливаем флаги
    $popf
    // Эмулируем прерывание
    $pushf
    $CS:
    call far OldInt10h
 }ELSE{
    // Восстанавливаем флаги
    $popf
    // Прыгаем на старый обработчик прерывания
    $CS:
    jmp far OldInt10h
 }
 // Сохраняем флаги
 $pushf
  // Сохраняем регистры
  $pusha
   // Сохраняем ES и DS
   push ES,DS
    // Устанавливаем DS на CS для адресации к переменным
    DS=CS;

    // Узнаем какой это режим - графический или текстовый
    outp(06h,03CEh);
    VideoModeStatusByte=inp(3CFh);

    $push ES,FS,BP
     // Устанавливаем ES на сегмент данных для установки фонта
     ES=DS;
     // Если это графический...
     IF (VideoModeStatusByte&1){
        IF (VideoModeStatusByte&1100b!=1100b){
           // Устанавливаем графический фонт
           AX=1120h; $int 10h
        }
     }ELSE{
        // Устанавливаем FS для адресации к данным биоса
        FS=40h;

        // Считываем количество байт в символе (высота символа)
        BH=FSBYTE[85h];

        // По количеству байт устанавливаем BP на адрес нужного фонта
        IF (BH==8) BP=#font8x8;
        ELSE IF (BH==14) BP=#font8x14;
        ELSE BP=#font8x16;

        // Устанавливаем и активизируем текстовый фонт
        AX=1110h; BL=0; CX=256; DX=0; int 10h
     }
    $pop BP,ES,FS

    // Устанавливаем цвет бордюра
    IF (rus==TRUE) BH=BorderColor; ELSE BH=0; AX=1001h; int 10h

   // Восстанавливаем DS и ES
   pop DS,ES
  // Восстанавливаем регистры
  $popa
 // Восстанавливаем флаги
 $popf
}


interrupt AlreadyInstall()
{
 // Сохраняем флаги
 $pushf
  IF (AH==0E8h) AL=0;
  ELSE IF (AH==0E9h) AX=CS;
  ELSE{
    // Восстанавливаем флаги
    $popf
    // Прыгаем на старый обработчик прерывания
    $CS:
    JMP FAR OldInt2fh
  }
 // Восстанавливаем флаги
 $popf
}
