;------------------------------------------------------------------------------ ; Let's try to recreate a bit of a level from Mario 2 ; ;;;; ; Create an iNES header .ines {"prog": 1, "char": 1, "mapper": 0, "mirror": 0} ;;;; ; Include all the symbols in the nes library .inc ;;;; ; Open the prog section bank 0 .segment prog 0 ;;;; ; Current horizontal scroll value .org $0000 .space horizontal_scroll 1 ;;;; ; Setup the interrupt vectors .org $FFFA .dw vblank .dw main .dw irq ;;;; ; Here is our code entry point, which we'll call main. .org $C000 .scope main ; Disable interrupts and decimal flag sei cld ; Wait for 2 vblanks wait_vb1: lda nes.ppu.status bpl wait_vb1 wait_vb2: lda nes.ppu.status bpl wait_vb2 ; Now we want to initialize the hardware to a known state lda #$00 ldx #$00 clear_segments: sta $00, x sta $0100, x sta $0200, x sta $0300, x sta $0400, x sta $0500, x sta $0600, x sta $0700, x inx bne clear_segments ; Reset the stack pointer ldx #$FF txs ; Disable all graphics and vblank nmi lda #$00 sta nes.ppu.control sta nes.ppu.mask ; Call subroutines to initialize the graphics jsr load_palette jsr load_name_tables jsr init_scrolling jsr init_ppu ; Resume interrupts and loop here forever cli forever: jmp forever . ;;;; ; nes.ppu.control: bitpattern is VPHB SINN ; V: NMI enable ; P: PPU master/slave (this does nothing on the NES) ; H: Sprite height 0 = 8x8, 1 = 8x16 ; B: Background pattern table address (0: $0000; 1: $1000) ; S: Sprite pattern table address for 8x8 sprites (0: $0000; 1: $1000; ignored in 8x16 mode) ; I: VRAM address increment per CPU read/write of nes.vram.io (0: add 1, going across; 1: add 32, going down) ; NN: Base nametable address (0 = $2000; 1 = $2400; 2 = $2800; 3 = $2C00) ; ; Equivalently, bits 0 and 1 are the most significant bit of the scrolling coordinates ; ; nes.ppu.mask: bitpattern is BGRs bMmG ; BGR: Color emphasis bits ; s: Sprite enable ; b: Background enable ; M: Background left column enable ; m: Sprite left column enable ; G: Greyscale ; .scope init_ppu lda #%10001000 ; NMI enable, 8x8 tile, Background: $0000, Sprites: $1000, Address increment: 1, Nametable: $2000 sta nes.ppu.control lda #%00011110 ; No color emphasis, Enable sprites, Enable Background, Enable sprite and bg left column, no greyscale sta nes.ppu.mask rts . ;;;; ; This initializes the scrolling value in the zero page ; So that we begin offscreen and can scroll down .scope init_scrolling lda #$00 sta horizontal_scroll zp rts . ;;;; ; Load palette into $3F00 .scope load_palette lda #$3F ldx #$00 sta nes.vram.address stx nes.vram.address loop: lda palette, x sta nes.vram.io inx cpx #$20 bne loop rts . ;;;; ; Load the background tiles into the name table .scope load_name_tables ldy #$00 ldx #$04 lda #background sta $11 lda #$24 sta nes.vram.address lda #$00 sta nes.vram.address loop: lda ($10), y sta nes.vram.io iny bne loop inc $11 dex bne loop ; Now clear the second nametable ldy #$00 ldx #$04 lda #$00 .scope loop: sta nes.vram.io iny bne loop dex bne loop . rts . ;;;; ; Scroll the screen if we have to .scope scroll_screen ldx #$00 ; Reset VRAM Address to $0000 stx nes.vram.address stx nes.vram.address ldx horizontal_scroll zp inx stx horizontal_scroll zp lda #$00 stx nes.ppu.scroll ; Write the new horizontal scroll value sta nes.ppu.scroll ; Write 0 for vertical scroll rts . ;;;; ; VBlank routine .scope vblank jsr scroll_screen rti . .scope irq rti . ;;;; ; Here is a bg palette which I ripped from Mario 2, but, I just put black for sprite palette palette: .bytes $21, $30, $12, $0F, $21, $30, $16, $0F, $21, $27, $17, $0F, $21, $29, $1A, $0F .bytes $0F, $0F, $0F, $0F, $0F, $0F, $0F, $0F, $0F, $0F, $0F, $0F, $0F, $0F, $0F, $0F ;;;; ; This is the background tile map, or "Name Table" for a bit of a Mario 2 Level. ; Here is how I generated this from a string of hex ; ary.map{|byte| "$%.2X" % byte.to_i(16) }.each_slice(32){|group| puts ".bytes #{group.join(', ')}" } background: .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $BA, $BC, $FA, $FA, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $BB, $BD, $FA, $FA, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $BA, $BC, $FA, $FA, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $BB, $BD, $FA, $FA, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $BA, $BC, $FA, $FA, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $BB, $BD, $FA, $FA, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $BA, $BC, $FA, $FA, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $BB, $BD, $FA, $FA, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $BA, $BC, $FA, $FA, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $BB, $BD, $FA, $FA, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $BA, $BC, $FA, $FA, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $B0, $B1, $B0, $B1, $90, $91, $FA, $FA, $FA, $FA .bytes $B4, $B6, $B8, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $60, $62, $64, $62, $64, $62, $64, $62, $64, $66, $FA, $FA .bytes $B5, $B7, $B9, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $46, $63, $65, $63, $65, $63, $65, $63, $65, $67, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $61, $63, $65, $63, $65, $63, $65, $63, $65, $67, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $61, $63, $65, $63, $65, $63, $65, $63, $65, $67, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $DE, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $61, $63, $65, $63, $65, $63, $65, $63, $65, $67, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $61, $63, $65, $63, $65, $63, $65, $63, $65, $67, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $61, $63, $65, $63, $65, $63, $65, $63, $65, $67, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $61, $63, $65, $63, $65, $63, $65, $63, $65, $67, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $61, $63, $65, $63, $65, $63, $65, $63, $65, $67, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $61, $63, $65, $63, $65, $63, $65, $63, $65, $67, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $61, $63, $65, $63, $65, $63, $65, $63, $65, $67, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $61, $63, $65, $63, $65, $63, $65, $63, $65, $67, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $61, $63, $65, $63, $65, $63, $65, $63, $65, $67, $FA, $FA .bytes $FA, $FA, $FA, $FA, $FA, $FA, $B0, $B1, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $FA, $61, $63, $65, $63, $65, $63, $65, $63, $65, $67, $FA, $FA .bytes $70, $72, $70, $72, $70, $72, $70, $72, $70, $72, $70, $72, $70, $72, $70, $72, $70, $72, $70, $72, $70, $72, $70, $72, $70, $72, $70, $72, $70, $72, $70, $72 .bytes $71, $73, $71, $73, $71, $73, $71, $73, $71, $73, $71, $73, $71, $73, $71, $73, $71, $73, $71, $73, $71, $73, $71, $73, $71, $73, $71, $73, $71, $73, $71, $73 .bytes $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF .bytes $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AE, $AE, $AE, $AE, $AE, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF, $AE, $AF .bytes $55, $55, $55, $55, $33, $44, $DD, $DD, $57, $55, $55, $55, $33, $44, $DD, $DD, $55, $55, $55, $55, $33, $44, $DD, $DD, $50, $55, $55, $55, $CC, $FF, $FF, $FF .bytes $55, $55, $55, $54, $FF, $FF, $FF, $FF, $55, $55, $55, $55, $33, $FF, $FF, $FF, $F5, $F5, $F5, $F5, $F3, $FF, $FF, $FF, $5A, $5A, $5A, $5A, $0A, $0A, $0A, $0A ;;;; ; Here we include an entire binary char rom from Mario 2, which contains 4KB of tile data ; No spirte data is included. .segment char 0 .org $0000 .incbin "mario2.char"