include "inc/cmdsys.plh"
//
// Apple II hardware constants.
//
const showgraphics = $C050
const showtext     = $C051
const showfull     = $C052
const showmix      = $C053
const showpage1    = $C054
const showpage2    = $C055
const showlores    = $C056
const showhires    = $C057
const show40       = $C00C
const show80       = $C00D
const mapmain      = $C000
const mapaux       = $C001
const an3on        = $C05E
const an3off       = $C05F
const ena80        = $C07E
const dis80        = $C07F
const page1        = 0
const page2        = 1
//
// Screen row address arrays.
//
word[] dgr1row = $0400,$0480,$0500,$0580,$0600,$0680,$0700,$0780
word           = $0428,$04A8,$0528,$05A8,$0628,$06A8,$0728,$07A8
word           = $0450,$04D0,$0550,$05D0,$0650,$06D0,$0750,$07D0
word[] dgr2row = $0800,$0880,$0900,$0980,$0A00,$0A80,$0B00,$0B80
word           = $0828,$08A8,$0928,$09A8,$0A28,$0AA8,$0B28,$0BA8
word           = $0850,$08D0,$0950,$09D0,$0A50,$0AD0,$0B50,$0BD0
word[] dgrbuff = @dgr1row, @dgr2row
word drawbuff
byte drawpage
//
// Color mapping.
//
byte[] evnclr = $00,$88,$11,$99,$22,$AA,$33,$BB
byte[]        = $44,$CC,$55,$DD,$66,$EE,$77,$FF
byte[] oddclr = $00,$11,$22,$33,$44,$55,$66,$77
byte[]        = $88,$99,$AA,$BB,$CC,$DD,$EE,$FF

asm dgrInc(buff)
!SOURCE    "vmsrc/plvmzp.inc"
GBASL    =    $26
GBASH    =    $27
GBASE    =    GBASL
GCLR     =    $30
end
//
// Plot pixel
//
export asm dgrPlot(x, y)#0
        ; GET ROW BUFFER ADDRESSES
		LDA     $3000
        STA     SRCL
        LDA     $3001
		STA		SRCH
        STX     ESP
        LDA     ESTKL,X     ; Y COORD
        AND     #$FE
        TAY
        LDA     (SRC),Y
        STA     GBASL
        INY
        LDA     (SRC),Y
        STA     GBASH
        LDA     ESTKL+1,X   ; X COORD
        LSR     ESTKL,X
        LDX     GCLR        ; COLOR
        PHP
        SEI
end
asm _dgrPlotPix
        JSR     $3000       ; _dgrSetPix
        PLP
        LDX     ESP
        INX
        INX
        RTS
end
//
// Plot horizontal row of pixels
//
export asm dgrHLin(x1, x2, y)#0
        ; GET ROW BUFFER ADDRESSES
		LDA     $3000
        STA     SRCL
        LDA     $3001
		STA		SRCH
        STX     ESP
        LDA     ESTKL+1,X    ; X2 COORD
        STA     TMPH
        LDA     ESTKL+0,X    ; Y COORD
        AND     #$FE
        TAY
        LDA     (SRC),Y
        STA     GBASL
        INY
        LDA     (SRC),Y
        STA     GBASH
        LDY     ESTKL+2,X   ; X1 COORD
        PHP
        SEI
-       LDA     ESTKL+0,X   ; Y COORD
        LSR
        TYA
        LDX     GCLR        ; COLOR
end
asm _dgrHLinPix
        JSR     $3000       ; _dgrSetPix
        LDX     ESP
        INC     ESTKL+2,X   ; X1 COORD
        LDY     ESTKL+2,X
        CPY     TMPH        ; X2 COORD
        BCC     -
        BEQ     -
        PLP
        INX
        INX
        INX
        RTS
end
//
// Plot horizontal row of pixels
//
export asm dgrVLin(y1, y2, x)#0
        ; GET ROW BUFFER ADDRESSES
		LDA     $3000
        STA     SRCL
        LDA     $3001
		STA		SRCH
        STX     ESP
        LDA     ESTKL+2,X   ; Y1 COORD
        PHP
        SEI
-       AND     #$FE
        TAY
        LDA     (SRC),Y
        STA     GBASL
        INY
        LDA     (SRC),Y
        STA     GBASH
        LDA     ESTKL+2,X
        LSR
        LDA     ESTKL+0,X   ; X COORD
        LDX     GCLR        ; COLOR
