PPU display background pattern
Posted: Thu Sep 12, 2013 9:11 am
Goal: I would like to set the NES background as a single repeating pattern.
Something like this:
Problem: I can't get my pattern to display. I have the pattern I want loaded into the pattern table, I have written the colors I want to the background palette, all name tables are pointing to tile zero, all my attribute tables are zero; yet nothing is being displayed.
Logical program flow (what I think my program is doing):
Here is my name tables according to FCEUX:
Yet my emulator is only displaying:
Secondary/tangent questions:
Something like this:
Problem: I can't get my pattern to display. I have the pattern I want loaded into the pattern table, I have written the colors I want to the background palette, all name tables are pointing to tile zero, all my attribute tables are zero; yet nothing is being displayed.
Logical program flow (what I think my program is doing):
- disable interrupts / set stack pointer
- set PPU control #1 bits to %00001000 so that:
- D0-D1: name table address set to $2000
- D2: PPU increment is 1
- D3: sprite pattern address is $1000
- D4: background pattern address is $0000
- D5: sprite size is 8x8
- D6: ?
- D7: disable NMI on Vblank
- set PPU control #2 bits to %00011110 so that:
- D0: color display
- D1: no background clipping
- D2: no sprite clipping
- D3: background is visible
- D4: sprites are visible (no sprites in this example)
- D5-D7: color intensity is set to none
- clear Vblank flag
- first wait for Vblank
- second wait for Vblank
- enable NMI on Vblank
- Branch:
- Main loop constantly sets $00 to whatever is in the Xreg
- on NMI interrupt
- write two bytes to the background palette (first is transparency, second is the color I want the pattern to be)
- write one byte of $00 to name table #0 and attribute table #0 (really does nothing)
Here is my name tables according to FCEUX:
Yet my emulator is only displaying:
Secondary/tangent questions:
- Why is so much of the NES memory mirrored? From a newb point of view this seems wasteful.
- From (http://wiki.nesdev.com/w/index.php/Init_code); disabling IRQs (opcode SEI) is good if one might later desire to manually call the RESET routine. This makes sense to me but I have noticed that the order in which NMI and IRQs are enabled (I'm referencing my "INIT:" label in "test.s" below) determines whether or not PPU memory is written to (i.e. calling "CLI" before setting the 7th bit of PPU control #1 to 1 causes pattern table, name table, and attribute table to be empty; it might actually be causing the whole NES to crash, I'm not sure.)
- Here I'm thinking it might be best to not manually disable IRQs (call SEI) and let the system do it naturally on interrupt for the benefit of simplicity.
Code: Select all
; TESTING
; cl65 -t none -C nes.cfg -o test.nes test.s
; Program ROM
.segment "PRG"
RESET:
; set up a few things and wait for PPU
SEI ; in case of manual reset call
CLD ; generic 6502 debugger friendly
LDX #$FF ; setting value for stack pointer
TXS ; setting stack pointer
LDX #%00001000 ; PPU control bits
STX $2000 ; set PPU control register #1
LDX #%00011110 ; PPU control bits
STX $2000 ; set PPU control register #2
BIT $2002 ; clears the Vblank flag on read (BIT sets the Neg flag to bit 7)
VBLANKWAIT1:
; wait for PPU to stabilize
BIT $2002 ; sets CPU Neg flag to Vblank flag
BPL VBLANKWAIT1 ; if the Neg flag isn't set branch to VBLANKWAIT
VBLANKWAIT2:
; wait a second time
BIT $2002 ; sets CPU Neg flag to Vblank flag
BPL VBLANKWAIT2 ; if the Neg flag isn't set branch to VBLANKWAIT
INIT:
; enable interrupts
LDX #%10001000 ; PPU control bits
STX $2000 ; set PPU control register #1
CLI
LOOP:
; main loop
STX $00
JMP LOOP
RTI
NMI:
; Non-maskable interrupt
LDA #$3F ; set address pointer in VRAM to $3F00
STA $2006
LDA #$00
STA $2006
LDA #$17 ; write a little to background palette
STA $2007
LDA #$03
STA $2007
LDA #$20 ; set address pointer in VRAM to $2000
STA $2006
LDA #$00
STA $2006
LDA #%00000000 ; write a little to name table #0
STA $2007
LDA #$23 ; set address pointer in VRAM to $23C0
STA $2006
LDA #$C0
STA $2006
LDA #%00000000 ; write a little to attibute table #0
STA $2007
RTI
IRQ:
; Interrupt request
RTI
; iNES header
.segment "HDR"
.byte "NES" ; signature
.byte $1A ; signature
.byte $02 ; # of 16kb PRG-ROM banks
.byte $01 ; # of 8kb CHR-ROM banks
.byte $00 ; ROM control byte one
.byte $00 ; ROM control byte two
.byte $00 ; # of 8kb RAM banks
.byte $00 ; reserved
; Vectors
.segment "VEC"
.addr NMI
.addr RESET
.addr IRQ
; Pattern tables
.segment "CHR"
; one tile
; least significant bit one
.byte %00011000
.byte %00100100
.byte %01011010
.byte %01000010
.byte %01000010
.byte %01011010
.byte %00100100
.byte %00011000
; least significant bit two
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000
.byte %00000000