Skip to content

Instantly share code, notes, and snippets.

@Solvalou
Created May 17, 2010 18:07
Show Gist options
  • Save Solvalou/404037 to your computer and use it in GitHub Desktop.
Save Solvalou/404037 to your computer and use it in GitHub Desktop.
; iNES - Header
.inesprg 1 ; size of PRG-ROM, 16kB
.ineschr 1 ; size of CHR-ROM/RAM, 8kB
.inesmir 0 ; type of mirroring, 0 = horizontal, 1 = vertical
.inesmap 0 ; used mapper, 0 = no mapper
.bank 1
.org $FFFA
.dw int_return ; NMI_Routine($FFFA)
.dw start ; Reset_Routine($FFFC)
.dw int_return ; IRQ_Routine($FFFE)
.bank 0
.org $0000 ; RAM, zero-page
missile_status: .db 0
alien_status: .db 0
a_status: .db 0 ; status of the a-button
first_run: .db 0
index: .db 0
collision_index:.db 0
vblank_count_status: .db 0
vblank_death_status: .db 0
vblank_scrolling_status:.db 0
vblank_count: .db 0
vblank_death: .db 0
vblank_scrolling: .db 0
anim_var: .db 0
anim0_status: .db 0
anim1_status: .db 0
anim2_status: .db 0
anim3_status: .db 0
alien_pos: .db 0
line_lo: .db 0
line_hi: .db 0
missile_left: .db 0
missile_right: .db 0
missile_top: .db 0
alien_left: .db 0
alien_right: .db 0
alien_bottom: .db 0
.org $0200
alien_data: .db $00, $00, $00, $00
.db $00, $00, $00, $00
.db $00, $00, $00
.org $0300 ; OAM-area
player_y: .db 0 ; y-position
player_t: .db 0 ; tile-number
player_f: .db 0 ; special flags
player_x: .db 0 ; x-position
_player_y: .db 0
_player_t: .db 0
_player_f: .db 0
_player_x: .db 0
missile_y: .db 0
missile_t: .db 0
missile_f: .db 0
missile_x: .db 0
explosion_y: .db 0
explosion_t: .db 0
explosion_f: .db 0
explosion_x: .db 0
death_y: .db 0
death_t: .db 0
death_f: .db 0
death_x: .db 0
_death_y: .db 0
_death_t: .db 0
_death_f: .db 0
_death_x: .db 0
hitbox_y: .db 0
hitbox_t: .db 0
hitbox_f: .db 0
hitbox_x: .db 0
; -------------------------------------------------------------------------------------
.org $8000 ; start of the PRG-ROM
start:
var_reset:
ldx #$00
stx a_status
stx vblank_count_status
stx vblank_death_status
stx vblank_scrolling_status
stx vblank_count
stx vblank_death
stx vblank_scrolling
stx anim_var
stx anim0_status
stx anim1_status
stx anim2_status
stx anim3_status
stx index
stx collision_index
stx first_run
CPU_init:
cld ; clear decimal mode, not supported
sei ; disable interrupts
stack_init:
ldx #$FF ; set x to $FF = top of stack
txs ; transfer x to stack
palette_init:
lda #$3F ; sets the start-address of the
sta $2006 ; palette-data at $3F00
lda #$00
sta $2006
ldx #$00
palette_load:
lda palette_data, x
sta $2007
inx
cpx #32
bne palette_load
nametable_init:
lda #$20
sta $2006
lda #$00
sta $2006 ; address set to $2000
ldx #$00 ; x reset
lda #$00 ; a reset
; clear 960 bytes
nametable_clear1:
sta $2007
sta $2007
sta $2007
inx
bne nametable_clear1 ; clear 3 x 256 bytes / 768 bytes
ldx #$00
nametable_clear2:
sta $2007
inx
cpx #$C0
bne nametable_clear2 ; clear 192 bytes
jsr scanline_reset
PPU_init:
lda #%00001000
sta $2000 ; background pattern table at $0000
; sprite pattern table at $1000
lda #%00011110
sta $2001 ; #%76543210
; 4 - sprites visible
; 3 - background visible
; 2 - no sprite clipping
; 1 - no background clipping
; 0 - color display
; -------------------------------------------------------------------------------------
; initialize variables
jsr sprite_init
jsr alien_init
jsr alien_data_init
lda #$01
sta anim0_status
infinite: ; infinite loop
; jsr vblank_reset
; jsr death_reset
; jsr input ; check input
sprite_loading:
jsr player_load ; load the player-ship
jsr missile_load ; load the missile-sprite, only when a-button was pressed
jsr sprite_load ; sprite DMA loading-routine
nametable_loading:
; jsr scrolling
jsr animation
jsr alien_load ; load nametable with aliens
; lda #$01
; sta first_run
collision_detection:
lda missile_status ; check if a missile was fired
beq infinite ; if not, jmp back to beginning of the infinite-loop
lda #$00
sta collision_index
collision_loop:
ldy collision_index ; if fired, ldy with the collision_index
lda alien_data, y ; check for alien
beq y_inc ; if (no alien/0) jmp y_inc
jsr missile_hitbox
jsr alien_hitbox
jsr draw_hitbox
; jsr sprite_load
jsr check_collision
inc collision_index
ldy collision_index
cpy #$0B
bne collision_loop ; if (collision_index = 11) jmp collision_end
jmp infinite
y_inc:
inc collision_index ; increment y, used as index
lda collision_index
cmp #$0B
beq collision_index_reset
jmp collision_loop ; next alien_data-position gets checked
collision_index_reset:
lda #$00
sta collision_index
jmp infinite
; trying to get away from this method
vblank_reset:
; lda vblank_count_status
; bne vblank_count_end
; lda #$00
; sta vblank_count
;vblank_count_end:
lda vblank_death_status
bne vblank_death_end
lda #$00
sta vblank_death
vblank_death_end:
lda vblank_scrolling_status
bne vblank_scrolling_end
lda #$00
sta vblank_scrolling
vblank_scrolling_end:
rts
; -------------------------------------------------------------------------------------
sprite_init:
lda #207
sta player_y ; set player_y position to 207
sta _player_y ; this is a solid position, it never gets changed
lda #16 ; set player_x position to 16
sta player_x ; this is the start position of the player
clc
adc #$08
sta _player_x
lda #$FF ; set missile_y position to $FF
sta missile_y ; $FF = off screen
lda #$00
sta player_t ; set the player-tile (0)
sta player_f ; reset the special-flags
sta _player_f
sta missile_f
sta death_f
sta _death_f
sta explosion_f
lda #$01
sta _player_t
lda #$02
sta missile_t
lda #$03
sta explosion_t
lda #$04
sta death_t
lda #$05
sta _death_t
rts
player_load:
lda player_x ; load the x-position for the first player sprite
clc
adc #$08 ; add 8
sta _player_x ; store the x-position for the second player sprite
lda #$FF ; set the explosion sprite off screen
sta explosion_y
rts
missile_load:
lda missile_status ; check missile_status, 1 = fired / 0 = unfired
beq sprite_end ; rts if it isn't fired
dec missile_y ; decrement y-position 2 times
dec missile_y ; missile flies towards top of the screen
lda missile_y
cmp #16
bcs sprite_end ; if (missile_y > 16) jmp sprite_end = rts
jsr explosion ; jump subroutine explosion (line 262)
lda #$00 ; reset the missile_status / unfired
sta missile_status
lda #$FF
sta missile_y ; set missile y-position off screen
rts
explosion:
; sets the explosion-position to the current missile-position
lda missile_y
sta explosion_y
lda missile_x
sbc #$03
sta explosion_x
rts
sprite_end:
rts
sprite_load:
jsr vblank ; wait vor vertical blank
lda #$03 ; set destination to $0300
sta $4014 ; beginn sprite-DMA
rts
death_reset:
lda death_y
cmp #$FF
bcs death_reset_end
lda vblank_death
cmp #10
bne death_reset_end
lda #$00
sta vblank_death_status
sta vblank_death
lda #$FF
sta death_y
sta _death_y
death_reset_end:
rts
; -------------------------------------------------------------------------------------
alien_init:
; sets the load-position of the nametable
lda #$21
sta line_lo
lda #$40
sta line_hi
lda #$05
sta alien_pos ; x-position of the first alien-tile
rts
alien_data_init:
ldx #$00 ; reset x, loop-index
lda #$01 ; set a to 1, 1 = alien enabled
alien_data_init_rtn:
; set the alien_data-table to "1"
sta alien_data, x
inx
cpx #$0B
bne alien_data_init_rtn
rts
scrolling:
lda vblank_scrolling
cmp #$20
bne scrolling_end
inc alien_pos
inc alien_pos
lda #$00
sta vblank_scrolling
scrolling_end:
rts
animation:
; lda #$01
; sta vblank_count_status
inc vblank_count
lda vblank_count
cmp #50
beq animation0
cmp #100
beq animation1
cmp #150
beq animation2
cmp #200
beq animation3
jmp animation_end
animation0:
lda #$00
sta anim0_status
lda #$01
sta anim1_status
jmp animation_end
animation1:
lda #$00
sta anim1_status
lda #$01
sta anim2_status
jmp animation_end
animation2:
lda #$00
sta anim2_status
lda #$01
sta anim3_status
jmp animation_end
animation3:
lda #$00
sta anim3_status
lda #$01
sta anim0_status
lda #$00
sta vblank_count
jmp animation_end
animation_end:
rts
; initialize actual alien-position
alien_load:
lda line_lo
sta $2006
lda line_hi
clc
adc alien_pos
sbc #$01
sta $2006
lda #$00
sta $2007
sta $2007
; ----------------
lda line_lo ; lo-part of the actual line address
sta $2006
lda line_hi ; load the hi-part of the actual line address
clc
adc alien_pos ; add the actual alien-position (x tile-position)
adc index ; add the current index twice
adc index
sta $2006
alien_load_loop:
ldx index
cpx #$0B
beq index_reset ; if (x = 12) jmp index_reset
lda anim_var
beq load_tile_end
lda alien_data, x ; load alien_data, 1 = alien enabled / 2 = alien disabled
bne load_tile ; if (a = 1) jmp load_tile
; if (a = 0) jmp load_empty
load_empty:
lda #$00 ; draw to empty tiles at the current position
sta $2007
sta $2007
load_tile_rtn:
; lda first_run
; bne after_first ; if (first_run = 1) jmp after_first
; lda #$01
; sta vblank_count_status
; lda vblank_count
; cmp #100 ; wait 5 vblanks
; bne load_tile_end ; if (vblank_count < 5) jmp load_tile_end
; lda #$00
; sta vblank_count ; reset vblank_count
after_first:
; lda #$00
; sta vblank_count_status
; lda #$01
; sta vblank_scrolling_status
inc index ; increase index
; lda first_run
; bne load_tile_end
jmp alien_load_loop
load_tile_end:
inc anim_var
jsr scanline_reset
rts
index_reset:
lda #$00
sta index
jsr scanline_reset
rts
load_tile:
lda anim0_status
bne load_tile0
lda anim1_status
bne load_tile1
lda anim2_status
bne load_tile2
lda anim3_status
bne load_tile3
load_tile0:
lda #$40
sta $2007
lda #$41
sta $2007
lda #$00
sta anim_var
jmp load_tile_rtn
load_tile1:
lda #$50
sta $2007
lda #$51
sta $2007
lda #$00
sta anim_var
jmp load_tile_rtn
load_tile2:
lda #$00
sta $2007
lda #$52
sta $2007
lda #$00
sta anim_var
jmp load_tile_rtn
load_tile3:
lda #$53
sta $2007
lda #$54
sta $2007
lda #$00
sta anim_var
jmp load_tile_rtn
; -------------------------------------------------------------------------------------
missile_hitbox:
lda missile_y
clc
adc #$04
sta missile_top
lda missile_x
sta missile_left
adc #$01
sta missile_right
rts
alien_hitbox:
tya
asl a
clc
adc alien_pos
tax
jsr address_calc
rts
; {
address_calc:
; ldx alien_pos
lda #$00
loop0:
adc #$08
dex
bne loop0
sta alien_left
adc #$10
sta alien_right
lda line_lo
and #$0F
beq ovr_jmp0
tax
lda #$00
loop1:
adc #64
dex
bne loop1
tay
ovr_jmp0:
lda line_hi
beq ovr_jmp1
lsr a
lsr a
lsr a
lsr a
lsr a
tax
inx
lda #$00
loop2:
adc #$08
dex
bne loop2
sta alien_bottom
tya
adc alien_bottom
sta alien_bottom
ovr_jmp1:
rts
; }
draw_hitbox:
lda #$10
sta hitbox_t
lda alien_left
sta hitbox_x
lda alien_bottom
clc
sbc #$08
sta hitbox_y
rts
; -------------------------------------------------------------------------------------
check_collision:
clc
;if (top1 > bottom2) return(0);
lda missile_top
cmp alien_bottom
bcs check_collision_end
;if (right1 < left2) return(0);
lda missile_right
cmp alien_left
bcc check_collision_end
;if (left1 > right2) return(0);
lda missile_left
cmp alien_right
bcs check_collision_end
collision_detected:
lda #$00
sta missile_status
lda #$FF
sta missile_y
lda #$01
sta vblank_death_status
lda alien_left
sta death_x
clc
adc #$08
sta _death_x
lda alien_bottom
clc
sbc #$08
sta death_y
sta _death_y
jsr vblank
lda line_lo
lda #$21
sta $2006
clc
lda line_hi
adc alien_pos
adc collision_index
adc collision_index
sta $2006
lda #$00
sta $2007
sta $2007
jsr scanline_reset
lda #$00
ldy collision_index
sta alien_data, y
check_collision_end:
rts
; -------------------------------------------------------------------------------------
input:
input_init:
lda #$01 ; strobe the joypad before read
sta $4016
lda #$00
sta $4016
input_read:
lda $4016 ; a-button
and #1
bne a_button
lda missile_status
bne a_return
lda #$00
sta a_status
a_return:
lda $4016 ; b-button
lda $4016 ; select-button
lda $4016 ; start-button
lda $4016 ; d-pad up
lda $4016 ; d-pad down
lda $4016 ; d-pad left
and #1
bne left
left_return:
lda $4016 ; d-pad right
and #1
bne right
right_return:
rts
a_button:
lda a_status
bne a_return
lda #$01
sta a_status
sta missile_status
lda player_x
clc
adc #$08
sta missile_x
lda player_y
sta missile_y
jmp a_return
left:
lda player_x
cmp #16
beq left_return
dec player_x
jmp left_return
right:
lda player_x
cmp #224
beq right_return
inc player_x
jmp right_return
; -------------------------------------------------------------------------------------
vblank:
lda $2002 ; waits for vertical blank
bpl vblank
; inc vblank_count
; inc vblank_death
; inc vblank_scrolling
rts
scanline_reset:
lda #$00
sta $2005
sta $2005
rts
int_return:
rti
; -------------------------------------------------------------------------------------
palette_data: .incbin "data\palette.pal"
nametable: .incbin "data\nametable.map"
.bank 2
.org $0000
.incbin "data\background.chr" ; 4kB of background sprites
.incbin "data\sprite.chr" ; 4kB of sprite-data
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment