/
ppuLoopyReg.go
103 lines (82 loc) · 2.34 KB
/
ppuLoopyReg.go
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package nes
// Loopy registers are 15 bit internal PPU registers used for implementing
// scrolling.
// Loopy register layout:
// yyy NN YYYYY XXXXX
//
// yyy - fine Y scroll
// NN - nametable select
// YYYYY - coarse Y scroll
// XXXXX - coarse X scroll
type PpuLoopyReg uint16
const (
loopyCoarseX PpuLoopyReg = 0b11111
loopyCoarseY = 0b11111 << 5
loopyNametable = 0b11 << 10
loopyFineY = 0b111 << 12
)
// Returns the value fo the loopy register as a unsigned 16-bit integer.
func (r *PpuLoopyReg) value() uint16 {
return uint16(*r)
}
// Sets coarse X (bits 0-4) of the loopy register with the low 5 bits of the
// given value.
func (r *PpuLoopyReg) setCoarseX(val byte) {
// Get relevant 5 bits
setBits := PpuLoopyReg(val) & 0b11111
// Clear bits about to be set
*r &^= loopyCoarseX
// Set new bits
*r |= (setBits)
}
// Sets coarse Y (bits 5-9) of the loopy register with the low 5 bits of the
// given value.
func (r *PpuLoopyReg) setCoarseY(val byte) {
// Get relevant 5 bits
setBits := PpuLoopyReg(val) & 0b11111
// Clear bits about to be set
*r &^= loopyCoarseY
// Set new bits
*r |= (setBits << 5)
}
// Sets nametable (bits 10-11) of the loopy register with the low 2 bits of the
// given value.
func (r *PpuLoopyReg) setNametable(val byte) {
// Get relevant 2 bits
setBits := PpuLoopyReg(val) & 0b11
// Clear bits about to be set
*r &^= loopyNametable
// Set new bits
*r |= (setBits << 10)
}
// Sets fine Y (bits 12-14) of the loopy register with the low 3 bits of the
// given value.
func (r *PpuLoopyReg) setFineY(val byte) {
// Get relevant 3 bits
setBits := PpuLoopyReg(val) & 0b111
// Clear bits about to be set
*r &^= loopyFineY
// Set new bits
*r |= (setBits << 12)
}
func (r *PpuLoopyReg) getCoarseX() byte {
return byte(*r & loopyCoarseX)
}
func (r *PpuLoopyReg) getCoarseY() byte {
return byte((*r & loopyCoarseY) >> 5)
}
func (r *PpuLoopyReg) getNametable() byte {
return byte((*r & loopyNametable) >> 10)
}
func (r *PpuLoopyReg) getFineY() byte {
return byte((*r & loopyFineY) >> 12)
}
// Swap to the other horizontal nametable.
// See: https://wiki.nesdev.com/w/index.php/PPU_scrolling#Wrapping_around
func (r *PpuLoopyReg) toggleNametableH() {
*r ^= 0x0400
}
// Swap to the other vertical nametable.
func (r *PpuLoopyReg) toggleNametableV() {
*r ^= 0x0800
}