home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / SCREEN / XFLASH1.ARC / XFLASH-2.ASM next >
Encoding:
Assembly Source File  |  1987-03-17  |  10.9 KB  |  435 lines

  1. ; XFLASH-2 by David Hite     -    Optimized for 8088-2 Processor
  2. ; Eliminates the flash that occurs during scrolling on the CGA.
  3. ; XFLASH is FreeWare.
  4.  
  5. ; Your machine may be able to move more characters or fewer
  6. ; characters during vertical retraces than mine (a Leading Edge Model M).  
  7. ; You can experiment by changing the values of max_vert and clr_max_vert.
  8. ; Max_horiz will probably not need to be changed, because it is
  9. ; based on the CGA's 200 scan lines.
  10.  
  11. ; The difference between XFLASH and XFLASH-2, other than the different
  12. ; values for max_vert and clr_max_vert, is that XFLASH-2 moves a word
  13. ; during the horizontal retrace, while XFLASH can only move a byte.
  14. ; The code is therefore slightly different.
  15.  
  16. ; for the Leading Edge Model M 8088-2 chip, the values are as follows
  17. ; clr_max_vert equ 500
  18. ; max_vert     equ 240
  19.  
  20.  
  21. clr_max_vert    equ    500        ; the maximum number of words to
  22.                         ; clear during a vertical retrace
  23. max_vert        equ    240        ; the maximum number of words to move in 
  24.                         ; a vertical retrace
  25. max_horiz    equ    197        ; the maximum number of horizontal retraces
  26.                         ; to be used for moving 1 word between 
  27.                         ; vertical retraces.  This is set to just
  28.                         ; less than the number of scan lines so that
  29.                         ; the next vertical retrace is not missed.  
  30.                         ; Increasing this value can actually slow the
  31.                         ; program down because it will have to wait
  32.                         ; longer for the next vertical retrace.
  33.  
  34. vstat        equ    3dah            ; the video status register
  35. v_retrace    equ    00001000b        ; vertical retrace bit mask
  36. h_retrace    equ    00000001b        ; horizontal retrace bit mask
  37.  
  38.  
  39. cseg    segment para public 'code'
  40.     assume cs:cseg,ds:cseg,ss:cseg,es:nothing
  41.     org    100h
  42.  
  43. start:
  44.     jmp install                ; install the program
  45.  
  46. savestack    dw    0,0
  47. request        dw    0            ; ax from interrupt
  48. fill_attrib    dw    0            ; bx from interrupt
  49. video_handler dd    0            ; address of the original video handler
  50. apage        db    0            ; active video page
  51. amode        db    3            ; active video mode
  52. display_seg     dw     0b800h        ; addr of cga display memory
  53.  
  54. new_video_int proc far            ; far label since it's entered by interrupt
  55.                             ; and thus must generate inter-segment ret
  56.     sti                        ; enable interrupts
  57.  
  58.     cmp    ah,0                    ; check for mode switch
  59.     jne    chk_mode
  60.     mov    cs:amode,al            ; remember new mode
  61.     jmp    short not_ours            ; and let bios change the mode
  62.  
  63. chk_mode:
  64.     cmp    cs:amode,3            ; we don't scroll graphics modes
  65.     jg    not_ours
  66.  
  67. chk_5:
  68.     cmp    ah,5                    ; check for page switch
  69.     jl    not_ours
  70.     jne    chk_6
  71.     mov    cs:apage,al            ; remember new page number
  72.     jmp    short not_ours            ; and let bios change the page
  73.  
  74. chk_6:
  75.     cmp    ah,6
  76.     jne    chk_7
  77. chk_6a:
  78.     cmp    cl,0                    ; we do it only for complete lines
  79.     jne    not_ours
  80.     cmp    dl,79
  81.     jne    not_ours
  82.     jmp    short scroll
  83.  
  84. chk_7:
  85.     cmp    ah,7
  86.     je    chk_6a
  87.  
  88. not_ours:
  89.     pushf                ; emulate int instruction
  90.     call dword ptr    [cs:video_handler]
  91.     iret
  92.  
  93. scroll:
  94.     mov cs:savestack,sp
  95.     mov cs:savestack+2,ss
  96.  
  97.     mov    cs:request,ax
  98.     mov    ax,cs
  99.     mov    ss,ax
  100.     mov    sp,100h
  101.  
  102.     push bp                ; set up a stack frame
  103.     mov    bp,sp
  104.     sub    sp,0eh
  105.     call savereg
  106.     mov    ds,ax
  107.     mov    ax,request
  108.  
  109.     call    main                ; that's where the work is done
  110.  
  111.     call restreg
  112.      add    sp,0eh
  113.     pop    bp
  114.  
  115.     mov ss,cs:savestack+2
  116.     mov sp,cs:savestack
  117.  
  118.     iret                ; return from interrupt
  119.  
  120. new_video_int    endp
  121.  
  122. inside proc near
  123. fix_ch0:
  124.     mov    ch,0
  125.     jmp    short chk_dh
  126. fix_ch24:
  127.     mov    ch,24
  128.     jmp    short chk_dh
  129. fix_dh0:
  130.     mov    dh,0
  131.     jmp    short chk_al
  132. fix_dh24:
  133.     mov    dh,24
  134.     jmp    short chk_al
  135. fix_al25:
  136.     mov    al,25
  137.     jmp    short regs_ok
  138.  
  139. main:
  140.     mov    fill_attrib,bx        ; save fill attribute for much later (clr_area)
  141.     push    dx                ; because MUL uses it
  142.     cmp    ch,0
  143.     jl    fix_ch0
  144.     cmp    ch,24
  145.     jg    fix_ch24
  146. chk_dh:
  147.     cmp    dh,0
  148.     jl    fix_dh0    
  149.     cmp    dh,24
  150.     jg    fix_dh24
  151. chk_al:
  152.     mov    ax,request
  153.     cmp    al,0
  154.     jle    fix_al25
  155.     cmp    al,25
  156.     jg    fix_al25
  157. regs_ok:
  158.     mov    request,ax        ; in case we fixed it
  159.     xor    bh,bh
  160.     mov    bl,apage            ; get the current page number
  161.     mov    ax,4096            ; the size of a a page
  162.     mul    bx                ; multiply by the page number to get offset
  163.     mov    di,ax            ; and put it in the destination index
  164.                         ; now calculate the offset of the window
  165.     mov    bl,ch            ; by getting the starting row
  166.     xor    bh,bh
  167.     mov    ax,160            ; we only handle full rows
  168.     mul    bx                ; and multiply by chars/row to get offset
  169.     add    di,ax            ; and adding to di to get address
  170.     mov    ax,di
  171.     mov    si,ax            ; and put it in the source index as well
  172.     pop    dx
  173.     mov    ax,request        ; get the original request
  174.     mov    bh,dh            ; move bottom line to bh
  175.     sub    bh,ch            ; subtract top line
  176.     inc    bh                ; bh now has number of lines in window
  177.  
  178.     cld                    ; we'll move forward unless scroll is down
  179.     mov    es,display_seg
  180.     cmp    al,0                ; clear the area?
  181.     jbe    m_1                ; yes
  182.     cmp    al,bh
  183.     je    m_1b                ; we are clearing all the lines
  184.     jb    m_2                ; we are clearing some of the lines
  185. m_1:                    ; we are clearing more than all the lines!
  186.     mov    al,bh            ; move number of lines in window to al
  187.     mov    request,ax
  188. m_1b:
  189.     jmp    clr_area
  190.  
  191. m_2:                    ; bh has lines in window, al has lines
  192.                         ; to scroll
  193.     cmp    ah,6                ; up or down?
  194.     je    up
  195. down:                    ; we are scrolling down
  196.     std                    ; so we move backwards
  197.  
  198.     sub    al,bh            ; the source is bh-al lines below si
  199.     neg    al                ; correct the sign
  200.     cbw                    ; convert to a word
  201.     mov    cx,160
  202.     mul    cx                ; multiply by chars/row
  203.     sub    ax,2                ; subtract a word to get end of line
  204.     add    si,ax            ; and add to si, the address of the up left
  205.  
  206.     ; the destination is the lower right which is bh lines 
  207.     ; below current di => di = di + bh*160 - 2
  208.  
  209.     mov    al,bh            ; get lines in window into al
  210.     cbw
  211.     mov    cx,160
  212.     mul    cx
  213.     sub    ax,2                ; subtract a word to get end of line
  214.     add    di,ax            ; di now has address of destination
  215.     
  216.     jmp    short movem
  217.  
  218. up:                        ; we are scrolling up
  219.     ; the source is al lines below si which is al*160 chars below current si
  220.  
  221.     cbw                    ; gets number of lines into ax
  222.     mov    cx,160
  223.     mul    cx
  224.     add    si,ax            ; si now has address of source
  225.  
  226.     ; the initial destination is correct, we don't need to change it
  227.  
  228. movem:                    ; now start to move words
  229.     ; fix bx such that it is number of words to move 
  230.     ; = (number of lines in window minus number of lines to scroll)*80
  231.  
  232.     mov    ax,request        ; get number of lines to scroll
  233.     cbw                    ; slightly faster than xor ah,ah
  234.     sub    al,bh            ; subtract lines in window from lines to scroll
  235.     neg    al                ; after correcting the sign, ax has lines to move
  236.     mov    cx,80            ; words/line
  237.     mul    cx                ; multiply to get words to move
  238.     mov    bx,ax            ; bx now has number of words to move
  239.  
  240.     push    ds                ; we're about to change it to display_seg
  241.     mov    dx,vstat            ; the video status register
  242.     mov    ds,display_seg        ; load address of display segment
  243.  
  244. mvm_vert:                ; first wait for a vertical refresh
  245.     mov    cx,bx            ; move words remaining to cx
  246.     cmp    cx,max_vert        ; too  many?
  247.     jle    mvm_many            ; no, go move'm
  248.     mov    cx,max_vert        ; yes, move max_vert more, maximum
  249. mvm_many:
  250.     sub    bx,cx            ; that many will remain when rep movsw ends
  251.  
  252. mvm_v_refresh:
  253.     in    al,dx
  254.     test    al,v_retrace
  255.     jnz    mvm_v_refresh        ; wait for a non retrace period
  256.  
  257. mvm_v_wait:
  258.     in    al,dx            ; get the retrace status
  259.     test    al,v_retrace        ; check for retrace in progress
  260.     jz    mvm_v_wait        ; wait until retrace
  261.  
  262.     ; in a vertical retrace, we can move many
  263.     rep    movsw
  264.     cmp    bx,0
  265.     je    mvm_end
  266.  
  267.     mov    cx,max_horiz
  268. mvm_1:
  269.     dec    bx
  270. mvm_h_refresh:
  271.     in    al,dx
  272.     test    al,h_retrace
  273.     jnz    mvm_h_refresh        ; wait for a non retrace period
  274.  
  275. ;    the next statement is commented out to prevent comm char loss 
  276. ;    cli                    ; disable interrupts while waiting (not long)
  277. mvm_h_wait:
  278.     in    al,dx            ; get the retrace status
  279.     test    al,h_retrace        ; check for retrace in progress
  280.     jz    mvm_h_wait        ; wait until retrace
  281.  
  282.     movsw                ; now move one word
  283. ;    sti                    ; and now enable interrupts again
  284.  
  285.     cmp    bx,0                ; are we finished?
  286.     je    mvm_end
  287.     loop    mvm_1
  288.     cmp    bx,0
  289.     je    mvm_end
  290.  
  291. mvm_do_cx_again:
  292.     mov    cx,bx            ; move words remaining to cx
  293.     cmp    cx,max_vert        ; too  many?
  294.     jle    mvm_h_many        ; no, go move'm
  295.     mov    cx,max_vert        ; yes, move max_vert more, maximum
  296. mvm_h_many:
  297.     sub    bx,cx            ; that many will remain when rep movsw ends
  298.     jmp    mvm_v_wait
  299.  
  300. mvm_end:                    ; we've finished moving
  301.     pop    ds                ; restore the data segment
  302.  
  303. clr_area:
  304. ;    we're now ready to blank the number of lines that were scrolled.
  305. ;    The direction flag and di and es are set correctly, given
  306. ;    what we've done so far.  All we need to do is calculate number of 
  307. ;    words to blank.
  308.  
  309.     mov    ax,request        ; to get number lines to scroll
  310.     cbw
  311.     mov    cx,80            ; words/line
  312.     mul    cx                ; ax now has words to blank
  313.     mov    bx,ax            ; put it in bx
  314.  
  315.     mov    dx,fill_attrib        ; dh now has the fill attribute
  316.     mov    dl,' '            ; move a space to dl
  317.  
  318.     mov    si,dx            ; move clear char to si
  319.  
  320. ;    the following code sets the screen border to the fill attribute.
  321. ;    un-comment it if you want to do this
  322. ;    mov    cl,4
  323. ;    shr    dh,cl
  324. ;    mov    al,dh
  325. ;    or    al,20h
  326. ;    mov    dx,03d9h            ; set border to fill attribute
  327. ;    out    dx,al
  328. ;    end of set border code
  329.  
  330.     mov    dx,vstat            ; the video status register
  331.  
  332. clr_vert:                ; first wait for a vertical refresh
  333.     mov    cx,bx            ; move words remaining to cx
  334.     cmp    cx,clr_max_vert    ; too  many?
  335.     jle    clr_many            ; no, go move'm
  336.     mov    cx,clr_max_vert    ; yes, move clr_max_vert more, maximum
  337. clr_many:
  338.     sub    bx,cx            ; that many will remain when rep stosw ends
  339.  
  340. clr_v_refresh:
  341.     in    al,dx
  342.     test    al,v_retrace
  343.     jnz    clr_v_refresh        ; wait for a non retrace period
  344.  
  345. clr_v_wait:
  346.     in    al,dx            ; get the retrace status
  347.     test    al,v_retrace        ; check for retrace in progress
  348.     jz    clr_v_wait        ; wait until retrace
  349.     xchg    ax,si
  350.     rep    stosw
  351.     xchg    ax,si
  352.     cmp    bx,0
  353.     je    clr_end
  354.  
  355.     mov    cx,max_horiz
  356. clr_1:
  357.     dec    bx
  358. clr_h_refresh:
  359.     in    al,dx
  360.     test    al,h_retrace
  361.     jnz    clr_h_refresh        ; wait for a non retrace period
  362.  
  363. ;    the next statement is commented out to prevent comm char loss 
  364. ;    cli                    ; disable interrupts while waiting (not long)
  365. clr_h_wait:
  366.     in    al,dx            ; get the retrace status
  367.     test    al,h_retrace        ; check for retrace in progress
  368.     jz    clr_h_wait        ; wait until retrace
  369.     xchg    ax,si
  370.     stosw                ; now move one word
  371. ;    sti                    ; and now enable interrupts again
  372.     xchg    ax,si
  373.     cmp    bx,0                ; are we finished?
  374.     je    clr_end
  375.     loop    clr_1
  376.     cmp    bx,0
  377.     je    clr_end
  378.  
  379. clr_do_cx_again:
  380.     mov    cx,bx            ; move words remaining to cx
  381.     cmp    cx,clr_max_vert    ; too  many?
  382.     jle    clr_h_many        ; no, go move'm
  383.     mov    cx,clr_max_vert    ; yes, move clr_max_vert more, maximum
  384. clr_h_many:
  385.     sub    bx,cx            ; that many will remain when rep movsw ends
  386.     jmp    clr_v_wait
  387.  
  388. clr_end:                    ; we've finished moving
  389.  
  390.     cld                    ; just for the heck of it
  391.     ret
  392.  
  393.  
  394. savereg:
  395.     mov    -2[bp],bx
  396.     mov    -4[bp],cx
  397.     mov    -6[bp],dx
  398.     mov    -8[bp],si
  399.     mov    -0ah[bp],di
  400.     mov    -0ch[bp],ds
  401.     mov    -0eh[bp],es
  402.     ret
  403. restreg:
  404.     mov    bx,-2[bp]
  405.     mov    cx,-4[bp]
  406.     mov    dx,-6[bp]
  407.     mov    si,-8[bp]
  408.     mov    di,-0ah[bp]
  409.     mov    ds,-0ch[bp]
  410.     mov    es,-0eh[bp]
  411.     ret
  412. inside    endp
  413.  
  414. install:
  415.  
  416.     mov ax,3510h            ; get interrupt 10 vector
  417.     int 21h
  418.     mov word ptr video_handler,bx
  419.     mov word ptr video_handler+2,es
  420.  
  421.     mov ax,2510h
  422.     mov dx,offset new_video_int    ; now put our routine there
  423.     int 21h
  424.  
  425.     mov dx,offset install    ; terminate and stay resident
  426.     mov cl,4
  427.     shr dx,cl
  428.     inc dx                ; round up
  429.     mov ah,31h
  430.     int 21h
  431.  
  432.  
  433. cseg ends
  434.     end start
  435.