;;; -*- Mode: asm; indent-tabs-mode: t; tab-width: 8 -*- .include "c64.inc" .include "enum.asm" VMBASE = $0400 .org PROGSTART .include "init.asm" ;must come first .include "utilities.asm" ;; Start screen, waits for space key to be pressed. titlescreen: ;; More visually interesting sprite positioning for ;; the title screen. Overrides default from init. lda #$82 sta SPRITE_0Y ldx #%01111111 ldy #%00010000 jsr keydown bne @dontstart ;; Start the game here. jsr loadgamefield ;set the background lda #mode::MainGame ;don't forget that # sta gamemode ;set the game mode to MainGame @dontstart: rts ;; Wait and highlight the score change for half a second. ;; Happens every time a player scores or whatever it's called in tennis scorewait: ;; While waiting we play a buzz lda #$0f sta SIDFMV lda #$08 sta SIDAD1 lda #$68 sta SIDSR1 lda #$45 sta SIDF1L lda #$1d sta SIDF1H lda #$11 sta SIDCR1 dec timer bne @dontresume ;; Reset gamemode lda #mode::MainGame sta gamemode ;; Reset background color lda #0 sta BGCOL0 ;; Stop sound lda #$10 sta SIDCR1 @dontresume: rts ;; Call after a player scores to highlight the win highlightscore: lda #mode::ScoreHighlight sta gamemode lda #25 sta timer lda #2 sta BGCOL0 rts .include "gameloop.asm" ;; "Victory" mode when 100 points has been reached. win: dec timer bne @skip dec timer2 bne @continue ;; After five seconds (10 half-seconds) we reset the game jmp PROGSTART @continue: lda #25 sta timer lda BGCOL0 eor #8 sta BGCOL0 @skip: rts winstop: lda #25 sta timer lda #10 sta timer2 lda #$0d sta BGCOL0 lda #mode::Win ;DO NOT FORGET THE # sta gamemode rts ball_x_inc: inc ball_x bne @done ;; If ball_x incremented to zero we have either looped around ;; the screen (shouldn't happen) or crossed the bit 8 boundry. ;; So we set the MSB to one, since we're going right. lda #%00000100 ora SPRITE_X_MSB sta SPRITE_X_MSB @done: rts ball_x_dec: dec ball_x lda ball_x cmp #$ff bne @done ;; If ball_x incremented to zero we have either looped around ;; the screen (shouldn't happen) or crossed the bit 8 boundry. ;; So we set the MSB to one, since we're going right. lda #%11111011 and SPRITE_X_MSB sta SPRITE_X_MSB @done: rts ball_bounce_vert: jsr color_change lda #%10000000 eor balldata sta balldata rts ball_bounce_hori: jsr color_change lda #%01000000 eor balldata sta balldata rts reset_ball: jsr ball_bounce_hori lda #$90 sta ball_y lda #$c0 sta ball_x lda #%11111011 and SPRITE_X_MSB sta SPRITE_X_MSB rts color_change: inc bordercol lda bordercol and #$0f cmp #2 bcs @fine lda #2 sta bordercol @fine: lda bordercol sta BORDER rts handle_collision: jsr ball_bounce_hori ;obvious, flip the ball's horizontal direction lda #$00 sta col ;clear the collision flag rts ;; Cheap trick to make a hexprinted number look decimal. ;; Score comes in the A register, clamped score returned in A clampscore: tax and #%00001111 cmp #$0a bcc @noclamplower ;; yes clamp, inc upper nybble, ex. $19 -> $20 txa and #%11110000 clc adc #$10 tax @noclamplower: txa and #%11110000 cmp #$a0 bcc @noclamp ;; over 99? just stop at that point, we'll flash some colors then reset jsr winstop pla pla @noclamp: txa rts modedispatch: jsr jumpwithtable .addr titlescreen .addr game ;normal gameplay .addr scorewait .addr win ;; Main IRQ subroutine. CPU gets sent here by the interrupts from the ;; VIC-II's raster and collision interrupts, and is responsible for ;; calling everything else. Since the game is interrupt-driven, you ;; could add a RTS to the init code and have the game run together ;; with BASIC. Would be pretty stupid but you *can* do it. That does ;; give me an idea though... irq: lda SSCOL ;need to do this for collision checking to work lda #%00000100 ;check if irq is for collision or not and VICINT beq @nocol ;; Collision sta col ;set the collision flag lda #$7f and VICINT sta VICINT jmp @skipgame @nocol: lda gamemode jsr modedispatch @skipgame: lda #$7f and VICINT sta VICINT jmp $ea31 .include "variables.asm" BALLVERT = %10000000 BALLHORI = %01000000 BALLVSPEED = %00000010 BALLHSPEED = %00000001 .include "graphics.asm" .include "zeropage.asm"