;***************************************************************
;*							       *
;*	SCREEN DRIVER FOR NEC 7220 			       *
;*							       *
;***************************************************************


;****** DOS entry **********************************************

;no terminal support (int 29h)

CrtOut: jcxz    ExCrt 

con$lp: mov     al,es:[di]      ;al <- char
        inc     di
        push    cx                  
	mov	byte ptr cs:[Reg_Ax+1],0eh	;for BIOS ref
        call    int10e          ;sel WrTTY
        pop     cx
        loop    con$lp
ExCrt:  jmp     exit

;****** BIOS INT 10h *******************************************


;====== Int10, func0: set video mode ===========================
;ignored

;====== Int10, func1: set cursor size ==========================
;ignored

;====== Int10, func2: set cursor position ======================

;test:   WS4
;entry: dh = Y (line)    dl = X (column) bh = Page: ignored
;exit:  none

Int102: mov     word ptr [NewXY],dx
        call    XYtoAdr                 ;dx <- crt mem adr
        mov     word ptr [CursAdr],dx
        call	GotoAdr                 ;set curs -> mem adr
        ret				;no ret pars

;====== Int10, func3: return current cursor position ===========

;entry: bh = page: ignored
;exit:  row/col in dh/dl, ch/cl = cursor start/end line

Int103: mov     dx,word ptr [NewXY]	;
	mov     word ptr [reg_dx],dx 	;ret cursor position
        mov     cx,256*15+15            ;?
        mov     word ptr [reg_cx],cx	;ret cursor size
        ret

;====== Int10, func4: read light pen position ==================

;ignored

;====== Int10, func5: set active display page ==================

;ignored

;====== Int10, func 06,07h: scroll window up,down ==============

;test shift:    WS4,^W
;test clear:    turbo 3, signon message

;entry: al = multiscroll factor, bh = blankline attr,
;ch = Y0, cl = X0, dh = Y1, dl = X1
;exit:  none
	
Int107: mov     word ptr [X0Y0],cx
        mov     word ptr [X1Y1],dx
        sub     dl,cl                   ;dl <- X1-X0 = len-1
        mov     ah,dh
        mov     dh,ch                   ;dh <- LastLine = Y0
        mov     ch,ah                   ;cx <- 1.dest = X0,Y1
        neg     al                      ;al <- neg multiscroll
        mov     ah,-1                   ;ah <- move up
        jmp     I106_7

;test:  WS4:^Z

Int106: mov     word ptr [X0Y0],cx
        mov     word ptr [X1Y1],dx
        sub     dl,cl                   ;dl <- X1-X0 = len-1
        mov     ah,+1                   ;ah <- move down

I106_7: mov     byte ptr [UpDown],ah	;+/- line advance
        mov     byte ptr [XLoop],dl	;window line len
        mov     byte ptr [WinEnd],dh	;terminating line
        mov     bl,byte ptr [Reg_Bx+1]	;bl <- bh
        call    Atr72			;bh <-7220 <- 6845
        mov     byte ptr [BlnkAtr],bh	;blank attribute
        mov     bx,cx                   ;bx -> 1.dest
        mov     dx,cx                   ;multiscroll offset:
        add     dh,al                   ;dx -> 1.source
        call    CurOff			
        cmp     dh,bh                   ;multiscroll = 0?
        jz      ClrWin                  ;true: clear window
        call    MovLns
ClrWin: call    ClrLns
XWin:   mov     dx,word ptr [CursAdr]	;no scrol:adr unchanged
        call    GoToAdr                 ;restore cursor
        call    CurOn			
        ret

;------ move source -> dest lines ------------------------------

RptMLns:add     bh,byte ptr [UpDown] 	;line inc/dec
        add     dh,byte ptr [UpDown]	;line inc/dec

MovLns: call    MovLine
        cmp     dh,byte ptr [WinEnd]	;rept until
        jnz     RptMLns                 ;source = last line
        ret                             ;is copied

;------ end of move: blank remaining dest lines ----------------

RptCln: add     dh,byte ptr [UpDown]

ClrLns: push    dx                      ;dx -> dest
        mov     cl,byte ptr [XLoop]
	xor	ch,ch
        call    Blanks
        pop     dx
        cmp     dh,byte ptr [WinEnd] 	;rept until
        jnz     RptCln                  ;dest = lastLine
        ret                             ;is cleared

;------ move (part of) line ------------------------------------

;entry: dx -> source, bx -> dest, len-1 at XLoop
;cx destroyed

MovLine:push    bx
        push    dx                      ;dx -> source
	push	di
	
;------ read (part of a) line from GDC -> buffer ---------------

