 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
angelo
Joined: 29 Aug 2007 Posts: 168
|
Posted: Sat Apr 05, 2008 9:17 pm Post subject: Sleep in PRX |
|
|
When my plugin is enabled, my PSP doesn't enter "Sleep" mode. Nor does the backlight switch off after a few minutes.
Is there a line that must be entered so this can happen?
| Code: | #include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>
#include <pspdisplay.h>
#include <string.h>
#include <pspiofilemgr.h>
#include <stdio.h>
#include "pikey.h"
#include "apihook.h"
#include "blit.h"
#include "mapkey.h"
PSP_MODULE_INFO("piKey", 0x1000, 1, 1);
/*****************************************************************************/
/* Write debug info to SIO? */
/* */
/* 0 : off */
/* 1 : major events */
/* 2 : debug events */
/* 3 : extra debug */
/*****************************************************************************/
#define DEBUG_OUTPUT 0
/*****************************************************************************/
/* Internal structs */
/*****************************************************************************/
typedef struct input_info {
struct input_info *prev;
struct input_info *next;
SceUID moduleID;
char moduleName[64];
} INPUT_INFO;
typedef struct output_info {
struct output_info *prev;
struct output_info *next;
SceUID moduleID;
char moduleName[64];
} OUTPUT_INFO;
void DumpMem(void *addr,unsigned size,int num);
typedef int (*DRIVERINFOFUNC)(DRIVERINFO *);
/*****************************************************************************/
/* Internal vars */
/*****************************************************************************/
int terminate = 0;
int numInputs;
int numOutputs;
SceUID pikeythread;
INPUT_INFO *inputs;
OUTPUT_INFO *outputs;
#define QUEUE_SIZE 256
#define MAX_PATH_SIZE 256
/*****************************************************************************/
/* Cyclic buffer of max-size QUEUE_SIZE for input chars. */
/*****************************************************************************/
wchar inBuffer[QUEUE_SIZE];
int queueInputPos;
int queueOutputPos;
int queueSize;
SceUID queueSema;
SceUID gExclusiveThread;
/*****************************************************************************/
/* Keyboard info display callbacks */
/*****************************************************************************/
#define MAX_DISPLAY_CALLBACKS 10
SceUID gDisplayCallbacks[MAX_DISPLAY_CALLBACKS];
int gNumDisplayCallbacks = 0;
SceUID callbackSema;
/*****************************************************************************/
/* Status indication */
/*****************************************************************************/
// num of vblanks to display status text for. (3 secs)
#define STATUS_DISPLAY_TIME 180
#define SCREEN_TEXT_WIDTH 80
static char centredText[SCREEN_TEXT_WIDTH + 1];
int gStatusCycles = 0;
int gStatusText = 0;
int statusMessages = 1;
int sioDebug = 0;
int disabledIn150 = 0;
/*****************************************************************************/
/* VSH mode? */
/*****************************************************************************/
int gvshmode = 0;
/*****************************************************************************/
/* Keypress mode vars */
/*****************************************************************************/
int gOldKeyMode = PIKEY_KEYMODE_KEYPRESS;
int gKeyMode = PIKEY_KEYMODE_KEYPRESS;
char gPressMap[KEY_MAX];
char gHoldMap[KEY_MAX];
int numPressed = 0;
int altHeld = 0;
int ctrlHeld = 0;
int shiftHeld = 0;
/*****************************************************************************/
/* Key repeat metrics - measured in vblanks */
/* */
/* REPEAT_TIME: time to first repeat */
/* REPEAT_PERIOD: time between repeats once started. */
/*****************************************************************************/
#define REPEAT_TIME 30
#define REPEAT_PERIOD 10
// measured in microseconds - time to simulate a keyhold event when sent a
// character in keypress mode.
#define FAKE_KEYPRESS_HOLD 80000
// length of a vblank frame (60hz) in microseconds.
#define FRAME_LENGTH_USECS 16667
/*****************************************************************************/
/* ESCAPE key timeout hack */
/*****************************************************************************/
int gEscTimer = -1;
// number of vblanks to wait for further chars in a vt100 escape sequence
#define ESC_TIMEOUT 6
/*****************************************************************************/
/* Config file control vars. */
/*****************************************************************************/
#define MAX_CONFIGS 10
char * configData[MAX_CONFIGS];
char * configOffset[MAX_CONFIGS];
int numConfigs = 0;
char cfgtoken[64];
char cfgvalue[128];
/*****************************************************************************/
/* Disabled plugins list */
/*****************************************************************************/
#define MAX_DISABLED_PLUGINS 10
char disabledPlugins[MAX_DISABLED_PLUGINS][128];
int numDisabledPlugins = 0;
/*****************************************************************************/
/* */
/* Code starts here */
/* */
/*****************************************************************************/
void sioPrint(const char *str)
{
#if DEBUG_OUTPUT!=0
if (sioDebug)
{
while (*str)
{
pspDebugSioPutchar(*str);
str++;
}
}
#endif
}
void sioPrintHex(char ch)
{
#if DEBUG_OUTPUT!=0
if (sioDebug)
{
static char * hexmap="0123456789ABCDEF";
pspDebugSioPutchar( hexmap[ (ch >> 4) & 0x0F ] );
pspDebugSioPutchar( hexmap[ (ch & 0x0F) ] );
}
#endif
}
void sioPrintWord(u32 data)
{
#if DEBUG_OUTPUT!=0
if (sioDebug)
{
sioPrintHex( (data >> 24) & 0x000000FFL );
sioPrintHex( (data >> 16) & 0x000000FFL );
sioPrintHex( (data >> 8) & 0x000000FFL );
sioPrintHex( data & 0x000000FFL );
}
#endif
}
int waitForModule(const char * modname)
{
int cycles = 0;
#if DEBUG_OUTPUT>=2
sioPrint("Wait for module ");
sioPrint(modname);
sioPrint(": ");
#endif
while (sceKernelFindModuleByName(modname) == NULL)
{
#if DEBUG_OUTPUT>=2
pspDebugSioPutchar('.');
#endif
if (cycles++ > 10)
{
#if DEBUG_OUTPUT>=2
sioPrint("TIMEOUT.\r\n");
#endif
// give up waiting after 5 secs
return 0;
}
sceKernelDelayThread(500000);
}
#if DEBUG_OUTPUT>=2
sioPrint("OK.\r\n");
#endif
return 1;
}
static struct SceLibraryEntryTable *_libsFindLibrary(SceUID uid, const char *library)
{
struct SceLibraryEntryTable *entry;
SceModule *pMod;
void *entTab;
int entLen;
pMod = sceKernelFindModuleByUID(uid);
if(pMod != NULL)
{
int i = 0;
entTab = pMod->ent_top;
entLen = pMod->ent_size;
while(i < entLen)
{
entry = (struct SceLibraryEntryTable *) (entTab + i);
if((entry->libname) && (strcmp(entry->libname, library) == 0))
{
return entry;
}
else if(!entry->libname && !library)
{
return entry;
}
i += (entry->len * 4);
}
}
return NULL;
}
static void* libsFindExportAddrByNid(SceUID uid, const char *library, u32 nid)
{
u32 *addr = NULL;
SceLibraryEntryTable *entry = _libsFindLibrary(uid, library);
if(entry)
{
int count;
int total;
unsigned int *vars;
total = entry->stubcount + entry->vstubcount;
vars = entry->entrytable;
if(entry->stubcount > 0)
{
for(count = 0; count < entry->stubcount; count++)
{
if(vars[count] == nid)
{
return (void*)(*((void**)(&vars[count+total])));
}
}
}
}
return addr;
}
SceUID load_module(const char *path, int flags, int type) {
SceKernelLMOption option;
SceUID mpid;
/* If the type is 0, then load the module in the kernel partition, otherwise load it
in the user partition. */
if (type == 0) mpid = 1;
else mpid = 2;
memset(&option, 0, sizeof(option));
option.size = sizeof(option);
option.mpidtext = mpid;
option.mpiddata = mpid;
option.position = 0;
option.access = 1;
return sceKernelLoadModule(path, flags, type > 0 ? &option : NULL);
}
void centre_string(const char *text)
{
centredText[SCREEN_TEXT_WIDTH] = '\0';
memset(centredText, ' ', SCREEN_TEXT_WIDTH);
int length = strlen(text);
int offset;
// Cope with over-length string
if (length > SCREEN_TEXT_WIDTH)
{
length = SCREEN_TEXT_WIDTH;
offset = 0;
}
else
{
// Note : calculation relies on max width being even to avoid overflow
offset = (SCREEN_TEXT_WIDTH - length) / 2;
}
int ii;
for (ii = 0; ii < length; ii++)
{
centredText[offset++] = text[ii];
}
}
void displayStatusText(const char *text)
{
if (statusMessages)
{
centre_string(text);
gStatusCycles = 0;
gStatusText = 1;
#if DEBUG_OUTPUT>=2
sioPrint("Show status text: ");
sioPrint(text);
sioPrint("\r\n");
#endif
}
}
void InitVars(void)
{
// empty queues, driver counts
numInputs = 0;
numOutputs = 0;
inputs = NULL;
outputs = NULL;
queueInputPos = 0;
queueOutputPos = 0;
queueSize = 0;
ctrlHeld = 0;
altHeld = 0;
shiftHeld = 0;
gExclusiveThread = 0;
queueSema = sceKernelCreateSema("pikey_q", 0, 1, 1, NULL);
callbackSema = sceKernelCreateSema("pikey_calls", 0, 1, 1, NULL);
gNumDisplayCallbacks = 0;
gStatusText = 0;
gStatusCycles = 0;
// default to keypress mode, no keys currently pressed
gKeyMode = PIKEY_KEYMODE_KEYPRESS;
memset(gPressMap, 0, sizeof(gPressMap));
numPressed = 0;
numConfigs = 0;
int ii;
for (ii = 0; ii < MAX_CONFIGS; ii++)
{
configData[ii] = NULL;
configOffset[ii] = NULL;
}
initApiHooks();
}
/*****************************************************************************/
/* Simple malloc clone. The block ID is stored just before the returned */
/* pointer. */
/*****************************************************************************/
void *myMalloc(size_t size)
{
SceUID memID = sceKernelAllocPartitionMemory(1, "", 0, size + 4, NULL);
if (memID < 0)
{
#if DEBUG_OUTPUT>=2
sioPrint("sKAPM failed: ");
sioPrintWord(memID);
sioPrint("\r\n");
#endif
return NULL;
}
unsigned int * lptr = sceKernelGetBlockHeadAddr(memID);
*lptr = memID;
#if DEBUG_OUTPUT>=3
sioPrint("alloced blockID: ");
sioPrintWord(memID);
sioPrint(" size ");
sioPrintWord(size);
sioPrint("\r\n");
#endif
return (lptr+1);
}
/*****************************************************************************/
/* Corresponding Free func for myMalloc */
/*****************************************************************************/
void myFree(void *blockaddr)
{
SceUID blockid = *(((SceUID*)blockaddr) - 1);
#if DEBUG_OUTPUT>=3
sioPrint("Free blockID: ");
sioPrintWord(blockid);
sioPrint("\r\n");
#endif
int rc = sceKernelFreePartitionMemory(blockid);
if (rc < 0)
{
sioPrint("Error freeing block at ");
sioPrintWord((int)blockaddr);
sioPrint(" err=");
sioPrintWord(rc);
sioPrint("\r\n");
}
}
SceIoDirent dirent;
void LoadDrivers(char *path, int isInput)
{
int status;
#if DEBUG_OUTPUT>=2
sioPrint("Load drivers from ");
sioPrint(path);
sioPrint("\r\n");
#endif
// iterate through "path/", loading all the prxs
memset(&dirent, 0, sizeof(SceIoDirent));
SceUID lid = sceIoDopen(path);
if (lid >= 0)
{
int lrc = 0;
do {
lrc = sceIoDread(lid, &dirent);
if (lrc > 0) {
if (strstr(dirent.d_name, ".prx") || strstr(dirent.d_name, ".PRX")) {
char namebuff[MAX_PATH_SIZE];
strncpy(namebuff, path, MAX_PATH_SIZE);
strcat(namebuff, "/");
strcat(namebuff, dirent.d_name);
#if DEBUG_OUTPUT>=2
sioPrint(namebuff);
sioPrint(":\r\n");
#endif
int disabled = 0;
int ii;
for (ii = 0; ii < numDisabledPlugins; ii++)
{
#if DEBUG_OUTPUT>=3
sioPrint("Check : '");
sioPrint(disabledPlugins[ii]);
sioPrint("'\r\n");
#endif
if (strcmp(dirent.d_name, disabledPlugins[ii]) == 0)
{
#if DEBUG_OUTPUT>=1
sioPrint("Skip ");
sioPrint(dirent.d_name);
sioPrint(" - disabled module\r\n");
#endif
disabled = 1;
}
}
if (disabled)
{
continue;
}
SceUID modid = load_module(namebuff, 0, 0);
if (modid < 0)
{
#if DEBUG_OUTPUT>=1
sioPrint("Load module failed: 0x");
sioPrintWord(modid);
sioPrint("\r\n");
#endif
}
int done = 0;
while (!done)
{
int lrc2 = sceKernelStartModule(modid, 0, NULL, &status, NULL);
if (lrc2 < 0)
{
#if DEBUG_OUTPUT>=1
sioPrint("Start module failed: 0x");
sioPrintWord(lrc2);
#endif
if (lrc2 == 0x8002013CL)
{
#if DEBUG_OUTPUT>=1
sioPrint("...sleep and retry...\r\n");
#endif
sceKernelDelayThread(500000);
}
else
{
#if DEBUG_OUTPUT>=1
sioPrint("...Give up.\r\n");
#endif
done = 1;
}
}
else
{
#if DEBUG_OUTPUT>=2
sioPrint("Started.\r\n");
#endif
done = 1;
// Now we started the module successfully, call its driverinfo func.
DRIVERINFOFUNC info_func = NULL;
DRIVERINFO ldriverinfo;
memset(&ldriverinfo, 0, sizeof(ldriverinfo));
SceKernelModuleInfo lmodinfo;
memset(&lmodinfo, 0, sizeof(lmodinfo));
lmodinfo.size = sizeof(lmodinfo);
int lmodinforc = sceKernelQueryModuleInfo(modid, &lmodinfo);
if (lmodinforc == 0)
{
info_func = libsFindExportAddrByNid(modid, lmodinfo.name, 0x79EC1E42);
#if DEBUG_OUTPUT>=1
if (info_func == NULL)
{
sioPrint("Failed to get driver info export.\r\n");
sioPrint("Was using name: '");
sioPrint(lmodinfo.name);
sioPrint("'\r\n");
}
#endif
ldriverinfo.apiVersion = PIKEY_THIS_VERSION;
}
#if DEBUG_OUTPUT>=1
else
{
sioPrint("Failed to get module info. RC=");
sioPrintWord(lmodinforc);
sioPrint("\r\n");
}
#endif
if ((info_func == NULL) || (info_func(&ldriverinfo) != PIKEY_SUCCESS))
{
// XXX should unload the driver here.
#if DEBUG_OUTPUT>=1
sioPrint("Would unload plugin here.\r\n");
#endif
}
else
{
#if DEBUG_OUTPUT>=1
// output some info about the driver
sioPrint("Successfully loaded driver '");
sioPrint(ldriverinfo.driverName);
sioPrint("' version ");
sioPrint(ldriverinfo.driverVersion);
sioPrint("\r\n");
#endif
}
/***************************************************************/
/* Save some info in our linked list of driver info. */
/***************************************************************/
if (isInput)
{
INPUT_INFO *linfo = (INPUT_INFO*)myMalloc(sizeof(INPUT_INFO));
if (!linfo)
{
sioPrint("malloc failed\r\n");
}
else
{
linfo->next = NULL;
if (inputs == NULL)
{
linfo->prev = NULL;
inputs = linfo;
}
else
{
INPUT_INFO *lptr = inputs;
while (lptr->next)
{
lptr = lptr->next;
}
linfo->prev = lptr;
lptr->next = linfo;
}
linfo->moduleID = modid;
strcpy(linfo->moduleName, ldriverinfo.driverName);
}
numInputs++;
}
else
{
OUTPUT_INFO *linfo = (OUTPUT_INFO*)myMalloc(sizeof(OUTPUT_INFO));
if (!linfo)
{
sioPrint("malloc failed\r\n");
}
else
{
linfo->next = NULL;
if (outputs == NULL)
{
linfo->prev = NULL;
outputs = linfo;
}
else
{
OUTPUT_INFO *lptr = outputs;
while (lptr->next)
{
lptr = lptr->next;
}
linfo->prev = lptr;
lptr->next = linfo;
}
linfo->moduleID = modid;
strcpy(linfo->moduleName, ldriverinfo.driverName);
}
numOutputs++;
}
}
}
}
}
}
while (lrc > 0);
sceIoDclose(lid);
}
}
#if DEBUG_OUTPUT>=1
void DumpMem(void *addr,unsigned size,int num)//DELME
{
char buf[270];
SceUID fd;
sprintf(buf,"ms0:/%d_%08X_%08X.bin",num,(int)addr,size);
fd = sceIoOpen(buf,PSP_O_WRONLY|PSP_O_CREAT|PSP_O_TRUNC,0777);
if(fd < 0)
return;
sceIoWrite(fd,addr,size);
sceIoClose(fd);
}
#endif
int main_thread(SceSize args, void *argp)
{
unsigned int disableHotkey = 0;
unsigned int oskstate = 0;
displayStatusText("Starting");
// Read the config file for user-defined control map
int cfg = configOpen("ms0:/seplugins/pikey/pikeyconfig.txt");
if (cfg >= 0)
{
while (configRead(cfg, cfgtoken, cfgvalue))
{
if (strcmp(cfgtoken, "SIO DEBUG") == 0)
{
sioDebug = ((cfgvalue[0] == 'Y') || (cfgvalue[0] == 'y'));
}
else if (strcmp(cfgtoken, "STATUS MESSAGES") == 0)
{
statusMessages = ((cfgvalue[0] == 'Y') || (cfgvalue[0] == 'y'));
}
else if (strcmp(cfgtoken, "DISABLED IN 150") == 0)
{
disabledIn150 = ((cfgvalue[0] == 'Y') || (cfgvalue[0] == 'y'));
}
else if (strcmp(cfgtoken, "DISABLED PLUGINS") == 0)
{
// split the CSV list, save in disabledPlugins[]
char *lptr = cfgvalue;
char *ldestptr = disabledPlugins[0];
numDisabledPlugins = 0;
while (*lptr != '\0')
{
if (*lptr == ' ')
{
// skip spaces
}
else if (*lptr == ',')
{
*ldestptr = '\0';
if (numDisabledPlugins++ > MAX_DISABLED_PLUGINS)
{
// too many disabled plugins
break;
}
else
{
ldestptr = disabledPlugins[numDisabledPlugins];
}
}
else
{
*ldestptr++ = *lptr;
}
lptr++;
}
// if we read any data, then adjust the disabledplugins count
// (since we didn't increment it at the end of the string, just the
// last comma)
if (ldestptr != disabledPlugins[0])
{
numDisabledPlugins ++;
}
}
else if (strcmp(cfgtoken, "DISABLE HOTKEY") == 0)
{
if ((cfgvalue[0] == '0') &&
((cfgvalue[1] == 'x') ||
(cfgvalue[1] == 'X')))
{
unsigned int lhex = 0;
char *lptr = &(cfgvalue[2]);
while ((*lptr != '\0') && (*lptr != ' '))
{
// This is a hex number, decode it.
char lhexdigit = (*lptr) - '0';
if (lhexdigit > 9)
{
lhexdigit -= ('A' - '9' - 1);
}
if (lhexdigit > 15)
{
lhexdigit -= ('a' - 'A');
}
if (lhexdigit < 0)
{
lhexdigit = 0;
}
lhex <<= 4;
lhex += lhexdigit;
lptr++;
}
disableHotkey = lhex;
}
}
}
configClose(cfg);
}
displayStatusText("line 806");
// If we're in v1.50 firmware, and we're disabled for this mode, then exit.
if (disabledIn150)
{
if (sceKernelDevkitVersion() == 0x01050001L)
{
sceKernelExitDeleteThread(0);
}
}
// If there's a disable hotkey, and it's pressed, then exit.
if (disableHotkey != 0)
{
SceCtrlData lpad;
sceCtrlPeekBufferPositive(&lpad, 1);
if ((lpad.Buttons & disableHotkey) == disableHotkey)
{
sceKernelExitDeleteThread(0);
}
}
if (sioDebug)
{
pspDebugSioInit();
sioPrint("\r\n\r\n");
#if DEBUG_OUTPUT>=2
pspDebugSioInstallKprintf();
pspDebugSioEnableKprintf();
#endif
sioPrint(" -----------------------\r\n");
sioPrint(" -- piKey is starting --\r\n");
sioPrint(" -----------------------\r\n");
#if DEBUG_OUTPUT >= 3
int ii;
for (ii = 1; ii <= 6; ii++)
{
sioPrint("\r\nFreemem: ");
sioPrintHex(ii);
sioPrint(" = ");
SceSize mem = sceKernelPartitionMaxFreeMemSize(ii);
sioPrintWord(mem);
}
#endif
}
InitVars();
gvshmode = waitForModule("sceVshBridge_Driver");
if (gvshmode)
{
sioPrint("Detected VSH mode\r\n");
// sleep here to avoid corrupting the startup animation
sceKernelDelayThread(4 * 1000 * 1000);
}
else
{
sioPrint("Detected GAME mode\r\n");
}
LoadDrivers("ms0:/seplugins/pikey/inputdrivers", 1);
LoadDrivers("ms0:/seplugins/pikey/outputdrivers", 0);
sioPrint("--- All plugins loaded ---\r\n");
displayStatusText("piKey is now ACTIVE");
while (!terminate)
{
sceKernelDelayThread(100); // Yields in a way that waitvblank does not
// Without this tiny sleep, we won't exit
// cleanly during module tidy-up.
sceDisplayWaitVblankStart();
// If we have something to display, display it
if (gStatusText)
{
font_init();
if (++gStatusCycles > STATUS_DISPLAY_TIME)
{
gStatusCycles = 0;
gStatusText = 0;
memset(centredText, ' ', sizeof(centredText));
blit_string(0, 0, centredText, 1);
}
else
{
blit_string(0, 0, centredText, 1);
}
}
// check for held keys. We only need to do this for stream mode, with
// some keys held.
if ((gKeyMode == PIKEY_KEYMODE_VT100STREAM) &&
(numPressed > 0))
{
int ii;
for (ii=0; ii < KEY_MAX; ii++)
{
if (gPressMap[ii])
{
if ((gHoldMap[ii])++ > REPEAT_TIME + REPEAT_PERIOD)
{
gHoldMap[ii] = REPEAT_TIME;
unsigned char str[16];
if (mapScanToVT100(ii, ctrlHeld, shiftHeld, altHeld, str))
{
unsigned char *lptr = str;
while (*lptr)
{
putNextChar(*lptr);
lptr++;
}
}
}
}
}
}
// Wait until we are activated with the NUM lock key.
if (gPressMap[KEY_NUMLOCK])
{
// check if JUST pressed
if (!(oskstate & 32))
{
oskstate |= 32; // NumLock pressed
oskstate ^= 4;
if (oskstate & 4)
{
sioPrint("NUM lock is ON\r\n");
displayStatusText("NUM lock is ON");
}
else
{
sioPrint("NUM lock is OFF\r\n");
displayStatusText("NUM lock is OFF");
}
}
}
else
oskstate &= ~32; // NumLock not pressed
// Wait until we are activated with the scroll lock key.
if (gPressMap[KEY_SCROLLLOCK])
{
// check if JUST pressed
if (!(oskstate & 16))
{
oskstate |= 16; // ScrollLock pressed
oskstate ^= 2;
if (oskstate & 2)
{
sioPrint("SCROLL lock is ON\r\n");
displayStatusText("SCROLL lock is ON");
}
else
{
sioPrint("SCROLL lock is OFF\r\n");
displayStatusText("SCROLL lock is OFF");
}
}
}
else
oskstate &= ~16; // ScrollLock not pressed
// Wait until we are activated with the CAPS lock key.
if (gPressMap[KEY_CAPSLOCK])
{
// check if JUST pressed
if (!(oskstate & 8))
{
oskstate |= 8; // CapsLock pressed
oskstate ^= 1;
if (oskstate & 1)
{
sioPrint("CAPS lock is ON\r\n");
displayStatusText("CAPS lock is ON");
}
else
{
sioPrint("CAPS lock is OFF\r\n");
displayStatusText("CAPS lock is OFF");
}
}
}
else
oskstate &= ~8; // CapsLock not pressed
// if we have an ESC charinput, in keypress mode, check whether we
// need to time it out into a simple ESC.
if ((gKeyMode == PIKEY_KEYMODE_KEYPRESS) &&
(gEscTimer != -1))
{
gEscTimer++;
if ((gEscTimer > ESC_TIMEOUT) &&
!(gPressMap[KEY_ESC]))
{
// we have a lone escape key. Press it...
resetMapkey();
sendKeyPress(KEY_ESC, 1, 0, 0, 0);
}
else if (gEscTimer > (ESC_TIMEOUT +(FAKE_KEYPRESS_HOLD / FRAME_LENGTH_USECS)))
{
// ... and release it after another timeout
sendKeyPress(KEY_ESC, 0, 0, 0, 0);
gEscTimer = -1;
}
}
}
sioPrint("--- Exiting piKey ---\r\n");
sceKernelExitDeleteThread(0);
return 0;
}
int main(void) {
int rc = 0;
/***************************************************************************/
/* Create main thread. */
/***************************************************************************/
pikeythread = sceKernelCreateThread("pikey", main_thread, 16, 0x1000, 0, NULL);
if (pikeythread >= 0)
{
rc = sceKernelStartThread(pikeythread, 0, NULL);
if (rc < 0)
{
return -2;
}
}
else
{
return -1;
}
return 0;
}
void throwAwayInput(int numchars)
{
while (numchars--)
{
if (numCharsAvailable() > 0) getNextChar();
}
}
void putNextCharW(wchar inChar) {
if (gKeyMode == PIKEY_KEYMODE_VT100STREAM)
{
// block until queue is not full
int lfull = 1;
while (lfull) {
sceKernelWaitSema(queueSema, 1, 0);
if (queueSize != QUEUE_SIZE) lfull = 0;
else {
sceKernelSignalSema(queueSema, 1);
sceKernelDelayThread(5000);
}
}
// add to Q
inBuffer[queueInputPos] = inChar;
queueInputPos = (queueInputPos + 1) % QUEUE_SIZE;
queueSize ++;
// release Q sema
sceKernelSignalSema(queueSema, 1);
}
else
{
// for keypress mode, we need to simulate a keypress and release
int shift, ctrl, alt;
int lscan = mapVT100toScan(inChar, &ctrl, &alt, &shift);
#if DEBUG_OUTPUT>=3
sioPrint("vt100: ");
sioPrintHex(inChar);
sioPrint("=> ");
sioPrintWord(lscan);
sioPrint(" : ");
sioPrintHex((ctrl << 2) | (alt << 1) | (shift));
sioPrint("\r\n");
#endif
// special hack to ESC chars - timeout a single ESC after a short time,
// if it isn't followed by any other chars.
if (inChar == 0x1b)
{
gEscTimer = 0;
}
if (lscan != -1)
{
gEscTimer = -1;
sendKeyPress(lscan, 1, shift, ctrl, alt);
sceKernelDelayThread(FAKE_KEYPRESS_HOLD);
sendKeyPress(lscan, 0, shift, ctrl, alt);
}
}
}
void putNextChar(char inChar) {
// we do a conversion to wchar then call the putwchar func.
// XXX : for now assume a very simple conversion
putNextCharW((wchar)inChar);
}
int numCharsAvailable(void) {
int lreturn = 0;
// only valid in stream mode
if (gKeyMode == PIKEY_KEYMODE_VT100STREAM)
{
sceKernelWaitSema(queueSema, 1, 0);
lreturn = queueSize;
// return 0 if there's an exclusive thread and we're not it
if (gExclusiveThread != 0)
{
if (sceKernelGetThreadId() != gExclusiveThread)
{
lreturn = 0;
}
}
sceKernelSignalSema(queueSema, 1);
}
else
{
lreturn = PIKEY_ERROR_WRONG_MODE;
}
return(lreturn);
}
/*****************************************************************************/
/* Returns PIKEY_SUCCESS if there are n chars available, copies them to */
/* buffer */
/*****************************************************************************/
int peekNChars(int n, wchar *buffer) {
int ii;
// only valid in stream mode
if (gKeyMode != PIKEY_KEYMODE_VT100STREAM)
{
return PIKEY_ERROR_WRONG_MODE;
}
sceKernelWaitSema(queueSema, 1, 0);
int lqueueSize = queueSize;
// override queue size if there's an exclusive thread and we're not it
if (gExclusiveThread != 0)
{
if (sceKernelGetThreadId() != gExclusiveThread)
{
lqueueSize = 0;
}
}
if (lqueueSize < n)
{
sceKernelSignalSema(queueSema, 1);
return PIKEY_ERROR_NOT_ENOUGH_CHARS;
}
// copy to buffer
for (ii = 0; ii < n; ii++)
{
buffer[ii] = inBuffer[(queueOutputPos + ii) % QUEUE_SIZE];
}
sceKernelSignalSema(queueSema, 1);
return(PIKEY_SUCCESS);
}
void _flushBuffer(void)
{
queueInputPos = 0;
queueOutputPos = 0;
queueSize = 0;
resetMapkey();
gEscTimer = -1;
}
void flushBuffer(void) {
sceKernelWaitSema(queueSema, 1, 0);
// do nothing if there's an exclusive thread and we're not it
if ((gExclusiveThread == 0) || (sceKernelGetThreadId() == gExclusiveThread))
{
_flushBuffer();
}
sceKernelSignalSema(queueSema, 1);
}
int requestExclusive(void)
{
SceUID lthid = sceKernelGetThreadId();
int lreturn;
// semaphore this using the standard queue semaphore
sceKernelWaitSema(queueSema, 1, 0);
/***************************************************************************/
/* Return success if we already have exclusivity. */
/***************************************************************************/
if (gExclusiveThread == lthid)
{
lreturn = 1;
}
/***************************************************************************/
/* Return failure if someone else already has exclusivity */
/***************************************************************************/
else if (gExclusiveThread != 0)
{
lreturn = 0;
}
else
{
gExclusiveThread = lthid;
gOldKeyMode = gKeyMode;
lreturn = 1;
}
sceKernelSignalSema(queueSema, 1);
return lreturn;
}
void releaseExclusive(void)
{
SceUID lthid = sceKernelGetThreadId();
sceKernelWaitSema(queueSema, 1, 0);
// Can only release exclusive if we are the exclusive thread
if (lthid == gExclusiveThread)
{
gExclusiveThread = 0;
_setMode(gOldKeyMode);
}
sceKernelSignalSema(queueSema, 1);
}
// mode: 0: keypress 1: stream
int setMode(int mode)
{
int lreturn = PIKEY_SUCCESS;
// change mode only if exclusive
SceUID lthid = sceKernelGetThreadId();
sceKernelWaitSema(queueSema, 1, 0);
// Can only change mode if we are the exclusive thread
if (lthid == gExclusiveThread)
{
_setMode(mode);
}
else
{
lreturn = PIKEY_ERROR_NOT_EXCLUSIVE;
}
sceKernelSignalSema(queueSema, 1);
return lreturn;
}
void _setMode(int mode)
{
gKeyMode = mode;
_flushKeyPresses();
_flushBuffer();
}
int getMode(void)
{
return gKeyMode;
}
int isKeyPressed(int keycode)
{
sceKernelWaitSema(queueSema, 1, 0);
int lreturn = gPressMap[keycode];
// return 0 if there's an exclusive thread and we're not it
if (gExclusiveThread != 0)
{
if (sceKernelGetThreadId() != gExclusiveThread)
{
lreturn = 0;
}
}
sceKernelSignalSema(queueSema, 1);
return lreturn;
}
void getMetaKeys(int *alt, int *ctrl, int *shift)
{
sceKernelWaitSema(queueSema, 1, 0);
// meaningless when not in keypress mode.
if (gKeyMode == PIKEY_KEYMODE_KEYPRESS)
{
*alt = altHeld;
*ctrl = ctrlHeld;
*shift = shiftHeld;
}
else
{
*alt = 0;
*ctrl = 0;
*shift = 0;
}
sceKernelSignalSema(queueSema, 1);
}
void _flushKeyPresses()
{
memset(gPressMap, 0, sizeof(gPressMap));
memset(gHoldMap, 0, sizeof(gHoldMap));
numPressed = 0;
gEscTimer = -1;
resetMapkey();
}
void flushKeyPresses()
{
sceKernelWaitSema(queueSema, 1, 0);
// don't allow flush if there's an exclusive thread and we're not it
if ((gExclusiveThread == 0) ||
(sceKernelGetThreadId() == gExclusiveThread))
{
_flushKeyPresses();
}
sceKernelSignalSema(queueSema, 1);
}
int numKeysPressed()
{
int lreturn = 0;
sceKernelWaitSema(queueSema, 1, 0);
// don't allow read if there's an exclusive thread and we're not it
if ((gExclusiveThread == 0) ||
(sceKernelGetThreadId() == gExclusiveThread))
{
lreturn = numPressed;
}
sceKernelSignalSema(queueSema, 1);
return lreturn;
}
void sendKeyPress(int keycode, int pressed, int shift, int ctrl, int alt)
{
if (pressed)
{
if (!gPressMap[keycode])
{
// only if wasn't already pressed (repeat issue)
gHoldMap[keycode] = 0;
gPressMap[keycode] = 1;
numPressed ++;
}
#if DEBUG_OUTPUT >= 3
sioPrint("Keypress: ");
sioPrintWord(keycode);
sioPrint(" ");
sioPrintWord((shift << 2) | (ctrl << 1) | alt);
sioPrint("\r\n");
#endif
if (gKeyMode != PIKEY_KEYMODE_KEYPRESS)
{
// We're in stream mode, so we need to be a bit fancier.
// If this is a press event, we just add the relevant char to the
// buffer.
// XXX : this needs a mapping to allow for capslock etc.
unsigned char str[16];
if (mapScanToVT100(keycode, ctrlHeld, shiftHeld, altHeld, str))
{
unsigned char *lptr = str;
while (*lptr)
{
putNextChar(*lptr);
lptr++;
}
}
}
shiftHeld = shift;
ctrlHeld = ctrl;
altHeld = alt;
}
else
{
// currently libpspirkeyb seems bugged for keycodes on at least the
// Targus. It sends a huge stream of released presses, so we need to
// filter for those keys that are actually pressed.
if (gPressMap[keycode])
{
#if DEBUG_OUTPUT >= 3
sioPrint("Keyrelease: ");
sioPrintWord(keycode);
sioPrint(" ");
sioPrintWord((shift << 2) | (ctrl << 1) | alt);
sioPrint("\r\n");
#endif
gPressMap[keycode] = 0;
numPressed --;
shiftHeld = shift;
ctrlHeld = ctrl;
altHeld = alt;
}
}
}
wchar getNextCharW(void) {
// block until queue is not empty
int lempty = 1;
SceUID lthid = sceKernelGetThreadId();
while (lempty) {
sceKernelWaitSema(queueSema, 1, 0);
// pretend empty if there's an exclusive thread and we are not it
if ((gExclusiveThread == 0) || (lthid == gExclusiveThread))
{
if (queueSize != 0)
{
lempty = 0;
}
}
if (lempty)
{
sceKernelSignalSema(queueSema, 1);
sceKernelDelayThread(5000);
}
}
wchar lchar = inBuffer[queueOutputPos];
queueOutputPos = (queueOutputPos + 1) % QUEUE_SIZE;
queueSize --;
sceKernelSignalSema(queueSema, 1);
return(lchar);
}
char getNextChar(void) {
// we call getNextCharW, then convert to 8bit
wchar lchar = getNextCharW();
// XXX: naive conversion func.
return ((char) lchar);
}
int registerDisplayCallback(SceUID hookid)
{
int lreturn = 0;
sceKernelWaitSema(callbackSema, 1, 0);
if (gNumDisplayCallbacks < MAX_DISPLAY_CALLBACKS)
{
gDisplayCallbacks[gNumDisplayCallbacks++] = hookid;
lreturn = 1;
#if DEBUG_INFO>=2
sioPrint("Registered display callback #");
sioPrintHex(gNumDisplayCallbackss);
sioPrint(" - ID ");
sioPrintWord(hookid);
sioPrint("\r\n");
#endif
}
sceKernelSignalSema(callbackSema, 1);
return lreturn;
}
void drawKeyboardInfo(DRAWINFO *argument)
{
int ii;
sceKernelWaitSema(callbackSema, 1, 0);
for (ii = 0; ii < gNumDisplayCallbacks; ii++)
{
sceKernelNotifyCallback(gDisplayCallbacks[ii], (int)argument);
}
sceKernelSignalSema(callbackSema, 1);
}
int isVshMode()
{
return gvshmode;
}
int configOpen(const char *filename)
{
int lreturn;
sceKernelWaitSema(queueSema, 1, 0);
#if DEBUG_OUTPUT>=3
sioPrint("configOpen: ");
sioPrint(filename);
sioPrint("\r\n");
#endif
if (numConfigs == MAX_CONFIGS)
{
sceKernelSignalSema(queueSema, 1);
return PIKEY_ERROR_TOO_MANY_CONFIGS;
}
int fh = sceIoOpen(filename, PSP_O_RDONLY, 0777);
if (fh < 0)
{
sceKernelSignalSema(queueSema, 1);
return fh;
}
int len = sceIoLseek32(fh, 0, SEEK_END);
int rc = sceIoLseek32(fh, 0, SEEK_SET);
if (rc < 0)
{
sioPrint("Error on file seek: ");
sioPrintWord(rc);
sioPrint("\r\n");
sceKernelSignalSema(queueSema, 1);
return rc;
}
// allocate mem to hold the file
configData[numConfigs] = myMalloc(len + 1);
if (configData[numConfigs] == NULL)
{
sceKernelSignalSema(queueSema, 1);
return PIKEY_ERROR_NO_MEM;
}
// set progress pointer to the start of the file data
configOffset[numConfigs] = configData[numConfigs];
#if DEBUG_OUTPUT>=3
sioPrint("Read the file\r\n");
#endif
// read the file into mem, null-terminate it.
rc = sceIoRead(fh, configData[numConfigs], len);
if (rc < len)
{
sceKernelSignalSema(queueSema, 1);
return PIKEY_ERROR_MISC;
}
configData[numConfigs][len] = '\0';
#if DEBUG_OUTPUT>=3
sioPrint("Close the file\r\n");
#endif
sceIoClose(fh);
lreturn = numConfigs++;
sceKernelSignalSema(queueSema, 1);
return lreturn;
}
int configRead(int cfgHandle, char *token, char *value)
{
int lreturn = 0;
sceKernelWaitSema(queueSema, 1, 0);
// valid handle?
if ((cfgHandle >= numConfigs) ||
(cfgHandle < 0) ||
(configData[cfgHandle] == NULL) ||
(configOffset[cfgHandle] == NULL))
{
sioPrint("configRead: Invalid config handle\r\n");
lreturn = 0;
}
else
{
// We start from configOffset, and seek to an EOL or EOF
int ldone = 0;
char *lendptr;
char *lequalptr;
while (!ldone)
{
lendptr = configOffset[cfgHandle];
lequalptr = NULL;
while ((*lendptr) && (*lendptr != '\n'))
{
if (*lendptr == '=')
{
lequalptr = lendptr;
}
lendptr++;
}
if ((configOffset[cfgHandle][0] == '#') &&
(*lendptr != '\0'))
{
// this is a comment, and we're not at EOF. Read the next line.
configOffset[cfgHandle] = lendptr + 1;
}
else
{
ldone = 1;
}
}
char *linestart = configOffset[cfgHandle];
// found an equals sign that's not in the first column?
if (lequalptr == NULL)
{
lreturn = 0;
}
else
{
// scan back through whitespace from the equals
char *ltokenend = lequalptr - 1;
while ((ltokenend > linestart) &&
((*ltokenend == ' ') ||
(*ltokenend == '\t')))
{
ltokenend--;
}
// token length too small or too big?
int toklen = ltokenend - linestart + 1;
if ((toklen == 0) || (toklen > 63))
{
lreturn = 0;
}
else
{
strncpy(token, linestart, toklen);
token[toklen] = '\0';
// ... and now the value. Scan forward from the equals, through
// any whitespace.
char *lvalstart = lequalptr + 1;
while ((lvalstart < lendptr) &&
((*lvalstart == ' ') ||
(*lvalstart == '\t')))
{
lvalstart++;
}
int lvallen = lendptr - lvalstart;
// value too large?
if (lvallen > 127)
{
lreturn = 0;
}
// we allow an empty value, but it is a special case (might be -ve length)
else if (lvallen < 0)
{
value[0] = '\0';
lreturn = 1;
}
else
{
strncpy(value, lvalstart, lvallen);
value[lvallen] = '\0';
// tweak for CRLF files - remove the CR if present.
if ((lvallen >= 1) &&
(value[lvallen-1] == '\r'))
{
value[lvallen-1] = '\0';
}
// all done, and we got a value of some sort. SUCCESS!
lreturn = 1;
}
}
}
// advance the config offset appropriately, ready for the next call.
if (*lendptr == '\0')
{
// EOF
configOffset[cfgHandle] = NULL;
}
else
{
// EOL
configOffset[cfgHandle] = lendptr + 1;
}
}
sceKernelSignalSema(queueSema, 1);
return lreturn;
}
void configClose(int cfgHandle)
{
sceKernelWaitSema(queueSema, 1, 0);
if ((cfgHandle >= numConfigs) ||
(cfgHandle < 0) ||
(configData[cfgHandle] == NULL))
{
sioPrint("Attempt to close bad config handle: ");
sioPrintWord(cfgHandle);
sioPrint("\r\n");
sceKernelSignalSema(queueSema, 1);
return;
}
#if DEBUG_OUTPUT>=3
sioPrint("Valid handle\r\n");
#endif
// We don't do anything about freeing the config slot here,
// since the cost of one slot is just 8 bytes, and we expect that MAX_CONFIGS
// is plenty for all the config files we will be expected to process during
// the lifetime of the PRX invocation.
// free the mem
myFree(configData[cfgHandle]);
configData[cfgHandle] = NULL;
configOffset[cfgHandle] = NULL;
sceKernelSignalSema(queueSema, 1);
}
int module_start(SceSize args, void *argp) __attribute__((alias("_start")));
int _start(SceSize args, void *argp)
{
main();
return 0;
}
/*****************************************************************************/
/* Shut everything down - kill the main thread, unload the modules. */
/*****************************************************************************/
void terminateAll()
{
terminate = 1;
// this seems to fail to unload most of the time, or just crashes in
// GAME150 mode - probably not worth running it, for the time being.
#if 0
if (inputs != NULL)
{
INPUT_INFO *lptr = inputs;
while (lptr)
{
int status, rc;
#if DEBUG_OUTPUT>=2
sioPrint("Shutdown module (");
sioPrintWord(lptr->moduleID);
sioPrint(")...");
#endif
rc = sceKernelStopModule(lptr->moduleID, 0, NULL, &status, NULL);
if (rc < 0)
{
#if DEBUG_OUTPUT>=2
sioPrint("Failed to stop module: ");
sioPrint(lptr->moduleName);
sioPrint(": ");
sioPrintWord(rc);
#endif
}
else
{
rc = sceKernelUnloadModule(lptr->moduleID);
if (rc < 0)
{
#if DEBUG_OUTPUT>=2
sioPrint("Failed to unload module: ");
sioPrint(lptr->moduleName);
sioPrint(": ");
sioPrintWord(rc);
#endif
}
}
sioPrint("\r\n");
lptr = lptr->next;
}
}
if (outputs != NULL)
{
OUTPUT_INFO *lptr = outputs;
while (lptr)
{
int status, rc;
#if DEBUG_OUTPUT>=2
sioPrint("Shutdown module (");
sioPrintWord(lptr->moduleID);
sioPrint(")...");
#endif
rc = sceKernelStopModule(lptr->moduleID, 0, NULL, &status, NULL);
if (rc < 0)
{
#if DEBUG_OUTPUT>=2
sioPrint("Failed to stop module: ");
sioPrint(lptr->moduleName);
sioPrint(": ");
sioPrintWord(rc);
#endif
}
else
{
rc = sceKernelUnloadModule(lptr->moduleID);
if (rc < 0)
{
#if DEBUG_OUTPUT>=2
sioPrint("Failed to unload module: ");
sioPrint(lptr->moduleName);
sioPrint(": ");
sioPrintWord(rc);
#endif
}
}
sioPrint("\r\n");
lptr = lptr->next;
}
}
#endif
sceKernelWaitThreadEnd(pikeythread, 0);
}
/*****************************************************************************/
/* This is apparently never called when running as a VSH OE plugin. */
/*****************************************************************************/
int module_stop(SceSize args, void *argp)
{
#if DEBUG_OUTPUT>=2
sioPrint("---SHUTDOWN---\r\n");
#endif
terminateAll();
return 0;
}
int module_bootstart()
{
#if DEBUG_OUTPUT>=2
sioPrint("---bootstart---\r\n");
#endif
return 0;
}
/*****************************************************************************/
/* This gets called immediately before the transition from VSH to GAME mode */
/* (and presumably vice-versa). */
/* */
/* We don't do anything with this call in piKey. */
/*****************************************************************************/
int module_reboot_before()
{
#if DEBUG_OUTPUT>=2
sioPrint("---boot before---\r\n");
#endif
return 0;
}
/*****************************************************************************/
/* Called 3 times during reboot to GAME mode. arg1 is 3, 2, 1 in the 3 */
/* calls, respectively. */
/*****************************************************************************/
int module_reboot_phase(int arg1)
{
#if DEBUG_OUTPUT>=2
sioPrint("---boot phase--- ");
sioPrintHex(arg1);
sioPrint("\r\n");
#endif
if (arg1 == 3) // first reboot phase
{
terminateAll();
}
return 0;
}
#if 0
Lessons from this crash:
- if a vsh kernel thread does not properly yield (must be delaythread,
waitvblank does not count) then it will not be killed during the reboot
to game mode.
- you can detect the transition via the little-known module_reboot_* funcs
and therefore end a thread loop that doesn't yield.
#endif
|
|
|
| Back to top |
|
 |
