GP2X Flickering Screen With 2.0.0 Firmware


thebooboo

Still Fresh
Joined
Mar 1, 2006
Messages
51
Location
London, UK
Website
www.timsrecordlabel.com
I've been testing my game, Level Shmup, on 2.0.0 firmware, unfortunately I'm getting flickering on the screen. This happened when I re-compiled the game using Paeryn's HW-accelerated SDL libraries for 1.4.0 firmware, but disappeared when I activated double buffering. I've still got double buffering turned on but I still get this flicker regardless of the setting under 2.0.0. Has anyone else had this problem and does anyone know of a solution?
 
Vimacs posted on May 4 2006 at 12:20 PM said:
probably related to the vsync problem of 2.0 firmware.
In particular, it appears that for some incomprehensible reason the meaning of the 'vsync' signal has changed. So old code that waited for the relevant bit in a MMSP2 register to go low now returns immediately because the bit is normally low and now goes high to indicate a a vsync.

The problem will have to be fixed in the SDL library. I'm not sure exactly what the best fix is for that since code will have to be compatible with both schemes. Perhaps some register contains information about which mode the vsync signal is in (I've been meaning to look that up for my own purposes). A crude hack would be to watch for any change in that bit and assume that means a vsync pulse is being entered.
 
Last edited by a moderator:
There's an even more crude hack involving a meat cleaver and whoever keeps fucking around with the vsync code, but I can't afford the trip to korea.
 
Dzz posted on May 4 2006 at 07:30 PM said:
The problem will have to be fixed in the SDL library. I'm not sure exactly what the best fix is for that since code will have to be compatible with both schemes.
Some of the code I've seen waits for the edge on the VSYNC signal, rather than looking specifically for the change to low, so the worst-case scenario is that you miss the 'flyback' time.

From a quick scan through the new sources, the change appears to be in /drivers/video/mmsp2fb.c. The call to DPC_UTIL_HVSYNC now sets the vertical polarity to false instead of true. This affects the MMSP GPIO register, DPC_FPIPOL1 at 0x2804 (Chapter 14 in the docs.) I guess somebody thought this was a great idea, but didn't think it through.

It should be possible to switch it back easily enough by masking out bit 0 (VSPOL), and restoring its previous state on exit, if anybody wants to try it...
 
Last edited by a moderator:
scorpio posted on May 4 2006 at 05:46 PM said:
Dzz posted on May 4 2006 at 07:30 PM said:
The problem will have to be fixed in the SDL library. I'm not sure exactly what the best fix is for that since code will have to be compatible with both schemes.
Some of the code I've seen waits for the edge on the VSYNC signal, rather than looking specifically for the change to low, so the worst-case scenario is that you miss the 'flyback' time.

From a quick scan through the new sources, the change appears to be in /drivers/video/mmsp2fb.c. The call to DPC_UTIL_HVSYNC now sets the vertical polarity to false instead of true. This affects the MMSP GPIO register, DPC_FPIPOL1 at 0x2804 (Chapter 14 in the docs.) I guess somebody thought this was a great idea, but didn't think it through.

It should be possible to switch it back easily enough by masking out bit 0 (VSPOL), and restoring its previous state on exit, if anybody wants to try it...
Thanks for this excellent detective work. Checking that register and waiting for the appropriate vsync polarity is probably the right thing to do and is not very hard.
 
Last edited by a moderator:
Dzz posted on May 5 2006 at 12:52 AM said:
Thanks for this excellent detective work. Checking that register and waiting for the appropriate vsync polarity is probably the right thing to do and is not very hard.
Well, hopefully I'm right, and it will work. Your suggestion also sounds a lot better than what I was thinking of. I was thinking that one might change the polarity setting at the program start, and restore it on exit, but of course, it's much better (and safer) to look at what it's set to and check for the appropriate signal level.
 
Last edited by a moderator:
I didn't realise they'd messed with the vsync in the new firmware, I've not done any programming since I updated.
I played around with this myself trying to get a stable (non-interlaced) screen, it should be no more than checking what the polarity is at the start, and choosing between low-high or high-low tests in the vsync wait.
I'll get SDL fixed and uploaded asap.
 
I've done a quick bodge to get the thing working again for the time being, which is to set the actual screen surface as a software surface, and declare another surface as a hardware surface, blit everything to the hardware surface to get it done quickly, then blit that surface to the sw surface and SDL_flip with the software surface. Hardly ideal but it still gives me an acceptable frame rate for this game.
 
I've just been bitten by this, took some of the code from the tut on demos and sat here for an hour reading the docs thinking that the wrong register had been used. Anyway i've done the following and works on my 2.0 Firmware. Is this what you meant?