;entry: len-1 at XLoop, CharPos in dx

        call    XYtoAdr                 ;goto source
        call    GoToAdr
        mov     cl,byte ptr [XLoop]  	;len-1
        mov     al,figs
        out     GdcCmd,al
        mov     al,2                    ;P1:char, draw dir
        out     GdcPar,al
        inc     cl                      ;word count
        mov     al,cl                   ;DC_lo:len-1 in dir1
        out     GdcPar,al
        xor     al,al                   ;DC_hi
        out     GdcPar,al
        mov     al,InDat
        out     GdcCmd,al
        xor     ch,ch
	lea	bx,cs:buffer
        sub     bx,2
        mov     dx,fifo
;	cld				;!
;	lea	di,cs:buffer

RdCatr:	in	al,GdcSts
        and	al,DatRdy
        jz	RdCAtr		;jz

RdCatr1:in      al,dx
        mov	ah,al			;char in ah
        add     bx,2
        in      al,dx
        xchg    al,ah			;char in al, atr in ah
	mov     word ptr [bx],ax	;1 word -> buffer
        loop    RdCatr                  ;17/5cyc

	pop	di
        pop     bx
        pop     dx                      ;dx -> dest

;------ write (part of a) line from buffer -> GDC --------------

;entry: len-1 at XLoop, CharPos in dx

        push    bx
        push    dx
	push	si
        call    XYtoAdr                 ;goto dest
        call    GoToAdr
        mov     cl,byte ptr [XLoop]  	;len-1
        mov     al,figs
        out     GdcCmd,al
        mov     al,2
        out     GdcPar,al
        xor     al,al
        out     GdcPar,al
        out     GdcPar,al
        mov     al,WriteW
        out     GdcCmd,al
        inc     cl                      ;word count
        xor     ch,ch
        mov     dx,gdcpar
	cld				
	lea	si,cs:buffer

WrCAtr: lodsw
        out     dx,al                   ;12cyc
        mov     al,ah
        out     dx,al
        loop    WrCatr                  ;17/5cyc

	pop	si
	pop     bx
        pop     dx                      ;dx -> source
	ret

;------ clear (part of a) line ---------------------------------

;called on screen ovl (autoscroll) and by move window
;GDC block fill cmd, no ovl checking
;entry: dx = start pos (XY), cx = len-1, attr at BlnkAtr
;test:  turbo3, signon

Blanks: call	clrfifo
	call    XYtoAdr
        call    GoToAdr                 
        mov     al,figs
	out	GdcCmd,al
        mov     al,02
	out	GdcPar,al
        mov     al,cl                   ;word count-1, lo
	out	GdcPar,al
	mov	al,ch
	out	GdcPar,al		;dito, hi
        mov     al,WriteW
	out	GdcCmd,al
        mov     al,' '                  ;char
	out	GdcPar,al
        mov     al,byte ptr [BlnkAtr] ;blanking atr
        xor     al,al    
	out	GdcPar,al
        ret

;====== Int10, func 08h: read char at cursor position ==========

;test:  WS4

;entry: bh = page: ignored
;exit:  ah = attr       al = char

Int108: mov     al,figs
        call    OutCmd
        mov     al,2                    ;P1:char, draw dir
        call	outpar	
        dec     al
        call	OutPar	
        xor     al,al                   ;DC_hi
        call	OutPar	
        mov     al,InDat
        call	OutCmd	
        call    InPar
        mov     ah,al                   ;char in ah
        in      al,fifo
        xchg    al,ah                   ;char in al
        mov     bl,ah
        call    Atr68
        mov     ah,bh
        mov     word ptr [reg_ax],ax 	;ret char & attr
        ret

;====== Int10, func 09h: Write char incl attribute =============

;fixed cursor, line wrapping, fixed screen, set attr

;test:  WS4
;entry: al = char       bl = attr(6845) cx = loop   bh = page
;return:none

Int109: mov     bl,byte ptr [Reg_Bx] 	;get current attr
        cmp     bl,byte ptr [Atr6845]	;comp last attr
        jnz     NxtAtr                  ;attr changed?

;====== Int10, func 0ah: Write char ============================

;fixed cursor, line wrapping, fixed screen, rpt attr

;entry: al = char       bh = page       cx = loop
;return:none

Int10A: cmp	al,15h			;?
	jnz	Int10A1
	mov	al,1ch			;true

Int10A1:cmp     al,80h                  
        jnc     char80

TxRdy:  mov     bl,al
	mov	dx,word ptr [NewXY]
	jmp	CharLp

RptOCA: call	ClrFifo			

