home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / asmutil / 80x0393.zip / MODEX.ASM < prev    next >
Assembly Source File  |  1993-03-30  |  57KB  |  1,686 lines

  1. ;
  2. ; MODEX.ASM - A Complete Mode X Library 
  3. ; By Matt Pritchard 
  4. ; With considerable input from Michael Abrash 
  5. ; The following information is donated to the public domain in 
  6. ; the hopes that save other programmers much frustration. 
  7. ; If you do use this code in a product, it would be nice if 
  8. ; you include a line like 'Mode X routine by Matt Pritchard' 
  9. ; in the credits. '
  10. ;
  11.  
  12.     .MODEL Medium, Basic
  13.     .286
  14.     PAGE    255, 132
  15.  
  16.     ; ==== MACROS ====
  17.  
  18. OUT_16 MACRO Register, Value
  19.     MOV     DX, Register        ; Select Register
  20.     MOV     AX, Value           ; Get Out Value
  21.     OUT     DX, AX              ; Set Register(s) 
  22.     ENDM
  23.  
  24. OUT_8 MACRO Register, Value
  25.     MOV     DX, Register        ; Select Register
  26.     MOV     AL, Value           ; Get Out Value
  27.     OUT     DX, AL              ; Set Register 
  28.     ENDM
  29.  
  30.     ; ==== General Constants ====
  31.  
  32.     False   EQU 0
  33.     True    EQU -1
  34.  
  35.     b       EQU BYTE PTR
  36.     w       EQU WORD PTR
  37.     d       EQU DWORD PTR
  38.  
  39.     ; ==== VGA Register Values ====
  40.  
  41.     VGA_Segment     EQU 0A000H  ; Vga Memory Segment
  42.  
  43.     ATTRIB_Ctrl     EQU 03C0H   ; VGA Attribute Controller
  44.     GC_Index        EQU 03CEH   ; VGA Graphics Controller
  45.     SC_Index        EQU 03C4H   ; VGA Sequencer Controller
  46.     SC_Data         EQU 03C5H   ; VGA Sequencer Data Port
  47.     CRTC_Index      EQU 03D4H   ; VGA CRT Controller
  48.     CRTC_Data       EQU 03D5H   ; VGA CRT Controller Data
  49.     MISC_OUTPUT     EQU 03C2H   ; VGA Misc Register
  50.     INPUT_1         EQU 03DAH   ; Input Status #1 Register
  51.  
  52.     DAC_WRITE_ADDR  EQU 03C8H   ; VGA DAC Write Addr Register
  53.     DAC_READ_ADDR   EQU 03C7H   ; VGA DAC Read Addr Register
  54.     PEL_DATA_REG    EQU 03C9H   ; VGA DAC/PEL data Register R/W
  55.  
  56.     MAP_MASK        EQU 02      ; Map Register #
  57.     READ_MAP        EQU 04      ; Read Map Register #
  58.     MAP_MASK_PLANE1 EQU 0102h   ; Map Register + Plane 1
  59.  
  60.     START_DISP_HI   EQU 0Ch     ; CRTC Index: Display Start Addr Hi
  61.     START_DISP_LO   EQU 0Dh     ; CRTC Index: Display Start Addr Lo
  62.  
  63.     PLANE_BITS      EQU 03h     ; Bits 0-1 of Xpos = Plane #
  64.     ALL_PLANES      EQU 0Fh     ; All Bit Planes Selected
  65.     ALL_PLANES_ON   EQU 0F02h   ; Map Register + All Bit Planes
  66.     CHAIN4_OFF      EQU 0604h   ; Chain 4 mode Off
  67.     ASYNC_RESET     EQU 0100h   ; (A)synchronous Reset
  68.     SEQU_RESTART    EQU 0300h   ; Sequencer Restart
  69.  
  70.     ; Constants Specific for these routines
  71.  
  72.     NUM_MODES       EQU 8       ; # of Mode X Variations
  73.  
  74.     ; Specific Mode Data Table format...
  75.  
  76.     M_MiscR         EQU 0       ; Value of MISC_OUTPUT register
  77.     M_Pages         EQU 1       ; Maximum Possible # of pages
  78.     M_XSize         EQU 2       ; X Size Displayed on screen
  79.     M_YSize         EQU 4       ; Y Size Displayed on screen
  80.     M_XMax          EQU 6       ; Maximum Possible X Size
  81.     M_YMax          EQU 8       ; Maximum Possible Y Size
  82.     M_CRTC          EQU 10      ; Table of CRTC register values
  83.  
  84.     ; ==== DGROUP STORAGE NEEDED (36 BYTES) =====
  85.  
  86.     .DATA?
  87.  
  88. SCREEN_WIDTH    DW  0           ; Width of a line in Bytes 
  89. SCREEN_WIDTHx4  DW  0           ; Width of a line in Pixels 
  90. SCREEN_HEIGHT   DW  0           ; Veritcal Height in Pixels
  91.  
  92. LAST_PAGE       DW  0           ; # of Display Pages 
  93. PAGE_ADDR       DW  0, 0, 0, 0  ; Offsets to start of each page
  94.  
  95. PAGE_SIZE       DW  0           ; Size of Page in Addr Bytes
  96.  
  97. DISPLAY_PAGE    DW  0           ; Page # currently displayed 
  98. ACTIVE_PAGE     DW  0           ; Page # currently active
  99.  
  100. CURRENT_PAGE    DW  0           ; Offset of current Page 
  101. CURRENT_SEGMENT DW  0           ; Segment of VGA memory
  102.  
  103. CURRENT_XOFFSET DW  0           ; Current Display X Offset 
  104. CURRENT_YOFFSET DW  0           ; Current Display Y Offset
  105.  
  106. CURRENT_MOFFSET DW  0           ; Current Start Offset
  107.  
  108. MAX_XOFFSET     DW  0           ; Current Display X Offset 
  109. MAX_YOFFSET     DW  0           ; Current Display Y Offset
  110.  
  111.     .CODE
  112.  
  113.     ; Data Tables, Put in Code Segement for Easy Access
  114.     ; (Like when all the other Segment Registers are in
  115.     ; use!!) and reduced DGROUP requirements...
  116.  
  117. LEFT_CLIP_MASK      DB  0FH, 0EH, 0CH, 08H
  118.  
  119. RIGHT_CLIP_MASK     DB  01H, 03H, 07H, 0FH
  120.  
  121. MODE_TABLE:
  122.         DW  OFFSET MODE_320x200, OFFSET MODE_320x400
  123.         DW  OFFSET MODE_360x200, OFFSET MODE_360x400
  124.         DW  OFFSET MODE_320x240, OFFSET MODE_320x480
  125.         DW  OFFSET MODE_360x240, OFFSET MODE_360x480
  126.  
  127. MODE_320x200:           ; Data for 320 by 200 Pixels
  128.  
  129.         DB  063h        ; 400 scan Lines & 25 Mhz Clock
  130.         DB  4           ; Maximum of 4 Pages
  131.         DW  320, 200    ; Displayed Pixels (X,Y)
  132.         DW  1302, 816   ; Max Possible X and Y Sizes
  133.  
  134.         ;CRTC Setup Data....
  135.  
  136.         DW  00014H      ; Dword Mode off
  137.         DW  0E317H      ; turn on Byte Mode
  138.         DW  00000h      ; End of CRTC Data for 320x200
  139.  
  140. MODE_320x400:           ; Data for 320 by 400 Pixels
  141.  
  142.         DB  063h        ; 400 scan Lines & 25 Mhz Clock
  143.         DB  2           ; Maximum of 2 Pages
  144.         DW  320, 400    ; Displayed Pixels X,Y
  145.         DW  648, 816    ; Max Possible X and Y Sizes
  146.  
  147.         ;CRTC Setup Data....
  148.  
  149.         DW  04009H      ; Cell Heigth (1 Scan Line)
  150.         DW  00014H      ; Dword Mode off
  151.         DW  0E317H      ; turn on Byte Mode
  152.         DW  00000h      ; End of CRTC Data for 320x400
  153.  
  154. MODE_360x240:           ; Data for 360 by 240 Pixels
  155.  
  156.         DB  0E7h        ; 480 scan Lines & 28 Mhz Clock
  157.         DB  3           ; Maximum of 3 Pages
  158.         DW  360, 240    ; Displayed Pixels X,Y
  159.         DW  1092, 728   ; Max Possible X and Y Sizes
  160.  
  161.         ;CRTC Setup Data....
  162.  
  163.         DW  06B00H      ; Horz total
  164.         DW  05901H      ; Horz Displayed
  165.         DW  05A02H      ; Start Horz Blanking
  166.         DW  08E03H      ; End Horz Blanking
  167.         DW  05E04H      ; Start H Sync
  168.         DW  08A05H      ; End H Sync
  169.         DW  00D06H      ; Vertical Total
  170.         DW  03E07H      ; Overflow
  171.         DW  04109H      ; Cell Heigth (2 Scan Lines)
  172.         DW  0EA10H      ; V Sync Start
  173.         DW  0AC11H      ; V Sync End/Prot Cr0 Cr7
  174.         DW  0DF12H      ; Vertical Displayed
  175.         DW  00014H      ; Dword Mode off
  176.         DW  0E715H      ; V Blank Start
  177.         DW  00616H      ; V Blank End
  178.         DW  0E317H      ; turn on Byte Mode
  179.         DW  00000h      ; End of CRTC Data for 360x240
  180.  
  181. MODE_360x480:           ; Data for 360 by 480 Pixels
  182.  
  183.         DB  0E7h        ; 480 scan Lines & 28 Mhz Clock
  184.         DB  1           ; Only 1 Page Possible
  185.         DW  360, 480    ; Displayed Pixels X,Y
  186.         DW  544, 728    ; Max Possible X and Y Sizes
  187.  
  188.         ;CRTC Setup Data....
  189.  
  190.         DW  06B00H      ; Horz total
  191.         DW  05901H      ; Horz Displayed
  192.         DW  05A02H      ; Start Horz Blanking
  193.         DW  08E03H      ; End Horz Blanking
  194.         DW  05E04H      ; Start H Sync
  195.         DW  08A05H      ; End H Sync
  196.         DW  00D06H      ; Vertical Total
  197.         DW  03E07H      ; Overflow
  198.         DW  04009H      ; Cell Heigth (1 Scan Line)
  199.         DW  0EA10H      ; V Sync Start
  200.         DW  0AC11H      ; V Sync End/Prot Cr0 Cr7
  201.         DW  0DF12H      ; Vertical Displayed
  202.         DW  00014H      ; Dword Mode off
  203.         DW  0E715H      ; V Blank Start
  204.         DW  00616H      ; V Blank End
  205.         DW  0E317H      ; turn on Byte Mode
  206.  
  207.         DW  00000h      ; End of CRTC Data for 360x480
  208.  
  209. MODE_320x240:           ; Data for 320 by 240 Pixels
  210.  
  211.         DB  0E3h        ; 480 scan Lines & 25 Mhz Clock
  212.         DB  3           ; Maximum of 3 Pages
  213.         DW  320, 240    ; Displayed Pixels X,Y
  214.         DW  1088, 818   ; Max Possible X and Y Sizes
  215.  
  216.         DW  00D06H      ; Vertical Total
  217.         DW  03E07H      ; Overflow
  218.         DW  04109H      ; Cell Heigth (2 Scan Lines)
  219.         DW  0EA10H      ; V Sync Start
  220.         DW  0AC11H      ; V Sync End/Prot Cr0 Cr7
  221.         DW  0DF12H      ; Vertical Displayed
  222.         DW  00014H      ; Dword Mode off
  223.         DW  0E715H      ; V Blank Start
  224.         DW  00616H      ; V Blank End
  225.         DW  0E317H      ; turn on Byte Mode
  226.  
  227.         DW  00000h      ; End of CRTC Data for 320x240
  228.  
  229. MODE_320x480:           ; Data for 320 by 480 Pixels
  230.  
  231.         DB  0E3h        ; 480 scan Lines & 25 Mhz Clock
  232.         DB  1           ; Only 1 Page Possible
  233.         DW  320, 480    ; Displayed Pixels X,Y
  234.         DW  540, 818    ; Max Possible X and Y Sizes
  235.  
  236.         DW  00D06H      ; Vertical Total
  237.         DW  03E07H      ; Overflow
  238.         DW  04009H      ; Cell Heigth (1 Scan Line)
  239.         DW  0EA10H      ; V Sync Start
  240.         DW  0AC11H      ; V Sync End/Prot Cr0 Cr7
  241.         DW  0DF12H      ; Vertical Displayed
  242.         DW  00014H      ; Dword Mode off
  243.         DW  0E715H      ; V Blank Start
  244.         DW  00616H      ; V Blank End
  245.         DW  0E317H      ; turn on Byte Mode
  246.  
  247.         DW  00000h      ; End of CRTC Data for 320x480
  248.  
  249. MODE_360x200:           ; Data for 360 by 200 Pixels
  250.  
  251.         DB  067h        ; 400 scan Lines & 28 Mhz Clock
  252.         DB  3           ; Maximum of 3 Pages
  253.         DW  360, 200    ; Displayed Pixels (X,Y)
  254.         DW  1302, 728   ; Max Possible X and Y Sizes
  255.  
  256.         ;CRTC Setup Data....
  257.  
  258.         DW  06B00H      ; Horz total
  259.         DW  05901H      ; Horz Displayed
  260.         DW  05A02H      ; Start Horz Blanking
  261.         DW  08E03H      ; End Horz Blanking
  262.         DW  05E04H      ; Start H Sync
  263.         DW  08A05H      ; End H Sync
  264.         DW  00014H      ; Dword Mode off
  265.         DW  0E317H      ; turn on Byte Mode
  266.         DW  00000h      ; End of CRTC Data for 360x200
  267.  
  268. MODE_360x400:           ; Data for 360 by 400 Pixels
  269.  
  270.         DB  067h        ; 400 scan Lines & 28 Mhz Clock
  271.         DB  1           ; Maximum of 1 Pages
  272.         DW  360, 400    ; Displayed Pixels X,Y
  273.         DW  648, 816    ; Max Possible X and Y Sizes
  274.  
  275.         ;CRTC Setup Data....
  276.  
  277.         DW  06B00H      ; Horz total
  278.         DW  05901H      ; Horz Displayed
  279.         DW  05A02H      ; Start Horz Blanking
  280.         DW  08E03H      ; End Horz Blanking
  281.         DW  05E04H      ; Start H Sync
  282.         DW  08A05H      ; End H Sync
  283.         DW  04009H      ; Cell Heigth (1 Scan Line)
  284.         DW  00014H      ; Dword Mode off
  285.         DW  0E317H      ; turn on Byte Mode
  286.         DW  00000h      ; End of CRTC Data for 360x400
  287.  
  288.  
  289. ; ===== ACTUAL ASSEMBLY CODE =====
  290.  
  291. ;====================================================== 
  292. ;SET_VGA_MODEX%(ModeType%, MaxXPos%, MaxYpos%, Pages%)
  293. ;====================================================== 
  294. ; Sets Up the specified version of Mode X.  Allows for 
  295. ; the setup of multiple video pages, and a virtual 
  296. ; screen which can be larger than the displayed screen 
  297. ; (which can then be scrolled a pixel at a time) 
  298. ; INPUT PARAMETERS: 
  299. ; ModeType%  - The Desired Version of 256 Color Mode X 
  300. ;     0 =  320 x 200, 4 Pages max,  1.2:1 Aspect Ratio 
  301. ;     1 =  320 x 400, 2 Pages max,  2.4:1 Aspect Ratio 
  302. ;     2 =  360 x 200, 3 Pages max,  1.35:1 Aspect Ratio 
  303. ;     3 =  360 x 400, 1 Page  max,  2.7:1 Aspect Ratio 
  304. ;     4 =  320 x 240, 3 Pages max,  1:1 Aspect Ratio 
  305. ;     5 =  320 x 480, 1 Page  max,  2:1 Aspect Ratio 
  306. ;     6 =  360 x 240, 3 Pages max,  1.125:1 Aspect Ratio 
  307. ;     7 =  360 x 480, 1 Page  max,  2.25:1 Aspect Ratio 
  308. ; MaxXpos = The Desired Virtual Screen Width 
  309. ; MaxYpos = The Desired Virtual Screen Height 
  310. ; Pages%  = The Desired # of Video Pages 
  311. ; RETURNS in AX:    0 (= Failure) or ffff (= Success) 
  312. ;
  313.  
  314. SVM_STACK   STRUC
  315.                 DW  ?,?,?,? ;DI,SI,DS,BP
  316.                 DD  ?       ;Caller
  317.     SVM_Pages   DW  ?
  318.     SVM_Ysize   DW  ?
  319.     SVM_Xsize   DW  ?
  320.     SVM_Mode    DW  ?
  321. SVM_STACK   ENDS
  322.  
  323.     PUBLIC  SET_VGA_MODEX
  324.  
  325. SET_VGA_MODEX   PROC    FAR
  326.  
  327.     PUSH    BP                  ; Preserve Important
  328.     PUSH    DS                  ; Register Values
  329.     PUSH    SI
  330.     PUSH    DI
  331.  
  332.     MOV     BP,SP               ; Set up Stack Frame
  333.  
  334.     ;Check Legality of Mode Request....
  335.  
  336.     MOV     BX, [BP].SVM_Mode   ; Get Requested Mode #
  337.     CMP     BX, NUM_MODES       ; Is it 0..7?
  338.     JAE     SVM_BadModeSetup    ; If Not, Error out
  339.  
  340.     SHL     BX, 1                   ; Scale BX
  341.     MOV     SI, w CS:MODE_TABLE[BX] ; CS:SI -> Mode Info
  342.     PUSH    SI                      ; Save for later use
  343.  
  344.     ;Check # of Requested Display Pages
  345.  
  346.     MOV     CX, [Bp].SVM_Pages  ; Get # of Requested Pages
  347.     CMP     CX, CS:[SI].M_Pages ; Check # Pages for mode
  348.     JA      SVM_BadModeSetup    ; Report Error if too Many
  349.     OR      CX, CX              ; # Pages = 0?
  350.     JE      SVM_BadModeSetup    ; Report Error if 0
  351.  
  352.     ;Check Validity of X Size
  353.  
  354.     AND     [BP].SVM_XSize, 0FFF8h  ;X size Mod 8 Must = 0
  355.  
  356.     MOV     AX, [BP].SVM_XSize  ; Get Logical Screen Width
  357.     CMP     AX, CS:[SI].M_XSize ; Check against Displayed X
  358.     JB      SVM_BadModeSetup    ; Report Error if too small
  359.     CMP     AX, CS:[SI].M_XMax  ; Check against Max X
  360.     JA      SVM_BadModeSetup    ; Report Error if too big
  361.  
  362.     ;Check Validity of Y Size
  363.  
  364.     MOV     BX, [BP].SVM_YSize  ; Get Logical Screen Height
  365.     CMP     BX, CS:[SI].M_YSize ; Check against Displayed Y
  366.     JB      SVM_BadModeSetup    ; Report Error if too small
  367.     CMP     BX, CS:[SI].M_YMax  ; Check against Max Y
  368.     JA      SVM_BadModeSetup    ; Report Error if too big
  369.  
  370.     ;Enough memory to Fit it all?
  371.  
  372.     SHR     AX, 2               ;# of Bytes:Line = XSize/4
  373.     MUL     BX                  ;# Bytes/Page = AX/4 * BX
  374.     JO      SVM_BadModeSetup    ;Exit if Page Size > 256K
  375.  
  376.     MUL     CX                  ;Total Mem = PageSize * Pages
  377.     JNO     SVM_Continue        ;Exit if Total Size > 256K
  378.  
  379. SVM_BadModeSetup:
  380.  
  381.     XOR     AX, AX              ; Return Value = False
  382.     JMP     SVM_Exit            ; Normal Exit
  383.  
  384. SVM_Continue:
  385.  
  386.     MOV     AX, 13H             ; Start with Mode 13H
  387.     INT     10H                 ; Let BIOS Set Mode
  388.  
  389.     OUT_16  SC_INDEX, CHAIN4_OFF    ; Disable Chain 4 Mode
  390.     OUT_16  SC_INDEX, ASYNC_RESET   ; (A)synchronous Reset
  391.  
  392.     MOV     DX, MISC_OUTPUT     ; VGA Misc Register
  393.     MOV     AL, CS:[SI].M_MiscR ; Get New Timing/Size Value
  394.     OUT     DX, AL              ; Set VGA Misc Register
  395.  
  396.     OUT_16  SC_INDEX, SEQU_RESTART  ; Restart Sequencer ...
  397.  
  398.     MOV     DX, CRTC_INDEX      ; Vga crtc Registers
  399.     MOV     AL, 11H             ; Vert Retrace End Register
  400.     OUT     DX, AL              ; Load Current Value
  401.     INC     DX                  ; Point to Data
  402.     IN      AL, DX              ; Get Value, Bit 7 = Protect
  403.     AND     AL, 7FH             ; Mask out Write Protect
  404.     OUT     DX, AL              ; And send it back
  405.  
  406.     MOV     DX, CRTC_INDEX      ; Vga Crtc Registers
  407.     ADD     SI, M_CRTC          ; SI -> CRTC Parameter Data
  408.  
  409. SVM_Setup_CRTC:
  410.  
  411.     MOV     AX, CS:[SI]         ; Get CRTC Data from Table
  412.     ADD     SI, 2               ; Advance Pointer
  413.     OR      AX, AX              ; At End of Data Table?
  414.     JZ      SVM_Set_Data        ; If so, Exit Loop
  415.  
  416.     OUT     DX, AX              ; Reprogram VGA CRTC reg
  417.     JMP     SVM_Setup_CRTC      ; Process Next Table Entry
  418.  
  419. SVM_Set_Data:
  420.  
  421.     XOR     AX, AX              ; AX = 0
  422.     MOV     DISPLAY_PAGE, AX    ; Display Page = 0
  423.     MOV     ACTIVE_PAGE, AX     ; Active Page = 0
  424.     MOV     CURRENT_PAGE, AX    ; Current Page (Offset) = 0
  425.     MOV     CURRENT_XOFFSET, AX ; Horz Scroll Index = 0
  426.     MOV     CURRENT_YOFFSET, AX ; Vert Scroll Index = 0
  427.     MOV     CURRENT_MOFFSET, AX ; Memory Scroll Index = 0
  428.  
  429.     MOV     AX, VGA_SEGMENT     ; Segment for VGA memory
  430.     MOV     CURRENT_SEGMENT, AX ; Save for Future LES's
  431.  
  432.     ;Set Logical Screen Width, X Scroll and Our Data
  433.  
  434.     POP     SI                  ; Get Saved Ptr to Mode Info
  435.     MOV     AX, [Bp].SVM_Xsize  ; Get Display Width
  436.  
  437.     MOV     CX, AX              ; CX = Logical Width
  438.     SUB     CX, CS:[SI].M_XSize ; CX = Max X Scroll Value
  439.     MOV     MAX_XOFFSET, CX     ; Set Maximum X Scroll
  440.  
  441.     MOV     SCREEN_WIDTHx4, AX  ; Save Width in Pixels
  442.     SHR     AX, 2               ; Bytes = Pixels / 4
  443.     MOV     SCREEN_WIDTH, AX    ; Save Width in Pixels
  444.  
  445.     SHR     AX, 1               ; Offset Value = Bytes / 2
  446.     MOV     AH, 13h             ; CRTC Offset Register Index
  447.     XCHG    AL, AH              ; Switch format for OUT
  448.     OUT     DX, AX              ; Set VGA CRTC Offset Reg
  449.  
  450.     ;Setup Data table, Y Scroll, Misc for Other Routines
  451.  
  452.     MOV     AX, [Bp].SVM_Ysize  ; Get Logical Screen Hieght
  453.  
  454.     MOV     CX, AX              ; CX = Logical Height
  455.     SUB     BX, CS:[SI].M_YSize ; CX = Max Y Scroll Value
  456.     MOV     MAX_YOFFSET, CX     ; Set Maximum Y Scroll
  457.  
  458.     MOV     SCREEN_HEIGHT, AX   ; Save Hight in Pixels
  459.     MUL     SCREEN_WIDTH        ; AX = Page Size in Bytes,
  460.     MOV     PAGE_SIZE, AX       ; Save Page Size
  461.  
  462.     MOV     CX, [Bp].SVM_Pages  ; Get # of Pages
  463.     MOV     LAST_PAGE, CX       ; Save # of Pages
  464.  
  465.     MOV     BX, 0               ; Page # = 0
  466.     MOV     DX, BX              ; Page 0 Offset = 0
  467.  
  468. SVM_Set_Pages:
  469.  
  470.     MOV     PAGE_ADDR[BX], DX   ; Set Page #(BX) Offset
  471.     ADD     BX, 2               ; Page#++
  472.     ADD     DX, AX              ; Compute Addr of Next Page
  473.     LOOP    SVM_Set_Pages       ; Loop until Done
  474.  
  475.     ;Clear VGA Memory
  476.  
  477.     OUT_16  SC_INDEX, ALL_PLANES_ON ; Select All Planes
  478.     LES     DI, d CURRENT_PAGE      ; Point to Start of VGA memory
  479.  
  480.     XOR     AX, AX              ; AX = 0
  481.     CLD                         ; Block Xfer Forwards
  482.     MOV     CX, 8000H           ; 32K * 4 * 2 = 256K
  483.     REP     STOSW               ; Clear dat memory!
  484.  
  485.     MOV     AX, True            ; Return Success Code
  486.  
  487. SVM_EXIT:
  488.  
  489.     POP     DI                  ; Restore Saved Registers
  490.     POP     SI
  491.     POP     DS
  492.     POP     BP
  493.  
  494.     RET     8                   ;We are Done.. Outa here
  495.  
  496. SET_VGA_MODEX   ENDP
  497.  
  498.  
  499. ;==================
  500. ;SET_MODEX% (Mode%)
  501. ;==================
  502. ;
  503. ; Quickie Mode Set - Sets Up Mode X to Default Configuration 
  504. ; INPUT PARAMETERS: 
  505. ; ModeType%  - The Desired Version of 256 Color Mode X 
  506. ;   (0 to 7 - See Chart under SET_VGA_MODEX) 
  507. ; RETURNS in AX:    0 (= Failure) or ffff (= Success) 
  508. ;
  509.  
  510. SM_STACK    STRUC
  511.                 DW  ?   ;BP
  512.                 DD  ?   ;Caller
  513.     SM_Mode     DW  ?
  514. SM_STACK    ENDS
  515.  
  516.     PUBLIC  SET_MODEX
  517.  
  518. SET_MODEX   PROC    FAR
  519.  
  520.     PUSH    BP                  ; Preserve Important
  521.     MOV     BP,SP               ; Set up Stack Frame
  522.  
  523.     XOR     AX, AX              ; Assume Failure
  524.     MOV     BX, [BP].SM_Mode    ; Get Desired Mode #
  525.  
  526.     CMP     BX, NUM_MODES       ; Is it 0..7?
  527.     JAE     @SX_Exit            ; If Not, don't Bother
  528.  
  529.     PUSH    BX                  ; Push Mode Parameter
  530.  
  531.     SHL     BX, 1                   ; Scale BX
  532.     MOV     SI, w CS:MODE_TABLE[BX] ;CS:SI -> Mode Info
  533.  
  534.     MOV     AX, CS:[SI].M_XSize ; Get Default X Size
  535.     PUSH    AX                  ; Push X Size Parameter
  536.  
  537.     MOV     AX, CS:[SI].M_Ysize ; Get Default Y size
  538.     PUSH    AX                  ; Push Y Size Parameter
  539.  
  540.     MOV     AL, CS:[SI].M_Pages ; Get Default # of Pages
  541.     MOV     AH, 0               ; Hi Byte = 0
  542.     PUSH    AX                  ; Push # Pages
  543.  
  544.     CALL    FAR PTR SET_VGA_MODEX   ; Set up Mode X!
  545.  
  546. @SX_Exit:
  547.  
  548.     POP     BP                  ; Restore Register
  549.     RET     2                   ; We are Done.. Outa here
  550.  
  551. SET_MODEX   ENDP
  552.  
  553.  
  554. ;============================
  555. ;CLEAR_VGA_SCREEN (ColorNum%)
  556. ;============================
  557. ;
  558. ; Clears the currently active display page to 
  559. ; all the color #ColorNum 
  560. ;
  561.  
  562. CVS_STACK   STRUC
  563.                 DW  ?,?     ;DI, BP
  564.                 DD  ?       ;Caller
  565.     CVS_COLOR   DB  ?,?     ;Color to Set Screen to 
  566. CVS_STACK ENDS
  567.  
  568.     PUBLIC  CLEAR_VGA_SCREEN
  569.  
  570. CLEAR_VGA_SCREEN    PROC    FAR
  571.  
  572.     PUSH    BP                  ; Preserve Registers
  573.     PUSH    DI
  574.  
  575.     MOV     BP, SP              ; Set up Stack Frame
  576.  
  577.     OUT_16  SC_INDEX, ALL_PLANES_ON ; Select All Planes
  578.     LES     DI, d CURRENT_PAGE      ; Point to Active VGA Page
  579.  
  580.     MOV     AL, [BP].CVS_COLOR  ; Get Color
  581.     MOV     AH, AL              ; Copy for Word Write
  582.     CLD                         ; Block fill Forwards
  583.  
  584.     MOV     CX, PAGE_SIZE       ; Get Size of Page
  585.     SHR     CX, 1               ; Divied by 2 for Words
  586.     REP     STOSW               ; Block Fill VGA memory
  587.  
  588.     POP     DI                  ; Restore Saved Registers
  589.     POP     BP
  590.  
  591.     RET     2                   ;We are Done.. Outa here
  592.  
  593. CLEAR_VGA_SCREEN    ENDP
  594.  
  595.  
  596. ;===================================
  597. ;SET_POINT (Xpos%, Ypos%, ColorNum%)
  598. ;===================================
  599. ;
  600. ; Sets a single Pixel at (Xpos, Ypos) on the active 
  601. ; Display Page to color #ColorNum 
  602. ;
  603.  
  604. SP_STACK    STRUC
  605.                 DW  ?   ;BP
  606.                 DD  ?   ;Caller
  607.     SETP_Color  DB  ?,?
  608.     SETP_Ypos   DW  ?
  609.     SETP_Xpos   DW  ?
  610. SP_STACK    ENDS
  611.  
  612.         PUBLIC SET_POINT
  613.  
  614. SET_POINT   PROC    FAR
  615.  
  616.     PUSH    BP                  ; Preserve Registers
  617.     MOV     BP, SP              ; Set up Stack Frame
  618.  
  619.     LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page
  620.  
  621.     MOV     AX, [BP].SETP_Ypos  ; Get Line # of Pixel
  622.     MUL     SCREEN_WIDTH        ; Get Offset to Start of Line
  623.  
  624.     MOV     BX, [BP].SETP_Xpos  ; Get Xpos
  625.     MOV     CX, BX
  626.     SHR     BX, 2               ; X offset (Bytes) = Xpos/4
  627.     ADD     BX, AX              ; Offset = Width*Ypos + Xpos/4
  628.  
  629.     MOV     AX, MAP_MASK_PLANE1 ; Map Mask & Plane Select Register
  630.     AND     CL, PLANE_BITS      ; Get Plane Bits
  631.     SHL     AH, CL              ; Get Plane Select Value
  632.     MOV     DX, SC_Index        ; Setup to select plane
  633.     OUT     DX, AX              ; Select Plane...
  634.  
  635.     MOV     AL,[BP].SETP_Color  ; Get Pixel Color
  636.     MOV     ES:[DI+BX], AL      ; Draw Pixel
  637.  
  638.     POP     BP                  ; Restore Saved Registers
  639.     RET     6                   ; Exit and Clean up Stack
  640.  
  641. SET_POINT        ENDP
  642.  
  643.  
  644. ;==========================
  645. ;READ_POINT% (Xpos%, Ypos%)
  646. ;==========================
  647. ;
  648. ; Returns the color of a pixel from the Active Display Page 
  649. ; RETURNS:  AX = Color of Pixel at (Xpos, Ypos) 
  650. ;
  651.  
  652. RP_STACK    STRUC
  653.             DW  ?   ;Bp
  654.             DD  ?   ;Caller
  655.     RP_Ypos DW  ?
  656.     RP_Xpos DW  ?
  657. RP_STACK    ENDS
  658.  
  659.         PUBLIC  READ_POINT
  660.  
  661. READ_POINT      PROC    FAR
  662.  
  663.     PUSH    BP                  ; Preserve Registers
  664.     MOV     BP, SP              ; Set up Stack Frame
  665.  
  666.     LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page
  667.  
  668.     MOV     AX, [Bp].RP_Ypos    ; Get Line # of Pixel
  669.     MUL     SCREEN_WIDTH        ; Get Offset to Start of Line
  670.  
  671.     MOV     BX, [BP].RP_Xpos    ; Get Xpos
  672.     MOV     CX, BX
  673.     SHR     BX, 2               ; X offset (Bytes) = Xpos/4
  674.     ADD     BX, AX              ; Offset = Width*Ypos + Xpos/4
  675.  
  676.     MOV     AL, READ_MAP        ; GC Read Mask Register
  677.     MOV     AH, CL              ; Get Xpos
  678.     AND     AH, PLANE_BITS      ; & mask out Plane #
  679.     MOV     DX, GC_INDEX        ; Setup to select Read Mask
  680.     OUT     DX, AX              ; Select Read Plane...
  681.  
  682.     XOR     AX, AX              ; Clear Return Value
  683.  
  684.     MOV     AL, ES:[DI+BX]      ; Get Color of Pixel
  685.  
  686.     POP     BP                  ; Restore Saved Registers
  687.     RET     4                   ; Exit and Clean up Stack
  688.  
  689. READ_POINT        ENDP
  690.  
  691.  
  692. ;====================================================== 
  693. ;FILL_BLOCK (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) 
  694. ;====================================================== 
  695. ; Fills a block on the current display Page from Point 
  696. ; (Xpos1, Ypos1) to Point (Xpos2, Ypos2) in Color #ColorNum 
  697. ;
  698.  
  699. FB_STACK    STRUC
  700.                 DW  ?,?,?,? ; DS, DI, SI, BP
  701.                 DD  ?       ; Caller
  702.     FB_Color    DB  ?,?     ; Fill Color
  703.     FB_Ypos2    DW  ?       ; Lower Right Pixel
  704.     FB_Xpos2    DW  ?       ;
  705.     FB_Ypos1    DW  ?       ; Upper Left Pixel
  706.     FB_Xpos1    DW  ?       ;
  707. FB_STACK    ENDS
  708.  
  709.         PUBLIC    FILL_BLOCK
  710.  
  711. FILL_BLOCK  PROC    FAR
  712.  
  713.     PUSH    BP                  ; Save Registers
  714.     PUSH    SI
  715.     PUSH    DI
  716.     PUSH    DS
  717.  
  718.     MOV     BP, SP              ; Set up Stack Frame
  719.  
  720.     LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page
  721.     CLD                         ; Direction Flag = Forward
  722.  
  723.     OUT_8   SC_INDEX, MAP_MASK  ; Set up for Plane Select
  724.  
  725.     ; Validate Pixel Coordinates
  726.     ; If necessary, Swap so X1 <= X2, Y1 <= Y2
  727.  
  728.     MOV     AX, [BP].FB_Ypos1   ; AX = Y1   is Y1< Y2?
  729.     MOV     BX, [BP].FB_Ypos2   ; BX = Y2
  730.     CMP     AX, BX
  731.     JLE     @FB_NOSWAP1
  732.  
  733.     MOV     [BP].FB_Ypos1, BX   ; Swap Y1 and Y2 and save Y1
  734.     XCHG    AX, BX              ; on stack for future use
  735.  
  736. @FB_NOSWAP1:
  737.     SUB     BX, AX              ; Get Y width
  738.     INC     BX                  ; Add 1 to avoid 0 value
  739.     MOV     [BP].FB_Ypos2, BX   ; Save in Ypos2
  740.  
  741.     MUL     SCREEN_WIDTH        ; Mul Y1 by Bytes per Line
  742.     ADD     DI, AX              ; DI = Start of Line Y1
  743.  
  744.     MOV     AX, [BP].FB_Xpos1   ; Check X1 <= X2
  745.     MOV     BX, [BP].FB_Xpos2   ;
  746.     CMP     AX, BX
  747.     JLE     @FB_NOSWAP2         ; Skip Ahead if Ok
  748.  
  749.     MOV     [BP].FB_Xpos2, AX   ; Swap X1 AND X2 and save X2
  750.     XCHG    AX, BX              ; on stack for future use
  751.  
  752.     ; All our Input Values are in order, Now determine
  753.     ; How many full "bands" 4 pixels wide (aligned) there
  754.     ; are, and if there are partial bands (<4 pixels) on
  755.     ; the left and right edges.
  756.  
  757. @FB_NOSWAP2:
  758.     MOV     DX, AX              ; DX = X1 (Pixel Position)
  759.     SHR     DX, 2               ; DX/4 = Bytes into Line
  760.     ADD     DI, DX              ; DI = Addr of Upper-Left Corner
  761.  
  762.     MOV     CX, BX              ; CX = X2 (Pixel Position)
  763.     SHR     CX, 2               ; CX/4 = Bytes into Line
  764.  
  765.     CMP     DX, CX              ; Start and end in same band?
  766.     JNE     @FB_NORMAL          ; if not, check for l & r edges
  767.     JMP     @FB_ONE_BAND_ONLY   ; if so, then special processing
  768.  
  769. @FB_NORMAL:
  770.     SUB     CX, DX              ; CX = # bands -1
  771.     MOV     SI, AX              ; SI = PLANE#(X1)
  772.     AND     SI, PLANE_BITS          ; if Left edge is aligned then ..
  773.     JZ      @FB_LEFT_PLANE_FLUSH    ; no special processing..
  774.  
  775.     ; Draw "Left Edge" vertical strip of 1-3 pixels...
  776.  
  777.     OUT_8   SC_Data, LEFT_CLIP_MASK[SI] ; Set Left Edge Plane Mask
  778.  
  779.     MOV     SI, DI              ; SI = Copy of Start Addr (UL)
  780.  
  781.     MOV     DX, [BP].FB_Ypos2   ; Get # of Lines to draw
  782.     MOV     AL, [BP].FB_Color   ; Get Fill Color
  783.     MOV     BX, SCREEN_WIDTH    ; Get Vertical increment Value
  784.  
  785. @FB_LEFT_LOOP:
  786.     MOV     ES:[SI], AL         ; Fill in Left Edge Pixels
  787.     ADD     SI, BX              ; Point to Next Line (Below)
  788.     DEC     DX                  ; Lines to go--
  789.     JZ      @FB_LEFT_CONT       ; Exit loop if all Lines Drawn
  790.  
  791.     MOV     ES:[SI], AL         ; Fill in Left Edge Pixels
  792.     ADD     SI, BX              ; Point to Next Line (Below)
  793.     DEC     DX                  ; Lines to go--
  794.     JNZ     @FB_LEFT_LOOP       ; loop until left strip is drawn
  795.  
  796. @FB_LEFT_CONT:
  797.  
  798.     INC     DI                  ; Point to Middle (or Right) Block
  799.     DEC     CX                  ; Reset CX insted of JMP @FB_RIGHT
  800.  
  801. @FB_LEFT_PLANE_FLUSH:
  802.     INC     CX                  ; Add in Left band to middle block
  803.  
  804.     ;DI = Addr of 1st middle Pixel (band) to fill
  805.     ;CX = # of Bands to fill -1
  806.  
  807. @FB_RIGHT:
  808.     MOV     SI, [BP].FB_Xpos2       ; Get Xpos2
  809.     AND     SI, PLANE_BITS          ; Get Plane values
  810.     CMP     SI, 0003                ; Plane = 3?
  811.     JE      @FB_RIGHT_EDGE_FLUSH    ; Hey, add to middle
  812.  
  813.     ; Draw "Right Edge" vertical strip of 1-3 pixels...
  814.  
  815.     OUT_8   SC_Data, RIGHT_CLIP_MASK[SI]    ; Set Right Edge Plane Mask
  816.  
  817.     MOV     SI, DI              ; Get Addr of Left Edge
  818.     ADD     SI, CX              ; Add Width-1 (Bands)
  819.     DEC     SI                  ; To point to top of Right Edge
  820.  
  821.     MOV     DX, [BP].FB_Ypos2   ; Get # of Lines to draw
  822.     MOV     AL, [BP].FB_Color   ; Get Fill Color
  823.     MOV     BX, SCREEN_WIDTH    ; Get Vertical increment Value
  824.  
  825. @FB_RIGHT_LOOP:
  826.     MOV     ES:[SI], AL         ; Fill in Right Edge Pixels
  827.     ADD     SI, BX              ; Point to Next Line (Below)
  828.     DEC     DX                  ; Lines to go--
  829.     JZ      @FB_RIGHT_CONT      ; Exit loop if all Lines Drawn
  830.  
  831.     MOV     ES:[SI], AL         ; Fill in Right Edge Pixels
  832.     ADD     SI, BX              ; Point to Next Line (Below)
  833.     DEC     DX                  ; Lines to go--
  834.     JNZ     @FB_RIGHT_LOOP      ; loop until left strip is drawn
  835.  
  836. @FB_RIGHT_CONT:
  837.  
  838.     DEC     CX                  ; Minus 1 for Middle bands
  839.     JCXZ    @FB_EXIT            ; Uh.. no Middle bands...
  840.  
  841. @FB_RIGHT_EDGE_FLUSH:
  842.  
  843.     ;DI = Addr of Upper Left block to fill
  844.     ;CX = # of Bands to fill in (width)
  845.  
  846.     OUT_8   SC_Data, 0FH        ; Write to All Planes
  847.  
  848.     MOV     DX, SCREEN_WIDTH    ; DX = DI Incrament
  849.     SUB     DX, CX              ;  = Screen_Width-# Planes Filled
  850.  
  851.     MOV     BX, CX              ; BX = Quick Refill for CX
  852.     MOV     SI, [BP].FB_Ypos2   ; SI = # of Line to Fill
  853.     MOV     AL, [BP].FB_Color   ; Get Fill Color
  854.  
  855. @FB_MIDDLE_LOOP:
  856.     REP     STOSB               ; Fill in entire line
  857.  
  858.     MOV     CX, BX              ; Recharge CX (Line Width)
  859.     ADD     DI, DX              ; Point to start of Next Line
  860.  
  861.     DEC     SI                  ; Lines to go--
  862.     JNZ     @FB_MIDDLE_LOOP     ; Loop until all lines drawn
  863.  
  864.     JMP     @FB_EXIT            ; Outa here
  865.  
  866. @FB_ONE_BAND_ONLY:
  867.     MOV     SI, AX                  ; Get Left CLip Mask, Save X1
  868.     AND     SI, PLANE_BITS          ; Mask out Row #
  869.     MOV     AL, LEFT_CLIP_MASK[SI]  ; Get Left Edge Mask
  870.     MOV     SI, BX                  ; Get Right Clip Mask, Save X2
  871.     AND     SI, PLANE_BITS          ; Mask out Row #
  872.     AND     AL, RIGHT_CLIP_MASK[SI] ; Get Right Edge Mask byte
  873.  
  874.     MOV     DX, SC_Data         ; Plane Selection
  875.     OUT     DX, AL              ; Clip For Left & Right Masks
  876.  
  877.     MOV     CX, [BP].FB_Ypos2   ; Get # of Lines to draw
  878.     MOV     AL, [BP].FB_Color   ; Get Fill Color
  879.     MOV     BX, SCREEN_WIDTH    ; Get Vertical increment Value
  880.  
  881. @FB_ONE_LOOP:
  882.     MOV     ES:[DI], AL         ; Fill in Pixels
  883.     ADD     DI, BX              ; Point to Next Line (Below)
  884.     DEC     CX                  ; Lines to go--
  885.     JZ      @FB_EXIT            ; Exit loop if all Lines Drawn
  886.  
  887.     MOV     ES:[DI], AL         ; Fill in Pixels
  888.     ADD     DI, BX              ; Point to Next Line (Below)
  889.     DEC     CX                  ; Lines to go--
  890.     JNZ     @FB_ONE_LOOP        ; loop until left strip is drawn
  891.  
  892. @FB_EXIT:
  893.     POP     DS
  894.     POP     DI
  895.     POP     SI
  896.     POP     BP                  ; Restore Registers
  897.  
  898.     RET     10                  ; Exit and Clean up Stack
  899.  
  900. FILL_BLOCK   ENDP
  901.  
  902.  
  903. ;===================================================== 
  904. ;DRAW_LINE (Xpos1%, Ypos1%, Xpos2%, Ypos2%, ColorNum%) 
  905. ;===================================================== 
  906. ; Draws a Line from (X1,Y1) to (X2,Y2) in Color #ColorNum 
  907. ; in VGA Mode X 
  908. ;
  909.  
  910. DL_STACK    STRUC
  911.                 DW  ?,?,?   ;DI, SI , BP
  912.                 DD  ?       ;Caller
  913.     DL_ColorF   DB  ?,?
  914.     DL_Ypos2    DW  ?
  915.     DL_Xpos2    DW  ?
  916.     DL_Ypos1    DW  ?
  917.     DL_Xpos1    DW  ?
  918. DL_STACK    ENDS
  919.  
  920.         PUBLIC DRAW_LINE
  921.  
  922. DRAW_LINE   PROC    FAR
  923.  
  924.     PUSH    BP                  ; Save Registers
  925.     PUSH    SI
  926.     PUSH    DI
  927.  
  928.     MOV     BP, SP              ; Set up Stack Frame
  929.     CLD                         ; Direction Flag = Forward
  930.  
  931.     OUT_8   SC_INDEX, MAP_MASK  ; Set up for Plane Select
  932.  
  933.     MOV     CH, [BP].DL_ColorF  ; Save Color in CH
  934.  
  935.     ;Check Line Type
  936.  
  937.     MOV     SI, [BP].DL_Xpos1   ; AX = X1   is X1< X2?
  938.     MOV     DI, [BP].DL_Xpos2   ; DX = X2
  939.     CMP     SI, DI              ; Is X1 < X2
  940.     JE      @DL_VLINE           ; If X1=X2, Draw Vertical Line
  941.     JL      @DL_NOSWAP1         ; If X1 < X2, don't swap
  942.  
  943.     XCHG    SI, DI              ; X2 IS > X1, SO SWAP THEM
  944.  
  945. @DL_NOSWAP1:
  946.  
  947.     ; SI = X1, DI = X2
  948.  
  949.     MOV     AX, [BP].DL_Ypos1   ; AX = Y1   is Y1 <> Y2?
  950.     CMP     AX, [BP].DL_Ypos2   ; Y1 = Y2?
  951.     JE      @DL_HORZ            ; If so, Draw a Horizontal Line
  952.  
  953.     JMP     @DL_BREZHAM         ; Diagonal line... go do it...
  954.  
  955.     ; This Code draws a Horizontal Line in Mode X where:
  956.     ; SI = X1, DI = X2, and AX = Y1/Y2
  957.  
  958. @DL_HORZ:
  959.  
  960.     MUL     SCREEN_WIDTH        ; Offset = Ypos * Screen_Width
  961.     MOV     DX, AX              ; CX = Line offste into Page
  962.  
  963.     MOV     AX, SI                  ; Get Left Edge CLip Mask, Save X1
  964.     AND     SI, PLANE_BITS          ; Mask out Row #
  965.     MOV     BL, LEFT_CLIP_MASK[SI]  ; Get Left Edge Mask
  966.     MOV     CX, DI                  ; Get Right Edge Clip Mask, Save X2
  967.     AND     DI, PLANE_BITS          ; Mask out Row #
  968.     MOV     BH, RIGHT_CLIP_MASK[DI] ; Get Right Edge Mask byte
  969.  
  970.     SHR     AX, 2               ; Get X1 Byte # (=X1/4)
  971.     SHR     CX, 2               ; Get X2 Byte # (=X2/4)
  972.  
  973.     LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page
  974.     ADD     DI, DX              ; Point to Start of Line
  975.     ADD     DI, AX              ; Point to Pixel X1
  976.  
  977.     SUB     CX, AX              ; CX = # Of Bands (-1) to set
  978.     JNZ     @DL_LONGLN          ; If longer than one segment, go ahead
  979.  
  980.     AND     BL, BH              ; otherwise, megre clip masks
  981.  
  982. @DL_LONGLN:
  983.  
  984.     OUT_8   SC_Data, BL         ; Set the Left Clip Mask
  985.  
  986.     MOV     AL, [BP].DL_ColorF  ; Get Line Color
  987.     MOV     BL, AL              ; BL = Copy of Line Color
  988.     STOSB                       ; Set Left (1-4) Pixels
  989.  
  990.     JCXZ    @DL_EXIT            ; Done if only one Line Segment
  991.  
  992.     DEC     CX                  ; CX = # of Middle Segemnts
  993.     JZ      @DL_XRSEG           ; If no middle segments....
  994.  
  995.     ;Draw Middle Segments
  996.  
  997.     MOV     AL, ALL_PLANES      ; Write to ALL Planes
  998.     OUT     DX, AL              ; Select Planes
  999.  
  1000.     MOV     AL, BL              ; Get Color from BL
  1001.     REP     STOSB               ; Draw Middle (4 Pixel) Segements
  1002.  
  1003. @DL_XRSEG:
  1004.     MOV     AL, BH              ; Get Right Clip Mask
  1005.     OUT     DX, AL              ; Select Planes
  1006.  
  1007.     MOV     AL, BL              ; Get Color Value
  1008.     STOSB                       ; Draw Right (1-4) Pixels
  1009.  
  1010.     JMP SHORT @DL_EXIT          ; We Are Done...
  1011.  
  1012.     ; This Code Draws A Vertical Line.  On entry:
  1013.     ; CH = Line Color, SI & DI = X1
  1014.  
  1015. @DL_VLINE:
  1016.  
  1017.     MOV     AX, [BP].DL_Ypos1   ; AX = Y1
  1018.     MOV     SI, [BP].DL_Ypos2   ; SI = Y2
  1019.     CMP     AX, SI              ; Is Y1 < Y2?
  1020.     JLE     @DL_NOSWAP2         ; if so, Don't Swap them
  1021.  
  1022.     XCHG    AX, SI              ; Ok, NOW Y1 < Y2
  1023.  
  1024. @DL_NOSWAP2:
  1025.  
  1026.     SUB     SI, AX              ; SI = Line Heigth (Y2-Y1+1)
  1027.     INC     SI
  1028.  
  1029.     ; AX = Y1, DI = X1, Get offset into Page into AX
  1030.  
  1031.     MUL     SCREEN_WIDTH        ; Offset = Y1 (AX) * Screen Width
  1032.     MOV     DX, DI              ; Copy Xpos into DX
  1033.     SHR     DI, 2               ; DI = Xpos/4
  1034.     ADD     AX, DI              ; DI = Xpos/4 + ScreenWidth * Y1
  1035.  
  1036.     LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page
  1037.     ADD     DI, AX              ; Point to Pixel X1, Y1
  1038.  
  1039.     ;Select Plane
  1040.  
  1041.     MOV     CL, DL              ; CL = Save X1
  1042.     AND     CL, PLANE_BITS      ; Get X1 MOD 4 (Plane #)
  1043.     MOV     AX, MAP_MASK_PLANE1 ; Code to set Plane #1
  1044.     SHL     AH, CL              ; Change to Correct Plane #
  1045.  
  1046.     MOV     DX, SC_Index        ; Set VGA Sequencer
  1047.     OUT     DX, AX              ; Select Plane!
  1048.  
  1049.     MOV     AL, CH              ; Get Saved Color
  1050.     MOV     BX, SCREEN_WIDTH    ; Get Offset to Advance Line By
  1051.  
  1052. @DL_VLoop:
  1053.     MOV     ES:[DI], AL         ; Draw Single Pixel
  1054.     ADD     DI, BX              ; Point to Next Line
  1055.  
  1056.     DEC     SI                  ; Lines to draw--
  1057.     JNZ     @DL_VLoop           ; Loop until Done
  1058.  
  1059. @DL_EXIT:
  1060.  
  1061.     JMP @DL_EXIT2               ; Done!
  1062.  
  1063.     ; This code Draws a diagonal line in Mode X
  1064.  
  1065. @DL_BREZHAM:
  1066.     LES     DI, d CURRENT_PAGE  ; Point to Active VGA Page
  1067.  
  1068.     MOV     AX, [BP].DL_Ypos1   ; get y1 value
  1069.     MOV     BX, [BP].DL_Ypos2   ; get y2 value
  1070.     MOV     CX, [BP].DL_Xpos1   ; Get Starting Xpos
  1071.  
  1072.     CMP     BX, AX              ; Y2-Y1 is?
  1073.     JNC     @DL_DeltaYOK        ; if Y2>=Y1 then goto...
  1074.  
  1075.     XCHG    BX, AX              ; Swap em...
  1076.     MOV     CX, [BP].DL_Xpos2   ; Get New Starting Xpos
  1077.  
  1078. @DL_DeltaYOK:
  1079.     MUL     SCREEN_WIDTH        ; Offset = SCREEN_WIDTH * Y1
  1080.  
  1081.     ADD     DI, AX              ; DI -> Start of Line Y1 on Page
  1082.     MOV     AX, CX              ; AX = Xpos (X1)
  1083.     SHR     AX, 2               ; /4 = Byte Offset into Line
  1084.     ADD     DI, AX              ; DI = Starting pos (X1,Y1)
  1085.  
  1086.     MOV     AL, 11h             ; Staring Mask
  1087.     AND     CL, PLANE_BITS      ; Get Plane #
  1088.     SHL     AL, CL              ; and shift into placE
  1089.     MOV     AH, [BP].DL_ColorF  ; Color in Hi Bytes
  1090.  
  1091.     PUSH    AX                  ; Save Mask,Color...
  1092.  
  1093.     MOV     DX, SC_Index
  1094.     MOV     AH, AL              ; Plane # in AH
  1095.     MOV     AL, MAP_MASK        ; Select Plane Register
  1096.     OUT     DX, AX              ; Select initial plane
  1097.  
  1098.     MOV     AX, [BP].DL_Xpos1   ; get x1 value
  1099.     MOV     BX, [BP].DL_Ypos1   ; get y1 value
  1100.     MOV     CX, [BP].DL_Xpos2   ; get x2 value
  1101.     MOV     DX, [BP].DL_Ypos2   ; get y2 value
  1102.  
  1103.     MOV     BP, SCREEN_WIDTH    ; Use BP for Line width to
  1104.                                 ; to avoid extra memory access
  1105.  
  1106.     SUB     DX, BX              ; figure delta_y
  1107.     JNC     @DL_DeltaYOK2       ; jump if y2>=y1
  1108.  
  1109.     ADD     BX, DX              ; put y2 into y1
  1110.     NEG     DX                  ; abs(Delta_y)
  1111.     XCHG    AX, CX              ; and exchange x1 and x2
  1112.  
  1113. @DL_DeltaYOK2:
  1114.     MOV     BX, 08000H          ; seed for fraction accumulator
  1115.  
  1116.     SUB     CX, AX              ; figure delta_x
  1117.     JC      @DL_DrawLeft        ; if negitive, go left
  1118.  
  1119.     JMP     @DL_DrawRight       ; Draw Line that slopes right
  1120.  
  1121. @DL_DrawLeft:
  1122.  
  1123.     NEG     CX                  ; abs(Delta_X)
  1124.  
  1125.     CMP     CX, DX              ; is X < Delta_Y?
  1126.     JB      @DL_SteepLeft       ; yes, so go do steep line (Delta_Y iterations)
  1127.  
  1128.     ; Draw a Shallow line to the left in Mode X
  1129.  
  1130. @DL_ShallowLeft:
  1131.     XOR     AX, AX              ; zero low word of Delta_y * 10000h
  1132.     SUB     AX, DX              ; DX:AX <- DX * 0FFFFh
  1133.     SBB     DX, 0
  1134.     DIV     CX                  ; divide by Delta_X
  1135.  
  1136.     MOV     SI, BX              ; Si = Acculmulator
  1137.     MOV     BX, AX              ; Bx = Addor
  1138.     POP     AX                  ; Get Color, Bit mask
  1139.     MOV     DX, SC_Data         ; Sequence controller data register
  1140.     INC     CX                  ; Inc Delta_X so we can unroll loop
  1141.  
  1142.     ; Loop (x2) to Draw Pixels, Move Left, and Maybe Down...
  1143.  
  1144. @DL_SLLLoop:
  1145.     MOV     ES:[DI], AH         ; set first pixel, plane data set up
  1146.  
  1147.     DEC     CX                  ; count down Delta_X
  1148.     JZ      @DL_SLLExit         ; Exit if done..
  1149.  
  1150.     ADD     SI, BX              ; add numerator to accumulator
  1151.     JNC     @DL_SLLL2nc         ; move down on carry
  1152.  
  1153.     ADD     DI, BP              ; Move Down one line...
  1154.  
  1155. @DL_SLLL2nc:
  1156.     DEC     DI                  ; Left one addr
  1157.     ROR     AL, 1               ; Move Left one plane
  1158.     CMP     AL, 87h             ; Skipped around?, if AL <88 then Carry set
  1159.     ADC     DI, 0               ; Adjust Address: DI = Di + Carry, ie. plane =
  1160.     OUT     DX, AL              ; Set up New Bit Plane mask
  1161.  
  1162.     MOV     ES:[DI], AH         ; set pixel
  1163.  
  1164.     ADD     SI, BX              ; add numerator to accumulator,
  1165.     JNC     @DL_SLLL3nc         ; move down on carry
  1166.  
  1167.     ADD     DI, BP              ; Move Down one line...
  1168.  
  1169. @DL_SLLL3nc:                    ; Now move left a pixel...
  1170.     DEC     DI                  ; Left one addr
  1171.     ROR     AL, 1               ; Move Left one plane
  1172.     CMP     AL, 87h             ; Skipped around?, if AL <88 then Carry set
  1173.     ADC     DI, 0               ; Adjust Address: DI = Di + Carry, ie. plane =
  1174.     OUT     DX, AL              ; Set up New Bit Plane mask
  1175.  
  1176.     DEC     CX                  ; count down Delta_X
  1177.     JNZ     @DL_SLLLoop         ; loop till done
  1178.  
  1179. @DL_SLLExit:
  1180.     JMP     @DL_EXIT2           ; and exit
  1181.  
  1182.     ; Draw a steep line to the left in Mode X
  1183.  
  1184. @DL_SteepLeft:
  1185.     XOR     AX, AX              ; zero low word of Delta_y * 10000h
  1186.     XCHG    DX, CX              ; Delta_Y switched with Delta_x
  1187.     DIV     CX                  ; divide by Delta_Y
  1188.  
  1189.     MOV     SI, BX              ; Si = Acculmulator
  1190.     MOV     BX, AX              ; Bx = Addor
  1191.     POP     AX                  ; Get Color, Bit mask
  1192.     MOV     DX, SC_Data         ; Sequence controller data register
  1193.     INC     CX                  ; Inc Delta_Y so we can unroll loop
  1194.  
  1195.     ; Loop (x2) to Draw Pixels, Move Down, and Maybe left
  1196.  
  1197. @DL_STLLoop:
  1198.  
  1199.     MOV     ES:[DI], AH         ; set first pixel
  1200.     DEC     CX                  ; Count Down Delta_Y
  1201.     JZ      @DL_STLExit         ; Exit if done
  1202.  
  1203.     ADD     SI, BX              ; add numerator to accumulator
  1204.     JNC     @DL_STLnc2          ; No carry, just move down!
  1205.  
  1206.     ; Move Left
  1207.  
  1208.     DEC     DI                  ; Left one addr
  1209.     ROR     AL, 1               ; Move Left one plane
  1210.     CMP     AL, 87h             ; Skipped around?, if AL <88 then Carry set
  1211.     ADC     DI, 0               ; Adjust Address: DI = Di + Carry, ie. plane =
  1212.     OUT     DX, AL              ; Set up New Bit Plane mask
  1213.  
  1214. @DL_STLnc2:
  1215.     ADD     DI, BP              ; advance to next line.
  1216.  
  1217.     MOV     ES:[DI], AH         ; set pixel
  1218.     ADD     SI, BX              ; add numerator to accumulator
  1219.     JNC     @DL_STLnc3          ; No carry, just move down!
  1220.  
  1221.     ;Move Left
  1222.  
  1223.     DEC     DI                  ; Left one addr
  1224.     ROR     AL, 1               ; Move Left one plane
  1225.     CMP     AL, 87h             ; Skipped around?, if AL <88 then Carry set
  1226.     ADC     DI, 0               ; Adjust Address: DI = Di + Carry, ie. plane =
  1227.     OUT     DX, AL              ; Set up New Bit Plane mask
  1228.  
  1229. @DL_STLnc3:
  1230.     ADD     DI, BP              ; advance to next line.
  1231.  
  1232.     DEC     CX                  ; count down Delta_Y
  1233.     JNZ     @DL_STLLoop         ; loop till done
  1234.  
  1235. @DL_STLExit:
  1236.     JMP     @DL_EXIT2           ; and exit
  1237.  
  1238.     ; Draw A line that goes to the Right...
  1239.  
  1240. @DL_DrawRight:
  1241.     CMP     CX, DX              ; is X < Delta_Y?
  1242.     JB      @DL_SteepRight      ; yes, so go do steep line (Delta_Y iterations)
  1243.  
  1244.     ; Draw a Shallow line to the Right in Mode X
  1245.  
  1246. @DL_ShallowRight:
  1247.     XOR     AX, AX              ; zero low word of Delta_y * 10000h
  1248.     SUB     AX, DX              ; DX:AX <- DX * 0FFFFh
  1249.     SBB     DX, 0
  1250.     DIV     CX                  ; divide by Delta_X
  1251.  
  1252.     MOV     SI, BX              ; Si = Acculmulator
  1253.     MOV     BX, AX              ; Bx = Addor
  1254.     POP     AX                  ; Get Color, Bit mask
  1255.     MOV     DX, SC_Data         ; Sequence controller data register
  1256.     INC     CX                  ; Inc Delta_X so we can unroll loop
  1257.  
  1258.     ; Loop (x2) to Draw Pixels, Move Right, and Maybe Down...
  1259.  
  1260. @DL_SLRLoop:
  1261.     MOV     ES:[DI], AH         ; set first pixel, mask already set up
  1262.  
  1263.     DEC     CX                  ; count down Delta_X
  1264.     JZ      @DL_SLRExit         ; Exit if done..
  1265.  
  1266.     ADD     SI, BX              ; add numerator to accumulator
  1267.     JNC     @DL_SLR2nc          ; don't move down if carry not set....
  1268.  
  1269.     ADD     DI, BP              ; Move Down one line...
  1270.  
  1271. @DL_SLR2nc:                     ; Now move right a pixel...
  1272.     ROL     AL, 1               ; Move Right one plane
  1273.     CMP     AL, 12h             ; Skipped around?, if AL >12 then Carry not set
  1274.     ADC     DI, 0               ; Adjust Address: DI = Di + Carry, ie. plane =
  1275.     OUT     DX, AL              ; Set up New Bit Plane mask
  1276.  
  1277.     MOV     ES:[DI], AH         ; set pixel
  1278.     ADD     SI, BX              ; add numerator to accumulator
  1279.     JNC     @DL_SLR3nc          ; don't move down if carry not set....
  1280.  
  1281.     ADD     DI, BP              ; Move Down one line...
  1282.  
  1283. @DL_SLR3nc:
  1284.     ROL     AL, 1               ; Move Right one plane
  1285.     CMP     AL, 12h             ; Skipped around?, if AL >12 then Carry not set
  1286.     ADC     DI, 0               ; Adjust Address: DI = Di + Carry, ie. plane =
  1287.     OUT     DX, AL              ; Set up New Bit Plane mask
  1288.  
  1289.     DEC     CX                  ; count down Delta_X
  1290.     JNZ     @DL_SLRLoop         ; loop till done
  1291.  
  1292. @DL_SLRExit:
  1293.     JMP     @DL_EXIT2           ; and exit
  1294.  
  1295.     ; Draw a Shallow line to the Right in Mode X
  1296.  
  1297. @DL_SteepRight:
  1298.     XOR     AX, AX              ; zero low word of Delta_y * 10000h
  1299.     XCHG    DX, CX              ; Delta_Y switched with Delta_x
  1300.     DIV     CX                  ; divide by Delta_Y
  1301.  
  1302.     MOV     SI, BX              ; Si = Acculmulator
  1303.     MOV     BX, AX              ; Bx = Addor
  1304.     POP     AX                  ; Get Color, Bit mask
  1305.     MOV     DX, SC_Data         ; Sequence controller data register
  1306.     INC     CX                  ; Inc Delta_Y so we can unroll loop
  1307.  
  1308.     ; Loop (x2) to Draw Pixels, Move Down, and Maybe Right
  1309.  
  1310. @STRLoop:
  1311.     MOV     ES:[DI], AH         ; set first pixel, mask already set up...
  1312.  
  1313.     DEC     CX                  ; count down Delta_Y
  1314.     JZ      @DL_EXIT2           ; Exit if Finished
  1315.  
  1316.     ADD     SI, BX              ; add numerator to accumulator
  1317.     JNC     @STRnc2             ; if no carry then just go down...
  1318.  
  1319.     ROL     AL, 1               ; Move Right one plane
  1320.     CMP     AL, 12h             ; Skipped around?, if AL >12 then Carry not set
  1321.     ADC     DI, 0               ; Adjust Address: DI = Di + Carry, ie. plane =
  1322.     OUT     DX, AL              ; Set up New Bit Plane mask
  1323.  
  1324. @STRnc2:
  1325.     ADD     DI, BP              ; advance to next line.
  1326.  
  1327.     MOV     ES:[DI], AH         ; set pixel
  1328.     ADD     SI, BX              ; add numerator to accumulator
  1329.     JNC     @STRnc3             ; if no carry then just go down...
  1330.  
  1331.     ROL     AL, 1               ; Move Right one plane
  1332.     CMP     AL, 12h             ; Skipped around?, if AL >12 then Carry not set
  1333.     ADC     DI, 0               ; Adjust Address: DI = Di + Carry, ie. plane =
  1334.     OUT     DX, AL              ; Set up New Bit Plane mask
  1335.  
  1336. @STRnc3:
  1337.     ADD     DI, BP              ; advance to next line.
  1338.  
  1339.     DEC     CX                  ; count down Delta_Y
  1340.     JNZ     @STRLoop            ; loop till done
  1341.  
  1342. @DL_EXIT2:
  1343.  
  1344.     POP     DI
  1345.     POP     SI
  1346.     POP     BP                  ; Restore BP, SI, & DI
  1347.  
  1348.     RET     10                  ; Exit and Clean up Stack
  1349.  
  1350. DRAW_LINE        ENDP
  1351.  
  1352.  
  1353. ;=========================
  1354. ;SET_ACTIVE_PAGE (PageNo%)
  1355. ;=========================
  1356. ;
  1357. ;Sets the Video Page to be used for future drawing 
  1358. ;
  1359.  
  1360. SAP_STACK   STRUC
  1361.                 DW  ?       ;BP
  1362.                 DD  ?       ;Caller
  1363.     SAP_Page    DW  ?       ;Page # for Drawing 
  1364. SAP_STACK   ENDS
  1365.  
  1366.     PUBLIC  SET_ACTIVE_PAGE
  1367.  
  1368. SET_ACTIVE_PAGE PROC    FAR
  1369.  
  1370.     PUSH    BP                  ; Preserve Registers
  1371.     MOV     BP, SP              ; Set up Stack Frame
  1372.  
  1373.     MOV     BX, [BP].SAP_Page   ; Get Desired Page #
  1374.     CMP     BX, LAST_PAGE       ; Is Page # Valid?
  1375.     JAE     @SAP_Exit           ; IF Not, Do Nothing
  1376.  
  1377.     MOV     ACTIVE_PAGE, BX     ; Set Active Page #
  1378.  
  1379.     SHL     BX, 1               ; Scale Page # to Word
  1380.     MOV     AX, PAGE_ADDR[BX]   ; Get offset to Page
  1381.  
  1382.     MOV     CURRENT_PAGE, AX    ; And set for future LES's
  1383.  
  1384. @SAP_Exit:
  1385.     POP     BP                  ; Restore Registers
  1386.  
  1387.     RET     2                   ; We are Done.. Outa here
  1388.  
  1389. SET_ACTIVE_PAGE ENDP
  1390.  
  1391.  
  1392. ;================
  1393. ;GET_ACTIVE_PAGE%
  1394. ;================
  1395. ;
  1396. ; Returns the Video Page # currently used for Drawing 
  1397. ; RETURNS:   AX = Current Video Page used for Drawing 
  1398. ;
  1399.  
  1400.     PUBLIC  GET_ACTIVE_PAGE
  1401.  
  1402. GET_ACTIVE_PAGE PROC    FAR
  1403.  
  1404.     MOV     AX, ACTIVE_PAGE     ; Get Active Page #
  1405.  
  1406.     RET                         ; We are Done.. Outa here
  1407.  
  1408. GET_ACTIVE_PAGE ENDP
  1409.  
  1410.  
  1411. ;==========================
  1412. ;SET_DISPLAY_PAGE (PageNo%)
  1413. ;==========================
  1414. ;
  1415. ;Sets the Video Page to be displayed on the screen 
  1416. ;
  1417.  
  1418.  
  1419. SDP_STACK   STRUC
  1420.                 DW  ?       ;BP
  1421.                 DD  ?       ;Caller
  1422.     SDP_Page    DW  ?       ;Page # to Display... 
  1423. SDP_STACK   ENDS
  1424.  
  1425.     PUBLIC  SET_DISPLAY_PAGE
  1426.  
  1427. SET_DISPLAY_PAGE    PROC    FAR
  1428.  
  1429.     PUSH    BP                  ; Preserve Registers
  1430.     MOV     BP, SP              ; Set up Stack Frame
  1431.  
  1432.     MOV     BX, [BP].SDP_Page   ; Get Desired Page #
  1433.     CMP     BX, LAST_PAGE       ; Is Page # Valid?
  1434.     JAE     @SDP_Exit           ; IF Not, Do Nothing
  1435.  
  1436.     MOV     DISPLAY_PAGE, BX    ; Set Display Page #
  1437.  
  1438.     SHL     BX, 1               ; Scale Page # to Word
  1439.     MOV     CX, PAGE_ADDR[BX]   ; Get offset in memory to Page
  1440.  
  1441.     ADD     CX, CURRENT_MOFFSET ; Adjust for any scrolling
  1442.  
  1443.     MOV     DX, CRTC_Index      ; We Change the VGA Sequencer
  1444.     MOV     AL, START_DISP_LO   ; Display Start Low Register
  1445.     MOV     AH, CL              ; Low 8 Bits of Start Addr
  1446.     OUT     DX, AX              ; Set Display Addr Low
  1447.  
  1448.     MOV     AL, START_DISP_HI   ; Display Start High Register
  1449.     MOV     AH, CH              ; High 8 Bits of Start Addr
  1450.     OUT     DX, AX              ; Set Display Addr High
  1451.  
  1452. @SDP_Exit:
  1453.     POP     BP                  ; Restore Registers
  1454.  
  1455.     RET     2                   ; We are Done.. Outa here
  1456.  
  1457. SET_DISPLAY_PAGE    ENDP
  1458.  
  1459.  
  1460. ;=================
  1461. ;GET_DISPLAY_PAGE%
  1462. ;=================
  1463. ;
  1464. ; Returns the Video Page # currently be displayed on the screen 
  1465. ; RETURNS: AX = Current Display Page 
  1466. ;
  1467.  
  1468.     PUBLIC  GET_DISPLAY_PAGE
  1469.  
  1470. GET_DISPLAY_PAGE    PROC    FAR
  1471.  
  1472.     MOV     AX, DISPLAY_PAGE    ; Get Display Page #
  1473.  
  1474.     RET                         ; We are Done.. Outa here
  1475.  
  1476. GET_DISPLAY_PAGE    ENDP
  1477.  
  1478.  
  1479. ;================================================= 
  1480. ;SET_DAC_REGISTER (Register%, Red%, Green%, Blue%) 
  1481. ;================================================= 
  1482. ; Sets a single (RGB) Vga Palette Register 
  1483. ; to the specified Reg, Green & Blue Values 
  1484. ;
  1485.  
  1486. SDR_STACK   STRUC
  1487.                     DW  ?   ; BP
  1488.                     DD  ?   ; Caller
  1489.     SDR_Blue        DB  ?,? ; Blue Data Value
  1490.     SDR_Green       DB  ?,? ; Green Data Value
  1491.     SDR_Red         DB  ?,? ; Red Data Value
  1492.     SDR_Register    DB  ?,? ; Palette Register # 
  1493. SDR_STACK   ENDS
  1494.  
  1495.     PUBLIC  SET_DAC_REGISTER
  1496.  
  1497. SET_DAC_REGISTER    PROC    FAR
  1498.  
  1499.     PUSH    BP                  ; Save Bp
  1500.     MOV     BP, SP              ; Set up Stack Frame
  1501.  
  1502.     ; Select which DAC Register to modify
  1503.  
  1504.     OUT_8   DAC_WRITE_ADDR, [BP].SDR_Register
  1505.  
  1506.     MOV     DX, PEL_DATA_REG    ; Dac Data Register
  1507.  
  1508.     MOV     AL, [Bp].SDR_Red    ; Get Red Intensity
  1509.     OUT     DX, AL              ; Set it
  1510.  
  1511.     MOV     AL, [Bp].SDR_Green  ; Get Green Intensity
  1512.     OUT     DX, AL              ; Set it
  1513.  
  1514.     MOV     AL, [Bp].SDR_Blue   ; Get Blue Intensity
  1515.     OUT     DX, AL              ; Set it
  1516.  
  1517.     POP     BP                  ; Restore Registers
  1518.     RET     8                   ; Exit & Clean Up Stack
  1519.  
  1520. SET_DAC_REGISTER    ENDP
  1521.  
  1522.  
  1523. ;==================================================== 
  1524. ;GET_DAC_REGISTER (Register%, &Red%, &Green%, &Blue%) 
  1525. ;==================================================== 
  1526. ; Gets the RGB Values of a single Vga Palette Register 
  1527. ; INPUT:  Red%, Green% & Blue% are offsets into DGROUP 
  1528. ;         that point to 16 bit integers that will hold 
  1529. ;         the returned red, green, and blue values 
  1530. ;
  1531.  
  1532. GDR_STACK   STRUC
  1533.                     DW  ?   ; BP
  1534.                     DD  ?   ; Caller
  1535.     GDR_Blue        DW  ?   ; Addr of Blue Data Value in DS
  1536.     GDR_Green       DW  ?   ; Addr of Green Data Value in DS
  1537.     GDR_Red         DW  ?   ; Addr of Red Data Value in DS
  1538.     GDR_Register    DB  ?,? ; Palette Register # 
  1539. GDR_STACK   ENDS
  1540.  
  1541.     PUBLIC  GET_DAC_REGISTER
  1542.  
  1543. GET_DAC_REGISTER    PROC    FAR
  1544.  
  1545.     PUSH    BP                  ; Save Bp
  1546.     MOV     BP, SP              ; Set up Stack Frame
  1547.  
  1548.     ; Select which DAC Register to read in
  1549.  
  1550.     OUT_8   DAC_READ_ADDR, [BP].GDR_Register
  1551.  
  1552.     MOV     DX, PEL_DATA_REG    ; Dac Data Register
  1553.     XOR     AX, AX              ; Clear AX
  1554.  
  1555.     IN      AL, DX              ; Read Red Value
  1556.     MOV     BX, [Bp].GDR_Red    ; Get Address of Red%
  1557.     MOV     [BX], AX            ; *Red% = AX
  1558.  
  1559.     IN      AL, DX              ; Read Green Value
  1560.     MOV     BX, [Bp].GDR_Green  ; Get Address of Green%
  1561.     MOV     [BX], AX            ; *Green% = AX
  1562.  
  1563.     IN      AL, DX              ; Read Blue Value
  1564.     MOV     BX, [Bp].GDR_Blue   ; Get Address of Blue%
  1565.     MOV     [BX], AX            ; *Blue% = AX
  1566.  
  1567.     POP     BP                  ; Restore Registers
  1568.     RET     8                   ; Exit & Clean Up Stack
  1569.  
  1570. GET_DAC_REGISTER    ENDP
  1571.  
  1572.  
  1573. ;=========================
  1574. ;SET_WINDOW (Xpos%, Ypos%)
  1575. ;=========================
  1576. ;
  1577. ; Since a Logical Screen can be larger than the Physical 
  1578. ; Screen, Scrolling is possible.  This routine sets the 
  1579. ; Upper Left Corner of the Screen to the specified Pixel. 
  1580. ; Xpos & Ypos  = Coordinates of the Pixel to put in the 
  1581. ;                upper left corner of the screen 
  1582. ;
  1583.  
  1584. SW_STACK    STRUC
  1585.                 DW  ?   ;BP
  1586.                 DD  ?   ;Caller
  1587.     SW_Ypos     DW  ?
  1588.     SW_Xpos     DW  ?
  1589. SW_STACK    ENDS
  1590.  
  1591.         PUBLIC SET_WINDOW
  1592.  
  1593. SET_WINDOW  PROC    FAR
  1594.  
  1595.     PUSH    BP                  ; Preserve Registers
  1596.     MOV     BP, SP              ; Set up Stack Frame
  1597.  
  1598.     ; Check if our Scroll Offsets are Valid
  1599.  
  1600.     MOV     AX, [BP].SW_Ypos    ; Get Desired Y Offset
  1601.     CMP     AX, MAX_YOFFSET     ; Is it Within Limitss?
  1602.     JA      @SW_Exit            ; if not, exit
  1603.  
  1604.     MOV     BX, [BP].SW_Xpos    ; Get Desired X Offset
  1605.     CMP     BX, MAX_XOFFSET     ; Is it Within Limitss?
  1606.     JA      @SW_Exit            ; if not, exit
  1607.  
  1608.     ; Compute proper Display start address to use
  1609.  
  1610.     MUL     SCREEN_WIDTH        ; AX = YOffset * Line Width
  1611.     MOV     CX, BX              ; CX = Copy of X Offset
  1612.     SHR     BX, 2               ; BX / 4 = Bytes into Line
  1613.     ADD     AX, BX              ; AX = Offset of Upper Left Pixel
  1614.  
  1615.     MOV     CURRENT_MOFFSET, AX ; Save Offset Info
  1616.  
  1617.     MOV     BX, DISPLAY_PAGE    ; Get Display Page #
  1618.     SHL     BX, 1               ; Scale Page # to Word
  1619.     ADD     AX, PAGE_ADDR[BX]   ; Get offset in VGA to Page
  1620.     MOV     BX, AX              ; BX = Desired Display Start
  1621.  
  1622.     MOV     DX, INPUT_1         ; Input Status #1 Register
  1623.  
  1624.     ; Wait for a Vertical Retrace to smooth out the scroll
  1625.  
  1626. @SW_WAIT:
  1627.     IN      AL, DX              ; Get VGA stauts
  1628.     JMP     $+2                 ; Delay (why?)
  1629.     AND     AL, 8               ; Bit 3 Gone Hi Yet?
  1630.     JZ      @SW_WAIT            ; If Not, wait for it
  1631.     CLI                         ; Don't Interrupt this!
  1632.  
  1633.     ; Set the Start Display Address to the New window
  1634.  
  1635.     MOV     DX, CRTC_Index      ; We Change the VGA Sequencer
  1636.     MOV     AL, START_DISP_LO   ; Display Start Low Register
  1637.     MOV     AH, BL              ; Low 8 Bits of Start Addr
  1638.     OUT     DX, AX              ; Set Display Addr Low
  1639.  
  1640.     MOV     AL, START_DISP_HI   ; Display Start High Register
  1641.     MOV     AH, BH              ; High 8 Bits of Start Addr
  1642.     OUT     DX, AX              ; Set Display Addr High
  1643.  
  1644.     ; Now Set the Horizontal Pixel Pan values
  1645.  
  1646.     MOV     DX, INPUT_1         ; Input Status #1 Register
  1647.     IN      AL, DX              ; Reset Attrib Flip/Flop
  1648.  
  1649.     OUT_8   ATTRIB_Ctrl, 33h    ; Select Pixel Pan Register
  1650.  
  1651.     MOV     AL, CL              ; Get Low Bits of X Offset
  1652.     AND     AL, 03              ; Get # of Pixels to Pan (0-3)
  1653.     SHL     AL, 1               ; Shift for 256 Color Mode
  1654.     OUT     DX, AX              ; Fine tune the display!
  1655.     STI                         ; Ok, Now you CAN interrupt
  1656.  
  1657. @SW_Exit:
  1658.     POP     BP                  ; Restore Saved Registers
  1659.     RET     4                   ; Exit and Clean up Stack
  1660.  
  1661. SET_WINDOW        ENDP
  1662.  
  1663.     END
  1664.