;---------------= Slopes =--------------
; Author:       Ian Graf
;               (ian_graf@geocities.com)
; Version:      2.0
; Platform:     ION
; Date:         11/3/99
;---------------------------------------


;---------------= header =--------------

        .nolist
        #define         slopes
        #define         snow
        #include        "slopes.inc"
        #include        "ion.inc"
        .list
#ifdef  TI83P
        .org    progstart-2
        .db     $BB,$6D
#else
        .org    progstart
#endif
        ret
        jr      nc,start_of_program
        .db     "Slopes 2.0 By Ian Graf",0


;-----------= detect levels =-----------

start_of_program:
        set     7,(iy+20)               ; write to graph
        xor     a                       ; initalize menu
        ld      (menusize),a            ;
        ld      (menuitem),a            ;
        ld      (menutop),a             ;
        ld      hl,(progptr)            ;
        ld      ix,detectstr            ;
        call    ionDetect               ;
        ret     nz                      ; no levels
store_item:
        ld      (curvat),de             ;
        push    hl                      ;
        ld      hl,menusize             ; inc menu size
        ld      a,(hl)                  ;
        inc     (hl)                    ;
        call    itemaddr                ; compute address of menu item
        pop     de                      ;
        ld      (hl),e                  ; store pointer to item
        inc     hl                      ;
        ld      (hl),d                  ;
nextl:  ld      hl,(curvat)             ; next level
        ld      ix,detectstr            ;
        call    ionDetect               ;
        jr      z,store_item            ;


;------------= title screen =-----------

title_screen:
#ifdef  snow
        ld      hl,flakes               ; reset flake coords
        ld      a,-1                    ;
        ld      b,15                    ;
snowzl: ld      (hl),a                  ;
        inc     hl                      ;
        sub     4                       ;
        push    af                      ;
        push    bc                      ;
        ld      b,93                    ; random x coord
        call    ionRandom               ;
        ld      (hl),a                  ;
        inc     hl                      ;
        pop     bc                      ;
        pop     af                      ;
        djnz    snowzl                  ;
#endif
titlel: call    drawtitle               ; draw title
        call    drawmenu                ; draw menu
#ifdef  snow
        call    drawsnow                ; draw snow
#endif
        call    ionFastcopy             ;
        bcall(_getk)                    ;
        dec     a                       ; [(down)]
        jr      nz,tup                  ; move highlight
        call    menudown                ;
        jr      titlel                  ;
tup:    sub     4-1                     ; [(up)]
        jr      nz,tquit                ; move highlight
        call    menuup                  ;
        jr      titlel                  ;
tquit:  sub     15-4                    ; [CLEAR]
        ret     z                       ; quit
        sub     54-15                   ;
        jr      nz,titlel               ;
            

;-------------= game play =-------------

game_start:
        ld      a,(menuitem)            ; get pointer to highlighted level
        call    itemaddr                ;
        bcall(_ldhlind)                 ;
        call    getlength               ; skip level name
        add     hl,de                   ;
        inc     hl                      ;
        ld      (highptr),hl            ; high score pointer
        ld      d,(hl)                  ; high score
        inc     hl                      ;
        ld      e,(hl)                  ;
        inc     hl                      ;
        ld      (high),de               ;
        ld      (level),hl              ; level data pointer
        ld      a,95                    ; reset time
        ld      (time),a                ;
        ld      (life),a                ; reset life
        ld      hl,0                    ; reset score
        ld      (score),hl              ;
        xor     a                       ; position skier
        ld      (row),a                 ;
        ld      a,5                     ;
        ld      (col),a                 ;
        ld      b,250                   ;
gamel:  push    bc                      ;
        ld      a,%11111111             ;
        out     (1),a                   ;
        ld      a,%11111110             ;
        out     (1),a                   ;
        in      a,(1)                   ;
        push    af                      ;
        bit     1,a                     ; [(left)]
        call    z,move_left             ; move skier left
        pop     af                      ;
        bit     2,a                     ; [(right)]
        call    z,move_right            ; move skier right
        call    draw                    ; draw screen
        jr      nz,gndead               ; dead
        call    shake                   ; shake screen
        pop     bc                      ;
        jr      game_done               ; display score
