From 97216d245d42a579b315a29bf96d50ec3023d815 Mon Sep 17 00:00:00 2001 From: Zsolt Tasnadi Date: Wed, 15 Jul 2026 22:39:08 +0200 Subject: [PATCH] intro screen --- README.md | 8 ++- common.asm | 41 ++++++++++----- intro.asm | 151 +++++++++++++++++++++++++++++++++++++++++++++++++++++ main.asm | 11 ++-- play.asm | 4 ++ title.asm | 12 +++-- 6 files changed, 205 insertions(+), 22 deletions(-) create mode 100644 intro.asm diff --git a/README.md b/README.md index fe63eb4..a422ac3 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,10 @@ in the original. ## How it works - PAL frame loop synced by polling the raster beam (no interrupts), one - state update per frame — title, play and game over are `updvec` states. + state update per frame — intro, menu, play and game over are `updvec` + states. Boot shows the giant TTG / Teletype Games logo with the gold + color wash from the c64-demo, then the menu with *fire = start game*; + losing brings up the final score with *fire = retry*. - The background is raster-split at the horizon: sky above, grass below. The road is a grey wedge of inverse-space characters between painted white edge lines, with trees along both shoulders. @@ -40,7 +43,8 @@ in the original. |------|----------| | `main.asm` | BASIC stub, init, frame loop, state dispatch | | `defs.asm` | registers, constants, zero page, macros | -| `title.asm` | title screen: logo, parked scooters, demo rabbits | +| `intro.asm` | boot screen: giant TTG logo with the gold wash | +| `title.asm` | menu screen: logo, start game, demo rabbits | | `play.asm` | gameplay: input, spawning, scoring, HUD | | `over.asm` | game over box + retry | | `common.asm` | shared routines: printing, road, input, RNG, rabbit positioning | diff --git a/common.asm b/common.asm index 70c56c9..d2623d2 100644 --- a/common.asm +++ b/common.asm @@ -67,7 +67,17 @@ draw_road: ldx #0 dr_loop: stx drtmp - txa + jsr road_row + ldx drtmp + inx + cpx #19 + bne dr_loop + jmp draw_trees + +; ---- redraw road row drtmp (0-18, char row 6+drtmp): +; edge chars + grey fill; also erases text printed over it ---- +road_row: + lda drtmp clc adc #6 ; road runs from char row 6 to row 24 tax @@ -90,21 +100,19 @@ dr_loop: lda #COL_EDGE sta (collo),y dey ; fill the surface between the edges -dr_fill: +rr_fill: cpy drleft - beq dr_rowdone + beq rr_done lda #$a0 ; inverse space: solid block sta (scrlo),y lda #COL_ROAD sta (collo),y dey - jmp dr_fill -dr_rowdone: - ldx drtmp - inx - cpx #19 - bne dr_loop -; falls through: the roadside trees + jmp rr_fill +rr_done: + rts + +; ---- the roadside trees ---- draw_trees: lda #0 sta ttidx @@ -537,14 +545,23 @@ txt_score: !scr "score" txt_miss: !scr "miss" txt_rabbit: !scr "rabbit" txt_scooter: !scr "scooter" -txt_press: !scr "press fire to start" -txt_info: !scr "joystick 2 or a/d fire starts" +txt_press: !scr "fire = start game" +txt_info: !scr "joystick 2 or a/d moves" +txt_ttgname: !scr "teletype games" +txt_presents:!scr "presents" txt_over: !scr "game over" txt_retry: !scr "fire = retry" txt_blank: !fill 19, $20 +washtbl: ; gold glow ramp (16 entries, cyclic) + !byte $09, $02, $08, $0a, $07, $07, $01, $01 + !byte $01, $01, $07, $07, $0a, $08, $02, $09 + ; ---- shared variables ---- framectr: !byte 0 ; frame counter, incremented by the main loop +washphase: !byte 0 ; gold wash offset on the intro letters +bg_top: !byte COL_SKY ; background color above / below the +bg_bot: !byte COL_GRASS ; horizon raster split seed: !byte $a7 ; rand8 LFSR state fheld: !byte 0 ; fire/space edge detection state joyb: !byte 0 ; joystick bits from read_joy (active high) diff --git a/intro.asm b/intro.asm new file mode 100644 index 0000000..9f6ddcd --- /dev/null +++ b/intro.asm @@ -0,0 +1,151 @@ +; ----------------------------------------------------------- +; intro.asm - boot screen in the spirit of the c64-demo: +; giant TTG letters built from 8x8 bitmaps with a gold color +; wash running down them, TELETYPE GAMES / PRESENTS below; +; advances to the menu after a few seconds or on fire +; ----------------------------------------------------------- + +INTRO_LROW = 3 ; top cell row of the giant letters +INTRO_TIME = 250 ; frames before it advances on its own + +intro_init: + lda #BLACK ; the intro plays on a black screen + sta bg_top + sta bg_bot + lda #0 + sta SPR_EN + jsr clear_screen + + ; T T G at columns 6 / 16 / 26 + lda #glyph_t + sta txthi + lda #6 + sta g8col + jsr draw_glyph8 + lda #16 + sta g8col + jsr draw_glyph8 + lda #glyph_g + sta txthi + lda #26 + sta g8col + jsr draw_glyph8 + + +prtext 13, 13, WHITE, txt_ttgname, 14 + +prtext 15, 16, LGREY, txt_presents, 8 + + lda #INTRO_TIME + sta introt + lda #0 + sta washphase + +setupd intro_update + rts + +intro_update: + ; gold wash: recolor the letter rows from the cyclic ramp + inc washphase + lda #0 + sta g8row +iw_row: + lda #INTRO_LROW + clc + adc g8row + tax + jsr row_ptr + lda washphase + lsr ; half speed keeps the shimmer gentle + clc + adc g8row + and #15 + tax + lda washtbl,x + sta rtmp + ldy #33 ; the letters span columns 6-33 +iw_col: + lda (scrlo),y + cmp #$a0 ; only touch the letter blocks + bne iw_skip + lda rtmp + sta (collo),y +iw_skip: + dey + cpy #5 + bne iw_col + inc g8row + lda g8row + cmp #8 + bne iw_row + + ; fire skips, otherwise wait out the timer + jsr start_edge + beq iw_tick + jmp title_init +iw_tick: + dec introt + bne iw_done + jmp title_init +iw_done: + rts + +; ---- draw an 8x8-cell giant letter: txtlo/hi = 8-byte +; bitmap, g8col = left cell column ---- +draw_glyph8: + lda #0 + sta g8row +g8_row: + lda #INTRO_LROW + clc + adc g8row + tax + jsr row_ptr + ldy g8row + lda (txtlo),y + sta curbits + ldy g8col + lda #8 + sta bitcnt +g8_bit: + asl curbits ; leftmost pixel first + bcc g8_next + lda #$a0 ; inverse space = solid block + sta (scrlo),y + lda #YELLOW + sta (collo),y +g8_next: + iny + dec bitcnt + bne g8_bit + inc g8row + lda g8row + cmp #8 + bne g8_row + rts + +; ---- 8x8 letter bitmaps ---- +glyph_t: + !byte %11111111 + !byte %11111111 + !byte %00111100 + !byte %00111100 + !byte %00111100 + !byte %00111100 + !byte %00111100 + !byte %00111100 +glyph_g: + !byte %00111100 + !byte %01111110 + !byte %11000011 + !byte %11000000 + !byte %11001111 + !byte %11000011 + !byte %01111110 + !byte %00111100 + +; ---- intro variables ---- +introt: !byte 0 ; frames left before auto-advancing +g8row: !byte 0 ; glyph renderer / wash internals +g8col: !byte 0 diff --git a/main.asm b/main.asm index 866a811..34e1ecd 100644 --- a/main.asm +++ b/main.asm @@ -65,7 +65,7 @@ sprcol: !ifdef AUTOPLAY { ; test builds boot straight into the game jsr play_init } else { - jsr title_init + jsr intro_init ; TTG logo, then the menu } ; ============================================================ @@ -74,16 +74,16 @@ sprcol: ; ============================================================ main: jsr wait_frame - lda #COL_SKY ; repaint the sky while the beam is off screen + lda bg_top ; repaint the sky while the beam is off screen sta BG inc framectr jsr rand8 ; stir the RNG once per frame jsr call_update ; finishes long before the horizon line wait_grass: lda RASTER ; split the background at the horizon: - cmp #RAS_SPLIT ; sky above, grass below - bne wait_grass - lda #COL_GRASS + cmp #RAS_SPLIT ; sky above, grass below (the intro + bne wait_grass ; sets both halves to black) + lda bg_bot sta BG jmp main @@ -114,6 +114,7 @@ wf_hit: ; ============================================================ ; the states and everything they share ; ============================================================ +!src "intro.asm" !src "title.asm" !src "play.asm" !src "over.asm" diff --git a/play.asm b/play.asm index c500144..95cd58e 100644 --- a/play.asm +++ b/play.asm @@ -6,6 +6,10 @@ ; ---- start (or restart) a round ---- play_init: + lda #COL_SKY ; in case we come from a black screen + sta bg_top + lda #COL_GRASS + sta bg_bot jsr clear_screen jsr draw_road diff --git a/title.asm b/title.asm index f53ef9c..9a1ac2e 100644 --- a/title.asm +++ b/title.asm @@ -5,12 +5,16 @@ ; ----------------------------------------------------------- title_init: + lda #COL_SKY ; back from the intro's black screen + sta bg_top + lda #COL_GRASS + sta bg_bot jsr clear_screen jsr draw_road +prbig 1, 8, RED, txt_rabbit, 6 +prtext 6, 16, WHITE, txt_scooter, 7 - +prtext 17, 4, WHITE, txt_info, 31 + +prtext 17, 8, WHITE, txt_info, 23 ; one parked scooter per lane on sprites 0-4, all in red ldx #4 @@ -86,10 +90,12 @@ tu_pos: lda framectr and #32 bne tu_hide - +prtext 15, 10, YELLOW, txt_press, 19 + +prtext 15, 11, YELLOW, txt_press, 17 jmp tu_start tu_hide: - +prtext 15, 10, YELLOW, txt_blank, 19 + lda #9 ; hide: repaint road row 15 over the text + sta drtmp + jsr road_row tu_start: jsr start_edge beq tu_done