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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
package tests
import (
"testing"
"crecher.net/gones/v2/cart"
"crecher.net/gones/v2/nes"
)
func newTestConsole(t *testing.T) *nes.Console {
t.Helper()
c, err := cart.Load("testdata/nestest.nes")
if err != nil {
t.Fatal(err)
}
return nes.New(c)
}
func strobe(n *nes.Console) {
n.Write(0x4016, 1)
n.Write(0x4016, 0)
}
func readBits(n *nes.Console, addr uint16, count int) []uint8 {
bits := make([]uint8, count)
for i := range bits {
bits[i] = n.Read(addr) & 1
}
return bits
}
func equalBits(a, b []uint8) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
func TestControllerReadsButtonsInOrder(t *testing.T) {
n := newTestConsole(t)
n.SetButtons(0, nes.ButtonA|nes.ButtonStart|nes.ButtonRight)
strobe(n)
// +---------------------- A
// | +------------------- B
// | | +---------------- Select
// | | | +------------- Start
// | | | | +---------- Up
// | | | | | +------- Down
// | | | | | | +---- Left
// | | | | | | | +- Right
// | | | | | | | |
want := []uint8{1, 0, 0, 1, 0, 0, 0, 1}
if got := readBits(n, 0x4016, 8); !equalBits(got, want) {
t.Errorf("bits = %v, want %v", got, want)
}
}
func TestControllerReturnsOneAfterEightReads(t *testing.T) {
n := newTestConsole(t)
strobe(n)
readBits(n, 0x4016, 8)
if got := readBits(n, 0x4016, 3); !equalBits(got, []uint8{1, 1, 1}) {
t.Errorf("bits after 8 reads = %v, want [1 1 1]", got)
}
}
func TestControllerStrobeHighKeepsReturningA(t *testing.T) {
n := newTestConsole(t)
n.SetButtons(0, nes.ButtonA)
n.Write(0x4016, 1)
if got := readBits(n, 0x4016, 3); !equalBits(got, []uint8{1, 1, 1}) {
t.Errorf("bits = %v, want [1 1 1]", got)
}
n.SetButtons(0, nes.ButtonB)
if got := readBits(n, 0x4016, 2); !equalBits(got, []uint8{0, 0}) {
t.Errorf("bits after releasing A = %v, want [0 0]", got)
}
}
func TestControllerLatchesOnStrobe(t *testing.T) {
n := newTestConsole(t)
n.SetButtons(0, nes.ButtonA)
strobe(n)
n.SetButtons(0, 0) // released after the latch, the readout should not change
want := []uint8{1, 0, 0, 0, 0, 0, 0, 0}
if got := readBits(n, 0x4016, 8); !equalBits(got, want) {
t.Errorf("bits = %v, want %v", got, want)
}
}
func TestControllerPortsAreIndependentWithSharedStrobe(t *testing.T) {
n := newTestConsole(t)
n.SetButtons(0, nes.ButtonA)
n.SetButtons(1, nes.ButtonSelect)
strobe(n)
if got := readBits(n, 0x4016, 3); !equalBits(got, []uint8{1, 0, 0}) {
t.Errorf("port 1 bits = %v, want [1 0 0]", got)
}
if got := readBits(n, 0x4017, 3); !equalBits(got, []uint8{0, 0, 1}) {
t.Errorf("port 2 bits = %v, want [0 0 1]", got)
}
}
func TestControllerReadHasOpenBusBit6(t *testing.T) {
n := newTestConsole(t)
strobe(n)
if got := n.Read(0x4016); got != 0x40 {
t.Errorf("$4016 with nothing pressed = %#02x, want 0x40", got)
}
}
|