Adding TV support to PSPGL and SDL - Updated last: 20081022

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Adding TV support to PSPGL and SDL - Updated last: 20081022

Post by J.F. »

I have recently been doing some work on Duke Nukem 3D for the PSP. I decided to look into adding TV support to it. However, it uses SDL, so what I was really looking into was TV support in SDL. However, it REALLY uses OpenGL through SDL, so I was REALLY looking into TV support in PSPGL. With that in mind, I looked into making the fewest changes to support TV out on the Slim in PSPGL.

The proper way to do it seemed to be to add displays to the list, the only current one being EGL_DEFAULT_DISPLAY (0). I've defined two more: EGL_INTERLACED_DISPLAY, and EGL_PROGRESSIVE_DISPLAY. Default is the normal 480x272 LCD display. Interlaced is for composite or component-interlaced output. Progressive is for component-progressive output. If you ask for interlaced or progressive and you don't have the dve manager or a cable or the wrong cable, you get a return of EGL_NO_DISPLAY, otherwise you get "LCD ", "LCDV" (which is just LCD with the addition of the DVE manager), "LACED", or "PROG". In case you were wondering, default used to return "foo" as the display.

So an example would be:

Code: Select all

	EGLCHK(dpy = eglGetDisplay(EGL_PROGRESSIVE_DISPLAY));
	if (dpy == (EGLDisplay)EGL_NO_DISPLAY)
		return 0;
	EGLCHK(eglInitialize(dpy, NULL, NULL));

	psp_log("EGL vendor \"%s\"\n", eglQueryString(dpy, EGL_VENDOR));
	psp_log("EGL version \"%s\"\n", eglQueryString(dpy, EGL_VERSION));
	psp_log("EGL extensions \"%s\"\n", eglQueryString(dpy, EGL_EXTENSIONS));

	EGLCHK(eglChooseConfig(dpy, attrib_list, &config, 1, &num_configs));

	if (num_configs == 0) {
		__pspgl_log("eglChooseConfig returned 0 configurations");
		return 0;
	}

	psp_log("eglChooseConfige() returned config 0x%04x\n", (unsigned int) config);

	EGLCHK(ctx = eglCreateContext(dpy, config, NULL, NULL));
	EGLCHK(surface = eglCreateWindowSurface(dpy, config, 0, NULL));
	EGLCHK(eglMakeCurrent(dpy, surface, surface, ctx));

	EGLCHK(eglGetConfigAttrib(dpy, config, EGL_WIDTH, &width));
	EGLCHK(eglGetConfigAttrib(dpy, config, EGL_HEIGHT, &height));
Of course, I also had to add the ability to switch to TV in glut. glutInit() now defaults to EGL_DEFAULT_DISPLAY. If you wish to use a TV mode, I currently require you to use glutInitWindowSize(). If you pass a height of 503, you get EGL_INTERLACED_DISPLAY, and if you pass a height of 480, you get EGL_PROGRESSIVE_DISPLAY. Since they can fail due to lack of the dve manager prx or cable, you really should check that you get a window ID from glutCreateWindow(). If it succeeds, you get a 1 back (since allocated ID ranges start at 1, and we only support one window). If it fails, you get 0. This is actually proper, unlike the current glutCreateWindow() return (always 0). So an example of using glut would be:

Code: Select all

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
	glutInitWindowSize(720, 480);
	if (!glutCreateWindow( __FILE__ ))
		return 0;
Here's the first test results... the eglCube demo done for LCD, interlaced, and progressive. I've tested all but composite out (since I don't have a composite cable... someone please test that for me). Note - the tests here don't have the error checking... if you don't have the dvemgr.prx or the cable, it's not going to work. Sorry, didn't add that in until I'd already made this post and the archives to go with it. All future stuff in the thread here will have the error checking.

http://www.mediafire.com/download.php?15lhaqwxl4m

A couple things you'll notice right off: progressive seems to be just as fast as the LCD; second, interlaced is clearly slower. It can't be helped. You have to render the display, then copy the alternate fields into the proper place in the frame buffer for an interlaced output. Because of this copying, I plan to enable the single buffer mode inside EGL so that you can just use the front buffer. It currently uses double buffering, even though it doesn't matter due to the copy. The frame buffer for the interlaced output is currently allocated from heap memory so that you don't have a buffer you can't render to cluttering up the vram. Would it be faster to keep it in vram? I might have to experiment with that sometime.

So if some folks would try this out the demos and give a little feedback, I can move on to providing the libs/includes and altered source. After PSPGL seems okay, I plan to go back to looking at TV support in SDL.
Last edited by J.F. on Thu Oct 23, 2008 2:11 pm, edited 3 times in total.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Okay, here's the current code for pspgl. The dve manager in the tv-stuff directory has the modification I made some time back to set the edram to 4MB when the TV out is activated. This allows you to easily do TV resolution rendering as you now have space in the edram-vram for multiple (32 bit) buffers. You can see this in the eglcube test I posted yesterday.

http://www.mediafire.com/download.php?jekrwx3mtzl

Now that I think about it, I should probably set the edram to 4 MB simply is you're on a Slim, regardless of the TV out. That would allow more space for textures and whatnot in LCD mode as well. I'll do that for the next version.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Here's example 08 (SpecialFX) from LTE in 720x480 progressive.
http://www.mediafire.com/download.php?105h0g3wk2l

Example 02 doesn't work, even on LCD, but I suspect it's more about the change from the old PSPGL that came with LTE than any changes I made.

EDIT: It has something to do with the levels... I switched the level back to the one that comes with LTE and it works fine. Also, the Q3Test example is the same way: works with their level data, but not mine even though it works with mine on the old PSPGL. Very odd.

Lemme tell you - Q3 style games are very playable on the TV just from looking at how the LTE examples run. At least for progressive. :)

