; GWIN.ASM:  Graphics window in text mode.

Ideal
Model Tiny
P186
CodeSeg
Org 100h

Start:      jmp Prog

PicX dw 8 dup(-1),128,6 dup(0),256,128,3,0,-193,254,0,-256,448,128,3
     dw 0,-193,-7937,0,-241,508,128,32775,0,60,-1023,0,127,33087,128
     dw 32775,0,60,7936,256,240,-7933,128,49167,0,60,1792,896,192,-3840
     dw 128,49167,0,60,768,960,192,-3840,128,-8161,0,60,768,1984,128
     dw 30976,128,-8161,0,60,256,2016,128,30976,128,-4036,0,60,256,2016
     dw 128,30976,128,-4036,0,60,256,4064,0,15616,128,30840,0,60,0,4080
     dw 0,15616,128,30840,0,60,0,4080,0,15616,128,15600,0,60,0,7920,0
     dw 256,128,15600,0,60,0,7920,0,256,384,7904,0,60,256,7904,0,256
     dw 384,7904,0,60,256,7904,0,256,896,4032,0,60,256,7904,0,256,896
     dw 4032,0,60,768,7872,0,256,1920,1920,128,60,768,7872,0,256,1920
     dw 1920,128,60,1792,7808,0,256,3968,768,192,60,15872,7680,0,256
     dw 3968,768,192,-193,-1793,7680,0,256,7808,256,224,-193,-1793,7680
     dw 0,256,7808,256,224,60,15872,7680,0,256,15488,0,240,60,1792,7808
     dw 0,256,15488,0,240,60,768,7872,0,256,32640,-1,248,60,768,7872
     dw 0,256,32640,-1,248,60,256,7904,0,256,-3968,0,60,60,256,7904,0
     dw 256,-3968,0,60,60,256,7904,0,256,-8063,0,30,60,0,7920,0,256,-8063
     dw 0,30,60,0,7920,0,256,49283,0,15,60,0,4080,0,15616,49283,0,15
     dw 60,0,4080,0,15616,32903,0,32775,60,256,4064,0,15616,32903,0,32775
     dw 60,256,2016,128,30976,143,0,49155,60,256,2016,128,30976,143,0
     dw 49155,60,768,1984,128,30976,143,0,49155,60,768,960,192,-3840
     dw 158,0,-8191,60,1792,896,192,-3840,158,0,-8191,60,7936,256,240
     dw -7933,188,0,-4096,60,-1023,0,127,33087,188,0,-4096,-193,-7937
     dw 0,-241,508,188,0,-4096,-193,254,0,-256,448,128,6 dup(0),256
     dw 8 dup(-1)

Proc        Prog

            call InitTG             ;Init textgraphics

            call FillScr            ;Fill screen with chars

            mov ax,10               ;Open window from
            mov bx,5                ;(10, 5) to (25, 7)
            mov cx,25               ;in green
            mov dx,7
            mov si,2
            call OpenWin            ;Do it...
            jc pr_done              ;Jump if error

            mov si,offset PicX      ;Show the picture
            call ShowPic

            xor ah,ah               ;Wait for a key
            int 16h

pr_done:    mov ax,3                ;Set text mode
            int 10h
            ret                     ;Return

EndP        Prog

Proc        FillScr

            pusha                   ;Save all registers
            push es
            push 0B800h             ;ES = 0B800h
            pop es

            xor di,di               ;Set up for loop
            mov ax,0700h
            mov cx,2000

fs_loop:    stosw                   ;Write char
            inc al                  ;Next char
            loop fs_loop            ;Loop back

            pop es                  ;Restore registers
            popa
            ret                     ;Return

EndP        FillScr

;---------------------------------------------------------------
; Text-Mode Graphics Window procedures start here
;---------------------------------------------------------------

GWinX1      dw 0                    ;Graphics window position
GWinY1      dw 0
GWinXD      dw 0                    ;Graphics window size
GWinYD      dw 0

OEData1     dw 0402h,0704h,0204h    ;Odd/Even release data
            dw 0005h,0C06h
OEData2     dw 0302h,0304h,0004h    ;Odd/Even restore data
            dw 1005h,0E06h

;**************************** InitTG -- Init textgraphics mode

Proc        InitTG

            pusha                   ;Save all registers

            mov ax,3                ;Set text mode
            int 10h
            mov ax,1114h            ;Load 16-point font
            int 10h

            mov dx,03C2h            ;Set 25MHz clock
            mov al,63h
            out dx,al

            mov dl,0C4h             ;Set 8 bit chars
            mov ax,0101h
            out dx,ax
            mov ax,0403h            ;Set double font
            out dx,ax

            mov dl,0DAh             ;Reset AC
            in al,dx

            mov dl,0C0h             ;Set pixel pan 0
            mov al,33h
            out dx,al
            mov al,00h
            out dx,al

            popa                    ;Restore registers
            ret                     ;Return

EndP        InitTG

;**************************** OpenWin -- Open a graphics window
;                             ---------------------------------
;                             AX=x1, BX=y1, CX=x2, DX=y2, SI=color
;                             Returns: CF=error

