VDP Status Register

For anything related to VDP (plane, color, sprite, tiles)

Moderators: BigEvilCorporation, Mask of Destiny

Nemesis
Very interested
Posts: 773
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

VDP Status Register

Post by Nemesis » Thu Jun 03, 2010 10:54 pm

While looking back over my own notes and my documentation archives, I've realised I don't seem to have any complete, accurate information on the status register for the VDP. There's stuff I'm just carrying around in my head, or have written as source comments in my emulator, that doesn't seem to be documented publically. There are also some things I don't know about the status register that I want to see if any of you guys know the answer to, so I'm going to write my own notes on the VDP status register here, and I'd like you guys to comment and correct/add to them if you know anything more.


Format of the status register:
The VDP status register is a 10-bit register. When you do a 16-bit read from the status register, the lower 10 bits correspond with the contents of the 10-bit status register. The upper 6 bits are undefined (See section below for how to define them). Here's the format of the 10-bit status register, according to my understanding:

Code: Select all

//-------------------------------------------------------------
//|  9  |  8  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
//|-----------------------------------------------------------|
//|EMPT |FULL |  F  |SOVR | COL | ODD | VB  | HB  | DMA | PAL |
//-------------------------------------------------------------
EMPT - FIFO Empty flag. When there are no pending writes held in the 4-word FIFO, this bit is set, otherwise it is clear.

FULL - FIFO full flag. When there are 4 pending writes held in the 4-word FIFO, this bit is set, otherwise it is clear.

F - Vint occurrance flag. This bit is set when a VINT is being asserted to the M68000. It represents the real-time state of VINT. When the status register is read, this bit is cleared immediately after, at which time, the VINT is no longer asserted. You need to do a status register read in a VINT handler in order to clear this bit to stop the VINT being asserted, otherwise the interrupt handler will
enter again as soon as it exits.

SOVR - Sprite overflow flag. This bit is set when a sprite overflow occurs. I don't have enough information on this flag, and I can't find any good notes right now. Does a dot overflow set this flag as well as too many sprites on a line? Exactly when is this flag set? Does it get set for too many sprites on a line before the line begins? Does a dot overflow get set during the line? What about a dot overflow off the edge of the screen? I do know this flag remains set until the status register is read, after which it is cleared.

COL - Sprite collision flag. This bit is set when two (non-transparent?) pixels in two sprites are found to overlap. Presumably this is set during active scan, at the time the pixel is being drawn, and is never set for any sprites, or any parts of sprites, which are off the edge of the screen, but I don't know this for certain. I do know this flag remains set until the status register is read, after which it is cleared.

ODD - Odd frame in interlace mode. This bit is set if interlacing is currently enabled, and the VDP is rendering the odd frame. I don't know exactly when this bit is set or cleared.

VB - Vertical blank flag. Set if the VDP is currently in vblank. IIRC, there's some good notes on this forum about the timing of when this is set and cleared.

HB - Horizontal blank flag. Set if the VDP is currently in hblank. IIRC, there's some good notes on this forum about the timing of when this is set and cleared.

DMA - Set if a DMA operation is currently in progress. Most likely is NOT set if a write which is supposed to start a DMA operation is currently held in the FIFO, and hasn't been processed yet, so code should look for this flag being clear, and the FIFO empty flag being set, in order to determine when a DMA operation is completed.

PAL - PAL/NTSC mode flag. Asserted if bit 3 of register 1 is set, to enable PAL mode. I assume this represents the real-time state of that bit, and this bit in the status register changes immediately after the register changes.


The upper 6 bits:
When you do a 16-bit read of the status register, the upper 6 bits are not set by the VDP. The value assigned to these bits will be whatever value these bits were set to from the last read the M68000 performed. Writes from the M68000 don't affect these bits, only reads.

Internally, the M68000 has a 16-bit data register it uses to read data from the bus (8-bit and 32-bit reads are both performed as 16-bit reads, see M68000 Users Manual). When performing a read, as the data lines are asserted by an external device, the M68000 latches the bits from the state the data lines are set to, and writes those bits into this internal register. The data is then moved from this internal register into the actual destination for the read.

