Beta Improved Sdl


Tried to get UAE4All with notaz' SDL running again in order to have doublebuffering and stable vsync all the time.

Same result as last time (even though I cut a lot of code from different source files) - the GUI works fine, but once you start the emulation the screen flashes between the emulated gfx and what's remained last in the SDL backbuffer. The emulated gfx are always just in 1 of the 2 buffers causing the screen to constantly switch every frame between the emulated gfx and 1 still picture (a white screen when you entered and left the gui twice).

After commenting out a lot of stuff (including the GUI's drawing calls) without solving the problem I don't have any idea how to make this work correctly.


Please help, notaz!


You can download this broken version here: http://www.mediafire.com/?b9j4bmlgt0914zl

Just extract the uae4all folder to your SD-card and then put a valid kick.rom in it.
Call run_new.sh and you'll see the gui. Press START to begin emulation. You should see the problem (with the gui's background pic in the backbuffer).
Press SELECT to reenter the gui and press SELECT again to return to the emulated flashing gfx (now with a white backbuffer).


As a - probably worthless - test I changed the SDL_Flip call in sdlgfx.cpp to this:
Code:
//test is an SDL_Surface*

if(test)
	SDL_Flip(test);
test = SDL_ConvertSurface(prSDLScreen, prSDLScreen->format, SDL_SWSURFACE);
SDL_FreeSurface(test);
With this you have a 50% chance every time you leave the gui to see the emulated gfx. Or you see a white screen (or the menu's background gfx when it's the first try).
So if you get a white screen you can just press select twice until you see the emulated gfx. As long as you don't enter the gui again they'll stay...
Because of the SDL_ConvertSurface every frame you need to overclock a bit - 650 MHz should suffice.

When you see the emulated gfx they scroll smoothly* - but unfortunately with strong tearing in either the top or the bottom half (meaning the smooth scrolling is limited to the other half). <_<

So this is not a solution to the problem.

But you can try this version as well: http://www.mediafire.com/?oalpm9nlexc7y7z
(start this just like the other version above)


Of course anyone else's help would be very welcome, too. Silver, sebt3, Pickle, SteveM - any ideas?


