// // Copyright (c) 2009, Pal_Bazzi. // // All rights reserved. // // This file is part of SDLPAL. // // SDLPAL is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // #include "main.h" #ifdef PSP #include #include #include #include PALINPUTSTATE g_InputState; BOOL g_fUseJoystick = TRUE; static SceCtrlData pad; static SDL_sem *pad_sem = 0; static SDL_Thread *bthread = 0; static int running = 0; static unsigned int old_button=0; static unsigned char old_x = 0, old_y = 0; // // Collect pad data about once per frame // int PSP_JoystickUpdate(void *data) { while (running) { SDL_SemWait(pad_sem); sceCtrlPeekBufferPositive(&pad, 1); SDL_SemPost(pad_sem); // // Delay 1/60th of a second // sceKernelDelayThread(1000000 / 60); } return 0; } void PAL_calc_Axes( unsigned char x, unsigned char y ) { if(x51) { g_InputState.dwKeyPress = kKeyDown; g_InputState.prevdir = g_InputState.dir; g_InputState.dir = kDirSouth; return; } if(x>y && x+y<51) { g_InputState.dwKeyPress = kKeyUp; g_InputState.prevdir = g_InputState.dir; g_InputState.dir = kDirNorth; return; } if(x>y && x+y>51) { g_InputState.dwKeyPress = kKeyRight; g_InputState.prevdir = g_InputState.dir; g_InputState.dir = kDirEast; return; } g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir); g_InputState.dir = kDirUnknown; } VOID PAL_JoystickEventFilter( VOID ) /*++ Purpose: Handle joystick events. Parameters: None. Return value: None. --*/ { unsigned int button; unsigned char x, y; SDL_SemWait(pad_sem); button = pad.Buttons; x = pad.Lx; y = pad.Ly; SDL_SemPost(pad_sem); // //Axes // x /= 5; y /= 5; BOOL onCenter=(x>16 && x<32) && (y>16 && y<32); if(!onCenter) { if(old_x != x || old_y != y) { PAL_calc_Axes(x,y); old_y = y; old_x = x; } } else if (!button) { g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir); g_InputState.dir = kDirUnknown; } // //Buttons // int changed = (button != old_button); old_button = button; if(changed) { if (button & PSP_CTRL_UP) { g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir); g_InputState.dir = kDirNorth; g_InputState.dwKeyPress = kKeyUp; return; } if (button & PSP_CTRL_DOWN) { g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir); g_InputState.dir = kDirSouth; g_InputState.dwKeyPress = kKeyDown; return; } if (button & PSP_CTRL_LEFT) { g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir); g_InputState.dir = kDirWest; g_InputState.dwKeyPress = kKeyLeft; return; } if (button & PSP_CTRL_RIGHT) { g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir); g_InputState.dir = kDirEast; g_InputState.dwKeyPress = kKeyRight; return; } if (button & PSP_CTRL_SQUARE) { g_InputState.dwKeyPress = kKeyForce; return; } if (button & PSP_CTRL_TRIANGLE) { g_InputState.dwKeyPress = kKeyThrowItem; return; } if (button & PSP_CTRL_CIRCLE) { g_InputState.dwKeyPress = kKeySearch; return; } if (button & PSP_CTRL_CROSS) { g_InputState.dwKeyPress = kKeyMenu; return; } if (button & PSP_CTRL_START) { g_InputState.dwKeyPress = kKeySearch; return; } if (button & PSP_CTRL_SELECT) { g_InputState.dwKeyPress = kKeyMenu; return; } if (button & PSP_CTRL_LTRIGGER) { g_InputState.dwKeyPress = kKeyUseItem; return; } if (button & PSP_CTRL_RTRIGGER) { g_InputState.dwKeyPress = kKeyRepeat; return; } g_InputState.prevdir = (gpGlobals->fInBattle ? kDirUnknown : g_InputState.dir); g_InputState.dir = kDirUnknown; } } #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION <= 2 static int SDLCALL PAL_EventFilter( const SDL_Event *lpEvent ) #else static int SDLCALL PAL_EventFilter( void *userdata, const SDL_Event *lpEvent ) #endif /*++ Purpose: SDL event filter function. A filter to process all events. Parameters: [IN] lpEvent - pointer to the event. Return value: 1 = the event will be added to the internal queue. 0 = the event will be dropped from the queue. --*/ { switch (lpEvent->type) { case SDL_QUIT: // // clicked on the close button of the window. Quit immediately. // PAL_Shutdown(); exit(0); } // // All events are handled here; don't put anything to the internal queue // return 0; } VOID PAL_ClearKeyState( VOID ) /*++ Purpose: Clear the record of pressed keys. Parameters: None. Return value: None. --*/ { g_InputState.dwKeyPress = 0; } VOID PAL_InitInput( VOID ) /*++ Purpose: Initialize the input subsystem. Parameters: None. Return value: None. --*/ { memset(&g_InputState, 0, sizeof(g_InputState)); g_InputState.dir = kDirUnknown; g_InputState.prevdir = kDirUnknown; #if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION <= 2 SDL_SetEventFilter(PAL_EventFilter); #else SDL_SetEventFilter(PAL_EventFilter, NULL); #endif // // Setup input // sceCtrlSetSamplingCycle(0); sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); pad.Buttons = 0; // // Start thread to read data // if((pad_sem = SDL_CreateSemaphore(1)) == NULL) { TerminateOnError("Can't create input semaphore\n"); return; } running = 1; if((bthread = SDL_CreateThread(PSP_JoystickUpdate, NULL)) == NULL) { TerminateOnError("Can't create input thread\n"); return; } } VOID PAL_ShutdownInput( VOID ) /*++ Purpose: Shutdown the input subsystem. Parameters: None. Return value: None. --*/ { // // Cleanup Threads and Semaphore. // running = 0; SDL_WaitThread(bthread, NULL); SDL_DestroySemaphore(pad_sem); } VOID PAL_ProcessEvent( VOID ) /*++ Purpose: Process all events. Parameters: None. Return value: None. --*/ { while (SDL_PollEvent(NULL)); PAL_JoystickEventFilter(); } #endif