end
asm _dgrVLinPix
        JSR     $3000       ; _dgrSetPix
        LDX     ESP
        INC     ESTKL+2,X   ; Y1 COORD
        LDA     ESTKL+2,X
        CMP     ESTKL+1,X   ; Y2 COORD
        BCC     -
        BEQ     -
        PLP
        INX
        INX
        INX
        RTS
end
//
// Draw sprite
//
export asm dgrBLT(x, y, width, height, src)#0
        ; GET ROW BUFFER ADDRESSES
		LDA     $3000
        STA     DSTL
        LDA     $3001
		STA		DSTH
        LDA     ESTKL,X     ; SPRITE
        STA     SRCL
        LDA     ESTKH,X
        STA     SRCH
        LDA     ESTKL+4,X   ; X1 COORD
        CMP     #80
        BPL     ++++
        CLC
        ADC     ESTKL+2,X
        BMI     ++++
        STA     ESTKH+2,X   ; X2 COORD
        LDA     ESTKL+3,X   ; Y1 COORD
        CMP     #48
        BPL     ++++
        STA     ESTKH+3,X   ; Y COORD
        CLC
        ADC     ESTKL+1,X
        BMI     ++++
        STA     ESTKH+1,X   ; Y2 COORD
        STX     ESP
        LDA     ESTKH+3,X
-       CMP     #48
        BCC     +
        LDA     SRCL        ; SKIP TO NEXT ROW
        CLC
        ADC     ESTKL+2,X   ; WIDTH
        STA     SRCL
        BCC     +++
        INC     SRCH
        BNE     +++
+       AND     #$FE
        TAY
        LDA     (DST),Y
        STA     GBASL
        INY
        LDA     (DST),Y
        STA     GBASH
        LDA     ESTKL+4,X   ; X1 COORD
        STA     ESTKH+4,X   ; X COORD
        PHP
        SEI
--      CMP     #80
        BCS     ++
        STA     TMP
        LDA     ESTKH+3,X   ; Y COORD
        LSR
        LDY     #$00
        LDA     (SRC),Y
        BMI     ++
        TAX
        LDA     TMP
end
asm _dgrBLTPix
        JSR     $4000       ; _dgrSetPix
        LDX     ESP
++      INC     SRCL
        BNE     +
        INC     SRCH
+       INC     ESTKH+4,X   ; X COORD
        LDA     ESTKH+4,X
        BMI     --
        CMP     ESTKH+2,X   ; X2 COORD
        BCC     --
        PLP
+++     INC     ESTKH+3,X   ; Y COORD
        LDA     ESTKH+3,X
        BMI     -
        CMP     ESTKH+1,X   ; Y2 COORD
        BCC     -
++++    INX
        INX
        INX
        INX
        INX
        RTS
end
//
// Internal set pixel routine
//  - It expects the carry to be set for even or odd scanlines. Bad.
//  - ACCUM has horizontal coordinate
//  - X_REG has color
//  - GBASE points to scanline
//
asm _dgrSetPix
        BCS     ++
        ; EVEN ROW
        LSR
        TAY
        BCS     +
end
asm _dgrSetEvnEvn
        ; EVEN PIXEL
        LDA     $2000,X
        AND     #$0F
        STA     TMP
        JSR     $0100       ; LDA AUX (DST),Y
        AND     #$F0
        ORA     TMP
        STA     $C005       ; WRITE AUX MEM
        STA     (GBASE),Y
        STA     $C004       ; WRITE MAIN MEM
        RTS
end
asm _dgrSetEvnOdd
        ; ODD PIXEL
+       LDA     $1000,X
        AND     #$0F
        STA     TMP
        LDA     (GBASE),Y
        AND     #$F0
        ORA     TMP
        STA     (GBASE),Y
        RTS
        ; ODD ROW
++      LSR
        TAY
        BCS     +++
end
asm _dgrSetOddEvn
        ; EVEN PIXEL
        LDA     $2000,X
        AND     #$F0
        STA     TMP
        JSR     $0100       ; LDA AUX (DST),Y
        AND     #$0F
        ORA     TMP
        STA     $C005       ; WRITE AUX MEM
        STA     (GBASE),Y
        STA     $C004       ; WRITE MAIN MEM
        RTS
end
asm _dgrSetOddOdd
        ; ODD PIXEL
+++     LDA     $1000,X
        AND     #$F0
        STA     TMP
        LDA     (GBASE),Y
        AND     #$0F
        ORA     TMP
        STA     (GBASE),Y
        RTS
