Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/coolboy-multirom-builder.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2020-09-17 19:48:27 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2020-09-17 19:48:27 +0300
commitb03de3e3eaf063dce942de66bbb3ebef21619a38 (patch)
tree82d3000b6841209c285ea8c9e0df74a544719cb1 /video.asm
parentb3c6426a170f0b1912eecc5ca342fec4deb9d90b (diff)
Spaces
Diffstat (limited to 'video.asm')
-rw-r--r--video.asm1826
1 files changed, 913 insertions, 913 deletions
diff --git a/video.asm b/video.asm
index 9c4fd40..2c0be23 100644
--- a/video.asm
+++ b/video.asm
@@ -1,913 +1,913 @@
- ; cursors target coordinates
-SPRITE_0_X_TARGET .rs 1
-SPRITE_0_Y_TARGET .rs 1
-SPRITE_1_X_TARGET .rs 1
-SPRITE_1_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
-
- ; constants
-CHARS_PER_LINE .equ 32
-LINES_PER_SCREEN .equ 30
-LINES_PER_VISIBLE_SCREEN .equ 15
-
-waitblank:
- pha
- tya
- pha
- txa
- pha
-
- bit $2002 ; reset vblank bit
-.loop:
- lda $2002 ; load A with value at location $2002
- bpl .loop ; if bit 7 is not set (not VBlank) keep checking
-
- ; scrolling
- jsr move_scrolling
- jsr scroll_fix
- ; updating sprites
- jsr sprite_dma_copy
- ; moving cursors
- jsr move_cursors
- ; reading controller
- jsr read_controller
- ; stars on the background
- .if ENABLE_STARS!=0
- jsr stars
- .endif
-
- pla
- tax
- pla
- tay
- pla
- ;plp
- rts
-
-waitblank_simple:
- pha
- bit $2002
-.loop:
- lda $2002 ; load A with value at location $2002
- bpl .loop ; if bit 7 is not set (not VBlank) keep checking
- pla
- rts
-
-scroll_fix:
- ; scrollong reset
- bit $2002
- lda #0
- sta $2005
- lda <SCROLL_LINES_MODULO
- cmp #LINES_PER_VISIBLE_SCREEN
- bcc .first_screen ; <?
- sec
- sbc #LINES_PER_VISIBLE_SCREEN ; substracting otherwise
- ldy #%00001010 ; second nametable
- jmp .really
-.first_screen:
- ldy #%00001000 ; first nametable
-.really:
- sty $2000
- asl A
- asl A
- asl A
- asl A
- clc
- adc <SCROLL_FINE
- .if ENABLE_TOP_OFFSET!=0
- sec ; для больших картинок сверху
- sbc #8 ; для больших картинок сверху
- .endif
- sta $2005
- rts
-
-scroll_line_down:
- lda <SCROLL_LINES
- clc
- adc #1
- sta <SCROLL_LINES
- lda <SCROLL_LINES+1
- adc #0
- sta <SCROLL_LINES+1
- inc <SCROLL_LINES_MODULO
- lda <SCROLL_LINES_MODULO
- cmp #LINES_PER_SCREEN
- bcc .modulo_ok
- lda #0
- sta <SCROLL_LINES_MODULO
-.modulo_ok:
- lda <LAST_LINE_GAME
- clc
- adc #1
- sta <LAST_LINE_GAME
- lda <LAST_LINE_GAME+1
- adc #0
- sta <LAST_LINE_GAME+1
- inc <LAST_LINE_MODULO
- lda <LAST_LINE_MODULO
- cmp #LINES_PER_SCREEN
- bcc .modulo_ok2
- lda #0
- sta <LAST_LINE_MODULO
-.modulo_ok2:
- jsr print_last_name
- rts
-
-scroll_line_up:
- lda <SCROLL_LINES
- sec
- sbc #1
- sta <SCROLL_LINES
- lda <SCROLL_LINES+1
- sbc #0
- sta <SCROLL_LINES+1
- dec <SCROLL_LINES_MODULO
- lda <SCROLL_LINES_MODULO
- bpl .modulo_ok
- lda #LINES_PER_SCREEN
- sta <SCROLL_LINES_MODULO
- dec <SCROLL_LINES_MODULO
-.modulo_ok:
- lda <LAST_LINE_GAME
- sec
- sbc #1
- sta <LAST_LINE_GAME
- lda <LAST_LINE_GAME+1
- sbc #0
- sta <LAST_LINE_GAME+1
- dec <LAST_LINE_MODULO
- lda <LAST_LINE_MODULO
- bpl .modulo_ok2
- lda #LINES_PER_SCREEN
- sta <LAST_LINE_MODULO
- dec <LAST_LINE_MODULO
-.modulo_ok2:
- jsr print_first_name
- rts
-
-load_base_chr:
- ; loading CHR
- lda #$06
- jsr select_bank
- lda #LOW(chr_data)
- sta COPY_SOURCE_ADDR
- lda #HIGH(chr_data)
- sta COPY_SOURCE_ADDR+1
- jsr load_chr
- rts
-
-load_base_pal:
- ; loading palette into $3F00 of PPU
- lda #$3F
- sta $2006
- lda #$00
- sta $2006
- ldx #$00
-loadpal:
- lda tilepal, x
- sta $2007
- inx
- cpx #32
- bne loadpal
-
- ; letters colors
- lda #$3F
- sta $2006
- lda #$0D
- sta $2006
- ldx #17
-loadpal2:
- lda tilepal, x
- sta $2007
- inx
- cpx #20
- bne loadpal2
- rts
-
-load_black:
- ; loading empty black palette into $3F00 of PPU
- lda #$3F
- sta $2006
- lda #$00
- sta $2006
- ldx #$00
- lda #$3F ; color
-load_black_pal:
- sta $2007
- inx
- cpx #32
- bne load_black_pal
- rts
-
- ; nametable cleanup
-clear_screen:
- lda #$20
- sta $2006
- lda #$00
- sta $2006
- lda #$00
- ldx #0
- ldy #$10
-.loop:
- sta $2007
- 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:
- ldx #0
- stx $2003
- ldx #HIGH(SPRITES)
- stx $4014
- rts
-
- ; loading header (image on the top), first part
-draw_header1:
- lda #$06
- jsr select_bank
- bit $2002
- lda #$20
- sta $2006
- lda #$00
- sta $2006
- ldx #0
- ldy #$40
-.loop:
- lda nametable, x
- sta $2007
- inx
- dey
- bne .loop
- rts
-
- ; loading header (image on the top), second part
-draw_header2:
- lda #$06
- jsr select_bank
- bit $2002
- lda #$20
- sta $2006
- lda #$40
- sta $2006
- ldx #$40
- ldy #$40
-.loop:
- lda nametable, x
- sta $2007
- inx
- dey
- bne .loop
- ; loading attributes for it
- lda #$23
- sta $2006
- lda #$C0
- sta $2006
- ldx #0
- ldy #8
-.palette_loop:
- lda nametable+$3C0, x
- sta $2007
- inx
- dey
- bne .palette_loop
- rts
-
- ; loading footer (image on the bottom), first part
-draw_footer1:
- lda #$06
- jsr select_bank
- ldx #0
- ldy #$40
-.loop:
- lda nametable+$340, x
- sta $2007
- inx
- dey
- bne .loop
- rts
-
- ; loading footer (image on the bottom), second part
-draw_footer2:
- lda #$06
- jsr select_bank
- ldx #0
- ldy #$40
-.loop:
- lda nametable+$380, x
- sta $2007
- inx
- dey
- bne .loop
- rts
-
- ; printing game name on the top
-print_first_name:
- pha
- lda <SCROLL_LINES
- sta <TEXT_DRAW_GAME
- lda <SCROLL_LINES+1
- sta <TEXT_DRAW_GAME+1
- lda <SCROLL_LINES_MODULO
- sta <TEXT_DRAW_ROW
- jsr print_name
- pla
- rts
-
- ; printing game name on the bottom
-print_last_name:
- pha
- lda <LAST_LINE_GAME
- sta <TEXT_DRAW_GAME
- lda <LAST_LINE_GAME+1
- sta <TEXT_DRAW_GAME+1
- lda <LAST_LINE_MODULO
- sta <TEXT_DRAW_ROW
- jsr print_name
- pla
- rts
-
-print_name:
- pha
- tya
- pha
- txa
- pha
- ; is it header lines?
- lda <TEXT_DRAW_GAME+1
- bne .not_header ; no
- lda <TEXT_DRAW_GAME
- beq .header1
- cmp #1
- beq .header2
- jmp .not_header
-.header1:
- jsr draw_header1
- jmp .end_really_really
-.header2:
- jsr draw_header2
- jmp .end_really_really
-.not_header:
- ; when there are not so many games we need so offset
- lda <TEXT_DRAW_ROW
- clc
- adc games_offset
- sta <TEXT_DRAW_ROW
- asl <TEXT_DRAW_ROW ; x2
- lda <TEXT_DRAW_ROW
- ; detecting target nametable
- cmp #LINES_PER_SCREEN
- bcc .first_screen
- ; second
- sec
- sbc #LINES_PER_SCREEN
- lsr A
- lsr A
- lsr A
- clc
- adc #$2C
- bit $2002
- sta $2006
- lda <TEXT_DRAW_ROW
- sec
- sbc #LINES_PER_SCREEN
- asl A
- asl A
- asl A
- asl A
- asl A
- sta $2006
- jmp .print_end
- ; first
-.first_screen:
- lsr A
- lsr A
- lsr A
- clc
- adc #$20
- bit $2002
- sta $2006
- lda <TEXT_DRAW_ROW
- asl A
- asl A
- asl A
- asl A
- asl A
- sta $2006
-.print_end:
- ; we need to substract 2 from game number
- lda <TEXT_DRAW_GAME
- sec
- sbc #2
- sta <TEXT_DRAW_GAME
- lda <TEXT_DRAW_GAME+1
- sbc #0
- sta <TEXT_DRAW_GAME+1
- ; is it footer?
- lda <TEXT_DRAW_GAME
- sec
- sbc games_count
- lda <TEXT_DRAW_GAME+1
- sbc games_count+1
- bcc .print_text_line
- ldx <TEXT_DRAW_GAME
- cpx games_count
- beq .footer1
- dex
- cpx games_count
- beq .footer2
- jmp .end
-.footer2:
- jsr draw_footer2
- ; lets keep for footer text palette, i like how it looks
- jmp .end
-.footer1:
- jsr draw_footer1
- jmp .end
-.print_text_line:
- lda <TEXT_DRAW_GAME+1
- jsr select_bank
- lda #LOW(game_names)
- clc
- adc <TEXT_DRAW_GAME
- sta <TMP
- lda #HIGH(game_names)
- adc #0
- sta <TMP+1
- lda <TMP
- clc
- adc <TEXT_DRAW_GAME
- sta <TMP
- lda <TMP+1
- adc #0
- sta <TMP+1
- ldy #0
- lda [TMP], y
- sta COPY_SOURCE_ADDR
- iny
- lda [TMP], y
- sta COPY_SOURCE_ADDR+1
- ; spaces on the left
- ldx #GAME_NAMES_OFFSET+1
-.print_blank:
- lda #$00
- sta $2007
- dex
- bne .print_blank
- ; text
- ldx #GAME_NAMES_OFFSET+1
- ldy #0
- lda #1
-.next_char:
- cmp #0 ; after zero we are not printing letters but printing spaces
- beq .end_of_line
- lda [COPY_SOURCE_ADDR], y
-.end_of_line:
- sta $2007
- iny
- inx
- cpx #CHARS_PER_LINE
- bne .next_char
-.end:
- ; but if it upper part, we need to erase two lines
- lda <TEXT_DRAW_ROW
- cmp #4
- bcs .end_really
- ldy #CHARS_PER_LINE
- lda #0
-.clear_2nd_line:
- sta $2007
- dey
- bne .clear_2nd_line
-.end_really:
- ; attributes for text
- lda <TEXT_DRAW_ROW
- cmp #LINES_PER_SCREEN
- bcc .print_palette_addr_first_screen
- ; second nametable
- lda #$2F
- sta $2006
- lda <TEXT_DRAW_ROW
- sec
- sbc #LINES_PER_SCREEN
- jmp .print_palette_addr_select_end
- ; first nametable
-.print_palette_addr_first_screen:
- lda #$23
- sta $2006
- lda <TEXT_DRAW_ROW
-.print_palette_addr_select_end:
- ; one byte for 4 rows
- lsr A
- lsr A
- asl A
- asl A
- asl A
- clc
- adc #$C0
- sta $2006
- lda #$FF
- sta $2007
- sta $2007
- sta $2007
- sta $2007
- sta $2007
- sta $2007
- sta $2007
- sta $2007
-.end_really_really:
- pla
- tax
- pla
- tay
- pla
- rts
-
-move_cursors:
- ; fine cursor scrolling
- lda <SPRITE_1_X_TARGET
- cmp SPRITE_1_X
- beq .sprite_1x_target_end
- bcs .sprite_1x_target_plus
- lda SPRITE_1_X
- sec
- sbc #4
- sta SPRITE_1_X
- jmp .sprite_1x_target_end
-.sprite_1x_target_plus:
- lda SPRITE_1_X
- clc
- adc #4
- sta SPRITE_1_X
-.sprite_1x_target_end:
- lda <SPRITE_1_Y_TARGET
- cmp SPRITE_1_Y
- beq .sprite_1y_target_end
- bcs .sprite_1y_target_plus
- lda SPRITE_1_Y
- sec
- sbc #4
- sta SPRITE_0_Y
- sta SPRITE_1_Y
- jmp .sprite_1y_target_end
-.sprite_1y_target_plus:
- lda SPRITE_1_Y
- clc
- adc #4
- sta SPRITE_0_Y
- sta SPRITE_1_Y
-.sprite_1y_target_end:
- rts
-
- ; fine scrolling to target line
-move_scrolling:
- ; determining scroll speed
- lda <SCROLL_LINES
- clc
- adc #2
- sta <TMP
- lda <SCROLL_LINES+1
- adc #0
- sta <TMP+1
- lda <SCROLL_LINES_TARGET
- sec
- sbc <TMP
- lda <SCROLL_LINES_TARGET+1
- sbc <TMP+1
- bcs .move_scrolling_fast_down
- lda <SCROLL_LINES_TARGET
- clc
- adc #2
- sta <TMP
- lda <SCROLL_LINES_TARGET+1
- adc #0
- sta <TMP+1
- lda <SCROLL_LINES
- sec
- sbc <TMP
- lda <SCROLL_LINES+1
- sbc <TMP+1
- bcs .move_scrolling_fast_up
- ; slow scrolling
- jsr .move_scrolling_real
- rts
- ; fast scrolling
-.move_scrolling_fast:
- jsr .move_scrolling_real
- jsr .move_scrolling_real
- jsr .move_scrolling_real
- jsr .move_scrolling_real
- rts
-.move_scrolling_fast_up:
- jmp scroll_line_up
-.move_scrolling_fast_down:
- jmp scroll_line_down
-.move_scrolling_real:
- ; do we need to move screen?
- ldx <SCROLL_LINES_TARGET
- cpx <SCROLL_LINES
- bne .need
- ldx <SCROLL_LINES_TARGET+1
- cpx <SCROLL_LINES+1
- bne .need
- ldx <SCROLL_FINE
- bne .need
- rts
- ; we need it
-.need:
- lda <SCROLL_LINES
- sec
- sbc <SCROLL_LINES_TARGET
- lda <SCROLL_LINES+1
- sbc <SCROLL_LINES_TARGET+1
- bcc .target_plus
- ; scrolling up
- lda <SCROLL_FINE
- sec
- sbc #4
- bmi .target_minus
- sta <SCROLL_FINE
- rts
-.target_minus:
- and #$0f
- sta <SCROLL_FINE
- jsr scroll_line_up
- rts
-.target_plus:
- ; scrolling down
- lda <SCROLL_FINE
- ; adding fine value
- clc
- adc #4
- sta <SCROLL_FINE
- cmp #16
- bne .end
- ; down if fine >=16
- lda #0
- sta <SCROLL_FINE
- jsr scroll_line_down
-.end:
- rts
-
-set_cursor_targets:
- ; set scroll targets first
-.not_ok1:
- lda <SCROLL_LINES_TARGET
- clc
- adc #10
- sta <TMP
- lda <SCROLL_LINES_TARGET+1
- adc #0
- sta <TMP+1
- lda <TMP
- sec
- sbc <SELECTED_GAME
- lda <TMP+1
- sbc <SELECTED_GAME+1
- bcs .ok1 ; надо скроллить вниз
- lda <SCROLL_LINES_TARGET
- clc
- adc #1
- sta <SCROLL_LINES_TARGET
- lda <SCROLL_LINES_TARGET+1
- adc #0
- sta <SCROLL_LINES_TARGET+1
- jmp .not_ok1
-.ok1:
-.not_ok2:
- lda <SELECTED_GAME
- sec
- sbc <SCROLL_LINES_TARGET
- lda <SELECTED_GAME+1
- sbc <SCROLL_LINES_TARGET+1
- bcs .ok2 ; надо скроллить вверх
- lda <SCROLL_LINES_TARGET
- sec
- sbc #1
- sta <SCROLL_LINES_TARGET
- lda <SCROLL_LINES_TARGET+1
- sbc #0
- sta <SCROLL_LINES_TARGET+1
- jmp .not_ok2
-.ok2:
- ; set cursor targets depending on selected game number
- ; left cursor, X
- ldx <SELECTED_GAME
- lda #GAME_NAMES_OFFSET*8
- sta <SPRITE_0_X_TARGET
- ; right cursor, X
- lda <SELECTED_GAME+1
- jsr select_bank
- ldx <SELECTED_GAME
- ldy loader_data_cursor_pos, x
- dey
- tya
- clc
- adc #GAME_NAMES_OFFSET+2
- asl A
- asl A
- asl A
- sta <SPRITE_1_X_TARGET
- ; Y coordinate it the same for both
- lda <SELECTED_GAME
- ; when there are not so many games
- clc
- adc games_offset
- sec
- sbc <SCROLL_LINES_TARGET
- clc
- adc #2
- asl A
- asl A
- asl A
- asl A
- sec
- sbc #1
- .if ENABLE_TOP_OFFSET!=0 ; for large images on top
- clc
- adc #8
- .endif
- sta <SPRITE_0_Y_TARGET
- sta <SPRITE_1_Y_TARGET
- rts
-
-stars:
- lda <STAR_SPAWN_TIMER
- cmp #$E0 ; stars count
- beq .spawn_end
- inc <STAR_SPAWN_TIMER
- lda <STAR_SPAWN_TIMER
- and #$0F
- cmp #0
- bne .spawn_end
- lda <STAR_SPAWN_TIMER
- lsr A
- lsr A
- tay
- lda <STAR_SPAWN_TIMER
- lda #$FC ; Y, below screen
- sta SPRITES+4, y
- iny
- jsr random ; random tile
- and #$03
- clc
- adc #$71
- sta SPRITES+4, y
- iny
- jsr random ; attributes, random palette
- and #%00000011 ; palette - tho lowest bits
- ora #%00100000 ; low priority bit
- sta SPRITES+4, y
- iny
- jsr random
- sta SPRITES+4, y
-.spawn_end:
- ldy #8
-.move_next:
- lda SPRITES, y
- cmp #$FF
- beq .move_end
- tya
- lsr A
- lsr A
- and #$07
- cmp #$00
- beq .move_fast
- cmp #$01
- beq .move_fast
- cmp #$02
- beq .move_fast
- cmp #$03
- beq .move_medium
- cmp #$04
- beq .move_medium
- cmp #$05
- beq .move_slow
- cmp #$06
- beq .move_slow
-.move_very_slow: ; default
- lda SPRITES, y
- sbc #1
- jmp .moved
-.move_slow:
- lda SPRITES, y
- sec
- sbc #2
- jmp .moved
-.move_medium:
- lda SPRITES, y
- sec
- sbc #3
- jmp .moved
-.move_fast:
- lda SPRITES, y
- sec
- sbc #4
-.moved:
- sta SPRITES, y
- cmp #$0A
- bcs .move_next1
- lda #$FC
- sta SPRITES, y ; reset Y
- jsr random ; random tile
- and #$03
- clc
- adc #$71
- sta SPRITES+1, y
- jsr random ; random X
- sta SPRITES+3, y
- jsr random ; random attributes
- and #%00000011 ; palette - lowest tho bits
- ora #%00100000 ; priority bit
- sta SPRITES+2, y
-.move_next1:
- iny
- iny
- iny
- iny
- bne .move_next
-.move_end:
- rts
-
-load_text_palette:
- lda #$23
- sta $2006
- lda #$C8
- sta $2006
- lda #$FF
- ldy #$38
-.print_warning_palette:
- sta $2007
- dey
- bne .print_warning_palette
- rts
-
- ; print null-terminated string from [COPY_SOURCE_ADDR]
-print_text:
- ldy #0
-.loop:
- lda [COPY_SOURCE_ADDR], y
- sta $2007
- iny
- cmp #0 ; stop at zero
- bne .loop
- rts
-
-saving_warning_show:
- ; disable PPU
- lda #%00000000
- sta $2000
- sta $2001
- jsr waitblank_simple
- jsr clear_screen
- lda #$21
- sta $2006
- lda #$C0
- sta $2006
- lda #LOW(saving_text)
- sta COPY_SOURCE_ADDR
- lda #HIGH(saving_text)
- sta COPY_SOURCE_ADDR+1
- jsr print_text
- jsr load_text_palette
- jsr waitblank_simple
- bit $2002
- lda #0
- sta $2005
- sta $2005
- lda #%00001000
- sta $2000
- lda #%00001010
- sta $2001
- jsr waitblank_simple
- rts
-
-saving_warning_hide:
- lda #%00000000 ; disable PPU
- sta $2000
- sta $2001
- jsr waitblank_simple
- jsr clear_screen
- rts
+ ; cursors target coordinates
+SPRITE_0_X_TARGET .rs 1
+SPRITE_0_Y_TARGET .rs 1
+SPRITE_1_X_TARGET .rs 1
+SPRITE_1_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
+
+ ; constants
+CHARS_PER_LINE .equ 32
+LINES_PER_SCREEN .equ 30
+LINES_PER_VISIBLE_SCREEN .equ 15
+
+waitblank:
+ pha
+ tya
+ pha
+ txa
+ pha
+
+ bit $2002 ; reset vblank bit
+.loop:
+ lda $2002 ; load A with value at location $2002
+ bpl .loop ; if bit 7 is not set (not VBlank) keep checking
+
+ ; scrolling
+ jsr move_scrolling
+ jsr scroll_fix
+ ; updating sprites
+ jsr sprite_dma_copy
+ ; moving cursors
+ jsr move_cursors
+ ; reading controller
+ jsr read_controller
+ ; stars on the background
+ .if ENABLE_STARS!=0
+ jsr stars
+ .endif
+
+ pla
+ tax
+ pla
+ tay
+ pla
+ ;plp
+ rts
+
+waitblank_simple:
+ pha
+ bit $2002
+.loop:
+ lda $2002 ; load A with value at location $2002
+ bpl .loop ; if bit 7 is not set (not VBlank) keep checking
+ pla
+ rts
+
+scroll_fix:
+ ; scrollong reset
+ bit $2002
+ lda #0
+ sta $2005
+ lda <SCROLL_LINES_MODULO
+ cmp #LINES_PER_VISIBLE_SCREEN
+ bcc .first_screen ; <?
+ sec
+ sbc #LINES_PER_VISIBLE_SCREEN ; substracting otherwise
+ ldy #%00001010 ; second nametable
+ jmp .really
+.first_screen:
+ ldy #%00001000 ; first nametable
+.really:
+ sty $2000
+ asl A
+ asl A
+ asl A
+ asl A
+ clc
+ adc <SCROLL_FINE
+ .if ENABLE_TOP_OFFSET!=0
+ ; for large images on the top
+ sec
+ sbc #8
+ .endif
+ sta $2005
+ rts
+
+scroll_line_down:
+ lda <SCROLL_LINES
+ clc
+ adc #1
+ sta <SCROLL_LINES
+ lda <SCROLL_LINES+1
+ adc #0
+ sta <SCROLL_LINES+1
+ inc <SCROLL_LINES_MODULO
+ lda <SCROLL_LINES_MODULO
+ cmp #LINES_PER_SCREEN
+ bcc .modulo_ok
+ lda #0
+ sta <SCROLL_LINES_MODULO
+.modulo_ok:
+ lda <LAST_LINE_GAME
+ clc
+ adc #1
+ sta <LAST_LINE_GAME
+ lda <LAST_LINE_GAME+1
+ adc #0
+ sta <LAST_LINE_GAME+1
+ inc <LAST_LINE_MODULO
+ lda <LAST_LINE_MODULO
+ cmp #LINES_PER_SCREEN
+ bcc .modulo_ok2
+ lda #0
+ sta <LAST_LINE_MODULO
+.modulo_ok2:
+ jsr print_last_name
+ rts
+
+scroll_line_up:
+ lda <SCROLL_LINES
+ sec
+ sbc #1
+ sta <SCROLL_LINES
+ lda <SCROLL_LINES+1
+ sbc #0
+ sta <SCROLL_LINES+1
+ dec <SCROLL_LINES_MODULO
+ lda <SCROLL_LINES_MODULO
+ bpl .modulo_ok
+ lda #LINES_PER_SCREEN
+ sta <SCROLL_LINES_MODULO
+ dec <SCROLL_LINES_MODULO
+.modulo_ok:
+ lda <LAST_LINE_GAME
+ sec
+ sbc #1
+ sta <LAST_LINE_GAME
+ lda <LAST_LINE_GAME+1
+ sbc #0
+ sta <LAST_LINE_GAME+1
+ dec <LAST_LINE_MODULO
+ lda <LAST_LINE_MODULO
+ bpl .modulo_ok2
+ lda #LINES_PER_SCREEN
+ sta <LAST_LINE_MODULO
+ dec <LAST_LINE_MODULO
+.modulo_ok2:
+ jsr print_first_name
+ rts
+
+load_base_chr:
+ ; loading CHR
+ lda #$06
+ jsr select_bank
+ lda #LOW(chr_data)
+ sta COPY_SOURCE_ADDR
+ lda #HIGH(chr_data)
+ sta COPY_SOURCE_ADDR+1
+ jsr load_chr
+ rts
+
+load_base_pal:
+ ; loading palette into $3F00 of PPU
+ lda #$3F
+ sta $2006
+ lda #$00
+ sta $2006
+ ldx #$00
+.loop:
+ lda tilepal, x
+ sta $2007
+ inx
+ cpx #32
+ bne .loop
+ ; letters colors
+ lda #$3F
+ sta $2006
+ lda #$0D
+ sta $2006
+ ldx #17
+.loop2:
+ lda tilepal, x
+ sta $2007
+ inx
+ cpx #20
+ bne .loop2
+ rts
+
+load_black:
+ ; loading empty black palette into $3F00 of PPU
+ lda #$3F
+ sta $2006
+ lda #$00
+ sta $2006
+ ldx #$00
+ lda #$3F ; color
+.loop:
+ sta $2007
+ inx
+ cpx #32
+ bne .loop
+ rts
+
+ ; nametable cleanup
+clear_screen:
+ lda #$20
+ sta $2006
+ lda #$00
+ sta $2006
+ lda #$00
+ ldx #0
+ ldy #$10
+.loop:
+ sta $2007
+ 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:
+ ldx #0
+ stx $2003
+ ldx #HIGH(SPRITES)
+ stx $4014
+ rts
+
+ ; loading header (image on the top), first part
+draw_header1:
+ lda #$06
+ jsr select_bank
+ bit $2002
+ lda #$20
+ sta $2006
+ lda #$00
+ sta $2006
+ ldx #0
+ ldy #$40
+.loop:
+ lda nametable, x
+ sta $2007
+ inx
+ dey
+ bne .loop
+ rts
+
+ ; loading header (image on the top), second part
+draw_header2:
+ lda #$06
+ jsr select_bank
+ bit $2002
+ lda #$20
+ sta $2006
+ lda #$40
+ sta $2006
+ ldx #$40
+ ldy #$40
+.loop:
+ lda nametable, x
+ sta $2007
+ inx
+ dey
+ bne .loop
+ ; loading attributes for it
+ lda #$23
+ sta $2006
+ lda #$C0
+ sta $2006
+ ldx #0
+ ldy #8
+.palette_loop:
+ lda nametable+$3C0, x
+ sta $2007
+ inx
+ dey
+ bne .palette_loop
+ rts
+
+ ; loading footer (image on the bottom), first part
+draw_footer1:
+ lda #$06
+ jsr select_bank
+ ldx #0
+ ldy #$40
+.loop:
+ lda nametable+$340, x
+ sta $2007
+ inx
+ dey
+ bne .loop
+ rts
+
+ ; loading footer (image on the bottom), second part
+draw_footer2:
+ lda #$06
+ jsr select_bank
+ ldx #0
+ ldy #$40
+.loop:
+ lda nametable+$380, x
+ sta $2007
+ inx
+ dey
+ bne .loop
+ rts
+
+ ; printing game name on the top
+print_first_name:
+ pha
+ lda <SCROLL_LINES
+ sta <TEXT_DRAW_GAME
+ lda <SCROLL_LINES+1
+ sta <TEXT_DRAW_GAME+1
+ lda <SCROLL_LINES_MODULO
+ sta <TEXT_DRAW_ROW
+ jsr print_name
+ pla
+ rts
+
+ ; printing game name on the bottom
+print_last_name:
+ pha
+ lda <LAST_LINE_GAME
+ sta <TEXT_DRAW_GAME
+ lda <LAST_LINE_GAME+1
+ sta <TEXT_DRAW_GAME+1
+ lda <LAST_LINE_MODULO
+ sta <TEXT_DRAW_ROW
+ jsr print_name
+ pla
+ rts
+
+print_name:
+ pha
+ tya
+ pha
+ txa
+ pha
+ ; is it header lines?
+ lda <TEXT_DRAW_GAME+1
+ bne .not_header ; no
+ lda <TEXT_DRAW_GAME
+ beq .header1
+ cmp #1
+ beq .header2
+ jmp .not_header
+.header1:
+ jsr draw_header1
+ jmp .end_really_really
+.header2:
+ jsr draw_header2
+ jmp .end_really_really
+.not_header:
+ ; when there are not so many games we need so offset
+ lda <TEXT_DRAW_ROW
+ clc
+ adc games_offset
+ sta <TEXT_DRAW_ROW
+ asl <TEXT_DRAW_ROW ; x2
+ lda <TEXT_DRAW_ROW
+ ; detecting target nametable
+ cmp #LINES_PER_SCREEN
+ bcc .first_screen
+ ; second
+ sec
+ sbc #LINES_PER_SCREEN
+ lsr A
+ lsr A
+ lsr A
+ clc
+ adc #$2C
+ bit $2002
+ sta $2006
+ lda <TEXT_DRAW_ROW
+ sec
+ sbc #LINES_PER_SCREEN
+ asl A
+ asl A
+ asl A
+ asl A
+ asl A
+ sta $2006
+ jmp .print_end
+ ; first
+.first_screen:
+ lsr A
+ lsr A
+ lsr A
+ clc
+ adc #$20
+ bit $2002
+ sta $2006
+ lda <TEXT_DRAW_ROW
+ asl A
+ asl A
+ asl A
+ asl A
+ asl A
+ sta $2006
+.print_end:
+ ; we need to substract 2 from game number
+ lda <TEXT_DRAW_GAME
+ sec
+ sbc #2
+ sta <TEXT_DRAW_GAME
+ lda <TEXT_DRAW_GAME+1
+ sbc #0
+ sta <TEXT_DRAW_GAME+1
+ ; is it footer?
+ lda <TEXT_DRAW_GAME
+ sec
+ sbc games_count
+ lda <TEXT_DRAW_GAME+1
+ sbc games_count+1
+ bcc .print_text_line
+ ldx <TEXT_DRAW_GAME
+ cpx games_count
+ beq .footer1
+ dex
+ cpx games_count
+ beq .footer2
+ jmp .end
+.footer2:
+ jsr draw_footer2
+ ; lets keep for footer text palette, i like how it looks
+ jmp .end
+.footer1:
+ jsr draw_footer1
+ jmp .end
+.print_text_line:
+ lda <TEXT_DRAW_GAME+1
+ jsr select_bank
+ lda #LOW(game_names)
+ clc
+ adc <TEXT_DRAW_GAME
+ sta <TMP
+ lda #HIGH(game_names)
+ adc #0
+ sta <TMP+1
+ lda <TMP
+ clc
+ adc <TEXT_DRAW_GAME
+ sta <TMP
+ lda <TMP+1
+ adc #0
+ sta <TMP+1
+ ldy #0
+ lda [TMP], y
+ sta COPY_SOURCE_ADDR
+ iny
+ lda [TMP], y
+ sta COPY_SOURCE_ADDR+1
+ ; spaces on the left
+ ldx #GAME_NAMES_OFFSET+1
+.print_blank:
+ lda #$00
+ sta $2007
+ dex
+ bne .print_blank
+ ; text
+ ldx #GAME_NAMES_OFFSET+1
+ ldy #0
+ lda #1
+.next_char:
+ cmp #0 ; after zero we are not printing letters but printing spaces
+ beq .end_of_line
+ lda [COPY_SOURCE_ADDR], y
+.end_of_line:
+ sta $2007
+ iny
+ inx
+ cpx #CHARS_PER_LINE
+ bne .next_char
+.end:
+ ; but if it upper part, we need to erase two lines
+ lda <TEXT_DRAW_ROW
+ cmp #4
+ bcs .end_really
+ ldy #CHARS_PER_LINE
+ lda #0
+.clear_2nd_line:
+ sta $2007
+ dey
+ bne .clear_2nd_line
+.end_really:
+ ; attributes for text
+ lda <TEXT_DRAW_ROW
+ cmp #LINES_PER_SCREEN
+ bcc .print_palette_addr_first_screen
+ ; second nametable
+ lda #$2F
+ sta $2006
+ lda <TEXT_DRAW_ROW
+ sec
+ sbc #LINES_PER_SCREEN
+ jmp .print_palette_addr_select_end
+ ; first nametable
+.print_palette_addr_first_screen:
+ lda #$23
+ sta $2006
+ lda <TEXT_DRAW_ROW
+.print_palette_addr_select_end:
+ ; one byte for 4 rows
+ lsr A
+ lsr A
+ asl A
+ asl A
+ asl A
+ clc
+ adc #$C0
+ sta $2006
+ lda #$FF
+ sta $2007
+ sta $2007
+ sta $2007
+ sta $2007
+ sta $2007
+ sta $2007
+ sta $2007
+ sta $2007
+.end_really_really:
+ pla
+ tax
+ pla
+ tay
+ pla
+ rts
+
+move_cursors:
+ ; fine cursor scrolling
+ lda <SPRITE_1_X_TARGET
+ cmp SPRITE_1_X
+ beq .sprite_1x_target_end
+ bcs .sprite_1x_target_plus
+ lda SPRITE_1_X
+ sec
+ sbc #4
+ sta SPRITE_1_X
+ jmp .sprite_1x_target_end
+.sprite_1x_target_plus:
+ lda SPRITE_1_X
+ clc
+ adc #4
+ sta SPRITE_1_X
+.sprite_1x_target_end:
+ lda <SPRITE_1_Y_TARGET
+ cmp SPRITE_1_Y
+ beq .sprite_1y_target_end
+ bcs .sprite_1y_target_plus
+ lda SPRITE_1_Y
+ sec
+ sbc #4
+ sta SPRITE_0_Y
+ sta SPRITE_1_Y
+ jmp .sprite_1y_target_end
+.sprite_1y_target_plus:
+ lda SPRITE_1_Y
+ clc
+ adc #4
+ sta SPRITE_0_Y
+ sta SPRITE_1_Y
+.sprite_1y_target_end:
+ rts
+
+ ; fine scrolling to target line
+move_scrolling:
+ ; determining scroll speed
+ lda <SCROLL_LINES
+ clc
+ adc #2
+ sta <TMP
+ lda <SCROLL_LINES+1
+ adc #0
+ sta <TMP+1
+ lda <SCROLL_LINES_TARGET
+ sec
+ sbc <TMP
+ lda <SCROLL_LINES_TARGET+1
+ sbc <TMP+1
+ bcs .move_scrolling_fast_down
+ lda <SCROLL_LINES_TARGET
+ clc
+ adc #2
+ sta <TMP
+ lda <SCROLL_LINES_TARGET+1
+ adc #0
+ sta <TMP+1
+ lda <SCROLL_LINES
+ sec
+ sbc <TMP
+ lda <SCROLL_LINES+1
+ sbc <TMP+1
+ bcs .move_scrolling_fast_up
+ ; slow scrolling
+ jsr .move_scrolling_real
+ rts
+ ; fast scrolling
+.move_scrolling_fast:
+ jsr .move_scrolling_real
+ jsr .move_scrolling_real
+ jsr .move_scrolling_real
+ jsr .move_scrolling_real
+ rts
+.move_scrolling_fast_up:
+ jmp scroll_line_up
+.move_scrolling_fast_down:
+ jmp scroll_line_down
+.move_scrolling_real:
+ ; do we need to move screen?
+ ldx <SCROLL_LINES_TARGET
+ cpx <SCROLL_LINES
+ bne .need
+ ldx <SCROLL_LINES_TARGET+1
+ cpx <SCROLL_LINES+1
+ bne .need
+ ldx <SCROLL_FINE
+ bne .need
+ rts
+ ; we need it
+.need:
+ lda <SCROLL_LINES
+ sec
+ sbc <SCROLL_LINES_TARGET
+ lda <SCROLL_LINES+1
+ sbc <SCROLL_LINES_TARGET+1
+ bcc .target_plus
+ ; scrolling up
+ lda <SCROLL_FINE
+ sec
+ sbc #4
+ bmi .target_minus
+ sta <SCROLL_FINE
+ rts
+.target_minus:
+ and #$0f
+ sta <SCROLL_FINE
+ jsr scroll_line_up
+ rts
+.target_plus:
+ ; scrolling down
+ lda <SCROLL_FINE
+ ; adding fine value
+ clc
+ adc #4
+ sta <SCROLL_FINE
+ cmp #16
+ bne .end
+ ; down if fine >=16
+ lda #0
+ sta <SCROLL_FINE
+ jsr scroll_line_down
+.end:
+ rts
+
+set_cursor_targets:
+ ; set scroll targets first
+.not_ok1:
+ lda <SCROLL_LINES_TARGET
+ clc
+ adc #10
+ sta <TMP
+ lda <SCROLL_LINES_TARGET+1
+ adc #0
+ sta <TMP+1
+ lda <TMP
+ sec
+ sbc <SELECTED_GAME
+ lda <TMP+1
+ sbc <SELECTED_GAME+1
+ bcs .ok1 ; надо скроллить вниз
+ lda <SCROLL_LINES_TARGET
+ clc
+ adc #1
+ sta <SCROLL_LINES_TARGET
+ lda <SCROLL_LINES_TARGET+1
+ adc #0
+ sta <SCROLL_LINES_TARGET+1
+ jmp .not_ok1
+.ok1:
+.not_ok2:
+ lda <SELECTED_GAME
+ sec
+ sbc <SCROLL_LINES_TARGET
+ lda <SELECTED_GAME+1
+ sbc <SCROLL_LINES_TARGET+1
+ bcs .ok2 ; надо скроллить вверх
+ lda <SCROLL_LINES_TARGET
+ sec
+ sbc #1
+ sta <SCROLL_LINES_TARGET
+ lda <SCROLL_LINES_TARGET+1
+ sbc #0
+ sta <SCROLL_LINES_TARGET+1
+ jmp .not_ok2
+.ok2:
+ ; set cursor targets depending on selected game number
+ ; left cursor, X
+ ldx <SELECTED_GAME
+ lda #GAME_NAMES_OFFSET*8
+ sta <SPRITE_0_X_TARGET
+ ; right cursor, X
+ lda <SELECTED_GAME+1
+ jsr select_bank
+ ldx <SELECTED_GAME
+ ldy loader_data_cursor_pos, x
+ dey
+ tya
+ clc
+ adc #GAME_NAMES_OFFSET+2
+ asl A
+ asl A
+ asl A
+ sta <SPRITE_1_X_TARGET
+ ; Y coordinate it the same for both
+ lda <SELECTED_GAME
+ ; when there are not so many games
+ clc
+ adc games_offset
+ sec
+ sbc <SCROLL_LINES_TARGET
+ clc
+ adc #2
+ asl A
+ asl A
+ asl A
+ asl A
+ sec
+ sbc #1
+ .if ENABLE_TOP_OFFSET!=0 ; for large images on top
+ clc
+ adc #8
+ .endif
+ sta <SPRITE_0_Y_TARGET
+ sta <SPRITE_1_Y_TARGET
+ rts
+
+stars:
+ lda <STAR_SPAWN_TIMER
+ cmp #$E0 ; stars count
+ beq .spawn_end
+ inc <STAR_SPAWN_TIMER
+ lda <STAR_SPAWN_TIMER
+ and #$0F
+ cmp #0
+ bne .spawn_end
+ lda <STAR_SPAWN_TIMER
+ lsr A
+ lsr A
+ tay
+ lda <STAR_SPAWN_TIMER
+ lda #$FC ; Y, below screen
+ sta SPRITES+4, y
+ iny
+ jsr random ; random tile
+ and #$03
+ clc
+ adc #$71
+ sta SPRITES+4, y
+ iny
+ jsr random ; attributes, random palette
+ and #%00000011 ; palette - tho lowest bits
+ ora #%00100000 ; low priority bit
+ sta SPRITES+4, y
+ iny
+ jsr random
+ sta SPRITES+4, y
+.spawn_end:
+ ldy #8
+.move_next:
+ lda SPRITES, y
+ cmp #$FF
+ beq .move_end
+ tya
+ lsr A
+ lsr A
+ and #$07
+ cmp #$00
+ beq .move_fast
+ cmp #$01
+ beq .move_fast
+ cmp #$02
+ beq .move_fast
+ cmp #$03
+ beq .move_medium
+ cmp #$04
+ beq .move_medium
+ cmp #$05
+ beq .move_slow
+ cmp #$06
+ beq .move_slow
+.move_very_slow: ; default
+ lda SPRITES, y
+ sbc #1
+ jmp .moved
+.move_slow:
+ lda SPRITES, y
+ sec
+ sbc #2
+ jmp .moved
+.move_medium:
+ lda SPRITES, y
+ sec
+ sbc #3
+ jmp .moved
+.move_fast:
+ lda SPRITES, y
+ sec
+ sbc #4
+.moved:
+ sta SPRITES, y
+ cmp #$0A
+ bcs .move_next1
+ lda #$FC
+ sta SPRITES, y ; reset Y
+ jsr random ; random tile
+ and #$03
+ clc
+ adc #$71
+ sta SPRITES+1, y
+ jsr random ; random X
+ sta SPRITES+3, y
+ jsr random ; random attributes
+ and #%00000011 ; palette - lowest tho bits
+ ora #%00100000 ; priority bit
+ sta SPRITES+2, y
+.move_next1:
+ iny
+ iny
+ iny
+ iny
+ bne .move_next
+.move_end:
+ rts
+
+load_text_palette:
+ lda #$23
+ sta $2006
+ lda #$C8
+ sta $2006
+ lda #$FF
+ ldy #$38
+.print_warning_palette:
+ sta $2007
+ dey
+ bne .print_warning_palette
+ rts
+
+ ; print null-terminated string from [COPY_SOURCE_ADDR]
+print_text:
+ ldy #0
+.loop:
+ lda [COPY_SOURCE_ADDR], y
+ sta $2007
+ iny
+ cmp #0 ; stop at zero
+ bne .loop
+ rts
+
+saving_warning_show:
+ ; disable PPU
+ lda #%00000000
+ sta $2000
+ sta $2001
+ jsr waitblank_simple
+ jsr clear_screen
+ lda #$21
+ sta $2006
+ lda #$C0
+ sta $2006
+ lda #LOW(saving_text)
+ sta COPY_SOURCE_ADDR
+ lda #HIGH(saving_text)
+ sta COPY_SOURCE_ADDR+1
+ jsr print_text
+ jsr load_text_palette
+ jsr waitblank_simple
+ bit $2002
+ lda #0
+ sta $2005
+ sta $2005
+ lda #%00001000
+ sta $2000
+ lda #%00001010
+ sta $2001
+ jsr waitblank_simple
+ rts
+
+saving_warning_hide:
+ lda #%00000000 ; disable PPU
+ sta $2000
+ sta $2001
+ jsr waitblank_simple
+ jsr clear_screen
+ rts