Proc        OpenWin

            pusha                   ;Save all registers
            push es
            push 0B800h             ;ES = video memory
            pop es

            sub cx,ax               ;CX, DX = distances
            sub dx,bx
            inc cx
            inc dx
            push cx dx              ;Save CX, DX

            xchg ax,cx              ;CX = size
            mul dx
            xchg ax,cx
            cmp cx,257              ;Too big?
            pop dx cx               ;Restore CX, DX
            jae ow_done

            mov [GWinX1],ax         ;Save parameters
            mov [GWinY1],bx
            mov [GWinXD],cx
            mov [GWinYD],dx

            imul bp,bx,160          ;BP = offset
            add bp,ax
            add bp,ax

            mov ax,si               ;AX = char data
            and al,7
            add al,8
            shl ax,8

            mov si,cx               ;SI = X distance

ow_oloop:   mov cx,si               ;CX = length
            mov di,bp               ;DI = offset

ow_loop:    stosw                   ;Write data
            inc ax                  ;Next char
            loop ow_loop            ;Loop back

            add bp,160              ;Next line
            dec dx                  ;Loop back
            jnz ow_oloop

            call ClearWin           ;Clear the window

            stc                     ;Set carry (gets flipped)

ow_done:    pop es                  ;Restore registers
            popa
            cmc                     ;Flip carry flag
            ret                     ;Return

EndP        OpenWin

;**************************** ClearWin -- Clear the graphics window

Proc        ClearWin

            pusha                   ;Save all registers
            push es
            push 0B800h             ;ES = video memory
            pop es

            call FontOn             ;Get font memory

            mov di,4000h            ;Clear font bank 1
            mov cx,2000h
            xor ax,ax
            rep stosw

            call FontOff            ;Back to normal mode

            pop es                  ;Restore registers
            popa
            ret                     ;Return

EndP        ClearWin

;**************************** FontOn -- Map in font memory

Proc        FontOn

            pusha                   ;Save all registers

            mov si,offset OEData1   ;SI = OE data 1 (on)
            mov dx,03C4h            ;Send 2 words to SC
            outsw
            outsw
            mov dl,0CEh             ;Send 3 words to GC
            outsw
            outsw
            outsw

            popa                    ;Restore registers
            ret                     ;Return

EndP        FontOn

;**************************** FontOff -- Map out font memory

Proc        FontOff

            pusha                   ;Save all registers

            mov si,offset OEData2   ;SI = OE data 2 (off)
            mov dx,03C4h            ;Send 2 words to SC
            outsw
            outsw
            mov dl,0CEh             ;Send 3 words to GC
            outsw
            outsw
            outsw

            popa                    ;Restore registers
            ret                     ;Return

EndP        FontOff

;**************************** SetPixel -- Set one pixel in window
;                             -----------------------------------
;                             BX=X, CX=Y, AL=on/off

Proc        SetPixel

            pusha                   ;Save all registers
            push es
            push 0B800h             ;ES = video memory
            pop es

            mov dx,[GWinXD]         ;Out of range X?
            shl dx,3
            cmp bx,dx
            jae sp_done

            mov dx,[GWinYD]         ;Out of range Y?
            shl dx,4
            cmp cx,dx
            jae sp_done

            call FontOn             ;Get font memory

            push ax                 ;Save AX

            mov ax,cx               ;AX = Y char * XD
            shr ax,4
            imul [GWinXD]

            mov si,bx               ;AX = Y char * XD + X char
            shr si,3
            add si,ax

            shl si,5                ;SI = offset
            and cx,15
            add si,cx
            add si,4000h

            mov cx,bx               ;CX = position
            and cx,7
            mov al,80h              ;AL = value
            shr al,cl

            pop bx                  ;BX = color value
            test bx,bx              ;Check color value
            jz sp_skip1

            or [es:si],al           ;Set pixel
            jmp sp_skip2

sp_skip1:   not al                  ;Reset pixel
            and [es:si],al

sp_skip2:   call FontOff            ;Back to normal mode

sp_done:    pop es                  ;Restore registers
            popa
            ret                     ;Return

EndP        SetPixel

;**************************** ShowPic -- Load a picture in the window
;                             ---------------------------------------
;                             SI = pointer to picture

Proc        ShowPic

            pusha                   ;Save all registers
            push es
            push 0B800h             ;ES = video memory
            pop es

            call FontOn             ;Get font memory

            mov bp,4000h            ;BP = 4000h

            mov dx,[GWinXD]         ;DX = width * 32
            shl dx,5
            mov bx,[GWinYD]         ;BX = height in chars

sp_loop1:   mov ax,16               ;16 lines/char
sp_loop2:   mov cx,dx               ;CX = length
            shr cx,5
            mov di,bp               ;DI = offset

sp_loop3:   movsb                   ;Move byte
            add di,31               ;Next byte
            loop sp_loop3           ;Loop back

            inc bp                  ;Move down 1 line
            dec ax                  ;Loop back
            jnz sp_loop2

            add bp,dx               ;Move down 1 char
            sub bp,16
            dec bx                  ;Loop back
            jnz sp_loop1

            call FontOff            ;Back to normal mode

            pop es                  ;Restore registers
            popa
            ret                     ;Return

EndP        ShowPic

End Start
