;------------------------------------------------------------------------;
; Disklite crea una versin de pantalla del indicador luminoso que hay    ;
; en las unidades de disco. La diferencia, no obstante, es que este in-  ;
; dicador luminoso s¢lo permanece  encendido el tiempo que se tarde      ;
; en leer o escribir en el disco. En otras palabras, no permanece encen- ;
; dido mientras el disco gira sin que se produzca actividad alguna       ;
;                                                                        ;
; Este programa intercepta el vector INT 13h, que es el punto de entrada ;
; a la rutina de diskettes de la ROM BIOS. Disklite muestra la letra de  ;
; la unidad en la esquina superior derecha de la pantalla, y restablece  ;
; esta seccin de la pantalla al terminar.                                ;
;------------------------------------------------------------------------;


;------------------------------------------------------------------------;
; Este es el punto de entrada de DISKLITE. Este salta a la rutina de     ;
; inicializacin que se encuentra al final, de modo que podemos quitarla  ;
; de la memoria una vez utilizada.                                       ;
;------------------------------------------------------------------------;
CODE_SEG     SEGMENT
   ASSUME    CS:CODE_SEG, DS:CODE_SEG
   ORG  100h    ;Reservar para el Prefijo de Segmento de Programa del DOS
BEGIN:  JMP  INIT_VECTORS

AUTHOR_STRING        DB     "Disklite instalado, por John Socha"
                     DB     0Dh, 0Ah, '$'


ROM_DISKETTE_INT     DD     ?

DISPLAY_BASE         DW     ?
OLD_DISPLAY_CHARS    DB     4 DUP (?)
DISPLAY_CHARS        DB     'A', 70h, ':', 70h
NUM_FLOPPIES         DB     ?         ;N£mero de unidades de discos flexibles

UPPER_LEFT   EQU     (80 - 2) * 2     ;Desplazamiento al indicador de unidad

;------------------------------------------------------------------------;
; Este procedimiento intercepta llamadas al vector de E/S de diskette    ;
; de la ROM BIOS, y hace varias cosas:                                   ;
;                                                                        ;
;  1. Comprueba si la pantalla est  en modo de texto de 80 columnas      ;
;     de modo que podamos escribir en la pantalla. Disklite no escribe   ;
;     ning£n car cter en la pantalla si no est  en un modo de 80 columnas;
;  2. Muestra la letra de la unidad de disco, "A:" por ejemplo, en la    ;
;     esquina superior derecha de la pantalla.                           ;
;  3. Llama a la rutina ROM BIOS antigua para que haga todo el trabajo.  ;
;  4. Restablece los dos caracteres que haba en la esquina superior de-  ;
;     recha de la pantalla.                                              ;
;------------------------------------------------------------------------;
INTERCEPT_DISKETTE_INT PROC FAR
   ASSUME    CS:CODE_SEG, DS:Nothing
   PUSHF                     ;Salva los indicadores antiguos
   PUSH AX
   PUSH SI
   PUSH DI
   PUSH DS
   PUSH ES
   CALL GET_DISPLAY_BASE     ;Calcula la base de visualizaci¢n de la pantalla
   CALL SAVE_SCREEN          ;Salva los dos caracteres de la esquina superior
                             ; izquierda
   CALL DISPLAY_DRIVE_LETTER ;Muestra la letra de unidad
   POP  ES
   POP  DS
   POP  DI
   POP  SI
   POP  AX
   POPF                      ;Restablece los indicadores antiguos

   PUSHF                     ;Simula una llamada INT
   CALL ROM_DISKETTE_INT     ; a la rutina antigua de la ROM BIOS

   PUSHF                     ;Salva los indicadores devueltos
   PUSH AX
   PUSH SI
   PUSH DI
   PUSH DS
   PUSH ES
   LEA  SI,OLD_DISPLAY_CHARS ;Apunta a la imagen antigua de la pantalla
   CALL WRITE_TO_SCREEN      ;Restablece los dos caracteres de la esquina
                             ; superior derecha
   POP  ES
   POP  DS
   POP  DI
   POP  SI
   POP  AX
   POPF                     ;Recupera los indicadores devueltos
   RET  2                   ;Deja intactos los indicadores de estado
INTERCEPT_DISKETTE_INT ENDP


;------------------------------------------------------------------------;
; Este procedimiento calcula la direcci¢n de segmento del adaptador de   ;
; pantalla que estamos usando                                            ;
;                                                                        ;
; Destruye:  AX                                                          ;
;------------------------------------------------------------------------;
GET_DISPLAY_BASE     PROC   NEAR
   ASSUME    CS:CODE_SEG, DS:Nothing
   INT  11h                 ;Obtiene el indicador de equipo en curso
   AND  AX,30h              ;Aisla los indicadores de pantalla
   CMP  AX,30h              ;Es esta una pantalla monocroma?
   MOV  AX,0B800h           ;Pone para un adaptador de gr fico de color
   JNE  DONE_GET_BASE       ;Gr ficos de color, base ya establecida
   MOV  AX,0B000h           ;Pone para pantalla monocroma
DONE_GET_BASE:
   MOV  DISPLAY_BASE,AX     ;Salva esta base de pantalla
   RET
GET_DISPLAY_BASE     ENDP


