Oh, the NES controller bit order is 100% arbitrary. There's no standard - it all depends on if the programmer decided to write a ROL or ROR instruction that day.
But I agree with your point.
You meant:
while (n--)
Re:Type-safe Bitmasks in C++
by theincredulousk on Wednesday June 13, 2018 @04:26PM
(#17306631)
Defining bit values (and other externally defined magic numbers) explicitly in e.g. a defined-to-be-canonical header file (which might be just those 8 #defines) is much safer and easier to debug/maintain
I'm all for modern C++, but this is correct, at least IME with embedded systems. You're overall better off sticking with C-style if working at an abstraction level where the interface itself uses bitmasks. At this point you're manipulating memory manually which is (a) C's wheelhouse and (b) where type safety becomes largely irrelevant.
There is a lot to be said for using custom enum class implementations (e.g. http://www.drdobbs.com/when-enum-just-isnt-enough-enumeratio...) but it isn't clear to me how this kind of thing benefits bitmasks when the goal is presumably absolute maximum efficiency.
> return 1 << static_cast<underlying_type>(o);
Relying on default enum values to and automagically converting these into power of two bit masks is very brittle, and can create unexpected bugs and interoperability problems. The mask values change if the enum changes, unused bits in the middle of the bitmask are hard to handle, and the bit order is assumed with the first item being the LSB. The last point is particularly relevant given the NES buttons example, because it uses a bit order opposite to how the controller data is usually read[1]. This article defines
The standard controller[2] state is sent from a shift register in the controller one bit at a time. This is usually read by the program as 8 reads from the I/O port, and shifted into a button state bitmask. E.g. something like: With the buttons being read in the order [A, B, ..., RIGHT], the recommended bitmask is: Obviously this is a minor mistake in a (probably untested) example. I just want to highlight how easily this type of "clever" - but brittle - coding style can introduce errors. Defining bit values (and other externally defined magic numbers) explicitly in e.g. a defined-to-be-canonical header file (which might be just those 8 #defines) is much safer and easier to debug/maintain. Then wrap those explicitly defined values into the C++ template for type safety or other fancy features.[1] https://wiki.nesdev.com/w/index.php/Controller_Reading
[2] https://wiki.nesdev.com/w/index.php/Standard_controller