home *** CD-ROM | disk | FTP | other *** search
- ;
- ; SCRPUTW.ASM
- ;
- ; From the book "Systems Programming in Turbo C", by Michael J. Young
- ;
- ; This version of ScrPutWin() is to be used for CGA monitors
- ; that produce 'snow' when writing directly to the screen
- ;
-
- EXTRN _VideoSeg:word
-
- assume cs:_text
-
- _text segment byte public 'code'
-
-
- ; ------------------------- ScrPutWin() ---------------------------
- public _ScrPutWin
-
- _ScrPutWin proc near
-
- sframe struc
- BasePtr dw ? ; Template to access stack frame
- RetAd dw ? ; Position of saved BP register
- buf_ad dw ? ; other models should use 'dd'
- ulr_s dw ? ; Upper-left row source
- ulc_s dw ? ; Upper-left column source
- lrr_s dw ? ; Lower-right row source
- lrc_s dw ? ; Lower-right column source
- ulr_d dw ? ; Upper-left row destination
- ulc_d dw ? ; Upper-left column destination
- sframe ends
-
- frame equ [bp - BasePtr] ; Base for accessing stack frame
- ; Standard initialization
- push bp
- mov bp, sp
- sub sp, BasePtr
- push di
- push si
-
- mov si, frame.buf_ad
-
- mov ax, frame.ulr_s ; Multiply starting row by 160
- mov bx, ax
- mov cl, 7
- shl ax, cl
- mov cl, 5
- shl bx, cl
- add bx, ax
-
- mov ax, frame.ulc_s ; Multiply starting column by 2
- shl ax, 1
- add bx, ax ; Total offset in BX
- add si, bx ; Add offset to SI
- ; SI now contains offset in source buffer
- mov ax, _VideoSeg ; Set ES to CGA video buffer
- mov es, ax
-
- ; Calculate video memory offset
- ; = (row * 160) + (col * 2)
- mov di, frame.ulr_d ; Place row in DI & multiply by 160
- mov ax, di
- mov cl, 7
- shl di, cl
- mov cl, 5
- shl ax, cl
- add di, ax
-
- mov ax, frame.ulc_d ; Multiply col by 2
- shl ax, 1
- add di, ax ; Add (col * 2) to DI
- ; DI now contains video memory offset
-
- ; Calculate number of rows in BL
- mov bl, byte ptr frame.lrr_s
- sub bl, byte ptr frame.ulr_s
- inc bl
- ; Calculate # of bytes/row in BH
- mov bh, byte ptr frame.lrc_s
- sub bh, byte ptr frame.ulc_s
- inc bh
- shl bh, 1
-
- mov ah, 160 ; Calculate SI, DI increment in AH
- sub ah, bh
-
- mov dx, 3dah ; Keep crt status register in DX
-
- cld
- mov ch, 0 ; Only need LSB of CX
-
- b01: mov cl, bh ; Load bytes/row into CX
-
- ; Pause until the beginning of a
- ; vertical retrace
- b02: in al, dx ; Loop to complete any retrace period
- test al, 8 ; in progress
- jnz b02
- b03: in al, dx ; Loop until start of a new vertical
- test al, 8 ; retrace
- jz b03
-
- rep movsb ; Move entire row during vertical retrace
- mov cl, ah ; AH stores SI, DI increment value
- add si, cx ; Adjust SI, DI to start of next row
- add di, cx
- dec bl ; Decrement row counter
- jz b06 ; Quit if no more rows
-
- ; Move another row, byte by byte, while
- ; waiting for next vertical retrace.
- ; Pause until the beginning of a
- ; horizontal retrace.
- mov cl, bh ; Loop to complete any retrace period
- b04: in al, dx ; in progress
- test al, 1
- jnz b04
- cli ; Don't want interrupt now
- b05: in al, dx ; Loop until start of a new horizontal
- test al, 1 ; retrace
- jz b05
- movsb ; Move one byte
- sti ; Byte transferred, so interrupts ok
- loop b04 ; Loop until entire row is moved
- mov cl, ah
- add si, cx ; Adjust SI, DI to start of next row
- add di, cx
- dec bl ; Decrement row counter
- jz b06 ; Quit if no more rows
- jmp b01 ; Go back to move another row during the
- ; next vertical retrace
-
- b06: pop si ; Restore C register variables
- pop di
- mov sp, bp
- pop bp
- ret ; Return to C program
-
- _ScrPutWin endp
-
- _text ends
- end