;------------------------------------------------------------------------;
; Este procedimiento salva los dos caracteres de la esquina superior     ;
; de la pantalla de modo que podamos restablecerla m s tarde.            ;
;                                                                        ;
; Destruye:  AX, SI, DI, DS, ES                                          ;
;------------------------------------------------------------------------;
SAVE_SCREEN  PROC    NEAR
   ASSUME    CS:CODE_SEG, DS:Nothing
   MOV  SI,UPPER_LEFT            ;Lee los caracteres de la pantalla
   LEA  DI,OLD_DISPLAY_CHARS     ;Escribe los caracteres en la memoria local
   MOV  AX,DISPLAY_BASE          ;Obtiene la direcci¢n de segmento de
                                 ; la pantalla
   MOV  DS,AX
   MOV  AX,CS                    ;Apunta a los datos locales
   MOV  ES,AX
   CLD                           ;Puesto para autoincremento
   MOVSW                         ;Mueve dos caracteres
   MOVSW
   RET
SAVE_SCREEN  ENDP


;------------------------------------------------------------------------;
; Este procedimiento muestra la letra de la unidad en la esquina supe-   ;
; rior derecha de la pantalla                                            ;
;                                                                        ;
; Destruye:  AX, SI                                                      ;
;------------------------------------------------------------------------;
DISPLAY_DRIVE_LETTER PROC   NEAR
   Assume    CS:CODE_SEG, DS:Nothing
   MOV  AL,DL               ;Obtiene el n£mero de unidad
   CMP  AL,80h              ;Es esta una unidad de disco duro?
   JB   DISPLAY_LETTER      ;No, entonces continua
   SUB  AL,80h              ;Convierte al n£mero de disco duro
   ADD  AL,NUM_FLOPPIES     ;Convierte en el n£mero de disco correcto
DISPLAY_LETTER:
   ADD  AL,'A'              ;Convierte esto en una letra de uidad
   LEA  SI,DISPLAY_CHARS    ;Apunta a la nueva imagen del car cter
   MOV  CS:[SI],AL          ;Salva este car cter
   CALL WRITE_TO_SCREEN
   RET
DISPLAY_DRIVE_LETTER ENDP


;------------------------------------------------------------------------;
; Este procedimiento escribe dos caracteres en la esquina superior       ;
; derecha de la pantalla.                                                ;
;                                                                        ;
; A la entrada:      CS:SI  Imagen de pantalla de dos caracteres         ;
; Destruye:  AX, SI, DI, DS, ES                                          ;
;------------------------------------------------------------------------;
WRITE_TO_SCREEN      PROC   NEAR
   ASSUME    CS:CODE_SEG, DS:Nothing
   MOV  DI,UPPER_LEFT       ;Escribe caracteres en la pantalla
   MOV  AX,DISPLAY_BASE     ;Obtiene la direcci¢n de segmento de la pantalla
   MOV  ES,AX
   MOV  AX,CS               ;Apunta a los datos locales
   MOV  DS,AX
   CLD                      ;Puesto para autoincremento
   MOVSW                    ;Mueve dos caracteres
   MOVSW
   RET
WRITE_TO_SCREEN      ENDP

;------------------------------------------------------------------------;
; Este procedimiento encadena Disklite al vector de E/S del diskette     ;
; de modo que podamos supervisar la actividad del disco.                 ;
;------------------------------------------------------------------------;
INIT_VECTORS PROC    NEAR
   ASSUME    CS:CODE_SEG, DS:CODE_SEG
   LEA  DX,AUTHOR_STRING       ;Imprime el nombre del autor
   MOV  AH,9                   ;Visualiza esta secuencia
   INT  21h

   CALL GET_NUM_FLOPPIES       ;Mira a ver cuantas unidades de discos flexibles
                               ; hay instaladas
   MOV  AH,35h                 ;Pide un vector de interrupci¢n
   MOV  AL,13h                 ;Obtiene el vector de INT 13h
   INT  21h                    ;Pone el vector en ES:BX
   MOV  WORD PTR ROM_DISKETTE_INT,BX
   MOV  WORD PTR ROM_DISKETTE_INT[2],ES

   MOV  AH,25h                 ;Pide que se ponga un vector de interrupci¢n
   MOV  AL,13h                 ;Pone el vector INT 13h a DS:DX
   MOV  DX,OFFSET INTERCEPT_DISKETTE_INT
   INT  21h                    ;Pone INT 13h para que apunte a nuestro
                               ; procedimiento

   MOV  DX,OFFSET INIT_VECTORS ;Fin de la parte residente
   INT  27h                    ;Termina pero permanece residente
INIT_VECTORS ENDP


;------------------------------------------------------------------------;
; Este procedimiento determina cuantas unidades de discos flexibles      ;
; l¢gicas hay en el sistema. La siguiente letra de unidad se usar para   ;
; unidades de disco duro.                                                ;
;------------------------------------------------------------------------;
GET_NUM_FLOPPIES     PROC   NEAR
   Assume    CS:CODE_SEG, DS:CODE_SEG
   INT  11h                 ;Obtiene el indicador del equipo
   MOV  CL,6
   SHR  AX,CL               ;Justifica a la derecha el n£mero de floppies
   AND  AL,3                ;Suprime todos los dem s indicadores
   INC  AL                  ;Devuelve 0 para 1 floppy
   CMP  AL,1                ;Es este un sistema con un floppy?
   JA   DONE_GET_FLOPPIES   ;No, entonces este es el n£mero correcto
   MOV  AL,2                ;S¡, hay dos unidades l¢gicas
DONE_GET_FLOPPIES:
   MOV  NUM_FLOPPIES,AL     ;Salva este n£mero
   RET
GET_NUM_FLOPPIES     ENDP


CODE_SEG     ENDS

   END  BEGIN
