;---------------------------------------------------------------;
;                                                               ;
; Snail Maze                                                    ;
; Drawing routines                                              ;
;                                                               ;
;---------------------------------------------------------------;

;------------------------------------------------
; drawSnail - draw the player (snail)
;   input:  none
;   output: none
;------------------------------------------------
drawSnail:
        ld      hl,0
        ld      a,(dir)
        ld      l,a
        add     a,a
        add     a,l
        ld      l,a
        ld      de,snailTable
        add     hl,de                           ; HL => snailTable entry
        bcall(_lddehl)                          ; DE => sprite
        push    de
        ld      hl,(sx)                         ; L = grid x
        ld      e,h                             ; E = grid y
        call    getScreenPos
        inc     de
        inc     l
        ld      a,(moveCount)
        bit     7,a
        call    z,dsOffset
        pop     ix                              ; IX => sprite
        call    drawSprite
        ret
dsOffset:
        ld      b,a
        ld      a,(dir)
        bit     1,a                             ; check which axis snail is moving on
        jr      nz,dsmXaxis
        bit     0,a                             ; moving up or down?
        ld      a,b
        ld      c,9
        jr      z,dsmAfterNeg
        neg
        ld      c,-2
dsmAfterNeg:
        add     a,l
        ld      l,a                             ; updated y pos
        push    hl
        push    de
        add     a,c
        ld      l,a
        ld      ix,sprRectHoriz
        call    drawSprite
        pop     de
        pop     hl
        ret
dsmXaxis:
        push    hl
        ex      de,hl                           ; HL = unmodified x pos
        ld      de,0
        ld      e,b                             ; DE = x offset
        bit     0,a                             ; moving left or right?
        jr      nz,dsmLeft
dsmRight:
        add     hl,de
        ld      bc,9
        jr      dsmXaxisDone
dsmLeft:
        or      a                               ; clear carry
        sbc     hl,de
        ld      bc,-2
dsmXaxisDone:
        ex      de,hl                           ; DE = updated x pos
        pop     hl                              ; L = y pos
        push    hl
        push    de
        ex      de,hl
        add     hl,bc
        ex      de,hl
        ld      ix,sprRectVert
        call    drawSprite
        pop     de
        pop     hl
        ret

;------------------------------------------------
; getScreenPos - convert maze grid position to actual screen position for drawing
;   input:  L = grid x
;           E = grid y
;   output: DE = x
;           L = y
;------------------------------------------------
getScreenPos:
        ld      h,TILE_SIZE
        mlt     hl
        ld      bc,MAZE_LEFT
        add     hl,bc                           ; HL = x position on screen
        push    hl
        ld      d,TILE_SIZE
        mlt     de
        ld      hl,MAZE_TOP
        add     hl,de                           ; L = y position on screen
        pop     de                              ; DE = x
        ret

;------------------------------------------------
; drawSprite - draw an 8bpp sprite
;   input:  DE = x
;           L = y
;           IX => sprite data
;   output: none
;------------------------------------------------
drawSprite:
        ld      a,(ix)
        ld      (__dsw),a
        inc     ix
        ld      a,(ix)
        ld      (__dsh),a
        inc     ix
        push    de
        ld      h,160
        mlt     hl
        add     hl,hl                           ; HL = offset to row
        ld      de,vbuf
        add     hl,de                           ; HL => row on vbuf
        pop     de                              ; DE = x
        add     hl,de                           ; HL => where to start drawing on vbuf
        ld      c,$00                           ; C = # rows to draw
__dsh                   = $-1
dsOuter:
        push    hl
        ld      b,$00                           ; B = # pixels per row
__dsw                   = $-1
dsInner:
        ld      a,(ix)                          ; A = sprite pixel
        ld      (hl),a
        inc     ix
        inc     hl
        djnz    dsInner
        pop     hl
        push    bc
        ld      bc,320
        add     hl,bc                           ; HL => where to start drawing next row on vbuf
        pop     bc
        dec     c
        jr      nz,dsOuter
        ret