Here's the LTE Q3Test set for 720x480 progressive.
http://www.mediafire.com/download.php?xfmtvjgy0ei
adrahil
Posts: 274
Joined: Thu Mar 16, 2006 1:55 am

Post by adrahil »

Good job :) I'll test later, but it might make me switch from GU to PSPGL :P
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

By the way, I think I know why some of the LTE examples don't work - LTE uses knowledge of the INTERNAL structures of PSPGL. The internal includes for the old PSPGL they used are quite a bit different from the latest, and you simply can't copy over the newer includes. I'm surprised LTE works with a newer PSPGL at all, much less to the extent it does. :)

So we need to wait for the much delayed update to LTE from the devs over there. Since it hasn't been released yet, maybe they can work in support for this version of PSPGL. In the meantime, I'm going to move on. I think the working LTE examples show my changes are working.

EDIT: One last thing I checked with LTE - interlaced mode. Here's the collision example in interlaced mode. It's not nearly as bad as I thought it would be.

http://www.mediafire.com/download.php?chmntuzpbch
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Okay, I've added TV support to SDL. Here's a first test app to get some feedback. One thing - this version has a bug with interlaced... I'll look at that tomorrow. For now, stick to LCD and non-interlaced TV.

To make things as simple as possible, I added a preference manager to the SDL video init - when you start the app, hold the TRIANGLE button to get the preference manager. If you don't have TV, it only asks if you want widescreen or not. That gives you 480x272 or 364x272 (software surface) - great for playing Duke Nukem 3D at the correct aspect ratio. If you have TV, it asks if you wish to use the TV. If you have the component cable, it then asks if you want to use interlaced. It then asks if you have a 16:9 TV. Then it finally asks if you want widescreen. Hence, the resolutions available for TV based on your choices are wider. Again, those are software surfaces. Hardware surfaces restricts you to 480x272 or 720x480.

It writes the prefs to a text file called SDL_VID_PREFS. If you don't hold down the TRI on start, it simply uses the settings in the pref file (or LCD WIDE if the file isn't present). So the default action is just like SDL used to be - using the LCD at 480x272. If you are wondering why the TV looks blocky, Duke3D only renders at 320x200. That is then stretched by SDL to whatever size the screen is. It's not very noticeable at 480x272, but rather noticeable at 688x448 (4:3 TV and not widescreen). Obviously, SDL apps could be written to use higher resolutions when the TV is available. SDL returns the video mode as 720x480 when you select TV out, so if the app actually checks (Duke3D doesn't), it can take advantage of the higher res.

I also think I've fixed a LONG outstanding bug in the PSP SDL video driver - the stretch blit uses integer vertex coords, but the amount of stretching is rarely even (480 was coincidentally an even multiple of 320, so Duke3D didn't show the bug until I started allowing for modes like 364 and 688). Internally, the GU apparently rounds the coords when scaling the texture to the destination. This left a blank vertical line in the dest pixmap every time you hit the rounding point. I added a little rounding to the dest coord (3/4) to try to compensate. It seems to work well with the various sizes I added for software surfaces.

Note: this version of Duke3D still has the bug in the music, and you can crash looking in mirrors. I haven't looked at those - I just wanted to make a nice test of the TV code in SDL.

http://www.mediafire.com/download.php?doacxznqt0y
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Okay, here's a version of Duke3D with interlace working too. Now also linking my SDL code. The only things to change were SDL_pspvideo.c, SDL_pspvideo.h, and Makefile (needed to add pspDveManager.o). Because I use the PSP utility dialog for the prefs, you need to link your SDL app with libpsputility.