When the M68000 is attempting to do a read from the bus, the input data lines are tri-state, meaning that the device which is being read must either pull the data lines high or low. If the device fails to pull a data line either high or low, but just leaves it floating, the M68000 never latches a value for the bit corresponding to that line, so the previously latched value is used.


Can anyone expand on this? I'm particularly interested in more information on the sprite overflow/collision flags, and in general, when and how sprite data is processed.

Eke
Very interested
Posts: 859
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Fri Jun 04, 2010 8:06 am

Hi Nemesis, welcome back (long time not seeing you here)
F - Vint occurrance flag. This bit is set when a VINT is being asserted to the M68000. It represents the real-time state of VINT. When the status register is read, this bit is cleared immediately after, at which time, the VINT is no longer asserted. You need to do a status register read in a VINT handler in order to clear this bit to stop the VINT being asserted, otherwise the interrupt handler will
enter again as soon as it exits.
This is the only thing I can think that was not properly documented, are you sure the bit is cleared and the IRQ lines are disabled ONLY once the status is read ? I know this was the behavior on SMS but thought this was different on Genesis VDP since the VDP had the INTACK signal ...

SOVR - Sprite overflow flag. This bit is set when a sprite overflow occurs. I don't have enough information on this flag, and I can't find any good notes right now. Does a dot overflow set this flag as well as too many sprites on a line? Exactly when is this flag set? Does it get set for too many sprites on a line before the line begins? Does a dot overflow get set during the line? What about a dot overflow off the edge of the screen? I do know this flag remains set until the status register is read, after which it is cleared.

COL - Sprite collision flag. This bit is set when two (non-transparent?) pixels in two sprites are found to overlap. Presumably this is set during active scan, at the time the pixel is being drawn, and is never set for any sprites, or any parts of sprites, which are off the edge of the screen, but I don't know this for certain. I do know this flag remains set until the status register is read, after which it is cleared.
I'm pretty sure all sprites are processed during blanking period, after Hint has been processed and parameters for next line being fetched from registers. There is also an internal sprite buffer that is filled during this period so it's very likely those flags are set during this blanking period. We also know that disabling display during HBLANK somehow limits sprites processing. According to Charles McDOnald, the sprite buffer is emptied during active display, when sprites pixels are mixed with plane ones so ...you could have various effect by disabling/enabling display mid line.
PAL - PAL/NTSC mode flag. Asserted if bit 3 of register 1 is set, to enable PAL mode. I assume this represents the real-time state of that bit, and this bit in the status register changes immediately after the register changes.
I don't think this is true, not all PAL games use the 240 line (PAL) mode set by this register bit, it's more likely related to the PAL input signal of the VDP which is forced according to the console region (!NTSC signal). It might be used by some games for region lockout.
Internally, the M68000 has a 16-bit data register it uses to read data from the bus (8-bit and 32-bit reads are both performed as 16-bit reads, see M68000 Users Manual). When performing a read, as the data lines are asserted by an external device, the M68000 latches the bits from the state the data lines are set to, and writes those bits into this internal register. The data is then moved from this internal register into the actual destination for the read.

When the M68000 is attempting to do a read from the bus, the input data lines are tri-state, meaning that the device which is being read must either pull the data lines high or low. If the device fails to pull a data line either high or low, but just leaves it floating, the M68000 never latches a value for the bit corresponding to that line, so the previously latched value is used.
I think it's related to how the 68k prefetch data
http://pasti.fxatari.com/68kdocs/68kPrefetch.html

Stef
Very interested
Posts: 3037
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Fri Jun 04, 2010 8:12 am

You mentionned something about F flag : Vint occurrance
You said that if the bit isn't cleared (by reading the status register) then the Vint stay asserted by the VDP and the 68000 will re-enter in V int routine infinitly. Are you sure of that behavior ? I never take care of that in MD dev as i'm not sure i've emulated it this way in Gens... anyway the VInt routine usually read the VDP SR at least once so that's not a big deal but that should impact in some few games i guess. It can also explain why i got so much troubles with the F flag and V int emulation ;)

