danzeff OSK
danzeff OSK
I'm making available the OSK I introduced with AFKIM2 under the BSD license so other projects can make use of it.
It was designed by myself and Jeff Chen from the pspupdates forums.
Latest Version: 2 -- http://localhost.geek.nz/crap/danzeff_src_2.zip
Currently there are only implementations for SDL and the PSP GU, please check the included info and add an implementation for something new :) and I can add it to the official distribution.
Any questions, just ask.
It was designed by myself and Jeff Chen from the pspupdates forums.
Latest Version: 2 -- http://localhost.geek.nz/crap/danzeff_src_2.zip
Currently there are only implementations for SDL and the PSP GU, please check the included info and add an implementation for something new :) and I can add it to the official distribution.
Any questions, just ask.
Last edited by danzel on Wed Apr 26, 2006 2:34 pm, edited 1 time in total.
Hi Danzel and Jeff,
Thanks to have let your work under BSD license. I've just released a CPC emulator (caprice32 port) using your nice keyboard.
PSPCap32
Caprice32 is GNU, so PSPCap32 is also GNU and sources are included.
Thanks to have let your work under BSD license. I've just released a CPC emulator (caprice32 port) using your nice keyboard.
PSPCap32
Caprice32 is GNU, so PSPCap32 is also GNU and sources are included.
The only good is knowledge and the only evil is ignorance.
Thanks to Jesper we now have an implementation for the PSP GU renderer. (No other changes)
Grab the new code at http://localhost.geek.nz/crap/danzeff_src_2.zip
If someone wants to add danzeff to the ps2dev svn then please go ahead, or get me a login and I will do it :)
Grab the new code at http://localhost.geek.nz/crap/danzeff_src_2.zip
If someone wants to add danzeff to the ps2dev svn then please go ahead, or get me a login and I will do it :)
bitstream vera sans mono I think it would be...
The raws are available at: http://localhost.geek.nz/crap/newkey3raw.zip
If you want to take a look, open them with gimp.
The raws are available at: http://localhost.geek.nz/crap/newkey3raw.zip
If you want to take a look, open them with gimp.
danzel: I want to use your OSK,but there are some problems.
psp-gcc -I. -Id:/pspdev/psp/sdk/include -O2 -G0 -Wall -c -o danzeff.o danzeff.c
psp-gcc -I. -Id:/pspdev/psp/sdk/include -O2 -G0 -Wall -L. -Ld:/pspdev/psp/sdk/lib main.o danzeff.o -lpng -lz -lm -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lc -lpspnet -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputility -lpspuser -lpspkernel -o PSP_Mobile.elf
danzeff.o: In function `surface_draw_offset':
danzeff.c:(.text+0x2f4): undefined reference to `sceGuAlphaFunc'
danzeff.c:(.text+0x2fc): undefined reference to `sceGuEnable'
danzeff.c:(.text+0x308): undefined reference to `sceGuTexFunc'
danzeff.c:(.text+0x310): undefined reference to `sceGuTexEnvColor'
danzeff.c:(.text+0x328): undefined reference to `sceGuBlendFunc'
danzeff.c:(.text+0x330): undefined reference to `sceGuEnable'
danzeff.c:(.text+0x344): undefined reference to `sceGuTexMode'
danzeff.c:(.text+0x35c): undefined reference to `sceGuTexImage'
danzeff.c:(.text+0x368): undefined reference to `sceGuTexFunc'
danzeff.c:(.text+0x370): undefined reference to `sceGuGetMemory'
danzeff.c:(.text+0x42c): undefined reference to `sceGuDrawArray'
danzeff.c:(.text+0x434): undefined reference to `sceGuDisable'
danzeff.c:(.text+0x460): undefined reference to `sceGuDisable'
collect2: ld returned 1 exit status
make: *** [PSP_Mobile.elf] Error 1
found that in danzeff.c has included "pspgu.h" . this is why?
psp-gcc -I. -Id:/pspdev/psp/sdk/include -O2 -G0 -Wall -c -o danzeff.o danzeff.c
psp-gcc -I. -Id:/pspdev/psp/sdk/include -O2 -G0 -Wall -L. -Ld:/pspdev/psp/sdk/lib main.o danzeff.o -lpng -lz -lm -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk -lc -lpspnet -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputility -lpspuser -lpspkernel -o PSP_Mobile.elf
danzeff.o: In function `surface_draw_offset':
danzeff.c:(.text+0x2f4): undefined reference to `sceGuAlphaFunc'
danzeff.c:(.text+0x2fc): undefined reference to `sceGuEnable'
danzeff.c:(.text+0x308): undefined reference to `sceGuTexFunc'
danzeff.c:(.text+0x310): undefined reference to `sceGuTexEnvColor'
danzeff.c:(.text+0x328): undefined reference to `sceGuBlendFunc'
danzeff.c:(.text+0x330): undefined reference to `sceGuEnable'
danzeff.c:(.text+0x344): undefined reference to `sceGuTexMode'
danzeff.c:(.text+0x35c): undefined reference to `sceGuTexImage'
danzeff.c:(.text+0x368): undefined reference to `sceGuTexFunc'
danzeff.c:(.text+0x370): undefined reference to `sceGuGetMemory'
danzeff.c:(.text+0x42c): undefined reference to `sceGuDrawArray'
danzeff.c:(.text+0x434): undefined reference to `sceGuDisable'
danzeff.c:(.text+0x460): undefined reference to `sceGuDisable'
collect2: ld returned 1 exit status
make: *** [PSP_Mobile.elf] Error 1
found that in danzeff.c has included "pspgu.h" . this is why?
The one in the first post of this thread?
The current official (c) version with a few modifications lives in the pspradio svn, http://sourceforge.net/svn/?group_id=166538
The current official (c) version with a few modifications lives in the pspradio svn, http://sourceforge.net/svn/?group_id=166538
If you use the GU version of Danzeff, you has to make sure that you have an active displaylist. I've written a short manual in the danzeff_readme.txt file.twuking wrote:danzel: When I used your OSK,I meet the problem,which is that when I run the danzeff_render() function,the psp power off. I found that the program stopped the sceGuAlphaFunc( GU_GREATER, 0, 0xff ) function.Can you tell me this why . I have the psp running on FW2.5
Br, Sandberg
Yep, danzeff_load will load the PNG images from your memory-stick and if that goes okay then danzeff_isinitialized will return true.twuking wrote:Thank you for your reply.
Before I run the danzeff_render() function,I have run the danzeff_load()and danzeff_isinitialized() returns true.There are some anything else,what I didnt do.
But note, there are 3 versions of danzeff in the same file. One which uses SDL, one which uses the GU and one which writes directly to VRAM. Which version that fits your own code best, can be selected by defining it on the command-line. You can see the defines needed, in the sourcecode.
Br, Sandberg
Code: Select all
svn co https://svn.sourceforge.net/svnroot/pspradio/trunk/PSP/SharedLib/danzeff
Compile the vram version with make -f Makefile.vram
Basically that should work. Assuming you have set up your screens etc. ?
I use the GU version in PSPTris my self. The sources are in the PSPRadio subversion repository also (skip the SharedLib/danzeff on checkout). Then under Plugins/GAME_PSPTris you can try to take a look at the code. Just grep for danzeff.
I use the GU version in PSPTris my self. The sources are in the PSPRadio subversion repository also (skip the SharedLib/danzeff on checkout). Then under Plugins/GAME_PSPTris you can try to take a look at the code. Just grep for danzeff.
Br, Sandberg
now my program dont stop! I have fixed it .but still have worked wrongly.
I use the danzeff OSK ,which has sdl and gu. I want to use GU,so I have defined DANZEFF_SCEGU. now letters have inputed correctly,but pics arent showed.
Code: Select all
#include <pspkernel.h>
#include <pspdebug.h>
#include <stdlib.h>
#include <string.h>
#include <pspgu.h>
#include "danzeff.h"
#define printf pspDebugScreenPrintf
static unsigned int __attribute__((aligned(16))) list[262144];
PSP_MODULE_INFO("PSP_Mobile", 0, 1, 1);
int done = 0;
// Exit callback
int exit_callback(int arg1, int arg2, void *common)
{
done = 1;
sceKernelExitGame();
return 0;
}
// Callback thread
int CallbackThread(SceSize args, void *argp)
{
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
return 0;
}
// Sets up the callback thread and returns its thread id
int SetupCallbacks(void)
{
int thid = 0;
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
if(thid >= 0)
{
sceKernelStartThread(thid, 0, 0);
}
return thid;
}
int main(void)
{
SceCtrlData pad;
char key;
pspDebugScreenInit();
SetupCallbacks();
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
danzeff_load();
if (!(danzeff_isinitialized()))
{
return 0;
}
danzeff_moveTo(0,0);
while(!done)
{
if(danzeff_dirty())
{
sceGuInit();
sceGuStart(GU_DIRECT,list);
danzeff_render();
sceGuFinish();
}
pspDebugScreenSetXY(0, 8);
sceCtrlReadBufferPositive(&pad, 1);
key=danzeff_readInput(pad);
switch (key)
{
case 0:
printf("You have pressed nothing!\n");
break;
case 8:
case '\n':
case DANZEFF_LEFT:
case DANZEFF_RIGHT:
case DANZEFF_SELECT:
case DANZEFF_START:
printf("You have put the unshowed key\n");
break;
default:
printf("You have input the key %c\n",key);
waitOneSecond();
break;
}
printf("Analog X = %d ", pad.Lx);
printf("Analog Y = %d \n", pad.Ly);
pspDebugScreenSetXY(0, 15);
if (pad.Buttons != 0){
if (pad.Buttons & PSP_CTRL_SQUARE){
printf("Square pressed \n");
}
if (pad.Buttons & PSP_CTRL_TRIANGLE){
printf("Triangle pressed \n");
}
if (pad.Buttons & PSP_CTRL_CIRCLE){
printf("Cicle pressed \n");
}
if (pad.Buttons & PSP_CTRL_CROSS){
printf("Cross pressed \n");
}
if (pad.Buttons & PSP_CTRL_UP){
printf("Up pressed \n");
}
if (pad.Buttons & PSP_CTRL_DOWN){
printf("Down pressed \n");
}
if (pad.Buttons & PSP_CTRL_LEFT){
printf("Left pressed \n");
}
if (pad.Buttons & PSP_CTRL_RIGHT){
printf("Right pressed \n");
}
if (pad.Buttons & PSP_CTRL_START){
printf("Start pressed \n");
}
if (pad.Buttons & PSP_CTRL_SELECT){
printf("Select pressed \n");
}
if (pad.Buttons & PSP_CTRL_LTRIGGER){
printf("L-trigger pressed \n");
}
if (pad.Buttons & PSP_CTRL_RTRIGGER){
printf("R-trigger pressed \n");
}
}
}
sceKernelExitGame();
return 0;
}
danzeff.c
Code: Select all
#include "danzeff.h"
// headerfiles needed for the GU version
#ifdef DANZEFF_SCEGU
#include <malloc.h>
#include "pspkernel.h"
#include "pspgu.h"
#include "png.h"
#endif // #ifdef DANZEFF_SCEGU
#define debug
#define printf pspDebugScreenPrintf
#define false 0
#define true 1
// structures used for drawing the keyboard
#ifdef DANZEFF_SCEGU
struct danzeff_vertex
{
float u, v;
unsigned int color;
float x,y,z;
};
struct danzeff_gu_surface
{
u32 surface_width;
u32 surface_height;
u32 texture_width;
u32 texture_height;
u32 *texture;
};
#endif //#ifdef DANZEFF_SCEGU
/*bool*/ int holding = false; //user is holding a button
/*bool*/ int dirty = true; //keyboard needs redrawing
/*bool*/ int shifted = false; //user is holding shift
int mode = 0; //charset selected. (0 - letters or 1 - numbers)
/*bool*/ int initialized = false; //keyboard is initialized
//Position on the 3-3 grid the user has selected (range 0-2)
int selected_x = 1;
int selected_y = 1;
//Variable describing where each of the images is
#define guiStringsSize 12 /* size of guistrings array */
#define PICS_BASEDIR "./graphics/"
char *guiStrings[] =
{
PICS_BASEDIR "keys.png", PICS_BASEDIR "keys_t.png", PICS_BASEDIR "keys_s.png",
PICS_BASEDIR "keys_c.png", PICS_BASEDIR "keys_c_t.png", PICS_BASEDIR "keys_s_c.png",
PICS_BASEDIR "nums.png", PICS_BASEDIR "nums_t.png", PICS_BASEDIR "nums_s.png",
PICS_BASEDIR "nums_c.png", PICS_BASEDIR "nums_c_t.png", PICS_BASEDIR "nums_s_c.png"
};
//amount of modes (non shifted), each of these should have a corresponding shifted mode.
#define MODE_COUNT 2
//this is the layout of the keyboard
char modeChar[MODE_COUNT*2][3][3][5] =
{
{ //standard letters
{ ",abc", ".def","!ghi" },
{ "-jkl","\010m n", "?opq" },
{ "(rst", ":uvw",")xyz" }
},
{ //capital letters
{ "^ABC", "@DEF","*GHI" },
{ "_JKL","\010M N", "\"OPQ" },
{ "=RST", ";UVW","/XYZ" }
},
{ //numbers
{ "\0\0\0001","\0\0\0002","\0\0\0003" },
{ "\0\0\0004", "\010\0 5","\0\0\0006" },
{ "\0\0\0007","\0\0\0008", "\0\00009" }
},
{ //special characters
{ "'(.)", "\"<'>","-[_]" },
{ "!{?}","\010\0 \0", "+\\=/" },
{ ":@;#", "~$`%","*^|&" }
}
};
/*bool*/ int danzeff_isinitialized()
{
return initialized;
}
/*bool*/ int danzeff_dirty()
{
return dirty;
}
/** Attempts to read a character from the controller
* If no character is pressed then we return 0
* Other special values: 1 = move left, 2 = move right, 3 = select, 4 = start
* Every other value should be a standard ascii value.
* An unsigned int is returned so in the future we can support unicode input
*/
unsigned int danzeff_readInput(SceCtrlData pspctrl)
{
//Work out where the analog stick is selecting
int x = 1;
int y = 1;
if (pspctrl.Lx < 85) x -= 1;
else if (pspctrl.Lx > 170) x += 1;
if (pspctrl.Ly < 85) y -= 1;
else if (pspctrl.Ly > 170) y += 1;
if (selected_x != x || selected_y != y) //If they've moved, update dirty
{
dirty = true;
selected_x = x;
selected_y = y;
}
//if they are changing shift then that makes it dirty too
if ((!shifted && (pspctrl.Buttons & PSP_CTRL_RTRIGGER)) || (shifted && !(pspctrl.Buttons & PSP_CTRL_RTRIGGER)))
dirty = true;
unsigned int pressed = 0; //character they have entered, 0 as that means 'nothing'
shifted = (pspctrl.Buttons & PSP_CTRL_RTRIGGER)?true:false;
if (!holding)
{
if (pspctrl.Buttons& (PSP_CTRL_CROSS|PSP_CTRL_CIRCLE|PSP_CTRL_TRIANGLE|PSP_CTRL_SQUARE)) //pressing a char select button
{
int innerChoice = 0;
if (pspctrl.Buttons & PSP_CTRL_TRIANGLE)
innerChoice = 0;
else if (pspctrl.Buttons & PSP_CTRL_SQUARE)
innerChoice = 1;
else if (pspctrl.Buttons & PSP_CTRL_CROSS)
innerChoice = 2;
else //if (pspctrl.Buttons & PSP_CTRL_CIRCLE)
innerChoice = 3;
//Now grab the value out of the array
pressed = modeChar[ mode*2 + shifted][y][x][innerChoice];
}
else if (pspctrl.Buttons& PSP_CTRL_LTRIGGER) //toggle mode
{
dirty = true;
mode++;
mode %= MODE_COUNT;
}
else if (pspctrl.Buttons& PSP_CTRL_DOWN)
{
pressed = '\n';
}
else if (pspctrl.Buttons& PSP_CTRL_UP)
{
pressed = 8; //backspace
}
else if (pspctrl.Buttons& PSP_CTRL_LEFT)
{
pressed = DANZEFF_LEFT; //LEFT
}
else if (pspctrl.Buttons& PSP_CTRL_RIGHT)
{
pressed = DANZEFF_RIGHT; //RIGHT
}
else if (pspctrl.Buttons& PSP_CTRL_SELECT)
{
pressed = DANZEFF_SELECT; //SELECT
}
else if (pspctrl.Buttons& PSP_CTRL_START)
{
pressed = DANZEFF_START; //START
}
}
holding = pspctrl.Buttons & ~PSP_CTRL_RTRIGGER; //RTRIGGER doesn't set holding
return pressed;
}
///-------------------------------------------------------------------------------
///These are specific to the implementation, they should have the same behaviour across implementations.
///-------------------------------------------------------------------------------
///-------------------------------------------------------------------------------
///This is the original SDL implementation
#ifdef DANZEFF_SDL
SDL_Surface* keyBits[guiStringsSize];
int keyBitsSize = 0;
int moved_x = 0, moved_y = 0; // location that we are moved to
///variable needed for rendering in SDL, the screen surface to draw to, and a function to set it!
SDL_Surface* danzeff_screen;
SDL_Rect danzeff_screen_rect;
void danzef_set_screen(SDL_Surface* screen)
{
danzeff_screen = screen;
danzeff_screen_rect.x = 0;
danzeff_screen_rect.y = 0;
danzeff_screen_rect.h = screen->h;
danzeff_screen_rect.w = screen->w;
}
///Internal function to draw a surface internally offset
//Render the given surface at the current screen position offset by screenX, screenY
//the surface will be internally offset by offsetX,offsetY. And the size of it to be drawn will be intWidth,intHeight
void surface_draw_offset(SDL_Surface* pixels, int screenX, int screenY, int offsetX, int offsetY, int intWidth, int intHeight)
{
//move the draw position
danzeff_screen_rect.x = moved_x + screenX;
danzeff_screen_rect.y = moved_y + screenY;
//Set up the rectangle
SDL_Rect pixels_rect;
pixels_rect.x = offsetX;
pixels_rect.y = offsetY;
pixels_rect.w = intWidth;
pixels_rect.h = intHeight;
SDL_BlitSurface(pixels, &pixels_rect, danzeff_screen, &danzeff_screen_rect);
}
///Draw a surface at the current moved_x, moved_y
void surface_draw(SDL_Surface* pixels)
{
surface_draw_offset(pixels, 0, 0, 0, 0, pixels->w, pixels->h);
}
/* load all the guibits that make up the OSK */
void danzeff_load()
{
if (initialized) return;
int a;
for (a = 0; a < guiStringsSize; a++)
{
keyBits[a] = IMG_Load(guiStrings[a]);
if (keyBits[a] == NULL)
{
//ERROR! out of memory.
//free all previously created surfaces and set initialized to false
int b;
for (b = 0; b < a; b++)
{
SDL_FreeSurface(keyBits[b]);
keyBits[b] = NULL;
}
initialized = false;
return;
}
}
initialized = true;
}
/* remove all the guibits from memory */
void danzeff_free()
{
if (!initialized) return;
int a;
for (a = 0; a < guiStringsSize; a++)
{
SDL_FreeSurface(keyBits[a]);
keyBits[a] = NULL;
}
initialized = false;
}
/* draw the keyboard at the current position */
void danzeff_render()
{
printf("Drawing Keyboard at %i,%i\n", selected_x, selected_y);
dirty = false;
///Draw the background for the selected keyboard either transparent or opaque
///this is the whole background image, not including the special highlighted area
//if center is selected then draw the whole thing opaque
if (selected_x == 1 && selected_y == 1)
surface_draw(keyBits[6*mode + shifted*3]);
else
surface_draw(keyBits[6*mode + shifted*3 + 1]);
///Draw the current Highlighted Selector (orange bit)
surface_draw_offset(keyBits[6*mode + shifted*3 + 2],
//Offset from the current draw position to render at
selected_x*43, selected_y*43,
//internal offset of the image
selected_x*64,selected_y*64,
//size to render (always the same)
64, 64);
}
/* move the position the keyboard is currently drawn at */
void danzeff_moveTo(const int newX, const int newY)
{
moved_x = newX;
moved_y = newY;
}
#endif //DANZEFF_SDL
///-------------------------------------------------------------------------------
///This is the GU implementation
#ifdef DANZEFF_SCEGU
struct danzeff_gu_surface keyTextures[guiStringsSize];
int moved_x = 0, moved_y = 0; // location that we are moved to
///Internal function to draw a surface internally offset
//Render the given surface at the current screen position offset by screenX, screenY
//the surface will be internally offset by offsetX,offsetY. And the size of it to be drawn will be intWidth,intHeight
void surface_draw_offset(struct danzeff_gu_surface* surface, int screenX, int screenY, int offsetX, int offsetY, int intWidth, int intHeight)
{
sceGuAlphaFunc( GU_GREATER, 0, 0xff );
sceGuEnable( GU_ALPHA_TEST );
sceGuTexFunc(GU_TFX_BLEND,GU_TCC_RGBA);
sceGuTexEnvColor(0xFF000000);
sceGuBlendFunc( GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0 );
sceGuEnable( GU_BLEND );
sceGuTexMode(GU_PSM_8888,0,0,GU_FALSE);
sceGuTexImage(0,surface->surface_width, surface->surface_height,surface->surface_width, surface->texture);
sceGuTexFunc(GU_TFX_MODULATE,GU_TCC_RGBA);
struct danzeff_vertex* c_vertices = (struct danzeff_vertex*)sceGuGetMemory(2 * sizeof(struct danzeff_vertex));
c_vertices[0].u = offsetX;
c_vertices[0].v = offsetY;
c_vertices[0].x = moved_x + screenX;
c_vertices[0].y = moved_y + screenY;
c_vertices[0].z = 0;
c_vertices[0].color = 0xFFFFFFFF;
c_vertices[1].u = offsetX + intWidth;
c_vertices[1].v = offsetY + intHeight;
c_vertices[1].x = moved_x + screenX + intWidth;
c_vertices[1].y = moved_y + screenY + intHeight;
c_vertices[1].z = 0;
c_vertices[1].color = 0xFFFFFFFF;
sceGuDrawArray(GU_SPRITES,GU_TEXTURE_32BITF|GU_COLOR_8888|GU_VERTEX_32BITF|GU_TRANSFORM_2D,2,0,c_vertices);
sceGuDisable( GU_BLEND );
sceGuDisable( GU_ALPHA_TEST );
}
void danzeff_block_copy(struct danzeff_gu_surface* surface, u32 *texture)
{
u32 *dest = surface->texture;
u32 stride = surface->surface_width - surface->texture_width;
u32 y, x;
for (y = 0 ; y < surface->texture_height ; y++)
{
for (x = 0 ; x < surface->texture_width ; x++)
{
*dest++ = *texture++;
}
// skip at the end of each line
if (stride > 0)
{
dest += stride;
}
}
}
static void danzeff_user_warning_fn(png_structp png_ptr, png_const_charp warning_msg)
{
// ignore PNG warnings
}
/* Get the width and height of a png image */
int danzeff_get_png_image_size(const char* filename, u32 *png_width, u32 *png_height)
{
png_structp png_ptr;
png_infop info_ptr;
unsigned int sig_read = 0;
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
FILE *fp;
if ((fp = fopen(filename, "rb")) == NULL) return -1;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
fclose(fp);
return -1;
}
png_set_error_fn(png_ptr, (png_voidp) NULL, (png_error_ptr) NULL, danzeff_user_warning_fn);
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
fclose(fp);
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
return -1;
}
png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, sig_read);
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL);
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
fclose(fp);
*png_width = width;
*png_height = height;
return 0;
}
/* Load a texture from a png image */
int danzeff_load_png_image(const char* filename, u32 *ImageBuffer)
{
png_structp png_ptr;
png_infop info_ptr;
unsigned int sig_read = 0;
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
size_t x, y;
u32* line;
FILE *fp;
if ((fp = fopen(filename, "rb")) == NULL) return -1;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL) {
fclose(fp);
return -1;
}
png_set_error_fn(png_ptr, (png_voidp) NULL, (png_error_ptr) NULL, danzeff_user_warning_fn);
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
fclose(fp);
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
return -1;
}
png_init_io(png_ptr, fp);
png_set_sig_bytes(png_ptr, sig_read);
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL);
png_set_strip_16(png_ptr);
png_set_packing(png_ptr);
if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_gray_1_2_4_to_8(png_ptr);
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
line = (u32*) malloc(width * 4);
if (!line) {
fclose(fp);
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
return -1;
}
for (y = 0; y < height; y++)
{
png_read_row(png_ptr, (u8*) line, png_bytep_NULL);
for (x = 0; x < width; x++)
{
ImageBuffer[y*width+x] = line[x];
}
}
free(line);
png_read_end(png_ptr, info_ptr);
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
fclose(fp);
return 0;
}
u32 danzeff_convert_pow2(u32 size)
{
u32 pow_counter = 0;
for ( ; pow_counter < 32 ; pow_counter++)
{
// Find the first value which is higher
if ((size >> pow_counter) == 0)
{
// take already good values into account
if ((1 << pow_counter) != size)
{
return (1 << pow_counter);
}
else
{
return (1 << (pow_counter-1));
}
}
}
return 0;
}
/* load all the guibits that make up the OSK */
void danzeff_load()
{
u32 *temp_texture;
if (initialized) return;
int a;
for (a = 0; a < guiStringsSize; a++)
{
u32 height, width;
if (danzeff_get_png_image_size(guiStrings[a], &width, &height) == 0)
{
// The png is always converted to PSM_8888 format when read
temp_texture = (u32 *)malloc(width*height*4);
if (danzeff_load_png_image(guiStrings[a], temp_texture) != 0)
{
// Error .. Couldn't get png info from one of the needed files
int b;
for (b = 0; b < a; b++)
{
free(keyTextures[b].texture);
keyTextures[b].texture = NULL;
}
initialized = false;
return;
}
else
{
// we need to store the texture in an image of width and heights of 2^n sizes
keyTextures[a].texture_width = (float)width;
keyTextures[a].texture_height = (float)height;
keyTextures[a].surface_width = (float)danzeff_convert_pow2(width);
keyTextures[a].surface_height = (float)danzeff_convert_pow2(height);
keyTextures[a].texture = (u32 *)malloc(keyTextures[a].surface_width*keyTextures[a].surface_height*4);
// block copy the texture into the surface
danzeff_block_copy(&keyTextures[a], temp_texture);
free(temp_texture);
}
}
else
{
// Error .. Couldn't get png info from one of the needed files
int b;
for (b = 0; b < a; b++)
{
free(keyTextures[b].texture);
keyTextures[b].texture = NULL;
}
initialized = false;
return;
}
}
initialized = true;
}
/* remove all the guibits from memory */
void danzeff_free()
{
if (!initialized) return;
int a;
for (a = 0; a < guiStringsSize; a++)
{
free(keyTextures[a].texture);
keyTextures[a].texture = NULL;
}
initialized = false;
}
/* draw the keyboard at the current position */
void danzeff_render()
{
dirty = false;
///Draw the background for the selected keyboard either transparent or opaque
///this is the whole background image, not including the special highlighted area
//if center is selected then draw the whole thing opaque
if (selected_x == 1 && selected_y == 1)
surface_draw_offset(&keyTextures[6*mode + shifted*3], 0, 0, 0, 0, keyTextures[6*mode + shifted*3].texture_width,
keyTextures[6*mode + shifted*3].texture_height);
else
surface_draw_offset(&keyTextures[6*mode + shifted*3 + 1], 0, 0, 0, 0, keyTextures[6*mode + shifted*3 + 1].texture_width,
keyTextures[6*mode + shifted*3 + 1].texture_height);
#ifdef debug
printf(" First surface_draw_offset() has ran \n");
#endif
///Draw the current Highlighted Selector (orange bit)
surface_draw_offset(&keyTextures[6*mode + shifted*3 + 2],
//Offset from the current draw position to render at
selected_x*43, selected_y*43,
//internal offset of the image
selected_x*64,selected_y*64,
//size to render (always the same)
64, 64);
#ifdef debug
printf(" Second surface_draw_offset() has ran \n");
#endif
}
/* move the position the keyboard is currently drawn at */
void danzeff_moveTo(const int newX, const int newY)
{
moved_x = newX;
moved_y = newY;
}
#endif //DANZEFF_SCEGU