Charlp:	mov     al,writew
	out     GdcCmd,al
        mov     al,bl			;char
	out     GdcPar,al
        mov     al,byte ptr [ChrAtr+1]	;attr 7220
	out     GdcPar,al

	inc     dl                      ;advance char pos
        cmp     dl,MaxCol+1
        jnc     WrapLn                  ;wrap line, ovl check

CPosRdy:loop    RptOCA

        cmp     byte ptr [Reg_Ax+1],0eh;WrTTY?
	jz	ExTTY

;------ exit fixed cursor --------------------------------------

        mov     dx,word ptr [CursAdr]	;no scroll=adr valid
	jmp	GotoAdr			;no ret pars

;------ exit WrTTY: new cursor position ------------------------

ExTTY:	mov	word ptr [NewXY],dx
	call	XYtoAdr			
        mov     word ptr [CursAdr],dx	
	ret

;------ rare jumps: attribute altered --------------------------

NxtAtr: mov     byte ptr [Atr6845],bl	;store for re-cmp & f8
        call    Atr72                  	;ret 7220 attr in bh
        mov     byte ptr [ChrAtr+1],bh	;store char attr
        jmp     Int10A

;------ character translation ----------------------------------

Char80: cmp     al,0e1h                 ;sz?
        jnz     Char801
        mov     al,1eh
        jmp     TxRdy
Char801:cmp     al,9Dh                  ;char >= 80h
        jc      TxChar
        mov     al,' '                  ;blockgraph -> blank
        jmp     TxRdy
TxChar: push	bx
	lea	bx,cs:ASCII 		;char translation
        xor     ah,ah
        sub     al,80h
        add     bx,ax
        mov     al,[bx]			
	pop	bx
        jmp     TxRdy

;------ line wrapping ------------------------------------------

WrapLn: inc     dh                      ;next line,
        xor     dl,dl                   ;col = 0
        cmp     dh,MaxLine+1
        jc      CPosRdy

;------ XYadr -> 2000: scroll/fix sreen ------------------------

CrtOvl:	push	cx
	cmp     byte ptr [Reg_Ax+1],0eh	;wrtty?
        jnz     FixCrt

        call    ScrUp			;1 x scroll

FixCrt: mov	dx,256*MaxLine		;bottom line,col = 0
	push	dx
        call    XYtoAdr
        call    GotoAdr
	pop	dx
	pop	cx
	jmp     CPosRdy

;====== Int10, func 0bh: set color palette =====================
;ignored
;====== Int10, func 0ch: write pixel ===========================
;ignored
;====== Int10, func 0dh: read pixel ============================
;ignored

;====== Int10, func 0eh: Write char TTY mode ===================

;advancing cursor, line wrapping, sroll on ovl, last attr

;test:  wschange

;entry  al = char  bl = foreground color,ignored
;       bh = page:ignored
;return:none


Int10E: cmp	byte ptr [EscLp],-1	;escape active?
	jz	NotEsc			;!
;!	jmp	DoEsc

NotEsc:	cmp     al,1fh
	jnc	NotCtl
	jmp	TxCtl

;------ WrTTY char output --------------------------------------

NotCtl:	mov     cx,1                    ;clear loop ount
        mov     bh,byte ptr [ChrAtr+1]  ;last attr.
        jmp     int10a

;====== Int10, func 0fh: return curr video mode ================

VMod0   equ     0       ;txt 40 x 25 gray16
VMod1   equ     1       ;txt 40 x 25 Color16/8
VMod2   equ     2       ;txt 80 x 25 gray16
VMod3   equ     3       ;txt 80 x 25 color16/8
VMod4   equ     4       ;gx 320 x 200 color4
VMod5   equ     5       ;gx 320 x 200 gray4
VMod6   equ     6       ;gx 640 x 200 color2
VMod7   equ     7       ;txt 80 x 25 b/w
VMod8   equ     8       ;gx 160 x 200 color16
VMod9   equ     9       ;gx 320 x 200 gray 4
VModA   equ     0AH     ;gx 640 x 200 color4
VModB   equ     0BH     ;res ega
VModC   equ     0CH     ;res ega
VModD   equ     0DH     ;ega 320x 200 color16
VModE   equ     0EH     ;ega 640x 200 color16
VModF   equ     0FH     ;ega 640x 350 b/w
VMod10  equ     10H     ;ega 640x 350 color16

;entry: none
;return:ah = col/line   al = videomode  bh = page

Int10F: mov     ax,256*80+VMod7         ;fixed:80 col, Mod7
        mov     word ptr [reg_ax],ax
        mov     bh,0                    ;page = 0
        mov     word ptr [reg_bx],bx
        ret

;====== GDC Subroutines ========================================

;------ convert 6845 <-> 7220 Attr bits ------------------------

;test: WS4 column block

