.org $8000                 ; CHR ROM is addressed starting with $8000.. this compensates making all Jumps valid
main:
        SEI
        CLD
        JSR ppuinit        ; initialize PPU
        JSR palette        ; setup palette
        JSR attrib         ; setup attribute table
        JSR mazer          ; write maze to name table
        JSR spriter        ; create sprite
end:
        JSR mover          ; take care of moving sprite with joystick
        JMP end
nmi:                       ; begin vblank interrupt (60 times per sec.)
        JSR sndinit        ; initialize sound
        JSR sounder        ; read sound values from memory and control music during the interrupt phase
        RTI
ppuinit:                   
        LDA #$80           ; See NES Document for register values and meaning
        STA $2000          ; Writes $80 to register $2000
        LDA #$1F           ; and
        STA $2001          ; $1F to register $2001
        RTS
sndinit:
        LDA #$1F           ; Make all sound channels active
        STA $4015
        LDA #$0F           ; See NES Document for register values and meaning
        STA $4000          ; Square 1
        STA $4004          ; Square 2
        STA $4008          ; Triangle 
        LDA #$00           ; See NES Document for register values and meaning
        STA $4001          ; Square 1
        STA $4005          ; Square 2
        STA $4009          ; Triangle
        RTS
square1:
        STX $4002          ; This subroutine stores the X and Y register values to $4002 & $4003
        STY $4003          ; Initiating a tone in the square wave channel #1
        RTS
square2:
        STX $4006          ; This subroutine stores the X and Y register values to $4006 & $4007
        STY $4007          ; Initiating a tone in the square wave channel #2
        RTS
triangle:
        STX $400A          ; This subroutine stores the X and Y register values to $400A & $400B
        STY $400B          ; Initiating a tone in the triangle wave channel
        RTS
palette:
        LDA #$3F           ; This is a really crazy way to map a palette..
        STA $2006          ; It's a ROM hog, but it works 
        LDA #$00           ; basically the first four lines set the PPU writing
        STA $2006          ; address to $3F00 and the remaining lines write value 
        LDA #$01           ; by value to the PPU through $2007 and every write to 
        STA $2007          ; $2007 results in an auto increment by one.. See NES
        LDA #$02           ; documentation for more details.
        STA $2007          ; This takes care of the Image Palette and the Sprite
        LDA #$03           ; Palette
        STA $2007
        LDA #$04
        STA $2007
        LDA #$01
        STA $2007
        LDA #$05
        STA $2007
        LDA #$06
        STA $2007
        LDA #$07
        STA $2007
        LDA #$01
        STA $2007
        LDA #$08
        STA $2007
        LDA #$09
        STA $2007
        LDA #$0A
        STA $2007
        LDA #$01
        STA $2007
        LDA #$0B
        STA $2007
        LDA #$0C
        STA $2007
        LDA #$0D
        STA $2007
        LDA #$01
        STA $2007
        LDA #$02
        STA $2007
        LDA #$03
        STA $2007
        LDA #$04
        STA $2007
        LDA #$01
        STA $2007
        LDA #$05
        STA $2007
        LDA #$06
        STA $2007
        LDA #$07
        STA $2007
        LDA #$01
        STA $2007
        LDA #$08
        STA $2007
        LDA #$09
        STA $2007
        LDA #$0A
        STA $2007
        LDA #$01
        STA $2007
        LDA #$0B
        STA $2007
        LDA #$0C
        STA $2007
        LDA #$0D
        STA $2007
        RTS
scroll:
        STX $2005       ; This routine writes the X and Y registers to the 
        STY $2005       ; scroll register.. See NES Doc. for more details.
        RTS
hput:
        STY $2007       ; This is not a general routine, but a specific routine
        DEX             ; for writing a chain of contiguous identical values to 
        BNE hput        ; the PPU.. The X register must be set to the number of 
        RTS             ; repeats, the Y reg. to the value, and the start address
                        ; must be written to through $2006 before calling this sub.
put:
        STY $2007       ; Just for writing a single value to the PPU
        RTS
attrib:
        LDX #$00        ; Initialize X register to 0
        LDA #$23        ;
        STA $2006       ; Set start address to PPU address $23C0
        LDA #$C0        ;    (1st attribute table)
        STA $2006       ;
lll:
        LDA #$FF        ; Write attribute table value and auto increment
        STA $2007       ; to next address
        INX             ; Increment the X register
        CPX #$40        ; Check to see if X register = $40 (size of Att. table)
        BNE lll         ; If X does not yet equal $40 the loop back to lll and 
        RTS             ; repeat
mazer:
        LDA #$20        ;
        STA $2006       ; Set start address to Name Table #1
        LDA #$00        ;
        STA $2006       ;
        LDX #$00        ; Set X index to 0