Duke3D: http://www.mediafire.com/download.php?mvzzye0amqi
SDL: http://www.mediafire.com/download.php?oizmzy5zimh
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

The previous code DIDN'T default to LCD when no prefs file was found and a cable was plugged in - it instead defaulted to the TV. I've corrected that. Here's the new SDL arc.

http://www.mediafire.com/download.php?qgbwz1nprat

I also recompiled Jump 'n Bump with the new SDL. Here's the arc for that. Note that I'm just using a makeshift ICON0 since the original converter didn't include it with the source. Jump 'n Bump uses a 400x256 display, which is then stretched to the final display resolution by SDL.

http://www.mediafire.com/download.php?22zzjdjhbyp
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Okay, new archive with the latest bug fixes. I've gotten more SDL stuff to work properly, and maybe stomped another bug in the old code.

BIG NEWS!!!!!!!

I rewrote the SDL_RateSLOW function on the audio converter! Now it's nearly as fast as the "fast" converters. So you don't get a hiccup when a sound is played in JFDuke3D or ROTT when using slow resampling anymore. Now there's no reason not to use this. :)

SDL_tv3.zip
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

JF, can you post your changes as individual patches for review so we can incorpotate them into svn?

As for the SDL_VID_PREFS stuff.. We've tried to add configuration stuff to SDL in the past, with features like joystick button remapping, optional mouse pointer emulation, and video mode selection being chosen at runtime through environment variables. The idea at the time was that a ported application could just add a slew of setenv() at the beginning to set things up, therefore reducing changes elsewhere in the application code. It was decided that this was a bit silly and "elsewhere in the application code" was really the right place to make PSP-specific changes. I think the only one of these environment variables that has survived is SDL_ASPECT_RATIO.

However, the choice for TV-out video mode actually is something that different users might want to configure at runtime, and so it might not be a bad idea to add a configuration option like you've done. Putting a preferences screen directly in SDL seems a bit out of place (it's a graphics library, actual user interaction should probably be handled in application code), but maybe others disagree with that. Anyway, my only immediate complailnt would be that the file should be named something more reasonable like sdl.ini and given a formal structure that we can extend with other things if the need arises.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Yeah, I'll get some patches posted today sometime.

As for embedding the prefs into SDL, the majority of SDL programs don't bother to query SDL, they simply ask for a fixed mode and count on SDL to massage it into something the system can handle. It would require major rewriting of most programs to add TV support. With the prefs in SDL, it's FREE. The programmer doesn't have to do ANYTHING other than recompile with the new SDL. If they want, they can init the video and then query SDL and do their own selection, but how many programmers are going to do that? The occasional odd-ball. :)

Besides, if the user isn't holding TRIANGLE when the video init occurs, they'll never even see or be affected by the prefs. We can also go back to your idea on the SDL prefs and add more if we want. I think it's actually a good idea as it makes converting programs easier. No need for trying to figure out how to make a PSP specific menu - just recompile. Remember that devs are lazy son's of b-tches. Given the choice of using a built-in prefs or being forced to make their own UI, they'll take the former 99 times out of 100. Look at how many SDL programs for the PSP actually have PSP specific UIs... none! :)
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Okay, here's the patches. I made sure I had the latest checkout of SDL and pspgl when I made these. I then applied them to a clean checkout of SDL and pspgl, then compiled and installed both, then compiled some programs that used each of them to check. Seems to be working for me.

http://www.mediafire.com/download.php?nm2ynyxv1tg

Note - compile pspgl first, then SDL. SDL is dependent to pspgl. Also, in looking at the diff files, I noticed that some replaced lines appear identical... I have my editor set to strip extraneous white space, so that's probably the difference. :)

Further note - it's clear than no one has made the tests in pspgl in a LONG time. They seem to be meant to be run from psplink. I made a sh script to generate the raw image files as the lines in the main makefile doesn't work in my Ubuntu setup. I then made little REGULAR makefiles for a couple of the tests, and altered the psp-setup.c for a modern SDK/toolchain. So for example, you generate the raws with the script, then make -f makefile.eglcube to get an eboot for the eglcube test app. The diff file for pspgl makes all those changes. That way you can actually test pspgl. :D
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

New update! I had a bug in the double-buffering that Zack and Wally ran into. I've corrected the bug, cleaned up a little bit, and added the "seamless" blitting I discovered while working on the video for Basilisk II. Try this out and see how it works.

http://www.mediafire.com/download.php?eqho1wocd90
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Here's a zip with two patch files for those who don't want to download a big file. There's one for SDL and one for pspgl. The patch file for pspgl is the same as the last one, but it's still not in the repo, so I'm including it so you can do both at the same time.

http://www.mediafire.com/download.php?c0ynmyzn0zn
Post Reply