;
;  National Center for Supercomputing Applications, University of Illinois
;  153 Water Resources Building
;  605 E. Springfield Ave.
;  Champaign, IL 61820
;
;  (217)244-0072
;
;  Code by Alex Wong  Spring 1986
;  C interface by Tim Krauskopf
;

		TITLE   PGA GRAPHICS RASTER DRIVER
    	NAME	PGA
		INCLUDE DOS.MAC
		SETX
		DSEG
;
otbase  equ     6000h           ;base location of output buffer
otwptr  equ     6300h           ;output write pointer
otrptr  equ     6301h           ;output read pointer
pgaoff  equ     0c000h          ;offset to DMA location
cboot   equ     6306h           ;cold restart flag location
wboot   equ     6307h           ;warm restart flag location
errf    equ     6308h           ;error enable flag
;
hreset  db      43h,58h,20h,0dh ;CX--set to hex mode
resetf  db      04h             ;RESETF--reset flags
displa  db      0d0h,00h        ;DISPLAY--set display mode
lutint  db      0ech            ;LUTINT--initialize color LUT
        db      02h             ;state 2
clears  db      0fh             ;CLEARS--clear screen
        db      00h             ;black background
normal  db      0d0h,01h
;
temp    db      0               ;temporary storage
buf     db      100 dup(0)
;

		ENDDS

		PSEG
		PUBLIC  INITPGA,RESTPGA,PGALINEA,MAPCOLOR,PGACLEAR
;**************************************************************************
;  PGALINEA for the IBM PGA
;
;   Write a stream of colors (represented by bytes) to the PGA 
;
;   Usage:     pgalinea(x,y,colorbuffer,n,expansion)
;            x,y = point to start line
;            colorbuffer = 4 byte pointer to stream of 
;            n    bytes.
;            expansion = how much horizontal pixel expansion you want
;

PGALINEA	PROC	FAR
		PUSH	BP
		MOV		BP,SP
		MOV     AX,[BP+X+6]       ; get color table segment
        MOV     ES,AX             ; use it now

        MOV		BX,479
		mov     ax,[BP+X+2]       ; get y value 0 < y < 480
        sub     bx,ax
        jnb     getx
		xor		bx,bx             ; if less than 0, set = 0
getx:
        MOV     AX,[BP+X]         ; get x value 0 < x < 640
;
		MOV     SI,[BP+X+4]       ; where to get the new colors

		MOV		CX,[BP+X+8]       ; number
		MOV		DX,[BP+X+10]      ; expansion factor, must be >= 1

		CALL    PGALINE

		POP		BP
		RET
PGALINEA	ENDP
		
;       
;
;       PGA routines
;
;       Alex Wong
;       March 1986
;
;
;       outspga
;
;       output a sting of bytes to the PGA buffer
;
;       INPUT:  si => start of data
;               cx =  number of bytes to send
;
;       OUTPUT: si => 1 byte past end of data
;
outspga proc    near
        push    bx              ;save regs
        push    di
        push    bp
        push    es
        push    dx
;
        mov     bx,pgaoff
        mov     es,bx           ;es = offset to pga i/o
        mov     bp,otrptr       ;bp => output read pointer
        mov     di,otwptr       ;di => output write pointer
;
outs:   mov     bl,es:[di]      ;write pointer
        inc     bl
        cmp     bl,es:[bp]      ;compare write with read
        je      outs            ;wait for buffer space if full
;
        mov     bl,[si]         ;get the byte to output
;
        push    bp
        mov     bp,otbase
        mov     dh,0
        mov     dl,es:[di]
        add     bp,dx
        mov     es:[bp],bl      ;output to PGA buffer
        pop     bp
;
        inc     si              ;inc ptr to data
        inc     byte ptr es:[di]   ;inc wptr MOD 255
        loop    outs
;
        pop     dx
        pop     es 
        pop     bp
        pop     di
        pop     bx
        ret                     ;--return
outspga endp   

;
;
;       setpga
;
;       initializes the PGA display and sets default colors
;
;
;
initpga proc    FAR
        push    bx
        push    cx
        push    si
;
        push    es
        push    di
        mov     bx,pgaoff
        mov     es,bx
        mov     di,wboot
        mov     byte ptr es:[di],1      ;set warm boot flag
        mov     di,errf
        mov     byte ptr es:[di],1      ;set error enable flag
        pop     di
        pop     es
;
        mov     cx,9000                 ;wait for initializations
iwait:  mov     cx,cx                   ;delay loop
        loop    iwait