end
//
// This gets copied to $0100!!!
//
asm auxRead
        STA     $C003       ; READ AUX MEM
        LDA     (GBASE),Y
        STA     $C002       ; READ MAIN MEM
        RTS
end
//
// Draw 8x8 tile (forced to 2x2 block address)
//
export asm dgrTile(x, y, src)#0
        ; GET ROW BUFFER ADDRESSES
		LDA     $3000
        STA     DSTL
        LDA     $3001
		STA		DSTH
        STX     ESP
        LDA     ESTKL,X       ; TILE
        STA     SRCL
        LDA     ESTKH,X
        STA     SRCH
        LDA     ESTKL+2,X   ; X1 COORD
        CMP     #80
        BPL     ++++
        CLC
        ADC     #$08
        BMI     ++++
        STA     ESTKH+2,X   ; X2 COORD
        LDA     ESTKL+1,X   ; Y1 COORD
        CMP     #48
        BPL     ++++
        STA     TMPL        ; Y COORD
        CLC
        ADC     #$08
        BMI     ++++
        STA     ESTKH+1,X   ; Y2 COORD
        LDA     TMPL        ; Y COORD
-       CMP     #48
        BCC     +
        LDA     SRCL        ; SKIP TO NEXT ROW
        ADC     #$07        ; CARRY = 1
        STA     SRCL
        BCC     +++
        INC     SRCH
        BNE     +++
+       AND     #$FE
        TAY
        LDA     (DST),Y
        STA     GBASL
        INY
        LDA     (DST),Y
        STA     GBASH
        LDA     ESTKL+2,X   ; X1 COORD
        STA     TMPH        ; X COORD
        PHP
        SEI
--      LSR
        TAY
        CMP     #40
        LDX     #$00
        LDA     (SRC,X)
        INC     SRCL
        BNE     +
        INC     SRCH
+       BCS     +
        STA     $C005       ; WRITE AUX MEM
        STA     (GBASE),Y
        STA     $C004       ; WRITE MAIN MEM
+       LDA     (SRC,X)
        INC     SRCL
        BNE     +
        INC     SRCH
+       BCS     ++
        STA     (GBASE),Y
++      INC     TMPH        ; X COORD
        INC     TMPH        ; X COORD
        LDA     TMPH
        BMI     --
        LDX     ESP
        CMP     ESTKH+2,X   ; X2 COORD
        BCC     --
        PLP
+++     INC     TMPL        ; Y COORD
        INC     TMPL        ; Y COORD
        LDA     TMPL
        BMI     -
        CMP     ESTKH+1,X   ; Y2 COORD
        BCC     -
++++    INX
        INX
        INX
        RTS
end
//
// Draw a string of tiles
//
export asm dgrTileStr(x, y, tilestr, strlen, tilebuff)#0
-       DEX
        DEX
        DEX
        LDA     ESTKL+7,X   ; X COORD
        STA     ESTKL+2,X
        LDA     ESTKL+6,X   ; Y COORD
        STA     ESTKL+1,X
        LDA     ESTKL+3,X   ; TILE
        STA     ESTKL,X
        LDA     ESTKH+3,X   ; TILE
        STA     ESTKH,X
end
asm _dgrTileTile
        JSR     $5000
        LDA     ESTKL+4,X   ; UPDATE X COORD
        CLC
        ADC     #$08
        CMP     #80         ; OFF RIGHT SIDE
        BPL     +
        STA     ESTKL+4,X
        DEC     ESTKL+1,X   ; DEC STRLEN
        BNE     -
+       INX
        INX
        INX
        INX
        INX
        RTS
end
//
// Fill a buffer with tiles
//
export asm dgrFill(x, y, tile)#0
        LDA     ESTKL+2,X
        AND     #$0F
        STA     ESTKL+2,X
        LDA     ESTKL+1,X
        AND     #$0F
        STA     ESTKL+1,X
        LDA     #$00
        SEC
        SBC     ESTKL+2,X   ; ORIGINAL X
        STA     ESTKL+2,X
        STA     ESTKH+2,X
        LDA     #$00
        SEC
        SBC     ESTKL+1,X
        STA     ESTKL+1,X
-       DEX
        DEX
        DEX
        LDA     ESTKL+5,X   ; X COORD
        STA     ESTKL+2,X
        LDA     ESTKL+4,X   ; Y COORD
        STA     ESTKL+1,X
        LDA     ESTKL+3,X   ; TILE
        STA     ESTKL,X
        LDA     ESTKH+3,X   ; TILE
        STA     ESTKH,X
