Отлов нажатий специальных кнопок (громкость, яркость, ...)
Четвертый день я пытаюсь написать программку на PSP, которая могла бы отлавливать нажатия специальных клавиш снизу (кнопки громкости, регулирования экрана и т.д). Для примера, FuSa Gamepad успешно делает это. Дело в том, что эти кнопки можно прочитать только в режиме ядра. Можно сделать программу, работающую в режиме ядра, всего лишь указав флаг 0x1000 в информации модуля:
PSP_MODULE_INFO("Sample program", 0x1000, 1, 1);
И тогда эти кнопки действительно отлавливаются, но PSP намертво зависает и выключается при попытке выхода любым способом, или при установке колбеков.
Если посмотреть на Fusa Gamepad, можно заметить, что он загружает PRX-плагин. Если декомпилировать Fusa Gamepad и посмотреть в секцию moduleinfo, видно что EBOOT.PBP стартует в пользовательском режиме (0x0), а плагин в режиме ядра (0x1006). Выходит, эти кнопки отлавливает именно плагин.
Разобравшись с загрузкой плагинов и функций из него, сделал свой плагин и пытался разными отлавливать кнопки из него, но безуспешно. Вот исходник самой "игры" (main.c) и плагина (module.c)
main.c
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <pspsdk.h>
#include <pspctrl.h>
#include <string.h>
PSP_MODULE_INFO("PRXLOADER", 0x0, 1, 1);
/* Define the main thread's attribute value (optional) */
PSP_MAIN_THREAD_ATTR(0);
/* Define printf, just to make typing easier */
#define printf pspDebugScreenPrintf
/* Imported function */
void *getModuleInfo(void);
int plus(int a, int b);
int waitForX(void);
void kReadBuffer(SceCtrlData *pad_data, int count);
void kReadBuffer2(SceCtrlData *pad_data, int count);
void updatePadData(void);
SceCtrlData getPadData(void);
int main(void)
{
SceUID modid;
SceModule *mod;
SceCtrlData pad, pad2, pad3;
int i;
int ret;
int fd;
pspDebugScreenInit();
/* Start mymodule.prx and dump its information */
printf("\nStart my module\n");
modid = pspSdkLoadStartModule("ms0:/mymodule.prx", PSP_MEMORY_PARTITION_KERNEL);
printf("Module ID %08X\n", modid);
/* Let's test the module's exports */
printf("Module Info %p\n", getModuleInfo());
printf("plus(41, 92): %d\n", plus(41, 92));
printf("waitForX()... ");
i = waitForX();
printf("%08X\n", i);
printf("Press X to continue\n");
while(1) {
sceCtrlReadBufferPositive(&pad, 1);
if(pad.Buttons & PSP_CTRL_CROSS) break;
}
pspDebugScreenClear();
while(1) {
kReadBuffer(&pad, 1);
kReadBuffer2(&pad2, 1);
pspDebugScreenSetXY(0, 2);
updatePadData();
pad3 = getPadData();
printf("B1: %08X\nB2: %08X\nB3: %08X\nPress O to exit\n", pad.Buttons, pad2.Buttons, pad3.Buttons);
if(pad.Buttons & PSP_CTRL_CIRCLE)
break;
sceKernelDelayThread(100000);
}
printf("Exiting...");
sceKernelExitGame();
// sceKernelExitDeleteThread(0);
return 0;
}
module.c
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
#include <stdio.h>
PSP_MODULE_INFO("TESTPRX", 0x5006, 1, 0);
//PSP_MAIN_THREAD_ATTR(0);
SceCtrlData gpad = {0, 0x42, 0, 0, NULL};
#define WELCOME_MESSAGE "Hello from the PRX\n"
#define printf pspDebugScreenPrintf
int main(int argc, char **argv)
{
int i;
printf(WELCOME_MESSAGE);
for(i = 0; i < argc; i++)
{
printf("Arg %d: %s\n", i, argv[i]);
}
sceKernelSleepThread();
return 0;
}
/* Exported function returns the address of module_info */
void* getModuleInfo(void)
{
return (void *) &module_info;
}
int plus(int a, int b) {
return a+b;
}
void updatePadData(void) {
sceCtrlReadBufferPositive(&gpad, 1);
}
SceCtrlData getPadData(void) {
return gpad;
}
void kReadBuffer2(SceCtrlData *pad_data, int count) {
SceCtrlData pad;
sceCtrlReadBufferPositive(&pad, count);
*pad_data = pad;
return;
}
void kReadBuffer(SceCtrlData *pad_data, int count) {
sceCtrlReadBufferPositive(pad_data, count);
return;
}
int waitForX(void) {
SceCtrlData pad;
while(1) {
sceCtrlReadBufferPositive(&pad, 1);
if (pad.Buttons & PSP_CTRL_CROSS) break;
}
return 0;
}
int module_start(SceSize args, void *argp) {
return 0;
}
int module_stop(void) {
return 0;
}
Вот экспорты функций:
exports.exp
# Define the exports for the prx
PSP_BEGIN_EXPORTS
# These four lines are mandatory (although you can add other functions like module_stop)
# syslib is a psynonym for the single mandatory export.
PSP_EXPORT_START(syslib, 0, 0x8000)
PSP_EXPORT_FUNC_HASH(module_start)
PSP_EXPORT_VAR_HASH(module_info)
PSP_EXPORT_END
# Export our function
PSP_EXPORT_START(TESTPRX, 0, 0x4001)
PSP_EXPORT_FUNC_HASH(plus)
PSP_EXPORT_FUNC_HASH(getModuleInfo)
PSP_EXPORT_FUNC_HASH(waitForX)
PSP_EXPORT_FUNC_HASH(kReadBuffer)
PSP_EXPORT_FUNC_HASH(kReadBuffer2)
PSP_EXPORT_FUNC_HASH(getPadData)
PSP_EXPORT_FUNC_HASH(updatePadData)
PSP_EXPORT_END
PSP_END_EXPORTS
Как видно, я пытался ловить кнопки несколькими способами:
1) Обычная обертка над стандарттной функцией - работает так-же как в пользовательском режиме (не возвращает состояние специальных клавиш)
2) Функция которая считывает кнопки в локальную переменную и присваивает структуру параметру - всегда возвращает 0xDEADBEEF, видимо какая-то заглушка?
3) Пара функций, одна из них считывает кнопки в глобальную переменную, а вторая возвращает эту глобальную переменную. Эта глобальная переменная не изменяется вообще! (всегда возвращает значение 0x42 которым я ее проинициализировал)
Ну и еще эта функция waitForX() - мой эксперимент, из которого понятно, что я вообще не понимаю каким образом выполняются функции в плагине. waitForX() по неизвестным мне причинам, будто бы сразу возвращает 0, проигнорировав вечный цикл.
Вот архив со всем проектом TestPRX.zip
А тут уже скомпилированный плагин и EBOOT.PBP, который можно закинуть в PSP/GAME/ и посмотреть на код в действии (mymodule.prx кидать в корень карты памяти) TestPRX_EBOOT.zip
В общем нужна просто программа которая способна отлавливать эти кнопки и корректно завершаться. Мне бы помогли исходники FuSa Gamepad или любой программы которая проделывает подобное, и вообще любая информация про это.
Последний раз редактировалось vla5102008; 10.07.2016 в 01:57.
vla5102008, ну я вам в чате отвечал на ваш вопрос.
Ого, работает! Выходит, мне нужно было устанавливать регистр K1 в 0, прежде чем делать что-то в функции модуля. Спасибо, осталось только понять, откуда разработчик keystester про это узнал. А может никто и не знает для чего нужен этот регистр, просто наследуют код поколениями?