About the sprite overflow flag :
From what i remember this flag is set if you have more than 20/16 sprites or 320/256 sprite pixels on a scanline depending the video mode (320 / 256), also i'm almost sure the offscreen sprites are taken in account, i remember a game which was using that feature to mask some sprites.
That make sense as the VDP has to parse the offscreen sprites anyway...


About the collision flag :
It's set when 2 non transparent sprite pixels overlap on a scanline, i guess it's set in realtime when the VDP is rendering sprites. I'm not sure if it actually take offscreen dot in account, i would say yes as it does it for sprite overflow flag.
Last edited by Stef on Fri Jun 04, 2010 2:06 pm, edited 1 time in total.

TmEE co.(TM)
Very interested
Posts: 2392
Joined: Tue Dec 05, 2006 1:37 pm
Location: Estonia, Rapla City
Contact:

Post by TmEE co.(TM) » Fri Jun 04, 2010 12:04 pm

About the F flag, I never read the VDP status reg in my Hint or Vint handler and I do not get infinite Vint happen... it would show as massive performance loss if it happened.....
Mida sa loed ? Nagunii aru ei saa ;)
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen

tomaitheous
Very interested
Posts: 256
Joined: Tue Sep 11, 2007 9:10 pm

Post by tomaitheous » Fri Jun 04, 2010 9:20 pm

Stef wrote:You mentionned something about F flag : Vint occurrance
You said that if the bit isn't cleared (by reading the status register) then the Vint stay asserted by the VDP and the 68000 will re-enter in V int routine infinitly. Are you sure of that behavior ?
Is it possible that the 68k requires a state change, rather than just the state position? I.e. like a lot of TTL latch systems. As in, you need to go from low to high in order to activate the corresponding IRQ # flag (or inverse but same logic)? The 68k would clear it's own internal flag or such when the corresponding vector is called. That would makes sense as to why you wouldn't get an infinite IRQ call loop in that situation. Unlike say, the 65x arch (I have no idea if this is the same behavior on the z80).

About the sprite overflow flag :
From what i remember this flag is set if you have more than 20/16 sprites or 320/256 sprite pixels on a scanline depending the video mode (320 / 256), also i'm almost sure the offscreen sprites are taken in account, i remember a game which was using that feature to mask some sprites.
That make sense as the VDP has to parse the offscreen sprites anyway...
Interesting. The PCE takes off screen sprites on the same line into account. I always thought the Genesis didn't.

Stef
Very interested
Posts: 3037
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Fri Jun 04, 2010 11:02 pm

tomaitheous wrote: Is it possible that the 68k requires a state change, rather than just the state position? I.e. like a lot of TTL latch systems. As in, you need to go from low to high in order to activate the corresponding IRQ # flag (or inverse but same logic)? The 68k would clear it's own internal flag or such when the corresponding vector is called. That would makes sense as to why you wouldn't get an infinite IRQ call loop in that situation. Unlike say, the 65x arch (I have no idea if this is the same behavior on the z80).
Actually the VDP is setting interrupt by asserting the 68000 IRQ lines (only IRL1 and IRL2 connected), when the 68000 jump to the interrupt routine, it's actually acknowleding it and assert a line for that which is connected to the VDP. Afaik the VDP doesn't know the level interrupt which the 68000 is actually acknowleding, it means that sometime because of weird timing it will mistake and re assert wrong IRQ (the 68000 will execute V Int 2 times instead of H Int and V Int). I'm not 100% sure of that, but that's why i "found" when i wrote Gens, i modified the interrupt implementation many times (using pending queue, simple clear...) and finally it was the method which gave the best results.
Interesting. The PCE takes off screen sprites on the same line into account. I always thought the Genesis didn't.
Just checked in Gens and i can confirm off screen sprites on same line are taken in account too. Gens isn't very accurate on some point but it is on sprite mask and overflow emulation.

Chilly Willy
Very interested
Posts: 2847
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Sat Jun 05, 2010 4:14 am

