;############## Calcuzap by Patrick Davidson

#ifdef  TI84CE
#include        ti84pce.inc
#define bcall(x) call x
_maybe_ClrScrn  =_ClrScrnFull
_DivHLBy10      =_DivHLBy10_s   
_DrawStatusBar  =$021A3C
#else
#include        ti84pcse.inc
#endif

frame_count     =cmdShadow+256
fire_pressed    =cmdShadow+258
enemies_left    =cmdShadow+259

b_count         =22
b_type          =0              ; player bullet structure
b_x             =1
b_y             =2
b_image         =3
#ifdef          TI84CE
b_size          =6
#else
b_size          =5
#endif

e_count         =21
e_type          =0              ; enemy structure
e_x             =1
e_y             =2
#ifdef          TI84CE
e_image         =3
e_misc          =6
e_dmg           =7
e_size          =8
#else
e_image         =3
e_misc          =5
e_dmg           =6
e_size          =7
#endif

eb_count        =25
eb_type         =0              ; enemy bullet structure
eb_x            =1
eb_y            =2
#ifdef          TI84CE
eb_image        =3
eb_misc         =6
eb_size         =7
#else
eb_image        =3
eb_misc         =5
eb_size         =6
#endif

        .org    userMem-2
#ifdef  TI84CE
        .db     tExtTok,tAsm84CeCmp
#else
        .db     $EF,$69
#endif

;############## Initialization / cleanup / save (CE only)

#ifdef TI84CE
        call    _RunIndicOff
        call    Read_Save_File
#else
        ld      a,1
        out     ($20),a         ; LUDICROUS SPEED!
        call    Display_Org
#endif
        call    main
#ifdef TI84CE
        call    Create_Save_File
#else
        call    Display_Normal  
#endif
        bcall(_DrawStatusBar)
        ld      hl,cmdShadow
        ld      (hl),' '
        ld      de,cmdShadow+1
        ld      bc,259
        ldir
        ld      hl,textShadow
        ld      (hl),' '
        ld      de,textShadow+1
        ld      bc,259
        ldir
        bcall(_maybe_ClrScrn)
        ret
        
main:   call    Clear_Screen
        
        xor     a               ; clear data
        ld      hl,cmdShadow
        ld      (hl),a
        ld      de,cmdShadow+1
        ld      bc,259
        ldir

        ld      hl,saved_flag
        ld      a,(hl)
        or      a
        ld      (hl),0
        jr      nz,play_game_resumed
        
save_game_not_found:
        ld      hl,data_start
        ld      (hl),0
        ld      de,data_start+1
        ld      bc,data_end-data_start-1
        ldir
        ld      hl,$b080
        ld      (p_x),hl
        ld      hl,img_player
        ld      (p_image),hl
        ld      a,1
        ld      (lives),a
        ld      hl,score
        ld      de,score+1
        ld      bc,5
        ld      (hl),'0'
        ldir
        
        call    Show_Title_Screen
        ld      (score_inc),a
        ld      a,l
        ld      (delay_amount),a
        call    Clear_Screen

play_game_resumed
        call    Show_Lives
        ld      a,(level)
        call    Decode_Level
        ld      hl,title_messages
        call    Draw_Strings    
        
#ifndef TI84CE
        ld      a,$45
        out     ($30),a         ; set timer frequency to 2048Hz
#endif
        jr      timer_wait_done

main_loop:
        ld      a,(score+4)
        or      1
        ld      hl,rand_inc
        add     a,(hl)
        ld      (hl),a
        
        ld      hl,(frame_count)
        inc     hl
        ld      (frame_count),hl
        ld      bc,33*4*256+232
        ld      hl,score
        call    Draw_String

#ifndef TI84CE
        ld      a,%10111111     ; mask most keys (allow 2nd)
        out     (1),a
#endif

#ifdef  TI84CE
;       ld      a,($F20001)
;       or      a
;       jr      nz,timer_loop
;       ld      hl,score
;       inc     (hl)
;       jr      timer_wait_done
timer_loop:
        ld      a,($F20001)
        or      a
        jr      nz,timer_loop
timer_wait_done:
        ld      hl,$F20030
        res     0,(hl)          ; disable timer
        set     1,(hl)          ; set frequency to 32768Hz
        res     2,(hl)          ; no interrupt
        inc     hl
        res     1,(hl)          ; count down
        ld      a,(delay_amount)
        ld      hl,2
        ld      ($F20004),hl
        ld      l,a
        add     hl,hl
        add     hl,hl
        add     hl,hl
        add     hl,hl
        inc     h
        ld      ($F20000),hl    ; value to count down from
        xor     a
        ld      ($F20003),a
        ld      ($F20006),a
        ld      hl,$F20030
        set     0,(hl)          ; re-enable timer
#else
;       in      a,(4)
;       bit     5,a
;       jr      z,timer_loop
;       ld      hl,score
;       inc     (hl)
;       jr      timer_wait_done
timer_loop: 
        in      a,(4)
        bit     5,a
        jr      z,timer_loop
timer_wait_done:
        xor     a
        out     ($31),a
        ld      a,(delay_amount)
        out     ($32),a          ; restart timer
#endif     
        
        ld      hl,fire_pressed
#ifdef  TI84CE
        call    GET_KEY
        ld      a,(getkeylastdata+6)
        bit     5,a
        jr      z,no_fire
#else
        in      a,(1)           ; shoot if 2nd is pressed
        bit     5,a
        jr      nz,no_fire