if( pWait_for_vbl )
{
if( (reg.hw.regs16[0x2805]&1) == 0 )
{
//No VSync
while((reg.hw.regs16[0x1182>>1]&(1<<4)) == 0);
//VSync
while(reg.hw.regs16[0x1182>>1]&(1<<4));
}
else
{
//No VSync
while(reg.hw.regs16[0x1182>>1]&(1<<4));
//VSync
while((reg.hw.regs16[0x1182>>1]&(1<<4)) == 0);
}
}
 
MadDog posted on May 8 2006 at 11:44 PM said:
if( (reg.hw.regs16[0x2805]&1) == 0 )
I presume that's a typo (I'm sure it should be 0x2804), but yes, that's pretty much what I was thinking of. Glad to know it worked out!
 
Last edited by a moderator:
MadDog posted on May 9 2006 at 07:42 PM said:
Nope, its a bug! LoL :lol: Better go make the change and retest.
That's interesting. If it worked like that then it suggests that the MMSP2's address decoder discards bit 0 off the address lines. This possibly means that the problem of reading and writing the registers as separate 8-bit halves is not because the GP2X is looking for a half-word transfer, but because you can't reach the high-order byte except through the data bus ... <strokes chin>
 
Last edited by a moderator:
I changed it to 0x2804 and it stopped working, had to change the if to " if( (reg.hw.regs16[0x2804]&1) )" instead of the typo " if( (reg.hw.regs16[0x2805]&1) == 0 )" to make it work. Although its untested on the 1.4 FW.

But yes, should have bombed from reading a 16bit value on an odd address. Even more intresting was that it was not reading the same value as one would expect. Do you know if its the MMU or the CPU it self that triggers the exception when reading from bad alignement? Yer, chin scratching time.

Intresting, just reading one of my 'new' books.ARM Architecture Reference Manual ISBN:0-201-73719-1
It says on the subject of Unaligned data accesses.
The Architecturally defined behavior of a load/store instruction which generates an unaligned access is one of the following.
  • It is UNPREDICTABLE
  • It ignores the low-order address bits that make the address unaligned. ( basic mask )
  • It ignores the low-order address bits that make the address unaligned for the memory address its self but then uses the low order-bits to control a rotation if the loaded data. ( This only applies to the LDR and SWP incstructions)
Reading about the MMU I see that it creates faults on four types.
  • Alignment
  • Translation
  • Domain
  • Permission
It seems that the fault on address alignment can only be turned on/off gloabbaly in the MMU's reg1. I can't see if there is anything to mark a memory region to not generate these faults. One thing though is that (if i'm reading the book right) domains 0->3 don't fault on address alignement. If this is that case and the memory returned is in one of these domains could explain why I did not get an exception. What I would have been getting was just junk in the data read back.


In short, its the MMU that tells the OS you've been naughty and not the CPU. :)
 
MadDog posted on May 9 2006 at 02:06 PM said:
I changed it to 0x2804 and it stopped working, had to change the if to " if( (reg.hw.regs16[0x2804]&1) )" instead of the typo " if( (reg.hw.regs16[0x2805]&1) == 0 )" to make it work. Although its untested on the 1.4 FW.
How come you address this one with reg.hw.regs16[0x2804] but others in your code are addressed like this:

> while(reg.hw.regs16[0x1182>>1]&(1<<4));

(with the shift)
 
Last edited by a moderator:
Thats a very good point, I just nicked that line from the demo tut. Mmm, I need to go and get the magnifying glass out and 'read' the docs, looks like I may have made a pigs ear of it. Its working, but how though? :lol:
 
MadDog posted on May 9 2006 at 02:20 PM said:
Thats a very good point, I just nicked that line from the demo tut. Mmm, I need to go and get the magnifying glass out and 'read' the docs, looks like I may have made a pigs ear of it. Its working, but how though? :lol:
When accessing the registers as shorts it should always use the shift. Could you let me know which demo material you got the bad code from? I'd like to go change it if I haven't fixed it already sometime in the past.

Edit: Whoops, none of the demos actually use the register 0x2804 stuff yet, so there's no typo to fix in that regard.

I'll update the VSync code in the next episode of the demo series to include the new firmware 2.0 requirements.
 
Last edited by a moderator:
The bad bit, the 'if', is my addition. Whoops, the bit I nabbed was the correct part with the shift. I did not know about the shift, where you get that little nugget from? Seems a bit of a hidden gotcha. ;)

Mmmmm, could I have got that code any more wrong? LoL :p
 
MadDog posted on May 9 2006 at 02:27 PM said:
The bad bit, the 'if', is my addition. Whoops, the bit I nabbed was the correct part with the shift. I did not know about the shift, where you get that little nugget from? Seems a bit of a hidden gotcha. ;)

Mmmmm, could I have got that code any more wrong? LoL :p
I got the >>1 convention from squidge and rlyeh and the other guys who figured this stuff out back in the mists of time. It looks a little weird but it makes sense to do it this way -- the register address matches the address in the MagicEyes documentation but since the memory is being addressed as an array of shorts instead of chars, the address needs to be divided by two.
 
Last edited by a moderator:
Back
Top