Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

View topic - Accessing the VDP too fast during VBlank

Reply to topic
Author Message
  • Joined: 17 Jun 2017
  • Posts: 19
Reply with quote
Accessing the VDP too fast during VBlank
Post Posted: Tue May 05, 2020 7:43 pm
Hi there,

I'm getting 'Accessing the VDP too fast' errors in Emulicious when calling an OUTI block during VBlank. I've read through a number of good VDP limit threads on the forum but can't work it out, so there must be something I still don't understand.

My VBlank handler at $0038 just satisfies the interrupt and jumps to the VBlank routine. This routine currently just blasts a SAT buffer to RAM by calling an OUTI block and it's one of these OUTI instructions that fails with the error. Interrupts are shown as disabled ('DI') in the side bar of the debugger. I've also tried switching the display off at the start of the routine before calling the OUTI block but this doesn't seem to work.

Is the OUTI block method still valid or does it violate VDP constraints even during VBlank? I was under the impression that writes during active display were the only ones I had to be worried about.

Thanks!
eljay
  View user's profile Send private message
  • Joined: 14 Apr 2013
  • Posts: 623
Reply with quote
Post Posted: Tue May 05, 2020 8:12 pm
eljay wrote
Hi there,

I'm getting 'Accessing the VDP too fast' errors in Emulicious when calling an OUTI block during VBlank. I've read through a number of good VDP limit threads on the forum but can't work it out, so there must be something I still don't understand.

My VBlank handler at $0038 just satisfies the interrupt and jumps to the VBlank routine. This routine currently just blasts a SAT buffer to RAM by calling an OUTI block and it's one of these OUTI instructions that fails with the error. Interrupts are shown as disabled ('DI') in the side bar of the debugger. I've also tried switching the display off at the start of the routine before calling the OUTI block but this doesn't seem to work.

Is the OUTI block method still valid or does it violate VDP constraints even during VBlank? I was under the impression that writes during active display were the only ones I had to be worried about.

Thanks!
eljay

Hi eljay,

the OUTI block in the VBlank handler is fine as long as it doesn't take longer than VBlank. If you only write your SAT, it's not longer than VBlank.
Is it possible that you have line interrupts enabled and that you acknowledge a line interrupt instead of a frame (vblank) interrupt?
  View user's profile Send private message Visit poster's website
  • Joined: 17 Jun 2017
  • Posts: 19
Reply with quote
Post Posted: Tue May 05, 2020 10:02 pm
No, line interrupts are showing as disabled in the VDP tab of the memory editor.

I was wrong before about disabling the display not fixing it. It seems to start working if I disable display at the start of VBlank and re-enable at the end. Is this necessary to do? I didn't think it was, so I wonder whether this is just masking the problem.

It also seems the OUTIs only error the first time around, every 4th OUTI or so, but if I skip the errors and continue past that initial frame it will then continue without errors for frames going forward. It suggests the first, and only the first, interrupt is happening while in active display but I can't see why. The display is off and interrupts disabled until just before starting the game loop, and the game loop then halts before doing anything. The VDP status flags returned on this problem interrupt are %1101 1111. After that they are %1001 1111.

My pseudo-code is:


.orga $38
    push af
    in a, ($bf)    ; satisfy interrupt
    jp vBlank

loop:
  ei
  halt
  ... small amount of logic
  jp loop

vBlank:
    ... transfer sprites

    ; Return from interrupt
    pop af
    ret

  View user's profile Send private message
  • Joined: 14 Apr 2013
  • Posts: 623
Reply with quote
Post Posted: Tue May 05, 2020 10:25 pm
eljay wrote
No, line interrupts are showing as disabled in the VDP tab of the memory editor.

I was wrong before about disabling the display not fixing it. It seems to start working if I disable display at the start of VBlank and re-enable at the end. Is this necessary to do? I didn't think it was, so I wonder whether this is just masking the problem.

It also seems the OUTIs only error the first time around, every 4th OUTI or so, but if I skip the errors and continue past that initial frame it will then continue without errors for frames going forward. It suggests the first, and only the first, interrupt is happening while in active display but I can't see why. The display is off and interrupts disabled until just before starting the game loop, and the game loop then halts before doing anything. The VDP status flags returned on this problem interrupt are %1101 1111. After that they are %1001 1111.

My pseudo-code is:


.orga $38
    push af
    in a, ($bf)    ; satisfy interrupt
    jp vBlank

loop:
  ei
  halt
  ... small amount of logic
  jp loop

vBlank:
    ... transfer sprites

    ; Return from interrupt
    pop af
    ret


At the time the Vblank interrupt happens you still have your interrupts disabled. With interrupts disabled you won't execute the
in a,($bf)
at the beginning of your interrupt handler. So when the
ei
is executed the interrupt is still pending and taken. So at this point your interrupt handler isn't executed at the beginning of Vblank but later instead. And as it seems it is executed late enough to get your code to execute during active display.
You can fix this issue by inserting
in a,($bf)
before your loop.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3757
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Wed May 06, 2020 2:11 pm
I would simply do:

vBlank:
    ... transfer sprites

    ; Return from interrupt
    pop af
    ei                           ; re-enable interrupts!
    reti                         ; return from interrupt


so that next vblank interrupt will be triggered at the expected moment

also don't worry, interrupt can't be triggered on the instruction after EI so you'll get your reti executed *before* next IRQ
  View user's profile Send private message Visit poster's website
  • Joined: 17 Jun 2017
  • Posts: 19
Reply with quote
Post Posted: Wed May 06, 2020 8:02 pm
Calindro wrote

You can fix this issue by inserting
in a,($bf)
before your loop.


Ooh, yes that fixes it, thanks! Does this mean vBlank is always happening behind the scenes (and setting the status flag) even if the display and interrupts are disabled in the VDP? I suppose that makes sense.

sverx wrote

I would simply do:

vBlank:
    ... transfer sprites

    ; Return from interrupt
    pop af
    ei                           ; re-enable interrupts!
    reti                         ; return from interrupt



Thanks! Yes I'll do that as well.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3757
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Thu May 07, 2020 3:39 pm
The VDP causes the IRQ(s) to be triggered only if the corresponding flag(s) is/are on.
But if they're ON and they get triggered when interrupts are disabled on the CPU (DI) then the interrupt service routine will be called later, when they'll be enabled again (EI).

That's what was happening here, you got your transfer sprites routine triggered as soon as you EI again, but you were no longer in vblank.
  View user's profile Send private message Visit poster's website
  • Joined: 17 Jun 2017
  • Posts: 19
Reply with quote
Post Posted: Fri May 08, 2020 5:38 pm
sverx wrote
The VDP causes the IRQ(s) to be triggered only if the corresponding flag(s) is/are on.


So the behaviour I'm seeing in Emulicious is that the VDP Status vblank flag gets set even though vblank isn't enabled in the VDP registers. Looking into it in the debugger it seems that it might be because vblanks are enabled by default on boot and disabling them in the VDP registers doesn't take effect until after the next frame, so the flag gets set once but not thereafter. Is this correct?
  View user's profile Send private message
Reply to topic



Back to the top of this page

Back to SMS Power!