Errors with INIDISP
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
Errors with INIDISP
Someone working on a game translation says they found some hardware glitches. I don't really understand the HDMA thing, but apparently writes to INIDISP during rendering can cause visible errors.
Thread here.
https://twitter.com/near_koukai/status/ ... 50177?s=19
I don't seem to be able to reply, for some reason.
Maybe someone here can explain these things to me.
Thread here.
https://twitter.com/near_koukai/status/ ... 50177?s=19
I don't seem to be able to reply, for some reason.
Maybe someone here can explain these things to me.
nesdoug.com -- blog/tutorial on programming for the NES
-
- Posts: 610
- Joined: Mon Jan 23, 2006 7:47 am
- Location: Germany
- Contact:
Re: Errors with INIDISP
https://twitter.com/near_koukai/status/ ... 3581258753
Who can reply?
People @near_koukai mentioned can reply.
My current setup:
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10
Re: Errors with INIDISP
I assume Near means "the last active HDMA channel" and not "channel #7" and that they would have written "channel #7" if they had meant that. With that in mind, BBADx=$00=INIDISP.Near wrote:if the last HDMA channel ends with BBADx=$00 on S-CPU A, subsequent DMAs fail after
That said, I've written programs that use a single HDMA channel writing to INIDISP to make a vertical wipe ... and I thought I used plain DMA again afterwards ... but I'm not certain I remember correctly.
This is basically the same glitch that I saw on the NES on writing to the monochrome bit: the data bus apparently isn't driven for the full time that the chip selects are selected, and the wrong value will get latched for one pixel. Since the open bus value ("MDR") on CPU-initiated writes to those registers will hold the MSbyte of the address, so writes to INIDISP should end up accidentally working fine as long as you don't use (edit) absolute long addressing to its mirrors in banks $80-$BF and you want to keep rendering enabled.Near wrote:*at least* for INIDISP.d7, the previous MDR.d7 bit leaks though and latches for part of a CPU cycle on 3CHIP consoles
HDMA, on the other hand, seems to do weird things with the upper address lines in my 1-1-1 SNES during the clock resynchronization, so I don't know if any options exist for INIDISP HDMA.
Apparently, disabling rendering for even just one pixel during hblanking of active display will trash OAM evaluation on a 3chip SNES, while a 1chip SNES appears to survive that.Near wrote:The same test ran on a 3CHIP. Magnificent.
(edit: maybe? Maybe the critical time is while the sprite sliver is being drawn instead? The test shown doesn't disambiguate)
Re: Errors with INIDISP
Apparently there are two glitches. First, on S-CPU A, if the last HDMA channel ends with its destination address set to $00 (meaning INIDISP), it disables the DMA unit (or at least borks regular DMA).
(This is good to know for me, as it means (if I understand correctly) that you can't turn the screen on with the very last HDMA channel. This restricts VRAM HDMA to 20 bytes per line rather than 24, although there may be a workaround depending on what precisely the phrase "last HDMA channel" means. This talk of 1CHIP reacting badly to INIDISP writes might mean more than that, though - I really should get my scheme tested on a known 1CHIP and/or Junior.)
The second glitch is that if you write to INIDISP, either open bus or your previous write (I don't know what MDR is) will get noticed for a moment. His experiment of writing #$0F8F to $20FF essentially means he's writing "screen off, full brightness" to an unused location right below INIDISP, and then immediately, one cycle later, writing "screen on, full brightness" to INIDISP itself. And apparently there's one pixel during which the S-PPU obeys the first command and not the second, even though it shouldn't have gone to INIDISP at all.
EDIT:
(This is good to know for me, as it means (if I understand correctly) that you can't turn the screen on with the very last HDMA channel. This restricts VRAM HDMA to 20 bytes per line rather than 24, although there may be a workaround depending on what precisely the phrase "last HDMA channel" means. This talk of 1CHIP reacting badly to INIDISP writes might mean more than that, though - I really should get my scheme tested on a known 1CHIP and/or Junior.)
The second glitch is that if you write to INIDISP, either open bus or your previous write (I don't know what MDR is) will get noticed for a moment. His experiment of writing #$0F8F to $20FF essentially means he's writing "screen off, full brightness" to an unused location right below INIDISP, and then immediately, one cycle later, writing "screen on, full brightness" to INIDISP itself. And apparently there's one pixel during which the S-PPU obeys the first command and not the second, even though it shouldn't have gone to INIDISP at all.
EDIT:
Somehow, I find this hilarious...lidnariq wrote: ↑Sat Feb 13, 2021 12:09 pmSince the open bus value ("MDR") on CPU-initiated writes to those registers will hold the MSbyte of the address, so writes to INIDISP should end up accidentally working fine as long as you don't use its mirrors in banks $80-$BF and you want to keep rendering enabled.
Last edited by 93143 on Wed Feb 17, 2021 10:11 pm, edited 1 time in total.
-
- Posts: 610
- Joined: Mon Jan 23, 2006 7:47 am
- Location: Germany
- Contact:
Re: Errors with INIDISP
MDR is the register that drives/receives the value on the data bus during the first/second half of a clock cycle (Φ1/Φ2) respectively.93143 wrote: ↑Sat Feb 13, 2021 1:46 pm The second glitch is that if you write to INIDISP, either open bus or your previous write (I don't know what MDR is) will get noticed for a moment. His experiment of writing #$0F8F to $20FF essentially means he's writing "screen off, full brightness" to an unused location right below INIDISP, and then immediately, one cycle later, writing "screen on, full brightness" to INIDISP itself. And apparently there's one pixel during which the S-PPU obeys the first command and not the second, even though it shouldn't have gone to INIDISP at all.
(Note that if nothing drives the bus the copper lines on a PCB can also act as a capacitor, holding the electrical charge for a moment before it dissipates. I'm fairly sure the MDR is a register though since it's in the 6502, called Data Output Register.)
EDIT: On the 6502 it's actually two registers, one for the data input (Input Data Latch) and one for the output (Data Output Register). The input/output registers are always receiving during Φ2/Φ1 respectively, but the output register's output is only forwarded in Φ2 when the CPU is writing.
Last edited by creaothceann on Wed Feb 17, 2021 10:29 am, edited 1 time in total.
My current setup:
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10
Re: Errors with INIDISP
Would you say it is safe to HDMA to INIDISP, as long as d7 is never set ? And as long as another HDMA channel is doing... something, so BBAD isn't left at $00. (?)
Hold on, maybe it is the previous value on the bus, BEFORE the INIDISP write is what is incorrectly going to INIDISP for 1 pixel. (?)
Hold on, maybe it is the previous value on the bus, BEFORE the INIDISP write is what is incorrectly going to INIDISP for 1 pixel. (?)
Last edited by dougeff on Sun Feb 14, 2021 12:34 pm, edited 1 time in total.
nesdoug.com -- blog/tutorial on programming for the NES
Re: Errors with INIDISP
I have a Japanese 1CHIP-02 and SD2SNES if someone needs me to test anything on an NTSC 1CHIP.
Re: Errors with INIDISP
Maybe Near will be kind enough to leave us a copy of his test ROM. The most obvious change to me is make it so that the writes to $20FF only happen once per scanline, instead of as fast as possible.
Re: Errors with INIDISP
The test ROMs were actually written by Undisbeliever.
The glitch was discovered when somebody reported sprite corruption in Bahamut Lagoon and it turned out to be caused by a once-per-scanline write to $20FF. The test ROM writes as fast as possible just to make the glitch visually obvious, but it's not required for the glitch to manifest.
The glitch was discovered when somebody reported sprite corruption in Bahamut Lagoon and it turned out to be caused by a once-per-scanline write to $20FF. The test ROM writes as fast as possible just to make the glitch visually obvious, but it's not required for the glitch to manifest.
Re: Errors with INIDISP
I was more hoping to find out which timing was the problem, but they describe that:
I wonder if it's literally "the sliver that would have been fetched during the pixel that's disabled isn't" ... can't be just that simple because of the bonus glitchy yellow sliver below the "B" in "OBJ" but...Undisbeliever wrote:On 3-chip consoles, if the INIDISP write occurs in h-blank and the previous value on the data-bus has bit 7 set then you sometimes see glitched sprites on the next scanline.
Re: Errors with INIDISP
What does $20FF actually do? It's out of the B bus area.
Would it help to enable rendering at minimum brightness ($80 to $00) on one scanline and then crank up the brightness ($00 to $0F) on the next line?
Would it help to write to INIDISP using a double-write (HDMA mode 2) instead of a single write (HDMA mode 0)?
Would it help to enable rendering at minimum brightness ($80 to $00) on one scanline and then crank up the brightness ($00 to $0F) on the next line?
Would it help to write to INIDISP using a double-write (HDMA mode 2) instead of a single write (HDMA mode 0)?
Re: Errors with INIDISP
Nothing. The only purpose here is to preload the data bus (or DOR, if relevant) with a clearly wrong value.
The translation (I assume) was getting random values instead, depending on what HDMA interrupted. The problem is if the open bus value will cause rendering to be temporarily disabled, that will cause glitches in a 3-chip SNES. Maybe one could use the 0,1 style of HDMA to write to $21FF (to seed open bus) then $2100?
-
- Posts: 610
- Joined: Mon Jan 23, 2006 7:47 am
- Location: Germany
- Contact:
Re: Errors with INIDISP
Maybe this also works with other registers (PPU or otherwise)?
My current setup:
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10
Super Famicom ("2/1/3" SNS-CPU-GPM-02) → SCART → OSSC → StarTech USB3HDCAP → AmaRecTV 3.10
Re: Errors with INIDISP
Probably, if it's anything like the NES. In the NES PPU, the registers are a random mixture of "entirely asynchronous", "latched on pixel edges", and "latched on end of write".
Re: Errors with INIDISP
There's a bug in the latest (1.10.3) fxpak firmware that makes even this unsafe. Its MCU performs background fetches between CPU cycles, and will update the MDR to hold a value where d7 can be set.Would you say it is safe to HDMA to INIDISP, as long as d7 is never set ?
Once that bug is fixed in a future firmware revision, the easy fix for this will be to HDMA to $21ff+$2100, and make sure both write the exact same value. That is how I intend to fix Bahamut Lagoon in revision 1.2.
Note that this bug works both ways. It can both erroneously turn the screen on *and* off on you, when you don't want that. It usually doesn't matter, but if the screen turns off during Hblank with active display, it disrupts OAM tiledata fetches. bsnes is accurate enough to reflect this in fact if I emulate this behavior.
This also means that the 1CHIP evidently *ignores* INIDISP.d7 and keeps fetching OAM tiledata inside Hblank which is ... remarkable in and of itself.
Not my test ROM. I don't own an S-CPU A sadly. I had to downsize my collection of 10 SNESes to just two to move out to Japan. The one skeud gave me was also not an S-CPU A.Maybe Near will be kind enough to leave us a copy of his test ROM.
It appears to offset the fetched data, so the sprite line gets pushed X pixels to the left or right (forget which offhand.) But don't quote me on this.I wonder if it's literally "the sliver that would have been fetched during the pixel that's disabled isn't"
I strongly suspect that to be the case at least for some registers, but it's very hard to tell with the other registers.Maybe this also works with other registers (PPU or otherwise)?
Maybe someone can figure out how to deduce this from the SNES PPU 100x die scans John McMaster did for us.