gndead: bcall(_getk)                    ;
        cp      15                      ; [CLEAR]
        jr      nz,nextk                ; quit
        pop     bc                      ;
        jp      title_screen            ;
nextk:  cp      55                      ; [MODE]
        jr      nz,npause               ; pause
        ld      hl,5*256+3              ;
        ld      (currow),hl             ;
        ld      hl,pausestr             ;
        bcall(_puts)                    ;
pausel: bcall(_getk)                    ;
        cp      55                      ;
        jr      nz,pausel               ;
npause: ld      hl,(score)              ; increment score
        inc     hl                      ;
        inc     hl                      ;
        ld      (score),hl              ;
        pop     bc                      ;
        djnz    gamel                   ;
        ld      hl,(score)              ; add bonus
        ld      de,5                    ;
        add     hl,de                   ;
        ld      (score),hl              ;


;--------= done with game play =--------

game_done:
        call    drawtitle               ; draw title
        call    ionFastCopy             ;
        ld      hl,3*256+5              ; write "Score:"
        ld      (currow),hl             ;
        ld      hl,scorestr             ;
        bcall(_puts)                    ;
        ld      hl,(score)              ; write score
        ld      a,(life)                ;
        ld      d,0                     ;
        ld      e,a                     ;
        add     hl,de                   ;
        ld      (score),hl              ;
        bcall(_disphl)                  ;
        ld      hl,3*256+6              ; write "High:"
        ld      (currow),hl             ;
        ld      hl,highstr              ;
        bcall(_puts)                    ;
        ld      hl,(high)               ; write high score
        bcall(_disphl)                  ;
        call    wait_for_2nd            ;
        ld      hl,(score)              ; check for new high score
        dec     hl                      ;
        ld      de,(high)               ;
        bcall(_cphlde)                  ;
        jp      c,title_screen          ;
        ld      de,(highptr)            ; save score
        ex      de,hl                   ;
        ld      (hl),d                  ;
        inc     hl                      ;
        ld      (hl),e                  ;
        call    ionFastCopy             ;
        ld      hl,4*256+5              ; write "New High"
        ld      (currow),hl             ;
        ld      hl,newstr1              ;
        bcall(_puts)                    ;
        ld      bc,5*256+6              ; write "Score"
        ld      (currow),bc             ;
        bcall(_puts)                    ;
        call    wait_for_2nd            ;
        jp      title_screen            ;


;-----------= wait for [2nd] =----------

wait_for_2nd:
        bcall(_getk)                    ; wait for [2nd]
        cp      54                      ;
        jr      nz,wait_for_2nd         ;
        ret                             ;


;----------= move skier right =---------

move_right:
        ld      a,(col)                 ;
        cp      11                      ;
        ret     z                       ;
        inc     a                       ;
        ld      (col),a                 ;
        ret                             ;


;----------= move skier left =----------

move_left:
        ld      a,(col)                 ;
        or      a                       ;
        ret     z                       ;
        dec     a                       ;
        ld      (col),a                 ;
        ret                             ;


;-------------= draw title =------------

drawtitle:
        bcall(_cleargbuf)               ;
        ld      hl,title                ;
        ld      de,grbuf+(12*5)         ;
        ld      bc,12*25                ;
        ldir                            ;
        ret                             ;


;---------= draw game screen =----------

draw:   bcall(_cleargbuf)               ;


;----------= check collision =----------

chkhit: ld      a,(col)                 ;
        srl     a                       ;
        push    af                      ;
        call    getoff                  ;
        ld      d,0                     ;
        ld      e,a                     ;
        add     hl,de                   ;
        pop     af                      ;
        ld      a,(hl)                  ;
        jr      c,odd                   ;
even:   and     %11110000               ;
        rra                             ;
        rra                             ;
        rra                             ;
        rra                             ;
odd:    and     %00001111               ;
        ld      hl,time                 ; check for clock
        cp      7                       ;
        jr      nz,calct                ;
        ld      (hl),95                 ;
        jr      drawlevel               ;
calct:  dec     (hl)                    ; time == 0
        jr      z,calcd                 ;
        dec     (hl)                    ;
