View Source Document

screen.s

;--- CONSTANTS -----------------------------------------------;

;--- DATA ----------------------------------------------------;

SEGMENT .bss

winbuf:     RESW    4096

SEGMENT .data

winbufptr:  dw  winbuf

;--- CODE ----------------------------------------------------;

SEGMENT .text

        ;;--------------------------------------------;
        ;; Given a row and a column, determine offset.
        ;; al: row (0-based) -> GARBAGE
        ;; ah: column (0-based) -> GARBAGE
        ;; cx: * -> GARBAGE
        ;; dx: * -> GARBAGE
        ;; di: * -> offset
CalcScreenOffset:mov    cl, ah
        xor ch, ch
        xor ah, ah
        xor dx, dx
        mul word [bytesperline]
        shl cx, 1
        add ax, cx
        mov di, ax
        ret



        ;;--------------------------------------------;
        ;; Save a row of the screen to a buffer.
        ;; di: ptr to start of screen row -> INCREMENTED
        ;; cl: length of row -> 0
        ;; ax: * -> GARBAGE
        ;; si: * -> GARBAGE
SaveScreenRow:  mov si, [winbufptr]
.Loop:      mov ax, [es:di]
        mov [ds:si], ax
        inc di
        inc di
        inc si
        inc si
        dec cl
        jnz .Loop
        mov [winbufptr], si
        ret

        ;;--------------------------------------------;
        ;; Save a portion of the screen to a buffer.
        ;; al: row (0-based) of upper-left corner ->
        ;; ah: column (0-based) of upper-left corner ->
        ;; bl: height of portion to save -> 0
        ;; bh: width of portion to save ->
        ;; cx: * -> GARBAGE
        ;; di: * -> GARBAGE
SaveScreen: push    ax
        push    bx
        call    CalcScreenOffset
.Loop:      mov cl, bh
        push    di
        call    SaveScreenRow
        pop di
        add di, [bytesperline]
        dec bl
        jnz .Loop
        mov di, [winbufptr]
        pop bx
        pop ax
        mov [ds:di], ax
        inc di
        inc di
        mov [ds:di], bx
        inc di
        inc di
        mov [winbufptr], di
        ret


        ;;--------------------------------------------;
        ;; Restore a row of the screen from the buffer.
        ;; di: ptr to start of screen row -> INCREMENTED
        ;; cl: length of row -> 0
        ;; ch: * -> GARBAGE
        ;; ax: * -> GARBAGE
        ;; si: * -> GARBAGE
RestoreScreenRow:xor    ch, ch
        mov si, [winbufptr]
        mov ax, cx
        shl ax, 1
        sub si, ax
        mov [winbufptr], si
.Loop:      mov ax, [ds:si]
        mov [es:di], ax
        inc di
        inc di
        inc si
        inc si
        dec cl
        jnz .Loop
        ret


        ;;--------------------------------------------;
        ;; Restore a portion of the screen from buffer.
        ;; *: * -> GARBAGE
RestoreScreen:  mov di, [winbufptr]
        dec di
        dec di
        mov bx, [ds:di]     ; bl = height, bh = width
        dec di
        dec di
        mov ax, [ds:di]     ; al = row, ah = column
        mov [winbufptr], di
        add al, bl          ; work from bot to top!
        dec al
        call    CalcScreenOffset    ; di = offset
.Loop:      mov cl, bh
        push    di
        call    RestoreScreenRow
        pop di
        sub di, [bytesperline]
        dec bl
        jnz .Loop
        ret

PopUpTest:  mov ax, 200ah
        mov bx, 0a05h
        call    SaveScreen

        mov bh, 0
        mov cx, 0a20h       ; (10,32)-
        mov dx, 0e29h       ; (14,41)
        mov ax, 0600h       ; BIOS clear rectangle
        int 10h

        ; draw a border here!

        call    GetKey

        call    RestoreScreen
        ret


;--- END -----------------------------------------------------;