"Danzeff".
The firmware OSK is nicer but the danzeff OSK can write a bit quicker once you're used to it, provided that it's implemented correctly. That's a big 'if', though. I've seen it used rather poorly in a couple places and very smoothly in others.
There is an OSK sample in the SDK under "sdk/samples/utility/osk".
My OSK code is here:
//OSK utility for RMXP/PSP NetPlay
#ifndef __OSK_H__
#define __OSK_H__
//{SciTE Folding - Includes
#include <psputility.h> //Contains main OSK handling
#include <string.h>
//}
extern unsigned list[];
//{SciTE Folding - Functions
void packUIStr(unsigned short* int_str, char* chr_str, int string_size) { //Converts and int string to a char string. (OSK)
int c;
memset(chr_str, 0, string_size);
for(c = 0; int_str[c]; c++) {
chr_str[c] = int_str[c];
}
}
void expandChrStr(char* chr_str, unsigned short* int_str, int string_size) { //Converts a char string to an int string. (OSK)
int c;
memset(int_str, 0, sizeof(unsigned short) * string_size);
for(c = 0; chr_str[c]; c++) {
int_str[c] = chr_str[c];
}
}
int getStringFromOSK(int string_size, char* buffer, char* desc, char* intext, int lines) {
//{SciTE Folding - Create OSK data structure
SceUtilityOskData data; //Declare an OSK data struct (The OSK needs this setting info to run.)
memset(&data, 0, sizeof(data)); //Set all bytes of the struct to 0
unsigned short int_desc[strlen(desc) + 1]; //Declare an array of unsigned ints to hold our description
expandChrStr(desc, int_desc, strlen(desc) + 1); //Convert our description to a uint array
data.desc = int_desc; //Pass the description pointer into the struct
unsigned short int_intext[strlen(intext) + 1]; //Same thing, but this time it's the text that will appear in the input box
expandChrStr(intext, int_intext, strlen(intext) + 1); //As above
data.intext = int_intext; //Text present in input box at start
data.lines = lines; //Number of lines that can be entered (More than 1 adds an 'enter' ("\n") button to the keypad.)
data.outtextlength = string_size; //Entries in outtext array
data.outtextlimit = string_size - 1; //Number of letters that can be entered (It's - 1 to make room for the trailing NULL)
unsigned short outtext[string_size]; //Here we're creating the int string to receive the input data
memset(outtext, 0, sizeof(unsigned short) * string_size); //And setting its contents to all 0's
data.outtext = outtext; //Then we pass it into the struct, just like the others
data.language = PSP_UTILITY_OSK_LANGUAGE_DEFAULT; //Use the PSP user's chosen language setting
data.unk_24 = 1; //Always set to 1 (Nobody knows...)
data.inputtype = PSP_UTILITY_OSK_INPUTTYPE_ALL; //Stuff that comes up when you push select. (See 'psputility_osk.h')
//}
//{SciTE Folding - Create OSK parameter structure
SceUtilityOskParams osk; //Create the parameter structure (settings for displaying the OSK)
memset(&osk, 0, sizeof(osk)); //Clear its memory with 0's
osk.base.size = sizeof(osk); //Let it know how big this struct is
sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_LANGUAGE, &osk.base.language); //Set the system message language
sceUtilityGetSystemParamInt(PSP_SYSTEMPARAM_ID_INT_UNKNOWN, &osk.base.buttonSwap); //Set the X/O buttonswap based on default
osk.base.graphicsThread = 17; //Thread priority
osk.base.accessThread = 19; //Thread priority
osk.base.fontThread = 18; //Thread priority
osk.base.soundThread = 16; //Thread priority
osk.datacount = 1; //Number of input fields (wth is this?)
osk.data = &data; //Pass it the other struct's location
//}
if(sceUtilityOskInitStart(&osk)) {return 0;} //Start the OSK (hopefully)
int done = 0; //Flag to exit OSK loop
while(!done) { //Process OSK updates until done
//{SciTE Folding - Clear the screen
sceGuStart(GU_DIRECT,list);
sceGuClear(GU_COLOR_BUFFER_BIT | GU_DEPTH_BUFFER_BIT);
sceGuFinish();
sceGuSync(0,0);
//}
switch(sceUtilityOskGetStatus()) { //Operate according to status reported by OSK
case PSP_UTILITY_DIALOG_VISIBLE:
sceUtilityOskUpdate(2); //Instruct the OSK to upate
sceKernelDelayThread(10000); //Slow down to 'normal' speed. Also allows for any callbacks to run more easily.
break;
case PSP_UTILITY_DIALOG_QUIT:
sceUtilityOskShutdownStart(); //Instruct the OSK to shut down.
break;
case PSP_UTILITY_DIALOG_NONE:
done = 1; //Break the loop
break;
}
sceDisplayWaitVblankStart();
flipScreen();
}
//int_str for output is now stored in 'outtext' (same pointer value as data.outtext).
packUIStr(outtext, buffer, string_size); //And now it's packed into a proper char string in our 'return' buffer.
clearScreen(0);
return 1; //Success! :)
}
//}
#endif
It looks very messy in the box there but if you paste it into an editor it should be more clear.
That's intended to be added as a to a project as a seperate file. Then you'd just call
int getStringFromOSK(int string_size, char* buffer, char* desc, char* intext, int lines)
string_size - number of characters in char buffer
buffer - char buffer to fill
desc - description text to appear when OSK runs
intext - text already in the text box when OSK runs
lines - maximum number of lines the OSK is allowed to return
Function returns 0 on failure and 1 on success.
Like the net dialog this requires that the GU is already set up and running.
I'd recommend not using it 'as-is', but rather reading through the code and comments and then writing your own implementation.