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 - VBlank and HBlank Interrupt help

Reply to topic
Author Message
  • Joined: 15 Jul 2022
  • Posts: 29
Reply with quote
VBlank and HBlank Interrupt help
Post Posted: Fri Jul 15, 2022 7:33 pm
Hello everyone,

I'm trying to learn the Z80 assembler and I'm starting on the development for master system.

I have a problem that I have been struggling with for a while and I can't find any answers from topics on this forum.

I'm trying to understand how VBlank and HBlank works and I used a tiny program for this.

First, I would like to know if we can only get VBlank interrupt without HBlank interrupt by enabling only IE (R1 bit 5) and not IE1 (R0 bit 4) ?
Or I need enable IE and IE1 but set the VDP Register 10 to $FF (for disable HBlank) ?

Secondly, on my program, I disable IE and enable IE1, set VDP Register 10 to $5E (to get an HBlank at the 95th line) BUT I still get an VBlank interrupt (read $BF from VPD_STATUS's port) and HBlank interrupt (read $1F from VDP_STATUS's port) without knowing why ?

Normally I should only get HBlank interrupt from VDP.
I'm doing ASM code and compile with wla-z80.

Does anyone can help me to understand what I'm doing wrong ?

Thanks in advance.
code.zip (2.61 KB)
Code ASM + Rom

  View user's profile Send private message
  • Joined: 15 Jul 2022
  • Posts: 29
Reply with quote
Post Posted: Sun Jul 17, 2022 7:53 pm
Hello,

I kept looking at this problem from my side.
It would appear that a VBlank interrupt is mandatory when you set a value in R10, even if VBlank interrupt in disable in register (bit 5 in R1).

As soon as we put a value in R10 (between 0 and 95), we will first received a VBlank Interrupt (the 7th bit from VDP_STATUS $bf is set) and after that, we will received on or many HBlank interrupts according to our value from R10 (the 7th bit from VDP_STATUS $bf is not set).

Does this make sense to you? or did I misunderstand something?
  View user's profile Send private message
  • Joined: 08 Sep 2018
  • Posts: 270
Reply with quote
Post Posted: Sun Jul 17, 2022 8:03 pm
From your code, you never disable interrupts on the CPU when entering your interrupt routine. If youve set the VDP to line interrupt and your interrupt handler is too slow, IRQ will trigger and restart before its done.

You can either have VBLANK or HBLANK or BOTH interrupts active. Their respective switches in VDP registers $00 and $01 are only switches that allow the triggers to be passed onto the IRQ line.

VDP register $0a (10) will not write your value to the line counter until the VDP has entered VBLANK or the current value within the counter has rolled over.

As far as reading the VDP Control Port for the interrupt flag, It ONLY returns the VBLANK interrupt and not HBLANK. This is useful if you want to differentiate between what interrupt happened.

Finally you can read more about how line counting and other VDP functions in depth worth here.
I suggest checking out the interrupt section on Charles MacDonald's document.

SMS POWER line counter
https://www.smspower.org/Development/ScanlineCounter
CM's VDP Doc
www.techno-junk.org/txt/msvdp.txt
  View user's profile Send private message
  • Joined: 15 Jul 2022
  • Posts: 29
Reply with quote
Post Posted: Mon Jul 18, 2022 5:50 pm
Hello and thanks for your message.

Are you sure about the fact that I need to disable interrupts on the CPU when entering in the interrupt routine at $0038 ?

Because, from the Software Reference Manual, at page 6: "When an INT is accepted, the interrupt system is turned off, exactly as if a "DI" instruction had been executed."

So, for me, no need to set a "DI" at $0038.

As I understood, the VDP Control ($BF) Port return both VBlank Interrupt and HBlank interrupt.
At $0038, the first thing to do is to read the value at $BF and check if the 7th bit is set or no.
If yes, it's a VBlank Interrupt, else it's a HBlank Interrupt.

That why I don't understant why I still received VBlank Interrupt, even if I disable his switch at register 1.
  View user's profile Send private message
  • Joined: 08 Sep 2018
  • Posts: 270
Reply with quote
Post Posted: Mon Jul 18, 2022 6:41 pm
Im pretty sure no matter what, internally the VDP still produces a VBLANK interrupt. The only difference is when its switch is off on Register 1 its interrupt doesn't get transmitted externally to the CPU. So you'll still see it in the control port even if its not what triggered the CPU Interrupt.

Let me read up on the interrupt mechanism of the VDP again and see if this is different.
  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14728
  • Location: London
Reply with quote
Post Posted: Mon Jul 18, 2022 6:53 pm
That’s right, you can poll for VBlank statuses even if the interrupts are off.
  View user's profile Send private message Visit poster's website
  • Joined: 15 Jul 2022
  • Posts: 29
Reply with quote
Post Posted: Mon Jul 18, 2022 7:38 pm
So, if I sum up correctly

Reg0, bit 4: on/off HBlank Interrupt.
Reg1, bit 5: on/off VBlank Interrupt.

On each interruption, from the VDP, and received by the CPU, I jumped at the address $0038.

Here, I need to read VDP_STATUS ($BF) for:
- Clears the IRQ from the VDP chip.
- Determine if I have received an VBlank or HBlank interrupt, by checking the last bit.

If the last bit is 1: I received a VBlank Interrupt, else it was an HBlank interrupt.

(And of course, I need to enable again interrupt request with 'EI').

