[comp.sys.handhelds] H. Piper! ver 1.2 SOURCE CODE

vapsppr@prism.gatech.EDU (Paul Raines) (05/23/91)

Below is the code for H. Piper!  I hope some
future programmers out there find it an interesting
learning tool.  For those who just wish to change
the key placement or type-o-matic rate, it should
be pretty easy to do by simply changing the
key definitions near the beginning.  Good luck.

Paul Raines	vapsppr@prism.gatech.edu

--------(start of Chipper code file for H. Piper)--------
;  H. Piper Game for the HP48SX
;  (c) 1991  5/22 Paul Raines
;  Version 1.2

;  Register usage:
;  V0:  Temporary data, may change during any call
;  V1:  Temporary data, may change during any call
;  V2:  Temporary data, may change during any call
;  V3:  Temporary data, may change during any call
;  V4:  Temporary data, may change during any call
;  V5:  Temporary data, may change during any call
;  V6:  Temporary data, may change during any call
;  V7:  Current Job Score (ones & tens)
;  V8:  Current Job Score (hundreds & up)
;  V9:  Current Box type
;  VA:  Box progression
;  VB:  Flow direction
;  VC:  Current Box pos
;  VD:  Paddle position
;  VE:  Speed Level
;  VF:  Flag register

;  NOTE: Box position is stored in one register such that
;                        #34h
;                  y pos --^^--- x pos on grid
;
;        Two registers are used for the score in order to
;        have a decimal number greater than 255.

; *************************
; START OF DEFINITIONS AREA
; *************************

F_UP    =   #00  ; direction definitions
F_DOWN  =   #03
F_RIGHT =   #06
F_LEFT  =   #05

B_NE    =   #1D  ; pipe definitions
B_SW    =   #15
B_NW    =   #1E            ; NOTE THAT
B_SE    =   #16            ;
B_VERT  =   #01            ;    B_SE xor F_UP   and #07 = F_RIGHT
B_HORZ  =   #02            ;    B_SW xor F_UP   and #07 = F_LEFT
B_CROS  =   #03            ;    B_NE xor F_LEFT and #07 = F_UP
B_ESTR  =   #07            ;    ...
B_WSTR  =   #08            ;    ...
B_NSTR  =   #09
B_SSTR  =   #0A

; Key definitions
;    ( 7 )  ->  #1    ( 8 )  ->  #2    ( 9 )  ->  #3    ( / )  ->  #C
;    ( 4 )  ->  #4    ( 5 )  ->  #5    ( 6 )  ->  #6    ( * )  ->  #D
;    ( 1 )  ->  #7    ( 2 )  ->  #8    ( 3 )  ->  #9    ( - )  ->  #E
;    ( 0 )  ->  #A    ( . )  ->  #0    ( _ )  ->  #B    ( + )  ->  #F

K_LEFT  =   #07
K_RIGHT =   #08
K_UP    =   #03
K_DOWN  =   #06
K_FAST  =   #0F
K_PLACE =   #01

TYPERATE =  #90   ; repeat rate for holding down key

; ******************
; START OF CODE AREA
; ******************

            JP    FIRST

COPYRIGHT:  DA    'v1.2 Raines (c) 1991'

FIRST:      DB    #00, #FF            ; turnon extend mode
            LD    VE, #4A             ; starting level
            LD    V0, 0               ; Zero total score
            LD    V1, 0               ;  "        "
            LD    I, TSCORE           ;  "        "
            LD    [I], V1             ;  "        "

; *** SETUP SCREEN, DATA AREA, AND REGISTERS FOR GAME PLAY ***
START:      CLS
            LD    V0, #0B             ; Fill grid array data
            LD    V1, #00             ; area with unfilled
            LD    V2, 0               ; unused grid sites
CLEARGRID:  LD    I, BOXINFO          ;  "        "
            ADD   I, V2               ;  "        "
            LD    [I], V1             ;  "        "
            ADD   V2, 2               ;  "        "
            SE    V2, 120             ;  "        "
            JP    CLEARGRID           ;  "        "
            LD    V0, #00             ; Fill preview array data
            LD    V2, 0               ; area with blank blocks
CLEARPREV:  LD    I, PBOXINFO         ;  "        "
            ADD   I, V2               ;  "        "
            LD    [I], V1             ;  "        "
            ADD   V2, 2               ;  "        "
            SE    V2, 6               ;  "        "
            JP    CLEARPREV           ;  "        "

            LD    I, TITLE            ; Draw title "H. Piper!"
            LD    V0, 38
            LD    V1, 57
            LD    V3, 0
