HBlank Timings

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

Moderators: BigEvilCorporation, Mask of Destiny

Post Reply
mickagame
Very interested
Posts: 256
Joined: Sat Jun 07, 2008 7:37 am

HBlank Timings

Post by mickagame » Tue Jun 10, 2008 8:51 pm

Hello,

My name is Mickaël and I'm french fan of Sega Genesis.
In my free time I develop a genesis emulator written in C++.
I have big problem to understand how Horizontal interrupt and Hblank period are ordained.

When i'm watching source code of gens, written by the fantastic Stef, H-Int is generated just after HBlank period. The line is rendered in the end of Hblank period too.
When I'm watching the other excellent emulator Gensis Plus (thank you to Eke for all informations), H-Int is generated just befor Hblank period, and line is rendered at start of Hblank period.

I don't know in which order it is in real hardware, and i'm searching docs, test s...

thank you for your help !!!
Last edited by mickagame on Sat Mar 07, 2009 9:14 am, edited 1 time in total.

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

Post by TmEE co.(TM) » Tue Jun 10, 2008 9:17 pm

I remember reading that Stef accidently swapped the two.
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

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

Post by Eke » Wed Jun 11, 2008 1:30 pm

from the "Sega Programming manual", HINT is generated just before HBLANK

in the genplus version I modified, I made an approximation by starting the line with Hint AND Hblank (in reality, I'm returning the HBLANK flag depending on the CPU cycle count)

also, as the doc said (same section), all informations for the line are fetched some cycles after HINT, during HBLANK, that's why I am also rendering the line before any CPU cycles is executed (even HINT) for this line, to prevent any V-RAM writes to be taken in account for this line...

however, when some VDP registers (like backdrop color or display ON/OFF switch) are updated during HBLANK (often in HINT handler), I need to redraw the line with those new parameters, this is not a very good method but this work well with timing sensitive games and does not break any others

mickagame
Very interested
Posts: 256
Joined: Sat Jun 07, 2008 7:37 am

Post by mickagame » Wed Jun 11, 2008 4:16 pm

Ok I understand.
My main loop emulation is very special, and if I want i can render the line some cycle after HBlank start in any case.
How many cycles does the vdp takes in order to fetch informations?

Thank you eke for all informations you give me ;-)

tails92
Interested
Posts: 41
Joined: Sun May 04, 2008 10:16 pm

Post by tails92 » Wed Jun 11, 2008 4:21 pm

It's nice that you're writing an emulator. How far are you?
Does the CPU core already work?

mickagame
Very interested
Posts: 256
Joined: Sat Jun 07, 2008 7:37 am

Post by mickagame » Sat Jun 14, 2008 6:50 am

I'm using Stephane Dallongeville C68k core rewritten in C++.
My aim is to do a genesis core which can be ported in any platform.
This core is 70% completed now.

mickagame
Very interested
Posts: 256
Joined: Sat Jun 07, 2008 7:37 am

Post by mickagame » Wed Feb 11, 2009 11:23 pm

Here is an extract of genesis plus source code :
/* active display */
if (line <= vdp_height)
{
/* H Interrupt */
if(--h_counter < 0)
{
h_counter = reg[10];
hint_pending = 1;
if (reg[0] & 0x10) irq_status = (irq_status & 0xff) | 0x14;

/* adjust timings to take further decrement in account (see below) */
if ((line != 0) || (h_counter == 0)) aim_m68k += 36;
}

/* HINT will be triggered on next line, approx. 36 cycles before VDP starts line rendering */
/* during this period, any VRAM/CRAM/VSRAM writes should NOT be taken in account before next line */
/* as a result, current line is shortened */
/* fix Lotus 1, Lotus 2 RECS, Striker, Zero the Kamikaze Squirell */
if ((line < vdp_height) && (h_counter == 0)) aim_m68k -= 36;

/* update DMA timings */
if (dma_length) dma_update();
I don't understand what is the delay of 36 cycles.
Can you explain me Eke or someone?

Thank you

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

Post by Eke » Thu Feb 12, 2009 8:54 am

it' because I assume that Hint occurs 36 cycles before the moment where the VDP latch all required informations for rendering the line: this moment coincides with the render_line function call in the emulator

in the emulator, the first thing done in a "line" is the HINT event, followed by line rendering

so, what I do is that, when an interrupt is going to be triggered NEXT line, I shorten the current line (in term of cycles count) to be able to trigger the upcoming HINT at the right moment, at the start of next line

on the next line start, when HINT occurs, I increase the current line length by re-adding the missing 36 cycles (this is not done on line 0 though since I assume frame starts with HINT, except if HINT is goig to be triggered on line 1 also, to keep the delta between 2 HINT occurences constant)


There are still some possible inaccuracies though:

1/ I'm not sure about the 36 cycles value: it seems to be mentionned in official docs but this would require real testing

2/ not everything is latched by the VDP atm, for example border color and display status can be modified during HBLANK, which is longer than 36 cycles and maybe also mid-line (not sure about that). This is the downside of having a line-accurate and not a cell-accurate renderer ;-)

