Ludum Dare 27 - CLIMB UP!!
;---------------------------------------- | |
; ### # ### # # ### # # ### # # | |
; # # # ### # # # # # # # # | |
; # # # ### ## # # ### # # | |
; # # # ### # # # # # | |
; ### ### ### # # ### ### # # # | |
; | |
; CLIMB UP!! - Ludum Dare 27 Compo by | |
; Barry "IsharaComix" Peddycord III | |
; | |
; Theme: 10 Seconds | |
; Other theme: Death is useful | |
; | |
; In the game of CLIMB UP!!, you want to jump out of the top of the stage. | |
; But you don't want to get your hands dirty, so you send your lil'dudes to | |
; get there for you. Lil'dudes can push blocks around and jump pretty high, | |
; but have tremendously short lifespans. After 10 seconds, they die. But | |
; luckily, dead lil'dudes are particularly useful as stepping stones, as they | |
; can be pushed around and jumped on like blocks. | |
; | |
; How many lil'dudes do you have to go through to reach the top? | |
; | |
; Controls: | |
; Left and Right, move left and right - push blocks in way | |
; A, jump | |
; | |
;---------------------------------------- | |
START: ; | |
.define PLAYER_X=$210 | |
.define PLAYER_Y=$220 | |
.define PLAYER_S=$230 | |
.define PLAYER_P=$240 | |
.define PLAYER_V=$250 | |
.define CURRENT_X=$201 | |
.define CURRENT_Y=$202 | |
.define CURRENT_V=$203 | |
.define BLOCK_POINT=$204 | |
.define TIMER_HI=$205 | |
.define TIMER_LO=$206 | |
.define ANIM_TICK=$207 | |
; Load the first stage into the game. | |
; This initializes everything | |
LDA #>stage1 | |
STA stage_pointer | |
LDA #<stage1 | |
STA stage_pointer+1 | |
JSR load_stage | |
LDA #10 | |
STA ANIM_TICK | |
; | |
LDA #%10010000 ; Turn back on rendering | |
STA PPUCTRL ; ; | |
LDA #%00011110 | |
STA PPUMASK | |
INFLOOP: JMP INFLOOP ; | |
;---------------------------------------- | |
; | |
; The NMI (non-maskable interrupt) code is run whenever | |
; the screen refreshes. | |
;---------------------------------------- | |
NMI: ; | |
LDA #%00010000 ; Turn off interrupts | |
STA PPUCTRL ; | |
; If we win, load the next stage. | |
LDA PLAYER_Y | |
CMP #10 | |
BCS nowin | |
JSR load_stage | |
nowin: | |
JSR control ; | |
LDA #$10 | |
STA $E2 | |
ogravloop: | |
LDX $E2 | |
DEX | |
STX ignore_me | |
LDA PLAYER_X,X | |
BEQ noexist | |
STA CURRENT_X | |
LDA PLAYER_Y,X | |
STA CURRENT_Y | |
LDA PLAYER_V,X | |
STA CURRENT_V | |
JSR gravity ; | |
LDX $E2 | |
DEX | |
LDA CURRENT_X | |
STA PLAYER_X,X | |
LDA CURRENT_Y | |
STA PLAYER_Y,X | |
LDA CURRENT_V | |
STA PLAYER_V,X | |
noexist: | |
DEC $E2 | |
BNE ogravloop | |
JSR render ; | |
;LDA TIMER_LO | |
;LDX #16 | |
;CMP #30 | |
;BCS drawtimertime | |
;LDX #17 | |
;drawtimertime: | |
;STX PLAYER_S | |
; Count down the timer. After apx 10 sec, the player dies | |
DEC TIMER_LO | |
BNE timeout | |
LDA #60 | |
STA TIMER_LO | |
DEC TIMER_HI | |
BNE timeout | |
LDA #10 | |
STA TIMER_HI | |
JSR dienow | |
timeout: | |
LDA #%10010000 ; Turn back on rendering | |
STA PPUCTRL ; | |
RTI ; Return from interrupt whenever | |
;---------------------------------------- the frame code is finished. | |
;---------------------------------------- | |
; CONTROL | |
; | |
; This subroutine handles the controller. | |
;---------------------------------------- | |
control: ; We do the fancy reader | |
LDA #0 | |
STA ignore_me | |
LDX #9 ; Start with 9 | |
STX CONTROL1 ; Strobe | |
DEX ; Now it's 8 | |
STX CONTROL1 ; | |
conloop: ; | |
LDA CONTROL1 ; Read button into bit 1 | |
ROR A ; Shift into carry | |
ROL $FF ; Shift back into $FF | |
DEX ; 8 times | |
BNE conloop ; | |
LDA $FF ; A register contains all buttons. | |
; jump | |
LDA $FF | |
AND #%10000000 | |
BEQ nojumping | |
LDA PLAYER_V | |
BNE nojumping | |
LDA #-8 | |
STA PLAYER_V | |
LDA #%01001100 | |
STA SQ1VOL | |
LDA #%10000000 | |
STA SQ1LO | |
LDA #%10001001 | |
STA SQ1HI | |
LDA #%11001001 | |
STA SQ1SWEEP | |
LDA #11 | |
STA SNDCHAN | |
nojumping: | |
LDA $FF | |
LDX #0 ; | |
AND #%00000011 ; Check to see if left/right was pressed | |
BEQ notmoving ; | |
CMP #%00000010 ; | |
BCC right ; | |
BNE notmoving ; | |
DEX ; | |
DEX ; | |
JSR lrmove ; | |
RTS ; | |
right: ; | |
INX ; | |
INX ; | |
JSR lrmove ; | |
notmoving: ; | |
RTS ; | |
;---------------------------------------- | |
;---------------------------------------- | |
; LRMOVE | |
; | |
; Attempt to move left or right by the | |
; value in X. Does not check error | |
; conditions. Movement will not occur if | |
; there is a background obstacle | |
;---------------------------------------- | |
lrmove: ; | |
DEC ANIM_TICK | |
BNE noanim | |
LDA PLAYER_S | |
EOR #1 | |
STA PLAYER_S | |
LDY #10 | |
STY ANIM_TICK | |
noanim: | |
CLC | |
STX $E3 | |
TXA | |
ADC PLAYER_X | |
TAX | |
LDY PLAYER_Y | |
DEY | |
STA $F8 | |
JSR collision | |
CMP #0 | |
BNE movecollided | |
LDA $F8 | |
STA PLAYER_X | |
RTS | |
movecollided: | |
LDA collide_me | |
BEQ nomovepush | |
SEC | |
SBC #1 | |
STA ignore_me ; $E4 contains what we collided with | |
TAX | |
LDY PLAYER_Y,X | |
LDA PLAYER_X,X | |
CLC | |
ADC $E3 | |
TAX | |
JSR collision | |
CMP #0 | |
BNE nomovepush | |
LDA $F8 | |
STA PLAYER_X | |
LDX ignore_me | |
LDA PLAYER_X,X | |
CLC | |
ADC $E3 | |
STA PLAYER_X,X | |
nomovepush: | |
RTS ; | |
;---------------------------------------- | |
;---------------------------------------- | |
; GRAVITY | |
; | |
; Gravity increases PLAYER_V by 1 unless | |
; the player collides with the ground. | |
;---------------------------------------- | |
gravity: | |
LDX CURRENT_V | |
BEQ skipgravity | |
CLC | |
LDA CURRENT_Y | |
ADC CURRENT_V | |
STA $FF | |
CPX #7 | |
BEQ notagain | |
INX | |
BNE notagain | |
INX | |
notagain: | |
STX CURRENT_V | |
; check to see if we hit a surface | |
LDY $FF | |
LDX CURRENT_X | |
JSR collision | |
CMP #0 ; if equal, no collision | |
BNE nogravity | |
LDA $FF | |
STA CURRENT_Y | |
RTS | |
nogravity: | |
LDA CURRENT_V | |
BPL uuup | |
LDA CURRENT_Y | |
ADC #4 | |
STA $FF | |
uuup: | |
LDA #0 | |
STA CURRENT_V | |
LDA $FF | |
AND #%11111000 | |
STA CURRENT_Y | |
DEC CURRENT_Y | |
RTS | |
; This checks below to see if there is empty to fall into. | |
skipgravity: | |
LDA CURRENT_Y | |
CLC | |
ADC #2 | |
TAY | |
LDX CURRENT_X | |
JSR collision | |
CMP #0 | |
BNE onfloor | |
LDA #1 | |
STA CURRENT_V | |
onfloor: | |
RTS | |
;---------------------------------------- | |
;---------------------------------------- | |
; COLLISION | |
; | |
; This function returns True if there is | |
; a collision with the playfield at | |
; X, Y (registers). This will check the | |
; tile we're in as well as the tile to the | |
; right and to the bottom. Returns a 0 | |
; value if empty and a non-zero if full. | |
; Destroys X and Y. | |
;---------------------------------------- | |
collision: ; | |
.define ignore_me=$C9 | |
.define collide_me=$C8 | |
STX $E6 | |
STY $E7 | |
LDA #0 | |
STA $EE | |
STA $EF | |
; X contains X position (column) | |
; Y contains Y position (row) | |
; There are 30 rows, with 4 bytes each. | |
; Y goes from 0 to 240. Divide by 8 | |
; to reach 0 to 30. Multiply by 4 to get | |
; the correct byte. | |
TYA | |
LSR A | |
BCC ok1 | |
INC $EE | |
ok1: | |
LSR A | |
BCC ok2 | |
INC $EE | |
ok2: | |
LSR A | |
BCC ok3 | |
INC $EE | |
ok3: | |
ASL A | |
ASL A | |
STA $FE ; fe has the y memory location | |
; There are 32 columns. Each byte contains | |
; 8 columns (one per bit). First find the | |
; correct column id (divide by 8) then find | |
; the byte (divide again by 8) | |
TXA | |
LSR A | |
BCC ok4 | |
INC $EF | |
ok4: | |
LSR A | |
BCC ok5 | |
INC $EF | |
ok5: | |
LSR A | |
BCC ok6 | |
INC $EF | |
ok6: | |
STA $FC ; fc has the x tile | |
STA $EE ; store the tile to verify offset | |
LSR A | |
LSR A | |
LSR A ; A has the memory offset | |
CLC | |
TAX | |
ADC $FE ; Add the memory location | |
STA $FE ; $400+FE has the byte of the current area | |
LDA $FC | |
; Now mod X by 8 to get the BIT | |
AND #%00000111 | |
TAX | |
LDA #%10000000 | |
colliloop: | |
CPX #0 | |
BEQ donecoli | |
LSR A | |
DEX | |
JMP colliloop | |
donecoli: | |
STA $FD ; $FE contains our byte. $FD contains our mask | |
; We check this bit. | |
; If EF, check one to the side | |
; If EE and EF, then check one below | |
; If EE, check one below | |
; if any of these bits are 1, we return !0. otherwise, zero. | |
LDX $FE | |
LDA $400,X | |
AND $FD | |
BNE collireport | |
CLC | |
ROR $FD | |
BCC loadrighter | |
INX | |
ROR $FD | |
loadrighter: | |
LDA $EF | |
BEQ alignedx | |
LDA $400,X | |
AND $FD | |
BNE collireport | |
alignedx: | |
INX | |
INX | |
INX | |
INX | |
LDA $EE | |
BEQ collireport | |
LDA $EF | |
BEQ alignedy | |
LDA $400,X | |
AND $FD | |
BNE collireport | |
alignedy: | |
CLC | |
ROL $FD | |
BCC loadlefter | |
DEX | |
ROL $FD | |
loadlefter: | |
LDA $400,X | |
AND $FD | |
BNE collireport | |
collireport: | |
CMP #0 | |
BEQ blockcollide | |
LDA #$FE | |
STA collide_me | |
RTS | |
blockcollide: ; This phase is where we check block/block | |
; collisions. X=$E6, Y=$E7 | |
CLC | |
LDA $E6 | |
ADC #7 | |
STA $E6 | |
LDA $E7 | |
ADC #7 | |
STA $E7 | |
LDX #0 | |
blkcolloop: | |
CPX ignore_me | |
BEQ endobcoloop | |
LDA PLAYER_X,X | |
CMP $E6 | |
BCS endobcoloop | |
ADC #14 | |
CMP $E6 | |
BCC endobcoloop | |
LDA PLAYER_Y,X | |
CMP $E7 | |
BCS endobcoloop | |
ADC #14 | |
CMP $E7 | |
BCC endobcoloop | |
INX | |
TXA | |
STA collide_me | |
RTS | |
endobcoloop: | |
INX | |
CPX #$10 | |
BNE blkcolloop | |
LDA #0 | |
STA collide_me | |
RTS | |
;---------------------------------------- | |
;---------------------------------------- | |
; RENDER | |
; | |
; This subroutine handles rendering. | |
;---------------------------------------- | |
render: | |
LDX #0 | |
LDY #0 | |
blocks: | |
LDA PLAYER_Y,X | |
STA $700,Y | |
INY | |
LDA PLAYER_S,X | |
STA $700,Y | |
INY | |
LDA PLAYER_P,X | |
STA $700,Y | |
INY | |
LDA PLAYER_X,X | |
STA $700,Y | |
INY | |
INX | |
CPX #$10 | |
BNE blocks | |
LDA #$00 ; Now pass the OAM parameters to the PPU | |
STA OAMADDR ; and do DMA | |
LDA #$07 ; Page 7 has our sprites. | |
STA OAMDMA ; Start DMA | |
RTS | |
;---------------------------------------- | |
;---------------------------------------- | |
; DIENOW | |
; | |
; This turns the player into a block | |
;---------------------------------------- | |
dienow: | |
LDX BLOCK_POINT | |
LDA PLAYER_X | |
STA PLAYER_X,X | |
LDA PLAYER_Y | |
STA PLAYER_Y,X | |
LDA #18 | |
STA PLAYER_S,X | |
LDA PLAYER_P | |
STA PLAYER_P,X | |
DEC BLOCK_POINT | |
BNE dieflipper | |
LDA #15 | |
STA BLOCK_POINT | |
dieflipper: | |
LDA init_x | |
STA PLAYER_X | |
LDA init_y | |
STA PLAYER_Y | |
DEC PLAYER_P | |
BPL samecolor | |
LDA #3 | |
STA PLAYER_P | |
samecolor: | |
LDA #%1100 | |
STA NOISEVOL | |
LDA #%11111000 | |
STA NOISELEN | |
LDA #%10001000 | |
STA NOISEMODE | |
RTS | |
;---------------------------------------- | |
; LOAD_STAGE: This loads a stage from the | |
; memory address pointed to by $00F0 using | |
; indirect addressing. | |
; | |
; Copies the stage into $0400-$04FF. | |
; Loads it into PPU nametable. | |
;---------------------------------------- | |
.define stage_pointer=$F0 ; | |
.define init_x=$400+120 | |
.define init_y=$400+136 | |
.define init_s=$400+152 | |
.define init_p=$400+168 | |
load_stage: ; | |
;---------------------------------------- | |
; First, we copy the stage to stage RAM. | |
;---------------------------------------- | |
LDY #0 ; | |
STY PPUMASK | |
stage_loop: ; | |
LDA (stage_pointer), Y ; | |
STA $0400, Y ; | |
INY ; | |
BNE stage_loop ; | |
;---------------------------------------- | |
; Now we read the new stage RAM to set | |
; up the VRAM and draw the playfield. | |
;---------------------------------------- | |
LDA PPUSTATUS | |
LDA #$20 ; | |
STA PPUADDR ; | |
LDA #0 ; | |
STA PPUADDR ; Start drawing on page $20 - the nametable | |
LDY #0 ; Y is outer loop, run until = 240 | |
stage_dloop: ; | |
LDX #8 ; X is inner loop | |
LDA $0400,Y ; Read from the RAM copy of the field | |
bits_loop: ; Read all 8 bits | |
ASL A ; Put leftmost bit in carry | |
PHA ; Save A | |
LDA #0 ; Get the sprite for air | |
BCC draw_nowall ; | |
LDA #16 ; Get the sprite for a wall | |
draw_nowall: ; | |
STA PPUDATA ; Store the sprite in playfield | |
PLA ; Get the A value back | |
DEX ; | |
BNE bits_loop ; 8 bits in a byte | |
INY ; | |
CPY #120 ; 120 * 8 = all we need | |
BNE stage_dloop ; | |
;---------------------------------------- | |
LDX #$40 | |
LDA stage_pointer+1 | |
AND #3 | |
STA $CB | |
ASL A | |
ASL A | |
ORA $CB | |
ASL A | |
ASL A | |
ORA $CB | |
ASL A | |
ASL A | |
ORA $CB | |
paletters: | |
STA PPUDATA | |
DEX | |
BNE paletters | |
LDA #10 | |
STA TIMER_HI | |
LDA #60 | |
STA TIMER_LO | |
LDA #15 | |
STA BLOCK_POINT | |
; Initialize player sprites and stuff | |
LDY #0 | |
charinit: | |
LDA $400+120,Y | |
STA $210,Y | |
INY | |
CPY #64 | |
BNE charinit | |
;---------------------------------------- | |
; Get the next stage ready. | |
;---------------------------------------- | |
LDA stage_pointer+1 | |
CMP #<stagelast | |
BNE norestart | |
LDA #<stage1 | |
STA stage_pointer+1 | |
JMP okalmostthere | |
norestart: | |
INC stage_pointer+1 | |
okalmostthere: | |
;---------------------------------------- | |
; Clean up and return. | |
;---------------------------------------- | |
LDA PPUSTATUS ; | |
LDA #0 ; Reset scroll latch | |
STA PPUSCROLL ; Fix scrolling values | |
STA PPUSCROLL ; | |
LDA #%00011110 | |
STA PPUMASK | |
RTS ; Return | |
;---------------------------------------- | |
.org $E000 | |
stage0: | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db 30,70,80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
.db 30,70,80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
.db 17,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32 | |
.db 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 | |
.org $E100 | |
stage1: | |
.db %11111111,%11111111,%11111111,%11001111 | |
.db %11111111,%11111111,%11111111,%11001111 | |
.db %11000001,%00000000,%00000000,%00000011 | |
.db %11000001,%00000000,%00000000,%00000011 | |
.db %11000001,%00000000,%00000000,%00000011 | |
.db %11000001,%00000000,%00000000,%00000011 | |
.db %11000001,%00000000,%00000000,%00000011 | |
.db %11000001,%00000000,%00000000,%00000011 | |
.db %11000001,%00000000,%00000000,%11111111 | |
.db %11000001,%00000000,%00000000,%10000011 | |
.db %11000001,%00000000,%00000000,%10000011 | |
.db %11000001,%00000000,%00000000,%10000011 | |
.db %11000001,%00000000,%00000111,%10000011 | |
.db %11000001,%00000000,%00000100,%00000011 | |
.db %11000001,%00000000,%00000100,%00000011 | |
.db %11000001,%00000000,%00000100,%00000011 | |
.db %11000001,%00000000,%00111100,%00000011 | |
.db %11000001,%00000000,%00100000,%00000011 | |
.db %11000001,%00000000,%00100000,%00000011 | |
.db %11000001,%00000000,%00100000,%00000011 | |
.db %11000001,%00000001,%11100000,%00000011 | |
.db %11000001,%00000001,%00000000,%00000011 | |
.db %11000001,%00000001,%00000000,%00000011 | |
.db %11000001,%00000001,%00000000,%00000011 | |
.db %11000000,%00001111,%00000000,%00000011 | |
.db %11000000,%00001000,%00000000,%00000011 | |
.db %11000000,%00001000,%00000000,%00000011 | |
.db %11000000,%00001000,%00000000,%00000011 | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db 30,215,00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
.db 30,30,00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
.db 17,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32 | |
.db 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 | |
.org $E200 | |
.db %11111111,%11111111,%11111111,%11000111 | |
.db %11111111,%11111111,%11111111,%11000111 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00111111 | |
.db %11000000,%00000000,%00000000,%11111111 | |
.db %11111111,%00001111,%00001111,%11111111 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db 30,120,178, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
.db 30,50,30, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
.db 17,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32 | |
.db 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 | |
.org $E300 | |
.db %11111111,%11111111,%11111111,%00011111 | |
.db %11111111,%11111111,%11111111,%00011111 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%11000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00011111 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000111,%11000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%11000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000111,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%11000001,%11111111,%11111111 | |
.db %11000000,%10000000,%00000000,%00000011 | |
.db %11000000,%10000000,%00000000,%00000011 | |
.db %11000000,%10000000,%00000000,%00000011 | |
.db %11000000,%10000000,%00000000,%00000011 | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db 30,70,00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
.db 30,70,00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
.db 17,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32 | |
.db 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 | |
.org $E400 | |
.db %11111111,%11111111,%11111111,%11001111 | |
.db %11111111,%11111111,%11111111,%11001111 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00110011 | |
.db %11001000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000010,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%01000000,%00100000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000001,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db 30,80,111, 175, 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
.db 30,30,30, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
.db 17,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32 | |
.db 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 | |
.org $E500 | |
stagelast: | |
.db %11111111,%11111110,%01111111,%11111111 | |
.db %11111111,%11111110,%01111111,%11111111 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11001010,%11101010,%01010111,%01010011 | |
.db %11001010,%10101010,%01010010,%01110011 | |
.db %11000100,%10101010,%01110010,%01110011 | |
.db %11000100,%10101010,%01110010,%01110011 | |
.db %11000100,%11101110,%01110111,%01010011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%01000110,%01010111,%00000011 | |
.db %11000000,%01000101,%01010101,%00000011 | |
.db %11000000,%01000101,%01110111,%00000011 | |
.db %11000000,%01000101,%00010101,%00000011 | |
.db %11000000,%01110110,%00010111,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11000000,%00000000,%00000000,%00000011 | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db %11111111,%11111111,%11111111,%11111111 | |
.db 125,20,50, 170, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
.db 30,30,30, 30, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
.db 17,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32 | |
.db 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 | |
; ****************************************************** | |
; STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP | |
; | |
; Don't change any of the code underneath this line unless | |
; you know what you are doing. Unlike many computers, the | |
; NES has to have time to warm up before it can run code. | |
; This code will warm up the NES, clear out the memory, | |
; and put it in a known state so that you can write the | |
; important stuff up above. | |
;******************************************************* | |
.org $F000 ; | |
RESET: ; | |
SEI ; Disable IRQs | |
CLD ; Disable decimal mode (not on NES) | |
LDX #$40 ; | |
STX FRAMECTRL ; Disable APU frame IRQ | |
LDX #$FF ; | |
TXS ; Set stack pointer to top of stack | |
INX ; Set X to 0 | |
STX PPUCTRL ; Disable NMI | |
STX PPUMASK ; Disable rendering | |
STX DMCFREQ ; Disable DMC IRQs | |
vblankwait1: ; Wait for the first vertical blank to | |
BIT PPUSTATUS ; ensure PPU is ready. | |
BPL vblankwait1 ; | |
clrmem: ; Zero out all memory | |
LDA #$00 ; | |
STA $0000, x ; | |
STA $0100, x ; | |
STA $0200, x ; | |
STA $0400, x ; | |
STA $0500, x ; | |
STA $0600, x ; | |
STA $0700, x ; | |
LDA #$FE ; | |
STA $0300, x ; | |
INX ; | |
BNE clrmem ; | |
vblankwait2: ; After 2 vertical blanks, the PPU is | |
BIT PPUSTATUS ; is ready to go. | |
BPL vblankwait2 ; | |
;---------------------------------------- | |
; Now we load our sprite palettes. | |
;---------------------------------------- | |
LDA PPUSTATUS ; read PPU status to reset the high/low latch | |
LDA #$3F ; | |
STA PPUADDR ; write the high byte of $3F00 address | |
LDA #$00 ; | |
STA PPUADDR ; write the low byte of $3F00 address | |
LDX #$00 ; start out at 0 | |
loadpalettes: ; | |
LDA palette, x ; load data from address (palette + the value in x) | |
STA PPUDATA ; write to PPU | |
INX ; X = X + 1 | |
CPX #$20 ; Compare X to hex $10, decimal 16 - copying 16 bytes = 4 sprites | |
BNE loadpalettes ; Branch to LoadPalettesLoop if compare was Not Equal to zero | |
; if compare was equal to 32, keep going down | |
;---------------------------------------- | |
; Now load a blank background. We need to fill $1000 bytes from $2000 to $3000 | |
;---------------------------------------- | |
LDA PPUSTATUS ; read PPU status to reset the high/low latch | |
LDA #$00 ; | |
STA PPUSCROLL ; Set the scrolling to 0 | |
STA PPUSCROLL ; | |
JMP START ; | |
;---------------------------------------- | |
; Here's the color palette. | |
;---------------------------------------- | |
palette: ; | |
.db $0F,$02,$12,$22 ; | |
.db $0F,$06,$16,$26 ; | |
.db $0F,$0B,$1B,$2B ; | |
.db $0F,$0C,$1C,$2C ; | |
.db $0F,$02,$12,$22 ; | |
.db $0F,$06,$16,$26 ; | |
.db $0F,$0B,$1B,$2B ; | |
.db $0F,$0C,$1C,$2C ; | |
;---------------------------------------- | |
; Interrupt table - located in the last six bytes of memory. | |
;---------------------------------------- | |
.org $FFFA ; Interrupt table is last three words | |
.dw NMI ; When an NMI happens (once per frame | |
; if enabled, the draw loop) | |
.dw RESET ; When the processor first turns on or | |
; is reset, it will jump to RESET | |
.dw 0 ; External interrupt IRQ is not used | |
;---------------------------------------- | |
; Define all of the memory locations in the memory map. | |
;---------------------------------------- | |
.define ZEROPAGE=$0000 ; | |
.define STACK=$0100 ; | |
.define PPUCTRL=$2000 ; | |
.define PPUMASK=$2001 ; | |
.define PPUSTATUS=$2002 ; | |
.define OAMADDR=$2003 ; | |
.define OAMDATA=$2004 ; | |
.define PPUSCROLL=$2005 ; | |
.define PPUADDR=$2006 ; | |
.define PPUDATA=$2007 ; | |
.define SQ1VOL=$4000 ; | |
.define SQ1SWEEP=$4001 ; | |
.define SQ1LO=$4002 ; | |
.define SQ1HI=$4003 ; | |
.define SQ2VOL=$4004 ; | |
.define SQ2SWEEP=$4005 ; | |
.define SQ2LO=$4006 ; | |
.define SQ2HI=$4007 ; | |
.define TRILIN=$4008 ; | |
.define TRILO=$400A ; | |
.define TRIHI=$400B ; | |
.define NOISEVOL=$400C ; | |
.define NOISEMODE=$400E ; | |
.define NOISELEN=$400F ; | |
.define DMCFREQ=$4010 ; | |
.define DMCRAW=$4011 ; | |
.define DMCSTART=$4012 ; | |
.define DMCLEN=$4013 ; | |
.define OAMDMA=$4014 ; | |
.define SNDCHAN=$4015 ; | |
.define CONTROL1=$4016 ; | |
.define CONTROL2=$4017 ; | |
.define FRAMECTRL=$4018 ; | |
.define PRGROM=$8000 ; | |
;---------------------------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment