aboutsummaryrefslogtreecommitdiff
path: root/nes/controller.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 /nes/controller.go
parent96ff6d8eda2ba434682909f4ff4ce350d78b2273 (diff)
downloadgones-99cae5a5a37f41f878a84857361eda47910303ba.tar.gz
gones-99cae5a5a37f41f878a84857361eda47910303ba.zip
sprites!!!!!!
Diffstat (limited to 'nes/controller.go')
-rw-r--r--nes/controller.go53
1 files changed, 53 insertions, 0 deletions
diff --git a/nes/controller.go b/nes/controller.go
new file mode 100644
index 0000000..51afe20
--- /dev/null
+++ b/nes/controller.go
@@ -0,0 +1,53 @@
+package nes
+
+// bit order matches the order the console reads them out in
+const (
+ ButtonA uint8 = 1 << iota
+ ButtonB
+ ButtonSelect
+ ButtonStart
+ ButtonUp
+ ButtonDown
+ ButtonLeft
+ ButtonRight
+)
+
+// standard controller, it is just an 8 bit shift register
+// https://www.nesdev.org/wiki/Standard_controller
+type controller struct {
+ buttons uint8 // what is held right now
+ shift uint8 // what the cpu is reading out
+ strobe bool
+}
+
+// while strobe is high the shift register keeps copying the buttons
+func (c *controller) setStrobe(on bool) {
+ c.strobe = on
+ if on {
+ c.shift = c.buttons
+ }
+}
+
+func (c *controller) setButtons(b uint8) {
+ c.buttons = b
+ if c.strobe {
+ c.shift = b
+ }
+}
+
+// returns one button per read, A first. with strobe high it stays on A
+func (c *controller) read() uint8 {
+ bit := c.shift & 1
+ if !c.strobe {
+ // ones get shifted in, so reads after the 8th return 1
+ c.shift = c.shift>>1 | 0x80
+ }
+ // upper bits are open bus, which is $40 here since that is the high byte
+ // of the address that was read
+ return 0x40 | bit
+}
+
+// port is 0 for controller 1 and 1 for controller 2
+func (n *Console) SetButtons(port int, buttons uint8) {
+ n.controllers[port].setButtons(buttons)
+}