PSPx форум

PSPx форум (https://www.pspx.ru/forum/index.php)
-   Программирование для PSP (https://www.pspx.ru/forum/forumdisplay.php?f=101)
-   -   Отлов нажатий специальных кнопок (громкость, яркость, ...) (https://www.pspx.ru/forum/showthread.php?t=106168)

vla5102008 10.07.2016 01:37

Отлов нажатий специальных кнопок (громкость, яркость, ...)
 
Вложений: 2
Четвертый день я пытаюсь написать программку на 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, проигнорировав вечный цикл.

Вот архив со всем проектом Вложение 11378
А тут уже скомпилированный плагин и EBOOT.PBP, который можно закинуть в PSP/GAME/ и посмотреть на код в действии (mymodule.prx кидать в корень карты памяти) Вложение 11379

В общем нужна просто программа которая способна отлавливать эти кнопки и корректно завершаться. Мне бы помогли исходники FuSa Gamepad или любой программы которая проделывает подобное, и вообще любая информация про это.

ErikPshat 10.07.2016 04:40

vla5102008, ну я вам в чате отвечал на ваш вопрос.

Цитата:

@vla5102008: посмотрите исходники Key[s]Tester

vla5102008 10.07.2016 12:03

Цитата:

Сообщение от ErikPshat (Сообщение 1103896)
vla5102008, ну я вам в чате отвечал на ваш вопрос.

Ого, работает! Выходит, мне нужно было устанавливать регистр K1 в 0, прежде чем делать что-то в функции модуля. Спасибо, осталось только понять, откуда разработчик keystester про это узнал. А может никто и не знает для чего нужен этот регистр, просто наследуют код поколениями?


Текущее время: 11:45. Часовой пояс GMT +3.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2025, vBulletin Solutions, Inc. Перевод: zCarot
PSPx Forum - Сообщество фанатов игровых консолей.