home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1989 / 06 / mono.asm < prev    next >
Assembly Source File  |  1989-01-03  |  18KB  |  376 lines

  1. ;------------------------------------------------------------------------;
  2. ;  MONO - TSR designed to make color applications readable on monochrome ;
  3. ;  labtop computers by converting color attributes to monochrome.        ;
  4. ;  Syntax:  MONO [U]                                                     ;
  5. ;  PC Magazine - Michael J. Mefford                                      ;
  6. ;------------------------------------------------------------------------;
  7. BIOS_DATA      SEGMENT AT 40H
  8.                ORG     17H
  9. KBD_FLAG       DB      ?
  10.                ORG     49H
  11. CRT_MODE       DB      ?
  12. CRT_COLS       DW      ?
  13.                ORG     4EH
  14. CRT_START      DW      ?
  15.                ORG     63H
  16. ADDR_6845      DW      ?
  17.                ORG     84H
  18. CRT_ROWS       DB      ?
  19. BIOS_DATA      ENDS
  20.  
  21. _TEXT          SEGMENT PUBLIC 'CODE'
  22.                ASSUME  CS:_TEXT,DS:_TEXT,ES:_TEXT,SS:_TEXT
  23.                ORG     100H
  24. START:         JMP     INITIALIZE
  25.  
  26. ;                 DATA AREA
  27. SIGNATURE      DB      CR,SPACE,SPACE,SPACE,CR,LF
  28. COPYRIGHT      DB      "MONO 1.0 (c) 1989 Ziff Communications Co.",CR,LF
  29. PROGRAMMER     DB      "PC Magazine ",BOX," Michael J. Mefford",CR,LF,LF,"$"
  30.                DB      CTRL_Z
  31.  
  32. CR             EQU     13
  33. LF             EQU     10
  34. CTRL_Z         EQU     26
  35. SPACE          EQU     32
  36. BELL           EQU     7
  37. BOX            EQU     254
  38.  
  39. ALT_SHIFT      EQU     08H
  40. PORT_A         EQU     60H
  41. PORT_B         EQU     61H
  42. COMMAND_PORT   EQU     20H
  43. EOI            EQU     20H
  44. M_SCAN_CODE    EQU     32H
  45.  
  46. OLD_INT_8      DW      ?,?
  47. OLD_INT_9      DW      ?,?
  48.  
  49. COUNTER        DB      0
  50. BUSY_FLAG      DB      0
  51. MODE_BYTE      DB      1
  52.  
  53. ;                   CODE AREA
  54. ;************* INTERRUPT HANDLERS *************;
  55.  
  56. MONO_INT_8     PROC    FAR
  57.                PUSHF
  58.                ADD     CS:COUNTER,64           ;Change attributes every 256/64
  59.                JNB     INT_8_END               ; timer ticks
  60.                PUSH    DS                      ; (approx. every 1/5 second.)
  61.                PUSH    CS
  62.                POP     DS                      ;Point to our data segment.
  63.                CMP     BUSY_FLAG,1             ;Are we already adjusting colors?
  64.                JZ      RESTORE_SEG             ;If yes, exit.
  65.  
  66.                STI                             ;Else, interrupts on.
  67.                CALL    ATTRIBUTES              ;Set the attributes.
  68. RESTORE_SEG:   POP     DS                      ;Restore data segment.
  69.  
  70. INT_8_END:     POPF
  71.                JMP     DWORD PTR CS:OLD_INT_8  ;Service old INT 8 interrupt.
  72. MONO_INT_8     ENDP
  73.  
  74. ;------------------------------------------------;
  75. MONO_INT_9     PROC    FAR
  76.                PUSH    AX                      ;Save some registers.
  77.                PUSHF
  78.                PUSH    DS
  79.  
  80.                MOV     AX,40H                  ;Is the Alt key depressed?
  81.                MOV     DS,AX
  82.                ASSUME  DS:BIOS_DATA
  83.                TEST    KBD_FLAG,ALT_SHIFT
  84.                JZ      INT_9_END               ;If no, exit.
  85.  
  86.                IN      AL,PORT_A               ;Else, is the "M" key pressed?
  87.                CMP     AL,M_SCAN_CODE
  88.                JNZ     INT_9_END               ;If no, exit.
  89.  
  90.                XOR     CS:MODE_BYTE,1          ;Else, toggle active state.
  91.                IN      AL,PORT_B               ;Retrieve Port B.
  92.                OR      AL,80H                  ;Turn bit 7 on to reset.
  93.                JMP     $ + 2                   ;I/O delay.
  94.                OUT     PORT_B,AL               ;Reset KBD.
  95.                AND     AL,NOT 80H              ;Turn bit 7 back off.
  96.                JMP     $ + 2                   ;I/O delay.
  97.                OUT     PORT_B,AL               ;Restore port.
  98.  
  99.                POP     DS                      ;Restore data segment.
  100.                POPF
  101.                CLI                             ;Interrupts off.
  102.                MOV     AL,EOI                  ;Send End Of Interrupt
  103.                OUT     COMMAND_PORT,AL         ; to 8259A PIC.
  104.                POP     AX                      ;Restore AX.
  105.                IRET                            ;Interrupt return.
  106.  
  107. INT_9_END:     POP     DS                      ;No-hot-key exit.
  108.                POPF
  109.                POP     AX
  110.                JMP     DWORD PTR CS:OLD_INT_9  ;Go to old INT 9 interrupt.
  111. MONO_INT_9     ENDP
  112.  
  113. ;-----------------------------------------;
  114. INACTIVE:      RET                             ;Quick exit.
  115.  
  116.                ASSUME  DS:_TEXT
  117. ATTRIBUTES:    CLD                             ;Strings operations forward.
  118.                CMP     MODE_BYTE,0             ;Is attribute mode active?
  119.                JZ      INACTIVE                ;If no, done here; exit.
  120.                MOV     BUSY_FLAG,1             ;Else, flag so non-reentrant.
  121.                PUSH    AX                      ;Save some registers.
  122.                PUSH    DS
  123.                MOV     AX,40H                  ;Point to BIOS data segment.
  124.                MOV     DS,AX
  125.                ASSUME  DS:BIOS_DATA
  126.                MOV     AL,CRT_MODE             ;Retrieve video mode.
  127.                CMP     AL,3                    ;Is it color text mode?
  128.                JBE     SAVE_REG                ;If yes, continue.
  129.                CMP     AL,7                    ;Is it mono text mode?
  130.                JNZ     QUICK_EXIT              ;If no, graphics; exit.
  131.  
  132. SAVE_REG:      PUSH    BX
  133.                PUSH    CX                      ;Else, save some more registers.
  134.                PUSH    DX
  135.                PUSH    DI
  136.                PUSH    ES
  137.  
  138.                MOV     AX,CRT_COLS             ;Retrieve CRT columns.
  139.                MOV     CL,CRT_ROWS             ;Retrieve CRT rows - 1.
  140.                OR      CL,CL                   ;Is in non-zero?
  141.                JNZ     DO_CRT_LENGTH           ;If yes, good value.
  142.                MOV     CL,24                   ;Otherwise, use 25 - 1 row value.
  143. DO_CRT_LENGTH: INC     CL                      ;Adjust row.
  144.                MUL     CL                      ;CRT length = rows * columns.
  145.                MOV     CX,AX                   ;Store in counter.
  146.  
  147.                MOV     DX,ADDR_6845            ;Retrieve 6845 address.
  148.                ADD     DX,6                    ;Convert to Status register.
  149.                MOV     DI,CRT_START            ;Retrieve start of CRT buffer.
  150.                INC     DI                      ;Point to first attribute.
  151.                MOV     AX,0B000H               ;Assume mono card segment.
  152.                CMP     DX,3BAH                 ;Is it?
  153.                JZ      VIDEO_SEG               ;If yes, continue.
  154.                ADD     AX,800H                 ;Else, color card segment.
  155. VIDEO_SEG:     MOV     DS,AX                   ;Set segment registers.
  156.                MOV     ES,AX
  157.                MOV     BX,7007H                ;Inverse video and normal attrib.
  158. ;              Jmp     Short SNOW_CHECK        ;Add this instruction for CGA.
  159.                NOP                             ;NOP bytes to add jump to
  160.                NOP                             ; snow check routine via Debug.
  161.  
  162. NEXT_ATTRIB:   MOV     AL,[DI]                 ;Retrieve an attribute.
  163.                MOV     AH,BH                   ;Assume inverse video.
  164.                TEST    AL,AH                   ;Is background non-zero?
  165.                JNZ     ADD_ATTRIB              ;If yes, use 70h attribute.
  166.                MOV     AH,BL                   ;Else, use 07h attribute.
  167. ADD_ATTRIB:    AND     AL,NOT 77H              ;Mask off all but intensity and
  168.                OR      AL,AH                   ; blinking; add attribute.
  169.                STOSB                           ;Store the attribute.
  170.                INC     DI                      ;Bump pointer past character.
  171.                LOOP    NEXT_ATTRIB             ;Do all attributes.
  172.                JMP     SHORT RESTORE_REG
  173.  
  174. ;---------------------------------------;
  175. ; Snow checking routine for CGA cards.  ;
  176. ;---------------------------------------;
  177. SNOW_CHECK:    MOV     AH,[DI]                 ;Retrieve an attribute.
  178.                MOV     AL,BH                   ;Assume inverse video.
  179.                TEST    AH,AL                   ;Is background non-zero?
  180.                JNZ     ADD_ATTRIB2             ;If yes, use 70h attribute.
  181.                MOV     AL,BL                   ;Else, use 07h attribute.
  182. ADD_ATTRIB2:   AND     AH,NOT 77H              ;Mask off all but intensity and
  183.                OR      AH,AL                   ; blinking; add attribute.
  184.  
  185. HORZ_RET:      IN      AL,DX                   ;Get status.
  186.                TEST    AL,1                    ;Is it low?
  187.                JNZ     HORZ_RET                ;If not, wait until it is.
  188.                CLI                             ;No more interrupts.
  189.  
  190. HWAIT:         IN      AL,DX                   ;Get status.
  191.                TEST    AL,1                    ;Is it high?
  192.                JZ      HWAIT                   ;If no, wait until it is.
  193.                XCHG    AL,AH                   ;Retrieve character; now it's OK
  194.                STOSB                           ; to write to screen buffer.
  195.                STI                             ;Interrupts back on.
  196.                INC     DI                      ;Bump pointer past character.
  197.                LOOP    SNOW_CHECK              ;Do all attributes.
  198.  
  199. RESTORE_REG:   POP     ES                      ;Restore registers.
  200.                POP     DI
  201.                POP     DX
  202.                POP     CX
  203.                POP     BX
  204.                ASSUME  DS:_TEXT
  205. QUICK_EXIT:    POP     DS
  206.                POP     AX
  207.                MOV     BUSY_FLAG,0             ;No longer busy.
  208.                RET
  209.  
  210. ;              DISPOSABLE DATA
  211. ;              ---------------
  212. SYNTAX         LABEL   BYTE
  213. DB             "Syntax:  MONO [U]",CR,LF
  214. DB             "U = uninstall",CR,LF
  215. DB             "Hot key =  Alt M"
  216. DB             CR,LF,LF,"$"
  217.  
  218. NOT_INSTALLED  DB      "MONO not installed",CR,LF,"$"
  219. UNLOAD_MSG     DB      "MONO can't uninstall",CR,LF,"$"
  220. NOT_ENOUGH     DB      "Not enough memory",CR,LF,"$"
  221. ALLOCATE_MSG   DB      "Memory allocation error",CR,LF,BELL,"$"
  222. INSTALL_MSG    DB      "Installed",CR,LF,"$"
  223. UNINSTALL_MSG  DB      "Uninstalled",CR,LF,"$"
  224.  
  225. ;--------------------------------------------------------------------;
  226. ; Search memory for a copy of our code, to see if already installed. ;
  227. ;--------------------------------------------------------------------;
  228. INITIALIZE     PROC    NEAR
  229.                CLD                             ;All string operations forward.
  230.                MOV     BX,OFFSET START         ;Point to start of code.
  231.                NOT     BYTE PTR [BX]           ;Change a byte so no false match.
  232.                XOR     DX,DX                   ;Start at segment zero.
  233.                MOV     AX,CS                   ;Store our segment in AX.
  234. NEXT_PARAG:    INC     DX                      ;Next paragraph.
  235.                MOV     ES,DX
  236.                CMP     DX,AX                   ;Is it our segment?
  237.                JZ      ANNOUNCE                ;If yes, search is done.
  238.                MOV     SI,BX                   ;Else, point to our signature.
  239.                MOV     DI,BX                   ; and offset of possible match.
  240.                MOV     CX,16                   ;Check 16 bytes for match.
  241.                REP     CMPSB
  242.                JNZ     NEXT_PARAG              ;If no match, keep looking.
  243.  
  244. ;------------------------------------------------;
  245. ANNOUNCE:      MOV     DX,OFFSET SIGNATURE     ;Display our signature.
  246.                CALL    PRINT_STRING
  247.                MOV     DX,OFFSET SYNTAX        ;And syntax.
  248.                CALL    PRINT_STRING
  249.  
  250. ;------------------------------------------------;
  251. PARSE:         MOV     SI,81H                  ;Point to command line again.
  252. NEXT_PARSE:    LODSB                           ;Get a byte.
  253.                CMP     AL,CR                   ;Is it CR?
  254.                JZ      INSTALL                 ;If yes, done here.
  255.                AND     AL,5FH
  256.                CMP     AL,"U"                  ;Is it "U" ?
  257.                JNZ     NEXT_PARSE              ;If no, next byte.
  258.                CALL    CK_INSTALLED            ;Else, see if installed.
  259.                MOV     DX,OFFSET NOT_INSTALLED ;If no, exit with error message.
  260.                JZ      MSG_EXIT
  261.                JMP     SHORT UNINSTALL         ;Else, uninstall.
  262.  
  263. ;------------------------------------------------;
  264. INSTALL:       CALL    CK_INSTALLED            ;Check if already installed.
  265.                JZ      CK_AVAILABLE            ;If no, see if enough memory.
  266.                XOR     AL,AL                   ;Else, done.
  267.                JMP     SHORT EXIT              ;Exit with ERRORLEVEL = 0.
  268.  
  269. ;--------------------------------;
  270. ; This is the install procedure. ;
  271. ;--------------------------------;
  272. CK_AVAILABLE:  MOV     BP,OFFSET SYNTAX        ;End of resident portion.
  273.                ADD     BP,15                   ;Round up.
  274.                CMP     BP,DS:[6]               ;TSR > PSP bytes in segment?
  275.                MOV     DX,OFFSET NOT_ENOUGH    ;If yes, exit without installing
  276.                JA      MSG_EXIT                ; with message.
  277.  
  278.                MOV     AX,3508H                ;Else, get INT 8 vector.
  279.                INT     21H
  280.                MOV     OLD_INT_8[0],BX         ;Save old interrupt.
  281.                MOV     OLD_INT_8[2],ES
  282.                MOV     DX,OFFSET MONO_INT_8    ;Install new interrupt.
  283.                MOV     AX,2508H
  284.                INT     21H
  285.  
  286.                MOV     AX,3509H                ;Get INT 9 vector.
  287.                INT     21H
  288.                MOV     OLD_INT_9[0],BX         ;Save old interrupt.
  289.                MOV     OLD_INT_9[2],ES
  290.                MOV     DX,OFFSET MONO_INT_9    ;Install new interrupt.
  291.                MOV     AX,2509H
  292.                INT     21H
  293.  
  294.                MOV     AX,DS:[2CH]             ;Get environment segment.
  295.                MOV     ES,AX
  296.                MOV     AH,49H                  ;Free up environment.
  297.                INT     21H
  298.  
  299.                MOV     DX,OFFSET INSTALL_MSG   ;Display install message.
  300.                CALL    PRINT_STRING
  301.                MOV     DX,BP                   ;Retrieve resident request.
  302.                MOV     CL,4
  303.                SHR     DX,CL                   ;Convert to paragraphs.
  304.                MOV     AX,3100H                ;Return error code of zero.
  305.                INT     21H                     ;Terminate but stay resident.
  306.  
  307. ;-------------------------------------------------------------------;
  308. ; Exit.  Return ERRORLEVEL code 0 if successful, 1 if unsuccessful. ;
  309. ;-------------------------------------------------------------------;
  310. MSG_EXIT:      CALL    PRINT_STRING
  311. ERROR_EXIT:    MOV     AL,1                    ;ERRORLEVEL = 1.
  312. EXIT:          MOV     AH,4CH                  ;Terminate.
  313.                INT     21H
  314.  
  315. ;---------------------------------------------------;
  316. ; This subroutine uninstalls the resident MONO.COM. ;
  317. ;---------------------------------------------------;
  318. UNINSTALL:     MOV     CX,ES                   ;Save segment in CX.
  319.                MOV     AX,3508H                ;Get interrupt 8.
  320.                INT     21H
  321.                CMP     BX,OFFSET MONO_INT_8    ;Has it been hooked by another?
  322.                JNZ     UNINSTALL_ERR           ;If yes, exit with error message.
  323.                MOV     BX,ES
  324.                CMP     BX,CX                   ;Is the segment vector same?
  325.                JNZ     UNINSTALL_ERR           ;If no, exit with error message.
  326.  
  327.                MOV     AX,3509H                ;Get interrupt 9.
  328.                INT     21H
  329.                CMP     BX,OFFSET MONO_INT_9    ;Has it been hooked by another?
  330.                JNZ     UNINSTALL_ERR           ;If yes, exit with error message.
  331.                MOV     BX,ES
  332.                CMP     BX,CX                   ;Is the segment vector same?
  333.                JNZ     UNINSTALL_ERR           ;If no, exit with error message.
  334.  
  335.                MOV     AH,49H                  ;Return memory to system pool.
  336.                INT     21H
  337.                MOV     DX,OFFSET ALLOCATE_MSG
  338.                JC      MSG_EXIT                ;Display message if problem.
  339.  
  340.                MOV     DX,ES:OLD_INT_8[0]      ;Restore old INT 8.
  341.                MOV     DS,ES:OLD_INT_8[2]
  342.                MOV     AX,2508H
  343.                INT     21H
  344.                MOV     DX,ES:OLD_INT_9[0]      ;Restore old INT 9.
  345.                MOV     DS,ES:OLD_INT_9[2]
  346.                MOV     AX,2509H
  347.                INT     21H
  348.  
  349.                PUSH    CS
  350.                POP     DS                      ;Point to our data.
  351.                MOV     DX,OFFSET UNINSTALL_MSG ;Display uninstall message.
  352.                CALL    PRINT_STRING
  353.                OR      AL,AL                   ;Exit with ERRORLEVEL = 0.
  354.                JMP     EXIT
  355.  
  356. UNINSTALL_ERR: MOV     ES,CX                   ;If error, exit
  357.                MOV     DX,OFFSET UNLOAD_MSG    ; with error message.
  358.                JMP     MSG_EXIT
  359. INITIALIZE     ENDP
  360.  
  361. ;-------------------------------------------------------;
  362. ; OUTPUT: ZR = 1 if not installed; ZR = 0 if installed. ;
  363. ;-------------------------------------------------------;
  364. CK_INSTALLED:  MOV     AX,ES
  365.                MOV     BX,CS
  366.                CMP     AX,BX                   ;Compare segments.
  367.                RET
  368.  
  369. ;------------------------------------------------;
  370. PRINT_STRING:  MOV     AH,9
  371. DOS_INT:       INT     21H                     ;Print string via DOS.
  372.                RET
  373.  
  374. _TEXT          ENDS
  375.                END     START
  376.