#endif
        ld      a,(hl)
        or      a
        jr      nz,fire_done
        inc     (hl)
        call    fire_bullet     
        jr      fire_done
no_fire:
        xor     a
        ld      (hl),a
fire_done:

        call    player_bullets
        call    process_enemies
        call    hit_enemy
        call    process_enemy_bullets
        ld      hl,(lives)
        ld      a,h
        or      l
        jr      nz,didnt_lose
        ld      hl,lose_message
        call    check_highscore
        ret
didnt_lose:

#ifndef TI84CE        
        ld      a,%11111110
        out     (1),a           ; mask most keys (allow arrows)
#endif
        ld      hl,player_move_done     ; ret from move jumps here
        push    hl                      
        ld      hl,p_x  
        
#ifdef  TI84CE
        ld      a,(getkeylastdata)
        cpl
#else
        in      a,(1)
#endif
        and     %1111
        add     a,a
        ld      (do_player+1),a
#ifndef TI84CE
        ld      a,%10111111     ; mask out most keys (allows DEL and MODE)
        out     (1),a
#endif
        ld      a,(player_cd)
        or      a
        jr      z,do_player

player_exploding:
        inc     a
        ld      (player_cd),a
        rra
        jr      nc,player_no_move
        
        push    hl
        ld      hl,(p_image)
        ld      de,394
        add     hl,de
        ld      (p_image),hl
        ld      a,(hl)
        or      a
        pop     hl
        jr      nz,player_no_move
        
player_explode_done:
        ld      de,img_enemy_explode
        ld      (p_image),de
        ld      (player_cd),a
        push    hl
        call    erase_object_x
        ld      hl,img_player
        ld      (p_image),hl
        pop     hl
        jr      player_no_move
        
do_player:
        jr      point_to_player_code
point_to_player_code:
        jr      player_no_move          ; 0000 all arrows pressed
        jr      player_up               ; all arrows pressed but down
        jr      player_right            ; all arrows pressed but left
        jr      player_up_right
        jr      player_left             ; 0100 all arrows pressed but right
        jr      player_up_left
        jr      player_no_move          ; up and down pressed
        jr      player_up
        jr      player_down             ; 1000 all arrows pressed but up
        jr      player_no_move          ; left and right pressed
        jr      player_down_right
        jr      player_right
        jr      player_down_left        ; 1100
        jr      player_left
        jr      player_down
                                        ; nothing pressed                                       
player_no_move:
        xor     a
        jp      move_up

player_up:
        inc     hl
        ld      a,(hl)
        cp      160
        ret     z
        dec     hl
        ld      a,-4
        jp      move_up

player_up_right:
        inc     hl
        ld      a,(hl)
        dec     hl
        cp      160                     ; check if at the top
        jr      z,player_right          ; if so, switch to right only
        ld      a,(hl)
        cp      160+48-8                ; check if at right edge
        jr      z,player_up             ; if so, switch to up only
        ld      bc,$02FC
        jp      move_up_right
        
player_up_left:
        inc     hl
        ld      a,(hl)
        dec     hl
        cp      160                     ; check if at the top
        jr      z,player_left           ; if so, switch to left only
        ld      a,(hl)
        cp      48                      ; check if at left edge
        jr      z,player_up             ; if so, switch to up only
        ld      bc,$FEFC
        jp      move_up_left
        
player_down_left:
        inc     hl
        ld      a,(hl)
        dec     hl
        cp      240                     ; check if at the bottom
        jr      z,player_left           ; if so, switch to left only
        ld      a,(hl)
        cp      48                      ; check if at left edge
        jr      z,player_down           ; if so, switch to down only
        ld      bc,$FE04
        jp      move_down_left
        
player_down:
        inc     hl
        ld      a,(hl)
        cp      240
        ret     z
        dec     hl
        ld      a,4
        jp      move_down

player_left:
        ld      a,(hl)
        cp      48
        ret     z
        ld      a,-2
        jp      move_left

player_right:
        ld      a,(hl)
        cp      160+48-8
        ret     z
        ld      a,2
        jp      move_right
        
player_down_right:
        inc     hl
        ld      a,(hl)
        dec     hl
        cp      240                     ; check if at the bottom
        jr      z,player_right          ; if so, switch to right only
        ld      a,(hl)
        cp      160+48-8                ; check if at right edge
        jr      z,player_down           ; if so, switch to down only
        ld      bc,$0204
        jp      move_down_right
        
player_move_done:
#ifdef  TI84CE
        ld      a,(getkeylastdata+6)
        add     a,a
        ret     c
        add     a,a
        jp      nc,main_loop
        inc     a
#else
        in      a,(1)
        add     a,a
        ret     nc
        add     a,a
        jp      c,main_loop
#endif
        
save_game:
        ld      (saved_flag),a
        ret
        
#ifdef   TI84CE
#include gfxce.asm
#include savece.asm
#else
#include gfx.asm
#endif
#include        text.asm
#include        bullets.asm
#include        enemies.asm
#include        collide.asm
#include        hitenemy.asm
#include        ebullets.asm
#include        eshoot.asm
#include        level.asm
#include        title.asm
#include        move.asm
#include        hiscore.asm
#include        chars.i
#include        data.asm
#ifdef   TI84CE
#include        imagesce.i
#else
#include        images.i
#endif
scroll_table:
#include        scroll_table.i

        .end