disable buttons in XMB menu
disable buttons in XMB menu
I am making a prx plugin and I want to disable psp buttons in XMB menu (like the VSH menu), they would work just in my prx plugin. How to do that?
Pragramming with:
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
It calls vshCtrlReadBufferPositive. It can be hooked with a syscall patch. Or by patching the import call directly. Syscall patch is easier.
There are probably other methods but the advantage of hooking this function is that you can use the value it returns to detect key presses for your plugin. The XMB will call it continuously, so just use the pad data from the call, and make it zero after you're done so that the XMB will not respond to buttons. Your plugin will not have the overhead of its own button reading loop.
There are probably other methods but the advantage of hooking this function is that you can use the value it returns to detect key presses for your plugin. The XMB will call it continuously, so just use the pad data from the call, and make it zero after you're done so that the XMB will not respond to buttons. Your plugin will not have the overhead of its own button reading loop.
Don't call the function! I mean that the XMB calls vshCtrlReadBufferPositive to read buttons. If you hook that function, and make the paddata parameter 0 it will not receive any button presses. And you can use the value before you make it zero in your own program to read the buttons instead of having a separate sceCtrlReadBufferPositive.hotter wrote:calling sceCtrlReadBufferPositive doesnt help when I call another function, for example delete file. Buttons works in XMB menu because delete file function take too long time... :(
Learn how to hook functions with syscall patch. Look at iop.prx source.
-
- Posts: 328
- Joined: Sun Jun 03, 2007 10:05 pm
well I guess I need to include something like: #include <pspctrl_kernel.h>NoEffex wrote:void buttons_Set(void)
{
sceCtrlSetButtonMasks(0xFFFF, 1);
sceCtrlSetButtonMasks(0x10000, 2);
return;
}
void buttons_unSet(void)
{
sceCtrlSetButtonMasks(0x10000, 0);
sceCtrlSetButtonMasks(0xFFFF, 0);
return;
}
Set makes it so your proggy has access, unset sets it back.
but I get error:
main.c:(.text+0x4f8): undefined reference to `sceCtrl_driver_7CA723DC'
Do I need to add something in makefile?
Pragramming with:
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
That doesn't work reliably for everyone. If your loop is not 60 calls per second it will still receive button presses. I use sceCtrlReadBufferPositive in some older plugins and XMB still works.KickinAezz wrote:Simply use sceCtrlReadBufferPositive in the main loop it will disable XMB entirely until you switch back to sceCtrlPeekBufferPositive. (I remember when I did this long back... but it should work)
Heres a modified version of the iop.prx that comes with DC, this one can be unloaded.
http://ifile.it/brjox3v/iop_unloadable.zip
http://ifile.it/brjox3v/iop_unloadable.zip
well I tried my best and that is what I get:
But it doesnt work, could you help?
Code: Select all
//...
int vshReadButtons(SceCtrlData *pad_data, int count)
{
int k1 = pspSdkSetK1(0);
int level = sctrlKernelSetUserLevel(8);
sceCtrlReadBufferPositive(&pad, 1);
sctrlKernelSetUserLevel(level);
pspSdkSetK1(k1);
return 0;
}
int module_start(SceSize args, void *argp)
{
PatchSyscall = (void *)sctrlHENFindFunction("SystemControl", "SystemCtrlForKernel", 0x826668E9);
if (!PatchSyscall)
{
PatchSyscall = (void *)sctrlHENFindFunction("SystemControl", "SystemCtrlForKernel", 0x02BFCB5F);
if (!PatchSyscall)
{
asm("break\n");
return 1;
}
}
orgaddr=sctrlHENFindFunction("vshCtrlReadBufferPositive", "Idontknowwhattowritehere", 0xC6395C03);
PatchSyscall(orgaddr, vshReadButtons);
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
//...
return 0;
}
//...
Pragramming with:
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
Code: Select all
//...
int (* vshCtrlReadBufferPositive)(SceCtrlData *pad_data, int count);
int vshReadButtons(SceCtrlData *pad_data, int count)
{
int ret, intc;
ret = vshCtrlReadBufferPositive(pad_data, count);
if(ret <= 0)
{
return ret;
}
intc = pspSdkDisableInterrupts();
//your program's button handling goes here. this function will be called automatically by the xmb.
if (pad_data.Buttons & PSP_CTRL_CIRCLE) //etc
{
//do your stuff for the buttons
}
//zero it after use so xmb will not respond
pad_data.Buttons = 0;
pspSdkEnableInterrupts(intc);
return ret;
}
int module_start(SceSize args, void *argp)
{
PatchSyscall = (void *)sctrlHENFindFunction("SystemControl", "SystemCtrlForKernel", 0x826668E9);
if (!PatchSyscall)
{
PatchSyscall = (void *)sctrlHENFindFunction("SystemControl", "SystemCtrlForKernel", 0x02BFCB5F);
if (!PatchSyscall)
{
asm("break\n");
return 1;
}
}
orgaddr=sctrlHENFindFunction("sceVshBridge_Driver", "sceVshBridge", 0xC6395C03);
vshCtrlReadBufferPositive = (void *)orgaddr;
PatchSyscall(orgaddr, vshReadButtons);
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
//...
return 0;
}
//...
This method will not increase CPU usage a lot because there needn't be a main loop to read the controls.
Also this method will not break the M33 VSHMenu. If VSHMenu is opened, your plugin will not receive input until the VSHMenu is closed.
well with some changes this code compiles but on psp it still dont work :(
It looks like function havent been patched because XMB still recave buttons ant my functions doesnt get buttons pressed.
It should disable XMB buttons from startup if I add prx to seplugins\vsh.txt and enable it, yes?
what could be wrong? :(
It looks like function havent been patched because XMB still recave buttons ant my functions doesnt get buttons pressed.
It should disable XMB buttons from startup if I add prx to seplugins\vsh.txt and enable it, yes?
what could be wrong? :(
Pragramming with:
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
You should wait for vshbridge to load before hooking.
Code: Select all
//globals
int OnModuleStart(SceModule2 *mod);
STMOD_HANDLER previous = NULL;
...
...
int OnModuleStart(SceModule2 *mod)
{
if (strcmp(mod->modname, "sceVshBridge_Driver") == 0)
{
orgaddr=sctrlHENFindFunction("sceVshBridge_Driver", "sceVshBridge", 0xC6395C03);
vshCtrlReadBufferPositive = (void *)orgaddr;
PatchSyscall(orgaddr, vshReadButtons);
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
}
if (!previous)
return 0;
return previous(mod);
}
int module_start(SceSize args, void *argp)
{
PatchSyscall = (void *)sctrlHENFindFunction("SystemControl", "SystemCtrlForKernel", 0x826668E9);
if (!PatchSyscall)
{
PatchSyscall = (void *)sctrlHENFindFunction("SystemControl", "SystemCtrlForKernel", 0x02BFCB5F);
if (!PatchSyscall)
{
asm("break\n");
return 1;
}
}
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
previous = sctrlHENSetStartModuleHandler(OnModuleStart); //add this
//...
return 0;
}
well now it disables buttons on start up but my program dont get them but I still trying to make it work.
I guess I need to include something because I get error:
error: expected '=', ',', ';', 'asm' or '__attribute__' before 'previous'
on this line:
STMOD_HANDLER previous = NULL;
I guess I need to include something because I get error:
error: expected '=', ',', ';', 'asm' or '__attribute__' before 'previous'
on this line:
STMOD_HANDLER previous = NULL;
Pragramming with:
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
I searched but I didnt find M33SDK... What if I will remove that variable?
This is edited code:
My program compiles. My functions gets buttons pushed but when I need to disable XMB menu buttons they are not disabled :( I guess I am doing something wrong in vshReadButtons function no?
This is edited code:
Code: Select all
void (* PatchSyscall)(u32 funcaddr, void *newfunc);
int (* vshCtrlReadBufferPositive)(SceCtrlData *pad_data, int count);
int OnModuleStart(SceModule2 *mod);
u32 orgaddr;
SceCtrlData pad;
int vshReadButtons(SceCtrlData *pad_data, int count)
{
int ret, intc;
ret = vshCtrlReadBufferPositive(pad_data, count);
if(ret <= 0)
{
return ret;
}
intc = pspSdkDisableInterrupts();
pad = *pad_data;
if (pad.Buttons & PSP_CTRL_CIRCLE)
{
//my menu on/off
if(a == 0){ a = 1; }
else{ a = 0; }
}
//if my menu on block buttons
if(a == 1)
{
pad.Buttons = 0;
}
pad_data = &pad;
pspSdkEnableInterrupts(intc);
return ret;
}
int OnModuleStart(SceModule2 *mod)
{
if (strcmp(mod->modname, "sceVshBridge_Driver") == 0)
{
orgaddr=sctrlHENFindFunction("sceVshBridge_Driver", "sceVshBridge", 0xC6395C03);
vshCtrlReadBufferPositive = (void *)orgaddr;
PatchSyscall(orgaddr, vshReadButtons);
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
}
}
int module_start(SceSize args, void *argp)
{
PatchSyscall = (void *)sctrlHENFindFunction("SystemControl", "SystemCtrlForKernel", 0x826668E9);
if (!PatchSyscall)
{
PatchSyscall = (void *)sctrlHENFindFunction("SystemControl", "SystemCtrlForKernel", 0x02BFCB5F);
if (!PatchSyscall)
{
asm("break\n");
return 1;
}
}
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
sctrlHENSetStartModuleHandler(OnModuleStart);
//...
return 0;
}
int module_stop(SceSize args, void *argp)
{
PatchSyscall((u32)vshReadButtons, (void *)orgaddr);
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
return 0;
}
Pragramming with:
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
You should directly use the value in pad_data. Since its a pointer, referencing it like the first element of an array pad_data[0] will give you the actual value.
You MUST include the previous pointer or it will break other plugins that hook module start, and possibly break M33 patches. The M33SDK comes in the 4.01M33 package.
You MUST include the previous pointer or it will break other plugins that hook module start, and possibly break M33 patches. The M33SDK comes in the 4.01M33 package.
Code: Select all
STMOD_HANDLER previous = NULL;
...
...
int OnModuleStart(SceModule2 *mod)
{
...
...
if (!previous)
return 0;
return previous(mod);
}
Code: Select all
int vshReadButtons(SceCtrlData *pad_data, int count)
{
int ret, intc;
ret = vshCtrlReadBufferPositive(pad_data, count);
if(ret <= 0)
{
return ret;
}
intc = pspSdkDisableInterrupts();
if (pad_data[0].Buttons & PSP_CTRL_CIRCLE)
{
//my menu on/off
if(a == 0){ a = 1; }
else{ a = 0; }
}
//if my menu on block buttons
if(a == 1)
{
pad_data[0].Buttons = 0;
}
pspSdkEnableInterrupts(intc);
return ret;
}
It is working!!! almost :D
now the buttons are disabled in XMB when my menu is on so its good, but the same error with "previous" variable.
now the buttons are disabled in XMB when my menu is on so its good, but the same error with "previous" variable.
Last edited by hotter on Tue Mar 24, 2009 3:29 pm, edited 2 times in total.
Pragramming with:
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
I added this:
and now I guess everything is working good!
Thx for help very much :)
Code: Select all
typedef int (* STMOD_HANDLER)(SceModule2 *);
Thx for help very much :)
Pragramming with:
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
Microsoft Visual C 2008 + pspsdk MINPSPW 0.8.10
-
- Posts: 1
- Joined: Thu Jun 11, 2009 8:31 am
I cant get this code to work
Code: Select all
int vshReadButtons(SceCtrlData *pad_data, int count)
{
int ret, intc;
ret = vshCtrlReadBufferPositive(pad_data, count);
if(ret <= 0)
{
return ret;
}
intc = pspSdkDisableInterrupts();
pad_data[0].Buttons = 0;
pspSdkEnableInterrupts(intc);
return ret;
}
int OnModuleStart(SceModule2 *mod)
{
if (strcmp(mod->modname, "sceVshBridge_Driver") == 0)
{
orgaddr=sctrlHENFindFunction("sceVshBridge_Driver", "sceVshBridge", 0xC6395C03);
vshCtrlReadBufferPositive = (void *)orgaddr;
PatchSyscall(orgaddr, vshReadButtons);
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
}
if (!previous)
return 0;
return previous(mod);
}
int module_start(SceSize args, void *argp)
{
sceCtrlSetButtonMasks(0x001000, 1);
PatchSyscall = (void *)sctrlHENFindFunction("SystemControl", "SystemCtrlForKernel", 0x826668E9);
if (!PatchSyscall)
{
PatchSyscall = (void *)sctrlHENFindFunction("SystemControl", "SystemCtrlForKernel", 0x02BFCB5F);
if (!PatchSyscall)
{
asm("break\n");
return 1;
}
}
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
sctrlHENSetStartModuleHandler(OnModuleStart);
return 0;
}
int module_stop(SceSize args, void *argp)
{
PatchSyscall((u32)vshReadButtons, (void *)orgaddr);
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
return 0;
}
Re: I cant get this code to work
Code: Select all
#include <pspsdk.h>
#include <pspctrl.h>
#include <pspkernel.h>
#include <systemctrl.h>
#include <string.h>
PSP_MODULE_INFO("myHold", 0x1000, 1, 1);
STMOD_HANDLER previous = NULL;
void (* PatchSyscall)(u32 funcaddr, void *newfunc);
int (* vshCtrlReadBufferPositive)(SceCtrlData *pad_data, int count);
int OnModuleStart(SceModule2 *mod);
u32 orgaddr;
SceCtrlData pad;
int a;
unsigned int paddata_old;
int vshReadButtons(SceCtrlData *pad_data, int count)
{
int ret, intc;
ret = vshCtrlReadBufferPositive(pad_data, count);
if(ret <= 0)
{
return ret;
}
intc = pspSdkDisableInterrupts();
if(paddata_old != pad_data[0].Buttons)
{
// simultaneously hotkey
// if( (pad_data[0].Buttons & PSP_CTRL_VOLUP) && (pad_data[0].Buttons & PSP_CTRL_VOLDOWN) )
if(pad_data[0].Buttons & PSP_CTRL_NOTE)
{
if(a == 0) { a = 1; }
else { a = 0; }
}
}
paddata_old = pad_data[0].Buttons;
if(a == 1)
{
pad_data[0].Buttons = 0;
}
pspSdkEnableInterrupts(intc);
return ret;
}
int OnModuleStart(SceModule2 *mod)
{
if (strcmp(mod->modname, "sceVshBridge_Driver") == 0)
{
orgaddr=sctrlHENFindFunction("sceVshBridge_Driver", "sceVshBridge", 0xC6395C03);
vshCtrlReadBufferPositive = (void *)orgaddr;
PatchSyscall(orgaddr, vshReadButtons);
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
}
if (!previous) return 0;
return previous(mod);
}
int module_start(SceSize args, void *argp)
{
PatchSyscall = (void *)sctrlHENFindFunction("SystemControl", "SystemCtrlForKernel", 0x826668E9);
if (!PatchSyscall)
{
PatchSyscall = (void *)sctrlHENFindFunction("SystemControl", "SystemCtrlForKernel", 0x02BFCB5F);
if (!PatchSyscall)
{
asm("break\n");
return 1;
}
}
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
previous = sctrlHENSetStartModuleHandler(OnModuleStart);
return 0;
}
int module_stop(SceSize args, void *argp)
{
PatchSyscall((u32)vshReadButtons, (void *)orgaddr);
sceKernelDcacheWritebackAll();
sceKernelIcacheClearAll();
return 0;
}
Code: Select all
#Makefile
TARGET = myHold
OBJS = myHold.o
BUILD_PRX = 1
PRX_EXPORTS =
USE_KERNEL_LIBC = 1
USE_KERNEL_LIBS = 1
INCDIR =
CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
LIBDIR =
LDFLAGS = -mno-crt0 -nostartfiles
LIBS = -lpspkubridge -lpspsystemctrl_user -lpspsystemctrl_kernel
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
I edited post, and this code is fully working. Thanks Torch.
Last edited by hyeokje on Sat Aug 08, 2009 2:01 pm, edited 4 times in total.