aboutsummaryrefslogtreecommitdiff
path: root/ppu/render.go
diff options
context:
space:
mode:
Diffstat (limited to 'ppu/render.go')
-rw-r--r--ppu/render.go36
1 files changed, 26 insertions, 10 deletions
diff --git a/ppu/render.go b/ppu/render.go
index bfde9e4..ef3ad9a 100644
--- a/ppu/render.go
+++ b/ppu/render.go
@@ -31,14 +31,15 @@ func (p *PPU) renderTick() {
}
}
+ if dot == 257 && (visibleLine || line == preRenderLine) {
+ p.evaluateSprites()
+ }
+
if visibleLine && dot >= 1 && dot <= ScreenWidth {
p.drawPixel(dot-1, line)
}
}
-// the fetch cycle, every tile takes 8 dots to fetch (nametable byte, attribute
-// byte, pattern low, pattern high), 2 dots each. dots 321-336 fetch the first two
-// tiles of the next line ahead of time
func (p *PPU) backgroundFetch(dot int) {
if !((dot >= 2 && dot <= 257) || (dot >= 321 && dot <= 337)) {
return
@@ -144,18 +145,33 @@ func (p *PPU) copyVertical() {
p.v = (p.v &^ 0x7BE0) | (p.t & 0x7BE0)
}
+func (p *PPU) backgroundPixel(x int) (pixel, palette uint8) {
+ if p.Mask&maskShowBackground == 0 || (x < 8 && p.Mask&maskShowBackgroundLeft == 0) {
+ return 0, 0
+ }
+ bit := uint16(0x8000) >> p.x
+ pixel = bitAt(p.patternHi, bit)<<1 | bitAt(p.patternLo, bit)
+ palette = bitAt(p.attrHi, bit)<<1 | bitAt(p.attrLo, bit)
+ return pixel, palette
+}
+
+// mixes the background and sprite pixel at (x, y) into the framebuffer
func (p *PPU) drawPixel(x, y int) {
- var pixel, palette uint8
- if p.Mask&maskShowBackground != 0 && (x >= 8 || p.Mask&maskShowBackgroundLeft != 0) {
- bit := uint16(0x8000) >> p.x
- pixel = bitAt(p.patternHi, bit)<<1 | bitAt(p.patternLo, bit)
- palette = bitAt(p.attrHi, bit)<<1 | bitAt(p.attrLo, bit)
+ bgPixel, bgPalette := p.backgroundPixel(x)
+ spritePixel, spritePalette, behind, isSprite0 := p.spritePixel(x)
+
+ // opaque sprite 0 pixel over an opaque background pixel, never at x = 255
+ if isSprite0 && bgPixel != 0 && x != 255 {
+ p.sprite0Hit = true
}
// pixel 0 of every palette is the shared backdrop color at $3F00
addr := uint16(0x3F00)
- if pixel != 0 {
- addr += uint16(palette)<<2 | uint16(pixel)
+ switch {
+ case spritePixel != 0 && (bgPixel == 0 || !behind):
+ addr = 0x3F10 | uint16(spritePalette)<<2 | uint16(spritePixel)
+ case bgPixel != 0:
+ addr |= uint16(bgPalette)<<2 | uint16(bgPixel)
}
color := p.readPalette(addr)
if p.Mask&maskGreyscale != 0 {