There's a technote on that from SEGA. The gist of it is that depending on what instruction the 68000 is doing right when the HINT for line 224 (NTSC) occurs, the 68000 might not generate the int ack until the VINT is also generated, so the VDP thinks the int ack is for the VINT, not the HINT, which is lost. SEGA's recommendation is to turn off the HINT at line 223, then in the VINT routine, call the HINT handler to simulate HINT 224. Or design your game to not use HINT 224.
:lol:

Nemesis
Very interested
Posts: 773
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Mon Jun 07, 2010 10:23 pm

Eke wrote:This is the only thing I can think that was not properly documented, are you sure the bit is cleared and the IRQ lines are disabled ONLY once the status is read ? I know this was the behavior on SMS but thought this was different on Genesis VDP since the VDP had the INTACK signal ...
No, I'm not sure. I have it written down in my notes, but I haven't cited any source for it, so I don't know if I confirmed that through testing, or just read it somewhere and took it as fact. I state it pretty definitively. These notes are quite old though, so I might not have tested it myself. That's one reason I'm going over the basics right now, I want to get an idea what I need to re-test to straighten out my notes. My current (old) VDP core does clear the interrupt on INTAK, but it's not very accurate either. I'm trying to complete my new VDP core, which is why I'm going over everything.

If the VDP interrupts are cleared by INTAK (which they easily could be), what about the Z80 INT line? All my notes say about Z80 INT is that it's "not asserted for very long". Does it get cleared on some kind of VDP access, or is it simply asserted for a fixed length of time and then cleared?
Eke wrote:I'm pretty sure all sprites are processed during blanking period, after Hint has been processed and parameters for next line being fetched from registers. There is also an internal sprite buffer that is filled during this period so it's very likely those flags are set during this blanking period. We also know that disabling display during HBLANK somehow limits sprites processing. According to Charles McDOnald, the sprite buffer is emptied during active display, when sprites pixels are mixed with plane ones so ...you could have various effect by disabling/enabling display mid line.
I'm really not clear on what is processed when for sprites at this point. There's essentially three questions:
1. When are the various peices of sprite data read from VRAM?
2. When is the data which has been read processed, and what form is it stored in?
3. When is the processed sprite data used?

I have a theory for example, that the sprite data for the upcoming line is actively read over the entire line proceeding it, including active scan and hblank. In the case of Mickey Mania, which reduces the number of sprites which can be displayed by disabling the display during hblank, a certain number of sprites have already been read during active scan, so it's only the sprites which haven't been buffered by that point which are affected.

I have another theory that the VDP processes the display in 2-cell blocks, and that every 2-cell block is drawn into a buffer, and that buffer is then read and output on the screen, and during the last 2-cell block and into the border/hblank, the sprite data is read and processed for the upcoming line, so by disabling the display during hblank, effectively, the second half of the sprite processing gets cut off.

I've read that the sprite collision flag is only set if non-transparent pixels of two sprites overlap. If it is, when does the pattern data for sprites actually get read? I would say only during the actual drawing of the line, which means the collision flag should get set mid-line. If that's the case though, why is there a maximum sprite dot count? Shouldn't there just be a maximum number of sprites, with no dot limitation? The sprite dot maximum suggests the dots get pre-processed and buffered. And the sprite overflow flag is also set on a dot overflow, right? Well, does this get evaluated before active scan, or during active scan? Maybe there's a buffer large enough to hold a full line of sprite data, and that buffer gets filled during hblank, and pixels just get moved out of that buffer during active scan?

There really are a lot of things here I'm not clear on. I think I need to do a lot of testing in this area. Since the sprite collision flag doesn't seem to be used mid-frame for any SMS games, and I don't think any mega drive games use it at all, I don't suppose it's been tested very thoroughly. Everything I read about it just leaves me with more questions.
Eke wrote:I don't think this is true, not all PAL games use the 240 line (PAL) mode set by this register bit, it's more likely related to the PAL input signal of the VDP which is forced according to the console region (!NTSC signal). It might be used by some games for region lockout.
Ok, I'll have to test that then.
About the F flag, I never read the VDP status reg in my Hint or Vint handler and I do not get infinite Vint happen... it would show as massive performance loss if it happened.....
Well that's a good indication this doesn't happen. Thanks. I think I'll have to do a test where VINT is generated, and the VDP isn't touched at all by the VINT handler, to be completely sure that no kind of VDP access is required in order to clear the interrupt. I still need to confirm what happens with the Z80 INT line though.


