For an 8-bit machine, having sprites that need 9 bits for an X-coordinate can be a pain…
There are 8 hardware sprites, and each has the low 8 bits stored in alternate registers from $D000 -> $D00E. All the top bits are packed together and stored in $D010.
One way around this is to only use the top 8 bits of the X-coordinate and keep everything in 1 byte, shifting the byte up to get the top bit into the carry, and branch to either clear or set the relevant bit in $D010 as a result. Problem with this method is you lose bit 0, so sprites don’t move as smoothly across the screen.
For my sprite multiplexer system I store the X and Y coordinates as 2 bytes. Y is simple as the low byte is an 8-bit fraction (used for smooth movements and fractional work), while the high byte is the actual hardware sprite Y coordinate.
But X-coordinate is different. For starters, the high byte stores the top 8 bits of the coordinate, while the low byte has bit 0, plus 7 fractional bits. To aid the multiplexer, I build the low 8 bits and store that by first shifting the low byte left to get bit 0 into the carry flag, rotate that into a copy of the top byte, and store that in a separate table. This means the system has the low 8 bits ready to store to the hardware, plus the original high byte with the top bit. Since my multiplexer builds 8 sprites at a time, for building the byte holding all the MSBs it’s a simple case of first clearing the Accumulator register, then for each sprite, load the high byte into the Y register, branching past an ORA #? instruction if positive. Once all sprites are done, the Accumulator can then be stored, ready for the multiplexer to use.
What all this means is that now in my game-side code, I can just grab the top byte of the X-coordinate and use that for performing 8-bit compares, as I don’t really need bit 0 for things like coordinate checking and collision detection. But for output, I have all 9 bits available, so the sprites can move smoothly across the screen.