2026-02-14 18:08:10 -05:00
.segment " HEADER"
INES_ M A P P E R = 0
INES_ M I R R O R = 1
INES_ S R A M = 0
.byte ' N' , ' E ' , ' S ' , $ 1 A
.byte $ 0 2
.byte $ 0 1
.byte INES_MIRROR
.byte ( INES_ M A P P E R & % 1 1 1 1 0 0 0 0 )
.byte $ 0 , $ 0 , $ 0 , $ 0 , $ 0 , $ 0 , $ 0 , $ 0
.segment " TILES"
.incbin " background. c h r "
.incbin " sprite. c h r "
.segment " VECTORS"
.word nmi
.word reset
.word irq
.segment " CODE"
reset :
sei
2026-02-17 09:53:46 -05:00
lda #0
2026-02-14 18:08:10 -05:00
sta $ 2 0 0 0
2026-02-16 00:27:56 -05:00
lda #0
2026-02-14 18:08:10 -05:00
sta $ 2 0 0 1
sta $ 4 0 1 5
sta $ 4 0 1 0
lda #40
sta $ 4 0 1 7
cld
ldx #$ F F
txs
bit $ 2 0 0 2
:
bit $ 2 0 0 2
bpl : -
lda #0
ldx #0
:
sta $ 0 0 0 0 , X
sta $ 0 1 0 0 , X
sta $ 0 2 0 0 , X
sta $ 0 3 0 0 , X
sta $ 0 4 0 0 , X
sta $ 0 5 0 0 , X
sta $ 0 6 0 0 , X
sta $ 0 7 0 0 , X
inx
bne : -
lda #255
ldx #0
:
sta o a m , X
inx
inx
inx
inx
bne : -
:
bit $ 2 0 0 2
bpl : -
2026-02-17 09:53:46 -05:00
lda #% 10101000 ; NMI enable, 8x16 sprites, ignored due to 8x16 mode
2026-02-14 18:08:10 -05:00
sta $ 2 0 0 0
jmp m a i n
.segment " ZEROPAGE"
nmi_lock : .res 1
nmi_count : .res 1
nmi_ready : .res 1
nmt_update_len : .res 1
2026-03-16 22:01:56 -04:00
nmt_column : .res 1
2026-03-18 14:56:40 -04:00
nmt_update_frame : .res 1
2026-02-14 18:08:10 -05:00
scroll_x : .res 1
scroll_y : .res 1
scroll_nmt : .res 1
2026-03-16 22:01:56 -04:00
scroll_page : .res 1
2026-02-14 18:08:10 -05:00
temp : .res 1
2026-03-16 22:01:56 -04:00
PPUCTRL_ d e f a u l t = % 1 0 1 0 1 0 0 0
2026-02-14 18:08:10 -05:00
.segment " BSS"
nmt_update : .res 256
palette : .res 32
.segment " OAM"
oam : .res 256
.segment " CODE"
nmi :
pha
txa
pha
tya
pha
lda n m i _ l o c k
beq : +
jmp @nmi_end
:
lda #1
sta n m i _ l o c k
lda n m i _ r e a d y
bne : +
jmp @ppu_update_end
:
cmp #2
bne : +
lda #% 00000000
sta $ 2 0 0 1
ldx #0
stx n m i _ r e a d y
jmp @ppu_update_end
:
ldx #0
stx $ 2 0 0 3
lda #> o a m
sta $ 4 0 1 4
2026-02-17 09:53:46 -05:00
lda #% 10101000 ; NMI enable, 8x16 sprites, ignored due to 8x16 mode
2026-02-14 18:08:10 -05:00
sta $ 2 0 0 0
lda $ 2 0 0 2
lda #$ 3 F
sta $ 2 0 0 6
stx $ 2 0 0 6
ldx #0
:
lda p a l e t t e , X
sta $ 2 0 0 7
inx
cpx #32
bcc : -
ldx #0
cpx n m t _ u p d a t e _ l e n
bcs @scroll
2026-03-16 22:01:56 -04:00
lda P P U C T R L _ d e f a u l t
;ora #%00000100
sta $ 2 0 0 0
ldy #0
2026-03-18 14:56:40 -04:00
ldx #0
2026-02-14 18:08:10 -05:00
@nmt_update_loop:
2026-03-18 14:56:40 -04:00
lda n m t _ u p d a t e _ f r a m e
cmp #0
bne : +
lda n m t _ u p d a t e + 0 , X
sta $ 2 0 0 6
lda n m t _ u p d a t e + 1 , X
sta $ 2 0 0 6
2026-03-16 22:01:56 -04:00
2026-03-18 14:56:40 -04:00
lda n m t _ u p d a t e + 2 , X
sta $ 2 0 0 7
lda n m t _ u p d a t e + 3 , X
sta $ 2 0 0 7
2026-03-16 22:01:56 -04:00
2026-03-18 14:56:40 -04:00
jmp : + +
:
lda n m t _ u p d a t e + 0 , X
sta $ 2 0 0 6
lda n m t _ u p d a t e + 1 , X
clc
adc #32
sta $ 2 0 0 6
2026-03-16 22:01:56 -04:00
2026-03-18 14:56:40 -04:00
lda n m t _ u p d a t e + 4 , X
sta $ 2 0 0 7
lda n m t _ u p d a t e + 5 , X
sta $ 2 0 0 7
:
2026-03-16 22:01:56 -04:00
2026-03-18 14:56:40 -04:00
inx
inx
inx
inx
inx
inx
2026-03-16 22:01:56 -04:00
iny
cpy n m t _ u p d a t e _ l e n
2026-02-14 18:08:10 -05:00
bcc @nmt_update_loop
2026-03-16 22:01:56 -04:00
lda P P U C T R L _ d e f a u l t
sta $ 2 0 0 0
2026-03-18 14:56:40 -04:00
inc n m t _ u p d a t e _ f r a m e
lda n m t _ u p d a t e _ f r a m e
cmp #2
bne : +
lda #0
sta n m t _ u p d a t e _ f r a m e
sta n m t _ u p d a t e _ l e n
:
2026-02-14 18:08:10 -05:00
@scroll:
lda s c r o l l _ n m t
and #% 00000011
2026-02-17 09:53:46 -05:00
ora #% 10101000
2026-02-14 18:08:10 -05:00
sta $ 2 0 0 0
lda s c r o l l _ x
sta $ 2 0 0 5
lda s c r o l l _ y
sta $ 2 0 0 5
lda #% 00011110
sta $ 2 0 0 1
ldx #0
stx n m i _ r e a d y
@ppu_update_end:
lda #0
sta n m i _ l o c k
@nmi_end:
pla
tay
pla
tax
pla
rti
.segment " CODE"
irq :
rti
.segment " CODE"
ppu_update :
lda #1
sta n m i _ r e a d y
:
lda n m i _ r e a d y
bne : -
rts
ppu_skip :
lda n m i _ c o u n t
:
cmp n m i _ c o u n t
beq : -
rts
ppu_off :
lda #2
sta n m i _ r e a d y
:
lda n m i _ r e a d y
bne : -
rts
PAD_ A = $ 0 1
PAD_ B = $ 0 2
PAD_ S E L E C T = $ 0 4
PAD_ S T A R T = $ 0 8
PAD_ U = $ 1 0
PAD_ D = $ 2 0
PAD_ L = $ 4 0
PAD_ R = $ 8 0
.segment " RODATA"
2026-02-16 00:27:56 -05:00
2026-03-16 22:01:56 -04:00
default_level :
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
2026-02-21 20:35:58 -05:00
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
2026-03-16 22:01:56 -04:00
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
.byte $ 8 0 , $ 8 0 , $ 8 0 , $ 8 0 , $ 8 0 , $ 8 0 , $ 8 0 , $ 8 0 , $ 8 0 , $ 8 0 , $ 8 0 , $ 8 0 , $ 8 0 , $ 8 0 , $ 8 0 , $ 8 0
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
;.byte $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
;.byte $00,$00,$00,$00,$00,$00,$00,$81,$00,$81,$00,$81,$00,$81,$00,$00
;.byte $82,$83,$00,$00,$00,$00,$00,$00,$81,$00,$0C,$00,$81,$00,$00,$00
;.byte $84,$85,$00,$00,$00,$00,$00,$81,$00,$81,$00,$81,$00,$81,$00,$00
;.byte $0F,$0E,$00,$00,$00,$00,$00,$00,$0C,$00,$0C,$00,$0C,$00,$00,$00
;.byte $0F,$0E,$00,$00,$00,$00,$00,$81,$00,$81,$00,$81,$00,$81,$00,$00
;.byte $0F,$0E,$00,$00,$00,$00,$00,$00,$81,$00,$0C,$00,$81,$00,$00,$00
;.byte $0F,$0E,$00,$00,$00,$00,$00,$81,$00,$81,$00,$81,$00,$81,$00,$00
;.byte $0F,$0E,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
;.byte $0F,$0E,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$8C,$87
;.byte $0F,$0E,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
;.byte $0F,$0E,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
;.byte $0F,$8C,$87,$87,$87,$87,$87,$87,$87,$87,$87,$87,$87,$87,$87,$87
;.byte $0F,$0E,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
;.byte $0F,$0E,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
default_level2 :
2026-02-21 20:35:58 -05:00
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0
.byte $ 0 0 , $ 8 C,$ 8 C ,$ 8 C ,$ 8 C ,$ 8 C ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0
2026-03-16 22:01:56 -04:00
.byte $ 0 0 , $ 0 9 , $ 0 1 , $ 0 1 , $ 0 1 , $ 8 C,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0
.byte $ 0 0 , $ 8 C,$ 8 C ,$ 8 C ,$ 0 1 ,$ 0 6 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0
.byte $ 0 0 , $ 0 9 , $ 0 1 , $ 0 1 , $ 0 1 , $ 8 C,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 8 2 ,$ 8 3 ,$ 0 0 ,$ 0 0 ,$ 0 0
2026-02-21 20:35:58 -05:00
.byte $ 0 0 , $ 8 C,$ 8 C ,$ 8 C ,$ 8 C ,$ 8 C ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 8 4 ,$ 8 5 ,$ 0 0 ,$ 0 0 ,$ 0 0
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 F,$ 0 E ,$ 0 0 ,$ 8 2 ,$ 8 3
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 F,$ 0 E ,$ 0 0 ,$ 8 4 ,$ 8 5
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 8 2 , $ 8 3 , $ 0 0 , $ 0 F,$ 0 E ,$ 0 0 ,$ 0 F ,$ 0 E
2026-03-16 22:01:56 -04:00
.byte $ 8 7 , $ 8 C,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 0 0 ,$ 8 4 ,$ 8 5 ,$ 0 0 ,$ 0 F ,$ 0 E ,$ 0 0 ,$ 0 F ,$ 0 E
2026-02-21 20:35:58 -05:00
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 F,$ 0 E ,$ 0 0 ,$ 0 F ,$ 0 E ,$ 0 0 ,$ 0 F ,$ 0 E
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 F,$ 0 E ,$ 0 0 ,$ 0 F ,$ 0 E ,$ 0 0 ,$ 0 F ,$ 0 E
.byte $ 8 7 , $ 8 7 , $ 8 7 , $ 8 7 , $ 8 7 , $ 8 C,$ 0 0 ,$ 0 0 ,$ 0 F ,$ 0 E ,$ 0 0 ,$ 0 F ,$ 0 E ,$ 0 0 ,$ 0 F ,$ 0 E
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 F,$ 0 E ,$ 0 0 ,$ 8 A ,$ 8 A ,$ 8 A ,$ 8 A ,$ 0 E
.byte $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 0 , $ 0 F,$ 0 E ,$ 0 0 ,$ 8 B ,$ 8 B ,$ 8 B ,$ 8 B ,$ 0 E
;level:
2026-02-21 14:31:21 -05:00
;.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
2026-02-21 20:35:58 -05:00
;.byte 0,1,0,0,1,0,0,0,0,1,0,0,2,7,7,3
;.byte 0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,9
;.byte 0,1,0,0,1,7,7,7,7,1,7,7,6,0,0,9
;.byte 0,0,1,1,0,0,0,0,0,1,0,0,4,8,8,5
;.byte 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0
2026-02-21 14:31:21 -05:00
;.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;.byte 0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0
;.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;.byte 0,0,0,0,0,0,0,0,0,0,0,10,10,10,10,10
2026-02-21 20:35:58 -05:00
;.byte 0,0,1,0,0,0,0,1,0,0,0,11,11,11,11,11
;.byte 0,1,2,3,4,5,6,7,8,9,0,11,11,11,11,11
2026-02-21 14:31:21 -05:00
;.byte 0,0,0,0,0,0,0,0,0,0,0,11,11,11,11,11
2026-02-19 14:04:29 -05:00
2026-02-16 20:33:50 -05:00
metatiles :
.byte 0 , 0 , 0 , 0 , 0
2026-02-21 20:35:58 -05:00
.byte $ 1 4 , $ 1 5 , $ 1 6 , $ 1 7 , % 0 0 0 0 0 0 0 0 ; 1: Full block
.byte $ 1 4 , $ 1 8 , $ 1 B,$ 0 0 ,% 0 0 0 0 0 0 0 0 ; 2: up / left
.byte $ 1 8 , $ 1 5 , $ 0 0 , $ 1 9 , % 0 0 0 0 0 0 0 0 ; 3: up / right
.byte $ 1 B,$ 0 0 ,$ 1 6 ,$ 1 A ,% 0 0 0 0 0 0 0 0 ; 4: down / left
.byte $ 0 0 , $ 1 9 , $ 1 A,$ 1 7 ,% 0 0 0 0 0 0 0 0 ; 5: down / right
.byte $ 1 B,$ 0 0 ,$ 1 B ,$ 0 0 ,% 0 0 0 0 0 0 0 0 ; 6: left
.byte $ 1 8 , $ 1 8 , $ 0 0 , $ 0 0 , % 0 0 0 0 0 0 0 0 ; 7: up
.byte $ 0 0 , $ 0 0 , $ 1 A,$ 1 A ,% 0 0 0 0 0 0 0 0 ; 8: down
.byte $ 0 0 , $ 1 9 , $ 0 0 , $ 1 9 , % 0 0 0 0 0 0 0 0 ; 9: right
.byte $ 1 0 , $ 1 1 , $ 1 2 , $ 1 3 , % 0 0 0 0 0 0 1 0 ; A: grass top
.byte $ 1 2 , $ 1 2 , $ 1 2 , $ 1 2 , % 0 0 0 0 0 0 1 0 ; B: grass bottom
.byte $ 1 4 , $ 1 5 , $ 1 6 , $ 1 7 , % 0 0 0 0 0 0 0 1 ; C: Intangible full block
.byte $ 0 1 , $ 0 1 , $ 0 1 , $ 0 1 , % 0 0 0 0 0 0 0 1 ; D: Intangible grey
.byte $ 1 B,$ 0 0 ,$ 1 B ,$ 0 0 ,% 0 0 0 0 0 0 0 0 ; E: Intangible left
.byte $ 0 0 , $ 1 9 , $ 0 0 , $ 1 9 , % 0 0 0 0 0 0 0 0 ; F: Intangible right
2026-02-16 20:33:50 -05:00
2026-02-14 18:08:10 -05:00
example_palette :
2026-02-16 00:27:56 -05:00
.byte $ 0 F,$ 0 0 ,$ 3 D ,$ 2 0 ; greyscale
2026-02-18 15:04:42 -05:00
.byte $ 0 F,$ 3 D ,$ 3 0 ,$ 0 0 ; whitescale
2026-02-16 00:27:56 -05:00
.byte $ 0 F,$ 0 9 ,$ 1 A ,$ 1 6 ; grass
2026-02-14 18:08:10 -05:00
.byte $ 0 F,$ 1 5 ,$ 2 6 ,$ 3 7 ; bg0 purple/pink
2026-02-17 11:19:51 -05:00
.byte $ 0 F,$ 2 D ,$ 1 0 ,$ 3 D ; reboot bottom
.byte $ 0 F,$ 2 D ,$ 1 0 ,$ 2 C ; reboot eye
2026-02-14 18:08:10 -05:00
.byte $ 0 F,$ 0 1 ,$ 1 1 ,$ 2 1 ; bg2 blue
.byte $ 0 F,$ 0 0 ,$ 1 0 ,$ 3 0 ; bg3 greyscale
2026-02-17 11:19:51 -05:00
; .byte $0F,$18,$28,$38 ; sp0 yellow
; .byte $0F,$14,$24,$34 ; sp1 purple
; .byte $0F,$1B,$2B,$3B ; sp2 teal
; .byte $0F,$12,$22,$32 ; sp3 marine
2026-02-14 18:08:10 -05:00
2026-03-16 22:01:56 -04:00
terrain :
; page pos struct
.byte $ 0 0 , $ 0 0 , $ 0 0
2026-02-14 18:08:10 -05:00
.segment " ZEROPAGE"
2026-02-16 00:27:56 -05:00
buttons : .res 1
2026-02-17 09:26:32 -05:00
player_pos_x : .res 1
2026-02-19 16:52:08 -05:00
player_nmt_x : .res 1
2026-02-17 09:26:32 -05:00
player_pos_y : .res 1
2026-02-18 15:04:42 -05:00
player_subpos_x : .res 1 ; XXXXYYYY | first 4 bits X subposition, last 4 bits Y
player_subpos_y : .res 1 ; XXXXYYYY | first 4 bits X subposition, last 4 bits Y
player_vel_x : .res 1 ; +PPPSSSS | first bit sign, next 3 pixels, last subpixels
player_vel_y : .res 1 ; in subpixels
2026-02-14 18:08:10 -05:00
2026-02-17 11:19:51 -05:00
player_status : .res 1 ; 76543210 | 0: facing (0 right, 1 left)
2026-02-19 16:52:08 -05:00
; | 1: nametable X
; | 2: nametable Y
2026-02-17 11:19:51 -05:00
; | 7: talking
2026-02-18 15:04:42 -05:00
horizontal_speed : .res 1
2026-02-21 16:40:26 -05:00
camera_speed : .res 1
2026-02-17 11:19:51 -05:00
2026-02-14 18:08:10 -05:00
cursor_x : .res 1
cursor_y : .res 1
temp_x : .res 1
temp_y : .res 1
2026-02-16 00:27:56 -05:00
temp_mul : .res 1
2026-02-14 18:08:10 -05:00
var_m : .res 1
var_n : .res 1
var_o : .res 1
var_p : .res 1
2026-05-15 11:23:10 -04:00
var_wide1 : .res 2
var_wide2 : .res 2
2026-02-14 18:08:10 -05:00
2026-02-16 20:33:50 -05:00
jump_pressed_last_frame : .res 1
2026-02-14 18:08:10 -05:00
frame_counter : .res 1
2026-02-17 22:52:47 -05:00
last_frame_jumped : .res 1
2026-02-18 16:56:16 -05:00
last_frame_moving : .res 1
2026-02-14 18:08:10 -05:00
2026-05-15 11:23:10 -04:00
column_pattern_pointer : .res 2
tile_update_pos : .res 1
2026-03-16 22:01:56 -04:00
2026-03-18 14:56:40 -04:00
pointer : .res 2
2026-03-16 22:01:56 -04:00
.segment " BSS"
level : .res 240
level2 : .res 240
2026-05-15 11:23:10 -04:00
room_buffer : .res 240
2026-03-16 22:01:56 -04:00
2026-02-14 18:08:10 -05:00
.segment " CODE"
main :
ldx #0
:
lda e x a m p l e _ p a l e t t e , X
sta p a l e t t e , X
inx
cpx #32
bcc : -
jsr s e t u p _ b a c k g r o u n d
jsr p p u _ u p d a t e
lda #$ 40
sta c u r s o r _ x
sta c u r s o r _ y
lda #0
sta f r a m e _ c o u n t e r
2026-02-17 22:52:47 -05:00
sta l a s t _ f r a m e _ j u m p e d
2026-02-14 18:08:10 -05:00
jsr i n i t _ o b j e c t s
2026-02-18 15:04:42 -05:00
2026-05-15 11:23:10 -04:00
jsr u p d a t e _ r o o m _ b u f f e r
2026-02-14 18:08:10 -05:00
@loop:
2026-02-18 15:04:42 -05:00
lda $ 2 0 0 2
2026-02-14 18:08:10 -05:00
lda f r a m e _ c o u n t e r
clc
adc #1
sta f r a m e _ c o u n t e r
2026-02-16 00:27:56 -05:00
jsr c o n t r o l l e r
jsr m o v e m e n t
2026-02-21 14:31:21 -05:00
jsr m o v e _ c a m e r a
2026-02-16 00:27:56 -05:00
@draw:
2026-02-17 09:26:32 -05:00
jsr d r a w _ p l a y e r
2026-02-16 00:27:56 -05:00
jsr p p u _ u p d a t e
2026-02-14 18:08:10 -05:00
jmp @loop
2026-02-21 14:31:21 -05:00
move_camera :
2026-02-21 16:40:26 -05:00
jmp @no
lda p l a y e r _ p o s _ x
2026-02-21 14:31:21 -05:00
clc
2026-02-21 16:40:26 -05:00
adc #240
2026-02-21 14:31:21 -05:00
cmp s c r o l l _ x
2026-02-21 16:40:26 -05:00
bmi : + +
lda #1
clc
adc s c r o l l _ x
cmp s c r o l l _ x
sta s c r o l l _ x
bcs : +
lda s c r o l l _ n m t
eor #% 00000001
sta s c r o l l _ n m t
:
:
rts
@no:
jsr b t n _ s e l e c t
cmp #0
beq : +
lda #% 11111111
sta c a m e r a _ s p e e d
jmp @end
:
jsr b t n _ s t a r t
cmp #0
beq : +
lda #1
sta c a m e r a _ s p e e d
2026-02-21 14:31:21 -05:00
:
2026-02-21 16:40:26 -05:00
@end:
2026-03-16 22:01:56 -04:00
jsr a d d _ s c r o l l _ x
jsr c h e c k _ c o l u m n _ u p d a t e
2026-02-21 14:31:21 -05:00
rts
2026-02-19 16:52:08 -05:00
2026-02-21 14:31:21 -05:00
draw_player :
2026-02-21 16:01:27 -05:00
lda p l a y e r _ p o s _ y
sec
sbc #1
sta o a m + ( 4 * 2 ) + 0
sta o a m + ( 4 * 3 ) + 0
sec
sbc #16
sta o a m + ( 4 * 0 ) + 0
sta o a m + ( 4 * 1 ) + 0
; RIGHT HALF LOGIC
2026-02-19 16:52:08 -05:00
; see if we can skip drawing the player because it's off screen
lda p l a y e r _ p o s _ x
sec
sbc s c r o l l _ x
cmp p l a y e r _ p o s _ x ; if underflow, nametable bits must be different to continue
2026-02-21 16:01:27 -05:00
beq @skip_bcs_right
2026-02-19 16:52:08 -05:00
bcs : +
2026-02-21 16:01:27 -05:00
@skip_bcs_right:
2026-02-21 14:31:21 -05:00
lda p l a y e r _ n m t _ x
2026-02-19 16:52:08 -05:00
eor s c r o l l _ n m t
2026-02-21 20:35:58 -05:00
bne @hide_player_right
2026-02-19 16:52:08 -05:00
jmp : + +
:
; if nothing, nametable bits must be same to continue
2026-02-21 14:31:21 -05:00
lda p l a y e r _ n m t _ x
2026-02-19 16:52:08 -05:00
eor s c r o l l _ n m t
2026-02-21 20:35:58 -05:00
beq @hide_player_right
2026-02-21 16:01:27 -05:00
:
jmp @end_hide_player_right
@hide_player_right:
lda p l a y e r _ s t a t u s
and #% 00000001
cmp #0
bne : +
lda #250
sta o a m + ( 4 * 1 ) + 0
sta o a m + ( 4 * 3 ) + 0
jmp : + +
:
lda #250
sta o a m + ( 4 * 0 ) + 0
sta o a m + ( 4 * 2 ) + 0
2026-02-19 16:52:08 -05:00
:
2026-02-21 16:01:27 -05:00
@end_hide_player_right:
2026-02-19 16:52:08 -05:00
2026-02-21 16:01:27 -05:00
; LEFT HALF LOGIC
; store what nametable the player's left half is on in var_n
; store what position the player's left half is at in var_p
lda p l a y e r _ p o s _ x
2026-02-21 14:31:21 -05:00
sec
2026-02-21 16:01:27 -05:00
sbc #8
sta v a r _ p
bcs : +
lda p l a y e r _ n m t _ x
eor #% 00000001
sta v a r _ n
jmp : + +
:
lda p l a y e r _ n m t _ x
sta v a r _ n
:
lda v a r _ p
2026-02-21 14:31:21 -05:00
sec
2026-02-21 16:01:27 -05:00
sbc s c r o l l _ x
cmp v a r _ p ; if underflow, nametable bits must be different to continue
beq @skip_bcs_left
bcs : +
@skip_bcs_left:
lda v a r _ n
eor s c r o l l _ n m t
2026-02-21 20:35:58 -05:00
bne @hide_player_left
2026-02-21 16:01:27 -05:00
jmp : + +
:
; if nothing, nametable bits must be same to continue
lda v a r _ n
eor s c r o l l _ n m t
2026-02-21 20:35:58 -05:00
beq @hide_player_left
2026-02-21 16:01:27 -05:00
:
jmp @end_hide_player_left
@hide_player_left:
lda p l a y e r _ s t a t u s
and #% 00000001
cmp #0
bne : +
lda #250
sta o a m + ( 4 * 0 ) + 0
sta o a m + ( 4 * 2 ) + 0
jmp : + +
:
lda #250
sta o a m + ( 4 * 1 ) + 0
sta o a m + ( 4 * 3 ) + 0
:
@end_hide_player_left:
2026-02-19 16:52:08 -05:00
2026-02-17 11:19:51 -05:00
lda p l a y e r _ s t a t u s
and #% 00000001
cmp #0
bne : +
lda p l a y e r _ p o s _ x
2026-02-19 13:07:55 -05:00
sec
sbc s c r o l l _ x
2026-02-17 11:19:51 -05:00
sta o a m + ( 4 * 1 ) + 3
sta o a m + ( 4 * 3 ) + 3
sec
sbc #8
sta o a m + ( 4 * 0 ) + 3
sta o a m + ( 4 * 2 ) + 3
jmp : + +
:
lda p l a y e r _ p o s _ x
2026-02-19 13:07:55 -05:00
sec
sbc s c r o l l _ x
2026-02-17 11:19:51 -05:00
sta o a m + ( 4 * 0 ) + 3
sta o a m + ( 4 * 2 ) + 3
sec
sbc #8
sta o a m + ( 4 * 1 ) + 3
sta o a m + ( 4 * 3 ) + 3
:
2026-02-19 16:52:08 -05:00
2026-02-17 11:19:51 -05:00
lda p l a y e r _ s t a t u s
and #% 10000000
cmp #0
bne : +
lda #$ 45
jmp : + +
:
lda #$ 49
:
sta o a m + ( 4 * 0 ) + 1
clc
adc #2
sta o a m + ( 4 * 1 ) + 1
lda #$ 65
sta o a m + ( 4 * 2 ) + 1
lda #$ 67
sta o a m + ( 4 * 3 ) + 1
lda p l a y e r _ s t a t u s
and #% 00000001
cmp #0
beq : +
lda #% 01000000
jmp : + +
:
lda #% 00000000
:
ora #% 00000001
sta o a m + ( 4 * 0 ) + 2
ora #% 00000001
sta o a m + ( 4 * 1 ) + 2
and #% 11111100
sta o a m + ( 4 * 2 ) + 2
and #% 11111100
sta o a m + ( 4 * 3 ) + 2
2026-02-17 09:26:32 -05:00
rts
2026-02-14 18:08:10 -05:00
init_objects :
2026-02-21 16:40:26 -05:00
lda #96
sta p l a y e r _ p o s _ x ; Set X position
lda #128
sta p l a y e r _ p o s _ y ; Set Y position
2026-02-14 18:08:10 -05:00
2026-02-16 00:27:56 -05:00
lda #0
2026-02-17 09:26:32 -05:00
sta p l a y e r _ v e l _ x
sta p l a y e r _ v e l _ y
2026-02-17 11:19:51 -05:00
sta p l a y e r _ s t a t u s
2026-02-21 16:40:26 -05:00
sta s c r o l l _ n m t
sta p l a y e r _ n m t _ x
2026-02-16 00:27:56 -05:00
2026-02-18 20:02:49 -05:00
lda #% 00101000
2026-02-18 15:04:42 -05:00
sta h o r i z o n t a l _ s p e e d
2026-02-17 22:52:47 -05:00
2026-02-21 16:40:26 -05:00
lda #0
sta c a m e r a _ s p e e d
2026-05-15 11:23:10 -04:00
sta t i l e _ u p d a t e _ p o s
2026-02-21 16:40:26 -05:00
2026-02-14 18:08:10 -05:00
rts
draw :
2026-02-16 00:27:56 -05:00
@end:
rts
2026-02-14 18:08:10 -05:00
2026-02-16 00:27:56 -05:00
movement :
2026-02-17 11:19:51 -05:00
; Talking
ldx #0
jsr b t n _ b
cmp #0
beq : +
lda p l a y e r _ s t a t u s
ora #% 10000000
sta p l a y e r _ s t a t u s
jmp : + +
:
lda p l a y e r _ s t a t u s
and #% 01111111
sta p l a y e r _ s t a t u s
:
2026-02-16 00:27:56 -05:00
; Horizontal velocity
2026-02-14 18:08:10 -05:00
ldx #0
2026-02-16 00:27:56 -05:00
jsr b t n _ r i g h t
cmp #0
beq : +
ldx #1
2026-02-18 15:04:42 -05:00
lda h o r i z o n t a l _ s p e e d
2026-02-17 09:26:32 -05:00
sta p l a y e r _ v e l _ x
2026-02-17 11:19:51 -05:00
lda p l a y e r _ s t a t u s
and #% 11111110
sta p l a y e r _ s t a t u s
2026-02-18 16:56:16 -05:00
lda f r a m e _ c o u n t e r
sta l a s t _ f r a m e _ m o v i n g
2026-02-16 00:27:56 -05:00
:
jsr b t n _ l e f t
cmp #0
beq : +
ldx #1
2026-02-18 15:04:42 -05:00
lda h o r i z o n t a l _ s p e e d
2026-02-18 16:56:16 -05:00
eor #% 11111111
clc
adc #1
2026-02-17 09:26:32 -05:00
sta p l a y e r _ v e l _ x
2026-02-17 11:19:51 -05:00
lda p l a y e r _ s t a t u s
ora #% 00000001
sta p l a y e r _ s t a t u s
2026-02-18 16:56:16 -05:00
lda f r a m e _ c o u n t e r
sta l a s t _ f r a m e _ m o v i n g
2026-02-16 00:27:56 -05:00
:
2026-02-18 16:56:16 -05:00
cpx #1 ; skip decay if right or left pressed
2026-02-16 00:27:56 -05:00
beq @end
lda f r a m e _ c o u n t e r
2026-02-18 16:56:16 -05:00
clc
sbc l a s t _ f r a m e _ m o v i n g
and #3
2026-02-16 00:27:56 -05:00
cmp #0
bne @end
2026-02-18 16:56:16 -05:00
lda p l a y e r _ v e l _ x
and #% 01111111
cmp #0
2026-02-17 09:26:32 -05:00
beq @end ; If player_vel_x = 0, skip decay
2026-02-16 00:27:56 -05:00
2026-02-18 16:56:16 -05:00
lda p l a y e r _ v e l _ x
and #% 10000000
; If player_vel_x positive, decrement
2026-02-18 20:02:49 -05:00
bne : + +
2026-02-18 15:04:42 -05:00
lda p l a y e r _ v e l _ x
sec
sbc #16
2026-02-18 16:56:16 -05:00
sta p l a y e r _ v e l _ x
2026-02-18 20:02:49 -05:00
cmp #0
bpl : +
; negative, clamp to 0
lda #0
sta p l a y e r _ v e l _ x
:
2026-02-16 00:27:56 -05:00
jmp @end
:
2026-02-17 09:26:32 -05:00
; Else if player_vel_x < 0, increment
2026-02-18 15:04:42 -05:00
lda p l a y e r _ v e l _ x
clc
adc #16
sta p l a y e r _ v e l _ x
2026-02-18 20:02:49 -05:00
cmp #0
beq : +
bmi : +
; positive, clamp to 0
lda #0
sta p l a y e r _ v e l _ x
:
2026-02-16 00:27:56 -05:00
@end:
2026-02-19 16:52:08 -05:00
2026-02-16 00:27:56 -05:00
; Jump
2026-02-16 20:33:50 -05:00
jsr b t n _ a
2026-02-16 00:27:56 -05:00
cmp #0
2026-02-16 20:33:50 -05:00
beq @fail_jump ; If jump not pressed, forget it
lda j u m p _ p r e s s e d _ l a s t _ f r a m e
cmp #1
beq @fail_jump ; If jump last frame, forget it
; Jump newly pressed this frame
2026-02-17 22:52:47 -05:00
lda #249
2026-02-17 09:26:32 -05:00
sta p l a y e r _ v e l _ y
2026-02-16 20:33:50 -05:00
2026-02-17 22:52:47 -05:00
lda f r a m e _ c o u n t e r
sta l a s t _ f r a m e _ j u m p e d
2026-02-16 20:33:50 -05:00
@fail_jump:
jsr b t n _ a
sta j u m p _ p r e s s e d _ l a s t _ f r a m e
2026-02-16 00:27:56 -05:00
; Gravity
lda f r a m e _ c o u n t e r
2026-02-17 22:52:47 -05:00
sec
sbc l a s t _ f r a m e _ j u m p e d
and #% 00000001
2026-02-16 00:27:56 -05:00
cmp #0
bne : +
2026-02-17 09:26:32 -05:00
lda p l a y e r _ v e l _ y
2026-02-14 18:08:10 -05:00
clc
adc #1 ; Add 2 to velocity
2026-02-17 09:26:32 -05:00
sta p l a y e r _ v e l _ y
2026-02-16 00:27:56 -05:00
:
2026-02-14 18:08:10 -05:00
2026-02-16 00:27:56 -05:00
; Apply Y velocity
2026-02-17 09:26:32 -05:00
lda p l a y e r _ p o s _ y
2026-02-16 00:27:56 -05:00
clc
2026-02-17 09:26:32 -05:00
adc p l a y e r _ v e l _ y
sta p l a y e r _ p o s _ y
2026-02-14 18:08:10 -05:00
2026-02-17 22:52:47 -05:00
; Apply X velocity
2026-02-18 15:04:42 -05:00
; Position
lda p l a y e r _ v e l _ x
and #% 10000000
cmp #0
bne : +
; 0: right
lda p l a y e r _ v e l _ x
2026-02-21 14:31:21 -05:00
sta v a r _ o ; store initial velocity in o
2026-02-18 16:56:16 -05:00
and #% 01111111
2026-02-18 15:04:42 -05:00
clc
ror
clc
ror
clc
ror
clc
ror
2026-02-18 16:56:16 -05:00
clc
adc p l a y e r _ p o s _ x
sta p l a y e r _ p o s _ x ; add pixels
2026-02-21 14:31:21 -05:00
bcc @end_pixel_overflow_right
lda p l a y e r _ n m t _ x
eor #% 00000001
sta p l a y e r _ n m t _ x
@end_pixel_overflow_right:
2026-02-18 15:04:42 -05:00
lda p l a y e r _ v e l _ x
; A contains signed subpixels
clc
adc p l a y e r _ s u b p o s _ x ; add subposition and velocity subpixels
and #% 00001111
cmp p l a y e r _ s u b p o s _ x ; if A (result) is less than current subpos, overflow occurred
2026-02-18 20:02:49 -05:00
sta p l a y e r _ s u b p o s _ x
beq @end_add_subpos
bcs @end_add_subpos ; so skip if subpos is smaller than result
2026-02-21 14:31:21 -05:00
lda p l a y e r _ p o s _ x
clc
adc #1
sta p l a y e r _ p o s _ x
bcc @end_subpixel_overflow_right
lda p l a y e r _ n m t _ x
eor #% 00000001
sta p l a y e r _ n m t _ x
@end_subpixel_overflow_right:
2026-02-18 15:04:42 -05:00
@end_add_subpos:
jmp : + +
:
; 1: left
lda p l a y e r _ v e l _ x
2026-02-21 14:31:21 -05:00
sta v a r _ o
2026-02-18 16:56:16 -05:00
sec
2026-02-18 15:04:42 -05:00
ror
2026-02-18 16:56:16 -05:00
sec
2026-02-18 15:04:42 -05:00
ror
2026-02-18 16:56:16 -05:00
sec
2026-02-18 15:04:42 -05:00
ror
2026-02-18 16:56:16 -05:00
sec
2026-02-18 15:04:42 -05:00
ror
2026-02-18 16:56:16 -05:00
ora #% 10000000
2026-02-18 20:02:49 -05:00
clc
2026-02-18 16:56:16 -05:00
adc p l a y e r _ p o s _ x
sta p l a y e r _ p o s _ x ; add pixels
2026-02-21 14:31:21 -05:00
bcs @end_pixel_overflow_left
lda p l a y e r _ n m t _ x
eor #% 00000001
sta p l a y e r _ n m t _ x
@end_pixel_overflow_left:
; :|
lda p l a y e r _ p o s _ x
clc
adc #1
sta p l a y e r _ p o s _ x ; add... correction?
bcc @end_correction
lda p l a y e r _ n m t _ x
eor #% 00000001
sta p l a y e r _ n m t _ x
@end_correction:
2026-02-18 16:56:16 -05:00
2026-02-18 15:04:42 -05:00
lda p l a y e r _ v e l _ x
; A contains signed subpixels
clc
adc p l a y e r _ s u b p o s _ x ; add subposition and velocity subpixels
and #% 00001111
cmp p l a y e r _ s u b p o s _ x ; if A (result) is greater than current subpos, underflow occurred
2026-02-18 20:02:49 -05:00
sta p l a y e r _ s u b p o s _ x
beq @end_sub_subpos
bcc @end_sub_subpos ; so skip if subpos is bigger than result
2026-02-21 14:31:21 -05:00
lda p l a y e r _ p o s _ x
sec
sbc #1
sta p l a y e r _ p o s _ x
bcs @end_subpixel_overflow_left
lda p l a y e r _ n m t _ x
eor #% 00000001
sta p l a y e r _ n m t _ x
@end_subpixel_overflow_left:
2026-02-18 15:04:42 -05:00
@end_sub_subpos:
:
2026-02-21 14:31:21 -05:00
2026-02-17 22:52:47 -05:00
; load x pos, filter blocks, check up and down
lda p l a y e r _ v e l _ y
cmp #0
bmi : + ; branch if moving up
jsr d o w n w a r d _ c o l l i s i o n _ c h e c k
jsr l e f t _ c o l l i s i o n _ c h e c k
jsr r i g h t _ c o l l i s i o n _ c h e c k
jsr u p w a r d _ c o l l i s i o n _ c h e c k
jmp : + +
:
jsr u p w a r d _ c o l l i s i o n _ c h e c k
jsr l e f t _ c o l l i s i o n _ c h e c k
jsr r i g h t _ c o l l i s i o n _ c h e c k
jsr d o w n w a r d _ c o l l i s i o n _ c h e c k
:
rts
2026-02-16 00:27:56 -05:00
; Keep grounded
cmp #200
bcc : +
lda #0
2026-02-17 09:26:32 -05:00
sta p l a y e r _ v e l _ y
2026-02-16 00:27:56 -05:00
lda #200
2026-02-17 09:26:32 -05:00
sta p l a y e r _ p o s _ y
2026-02-16 00:27:56 -05:00
:
2026-02-16 20:33:50 -05:00
; Bonk
lda #8
2026-02-17 09:26:32 -05:00
cmp p l a y e r _ p o s _ y
2026-02-16 20:33:50 -05:00
bcc : +
lda #0
2026-02-17 09:26:32 -05:00
sta p l a y e r _ v e l _ y
2026-02-16 20:33:50 -05:00
lda #8
2026-02-17 09:26:32 -05:00
sta p l a y e r _ p o s _ y
2026-02-16 20:33:50 -05:00
:
2026-02-16 00:27:56 -05:00
rts
2026-02-14 18:08:10 -05:00
setup_background :
2026-03-16 22:01:56 -04:00
ldx #0
:
lda d e f a u l t _ l e v e l , X
sta l e v e l , X
inx
cpx #240
bne : -
ldx #0
:
lda d e f a u l t _ l e v e l 2 , X
sta l e v e l 2 , X
inx
cpx #240
bne : -
ldx #0
:
lda d e f a u l t _ l e v e l , X
sta l e v e l , X
inx
cpx #240
bne : -
ldx #0
:
lda d e f a u l t _ l e v e l 2 , X
sta l e v e l 2 , X
inx
cpx #240
bne : -
2026-02-16 20:33:50 -05:00
lda $ 2 0 0 2 ; reset latch
lda #$ 20
sta $ 2 0 0 6
lda #$ 00
sta $ 2 0 0 6
; empty nametable
lda #0
ldy #30 ; 30 rows
:
ldx #32 ; 32 columns
:
sta $ 2 0 0 7
dex
bne : -
dey
bne : - -
2026-02-19 14:04:29 -05:00
; ------------- Nametable 1: level
2026-02-16 20:33:50 -05:00
lda $ 2 0 0 2
2026-02-19 14:04:29 -05:00
lda #$ 20
2026-02-16 20:33:50 -05:00
sta $ 2 0 0 6
lda #$ 00
sta $ 2 0 0 6
ldy #0
2026-02-19 14:04:29 -05:00
@row_start_nmt1:
2026-02-16 20:33:50 -05:00
ldx #0
:
txa
pha
; index is (Y * 16) + X
stx t e m p _ x
lda #16
jsr m u l _ y
clc
adc t e m p _ x
tax
lda l e v e l , X
2026-02-21 20:35:58 -05:00
and #% 01111111
2026-02-16 20:33:50 -05:00
ldx #5
jsr m u l _ x
tax
lda m e t a t i l e s + 0 , X
sta $ 2 0 0 7
lda m e t a t i l e s + 1 , X
sta $ 2 0 0 7
pla
tax
inx
cpx #16
bne : -
; again
ldx #0
:
txa
pha
; index is (Y * 16) + X
stx t e m p _ x
lda #16
jsr m u l _ y
clc
adc t e m p _ x
tax
lda l e v e l , X
2026-02-21 20:35:58 -05:00
and #% 01111111
2026-02-16 20:33:50 -05:00
ldx #5
jsr m u l _ x
tax
lda m e t a t i l e s + 2 , X
sta $ 2 0 0 7
lda m e t a t i l e s + 3 , X
sta $ 2 0 0 7
pla
tax
inx
cpx #16
bne : -
iny
cpy #15
2026-02-19 14:04:29 -05:00
bne @row_start_nmt1
2026-02-16 20:33:50 -05:00
; clear attributes
2026-02-18 15:04:42 -05:00
;lda #0
;ldx #64 ; 64 bytes
;:
; lda #%11100100
;
; sta $2007
; dex
; bne :-
2026-02-16 20:33:50 -05:00
lda #0
2026-02-18 15:04:42 -05:00
sta $ 5 0
2026-02-16 20:33:50 -05:00
2026-02-18 15:04:42 -05:00
ldy #0
:
tya
pha
2026-02-16 20:33:50 -05:00
2026-02-18 15:04:42 -05:00
ldx #0
:
tya
pha
txa
pha
2026-02-16 20:33:50 -05:00
2026-02-18 15:04:42 -05:00
tya
asl
asl
asl
asl
asl
sta t e m p _ y
2026-02-16 20:33:50 -05:00
2026-02-18 15:04:42 -05:00
txa
asl
2026-02-16 20:33:50 -05:00
2026-02-18 15:04:42 -05:00
clc
adc t e m p _ y
2026-02-16 00:27:56 -05:00
2026-02-18 15:04:42 -05:00
tax
2026-02-16 00:27:56 -05:00
2026-02-18 15:04:42 -05:00
lda l e v e l , X
2026-02-21 20:35:58 -05:00
and #% 01111111
2026-02-18 15:04:42 -05:00
tay
lda #5
jsr m u l _ y
tay
lda m e t a t i l e s + 4 , Y
2026-02-21 20:35:58 -05:00
and #% 00000011
2026-02-18 15:04:42 -05:00
sta t e m p _ x
2026-02-16 00:27:56 -05:00
2026-02-18 15:04:42 -05:00
lda l e v e l + 1 , X
2026-02-21 20:35:58 -05:00
and #% 01111111
2026-02-18 15:04:42 -05:00
tay
lda #5
jsr m u l _ y
tay
lda m e t a t i l e s + 4 , Y
2026-02-21 20:35:58 -05:00
and #% 00000011
2026-02-18 15:04:42 -05:00
asl
asl
adc t e m p _ x
sta t e m p _ x
2026-02-16 00:27:56 -05:00
2026-02-18 15:04:42 -05:00
lda l e v e l + 1 6 , X
2026-02-21 20:35:58 -05:00
and #% 01111111
2026-02-18 15:04:42 -05:00
tay
lda #5
jsr m u l _ y
tay
lda m e t a t i l e s + 4 , Y
2026-02-21 20:35:58 -05:00
and #% 00000011
2026-02-18 15:04:42 -05:00
asl
asl
asl
asl
adc t e m p _ x
sta t e m p _ x
2026-02-16 00:27:56 -05:00
2026-02-18 15:04:42 -05:00
lda l e v e l + 1 7 , X
2026-02-21 20:35:58 -05:00
and #% 01111111
2026-02-18 15:04:42 -05:00
tay
lda #5
jsr m u l _ y
tay
lda m e t a t i l e s + 4 , Y
2026-02-21 20:35:58 -05:00
and #% 00000011
2026-02-18 15:04:42 -05:00
asl
asl
asl
asl
asl
asl
adc t e m p _ x
sta $ 2 0 0 7
2026-02-16 00:27:56 -05:00
2026-02-18 15:04:42 -05:00
ldx $ 5 0
inx
stx $ 5 0
2026-02-14 18:08:10 -05:00
2026-02-18 15:04:42 -05:00
sta $ 6 0 , X
2026-02-14 18:08:10 -05:00
2026-02-18 15:04:42 -05:00
pla
tax
pla
tay
inx
cpx #8
2026-02-21 20:35:58 -05:00
beq @left_jump
jmp : -
@left_jump:
2026-02-14 18:08:10 -05:00
2026-02-18 15:04:42 -05:00
pla
tay
iny
cpy #8
2026-02-21 20:35:58 -05:00
beq : +
jmp : - -
:
2026-02-19 14:04:29 -05:00
; ---------------- End nametable 1: Level
; ---------------- Begin nametable 2: Level 2
lda $ 2 0 0 2
lda #$ 24
sta $ 2 0 0 6
lda #$ 00
sta $ 2 0 0 6
ldy #0
@row_start_nmt2:
ldx #0
:
txa
pha
2026-02-14 18:08:10 -05:00
2026-02-19 14:04:29 -05:00
; index is (Y * 16) + X
stx t e m p _ x
lda #16
jsr m u l _ y
clc
adc t e m p _ x
tax
lda l e v e l 2 , X
2026-02-21 20:35:58 -05:00
and #% 01111111
2026-02-19 14:04:29 -05:00
ldx #5
jsr m u l _ x
tax
lda m e t a t i l e s + 0 , X
sta $ 2 0 0 7
lda m e t a t i l e s + 1 , X
sta $ 2 0 0 7
pla
tax
inx
cpx #16
bne : -
; again
ldx #0
:
txa
pha
; index is (Y * 16) + X
stx t e m p _ x
lda #16
jsr m u l _ y
clc
adc t e m p _ x
tax
lda l e v e l 2 , X
2026-02-21 20:35:58 -05:00
and #% 01111111
2026-02-19 14:04:29 -05:00
ldx #5
jsr m u l _ x
tax
lda m e t a t i l e s + 2 , X
sta $ 2 0 0 7
lda m e t a t i l e s + 3 , X
sta $ 2 0 0 7
pla
tax
inx
cpx #16
bne : -
iny
cpy #15
bne @row_start_nmt2
; clear attributes
;lda #0
;ldx #64 ; 64 bytes
;:
; lda #%11100100
;
; sta $2007
; dex
; bne :-
lda #0
sta $ 5 0
ldy #0
2026-02-19 13:07:55 -05:00
:
2026-02-19 14:04:29 -05:00
tya
pha
ldx #0
:
tya
pha
txa
pha
tya
asl
asl
asl
asl
asl
sta t e m p _ y
txa
asl
clc
adc t e m p _ y
tax
lda l e v e l 2 , X
2026-02-21 20:35:58 -05:00
and #% 01111111
2026-02-19 14:04:29 -05:00
tay
lda #5
jsr m u l _ y
tay
lda m e t a t i l e s + 4 , Y
2026-02-21 20:35:58 -05:00
and #% 00000011
2026-02-19 14:04:29 -05:00
sta t e m p _ x
lda l e v e l 2 + 1 , X
2026-02-21 20:35:58 -05:00
and #% 01111111
2026-02-19 14:04:29 -05:00
tay
lda #5
jsr m u l _ y
tay
lda m e t a t i l e s + 4 , Y
2026-02-21 20:35:58 -05:00
and #% 00000011
2026-02-19 14:04:29 -05:00
asl
asl
adc t e m p _ x
sta t e m p _ x
lda l e v e l 2 + 1 6 , X
2026-02-21 20:35:58 -05:00
and #% 01111111
2026-02-19 14:04:29 -05:00
tay
lda #5
jsr m u l _ y
tay
lda m e t a t i l e s + 4 , Y
2026-02-21 20:35:58 -05:00
and #% 00000011
2026-02-19 14:04:29 -05:00
asl
asl
asl
asl
adc t e m p _ x
sta t e m p _ x
lda l e v e l 2 + 1 7 , X
2026-02-21 20:35:58 -05:00
and #% 01111111
2026-02-19 14:04:29 -05:00
tay
lda #5
jsr m u l _ y
tay
lda m e t a t i l e s + 4 , Y
2026-02-21 20:35:58 -05:00
and #% 00000011
2026-02-19 14:04:29 -05:00
asl
asl
asl
asl
asl
asl
adc t e m p _ x
sta $ 2 0 0 7
ldx $ 5 0
inx
stx $ 5 0
sta $ 6 0 , X
pla
tax
pla
tay
inx
cpx #8
2026-02-21 20:35:58 -05:00
beq @right_jump
jmp : -
@right_jump:
2026-02-19 14:04:29 -05:00
pla
tay
iny
cpy #8
2026-02-21 20:35:58 -05:00
beq : +
jmp : - -
:
2026-02-19 13:07:55 -05:00
2026-02-18 15:04:42 -05:00
rts
2026-02-14 18:08:10 -05:00
2026-03-16 22:01:56 -04:00
add_scroll_x :
lda c a m e r a _ s p e e d
bmi @left
clc
adc s c r o l l _ x
cmp s c r o l l _ x
sta s c r o l l _ x
bcs : +
lda s c r o l l _ n m t
eor #% 00000001
sta s c r o l l _ n m t
ldx s c r o l l _ p a g e
inx
sta s c r o l l _ p a g e
:
rts
@left:
clc
adc s c r o l l _ x
cmp s c r o l l _ x
sta s c r o l l _ x
bcc : +
lda s c r o l l _ n m t
eor #% 00000001
sta s c r o l l _ n m t
ldx s c r o l l _ p a g e
dex
sta s c r o l l _ p a g e
:
rts
check_column_update :
clc
lda s c r o l l _ n m t
beq : +
sec
:
lda s c r o l l _ x
ror
lsr
lsr
lsr
2026-05-15 11:23:10 -04:00
; Thought: Level layout will be decoded from somewhere into the room_buffer_r or _l buffers, then they will be indexed into by this to load their column patterns
cmp t i l e _ u p d a t e _ p o s
2026-03-16 22:01:56 -04:00
bne : +
2026-05-15 11:23:10 -04:00
jsr l o a d _ c o l u m n _ p a t t e r n
2026-03-18 20:47:38 -04:00
; Apply pattern
2026-03-16 22:01:56 -04:00
jsr u p d a t e _ n m t _ c o l u m n
2026-03-18 20:47:38 -04:00
2026-05-15 11:23:10 -04:00
; Increment tile_update_pos
lda t i l e _ u p d a t e _ p o s
2026-03-16 22:01:56 -04:00
clc
adc #1
and #% 00011111
2026-05-15 11:23:10 -04:00
sta t i l e _ u p d a t e _ p o s
:
rts
load_column_pattern :
; Based on tile update pos r, use that row to index in to the room buffer. Columns in the room buffer are stored as rows for sequential access.
;
; IDEA: Do we only need one tile update position? If for example we're going right and updating there, we don't need to do anything going left until that point is reached again on the left side. But it's the same point. It's the "seam" in the level. Maybe just an offset by one or something.
lda #< r o o m _ b u f f e r
sta c o l u m n _ p a t t e r n _ p o i n t e r
lda #> r o o m _ b u f f e r
sta c o l u m n _ p a t t e r n _ p o i n t e r + 1
; Since column pattern pointer points to the current column we need to draw, we start it at the beginning of the room buffer (which stores columns as rows), then we add 16 (going to the next "row" in memory which is the next column in reality) how many ever times in column_pattern_pointer to point to the correct row. From there, anything can just loop 16 times from that pointer to get the currently drawing row.
lda t i l e _ u p d a t e _ p o s
and #% 00001111
tax
2026-03-16 22:01:56 -04:00
:
2026-05-15 11:23:10 -04:00
lda c o l u m n _ p a t t e r n _ p o i n t e r
clc
adc #16
sta c o l u m n _ p a t t e r n _ p o i n t e r
lda c o l u m n _ p a t t e r n _ p o i n t e r + 1
adc #0
sta c o l u m n _ p a t t e r n _ p o i n t e r + 1
2026-03-16 22:01:56 -04:00
2026-05-15 11:23:10 -04:00
dex
cpx #0
bne : -
2026-03-16 22:01:56 -04:00
rts
update_nmt_column :
2026-03-18 14:56:40 -04:00
; X represents the row of the current tile being updated
2026-03-16 22:01:56 -04:00
ldx #0
2026-03-18 14:56:40 -04:00
@row_loop:
2026-05-15 11:23:10 -04:00
lda t i l e _ u p d a t e _ p o s
2026-03-18 14:56:40 -04:00
clc
2026-03-18 16:56:37 -04:00
; Add offset in tiles from left edge of screen
2026-03-18 20:47:38 -04:00
adc #16
2026-03-18 14:56:40 -04:00
sta v a r _ n
; Nametable base
lda #$ 20
sta v a r _ o
lda #< l e v e l
sta p o i n t e r
lda #> l e v e l
sta p o i n t e r + 1
lda v a r _ n
and #% 00010000
cmp #0
beq : +
lda p o i n t e r
clc
adc #240
sta p o i n t e r
lda p o i n t e r + 1
adc #0
sta p o i n t e r + 1
lda #$ 24
sta v a r _ o
:
lda v a r _ n
and #% 00001111
sta v a r _ p
2026-03-16 22:01:56 -04:00
lda #16
jsr m u l _ x
clc
2026-03-18 14:56:40 -04:00
adc v a r _ p
2026-03-16 22:01:56 -04:00
tay
2026-03-18 20:47:38 -04:00
2026-03-18 14:56:40 -04:00
; Specifies what tile gets written to the column
2026-05-15 11:23:10 -04:00
;
; T------>
;lda column_pattern
;ror
;sta var_wide1
; >-----BX
;lda column_pattern+1
;ror
;sta var_wide1+1
;stx var_m
;:
;lda var_wide1+1
;rol
;sta var_wide1+1
;lda var_wide1
;rol
;sta var_wide1
;dec var_m
;bpl :-
;lda var_wide1
;and #%10000000
;cmp #0
;beq :+
; What metatile do we load for a non-empty shape?
;lda #%10000001
;:
; Preserve Y (our index in to level)
tya
pha
2026-03-18 20:47:38 -04:00
2026-05-15 11:23:10 -04:00
; Transfer X to Y (our current row in the updated column)
txa
tay
; Instead of all that nonsense constructing the tile that we want to draw, just index in to the column_pattern_pointer
; Storing in var wide 1 because I know it's not used
lda ( c o l u m n _ p a t t e r n _ p o i n t e r ) , Y
sta v a r _ w i d e 1
; Restore Y
pla
tay
; Write our new metatile to level (for collision mostly)
lda v a r _ w i d e 1
2026-03-18 14:56:40 -04:00
sta ( p o i n t e r ) , Y
2026-03-16 22:01:56 -04:00
2026-05-15 11:23:10 -04:00
; ...and actually perform a nametable update
2026-03-16 22:01:56 -04:00
and #% 01111111
ldy #5
jsr m u l _ y
tay
2026-03-18 14:56:40 -04:00
; Preserve X
2026-03-16 22:01:56 -04:00
txa
pha
lda #6
jsr m u l _ x
tax
lda m e t a t i l e s + 0 , Y
sta n m t _ u p d a t e + 2 , X
lda m e t a t i l e s + 1 , Y
sta n m t _ u p d a t e + 3 , X
lda m e t a t i l e s + 2 , Y
sta n m t _ u p d a t e + 4 , X
lda m e t a t i l e s + 3 , Y
sta n m t _ u p d a t e + 5 , X
2026-03-18 14:56:40 -04:00
; Recover X (to Y)
2026-03-16 22:01:56 -04:00
pla
tay
lsr
lsr
2026-03-18 14:56:40 -04:00
; Add nametable base
2026-03-16 22:01:56 -04:00
clc
2026-03-18 14:56:40 -04:00
adc v a r _ o
2026-03-16 22:01:56 -04:00
sta n m t _ u p d a t e + 0 , X
lda #64
jsr m u l _ y
clc
2026-03-18 14:56:40 -04:00
adc v a r _ p
2026-03-16 22:01:56 -04:00
clc
2026-03-18 14:56:40 -04:00
adc v a r _ p
2026-03-16 22:01:56 -04:00
sta n m t _ u p d a t e + 1 , X
tya
tax
inx
cpx #15
2026-03-18 14:56:40 -04:00
beq : +
jmp @row_loop
:
2026-03-16 22:01:56 -04:00
2026-03-18 16:56:37 -04:00
lda #15
2026-03-16 22:01:56 -04:00
sta n m t _ u p d a t e _ l e n
rts
2026-05-15 11:23:10 -04:00
update_room_buffer :
ldx #0
:
lda d e f a u l t _ l e v e l 2 , X
sta r o o m _ b u f f e r , X
inx
cpx #240
bne : -
rts
2026-02-16 00:27:56 -05:00
mul_x :
2026-02-16 20:33:50 -05:00
cmp #0
beq @zero
cpx #0
beq @zero
2026-02-16 00:27:56 -05:00
sta t e m p _ m u l
2026-02-16 20:33:50 -05:00
txa
pha
2026-02-16 00:27:56 -05:00
lda #0
:
clc
adc t e m p _ m u l
dex
bne : -
2026-02-16 20:33:50 -05:00
sta t e m p _ m u l
pla
tax
lda t e m p _ m u l
rts
@zero:
lda #0
2026-02-16 00:27:56 -05:00
rts
mul_y :
2026-02-16 20:33:50 -05:00
cmp #0
beq @zero
cpy #0
beq @zero
2026-02-16 00:27:56 -05:00
sta t e m p _ m u l
2026-02-16 20:33:50 -05:00
tya
pha
2026-02-16 00:27:56 -05:00
lda #0
:
clc
adc t e m p _ m u l
dey
bne : -
2026-02-16 20:33:50 -05:00
sta t e m p _ m u l
pla
tay
lda t e m p _ m u l
rts
@zero:
lda #0
2026-02-16 00:27:56 -05:00
rts
controller :
lda #1
sta $ 4 0 1 6
sta b u t t o n s
lda #0
sta $ 4 0 1 6
:
lda $ 4 0 1 6
lsr
rol b u t t o n s
bcc : -
rts
btn_right :
lda b u t t o n s
and #% 00000001
rts
btn_left :
lda b u t t o n s
and #% 00000010
lsr
rts
btn_down :
lda b u t t o n s
and #% 00000100
lsr
lsr
rts
btn_up :
lda b u t t o n s
and #% 00001000
lsr
lsr
lsr
rts
btn_start :
lda b u t t o n s
and #% 00010000
lsr
lsr
lsr
lsr
rts
btn_select :
lda b u t t o n s
and #% 00100000
lsr
lsr
lsr
lsr
lsr
rts
btn_b :
lda b u t t o n s
and #% 01000000
lsr
lsr
lsr
lsr
lsr
lsr
rts
btn_a :
lda b u t t o n s
and #% 10000000
lsr
lsr
lsr
lsr
lsr
lsr
lsr
rts
2026-02-17 22:52:47 -05:00
downward_collision_check :
lda #0
sta v a r _ n
@begin_check:
lda p l a y e r _ p o s _ x
ldx v a r _ n
cpx #0
bne : +
sec
2026-02-18 20:02:49 -05:00
sbc #5
2026-02-17 22:52:47 -05:00
jmp : + +
:
clc
2026-02-18 20:02:49 -05:00
adc #4
2026-02-17 22:52:47 -05:00
:
; divide by 16
clc
ror
clc
ror
clc
ror
clc
ror
sta t e m p _ x
lda p l a y e r _ p o s _ y
; divide by 16
clc
adc #8
clc
ror
clc
ror
clc
ror
clc
ror
tay
lda #16
jsr m u l _ y
adc t e m p _ x
tax
2026-02-21 20:35:58 -05:00
lda p l a y e r _ n m t _ x
cmp #0
beq : +
lda l e v e l 2 , X
jmp : + +
:
lda l e v e l , X
:
and #% 10000000
2026-02-17 22:52:47 -05:00
cmp #0
beq : +
tya
asl
asl
asl
asl
sec
sbc #8
cmp p l a y e r _ p o s _ y
bcs : +
sta p l a y e r _ p o s _ y
lda #0
sta p l a y e r _ v e l _ y
:
ldx v a r _ n
inx
stx v a r _ n
cpx #1
beq @begin_check
rts
upward_collision_check :
lda #0
sta v a r _ n
@begin_check:
lda p l a y e r _ p o s _ x
ldx v a r _ n
cpx #0
bne : +
sec
2026-02-18 20:02:49 -05:00
sbc #5
2026-02-17 22:52:47 -05:00
jmp : + +
:
clc
2026-02-18 20:02:49 -05:00
adc #4
2026-02-17 22:52:47 -05:00
:
; divide by 16
clc
ror
clc
ror
clc
ror
clc
ror
sta t e m p _ x
lda p l a y e r _ p o s _ y
; divide by 16
sec
sbc #8
clc
ror
clc
ror
clc
ror
clc
ror
tay
lda #16
jsr m u l _ y
adc t e m p _ x
tax
2026-02-21 20:35:58 -05:00
lda p l a y e r _ n m t _ x
cmp #0
beq : +
lda l e v e l 2 , X
jmp : + +
:
lda l e v e l , X
:
and #% 10000000
2026-02-17 22:52:47 -05:00
cmp #0
beq : +
iny
tya
asl
asl
asl
asl
clc
adc #8
cmp p l a y e r _ p o s _ y
bcc : +
sta p l a y e r _ p o s _ y
lda #0
sta p l a y e r _ v e l _ y
:
ldx v a r _ n
inx
stx v a r _ n
cpx #1
beq @begin_check
rts
right_collision_check :
lda #0
sta v a r _ n
@begin_check:
lda p l a y e r _ p o s _ x
; divide by 16
clc
adc #8
clc
ror
clc
ror
clc
ror
clc
ror
sta t e m p _ x
lda p l a y e r _ p o s _ y
ldx v a r _ n
cpx #0
bne : +
sec
sbc #7
jmp : + +
:
clc
adc #6
:
; divide by 16
clc
ror
clc
ror
clc
ror
clc
ror
tay
lda #16
jsr m u l _ y
adc t e m p _ x
tax
2026-02-21 20:35:58 -05:00
lda p l a y e r _ n m t _ x
cmp #0
beq : +
lda l e v e l 2 , X
jmp : + +
:
lda l e v e l , X
:
and #% 10000000
2026-02-17 22:52:47 -05:00
cmp #0
beq : +
lda t e m p _ x
asl
asl
asl
asl
sec
sbc #8
cmp p l a y e r _ p o s _ x
bcs : +
sta p l a y e r _ p o s _ x
lda #0
sta p l a y e r _ v e l _ x
:
ldx v a r _ n
inx
stx v a r _ n
cpx #1
beq @begin_check
rts
left_collision_check :
lda #0
sta v a r _ n
@begin_check:
lda p l a y e r _ p o s _ x
; divide by 16
sec
sbc #8
clc
ror
clc
ror
clc
ror
clc
ror
sta t e m p _ x
lda p l a y e r _ p o s _ y
ldx v a r _ n
cpx #0
bne : +
sec
sbc #7
jmp : + +
:
clc
adc #6
:
; divide by 16
clc
ror
clc
ror
clc
ror
clc
ror
tay
lda #16
jsr m u l _ y
adc t e m p _ x
tax
2026-02-21 20:35:58 -05:00
lda p l a y e r _ n m t _ x
cmp #0
beq : +
lda l e v e l 2 , X
jmp : + +
:
lda l e v e l , X
:
and #% 10000000
2026-02-17 22:52:47 -05:00
cmp #0
beq : +
lda t e m p _ x
clc
adc #1
asl
asl
asl
asl
clc
adc #8
cmp p l a y e r _ p o s _ x
bcc : +
sta p l a y e r _ p o s _ x
lda #0
sta p l a y e r _ v e l _ x
:
ldx v a r _ n
inx
stx v a r _ n
cpx #1
beq @begin_check
rts
2026-02-21 20:35:58 -05:00