Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .inesprg 1 ; 1x 16KB PRG code
- .ineschr 1 ; 1x 8KB CHR data
- .inesmap 0 ; mapper 0 = NROM, no bank swapping
- .inesmir 1 ; background mirroring
- ;;;;;;;;;;;;;;;
- ;---------------------------------------------------------------------------------------------------------------
- .rsset $0000
- CharX .rs 1 ;Setting variable for the Mushroom X Position
- CharY .rs 1 ;Setting variable for the Mushroom Y Position
- buttons1 .rs 1 ; player 1 gamepad buttons, one bit per button
- buttons2 .rs 1 ; player 2 gamepad buttons, one bit per button
- AddrLow: .rs 1
- AddrHigh: .rs 1
- vBlankTimer .rs 1 ;** increments once per frame until it wraps back around to zero.
- ;** used to sync game logic to once a frame
- .bank 0
- .org $C000
- ;** We can put subroutines here for now, where they wouldn't be reached unless called
- ;---------------------------------------------------------------------------------------------------------------------
- ReadController1:
- LDA #$01
- STA $4016
- LDA #$00
- STA $4016
- LDX #$08
- ReadController1Loop:
- LDA $4016
- LSR A ; bit0 -> Carry
- ROL buttons1 ; bit0 <- Carry
- DEX
- BNE ReadController1Loop
- RTS
- ;---------------------------------------------------------------------------------------------------------------------
- ;---------------------------------------------------------------------------------------------------------------------
- MovePlayerAccordingToControllerInput:
- ReadDOWN:
- LDA buttons1
- AND #%00000001 ; only look at bit 0
- BEQ ReadDOWNDone ; branch to ReadBDone if button is NOT pressed (0)
- ; add instructions here to do something when button IS pressed (1)
- LDA CharY ; load sprite X position
- SEC ; make sure carry flag is set
- SBC #$01 ; A = A - 1
- STA CharY ; save sprite X position
- ReadDOWNDone: ; handling this button is done
- ReadUP:
- LDA buttons1
- AND #%00000010 ; only look at bit 0
- BEQ ReadUPDone ; branch to ReadADone if button is NOT pressed (0)
- ; add instructions here to do something when button IS pressed (1)
- LDA CharY ; load sprite X position
- CLC ; make sure the carry flag is clear
- ADC #$01 ; A = A + 1
- STA CharY ; save sprite X position
- ReadUPDone: ; handling this button is done
- ReadRIGHT:
- LDA buttons1
- AND #%00000100 ; only look at bit 0
- BEQ ReadRIGHTDone ; branch to ReadBDone if button is NOT pressed (0)
- ; add instructions here to do something when button IS pressed (1)
- LDA CharX ; load sprite X position
- SEC ; make sure carry flag is set
- SBC #$01 ; A = A - 1
- STA CharX ; save sprite X position
- ReadRIGHTDone: ; handling this button is done
- ReadLEFT:
- LDA buttons1
- AND #%00001000 ; only look at bit 0
- BEQ ReadLEFTDone ; branch to ReadADone if button is NOT pressed (0)
- ; add instructions here to do something when button IS pressed (1)
- LDA CharX ; load sprite X position
- CLC ; make sure the carry flag is clear
- ADC #$01 ; A = A + 1
- STA CharX ; save sprite X position
- ReadLEFTDone: ; handling this button is done
- RTS
- ;---------------------------------------------------------------------------------------------------------------------
- ;---------------------------------------------------------------------------------------------------------------------
- BufferSprites:
- LDX #$00 ; Start routine a 0 to load the first sprite and to store at the first byte of OAM buffer
- StoreSpritesIntoOamBuffer:
- LDA CharY ; Load the object Y position
- CLC
- ADC sprites, x ; Add Y offset of sprite from object position
- STA $0200, x ; Store to OAM buffer
- INX
- LDA sprites, x ; Load the sprite tile
- STA $0200, x ; Store to OAM buffer
- INX
- LDA sprites, x ; Load the sprite attribute
- STA $0200, x ; Store to OAM buffer
- INX
- LDA CharX ; Load the object X position
- CLC
- ADC sprites, x ; Add X offset of sprite from object position
- STA $0200, x ; Store to OAM buffer
- INX
- CPX #$10 ; See if this was the last sprite that needed to be loaded
- BNE StoreSpritesIntoOamBuffer ; Loop back if not.
- RTS
- ;---------------------------------------------------------------------------------------------------------------------
- RESET:
- SEI ; disable IRQs
- CLD ; disable decimal mode
- LDX #$40
- STX $4017 ; disable APU frame IRQ
- LDX #$FF
- TXS ; Set up stack
- INX ; now X = 0
- STX $2000 ; disable NMI
- STX $2001 ; disable rendering
- STX $4010 ; disable DMC IRQs
- vblankwait1: ; First wait for vblank to make sure PPU is ready
- BIT $2002
- BPL vblankwait1
- clrmem:
- 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
- INX
- BNE clrmem
- vblankwait2: ; Second wait for vblank, PPU is ready after this
- BIT $2002
- BPL vblankwait2
- ;---------------------------------------------------------------------------------------------------------------
- ;Any code you want to run should be after this point at the earliest
- ;** No need to read your controller here because it's only going to happen once
- ; JSR ReadController1
- **You can, however, move your position initialization here to occur before your game loop
- LDA #$3C ;Load the x position for the mushroom player; 64 in deminal
- STA CharX
- LDX #$AB ;Load the x position for the mushroom player; 268 in deminal
- STA CharY
- LoadPalettes:
- LDA $2002 ; read PPU status to reset the high/low latch
- LDA #$3F
- STA $2006 ; write the high byte of $3F00 address
- LDA #$00
- STA $2006 ; write the low byte of $3F00 address
- LDX #$00 ; start out at 0
- LoadPalettesLoop:
- LDA palette, x ; load data from address (palette + the value in x)
- ; 1st time through loop it will load palette+0
- ; 2nd time through loop it will load palette+1
- ; 3rd time through loop it will load palette+2
- ; etc
- STA $2007 ; write to PPU
- INX ; X = X + 1
- CPX #$20
- BNE LoadPalettesLoop
- ;---------------------------------------------------------------------------------------------------------------
- LDA $2002
- LDA #$20
- STA $2006 ; write the high byte of $2000 address
- LDA #$00
- STA $2006 ; write the low byte of $2000 address
- LDA #low(background)
- STA AddrLow
- LDA #high(background)
- STA AddrHigh
- LDX #$04 ; Loop X 4 times
- LDY #$00 ; Loop Y 256 times
- LoadBackgroundsLoop:
- LDA [AddrLow],y
- STA $2007
- INY
- BNE LoadBackgroundsLoop
- ; Outer loop
- INC AddrHigh ; increment high byte of address backg to next 256 byte chunk
- DEX ; one chunk done so X = X - 1.
- BNE LoadBackgroundsLoop ; if X isn't zero, do again
- LDA $2002 ; Reset Scroll
- LDA #$00
- STA $2005
- STA $2005
- STA $2006
- STA $2006
- LDA #%10010000 ; enable NMI, sprites from Pattern Table 0, background from Pattern Table 1
- STA $2000
- LDA #%00011110 ; enable sprites, enable background, no clipping on left side
- STA $2001
- ;-------------------------------------------------------------------------------------------------------
- ;**This is your main game loop
- ;** these are things that happen once every frame but don't need to be in vBlank
- Forever:
- JSR ReadController1
- JSR MovePlayerAccordingToControllerInput
- JSR BufferSprites
- LDA vBlankTimer
- MainVblankTimer: ; ** This timer prevents your game logic from running more than once per frame
- CMP vBlankTimer
- BEQ MainVblankTimer
- JMP Forever ;jump back to Forever, infinite loop
- ;-------------------------------------------------------------------------------------------------------
- ;-------------------------------------------------------------------------------------------------------
- ;**This is your NMI. It runs once per frame in vBlank annd must end with an RTI statement
- NMI:
- PHA
- LDA $2002
- 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
- INC vBlankTimer
- PLA
- RTI ;** <--- you forgot to return from interrupt after your NMI is called
- ;-------------------------------------------------------------------------------------------------------
- .bank 1
- .org $E000
- palette:
- .db $22,$29,$1A,$0F, $22,$36,$17,$0F, $22,$30,$21,$0F, $22,$27,$17,$0F ;;background palette
- .db $22,$16,$30,$26, $22,$02,$38,$3C, $22,$1C,$15,$14, $22,$02,$38,$3C ;;sprite palette
- sprites:
- ;vert tile attr horiz
- .db $00, $76, $00, $00
- .db $00, $77, $00, $08
- .db $08, $78, $00, $00
- .db $08, $79, $00, $08
- background:
- ;X Pos 0 8 16 24 32 40 48 56 64 72 80 88 96 104 112 120
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 1
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 0
- ;; 128 136 144 152 160 168 176 184 192 200 208 216 224 232 240 248
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 2
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 8
- ;Column 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
- .db $24,$24,$24,$1F,$12,$15,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 3
- .db $24,$24,$20,$18,$1B,$15,$0D,$24,$24,$1D,$12,$16,$0E,$24,$24,$24 ;; Y Position 16
- ; 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
- .db $24,$24,$24,$00,$00,$00,$00,$00,$00,$24,$24,$19,$29,$00,$00,$24 ;; Row 4
- .db $24,$24,$24,$09,$28,$01,$24,$24,$24,$24,$00,$00,$00,$24,$24,$24 ;; Y Position 24
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 5
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 32
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$36,$37,$24,$24,$24,$24 ;; Row 6
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 40
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$35,$25,$25,$38,$24,$24,$24 ;; Row 7
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 48
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$39,$3A,$3B,$3C,$24,$24,$24 ;; Row 8
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 56
- .db $24,$24,$24,$24,$24,$24,$36,$37,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 9
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 64
- .db $24,$24,$24,$24,$24,$35,$25,$25,$38,$24,$24,$24,$24,$24,$24,$24 ;; Row 10
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 72
- .db $24,$24,$24,$24,$24,$39,$3A,$3B,$3C,$24,$24,$24,$24,$24,$24,$24 ;; Row 11
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 80
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 12
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 88
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 13
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 96
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 14
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 104
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$11,$0E,$15,$15,$18,$24 ;; Row 15
- .db $20,$18,$1B,$15,$0D,$2B,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 112
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 16
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 120
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 17
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 128
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 18
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 136
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 19
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 144
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 20
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 152
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 21
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 160
- .db $24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24,$24 ;; Row 22
- .db $24,$24,$24,$24,$24,$24,$31,$32,$24,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 168
- .db $24,$24,$24,$24,$24,$24,$24,$60,$61,$62,$63,$24,$24,$24,$24,$24 ;; Row 23
- .db $24,$24,$24,$24,$24,$30,$26,$34,$33,$24,$24,$24,$24,$24,$24,$24 ;; Y Position 176
- .db $24,$24,$24,$24,$24,$24,$24,$64,$65,$66,$67,$24,$24,$24,$24,$24 ;; Row 24
- .db $24,$24,$24,$24,$30,$26,$26,$26,$26,$33,$24,$24,$24,$24,$24,$24 ;; Y Position 184
- .db $24,$24,$24,$24,$24,$24,$24,$68,$69,$26,$6A,$24,$24,$24,$24,$24 ;; Row 25
- .db $24,$24,$24,$30,$26,$34,$26,$26,$34,$26,$33,$24,$24,$24,$24,$24 ;; Y Position 192
- .db $24,$24,$24,$24,$24,$24,$24,$68,$69,$26,$6A,$24,$24,$24,$24,$24 ;; Row 26
- .db $24,$24,$30,$26,$26,$26,$26,$26,$26,$26,$26,$33,$24,$24,$24,$24 ;; Y Position 200
- .db $B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5 ;; Row 27
- .db $B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5 ;; Y Position 208
- .db $B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7 ;; Row 28
- .db $B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7 ;; Y Position 216
- .db $B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5 ;; Row 29
- .db $B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5,$B4,$B5 ;; Y Position 224
- .db $B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7 ;; Row 30
- .db $B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7,$B6,$B7 ;; Y Position 232
- attribute:
- ;; Each 2 bits on each binary byte are a tile's palette information; so each byte
- ;; manages to color a square 2x2 tile's portion of the screen; and its arranged like this:
- ;;
- ;; If we separate tbese binary number like this:
- ;;
- ;; Position: 0 1 2 3
- ;; %00 01 10 11
- ;;
- ;; We can tell which 2 bits are arranging our tile pallette if we follow this pattern in
- ;; a square 2x2 tile
- ;;
- ;; Square 2x2 Tile: XX XX
- ;; XX XX
- ;;
- ;; Attribute pattern on these tiles: 03 02
- ;; 00 01
- ;;
- ;; So, the binary in the example adobe are arranged like this using the full byte:
- ;;
- ;; Atribute output: 11 10
- ;; 00 01
- .db %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010
- .db %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010
- .db %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010
- .db %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010
- .db %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010, %10101010
- .db %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000, %00000000
- .db %01010000, %01010000, %01010000, %01010000, %01010000, %01010000, %01010000, %01010000
- .db %01010101, %01010101, %01010101, %01010101, %01010101, %01010101, %01010101, %01010101
- .org $FFFA ;first of the three vectors starts here
- .dw NMI ;when an NMI happens (once per frame if enabled) the
- ;processor will jump to the label NMI:
- .dw RESET ;when the processor first turns on or is reset, it will jump
- ;to the label RESET:
- .dw 0 ;external interrupt IRQ is not used in this tutorial
- ;;;;;;;;;;;;;;
- .bank 2
- .org $0000
- .incbin "mario.chr" ;includes 8KB graphics file from SMB1
RAW Paste Data