    public ?vdputc, ?vdpinit


VDP_TRANSPARENT equ 0
VDP_BLACK equ 1
VDP_MED_GREEN equ 2
VDP_LIGHT_GREEN equ 3
VDP_DARK_BLUE equ 4
VDP_LIGHT_BLUE equ 5
VDP_DARK_RED equ 6
VDP_CYAN equ 7
VDP_MED_RED equ 8
VDP_LIGHT_RED equ 9
VDP_DARK_YELLOW equ 10
VDP_LIGHT_YELLOW equ 11
VDP_DARK_GREEN equ 12
VDP_MAGENTA equ 13
VDP_GRAY equ 14
VDP_WHITE equ 15

;Includes
    maclib syscfg
;include z80.lib

bs  equ 8   ;backspace
cr  equ 13  ;Carriage Return
lf  equ 10  ;Line Feed
esc equ 27  ;Escape
eos equ 0
linelen equ 40
nlines  equ 24
ntable  equ 0x800
VDP_COLOR equ (VDP_BLACK << 4) + VDP_WHITE
;VDP_COLOR equ (VDP_DARK_GREEN << 4) + VDP_BLACK
cseg
?vdpinit:
;VDP text mode
    ;ld sp, stack$end
    ld hl, textmode
    ld b, _textmode-textmode
    ld c, p$vdp+1
    otir

    ;Set colors
    ld a,VDP_COLOR! out (p$vdp+1),a ;Colors
    ld a, 87h! out (p$vdp+1),a ;Reg7
 
    ;flush VRAM
    ld hl, 0! call vram$wraddr
    ld bc, 0xffff
 flush$vram:
    dec bc
    xor a! out(p$vdp), a
    cp c! jp nz, flush$vram
    cp b! jp nz, flush$vram

    ; Init pattern table
    ld hl, 0x100! call vram$wraddr
    ld hl, patterns
    ld b, 8
 init$pt:
    ld d,b ;save b in d
    ld c, p$vdp! ld b, 0xff! otir
    ld b,d ;restore b from d
    djnz init$pt

; Init vars
    xor a! ld (x), a
    ld hl, ntable! ld(y), hl
    call vram$wraddr

    ret 

; Character to print in register c
?vdputc:
    ld a,(lastchr)! out(p$vdp)    ;remove cursor
    ld hl,(y)! ld de,(x)! add hl,de 
    call vram$wraddr
    ld a,c
    cp a,lf! jp z,_lf
    cp a,cr! jp z,_cr
    cp a,bs! jp z,_bs
    cp a,esc! jp z,_esc

    out(p$vdp)                      ;print character to screen

    ld a,(x)! inc a! ld (x),a       ;inc col counter
    cp linelen                      ;end of line?
    jp m, vdputc$end                ;jump to the end of routine if not end of line
    xra a! ld(x),a
    ;Fall through
    _lf:    ; 
        ld hl,(y)
        ld de, ntable+(nlines-1)*linelen
        sbc hl,de! jp z, _scroll 

        ld hl,(y)! ld de,linelen! add hl,de ! ld(y),hl  ;next line
        ld de,(x)! add hl,de                            ;add column
        call vram$wraddr
        jp vdputc$end
        _scroll:
        ld hl,ntable! ld (wrline),hl                ;wrline: screen line to write to
            ld de,linelen! add hl,de! ld (rdline),hl    ;rdline: screen line to read from
            ld b, nlines-1
        _scroll$lp:
            push bc
            ;copy line y+1 to line y
            ld hl,(rdline) ;screen line to read to
            call vram$rdaddr
            ld c,p$vdp! ld b,linelen! ld hl,linebuf 
            inir
            ld hl,(wrline) ;screen line to write to
            call vram$wraddr
            ld b,linelen! ld hl,linebuf
            otir

            ld hl,(wrline)! ld de,linelen! add hl,de! ld (wrline),hl ; wrline=wrline+40
            ld hl,(rdline)! ld de,linelen! add hl,de! ld (rdline),hl ; rdline=rldline+40
            pop bc
            djnz _scroll$lp

            ;Blank out last line
            ld hl, ntable+(nlines-1)*linelen
            call vram$wraddr
            ld a,32! ld b, 40
            _lp:
                out(p$vdp)
                djnz _lp
            call vram$wraddr
        jp vdputc$end

    _cr:    ; 
        xra a! ld(x),a         ;reset column count
        ld hl,(y)                 ;get current line pointer
        call vram$wraddr
        jp vdputc$end

    _bs:
        ld a,(x)
        cp 0! jp nz,_erase
        ld hl,(y)! ld de,linelen! sbc hl,de! ld(y),hl  ;prev line
        ld a,linelen! ld (x),a
        _erase:
        dec a! ld (x),a       ;x=x-1, go back
        ld e,a! ld d,0
        ld hl,(y)! add hl,de            ;VRAM addr of character to erase
        call vram$wraddr
        ld a,32! out (p$vdp)
        call vram$wraddr
        jp vdputc$end

    _esc:
    ;todo: escape sequences

 vdputc$end:
    ld hl,(y)! ld de,(x)! add hl,de 
    call vram$rdaddr
    in (p$vdp)! ld (lastchr), a  ;save whatÂ´s under the current cursor pos.
    call vram$wraddr
    ld a, 127! out (p$vdp) ;Set cursor
    ld hl,(y)! ld de,(x)! add hl,de 
    call vram$wraddr
    ret

