HBlank Timings

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

Moderators: BigEvilCorporation, Mask of Destiny

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

Post by Nemesis » Fri Mar 13, 2009 12:15 am

Wow, there's some great info in this thread. I haven't done this level of testing on the timing of all the VDP output signals yet. Thanks a lot for the images you posted Eke, they've given me a much clearer picture of what goes on within a line.
Eke wrote:It would require someone willing to test exactly when the HBLANK flag is set/cleared regarding to the HINT occurence...
These are tests I've always wanted to do on the VDP output. In particular, I want to know the exact cycles when all the various register values are modified (H/V counter, hblank flag, vblank flag, vint occurance flag), and how they are aligned with the analog output signals, such as hsync and vsync, and how they line up with hint/vint. This would give you the precise data you need in order to know when to set all these values.

I haven't done these tests yet, but this is something I've planned for, and this thread is motivating me to start them. I recently purchased a logic analyser. I haven't tested it yet, but in theory, I can now snoop on signals as they pass over the bus. By, for example, running code which constantly reads from the status register as fast as possible, and monitoring those reads with the logic analyser, which is also hooked into other lines (such as the clock pulse and interrupt lines), I can, in theory, determine the exact cycle when these register values change, and also measure when that cycle occurs relative to other known outputs. Combined with the other information already in this thread, these tests should be able to give us all the information to get all these timing events absolutely perfect.

I'll test out my logic analyser this weekend. I haven't tried it yet, so I still don't know how well it's going to go, but I'll let you guys know the results.

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

Post by mickagame » Fri Mar 13, 2009 6:50 am

That's would be wonderful if we can have all this infos !!!
I have to be patient now :lol: ...

Thank you !!!

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

Post by mickagame » Fri Mar 13, 2009 6:55 pm

I made some tests with timings supposed :

With this timings :
http://img3.imageshack.us/img3/2307/vdptimings.gif

Problem in sonic 2 2 players mode (blue bar).
The delay between H-Int and hblank flag end period is too long.

With this timings :
http://img10.imageshack.us/img10/7427/vdptimingsh40.gif
The delay is correct so sonic 2 is ok.
The display of Mickey Mania (HCounter sensitive) in "3d" level is wrong.

So this timings are wrong.

I tested with hcounter beginning with A4 and hblank flag period between B6 and 07 and all is ok.

Now waiting Jorge and Nemesis Tests to know the secrets of vdp timings :-)

Jorge Nuno
Very interested
Posts: 374
Joined: Mon Jun 11, 2007 3:09 am
Location: Azeitão, PT

Post by Jorge Nuno » Sat Mar 14, 2009 2:36 am

This is my best code for now, to read the HV, without disrupting normal program operation:

Code: Select all

;This piece of code is intended to run with my program (inserted into $E0F800 by hand ("only" 18 Move.longs)).
;The horizontal interrupt pointer location of my program is $E0F000, so any code could be HBL.
;When the "Read Pointer" command is activated the main code calls a subroutine in $E0F800, which only has a RTS by default.


;Code to load in $E0F800:
Submain:	
			MOVEM.l	a4-a6,				-(a7)
			MOVE.w	#$8004,				(a6)		;Disable H
			MOVE.w	#$8144,				(a6)		;Disable V
			ADDQ.l	#$4,				a6
			LEA		HBL3(pc),			a5
			LEA		$E0F000,			a4
			
LoadHBL3:	
			MOVE.w	(a5)+,				(a4)+
			BNE.s	LoadHBL3
			MOVE.w	#$8014,				-$4(a6)		;Enable H
			

Loop:		
			MOVE.w	(a6),				a4			;3856
			BRA.s	Loop							;60FC

			MOVEM.l	(a7)+,				a4-a6		;4CDF 7000
			MOVE.w	#$8164,				(a6)		;Enable V
			MOVE.w	#$8004,				(a6)		;Disable H
			RTS										;Return to main program execution
			
