aboutsummaryrefslogtreecommitdiff
path: root/ppu/render.go
diff options
context:
space:
mode:
authorcrecher <crecher@crecher.net>2026-10-13 01:13:13 +0200
committercrecher <crecher@crecher.net>2026-10-13 01:13:13 +0200
commit99cae5a5a37f41f878a84857361eda47910303ba (patch)
tree31c8665ca991f95e09e93bb2e6ec91d81d2427ff /ppu/render.go
parent96ff6d8eda2ba434682909f4ff4ce350d78b2273 (diff)
downloadgones-99cae5a5a37f41f878a84857361eda47910303ba.tar.gz
gones-99cae5a5a37f41f878a84857361eda47910303ba.zip
sprites!!!!!!
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 {