calcd:  ld      hl,damage               ;
        ld      d,0                     ;
        ld      e,a                     ;
        add     hl,de                   ;
        ld      a,(hl)                  ;
        ld      hl,life                 ;
        add     a,(hl)                  ;
        cp      106                     ; check if life > 105
        jr      c,chkc                  ;
        xor     a                       ;
chkc:   cp      96                      ; check if life > 95
        jr      c,sto                   ;
        ld      a,95                    ; set life to 0
sto:    ld      (hl),a                  ; store life


;-------------= draw level =------------

drawlevel:
        call    getoff                  ; decompress data
        ld      de,leveldata            ;
        push    de                      ;
        ld      bc,48*256+15            ;
        call    ionDecompress           ;
        ld      a,250                   ; determine number of rows to draw
        ld      hl,row                  ;
        sub     (hl)                    ;
        cp      8                       ;
        jr      c,contd                 ;
        ld      a,8                     ;
contd:  ld      b,a                     ;
        pop     hl                      ;
        ld      de,grbuf                ;
        push    de                      ;
drawl1: push    bc                      ;
        ld      b,12                    ; 12 cols
drawl2: push    bc                      ;
        push    de                      ;
        push    hl                      ;
        ld      a,(hl)                  ; get item
        call    drawi                   ; draw item
        pop     hl                      ;
        pop     de                      ;
        pop     bc                      ;
        inc     hl                      ;
        inc     de                      ;
        djnz    drawl2                  ;
        ld      b,84                    ; next row
drawl3: inc     de                      ;
        djnz    drawl3                  ;
        pop     bc                      ;
        djnz    drawl1                  ;
        ld      a,(col)                 ; draw skier
        ld      d,0                     ;
        ld      e,a                     ;
        pop     hl                      ;
        add     hl,de                   ;
        ex      de,hl                   ;
        ld      a,8                     ;
        call    drawi                   ;


;----------= draw time scale =----------

drawtime:
        ld      hl,grbuf+(12*61)        ; blank out bottom 3 rows
        ld      (hl),0                  ;
        ld      de,grbuf+((12*61)+1)    ;
        ld      bc,47                   ;
        ldir                            ;
        ld      hl,grbuf+(12*62)        ; draw line from (0,61) to (time,61)
        ld      a,(time)                ;
        call    drawline                ;


;----------= draw life scale =----------

drawlife:
        ld      hl,grbuf+(12*63)        ; draw line from (0,62) to (life,62)
        ld      a,(life)                ;
        call    drawline                ;
        call    ionFastCopy             ;
        ld      b,12                    ; delay
        call    delay                   ;
        ld      hl,row                  ; move to next row
        inc     (hl)                    ;
        ld      a,(time)                ; check time
        or      a                       ;
        ret     z                       ;
        ld      a,(life)                ; check life
        or      a                       ;
        ret                             ;


;--------------= put item =-------------

drawi:  dec     a                       ; draw item
        ret     m                       ;
        push    de                      ;
        sla     a                       ;
        sla     a                       ;
        sla     a                       ;
        ld      hl,sprites              ;
        ld      d,0                     ;
        ld      e,a                     ;
        add     hl,de                   ;
        pop     de                      ;
        ld      b,8                     ;
drawl:  ld      a,(hl)                  ;
        ld      (de),a                  ;
        push    hl                      ;
        ld      hl,12                   ;
        add     hl,de                   ;
        ex      de,hl                   ;
        pop     hl                      ;
        inc     hl                      ;
        djnz    drawl                   ;
        ret                             ;


;-------------= draw line =-------------

drawline:
        ld      b,0                     ;
        ld      c,a                     ;
        inc     c                       ;
        ld      d,%10000000             ;
        ld      a,(hl)                  ;
linel:  or      d                       ;
        dec     c                       ;
        jr      z,endl                  ;
        rrc     d                       ;
        jr      nc,linel                ;
        ld      (hl),a                  ;
        inc     hl                      ;
        ld      a,(hl)                  ;
        jr      linel                   ;
endl:   ld      (hl),a                  ;
        ret                             ;


#ifdef  snow
;-------------= draw snow =-------------

drawsnow:
        ld      hl,flakes               ;
        ld      b,15                    ;
