.segment "HEADER"
.byte "NES", $1A ; iNES header identifier
.byte 2 ; 2x 16KB PRG code
.byte 1 ; 1x 8KB CHR data
.byte $01, $00 ; mapper 0, vertical mirroring
; "NES" linker config requires a STARTUP section, even if it's empty
.segment "STARTUP"
.segment "ZEROPAGE"
.segment "CODE"
reset:
sei ; disable IRQs
cld ; disable decimal mode
ldx #$40
stx $4017 ; disable APU frame IRQ
ldx #$ff ; set up stack
txs ; .
inx ; now X = 0
stx $2000 ; disable NMI
stx $2001 ; disable rendering
stx $4010 ; disable DMC IRQs
jsr vBlankWait ; wait for vblank to make sure PPU is ready
@clear_memory:
lda #$00
sta $0000, x
sta $0100, x
sta $0300, x
sta $0400, x
sta $0500, x
sta $0600, x
sta $0700, x
lda #$fe
sta $0200, x ; move all sprites off screen
inx
bne @clear_memory
jsr vBlankWait ; wait for vblank, PPU is ready after this
load_palettes:
lda $2002 ; read PPU status to reset the high/low latch
lda #$3f ; write the high byte of $3f00
sta $2006 ; .
lda #$00 ; write the low byte of $3f00
sta $2006 ; .
ldx #$00
@loop:
lda bgPalette, x ; load palette byte
sta $2007 ; write to PPU
inx ; set index to next byte
cpx #$10
bne @loop ; if x = $10, 32 bytes copied, all done
ldx #$00 ; reset our index to 0 for the next loop
@sLoop:
lda sPalette, x ; load palette byte
sta $2007 ; write to PPU
inx ; set index to next byte
cpx #$10
bne @sLoop ; if x = $10, all done
jsr vBlankWait
load_background:
lda $2002 ; read PPU status to reset the high/low latch
lda #$20
sta $2006 ; write the high byte of $2000 address
lda #$00
sta $2006 ; write the low byte of $2000 address
lda #<background
sta $03
lda #>background
sta $04
ldx #$00 ; start out at 0
ldy #$00
@OutsideLoop:
@InsideLoop:
lda ($03), y ; load data from address (background + x)
sta $2007 ; write to PPU
iny ; x = x + 1
cpy #$00 ; compare x to hex $80, decimal 128
bne @InsideLoop
inc $04
inx
cpx #$04
bne @OutsideLoop
lda #%10001000 ; enable NMI, sprites from pattern table 0, background from pattern table 1
sta $2000
lda #%00011110 ; enable sprites, enable background, no clipping on left
sta $2001
forever:
jmp forever
; NMI handler
nmi:
lda #$00
sta $2003 ; set the low byte (00) of the RAM address
lda #$02
sta $4014 ; set the high byte (02) of the RAM address, start the transfer
jsr ReadController
ldx #$00
ldy #$00
lda #$03
sta $03
updateTruck:
lda truckMetasprite+1, y
sta $0200, y
iny
cpy $03
bne updateTruck
lda truckMetasprite+1, y
clc
adc $02
sta $0200, y
iny
tya
clc
adc #$03
sta $03
inx
cpx truckMetasprite
bne updateTruck
; This is the PPU clean up section, so rendering the next frame starts
lda #%10001000 ; enable NMI, sprites from pattern table 0,
sta $2000 ; background from pattern table 1
lda #%00011110 ; enable sprites, enable background,
sta $2001 ; no clipping on left
lda #$00 ; tell the PPU there is no background scrolling
sta $2005
sta $2005
rti
vBlankWait:
bit $2002
bpl vBlankWait
rts
ReadController:
lda #$01
sta $4016
lda #$00
sta $4016
ldx #$08
@ReadControllerLoop:
lda $4016
lsr A ; use bit shifting to pull lowest bit from controller and put into buttons
rol $05
dex
bne @ReadControllerLoop
lda $05
and #%00000001
cmp #%00000001
bne @SkipRight
lda $02
cmp #$C0
beq @SkipRight
clc
adc #$01
sta $02
@SkipRight:
lda $05
and #%00000010
cmp #%00000010
bne @end
lda $02
cmp #$00
beq @end
sec
sbc #$01
sta $02
@end:
rts
; DATA
background:
.byte $2b,$2b,$2b,$2b,$2b,$2b,$2b,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$29
.byte $2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b
.byte $29,$29,$29,$29,$2b,$2b,$2b,$2b,$2b,$2b,$29,$29,$29,$29,$29,$29,$29,$29,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b
.byte $29,$29,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$29,$29,$29,$29,$2b,$2b,$2b,$2b,$2b,$2b,$29,$29,$29,$29,$29,$29,$29,$2b,$2b
.byte $29,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$29,$29,$29,$29,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$29,$29,$29,$29,$29,$29,$29
.byte $2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$29,$29,$29,$29,$29,$29,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$29,$29,$29,$29,$29,$29
.byte $2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$29,$29,$29,$29,$29,$29,$2b,$2b,$2b,$2b,$2b,$2b,$29,$29,$29,$29,$29,$2b,$2b,$2b
.byte $2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$2b,$2b,$2b,$2b,$2b,$2b,$2b
.byte $2b,$2b,$2b,$2b,$2b,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$2b,$2b,$2b,$2b,$2b,$2b,$2b,$29
.byte $2b,$2b,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29
.byte $29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29
.byte $29,$29,$29,$29,$29,$24,$25,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$24,$25,$29,$29,$29,$29,$29,$29,$24,$25,$29,$29,$29,$29,$29
.byte $29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29
.byte $29,$24,$25,$29,$29,$24,$25,$29,$29,$29,$29,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$29,$29,$29,$29,$24,$25,$29,$29,$24,$25,$29
.byte $29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29
.byte $29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29
.byte $29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29
.byte $29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29
.byte $29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29
.byte $29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29,$29,$24,$25,$29
.byte $29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29,$29
.byte $29,$26,$27,$29,$29,$26,$27,$29,$29,$26,$27,$29,$29,$26,$27,$29,$29,$26,$27,$29,$29,$26,$27,$29,$29,$26,$27,$29,$29,$26,$27,$29
.byte $2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a
.byte $28,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48
.byte $28,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48
.byte $28,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48,$48
.byte $2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a
.byte $2a,$15,$08,$04,$12,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$0c,$14,$0d,$08,$13,$08,$0e,$0d,$12,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a
.byte $2a,$2d,$2d,$2d,$2d,$2d,$2d,$2d,$2d,$2a,$2a,$2a,$2c,$2c,$2c,$2c,$2c,$2c,$2c,$2c,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a
.byte $2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a
.byte %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
.byte %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
.byte %00000000, %10100000, %00000000, %00000000, %01010000, %00000000, %01010000, %00000000
.byte %01010101, %10101010, %01010000, %10101010, %01010101, %10100000, %01010101, %10101010
.byte %01010101, %10101010, %01010101, %10101010, %01010101, %10101010, %01010101, %10101010
.byte %01010101, %01011010, %01010101, %01011010, %01010101, %01011010, %01010101, %01011010
.byte %01010101, %01010101, %01010101, %01010101, %01010101, %01010101, %01010101, %01010101
.byte %11111111, %11111111, %11111111, %11111111, %11111111, %11111111, %01010101, %01010101
bgPalette:
.byte $2D,$1C,$21,$31
.byte $2D,$00,$3D,$30
.byte $2D,$00,$0B,$30
.byte $2D,$00,$06,$27
truckMetasprite:
.byte $14
.byte $BE,$13,$00,$00
.byte $B9,$14,$00,$08
.byte $C1,$15,$00,$08
.byte $C1,$15,$00,$28
.byte $AE,$17,$00,$10
.byte $B6,$18,$00,$10
.byte $BE,$19,$00,$10
.byte $BE,$1A,$00,$18
.byte $B6,$1B,$00,$18
.byte $AE,$1A,$80,$18
.byte $AE,$1D,$01,$20
.byte $A9,$1E,$00,$28
.byte $A1,$1F,$00,$28
.byte $AE,$1A,$C0,$30
.byte $B6,$1B,$40,$30
.byte $BE,$1A,$40,$30
.byte $B6,$20,$01,$20
.byte $B1,$21,$01,$28
.byte $B9,$22,$01,$28
.byte $BE,$1C,$80,$20
sPalette:
.byte $2D,$0F,$3D,$2D
.byte $2D,$0F,$3D,$06
.byte $2D,$00,$0A,$30
.byte $2D,$00,$06,$27
;;;;;;;;;;;;;;
.segment "VECTORS"
.word nmi
.word reset
.word 0
;;;;;;;;;;;;;;
.segment "CHARS"
.incbin "invader.chr" ; includes 8KB graphics