bli6845  equ     10000000b              ;blink bit
bac6845  equ     01110000b              ;background R-G-B
int6845  equ     00001000b              ;intensity bit
for6845  equ     00000111b              ;foreground R-G-B
dim7220  equ     00000100b              ;half intensity
bli7220  equ     00000010b              ;blink bit
inv7220  equ     00000001b              ;invers bit

;entry:  bl = attribute 6845
;return: bh = attribute 7220

Atr72:  xor    bh,bh                    ;default no attr
Invers: and    bl,Bac6845               ;any background color?
        jz     Dark
        or     bh,Inv7220               ;true: set invers
Dark:   and    bl,Int6845
        jnz    Blink                    ;intensity = 0?
        or     bh,dim7220               ;true: set half intensity
Blink:  and    bl,Bli6845               ;blinking?
        jz     ExAtr
        or     bh,bli7220               ;yes
ExAtr:  ret                             ;7220 atr in bh

;entry: bl = attribute 7220
;return:bh = attribute 6845

Atr68:  mov     bh,00001111b            ;default white foreground,
        and     bl,Inv7220              ;full intensity
        jz      DarkB
        mov     bh,01111000b            ;invers, bright
DarkB:  and     bl,dim7220
        jz      BlinkB
        and     bh,11110111b            ;lo intensity
BlinkB: and     bl,bli7220
        jz      XAtr68
        or      bh,Bli6845
XAtr68: ret

;------ cursor move: convert X-Y to crt mem adr ----------------

;no hardscroll -> sp1 fixed to 0 -> no mem ovl check

;entry: X-Y in dx
;exit:  crt adr in dx

XYtoAdr:mov     al,dh                   ;line in al
	mov	ah,MaxCol+1		
        mul     ah			;ax <- line * 80
        xor     dh,dh			;dx <- col
        add     dx,ax                   ;dx = line x 80 + col
	ret

;------ set cursor to crt mem adr ------------------------------

;entry: crt adr in dx
;return:crt adr in dx

GotoAdr:call	clrfifo			;!
	mov     al,CrsW         
        out	GdcCmd,al	
        mov     al,dl           
	out     GdcPar,al	
        mov     al,dh           
        out     GdcPar,al	
        ret

;====== GDC lo level I/O =======================================

IniCrt: mov    ax,0
	mov    word ptr cs:[SP1],ax    ;start page0 = 0
	mov    word ptr cs:[SP2],ax    ;start page1 = 0
	mov    byte ptr cs:[LP22],al   ;len   page1 = 0
	mov    al,MaxLine+1            ;
	mov    byte ptr cs:[LP12],al   ;len   page0 = 25 lines

NewCrt:	mov    al,Figs
        call   OutCmd
        mov    al,2
        call   OutPar
        call   SetPRAM
        ret

SetPRAM:push    bx
        push    cx
        call	ClrFifo			
        mov     al,PRAM
	out	GdcCmd,al		
 	lea	bx,cs:SP1
	mov     cx,08                   ;transfer count
XSULP:  mov     al,[bx]	
        out	GdcPar,al
        inc     bx
        loop    XSULP
        pop     cx
        pop     bx
        ret

SetMsk: call	ClrFifo
        mov     al,GMask
        call    OutCmd
        mov     al,-1
        out     GdcPar,al               ;??
        out     GdcPar,al
        ret

CurOff: push	ax
	mov    al,CChar
        call   OutCmd
        mov    al,0fh
	call   OutPar
   	pop	ax
        ret

CurOn:  push	ax
	mov     al,CChar
        call    OutCmd
        mov     al,8fh
        call    OutPar
        mov     al,0ceh
        call    OutPar
        mov     al,72h
        call    OutPar
	pop	ax
        ret

OutCmd: push    ax                      ;wait for output to GDC
OutCmdA:in      al,GdcSts
        and     al,FiFull
        jnz     OutCmdA
        pop     ax
        out     (GdcCmd),al
        ret

OutPar: push    ax                      ;wait for output to GDC
OutPar1:in      al,GdcSts
        and     al,FiFull
        jnz     OutPar1     ;jnz
        pop     ax
        out     (GdcPar),al
        ret

ClrFifo:in      al,GdcSts
        and     al,FiEmpty
        jz     ClrFifo
        ret

InPar:  in     al,GdcSts
        and    al,DatRdy
        jz     InPar
        in     al,fifo
        ret


ASCII:  db      ' ',99h,8bh,' ',90h,8ah,92h,88h,'     ',9bh,80h,' '
;       90  91  92 93  oe  95  96  97  98  OEk  UE 9B  9C  9D..FF
db      84h,91,81h,' ',96h,98h,' ',9Ah,' ',86h,89h,87h,83h