snowl:  push    bc                      ;
        ld      a,(hl)                  ;
        cp      61                      ;
        jr      nz,fdown                ;
        ld      (hl),$FF                ;
        ld      b,93                    ;
        call    ionRandom               ;
        inc     hl                      ;
        ld      (hl),a                  ;
        dec     hl                      ;
fdown:  inc     (hl)                    ;
        ld      a,(hl)                  ;
        inc     hl                      ;
        push    hl                      ;
        or      a                       ;
        ld      e,a                     ;
        ld      a,(hl)                  ;
        ld      hl,flake                ;
        call    p,sprite                ;
        pop     hl                      ;
        pop     bc                      ;
        inc     hl                      ;
        djnz    snowl                   ;
        ret                             ;


;------------= draw sprite =------------

sprite: push    hl                      ;
        ld      hl,0                    ;
        ld      d,0                     ;
        add     hl,de                   ;
        add     hl,de                   ;
        add     hl,de                   ;
        add     hl,hl                   ;
        add     hl,hl                   ;
        ld      e,a                     ;
        srl     e                       ;
        srl     e                       ;
        srl     e                       ;
        add     hl,de                   ;
        ld      de,grbuf                ;
        add     hl,de                   ;
        and     %00000111               ;
        or      a                       ;
        jr      z,align                 ;
        pop     ix                      ;
        ld      d,a                     ;
        ld      e,3                     ;
liloop: ld      b,(ix+0)                ;
        ld      c,0                     ;
        push    de                      ;
shloop: srl     b                       ;
        rr      c                       ;
        dec     d                       ;
        jr      nz,shloop               ;
        pop     de                      ;
        ld      a,b                     ;
        or      (hl)                    ;
        ld      (hl),a                  ;
        inc     hl                      ;
        ld      a,c                     ;
        or      (hl)                    ;
        ld      (hl),a                  ;
        ld      bc,11                   ;
        add     hl,bc                   ;
        inc     ix                      ;
        dec     e                       ;
        jr      nz,liloop               ;
        ret                             ;
align:  pop     de                      ;
        ld      b,3                     ;
aloop:  ld      a,(de)                  ;
        or      (hl)                    ;
        ld      (hl),a                  ;
        inc     de                      ;
        push    bc                      ;
        ld      bc,12                   ;
        add     hl,bc                   ;
        pop     bc                      ;
        djnz    aloop                   ;
        ret                             ;
#endif


;-------------= draw menu =-------------

drawmenu:
        ld      a,36                    ; reset row
        ld      (penrow),a              ;
        ld      a,(menutop)             ;
        ld      b,a                     ; top of menu
drawml: push    bc                      ;
        ld      a,b                     ; get address to item
        call    itemaddr                ;
        bcall(_ldhlind)                 ; get address to name
        ld      a,5                     ; reset col
        ld      (pencol),a              ;
        push    hl                      ; draw name centered
        call    getlength               ; get length of string
        ld      b,e                     ;
        xor     a                       ;
countl: push    bc                      ;
        push    hl                      ;
        push    af                      ;
        ld      a,(hl)                  ; get character
        ld      h,0                     ;
        ld      l,a                     ;
        add     hl,hl                   ; hl = hl*8
        add     hl,hl                   ;
        add     hl,hl                   ;
        bcall(_sfontlen)                ; get char width
        pop     af                      ;
        cp      93                      ; clip?
        jr      nc,contc                ;
        add     a,b                     ;
contc:  pop     hl                      ;
        inc     hl                      ;
        pop     bc                      ;
        djnz    countl                  ;
        ld      b,a                     ; center string
        ld      a,96                    ;
        sub     b                       ;
        srl     a                       ;
        ld      (pencol),a              ;
        pop     hl                      ;
        bcall(_vputs)                   ; draw string
        ld      a,(penrow)              ; next col
        add     a,7                     ;
        ld      (penrow),a              ;
        pop     bc                      ;
        inc     b                       ;
        ld      a,(menutop)             ; check 3 items drawn
        add     a,3                     ;
        cp      b                       ;
        jr      z,dmdone                ;
        ld      a,(menusize)            ; check end of menu
        cp      b                       ;
        jr      nz,drawml               ;