DRAWTITLE:  ADD   I, V3
            DRW   V0, V1, 5
            LD    V3, 5
            ADD   V0, 8
            SE    V0, 70
            JP    DRAWTITLE

            LD    I, HDSCORE          ; Draw score and level heading
            LD    V0, 104
            LD    V1, 2
            DRW   V0, V1, 5
            ADD   V0, 8
            LD    V2, 5
            ADD   I, V2
            DRW   V0, V1, 5
            LD    I, HDLEVEL
            LD    V0, 104
            LD    V1, 42
            DRW   V0, V1, 5
            ADD   V0, 8
            LD    V2, 5
            ADD   I, V2
            DRW   V0, V1, 5

            LD    V1, VE              ; draw needed score
            SHR   V1
            LD    V0, 100
            SUB   V0, V1                 ; determine needed score
            LD    I, TEMP
            LD    B, V0                  ; write BCD of needed score
            LD    V2, [I]                ; read BCD in three parts
            LD    V3, 90
            LD    V4, 57
            LD    F, V1                  ; point to sprite of tens digit
            DRW   V3, V4, 5              ; draw it
            ADD   V3, 5
            LD    F, V2                  ; point to sprite of ones digit
            DRW   V3, V4, 5              ; draw it

            LD    V0, VE              ; store the current level in memory
            LD    I, LEVEL            ;   in case some uses FAST key
            LD    [I], V0

            LD    I, HORZBOX          ; draw top border
            LD    V0, 0
            LD    V1, 0
RDTOP:      DRW   V0, V1, 2
            ADD   V0, 8
            SE    V0, 96
            JP    RDTOP



            LD    V4, 2
RDPRV:      LD    I, PRV1BOX          ; Draw preview boxes grids
            LD    V0, 0
            DRW   V0, V4, 12
            LD    I, PRV2BOX
            LD    V0, 8
            DRW   V0, V4, 12
            ADD   V4, 12
            SE    V4, 62
            JP    RDPRV
            LD    V6, 0

PREVAGAIN:  LD    V0, V6              ; favor corners for first 4 preview boxes
            CALL  NEWPREV             ; randomly get five new
            ADD   V6, 1               ;    preview boxes
            SE    V6, 5
            JP    PREVAGAIN

            LD    V1, 50              ; draw bottom border
            LD    V0, 16
            LD    I, FULLBOX
RDBBDR:     DRW   V0, V1, 6
            ADD   V0, 8
            SE    V0, 96
            JP    RDBBDR

            LD    V1, 0               ; Draw right border
            LD    V0, 96
            LD    I, RBORDER
RDRBDR:     DRW   V0, V1, 2
            ADD   V1, 2
            SE    V1, 56
            JP    RDRBDR

            LD    VD, #34             ; Draw initial paddles
            CALL  DRAWBPADL
            CALL  DRAWSPADL
            CALL  DRAWCRSHR

            LD    V1, 2               ; Draw grid boxes
            LD    I, GRID
RDGRID1:    LD    V0, 16
RDGRID2:    DRW   V0, V1, 8
            ADD   V0, 8
            SE    V0, 96
            JP    RDGRID2
            ADD   V1, 8
            SE    V1, 50
            JP    RDGRID1

            RND   V3, 7               ; Draw random starting box
            ADD   V3, 1
            RND   VC, #30
            ADD   VC, #10
            ADD   VC, V3              ; get random placement
            RND   V3, 3
            SHL   V3
            LD    I, RANDDIR
            ADD   I, V3               ; get random direction of opening
            LD    V1, [I]
            LD    VB, V0              ; starting flow direction
            LD    V2, V1
            LD    V9, V2              ; starting box type
            LD    V0, VC
            CALL  DRAWBOX
            CALL  GETBOXTYPE          ; prevent change of starting box

            LD    VA, 2               ; set starting progression
            LD    V7, 0               ; zero current job score
            LD    V8, 0
            CALL  WRITESCORE
            CALL  WRITELEVEL
            LD    V0, #FF             ; maximum delay of progression
            LD    DT, V0              ;    for beginning of game

; *** MAIN PROCEDURE FOR PLAYING GAME  ***
GAMELOOP:   LD    V0, K_LEFT
            SKNP  V0
            CALL  MOVELEFT          ; move left if K_LEFT key pressed
            LD    V0, K_RIGHT
            SKNP  V0
            CALL  MOVERIGHT         ; move right
            LD    V0, K_UP
            SKNP  V0
            CALL  MOVEUP            ; move up
            LD    V0, K_DOWN
            SKNP  V0
            CALL  MOVEDOWN          ; move down
            LD    V0, K_PLACE
            SKNP  V0
            CALL  PLACEBOX          ; place box
            LD    V0, K_FAST
            SKNP  V0
            LD    VE, #02           ; go fast
            LD    V0, DT
            SNE   V0, 0
            CALL  PROGRESS
            JP    GAMELOOP