Btw., the available release version (using SteveM's modified sdl) has perfectly smooth vsync - but only for about a minute until the tearing sets in - then you always have to enter and leave the menu to make it smooth again (for another minute).
 
Is there a way to manually swap buffers?

What I would suggest is when you start the emulation code, clear the screen in the current buffer, force a buffer swap, then clear the screen in the newly swapped buffer.

Then let the emulation code run and draw.
 
From the description it looks like it doesn't really do doublebuffering right (i.e. it always draws to the same surface)? If so you'll have hard time to have it not to tear, it would help to see your source.
 
Thank you for the quick reply.


The SDL_Surface* is created like this (in gui.cpp):

prSDLScreen = SDL_SetVideoMode(320, 240, 16, SDL_SWSURFACE|SDL_FULLSCREEN|SDL_DOUBLEBUF);


Now always when the in sdlgfx.cpp defined int drawfinished gets set to 1 in drawing.cpp (see attachment) SDL_Flip is called in sdlgfx.cpp's function flush_block().

This is all that happens then in sdlgfx.cpp (should be every frame):

Code:
void flush_block()
{
    uae4all_prof_start(13);
    SDL_UnlockSurface (prSDLScreen);
    if(drawfinished)
    {
        drawfinished=0;
        SDL_Flip(prSDLScreen);
    }
    SDL_LockSurface (prSDLScreen);
    uae4all_prof_end(13);
}

Attached source files (the forum wouldn't let me upload .cpp-files hence the zip-format):
View attachment 550
View attachment 551
View attachment 552

I have to add I have no idea how and where exactly the emulated gfx from drawing.cpp are drawn onto sdlgfx.cpp's SDL_Surface* prSDLScreen.



PokeParadox said:
Is there a way to manually swap buffers?

What I would suggest is when you start the emulation code, clear the screen in the current buffer, force a buffer swap, then clear the screen in the newly swapped buffer.

Then let the emulation code run and draw.
Thanks for the suggestion. I already cut basically any drawing of the GUI prior to the emulation code, but that didn't help either (maybe I forgot something that still drew to it though).
So is it possible to manually swap the buffers, notaz?

Btw., also tried SDL_FreeSurface(prSDLScreen); for 100 frames after the emulation has started (and of course no SDL_Flip during that time). But that didn't help either.
 
Last edited by a moderator:
john4p said:
So is it possible to manually swap the buffers, notaz?
That's what SDL_Flip() is supposed to do.

From your description it feels like it is doing SDL_Flip() twice per frame, which basically makes it non-functional and front buffer never updates. I see SDL_Flip() is called from updatescreen(), maybe something is calling that? Otherwise you could try printing timestamps in flush_block() and see how often it's called, assuming PAL it should be in ~20ms intervals for 50Hz.

You could provide full source too so that I don't have to guess things.

EDIT: found it in the other thread, uae4all is as horrible as usual. Here:
Code:
void flush_block (int ystart, int ystop)
{
...
    if (drawfinished)
    {
        drawfinished=0;
#if !defined (GP2X) && !defined (PSP) && !defined (GIZMONDO)
        if (vkbd_mode)
                vkbd_key=vkbd_process();
#endif
#ifndef PANDORA
        updatescreen( prSDLScreen, 0, 0, current_width, current_height );
#endif
    }
#ifdef PANDORA
        updatescreen( prSDLScreen, 0, 0, current_width, current_height );
#endif
#ifndef DREAMCAST
    SDL_LockSurface (prSDLScreen);
#endif
}
flush_block() is called almost randomly, you should really have updatescreen() in if(drawfinished) {} block.
 
Last edited by a moderator:
Thanks for the input.

notaz said:
From your description it feels like it is doing SDL_Flip() twice per frame, which basically makes it non-functional and front buffer never updates.
Makes sense. I'll then try to only do SDL_Flip in 1 out of 2 calls (every other call) of flush_block(). Let's see what that'll produce.

notaz said:
I see SDL_Flip() is called from updatescreen(), maybe something is calling that?
I already tried setting a flag when flush_block gets called. When this flag was set updatescreen didn't do SDL_Flip anymore (just return;). And in flush_block() I directly called SDL_Flip. So really only flush_block() was calling SDL_Flip - the behaviour was the same as before.

notaz said:
Otherwise you could try printing timestamps in flush_block() and see how often it's called, assuming PAL it should be in ~20ms intervals for 50Hz.
Thanks, I'll try that, too.

notaz said:
flush_block() is called almost randomly, you should really have updatescreen() in if(drawfinished) {} block.
It was inside that block all the time (with same behaviour). Only yesterday I moved it out of there because I found that with SteveM's SDL the sometimes occuring tearing is less now (still not satisfying).
 
Last edited by a moderator:
>> I'll then try to only do SDL_Flip in 1 out of 2 calls (every other call) of flush_block(). Let's see what that'll produce.

Tried this - but still the same behaviour. It only now switches at half speed* between the emulated gfx and the still picture. :(


edit: printed out the timestamps now (with calling SDL_Flip every call of flush_block again). It is about every 20ms:

1303887701:018707
1303887701:036437
1303887701:057128
1303887701:078887
1303887701:098632
1303887701:116821
1303887701:136871
1303887701:167053
1303887701:177856
1303887701:198760
1303887701:219940
1303887701:237884
1303887701:258758
1303887701:276794
1303887701:298461
1303887701:318786
1303887701:337371

(format: seconds since 1970 : microseconds)


So the problem should lie somewhere else.
 
Try adding this at the end of flush_block():
Code:
gfx_mem = (char *)prSDLScreen->pixels;
init_row_map();

then remove "static _INLINE_" from init_row_map() in drawing.cpp so that it all compiles.
 
No idea what that exactly does, but it must've took you quite a bit effort delving into that drawing.cpp code...
Thanks a lot for your help and debugging! :)

Unfortunately I won't have access to my Pandora until saturday (locked the Pandora in my car - then my car key broke in two pieces and a new key won't be there before saturday).
I'll try that right away then.
 
john4p said:
No idea what that exactly does, but it must've took you quite a bit effort delving into that drawing.cpp code...
Thanks a lot for your help and debugging! :)