beg:
        LDY maze,X      ; Load Y index with "maze" + X offset
rep:
        LDA #$01        ; begin 1st cycle of writing $01 to the name table
        STA $2007       ; the number of times in the Y register
        DEY             ; Decrement Y and
        BNE rep         ; Repeat if Y is not yet zero
        INX             ; Increment X and
        LDY maze,X      ; Read the next maze value into the Y register
repa:
        LDA #$00        ; begin 2nd cycle of writing $00 to the name table
        STA $2007       ; the number of times in the Y register
        DEY             ; Decrement Y and
        BNE repa        ; Repeat if Y is not zero
        INX             ; Increment X
        CPX #252        ; right now the routine quits after 252 maze values
        BNE beg         ; repeat the 1st & 2nd cycle if X isn't yet 252
        RTS
beep:                   ; Just makes a beep
        LDA #$03
        STA $4006
        LDA #$AA
        STA $4007
        RTS
sounder:                ; Takes care of sound handling
        STX $06         ; Save X value in case it's being used when sounder is called
        LDX $03         ; Load the contents of memory address $03 into X
        INX             ; and add one
        STX $03         ; then put it back
        CPX #15         ; If $03 is equal to 15 then continue otherwise go to 
        BNE noplay      ; label noplay
        LDX #$00        ; BEGIN SOUND CODE (4 times per 60 cycles or 1 second)
        STX $03         ; Start $03 at zero again
        LDX $02         ; $02 is an index value to tell which set of notes are 
        LDA music,X     ; being used from the music data
        STA $4002       ; 
        INX             ;   Loads two bytes into square wave #1 registers 
        LDA music,X     ;
        STA $4003       ; <
        INX             ;
        LDA music,X     ;
        STA $4006       ;   Loads two bytes into square wave #2 registers
        INX             ;
        LDA music,X     ;
        STA $4007       ; <
        INX             ;
        LDA music,X     ;
        STA $400A       ;
        INX             ;   Loads two bytes into triangle wave registers
        LDA music,X     ;
        STA $400B       ;
        INX             ; <
        CPX #192        ; there are currently 192 music entries 
        BNE noreset     ; skip setting X to zero if it's less than 192
        LDX #$00
noreset:
        STX $02         ; store X at $02 for future use
noplay:
        LDX $06         ; load the value of X from $06 stored before this 
        RTS             ; sound function executed
spriter:
        LDA #$00        ; Routine for initializing a sprite.. Just writes 
        STA $2003       ; values to Sprite Ram via registers
        LDA #135
        STA $2004
        STA $04
        LDA #$0F
        STA $2004
        LDA #$00
        STA $2004
        LDA #232
        STA $2004
        STA $05
        RTS
joya:                 ; Detect A button press by setting the A register to 0 or 1
        LDA #$01      ;
        STA $4016     ; Reset joystick.. see NES documentation for details
        LDA #$00      ;
        STA $4016     ;
        LDA $4016     ; The first read will have the A button status in it's first bit
        AND #$01      ; Set A to 1 if pressed ; 0 if not
        RTS
joyb:
        LDA #$01      ; See joystick A routine
        STA $4016
        LDA #$00
        STA $4016
        LDA $4016
        LDA $4016     ; The second read will have the B button status
        AND #$01
        RTS
joysel:
        LDA #$01
        STA $4016
        LDA #$00
        STA $4016
        LDA $4016
        LDA $4016
        LDA $4016     ; 3 reads for select
        AND #$01
        RTS
joyst:
        LDA #$01
        STA $4016
        LDA #$00
        STA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016    ; 4 reads for start
        AND #$01
        RTS
joyup:
        LDA #$01
        STA $4016
        LDA #$00
        STA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016     ; 5 reads for up
        AND #$01
        RTS
joydown:
        LDA #$01
        STA $4016
        LDA #$00
        STA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016     ; 6 reads for down
        AND #$01
        RTS
joyleft:
        LDA #$01
        STA $4016
        LDA #$00
        STA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016    ; 7 reads for left
        AND #$01
        RTS
joyright:
        LDA #$01
        STA $4016
        LDA #$00
        STA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016
        LDA $4016     ; 8 reads for down
        AND #$01
        RTS
movesprite:
        LDA #$00       ; writes to sprite RAM to move sprite #0 to the coordinates
        STA $2003      ; in the X and Y registers
        STY $2004
        LDA #$03
        STA $2003
        STX $2004
        RTS
