Created
May 17, 2010 18:13
-
-
Save Solvalou/404047 to your computer and use it in GitHub Desktop.
Space Invaders NES Reconstruction
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; 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 | |
death_status: .db 0 | |
index: .db 0 | |
line_index: .db 0 | |
collision_index: .db 0 | |
collision_line_index: .db 0 | |
collision_offset: .db 0 | |
line_address: .db 0 | |
line_carry: .db 0 | |
line_offset: .db 0 | |
vblank_count: .db 0 | |
death_count: .db 0 | |
temp: .db 0 | |
anim_var: .db 0 | |
direction: .db 0 | |
anim0_status: .db 0 | |
anim1_status: .db 0 | |
anim2_status: .db 0 | |
anim3_status: .db 0 | |
alien_pos: .db 0 | |
alien_max: .db 0 | |
alien_min: .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, $00, $00, $00, $00, $00, $00, $00 | |
.db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 | |
.db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 | |
.db $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 | |
.db $00, $00, $00, $00, $00, $00, $00, $00, $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 | |
stx death_count | |
stx death_status | |
stx anim_var | |
stx anim0_status | |
stx anim1_status | |
stx anim2_status | |
stx anim3_status | |
stx direction | |
stx alien_pos | |
stx alien_min | |
stx alien_max | |
stx index | |
stx temp | |
stx line_index | |
stx line_address | |
stx line_offset | |
stx line_carry | |
stx collision_index | |
stx collision_offset | |
stx collision_line_index | |
temp_var: ; must be erased later | |
lda #$07 | |
sta alien_max | |
lda #$03 | |
sta alien_min | |
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 vblank ; wait vor vertical blank | |
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 | |
sta collision_line_index | |
collision_loop: | |
jsr collision_offset_calc | |
; lda #1 | |
; sta collision_line_index | |
; lda #11 | |
; sta collision_offset | |
lda collision_index ; if fired, ldy with the collision_index | |
adc collision_offset | |
tay | |
lda alien_data, y ; check for alien | |
beq a_inc ; if (no alien/0) jmp y_inc | |
; beq b_inc | |
; inc collision_index | |
jsr missile_hitbox | |
jsr alien_hitbox | |
jsr draw_hitbox | |
; jsr vblank | |
; jsr sprite_load | |
jsr check_collision | |
lda #$00 | |
sta collision_line_index | |
inc collision_index | |
ldy collision_index | |
cpy #$0B | |
bne collision_loop ; if (collision_index = 11) jmp collision_end | |
jmp infinite | |
; ..................... | |
a_inc: | |
inc collision_line_index | |
lda collision_line_index | |
cmp #$05 | |
beq collision_line_index_reset | |
jmp collision_loop | |
b_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 | |
collision_line_index_reset: | |
; inc line_index | |
lda #$00 | |
sta collision_line_index | |
jmp infinite | |
; ..................... | |
collision_offset_calc: | |
lda #$00 | |
sta collision_offset | |
ldx collision_line_index | |
beq collision_offset_end | |
collision_offset_loop: | |
lda collision_offset | |
adc #$0B | |
sta collision_offset | |
dex | |
bne collision_offset_loop | |
collision_offset_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: | |
lda #$03 ; set destination to $0300 | |
sta $4014 ; beginn sprite-DMA | |
rts | |
death_reset: | |
lda death_y | |
cmp #$FF | |
bcs death_reset_end | |
lda death_status | |
beq death_reset_end | |
lda death_count | |
cmp #05 | |
bne death_count_inc | |
lda #$00 | |
sta death_count | |
lda #$FF | |
sta death_y | |
sta _death_y | |
death_count_inc: | |
inc death_count | |
death_reset_end: | |
rts | |
; ------------------------------------------------------------------------------------- | |
alien_init: | |
; sets the load-position of the nametable | |
lda #$21 | |
sta line_lo | |
lda #$C0 | |
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 #55 | |
bne alien_data_init_rtn | |
rts | |
animation: | |
lda vblank_count | |
cmp #$05 | |
beq animation0 | |
cmp #$0A | |
beq animation1 | |
cmp #$0F | |
beq animation2 | |
cmp #$14 | |
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: | |
; inc alien_pos | |
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: | |
line_address_calc: | |
lda line_index | |
asl a | |
asl a | |
asl a | |
asl a | |
asl a | |
asl a | |
sta line_address | |
line_carry_calc: | |
lda line_index | |
cmp #$04 | |
bne line_carry_reset | |
lda #$01 | |
sta line_carry | |
jmp alien_load_init | |
line_carry_reset: | |
lda #$00 | |
sta line_carry | |
; ---------------- | |
alien_load_init: | |
lda line_lo | |
sec | |
sbc line_carry | |
sta $2006 | |
lda line_hi | |
clc | |
adc alien_pos | |
sec | |
sbc #$01 | |
sta $2006 | |
lda #$00 | |
sta $2007 | |
; ---------------- | |
alien_load_loop: | |
lda index | |
cmp #$0B | |
beq index_reset ; if (x = 12) jmp index_reset | |
jsr line_offset_calc | |
lda index | |
adc line_offset | |
tax | |
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: | |
inc index ; increase index | |
jmp alien_load_loop | |
load_tile_end: | |
inc anim_var | |
jsr scanline_reset | |
rts | |
index_reset: | |
inc vblank_count | |
lda #$00 | |
sta index | |
inc line_index | |
lda line_index | |
cmp #$05 | |
beq line_index_reset | |
jmp index_end | |
line_index_reset: | |
lda direction | |
beq jmp0 | |
jsr alien_pos_dec | |
jmp ovr_jmp | |
jmp0: | |
jsr alien_pos_inc | |
ovr_jmp: | |
jsr direction_init | |
lda #$00 | |
sta line_index | |
index_end: | |
jsr scanline_reset | |
inc anim_var | |
rts | |
load_tile: | |
lda anim_var | |
beq load_tile_end | |
lda direction ; 0 = right, 1 = left | |
beq direction_right | |
jmp direction_left | |
direction_right: | |
jsr alien_load_init1 | |
jsr alien_load_init0 | |
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 | |
direction_left: | |
jsr alien_load_init1 | |
jsr alien_load_init0 | |
lda anim0_status | |
bne load_tile3 | |
lda anim1_status | |
bne load_tile2 | |
lda anim2_status | |
bne load_tile1 | |
lda anim3_status | |
bne load_tile0 | |
alien_pos_inc: | |
lda anim2_status | |
beq alien_pos_inc_end | |
inc alien_pos | |
alien_pos_inc_end: | |
rts | |
alien_pos_dec: | |
lda anim0_status | |
beq alien_pos_dec_end | |
dec alien_pos | |
alien_pos_dec_end: | |
rts | |
direction_init: | |
check_right: | |
lda anim0_status | |
beq check_left | |
lda alien_pos | |
cmp alien_max | |
bne check_left | |
lda #$01 | |
sta direction | |
lda line_hi | |
adc #$20 | |
sta line_hi | |
lda #$0F | |
sta vblank_count | |
jmp direction_end | |
check_left: | |
lda anim3_status | |
beq direction_end | |
lda alien_pos | |
cmp alien_min | |
bne direction_end | |
lda #$00 | |
sta direction | |
lda line_hi | |
adc #$20 | |
sta line_hi | |
direction_end: | |
rts | |
; ---------------- | |
alien_load_init0: | |
lda line_lo ; lo-part of the actual line address | |
sec | |
sbc line_carry | |
sta $2006 | |
lda line_hi ; load the hi-part of the actual line address | |
sec | |
sbc 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 | |
rts | |
; ---------------- | |
alien_load_init1: | |
lda line_lo ; lo-part of the actual line address | |
sec | |
sbc line_carry | |
sta $2006 | |
lda line_hi ; load the hi-part of the actual line address | |
sec | |
sbc line_address | |
sbc #$20 | |
clc | |
adc alien_pos ; add the actual alien-position (x tile-position) | |
adc index ; add the current index twice | |
adc index | |
sta $2006 | |
lda #$00 | |
sta $2007 | |
sta $2007 | |
rts | |
; ...................... | |
line_offset_calc: | |
lda #$00 | |
sta line_offset | |
ldx line_index | |
beq line_offset_end | |
line_offset_loop: | |
lda line_offset | |
adc #$0B | |
sta line_offset | |
dex | |
bne line_offset_loop | |
line_offset_end: | |
rts | |
; ------------------------------------------------------------------------------------- | |
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: | |
lda collision_index | |
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 | |
sta temp | |
tax | |
inx | |
lda #$00 | |
loop2: | |
adc #$08 | |
dex | |
bne loop2 | |
sta alien_bottom | |
tya | |
adc alien_bottom | |
sta alien_bottom | |
lda collision_line_index | |
asl a | |
beq ovr_jmp1 | |
tax | |
lda #$00 | |
loop3: | |
adc #$08 | |
dex | |
bne loop3 | |
sta temp | |
lda alien_bottom | |
sec | |
sbc temp | |
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 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 | |
clc | |
lda collision_index | |
adc collision_offset | |
tay | |
lda #$00 | |
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 | |
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