36

I'm taking a look at the chapter on sprites from a NES programming guide at famicom.party. There is a little table which describes what the different sprite attribute flags do:

Bit # Purpose
7 Flips sprite vertically (if "1")
6 Flips sprite horizontally (if "1")
5 Sprite priority (behind background if "1")
4–2 Not used
1–0 Palette for sprite

I'm generally amazed by how well the memory space is utilised in the console, so I was surprised to see that there are 3 bits per sprite which are not used. Two of these bits could specify a rotation orientation of the sprite. Why was this not implemented on the hardware?

Were these bits used by game programmers for their own sprite-specific information, potentially unrelated to graphics? Were they left unused intentionally for this reason?

15
  • 3
    Link works fine for me. But it’s something of an annoyance (and a bit spammy too) to link to the front page instead of the specific chapter in question, so I edited that. Commented Nov 9, 2021 at 12:22
  • 7
    Note that you'd only need one bit for rotation. If it's set, rotate 90° to the right after applying any flipping. Rotating 180° is already possible with two flips, and 270° would be possible with two flips and a 90° rotation.
    – rydwolf
    Commented Nov 9, 2021 at 18:34
  • 4
    Incidentally, if one looks at the die layout for the PPU, the memory array used for the OAM omits the storage transistors for the unused bits. From a software standpoint, giving functions to those bits would have been "free", but each extra bit would have expanded the size of the array by about 3%. That having been said, I think the functions I'd have liked to have seen given an extra OAM bit would have been per-sprite control of height, and per-sprite interrupt enable (versus having only sprite 0 support collision detection).
    – supercat
    Commented Nov 10, 2021 at 20:55
  • 1
    @supercat that's super interesting! So the answer to 'were these bits used by game developers for non- graphics purposes' is 'no, because the hardware didn't actually contain those bits'?
    – Jojo
    Commented Nov 10, 2021 at 23:09
  • 1
    Also, it's worth noting that the CPU is intended to be able to random-access individual OAM entries, but that feature is extremely buggy: due to an unintended interaction with the DRAM refresh circuitry, changing the CPU's OAM address pointer causes the in-progress DRAM refresh to write to the wrong location. So, the only reliable thing to do after writing OAMADDR is to immediately overwrite all 256 bytes of OAM using OAMDATA or OAMDMA (because you don't know what might have been corrupted).
    – NobodyNada
    Commented Nov 11, 2021 at 20:11

1 Answer 1

91

For each sprite displayed on a scanline, the hardware fetches two bytes from memory, and then clocks the pixels out one by one. The sprite is eight pixels wide, and each pixel is two bits, which is why it's two memory accesses per sprite per scanline. You can imagine that this arrangement just needs a couple of shift registers per sprite to clock the pixels out.

Now, flipping the sprite about its vertical axis is easy: you just clock the pixels out in reverse order! Similarly, flipping the sprite about its horizontal axis is also easy: You just fetch the bitmap from memory in reverse order. Rotating by 180° of course is the same as flipping both horizontally and vertically.

But if you wanted to rotate the sprite 90° or 270°, that's much harder. That's because the hardware would need to get one pixel from each pair of bytes, which means fetching 16 bytes from memory instead of just two. There is not enough time on this slow hardware to do that. Incidentally, this is also where the maximum number of sprites per scanline limitation comes from.

It's a similar story on the Commodore 64, the Atari 2600, and many others: These platforms can do some simple 2D manipulations on sprites like stretching and sometimes flipping like you've seen, but never rotations.

4
  • 20
    "I don't think there's enough time on this slow hardware to do that." There absolutely is not enough time. See the NESDev Wiki's frame timing description and diagram: each memory access takes 2 cycles, and there is only one idle cycle per scanline. So adding another 14 bytes * 2 bytes/cycle * 8 sprites per scanline = 224 cycles per scanline would certainly not be feasible.
    – NobodyNada
    Commented Nov 9, 2021 at 19:32
  • 5
    One can imagine a more complex PPU design that could access memory in one cycle, or gradually loads sprite tiles over a period of 8 lines before they're needed -- but any method to rotate sprites would have greatly increased the cost and complexity of the PPU for very little benefit, and keeping costs down was extremely high-priority during the NES's development.
    – NobodyNada
    Commented Nov 9, 2021 at 19:32
  • 15
    @NobodyNada: Exactly. If you need to rotate a sprite by 90°, the fast and easy solution is to make a set of pre-rotated bitmaps. Sure, it doubles the amount of ROM needed for the sprite, but that's the only cost, and I doubt that it would be breaking for most games that need it. And if you don't need it, you won't need to pay the cost. Commented Nov 9, 2021 at 22:36
  • 8
    Note that this is somewhat true today. Simple GPU settings can set tiling to x=-1 (horizontal flip) or y=-1 (vertical flip) or both (180 rotation). A 90 or 270 rotation requites playing with the matrixes. Commented Nov 10, 2021 at 0:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .