graphics tweaks

This commit is contained in:
2026-07-21 16:46:09 +02:00
parent c703d8b5f3
commit 8420213065
13 changed files with 1131 additions and 290 deletions
+25 -14
View File
@@ -3,23 +3,30 @@
**LabyrinTwo** - a two-player maze duel for the Commodore 64 **LabyrinTwo** - a two-player maze duel for the Commodore 64
(ACME + VICE), in the same spirit as [rabbitc64](../rabbitc64). (ACME + VICE), in the same spirit as [rabbitc64](../rabbitc64).
A fresh maze is carved every round on a 39x23 lattice where the walls A fresh maze carves itself on screen at the start of every round on
are exactly as wide as the corridors. **Player 1** (joystick 2, or a 39x23 lattice where the walls are exactly as wide as the corridors.
`w a s d`) runs the corridors toward the green diamond exit while **Player 1** (joystick 2, or `w a s d`) runs the corridors toward the
dodging the roaming colored enemies. **Player 2** (joystick 1, or green exit portal while dodging the roaming enemies. **Player 2**
`i j k l`) rides the corners of the walls with a blinking cursor - (joystick 1, or `i j k l`) rides the corners of the walls with a
fire (or `return`) spins the four wall pieces around the cursor by bracket cursor - fire (or `return`) spins the four wall pieces around
90 degrees, reshaping the maze in real time. A spin is denied while the cursor by 90 degrees, reshaping the maze in real time. A spin is
anyone is standing in one of the four slots. denied while anyone is standing in one of the four slots (the border
blips red); the spun pieces flash white.
The look: brick walls and bolted pivot posts from a custom RAM
charset, every actor (runner, cursor, bullet, enemies) a hardware
sprite gliding smoothly between the cells, an animated exit portal,
a raster color band behind the status row, and a fade to black
between all screens. The menu floats over a dark maze backdrop.
The options screen adds two optional twists: The options screen adds two optional twists:
- **runner gun** - player 1 shoots a bullet with fire/`space`; a hit - **runner gun** - player 1 shoots a bullet with fire/`space`; a hit
enemy respawns on a random cell after a pause. enemy respawns on a random cell after a pause.
- **spin cooldown** - each spin starts a recharge; further spins are - **spin cooldown** - each spin starts a recharge; further spins are
denied until the draining bar on the status row runs out and the denied until the bar on the status row drains (pixel by pixel) and
readout flips back from *wait* to *ready* (the cursor also dims the readout flips back from *wait* to *ready* (the cursor also
while recharging). turns red while recharging).
Screens: TTG intro (ported from rabbitc64) -> main menu Screens: TTG intro (ported from rabbitc64) -> main menu
(play / options / rules / controls / credits) -> game -> win (back (play / options / rules / controls / credits) -> game -> win (back
@@ -45,15 +52,19 @@ acme -DAUTOPLAY=1 -f cbm -o labyrintwo.prg main.asm
## Files ## Files
- `main.asm` - entry point, BASIC stub, per-frame state machine - `main.asm` - entry point, BASIC stub, per-frame state machine,
the border/status-band raster work
- `defs.asm` - registers, constants, zero page, macros - `defs.asm` - registers, constants, zero page, macros
- `intro.asm` - TTG boot logo with the gold color wash - `intro.asm` - TTG boot logo with the gold color wash
- `menu.asm` - main menu card - `menu.asm` - main menu card over a dark maze backdrop
- `options.asm` - the optional extras and their toggle screen - `options.asm` - the optional extras and their toggle screen
- `rules.asm` - how to play - `rules.asm` - how to play
- `controls.asm` - joystick + keyboard mappings - `controls.asm` - joystick + keyboard mappings
- `credits.asm` - the crew - `credits.asm` - the crew
- `play.asm` - maze generation (recursive backtracker) + the game - `play.asm` - maze generation (recursive backtracker, animated)
+ the game
- `win.asm` / `over.asm` - end screens - `win.asm` / `over.asm` - end screens
- `common.asm` - shared routines: printing, big block font, input, RNG - `common.asm` - shared routines: printing, big block font, input, RNG
- `sound.asm` - single-voice SID SFX driver - `sound.asm` - single-voice SID SFX driver
- `gfx.asm` - RAM charset with the custom tiles, the sprite engine,
the portal animation and the fade-to-black transition
+1 -1
View File
@@ -33,7 +33,7 @@ co_hide:
co_input: co_input:
jsr start_edge jsr start_edge
beq co_stay beq co_stay
jmp menu_init +fadeto menu_init
co_stay: co_stay:
rts rts
+1 -1
View File
@@ -135,7 +135,7 @@ cu_hide:
cu_input: cu_input:
jsr start_edge jsr start_edge
beq cu_stay beq cu_stay
jmp menu_init ; back to the menu +fadeto menu_init ; back to the menu
cu_stay: cu_stay:
rts rts
+40 -7
View File
@@ -9,11 +9,25 @@ BORDER = $d020 ; border color register
BG = $d021 ; background color register BG = $d021 ; background color register
SCREEN = $0400 ; screen RAM (40x25 chars) SCREEN = $0400 ; screen RAM (40x25 chars)
COLRAM = $d800 ; color RAM COLRAM = $d800 ; color RAM
SPR_EN = $d015 ; sprite enable bits (parked at 0) SCRCTL = $d011 ; control 1: raster msb, y-scroll
SPR_EN = $d015 ; sprite enable bits
SPRX0 = $d000 ; sprite 0 x (x/y pairs go up from here)
SPRY0 = $d001 ; sprite 0 y
SPRMSB = $d010 ; 9th x position bit of each sprite
SPRDBLY = $d017 ; sprite y expand
VMCSB = $d018 ; memory setup: screen + charset base
SPRPRI = $d01b ; sprite/background priority
SPRMCEN = $d01c ; sprite multicolor enable
SPRDBLX = $d01d ; sprite x expand
SPRCOL = $d027 ; sprite colors, 8 registers
CPUPORT = $01 ; 6510 port: ROM/RAM banking
CIA1_PA = $dc00 ; CIA1 port A: keyboard columns / joystick 2 CIA1_PA = $dc00 ; CIA1 port A: keyboard columns / joystick 2
CIA1_PB = $dc01 ; CIA1 port B: keyboard rows / joystick 1 CIA1_PB = $dc01 ; CIA1 port B: keyboard rows / joystick 1
CIA1_TA = $dc04 ; CIA1 timer A low byte: free-running entropy CIA1_TA = $dc04 ; CIA1 timer A low byte: free-running entropy
CHARSET = $3800 ; RAM charset: ROM font + the custom tiles
SPRPTR = SCREEN + $3f8 ; sprite shape pointers
; ---- SID registers (single-voice SFX driver) ---- ; ---- SID registers (single-voice SFX driver) ----
SID_V1FL = $d400 ; voice 1 frequency low SID_V1FL = $d400 ; voice 1 frequency low
SID_V1FH = $d401 ; voice 1 frequency high SID_V1FH = $d401 ; voice 1 frequency high
@@ -71,16 +85,24 @@ MAZE_CH = 11 ; cells down
NCELLS = MAZE_CW * MAZE_CH NCELLS = MAZE_CW * MAZE_CH
NENEMIES = 4 NENEMIES = 4
CH_WALL = $a0 ; inverse space: solid wall block ; ---- characters (the custom tiles live in the RAM charset) ----
CH_WALL = $e0 ; brick block: spinnable wall piece
CH_POST = $e1 ; bolted plate: fixed pivot post
CH_EXIT = $e2 ; the portal out (4 animated glyph frames)
CH_FLOOR = $20 ; space: corridor CH_FLOOR = $20 ; space: corridor
CH_EXIT = $5a ; diamond: the goal CH_BAR = $e3 ; 7 chars: a bar cell 1-7 pixels full
CH_PLAYER = $51 ; filled ball: the runner
CH_ENEMY = $57 ; open circle: an enemy ; ---- the actors are hardware sprites ----
CH_SHOT = $2a ; asterisk: the runner's bullet SP_RUN = 0 ; player 1, the runner
SP_CUR = 1 ; player 2, the corner cursor
SP_SHOT = 2 ; the optional bullet
SP_EN = 3 ; the enemies ride sprites 3-6
COL_WALL = MGREY ; spinnable wall pieces COL_WALL = MGREY ; spinnable wall pieces
COL_POST = DGREY ; fixed pivot posts COL_POST = DGREY ; fixed pivot posts
COL_EXIT = LGREEN ; the exit diamond COL_EXIT = LGREEN ; the exit portal
COL_HILITE = YELLOW ; walls the cursor's spin would move
STATCOL = BLUE ; background band behind the status row
; ---- game timing ---- ; ---- game timing ----
REP_HOLD = 10 ; runner: frames before a held dir repeats REP_HOLD = 10 ; runner: frames before a held dir repeats
@@ -90,6 +112,7 @@ CREP_PERIOD = 7
COOL_TIME = 160 ; spin cooldown option: recharge frames COOL_TIME = 160 ; spin cooldown option: recharge frames
RESPAWN_TIME = 150 ; gun option: frames until a hit enemy returns RESPAWN_TIME = 150 ; gun option: frames until a hit enemy returns
RAS_SYNC = 251 ; raster line polled for the frame sync RAS_SYNC = 251 ; raster line polled for the frame sync
BUILD_STEPS = 8 ; maze carve animation: generator steps a frame
; ---- zero page pointers (same slots as rabbitc64) ---- ; ---- zero page pointers (same slots as rabbitc64) ----
txtlo = $f5 ; text pointer for the print routines (2 bytes) txtlo = $f5 ; text pointer for the print routines (2 bytes)
@@ -140,3 +163,13 @@ colhi = $fe
lda #>.addr lda #>.addr
sta updvec+1 sta updvec+1
} }
; ---- leave the current screen: fade to black, then run the
; init routine of the next one ----
!macro fadeto .addr {
lda #<.addr
sta fadevec
lda #>.addr
sta fadevec+1
jmp fade_start
}
+481
View File
@@ -0,0 +1,481 @@
; -----------------------------------------------------------
; gfx.asm - the graphics layer:
; - the ROM font is copied into RAM and a handful of custom
; tiles are stamped over it (brick wall, pivot post, the
; animated exit portal, the 1/8-step cooldown bar cells)
; - a small sprite engine: every actor lives on the char
; grid, its sprite glides toward the cell a few pixels a
; frame (the runner bobs, the enemies wave)
; - fade to black: the transition between two screens
; -----------------------------------------------------------
; ---- one-time setup: font to RAM, custom tiles, VIC ----
gfx_init:
lda #$33 ; char ROM in at $d000 (I/O out briefly)
sta CPUPORT
lda #$d0
sta txthi
lda #>CHARSET
sta scrhi
lda #0
sta txtlo
sta scrlo
ldx #8 ; 2 KB: the full uppercase set
gc_page:
ldy #0
gc_byte:
lda (txtlo),y
sta (scrlo),y
iny
bne gc_byte
inc txthi
inc scrhi
dex
bne gc_page
lda #$37 ; I/O back in
sta CPUPORT
; the brick wall + the pivot post (two consecutive codes)
ldx #15
gc_tiles:
lda tile_gfx,x
sta CHARSET+CH_WALL*8,x
dex
bpl gc_tiles
; the portal starts on frame 0
ldx #7
gc_portal:
lda portal_gfx,x
sta CHARSET+CH_EXIT*8,x
dex
bpl gc_portal
; the seven bar cells: 1-7 pixels filled from the left
ldx #0
ldy #0
gc_bar:
lda barmask,x
sta rtmp
lda #8
sta rtmp2
gc_bar8:
lda rtmp
sta CHARSET+CH_BAR*8,y
iny
dec rtmp2
bne gc_bar8
inx
cpx #7
bne gc_bar
; VIC: screen at $0400, charset at $3800
lda #$1e
sta VMCSB
; sprites: hires, unexpanded, in front of the chars
lda #0
sta SPRDBLY
sta SPRDBLX
sta SPRMCEN
sta SPRPRI
sta SPRMSB
rts
; ---- cycle the portal glyph: 4 frames, one every 8 frames;
; rewriting the definition animates every portal on screen ----
upd_portal:
lda framectr
and #7
bne up_done
lda framectr
and #$18 ; (frame index) * 8 = data offset
tay
ldx #0
up_copy:
lda portal_gfx,y
sta CHARSET+CH_EXIT*8,x
iny
inx
cpx #8
bne up_copy
up_done:
rts
; ============================================================
; sprite engine
; ============================================================
; grid cell (tgc, tgr) -> pixel target tgxl/tgxh, tgy
set_target:
lda #0
sta tgxh
lda tgc
asl
rol tgxh
asl
rol tgxh
asl
rol tgxh
clc
adc #24 ; first visible pixel column
sta tgxl
bcc st_y
inc tgxh
st_y:
lda tgr
asl
asl
asl
clc
adc #50 ; first visible raster line
sta tgy
rts
; sprite X snaps straight onto the target
spr_jump:
lda tgxl
sta sprxl,x
lda tgxh
sta sprxh,x
lda tgy
sta spry,x
rts
; sprite X slides gspd pixels per axis toward the target; the
; actors re-target every frame, so the distance always fits in
; a signed byte and a step never overshoots
spr_glide:
lda tgxl
sec
sbc sprxl,x
sta dtmp
lda tgxh
sbc sprxh,x ; the high byte only carries the sign
lda dtmp
beq sg_y
bmi sg_left
cmp gspd ; rightward: step = min(distance, speed)
bcc sg_rgo
lda gspd
sg_rgo:
clc
adc sprxl,x
sta sprxl,x
bcc sg_y
inc sprxh,x
jmp sg_y
sg_left:
eor #$ff ; leftward: the same on the distance
clc
adc #1
cmp gspd
bcc sg_lgo
lda gspd
sg_lgo:
sta dtmp
lda sprxl,x
sec
sbc dtmp
sta sprxl,x
bcs sg_y
dec sprxh,x
sg_y:
lda tgy
sec
sbc spry,x
beq sg_done
bmi sg_up
cmp gspd
bcc sg_dgo
lda gspd
sg_dgo:
clc
adc spry,x
sta spry,x
rts
sg_up:
eor #$ff
clc
adc #1
cmp gspd
bcc sg_ugo
lda gspd
sg_ugo:
sta dtmp
lda spry,x
sec
sbc dtmp
sta spry,x
sg_done:
rts
; push all eight sprite positions + the x msb bits to the VIC
spr_commit:
lda #0
sta dtmp
ldx #7
sc_loop:
lda sprxh,x
beq sc_low
lda dtmp
ora sprbit,x
sta dtmp
sc_low:
txa
asl
tay
lda sprxl,x
sta SPRX0,y
lda spry,x
sta SPRY0,y
dex
bpl sc_loop
lda dtmp
sta SPRMSB
rts
sprbit: !byte 1, 2, 4, 8, 16, 32, 64, 128
; ============================================================
; fade to black - six passes walk every color RAM cell (and
; the sprite colors) down the luminance chains, half a screen
; per frame; then control jumps to the init routine the
; +fadeto macro left in fadevec
; ============================================================
fade_start:
lda #$ff
sta statbg ; no status band while fading
lda #0
sta bflash
sta borbase
sta fadecnt
sta fadehalf
+setupd fade_update
rts
fade_update:
lda fadehalf ; half the color RAM per frame
eor #1
sta fadehalf
bne fu_hi
ldx #0
fu_lo:
lda COLRAM,x
and #15
tay
lda fadetbl,y
sta COLRAM,x
lda COLRAM+$100,x
and #15
tay
lda fadetbl,y
sta COLRAM+$100,x
inx
bne fu_lo
rts
fu_hi:
ldx #0
fu_hi2:
lda COLRAM+$200,x
and #15
tay
lda fadetbl,y
sta COLRAM+$200,x
lda COLRAM+$2e8,x
and #15
tay
lda fadetbl,y
sta COLRAM+$2e8,x
inx
bne fu_hi2
ldx #7 ; the sprites sink with the screen
fu_spr:
lda SPRCOL,x
and #15
tay
lda fadetbl,y
sta SPRCOL,x
dex
bpl fu_spr
inc fadecnt
lda fadecnt
cmp #6 ; the longest chain is black after 5
bne fu_stay
lda #0
sta SPR_EN
jmp (fadevec) ; its rts returns to the main loop
fu_stay:
rts
fadetbl: ; each color, one step darker
!byte $00, $0f, $09, $0c, $0b, $0b, $00, $08
!byte $02, $00, $02, $00, $0b, $05, $06, $0c
; ---- the custom tiles ----
tile_gfx: ; CH_WALL: bricks with dark mortar
!byte %11111111
!byte %11110111
!byte %11110111
!byte %00000000
!byte %11111111
!byte %01111111
!byte %01111111
!byte %00000000
; CH_POST: a bolted plate
!byte %11111111
!byte %10000001
!byte %10111101
!byte %10100101
!byte %10100101
!byte %10111101
!byte %10000001
!byte %11111111
portal_gfx: ; CH_EXIT frame 0: closed
!byte %00000000
!byte %00011000
!byte %00111100
!byte %01100110
!byte %01100110
!byte %00111100
!byte %00011000
!byte %00000000
; frame 1: opening
!byte %00011000
!byte %00111100
!byte %01100110
!byte %11000011
!byte %11000011
!byte %01100110
!byte %00111100
!byte %00011000
; frame 2: wide open, sparkling
!byte %00111100
!byte %01100110
!byte %11011011
!byte %10111101
!byte %10111101
!byte %11011011
!byte %01100110
!byte %00111100
; frame 3: closing again
!byte %00011000
!byte %00111100
!byte %01100110
!byte %11000011
!byte %11000011
!byte %01100110
!byte %00111100
!byte %00011000
barmask: ; bar cell fills, 1-7 pixels
!byte $80, $c0, $e0, $f0, $f8, $fc, $fe
; ---- graphics layer variables ----
sprxl: !fill 8, 0 ; sprite pixel positions (x low/high, y)
sprxh: !fill 8, 0
spry: !fill 8, 0
tgc: !byte 0 ; set_target input: grid column / row
tgr: !byte 0
tgxl: !byte 0 ; set_target output: pixel target
tgxh: !byte 0
tgy: !byte 0
gspd: !byte 0 ; spr_glide: pixels per frame
dtmp: !byte 0 ; scratch
statbg: !byte $ff ; status band color, $ff = no band
bflash: !byte 0 ; border flash: frames left + color
bcolor: !byte 0
borbase: !byte 0 ; steady border color of the screen
fadevec: !byte 0, 0 ; where fade_update jumps when done
fadecnt: !byte 0 ; fade passes completed
fadehalf: !byte 0 ; which color RAM half is next
!if (fadevec & 255) = 255 { !error "fadevec must not straddle a page" }
; ---- sprite shapes: 8x8 art in the top-left of each block ----
!align 63, 0
spr_run0: ; the runner: a bright-eyed ball...
!byte %00111100, 0, 0
!byte %01111110, 0, 0
!byte %11011011, 0, 0
!byte %11111111, 0, 0
!byte %11111111, 0, 0
!byte %11111111, 0, 0
!byte %01111110, 0, 0
!byte %00111100, 0, 0
!fill 40, 0
spr_run1: ; ...that bobs as it goes
!byte %00000000, 0, 0
!byte %00111100, 0, 0
!byte %01111110, 0, 0
!byte %11011011, 0, 0
!byte %11111111, 0, 0
!byte %11111111, 0, 0
!byte %01111110, 0, 0
!byte %00111100, 0, 0
!fill 40, 0
spr_shot0: ; the bullet
!byte %00000000, 0, 0
!byte %00000000, 0, 0
!byte %00011000, 0, 0
!byte %00111100, 0, 0
!byte %00111100, 0, 0
!byte %00011000, 0, 0
!byte %00000000, 0, 0
!byte %00000000, 0, 0
!fill 40, 0
spr_cur0: ; the corner cursor: four brackets
!byte %11100111, 0, 0
!byte %10000001, 0, 0
!byte %10000001, 0, 0
!byte %00000000, 0, 0
!byte %00000000, 0, 0
!byte %10000001, 0, 0
!byte %10000001, 0, 0
!byte %11100111, 0, 0
!fill 40, 0
spr_ena0: ; enemies 0-1: a ghost, skirt waving
!byte %00111100, 0, 0
!byte %01111110, 0, 0
!byte %11011011, 0, 0
!byte %11011011, 0, 0
!byte %11111111, 0, 0
!byte %11111111, 0, 0
!byte %11111111, 0, 0
!byte %10110101, 0, 0
!fill 40, 0
spr_ena1:
!byte %00111100, 0, 0
!byte %01111110, 0, 0
!byte %11011011, 0, 0
!byte %11011011, 0, 0
!byte %11111111, 0, 0
!byte %11111111, 0, 0
!byte %11111111, 0, 0
!byte %01101101, 0, 0
!fill 40, 0
spr_enb0: ; enemies 2-3: a crawler, legs pumping
!byte %00000000, 0, 0
!byte %10111101, 0, 0
!byte %01111110, 0, 0
!byte %11011011, 0, 0
!byte %01111110, 0, 0
!byte %10111101, 0, 0
!byte %00000000, 0, 0
!byte %00000000, 0, 0
!fill 40, 0
spr_enb1:
!byte %00000000, 0, 0
!byte %00111100, 0, 0
!byte %01111110, 0, 0
!byte %11011011, 0, 0
!byte %01111110, 0, 0
!byte %00111100, 0, 0
!byte %00000000, 0, 0
!byte %00000000, 0, 0
!fill 40, 0
SPR_RUN = spr_run0 DIV 64
SPR_SHOT = spr_shot0 DIV 64
SPR_CUR = spr_cur0 DIV 64
SPR_ENA = spr_ena0 DIV 64
SPR_ENB = spr_enb0 DIV 64
!if spr_run0 < $2000 { !error "sprite data slid under $2000: the VIC sees the char ROM shadow there" }
!if * > CHARSET { !error "the program ran into the charset at $3800" }
+2 -2
View File
@@ -78,11 +78,11 @@ iw_skip:
; fire skips, otherwise wait out the timer ; fire skips, otherwise wait out the timer
jsr start_edge jsr start_edge
beq iw_tick beq iw_tick
jmp menu_init +fadeto menu_init
iw_tick: iw_tick:
dec introt dec introt
bne iw_done bne iw_done
jmp menu_init +fadeto menu_init
iw_done: iw_done:
rts rts
+41 -5
View File
@@ -1,7 +1,7 @@
; ----------------------------------------------------------- ; -----------------------------------------------------------
; main.asm - LABYRINTWO for the C64 ; main.asm - LABYRINTWO for the C64
; two-player maze duel: player 1 runs the corridors toward ; two-player maze duel: player 1 runs the corridors toward
; the green diamond exit while dodging the roaming colored ; the green exit portal while dodging the roaming colored
; enemies; player 2 rides the wall corners with a cursor ; enemies; player 2 rides the wall corners with a cursor
; and fire spins the four wall pieces around it by 90 ; and fire spins the four wall pieces around it by 90
; degrees, reshaping the maze under the runner's feet ; degrees, reshaping the maze under the runner's feet
@@ -9,7 +9,7 @@
; Files: ; Files:
; defs.asm - constants, zero page, macros ; defs.asm - constants, zero page, macros
; intro.asm - TTG boot logo (ported from rabbitc64) ; intro.asm - TTG boot logo (ported from rabbitc64)
; menu.asm - main menu: play / options / rules / ... ; menu.asm - main menu over a dark maze backdrop
; options.asm - optional extras: runner gun, spin cooldown ; options.asm - optional extras: runner gun, spin cooldown
; rules.asm - how to play ; rules.asm - how to play
; controls.asm- joystick + keyboard mappings ; controls.asm- joystick + keyboard mappings
@@ -19,6 +19,7 @@
; over.asm - game over screen with retry ; over.asm - game over screen with retry
; common.asm - shared routines, input, RNG, texts ; common.asm - shared routines, input, RNG, texts
; sound.asm - single-voice SFX driver ; sound.asm - single-voice SFX driver
; gfx.asm - RAM charset, sprite engine, fades
; ;
; Build: acme -f cbm -o labyrintwo.prg main.asm ; Build: acme -f cbm -o labyrintwo.prg main.asm
; ----------------------------------------------------------- ; -----------------------------------------------------------
@@ -44,9 +45,10 @@ start:
sta BORDER sta BORDER
sta BG sta BG
lda #0 lda #0
sta SPR_EN ; character-only game: sprites stay off sta SPR_EN ; the actors arrive with the game screen
sta framectr sta framectr
sta fheld sta fheld
jsr gfx_init ; RAM charset + VIC + sprite registers
jsr sfx_init jsr sfx_init
!ifdef AUTOPLAY { ; test builds boot straight into one state !ifdef AUTOPLAY { ; test builds boot straight into one state
@@ -81,13 +83,46 @@ start:
; ============================================================ ; ============================================================
; main loop - one state update per PAL frame, synced to the ; main loop - one state update per PAL frame, synced to the
; raster beam in the lower border ; raster beam in the lower border; the loop also paints the
; border (event flashes decay back to the screen's base
; color) and, when a screen asks for one, lays a background
; band behind the status row with two more raster waits
; ============================================================ ; ============================================================
main: main:
jsr wait_frame jsr wait_frame ; raster line RAS_SYNC, once a frame
lda bflash ; border: flash, else the base color
beq mb_base
dec bflash
lda bcolor
jmp mb_border
mb_base:
lda borbase
mb_border:
sta BORDER
inc framectr inc framectr
jsr rand8 ; stir the RNG once per frame jsr rand8 ; stir the RNG once per frame
jsr sfx_update ; advance the sound effect jsr sfx_update ; advance the sound effect
lda statbg ; $ff = no band: update right away
bmi mb_update
mb_w1:
bit SCRCTL ; the beam reaches line 256...
bpl mb_w1
mb_w2:
bit SCRCTL ; ...and wraps to line 0
bmi mb_w2
mb_w3:
lda RASTER
cmp #49 ; still in the border above the window
bcc mb_w3
lda statbg
sta BG
mb_w4:
lda RASTER
cmp #59 ; the switch back hides behind row 1's
bcc mb_w4 ; wall tops (their top line is solid)
lda #BLACK
sta BG
mb_update:
jsr call_update jsr call_update
jmp main jmp main
@@ -120,3 +155,4 @@ wf_hit:
!src "over.asm" !src "over.asm"
!src "common.asm" !src "common.asm"
!src "sound.asm" !src "sound.asm"
!src "gfx.asm"
+32 -5
View File
@@ -11,6 +11,33 @@ MENU_ITEMS = 5
menu_init: menu_init:
jsr clear_screen jsr clear_screen
; a dark maze weaves behind the whole card
lda #DGREY
sta latwcol
sta latpcol
jsr draw_lattice
jsr gen_init
jsr gen_maze_full
; a clean panel for the menu itself (rows 9-22, cols 4-35)
ldx #9
mi_panel:
stx ptmp
jsr row_ptr
ldy #35
mi_pcol:
lda #$20
sta (scrlo),y
lda #BLACK
sta (collo),y
dey
cpy #3
bne mi_pcol
ldx ptmp
inx
cpx #23
bne mi_panel
+prbig 2, 0, YELLOW, txt_t1, 7 +prbig 2, 0, YELLOW, txt_t1, 7
+prbig 2, 28, CYAN, txt_t2, 3 +prbig 2, 28, CYAN, txt_t2, 3
+prtext 9, 13, LGREY, txt_ttgname, 14 +prtext 9, 13, LGREY, txt_ttgname, 14
@@ -162,15 +189,15 @@ mu_start:
beq mg_rules beq mg_rules
cmp #3 cmp #3
beq mg_controls beq mg_controls
jmp credits_init ; each init's rts returns to the main loop +fadeto credits_init ; every screen change fades to black
mg_play: mg_play:
jmp play_init +fadeto play_init
mg_options: mg_options:
jmp options_init +fadeto options_init
mg_rules: mg_rules:
jmp rules_init +fadeto rules_init
mg_controls: mg_controls:
jmp controls_init +fadeto controls_init
mu_done: mu_done:
rts rts
+1 -1
View File
@@ -122,7 +122,7 @@ ou_done:
ou_back: ou_back:
lda #SFX_SELECT lda #SFX_SELECT
jsr sfx_play jsr sfx_play
jmp menu_init +fadeto menu_init
; ---- draw option line X, yellow when it is the picked one ---- ; ---- draw option line X, yellow when it is the picked one ----
draw_oitem: draw_oitem:
+5 -2
View File
@@ -6,6 +6,9 @@
lose_init: lose_init:
jsr clear_screen jsr clear_screen
lda #RED ; the border mourns with the letters
sta borbase
+prbig 3, 2, RED, txt_gameover, 9 +prbig 3, 2, RED, txt_gameover, 9
+prtext 11, 10, WHITE, txt_caught, txt_caughte-txt_caught +prtext 11, 10, WHITE, txt_caught, txt_caughte-txt_caught
@@ -28,7 +31,7 @@ lu_input:
; fire or space: straight back in with a fresh maze ; fire or space: straight back in with a fresh maze
jsr start_edge jsr start_edge
beq lu_nofire beq lu_nofire
jmp play_init +fadeto play_init
lu_nofire: lu_nofire:
; the m key: keyboard column 4, row bit 4 (start_edge has ; the m key: keyboard column 4, row bit 4 (start_edge has
; already returned zero here, so joystick fire is not ; already returned zero here, so joystick fire is not
@@ -40,7 +43,7 @@ lu_nofire:
bne lu_done bne lu_done
lda #$ff lda #$ff
sta CIA1_PA sta CIA1_PA
jmp menu_init +fadeto menu_init
lu_done: lu_done:
lda #$ff lda #$ff
sta CIA1_PA sta CIA1_PA
+491 -250
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -33,7 +33,7 @@ ru_hide:
ru_input: ru_input:
jsr start_edge jsr start_edge
beq ru_stay beq ru_stay
jmp menu_init +fadeto menu_init
ru_stay: ru_stay:
rts rts
+10 -1
View File
@@ -17,6 +17,15 @@ win_init:
rts rts
win_update: win_update:
; the border celebrates along on the same gold ramp
lda framectr
lsr
lsr
and #15
tax
lda washtbl,x
sta borbase
; the gold wash rolls down the big letters (rows 3-7) ; the gold wash rolls down the big letters (rows 3-7)
inc washphase inc washphase
lda #0 lda #0
@@ -62,7 +71,7 @@ wu_hide:
wu_input: wu_input:
jsr start_edge jsr start_edge
beq wu_stay beq wu_stay
jmp menu_init ; a win leads back to the main screen +fadeto menu_init ; a win leads back to the main screen
wu_stay: wu_stay:
rts rts