dmdone: ld      a,(menutop)             ; get offset of highlighted item
        ld      b,a                     ;
        ld      a,(menuitem)            ;
        sub     b                       ;
        ld      h,84                    ;
        ld      l,a                     ;
        bcall(_htimesl)                 ;
        ld      de,grbuf+(12*36)        ;
        add     hl,de                   ;
        ld      b,12*7                  ;
dminvl: ld      a,(hl)                  ; invert item
        cpl                             ;
        ld      (hl),a                  ;
        inc     hl                      ;
        djnz    dminvl                  ;
        ret                             ;


;---------= move highlight up =---------

menuup: ld      a,(menuitem)            ;
        or      a                       ;
        jr      nz,up                   ;
        ld      a,(menusize)            ;
        ld      b,a                     ;
        dec     a                       ;
        cp      3                       ;
        jr      nc,uptop                ;
        ld      a,2                     ;
uptop:  dec     a                       ;
        dec     a                       ;
        ld      (menutop),a             ;
        jr      updone                  ;
up:     ld      b,a                     ;
        ld      a,(menutop)             ;
        cp      b                       ;
        jr      nz,updone               ;
        dec     a                       ;
        ld      (menutop),a             ;
updone: ld      a,b                     ;
        dec     a                       ;
        ld      (menuitem),a            ;
        ret                             ;


;--------= move highlight down =--------

menudown:
        ld      hl,menutop              ;
        ld      a,(menusize)            ;
        ld      b,a                     ;
        ld      a,(menuitem)            ;
        inc     a                       ;
        cp      b                       ;
        jr      nz,down                 ;
        xor     a                       ;
        ld      (hl),a                  ;
down:   ld      (menuitem),a            ;
        ld      b,a                     ;
        ld      a,(hl)                  ;
        add     a,3                     ;
        cp      b                       ;
        ret     nz                      ;
        inc     (hl)                    ;
        ret                             ;


;------= get address of menu item =-----

itemaddr:
        sla     a                       ; a = item number
        ld      d,0                     ;
        ld      e,a                     ;
        ld      hl,menustart            ;
        add     hl,de                   ; hl = address
        ret                             ;

 
;--------= get length of string =-------

getlength:
        ld      bc,24                   ; get length of string in hl
        xor     a                       ; max length 24 chars
        push    hl                      ;
        cpir                            ;
        ld      hl,23                   ;
        sbc     hl,bc                   ;
        ex      de,hl                   ;
        pop     hl                      ;
        ret                             ; de = length


;-------------= get offset =------------

getoff: push    af                      ;
        ld      a,(row)                 ;
        ld      hl,0                    ;
        ld      d,0                     ;
        ld      e,a                     ;
        add     hl,de                   ;
        add     hl,de                   ;
        add     hl,de                   ;
        add     hl,hl                   ;
        ld      de,(level)              ;
        add     hl,de                   ;
        pop     af                      ;
        ret                             ;


;-------= invert and shake screen =-----

shake:  ld      hl,grbuf                ; invert screen
        ld      bc,768                  ;
invl:   ld      a,(hl)                  ;
        cpl                             ;
        ld      (hl),a                  ;
        inc     hl                      ;
        dec     bc                      ;
        ld      a,b                     ;
        or      c                       ;
        jr      nz,invl                 ;
        call    ionFastCopy             ;
        ld      b,2                     ;
shakel: push    bc                      ;
        ld      b,10                    ;
        call    delay                   ; delay
        ld      a,$42                   ; set hardware scrolling offset
        out     (lcdinstport),a         ;
        ld      b,10                    ;
        call    delay                   ; delay
        ld      a,$40                   ; set hardware scrolling offset
        out     (lcdinstport),a         ;
        pop     bc                      ;
        djnz    shakel                  ;
        ret                             ;


;---------------= delay =---------------

delay:  ei                              ;
delayl: halt                            ;
        djnz    delayl                  ;
        ret                             ;


;---------------= dialog =--------------

pausestr:
        .db     "Paused",0
scorestr:
        .db     "Score",0
highstr:
        .db     "High ",0
newstr1:
        .db     "New High",0
newstr2:
        .db     "Score!",0


;-------= level detection string =------

detectstr:
        .db     "ZSLPS",0


;--------= damage done per item =-------

damage: .db     0,-5,-50,-20,-40,-5,10


        #include        "slopes.grx"


        .end