If what I have understood is correct, I don't understand why, with the parameters mentioned at the beginning, I still receive VBlanks and HBlank, with VBlank interrupt disabled (Debug with a break at $0038 on each frame).
  View user's profile Send private message
  • Joined: 06 Mar 2022
  • Posts: 665
  • Location: London, UK
Reply with quote
Post Posted: Mon Jul 18, 2022 8:00 pm
KingQuack wrote
If what I have understood is correct, I don't understand why, with the parameters mentioned at the beginning, I still receive VBlanks and HBlank, with VBlank interrupt disabled (Debug with a break at $0038 on each frame).


Given everything starts clear, you will get your first interrupt on line 95, and your status port will read bit 7 as 0.

Then you'll get your next interrupt on line 190 of frame 2, and your status port will also read bit 7 as 0.

The third interrupt you get will be on line 95 of the next frame, and at this point you will read bit 7 as 1 because line 193* always sets bit 7 to 1 regardless of the interrupt bits in r0 and r1.

Of course you'll read the status port and clear the bit, so the fourth interrupt you get will be on line 190 of frame 2 and bit 7 will be clear again because you cleared it earlier.

So I think you'll see bit 7 set on every other interrupt (line 95). Is that what you're seeing?

(* assuming 192 line display)
  View user's profile Send private message Visit poster's website
  • Joined: 08 Sep 2018
  • Posts: 270
Reply with quote
Post Posted: Tue Jul 19, 2022 1:32 am
I get these same results. There's no counter or user defined flag in z80 memory set up in their program so its not obvious at first when things are happening.
The status port also indicates that its definitely cycling through HBlank, as the rest of the status register always reads sprite collision and overflow occurring. Something that would have cleared after the first HBlank read if the program was actually stopping at the following VBlank.
Its stopping at every Hblank "frame" but it just happens to also be holding the last VBlank flag during even Hblank "frames" as well. Reading the V counter on port $7E should reveal enough info for the programmer to set up their IRQ routine.

TLDR: Your program is running fine, you just need a bit more to differentiate between Hblanks and when they occur.

willbritton wrote

Given everything starts clear, you will get your first interrupt on line 95, and your status port will read bit 7 as 0.

Then you'll get your next interrupt on line 190 of frame 2, and your status port will also read bit 7 as 0.

The third interrupt you get will be on line 95 of the next frame, and at this point you will read bit 7 as 1 because line 193* always sets bit 7 to 1 regardless of the interrupt bits in r0 and r1.

Of course you'll read the status port and clear the bit, so the fourth interrupt you get will be on line 190 of frame 2 and bit 7 will be clear again because you cleared it earlier.

So I think you'll see bit 7 set on every other interrupt (line 95). Is that what you're seeing?

(* assuming 192 line display)
  View user's profile Send private message
  • Joined: 15 Jul 2022
  • Posts: 29
Reply with quote
Post Posted: Wed Jul 20, 2022 7:00 pm
Hi everyone,

Thank you very much for the time spent on my problem !
On my program, with these parameters :
Reg0 Bit 4 at 1 (HBlank Interrupt on)
Reg1 Bit 5 at 0 (VBlank Interrupt off)
Reg10 with $5E (94 base10).

If I do a break at $0038, I oscillate between these value from VDP_Status ($BF) :
- $1F (7th bit at 0)
- $9F (7th bit at 1)
- $1F (7th bit at 0)
- $9F (7th bit at 1)
- and so on.

I naively thought that the reading of this 7th bit was enough to determine in my program what to do if it is a VBlank or an HBlank.

Indeed, reading the V counter from the $7E port will reveal enough to determine what interrupt just happened.

Again, thank you for your answers.
  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14728
  • Location: London
Reply with quote
Post Posted: Wed Jul 20, 2022 7:57 pm
The VBlank bit is set because vblank happened. You get two interrupts per frame (lines 95 and 189, I think) and the first has the vblank status bit set because it hasn’t been read yet. You are likely to need the vblank interrupt to allow you to manage state anyway, so you may as well enable it and handle it separately. Then you’ll get the expected two interrupts with the flag not set.
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 665
  • Location: London, UK
Reply with quote
Post Posted: Thu Jul 21, 2022 9:44 am
KingQuack wrote
I naively thought that the reading of this 7th bit was enough to determine in my program what to do if it is a VBlank or an HBlank.


Well I think it is enough to check bit 7, although perhaps it depends what your exact use-case is(??)

If you only have line interrupts enabled, then so long as you know when to expect your line interrupts (which you certainly do, because you set up r10), you can handle them and use bit 7 to determine which one is the first one of the frame.

If you have both frame and line interrupts enabled, then you can use the knowledge that the frame interrupt gets generated on line 193 and no line interrupt will be generated on the same line, so as @Maxim says you can simply handle the frame interrupt anyway, it will be the first interrupt where bit 7 is set, and then you know that everything else is a line interrupt.
  View user's profile Send private message Visit poster's website
  • Joined: 15 Jul 2022
  • Posts: 29
Reply with quote
Post Posted: Sat Jul 23, 2022 8:05 pm
I didn't really have any ideas in mind, I wanted to see how Vblank and HBlank works.
I am a beginner in programming on this type hardware and these were concepts that I didn't know.

I'm thinking of trying some effects now: changing the palette, delayed scrolling. So heavily based on the HBlank interrupt.

Thank you all, now I understand much better how to interpret what I was seeing.
  View user's profile Send private message
Reply to topic



Back to the top of this page

Back to SMS Power!