Closed cogwheel closed 11 months ago
Looking broadly at this, I don't think it's a good idea to do any major surgery to nesdoug. These are dougeff's example libraries, ported to llvm-mos for the purpose of allowing the nesdoug tutorial series (in its entirety) to function on llvm-mos with a minimum of alterations. If we want to build out a really solid standard library for NES development on llvm-mos, that's cool, but it should probably be broken out separately as a new NES stdlib, rather than backwards incompatibly changing these pseudo-historical ones, particularly if they bear someone's name.
FWIW, the only potentially breaking change here is that multi_vram_buffer
takes an extra byte of storage. But in my experience, if you have enough operations to risk filling the buffer, then the NMI routine would take longer than VBLANK anyway. Also, in the original CC65 version, the VRAM_BUF shares space with the software stack. So as long as you're following CC65 "best practices" of using ZP globals for arguments/returns, the total VRAM buffer capacity is nearly a page, compared to the half-page in llvm-mos.
So I'm wondering how you'd feel about a change similar to the first commit on this branch, but without all the noise about supporting more operations. It would just be a straight performance improvement.
Performance work like that seems fine; I've already had to do a fair bit a lot of internal rearranging to make it work with llvm-mos's assembler.
This restructures the multivram* headers to use a byte for the opcode rather than overloading with the upper byte of the VRAM address. This makes it possible to add many more types of operations to the VRAM buffer.
This involved some high level restructuring of the APIs:
The range of operations now supported by the vram buffer include:
nametable_buffer_one
- Equivalent to the oldone_vram_buffer
nametable_buffer_copy
- Equivalent to the oldmulti_vram_buffer_horz/vert
nametable_buffer_fill
- Fill a span with a single characternametable_buffer_ref
- Put a pointer into the buffer and fill a span from the data it points toEach of these has helpers for the different directions and also some low level versions to aid composability. For example:
nametable_buffer_copy_op
- Takes a nametable_opcode along with the other args to construct a header and copy data.nametable_buffer_copy
- C wrapper of the above, taking a nametable_dir and constructing the opcodenametable_buffer_copy_horz/vert
- Wrapper for the above with an implicit direction flag