jean

Joined: 05 Jan 2008 Posts: 489
|
Posted: Sat Apr 05, 2008 11:03 pm Post subject: |
|
|
It's not "sleep"....it's a freeze, and it's a pikey well known problem. As I PMed you, if you can live without SIO output, just turn off every debug flag you can find.
PS: not a good idea to post that huge code...people gets frightened and doesn't answer! ;) |
|
| Back to top |
|
 |
angelo
Joined: 29 Aug 2007 Posts: 168
|
Posted: Sun Apr 06, 2008 8:42 am Post subject: OK |
|
|
OK,
I just posted it so people have a better idea!
Since piKey is made up of about 9 PRX's, do I have to remove dubugging flags on all six? |
|
| Back to top |
|
 |
jean

Joined: 05 Jan 2008 Posts: 489
|
Posted: Sun Apr 06, 2008 7:51 pm Post subject: |
|
|
| If you take a look to the code you'll figure out by yourself: in "main" pikey plugin the SIO debug functions are defined as proper functions or empty functions depending on the debug flag, so if it's disabled, other modules can safely call it and nothing will happen. i.e you can disable debug only in pikey.c, but it's more elegant not to leave code around calling empty functions.... |
|
| Back to top |
|
 |
angelo
Joined: 29 Aug 2007 Posts: 168
|
Posted: Sun Apr 06, 2008 8:08 pm Post subject: OK |
|
|
Oh I see!
Thanks! |
|
| Back to top |
|
 |