mover:
        JSR joyup      ; This routine handles moving the sprite based on input
        BEQ aa         ; It's rather complex to document.. see if you can figure
        LDX $05        ; it out :) .. all the JSR calls are just for the sake of
        LDY $04        ; slowing down the function enough to make each frame of
        DEY            ; movement visible.. each movement moves eight spaces to
        JSR pause      ; keep the sprite in-line with name table entries.. and just
        DEY            ; to make things more confusing, the sprite coordinates are
        JSR pause      ; updated in the pause routine.. Have fun deciphering this one
        DEY
        JSR pause
        DEY
        JSR pause
        DEY
        JSR pause
        DEY
        JSR pause
        DEY
        JSR pause
        DEY
        JSR pause
        STY $04
        JSR beep
aa:
        JSR joydown
        BEQ bb
        LDX $05
        LDY $04
        INY
        JSR pause
        INY
        JSR pause
        INY
        JSR pause
        INY
        JSR pause
        INY
        JSR pause
        INY
        JSR pause
        INY
        JSR pause
        INY
        JSR pause
        STY $04
        JSR beep
bb:
        JSR joyleft
        BEQ cc
        LDX $05
        LDY $04
        DEX
        JSR pause
        DEX
        JSR pause
        DEX
        JSR pause
        DEX
        JSR pause
        DEX
        JSR pause
        DEX
        JSR pause
        DEX
        JSR pause
        DEX
        JSR pause
        STX $05
        JSR beep
cc:
        JSR joyright
        BEQ dd
        LDX $05
        LDY $04
        INX
        JSR pause
        INX
        JSR pause
        INX
        JSR pause
        INX
        JSR pause
        INX
        JSR pause
        INX
        JSR pause
        INX
        JSR pause
        INX
        JSR pause
        STX $05
        JSR beep
dd:
        RTS
timehog:
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        RTS
time:
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        JSR timehog
        RTS
pause:
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR time
        JSR movesprite
        RTS
music:                           ; music data.. each line goes with a set of values for all three music channels
.db $B4,$10,$EF,$40,$B4,$40
.db $B4,$10,$EF,$40,$B4,$40
.db $A0,$20,$EF,$40,$B4,$40
.db $B4,$10,$EF,$40,$B4,$40
.db $B4,$10,$EF,$40,$B4,$40
.db $B4,$10,$EF,$40,$B4,$40
.db $A9,$20,$EF,$40,$B4,$40
.db $B4,$10,$EF,$40,$B4,$40
.db $B4,$10,$EF,$40,$B4,$40
.db $B4,$10,$EF,$40,$B4,$40
.db $8E,$10,$EF,$40,$B4,$40
.db $B4,$10,$EF,$40,$B4,$40
.db $A0,$10,$EF,$40,$B4,$40
.db $B4,$10,$EF,$40,$B4,$40
.db $A9,$10,0,0,$7F,$40
.db $B4,$10,0,0,$78,$40
.db $B4,$10,$D4,$40,$A0,$40
.db $B4,$10,$D4,$40,$A0,$40
.db $A0,$20,$D4,$40,$A0,$40
.db $B4,$10,$D4,$40,$A0,$40
.db $B4,$10,$D4,$40,$A0,$40
.db $B4,$10,$D4,$40,$A0,$40
.db $A9,$20,$D4,$40,$A0,$40
.db $B4,$10,$D4,$40,$A0,$40
.db $B4,$10,$D4,$40,$A0,$40
.db $B4,$10,$D4,$40,$A0,$40
.db $8E,$10,$D4,$40,$A0,$40
.db $B4,$10,$D4,$40,$A0,$40
.db $A0,$10,$D4,$40,$A0,$40
.db $B4,$10,$D4,$40,$A0,$40
.db $A9,$10,0,0,$7F,$40
.db $B4,$10,0,0,$78,$40
maze:                                   ; maze data.. the first value represents contiguous blocks.. the second value represents contiguous empty space.. and it alternates like this
.db 64
.db 3,1,14,1,5,1,5,2
.db 3,1,14,1,5,1,5,3
.db 2,1,2,10,2,1,2,1,2,1,2,1,2,3
.db 2,1,5,1,5,1,2,1,2,1,2,1,2,1,2,3
.db 2,1,5,1,5,1,2,1,2,1,2,1,2,1,2,3
.db 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,3
.db 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,3
.db 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,3
.db 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,3
.db 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,3
.db 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,3       
.db 2,1,2,1,2,1,2,1,2,1,5,1,2,1,2,1,2,3
.db 2,1,2,1,2,1,2,1,2,1,5,1,2,1,2,1,2,3    
.db 2,1,2,1,2,1,2,1,2,7,2,1,2,1,2,3        
.db 5,1,5,1,14,1,2,3      
.db 5,1,5,1,14,1,2,34      
               
       .end                         ; finally :)


