|
Post by matalog on Jul 3, 2017 4:12:36 GMT -5
I wrote a small program last night to test how often the HBLANK occurs, so I could possibly use it as a faster timer than 1/50 or 1/60th of a second from VBLANK.
From the results of my program, it looks like a HBLANK occurs around 34 or 35 times as often as a VBLANK, I would have expected it to be 224 times more often, if they are doing what I initially thought, but then I thought that maybe it is the sensitivity of the program I wrote, or the fact that it was written in BEX, maybe it does not cycle or loop fast enough to accurately register each HBLANK?
Any ideas?
Another question, as I was adding the print statements in the program, I noticed that it was very hard not to have some unwanted numbers appear at the start of the line dislpaying the modulo increment, does anyone know why that may be? For example, in this program, when the VBLANK modulo increment gets above 141, then "101" appears at the start of the line, unwanted, and un-asked-for.
Here is the program.
'HBLANK VS VBLANK
global T as integer global J as integer global Q as integer global U as integer U=0 T=0 J=0 Q=0
locate 0,2:print "HBLANK" locate 9,2:print "VBLANK"
do hblank 0 on Hblank gosub GL enable INTERRUPT HBLANK on VBLANK gosub KL enable INTERRUPT VBLANK loop GL:
J=J+1 locate 1,2:print J if J % 60=59 then Q=Q+1 locate 2,5:print Q endif
if J<0 or J>32000 then J=1 locate 1,2:print " " endif return KL:
T=T+1 locate 10,2: print T if T % 60=59 then U=U+1 locate 11,5:print U endif if T<0 or T>32000 then T=1 locate 10,2:print " " endif return
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Jul 3, 2017 7:32:41 GMT -5
Hblank triggers to whatever you set it to via the Hblank command. You can set it to trigger after every scanline, every other, or every 200.
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Jul 3, 2017 7:33:15 GMT -5
Also, hblank 0 won't let the vblank trigger
|
|
|
Post by matalog on Jul 3, 2017 10:41:38 GMT -5
If I don't include the Hblank 0, then there are even more of the 'unwanted' numbers being printed at the start of the last line (printed on screen), and if I change it to HBLANK 1, then the same 'unwanted' numbers appear - AND the result is not any different. The HBLANK number is still roughly 35 times bigger than the VBLANK. In fact - it stays the same whether it is HBLANK 1,2,3,4,5 or 6, then slows down as expected at HBLANK 7 and upwards, I guess that each loop of the program senses a HBLANK, but the loop of the program is not frequent enough to capture (sense or intercept?) all of the 224 HBLANKS per 1/60th of a second. If I worked it out correctly, my short program sees a maximum of 36 HBLANKS over 1/60th of a second, so it must loop every 1/2140th of a second, whereas it would need to loop at least every 1/13440th of a second to sense all of the HBLANKS.
Does anyone know why this is, or why the numbers appear PRINTed where they were not instructed to?
Thanks for any help,
matalog.
|
|
|
Post by landeel on Jul 3, 2017 11:32:38 GMT -5
Hm this gave me a great idea, and looks like it works, so thank you
|
|
|
Post by matalog on Jul 3, 2017 12:26:45 GMT -5
Hm this gave me a great idea, and looks like it works, so thank you You're welcome. Please share your idea :-). And please enlighten us on the cause of any of the behaviour if you can.
|
|
|
Post by landeel on Jul 3, 2017 12:39:55 GMT -5
It's about stef's new xgm driver. I can use the hblank interrupt to handle the vint process and still use the vblank interrupt for myself. I haven't tried with real hardware yet, but it seems to work fine with emulators.
|
|
|
Post by matalog on Jul 4, 2017 3:02:00 GMT -5
Is it a coincidence that I found the following information: OTHER:
- DMA
• removes the 68000 from the BUS
• can move 205 Bytes/scanline during VBLANK
- there are 36 scanlines during VBLANK
- DMA can move 7380 Bytes during VBLANK
- Horizontal & Vertical interruptsIn the document Sega Genesis Manual
What I am asking is, Is it a coincidence that the little program I wrote, at most measured 36 HBLANKs (which could be considered scanlines), in the time that it measured 1 VBLANK?
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Jul 4, 2017 7:26:37 GMT -5
Okay, now that I'm not on my phone responding:
HBLANK triggers after a specified amount of scanlines set by the HBlank command:
HBlank 10
Default may be 0, I'm not 100% sure. The HBlank is quick. Very quick. VBlank runs at 1 cycle every 16.6 milliseconds where the HBlank triggers in 0.004 seconds (about 4 times faster than VBlank).
So what happens if you put a lot of code to execute in your HBLank function? It *seems* to work fine in emulation (which isn't perfect, at all), but what it's really doing is bleeding over into the VBlank period and/or not run all of the code in the HBlank.
You have enough time to run about 7 ASM commands during the HBlank period. Past that, you're risking slowdown in places that wouldn't normally have slowdown, or things not executing at all because there's not enough time left during the blanking periods.
Also, I hate to break it to you, your GL: routine is WAY too long for the HBlank, so it's bleeding into the VBlank. It doesn't make sense "measured 36 HBlanks". If you didn't specify a number, it should 0, which means you should have had the HBlank trigger over 200 times (223 times, to be exact).
So, to answer your original question: HBlank triggers after Y+1 scanlines. The lower the number, the more times the HBlank will trigger. Each HBlank period is 0.004 seconds, or about 4 times quicker than 1 VBlank cycle, which is 16 milliseconds (0.016 seconds) for NTSC and 0.02 seconds for PAL.
In your example in the first post, you're using HBlank 0, which means it's triggering after every scanline is finished being drawn. So what's happening? Your HBlank routine is running into the VBlank period. Notice your VBlank counter is running ~25% slower than if you weren't using the HBlank. If you comment everything out of your VBlank routine except for the J=J+1 (you should change that to J++) and the Print J, you'll get a faster counter.
So, long story short, your example proves what I've been saying - too much code in the HBlank will interfere with the VBlank and cause slowdown.
|
|
|
Post by matalog on Jul 4, 2017 12:04:56 GMT -5
Okay, now that I'm not on my phone responding: HBLANK triggers after a specified amount of scanlines set by the HBlank command: Default may be 0, I'm not 100% sure. The HBlank is quick. Very quick. VBlank runs at 1 cycle every 16.6 milliseconds where the HBlank triggers in 0.004 seconds (about 4 times faster than VBlank). As far as I can see HBLANK triggers a lot more often than what you have said, in fact around 10 times more often. Actually around 36 triggers per every trigger of VBLANK, like I said.
Why does VBLANK 1 not trigger 224 (scanlines)*60 (screen refresh rate) times per second?So what happens if you put a lot of code to execute in your HBLank function? It *seems* to work fine in emulation (which isn't perfect, at all), but what it's really doing is bleeding over into the VBlank period and/or not run all of the code in the HBlank. Are you saying that I should not use HBLANK and VBLANK together in the one piece of code?
You have enough time to run about 7 ASM commands during the HBlank period. Past that, you're risking slowdown in places that wouldn't normally have slowdown, or things not executing at all because there's not enough time left during the blanking periods. I didn't actually think that I was holding back the progress of the HBLANK period - I actually thought that I was just requesting an increment and PRINT starting from the time that a HBLANK was triggered.
In the end, all I want is a timing method for a game I am working on, and HBLANK is nice and fast to give a good range of speed control for a program. Is there a good way to use HBLANK, that it will not cause problems for a program?Also, I hate to break it to you, your GL: routine is WAY too long for the HBlank, so it's bleeding into the VBlank. It doesn't make sense "measured 36 HBlanks". If you didn't specify a number, it should 0, which means you should have had the HBlank trigger over 200 times (223 times, to be exact). I'm glad to hear that some thing caused it :-).
So, now you are saying that the HBLANK should have triggered 223 times during one triggering of a VBLANK, whereas above, you said it is 4 times faster.
Can you show me a program that will increment an on screen number 223 times per 1/60th of a second, on screen - using HBLANK? I am struggling to get a program to increment a number more than 36 times every 1/60th of a second.
So, to answer your original question: HBlank triggers after Y+1 scanlines. The lower the number, the more times the HBlank will trigger. Each HBlank period is 0.004 seconds, or about 4 times quicker than 1 VBlank cycle, which is 16 milliseconds (0.016 seconds) for NTSC and 0.02 seconds for PAL. Like I said, I can not see a difference in a printed number if I use HBLANK 6, 5, 4, 3, 2, or 1 - and that was a large part of my original question. Why is there no difference? Even when measuring how often HBLANK only is by printing a number to the screen.In your example in the first post, you're using HBlank 0, which means it's triggering after every scanline is finished being drawn. So what's happening? Your HBlank routine is running into the VBlank period. Notice your VBlank counter is running ~25% slower than if you weren't using the HBlank. If you comment everything out of your VBlank routine except for the J=J+1 (you should change that to J++) and the Print J, you'll get a faster counter. So, long story short, your example proves what I've been saying - too much code in the HBlank will interfere with the VBlank and cause slowdown. Thanks for replying. Is there a way to use the timing of a HBLANK trigger, without having the code slowing down the HBLANK? Or so that it will not cause problems?
matalog.
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Jul 4, 2017 13:50:15 GMT -5
Ugh, yellow on blue and then bold yellow is just a pain to follow, so if I miss anything, sorry First, an example: Global a As Integer
hBlank 200 On InterruptHBlank GoSub hb Enable InterruptHBlank While 1 Print a, b b++ If b > 60 Then Disable InterruptHBlank End End If Wend hb: a++ Return
Change the HBLANK value to see varying results. The hblank triggers ONCE per scanline. 1 scanline = 1 row of pixels 1 pixel in height. It does not trigger any more or less. When you specify the value in the hblank command: hBlank <value>
You're telling the HBLANK to trigger every <value>+1 scanlines. The higher the number, the less the hblank will trigger. In the above example, if you do HBlank 0, you'll end up with a really high value, but if you do HBlank 1, you'll get a significantly lower value. Why? Because the hblank is happening every scanline, the program loop doesn't have time to execute. So no, the hblank only triggers once per scanline. If you have it set to hblank 0 (every scanline), then it will trigger 224 times, hblank 1 will trigger 112 times (every other line), etc. The more hblank triggers, the less time VBLANK has to complete its cycle. The VBLANK fires off 60 times per second on NTSC, 50 times on PAL consoles. Why? That's just the way the hardware works. I can get into the specifics, but it's not necessary unless you don't want to accept the fact We can test this out like so:
On InterruptVBlank GoSub vb Enable InterruptVBlank While 1 b++ Locate 1,1: Print a,b If b = 120 Then Disable InterruptVBlank End End If Sleep 1 Wend
vb: a++ Return
Run the code and compare to your computer clock to see that this done run for 2 seconds. There is no "VBLANK 1" or "VBLANK <value>". Not at all. I'm saying you shouldn't rely on normal operations to execute through the HBLANK because it will cause slowdown and other undesirable effects if your code is too long to execute during the horizontal blanking period (0.004 seconds). HBLANK is generally used for raster/line scrolling effects, such as distorting layers to give various effects (wobble, "flip", skew, etc). It should NOT be used for music, loading graphics, etc. No, that's the maximum amount the hblank can trigger during 1 screen refresh. If you do trigger it that much, you slow down every other piece of code. In the first example, you'll see that the variable "a" becomes rather enormous while "b" remains "normal". This is because the hblank keeps interrupting and slows down the application by a significant magnitude. Because you're printing in the routine so the program is already slowed down. Here's an outline of how the VBLANK and HBLANK operates in the code: ' Main program Loop: While 1 ' Always true, keep looping until we force an exit ' All code here will get interrupted by the vblank and hblank
sleep 1 wend
VblankRoutine: ' Everything in here gets interrupted by the hblank return
HblankRoutine: ' Nothing interrupts me return
When the HBLANK interrupts, it interrupts everything until it's finished. When the VBLANK triggers, it does the same. You have a lot more time during the VBLANK (0.016 seconds). Let's do some math: 1 second divided by the number of scanlines (224) = 0.00446 per execution cycle per second. 1 second divided by the number of times the VBLANK triggers (NTSC/60) = 0.01667 seconds per execution, (PAL/50) = 0.02 seconds If the hblank triggers every scanline, you come up to 1 second, so the time for vblank doesn't exist (you may get some things, but not much, and it will be incredibly slow), but then your code outside of the hblank and vblank may not even execute at all. We can derive a formula to figure out how much time is being utilized: VBLANKtime = 1 - (ScreenResolutionY / (hb_scanlines+1)) * 0.004s Most people stick to the NTSC resolution of 320x224 rather than 320x240, so ScreenResolutionY = 224, hb_scanlines is what you define with Hblank <value>, and the 0.004 is how long each HBLANK triggers Or you can calculate your HBLANK time by adjusting the above to this: HBLANKtime = ScreenResY / (hb_scanlines+1) Hope this helps!
|
|
|
Post by matalog on Jul 4, 2017 14:11:18 GMT -5
Okay so
Indeed shows that HBLANK can count to 13440 in roughly a second, which is good. That is what I initially expected to see, given there are 224 hblanks per vblank and 60 vblanks per second.
So, you say that i shouldn't use HBLANK to load graphics - I have been using HBLANK 80 to time my whole program so far! Is that a terrible idea then?
The problem is, that I find VBLANK too infrequent for my characters movement and I (for the first time ever) am trying to control the speed of my program with a timer of sorts (definitely instead of SLEEP 1 as that stops all processing), instead of just letting the program run at full speed ahead - which will probably change as the program becomes more advacned.
What do you think?
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Jul 4, 2017 15:14:45 GMT -5
*sigh* I give up on trying to help you with the HBlank. Honestly, with what you just posted, you shouldn't bother messing with the Hblank until you learn more about the platform and language. It's an advanced thing.
Now, if you're using sleep 1 in the vblank, take it out. Oh, another fun fact. Using the horizontal interrupt, sleep commands will halt execution due to a conflict.
Here's a sprite moving example:
Dim spr As Integer, j As Integer, sx As Integer, sy As Integer spr = AddSprite(1,1) PropSprite spr,1,0 sx = 128 sy = 128 MoveSprite spr,sx,sy
On InterruptVBlank GoSub vb Enable InterruptVBlank
While 1 j = JoyPad(0) Locate 24,0: Print sx,sy Sleep 1 Wend
vb: 'j = JoyPad(0) sy+=j.1-j.0 sx+=j.3-j.2 MoveSprite spr,sx,sy Return
You can put the j = joypad(0) in either the main program loop (the While...Wend block) or in the vblank (vb:). The vblank lines may need adjusting as I wrote this in SecondBASIC.
If that's too slow for you, you can do:
sy+=(j.1-j.0)<<1 sx+=(j.3-j.2)<<1
instead. The <<1 is logical shift left (acts as * 2 here, just faster).
|
|
|
Post by matalog on Jul 4, 2017 15:26:31 GMT -5
I thought that HBLANK was an interrupt and could be used to set up timing in a program, is that incorrect then?
Yeah, i know how to get sprites moving, and I would always choose not to use SLEEP 1, that you have suggested, as it halts the program, not just the movement. Anyway, I want to get my sprites moving with more speed than a 1/60th of a second frequency allows, I would prefer 1/150th of a second roughly. How could I achieve that?
|
|
Deleted
Deleted Member
Posts: 0
|
Post by Deleted on Jul 4, 2017 16:21:28 GMT -5
No, you shouldn't use the HBLANK as a counter. I mean, you can, but there's no point. Using HBLANK takes away time from the VBLANK. If you're going to use a counter, then don't put it in HBLANK. HBLANK can only execute 7 ASSEMBLY commands before it reaches its end. Not BASIC commands, ASSEMBLY.
Sleep only halts your program because you have HBLANK enabled, as I stated in one of my last posts. Quit using the HBLANK and you won't have those issues.
If you want to control the speed slower than the VBLANK, or using Sleep 1 outside of the VBLANK, then replace the vblank routine in my last example with this:
vb: 'j = JoyPad(0) counter++ If counter % 100 = 1 Then sy+=j.1-j.0 sx+=j.3-j.2 MoveSprite spr,sx,sy End If Return
Change the % 100 to whatever you want. Higher = slower, lower = faster.
Anyway, since you're insistent on wanting to use the HBLANK and not listening to reason, chances of me responding are nil.
|
|