;
        mov     si,offset hreset
        mov     cx,11
        call    outspga                 ;clear screen, high function
;
        pop     si
        pop     cx
        pop     bx
        ret                             ;--return
initpga endp
;
;       restpga
;
;       restores the PGA to the original (emulator) display
;
restpga proc    FAR
        mov     si,offset normal
        mov     cx,2
        call    outspga                 ;set to emulator screen
        ret                             ;--return
restpga endp
;
;       pgaline
;
;       output a line of pixels to the display
;
;       INPUT:  ax =  starting X location
;               bx =  starting Y location
;               cx =  number of pixels to write
;               dl =  expansion factor
;               es:si => sequence of pixel values in bytes, from 0-255
;                       (grey scale)   
;
;       OUTPUT: data sent to PGA
;
; note: image write command format:  D9 lline hline
;                                       lowx1 highx1
;                                       lowx2 highx2
;                                       data
;
pgaline proc    near
        push    si
        push    di
        push    ax
        push    bx
        push    cx
        push    dx
;
        push    si
        push    cx
;
        mov     si,offset buf
        mov     byte ptr [si],0d9h       ;image write command
        inc     si
        mov     [si],bx         ;line number
        inc     si
        inc     si
        mov     [si],ax         ;starting x
        inc     si
        inc     si
multi:  add     ax,cx           ;ending x
        dec     dl
        jnz     multi           ;add if multiple occurances
        dec     ax              ;still 1 too many
        mov     [si],ax   
        mov     si,offset buf   ;reset to beginning
        mov     cx,7
        call    outspga         ;send iwrite header
        pop     dx              ;restore number of pixels
        pop     di              ;di => pixel data
newpix: mov     bl,es:[di]      ;get a pixel
        mov     al,-1
;
same:   inc     di              ;di => next pixel
        inc     al              ;al = number of same pixels - 1
        dec     dx
        cmp     al,127
        je      ddone           ;overflow
        cmp     dx,0
        jz      ddone           ;end of data
        cmp     bl,es:[di]      ;compare current pixel with next pixel
        je      same
;
ddone:  mov     si,offset buf
        inc     al              ;al = number of pixels to show
        pop     cx              ;get expansion factor
        push    cx              ;put it back on the stack
        mul     cl              ;ax = total number of pixels
        dec     ax              ;want count-1
nxtblk: cmp     ax,128
        jl      fits            ;just do it once if it fits
        mov     byte ptr [si],127  ;block of 127+1 pixels
        mov     [si+1],bl       ;pixel color
        mov     cx,2
        call    outspga         ;output to buffer
        sub     ax,128
        jmp     nxtblk

fits:   mov     [si],al         ;put count into buffer
        mov     [si+1],bl       ;put pixel color into buffer
        mov     cx,2
        call    outspga         ;output this block
        cmp     dx,0
        jg      newpix
;
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        pop     di
        pop     si
;
        ret                     ;--return
pgaline endp
;
;
;  C interface to mapcolor
;
;  usage:  mapcolor(entry,r,g,b)  all ints (0-15)
;
MAPCOLOR  PROC  FAR
	PUSH BP
        MOV  BP,SP
        MOV  CL,[BP+X]
        MOV  CH,[BP+X+2]
        MOV  DL,[BP+X+4]
        MOV  DH,[BP+X+6]
        CALL SETPAL
        POP  BP
        RET

MAPCOLOR		ENDP

;       setpal
;
;       sets a color in the look up table
;
;       cl      table entry number (0-255)
;       ch      red intensity (0-15)
;       dl      green intensity (0-15)
;       dh      blue intensity (0-15)
;
setpal  proc    near
        push    si
        push    cx

        mov     si,offset buf
        mov     byte ptr [si],0eeh      ;LUT
        mov     [si+1],cl               ;entry number
        mov     [si+2],ch               ;red intensity
        mov     [si+3],dl               ;green intensity
        mov     [si+4],dh               ;blue intensity
        mov     cx,5                    ;set count for outspga
        call    outspga                 ;output LUT command

        pop     cx
        pop     si
        ret                             ;--return
setpal  endp

PGACLEAR PROC FAR
;       clears the screen in high function mode
;
        push  bp
        mov  bp,sp
        push    si
        push    cx
        mov     si,offset clears
        mov     cx,2
        call    outspga
        pop     cx
        pop     si
        pop     bp
        ret                     ;return

PGACLEAR ENDP

		ENDPS
		END