jean

Joined: 05 Jan 2008 Posts: 489
|
Posted: Sun Apr 06, 2008 11:04 pm Post subject: |
|
|
just to save you the time to face the other difficulties like k1 stuff etc, here's my version of pikey working on 3.xx (so on slim&lite, too...)
[[link removed]]
jean
Last edited by jean on Thu Jul 17, 2008 6:15 pm; edited 1 time in total |
|
| Back to top |
|
 |
angelo
Joined: 29 Aug 2007 Posts: 168
|
Posted: Mon Apr 07, 2008 1:05 am Post subject: Burst bubble |
|
|
Sorry to pop your buble jean, but it fails in 3.XX mode. :(
Works fine in VSH and Game150 mode too.
What's the change log? Maybe you and I can swap bit of each others sources so we can improve it!
I've noticed you're using an out of date PSPIRKeyB as this one does repeat it's keys when keys are held down.
Is SIO fixed and that all?
It'll be great to have you on our team as neither of us have a SIO keyboard! |
|
| Back to top |
|
 |
jean

Joined: 05 Jan 2008 Posts: 489
|
Posted: Mon Apr 07, 2008 2:41 am Post subject: |
|
|
SIO is still working in read only mode (when i'll have time i'll try to fix this..promised :) ) and to be honest i only tested VSH mode (that's what i most care about, with my openKeyboard project). This means prx is functional (no changes in usermode NIDs for ctrl hooks)....if you're trying "3.xx game mode" with the same old included sample, then nobody will be surprised it's not working: all measures needed to port old samples to new 3.xx fw are to be taken into account. So, if you code something of your own following the guidelines stated in a bunch of posts here around, it should work (i cannot swear upon old homebrews using old pikey...that's a "client side" issue). I made a quick snapshot of the project as it is on my harddrive, and -to be honest- i'm not interested in a repack with installer and examples for noobs/users at the moment (still work-in-progress...).
PS: see
http://forums.ps2dev.org/viewtopic.php?t=9948&highlight=pikey+mod
for a list of changes... |
|
| Back to top |
|
 |
