Errors with INIDISP

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
User avatar
dougeff
Posts: 3078
Joined: Fri May 08, 2015 7:17 pm

Errors with INIDISP

Post by dougeff »

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.
nesdoug.com -- blog/tutorial on programming for the NES
creaothceann
Posts: 610
Joined: Mon Jan 23, 2006 7:47 am
Location: Germany
Contact:

Re: Errors with INIDISP

Post by creaothceann »

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
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: Errors with INIDISP

Post by lidnariq »

dougeff wrote: Sat Feb 13, 2021 8:20 am 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.
[...]
Maybe someone here can explain these things to me.
Near wrote:if the last HDMA channel ends with BBADx=$00 on S-CPU A, subsequent DMAs fail after
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.

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.
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
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.

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.
Near wrote:The same test ran on a 3CHIP. Magnificent.
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.

(edit: maybe? Maybe the critical time is while the sprite sliver is being drawn instead? The test shown doesn't disambiguate)
93143
Posts: 1715
Joined: Fri Jul 04, 2014 9:31 pm

Re: Errors with INIDISP

Post by 93143 »

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:
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.
Somehow, I find this hilarious...
Last edited by 93143 on Wed Feb 17, 2021 10:11 pm, edited 1 time in total.
creaothceann
Posts: 610
Joined: Mon Jan 23, 2006 7:47 am
Location: Germany
Contact:

Re: Errors with INIDISP

Post by creaothceann »

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.
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.

(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
User avatar
dougeff
Posts: 3078
Joined: Fri May 08, 2015 7:17 pm

Re: Errors with INIDISP

Post by dougeff »

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. (?)
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
Pokun
Posts: 2675
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Errors with INIDISP

Post by Pokun »

I have a Japanese 1CHIP-02 and SD2SNES if someone needs me to test anything on an NTSC 1CHIP.
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: Errors with INIDISP

Post by lidnariq »

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.
Screwtape
Posts: 8
Joined: Wed Jul 10, 2019 11:34 pm

Re: Errors with INIDISP

Post by Screwtape »

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.
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: Errors with INIDISP

Post by lidnariq »

I was more hoping to find out which timing was the problem, but they describe that:
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.
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...
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Errors with INIDISP

Post by tepples »

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)?
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: Errors with INIDISP

Post by lidnariq »

tepples wrote: Mon Feb 15, 2021 11:02 pm What does $20FF actually do? It's out of the B bus area.
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?
creaothceann
Posts: 610
Joined: Mon Jan 23, 2006 7:47 am
Location: Germany
Contact:

Re: Errors with INIDISP

Post by creaothceann »

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
lidnariq
Posts: 11429
Joined: Sun Apr 13, 2008 11:12 am

Re: Errors with INIDISP

Post by lidnariq »

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".
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Re: Errors with INIDISP

Post by Near »

Would you say it is safe to HDMA to INIDISP, as long as d7 is never set ?
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.

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.
Maybe Near will be kind enough to leave us a copy of his test ROM.
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.
I wonder if it's literally "the sliver that would have been fetched during the pixel that's disabled isn't"
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.
Maybe this also works with other registers (PPU or otherwise)?
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 someone can figure out how to deduce this from the SNES PPU 100x die scans John McMaster did for us.
Post Reply