PDA

View Full Version : SDL Window on Mac OS



Mario Donick
05-01-2011, 05:20 PM
As already written in the compiler forum, I finally managed to compile, link and run my game on Mac OS X. The game has two output modes, a console mode where it runs in a 80x25 terminal, and a graphical mode using SDL.

The console mode works just fine, as does the SDL mode, as long as my game window is only 800x600 big.

When I try to open a 1024x768 window, the game crashes with an invalid floating point operation. I have isolated the error so far that I know that it occurs when I call IMG_LOAD:



procedure LoadImage_Back(n: ansistring);
begin
if fileexists(n) = True then
begin
backgroundGraph := IMG_LOAD(PChar(n))
end
else
begin
Writeln('ERROR: File ' + n + ' not found.');
Halt;
end;
end;


I call this procedure to load a background image for the appropriate window size, such as

LoadImage_Back('graphics/bg-1024.png');


Now, very funny it is that I can change this single line to

LoadImage_Back('graphics/bg-800.png');

in order to load the background image that is for 800x600 -- and here the game runs just fine (of course with a mis-sized background, but it runs).


Of course the file 'graphics/bg-1024.png' exists, and it's a simple .png file, as is the other. I then opened the file in the Mac OS preview program and saved it again -- since then everything runs fine, so I assume that either the .png was broken, or SDL_IMAGE for Mac OS has bugs.

No such problems on Windows and Linux. What is happening here?

code_glitch
05-01-2011, 05:32 PM
Now I use a combination of both Ubuntu (linux) and Win 7. And all I can say is that on both of these platofrms I have never encountered a single problem. Your problem sound quite perculiar. Could you please supply the Sdl_SetVideoMode() and render methods? Because an error in IMG_LOAD sounds unlikely, but I am aware that random stuff can occur in the setvideomode and render procedures...

Although, the following comes to mind: try sdl_init_everything when you call sdl_init(). You never know, there might be something there ;) It feels funny talking about SDL like this as I am making my transistion out of it at the moment couresty of Prometheus.

JSoftware
05-01-2011, 05:39 PM
As a test, try to include the math unit and call SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide,exOverflow, exUnderflow, exPrecision]); before you use any SDL functions

Some C libraries depend on certain FPU behavior. Most don't want exceptions when they divide by zero for example, which FPC doesn't mask. Sounds like that could be your problem in this case

Mario Donick
05-01-2011, 05:40 PM
Indeed, on Windows XP, Windows 7, Windows Vista and Ubuntu it works fine for me, too.

I use

SDL_SETVIDEOMODE(1024, 768, 24, SDL_HWSURFACE + FullscreenFlag)

This works all the time and the game now runs nearly perfectly on MacOS -- except with that particular image file.


One thing, though: I've got an option to switch between windowed mode and full screen. This option works fine under Windows and Linux, but leads to another Invalid Floating Point error:



UseFullscreen := BoolToggle(UseFullscreen); // reverts a boolean value
SaveConfig; // saves game config

SDL_FREESURFACE(screen); // first free existing video surface, to prevent memory leaks when using screen again

if UseFullScreen = True then
FullscreenFlag := SDL_Fullscreen
else
FullscreenFlag := 0;
SDL_QUIT;

delay(50);

SDL_INIT(SDL_INIT_VIDEO);
SDL_ENABLEUNICODE(1);
SDL_ENABLEKEYREPEAT(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);

SDL_WM_SETCAPTION('LambdaRogue ' + strVersion, 'LambdaRogue ' + strVersion);

if UseHiRes = False then
screen := SDL_SETVIDEOMODE(800, 600, 24, SDL_HWSURFACE + FullscreenFlag)
else
screen := SDL_SETVIDEOMODE(1024, 768, 24, SDL_HWSURFACE + FullscreenFlag);


It crashes directly before SDL_SETVIDEOMODE.

What's wrong here?

code_glitch
05-01-2011, 05:49 PM
I can;t help noticing you use + for the flags... I have a habit of inserting {$Mode Delphi} or {$Mode ObjFpc} and using OR instead. Don't know whether there is any difference though.

At this stage I would try SW_SURFACE as they are supposedly more stable (doubt it though), when calling sdl_init try sdl_init_everything just to be on the safe side, leave out the unicode line and also remove that sadl_quit line perhaps. I wouldn't recommend leaving it like that but what I'm trying to say is do a debug launch of the app - ie. only the bare necessities: sdl_init and videomode. See if that changes anything. If it does it might be down to the order you are doing things.

Otherwise might I suggest:



if Screen <> Nil then
sdl_freesurfce(screen);
Oh, and where it says
FullScreenFlag := 0; change it to
FullScreenFlag := NilI hope that works ;)

oh, and as a last resort in case something seriously weird is happening try setting the colour depth to that of your window manager - thats pretty much everyhting I can think of without pulling out the Docs and scrutinising :p

Mario Donick
05-01-2011, 05:51 PM
As a test, try to include the math unit and call SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide,exOverflow, exUnderflow, exPrecision]); before you use any SDL functions

This worked. Can I simply keep it that way, or do I need to find a more clean way to cope with that?

Mario Donick
05-01-2011, 05:52 PM
Ah, thanks for the small hints regarding OR and nil instead 0. :)

Edit: Though "nil" does not work (got "Pointer" expected "LongWord", which makes sense).

code_glitch
05-01-2011, 05:59 PM
Ah yes, I feared that, I know there is a value like it other than 0 but couldn't remeber.. All these subtle differences. Glad your problem is solved though :) I have a small obsession with perfect looking code for some reason. It takes time but I find it worth it for some reason or other.

JSoftware
05-01-2011, 06:20 PM
You can keep it, I think, but you need to know what it means. Practically it means that when you work with floating point numbers it won't throw exceptions when you do something bad, like dividing by zero. In this case for example it'll return INF(infinity) instead of throwing an error

If it results in problems on other platforms just do some ifdefs around it for the platforms where you need it :)