;------------------------------------------------
; copySprite - draw a sprite to top-left of vBuf and copy a portion to a position on vRam (used in the SEGA intro)
;   input:  B = x position of vBuf to start copy from
;           C = width of copy
;           DE = x position of vRam to display at
;           IX => sprite data
;   output: none
;   notes:  hardcoded height & destination y position because this routine is only used in the intro and all sprites are the same height and shown at the same row
;------------------------------------------------
copySprite:
        push    de
        push    bc
        ld      de,0
        ld      l,0
        call    drawSprite
        pop     bc                              ; B = source x, C = width
        ld      de,0
        ld      e,b
        ld      hl,vBuf
        add     hl,de                           ; HL => byte of vBuf to start copy from
        ex      (sp),hl                         ; HL = dest x
        ld      de,vRam+(320*SEGA_Y)            ; DE => dest row of vRam
        add     hl,de                           ; HL => byte of vRam to start paste to
        pop     de                              ; DE => byte of vBuf to start copy from
        ld      b,SEGA_HEIGHT
csOuter:
        push    bc
        push    hl
        push    de
csInner:
        ld      a,(de)
        ld      (hl),a
        inc     de
        inc     hl
        dec     c
        jr      nz,csInner
        pop     hl
        ld      bc,320
        add     hl,bc
        ex      de,hl
        pop     hl
        add     hl,bc
        pop     bc
        djnz    csOuter
        ret

;------------------------------------------------
; drawMaze - draw the maze on vBuf and slide it on to vRam
;   input:  none
;   output: none
;------------------------------------------------
drawMaze:
        ld      ix,maze
        ld      b,MAZE_HEIGHT                   ; B = # rows to draw
        ld      l,MAZE_TOP                      ; L = y coord to start on
dmOuter:
        push    bc
        push    hl
        ld      b,MAZE_WIDTH                    ; B = # columns to draw
        ld      de,MAZE_LEFT                    ; DE = x coord to start on
dmInner:
        push    bc
        push    ix
        push    hl
        push    de
        ld      hl,0
        ld      l,(ix)                          ; HL = tile #
        push hl \ pop de
        add     hl,hl
        add     hl,de                           ; x3
        ld      de,tileTable
        add     hl,de                           ; HL => tileTable entry
        bcall(_lddehl)                          ; DE => tile data
        push    de
        pop     ix                              ; IX => tile data
        pop     de                              ; DE = x
        pop     hl                              ; HL = y
        push    hl
        push    de
        call    drawSprite                      ; draw sprite
        pop     de
        ld      hl,TILE_SIZE
        add     hl,de
        ex      de,hl                           ; DE = next x
        pop     hl                              ; HL = y
        pop     ix
        inc     ix                              ; IX => next tile #
        pop     bc
        djnz    dmInner                         ; loop for this row
        pop     hl
        ld      de,TILE_SIZE
        add     hl,de                           ; HL = next y
        pop     bc
        djnz    dmOuter
        ; draw right border
        ld      hl,BORDER_RIGHT                 ; HL => where on vbuf to start drawing border
        ld      de,320                          ; DE = bytes to skip each loop
        ld      bc,MAZE_HEIGHT*TILE_SIZE        ; BC = # pixels to draw
dmRight:
        ld      (hl),C_WALL
        add     hl,de
        dec     bc
        ld      a,b
        or      c
        jr      nz,dmRight
        ; draw bottom border
        ld      hl,BORDER_BOTTOM
        ld      bc,MAZE_WIDTH*TILE_SIZE+1       ; extra pixel to get bottom-right corner
dmBottom:
        ld      (hl),C_WALL
        inc     hl
        dec     bc
        ld      a,c
        or      b
        jr      nz,dmBottom
        ; draw goal
        ld      hl,(gx)
        ld      e,h
        call    getScreenPos
        inc     de
        inc     l
        ld      ix,sprGoal
        call    drawSprite
        ; do the slide effect
        ld      bc,320                          ; B = 320 frames of animation to perform
        ld      hl,vBuf+(320*MAZE_TOP)+319      ; HL => right side of first row
        ld      ix,vRam+(320*MAZE_TOP)+319
slideMaze:
        push    bc
        push    hl
        push    ix
        ld      b,MAZE_BOTTOM-MAZE_TOP+1        ; B = # pixels per column
smLoop:
        ld      a,(hl)
        ld      (ix),a
        ld      de,320
        add     hl,de
        add     ix,de
        djnz    smLoop
        ld      bc,300
        call    waitBC
        pop ix \ dec ix
        pop hl \ dec hl
        pop bc \ dec bc
        bcall(_chkBCis0)
        jr      nz,slideMaze
        ret

.end