angelo
Joined: 29 Aug 2007 Posts: 168
|
Posted: Mon Apr 07, 2008 3:19 am Post subject: Oh OK |
|
|
Ok cool.
So only the SIO PRX has been altered. That's cool.
As for all the "Noobz extras", all of that I'm dealing with. Docs, keymaps, tutorials...
It's nice to see that SIO is up and running. What I'll do it this. I'll keep working on piKey for IR and clear up the bugs on that and when SIO is done in the OSK, drop me a PM and I will add the fixed SIO driver to the source and compile it all.
piKey so far is deffinantly usable but not 100% perfect.
Great to see somebody who has work on this!
Angelo |
|
| Back to top |
|
 |
jean

Joined: 05 Jan 2008 Posts: 489
|
Posted: Mon Apr 07, 2008 3:43 am Post subject: Re: Oh OK |
|
|
| angelo wrote: |
So only the SIO PRX has been altered.
|
....nope.... read carefully the post i linked (or alternatively the whole sourcecode :p). |
|
| Back to top |
|
 |
angelo
Joined: 29 Aug 2007 Posts: 168
|
Posted: Mon Apr 07, 2008 6:36 am Post subject: Can't see |
|
|
I cannot see what else has been altered that isn't SIO releated...
It's probably because I'm tired or I'm going BLIND!
Also, I think porting the Sample to 3.XX cannot be done yet.
IRDA fails in 3.XX. How are IRDA users (most of piKey users) going to overcome this? |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|