; *****************************
; START OF SUBROUTINE CODE AREA
; *****************************

; Places next box on a grid site if allowed and updates preview boxes
; V1 - V5 modified
PLACEBOX:   LD    V0, #F            ; don't favor corners
            CALL  NEWPREV           ; get next box type (V2) and update preview
            LD    V0, VD            ; get pos to draw box
            CALL  DRAWBOX           ; draw box (V2) at desired box coord
            RET

; Takes paddle coord in VD and put x coord in V0, y coord in V1
; V0 := (out) paddle x coord
; V1 := (out) paddle y coord
; VD := bott coord
SPLITPOS:   LD    V0, VD
            LD    V1, #0F
            AND   V0, V1            ; store x part in V0
            LD    V1, VD
            SUB   V1, V0            ; store y part in V1
            RET

; The following 4 subroutines move the crosshair in the desired direction
; V0 := --- (m)
; V1 := --- (m)
; VD := paddle coord
MOVELEFT:   CALL  DRAWBPADL      ;erase old paddle
            CALL  DRAWCRSHR
            CALL  SPLITPOS       ; calculate new pos
            ADD   V0, #FF        ;  "
            SNE   V0, #FF        ;  "
            LD    V0, 0          ;  "
            LD    VD, V1         ; save new pos
            ADD   VD, V0
            CALL  DRAWBPADL      ; draw new position
            CALL  DRAWCRSHR
            LD    V0, TYPERATE
            CALL  PAUSE
            RET

MOVERIGHT:  CALL  DRAWBPADL      ;erase old paddle
            CALL  DRAWCRSHR
            CALL  SPLITPOS       ; calculate new pos
            ADD   V0, #01        ;  "
            SNE   V0, #0A        ;  "
            LD    V0, 9          ;  "
            LD    VD, V1         ; save new pos
            ADD   VD, V0
            CALL  DRAWBPADL      ; draw new position
            CALL  DRAWCRSHR
            LD    V0, TYPERATE
            CALL  PAUSE
;NORIGHT:    LD    V0, K_RIGHT    ; wait till key released
;            SKNP  V0
;            JP    NORIGHT
            RET

MOVEUP:     CALL  DRAWSPADL      ;erase old paddle
            CALL  DRAWCRSHR
            CALL  SPLITPOS       ; calculate new pos
            ADD   V1, #F0        ;  "
            SNE   V1, #F0        ;  "
            LD    V1, 0          ;  "
            LD    VD, V1         ; save new pos
            ADD   VD, V0
            CALL  DRAWSPADL      ; draw new position
            CALL  DRAWCRSHR
            LD    V0, TYPERATE
            CALL  PAUSE
            RET

MOVEDOWN:   CALL  DRAWSPADL      ;erase old paddle
            CALL  DRAWCRSHR
            CALL  SPLITPOS       ; calculate new pos
            ADD   V1, #10        ;  "
            SNE   V1, #60        ;  "
            LD    V1, #50        ;  "
            LD    VD, V1         ; save new pos
            ADD   VD, V0
            CALL  DRAWSPADL      ; draw new position
            CALL  DRAWCRSHR
            LD    V0, TYPERATE
            CALL  PAUSE
            RET

; Draw bottom paddle
; V0 := --- (m)
; V1 := --- (m)
; VD := paddle coord
DRAWBPADL:  CALL  SPLITPOS       ; get paddle position
            ADD   V0, #60
            CALL  BOXTOSCR
            LD    I, BOTTPADL    ; draw it
            DRW   V0, V1, 4
            RET

; Draw side paddle
; V0 := --- (m)
; V1 := --- (m)
; VD := paddle coord
DRAWSPADL:  CALL  SPLITPOS
            LD    V0, V1
            ADD   V0, #0A
            CALL  BOXTOSCR
            LD    I, SIDEPADL
            DRW   V0, V1, 8
            RET

; Draw crosshair
; V0 := --- (m)
; V1 := --- (m)
; VD := paddle coord
DRAWCRSHR:  LD    V0, VD
            CALL  BOXTOSCR
            LD    I, CROSSHAIR
            DRW   V0, V1, 8
            RET

