-
Notifications
You must be signed in to change notification settings - Fork 0
/
ppi.go
114 lines (94 loc) · 2.1 KB
/
ppi.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
104
105
106
107
108
109
110
111
112
113
114
package msx
import (
"fmt"
"sync"
"github.com/laullon/b2t80s/emulator"
"github.com/laullon/b2t80s/emulator/storage/cassette"
)
type ppi struct {
mem *memory
cassette cassette.Cassette
click bool
soundOut []*emulator.SoundData
mux sync.Mutex
keyboardRows []byte
c byte
}
func newPPI(mem *memory, cassette cassette.Cassette) *ppi {
ppi := &ppi{
mem: mem,
cassette: cassette,
keyboardRows: make([]byte, 0x10),
}
for idx := 0; idx < len(ppi.keyboardRows); idx++ {
ppi.keyboardRows[idx] = 0xff
}
return ppi
}
func (ppi *ppi) ReadPort(port uint16) (byte, bool) {
switch port & 0xff {
case 0xa8:
res := byte(0)
for slot := 0; slot < 4; slot++ {
res |= ppi.mem.cfg[slot] << (slot * 2)
}
// fmt.Printf("[ppi.ReadPort] mem.cfg: %v (0b%08b)\n", ppi.mem.cfg, res)
return res, false
case 0xa9:
res := ppi.keyboardRows[ppi.c&0x0f]
return res, false
case 0xaa:
return ppi.c, false
}
panic(fmt.Sprintf("[ReadPort] Unsopported port: 0x%02X", port))
}
func (ppi *ppi) WritePort(port uint16, data byte) {
switch port & 0xff {
case 0xa8:
for slot := 0; slot < 4; slot++ {
ppi.mem.cfg[slot] = (data >> (slot * 2)) & 3
}
// fmt.Printf("mem.cfg: %v (0b%08b)\n", ppi.mem.cfg, data)
case 0xa9:
panic(fmt.Sprintf("unsopported port: 0x%02X", port))
case 0xaa:
ppi.c = data
case 0xab:
if (data & 0x80) == 0 {
bit := (data >> 1) & 7
if (data & 1) == 1 {
ppi.c |= 1 << bit
} else {
ppi.c &= ^(1 << bit)
}
} else {
print(fmt.Sprintf("invalid c (%d) value\n", data))
}
}
}
func (ppi *ppi) SoundTick() {
ppi.mux.Lock()
defer ppi.mux.Unlock()
v := 0.0
if ppi.click {
v = 1
}
ppi.soundOut = append(ppi.soundOut, &emulator.SoundData{L: v, R: v})
}
func (ppi *ppi) GetBuffer(max int) (res []*emulator.SoundData, l int) {
ppi.mux.Lock()
defer ppi.mux.Unlock()
if len(ppi.soundOut) > max {
res = ppi.soundOut[:max]
ppi.soundOut = ppi.soundOut[max:]
l = max
} else {
res = ppi.soundOut
ppi.soundOut = nil
l = len(res)
}
return
}
func (ppi *ppi) GetChannels() []emulator.SoundChannel {
return []emulator.SoundChannel{ppi}
}