Unfortunately I won't have access to my Pandora until saturday (locked the Pandora in my car - then my car key broke in two pieces and a new key won't be there before saturday).
I'll try that right away then.

What's the number of your car and where do you live? Also, if you hear a smashing sound and a car alarm at 2am, just shut your eyes and go back to sleep....

On a more serious note though thank you everyone for your continued efforts to bring smooth emulation to our pandora screens. I was playing with Vice 64 the other night and had to turn double buffering off to get it to run smoother (but still not as good as I was hoping). Am I right in thinking that improved SDL will be applicable (and hopefully applied) to other emulators in due course? I love the amiga emulator (despite its bugs) and the C64 was in my nostalgia clouded eyes the greatest machine ever devised. I started with c64, then got my Amiga 1200, a cheap 2nd hand megadrive so I could play Road Rash 2 and later at uni I bought and repaired a PSX (which cost £25 in total including spare parts and a mod chip that I soldered in - what an bargain). I'm delighted at how well the pandora plays the games of my delightfully misspent youth, and the prospect of ironing out the remaining glitches is exciting. Keep up the good work people, I wish I was clever enough to assist.

With luck, due to the miserable state of the global economy, those hindered by the inconvenience of a "real" job may soon be relieved of their terrible burden.
 
Last edited by a moderator:
TitanUranus said:
What's the number of your car and where do you live? Also, if you hear a smashing sound and a car alarm at 2am, just shut your eyes and go back to sleep....
lol :lol:
 
Last edited by a moderator:
It works!!!!

Thanks a bunch, notaz! :)

You have the eternal gratitude of me and all Pandora owning Amiga fans.
 
Gfx scaling and vsync is working perfectly with this modified SDL. Thanks again for your help, Notaz.

Now I have one last function wish.

Could you please implement the following functionality (if it's possible) - and provide a system call like this:

./op_fb_scale_sdlsurface_part <size of the sdl surface part> <size to be upscaled to>

I want to be able to have for example an sdl surface with the size 320x262 pixels, but have the framebuffer only display a defined part of this surface (for example only the first 320x200 pixels of it) and upscale (and output) it to a defined size.
And I'd need to be able to call this multiple times (to change to different resolutions).

So that this call:

./op_fb_scale_sdlsurface_part 320x200 768x480

would automatically take the rectangle [0,0,320,200] of the currently used sdl surface (which of course needs to be greater than 320x200 - or at least the same size) and upscale it to use 768x480 pixels of the Pandora's screen.

and a later call:

./op_fb_scale_sdlsurface_part 320x256 600x480

would then upscale the rectangle [0,0,320,256] to the "new framebuffer output size" of 600x480 pixels.

For UAE4All I'd only always need a rectangle starting from (0,0) to (320,xxx) size.
To make this even more generally useful the function could also be like this:

./op_fb_scale_sdlsurface_part X-Y-W-H <output framebuffer upscale size> (X/Y: starting pixel in sdl surface, W/H: width&height of rectangle to be upscaled)

so that ./op_fb_scale_sdlsurface_part 50-40-200-100 640x480 would take the rectangle from (50,40) to (249,139) of the sdl surface and display it in 4:3 format at 640x480 on our Pandora.

Instead of a system call of course a C-function would be as good (or even better).


Is this possible to implement? And, if yes, are you willing to do this?
 
This is going to be awesome for UAE4ALL, cant wait for screen scaling change on the fly!

Thanks both Notaz and John!! ;)
 
Hi, I got a problem:
I already implemented this into a pnd and it works, but with another program, it just says No available videodevice, when launching the app.

I did the SDL_Init as proposed by sebt3 some posts before, but nothing seems to help.
Without this modded sdl, it works windowed and fullscreen in 800x600.

Any ideas?
 
Sorry for lack of action here, but I'm busy with other stuff, including some painful "reallife" issues.

Also, unfortunately, I'm real SDL hater so it's hard to schedule some cycles for this project. My todo list for various projects has enough work for something like 10 years now :(
 
Back
Top