home *** CD-ROM | disk | FTP | other *** search
/ Piper's Pit BBS/FTP: ibm 0000 - 0009 / ibm0000-0009 / ibm0003.tar / ibm0003 / TPOWER53.ZIP / TPASM.ARC / TPCRT.ASM < prev    next >
Encoding:
Assembly Source File  |  1989-07-10  |  42.0 KB  |  1,596 lines

  1. ;******************************************************
  2. ;           TPCRT.ASM 5.07
  3. ;        Low level CRT routines
  4. ;     Copyright (c) TurboPower Software 1987.
  5. ; Portions copyright (c) Sunny Hill Software 1985, 1986
  6. ;     and used under license to    TurboPower Software
  7. ;         All rights reserved.
  8. ;******************************************************
  9.  
  10.     INCLUDE    TPCOMMON.ASM
  11.  
  12. ;******************************************************    Equates
  13.  
  14. ;structure of a    Turbo FIB (File    Interface Block)
  15.  
  16. FHandle        EQU    (WORD PTR 0)
  17. FMode        EQU    (WORD PTR 2)
  18. FBufSize    EQU    (WORD PTR 4)
  19. FPrivate    EQU    (WORD PTR 6)
  20. FBufPos        EQU    (WORD PTR 8)
  21. FBufEnd        EQU    (WORD PTR 10)
  22. FBufPtr        EQU    (DWORD PTR 12)
  23. FOpenProc    EQU    (DWORD PTR 16)
  24. FInOutProc    EQU    (DWORD PTR 20)
  25. FFlushProc    EQU    (DWORD PTR 24)
  26. FCloseProc    EQU    (DWORD PTR 28)
  27. FUserData    EQU    (BYTE PTR 32)
  28. FName        EQU    (BYTE PTR 48)
  29. FBuffer        EQU    (BYTE PTR 128)
  30.  
  31. ;FMode constants
  32.  
  33. FMClosed    =    0D7B0h
  34. FMInput        =    0D7B1h
  35. FMOutput    =    0D7B2h
  36. FMInOut        =    0D7B3h
  37.  
  38. ;equates for referencing pointers to FIB's on the stack
  39.  
  40. TextFile    EQU    DWORD PTR SS:[BX+4]
  41. TextFileBP    EQU    [BP+6]
  42. TFPtr        EQU    ES:[DI]
  43.  
  44. ;keys /    control    characters
  45.  
  46. Null        =    0
  47. CtrlA        =    1
  48. CtrlC        =    3
  49. CtrlD        =    4
  50. CtrlF        =    6
  51. Bell        =    7
  52. BkSp        =    8
  53. LineFeed    =    10
  54. Return        =    13
  55. CR        =    13
  56. CtrlR        =    18
  57. CtrlS        =    19
  58. CtrlX        =    24
  59. CtrlZ        =    26
  60. Escape        =    27
  61. CtrlBkSp    =    127
  62.  
  63. ;******************************************************    Macros
  64.  
  65. Write        MACRO    Char
  66.         MOV    AL, Char    ;Al has    character to write
  67.         CALL    WriteChar    ;Write it
  68.         ENDM
  69.  
  70. WriteLn        MACRO
  71.         Write    CR        ;Write the carriage return
  72.         Write    LineFeed    ;Write the line    feed
  73.         ENDM
  74.  
  75. ;******************************************************    Data
  76.  
  77. DATA    SEGMENT    BYTE PUBLIC
  78.  
  79.     ;Pascal    variables
  80.  
  81.     EXTRN    CheckBreak : BYTE        ;Check for ^Break?
  82.     EXTRN    CheckEof : BYTE            ;Check for ^Z on Read/Ln?
  83.     EXTRN    DirectVideo : BYTE        ;If false, use BIOS
  84.     EXTRN    WindMin    : WORD            ;Min. XY coordinates
  85.     EXTRN    WindMax    : WORD            ;Max. XY coordinates
  86.     EXTRN    LastMode : WORD            ;Current video mode
  87.     EXTRN    CurrentMode : BYTE        ;Current video mode
  88.     EXTRN    CurrentPage : BYTE        ;Current video page
  89.     EXTRN    ScreenWidth : BYTE        ;Current width of display
  90.     EXTRN    VirtualWidth : BYTE        ;Current width of virtual display
  91.     EXTRN    ScreenHeight : BYTE        ;Current height    of display
  92.     EXTRN    CurrentHeight :    BYTE        ;Current height    of display-1
  93.     EXTRN    CurrentDisplay : BYTE        ;Current display type
  94.     EXTRN    EnhancedDisplay    : BYTE        ;Type of enhanced display
  95.                         ;installed, if any
  96.     EXTRN    WhichHerc : BYTE        ;Type of Herc card installed
  97.     EXTRN    InTextMode : BYTE        ;False if in graphics mode
  98.     EXTRN    TextAttr : BYTE            ;Current video attribute
  99.     EXTRN    TextChar : BYTE            ;background character
  100.     EXTRN    NormalAttr : BYTE;        ;Attribute for NormVideo
  101.     EXTRN    CheckSnow : BYTE        ;If true, check    for retrace
  102.     EXTRN    CtrlBreakFlag :    BYTE        ;True if ^Break    pressed
  103.     EXTRN    VideoSegment : WORD        ;Segment of Video Memory
  104.     EXTRN    VirtualSegment : WORD        ;Segment of Video Memory--alt
  105.     EXTRN    BufLen : WORD            ;Max length of string for Read
  106.     EXTRN    ExitProc : DWORD        ;Turbo's ExitProc pointer
  107.     EXTRN    Save1B : DWORD            ;Previous INT 1Bh handler
  108.     EXTRN    DetectMultitasking : BYTE    ;If True, automatically    checks
  109.                         ;  for multitasker
  110.     EXTRN    MultitaskingOn : BYTE        ;True if running under
  111.                         ;  multitasker
  112.     EXTRN    IsCompaq : BYTE            ;True if system    is a COMPAQ
  113.     EXTRN    BiosScroll : BYTE        ;If False, use special scroll
  114.                         ;  routine
  115.     EXTRN    DisplayOverride    : BYTE        ;override auto-detection
  116.     EXTRN    NextChar : BYTE            ;Used by KeyPressed/ReadKey
  117.     EXTRN    OneMS :    WORD            ;Loop count for    1 ms delay
  118.     EXTRN    SaveExitProc :DWORD        ;Saves old ExitProc
  119.  
  120. DATA    ENDS
  121.  
  122. ;******************************************************    Code
  123.  
  124. CODE    SEGMENT    BYTE PUBLIC
  125.  
  126.     ASSUME    CS:CODE, DS:DATA
  127.  
  128.     ;Pascal    routines
  129.  
  130.     EXTRN    WhichHercCard :    NEAR    ;Herc detection    routine
  131.  
  132.     ;standard CRT unit routines
  133.  
  134.     PUBLIC    ReadKey, InitCrt, AssignCrt
  135.  
  136.     ;extensions
  137.  
  138.     PUBLIC    ReInitCrt
  139.  
  140.     ;low-level routines
  141.  
  142.     PUBLIC    ReadCursorPrim,    SetCursorPrim, GetCursorPrim, GetCrtModePrim
  143.     PUBLIC    ScrollUpPrim, ScrollDownPrim, AdapterCheck, DelayMS
  144.     PUBLIC    GetCharAttr, SetWindowPrim, FullWindow,    GetAttribute
  145.  
  146.     ;data in code segment
  147.  
  148.     OurDS    DW    DATA        ;Init'd by EXE loader to value of DS
  149.  
  150. AdapterTable1    LABEL BYTE
  151.     DB    UnknownD    ;0 = no    display
  152.     DB    Mono        ;1 = mono
  153.     DB    CGA        ;2 = CGA
  154.     DB    UnknownD    ;3 = reserved
  155.     DB    EGA        ;4 = EGA w/color
  156.     DB    EGA        ;5 = EGA w/mono
  157.     DB    PGC        ;6 = Professional Graphics controller
  158.     DB    VGA        ;7 = VGA w/mono
  159.     DB    VGA        ;8 = VGA w/color
  160.     DB    UnknownD    ;9 = reserved
  161.     DB    MCGA        ;A = MCGA w/digital color
  162.     DB    MCGA        ;B = MCGA w/mono
  163.     DB    MCGA        ;C = MCGA w/analog color
  164.  
  165. AdapterTable2    LABEL BYTE
  166.     DB    Unenhanced    ;0 = not enhanced
  167.     DB    Unenhanced    ;1 = "
  168.     DB    Unenhanced    ;2 = "
  169.     DB    Unenhanced    ;3 = "
  170.     DB    EGA        ;4 = EGA w/color
  171.     DB    EGA        ;5 = EGA w/mono
  172.     DB    PGC        ;6 = Professional Graphics controller
  173.     DB    VGA        ;7 = VGA w/mono
  174.     DB    VGA        ;8 = VGA w/color
  175.     DB    Unenhanced    ;9 = not enhanced
  176.     DB    MCGA        ;A = MCGA w/digital color
  177.     DB    MCGA        ;B = MCGA w/mono
  178.     DB    MCGA        ;C = MCGA w/analog color
  179.  
  180. ;******************************************************    AdapterCheck
  181.  
  182. JunkValue    =    0FFFFh
  183.  
  184. AdapterCheck    PROC NEAR
  185.  
  186.     MOV    WP ScreenHeight,25    ;Assume    25-line    mode
  187.     MOV    WP CurrentHeight,24
  188.     AND    WP LastMode,00FFh    ;Clear high byte of LastMode
  189.  
  190.     MOV    AL,DisplayOverride    ;check for override
  191.     CMP    AL,-1            ;-1 means no override
  192.     JE    ACauto            ;if -1,    use auto detect
  193.     CMP    AL,VGA            ;is it in Mono..VGA?
  194.     JA    ACauto            ;if not, use auto detect
  195.     MOV    CurrentDisplay,AL    ;use the override
  196.     MOV    EnhancedDisplay,AL
  197.     CMP    AL,MCGA            ;is MCGA or higher indicated?
  198.     JAE    ACgetheight        ;if so,    check height
  199.     MOV    EnhancedDisplay,0    ;not enhanced
  200.     MOV    CurrentDisplay,CGA    ;assume    CGA
  201.     CMP    CurrentMode,7        ;Current mode =    7?
  202.     JNE    ACexit1            ;if not, done
  203.     MOV    CurrentDisplay,Mono    ;else, mono
  204. ACexit1:
  205.     RET                ;done
  206. ACgetHeight:
  207.     JMP    SHORT ACheight
  208.  
  209.     ;test for VGA, MCGA
  210. ACauto:
  211.     VidCallAX    1A00h        ;Video display combination
  212.     CMP    AL,1Ah            ;AL = $1A signals valid    call
  213.     JNE    ACega            ;Check for EGA if invalid
  214.  
  215.     ;get current display type
  216.     MOV    DX,BX            ;move result from BX into DX
  217.     CMP    DL,0Ch            ;DL should be in range 1..C
  218.     JA    ACega
  219.     MOV    AL,DL            ;translate into    our terms
  220.     MOV    BX,Offset AdapterTable1
  221.     XLAT    BYTE PTR CS:[0]
  222.     CMP    AL,UnknownD        ;check for unknown adapter
  223.     JE    ACega            ;use EGA test after all
  224.     MOV    CurrentDisplay,AL    ;save result
  225.  
  226.     ;get enhanced display type
  227.     MOV    AL,DL            ;assume    one display
  228.     OR    DH,DH            ;DH of 0 means one display
  229.     JZ    ACone
  230.     CMP    DH,0Ch            ;else DH should    be in range 1..C
  231.     JA    ACone
  232.     CMP    DH,DL            ;if two, enhanced has higher value
  233.     JB    ACone
  234.     MOV    AL,DH
  235. ACone:    MOV    BX,Offset AdapterTable2
  236.     XLAT    BYTE PTR CS:[0]
  237.     MOV    EnhancedDisplay,AL    ;save result
  238.     JMP    SHORT ACHeight        ;Check the height
  239.  
  240.     ;test for EGA
  241. ACega:    MOV    CurrentDisplay,EGA    ;Assume    EGA
  242.     MOV    EnhancedDisplay,EGA
  243.     MOV    BX,0FF10h        ;Return    EGA information
  244.     MOV    CX,JunkValue        ;Load CX with junk value
  245.     VidCallAX    1200h        ;Alternate function select
  246.     SetZero    AL            ;AL = 0
  247.     CMP    CX,JunkValue        ;CX unchanged?
  248.     JE    ACnotEnhanced        ;If so,    not an enhanced    display
  249.     CMP    BH,1            ;BH should be 0    or 1
  250.     JA    ACnotEnhanced        ;Mono or CGA if    it isn't
  251.  
  252.     ;See if    EGA/VGA    is the active monitor
  253.     CMP    BH,1            ;mono display?
  254.     JE    ACMono            ;If so,    use mono check
  255.     CMP    CurrentMode,7        ;In mono mode?
  256.     JE    ACPlain            ;If so,    we're not on the EGA/VGA/MCGA
  257.     JMP    SHORT ACHeight        ;Else check height
  258. ACMono:
  259.     CMP    CurrentMode,7        ;Current mode =    7?
  260.     JNE    ACPlain            ;Exit if not
  261.  
  262.     ;check the height of the display
  263. ACHeight:
  264.     MOV    CX,40h            ;CX = $40
  265.     MOV    ES,CX            ;ES = $40
  266.     MOV    CL,ES:[84h]        ;CL = Number of    rows - 1
  267.     MOV    CurrentHeight,CL    ;Set CurrentHeight and ScreenHeight
  268.     INC    CL
  269.     MOV    ScreenHeight,CL
  270.     CMP    CL,25            ;Is it 25-line mode?
  271.     JE    ACexit            ;If so,    done
  272.     OR    WP LastMode,Font8x8    ;Set Font8x8 bit
  273.     CMP    CL,43            ;Is it 43-line mode?
  274.     JE    ACexit            ;if so,    done
  275.     CMP    CL,50            ;Is it 50-line mode?
  276.     JE    ACexit            ;if so,    done
  277.     AND    WP LastMode,00FFh    ;Clear Font8x8 bit of LastMode
  278. ACexit:
  279.     RET
  280.  
  281. ACnotEnhanced:
  282.     MOV    EnhancedDisplay,0    ;No enhanced display installed
  283.  
  284. ACPlain:
  285.     CMP    CurrentDisplay,EGA    ;Set to    EGA?
  286.     JNE    ACExit            ;Exit if not
  287.     MOV    CurrentDisplay,CGA    ;Assume    CGA
  288.     CMP    CurrentMode,7        ;Mono mode
  289.     JNE    ACExit            ;Done if not
  290.     MOV    CurrentDisplay,Mono    ;Else, Mono
  291.     RET
  292.  
  293. AdapterCheck    ENDP
  294.  
  295. ;******************************************************    BreakCheck
  296.  
  297. ;Check for ^Break
  298.  
  299. BreakCheck    PROC NEAR
  300.  
  301.     CMP    CtrlBreakFlag,False    ;Break flag set?
  302.     JE    BreakExit        ;Done if not
  303.     MOV    CtrlBreakFlag,False    ;Reset break flag
  304.  
  305. FlushKbdBuffer:
  306.     KbdCall    1            ;Key pressed function
  307.     JZ    BreakCtrlC        ;If no keypress, continue
  308.     KbdCall    0            ;Read next character
  309.     JMP    SHORT FlushKbdBuffer    ;Repeat
  310.  
  311. BreakCtrlC:
  312.     Write    '^'            ;Write the caret
  313.     Write    'C'            ;Write the 'C'
  314.     WriteLn                ;Write a CR/LF
  315.     INT    23h            ;Abort
  316.  
  317. BreakExit:
  318.     RET
  319.  
  320. BreakCheck    ENDP
  321.  
  322. ;******************************************************    ReadKey
  323.  
  324. ;function ReadKey : Char;
  325. ;Read a    character from the keyboard
  326.  
  327. ReadKey    PROC FAR
  328.  
  329.     MOV    AL,NextChar        ;AL = NextChar
  330.     MOV    NextChar,0        ;NextChar = 0
  331.     OR    AL,AL            ;See if    NextChar = 0
  332.     JNZ    ReadKeyExit        ;If not, we're done
  333.  
  334. ReadKeyStart:
  335.     INT    28h            ;Help keep popups from locking out
  336.                     ;other TSR's
  337.     KbdCall    1            ;Key pressed function
  338.     JZ    ReadKeyStart        ;If no keypress, loop
  339.  
  340.     KbdCall    0            ;Read next char    service
  341.     OR    AL,AL            ;Check for AL =    0
  342.     JNZ    ReadKeyExit        ;Exit if AL <> 0
  343.  
  344.     MOV    NextChar,AH        ;Save extended scan code
  345.     OR    AH,AH            ;Check for scan    code of    0 (^Break)
  346.     JNZ    ReadKeyExit        ;Exit if AH <> 0
  347.     MOV    AL,CtrlC        ;Else, AL = ^C
  348.  
  349. ReadKeyExit:
  350.     CALL    BreakCheck        ;Check for break if necessary
  351.     RET
  352.  
  353. ReadKey    ENDP
  354.  
  355. ;******************************************************    SetCursorPrim
  356.  
  357. ;Primitive routine to set cursor coordinates
  358. ;On entry, DH has row (Y), DL has column (X)
  359.  
  360. SetCursorPrim    PROC NEAR
  361.  
  362.     CMP    DirectVideo,False    ;Direct    video flag on?
  363.     JE    SCNotDirect        ;If not, use BIOS call
  364.     CMP    MultitaskingOn,True    ;Multitasking flag on?
  365.     JE    SCNotDirect        ;If so,    use BIOS call
  366.  
  367.     ;Set cursor position in    BIOS data area
  368.     MOV    BX,0040h        ;BX = $40
  369.     MOV    ES,BX            ;ES = $40
  370.     MOV    BL,CurrentPage        ;BL = CurrentPage, BH =    0
  371.     SHL    BX,1            ;Multiply by 2
  372.     MOV    ES:50h[BX],DX        ;DX has    cursor position
  373.  
  374.     ;program the 6845
  375.     SetZero    AH
  376.     MOV    AL,DH            ;AL = Row
  377.     MUL    ScreenWidth        ;AX = Row * width of screen
  378.     SetZero    DH            ;DX = Column (in DL, DH    is 0)
  379.     ADD    AX,DX            ;AX = (Row * width) + Column
  380.     SHL    AX,1            ;Multiply by 2
  381.     ADD    AX,ES:[4Eh]        ;DX has    starting offset    of video memory
  382.     SHR    AX,1            ;Divide    by 2
  383.     MOV    BX,AX            ;BX = (Row * width) + Column
  384.     MOV    DX,ES:[63h]        ;DX has    address    of 6845    ($03D4/$03B4)
  385.  
  386.     MOV    AL,14            ;Select    cursor address (high) register
  387.     OUT    DX,AL            ;Write the byte
  388.     NullJump            ;Wait
  389.     MOV    AL,BH            ;Get high byte of word
  390.     INC    DX            ;Next register ($03D5/$03B5)
  391.     OUT    DX,AL            ;Write the byte
  392.  
  393.     NullJump            ;Wait
  394.     DEC    DX            ;Previous register ($03D4/$03B4)
  395.  
  396.     MOV    AL,15            ;Select    cursor address (low) register
  397.     OUT    DX,AL            ;Write the byte
  398.     NullJump            ;Wait
  399.     MOV    AL,BL            ;Get low byte of word
  400.     INC    DX            ;Next register ($03D5/$03B5)
  401.     OUT    DX,AL            ;Write the byte
  402.     NullJump            ;Wait
  403.     RET
  404.  
  405. SCNotDirect:
  406.     ;Set cursor position with BIOS call
  407.     MOV    BH,CurrentPage        ;BH = current display page
  408.     VideoCall    2        ;Set cursor service
  409.     RET
  410.  
  411. SetCursorPrim    ENDP
  412.  
  413. ;******************************************************    GetCursorPrim
  414.  
  415. ;Primitive routine to get cursor coordinates
  416. ;On exit, DH has row, DL has column, CH    has starting scan line,    CL has ending
  417.  
  418. GetCursorPrim    PROC NEAR
  419.  
  420.     CMP    DirectVideo,False    ;Direct    video flag on?
  421.     JE    GCNotDirect        ;If not, use BIOS call
  422.     CMP    MultitaskingOn,True    ;Multitasking flag on?
  423.     JE    GCNotDirect        ;If so,    use BIOS call
  424.  
  425.     ;get cursor position from BIOS data area
  426.     MOV    BX,0040h        ;BX = $40
  427.     MOV    ES,BX            ;ES = $40
  428.     MOV    BL,CurrentPage        ;BL = CurrentPage, BH =    0
  429.     SHL    BX,1            ;Multiply by 2
  430.     MOV    DX,ES:50h[BX]        ;DX has    cursor position    for CurrentPage
  431.     MOV    CX,ES:60h        ;CX has    cursor shape
  432.     RET
  433.  
  434. GCNotDirect:
  435.     ;get cursor position with BIOS call
  436.     MOV    BH,CurrentPage        ;BH = current display page
  437.     VideoCall    3        ;Read cursor service
  438.     RET
  439.  
  440. GetCursorPrim    ENDP
  441.  
  442. ;******************************************************    ReadCursorPrim
  443.  
  444. ;Primitive routine to get cursor size and position
  445. ;On exit, DH has row, DL has column, AH    has starting scan line,    AL has ending
  446.  
  447. ReadCursorPrim    PROC NEAR
  448.  
  449.     CALL    GetCursorPrim
  450.     MOV    AX,CX            ;Scan lines from CX into AX
  451.     RET
  452.  
  453. ReadCursorPrim    ENDP
  454.  
  455. ;******************************************************    DelayMS
  456.  
  457. ;Delay one millisecond
  458.  
  459. DelayMS    PROC NEAR
  460.  
  461.     CMP    AL,ES:[DI]
  462.     JNE    DMSexit
  463.     LOOP    DelayMS
  464. DMSexit:
  465.     RET
  466.  
  467. DelayMS    ENDP
  468.  
  469. ;******************************************************    CrtExitProc
  470.  
  471. ;Invoked when a    program    is ending. Restore INT 1B vector.
  472.  
  473. CrtExitProc    PROC FAR
  474.  
  475.     GetPtr    SaveExitProc        ;ES:DI points to old ExitProc
  476.     SetPtr    ExitProc, ES, DI    ;Restore old ExitProc
  477.     MOV    CtrlBreakFlag,False    ;Reset CtrlBreakFlag
  478.     PUSH    DS            ;Save DS
  479.     LDS    DX,Save1B        ;DS:DX has saved vector
  480.     MOV    AX,251Bh        ;AH = Set interrupt vector service
  481.                     ;AL = interrupt    vector
  482.     INT    21h            ;Call DOS
  483.     POP    DS            ;Restore DS
  484.     RET
  485.  
  486. CrtExitProc    ENDP
  487.  
  488. ;******************************************************    Int1B
  489.  
  490. ;Handles INT 1Bh, ^Break interrupt
  491.  
  492. Int1B    PROC NEAR
  493.  
  494.     PUSH    DS            ;Save DS
  495.     PUSH    AX            ;Save AX
  496.     MOV    DS,CS:OurDS        ;Restore our DS
  497.     MOV    AL,CheckBreak        ;If CheckBreak is True...
  498.     MOV    CtrlBreakFlag,AL    ;CtrlBreakFlag will be True also
  499.     POP    AX            ;Restore AX
  500.     POP    DS            ;Restore DS
  501.     IRET
  502.  
  503. Int1B    ENDP
  504.  
  505. ;******************************************************    GetCharAttr
  506.  
  507. ;Get current character and attribute
  508. ;Returns attribute in AH, character in AL
  509.  
  510. GetCharAttr    PROC NEAR
  511.  
  512.     MOV    BH,CurrentPage        ;BH = current video page
  513.     VideoCall    8        ;Read char and attribute service
  514.     RET
  515.  
  516. GetCharAttr    ENDP
  517.  
  518. ;******************************************************    GetAttribute
  519.  
  520. ;Get current attribute at cursor
  521.  
  522. GetAttribute    PROC NEAR
  523.  
  524.     CALL    GetCharAttr        ;Get char and attribute
  525.     AND    AH,01111111b        ;Mask out the blink bit
  526.     MOV    TextAttr,AH        ;Attribute at cursor is    in AH
  527.     MOV    NormalAttr,AH        ;Attribute for NormVideo
  528.     RET
  529.  
  530. GetAttribute    ENDP
  531.  
  532. ;******************************************************    GetCrtModePrim
  533.  
  534. ;Return    the current video mode in AL, initialize most global screen variables
  535.  
  536. GetCrtModePrim    PROC NEAR
  537.  
  538.     VideoCall    0Fh        ;Get video mode    service
  539.     AND    AL,7Fh            ;mask out high bit, sometimes set on EGA
  540.     MOV    CurrentMode,AL        ;Save video mode
  541.     MOV    ScreenWidth,AH        ;Save width
  542.     MOV    VirtualWidth,AH
  543.     MOV    CurrentPage,BH        ;Save page
  544.     MOV    InTextMode,True        ;Assume    text mode
  545.     SetZero    DX            ;DX = 0
  546.     MOV    CX,0B000h        ;Assume    mono card
  547.     CMP    AL,7            ;In monochrome mode?
  548.     JE    GetCrtExit        ;If so,    exit
  549.  
  550.     ;get the segment of video memory for the current page
  551.  
  552.     MOV    CX,40h            ;CX = $40
  553.     MOV    ES,CX            ;ES = $40
  554.     MOV    CX,ES:[4Eh]        ;CX = MemW[$40:$4E]
  555.     SHR    CX,1            ;Convert offset    to paragraph
  556.     SHR    CX,1
  557.     SHR    CX,1
  558.     SHR    CX,1
  559.     ADD    CX,0B800h        ;Color card
  560.  
  561.     ;make sure we're not in graphics mode
  562.     CMP    AL,3            ;In mode 0-3?
  563.     JNA    GetCrtExit        ;If so,    in text    mode
  564.     MOV    InTextMode,False    ;Else, graphics    mode
  565.  
  566. GetCrtExit:
  567.     MOV    VideoSegment,CX        ;Save video segment
  568.     MOV    VirtualSegment,CX
  569.     CMP    DetectMultitasking,True    ;Check for multitasker?
  570.     JE    GCcheck            ;If so,    do the check
  571.     MOV    MultitaskingOn,False    ;Else, turn the    flag off
  572.     RET
  573.  
  574.     ;check for multitasker
  575. GCcheck:
  576.     MOV    ES,CX            ;Put video segment in ES
  577.     SetZero    DI            ;DI = 0
  578.     PUSH    BP            ;Save BP
  579.     VidCallAX    0FE00h        ;Get segment of    virtual    screen
  580.     POP    BP            ;Restore BP
  581.     SetZero    AL            ;AL = False
  582.     MOV    BX,ES            ;Return    value into BX
  583.     CMP    BX,VideoSegment        ;Same as before?
  584.     JE    GCno            ;If so,    not multitasking
  585.     MOV    VideoSegment,BX        ;Save segment
  586.     MOV    VirtualSegment,BX
  587.     INC    AL            ;AL = True
  588. GCno:
  589.     MOV    MultitaskingOn,AL    ;Save multitasking flag
  590.     MOV    AL,CurrentMode        ;Return    current    mode in    AL
  591.     RET
  592.  
  593. GetCrtModePrim    ENDP
  594.  
  595. ;******************************************************    SetWindowPrim
  596.  
  597. ;Primitive routine to set current window coordinates
  598. ;On entry, the new Y coordinates must be in CX,    X coordinates in DX
  599.  
  600. SetWindowPrim    PROC NEAR
  601.  
  602.     MOV    WindMin.XLow,DL        ;Set XLow
  603.     MOV    WindMax.XHigh,DH    ;Set XHigh
  604.     MOV    WindMin.YLow,CL        ;Set YLow
  605.     MOV    WindMax.YHigh,CH    ;Set YHigh
  606.     RET
  607.  
  608. SetWindowPrim    ENDP
  609.  
  610. ;******************************************************    FullWindow
  611.  
  612. ;Makes the entire screen the window
  613.  
  614. FullWindow    PROC NEAR
  615.  
  616.     SetZero    DL            ;XLow =    0
  617.     MOV    CL,DL            ;YLow =    0
  618.     MOV    DH,ScreenWidth        ;DH = ScreenWidth-1
  619.     DEC    DH
  620.     MOV    CH,CurrentHeight    ;CH = ScreenHeight-1 = CurrentHeight
  621.     CALL    SetWindowPrim        ;Call primitive    routine
  622.     RET
  623.  
  624. FullWindow    ENDP
  625.  
  626. ;******************************************************    ScrollUpPrim
  627.  
  628. ;Primitive routine to scroll a window up, with optional    snow/flicker prevention
  629.  
  630. COMMENT    |
  631.  
  632. On entry:
  633.     BH has the video attribute to use as filler
  634.     CH has top row of window
  635.     CL has left column
  636.     DH has bottom row
  637.     DL has right column
  638.     AL has number of lines to scroll, AL = 0 means clear the whole window
  639. |
  640.  
  641. SPcharsPerRow    EQU    BYTE PTR [BP-1]    ;# of char/attr    pairs per window row
  642. SProwsToMove    EQU    BYTE PTR [BP-2]    ;# of rows to move
  643. SProwsToFill    EQU    BYTE PTR [BP-3]    ;# of rows to fill
  644. SPattr        EQU    BYTE PTR [BP-4]    ;attribute to fill with
  645. SPchar        EQU    BYTE PTR [BP-5]    ;char to fill with
  646.  
  647. ScrollUpPrim    PROC NEAR
  648.  
  649.     CMP    BiosScroll,False    ;Use special scroll routine?
  650.     JE    SUspecial        ;If not, use BIOS
  651.     CMP    TextChar,' '        ;Use ours if TextChar <> ' '
  652.     JNE    SUspecial
  653.     VideoCall    06h        ;Scroll    window up service
  654.     RET
  655.  
  656. SUspecial:
  657.     CLD                ;Go forward
  658.     PUSH    DS            ;Save DS
  659.     StackFrameBP
  660.     SUB    SP,5            ;Make room for locals
  661.     MOV    SPattr,BH        ;Save attribute
  662.     MOV    AH,TextChar        ;Save character
  663.     MOV    SPchar,AH
  664.     MOV    TextChar,' '        ;Reset TextChar
  665.  
  666.     ;Get rows in window into AH
  667.     MOV    AH,DH            ;AH = bottom row
  668.     SUB    AH,CH            ;AH = bottom row - top row
  669.     INC    AH            ;AH = Succ(bottom row -    top row)
  670.  
  671.     ;Get rows to scroll into AL
  672.     CMP    AL,AH            ;AL > AH?
  673.     JNA    SUcheckZero        ;If not, check for AL =    0
  674.     MOV    AL,AH            ;Else, AL = AH
  675.     JMP    SHORT SUnotWhole    ;Continue
  676. SUcheckZero:
  677.     OR    AL,AL            ;Is AL 0?
  678.     JNZ    SUnotWhole        ;If not, use actual value
  679.     MOV    AL,AH            ;Else, scroll entire window
  680. SUnotWhole:
  681.     MOV    SProwsToFill,AL        ;Save #    of rows    to fill
  682.     SUB    AH,AL            ;AH = #    of rows    to move
  683.     MOV    SProwsToMove,AH        ;Save #    of rows    to move
  684.  
  685.     ;Get # of chars    per row
  686.     SetZero    AH            ;AH = 0
  687.     MOV    AL,DL            ;AL = right column
  688.     SUB    AL,CL            ;AL = right column - left column
  689.     INC    AL            ;AL = Succ(right column    - left column)
  690.     MOV    SPcharsPerRow,AL    ;Save #    of char/attr pairs per row
  691.     MOV    SI,AX            ;Save in SI too
  692.  
  693.     ;Get starting value for    DI
  694.     MOV    BX,WP ScreenWidth    ;BX = Chars per    screen row
  695.     MOV    AL,CH            ;AX = top row
  696.     MUL    BX            ;AX = row * current width
  697.     SetZero    CH            ;CH = 0, CX = LeftCol
  698.     ADD    AX,CX            ;AX = (row * current width) + col
  699.     SHL    AX,1            ;account for attribute bytes
  700.     MOV    DI,AX            ;DI has    starting offset    for top    left
  701.                     ; corner of window
  702.  
  703.     SHL    SI,1            ;SI = bytes per    window row
  704.     SHL    BX,1            ;BX = Video words per screen row
  705.     MOV    CX,BX            ;CX = Video words per screen row
  706.     SUB    BX,SI            ;BX has    delta to add when looping
  707.  
  708.     SetZero    AH            ;AH = 0
  709.     MOV    AL,SProwsToFill        ;AX = #    of rows    to fill
  710.     MUL    CX            ;AX = rows to fill * words/screen row
  711.     MOV    SI,DI            ;SI = DI
  712.     ADD    SI,AX            ;Point SI to first row to move
  713.  
  714.     MOV    AL,CheckSnow        ;Grab this before changing DS
  715.     MOV    DX,VideoSegment        ;DX = VideoSegment
  716.     MOV    ES,DX            ;ES = VideoSegment
  717.     MOV    DS,DX            ;DS = VideoSegment
  718.     SetZero    CH            ;CH = 0
  719.  
  720.     SHR    AL,1            ;Snow checking on?
  721.     JNC    SUfullSpeed        ;Skip next check if not
  722.     CMP    DH,0B8h            ;See if    we're moving/filling CGA memory
  723.     JNE    SUfullSpeed        ;If not, don't wait for retrace
  724.  
  725.     ;Move screen data (with    snow prevention)
  726.     MOV    DX,03DAh        ;Point DX to CGA status    port
  727.     CMP    SProwsToMove,0        ;Any rows to move?
  728.     JE    SUstartFillWait        ;If not, start filling
  729. SUmoveWait:
  730.     MOV    CL,SPcharsPerRow    ;CX = #    of char/attr pairs to move
  731.     WordMoveNoSnow            ;Move CX words,    preventing snow
  732.     ADD    DI,BX            ;Point DI to next row
  733.     ADD    SI,BX            ;Point SI to next row
  734.     DEC    SProwsToMove        ;Decrement # of    rows to    move
  735.     JNZ    SUmoveWait        ;If not    zero, repeat
  736.  
  737.     ;Fill with blanks (with    snow prevention)
  738. SUstartFillWait:
  739.     MOV    SI,BX            ;Delta into SI
  740.     MOV    BH,SPattr        ;Attribute into    BH
  741.     MOV    BL,SPchar        ;Filler    into BL
  742. SUfillWait:
  743.     MOV    CL,SPcharsPerRow    ;CX = #    of char/attr pairs to fill
  744. SUfillNext:
  745.     WaitForRetrace            ;Wait for opportunity to write
  746.     WordToCGA    BX        ;Move the word
  747.     LOOP    SUfillNext        ;Fill next video word
  748.     ADD    DI,SI            ;Point DI to next row
  749.     DEC    SProwsToFill        ;Decrement # of    rows to    fill
  750.     JNZ    SUfillWait        ;Repeat    if not zero
  751.     JMP    SHORT SUExit        ;All done
  752.  
  753.     ;Move screen data (no snow prevention)
  754.  
  755. SUfullSpeed:
  756.     MOV    DL,SPcharsPerRow    ;DL = #    of char/attr pairs to move
  757.     MOV    DH,SProwsToMove        ;DH = #    of rows    to move
  758.     MOV    AH,SPattr        ;Attribute into    AH
  759.     MOV    AL,SPchar        ;Filler    into AL
  760.     OR    DH,DH            ;Any rows to move?
  761.     JZ    SUstartFillNoWait    ;If not, start filling
  762. SUmoveNoWait:
  763.     MOV    CL,DL            ;CX = #    of char/attr pairs to move
  764.     REP    MOVSW            ;Move 'em
  765.     ADD    DI,BX            ;Point DI to next row
  766.     ADD    SI,BX            ;Point SI to next row
  767.     DEC    DH            ;Decrement # of    rows to    move
  768.     JNZ    SUmoveNoWait        ;If not    zero, repeat
  769.  
  770.     ;Fill with blanks (no snow prevention)
  771.  
  772. SUstartFillNoWait:
  773.     MOV    DH,SProwsToFill        ;DH = #    of rows    to fill
  774. SUfillNoWait:
  775.     MOV    CL,DL            ;CX = #    of char/attr pairs to move
  776.     REP    STOSW            ;Fill this row
  777.     ADD    DI,BX            ;Point DI to next row
  778.     DEC    DH            ;Decrement # of    rows to    fill
  779.     JNZ    SUfillNoWait        ;Repeat    if not zero
  780.  
  781. SUExit:
  782.     MOV    SP,BP            ;Restore SP
  783.     POP    BP            ;Restore BP
  784.     POP    DS            ;Restore DS
  785.     RET                ;Return
  786.  
  787. ScrollUpPrim    ENDP
  788.  
  789. ;******************************************************    ScrollDownPrim
  790.  
  791. ;Primitive routine to scroll a window down, with optional snow/flicker prevention
  792.  
  793. COMMENT    |
  794.  
  795. On entry:
  796.     BH has the video attribute to use as filler
  797.     CH has top row of window
  798.     CL has left column
  799.     DH has bottom row
  800.     DL has right column
  801.     AL has number of lines to scroll, AL = 0 means clear the whole window
  802. |
  803.  
  804. ScrollDownPrim    PROC NEAR
  805.  
  806.     CMP    BiosScroll,False    ;Use special scroll routine?
  807.     JE    SDspecial        ;If not, use BIOS
  808.     CMP    TextChar,' '        ;Use ours if TextChar <> ' '
  809.     JNE    SDspecial
  810.     VideoCall    07h        ;Scroll    window down service
  811.     RET
  812.  
  813. SDspecial:
  814.     CLD                ;Go forward
  815.     PUSH    DS            ;Save DS
  816.     StackFrameBP
  817.     SUB    SP,5            ;Make room for locals
  818.     MOV    SPattr,BH        ;Save attribute
  819.     MOV    AH,TextChar        ;Save character
  820.     MOV    SPchar,AH
  821.     MOV    TextChar,' '        ;Reset TextChar
  822.  
  823.     ;Get rows in window into BL
  824.     MOV    BL,DH            ;BL = bottom row
  825.     SUB    BL,CH            ;BL = bottom row - top row
  826.     INC    BL            ;BL = Succ(bottom row -    top row)
  827.  
  828.     ;Get rows to scroll into AL
  829.     CMP    AL,BL            ;AL > BL?
  830.     JNA    SDcheckZero        ;If not, check for AL =    0
  831.     MOV    AL,BL            ;Else, AL = AH
  832.     JMP    SHORT SDnotWhole    ;Continue
  833. SDcheckZero:
  834.     OR    AL,AL            ;Is AL 0?
  835.     JNZ    SDnotWhole        ;If not, use actual value
  836.     MOV    AL,BL            ;Else, scroll entire window
  837. SDnotWhole:
  838.     MOV    SProwsToFill,AL        ;Save #    of rows    to fill
  839.     SUB    BL,AL            ;BL = #    of rows    to move
  840.     MOV    SProwsToMove,BL        ;Save #    of rows    to move
  841.  
  842.     ;Get # of chars    per row
  843.     SetZero    AH            ;AH = 0
  844.     MOV    AL,DL            ;AL = right column
  845.     SUB    AL,CL            ;AL = right column - left column
  846.     INC    AL            ;AL = Succ(right column    - left column)
  847.     MOV    SPcharsPerRow,AL    ;Save #    of char/attr pairs per row
  848.     MOV    SI,AX            ;Save in SI too
  849.  
  850.     ;Get starting value for    SI
  851.     MOV    AL,DH            ;AX = bottom row
  852.     MOV    BX,WP ScreenWidth    ;BX = Chars per    screen row
  853.     MUL    BX            ;AX = row * current width
  854.     SetZero    CH            ;CH = 0, CX = LeftCol
  855.     ADD    AX,CX            ;AX = (row * current width) + col
  856.     SHL    AX,1            ;account for attribute bytes
  857.     MOV    DI,AX            ;SI has    starting offset    for last row
  858.  
  859.     SHL    SI,1            ;SI = bytes per    window row
  860.     SHL    BX,1            ;BX = Video words per screen row
  861.     MOV    CX,BX            ;CX = Video words per screen row
  862.     ADD    BX,SI            ;BX has    delta to subtract when looping
  863.  
  864.     SetZero    AH            ;AH = 0
  865.     MOV    AL,SProwsToFill        ;AX = #    of rows    to fill
  866.     MUL    CX            ;AX = rows to fill * words/screen row
  867.     MOV    SI,DI            ;SI = DI
  868.     SUB    SI,AX            ;Point SI to first row to move
  869.  
  870.     MOV    AL,CheckSnow        ;Grab this before changing DS
  871.     MOV    DX,VideoSegment        ;DX = VideoSegment
  872.     MOV    ES,DX            ;ES = VideoSegment
  873.     MOV    DS,DX            ;DS = VideoSegment
  874.     SetZero    CH            ;CH = 0
  875.  
  876.     SHR    AL,1            ;Snow checking on?
  877.     JNC    SDfullSpeed        ;Skip next check if not
  878.     CMP    DH,0B8h            ;See if    we're moving/filling CGA memory
  879.     JNE    SDfullSpeed        ;If not, don't wait for retrace
  880.  
  881.     ;Move screen data (with    snow prevention)
  882.     MOV    DX,03DAh        ;Point DX to CGA status    port
  883.     CMP    SProwsToMove,0        ;Any rows to move?
  884.     JE    SDstartFillWait        ;If not, start filling
  885. SDmoveWait:
  886.     MOV    CL,SPcharsPerRow    ;CX = #    of char/attr pairs to move
  887.     WordMoveNoSnow            ;Move CX words,    preventing snow
  888.     SUB    DI,BX            ;Point DI to previous row
  889.     SUB    SI,BX            ;Point SI to previous row
  890.     DEC    SProwsToMove        ;Decrement # of    rows to    move
  891.     JNZ    SDmoveWait        ;If not    zero, repeat
  892.  
  893.     ;Fill with blanks (with    snow prevention)
  894. SDstartFillWait:
  895.     MOV    SI,BX            ;Delta into SI
  896.     MOV    BH,SPattr        ;Attribute into    BH
  897.     MOV    BL,SPchar        ;Filler    into BL
  898. SDfillWait:
  899.     MOV    CL,SPcharsPerRow    ;CX = #    of char/attr pairs to fill
  900. SDfillNext:
  901.     WaitForRetrace            ;Wait for opportunity to write
  902.     MOV    AX,BX            ;Get word back into AX
  903.     STOSW                ;Store the word
  904.     STI                ;Allow interrupts
  905.     LOOP    SDfillNext        ;Fill next video word
  906.     SUB    DI,SI            ;Point DI to previous row
  907.     DEC    SProwsToFill        ;Decrement # of    rows to    fill
  908.     JNZ    SDfillWait        ;Repeat    if not zero
  909.     JMP    SHORT SDExit        ;All done
  910.  
  911.     ;Move screen data (no snow prevention)
  912.  
  913. SDfullSpeed:
  914.     MOV    DL,SPcharsPerRow    ;DL = #    of char/attr pairs to move
  915.     MOV    DH,SProwsToMove        ;DH = #    of rows    to move
  916.     MOV    AH,SPattr        ;Attribute into    AH
  917.     MOV    AL,SPchar        ;Filler    into AL
  918.     OR    DH,DH            ;Any rows to move?
  919.     JZ    SDstartFillNoWait    ;If not, start filling
  920. SDmoveNoWait:
  921.     MOV    CL,DL            ;CX = #    of char/attr pairs to move
  922.     REP    MOVSW            ;Move 'em
  923.     SUB    DI,BX            ;Point DI to previous row
  924.     SUB    SI,BX            ;Point SI to previous row
  925.     DEC    DH            ;Decrement # of    rows to    move
  926.     JNZ    SDmoveNoWait        ;If not    zero, repeat
  927.  
  928.     ;Fill with blanks (no snow prevention)
  929.  
  930. SDstartFillNoWait:
  931.     MOV    DH,SProwsToFill        ;DH = #    of rows    to fill
  932. SDfillNoWait:
  933.     MOV    CL,DL            ;CX = #    of char/attr pairs to move
  934.     REP    STOSW            ;Fill this row
  935.     SUB    DI,BX            ;Point DI to previous row
  936.     DEC    DH            ;Decrement # of    rows to    fill
  937.     JNZ    SDfillNoWait        ;Repeat    if not zero
  938.  
  939. SDExit:
  940.     MOV    SP,BP            ;Restore SP
  941.     POP    BP            ;Restore BP
  942.     POP    DS            ;Restore DS
  943.     RET                ;Return
  944.  
  945. ScrollDownPrim    ENDP
  946.  
  947. ;******************************************************    CrtNop
  948.  
  949. ;Do-nothing file handling procedure
  950. ;On entry, a pointer to    a FileRec is on    the stack
  951.  
  952. CrtNop    PROC FAR
  953.  
  954.     SetZero    AX            ;Signal    AOK
  955.     RET    4
  956.  
  957. CrtNop    ENDP
  958.  
  959. ;******************************************************    OutputChar
  960.  
  961. ;On entry, AL has character to write
  962.  
  963. OutputChar    PROC NEAR
  964.  
  965.     PUSH    DI            ;Save DI
  966.     MOV    CL,AL            ;CL has    character
  967.     MOV    CH,TextAttr        ;CH has    TextAttr
  968.     CMP    DirectVideo,True    ;Write directly    to video memory?
  969.     JNE    BiosOutput        ;If not, use BIOS
  970.     CMP    InTextMode,True        ;In text mode?
  971.     JNE    BiosOutput        ;If not, use BIOS
  972.  
  973.     CMP    MultitaskingOn,True    ;Multitasking?
  974.     JNE    OCgetCursor        ;if not, don't need BIOS call
  975.  
  976.     ;get cursor position with BIOS call
  977.     PUSH    CX            ;Save CX
  978.     MOV    BH,CurrentPage        ;BH = current display page
  979.     VideoCall    3        ;Read cursor service
  980.     POP    CX            ;Restore CX
  981.     JMP    SHORT OCcalcAddress    ;Ready to calculate address
  982.  
  983.     ;get cursor position from BIOS data area into DX
  984. OCgetCursor:
  985.     MOV    BX,0040h        ;BX = $40
  986.     MOV    ES,BX            ;ES = $40
  987.     MOV    BL,CurrentPage        ;BL = CurrentPage, BH =    0
  988.     SHL    BX,1            ;Multiply by 2
  989.     MOV    DX,ES:50h[BX]        ;DX has    cursor position    for CurrentPage
  990.  
  991.     ;calculate address in video memory
  992. OCcalcAddress:
  993.     MOV    AL,DH            ;AL = row
  994.     SetZero    DH            ;DH = 0    (DX = column)
  995.     MUL    ScreenWidth        ;AL = (row * width)
  996.     MOV    DI,AX            ;DI = (row * width)
  997.     ADD    DI,DX            ;DI = (row * width) + column
  998.     SHL    DI,1            ;Account for attribute bytes
  999.     MOV    ES,VideoSegment        ;ES has    segment    of video memory
  1000.  
  1001.     ;determine which method    of output to use
  1002.     CMP    CheckSnow,False        ;Snow checking off?
  1003.     JE    OutputStore        ;If so,    go
  1004.  
  1005.     ;Use the following only    for color cards    when retrace checking is on
  1006.     MOV    DX,03DAh        ;Point DX to CGA status    port
  1007.     WaitForRetrace            ;Wait for an opportunity to write
  1008.  
  1009. OutputStore:
  1010.     WordToCGA    CX        ;Write the word
  1011.     JMP    SHORT OutputExit    ;Return
  1012.  
  1013.     ;Write with a BIOS call
  1014.  
  1015. BiosOutput:
  1016.     MOV    AL,CL            ;AL = character
  1017.     MOV    BL,CH            ;BL = Video attribute
  1018.     MOV    BH,CurrentPage        ;BH = Current video page
  1019.     MOV    CX,1            ;CX = number of    chars to repeat
  1020.     VideoCall    9        ;Write character and attribute service
  1021.  
  1022. OutputExit:
  1023.     POP    DI            ;Restore DI
  1024.     RET
  1025.  
  1026. OutputChar    ENDP
  1027.  
  1028. ;******************************************************    DoLineFeed
  1029.  
  1030. DoLineFeed    PROC NEAR
  1031.  
  1032.     INC    DH            ;Next row
  1033.     CMP    DH,WindMax.YHigh    ;Still inside window?
  1034.     JBE    DLFexit            ;If so,    go
  1035.     DEC    DH            ;Back up to current row
  1036.     PUSH    BX            ;save registers
  1037.     PUSH    CX
  1038.     PUSH    DI
  1039.     PUSH    SI
  1040.     PUSH    ES
  1041.     PUSH    DX
  1042.     MOV    BH,TextAttr        ;Filler    character
  1043.     MOV    CX,WindMin        ;Top row and left column
  1044.     MOV    DX,WindMax        ;Bottom    row and    right column
  1045.     MOV    AL,1            ;AL = 1    (lines to scroll)
  1046.     CALL    ScrollUpPrim        ;Call scroll window up primitive
  1047.     POP    DX
  1048.     POP    ES            ;Restore registers
  1049.     POP    SI
  1050.     POP    DI
  1051.     POP    CX
  1052.     POP    BX
  1053. DLFexit:
  1054.     RET
  1055.  
  1056. DoLineFeed    ENDP
  1057.  
  1058. ;******************************************************    WriteChar
  1059.  
  1060. ;Write one character
  1061. ;On entry, AL has character to write
  1062.  
  1063. WriteChar    PROC NEAR
  1064.  
  1065.     ;Save registers
  1066.  
  1067.     PUSH    DI
  1068.     PUSH    SI
  1069.     PUSH    BX
  1070.     PUSH    CX
  1071.     PUSH    DX
  1072.     PUSH    ES
  1073.  
  1074.     ;Get current position of cursor
  1075.  
  1076.     PUSH    AX
  1077.     CALL    GetCursorPrim
  1078.     POP    AX
  1079.  
  1080.     ;Check for special characters
  1081.  
  1082.     CMP    AL,CR            ;Carriage return?
  1083.     JE    CarriageReturn
  1084.     CMP    AL,LineFeed        ;Line feed?
  1085.     JE    WCLineFeed
  1086.     CMP    AL,BkSp            ;Backspace?
  1087.     JE    BackSpace
  1088.     CMP    AL,Bell            ;Bell (^G)?
  1089.     JE    RingBell
  1090.  
  1091.     ;Normal    character
  1092.  
  1093.     PUSH    DX            ;Save DX
  1094.     CALL    OutputChar        ;Write the character
  1095.     POP    DX            ;Restore DX
  1096.  
  1097.     ;Now move the cursor
  1098.  
  1099.     INC    DL            ;Cursor    to next    column
  1100.     CMP    DL,WindMax.XHigh    ;Still inside window?
  1101.     JBE    WCSetCursor        ;If so,    move cursor and    exit
  1102.     MOV    DL,WindMin.XLow        ;Else, do a 'carriage return'...
  1103.     JMP    SHORT WCLineFeed    ;... and 'line feed'
  1104.  
  1105. RingBell:
  1106.     VideoCall    0Eh        ;Write character as TTY
  1107.     JMP    SHORT WCExit        ;Done
  1108.  
  1109. BackSpace:
  1110.     CMP    DL,WindMin.XLow        ;Cursor    at start of this column?
  1111.     JE    WCExit            ;If so,    do nothing
  1112.     DEC    DL            ;Else, previous    column
  1113.     JMP    SHORT WCSetCursor    ;Move cursor and exit
  1114.  
  1115. CarriageReturn:
  1116.     MOV    DL,WindMin.XLow        ;First column in window
  1117.     JMP    SHORT WCSetCursor    ;Move cursor and exit
  1118.  
  1119. WCLineFeed:
  1120.     CALL    DoLineFeed        ;generate a line feed
  1121.  
  1122. WCSetCursor:
  1123.     CALL    SetCursorPrim
  1124. WCExit:
  1125.     POP    ES            ;Restore registers
  1126.     POP    DX
  1127.     POP    CX
  1128.     POP    BX
  1129.     POP    SI
  1130.     POP    DI
  1131.     RET
  1132.  
  1133. WriteChar    ENDP
  1134.  
  1135. ;******************************************************    FlushString
  1136.  
  1137. FlushString    PROC NEAR
  1138.  
  1139.     PUSH    CX            ;save CX
  1140.     MOV    CX,DI            ;get number of characters to write
  1141.     SUB    CX,SI
  1142.     JCXZ    FSexit            ;done if CX = 0
  1143.  
  1144.     PUSH    DX            ;save registers    used
  1145.     PUSH    DI
  1146.     PUSH    DS
  1147.     PUSH    ES
  1148.  
  1149.     ;calculate address in video memory
  1150.  
  1151.     MOV    AL,BH            ;AL = row
  1152.     SetZero    BH            ;BH = 0    (BX = column)
  1153.     MUL    ScreenWidth        ;AL = (row * width)
  1154.     MOV    DI,AX            ;DI = (row * width)
  1155.     ADD    DI,BX            ;DI = (row * width) + column
  1156.     SHL    DI,1            ;Account for attribute bytes
  1157.  
  1158.     MOV    AH,TextAttr        ;AH has    attribute
  1159.     MOV    AL,CheckSnow        ;AL = CheckSnow
  1160.  
  1161.     MOV    BX,VideoSegment        ;BX = VideoSegment
  1162.     PUSH    ES            ;DS:SI points to string
  1163.     POP    DS
  1164.     MOV    ES,BX            ;ES has    segment    of video memory
  1165.  
  1166.     ;determine which method    of output to use
  1167.     CLD                ;go forward
  1168.     OR    AL,AL            ;Snow checking off?
  1169.     JZ    FSfast            ;If so,    go fast
  1170.     MOV    DX,03DAh        ;Point DX to CGA status    port
  1171.  
  1172.     ;Use the following only    for color cards    when retrace checking is on
  1173. FSgetNext:
  1174.     LODSB                ;Load next character into AL
  1175.     MOV    BX,AX            ;Store video word in BX
  1176.     WaitForRetrace            ;Wait for an opportunity to write
  1177.     WordToCGA    BX        ;Move the word
  1178.     LOOP    FSgetNext        ;Get next character
  1179.     JMP    SHORT FSdone        ;Done
  1180.  
  1181. FSfast:
  1182.     LODSB                ;load next character
  1183.     STOSW                ;write it
  1184.     LOOP    FSfast            ;get next character
  1185.  
  1186. FSdone:
  1187.     POP    ES            ;restore registers
  1188.     POP    DS
  1189.     POP    DI
  1190.     POP    DX
  1191. FSexit:
  1192.     POP    CX
  1193.     RET
  1194.  
  1195. FlushString    ENDP
  1196.  
  1197. ;******************************************************    WriteString
  1198.  
  1199. ;on entry: ES:DI points    to start of string, CX has its length
  1200.  
  1201. WriteString    PROC NEAR
  1202.  
  1203.     PUSH    ES
  1204.     PUSH    DI
  1205.     PUSH    CX
  1206.     CALL    GetCursorPrim        ;Get cursor coordinates    into DX
  1207.     POP    CX
  1208.     POP    DI
  1209.     POP    ES
  1210.     MOV    BX,DX            ;save them in BX
  1211.     MOV    SI,DI            ;ES:SI points to start of string
  1212.  
  1213. WSnext:
  1214.     MOV    AL,ES:[DI]        ;next character    into AL
  1215.     CMP    AL,CR            ;check for control characters
  1216.     JA    WSplain
  1217.     JE    WScr
  1218.     CMP    AL,LineFeed
  1219.     JE    WSlinefeed
  1220.     CMP    AL,BkSp
  1221.     JE    WSbksp
  1222.     CMP    AL,Bell
  1223.     JE    WSbell
  1224.  
  1225. WSplain:
  1226.     INC    DI            ;point to next character
  1227.     INC    DL            ;next column
  1228.     CMP    DL,WindMax.XHigh    ;past end of window?
  1229.     JBE    WSskip            ;if not, skip to next character
  1230.  
  1231.     CALL    FlushString        ;else, flush string
  1232.     CALL    DoLineFeed        ;do a line feed
  1233.     MOV    DL,WindMin.XLow        ;DL has    first column
  1234.     JMP    SHORT WSnoAdvance
  1235.  
  1236. WSbell:
  1237.     CALL    FlushString        ;flush the string
  1238.     Write    Bell            ;sound the bell
  1239.     JMP    SHORT WSadvance
  1240.  
  1241. WSbksp:
  1242.     CALL    FlushString        ;flush the string
  1243.     CMP    DL,WindMin.XLow        ;already at first column?
  1244.     JE    WSadvance        ;if so,    don't back up
  1245.     DEC    DL            ;else, previous    column
  1246.     JMP    SHORT WSadvance
  1247.  
  1248. WSlinefeed:
  1249.     CALL    FlushString        ;flush the string
  1250.     CALL    DoLineFeed        ;do a line feed
  1251.     JMP    SHORT WSadvance
  1252.  
  1253. WScr:
  1254.     CALL    FlushString        ;flush the string
  1255.     MOV    DL,WindMin.XLow        ;DL has    first column
  1256.  
  1257. WSadvance:
  1258.     INC    DI            ;point to next character
  1259.  
  1260. WSnoAdvance:
  1261.     MOV    SI,DI            ;SI = DI
  1262.     MOV    BX,DX            ;save cursor position
  1263.  
  1264. WSskip:
  1265.     LOOP    WSnext            ;do it again
  1266.     CALL    FlushString        ;flush the string
  1267.     CALL    SetCursorPrim        ;position the cursor
  1268.     RET
  1269.  
  1270. WriteString    ENDP
  1271.  
  1272. ;******************************************************    WriteCrt
  1273.  
  1274. ;On entry, a pointer to    an FIB is on the stack
  1275.  
  1276. WriteCrt    PROC FAR
  1277.  
  1278.     StackFrame
  1279.     GetPtr    TextFile        ;ES:DI points to file
  1280.     MOV    CX,TFPtr.FBufPos    ;CX = number of    chars to write
  1281.     JCXZ    WCrtExit        ;Exit if string    empty
  1282.     SUB    TFPtr.FBufPos,CX    ;Back up pointer to start of string
  1283.     GetPtr    TFPtr.FBufPtr        ;Point ES:DI to    the start of the buffer
  1284.     MOV    TextChar,' '        ;Force TextChar    to ' '
  1285.  
  1286.     CMP    DirectVideo,True    ;Write directly    to screen?
  1287.     JNE    WriteNext        ;nope, write character at a time
  1288.     CMP    InTextMode,True
  1289.     JNE    WriteNext
  1290.  
  1291.     CALL    WriteString        ;else, write string at a time
  1292.     JMP    SHORT WCrtExit        ;we're done
  1293.  
  1294. WriteNext:
  1295.     Write    TFPtr            ;Write the next    character
  1296.     INC    DI            ;point to next char
  1297.     LOOP    WriteNext        ;Next character
  1298.  
  1299. WCrtExit:
  1300.     CALL    BreakCheck        ;Check for ^Break
  1301.     SetZero    AX            ;Signal    AOK
  1302.     RET    4
  1303.  
  1304. WriteCrt    ENDP
  1305.  
  1306. ;******************************************************    ReadCrt
  1307.  
  1308. ;On entry, a pointer to    an FIB is on the stack
  1309.  
  1310. ;constants
  1311. CrLf        =    0A0Dh
  1312.  
  1313. COMMENT    |
  1314.   Register usage:
  1315.     BX always points to    the next available slot    in the text buffer
  1316.     CX contains    a loop count (0    or 1). When CX = 0, LOOP instructions
  1317.       set CX to    FFFFh, so the loop gets    executed until some other
  1318.       condition    is met.
  1319. |
  1320.  
  1321. ReadCrt    PROC FAR
  1322.  
  1323.     StackFrameBP
  1324.     GetPtr    TextFileBP        ;ES:DI points to FileRec
  1325.     MOV    SI,TFPtr.FBufPos    ;SI = BufPos
  1326.     MOV    CX,TFPtr.FBufSize    ;CX = BufSize
  1327.     DEC    CX
  1328.     DEC    CX            ;CX = 126
  1329.     PUSH    CX            ;Save this for later
  1330.     SetZero    BX            ;Start at beginning of the buffer
  1331.     GetPtr    TFPtr.FBufPtr        ;ES:DI points to BufPtr^
  1332.     MOV    AX,BufLen        ;AX = BufLen
  1333.     OR    AX,AX            ;AX = 0?
  1334.     JZ    ResetBufLen        ;If so,    set it to the default
  1335.  
  1336.     CMP    AX,CX            ;BufLen    > BufSize?
  1337.     JNA    ReadNext        ;If not, proceed
  1338.  
  1339. ResetBufLen:
  1340.     MOV    Buflen,CX        ;BufLen    = 126
  1341.  
  1342. ReadNext:
  1343.     MOV    NextChar,Null        ;Filter    keys with extended scan    codes
  1344.     CALL    ReadKey            ;Get next character into AL
  1345.     MOV    CX,1            ;Loop counter =    1
  1346.     CMP    AL,BkSp            ;Backspace?
  1347.     JE    ReadBkSp
  1348.     CMP    AL,CtrlS        ;^S? (=    Backspace)
  1349.     JE    ReadBkSp
  1350.     CMP    AL,CtrlD        ;^D? (Restore one character)
  1351.     JE    ReadRestore
  1352.     DEC    CX            ;BkSp loop counter = 0
  1353.     CMP    AL,Escape        ;Escape? (Delete line)
  1354.     JE    ReadBkSp
  1355.     CMP    AL,CtrlBkSp        ;^BkSp?    (Delete    line)
  1356.     JE    ReadBkSp
  1357.     CMP    AL,CtrlA        ;^A? (Delete line)
  1358.     JE    ReadBkSp
  1359.     CMP    AL,CtrlF        ;^F? (Restore whole line)
  1360.     JE    ReadRestore
  1361.     CMP    AL,CtrlZ        ;^Z? (close Input?)
  1362.     JE    ReadEofCheck        ;If so,    see if we should close shop
  1363.     CMP    AL,Return        ;Enter key?
  1364.     JE    ReadCrlf        ;If so,    write a    CrLf and stop
  1365.     CMP    AL,' '            ;Regular ASCII character?
  1366.     JB    ReadNext        ;If not, continue
  1367.  
  1368.     ;Process the character
  1369.     CMP    BX,BufLen        ;Line full?
  1370.     JE    ReadNext        ;If so,    don't add to it
  1371.     MOV    TFPtr[BX],AL        ;Add character to end of buffer
  1372.     CALL    WriteChar        ;Write the character
  1373.     INC    BX            ;Increment the buffer pointer
  1374.     CMP    BX,SI            ;BX > BufPos?
  1375.     JNA    ReadNext        ;If not, continue
  1376.     MOV    SI,BX            ;Else set BufPos to BX
  1377.     JMP    SHORT ReadNext
  1378.  
  1379. ReadExit:
  1380.     GetPtr    TextFileBP        ;ES:DI points to FileRec
  1381.     POP    CX            ;Get back default Buflen setting
  1382.     MOV    BufLen,CX        ;Reset BufLen to default
  1383.     SetZero    AX            ;No I/O    error
  1384.     MOV    TFPtr.FBufPos,AX    ;Reset BufPos to 0 for next read
  1385.     MOV    TFPtr.FBufEnd,BX    ;FBufEnd has length of the string
  1386.     ExitCode    4
  1387.  
  1388. ReadRestore:
  1389.     CMP    BX,SI            ;Does BX point to end of buffer?
  1390.     JE    ReadNext        ;If so,    do nothing
  1391.     MOV    AL,TFPtr[BX]        ;Next character    into AL
  1392.     CMP    AL,' '            ;Is it a control character?
  1393.     JB    ReadNext        ;If so,    do nothing
  1394.     CALL    WriteChar        ;Write it
  1395.     INC    BX            ;Point to next character in buffer
  1396.     LOOP    ReadRestore        ;Repeat    if CX was 0 on entry
  1397. ReadJump:
  1398.     JMP    SHORT ReadNext
  1399.  
  1400. ReadEofCheck:
  1401.     CMP    CheckEof,False        ;CheckEof false?
  1402.     JE    ReadNext        ;If so,    continue
  1403.     MOV    TFPtr[BX],AL        ;Add character to end of buffer
  1404.     INC    BX            ;Increment BX
  1405.     JMP    SHORT ReadExit        ;And exit
  1406.  
  1407. ReadBkSp:
  1408.     OR    BX,BX            ;BX = 0?
  1409.     JZ    ReadJump        ;If so,    don't back up
  1410.     Write    BkSp            ;Move the cursor back
  1411.     Write    ' '            ;Overwrite the last character
  1412.     Write    BkSp            ;Move the cursor back again
  1413.     DEC    BX            ;Decrement buffer pointer
  1414.     LOOP    ReadBkSp        ;Repeat    if CX was 0 on entry
  1415.     JMP    ReadNext        ;Continue
  1416.  
  1417. ReadCrlf:
  1418.     WriteLn                ;Write a CR/LF
  1419.     MOV    WP TFPtr[BX],CrLf    ;Add the CrLf to the buffer
  1420.     INC    BX
  1421.     INC    BX
  1422.     JMP    SHORT ReadExit        ;And exit
  1423.  
  1424. ReadCrt    ENDP
  1425.  
  1426. ;******************************************************    OpenCrt
  1427.  
  1428. ;Open input or output files
  1429. ;Parameter is a    pointer    to an FIB
  1430.  
  1431. COMMENT    |
  1432.    Register usage:
  1433.    AX has offset of the    Read/Write procedure
  1434.    BX            Flush
  1435.    CX            Close
  1436. |
  1437.  
  1438. OpenCrt    PROC FAR
  1439.  
  1440.     StackFrame
  1441.     GetPtr    TextFile        ;ES:DI points to FileRec
  1442.  
  1443.     ;assume    we're opening for input
  1444.     MOV    CX,OFFSET CrtNop    ;CX = Ofs(CrtNop)
  1445.     MOV    BX,CX            ;BX = Ofs(CrtNop)
  1446.     MOV    AX,OFFSET ReadCrt    ;AX = Ofs(ReadCrt)
  1447.     CMP    TFPtr.FMode,FMInput    ;Opening for input?
  1448.     JE    OpenIt            ;If so,    AX-BX-CX are correct
  1449.  
  1450.     ;nope, opening for output
  1451.     MOV    TFPtr.FMode,FMOutput    ;Open for output
  1452.     MOV    AX,OFFSET WriteCrt    ;AX = Ofs(WriteCrt)
  1453.     MOV    BX,AX            ;BX = Ofs(WriteCrt) (Flush with    write)
  1454.  
  1455. OpenIt:
  1456.     SetPtr    TFPtr.FInOutProc, CS, AX    ;Set up    Read/Write routine
  1457.     SetPtr    TFPtr.FFlushProc, CS, BX    ;Set up    Flush routine
  1458.     SetPtr    TFPtr.FCloseProc, CS, CX    ;Do nothing with a Close()
  1459.     SetZero    AX            ;Signal    success
  1460.     RET    4
  1461.  
  1462. OpenCrt    ENDP
  1463.  
  1464. ;******************************************************    AssignCrt
  1465.  
  1466. ;procedure AssignCrt(var F : Text);
  1467. ;Parameter is a    pointer    to an FIB
  1468.  
  1469. AssignCrt    PROC FAR
  1470.  
  1471.     StackFrame
  1472.     GetPtr    TextFile        ;ES:DI points to F
  1473.     MOV    BX, OFFSET OpenCrt    ;BX has    offset of OpenCrt
  1474.     SetPtr    TFPtr.FOpenProc, CS, BX    ;Open with OpenCrt
  1475.     MOV    TFPtr.FMode,FMClosed    ;File is closed
  1476.     MOV    TFPtr.FName,0        ;No filename
  1477.     LEA    AX,TFPtr.FBuffer    ;Set up    file buffer
  1478.     MOV    TFPtr.FBufPtr.Segm,ES     ;Initialize record
  1479.     MOV    TFPtr.FBufPtr.Ofst,AX
  1480.     MOV    AX,128            ;AX = Default buffersize
  1481.     MOV    TFPtr.FBufSize,AX    ;Store Buffer size
  1482.     DEC    AX
  1483.     DEC    AX            ;AX = Buffer size - 2
  1484.     MOV    BufLen,AX        ;BufLen    = Buffer size -    2
  1485.     RET    4
  1486.  
  1487. AssignCrt    ENDP
  1488.  
  1489. ;******************************************************    ReInitCrt
  1490.  
  1491. ;procedure ReInitCrt;
  1492.  
  1493. ;Reinitialize CRT unit's internal variables. For TSR's or programs with
  1494. ;DOS shells.
  1495.  
  1496. ReInitCrt    PROC FAR
  1497.  
  1498.     ;save current video mode
  1499.     CALL    GetCrtModePrim        ;Current video mode into AL
  1500.  
  1501.     ;check for EGA/VGA/etc.
  1502.     CALL    AdapterCheck        ;Check for EGA
  1503.     CALL    WhichHercCard        ;Check for Herc    card type
  1504.     MOV    WhichHerc,AL        ;save it in WhichHerc
  1505.  
  1506.     ;set retrace checking variable
  1507.     MOV    CheckSnow,False        ;Assume    false
  1508.     CMP    IsCompaq,True        ;Is it a Compaq?
  1509.     JE    SetWindow        ;If so,    won't need to wait
  1510.     CMP    CurrentDisplay,CGA    ;CGA installed?
  1511.     JNE    SetWindow        ;If not, won't need to wait
  1512.     INC    CheckSnow        ;Else, may have    to wait    when writing
  1513.                     ; to the color card
  1514. SetWindow:
  1515.     CALL    FullWindow        ;set window coordinates
  1516.     RET
  1517.  
  1518. ReInitCrt    ENDP
  1519.  
  1520. ;******************************************************    InitCrt
  1521.  
  1522. ;procedure InitCrt;
  1523. ;Initialization    stuff
  1524.  
  1525. InitCrt    PROC NEAR
  1526.  
  1527.     ;Run test to see if DirectVideo    will cause problems
  1528.     MOV    DirectVideo,False    ;try it    with DirectVideo false
  1529.     CALL    GetCursorPrim        ;Get current coordinates into DX
  1530.     PUSH    DX            ;save result on    stack
  1531.     MOV    DirectVideo,True    ;try it    with DirectVideo on
  1532.     CALL    GetCursorPrim        ;Get current coordinates into DX
  1533.     POP    AX            ;first result into AX
  1534.     CMP    AX,DX            ;results the same?
  1535.     JE    DirectVideoOK        ;if so,    DirectVideo=True presumably OK
  1536.     MOV    DirectVideo,False    ;else, force it    to false
  1537.  
  1538. DirectVideoOK:
  1539.     SetZero    AL            ;AL = 0
  1540.     MOV    NextChar,AL        ;NextChar = 0
  1541.     MOV    CtrlBreakFlag,AL    ;CtrlBreakFlag = False
  1542.     MOV    WP ScreenWidth,80    ;ScreenWidth = 80
  1543.     MOV    WP VirtualWidth,80
  1544.     CALL    ReinitCrt        ;Init code shared w/ ReInitCrt
  1545.  
  1546.     CALL    GetAttribute        ;get current attribute at cursor
  1547.  
  1548.     ;set up    our ExitProc routine
  1549.     MOV    AX, OFFSET CrtExitProc    ;AX has    offset of CrtExitProc
  1550.     GetPtr    ExitProc        ;ES:DI points to ExitProc^
  1551.     SetPtr    SaveExitProc, ES, DI    ;Save current value of ExitProc
  1552.     SetPtr    ExitProc, CS, AX    ;Replace with address of CrtExitProc
  1553.  
  1554.     ;take over INT 1Bh
  1555.     MOV    AX,351Bh        ;AH = Get interrupt vector service
  1556.                     ;AL = interrupt    vector
  1557.     INT    21h            ;Call DOS
  1558.     SetPtr    Save1B,    ES, BX        ;Save pointer returned in ES:BX
  1559.     MOV    DX,OFFSET Int1B        ;DX = Ofs(Int1B)
  1560.     PUSH    DS            ;Save DS
  1561.     MOV    AX,CS            ;AX = CS
  1562.     MOV    DS,AX            ;DS = CS
  1563.     MOV    AX,251Bh        ;AH = Set interrupt vector service
  1564.                     ;AL = interrupt    vector
  1565.     INT    21h            ;Call DOS
  1566.     POP    DS            ;Restore DS
  1567.  
  1568.     ;set up    delay count
  1569.     MOV    AX,40h            ;AX = $40
  1570.     MOV    ES,AX            ;ES = $40
  1571.     MOV    DI,6Ch            ;ES:DI => low word of BIOS timer count
  1572.     MOV    AL,ES:[DI]        ;AL has    first byte there
  1573.     STI
  1574. WaitForChange:
  1575.     CMP    AL,ES:[DI]        ;wait for the byte to change
  1576.     JZ    WaitForChange
  1577.  
  1578.     MOV    AL,ES:[DI]        ;see how many times DelayMS has    to
  1579.     MOV    CX,0FFFFh        ;loop before the timer count changes
  1580.     CALL    DelayMS
  1581.  
  1582.     MOV    AX,55            ;now calculate OneMS
  1583.     XCHG    CX,AX
  1584.     NOT    AX
  1585.     XOR    DX,DX
  1586.     DIV    CX
  1587.     MOV    OneMS,AX        ;AX has    OneMS
  1588.     RET
  1589.  
  1590. InitCrt    ENDP
  1591.  
  1592. CODE    ENDS
  1593.  
  1594.     END
  1595.  
  1596.