home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / ASM / GR110.ZIP / GR.ASM next >
Encoding:
Assembly Source File  |  1985-08-26  |  31.0 KB  |  1,039 lines

  1.     page    60,132
  2.     title    GR - Graphics Routines
  3. ;
  4. ; Graphics Routines
  5. ;   Version 1.1.0
  6. ;      8/16/85
  7. ;
  8. ; By Michael A. Quinlan
  9. ;
  10.  
  11.     org    0
  12. code    segment
  13.     assume    cs:code,ds:nothing,es:nothing
  14. main    proc    near
  15. start:
  16.     jmp    GrHGCThere        ;  0
  17.     jmp    GrCGAThere        ;  3
  18.     jmp    GrInitHGC        ;  6
  19.     jmp    GrInitCGA        ;  9
  20.     jmp    GrTermHGC        ; 12
  21.     jmp    GrTermCGA        ; 15
  22.     jmp    ScrWriteDotHGC        ; 18
  23.     jmp    ScrWriteDotCGA        ; 21
  24.     jmp    ScrDrawLineHGC        ; 24
  25.     jmp    ScrDrawLineCGA        ; 27
  26.     jmp    GrFillWindowHGC        ; 30
  27.     jmp    GrFillWindowCGA        ; 33
  28.     jmp    ScrDrawCharHGC        ; 36
  29.     jmp    ScrDrawCharCGA        ; 39
  30.     jmp    GrSaveWindowHGC        ; 42
  31.     jmp    GrSaveWindowCGA        ; 45
  32.     jmp    GrRestoreWindowHGC    ; 48
  33.     jmp    GrRestoreWindowCGA    ; 51
  34.     jmp    GrOutCodes        ; 54
  35.     jmp    ScrReadDotHGC        ; 57
  36.     jmp    ScrReadDotCGA        ; 60
  37.     jmp    GrISwap            ; 63
  38.  
  39. HGCBase    equ    0B000h        ;segment for HGC regen buffer page 0
  40. CGABase    equ    0B800h        ;segment for CGA regen buffer page 0
  41.  
  42. herc_index    equ    03B4h
  43. herc_cntrl    equ    03B8h
  44. herc_status    equ    03BAh
  45. herc_config    equ    03BFh
  46.  
  47. scrn_on    equ    08h
  48. grph    equ    02h
  49. text    equ    20h
  50.  
  51. gtable    db    35h,2dh,2eh,07h
  52.     db    5bh,02h,57h,57h
  53.     db    02h,03h,00h,00h
  54.  
  55. ttable    db    61h,50h,52h,0fh
  56.     db    19h,06h,19h,19h
  57.     db    02h,0dh,0bh,0ch
  58.  
  59. XStep    dw    0
  60. YStep    dw    0
  61. DeltaX    dw    0
  62. DeltaY    dw    0
  63.  
  64. GrHGCThere:
  65. ; Determine if the Hercules Graphics Card is installed.
  66. ; This code is from
  67. ;
  68. ;   HERC.ASM version 1.11B by Bela Lubkin 3/4/85
  69. ;   Copyright (C) 1985, Borland International
  70. ;
  71.     push    ds        ;save DS for Turbo Pascal
  72.  
  73.     MOV    BX,0100H
  74.     MOV    DX,herc_status    ; Loop looking for status port bit 7 to
  75.     IN    AL,DX        ;   be on.  Herc uses it as a retrace
  76.     MOV    AH,AL        ;   indicator while IBM doesn't ever
  77.     AND    AH,80H        ;   turn it on.
  78. II1:    MOV    CX,0040H
  79. II2:    IN    AL,DX
  80.     AND    AL,80H
  81.     CMP    AL,AH
  82.     LOOPZ    II2
  83.     JNZ    EndLoop
  84.     DEC    BX
  85.     JNZ    II1
  86. EndLoop: JZ    NotThere    ; Not a herc if status doesn't change
  87.     MOV    AX,HGCBase
  88.     MOV    DS,AX        ; Need DS prefixes because of DS:Nothing
  89.     MOV    BL,DS:[7FFFH]    ;Check for at least a full 32K of
  90.     MOV    CL,DS:[3FFFH]    ;   memory.  (Some cards other than herc
  91.     INC    Byte ptr DS:[3FFFH]    ;   do set bit 7)
  92.     CMP    BL,DS:[7FFFH]
  93.     MOV    DS:[3FFFH],CL    ; Restore former value
  94.     JE    There
  95.     MOV    DX,Herc_Config    ; [DX]=Configuration port
  96.     MOV    AL,1        ; Allow graphics, page 0 only
  97.     OUT    DX,AL        ; -- in case memory test failed because
  98.     MOV    BL,DS:[7FFFH]    ;    the card was in 'diagnostic' mode
  99.     MOV    CL,DS:[3FFFH]
  100.     INC    Byte ptr DS:[3FFFH]
  101.     CMP    BL,DS:[7FFFH]
  102.     MOV    DS:[3FFFH],CL
  103.     JNE    NotThere    ; Not >=32K RAM: not a herc
  104. There:
  105.     mov    ax,1
  106.     jmp    short BooleanRet
  107. NotThere:
  108.     mov    ax,0
  109. BooleanRet:
  110.     cmp    ax,0
  111.     pop    ds
  112.     ret
  113.  
  114. GrCGAThere:
  115. ; see if an IBM Color Graphics Adaptor is installed
  116.     push    ds
  117.     mov    ax,CGABase    ;segment for CGA regen buffer
  118.     mov    ds,ax
  119.     mov    bh,ds:[0]    ;get an byte from the buffer
  120.     inc    byte ptr ds:[0]    ;change the byte
  121.     cmp    bh,ds:[0]    ;did the byte change
  122.     je    NotThere    ;did not change -- no CGA installed
  123.     mov    ds:[0],bh    ;restore the value
  124.     jmp    There        ;yes it did change -- assume CGA is there
  125.  
  126. GrInitHGC:
  127. ; Initialize the HGC in graphics mode. Code mostly from the Hercules
  128. ; Graphics Card Owner's Manual.
  129.     call    InitH010
  130. InitH010:
  131.     pop    si    ;address of InitH010 now in si
  132.     sub    si,InitH010-Main  ;calc address of start of our code
  133. ; we can now address data areas using cs:[si+offset]
  134.     push    ds    ;save reg for Turbo Pascal
  135.     push    cs
  136.     pop    ds    ;copy cs to ds
  137.     mov    al,grph
  138.     add    si,offset gtable
  139.     mov    bx,0
  140.     mov    cx,4000h
  141.     call    setmd
  142.     pop    ds
  143.     ret
  144.     
  145. GrInitCGA:
  146. ; initialize the Color Grahics Adaptor in high res graphics mode
  147.     push    ds
  148.     mov    ax,40h        ;address BIOS data segment
  149.     mov    ds,ax
  150.     and    byte ptr ds:[11h],0CFh    ;turn off video mode bits
  151.     or    byte ptr ds:[11h],020h    ;force 80x25 color graphics adaptor
  152.     pop    ds
  153.  
  154.     mov    ah,0        ;set mode
  155.     mov    al,6        ;640x200 graphics
  156.     int    10h
  157.     ret
  158.  
  159. GrTermHGC:
  160. ; restore the Hercules Graphics Card to text mode
  161.     call    TermH010
  162. TermH010:
  163.     pop    si
  164.     sub    si,TermH010-Main
  165.     push    ds
  166.     push    cs
  167.     pop    ds
  168.     mov    al,text
  169.     add    si,offset ttable
  170.     mov    bx,720h
  171.     mov    dx,2000
  172.     call    setmd
  173.     pop    ds
  174.     ret
  175.  
  176. GrTermCGA:
  177. ; restore the IBM Color Graphics Adaptor to text mode
  178.     mov    ah,0
  179.     mov    al,3
  180.     int    10h
  181.     ret
  182.  
  183. ScrWriteDotHGC:
  184.     mov    bx,offset HGCRegen    ;set up offset of regen scan line table
  185.     mov    ax,HGCBase        ;segment for regen buffer
  186.     mov    es,ax
  187.     jmp    short WriteDot        ;use common dot writing routine
  188.  
  189. ScrWriteDotCGA:
  190.     mov    bx,offset CGARegen    ;set up offset of regen scan line table
  191.     mov    ax,CGABase        ;segment for regen buffer
  192.     mov    es,ax
  193. ;    jmp    short WriteDot        ;use common dot writing routine
  194.  
  195. WriteDot:
  196. ; invoked from ScrWriteDot via JMP
  197. ;  [bp+4] = color
  198. ;  [bp+6] = y coordinate
  199. ;  [bp+8] = x coordinate
  200. ;
  201. ;  bx = address of Regen Scan Line Table
  202. ;  es = regen buffer segment
  203.  
  204.     call    WtDot010
  205. WtDot010:
  206.     pop    di        ;di has offset of WtDot010
  207.     sub    di,WtDot010-Main  ;di has offset of start of our code
  208. ; we can now address data areas using si as a base register
  209.     push    ds        ;save for Turbo Pascal
  210.     push    cs
  211.     pop    ds
  212. ; calculate byte address of dot in regen buffer
  213.     mov    si,[bp+6]    ;get y coordinate
  214.     shl    si,1        ;mult by 2 to get offset in Scan Line Table
  215.     add    si,di        ;add base address of our code
  216.     mov    si,[bx][si]    ;get address of start of scan line from table
  217.     mov    ax,[bp+8]    ;get x coordinate
  218.     mov    cl,3
  219.     shr    ax,cl        ;divide by 8 to get byte offset
  220.     add    si,ax        ;es:si has address of byte with the bit
  221. ; build the bit mask for the specific dot in the byte
  222.     mov    cx,[bp+8]    ;get x coordinate
  223.     and    cx,0007h    ;get bit number within the byte
  224.     mov    al,80h        ;prepare bit mask
  225.     shr    al,cl        ;al has bit mask
  226. ; either turn on the bit or turn it off, depending on the color
  227.     cmp    word ptr [bp+4],0    ;turn off bit?
  228.     je    WtDot020    ;yes -- branch
  229. ; turn on the bit
  230.     or    byte ptr es:[si],al
  231.     jmp    short WtDot030
  232. WtDot020:
  233. ; turn off the bit
  234.     xor    al,0FFh
  235.     and    byte ptr es:[si],al
  236. WtDot030:
  237. ; done. restore and return
  238.     pop    ds
  239.     mov    sp,bp
  240.     pop    bp
  241.     ret    6
  242.  
  243. ScrReadDotHGC:
  244.     mov    bx,offset HGCRegen    ;set up offset of regen scan line table
  245.     mov    ax,HGCBase        ;segment for regen buffer
  246.     mov    es,ax
  247.     jmp    short ReadDot        ;use common dot reading routine
  248.  
  249. ScrReadDotCGA:
  250.     mov    bx,offset CGARegen    ;set up offset of regen scan line table
  251.     mov    ax,CGABase        ;segment for regen buffer
  252.     mov    es,ax
  253. ;    jmp    short ReadDot        ;use common dot reading routine
  254.  
  255. ReadDot:
  256. ; invoked from ScrReadDot via JMP
  257. ;  [bp+4] = y coordinate
  258. ;  [bp+6] = x coordinate
  259. ;
  260. ;  dot value is to be returned in AX
  261. ;
  262. ;  bx = address of Regen Scan Line Table
  263. ;  es = regen buffer segment
  264.  
  265.     call    RdDot010
  266. RdDot010:
  267.     pop    di        ;di has offset of RdDot010
  268.     sub    di,RdDot010-Main  ;di has offset of start of our code
  269. ; we can now address data areas using si as a base register
  270.     push    ds        ;save for Turbo Pascal
  271.     push    cs
  272.     pop    ds
  273. ; calculate byte address of dot in regen buffer
  274.     mov    si,[bp+4]    ;get y coordinate
  275.     shl    si,1        ;mult by 2 to get offset in Scan Line Table
  276.     add    si,di        ;add base address of our code
  277.     mov    si,[bx][si]    ;get address of start of scan line from table
  278.     mov    ax,[bp+6]    ;get x coordinate
  279.     mov    cl,3
  280.     shr    ax,cl        ;divide by 8 to get byte offset
  281.     add    si,ax        ;es:si has address of byte with the bit
  282. ; build the bit mask for the specific dot in the byte
  283.     mov    cx,[bp+6]    ;get x coordinate
  284.     and    cx,0007h    ;get bit number within the byte
  285.     mov    al,80h        ;prepare bit mask
  286.     shr    al,cl        ;al has bit mask
  287. ; pick up the bit from the regen buffer
  288.     test    byte ptr es:[si],al
  289.     jz    RdDot020    ;branch if bit is zero
  290.     mov    ax,1        ;else return foreground bit value
  291.     jmp    short RdDot030
  292. RdDot020:
  293.     xor    ax,ax        ;bit is zero
  294. RdDot030:
  295. ; done. restore and return
  296.     pop    ds
  297.     mov    sp,bp
  298.     pop    bp
  299.     ret    4
  300.  
  301. ScrDrawLineHGC:
  302.     mov    bx,offset HGCRegen    ;set up offset of regen scan line table
  303.     mov    ax,HGCBase        ;regen buffer segment
  304.     mov    es,ax
  305.     jmp    short DrawLine        ;use common line drawing routine
  306.  
  307. ScrDrawLineCGA:
  308.     mov    bx,offset CGARegen    ;set up offset of regen scan line table
  309.     mov    ax,CGABase        ;regen buffer segment
  310.     mov    es,ax
  311. ;    jmp    short DrawLine        ;use common line drawing routine
  312.  
  313. DrawLine:
  314. ; invoked from ScrDrawLine via JMP
  315. ;
  316. ;   [bp+4] = color
  317. ;   [bp+6] = y2 coordinate
  318. ;   [bp+8] = x2 coordinate
  319. ;   [bp+10] = y1 coordinate
  320. ;   [bp+12] = x1 coordinate
  321. ;
  322. ;   BX = offset of Regen Scan Line Table
  323. ;   ES = regen buffer segment
  324.  
  325.     call    DrLine010
  326. DrLine010:
  327.     pop    di        ;di has offset of DrLine010
  328.     sub    di,DrLine010-Main  ;di has offset of start of our code
  329. ; we can now address data areas using si as a base register
  330.     push    ds        ;save for Turbo Pascal
  331.     push    cs
  332.     pop    ds
  333. ; calculate scan line address in regen buffer for y1
  334.     mov    ax,[bp+10]    ;get y1 coordinate
  335.     shl    ax,1        ;mult by 2 to get offset of entry in table
  336.     add    bx,ax        ;add to table beginning offset
  337.     add    bx,di        ;add in our code offset
  338. ; set increment for x and y
  339.     mov    ds:XStep[di],1    ;default to forward
  340.     mov    ds:YStep[di],1
  341.     xor    dx,dx        ;direction = 0
  342.     mov    ax,[bp+8]    ;get x2
  343.     sub    ax,[bp+12]    ;get delta x (x2 - x1)
  344.     jns    DrLine020    ;branch if result is positive
  345.     neg    ax        ;else take absolute value
  346.     mov    ds:XStep[di],-1    ;and remember to step backwards
  347.     jmp    short DrLine030
  348. DrLine020:
  349.     jnz    DrLine030    ;jump if delta x is not zero
  350.     mov    dx,-1        ;set direction = -1 if delta x = 0
  351. DrLine030:
  352.     mov    ds:DeltaX[di],ax
  353.     mov    ax,[bp+6]    ;get y2
  354.     sub    ax,[bp+10]    ;get delta y (y2 - y1)
  355.     jns    DrLine040    ;branch if result is positive
  356.     neg    ax        ;else take absolute value
  357.     mov    ds:YStep[di],-1    ;and remember to step backwards
  358. DrLine040:
  359.     mov    ds:DeltaY[di],ax
  360.     mov    ax,[bp+12]    ;get x1
  361.     mov    cx,[bp+10]    ;get y1
  362. ;;;
  363. ;;;  ax = x
  364. ;;;  bx = y (encoded as address in the Scan Line Table)
  365. ;;;  cx = y
  366. ;;;  dx = direction
  367. ;;;
  368.     cmp    word ptr [bp+4],0 ;set to background color?
  369.     je    DrLine080
  370. DrLine050:
  371. ; loop drawing the points of the line
  372.     cmp    ax,[bp+8]    ;x = x2?
  373.     jne    DrLine060    ;no: continue with loop
  374.     cmp    cx,[bp+6]    ;y = y2?
  375.     je    DrLineRet    ;yes: finished!!!
  376. DrLine060:
  377. ; draw a point at (x,y)
  378.     push    cx        ;save regs used
  379.     push    ax
  380.     mov    cl,3
  381.     shr    ax,cl        ;adjust ax for byte offset
  382.     mov    si,ds:[bx]    ;get scan line address
  383.     add    si,ax        ;get byte address in regen buffer
  384.     pop    cx        ;restore x value
  385.     push    cx
  386.     and    cx,0007h    ;build bit mask
  387.     mov    ah,80h
  388.     shr    ah,cl
  389.     or    es:[si],ah    ;turn on the bit
  390.     pop    ax        ;restore regs used
  391.     pop    cx
  392. ; adjust for the next point
  393.     cmp    dx,0        ;direction less than zero?
  394.     jge    DrLine070    ;no: jump
  395.     add    cx,ds:YStep[di]
  396.     add    bx,ds:YStep[di]
  397.     add    bx,ds:YStep[di]
  398.     add    dx,ds:DeltaX[di]
  399.     jmp    DrLine050
  400. DrLine070:
  401.     add    ax,ds:XStep[di]
  402.     sub    dx,ds:DeltaY[di]
  403.     jmp    DrLine050
  404.  
  405. DrLineRet:
  406.     pop    ds
  407.     mov    sp,bp
  408.     pop    bp
  409.     ret    10
  410.  
  411. DrLine080:
  412. ; loop setting points of the line to the background color
  413.     cmp    ax,[bp+8]    ;x = x2?
  414.     jne    DrLine090    ;no: continue with loop
  415.     cmp    cx,[bp+6]    ;y = y2?
  416.     je    DrLineRet    ;yes: finished!!!
  417. DrLine090:
  418. ; draw a point at (x,y)
  419.     push    cx        ;save regs used
  420.     push    ax
  421.     mov    cl,3
  422.     shr    ax,cl        ;adjust ax for byte offset
  423.     mov    si,ds:[bx]    ;get scan line address
  424.     add    si,ax        ;get byte address in regen buffer
  425.     pop    cx        ;restore x value
  426.     push    cx
  427.     and    cx,0007h    ;build bit mask
  428.     mov    ah,80h
  429.     shr    ah,cl
  430.     xor    ah,0FFh
  431.     and    es:[si],ah    ;turn off the bit
  432.     pop    ax        ;restore regs used
  433.     pop    cx
  434. ; adjust for the next point
  435.     cmp    dx,0        ;direction less than zero?
  436.     jge    DrLine100    ;no: jump
  437.     add    cx,ds:YStep[di]
  438.     add    bx,ds:YStep[di]
  439.     add    bx,ds:YStep[di]
  440.     add    dx,ds:DeltaX[di]
  441.     jmp    DrLine080
  442. DrLine100:
  443.     add    ax,ds:XStep[di]
  444.     sub    dx,ds:DeltaY[di]
  445.     jmp    DrLine080
  446.  
  447. GrFillWindowHGC:
  448.     mov    bx,offset HGCRegen    ;set up addr of Scan Line Table
  449.     mov    ax,HGCBase        ;regen buffer segment
  450.     mov    es,ax
  451.     jmp    short FillWindow    ;use common window filling routine
  452.  
  453. GrFillWindowCGA:
  454.     mov    bx,offset CGARegen    ;set up addr of Scan Line Table
  455.     mov    ax,CGABase        ;regen buffer segment
  456.     mov    es,ax
  457. ;    jmp    short FillWindow    ;use common window filling routine
  458.  
  459. FillWindow:
  460. ; invoked from GrFillWindow via JMP
  461. ;
  462. ;   [bp+4] = color
  463. ;   [bp+6] = y2 coordinate
  464. ;   [bp+8] = x2 coordinate
  465. ;   [bp+10] = y1 coordinate
  466. ;   [bp+12] = x1 coordinate
  467. ;
  468. ;   BX = offset of Regen Scan Line Table
  469. ;   ES = regen buffer segment address
  470.  
  471.     call    FillW010
  472. FillW010:
  473.     pop    di        ;di has offset of FillW010
  474.     sub    di,FillW010-Main  ;di has offset of start of our code
  475. ; we can now address data areas using si as a base register
  476.     push    ds        ;save for Turbo Pascal
  477.     push    cs
  478.     pop    ds
  479. ; calculate scan line address in regen buffer for y1
  480.     mov    ax,[bp+10]    ;get y1 coordinate
  481.     shl    ax,1        ;mult by 2 to get offset of entry in table
  482.     add    bx,ax        ;add to table beginning offset
  483.     add    bx,di        ;add in our code offset
  484. ; calculate the number of bytes to fill on each line
  485.     mov    dx,[bp+8]    ;get x2
  486.     sub    dx,[bp+12]    ;calc x2-x1
  487.     mov    cl,3
  488.     shr    dx,cl        ;convert from bits to bytes
  489.     inc    dx
  490. ; calculate the number of scan lines to fill
  491.     mov    cx,[bp+6]    ;get y2
  492.     sub    cx,[bp+10]    ;calc y2-y1
  493.     inc    cx
  494. ; calculate the start address within the scan line
  495.     push    cx
  496.     mov    ax,[bp+12]    ;get x1
  497.     mov    cl,3
  498.     shr    ax,cl
  499.     mov    si,ax
  500.     pop    cx
  501. ; get the byte value to put in the buffer
  502.     mov    al,0FFh
  503.     cmp    word ptr [bp+4],0 ;set to background color?
  504.     jne    FillW015
  505.     xor    al,al
  506. FillW015:
  507.     cld            ;set for forward processing
  508. FillW020:
  509. ; loop for each scan line
  510.     push    cx
  511.     mov    di,ds:[bx]    ;get scan line start address
  512.     add    di,si        ;add offset to first byte
  513.     mov    cx,dx        ;# bytes to fill
  514.     rep    stosb        ;fill the scan line
  515.     inc    bx        ;get addr for next scan line
  516.     inc    bx
  517.     pop    cx
  518.     loop    FillW020    ;do the next scan line
  519. ; restore and return
  520.     pop    ds
  521.     mov    sp,bp
  522.     pop    bp
  523.     ret    10
  524.  
  525. GrSaveWindowHGC:
  526.     mov    bx,offset HGCRegen    ;set up addr of Scan Line Table
  527.     mov    ax,HGCBase        ;regen buffer segment
  528.     jmp    short SaveWindow    ;use common window saving routine
  529.  
  530. GrSaveWindowCGA:
  531.     mov    bx,offset CGARegen    ;set up addr of Scan Line Table
  532.     mov    ax,CGABase        ;regen buffer segment
  533. ;    jmp    short SaveWindow    ;use common window saving routine
  534.  
  535. SaveWindow:
  536. ; invoked from GrSaveWindow via JMP
  537. ;
  538. ;   [bp+4] = y2 coordinate
  539. ;   [bp+6] = x2 coordinate
  540. ;   [bp+8] = y1 coordinate
  541. ;   [bp+10] = x1 coordinate
  542. ;   [bp+12] = offset of area
  543. ;   [bp+14] = segment of area
  544. ;
  545. ;   BX = offset of Regen Scan Line Table
  546. ;   AX = regen buffer segment address
  547.  
  548.     call    SaveW010
  549. SaveW010:
  550.     pop    di        ;di has offset of SaveW010
  551.     sub    di,SaveW010-Main  ;di has offset of start of our code
  552. ; we can now address data areas using si as a base register
  553.     push    ds        ;save for Turbo Pascal
  554.     mov    ds,ax        ;ds = source (regen buffer) segment
  555. ; calculate scan line address in regen buffer for y1
  556.     mov    ax,[bp+8]    ;get y1 coordinate
  557.     shl    ax,1        ;mult by 2 to get offset of entry in table
  558.     add    bx,ax        ;add to table beginning offset
  559.     add    bx,di        ;add in our code offset
  560. ; calculate the number of bytes to copy on each line
  561.     mov    dx,[bp+6]    ;get x2
  562.     sub    dx,[bp+10]    ;calc x2-x1
  563.     mov    cl,3
  564.     shr    dx,cl        ;convert from bits to bytes
  565.     inc    dx
  566. ; calculate the number of scan lines to copy
  567.     mov    cx,[bp+4]    ;get y2
  568.     sub    cx,[bp+8]    ;calc y2-y1
  569.     inc    cx
  570. ; calculate the start address within the scan line
  571.     push    cx
  572.     mov    ax,[bp+10]    ;get x1
  573.     mov    cl,3
  574.     shr    ax,cl
  575.     pop    cx
  576. ; set up destination addresses in ES:DI
  577.     les    di,dword ptr [bp+12]    ;set up destination seg & offset
  578. ; set to process the data forwards
  579.     cld
  580. ; loop for each scan line
  581. SaveW020:
  582.     push    cx
  583.     mov    si,cs:[bx]    ;get scan line start address
  584.     add    si,ax        ;add offset to first byte
  585.     mov    cx,dx        ;# bytes to copy
  586.     rep    movsb        ;copy the scan line
  587.     inc    bx        ;get addr for next scan line
  588.     inc    bx
  589.     pop    cx
  590.     loop    SaveW020    ;do the next scan line
  591. ; restore and return
  592.     pop    ds
  593.     mov    sp,bp
  594.     pop    bp
  595.     ret    12
  596.  
  597. GrRestoreWindowHGC:
  598.     mov    bx,offset HGCRegen    ;set up addr of Scan Line Table
  599.     mov    ax,HGCBase        ;regen buffer segment
  600.     mov    es,ax
  601.     jmp    short RestoreWindow    ;use common window restoring routine
  602.  
  603. GrRestoreWindowCGA:
  604.     mov    bx,offset CGARegen    ;set up addr of Scan Line Table
  605.     mov    ax,CGABase        ;regen buffer segment
  606.     mov    es,ax
  607. ;    jmp    short RestoreWindow    ;use common window restoring routine
  608.  
  609. RestoreWindow:
  610. ; invoked from GrRestoreWindow via JMP
  611. ;
  612. ;   [bp+4] = offset of area to restore window from
  613. ;   [bp+6] = segment of area to restore window from
  614. ;   [bp+8] = y2 coordinate
  615. ;   [bp+10] = x2 coordinate
  616. ;   [bp+12] = y1 coordinate
  617. ;   [bp+14] = x1 coordinate
  618. ;
  619. ;   BX = offset of Regen Scan Line Table
  620. ;   ES = regen buffer segment address
  621.  
  622.     call    RestW010
  623. RestW010:
  624.     pop    di        ;di has offset of RestW010
  625.     sub    di,RestW010-Main  ;di has offset of start of our code
  626. ; we can now address data areas using si as a base register
  627.     push    ds        ;save for Turbo Pascal
  628. ; calculate scan line address in regen buffer for y1
  629.     mov    ax,[bp+12]    ;get y1 coordinate
  630.     shl    ax,1        ;mult by 2 to get offset of entry in table
  631.     add    bx,ax        ;add to table beginning offset
  632.     add    bx,di        ;add in our code offset
  633. ; calculate the number of bytes to restore on each line
  634.     mov    dx,[bp+10]    ;get x2
  635.     sub    dx,[bp+14]    ;calc x2-x1
  636.     mov    cl,3
  637.     shr    dx,cl        ;convert from bits to bytes
  638.     inc    dx
  639. ; calculate the number of scan lines to fill
  640.     mov    cx,[bp+8]    ;get y2
  641.     sub    cx,[bp+12]    ;calc y2-y1
  642.     inc    cx
  643. ; calculate the start address within the scan line
  644.     push    cx
  645.     mov    ax,[bp+14]    ;get x1
  646.     mov    cl,3
  647.     shr    ax,cl
  648.     pop    cx
  649. ; get the source address in DS:SI
  650.     lds    si,dword ptr [bp+4]
  651. ; set to process the data forwards
  652.     cld
  653. RestW020:
  654. ; loop for each scan line
  655.     push    cx
  656.     mov    di,cs:[bx]    ;get scan line start address
  657.     add    di,ax        ;add offset to first byte
  658.     mov    cx,dx        ;# bytes to copy
  659.     rep    movsb        ;copy the scan line
  660.     inc    bx        ;get addr for next scan line
  661.     inc    bx
  662.     pop    cx
  663.     loop    RestW020    ;do the next scan line
  664. ; restore and return
  665.     pop    ds
  666.     mov    sp,bp
  667.     pop    bp
  668.     ret    12
  669.  
  670. ScrDrawCharHGC:
  671.     mov    bx,offset HGCRegen    ;set up offset of regen scan line table
  672.     mov    ax,HGCBase        ;regen buffer segment
  673.     mov    es,ax
  674.     jmp    short DrawChar        ;use common character drawing routine
  675.  
  676. ScrDrawCharCGA:
  677.     mov    bx,offset CGARegen    ;set up offset of regen scan line table
  678.     mov    ax,CGABase        ;regen buffer segment
  679.     mov    es,ax
  680. ;    jmp    short DrawChar        ;user common character drawing routine
  681.  
  682. DrawChar:
  683. ; invoked from ScrDrawChar via JMP
  684. ;   [bp+4] = character to draw
  685. ;   [bp+6] = y coordinate
  686. ;   [bp+8] = x coordinate
  687. ;
  688. ;   BX = offset of Regen Scan Line Table
  689. ;   ES = regen buffer segment address
  690.  
  691.     call    DrawCh010
  692. DrawCh010:
  693.     pop    di        ;di has offset of DrawCh010
  694.     sub    di,DrawCh010-Main  ;di has offset of start of our code
  695. ; we can now address data areas using si as a base register
  696.     push    ds        ;save for Turbo Pascal
  697.     push    cs
  698.     pop    ds
  699. ; determine offset to character in character table
  700.     mov    si,[bp+4]    ;get character
  701.     and    si,007Fh    ;strip invalid bits
  702.     mov    cl,3        ;mult by 8 to get offset into table
  703.     shl    si,cl
  704.     add    si,di        ;ds:si is addr of character in table
  705.     add    si,offset Crt_Char  ;add in table base offset
  706. ; adjust x coordinate for byte offset into regen buffer
  707.     mov    dx,[bp+8]    ;get x coordinate
  708.     add    dx,7        ;adjust to next byte boundary if reqd
  709.     mov    cl,3
  710.     shr    dx,cl        ;adjust for byte displacement into buffer
  711. ; get address in Regen Scan Line Table based on y coordinate
  712.     mov    ax,[bp+6]    ;get y coordinate
  713.     shl    ax,1        ;mult by 2 for offset into scan line table
  714.     add    ax,di        ;add base of our code
  715.     add    bx,ax        ;add to offset of table to get entry address
  716. ; loop 8 times to draw the character
  717.     mov    cx,8
  718. DrawCh020:
  719.     lodsb            ;al = byte from DS:SI; incr SI
  720.     mov    di,[bx]        ;get offset into regen buffer
  721.     add    di,dx        ;adjust for x coordinate
  722.     mov    es:[di],al    ;store 8 pixels of char into regen buffer
  723.     inc    bx        ;incr for next scan line
  724.     inc    bx
  725.     loop    DrawCh020
  726. ; restore and return
  727.     pop    ds
  728.     mov    sp,bp
  729.     pop    bp
  730.     ret    6
  731.  
  732. GrOutcodes:
  733. ;
  734. ; called to quickly generate OUTCODE for the Cohen-Sutherland clipping
  735. ;
  736. ;   [bp+4]  = ymax
  737. ;   [bp+6]  = xmax
  738. ;   [bp+8]  = y
  739. ;   [bp+10] = x
  740. ;
  741. ;  Xmin and Ymin are always zero
  742. ;
  743. ; returns the 4-bit OUTCODE as an integer in AX
  744. ;
  745.     push    bp
  746.     mov    bp,sp
  747.     xor    ax,ax
  748.     mov    bx,[bp+4]    ;ymax
  749.     mov    dx,[bp+8]    ;y
  750.     sub    bx,dx        ;ymax - y
  751.     rol    bh,1        ;move sign to low bit of bh
  752.     and    bh,01h        ;clear all other bits
  753.     or    al,bh        ;put bit into result
  754.     rol    dh,1        ;move sign to correct bit of dh
  755.     rol    dh,1
  756.     and    dh,02h        ;get rid of extra bits
  757.     or    al,dh        ;put bit into result
  758.     mov    bx,[bp+6]    ;xmax
  759.     mov    dx,[bp+10]    ;x
  760.     sub    bx,dx        ;xmax - x
  761.     mov    cl,3
  762.     rol    bh,cl        ;move sign to correct bit of bh
  763.     and    bh,04h        ;get rid of other bits
  764.     or    al,bh        ;put bit into result
  765.     mov    cl,4
  766.     rol    dh,cl        ;move sign to correct bit of dh
  767.     and    dh,08h        ;get rid of other bits
  768.     or    al,dh        ;put bit into result
  769.     mov    sp,bp
  770.     pop    bp
  771.     ret    8        ;return with result in ax
  772.  
  773. GrISwap:
  774. ;
  775. ; called to swap two integers
  776. ;
  777. ;  [bp+4]  = offset of j
  778. ;  [bp+6]  = segment of j
  779. ;  [bp+8]  = offset of i
  780. ;  [bp+10] = segment of i
  781.  
  782.     push    bp
  783.     mov    bp,sp
  784.     push    ds
  785.     lds    si,[bp+4]    ;get address of j
  786.     mov    ax,ds:[si]    ;get j
  787.     les    di,[bp+8]    ;get address of i
  788.     mov    bx,es:[di]    ;get i
  789.     mov    ds:[si],bx    ;move i
  790.     mov    es:[di],ax    ;move j
  791.     pop    ds
  792.     mov    sp,bp
  793.     pop    bp
  794.     ret    8
  795.  
  796. setmd:
  797. ; from Hercules Graphics Card Owner's Manual    
  798.     push    ds
  799.     push    es
  800.     push    ax
  801.     push    bx
  802.     push    cx
  803.     mov    dx,herc_cntrl
  804.     out    dx,al
  805.     mov    ax,ds
  806.     mov    es,ax
  807.     mov    dx,herc_index
  808.     mov    cx,12
  809.     xor    ah,ah
  810. parms:    mov    al,ah
  811.     out    dx,al
  812.     inc    dx
  813.     lodsb
  814.     out    dx,al
  815.     inc    ah
  816.     dec    dx
  817.     loop    parms
  818.     pop    cx
  819.     mov    ax,HGCBase
  820.     cld
  821.     mov    es,ax
  822.     xor    di,di
  823.     pop    ax
  824.     rep    stosw
  825.     mov    dx,herc_cntrl
  826.     pop    ax
  827.     add    al,scrn_on
  828.     out    dx,al
  829.     pop    es
  830.     pop    ds
  831.     ret
  832.  
  833. Crt_Char:
  834.     db    000h,000h,000h,000h,000h,000h,000h,000h    ; #0
  835.     db    07Eh,081h,0A5h,081h,0BDh,099h,081h,07Eh    ; #1
  836.     db    07Eh,0FFh,0DBh,0FFh,0C3h,0E7h,0FFh,07Eh    ; #2
  837.     db    06Ch,0FEh,0FEh,0FEh,07Ch,038h,010h,000h    ; #3
  838.     db    010h,038h,07Ch,0FEh,07Ch,038h,010h,000h    ; #4
  839.     db    038h,07Ch,038h,0FEh,0FEh,07Ch,038h,07Ch    ; #5
  840.     db    010h,010h,038h,07Ch,0FEh,07Ch,038h,07Ch    ; #6
  841.     db    000h,000h,018h,03Ch,03Ch,018h,000h,000h    ; #7
  842.     db    0FFh,0FFh,0E7h,0C3h,0C3h,0E7h,0FFh,0FFh    ; #8
  843.     db    000h,03Ch,066h,042h,042h,066h,03Ch,000h    ; #9
  844.     db    0FFh,0C3h,099h,0BDh,0BDh,099h,0C3h,0FFh    ; #10
  845.     db    00Fh,007h,00Fh,07Dh,0CCh,0CCh,0CCh,078h    ; #11
  846.     db    03Ch,066h,066h,066h,03Ch,018h,07Eh,018h    ; #12
  847.     db    03Fh,033h,03Fh,030h,030h,070h,0F0h,0E0h    ; #13
  848.     db    07Fh,063h,07Fh,063h,063h,067h,0E6h,0C0h    ; #14
  849.     db    099h,05Ah,03Ch,0E7h,0E7h,03Ch,05Ah,099h    ; #15
  850.     db    080h,0E0h,0F8h,0FEh,0F8h,0E0h,080h,000h    ; #16
  851.     db    002h,00Eh,03Eh,0FEh,03Eh,00Eh,002h,000h    ; #17
  852.     db    018h,03Ch,07Eh,018h,018h,07Eh,03Ch,018h    ; #18
  853.     db    066h,066h,066h,066h,066h,000h,066h,000h    ; #19
  854.     db    07Fh,0DBh,0DBh,07Bh,01Bh,01Bh,01Bh,000h    ; #20
  855.     db    03Eh,063h,038h,06Ch,06Ch,038h,0CCh,078h    ; #21
  856.     db    000h,000h,000h,000h,07Eh,07Eh,07Eh,000h    ; #22
  857.     db    018h,03Ch,07Eh,018h,07Eh,03Ch,018h,0FFh    ; #23
  858.     db    018h,03Ch,07Eh,018h,018h,018h,018h,000h    ; #24
  859.     db    018h,018h,018h,018h,07Eh,03Ch,018h,000h    ; #25
  860.     db    000h,018h,00Ch,0FEh,00Ch,018h,000h,000h    ; #26
  861.     db    000h,030h,060h,0FEh,060h,030h,000h,000h    ; #27
  862.     db    000h,000h,0C0h,0C0h,0C0h,0FEh,000h,000h    ; #28
  863.     db    000h,024h,066h,0FFh,066h,024h,000h,000h    ; #29
  864.     db    000h,018h,03Ch,07Eh,0FFh,0FFh,000h,000h    ; #30
  865.     db    000h,0FFh,0FFh,07Eh,03Ch,018h,000h,000h    ; #31
  866.     db    000h,000h,000h,000h,000h,000h,000h,000h    ; #32 ' '
  867.     db    030h,078h,078h,030h,030h,000h,030h,000h    ; #33 '!'
  868.     db    06Ch,06Ch,06Ch,000h,000h,000h,000h,000h    ; #34 '"'
  869.     db    06Ch,06Ch,0FEh,06Ch,0FEh,06Ch,06Ch,000h    ; #35 '#'
  870.     db    030h,07Ch,0C0h,078h,00Ch,0F8h,030h,000h    ; #36 '$'
  871.     db    000h,0C6h,0CCh,018h,030h,066h,0C6h,000h    ; #37 '%'
  872.     db    038h,06Ch,038h,076h,0DCh,0CCh,076h,000h    ; #38 '&'
  873.     db    060h,060h,0C0h,000h,000h,000h,000h,000h    ; #39 '''
  874.     db    018h,030h,060h,060h,060h,030h,018h,000h    ; #40 '('
  875.     db    060h,030h,018h,018h,018h,030h,060h,000h    ; #41 ')'
  876.     db    000h,066h,03Ch,0FFh,03Ch,066h,000h,000h    ; #42 '*'
  877.     db    000h,030h,030h,0FCh,030h,030h,000h,000h    ; #43 '+'
  878.     db    000h,000h,000h,000h,000h,030h,030h,060h    ; #44 ','
  879.     db    000h,000h,000h,0FCh,000h,000h,000h,000h    ; #45 '-'
  880.     db    000h,000h,000h,000h,000h,030h,030h,000h    ; #46 '.'
  881.     db    006h,00Ch,018h,030h,060h,0C0h,080h,000h    ; #47 '/'
  882.     db    07Ch,0C6h,0CEh,0DEh,0F6h,0E6h,07Ch,000h    ; #48 '0'
  883.     db    030h,070h,030h,030h,030h,030h,0FCh,000h    ; #49 '1'
  884.     db    078h,0CCh,00Ch,038h,060h,0CCh,0FCh,000h    ; #50 '2'
  885.     db    078h,0CCh,00Ch,038h,00Ch,0CCh,078h,000h    ; #51 '3'
  886.     db    01Ch,03Ch,06Ch,0CCh,0FEh,00Ch,01Eh,000h    ; #52 '4'
  887.     db    0FCh,0C0h,0F8h,00Ch,00Ch,0CCh,078h,000h    ; #53 '5'
  888.     db    038h,060h,0C0h,0F8h,0CCh,0CCh,078h,000h    ; #54 '6'
  889.     db    0FCh,0CCh,00Ch,018h,030h,030h,030h,000h    ; #55 '7'
  890.     db    078h,0CCh,0CCh,078h,0CCh,0CCh,078h,000h    ; #56 '8'
  891.     db    078h,0CCh,0CCh,07Ch,00Ch,018h,070h,000h    ; #57 '9'
  892.     db    000h,030h,030h,000h,000h,030h,030h,000h    ; #58 ':'
  893.     db    000h,030h,030h,000h,000h,030h,030h,060h    ; #59 ';'
  894.     db    018h,030h,060h,0C0h,060h,030h,018h,000h    ; #60 '<'
  895.     db    000h,000h,0FCh,000h,000h,0FCh,000h,000h    ; #61 '='
  896.     db    060h,030h,018h,00Ch,018h,030h,060h,000h    ; #62 '>'
  897.     db    078h,0CCh,00Ch,018h,030h,000h,030h,000h    ; #63 '?'
  898.     db    07Ch,0C6h,0DEh,0DEh,0DEh,0C0h,078h,000h    ; #64 '@'
  899.     db    030h,078h,0CCh,0CCh,0FCh,0CCh,0CCh,000h    ; #65 'A'
  900.     db    0FCh,066h,066h,07Ch,066h,066h,0FCh,000h    ; #66 'B'
  901.     db    03Ch,066h,0C0h,0C0h,0C0h,066h,03Ch,000h    ; #67 'C'
  902.     db    0F8h,06Ch,066h,066h,066h,06Ch,0F8h,000h    ; #68 'D'
  903.     db    0FEh,062h,068h,078h,068h,062h,0FEh,000h    ; #69 'E'
  904.     db    0FEh,062h,068h,078h,068h,060h,0F0h,000h    ; #70 'F'
  905.     db    03Ch,066h,0C0h,0C0h,0CEh,066h,03Eh,000h    ; #71 'G'
  906.     db    0CCh,0CCh,0CCh,0FCh,0CCh,0CCh,0CCh,000h    ; #72 'H'
  907.     db    078h,030h,030h,030h,030h,030h,078h,000h    ; #73 'I'
  908.     db    01Eh,00Ch,00Ch,00Ch,0CCh,0CCh,078h,000h    ; #74 'J'
  909.     db    0E6h,066h,06Ch,078h,06Ch,066h,0E6h,000h    ; #75 'K'
  910.     db    0F0h,060h,060h,060h,062h,066h,0FEh,000h    ; #76 'L'
  911.     db    0C6h,0EEh,0FEh,0FEh,0D6h,0C6h,0C6h,000h    ; #77 'M'
  912.     db    0C6h,0E6h,0F6h,0DEh,0CEh,0C6h,0C6h,000h    ; #78 'N'
  913.     db    038h,06Ch,0C6h,0C6h,0C6h,06Ch,038h,000h    ; #79 'O'
  914.     db    0FCh,066h,066h,07Ch,060h,060h,0F0h,000h    ; #80 'P'
  915.     db    078h,0CCh,0CCh,0CCh,0DCh,078h,01Ch,000h    ; #81 'Q'
  916.     db    0FCh,066h,066h,07Ch,06Ch,066h,0E6h,000h    ; #82 'R'
  917.     db    078h,0CCh,0E0h,070h,01Ch,0CCh,078h,000h    ; #83 'S'
  918.     db    0FCh,0B4h,030h,030h,030h,030h,078h,000h    ; #84 'T'
  919.     db    0CCh,0CCh,0CCh,0CCh,0CCh,0CCh,0FCh,000h    ; #85 'U'
  920.     db    0CCh,0CCh,0CCh,0CCh,0CCh,078h,030h,000h    ; #86 'V'
  921.     db    0C6h,0C6h,0C6h,0D6h,0FEh,0EEh,0C6h,000h    ; #87 'W'
  922.     db    0C6h,0C6h,06Ch,038h,038h,06Ch,0C6h,000h    ; #88 'X'
  923.     db    0CCh,0CCh,0CCh,078h,030h,030h,078h,000h    ; #89 'Y'
  924.     db    0FEh,0C6h,08Ch,018h,032h,066h,0FEh,000h    ; #90 'Z'
  925.     db    078h,060h,060h,060h,060h,060h,078h,000h    ; #91 '['
  926.     db    0C0h,060h,030h,018h,00Ch,006h,002h,000h    ; #92 '\'
  927.     db    078h,018h,018h,018h,018h,018h,078h,000h    ; #93 ']'
  928.     db    010h,038h,06Ch,0C6h,000h,000h,000h,000h    ; #94 '^'
  929.     db    000h,000h,000h,000h,000h,000h,000h,0FFh    ; #95 '_'
  930.     db    030h,030h,018h,000h,000h,000h,000h,000h    ; #96 '`'
  931.     db    000h,000h,078h,00Ch,07Ch,0CCh,076h,000h    ; #97 'a'
  932.     db    0E0h,060h,060h,07Ch,066h,066h,0DCh,000h    ; #98 'b'
  933.     db    000h,000h,078h,0CCh,0C0h,0CCh,078h,000h    ; #99 'c'
  934.     db    01Ch,00Ch,00Ch,07Ch,0CCh,0CCh,076h,000h    ; #100 'd'
  935.     db    000h,000h,078h,0CCh,0FCh,0C0h,078h,000h    ; #101 'e'
  936.     db    038h,06Ch,060h,0F0h,060h,060h,0F0h,000h    ; #102 'f'
  937.     db    000h,000h,076h,0CCh,0CCh,07Ch,00Ch,0F8h    ; #103 'g'
  938.     db    0E0h,060h,06Ch,076h,066h,066h,0E6h,000h    ; #104 'h'
  939.     db    030h,000h,070h,030h,030h,030h,078h,000h    ; #105 'i'
  940.     db    00Ch,000h,00Ch,00Ch,00Ch,0CCh,0CCh,078h    ; #106 'j'
  941.     db    0E0h,060h,066h,06Ch,078h,06Ch,0E6h,000h    ; #107 'k'
  942.     db    070h,030h,030h,030h,030h,030h,078h,000h    ; #108 'l'
  943.     db    000h,000h,0CCh,0FEh,0FEh,0D6h,0C6h,000h    ; #109 'm'
  944.     db    000h,000h,0F8h,0CCh,0CCh,0CCh,0CCh,000h    ; #110 'n'
  945.     db    000h,000h,078h,0CCh,0CCh,0CCh,078h,000h    ; #111 'o'
  946.     db    000h,000h,0DCh,066h,066h,07Ch,060h,0F0h    ; #112 'p'
  947.     db    000h,000h,076h,0CCh,0CCh,07Ch,00Ch,01Eh    ; #113 'q'
  948.     db    000h,000h,0DCh,076h,066h,060h,0F0h,000h    ; #114 'r'
  949.     db    000h,000h,07Ch,0C0h,078h,00Ch,0F8h,000h    ; #115 's'
  950.     db    010h,030h,07Ch,030h,030h,034h,018h,000h    ; #116 't'
  951.     db    000h,000h,0CCh,0CCh,0CCh,0CCh,076h,000h    ; #117 'u'
  952.     db    000h,000h,0CCh,0CCh,0CCh,078h,030h,000h    ; #118 'v'
  953.     db    000h,000h,0C6h,0D6h,0FEh,0FEh,06Ch,000h    ; #119 'w'
  954.     db    000h,000h,0C6h,06Ch,038h,06Ch,0C6h,000h    ; #120 'x'
  955.     db    000h,000h,0CCh,0CCh,0CCh,07Ch,00Ch,0F8h    ; #121 'y'
  956.     db    000h,000h,0FCh,098h,030h,064h,0FCh,000h    ; #122 'z'
  957.     db    01Ch,030h,030h,0E0h,030h,030h,01Ch,000h    ; #123 '{'
  958.     db    018h,018h,018h,000h,018h,018h,018h,000h    ; #124 '|'
  959.     db    0E0h,030h,030h,01Ch,030h,030h,0E0h,000h    ; #125 '}'
  960.     db    076h,0DCh,000h,000h,000h,000h,000h,000h    ; #126 '~'
  961.     db    000h,010h,038h,06Ch,0C6h,0C6h,0FEh,000h    ; #127
  962.  
  963. HGCRegen:        ;offsets into HGC regen buffer for each scan line
  964.     dw    0,8192,16384,24576,90,8282,16474,24666
  965.     dw    180,8372,16564,24756,270,8462,16654,24846
  966.     dw    360,8552,16744,24936,450,8642,16834,25026
  967.     dw    540,8732,16924,25116,630,8822,17014,25206
  968.     dw    720,8912,17104,25296,810,9002,17194,25386
  969.     dw    900,9092,17284,25476,990,9182,17374,25566
  970.     dw    1080,9272,17464,25656,1170,9362,17554,25746
  971.     dw    1260,9452,17644,25836,1350,9542,17734,25926
  972.     dw    1440,9632,17824,26016,1530,9722,17914,26106
  973.     dw    1620,9812,18004,26196,1710,9902,18094,26286
  974.     dw    1800,9992,18184,26376,1890,10082,18274,26466
  975.     dw    1980,10172,18364,26556,2070,10262,18454,26646
  976.     dw    2160,10352,18544,26736,2250,10442,18634,26826
  977.     dw    2340,10532,18724,26916,2430,10622,18814,27006
  978.     dw    2520,10712,18904,27096,2610,10802,18994,27186
  979.     dw    2700,10892,19084,27276,2790,10982,19174,27366
  980.     dw    2880,11072,19264,27456,2970,11162,19354,27546
  981.     dw    3060,11252,19444,27636,3150,11342,19534,27726
  982.     dw    3240,11432,19624,27816,3330,11522,19714,27906
  983.     dw    3420,11612,19804,27996,3510,11702,19894,28086
  984.     dw    3600,11792,19984,28176,3690,11882,20074,28266
  985.     dw    3780,11972,20164,28356,3870,12062,20254,28446
  986.     dw    3960,12152,20344,28536,4050,12242,20434,28626
  987.     dw    4140,12332,20524,28716,4230,12422,20614,28806
  988.     dw    4320,12512,20704,28896,4410,12602,20794,28986
  989.     dw    4500,12692,20884,29076,4590,12782,20974,29166
  990.     dw    4680,12872,21064,29256,4770,12962,21154,29346
  991.     dw    4860,13052,21244,29436,4950,13142,21334,29526
  992.     dw    5040,13232,21424,29616,5130,13322,21514,29706
  993.     dw    5220,13412,21604,29796,5310,13502,21694,29886
  994.     dw    5400,13592,21784,29976,5490,13682,21874,30066
  995.     dw    5580,13772,21964,30156,5670,13862,22054,30246
  996.     dw    5760,13952,22144,30336,5850,14042,22234,30426
  997.     dw    5940,14132,22324,30516,6030,14222,22414,30606
  998.     dw    6120,14312,22504,30696,6210,14402,22594,30786
  999.     dw    6300,14492,22684,30876,6390,14582,22774,30966
  1000.     dw    6480,14672,22864,31056,6570,14762,22954,31146
  1001.     dw    6660,14852,23044,31236,6750,14942,23134,31326
  1002.     dw    6840,15032,23224,31416,6930,15122,23314,31506
  1003.     dw    7020,15212,23404,31596,7110,15302,23494,31686
  1004.     dw    7200,15392,23584,31776,7290,15482,23674,31866
  1005.     dw    7380,15572,23764,31956,7470,15662,23854,32046
  1006.     dw    7560,15752,23944,32136,7650,15842,24034,32226
  1007.     dw    7740,15932,24124,32316
  1008.  
  1009. CGARegen:        ;offset into CGA scan buffer for each scan line
  1010.     dw    0,8192,80,8272,160,8352,240,8432
  1011.     dw    320,8512,400,8592,480,8672,560,8752
  1012.     dw    640,8832,720,8912,800,8992,880,9072
  1013.     dw    960,9152,1040,9232,1120,9312,1200,9392
  1014.     dw    1280,9472,1360,9552,1440,9632,1520,9712
  1015.     dw    1600,9792,1680,9872,1760,9952,1840,10032
  1016.     dw    1920,10112,2000,10192,2080,10272,2160,10352
  1017.     dw    2240,10432,2320,10512,2400,10592,2480,10672
  1018.     dw    2560,10752,2640,10832,2720,10912,2800,10992
  1019.     dw    2880,11072,2960,11152,3040,11232,3120,11312
  1020.     dw    3200,11392,3280,11472,3360,11552,3440,11632
  1021.     dw    3520,11712,3600,11792,3680,11872,3760,11952
  1022.     dw    3840,12032,3920,12112,4000,12192,4080,12272
  1023.     dw    4160,12352,4240,12432,4320,12512,4400,12592
  1024.     dw    4480,12672,4560,12752,4640,12832,4720,12912
  1025.     dw    4800,12992,4880,13072,4960,13152,5040,13232
  1026.     dw    5120,13312,5200,13392,5280,13472,5360,13552
  1027.     dw    5440,13632,5520,13712,5600,13792,5680,13872
  1028.     dw    5760,13952,5840,14032,5920,14112,6000,14192
  1029.     dw    6080,14272,6160,14352,6240,14432,6320,14512
  1030.     dw    6400,14592,6480,14672,6560,14752,6640,14832
  1031.     dw    6720,14912,6800,14992,6880,15072,6960,15152
  1032.     dw    7040,15232,7120,15312,7200,15392,7280,15472
  1033.     dw    7360,15552,7440,15632,7520,15712,7600,15792
  1034.     dw    7680,15872,7760,15952,7840,16032,7920,16112
  1035.  
  1036. main    endp
  1037. code    ends
  1038.     end    start
  1039.