However, this approach seems to fix all VDP sensitive games (all those who use HBLANK with HINT or HVCounter to do some mid-frame changes)

Hope it's more clear, I should probably write the code commentaries better

mickagame
Very interested
Posts: 256
Joined: Sat Jun 07, 2008 7:37 am

Post by mickagame » Thu Feb 12, 2009 9:30 am

So, If i understand :

Code: Select all

                           
                               LINE N                 LINE N + 1
  |----------------------------------------------|--------------------   
<HBS>---------<HBE>----------------------------<HBS>
                                            |
                                         <H-INT>
                                                 |
                                               <LRE>

HBS -> HBLANK start
HBE -> HBLANK end
H-INT -> H-INT Trigger
LRE -> Line rendering          

               


Do delay between Hint and Hblank start is also 36 cycles?
Does your HCounter table in genesis plus start at Hint?

In the emulator i actually write, if i execute 36 cycles of 68k between Hint and Line rendering, I have glitch (Lotus -> write values to CRAM in start of H-Int function and landstalker -> one line is clipping).

notaz
Very interested
Posts: 193
Joined: Mon Feb 04, 2008 11:58 pm
Location: Lithuania

Post by notaz » Thu Feb 12, 2009 9:35 am

mickagame wrote:I'm using Stephane Dallongeville C68k core rewritten in C++.
AFAIK it's done in C, not C++ (i.e. no OOP there).

mickagame
Very interested
Posts: 256
Joined: Sat Jun 07, 2008 7:37 am

Post by mickagame » Thu Feb 12, 2009 9:46 am

I rewrote the core in C++.

notaz
Very interested
Posts: 193
Joined: Mon Feb 04, 2008 11:58 pm
Location: Lithuania

Post by notaz » Thu Feb 12, 2009 10:25 am

mickagame wrote:I rewrote the core in C++.
Hm, and what benefit it gave you? CPU object?
(just wondering why people may want to use OOP in emulators).

Snake
Very interested
Posts: 206
Joined: Sat Sep 13, 2008 1:01 am

Post by Snake » Thu Feb 12, 2009 10:31 am

notaz wrote:
mickagame wrote:I rewrote the core in C++.
Hm, and what benefit it gave you? CPU object?
(just wondering why people may want to use OOP in emulators).
I was going to ask the same thing :)

I've often thought it would be really nice to do this. 68K, Z80, sound chips, video, bus, etc. all nicely hidden away inside their own classes, and a class for the machine containing all the needed parts.

I admit I haven't exactly put a huge amount of thought into this, but I couldn't see a nice way of doing this, and still having all the parts communicate easily, without some nasty hack (and yes, that includes using globals or any other 'non-c++' tricks), or a performance penalty. If you can't do it cleanly, there's not much point, IMO.

Still, it's a nice idea, and would definitely make my life easier.

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

Post by Eke » Thu Feb 12, 2009 10:44 am

Do delay between Hint and Hblank start is also 36 cycles?
no, I made Hblank, Vcounter jump and Hint starts at the same time, even if it's probably not *exactly* what happen on the real thing but it's easier and does not seem to break anything

more precisely, there is two things to handle with HBLANK: the HBLANK flag which is polled by some games and some register writes during HBLANK period which can affect the current line (which has already been drawn by the emulator)

Does your HCounter table in genesis plus start at Hint?
correct, Hcounter table starts at 0x85 in H32 mode and 0xA5 in H40 mode
again, not sure if this is completely accurate but it works
In the emulator i actually write, if i execute 36 cycles of 68k between Hint and Line rendering, I have glitch (Lotus -> write values to CRAM in start of H-Int function and landstalker -> one line is clipping)
it's because Hint processing takes some time (at least 44 cycles to start the processing) so the cycles executed during Hint routine should be executed AFTER the line rendering, because at that time, the VDP has already latched those values and the CRAM/VSRAM/whatever changes will only occur on the next line


at least, this is what happen with Lotus games, not sure about Landtstalker, I never had any problems with this one, I just know that it requires proper DMA operation somewhere


so, I do NOT execute 36 cycles between Hint triggering and line rendering but instead, I ADJUST the events timing regarding of Hint occurences, do you see the difference ?
Last edited by Eke on Thu Feb 12, 2009 10:54 am, edited 3 times in total.

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

Post by Eke » Thu Feb 12, 2009 10:49 am

I've often thought it would be really nice to do this. 68K, Z80, sound chips, video, bus, etc. all nicely hidden away inside their own classes, and a class for the machine containing all the needed parts.
I found this nice also, I think that is how Nemesis emulator is designed by the way (please correct me if i'm wrong)
each "hardware" sub-component put in a class with public functions for common read/write/ctrl operations

Post Reply