Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

H-blank IRQs appear to fire too early? #2310

Closed
fleroviux opened this issue Sep 16, 2021 · 3 comments
Closed

H-blank IRQs appear to fire too early? #2310

fleroviux opened this issue Sep 16, 2021 · 3 comments
Labels
platform:GBA Game Boy Advance-related issues
Milestone

Comments

@fleroviux
Copy link

I attempted to measure some PPU timings to make sense of the Metal Max 2 Kai (first revision) bug that mGBA used to have and NanoBoyAdvance still has. In particular I was interested in the H-blank IRQ timing due to the nature of the race condition.

I compared measurements between HW, mGBA and NBA and found what I believe means that mGBA could fire the H-blank IRQ ~48 cycles too early.

My test ROM synchronizes to the start of a scanline (when VCOUNT changes) and then triggers an immediate DMA to pull samples from REG_IF into a buffer. The lower 8-bits of the samples are then dumped into SRAM.

For mGBA the H-blank IRQ bit is asserted during sample 0x1D0
grafik

While on real hardware it is asserted during sample 0x1E8
grafik

Each sample should amount to 2 cycles (1 REG_IF read and 1 IWRAM write)

Here is the test ROM I've used. The source code also contains two additional tests which are commented out but there didn't appear to be any issues with them.
newhblankirq.zip

Of course raising the IRQ at a later time would most likely have influence on the Metal Max 2 Kai race condition, so this needs to be approached carefully. I don't yet know how to fire the H-blank IRQ at the right point in time and also have that game work...

@endrift
Copy link
Member

endrift commented Sep 18, 2021

Hmm, this is a weird one. You may have noticed that mGBA 0.9 introduced a "mid-hblank" phase that deasserts the HBlank field in dispstat at 46 cycles before the end of hblank. This was based in part due to some research I did on hardware and I think a weird reading I found of some really specific thing in GBATEK that I'd have to dig up again. Regardless, it seems I may have inverted the behavior? Do you have info about when HBlank IRQs stop being asserted? Also 46 is a weird number (not divisible by 4) so 48 is probably the accurate number here.

@endrift endrift added this to the mGBA 0.10.0 milestone Sep 18, 2021
@fleroviux
Copy link
Author

fleroviux commented Sep 18, 2021

Although the drawing time is only 960 cycles (240*4), the H-Blank flag is "0" for a total of 1006 cycles.

Are you referring to this bit in the DISPSTAT section of GBATEK? I also handle that in NanoBoyAdvance, but slightly differently.

Instead of adding a third "mid-hblank" phase I extended the length of the H-draw phase to 1006 cycles and the H-blank phase is only 226 cycles. I assert H-blank DMA and IRQ after 1006 cycles. VCOUNT is updated at the end of H-blank.

I've made two diagrams to compare mGBA's (to my best understanding) state machine with NBA's :

mGBA

XXXXXXXXXXXXXXXXXXXXXXYYYYYYYYYYZZZZ
                      ^             ^
                      |             |
                      |             |_ Update VCOUNT
                      |
                      |_ Request H-blank DMA and IRQ
Phases:
X = H-draw , H-blank bit = 0 (960 cycles)
Y = H-blank, H-blank bit = 1 (226 cycles)
Z = H-blank flip, H-blank bit = 0 (46 cycles)

NanoBoyAdvance

XXXXXXXXXXXXXXXXXXXXXXXXXXYYYYYYYYYY
                          ^         ^
                          |         |
                          |         |_ Update VCOUNT
                          | 
                          |_ Request H-blank DMA and IRQ

Phases:
X = H-draw , H-blank bit = 0 (1006 cycles)
Y = H-blank, H-blank bit = 1 (226 cycles)

In both cases the H-blank bit is unset for 1006 cycles and set for 226 cycles, just aligned differently to the system clock.
However the major difference is when the H-blank IRQ and DMA are triggered in relation to when VCOUNT is updated.

I have updated my test ROM and uploaded it with source code here:
https://github.com/fleroviux/nba-hw-tests/tree/master/ppu/basic-timing

This is the result mGBA currently gets:
grafik

And this is the result on hardware:
grafik

From that result it seems like mGBA:

  1. asserts H-blank DMA ~46 cycles too early relative to the VCOUNT update (HBL DMA test)
  2. as a direct consequence of 1. the V-count coincidence bit is measured to be set and unset ~46 cycles too late relative to the H-blank DMA (STAT VCNT SET and STAT VCNT UNSET)
  3. asserts H-blank IRQ ~54?? cycles too early relative to the VCOUNT update (HBL IRQ test)

NanoBoyAdvance "passes" this ROM with a minor few cycles difference in when the H-blank IRQ is asserted, so I'd hope that even though the timing in relation to the system clock might still be incorrect, the events should happen with correct timing in relation to each other.

I don't know what you mean by H-blank IRQs getting unasserted. I don't think it should get unasserted until it has been acknowledged by a write to IF. But I hope that this info and the test ROM are useful.

@endrift endrift added the platform:GBA Game Boy Advance-related issues label Sep 19, 2021
@endrift endrift closed this as completed Jan 27, 2022
@endrift
Copy link
Member

endrift commented Jan 27, 2022

Yes, I know the numbers are off by two, but for whatever reason your tests didn't pass with the right numbers. It needs closer investigation, but it's much closer now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platform:GBA Game Boy Advance-related issues
Projects
None yet
Development

No branches or pull requests

2 participants