; All purpose pause subroutine
; V0 := (in) time to delay (m)
PAUSE:      ADD   V0, #FF
            SE    V0, 0
            JP    PAUSE
            RET

; Progress flow through current box
; V0 := --- (m)
; V1 := --- (m)
; V2 := --- (m)
; V3 := --- (m)
; V9 := current box type
; VA := box progression so far
; VB := flow direction
; VC := current box pos

PROGRESS:   LD    V0, V9       ; Get box type
            LD    V1, #F0
            AND   V0, V1       ; if box is a corner (type = #1X)
            SNE   V0, 0        ;    then see if need to change direction
            JP    KEEPDIR
            SE    VA, 5        ; if at 5th progression, change direction
            JP    KEEPDIR
            XOR   VB, V9       ; CHECK THIS OUT! Those value assignments
            LD    V0, #07      ;    for box and direction aren't arbitrary
            AND   VB, V0
KEEPDIR:    ADD   VA, 1        ; increment progression
            LD    V2, VA       ; store progression in v2
            SE    VB, 0        ; invert progression if moving up
            JP    NOINVERT     ;     ^- you will see why below (y position)
            LD    V2, 8
            SUB   V2, VA
NOINVERT:   LD    V0, VB       ; store flow direction in v0
            SHR   V0
            SHR   V0
            SE    V0, 0        ; if flowing right left, skip to R_L_PROG
            JP    R_L_PROG
            SE    VB, 0        ; if flowing down, subtract one from progression
            ADD   V2, #FF      ;                     ^- graphical adjustment
            LD    V0, VC       ; copy box coord to v0
            CALL  BOXTOSCR     ; convert to screen coord, v0=x,v1=y
            ADD   V1, V2       ; add progression to y coord for screen pos
            LD    I, VERTMOVE  ; load address of vert moving flow
            DRW   V0, V1, 1    ; draw vert moving flow
            SNE   VF, 0        ; if collision took place
            JP    SKIPIT       ;     check to make sure it
            SNE   VA, 1        ;     was only with crosshair
            JP    ENDGAME      ; else end the game
            JP    SKIPIT       ; end of vertical flow
R_L_PROG:   SE    VB, 5        ; skip to right program if moving right
            JP    RIGHTPRG
            LD    V3, #80      ; start with 10000000 bitmap graphic
LEFTPRG:    SNE   V2, 8        ; iterate over progressions left
            JP    R_L_DRAW
            SHR   V3           ; build proper sprite by shifting 1 digit right
            ADD   V2, 1        ;    for each progression not obtained
            JP    LEFTPRG      ; end of left flow
RIGHTPRG:   LD    V3, #01      ; start with 00000001
RIGHTPRG2:  SNE   V2, 8        ; iterate over progressions left
            JP    R_L_DRAW
            SHL   V3           ; build proper sprite
            ADD   V2, 1
            JP    RIGHTPRG2    ; end of right flow
R_L_DRAW:   LD    V1, V3
            LD    V0, V3
            LD    I, TEMP
            LD    [I], V1      ; store built sprite doubled in memory
            LD    I, TEMP
            LD    V0, VC
            CALL  BOXTOSCR     ; get position of box to progress flow
            ADD   V1, 3
            SE    V9, B_CROS   ; "tunnel under" if a crossbar and on 4,5 progr
            JP    DRAWIT       ;    else draw the progression
            SNE   VA, 4
            JP    NODRAW
            SE    VA, 5
DRAWIT:     DRW   V0, V1, 2    ; write sprite to screen
NODRAW:     SNE   VF, 0        ; if collision took place
            JP    SKIPIT       ;     check to make sure it
            SNE   VA, 1        ;     was only with crosshair
            JP    ENDGAME      ; else end the game
SKIPIT:     SE    VA, 8        ; if at end of progression through box
            JP    ENDPROG
            CALL  WRITESCORE
            LD    V0, 0
SCOREIT:    ADD   V7, 1         ; earn 3 points for each box passed
            SE    V7, 100
            JP    SCOREIT2
            ADD   V8, 1
            LD    V7, 0
SCOREIT2:   ADD   V0, 1
            SE    V0, 3
            JP    SCOREIT
            CALL  WRITESCORE
            LD    VA, 0
            CALL  GETNEXTBOX     ; get next box pos
            CALL  GETBOXTYPE     ; get next box type and prevent change
            SNE   V9, #0B
            JP    ENDGAME
ENDPROG:    LD    V0, VE        ; resest timer for next progress check
            LD    V1, V8
            ADD   V1, V7
            SNE   V1, 0
            ADD   V0, #B4       ; increase timer if only starting
            LD    DT, V0
            RET

; Wait until space key is pressed
; V0 := --- (m)
WAIT:       LD    V0, #B
WAIT2:      SKP   V0            ; wait till press space
            JP    WAIT2
WAIT3:      SKNP  V0
            JP    WAIT3         ; wait till space key released
            RET

; Determine if game ends, tally score, and reset for next screen
; Changes everything
ENDGAME:    LD    V0, #3
            LD    ST, V0        ; BEEP
            CALL  WAIT
            CLS
            LD    V2, 0
            LD    V3, 0
CHECKBONUS: LD    I, BOXINFO    ; iterate through box grid array
            ADD   I, V2         ;    adding together field
            LD    V1, [I]       ;    that has a 1 if flowed through
            ADD   V2, 2
            ADD   V3, V1
            SE    V2, 120
            JP    CHECKBONUS    ; if every box flowed through
            SNE   V3, 60        ;    then give a bonus 100 points
            ADD   V8, 1

            LD    I, TSCORE     ; get old stored total score
            LD    V1, [I]
            ADD   V0, V7        ; add new score to total
            LD    V3, 100
            SUB   V0, V3
            LD    V4, VF
            SE    V4, 0         ; if over 100
            ADD   V1, 1         ;     increment hundereds digit
            SE    V4, 1         ; else
            ADD   V0, 100       ;     put back to normal
            ADD   V1, V8
            LD    I, TSCORE     ; save new total
            LD    [I], V1

            LD    V5, V0        ; store tens & ones digit
            LD    V3, 40        ; x coord to display total
            LD    V4, 40        ; y coord to display total
            LD    I, SCORE      ; STORE BCD
            LD    B, V1         ;     of hundreds score to  memory
            LD    V2, [I]       ; read BCD
            DB    #F0, #30      ; point to sprite of ten thousands digit
            DRW   V3, V4, 10
            ADD   V3, 11
            DB    #F1, #30      ; point to sprite of thousands digit
            DRW   V3, V4, 10
            ADD   V3, 11
            DB    #F2, #30      ; point to sprite of hundreds digit
            DRW   V3, V4, 10
            LD    I, SCORE      ; STORE BCD
            LD    B, V5         ;     of tens & ones score to memory
            LD    V2, [I]       ; read BCD
            ADD   V3, 11
            DB    #F1, #30      ; point to sprite of tens digit
            DRW   V3, V4, 10
            ADD   V3, 11
            DB    #F2, #30      ; point to sprite of ones digit
            DRW   V3, V4, 10

            CALL  WRITESCORE    ; write score of last job in corner
            LD    I, LEVEL
            LD    V0, [I]
            LD    VE, V0        ; get stored level in case FAST used
            SNE   VE, #02       ; don't go beyond level 10
            ADD   VE, #08
            ADD   VE, #F8       ; make level harder

            SE    V8, 0
            JP    GOODSCORE     ; check if score good enough to continue
            SHR   V0            ; need 100 - (41 - 4 * LEVEL) pts
            LD    V1, 100       ;     in order to continue
            SUB   V1, V0        ;     LVL 1 -> 63
            SUB   V7, V1        ;     LVL 2 -> 67
            SNE   VF, 0         ;     LVL 3 -> 71, and so on
            JP    GAMEOVER      ; if not, gameover
GOODSCORE:  CALL  DROPWAIT      ; show the dripping graphic and wait

            JP    START         ; go to next job

GAMEOVER:   LD    I, HDOVER     ; print 'OVER' on screen
            LD    V0, 42
            LD    V1, 24
            DRW   V0, V1, 5
            ADD   V0, 8
            LD    V2, 5
            ADD   I, V2
            DRW   V0, V1, 5
            CALL  DROPWAIT      ; show the dripping graphic and wait
            LD    I, TSCORE     ; get old stored total score
            LD    V1, [I]
            DB    #F1, #75      ; store total score in user flags
            DB    #00, #FD      ; exit game

; Wait with drop graphic
; V0 := --- (m)
; V1 := --- (m)
; V2 := --- (m)
; V3 := --- (m)
; V4 := --- (m)
DROPWAIT:   LD    I, HORZBOX          ; draw faucet type pipe
            LD    V3, 2
            LD    V4, 8
            DRW   V3, V4, 8
            LD    I, SWBOX
            LD    V3, 10
            DRW   V3, V4, 8
            LD    I, DROP             ; draw drop and animate
DROPIT:     LD    V3, 14
            LD    V4, 16
            DRW   V3, V4, 7
DRAWDROP:   LD    V0, #25
            CALL  PAUSE
            LD    V0, #B
            SKNP  V0
            JP    ENDDROP
            DRW   V3, V4, 7
            ADD   V4, 2
            SNE   V4, 56
            JP    DROPIT
            DRW   V3, V4, 7
            JP    DRAWDROP
ENDDROP:    RET

; Get screen coord from box coord
;   V0 := (in) box coord, (out) screen x
;   V1 :=                 (out) screen y
BOXTOSCR:   LD    V1, V0
            LD    VF, #F0
            AND   V1, VF
            SHR   V1           ; get y part of box coord
            LD    VF, #0F
            AND   V0, VF       ; get x part of box coord
            SHL   V0           ; multipy box coords by 8
            SHL   V0
            SHL   V0
            ADD   V0, 16       ; add proper offsets to get screen coord
            ADD   V1, 2
            RET

; Get box coord from screen coord
;   V0 := (in) screen x, (out) box coord
;   V1 := (in) screen y, (m)
SCRTOBOX:   ADD   V0, #F0      ; substr proper offsets
            ADD   V1, #FE
            SHR   V0           ; divide screen coords by 8
            SHR   V0
            SHR   V0
            SHL   V1
            ADD   V0, V1       ; put together into one register
            RET

; Get grid array addr from box coord
;   V0 := (in) box coord  (m)
;   V1 :=                 (m)
;   I  := addr
BOXTOADDR:  LD    I, BOXINFO   ; set address to beginning of box array
            LD    V1, V0
            LD    VF, #0F
            AND   V1, VF
            SHL   V1
            ADD   I, V1        ; add x offset (2 * box x)
            LD    VF, #F0
            AND   V0, VF
            SHR   V0
            LD    V1, V0
            SHR   V1
            SHR   V1
            ADD   V0, V1
            SHL   V0
            ADD   I, V0        ; add y offset (20 * box y)
            RET

; Draws a box on the grid if possible. if not, penalize
;   V0 := box coord (m)
;   V1 :=   ---     (m)
;   V2 := box type  (m)
;   V3 :=   ---     (m)
;   V4 :=   ---     (m)
;   V5 :=   ---     (m)
DRAWBOX:    LD    V3, V0           ; push box coord
            CALL  BOXTOADDR        ; set I to array address
            LD    V1, [I]          ; read in current box
            LD    V5, 0
            SE    V0, #0B          ; if box already placed there,
            LD    V5, #FF          ;     then penalty
            SNE   V1, 00           ; if box full
            JP    DRAWBOX2
            LD    V1, #3           ;   then disallow
            LD    ST, V1           ;   and beep
            JP    SKIPDRAW
DRAWBOX2:   CALL  GETBITADDR       ; get mask addr for current box
            LD    V0, V3           ; pop box coord
            CALL  BOXTOSCR         ; convert to scr coord
            DRW   V0, V1, 8        ; erase current box
            LD    V0, V3           ; pop box coord
            CALL  BOXTOADDR        ; set I to array address
            LD    V1, 0
            LD    V0, V2
            LD    [I], V1          ; write box type to array
            LD    V0, V2
            CALL  GETBITADDR       ; get mask addr for box
            LD    V0, V3           ; pop box coord
            CALL  BOXTOSCR         ; get screen coord
            DRW   V0, V1, 8        ; draw desired box
SKIPDRAW:   CALL  WRITESCORE
            ADD   V7, V5           ; substract penalty
            SE    V7, #FF          ; if V7 was not 0
            JP    NOADJUST         ;     no adjustment needed
            SNE   V8, 0            ; else if V8 is 0
            JP    ZEROOUT          ;          set job score to 0
            ADD   V8, #FF          ;      else substract 100
            LD    V7, 99           ;           and add 99
            JP    NOADJUST
ZEROOUT     LD    V7, 0
NOADJUST:   CALL  WRITESCORE
            RET

; Gets bitmap address for box type
; V0 := box type
; V1 := --- (m)
GETBITADDR: LD    V1, #0F
            AND   V0, V1           ; get offset to mask for box
            SHL   V0
            SHL   V0
            SHL   V0
            LD    I, ZEROBOX       ; set I to mask address
            ADD   I, V0            ; add offset
            RET


; Get box type from storage array and mark it as unchangable
; V0 := (m)
; V1 := (m)
; V9 := (out) box type
; VC := box pos
GETBOXTYPE: LD    V0, VC             ; get array addr from box pos
            CALL  BOXTOADDR
            LD    V1, [I]            ; read boxtype
            LD    V9, V0
            LD    V0, VC
            CALL  BOXTOADDR          ; prevent change of box
            LD    V0, V9
            LD    V1, #01
            LD    [I], V1
            RET

; Get box coord for next box depending on direction from last
; V0 := --- (m)
; V1 := --- (m)
; VB := direction of flow
; VC := (in) curr box coord, (out) next box coord
GETNEXTBOX: LD    V0, #00
            SNE   VB, F_RIGHT
            LD    V0, #01      ; if right, add one to x
            SNE   VB, F_DOWN
            LD    V0, #10      ; if down, add one to y
            SNE   VB, F_UP
            LD    V0, #F0      ; if up, substract 1 from y
            SNE   VB, F_LEFT
            LD    V0, #FF      ; if left, subtract 1 from x
            LD    V1, VC
            ADD   V1, V0       ; adjust
            LD    VF, #F0
            AND   V1, VF
            SNE   V1, #F0      ; if gone off top
            JP    ENDGAME
            SNE   V1, #60      ; if gone off bottom
            JP    ENDGAME
            LD    V1, VC
            ADD   V1, V0
            LD    VF, #0F
            AND   V1, VF
            SNE   V1, #0F      ; if gone off left
            JP    ENDGAME
            SNE   V1, #0A      ; if gone off right
            JP    ENDGAME
            ADD   VC, V0
            RET

; Get a new preview box and update list
; V0 := --- (m)
; V1 := --- (m)
; V2 := --- (m) , (out) box type dropped
; V3 := --- (m)
; V4 := --- (m)
; V5 := --- (m)
NEWPREV:    RND   V1, 7               ; randomly determine new box
            SHR   V0
            SHR   V0
            SNE   V0, 0               ; if favoring corners (V0 = 0,1,2,3)
            SHR   V1                  ;   divide offset by 2
            LD    I, RANDBLK
            ADD   I, V1
            LD    V0, [I]
            LD    V5, V0              ; store new box type in V5
            LD    V4, 3               ; top preview box coord
            LD    V3, 0
NEXTPREV:   LD    I, PBOXINFO         ; shift old box graphics down
            ADD   I, V3
            LD    V0, [I]
            LD    V2, V0
            CALL  GETBITADDR                 ; erase old box graphic
            LD    V0, 4
            DRW   V0, V4, 8
            LD    I, PBOXINFO
            ADD   I, V3
            LD    V0, V5
            LD    [I], V0
            CALL  GETBITADDR                 ; draw new box graphic
            LD    V0, 4
            DRW   V0, V4, 8
            ADD   V4, 12
            LD    V5, V2
            ADD   V3, 1
            SE    V3, 5
            JP    NEXTPREV
            RET

; Write the score to screen
; V0 := --- (m)
; V1 := --- (m)
; V2 := --- (m)
; V3 := --- (m)
; V4 := --- (m)
; V7 := (in) score
WRITESCORE: LD    V3, 105                ; x pos
            LD    V4, 9                  ; y pos
            LD    I, SCORE               ; write BCD
            LD    B, V8                  ;     of hundred score to memory
            LD    V2, [I]                ; read BCD
            LD    F, V2                  ; point to sprite of hundreds digit
            DRW   V3, V4, 5
            ADD   V3, 6
            LD    I, SCORE               ; write BCD
            LD    B, V7                  ;     of tens and ones score to memory
            LD    V2, [I]                ; read BCD
            LD    F, V1                  ; point to sprite of tens digit
            DRW   V3, V4, 5
            ADD   V3, 6
            LD    F, V2                  ; point to sprite of ones digit
            DRW   V3, V4, 5
            RET

; Write the level to screen
; V0 := --- (m)
; V1 := --- (m)
; V2 := --- (m)
; V3 := --- (m)
; V4 := --- (m)
; VE := (in) level
WRITELEVEL: LD    V0, VE                 ; convert speed to game level
            ADD   V0, #FE
            SHR   V0
            SHR   V0
            SHR   V0
            LD    V1, #0A
            SUB   V1, V0
            LD    I, SCORE               ; write BCD
            LD    B, V1                  ;     of level to memory
            LD    V2, [I]                ; read BCD
            DB    #F1, #30               ; point to sprite of tens digit
            LD    V3, 104
            LD    V4, 50
            DRW   V3, V4, 10
            ADD   V3, 11
            DB    #F2, #30               ; point to sprite of ones digit
            DRW   V3, V4, 10
            RET

; ******************
; START OF DATA AREA
; ******************

RBORDER:    DW    #F8F8

PRV1BOX:    DW    #C0C0, #C0C0, #C0C0, #C0C0, #C0C0, #C0FF

PRV2BOX:    DW    #0303, #0303, #0303, #0303, #0303, #03FF

LEVEL:      DW    #0000

ZEROBOX:    DW    #0000, #0000, #0000, #0000   ;0  blank box

VERTBOX:    DW    #C3C3, #C3C3, #C3C3, #C3C3   ;1  vertical pipe

HORZBOX:    DW    #FFFF, #0000, #0000, #FFFF   ;2  horizontal pipe

CROSBOX:    DW    #C3C3, #0000, #0000, #C3C3   ;3  crossing pipes

FULLBOX:    DW    #FFFF, #FFFF, #FFFF, #FFFF   ;4  full box

SWBOX:      DW    #FFFF, #0303, #0303, #C3C3   ;5  south to west pipe

SEBOX:      DW    #FFFF, #C0C0, #C0C0, #C3C3   ;6  south to east pipe

ESTRBOX:    DW    #FFFF, #C0C0, #C0C0, #FFFF   ;7  east open start pipe

WSTRBOX:    DW    #FFFF, #0303, #0303, #FFFF   ;8  west open start pipe

NSTRBOX:    DW    #C3C3, #C3C3, #C3C3, #FFFF   ;9  north open start pipe

SSTRBOX:    DW    #FFFF, #C3C3, #C3C3, #C3C3   ;A  south open start pipe

GRID:       DW    #007E, #4242, #4242, #7E00   ;11 (B) empty grid site

TEMP:       DW    #0000, #0000, #0000, #0000   ;12 (C) temp memory area

NEBOX:      DW    #C3C3, #C0C0, #C0C0, #FFFF   ;13 (D) north to east pipe

NWBOX:      DW    #C3C3, #0303, #0303, #FFFF   ;14 (E) north to west pipe

CROSSHAIR:  DW    #0000, #183C, #3C18, #0000   ;15 (F)

SIDEPADL:   DW    #0010, #1070, #7010, #1000

BOTTPADL:   DW    #0018, #187E

VERTMOVE:   DW    #1800                        ; bitmap of vertical flow

RANDBLK:    DW    #1D15, #161E, #0102, #0303   ; used for random block select

RANDDIR:    DW    #0607, #0508, #0009, #030A   ; used for random direction

PBOXINFO:   DW    #0000, #0000, #0000          ; preview box info

SCORE:      DW    #0000, #0000                 ; total score storage
TSCORE:     DW    #0000, #0000                 ; temp score area

TITLE:      DW    #A3A2, #E3A2, #AABB, #9293, #123A
TITLE2:     DW    #BBA2, #B322, #3A88, #8888, #4048
HDSCORE:    DW    #D992, #D252, #D93B, #AAB3, #AA2B
HDLEVEL:    DW    #9A92, #9A91, #D9B4, #A4B4, #2436
HDOVER:     DW    #EAAA, #AEA4, #E4EE, #8ACE, #89E9
DROP:       DW    #2020, #70F8, #F8F8, #7000

BOXINFO:    DW    #0B00, #0B00, #0B00, #0B00, #0B00  ; 60x2 array for
X1:         DW    #0B00, #0B00, #0B00, #0B00, #0B00  ; storage of grid
X2:         DW    #0B00, #0B00, #0B00, #0B00, #0B00  ; placements and
X3:         DW    #0B00, #0B00, #0B00, #0B00, #0B00  ; flow control
X4:         DW    #0B00, #0B00, #0B00, #0B00, #0B00
X5:         DW    #0B00, #0B00, #0B00, #0B00, #0B00
X6:         DW    #0B00, #0B00, #0B00, #0B00, #0B00
X7:         DW    #0B00, #0B00, #0B00, #0B00, #0B00
X8:         DW    #0B00, #0B00, #0B00, #0B00, #0B00
X9:         DW    #0B00, #0B00, #0B00, #0B00, #0B00
X10:        DW    #0B00, #0B00, #0B00, #0B00, #0B00
X11:        DW    #0B00, #0B00, #0B00, #0B00, #0B00
------( end of source code)--------------------------
-- 
Paul Raines
Georgia Institute of Technology, Atlanta Georgia, 30332
uucp:	  ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!vapsppr
Internet: vapsppr@prism.gatech.edu

S088960@UMRVMA.UMR.EDU (05/24/91)

Sorry, wrong title.

I am having a big problem with superchip.  I cannot get asc to convert
the file into a lib.  I have used asc on other program, including
the older version of chip.

If Anyone has a copy of Schip that they know will work, please send it to
me.  I would greatly appreciate it.