I want to get more information about when the VDP accesses its VRAM. I came across this post:
viewtopic.php?t=239&postdays=0&postorde ... p&start=28
by HardWareMan, where he links to a couple of videos which are supposed to show when VRAM access occurs, but the links are dead. Does anyone have copies of these files? I'd like to take a look at them. I also came across this thread:
viewtopic.php?t=666&postdays=0&postorde ... fo&start=0
from earlier this year, and it has some really good information from Charles MacDonald about what sprite data is buffered from the sprite table, which gives some good insights into the internal render process for sprites, but I think we really need to get more information about how and when sprites are processed over a single line. If we know more about what the VDP does to process sprites internally, the answers to a lot of these questions should become obvious.

Charles MacDonald
Very interested
Posts: 283
Joined: Sat Apr 21, 2007 1:14 am

Post by Charles MacDonald » Tue Jun 08, 2010 1:03 am

VDP core does clear the interrupt on INTAK, but it's not very accurate either. I'm trying to complete my new VDP core, which is why I'm going over everything.
In mode 5 the interrupt is cleared automatically when the 68000 issues an interrupt acknowledge cycle.

In mode 4 this does not happen and you must read the status register to clear the interrupt. Just like the SMS.

I'm sure there are all kinds of edge cases where you switch video modes before/during/after the interrupt acknowledge cycle that need to be tested. :)
what about the Z80 INT line? All my notes say about Z80 INT is that it's "not asserted for very long". Does it get cleared on some kind of VDP access, or is it simply asserted for a fixed length of time and then cleared?
The INT output is asserted every frame for exactly one scanline, and it can't be disabled. A very short Z80 interrupt routine would be triggered multiple times if it finishes within 228 Z80 clock cycles. I think (but cannot recall the specifics) that some games have delay loops in the interrupt handler for this very reason.

There are no VDP register settings that can change how this operates in mode 5, but I don't know if it operates any differently in mode 4.
Eke wrote:According to Charles MacDonald, the sprite buffer is emptied during active display, when sprites pixels are mixed with plane ones so ...you could have various effect by disabling/enabling display mid line.
Just to expand on this:

The VDP has two line buffers which are swapped per line, one for rendering and one for display. The buffer being displayed is erased simultaneously as it is read out.

If you blank the screen sprite rendering is disabled. If you turn it on a few scanlines later you see the old buffer contents for one line because it was never overwritten (old sprites still there) and never displayed (nothing erased).

The exact same thing happens with the left 8 pixels if you use the left column blanking. This would seem to mean it inhibits sprite rendering to the first eight pixels even though all remaining pixels on the line can be written with sprite data.

This is why games that do mid-frame screen blanking like Sonic 2 have that line of sprite garbage right after the screen is turned on again.

You can mix both blanking bits, for fun try this:
1. Turn the screen and left column off on one line. Wait a few lines.
2. Turn the screen on. Wait a few lines.
3. Turn the left column on.

The left column retains the old sprite data from #1 even though the buffer was partially scanned out at #2 and partially drawn into at #3. :)
I have another theory that the VDP processes the display in 2-cell blocks, and that every 2-cell block is drawn into a buffer, and that buffer is then read and output on the screen, and during the last 2-cell block and into the border/hblank, the sprite data is read and processed for the upcoming line, so by disabling the display during hblank, effectively, the second half of the sprite processing gets cut off.
This is a great idea but in tests where you select invalid sprite entries and they flicker, the flicker 'resolution' is as fine as 8 pixels, maybe finer.
I've read that the sprite collision flag is only set if non-transparent pixels of two sprites overlap. If it is, when does the pattern data for sprites actually get read? I would say only during the actual drawing of the line, which means the collision flag should get set mid-line.
I agree that it is during the actual render time.
If that's the case though, why is there a maximum sprite dot count? Shouldn't there just be a maximum number of sprites, with no dot limitation?
The VDP can only spend so much time writing to the line buffer. If you had 16 32x32 sprites fall on a line in 32-cell mode, that would be 512 pixels to draw. But as the fill rate is equal to the pixel clock you only get 342 cycles (pixels written) at most, and we know a chunk of that is used for other things, leaving even less.

