PALETTE_CACHE .rs 32 ; temporary memory for palette, for dimming ; cursors target coordinates SPRITE_0_X_TARGET .rs 1 SPRITE_1_X_TARGET .rs 1 SPRITE_Y_TARGET .rs 1 ; variables for game name drawing TEXT_DRAW_GAME .rs 2 TEXT_DRAW_ROW .rs 1 SCROLL_LINES .rs 2 ; current scroll line SCROLL_LINES_MODULO .rs 1 ; current scroll line % 30 LAST_LINE_MODULO .rs 1 LAST_LINE_GAME .rs 2 SCROLL_FINE .rs 1 ; fine scroll position SCROLL_LINES_TARGET .rs 2 ; scrolling target STAR_SPAWN_TIMER .rs 1 ; stars spawn timer STAR_SPAWN_COUNTER .rs 1 ; stars spawn counter ; for build info CHR_RAM_SIZE .rs 1 ; CHR RAM size 8*2^xKB LAST_ATTRIBUTE_ADDRESS .rs 1 ; to prevent duplicate writes SCHEDULE_PRINT_FIRST .rs 1 SCHEDULE_PRINT_LAST .rs 1 ; flag to lock scrollin at zero SCROLL_LOCK .rs 1 ; constants CHARS_PER_LINE .equ 32 LINES_PER_SCREEN .equ 15 SPRITE_0_Y .equ SPRITES + 0 SPRITE_0_TILE .equ SPRITES + 1 SPRITE_0_ATTR .equ SPRITES + 2 SPRITE_0_X .equ SPRITES + 3 SPRITE_1_Y .equ SPRITES + 4 SPRITE_1_TILE .equ SPRITES + 5 SPRITE_1_ATTR .equ SPRITES + 6 SPRITE_1_X .equ SPRITES + 7 waitblank: pha tya pha txa pha bit PPUSTATUS ; reset vblank bit .loop: lda PPUSTATUS ; load A with value at location PPUSTATUS bpl .loop ; if bit 7 is not set (not VBlank) keep checking ; updating sprites jsr sprite_dma_copy lda SCHEDULE_PRINT_FIRST beq .first_not_scheduled jsr print_first_name lda #0 sta SCHEDULE_PRINT_FIRST .first_not_scheduled: lda SCHEDULE_PRINT_LAST beq .last_not_scheduled jsr print_last_name lda #0 sta SCHEDULE_PRINT_LAST .last_not_scheduled: jsr scroll_fix ; scrolling lda SCROLL_LOCK bne .skip_scrolling jsr move_scrolling .skip_scrolling: ; moving cursors jsr move_cursors ; reading controller jsr read_controller ; stars on the background .if STARS!=0 jsr stars .endif pla tax pla tay pla rts waitblank_simple: pha bit PPUSTATUS .loop: lda PPUSTATUS ; load A with value at location PPUSTATUS bpl .loop ; if bit 7 is not set (not VBlank) keep checking pla rts waitblank_x: ; for for v-blank X times cpy #0 bne .loop rts .loop: jsr waitblank dex bne .loop rts scroll_fix: pha tya pha ; scrolling reset bit PPUSTATUS ; X coordinate always 0 lda #0 sta PPUSCROLL ldy SCROLL_LOCK beq .need_to_scroll ; scolling is locked sta PPUSCROLL ldy #%00001000 ; first nametable sty PPUCTRL ; set base nametable jmp .scroll_done .need_to_scroll: lda > 8) & $FF sta > 8) & $FF sta > 8) & $FF sta > 8) & $FF sta 0 .endif jsr preload_base_palette jsr dim jsr dim jsr dim jsr load_palette ldx #DIM_IN_DELAY jsr waitblank_x ;lda BUTTONS ;bne .done ; skip if any button pressed jsr preload_base_palette jsr dim jsr dim jsr load_palette ldx #DIM_IN_DELAY jsr waitblank_x ;lda BUTTONS ;bne .done ; skip if any button pressed jsr preload_base_palette jsr dim jsr load_palette ldx #DIM_IN_DELAY jsr waitblank_x .endif .done: jsr preload_base_palette jsr load_palette jsr waitblank rts ; dimming base palette out in dim_base_palette_out: .if ENABLE_DIM_OUT!=0 .if DIM_OUT_DELAY <= 0 .fail DIM_OUT_DELAY must be > 0 .endif jsr preload_base_palette jsr dim jsr load_palette ldx #DIM_OUT_DELAY jsr waitblank_x jsr preload_base_palette jsr dim jsr dim jsr load_palette ldx #DIM_OUT_DELAY jsr waitblank_x jsr preload_base_palette jsr dim jsr dim jsr dim jsr load_palette ldx #DIM_OUT_DELAY jsr waitblank_x .endif jsr load_black jsr waitblank rts ; loading empty black palette into $3F00 of PPU load_black: ; waiting for vblank ; need even if rendering is disabled ; to prevent lines on black screen jsr waitblank_simple lda #$3F sta PPUADDR lda #$00 sta PPUADDR ldx #$00 lda #$3F ; color .loop: sta PPUDATA inx cpx #32 bne .loop rts ; nametable cleanup clear_screen: lda #$20 sta PPUADDR lda #$00 sta PPUADDR lda #$00 ldx #0 ldy #$10 .loop: sta PPUDATA inx bne .loop dey bne .loop rts ; clear all sprites data clear_sprites: lda #$FF ldx #0 .loop: sta SPRITES, x inx bne .loop rts ; DMA sprites loading sprite_dma_copy: pha lda #0 sta OAMADDR lda #HIGH(SPRITES) sta OAMDMA pla rts ; loading header (image on the top), first part draw_header1: lda #BANK(nametable_header) / 2 ; bank with header jsr select_prg_bank ldx #0 ldy #$40 .loop: lda nametable_header, x sta PPUDATA inx dey bne .loop rts ; loading header (image on the top), second part draw_header2: lda #BANK(nametable_header) / 2 ; bank with header jsr select_prg_bank ldx #$40 ldy #$40 .loop: lda nametable_header, x sta PPUDATA inx dey bne .loop rts ; loading footer (image on the bottom), first part draw_footer1: lda #$06 jsr select_prg_bank ldx #0 ldy #$40 .loop: lda nametable_footer, x sta PPUDATA inx dey bne .loop rts ; loading footer (image on the bottom), second part draw_footer2: lda #$06 jsr select_prg_bank ldx #$40 ldy #$40 .loop: lda nametable_footer, x sta PPUDATA inx dey bne .loop rts ; printing game name on the top print_first_name: pha lda > 8) & $FF bne .not_footer_1 lda > 8) & $FF bne .not_footer_2 lda > 8) & $FF bcs .end lda > 8) & $FF bne .not_footer lda =16 lda #0 sta 0 .endif .if STARS > 62 .fail STARS must be <= 62 .endif stars: ; one time spawner lda