[SOLVED] sceCtrlReadLatch() strange behavior

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

Moderators: cheriff, TyRaNiD

Post Reply
lgnr
Posts: 12
Joined: Thu Dec 17, 2009 2:57 am

[SOLVED] sceCtrlReadLatch() strange behavior

Post by lgnr »

It got a little bigger than i expected. I'll try to explain:
I was writing/learning with a controller homebrew to use with some WinAPI stuff. That turned out to be really fun and useful. Here starts my problem:
I have used SceCtrlData objects and sceCtrlReadBufferPositive() to get key presses.
Everything was going great untill i felt the need to use key releases events. I know i could have just used sceCtrlReadBufferNegative(), but another solution seemed more easy and usefull, since it gets just ONE key press, which is what I'm looking for. So in one of the topics here, someone suggested using SceCtrlLatch and sceCtrlReadLatch(), which is great. Everything worked out. Its all working. Only problem is: PSP freezes on program exit.

Here the main loop from main.c:

Code: Select all

while(1)
	{		
		if((button = get_button(&ispressed))) 
		{
			if(button == PSP_CTRL_SELECT) 
			{
				//Do some stuff
			}
					
			else
			{ 
                                //----> This also works
				printf("\nPressed = %d\n", ispressed);
				
                                //-----> Send info to socket on server - Its working
				
                                //A dumb try to avoid freezing
				sleep(2000);
			}
		}
  }
And here is the get_button function:

Code: Select all

int get_button(int *ispressed)
{
	SceCtrlLatch latch; 
   	sceCtrlSetSamplingCycle(0); 
   	sceCtrlSetSamplingMode(PSP_CTRL_MODE_DIGITAL);
	
	while(1)
	{
		//Read Pad
		sceCtrlReadLatch(&latch);

		if(latch.uiMake)
		{
			//Means a button was pressed
			*ispressed = 1;

			if(latch.uiMake & PSP_CTRL_CROSS) return PSP_CTRL_CROSS;
			else if(latch.uiMake & PSP_CTRL_CIRCLE) return PSP_CTRL_CIRCLE;
			else if(latch.uiMake & PSP_CTRL_SQUARE) return PSP_CTRL_SQUARE;
			else if(latch.uiMake & PSP_CTRL_TRIANGLE) return PSP_CTRL_TRIANGLE;
			else if(latch.uiMake & PSP_CTRL_START) return PSP_CTRL_START;
			else if(latch.uiMake & PSP_CTRL_SELECT) return PSP_CTRL_SELECT;
			else if(latch.uiMake & PSP_CTRL_LTRIGGER) return PSP_CTRL_LTRIGGER;
			else if(latch.uiMake & PSP_CTRL_RTRIGGER) return PSP_CTRL_RTRIGGER;
			else if(latch.uiMake & PSP_CTRL_UP) return PSP_CTRL_UP;
			else if(latch.uiMake & PSP_CTRL_DOWN) return PSP_CTRL_DOWN;	
			else if(latch.uiMake & PSP_CTRL_LEFT) return PSP_CTRL_LEFT;
			else if(latch.uiMake & PSP_CTRL_RIGHT) return PSP_CTRL_RIGHT;
			//And if a useless button was pressed, return 0
			else return 0;

		}
		
		else if(latch.uiBreak)
		{
			//Means a button was relesead
			*ispressed = 0;
	
			if(latch.uiBreak & PSP_CTRL_CROSS) return PSP_CTRL_CROSS;
			else if(latch.uiBreak & PSP_CTRL_CIRCLE) return PSP_CTRL_CIRCLE;
			else if(latch.uiBreak & PSP_CTRL_SQUARE) return PSP_CTRL_SQUARE;
			else if(latch.uiBreak & PSP_CTRL_TRIANGLE) return PSP_CTRL_TRIANGLE;
			else if(latch.uiBreak & PSP_CTRL_START) return PSP_CTRL_START;
			else if(latch.uiBreak & PSP_CTRL_SELECT) return PSP_CTRL_SELECT;
			else if(latch.uiBreak & PSP_CTRL_LTRIGGER) return PSP_CTRL_LTRIGGER;
			else if(latch.uiBreak & PSP_CTRL_RTRIGGER) return PSP_CTRL_RTRIGGER;
			else if(latch.uiBreak & PSP_CTRL_UP) return PSP_CTRL_UP;
			else if(latch.uiBreak & PSP_CTRL_DOWN) return PSP_CTRL_DOWN;	
			else if(latch.uiBreak & PSP_CTRL_LEFT) return PSP_CTRL_LEFT;
			else if(latch.uiBreak & PSP_CTRL_RIGHT) return PSP_CTRL_RIGHT;
			//And if a useless button was released, return 0
			else return 0;
			
		}
	}
}
Summing up: everything is great untill the program quits. Then the PSP freezes and you have to force shutdown. As when you press the 'home' button the program is running the while(1) from the get_button() function, we can assume the problem is in the function, right? Can it have something to do with the 'event' of pressing the 'home' button? I'm really out of guesses.