;****************************************************************************
;To $E0F000 (auto loaded by Submain)
HBL3:
			MOVE.w	a4,					$E05000		;Save HV in this location	(reads #$7FD6 in regen, Real mach not tested yet)
			MOVE.l	#$4E714E71,			$E0F822		;Overwrite Loop with 2 NOPS (self modifying code :D)
			RTE
			
HBL3END:	
			dc.w	$0000


It's a pain to insert it manually into ram, any space optimization is welcomed (even if it makes worse on #cycles except the "Loop") .

My code doesn't run in Gens, debugging the 68K in Regen when executing code from RAM it crashes on my pc, but it runs fine on the real machine.

Main program reuploaded.

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

Post by mickagame » Sat Mar 14, 2009 8:51 am

Do you have the.bin of your program?
It would be interesting for me to test in my emulator to see if hvcounter readed is the good value according to the timing table i'm using :)

Thank you

Jorge Nuno
Very interested
Posts: 374
Joined: Mon Jun 11, 2007 3:09 am
Location: Azeitão, PT

Post by Jorge Nuno » Sat Mar 14, 2009 1:20 pm

This? Main Prog:
http://trapalhadas.no.sapo.pt/JORGE.BIN

Or this? Code piece:

Code: Select all

48E7 000E 3CBC 8004 3CBC 8144 588E 4BFA
0024 49F9 00E0 F000 38DD 66FC 3D7C 8014
FFFC 3856 60FC 4CDF 7000 3CBC 8164 3CBC
8004 4E75 33CC 00E0 5000 23FC 4E71 4E71
00E0 F822 4E73 0000
Press B and load the code using the program interface, then load a2 with #$E0F5000, then push START 2 times...
Or Press B, do a savestate, open it in a hex editor and place the compiled code piece in $F800 + $SStateRamOffset ($2478 I think), then load the SState, load a2 with #$E0F5000, and push START 2 times...

My code-piece has a bug because if you press START one more time, it will load an unrelated value to #$E0F5000


Also, I think that the Vcounter should be #$80... not #$7F, I'm not sure if my code is good.



Or you can skip the Code loading section and read $E01000/$E01002, the number of times you want which uses my first method of dumping HV+VDPstatus at the start of H-int.

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

Post by mickagame » Sat Mar 14, 2009 1:39 pm

I don't understand exactly how your program work :D

Did you test it on real hardware?
What is the value you obtain for hvcounter?

Jorge Nuno
Very interested
Posts: 374
Joined: Mon Jun 11, 2007 3:09 am
Location: Azeitão, PT

Post by Jorge Nuno » Sat Mar 14, 2009 1:55 pm

Using the new method I didn't test yet. Becuase I'm laz.. I mean the input method is very boring to load the code piece.


And yeah I know my program is not that user-friendly. Though I can explain anything 8) .

Jorge Nuno
Very interested
Posts: 374
Joined: Mon Jun 11, 2007 3:09 am
Location: Azeitão, PT

Post by Jorge Nuno » Sat Mar 14, 2009 10:13 pm

Allright, this is what you get initially in PAL:
Image

Then B button is pressed and this appears, the cursor '*' can be moved up/down:
Image

Now A is pressed with the cursor at the top, and a '_' appears under a digit to mark it as changeable, up/down to change it's value, or left right to change the changeable digit:
Image

After the first field is entered, A is pressed to commit it's value, then B to free the '*' again, then it's moved down, and I manually insert the first instruction into (a2):
Image

And at last, after a lot of time, I loaded them all, I moved #$E05000 into a2 and pressed START 2 times:
Image
It's #$80A8...


This is Fusion351:
Image

Regen 093 b4 (debug ver) gives me a #$7FD6
Regen 095 (debug) shows #$7F93
(no PIC)

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

Post by Nemesis » Sun Mar 15, 2009 1:09 am

Well, the logic analyser thing didn't go so well. I'll have another go at it later.

What I did instead was create a test ROM which is actively polling the status register and HV counter in tandem as fast as possible, and writing that sampled data to RAM. I ran the ROM multiple times over, under a variety of conditions, both with an without interrupt handler routines, dumping the contents of RAM out to my PC to generate around 1MB of sampled data.

The only tests I've done so far have been in V28/H32 mode on a PAL system, but the data I've compiled suggest the following:
-The HBLANK flag in the status register is set when the HCOUNTER value "jumps" from what appears to be 93 to E9. I assume in other display modes, the HBLANK flag will also be set when the HCOUNTER value jumps ahead, regardless of what the actual values are under that mode.
-The HBLANK flag is cleared at what appears to be a HCOUNTER value of 06.
-HINT is triggered at the exact same time as the HBLANK flag in the status register is set, and the HCOUNTER value jumps. In other words, the HCOUNTER jump, HINT, and HBLANK flag being set, all occur at the same time.
-The VCOUNTER is incremented slightly before HBLANK is set, at an apparent HCOUNTER value of 85. IE, if the VCOUNTER was 14 when HCOUNTER was 84, when HCOUNTER is 85, VCOUNTER will now be 15.
-On the last line, the VBLANK flag is set when the VCOUNTER value is incremented to E0.
-The VBLANK flag is cleared when the VCOUNTER value is incremented from FE to FF the second time. As per the info from Charles MacDonald, and my own tests, the VCOUNTER in this PAL mode counts in the following sequence: 00-FF, 00-02, CA-FF. VBLANK is set when VCOUNTER hits E0, during the 00-FF block. When VCOUNTER hits FF in the CA-FF block, VBLANK is cleared.
-VINT is triggered when the HCOUNTER resets from FF to 00, well after the VCOUNTER has been incremented to E0 and the VBLANK flag has been set.
-The VINT occurrance flag is set as soon as VINT is asserted. It only reads as set when the interrupt has not yet been taken. Reading the status register immediately after entering the VINT routine for example registers this bit as unset.