dseg
rdline dw 0
wrline dw 0
linebuf ds 40   ;line currently scrolled
lastchr db 0


;-------------------- Helper functions ------------------------
; hl: VRAM first write address
vram$wraddr:
    push af
    ld a,l! out (p$vdp+1), a ;Start addr., LSB
    ld a,h! or 0x40! out (p$vdp+1), a ;Start addr. MSB + 0x40
    pop af
    ret
; hl: VRAM first read address
vram$rdaddr
    push af
    ld a,l! out (p$vdp+1), a ;Start addr., LSB
    ld a,h! out (p$vdp+1), a ;Start addr. MSB + 0x40
    pop af
    ret

dseg
; Data area
;Variables
    x dw 0  
    y dw 0 ;VRAM address of current line (y*40)
    crsr defw 0   ;current position in name table

textmode:
    db 0, 0x80      ;Reg0
    db 0xD0, 0x81   ;Reg1 Ram size 16k, blanking on
    db 0x02, 0x82  ;Reg2 Name table at 0800h
    db 0, 0x84      ;Reg4 Pattern table at 0h
_textmode equ $

patterns:
    db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; Blank
    db 0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00 ; !
    db 0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00 ; "
    db 0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x00 ; #
    db 0x20,0x78,0xA0,0x70,0x28,0xF0,0x20,0x00 ; 0x
    db 0xC0,0xC8,0x10,0x20,0x40,0x98,0x18,0x00 ; %
    db 0x40,0xA0,0xA0,0x40,0xA8,0x90,0x68,0x00 ; &
    db 0x20,0x20,0x20,0x00,0x00,0x00,0x00,0x00 ; '
    db 0x20,0x40,0x80,0x80,0x80,0x40,0x20,0x00 ; (
    db 0x20,0x10,0x08,0x08,0x08,0x10,0x20,0x00 ; )
    db 0x20,0xA8,0x70,0x20,0x70,0xA8,0x20,0x00 ; *
    db 0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00 ; +
    db 0x00,0x00,0x00,0x00,0x20,0x20,0x40,0x00 ; ,
    db 0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00 ; -
    db 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00 ; .
    db 0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00 ; /
    db 0x70,0x88,0x98,0xA8,0xC8,0x88,0x70,0x00 ; 0
    db 0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00 ; 1
    db 0x70,0x88,0x08,0x30,0x40,0x80,0xF8,0x00 ; 2
    db 0xF8,0x08,0x10,0x30,0x08,0x88,0x70,0x00 ; 3
    db 0x10,0x30,0x50,0x90,0xF8,0x10,0x10,0x00 ; 4
    db 0xF8,0x80,0xF0,0x08,0x08,0x88,0x70,0x00 ; 5
    db 0x38,0x40,0x80,0xF0,0x88,0x88,0x70,0x00 ; 6
    db 0xF8,0x08,0x10,0x20,0x40,0x40,0x40,0x00 ; 7
    db 0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00 ; 8
    db 0x70,0x88,0x88,0x78,0x08,0x10,0xE0,0x00 ; 9
    db 0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x00 ; :
    db 0x00,0x00,0x20,0x00,0x20,0x20,0x40,0x00 ; ;
    db 0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x00 ; <
    db 0x00,0x00,0xF8,0x00,0xF8,0x00,0x00,0x00 ; =
    db 0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00 ; >
    db 0x70,0x88,0x10,0x20,0x20,0x00,0x20,0x00 ; ?

	db	0x38,0x44,0x94,0xAC,0x98,0x40,0x3C,0x00 ; @