Sorry for my bad English and thanks in advance. Also, others suggestions are encouraged. Thanks!
Last edited by lgnr on Tue Jan 26, 2010 11:10 am, edited 1 time in total.
Devun_06
Posts: 15
Joined: Sat Jun 17, 2006 7:01 pm

Post by Devun_06 »

If you get the home button, your code skips to send the information to the socket on a server, then waits a little while to avoid freezing. If you assume waiting will fix the problem, that means another thread must be running that isn't quite finished yet in some cases. If that's the case, use sceKernelDelayThread() and set it to wait long enough for the other thread to complete(I don't know what code is omitted).

If that's not the case, meaning that wait doesn't actually help any, and didn't before, then you need to, or should install the callbacks for the home key. If you do, I suggest you continue to ignore reading it since it'll be handled by the callback thread.

If you don't want to use that method, you need to create a method for reaching your application's final return statement. Call a break or a return if a certain case is met in your main's while loop. You're using an int for button checking, in C, anything above zero is true, so return -1 or lower for a special case, and manually handle the exit(this cannot be done if you have the callbacks setup).

The problem could be your code that's omitted.
lgnr
Posts: 12
Joined: Thu Dec 17, 2009 2:57 am

Post by lgnr »

Thanks for the reply. I'll try to handle the home button particularly. But what puzzles me, and what makes me think that the trouble is not with the rest of the code, is that it does NOT freeze with the sceCtrlReadBufferPositive().
I do not run other threads, so i guess thats not the reason.
Anyway, I was thinking that perhaps the problem is with the function. I mean, the functions runs on every key press, since it returns a value and calls the function again. And it creates a new SceCtrlLatch struct everytime.
I'll try to do something like

Code: Select all


else if(button == PSP_CTRL_HOME)
{
            //does nothins
}
...

I'll post here when I do, but I thought I might have any other evident problem. Again, what puzzles me is that it runs OK with the sceCtrlReadBufferPositive() and the SceCtrlData struct.
Thanks dude!
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

Add a sceDisplayWaitVblankStart() inside the loop. The syscon sends control packets at 60Hz anyway.

Use this instead of latch.

Code: Select all

prevButtons = 0;

while (1)
{
	sceCtrlReadBufferPositive(&newButtons, 1)
	if ((prevButtons^newButtons) & PSP_CTRL_CROSS)
	{
		if (newButtons & PSP_CTRL_CROSS)
			//make cross
		else
			//break cross
	}
	prevButtons = newButtons;
	sceDisplayWaitVblankStart();
}
Last edited by Torch on Tue Jan 26, 2010 6:03 am, edited 1 time in total.
Davee
Posts: 43
Joined: Mon Jun 22, 2009 3:58 am

Post by Davee »

Might wanna lookup a bit on structures there. :/
User avatar
Raphael
Posts: 646
Joined: Tue Jan 17, 2006 4:54 pm
Location: Germany
Contact:

Post by Raphael »

while(1)
There is the one and only reason why your program hangs up on exit. It has nothing to do with the *latch functions. Fix it and it will work.
<Don't push the river, it flows.>
http://wordpress.fx-world.org - my devblog
http://wiki.fx-world.org - VFPU documentation wiki

Alexander Berl
lgnr
Posts: 12
Joined: Thu Dec 17, 2009 2:57 am

Post by lgnr »

So just sceDisplayWaitVblankStart(); wont fix it?
Thanks y'all guys.
lgnr
Posts: 12
Joined: Thu Dec 17, 2009 2:57 am

Post by lgnr »

sceDisplayWaitVblankStart(); fixed it.
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

You should really only be using sceDisplayVblankStart() within your rendering loop when you're making a proper application. Its not required for sceCtrlReadBuffer* functions because they already delay internally to keep up with the sampling rate.

There's no need for a separate loop for reading buttons unless you specifically need high resolution buffered input independent of your game FPS.
Post Reply