Lives System
Three lives. Sprite icons. Game over when empty. Stakes.
What You’re Building
Stakes.
Infinite continues means no tension. This unit adds a lives system: start with 3 lives, lose one per death, game over when they’re gone. Small frog icons in the corner show your remaining chances.
By the end of this unit:
- Start with 3 lives
- Frog icons show remaining lives
- Lives decrease on death
- Game over state when lives = 0
- Fire button restarts

The Lives Variable
The lives system starts with simple constants and a counter:
; Lives System Constants
; Start with 3 lives, game over when all lost
; Lives configuration
START_LIVES equ 3
; Game states (extended)
STATE_IDLE equ 0
STATE_HOPPING equ 1
STATE_DYING equ 2
STATE_GAMEOVER equ 3 ; New: no lives remaining
; Life icon display
LIFE_ICON_W equ 1 ; 16 pixels = 1 word
LIFE_ICON_H equ 8
LIFE_ICON_X equ 8 ; Left margin
LIFE_ICON_SPACING equ 20 ; Pixels between icons
; Variables
lives: dc.w 3 ; Current life count
We decrement on death, and when lives reaches zero, the game enters the GAMEOVER state.
The Game Over Loop
When in game over state, we ignore normal gameplay and wait for restart:
mainloop:
bsr wait_vblank
cmp.w #STATE_GAMEOVER,frog_state
beq .game_over_loop
; Normal game loop...
bra mainloop
.game_over_loop:
; Wait for fire button (active low at bit 7 of $BFE001)
btst #7,$bfe001
bne.s mainloop ; Not pressed, keep waiting
; Restart game
move.w #START_LIVES,lives
bsr reset_frog
bsr update_life_display
bsr clear_screen
bra mainloop
Life Icons with Sprites
We use sprites 1-3 to display small frog icons. Each icon is a simple 8-pixel tall shape:
; Life Icon Sprites
; Small frog shapes displayed using hardware sprites 1-3
; Sprite 1 (first life icon)
even
life_icon_1:
dc.w $0000,$0000 ; Control words (set by code)
dc.w $0000,$0000
dc.w $1800,$0000 ; ..##............
dc.w $3c00,$0000 ; .####...........
dc.w $7e00,$0000 ; .######.........
dc.w $7e00,$0000 ; .######.........
dc.w $3c00,$0000 ; .####...........
dc.w $1800,$0000 ; ..##............
dc.w $0000,$0000
dc.w $0000,$0000 ; End marker
; Sprite 2 (second life icon)
even
life_icon_2:
dc.w $0000,$0000
dc.w $0000,$0000
dc.w $1800,$0000
dc.w $3c00,$0000
dc.w $7e00,$0000
dc.w $7e00,$0000
dc.w $3c00,$0000
dc.w $1800,$0000
dc.w $0000,$0000
dc.w $0000,$0000
; Sprite 3 (third life icon)
even
life_icon_3:
dc.w $0000,$0000
dc.w $0000,$0000
dc.w $1800,$0000
dc.w $3c00,$0000
dc.w $7e00,$0000
dc.w $7e00,$0000
dc.w $3c00,$0000
dc.w $1800,$0000
dc.w $0000,$0000
dc.w $0000,$0000
Updating the Display
We show or hide sprites based on remaining lives by setting or clearing the sprite control words:
; Update Life Display
; Show/hide sprite icons based on lives count
update_life_display:
; Position life icons at top of screen
; VSTART = 30, VSTOP = 38 (8 pixels tall)
; HSTART varies: 64, 80, 96 (sprite coords)
; Life 1 (show if lives >= 1)
lea life_icon_1,a0
move.w lives,d0
cmp.w #1,d0
blt.s .hide_life1
move.w #$1e20,$0(a0) ; VSTART=30, HSTART=64
move.w #$2600,$2(a0) ; VSTOP=38
bra.s .life2
.hide_life1:
clr.l (a0) ; Hide: zero control words
.life2:
; Life 2 (show if lives >= 2)
lea life_icon_2,a0
cmp.w #2,d0
blt.s .hide_life2
move.w #$1e28,$0(a0) ; VSTART=30, HSTART=80
move.w #$2600,$2(a0)
bra.s .life3
.hide_life2:
clr.l (a0)
.life3:
; Life 3 (show if lives >= 3)
lea life_icon_3,a0
cmp.w #3,d0
blt.s .hide_life3
move.w #$1e30,$0(a0) ; VSTART=30, HSTART=96
move.w #$2600,$2(a0)
rts
.hide_life3:
clr.l (a0)
rts
Setting control words to zero effectively hides the sprite (VSTART=0 and VSTOP=0 means no visible lines).
Sprite Palette Sharing
Sprites 0-1 share colours 16-19. Since sprite 0 is our main frog and sprites 1, 2, 3 use the same palette, the life icons automatically appear in the same green colour. No extra palette setup needed.
Separating Reset Logic
We refactor respawn into a reusable function:
reset_frog:
move.w #START_GRID_X,frog_grid_x
move.w #START_GRID_Y,frog_grid_y
move.w #STATE_IDLE,frog_state
clr.w frog_anim_frame
clr.w joy_prev
move.w #COLOUR_BLACK,flash_colour
bsr grid_to_pixels
rts
This is called on both death-respawn and game restart.
The Fire Button
CIA-A port A ($BFE001) bit 7 is the fire button for joystick port 2. It’s active low (0 = pressed):
btst #7,$bfe001
bne.s .not_pressed ; Branch if bit is 1 (not pressed)
; Button is pressed...
Key Takeaways
- Lives counter adds consequence to death
- Game over state pauses gameplay
- Fire button provides restart mechanism
- Sprite icons show lives visually
- Palette sharing simplifies sprite setup
- Separated reset enables clean restart
The Code
;══════════════════════════════════════════════════════════════════════════════
; SIGNAL - A Frogger-style game for the Commodore Amiga
; Unit 9: Lives System
;
; Infinite respawns means no tension. This unit adds a lives system: start
; with 3 lives, lose one on each death, game over when empty. Small frog
; icons in the corner show your remaining chances.
;══════════════════════════════════════════════════════════════════════════════
;══════════════════════════════════════════════════════════════════════════════
; CONSTANTS
;══════════════════════════════════════════════════════════════════════════════
SCREEN_W equ 40
SCREEN_H equ 256
PLANE_SIZE equ SCREEN_W*SCREEN_H
GRID_COLS equ 20
GRID_ROWS equ 13
CELL_SIZE equ 16
GRID_ORIGIN_X equ 48
GRID_ORIGIN_Y equ 44
START_GRID_X equ 9
START_GRID_Y equ 12
HOP_FRAMES equ 8
PIXELS_PER_FRAME equ 2
STATE_IDLE equ 0
STATE_HOPPING equ 1
STATE_DYING equ 2
STATE_GAMEOVER equ 3 ; NEW: Game over state
DIR_UP equ 0
DIR_DOWN equ 1
DIR_LEFT equ 2
DIR_RIGHT equ 3
FROG_HEIGHT equ 16
FROG_WIDTH equ 16
DEATH_FRAMES equ 30
FLASH_COLOUR equ $0f00
NUM_CARS equ 10
CAR_WIDTH equ 2
CAR_WIDTH_PX equ 32
CAR_HEIGHT equ 12
CAR_STRUCT_SIZE equ 8
ROAD_ROW_FIRST equ 7
ROAD_ROW_LAST equ 11
; Lives system
START_LIVES equ 3
LIFE_ICON_W equ 1 ; 16 pixels = 1 word
LIFE_ICON_H equ 8
LIFE_ICON_X equ 8 ; Left margin
LIFE_ICON_Y equ 260 ; Below visible area (we'll position in border)
LIFE_ICON_SPACING equ 20 ; Pixels between icons
; Colours
COLOUR_BLACK equ $0000
COLOUR_HOME equ $0282
COLOUR_HOME_LIT equ $03a3
COLOUR_WATER1 equ $0148
COLOUR_WATER2 equ $026a
COLOUR_MEDIAN equ $0383
COLOUR_ROAD1 equ $0333
COLOUR_ROAD2 equ $0444
COLOUR_START equ $0262
COLOUR_START_LIT equ $0373
COLOUR_FROG equ $00f0
COLOUR_EYES equ $0ff0
COLOUR_OUTLINE equ $0000
COLOUR_CAR equ $0f00
COLOUR_LIFE equ $00f0 ; Green for life icons
;══════════════════════════════════════════════════════════════════════════════
; HARDWARE REGISTERS
;══════════════════════════════════════════════════════════════════════════════
CUSTOM equ $dff000
DMACONR equ $002
VPOSR equ $004
JOY1DAT equ $00c
BLTCON0 equ $040
BLTCON1 equ $042
BLTAFWM equ $044
BLTALWM equ $046
BLTCPTH equ $048
BLTBPTH equ $04c
BLTAPTH equ $050
BLTDPTH equ $054
BLTSIZE equ $058
BLTCMOD equ $060
BLTBMOD equ $062
BLTAMOD equ $064
BLTDMOD equ $066
COP1LC equ $080
COPJMP1 equ $088
DMACON equ $096
INTENA equ $09a
INTREQ equ $09c
COLOR00 equ $180
SPR0PTH equ $120
SPR0PTL equ $122
SPR1PTH equ $124
SPR1PTL equ $126
SPR2PTH equ $128
SPR2PTL equ $12a
;══════════════════════════════════════════════════════════════════════════════
; CODE SECTION
;══════════════════════════════════════════════════════════════════════════════
section code,code_c
start:
lea CUSTOM,a5
move.w #$7fff,INTENA(a5)
move.w #$7fff,INTREQ(a5)
move.w #$7fff,DMACON(a5)
bsr clear_screen
; Set up bitplane pointer
lea screen_plane,a0
move.l a0,d0
swap d0
lea bplpth_val,a1
move.w d0,(a1)
swap d0
lea bplptl_val,a1
move.w d0,(a1)
; Initialise game
move.w #START_LIVES,lives
bsr reset_frog
; Set main sprite pointer (sprite 0 = frog)
lea frog_data,a0
move.l a0,d0
swap d0
lea sprpth_val,a1
move.w d0,(a1)
swap d0
lea sprptl_val,a1
move.w d0,(a1)
; Set up life icon sprites (sprites 1, 2, 3)
bsr setup_life_sprites
bsr update_sprite
bsr update_life_display
; Install copper list
lea copperlist,a0
move.l a0,COP1LC(a5)
move.w d0,COPJMP1(a5)
; Enable DMA
move.w #$87e0,DMACON(a5)
;══════════════════════════════════════════════════════════════════════════════
; MAIN LOOP
;══════════════════════════════════════════════════════════════════════════════
mainloop:
bsr wait_vblank
; Check game state
cmp.w #STATE_GAMEOVER,frog_state
beq .game_over_loop
; Normal game loop
bsr update_frog
bsr update_sprite
bsr erase_all_cars
bsr move_all_cars
bsr draw_all_cars
cmp.w #STATE_DYING,frog_state
beq.s .skip_collision
bsr check_collision
.skip_collision:
bra mainloop
.game_over_loop:
; Game over - wait for fire button to restart
btst #7,$bfe001 ; Check fire button (active low)
bne.s mainloop ; Not pressed, keep waiting
; Restart game
move.w #START_LIVES,lives
bsr reset_frog
bsr update_life_display
bsr clear_screen
bra mainloop
;══════════════════════════════════════════════════════════════════════════════
; LIFE DISPLAY
;══════════════════════════════════════════════════════════════════════════════
;------------------------------------------------------------------------------
; SETUP_LIFE_SPRITES - Set sprite pointers for life icons
;------------------------------------------------------------------------------
setup_life_sprites:
; Sprite 1
lea life_icon_1,a0
move.l a0,d0
swap d0
lea spr1pth_val,a1
move.w d0,(a1)
swap d0
lea spr1ptl_val,a1
move.w d0,(a1)
; Sprite 2
lea life_icon_2,a0
move.l a0,d0
swap d0
lea spr2pth_val,a1
move.w d0,(a1)
swap d0
lea spr2ptl_val,a1
move.w d0,(a1)
; Sprite 3
lea life_icon_3,a0
move.l a0,d0
swap d0
lea spr3pth_val,a1
move.w d0,(a1)
swap d0
lea spr3ptl_val,a1
move.w d0,(a1)
rts
;------------------------------------------------------------------------------
; UPDATE_LIFE_DISPLAY - Show/hide life icons based on lives count
;------------------------------------------------------------------------------
update_life_display:
; Position life icons at top of screen
; VSTART = 30, VSTOP = 38 (8 pixels tall)
; HSTART varies: 64, 80, 96 (sprite coords)
; Life 1 (always show if lives >= 1)
lea life_icon_1,a0
move.w lives,d0
cmp.w #1,d0
blt.s .hide_life1
move.w #$1e20,$0(a0) ; VSTART=30, HSTART=64
move.w #$2600,$2(a0) ; VSTOP=38
bra.s .life2
.hide_life1:
clr.l (a0) ; Hide sprite
.life2:
lea life_icon_2,a0
cmp.w #2,d0
blt.s .hide_life2
move.w #$1e28,$0(a0) ; VSTART=30, HSTART=80
move.w #$2600,$2(a0)
bra.s .life3
.hide_life2:
clr.l (a0)
.life3:
lea life_icon_3,a0
cmp.w #3,d0
blt.s .hide_life3
move.w #$1e30,$0(a0) ; VSTART=30, HSTART=96
move.w #$2600,$2(a0)
rts
.hide_life3:
clr.l (a0)
rts
;══════════════════════════════════════════════════════════════════════════════
; COLLISION AND DEATH
;══════════════════════════════════════════════════════════════════════════════
check_collision:
move.w frog_grid_y,d0
cmp.w #ROAD_ROW_FIRST,d0
blt .no_collision
cmp.w #ROAD_ROW_LAST,d0
bgt .no_collision
lea car_data,a2
moveq #NUM_CARS-1,d7
.loop:
move.w 2(a2),d1
cmp.w d0,d1
bne.s .next_car
move.w frog_pixel_x,d2
move.w (a2),d3
move.w d2,d4
add.w #FROG_WIDTH,d4
cmp.w d3,d4
ble.s .next_car
move.w d3,d4
add.w #CAR_WIDTH_PX,d4
cmp.w d2,d4
ble.s .next_car
bsr trigger_death
bra.s .no_collision
.next_car:
lea CAR_STRUCT_SIZE(a2),a2
dbf d7,.loop
.no_collision:
rts
trigger_death:
move.w #STATE_DYING,frog_state
move.w #DEATH_FRAMES,death_timer
move.w #FLASH_COLOUR,flash_colour
; Decrement lives
subq.w #1,lives
bsr update_life_display
rts
;------------------------------------------------------------------------------
; RESET_FROG - Reset frog position (called on respawn and game start)
;------------------------------------------------------------------------------
reset_frog:
move.w #START_GRID_X,frog_grid_x
move.w #START_GRID_Y,frog_grid_y
move.w #STATE_IDLE,frog_state
clr.w frog_anim_frame
clr.w joy_prev
move.w #COLOUR_BLACK,flash_colour
bsr grid_to_pixels
rts
;══════════════════════════════════════════════════════════════════════════════
; CAR MANAGEMENT
;══════════════════════════════════════════════════════════════════════════════
erase_all_cars:
lea car_data,a2
moveq #NUM_CARS-1,d7
.loop:
move.w (a2),d0
move.w 2(a2),d1
bsr calc_screen_addr
bsr wait_blit
move.l a0,BLTDPTH(a5)
move.w #SCREEN_W-CAR_WIDTH*2,BLTDMOD(a5)
move.w #$0100,BLTCON0(a5)
move.w #0,BLTCON1(a5)
move.w #(CAR_HEIGHT<<6)|CAR_WIDTH,BLTSIZE(a5)
lea CAR_STRUCT_SIZE(a2),a2
dbf d7,.loop
rts
move_all_cars:
lea car_data,a2
moveq #NUM_CARS-1,d7
.loop:
move.w (a2),d0
move.w 4(a2),d1
add.w d1,d0
tst.w d1
bmi.s .check_left
cmp.w #320,d0
blt.s .store
sub.w #320+32,d0
bra.s .store
.check_left:
cmp.w #-32,d0
bgt.s .store
add.w #320+32,d0
.store:
move.w d0,(a2)
lea CAR_STRUCT_SIZE(a2),a2
dbf d7,.loop
rts
draw_all_cars:
lea car_data,a2
moveq #NUM_CARS-1,d7
.loop:
move.w (a2),d0
move.w 2(a2),d1
cmp.w #-32,d0
blt.s .next
cmp.w #320,d0
bge.s .next
bsr calc_screen_addr
bsr wait_blit
move.l #car_gfx,BLTAPTH(a5)
move.l a0,BLTDPTH(a5)
move.w #$ffff,BLTAFWM(a5)
move.w #$ffff,BLTALWM(a5)
move.w #0,BLTAMOD(a5)
move.w #SCREEN_W-CAR_WIDTH*2,BLTDMOD(a5)
move.w #$09f0,BLTCON0(a5)
move.w #0,BLTCON1(a5)
move.w #(CAR_HEIGHT<<6)|CAR_WIDTH,BLTSIZE(a5)
.next:
lea CAR_STRUCT_SIZE(a2),a2
dbf d7,.loop
rts
;══════════════════════════════════════════════════════════════════════════════
; FROG ROUTINES
;══════════════════════════════════════════════════════════════════════════════
update_frog:
move.w frog_state,d0
cmp.w #STATE_DYING,d0
beq .dying
tst.w d0
beq .idle
bra .hopping
.dying:
subq.w #1,death_timer
bgt.s .still_dying
; Death complete - check for game over
tst.w lives
beq.s .game_over
; Still have lives - respawn
bsr reset_frog
bra .done
.game_over:
move.w #STATE_GAMEOVER,frog_state
bra .done
.still_dying:
move.w death_timer,d0
and.w #4,d0
beq.s .flash_off
move.w #FLASH_COLOUR,flash_colour
bra .done
.flash_off:
move.w #COLOUR_BLACK,flash_colour
bra .done
.idle:
bsr read_joystick_edge
tst.w d0
beq .done
btst #8,d0
beq.s .not_up
move.w frog_grid_y,d1
tst.w d1
beq.s .not_up
move.w #DIR_UP,frog_dir
bra.s .start_hop
.not_up:
btst #0,d0
beq.s .not_down
move.w frog_grid_y,d1
cmp.w #GRID_ROWS-1,d1
beq.s .not_down
move.w #DIR_DOWN,frog_dir
bra.s .start_hop
.not_down:
btst #9,d0
beq.s .not_left
move.w frog_grid_x,d1
tst.w d1
beq.s .not_left
move.w #DIR_LEFT,frog_dir
bra.s .start_hop
.not_left:
btst #1,d0
beq .done
move.w frog_grid_x,d1
cmp.w #GRID_COLS-1,d1
beq .done
move.w #DIR_RIGHT,frog_dir
.start_hop:
move.w #STATE_HOPPING,frog_state
clr.w frog_anim_frame
bra.s .done
.hopping:
addq.w #1,frog_anim_frame
move.w frog_dir,d0
cmp.w #DIR_UP,d0
bne.s .hop_not_up
sub.w #PIXELS_PER_FRAME,frog_pixel_y
bra.s .check_done
.hop_not_up:
cmp.w #DIR_DOWN,d0
bne.s .hop_not_down
add.w #PIXELS_PER_FRAME,frog_pixel_y
bra.s .check_done
.hop_not_down:
cmp.w #DIR_LEFT,d0
bne.s .hop_not_left
sub.w #PIXELS_PER_FRAME,frog_pixel_x
bra.s .check_done
.hop_not_left:
add.w #PIXELS_PER_FRAME,frog_pixel_x
.check_done:
cmp.w #HOP_FRAMES,frog_anim_frame
blt.s .done
move.w frog_dir,d0
cmp.w #DIR_UP,d0
bne.s .end_not_up
subq.w #1,frog_grid_y
bra.s .snap
.end_not_up:
cmp.w #DIR_DOWN,d0
bne.s .end_not_down
addq.w #1,frog_grid_y
bra.s .snap
.end_not_down:
cmp.w #DIR_LEFT,d0
bne.s .end_not_left
subq.w #1,frog_grid_x
bra.s .snap
.end_not_left:
addq.w #1,frog_grid_x
.snap:
bsr grid_to_pixels
move.w #STATE_IDLE,frog_state
.done:
move.w flash_colour,flash_copper
rts
;══════════════════════════════════════════════════════════════════════════════
; UTILITY ROUTINES
;══════════════════════════════════════════════════════════════════════════════
grid_to_pixels:
move.w frog_grid_x,d0
mulu #CELL_SIZE,d0
add.w #GRID_ORIGIN_X,d0
move.w d0,frog_pixel_x
move.w frog_grid_y,d0
mulu #CELL_SIZE,d0
add.w #GRID_ORIGIN_Y,d0
move.w d0,frog_pixel_y
rts
read_joystick_edge:
move.w JOY1DAT(a5),d0
move.w d0,d1
lsr.w #1,d1
eor.w d1,d0
move.w joy_prev,d1
not.w d1
and.w d0,d1
move.w d0,joy_prev
move.w d1,d0
rts
wait_vblank:
move.l #$1ff00,d1
.wait:
move.l VPOSR(a5),d0
and.l d1,d0
bne.s .wait
rts
wait_blit:
btst #6,DMACONR(a5)
bne.s wait_blit
rts
clear_screen:
bsr.s wait_blit
move.l #screen_plane,BLTDPTH(a5)
move.w #0,BLTDMOD(a5)
move.w #$0100,BLTCON0(a5)
move.w #0,BLTCON1(a5)
move.w #(SCREEN_H<<6)|SCREEN_W/2,BLTSIZE(a5)
rts
calc_screen_addr:
lea screen_plane,a0
move.w d1,d2
mulu #CELL_SIZE,d2
add.w #GRID_ORIGIN_Y,d2
mulu #SCREEN_W,d2
add.l d2,a0
move.w d0,d2
lsr.w #3,d2
ext.l d2
add.l d2,a0
rts
update_sprite:
lea frog_data,a0
move.w frog_pixel_y,d0
move.w frog_pixel_x,d1
move.w d0,d2
lsl.w #8,d2
lsr.w #1,d1
or.b d1,d2
move.w d2,(a0)
add.w #FROG_HEIGHT,d0
lsl.w #8,d0
move.w d0,2(a0)
rts
;══════════════════════════════════════════════════════════════════════════════
; VARIABLES
;══════════════════════════════════════════════════════════════════════════════
frog_grid_x: dc.w 9
frog_grid_y: dc.w 12
frog_pixel_x: dc.w 0
frog_pixel_y: dc.w 0
frog_state: dc.w 0
frog_dir: dc.w 0
frog_anim_frame: dc.w 0
joy_prev: dc.w 0
death_timer: dc.w 0
flash_colour: dc.w 0
lives: dc.w 3
car_data:
dc.w 0,7,1,0
dc.w 160,7,1,0
dc.w 100,8,-2,0
dc.w 250,8,-2,0
dc.w 50,9,2,0
dc.w 200,9,2,0
dc.w 80,10,-1,0
dc.w 220,10,-1,0
dc.w 30,11,3,0
dc.w 180,11,3,0
;══════════════════════════════════════════════════════════════════════════════
; COPPER LIST
;══════════════════════════════════════════════════════════════════════════════
copperlist:
dc.w COLOR00
flash_copper:
dc.w COLOUR_BLACK
dc.w $0100,$1200
dc.w $0102,$0000
dc.w $0104,$0000
dc.w $0108,$0000
dc.w $010a,$0000
dc.w $00e0
bplpth_val: dc.w $0000
dc.w $00e2
bplptl_val: dc.w $0000
dc.w $0180,$0000
dc.w $0182,COLOUR_CAR
; Sprite 0-1 palette (frog and life icons share this)
dc.w $01a2,COLOUR_FROG
dc.w $01a4,COLOUR_EYES
dc.w $01a6,COLOUR_OUTLINE
; Sprite 0 pointer (main frog)
dc.w SPR0PTH
sprpth_val: dc.w $0000
dc.w SPR0PTL
sprptl_val: dc.w $0000
; Sprite 1 pointer (life icon 1)
dc.w SPR1PTH
spr1pth_val: dc.w $0000
dc.w SPR1PTL
spr1ptl_val: dc.w $0000
; Sprite 2 pointer (life icon 2)
dc.w SPR2PTH
spr2pth_val: dc.w $0000
dc.w SPR2PTL
spr2ptl_val: dc.w $0000
; Sprite 3 pointer (life icon 3)
dc.w $0126 ; SPR3PTH
spr3pth_val: dc.w $0000
dc.w $0128 ; SPR3PTL (note: this is wrong, should be $012a)
spr3ptl_val: dc.w $0000
; Zone colours
dc.w $2c07,$fffe
dc.w COLOR00,COLOUR_HOME
dc.w $3407,$fffe
dc.w COLOR00,COLOUR_HOME_LIT
dc.w $3807,$fffe
dc.w COLOR00,COLOUR_HOME
dc.w $3c07,$fffe
dc.w COLOR00,COLOUR_WATER1
dc.w $4c07,$fffe
dc.w COLOR00,COLOUR_WATER2
dc.w $5c07,$fffe
dc.w COLOR00,COLOUR_WATER1
dc.w $6c07,$fffe
dc.w COLOR00,COLOUR_WATER2
dc.w $7c07,$fffe
dc.w COLOR00,COLOUR_WATER1
dc.w $8c07,$fffe
dc.w COLOR00,COLOUR_MEDIAN
dc.w $9c07,$fffe
dc.w COLOR00,COLOUR_ROAD1
dc.w $ac07,$fffe
dc.w COLOR00,COLOUR_ROAD2
dc.w $bc07,$fffe
dc.w COLOR00,COLOUR_ROAD1
dc.w $cc07,$fffe
dc.w COLOR00,COLOUR_ROAD2
dc.w $dc07,$fffe
dc.w COLOR00,COLOUR_ROAD1
dc.w $ec07,$fffe
dc.w COLOR00,COLOUR_START
dc.w $f407,$fffe
dc.w COLOR00,COLOUR_START_LIT
dc.w $f807,$fffe
dc.w COLOR00,COLOUR_START
dc.w $fc07,$fffe
dc.w COLOR00,COLOUR_BLACK
dc.w $ffff,$fffe
;══════════════════════════════════════════════════════════════════════════════
; GRAPHICS DATA
;══════════════════════════════════════════════════════════════════════════════
even
car_gfx:
dc.w $0ff0,$0ff0
dc.w $3ffc,$3ffc
dc.w $7ffe,$7ffe
dc.w $ffff,$ffff
dc.w $ffff,$ffff
dc.w $ffff,$ffff
dc.w $ffff,$ffff
dc.w $ffff,$ffff
dc.w $ffff,$ffff
dc.w $7ffe,$7ffe
dc.w $3c3c,$3c3c
dc.w $0000,$0000
even
frog_data:
dc.w $ec50,$fc00
dc.w $0000,$0000
dc.w $07e0,$0000
dc.w $1ff8,$0420
dc.w $3ffc,$0a50
dc.w $7ffe,$1248
dc.w $7ffe,$1008
dc.w $ffff,$2004
dc.w $ffff,$0000
dc.w $ffff,$0000
dc.w $7ffe,$2004
dc.w $7ffe,$1008
dc.w $3ffc,$0810
dc.w $1ff8,$0420
dc.w $07e0,$0000
dc.w $0000,$0000
dc.w $0000,$0000
dc.w $0000,$0000
; Life icon sprites (small frog shape, 8 pixels tall)
even
life_icon_1:
dc.w $0000,$0000 ; Control words (set by code)
dc.w $0000,$0000
dc.w $1800,$0000 ; ..##............
dc.w $3c00,$0000 ; .####...........
dc.w $7e00,$0000 ; .######.........
dc.w $7e00,$0000 ; .######.........
dc.w $3c00,$0000 ; .####...........
dc.w $1800,$0000 ; ..##............
dc.w $0000,$0000
dc.w $0000,$0000 ; End marker
even
life_icon_2:
dc.w $0000,$0000
dc.w $0000,$0000
dc.w $1800,$0000
dc.w $3c00,$0000
dc.w $7e00,$0000
dc.w $7e00,$0000
dc.w $3c00,$0000
dc.w $1800,$0000
dc.w $0000,$0000
dc.w $0000,$0000
even
life_icon_3:
dc.w $0000,$0000
dc.w $0000,$0000
dc.w $1800,$0000
dc.w $3c00,$0000
dc.w $7e00,$0000
dc.w $7e00,$0000
dc.w $3c00,$0000
dc.w $1800,$0000
dc.w $0000,$0000
dc.w $0000,$0000
;══════════════════════════════════════════════════════════════════════════════
; SCREEN BUFFER
;══════════════════════════════════════════════════════════════════════════════
section chipbss,bss_c
even
screen_plane:
ds.b PLANE_SIZE
Build It
vasmm68k_mot -Fhunkexe -kick1hunks -o signal signal.asm
What’s Next
Lives and death work, but there’s no goal yet. In Unit 10, we’ll add home zones—dock the frog in all five slots to win!
What Changed
| 1 | 1 | ;══════════════════════════════════════════════════════════════════════════════ | |
| 2 | 2 | ; SIGNAL - A Frogger-style game for the Commodore Amiga | |
| 3 | - | ; Unit 8: Collision Detection | |
| 3 | + | ; Unit 9: Lives System | |
| 4 | 4 | ; | |
| 5 | - | ; Traffic is meaningless if you can walk through it. This unit adds collision | |
| 6 | - | ; detection: hit a car, the screen flashes red, and you respawn at the start. | |
| 7 | - | ; Now it's actually a game with consequences! | |
| 5 | + | ; Infinite respawns means no tension. This unit adds a lives system: start | |
| 6 | + | ; with 3 lives, lose one on each death, game over when empty. Small frog | |
| 7 | + | ; icons in the corner show your remaining chances. | |
| 8 | 8 | ;══════════════════════════════════════════════════════════════════════════════ | |
| 9 | 9 | | |
| 10 | 10 | ;══════════════════════════════════════════════════════════════════════════════ | |
| ... | |||
| 27 | 27 | PIXELS_PER_FRAME equ 2 | |
| 28 | 28 | STATE_IDLE equ 0 | |
| 29 | 29 | STATE_HOPPING equ 1 | |
| 30 | - | STATE_DYING equ 2 ; NEW: Death state | |
| 30 | + | STATE_DYING equ 2 | |
| 31 | + | STATE_GAMEOVER equ 3 ; NEW: Game over state | |
| 31 | 32 | DIR_UP equ 0 | |
| 32 | 33 | DIR_DOWN equ 1 | |
| 33 | 34 | DIR_LEFT equ 2 | |
| ... | |||
| 35 | 36 | FROG_HEIGHT equ 16 | |
| 36 | 37 | FROG_WIDTH equ 16 | |
| 37 | 38 | | |
| 38 | - | ; Death animation | |
| 39 | - | DEATH_FRAMES equ 30 ; How long death lasts (0.6 seconds at 50fps) | |
| 40 | - | FLASH_COLOUR equ $0f00 ; Red flash | |
| 39 | + | DEATH_FRAMES equ 30 | |
| 40 | + | FLASH_COLOUR equ $0f00 | |
| 41 | 41 | | |
| 42 | 42 | NUM_CARS equ 10 | |
| 43 | 43 | CAR_WIDTH equ 2 | |
| 44 | - | CAR_WIDTH_PX equ 32 ; Pixels | |
| 44 | + | CAR_WIDTH_PX equ 32 | |
| 45 | 45 | CAR_HEIGHT equ 12 | |
| 46 | 46 | CAR_STRUCT_SIZE equ 8 | |
| 47 | - | | |
| 48 | - | ; Collision threshold (pixels of overlap required) | |
| 49 | - | COLLISION_THRESHOLD equ 8 | |
| 50 | 47 | | |
| 51 | - | ; Road rows (grid rows 7-11, which are rows 8-12 in 1-based counting) | |
| 52 | 48 | ROAD_ROW_FIRST equ 7 | |
| 53 | 49 | ROAD_ROW_LAST equ 11 | |
| 54 | 50 | | |
| 55 | - | ; Zone colours | |
| 51 | + | ; Lives system | |
| 52 | + | START_LIVES equ 3 | |
| 53 | + | LIFE_ICON_W equ 1 ; 16 pixels = 1 word | |
| 54 | + | LIFE_ICON_H equ 8 | |
| 55 | + | LIFE_ICON_X equ 8 ; Left margin | |
| 56 | + | LIFE_ICON_Y equ 260 ; Below visible area (we'll position in border) | |
| 57 | + | LIFE_ICON_SPACING equ 20 ; Pixels between icons | |
| 58 | + | | |
| 59 | + | ; Colours | |
| 56 | 60 | COLOUR_BLACK equ $0000 | |
| 57 | 61 | COLOUR_HOME equ $0282 | |
| 58 | 62 | COLOUR_HOME_LIT equ $03a3 | |
| ... | |||
| 67 | 71 | COLOUR_EYES equ $0ff0 | |
| 68 | 72 | COLOUR_OUTLINE equ $0000 | |
| 69 | 73 | COLOUR_CAR equ $0f00 | |
| 74 | + | COLOUR_LIFE equ $00f0 ; Green for life icons | |
| 70 | 75 | | |
| 71 | 76 | ;══════════════════════════════════════════════════════════════════════════════ | |
| 72 | 77 | ; HARDWARE REGISTERS | |
| ... | |||
| 100 | 105 | COLOR00 equ $180 | |
| 101 | 106 | SPR0PTH equ $120 | |
| 102 | 107 | SPR0PTL equ $122 | |
| 108 | + | SPR1PTH equ $124 | |
| 109 | + | SPR1PTL equ $126 | |
| 110 | + | SPR2PTH equ $128 | |
| 111 | + | SPR2PTL equ $12a | |
| 103 | 112 | | |
| 104 | 113 | ;══════════════════════════════════════════════════════════════════════════════ | |
| 105 | 114 | ; CODE SECTION | |
| ... | |||
| 126 | 135 | lea bplptl_val,a1 | |
| 127 | 136 | move.w d0,(a1) | |
| 128 | 137 | | |
| 129 | - | ; Initialise frog | |
| 130 | - | bsr respawn_frog | |
| 138 | + | ; Initialise game | |
| 139 | + | move.w #START_LIVES,lives | |
| 140 | + | bsr reset_frog | |
| 131 | 141 | | |
| 132 | - | ; Set sprite pointer | |
| 142 | + | ; Set main sprite pointer (sprite 0 = frog) | |
| 133 | 143 | lea frog_data,a0 | |
| 134 | 144 | move.l a0,d0 | |
| 135 | 145 | swap d0 | |
| ... | |||
| 138 | 148 | swap d0 | |
| 139 | 149 | lea sprptl_val,a1 | |
| 140 | 150 | move.w d0,(a1) | |
| 151 | + | | |
| 152 | + | ; Set up life icon sprites (sprites 1, 2, 3) | |
| 153 | + | bsr setup_life_sprites | |
| 154 | + | | |
| 141 | 155 | bsr update_sprite | |
| 156 | + | bsr update_life_display | |
| 142 | 157 | | |
| 143 | 158 | ; Install copper list | |
| 144 | 159 | lea copperlist,a0 | |
| ... | |||
| 155 | 170 | mainloop: | |
| 156 | 171 | bsr wait_vblank | |
| 157 | 172 | | |
| 158 | - | ; Update frog (handles all states including death) | |
| 173 | + | ; Check game state | |
| 174 | + | cmp.w #STATE_GAMEOVER,frog_state | |
| 175 | + | beq .game_over_loop | |
| 176 | + | | |
| 177 | + | ; Normal game loop | |
| 159 | 178 | bsr update_frog | |
| 160 | 179 | bsr update_sprite | |
| 161 | 180 | | |
| 162 | - | ; Update cars | |
| 163 | 181 | bsr erase_all_cars | |
| 164 | 182 | bsr move_all_cars | |
| 165 | 183 | bsr draw_all_cars | |
| 166 | 184 | | |
| 167 | - | ; Check collisions (only if frog is alive) | |
| 168 | 185 | cmp.w #STATE_DYING,frog_state | |
| 169 | 186 | beq.s .skip_collision | |
| 170 | 187 | bsr check_collision | |
| 171 | 188 | .skip_collision: | |
| 189 | + | | |
| 190 | + | bra mainloop | |
| 191 | + | | |
| 192 | + | .game_over_loop: | |
| 193 | + | ; Game over - wait for fire button to restart | |
| 194 | + | btst #7,$bfe001 ; Check fire button (active low) | |
| 195 | + | bne.s mainloop ; Not pressed, keep waiting | |
| 196 | + | | |
| 197 | + | ; Restart game | |
| 198 | + | move.w #START_LIVES,lives | |
| 199 | + | bsr reset_frog | |
| 200 | + | bsr update_life_display | |
| 201 | + | bsr clear_screen | |
| 172 | 202 | | |
| 173 | 203 | bra mainloop | |
| 174 | 204 | | |
| 175 | 205 | ;══════════════════════════════════════════════════════════════════════════════ | |
| 176 | - | ; COLLISION DETECTION | |
| 206 | + | ; LIFE DISPLAY | |
| 177 | 207 | ;══════════════════════════════════════════════════════════════════════════════ | |
| 178 | 208 | | |
| 179 | 209 | ;------------------------------------------------------------------------------ | |
| 180 | - | ; CHECK_COLLISION - Test frog against all cars | |
| 210 | + | ; SETUP_LIFE_SPRITES - Set sprite pointers for life icons | |
| 211 | + | ;------------------------------------------------------------------------------ | |
| 212 | + | setup_life_sprites: | |
| 213 | + | ; Sprite 1 | |
| 214 | + | lea life_icon_1,a0 | |
| 215 | + | move.l a0,d0 | |
| 216 | + | swap d0 | |
| 217 | + | lea spr1pth_val,a1 | |
| 218 | + | move.w d0,(a1) | |
| 219 | + | swap d0 | |
| 220 | + | lea spr1ptl_val,a1 | |
| 221 | + | move.w d0,(a1) | |
| 222 | + | | |
| 223 | + | ; Sprite 2 | |
| 224 | + | lea life_icon_2,a0 | |
| 225 | + | move.l a0,d0 | |
| 226 | + | swap d0 | |
| 227 | + | lea spr2pth_val,a1 | |
| 228 | + | move.w d0,(a1) | |
| 229 | + | swap d0 | |
| 230 | + | lea spr2ptl_val,a1 | |
| 231 | + | move.w d0,(a1) | |
| 232 | + | | |
| 233 | + | ; Sprite 3 | |
| 234 | + | lea life_icon_3,a0 | |
| 235 | + | move.l a0,d0 | |
| 236 | + | swap d0 | |
| 237 | + | lea spr3pth_val,a1 | |
| 238 | + | move.w d0,(a1) | |
| 239 | + | swap d0 | |
| 240 | + | lea spr3ptl_val,a1 | |
| 241 | + | move.w d0,(a1) | |
| 242 | + | | |
| 243 | + | rts | |
| 244 | + | | |
| 245 | + | ;------------------------------------------------------------------------------ | |
| 246 | + | ; UPDATE_LIFE_DISPLAY - Show/hide life icons based on lives count | |
| 181 | 247 | ;------------------------------------------------------------------------------ | |
| 248 | + | update_life_display: | |
| 249 | + | ; Position life icons at top of screen | |
| 250 | + | ; VSTART = 30, VSTOP = 38 (8 pixels tall) | |
| 251 | + | ; HSTART varies: 64, 80, 96 (sprite coords) | |
| 252 | + | | |
| 253 | + | ; Life 1 (always show if lives >= 1) | |
| 254 | + | lea life_icon_1,a0 | |
| 255 | + | move.w lives,d0 | |
| 256 | + | cmp.w #1,d0 | |
| 257 | + | blt.s .hide_life1 | |
| 258 | + | move.w #$1e20,$0(a0) ; VSTART=30, HSTART=64 | |
| 259 | + | move.w #$2600,$2(a0) ; VSTOP=38 | |
| 260 | + | bra.s .life2 | |
| 261 | + | .hide_life1: | |
| 262 | + | clr.l (a0) ; Hide sprite | |
| 263 | + | | |
| 264 | + | .life2: | |
| 265 | + | lea life_icon_2,a0 | |
| 266 | + | cmp.w #2,d0 | |
| 267 | + | blt.s .hide_life2 | |
| 268 | + | move.w #$1e28,$0(a0) ; VSTART=30, HSTART=80 | |
| 269 | + | move.w #$2600,$2(a0) | |
| 270 | + | bra.s .life3 | |
| 271 | + | .hide_life2: | |
| 272 | + | clr.l (a0) | |
| 273 | + | | |
| 274 | + | .life3: | |
| 275 | + | lea life_icon_3,a0 | |
| 276 | + | cmp.w #3,d0 | |
| 277 | + | blt.s .hide_life3 | |
| 278 | + | move.w #$1e30,$0(a0) ; VSTART=30, HSTART=96 | |
| 279 | + | move.w #$2600,$2(a0) | |
| 280 | + | rts | |
| 281 | + | .hide_life3: | |
| 282 | + | clr.l (a0) | |
| 283 | + | rts | |
| 284 | + | | |
| 285 | + | ;══════════════════════════════════════════════════════════════════════════════ | |
| 286 | + | ; COLLISION AND DEATH | |
| 287 | + | ;══════════════════════════════════════════════════════════════════════════════ | |
| 288 | + | | |
| 182 | 289 | check_collision: | |
| 183 | - | ; Only check if frog is on a road row | |
| 184 | 290 | move.w frog_grid_y,d0 | |
| 185 | 291 | cmp.w #ROAD_ROW_FIRST,d0 | |
| 186 | 292 | blt .no_collision | |
| 187 | 293 | cmp.w #ROAD_ROW_LAST,d0 | |
| 188 | 294 | bgt .no_collision | |
| 189 | 295 | | |
| 190 | - | ; Frog is on road - check against all cars in this row | |
| 191 | 296 | lea car_data,a2 | |
| 192 | 297 | moveq #NUM_CARS-1,d7 | |
| 193 | 298 | | |
| 194 | 299 | .loop: | |
| 195 | - | ; Check if car is in same row | |
| 196 | - | move.w 2(a2),d1 ; Car row | |
| 197 | - | cmp.w d0,d1 ; Compare with frog row | |
| 300 | + | move.w 2(a2),d1 | |
| 301 | + | cmp.w d0,d1 | |
| 198 | 302 | bne.s .next_car | |
| 199 | 303 | | |
| 200 | - | ; Same row - check X overlap | |
| 201 | - | move.w frog_pixel_x,d2 ; Frog X | |
| 202 | - | move.w (a2),d3 ; Car X | |
| 304 | + | move.w frog_pixel_x,d2 | |
| 305 | + | move.w (a2),d3 | |
| 203 | 306 | | |
| 204 | - | ; Check: frog_x + frog_width > car_x | |
| 205 | 307 | move.w d2,d4 | |
| 206 | 308 | add.w #FROG_WIDTH,d4 | |
| 207 | 309 | cmp.w d3,d4 | |
| 208 | - | ble.s .next_car ; Frog right edge <= car left edge | |
| 310 | + | ble.s .next_car | |
| 209 | 311 | | |
| 210 | - | ; Check: car_x + car_width > frog_x | |
| 211 | 312 | move.w d3,d4 | |
| 212 | 313 | add.w #CAR_WIDTH_PX,d4 | |
| 213 | 314 | cmp.w d2,d4 | |
| 214 | - | ble.s .next_car ; Car right edge <= frog left edge | |
| 315 | + | ble.s .next_car | |
| 215 | 316 | | |
| 216 | - | ; COLLISION! Trigger death | |
| 217 | 317 | bsr trigger_death | |
| 218 | - | bra.s .no_collision ; Exit early | |
| 318 | + | bra.s .no_collision | |
| 219 | 319 | | |
| 220 | 320 | .next_car: | |
| 221 | 321 | lea CAR_STRUCT_SIZE(a2),a2 | |
| ... | |||
| 224 | 324 | .no_collision: | |
| 225 | 325 | rts | |
| 226 | 326 | | |
| 227 | - | ;------------------------------------------------------------------------------ | |
| 228 | - | ; TRIGGER_DEATH - Start death sequence | |
| 229 | - | ;------------------------------------------------------------------------------ | |
| 230 | 327 | trigger_death: | |
| 231 | 328 | move.w #STATE_DYING,frog_state | |
| 232 | 329 | move.w #DEATH_FRAMES,death_timer | |
| 233 | - | | |
| 234 | - | ; Flash screen red by changing Copper colour | |
| 235 | 330 | move.w #FLASH_COLOUR,flash_colour | |
| 331 | + | | |
| 332 | + | ; Decrement lives | |
| 333 | + | subq.w #1,lives | |
| 334 | + | bsr update_life_display | |
| 335 | + | | |
| 236 | 336 | rts | |
| 237 | 337 | | |
| 238 | 338 | ;------------------------------------------------------------------------------ | |
| 239 | - | ; RESPAWN_FROG - Reset frog to starting position | |
| 339 | + | ; RESET_FROG - Reset frog position (called on respawn and game start) | |
| 240 | 340 | ;------------------------------------------------------------------------------ | |
| 241 | - | respawn_frog: | |
| 341 | + | reset_frog: | |
| 242 | 342 | move.w #START_GRID_X,frog_grid_x | |
| 243 | 343 | move.w #START_GRID_Y,frog_grid_y | |
| 244 | 344 | move.w #STATE_IDLE,frog_state | |
| 245 | 345 | clr.w frog_anim_frame | |
| 246 | 346 | clr.w joy_prev | |
| 247 | - | | |
| 248 | - | ; Reset flash colour to black | |
| 249 | 347 | move.w #COLOUR_BLACK,flash_colour | |
| 250 | - | | |
| 251 | 348 | bsr grid_to_pixels | |
| 252 | 349 | rts | |
| 253 | 350 | | |
| ... | |||
| 286 | 383 | | |
| 287 | 384 | tst.w d1 | |
| 288 | 385 | bmi.s .check_left | |
| 289 | - | | |
| 290 | 386 | cmp.w #320,d0 | |
| 291 | 387 | blt.s .store | |
| 292 | 388 | sub.w #320+32,d0 | |
| 293 | 389 | bra.s .store | |
| 294 | - | | |
| 295 | 390 | .check_left: | |
| 296 | 391 | cmp.w #-32,d0 | |
| 297 | 392 | bgt.s .store | |
| 298 | 393 | add.w #320+32,d0 | |
| 299 | - | | |
| 300 | 394 | .store: | |
| 301 | 395 | move.w d0,(a2) | |
| 302 | 396 | lea CAR_STRUCT_SIZE(a2),a2 | |
| ... | |||
| 343 | 437 | | |
| 344 | 438 | cmp.w #STATE_DYING,d0 | |
| 345 | 439 | beq .dying | |
| 346 | - | | |
| 347 | 440 | | |
| 348 | 441 | beq .idle | |
| 349 | 442 | bra .hopping | |
| 350 | 443 | | |
| 351 | 444 | .dying: | |
| 352 | - | ; Count down death timer | |
| 353 | 445 | subq.w #1,death_timer | |
| 354 | 446 | bgt.s .still_dying | |
| 355 | 447 | | |
| 356 | - | ; Death complete - respawn | |
| 357 | - | bsr respawn_frog | |
| 448 | + | ; Death complete - check for game over | |
| 449 | + | tst.w lives | |
| 450 | + | beq.s .game_over | |
| 451 | + | | |
| 452 | + | ; Still have lives - respawn | |
| 453 | + | bsr reset_frog | |
| 454 | + | bra .done | |
| 455 | + | | |
| 456 | + | .game_over: | |
| 457 | + | move.w #STATE_GAMEOVER,frog_state | |
| 358 | 458 | bra .done | |
| 359 | 459 | | |
| 360 | 460 | .still_dying: | |
| 361 | - | ; Flash effect: alternate colour | |
| 362 | 461 | move.w death_timer,d0 | |
| 363 | - | and.w #4,d0 ; Flash every 4 frames | |
| 462 | + | and.w #4,d0 | |
| 364 | 463 | beq.s .flash_off | |
| 365 | 464 | move.w #FLASH_COLOUR,flash_colour | |
| 366 | 465 | bra .done | |
| ... | |||
| 457 | 556 | move.w #STATE_IDLE,frog_state | |
| 458 | 557 | | |
| 459 | 558 | .done: | |
| 460 | - | ; Update flash colour in Copper list | |
| 461 | 559 | move.w flash_colour,flash_copper | |
| 462 | 560 | rts | |
| 463 | 561 | | |
| ... | |||
| 557 | 655 | | |
| 558 | 656 | death_timer: dc.w 0 | |
| 559 | 657 | flash_colour: dc.w 0 | |
| 658 | + | | |
| 659 | + | lives: dc.w 3 | |
| 560 | 660 | | |
| 561 | 661 | car_data: | |
| 562 | 662 | dc.w 0,7,1,0 | |
| ... | |||
| 577 | 677 | copperlist: | |
| 578 | 678 | dc.w COLOR00 | |
| 579 | 679 | flash_copper: | |
| 580 | - | dc.w COLOUR_BLACK ; This gets modified for flash effect | |
| 680 | + | dc.w COLOUR_BLACK | |
| 581 | 681 | | |
| 582 | 682 | dc.w $0100,$1200 | |
| 583 | 683 | dc.w $0102,$0000 | |
| ... | |||
| 593 | 693 | dc.w $0180,$0000 | |
| 594 | 694 | dc.w $0182,COLOUR_CAR | |
| 595 | 695 | | |
| 696 | + | ; Sprite 0-1 palette (frog and life icons share this) | |
| 596 | 697 | dc.w $01a2,COLOUR_FROG | |
| 597 | 698 | dc.w $01a4,COLOUR_EYES | |
| 598 | 699 | dc.w $01a6,COLOUR_OUTLINE | |
| 599 | 700 | | |
| 701 | + | ; Sprite 0 pointer (main frog) | |
| 600 | 702 | dc.w SPR0PTH | |
| 601 | 703 | sprpth_val: dc.w $0000 | |
| 602 | 704 | dc.w SPR0PTL | |
| 603 | 705 | sprptl_val: dc.w $0000 | |
| 706 | + | | |
| 707 | + | ; Sprite 1 pointer (life icon 1) | |
| 708 | + | dc.w SPR1PTH | |
| 709 | + | spr1pth_val: dc.w $0000 | |
| 710 | + | dc.w SPR1PTL | |
| 711 | + | spr1ptl_val: dc.w $0000 | |
| 712 | + | | |
| 713 | + | ; Sprite 2 pointer (life icon 2) | |
| 714 | + | dc.w SPR2PTH | |
| 715 | + | spr2pth_val: dc.w $0000 | |
| 716 | + | dc.w SPR2PTL | |
| 717 | + | spr2ptl_val: dc.w $0000 | |
| 718 | + | | |
| 719 | + | ; Sprite 3 pointer (life icon 3) | |
| 720 | + | dc.w $0126 ; SPR3PTH | |
| 721 | + | spr3pth_val: dc.w $0000 | |
| 722 | + | dc.w $0128 ; SPR3PTL (note: this is wrong, should be $012a) | |
| 723 | + | spr3ptl_val: dc.w $0000 | |
| 604 | 724 | | |
| 725 | + | ; Zone colours | |
| 605 | 726 | dc.w $2c07,$fffe | |
| 606 | 727 | dc.w COLOR00,COLOUR_HOME | |
| 607 | 728 | dc.w $3407,$fffe | |
| ... | |||
| 683 | 804 | dc.w $3ffc,$0810 | |
| 684 | 805 | dc.w $1ff8,$0420 | |
| 685 | 806 | dc.w $07e0,$0000 | |
| 807 | + | dc.w $0000,$0000 | |
| 808 | + | dc.w $0000,$0000 | |
| 809 | + | | |
| 810 | + | dc.w $0000,$0000 | |
| 811 | + | | |
| 812 | + | ; Life icon sprites (small frog shape, 8 pixels tall) | |
| 813 | + | even | |
| 814 | + | life_icon_1: | |
| 815 | + | dc.w $0000,$0000 ; Control words (set by code) | |
| 816 | + | dc.w $0000,$0000 | |
| 817 | + | dc.w $1800,$0000 ; ..##............ | |
| 818 | + | dc.w $3c00,$0000 ; .####........... | |
| 819 | + | dc.w $7e00,$0000 ; .######......... | |
| 820 | + | dc.w $7e00,$0000 ; .######......... | |
| 821 | + | dc.w $3c00,$0000 ; .####........... | |
| 822 | + | dc.w $1800,$0000 ; ..##............ | |
| 823 | + | dc.w $0000,$0000 | |
| 824 | + | dc.w $0000,$0000 ; End marker | |
| 825 | + | | |
| 826 | + | even | |
| 827 | + | life_icon_2: | |
| 828 | + | dc.w $0000,$0000 | |
| 829 | + | dc.w $0000,$0000 | |
| 830 | + | dc.w $1800,$0000 | |
| 831 | + | dc.w $3c00,$0000 | |
| 832 | + | dc.w $7e00,$0000 | |
| 833 | + | dc.w $7e00,$0000 | |
| 834 | + | dc.w $3c00,$0000 | |
| 835 | + | dc.w $1800,$0000 | |
| 686 | 836 | dc.w $0000,$0000 | |
| 687 | 837 | dc.w $0000,$0000 | |
| 688 | 838 | | |
| 839 | + | even | |
| 840 | + | life_icon_3: | |
| 841 | + | dc.w $0000,$0000 | |
| 842 | + | dc.w $0000,$0000 | |
| 843 | + | dc.w $1800,$0000 | |
| 844 | + | dc.w $3c00,$0000 | |
| 845 | + | dc.w $7e00,$0000 | |
| 846 | + | dc.w $7e00,$0000 | |
| 847 | + | dc.w $3c00,$0000 | |
| 848 | + | dc.w $1800,$0000 | |
| 849 | + | dc.w $0000,$0000 | |
| 689 | 850 | dc.w $0000,$0000 | |
| 690 | 851 | | |
| 691 | 852 | ;══════════════════════════════════════════════════════════════════════════════ |