Closed mysterymath closed 11 months ago
@asiekierka , @jroweboy
This incorporates some of what we talked about; what's maybe new is explicitly divvying up bits as either PRG state or CHR state. CHR state gets the set/split/defer treatment we talked about, while PRG sets are always immediate, and NMI leaves them alone. I've also honed in on reliability guarantees. For the most part, all sets need to be atomic and reliable with respect to IRQs/NMIs, except splits. Splits should be fine to drop if interrupted by a NMI (they're too late in that case). The still mustn't misfire and overwrite something else. If atomicity is cheap, it may still make sense to do it there too, but it doesn't seem strictly required.
If this looks good, I intend to continue refactoring in this fashion with MMC3, then on to the other mappers (working from greatest to least familiarity). I plan to merge all these pull requests together; little point in doing it halfway.
I've spent a bit thinking about whether set
needs to be reliable in the case of NMI; I don't think it does. See the commit message for the details.
I think I agree. The only situation where unreliability could cause problem is if an NMI handler calls set
while the non-NMI code is in the middle of calling set
; but having both NMI and non-NMI code try to change the PPU state at the same time is bad programming practice.
I was gonna wait on this one, but I think this needs to go in sooner rather than later. MMC1 banking was a lot more subtly broken than I thought; this is as much a set of bug fixes as it is a naming change now.
This makes the interface for banking on MMC1 more consistent with the other mappers.
Removed direct access to shadow registers, replacing it with getter functions where required. These values may need to be computed on some mappers, so using functions allows the interfaces to look more similar across mappers. Inlining should completely fold this away.
Added accessors for the high part of the CHR bank. On some MMC1 boards, this controls PRG-RAM/ROM state, so it must be visibile to allow saving/restoring that state.
Replaced the retry versions of chr bank setters with ones that reliably control just the high bits. The retry versions were always intended just to control the high bits; this makes this explicit and separate from true CHR bank control.
The "set" functions that affect PPU/CHR state now take effect immediately, as well as being rewritten on NMI (previously they only did the latter). The "set" and "split" functions are left unreliable with respect to NMI (i.e., NMI may clobber their values), but now internally disable IRQs. New "defer" functions were added to set the NMI state (the previous "set" behavior); these are intrinsically reliable.
Remove weak from definitions; the library is fairly integrated, so it should be taken or left as a whole, pending a use for replacing specific functions.
Make mirroring an enum type.
Default NMI mirroring setting to vertical.
Add routines to directly control CHR banking mode.