aboutsummaryrefslogtreecommitdiff
path: root/ppu/memory.go
blob: 3379242fadf76fa563107d3cae9c5f3c6324702a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package ppu

import "crecher.net/gones/v2/cart"

// maps a $2000-$3EFF address onto an offset into the 2KB of nametable RAM,
// according to the cartridge's mirroring mode. four-screen carts will be
// expected to use their own extra 2KB of RAM via the mapper, but since no
// implemented mapper does that yet, four-screen just falls back to the vertical
// mirroring as a placeholder

func (p *PPU) nametableOffset(addr uint16) int {
	addr &= 0x0FFF
	table := addr / 0x400
	offset := int(addr % 0x400)

	var page uint16
	switch p.mirroring {
	case cart.Horizontal:
		page = table / 2
	case cart.SingleScreenLower:
		page = 0
	case cart.SingleScreenUpper:
		page = 1
	default: // TODO: add correct four-screen behavior once four-screen carts are added
		page = table % 2
	}
	return int(page)*0x400 + offset
}

// paletteIndex applies the $3F10/$3F14/$3F18/$3F1C -> $3F00/$3F04/$3F08/$3F0C
// mirroring
func paletteIndex(addr uint16) uint16 {
	idx := addr & 0x1F
	if idx >= 0x10 && idx%4 == 0 {
		idx -= 0x10
	}
	return idx
}

func (p *PPU) readPalette(addr uint16) uint8 {
	return p.palette[paletteIndex(addr)]
}

func (p *PPU) writePalette(addr uint16, v uint8) {
	p.palette[paletteIndex(addr)] = v
}