end
asm _dgrFillTile
        JSR     $5000
        LDA     ESTKL+2,X   ; UPDATE X COORD
        CLC
        ADC     #$08
        STA     ESTKL+2,X
        CMP     #80         ; OFF RIGHT SIDE?
        BMI     -
        LDA     ESTKH+2,X   ; RESTORE X COORD
        STA     ESTKL+2,X
        LDA     ESTKL+1,X   ; UPDATE Y COORD
        CLC
        ADC     #$08
        STA     ESTKL+1,X
        CMP     #48         ; OFF BOTTOM?
        BMI     -
        INX
        INX
        INX
        RTS
end
//
// Wait for VLB - Only IIe/IIGS.
//
asm vlbWait#0
-       LDA     $C019
        BMI     -
-       LDA     $C019
        BPL     -
        RTS
end
// Wait for VBL on IIc is entirely different from others.
// Setup, one-time *only* if polling will be used exclusively.
// Otherwise requires restoring the mode on exit,
// and setting up per-use instead.
//   [php]
//   sei         ; otherwise interrupt is still raised
//   sta   $C07F ; enable access to VBL register
//   sta   $C05B ; enable VBL polling
//   sta   $C07E ; disable access to VBL register
//
// wait for VBL:
// - bit   $C019
//   bpl   -
//   lda   $C070 ; $c019 bit 7 is sticky, reset it
//
// To allow other methods of VBL, restore access:
// - bit   $C019
//   bpl   -
//   lda   $C070 ; $c019 bit 7 is sticky, reset it
//   sta   $C07F ; enable access to VBL register
//   sta   $C05A ; disable VBL polling
//   sta   $C07E ; disable access to VBL register
//   [plp]

//
// Clear the buffer
//
export def dgrClear(clr)#0
    byte[32] clrtile

    clr = evnclr[clr&$0F] | (oddclr[clr&$0F] << 8)
    memset(@clrtile, clr, 32)
    dgrFill(0, 0, @clrtile)
end
export def dgrMode(mode)#1
    if mode
        //
        // Set double lores graphics, return draw buffer
        //
        ^showlores
        ^showfull
        ^showgraphics
        ^showpage1
        ^ena80  = 0
        ^show80 = 0
        ^an3on
        drawpage = 1
        drawbuff = dgrbuff[1]
        return 1
    fin
    //
    // Set text mode
    //
    ^showtext
    ^showpage1
    ^ena80   = 0
    ^show40  = 0
    ^mapmain = 0
    ^an3off
    call($FC58, 0, 0, 0, 0) // home()
    return 0
end
//
// Set display page, return other page
//
export def dgrShow(page)#1
    page = page & 1
    ^(showpage1 + page)
    return page ^ 1
end
export def dgrSwap#0
    ^(showpage1 + drawpage)
    drawpage   = drawpage ^ 1
    drawbuff = dgrbuff[drawpage]
end
export def dgrDrawBuf(page)#0
    drawpage   = page
    drawbuff = dgrbuff[drawpage]
end
//
// Set color for clear & plot routines
//
export def dgrColor(clr)#0
    ^$30 = clr & $0F
end
//
// Make sure we are a 128K //e or //c
//
if MACHID & $F0 <> $B0
    puts("\n128K required for double-lores.\n")
    ^$C010
    while ^$C000 < 128; loop
    return -1
fin
//
// Assembly fixups
//
_dgrPlotPix:1   = @_dgrSetPix
_dgrHLinPix:1   = @_dgrSetPix
_dgrVLinPix:1   = @_dgrSetPix
_dgrBLTPix:1    = @_dgrSetPix
_dgrTileTile:1  = @dgrTile
_dgrFillTile:1  = @dgrTile
_dgrSetEvnEvn:1 = @evnclr
_dgrSetEvnOdd:1 = @oddclr
_dgrSetOddEvn:1 = @evnclr
_dgrSetOddOdd:1 = @oddclr
//
// Fixups for drawbuff
//
dgrPlot:1       = @drawbuff
dgrPlot:6       = @drawbuff+1
dgrHLin:1       = @drawbuff
dgrHLin:6       = @drawbuff+1
dgrVLin:1       = @drawbuff
dgrVLin:6       = @drawbuff+1
dgrBLT:1        = @drawbuff
dgrBLT:6        = @drawbuff+1
dgrTile:1       = @drawbuff
dgrTile:6       = @drawbuff+1
// Put read AUX mem routine in scary location
memcpy($0100, @auxRead, 9)
done