These readings I took mostly line up with this timing info Eke posted:
http://img10.imageshack.us/img10/8066/vdptimingsh32.gif
With the exception of the VCOUNTER increment, which I read as happening when HCOUNTER reaches 85, not when it reaches 86. The additional info I've provided, such as interrupt timing and vblank flag timing, fit into this diagram as I've described above.

This is preliminary info. I need to do a lot more analysis and sampling, and in particular test under different screen modes such as H40, V30, and on NTSC systems, but I can be pretty confident about what I've posted. Regarding the interrupt timing, note that I sampled those times by determining the last sample I was able to capture before the interrupt was taken, so interrupt execution times haven't affected my readings. Due to the volume of sample data I've captured, I'm reasonably confident the info I've given is accurate, but I do need to carry out more tests.

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

Post by mickagame » Sun Mar 15, 2009 8:43 am

Very interesting infos !!

Thank you Jorge and Nemesis.
What I notice in your post Nemesis is :
HINT is triggered at the exact same time as the HBLANK flag in the status register is set, and the HCOUNTER value jumps. In other words, the HCOUNTER jump, HINT, and HBLANK flag being set, all occur at the same time.
The fact this events occurs at the same time can help to positionning value of h-counter in the schemas eke posted :-)
It would be very interesting to do the same tests in H40 mode ...

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

Post by Eke » Sun Mar 15, 2009 10:36 am

well, we still need the HINT/VINT occurence measured against the /YS and HSYNC signals to know exactly when interrupts are triggered on the line in H32 mode
the relation between Hcounter and display areas might be wrong (probably wrong btw)

Here's what I got if I consider HBLANK flag and HINT occurs at the same moment in H40 mode as well:

Image


And here's what I got for H32 mode if we consider the Hcounter = 0x00 coincides with the same video signal area (Hsync start) in both modes:

Image

However, I feel that the Hcounter most problably is reloaded with 0xE4 (0xE9 in H32 mode) when the VDP is reseted or reaches 0xB6 (0x93 in H32 mode) and then overflows to 0x00, which means the 0xE4 (0xE9) value should coincide with the beginning of one of the video signal area (i.e what the VDP outputs first)

Jorge Nuno
Very interested
Posts: 374
Joined: Mon Jun 11, 2007 3:09 am
Location: Azeitão, PT

Post by Jorge Nuno » Sun Mar 15, 2009 11:52 am

Shouldn't the Hblank flag coincide with the YS signal going inactive (high), except on the active area? Set with YS /-- and cleared when YS \__ ?

Bah there is almost no way to make a relation between [VDPstatus/HVcounter <-> Output signals]

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

Post by Eke » Sun Mar 15, 2009 12:01 pm

Jorge Nuno wrote:Shouldn't the Hblank flag coincide with the YS signal going inactive (high), except on the active area? Set with YS /-- and cleared when YS \__ ?
that what we thought first, but does not seem to be the case

Bah there is almost no way to make a relation between [VDPstatus/HVcounter <-> Output signals
maybe by reading Hcounter value as soon as the system is powered ON
and measuring VDP reset signal in relation with video signals (this would also gives us the effective line number where VDP starts)

most probably, Hcounter is *always* reseted with the same value when the VDP resets
also, it appears to be reloaded with 0xe4 (0xe9) each time it reaches 0xb6 (0x93)

Jorge Nuno
Very interested
Posts: 374
Joined: Mon Jun 11, 2007 3:09 am
Location: Azeitão, PT

Post by Jorge Nuno » Sun Mar 15, 2009 12:11 pm

Eke wrote:maybe by reading Hcounter value as soon as the system is powered ON
and measuring VDP reset signal in relation with video signals

most probably, Hcounter is *always* reseted with the same value when the VDP resets
also, it appears to be reloaded with 0xe4 (0xe9) each time it reaches 0xb6 (0x93)
That needs a no-TMSS MD or doing the ROM decoding manually, to be independent of the state of /CART_IN, or running from the SegaCD port...

Or take out the 68000, and hard-wire manually VA[1:23] to make $C00008 :twisted: :shock: and checking VD[0:15] on a logic analyser

Post Reply