This is why there are upper limits which are also resolution dependent. The SNES and the Neo Geo are also line-buffered and have similar pixel count limits, even though the Neo renders much faster than the display rate.
Maybe there's a buffer large enough to hold a full line of sprite data, and that buffer gets filled during hblank, and pixels just get moved out of that buffer during active scan?
Yes, that's it IMO. It's a familiar design in the arcade world as designs without line buffers have to have hugely parallel sprite circuits (one per sprite!) and that eats up PCB space.

Of course when you can move all that into an ASIC it is no big deal, and systems like the PCE have a traditional parallel structure for sprites. But I am sure their prototype sprite hardware was enormous. ;)

BTW I love the work you did on the YM2612 and it is great to see you working on the VDP!

Eke
Very interested
Posts: 859
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Wed Jun 09, 2010 10:11 am

Charles MacDonald wrote: A very short Z80 interrupt routine would be triggered multiple times if it finishes within 228 Z80 clock cycles. I think (but cannot recall the specifics) that some games have delay loops in the interrupt handler for this very reason.
This one I didn't know, i would have thought the VDP would be clearing the /INT line when detecting a Z80 Interrupt Ack cycle , thanks for clearing that up.
Nemesis wrote: VB - Vertical blank flag. Set if the VDP is currently in vblank. IIRC, there's some good notes on this forum about the timing of when this is set and cleared.
On that one, just to be clear: is the bit cleared at the start of the last line (when VCounter is incremented from 0xFE to 0xFF) or at the start of active display (when VCounter is incremented from 0xFF to 0x00, i.e when the first HINT could be triggered) ?

If it is confirmed to be the first case, does that mean that the last line of vertical blanking has the same restrictions as when we are in active range (limited CPU/DMA access to VDP) ?

For the record, I actually found one game (Bugs Bunny Double Trouble, 2nd level with the bull) that on some frames will change the display width (from H32 to H40) during vertical blanking to gain some extra DMA speed then wait for the VBLANK flag to be cleared before switching back to H32 mode. Doing that on line 0 causes some glitches to happen since the mode is changed mid-line.

Charles MacDonald
Very interested
Posts: 283
Joined: Sat Apr 21, 2007 1:14 am

Post by Charles MacDonald » Wed Jun 09, 2010 8:49 pm

This one I didn't know, i would have thought the VDP would be clearing the /INT line when detecting a Z80 Interrupt Ack cycle , thanks for clearing that up.
Going through my notes I noticed I measured that on a Sega C2 arcade board (they use INT for the 68000 V-Blank interrupt, weird). It should apply to the Genesis though -- if it breaks anything I'd like to know. As I recall the Sonic games (Part 3?) are quite sensitive to Z80 interrupt behavior.
For the record, I actually found one game (Bugs Bunny Double Trouble, 2nd level with the bull) that on some frames will change the display width (from H32 to H40) during vertical blanking to gain some extra DMA speed then wait for the VBLANK flag to be cleared before switching back to H32 mode. Doing that on line 0 causes some glitches to happen since the mode is changed mid-line.
Wow, this is really surprising. I have tried for a long time to do mid-frame resolution changing and it always throws the display timing off so that the screen is heavily distorted.

For example if you look above the player's head:

http://cgfm2.emuviews.com/img/cv-32-split.gif

The TV is synchronized to the horizontal sync using a PLL. Once the mode changes, the sync rate is different and the PLL tries to lock on, but it takes a few scanlines to do that. This is why the lines are curved less and less until a lock is made.

Maybe there aren't any screen issues if the duration of the mode switch is less than one scanline? I've always tried it in units of 1 or more scanlines. Does the game just change register $8C or are there other register changes associated with the mode switching?

