Re: Adding 4screen mirroring to UNROM-512 mapper definition
Posted: Thu Jan 10, 2019 6:05 pm
The reason I suggest that is that I think for the canonical 4-screen case it creates a redundant and error prone situation to try and include it as CHR-RAM.
For most mappers you should be able to substitute CHR-RAM for CHR-ROM and have exactly the same behaviour, and exactly the same size for the CHR-RAM version as CHR-ROM. Swapping ROM for RAM should not affect anything else, it should be unrelated to other factors as much as possible.
Similarly, canonical 4-screen should also be as orthogonal as it can be. 4-screen should just mean there is automatically 4k of dedicated RAM, and it shouldn't interfere with or interact with anything else. We shouldn't have think about whether the cart did it as 2k of RAM + CIRAM, or completely internal 4k, etc. any hiccups like that should only be non-canonical mapper-specific exceptions. It also shouldn't add on to other CHR-RAM that's only used for pattern tables. 8k + 2k? 8k + 4k? 16k? The standard 4-screen meaning should not require determining interactions like this. It should just be able to "drop in" on most mappers without having to parse the other fields to figure it out.
With mapper 77, you could call it 6k CHR-RAM + canonical 4-screen 1..0. You could also call it 8k CHR-RAM + 1..0, but I don't think that's canonical anymore (at least not by the way I suggest defining it); in this case it's a special variation of 4-screen where you're specifically including 2k it as part of the CHR-RAM. 0..0 "mapper defined" + 8k CHR-RAM also seems valid to me, which is just as much a special case. ...but there is only one possible thing to emulate here, all of the PPU-RAM is implied directly by the mapper, so arbitrarily even putting a 0 in the CHR-RAM field seems valid to me. (I don't really have a preference between these 3 possibilities, but I think it's an inherently ambiguous case that can't really be resolved by anything less than a special callout. Otherwise I think interpretations are going to differ here for any way we might attempt to define around making it a special case.)
In 356/512 it sounds like it's a completely separate and dedicated RAM just for nametables in the specific mode. That seems like a part of the mapper itself, not a "CHR-RAM" chip that needs to be specified as +4K on the CHR-RAM value. MMC5 ExRAM seems like the same situation to me, I wouldn't expect to put +1k into the CHR-RAM field for that. That's sort of what bugs me about trying to put it in the CHR-RAM field. It puts complicated interactions into the parsing of that field.
Though a way to demonstrate what I'm suggesting is that you should be able to take a UNROM with 8k CHR-RAM, and then set 1..0 for canonical 4-screen, and just get that without having to now specify 10k or 12k or 16k or 32k CHR-RAM. If you want to implement it any other way than some dedicated separate nametable RAM, it should be a new mapper or special case definition (like UNROM512).
Even though putting a flat 32k SRAM across the PPU address space would be the most straightforward way to build a simple CHR-RAM + 4-screen mapper, this should not be included in the canonical 4-screen case, it should be a special case. The canonical has to be more restricted than that, especially w.r.t. the $3000-3FFF mirrored area, because otherwise it's incompatible with the original 4-screen mappers that did it with half CIRAM. In the example I just gave, would 10k and 16k/32k have functionally different meanings (half CIRAM, mirrored twice, vs. no CIRAM and no mirror), and 12k would be functionally the same as 10k but somehow explicitly saying not to use CIRAM...? These possibilities feel really weird to me, and I think there's a lot of unpleasant room for interpretation if you go that route.
At least, that's what I would suggest as the standard/canonical definition of 1..0. The examples I'm giving about taking an existing mapper and changing ROM to RAM, or fixed mirroring to 4-screen, etc. obviously the games for this don't exist at this point, but the question that is in my mind is if I'm an emulator parsing a header, or a homebrew author trying to choose a mapper, can I deduce what's will/should happen if I take old mapper X and write "4-screen" in its header? Can I know what happens if I write 0 CHR-ROM and 256 CHR-RAM? The less interaction between fields, the less room for interpretation there is.
My approach may be unwarranted though. You could also decide that any mapper that has not already established a 4-screen variant is not allowed to use that bit... though in that case we should have to say that each of the ones that can use it is special. (Though, that's still a pretty small an practical list?) I had for a long time felt comfortable in thinking of the 4-screen bit as something that could at least in theory be easily applied to a great many mappers, but I'm not sure if others feel that is even a necessary goal. (In practice... support for it is very restricted in many emulators, I think.)
For most mappers you should be able to substitute CHR-RAM for CHR-ROM and have exactly the same behaviour, and exactly the same size for the CHR-RAM version as CHR-ROM. Swapping ROM for RAM should not affect anything else, it should be unrelated to other factors as much as possible.
Similarly, canonical 4-screen should also be as orthogonal as it can be. 4-screen should just mean there is automatically 4k of dedicated RAM, and it shouldn't interfere with or interact with anything else. We shouldn't have think about whether the cart did it as 2k of RAM + CIRAM, or completely internal 4k, etc. any hiccups like that should only be non-canonical mapper-specific exceptions. It also shouldn't add on to other CHR-RAM that's only used for pattern tables. 8k + 2k? 8k + 4k? 16k? The standard 4-screen meaning should not require determining interactions like this. It should just be able to "drop in" on most mappers without having to parse the other fields to figure it out.
With mapper 77, you could call it 6k CHR-RAM + canonical 4-screen 1..0. You could also call it 8k CHR-RAM + 1..0, but I don't think that's canonical anymore (at least not by the way I suggest defining it); in this case it's a special variation of 4-screen where you're specifically including 2k it as part of the CHR-RAM. 0..0 "mapper defined" + 8k CHR-RAM also seems valid to me, which is just as much a special case. ...but there is only one possible thing to emulate here, all of the PPU-RAM is implied directly by the mapper, so arbitrarily even putting a 0 in the CHR-RAM field seems valid to me. (I don't really have a preference between these 3 possibilities, but I think it's an inherently ambiguous case that can't really be resolved by anything less than a special callout. Otherwise I think interpretations are going to differ here for any way we might attempt to define around making it a special case.)
In 356/512 it sounds like it's a completely separate and dedicated RAM just for nametables in the specific mode. That seems like a part of the mapper itself, not a "CHR-RAM" chip that needs to be specified as +4K on the CHR-RAM value. MMC5 ExRAM seems like the same situation to me, I wouldn't expect to put +1k into the CHR-RAM field for that. That's sort of what bugs me about trying to put it in the CHR-RAM field. It puts complicated interactions into the parsing of that field.
Though a way to demonstrate what I'm suggesting is that you should be able to take a UNROM with 8k CHR-RAM, and then set 1..0 for canonical 4-screen, and just get that without having to now specify 10k or 12k or 16k or 32k CHR-RAM. If you want to implement it any other way than some dedicated separate nametable RAM, it should be a new mapper or special case definition (like UNROM512).
Even though putting a flat 32k SRAM across the PPU address space would be the most straightforward way to build a simple CHR-RAM + 4-screen mapper, this should not be included in the canonical 4-screen case, it should be a special case. The canonical has to be more restricted than that, especially w.r.t. the $3000-3FFF mirrored area, because otherwise it's incompatible with the original 4-screen mappers that did it with half CIRAM. In the example I just gave, would 10k and 16k/32k have functionally different meanings (half CIRAM, mirrored twice, vs. no CIRAM and no mirror), and 12k would be functionally the same as 10k but somehow explicitly saying not to use CIRAM...? These possibilities feel really weird to me, and I think there's a lot of unpleasant room for interpretation if you go that route.
At least, that's what I would suggest as the standard/canonical definition of 1..0. The examples I'm giving about taking an existing mapper and changing ROM to RAM, or fixed mirroring to 4-screen, etc. obviously the games for this don't exist at this point, but the question that is in my mind is if I'm an emulator parsing a header, or a homebrew author trying to choose a mapper, can I deduce what's will/should happen if I take old mapper X and write "4-screen" in its header? Can I know what happens if I write 0 CHR-ROM and 256 CHR-RAM? The less interaction between fields, the less room for interpretation there is.
My approach may be unwarranted though. You could also decide that any mapper that has not already established a 4-screen variant is not allowed to use that bit... though in that case we should have to say that each of the ones that can use it is special. (Though, that's still a pretty small an practical list?) I had for a long time felt comfortable in thinking of the 4-screen bit as something that could at least in theory be easily applied to a great many mappers, but I'm not sure if others feel that is even a necessary goal. (In practice... support for it is very restricted in many emulators, I think.)