;    db 0x70,0x88,0xA8,0xB8,0xB0,0x80,0x78,0x00 ; @
    db 0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00 ; A
    db 0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x00 ; B
    db 0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00 ; C
    db 0xF0,0x88,0x88,0x88,0x88,0x88,0xF0,0x00 ; D
    db 0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00 ; E
    db 0xF8,0x80,0x80,0xF0,0x80,0x80,0x80,0x00 ; F
    db 0x78,0x80,0x80,0x80,0x98,0x88,0x78,0x00 ; G
    db 0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x00 ; H
    db 0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00 ; I
    db 0x08,0x08,0x08,0x08,0x08,0x88,0x70,0x00 ; J
    db 0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x00 ; K
    db 0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x00 ; L
    db 0x88,0xD8,0xA8,0xA8,0x88,0x88,0x88,0x00 ; M
    db 0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x00 ; N
    db 0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00 ; O
    db 0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x00 ; P
    db 0x70,0x88,0x88,0x88,0xA8,0x90,0x68,0x00 ; Q
    db 0xF0,0x88,0x88,0xF0,0xA0,0x90,0x88,0x00 ; R
    db 0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00 ; S
    db 0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x00 ; T
    db 0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00 ; U
    db 0x88,0x88,0x88,0x88,0x88,0x50,0x20,0x00 ; V
    db 0x88,0x88,0x88,0xA8,0xA8,0xD8,0x88,0x00 ; W
    db 0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00 ; X
    db 0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00 ; Y
    db 0xF8,0x08,0x10,0x20,0x40,0x80,0xF8,0x00 ; Z
	db 0x78,0x40,0x40,0x40,0x40,0x40,0x78,0x00 ; [
    db 0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00 ; \
	db 0xF0,0x10,0x10,0x10,0x10,0x10,0xF0,0x00 ; ]
    db 0x00,0x00,0x20,0x50,0x88,0x00,0x00,0x00 ; ^
    db 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8 ; _
    db 0x40,0x20,0x10,0x00,0x00,0x00,0x00,0x00 ; `
	db 0x00,0x00,0x60,0x10,0x70,0x90,0x68,0x00 ; a
	db 0x80,0x80,0xB0,0xC8,0x88,0xC8,0xB0,0x00 ; b
	db 0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00 ; c
	db 0x08,0x08,0x78,0x88,0x88,0x88,0x78,0x00 ; d
	db 0x00,0x00,0x70,0x88,0xF8,0x80,0x78,0x00 ; e
	db 0x30,0x48,0x40,0xF0,0x40,0x40,0x40,0x00 ; f
	db 0x00,0x00,0x68,0x98,0x98,0x68,0x08,0xF0 ; g
	db 0x80,0x80,0xB0,0xC8,0x88,0x88,0x88,0x00 ; h
	db 0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00 ; i
	db 0x08,0x00,0x18,0x08,0x08,0x08,0x48,0x30 ; j
	db 0x80,0x80,0x88,0x90,0xA0,0xD0,0x88,0x00 ; k
	db 0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00 ; l
	db 0x00,0x00,0x50,0xF8,0xA8,0xA8,0xA8,0x00 ; m
	db 0x00,0x00,0xB0,0xC8,0x88,0x88,0x88,0x00 ; n
	db 0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00 ; o
	db 0x00,0x00,0xB0,0xC8,0xC8,0xB0,0x80,0x80 ; p
	db 0x00,0x00,0x68,0x98,0x98,0x68,0x08,0x08 ; q
	db 0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x00 ; r
	db 0x00,0x00,0x70,0x80,0x70,0x08,0xF0,0x00 ; s
	db 0x40,0x40,0xF0,0x40,0x40,0x48,0x30,0x00 ; t
	db 0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x00 ; u
	db 0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00 ; v
	db 0x00,0x00,0x88,0xA8,0xA8,0xA8,0x50,0x00 ; w
	db 0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00 ; x
	db 0x00,0x00,0x88,0x88,0x98,0x68,0x08,0x70 ; y
	db 0x00,0x00,0xF8,0x10,0x20,0x40,0xF8,0x00 ; z

;    db 0x00,0x00,0x70,0x88,0xF8,0x88,0x88,0x00 ; a
;    db 0x00,0x00,0xF0,0x48,0x70,0x48,0xF0,0x00 ; b
;    db 0x00,0x00,0x78,0x80,0x80,0x80,0x78,0x00 ; c
;    db 0x00,0x00,0xF0,0x48,0x48,0x48,0xF0,0x00 ; d
;    db 0x00,0x00,0xF0,0x80,0xE0,0x80,0xF0,0x00 ; e
;    db 0x00,0x00,0xF0,0x80,0xE0,0x80,0x80,0x00 ; f
;    db 0x00,0x00,0x78,0x80,0xB8,0x88,0x70,0x00 ; g
;    db 0x00,0x00,0x88,0x88,0xF8,0x88,0x88,0x00 ; h
;    db 0x00,0x00,0x70,0x20,0x20,0x20,0xF8,0x00 ; i
;    db 0x00,0x00,0x70,0x20,0x20,0xA0,0xE0,0x00 ; j
;    db 0x00,0x00,0x90,0xA0,0xC0,0xA0,0x90,0x00 ; k
;    db 0x00,0x00,0x80,0x80,0x80,0x80,0xF8,0x00 ; l
;    db 0x00,0x00,0x88,0xD8,0xA8,0x88,0x88,0x00 ; m
;    db 0x00,0x00,0x88,0xC8,0xA8,0x98,0x88,0x00 ; n
;    db 0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00 ; o
;    db 0x00,0x00,0xF0,0x88,0xF0,0x80,0x80,0x00 ; p
;    db 0x00,0x00,0xF8,0x88,0xA8,0x90,0xE8,0x00 ; q
;    db 0x00,0x00,0xF8,0x88,0xF8,0xA0,0x90,0x00 ; r
;    db 0x00,0x00,0x78,0x80,0x70,0x08,0xF0,0x00 ; s
;    db 0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x00 ; t
;    db 0x00,0x00,0x88,0x88,0x88,0x88,0x70,0x00 ; u
;    db 0x00,0x00,0x88,0x88,0x90,0xA0,0x40,0x00 ; v
;    db 0x00,0x00,0x88,0x88,0xA8,0xD8,0x88,0x00 ; w
;    db 0x00,0x00,0x88,0x60,0x20,0x60,0x88,0x00 ; x
;    db 0x00,0x00,0x88,0x50,0x20,0x20,0x20,0x00 ; y
;    db 0x00,0x00,0xF8,0x10,0x20,0x40,0xF8,0x00 ; z

    db 0x38,0x40,0x20,0xC0,0x20,0x40,0x38,0x00 ; {
    db 0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00 ; >
    db 0xE0,0x10,0x20,0x18,0x20,0x10,0xE0,0x00 ; }
    db 0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00 ; ~
    db 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF 
_patterns 

    stack ds 16
    db 'ende'
    stack$end equ $