I wonder why the do the mode change conditionally instead of just always doing it. Maybe it's to reduce screen glitches that would then show up intermittently instead of on every frame. This is fascinating!

TascoDLX
Very interested
Posts: 256
Joined: Tue Feb 06, 2007 8:18 pm

Post by TascoDLX » Thu Jun 10, 2010 5:27 am

Eke wrote:For the record, I actually found one game (Bugs Bunny Double Trouble, 2nd level with the bull) that on some frames will change the display width (from H32 to H40) during vertical blanking to gain some extra DMA speed then wait for the VBLANK flag to be cleared before switching back to H32 mode.
To clear that up:

It waits for HBLANK=1 before switching to H40. After it's done with the DMA, it waits for HBLANK=1 then NOPs past the HSYNC period before switching back.

Eke
Very interested
Posts: 859
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Thu Jun 10, 2010 6:17 am

Actually you are right, my mistake, I was confused by the fact that the DMA ended at the end of the frame.

tomaitheous
Very interested
Posts: 256
Joined: Tue Sep 11, 2007 9:10 pm

Post by tomaitheous » Thu Jun 10, 2010 6:42 pm

Wow, this is really surprising. I have tried for a long time to do mid-frame resolution changing and it always throws the display timing off so that the screen is heavily distorted.
Wait.. you can change the dot clock during active display, but not during vblank (to get faster DMA clock)? So, does that mean you just change from h32 to h40 on the last displayable scanline, in order to get the benefit of h40 dot clock for DMA purposes? And then change it back to h32 on the first displayable scanline?

Eke
Very interested
Posts: 859
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Wed Jun 23, 2010 2:15 pm

Just to expand on this:

The VDP has two line buffers which are swapped per line, one for rendering and one for display. The buffer being displayed is erased simultaneously as it is read out.

If you blank the screen sprite rendering is disabled. If you turn it on a few scanlines later you see the old buffer contents for one line because it was never overwritten (old sprites still there) and never displayed (nothing erased).

The exact same thing happens with the left 8 pixels if you use the left column blanking. This would seem to mean it inhibits sprite rendering to the first eight pixels even though all remaining pixels on the line can be written with sprite data.

This is why games that do mid-frame screen blanking like Sonic 2 have that line of sprite garbage right after the screen is turned on again.

You can mix both blanking bits, for fun try this:
1. Turn the screen and left column off on one line. Wait a few lines.
2. Turn the screen on. Wait a few lines.
3. Turn the left column on.

The left column retains the old sprite data from #1 even though the buffer was partially scanned out at #2 and partially drawn into at #3.
How did you get there was two line buffers ? Wouldn't it be possible to get same effects with only one buffer (the same buffer is filled during HBLANK and pixels cleared as they are being displayed) ?

Another game to try is Deadly Move (Power Instinct) which disable display before the end of active screen and re-enable it only at line 15. You can make your character (sprite) jump and see that the first line of sprite is not drawn, just like in Sonic 2 when you make your character jump in the bottom screen.

No emulator handle this accurately right now and I must say I have some trouble emulating this correctly (without breaking other sprites-sensitive games).

What we know :

(1) contrary to Master System VDP, sprite Ypos is directly related to the Vcounter value which seems to indicate that sprite pre-processing starts with Vcounter increment (unlike the SMS VDP where it is done on the previous line, as described in TMS9918 recent docs also)

(2) clearing the 'display enable' bit during a limited period within HBLANK somehow reduces the amount of sprites displayed on the upcoming line but does not stop sprites processing completely (cf. Mickey Mania 3D level)

(3) clearing the 'display enable' bit during line N then re-enabling display between lines N and N+1 (generally during HBLANK but some games sometime set the bit near the end of line N, resuting in some flickering pixels) stops sprites from being displayed on line N (cf. Sonic 2 VS mode, Deadly Moves)

This is where I have trouble understanding how it internally works: I would have thought initially that all sprites are processed during HBLANK and internal line buffer filled as long as the 'display enable' bit is set but it seems that the state of previous line somehow matters also.

Post Reply