[PSP] menú de un inexperto (el código)

Pues bien, después de hacer mis primeras cosillas con C y PSPSDK decidí hacer un "intento" de menú con la primera manera que se me ocurrió, antes de que veais el código y os riais de mí, he de deciros que solo he tocado C durante dos dias, no tenia ni idea de esto, y creo que tampoco avanzo mucho xD.

Este menú es una mierdecilla, no me mateis con los post [buuuaaaa]

Pues bien... (redoble de tambores...)
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <pspctrl.h>
#include <pspkerneltypes.h>

PSP_MODULE_INFO("Pyronhell", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR(0);

#define printf pspDebugScreenPrintf

void clearscreen() {
     sceDisplayWaitVblankStart();
     pspDebugScreenClear();
}

/* Llamada de salida */
int menu = 1;
int submenu = 1;
int posiciones = 4;
int posicion = 1;
int en_menu = 1;
int pulsada = 0;
typedef int fichero;
SceCtrlData controles;
/*
int exit_callback(int arg1, int arg2, void *common) {
          sceKernelExitGame();
          return 0;
}

int CallbackThread(SceSize args, void *argp) {
          int cbid;

          cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
          sceKernelRegisterExitCallback(cbid);

          sceKernelSleepThreadCB();

          return 0;
}

int SetupCallbacks(void) {
          int thid = 0;

          thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
          if(thid >= 0) {
                    sceKernelStartThread(thid, 0, 0);
          }

          return thid;
}

*/

void show_menu() {
     en_menu = 1;
     clearscreen();
     if (menu==1) {
        if (submenu==1) {
          printf("[");
          if (posicion==1) { printf("X"); } else { printf(" "); }
          printf("] Gestion de ficheros\n");
          printf("[");
          if (posicion==2) { printf("X"); } else { printf(" "); }
          printf("] Lanzar un EBOOT\n");
          printf("[");
          if (posicion==3) { printf("X"); } else { printf(" "); }
          printf("] Ver botones\n");
          printf("[");
          if (posicion==4) { printf("X"); } else { printf(" "); }
          printf("] Salir");
        }
     }
     if (menu==2) {
        if (submenu==1) {
          printf("[");
          if (posicion==1) { printf("X"); } else { printf(" "); }
          printf("] Comprobar config.txt\n");
          printf("[");
          if (posicion==2) { printf("X"); } else { printf(" "); }
          printf("] Borrar config.txt\n");
          printf("[");
          if (posicion==3) { printf("X"); } else { printf(" "); }
          printf("] Crear config.txt\n");
          printf("[");
          if (posicion==4) { printf("X"); } else { printf(" "); }
          printf("] Volver al menu principal");
        }
     }
}

void launch() {
     en_menu = 0;
     if (menu==1) {
        if (submenu==1) {
           if (posicion==1) {
              menu = 2;
              submenu = 1;
              posiciones = 4;
              show_menu();
              }                 
           if (posicion==4) {
              sceKernelExitGame();
           }
        }
     }
     if (menu==2) {
        if (submenu==1) {
           if (posicion==1) {
              clearscreen();   
              en_menu = 0;         
              printf("Comprobando que exista ms0:/config.txt...\n");
                  if (!sceIoOpen("ms0:/config.txt", PSP_O_RDONLY, 0777)) {
                     printf("El archivo ms0:/config.txt NO existe!!\n");
                     printf("Pulsa O para continuar..."); 
                                while(1) {
                                sceCtrlReadBufferPositive(&controles, 1);
                                if (controles.Buttons & PSP_CTRL_CIRCLE) {
                                  break;
                                }
                                }
                  } else {
                      printf("El archivo ms0:/config.txt existe\n");
                      printf("Pulsa O para continuar...");   
                                while(1) {
                                sceCtrlReadBufferPositive(&controles, 1);
                                if (controles.Buttons & PSP_CTRL_CIRCLE) {
                                  break;
                                }
                                }
                  } 
              en_menu = 1;
              show_menu(); 
           }
           if (posicion==2) {
              menu = 1;
              submenu = 1;
              posiciones = 4;
              show_menu(); 
           }
           if (posicion==3) {
              menu = 1;
              submenu = 1;
              posiciones = 4;
              show_menu(); 
           }       
           if (posicion==4) {
              menu = 1;
              submenu = 1;
              posiciones = 4;
              show_menu(); 
           }
        }
     }
}


int main() {
pspDebugScreenInit();

show_menu();
for (;;) {
if (en_menu) {
        while(1) {
        sceCtrlReadBufferPositive(&controles, 1);
                 if (controles.Buttons & PSP_CTRL_DOWN) {
                   posicion++;
                   if (posicion > posiciones) { posicion = posiciones; }
                   pulsada = 1;
                   show_menu();
                }
                if (controles.Buttons & PSP_CTRL_UP) {
                    posicion--;
                    if (posicion < 1) { posicion = 1; }
                    pulsada = 1;
                    show_menu();
                }
                if (controles.Buttons & PSP_CTRL_CROSS) {
                    pulsada = 1;
                    launch();
                }
          }
       
}
}

sceKernelSleepThread();
return 0;
}
Creo que sí que iba pero con el problemilla de que no consegui que las teclas se parasen y eso... por favor los grandes de estas cosas no os riais mucho y decidme que tal voy anda, y ayudadme a mejorar que saber C nunca viene mal del todo ;)

Salu2

PD: A ver si nos abren el dichoso subforoooooooooo
parece que está bastante bien algo simple pero bien, te acosejaría el uso de swicht( ) y case: por lo demás si es lo que querías conseguir te vale
saulotmalo escribió:parece que está bastante bien algo simple pero bien, te acosejaría el uso de swicht( ) y case: por lo demás si es lo que querías conseguir te vale

Si, en PHP estoy muy acostumbrado a usarlo, lo que pasa que en C no se como es la sintaxis correcta, por eso no lo he usado.

En PHP es así:
switch($variable) {
case(opcion):
// cosas de la opción
break;
default:
// cosas de la opción por defecto
break;
}


¿Cómo es su sintaxis en C?

Respecto a lo del menú, no hace todo lo que yo quiero, pero como es la primera vez que toco C y tal he usado lo primero que se me ha venido a la cabeza.
switch(variable) {
case(valor):
// cosas de la opción
break;
default:
// cosas de la opción por defecto
break;
}

así es en c/c++ ;) lo tendrás fácil esto hace que vaya más rápido al ejecutarlo si compilas con -O2 ( o debería ).
Puedes usar el syscall sceKernelDelayThread()

Le tienes que pasar un entero, que creo que es en milisegundos, conseguiras que vaya mas lento con el boton pulsado. Prueba con 180000.

Te recomiendo que pongas uno dentro de cada if de subir y bajar del bucle de main.

Salu2!
LLevo tiempo preguntandome como hacer para que en un programa me reconozca una pulsacion desde que aprieto asta que suelto y no 15 pulsaciones o asi en un toke rapido

mirando otros codigos y tal pero no logro hacer nada

1º pense q con esto
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); ( saque la conclusion que era esto viendo algun codigo )

pero como el pspDebugScreenSetXY(x, y); solo me funciono en un codigo y me lo ponia en unas coordenadas que no eran las indicadas no se q pensar
Un año programando en c++ y no me entero de nada [+risas] [+risas] [+risas]

Lo que hace la educación pública... [mad]
Zor escribió:Un año programando en c++ y no me entero de nada [+risas] [+risas] [+risas]

Lo que hace la educación pública... [mad]


educación y publica en una misma frase?? curioso xD

kyp mmm no podrías guardar una variable que cuando esté pulsado se ponga a 1 y cuando se suelte a 0? y luego comparar?? esque la verdad yo al gastar glut o lte esto no sé como funciona del todo...


pd: Más argumentos que post como este para el foro de programación... no sé que quieren
El codigo tiene buena pinta , lo unico que veo es que abusas un poco de los condicionales , y entre eso , y la identacion del codigo , se hace dificil de entender.

Te recomiendo que en lugar de emplear variables globales crees un struct con las variables necesarias y lo pases a las funciones.

Despues de esto , te animo a que sigas , pues para llevar solo 2 dias esta muy pero que muy bien , de hecho empezar con la psp es mucho mas dificil que programar para pc . :-)


Edit : por ejemplo aqui , puedes utilizar el modulo para que el menu sea circular(si pasas de la ultima opcion , se va a la primera , y de paso te ahorras un condicional)
if (controles.Buttons & PSP_CTRL_DOWN) {
                   posicion++;
                   if (posicion > posiciones) { posicion = posiciones; }
                   pulsada = 1;
                   show_menu();
                }


asi:

if (controles.Buttons & PSP_CTRL_DOWN) {
                   posicion = posicion % posiciones +1;
                   pulsada = 1;
                   show_menu();
                }


o para que haga lo mismo que el tuyo pero ahorrando modificar la variable 2 veces

if (controles.Buttons & PSP_CTRL_DOWN) {
                   if (posicion < posiciones)
                            posicion++;
                   pulsada = 1;
                   show_menu();
                }


Parece que lo de si la tecla esta pulsada no lo has cogido del todo.

Otra cosa, en el si guiente fragmento , veo 2 cosas que no me gustan , primero los bucles infinitos while(1) , la verdad es que el codigo funciona , pero es mas elegante poner una condicion
                     printf("Pulsa O para continuar..."); 
                                while(1) {
                                sceCtrlReadBufferPositive(&controles, 1);
                                if (controles.Buttons & PSP_CTRL_CIRCLE) {
                                  break;
                                }


quedaria algo como esto
                     printf("Pulsa O para continuar..."); 
                     do
                               sceCtrlReadBufferPositive(&controles, 1);
                     while( ! (controles.Buttons & PSP_CTRL_CIRCLE) );

}
por ultimo , en este trozo , para 3 condiciones se hace lo mismo , por tanto se pueden agrupar
           if (posicion==2) {
              menu = 1;
              submenu = 1;
              posiciones = 4;
              show_menu(); 
           }
           if (posicion==3) {
              menu = 1;
              submenu = 1;
              posiciones = 4;
              show_menu(); 
           }       
           if (posicion==4) {
              menu = 1;
              submenu = 1;
              posiciones = 4;
              show_menu(); 
           }
        }


asi

if (posicion==2 || posicion == 3 || posicion == 4) {
              menu = 1;
              submenu = 1;
              posiciones = 4;
              show_menu(); 
           }


o incluso si solo va hasta el 4:

if (posicion > 4) {
              menu = 1;
              submenu = 1;
              posiciones = 4;
              show_menu(); 
           }


Por cierto , si las condiciones son excluyentes ( por ejemplo si un numero es = 3 no puede ser = 4 , es mejor poner else if en lugar de if , pues te ahorras esas comparaciones inutiles ( o un switch , que es lo mismo )
Como ya t han dixo, abusas d los condicionales, x ejemplo:
if (menu==1) {
if (submenu==1) {

Aunq ese es d 2, he llegado a ver d hasta 3 o 4 niveles xD.
Y la mayoria los podrias solucionar con un:
if (menu && submenu) {

(este es a partir dl q he citado antes)
Salu2
BlackSith escribió:Como ya t han dixo, abusas d los condicionales, x ejemplo:

Aunq ese es d 2, he llegado a ver d hasta 3 o 4 niveles xD.
Y la mayoria los podrias solucionar con un:

(este es a partir dl q he citado antes)
Salu2


creo que como tu propones no tiene sentido( si es como yo lo entiendo ) ya que hay siempre te dirá que si porque trataría igual menu(valiendo 1 ) que menu (valiendo 2 ) ya que en los dos es true y creo que el lo hace para diferenciar los distintos casos, lo que tu has hecho se suele hacer para comprobar una condicion de que se cumple algo
saulotmalo escribió:creo que como tu propones no tiene sentido( si es como yo lo entiendo ) ya que hay siempre te dirá que si porque trataría igual menu(valiendo 1 ) que menu (valiendo 2 ) ya que en los dos es true y creo que el lo hace para diferenciar los distintos casos, lo que tu has hecho se suele hacer para comprobar una condicion de que se cumple algo

X eso aclare q era para lo primero q cité ;). Con eso queria matar 2 pajaros d un tiro: el uso dl operador logico && y lo otro era para resumir el codigo, ya q no existia un submenu 2 dentro dl primer if.
Salu2
uys perdon :$ jejej weno entonces vale pensaba que era para el primer código :) no pasa res...
Muchas gracias por toda la ayuda recibida, es de agradecer ^^

He "arreglado" un poco el "homebrew", gracias a un par de cosas que me habeis dicho.
He conseguido poner el switch() sin problemas, el sceKernelDelayThread() y ahora ya parece algo más profesional y todo.
Le he puesto una pijadita es ASCII xD

Queda algo así (en la PSP):
Imagen

El Código:
#include <pspkernel.h>
#include <pspiofilemgr.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <pspctrl.h>
#include <pspkerneltypes.h>

PSP_MODULE_INFO("Pyronhell", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR(0);

#define printf pspDebugScreenPrintf

void clearscreen() {
     sceDisplayWaitVblankStart();
     pspDebugScreenClear();
}

/* Llamada de salida */
int menu = 1;
int submenu = 1;
int posiciones = 4;
int posicion = 1;
int en_menu = 1;
int pulsada = 0;
typedef int fichero;
SceCtrlData controles;
/*
int exit_callback(int arg1, int arg2, void *common) {
          sceKernelExitGame();
          return 0;
}

int CallbackThread(SceSize args, void *argp) {
          int cbid;

          cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
          sceKernelRegisterExitCallback(cbid);

          sceKernelSleepThreadCB();

          return 0;
}

int SetupCallbacks(void) {
          int thid = 0;

          thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
          if(thid >= 0) {
                    sceKernelStartThread(thid, 0, 0);
          }

          return thid;
}

*/

void show_menu() {
     en_menu = 1;
     clearscreen();
        printf("                                   .__           .__  .__   \n");
        printf("______ ___.__._______  ____   ____ |  |__   ____ |  | |  |  \n");
        printf("\\____ <   |  |\\_  __ \\/  _ \\ /    \\|  |  \\_/ __ \\|  | |  |  \n");
        printf("|  |_> >___  | |  | \\(  <_> )   |  \\   Y  \\  ___/|  |_|  |__\n");
        printf("|   __// ____| |__|   \\____/|___|  /___|  /\\___  >____/____/\n");
        printf("|__|   \\/                        \\/     \\/     \\/           \n\n\n");
     switch(menu) {
     case(1):
        if (submenu==1) {
          printf("[");
          if (posicion==1) { printf("X"); } else { printf(" "); }
          printf("] Gestion de ficheros ->\n");
          printf("[");
          if (posicion==2) { printf("X"); } else { printf(" "); }
          printf("] Lanzar un EBOOT (PSP/GAME/holamundo/EBOOT.PBP)\n");
          printf("[");
          if (posicion==3) { printf("X"); } else { printf(" "); }
          printf("] Ver botones\n");
          printf("[");
          if (posicion==4) { printf("X"); } else { printf(" "); }
          printf("] Salir");
        }
     break;
     case(2):
        if (submenu==1) {
          printf("[");
          if (posicion==1) { printf("X"); } else { printf(" "); }
          printf("] Comprobar config.txt\n");
          printf("[");
          if (posicion==2) { printf("X"); } else { printf(" "); }
          printf("] Borrar config.txt\n");
          printf("[");
          if (posicion==3) { printf("X"); } else { printf(" "); }
          printf("] Crear config.txt\n");
          printf("[");
          if (posicion==4) { printf("X"); } else { printf(" "); }
          printf("] <- Volver al menu principal");
        }
     break;
     }
     
}

void launch() {
     sceKernelDelayThread(180000);
     en_menu = 0;
     switch(menu) {
     case(1):
        switch(submenu) {
          case(1):
           if (posicion==1) {
              menu = 2;
              submenu = 1;
              posiciones = 4;
              show_menu();
           }
           if (posicion==2) {
              sceKernelLoadExec("ms0:/PSP/GAME/holamundo/EBOOT.PBP", 0);
           }                 
           if (posicion==4) {
              sceKernelExitGame();
           }
        }
     break;
     case(2):
        switch(submenu) {
        case(1):
           if (posicion==1) {
              clearscreen();   
              en_menu = 0;         
              printf("Comprobando que exista ms0:/config.txt...\n");
                  if (!sceIoOpen("ms0:/config.txt", PSP_O_RDONLY, 0777)) {
                     printf("El archivo ms0:/config.txt NO existe!!\n");
                  } else {
                      printf("El archivo ms0:/config.txt existe\n");
                  }
                  //sceIoClose(fichero); 
                  printf("Pulsa O para continuar...");   
                                while(1) {
                                sceCtrlReadBufferPositive(&controles, 1);
                                if (controles.Buttons & PSP_CTRL_CIRCLE) {
                                  break;
                                }
                                }
             
              en_menu = 1;
              show_menu(); 
           }
           if (posicion==3) {
              clearscreen();   
              en_menu = 0;     
              printf("Procediendo a crear ms0:/config.txt...\n");
                if(sceIoOpen("ms0:/config.txt", PSP_O_WRONLY|PSP_O_CREAT, 0777)) {
                       printf("El archivo fue creado :)");                               
                } else {
                       printf("El archivo no pudo ser creado\n");
                }
                //sceIoClose(fichero); 
                printf("Pulsa O para continuar...");   
                                while(1) {
                                sceCtrlReadBufferPositive(&controles, 1);
                                if (controles.Buttons & PSP_CTRL_CIRCLE) {
                                  break;
                                }
                                }
             
              en_menu = 1;
              show_menu();
           }
           if (posicion==4) {
              menu = 1;
              submenu = 1;
              posiciones = 4;
              show_menu();
           }
       }
    break;
    }
}


int main() {
pspDebugScreenInit();

show_menu();
for (;;) {
if (en_menu) {
        while(1) {
        sceCtrlReadBufferPositive(&controles, 1);
                 if (controles.Buttons & PSP_CTRL_DOWN) {
                   posicion++;
                   if (posicion > posiciones) { posicion = 1; }
                   show_menu();
                   sceKernelDelayThread(180000);
                }
                if (controles.Buttons & PSP_CTRL_UP) {
                    posicion--;
                    if (posicion < 1) { posicion = posiciones; }
                    show_menu();
                    sceKernelDelayThread(180000);
                }
                if (controles.Buttons & PSP_CTRL_CROSS) {
                    launch();
                    sceKernelDelayThread(180000);
                }
          }
       
}
}

sceKernelSleepThread();
return 0;
}


Ahora lo que no consigo que me funcione (desde que empezé a probar) es lo de creación de ficheros (lectura, creación, escritura... etc etc).
Probé (en otro elf) ponerlo como ponia en los docs (fichero = sceIoOpen(...) pero tampoco funcionaba (poniendo fichero en typedef int creo que era).
Y no consigo que funcione tampoco lo de ejecutar un eboot (que tampoco estoy seguro de como hay que hacerlo ya que el los docs no veo nada).

¡¡Salu2 y espero vuestros comentarios!!
killer-x escribió:Puedes usar el syscall sceKernelDelayThread()

Le tienes que pasar un entero, que creo que es en milisegundos, conseguiras que vaya mas lento con el boton pulsado. Prueba con 180000.

Sólo remarcar una cosilla: el parámetro es en microsegundos, con lo cual 1000000 pausará el thread un segundo.

Pyronhell escribió:Y no consigo que funcione tampoco lo de ejecutar un eboot (que tampoco estoy seguro de como hay que hacerlo ya que el los docs no veo nada).

Echa un vistazo a sceKernelLoadExec. Para eso necesitarás estar en kernel mode, pero veo que ya lo estás (aunque no parecía necesario, hasta ahora): PSP_MODULE_INFO("Pyronhell", 0x1000, 1, 1);
Uso esa función, pero me manda al XMB, supongo que habrá que introducir algún parámetro con sceKernelSetArg() o algo así, pero ni idea y como ya he dicho en los docs poco viene

sceKernelLoadExec("ms0:/PSP/GAME/holamundo/EBOOT.PBP", 0);
Pyronhell escribió:Uso esa función, pero me manda al XMB, supongo que habrá que introducir algún parámetro con sceKernelSetArg() o algo así, pero ni idea y como ya he dicho en los docs poco viene

Tienes que rellenar la estructura:
#define PROGRAMA "ms0:/cualquier/EBOOT.PBP"

struct SceKernelLoadExecParam param;

param.size = sizeof(param);
param.argp = PROGRAMA;
param.args = strlen(PROGRAMA) + 1;
param.key = "game";
sceKernelLoadExec(PROGRAMA, ¶m);
Syntax error before . token:

parametros.argp = programa;

Me dice que parámetros está mal

#define programa "ms0:/PSP/GAME/holamundo/EBOOT.PBP"

struct sceKernelLoadExecParam parametros;
parametros.argp = programa;
parametros.args = strlen(programa) + 1;
parametros.key = "GAME";
parametros.size = sizeof(parametros);


Por cierto... los documentos dicen que Key es la clave de encriptacion :S
parametros.args pone que es el tamaño de los argumentos, no seria strlen(parametros) ¿?

Si sabeis de alguna web donde expliquen cosillas de estas os lo agradeceria, asi no estaria dando el coñazo todo el rato.
He buscado en google y tal, pero el hello world ya como qué... xD
Aunque sean webs en Inglés me es indiferente.

Gracias a todos ^^
Pyronhell escribió:Por cierto... los documentos dicen que Key es la clave de encriptacion :S


Key no es más que "lo que quieres ejecutar". Suele ponerse como "game" para ejecutar programas (homebrew en general) y juegos, "updater" si lo que quieres ejecutar es una actualización de firmware o "vsh" que no tengo muy claro para que vale, aunque parece guardar relación con ejecutar algo desde flash0.

Pyronhell escribió:parametros.args pone que es el tamaño de los argumentos, no seria strlen(parametros) ¿?


Es strlen(parametros)+1 porque la función strlen cuenta todos los caracteres excepto el final de cadena (caracter nulo, que es un 0 como entero o '\0' representado como carácter), por eso se debe sumar uno, para obtener la longitud total de la cadena incluido el nulo que determina su final.

En cuanto al error, si pudieras poner el makefile o los #include de tu main, quizá sería más fácil saber de donde viene, pues los campos los estás rellenando bien, así que lo probable es que te falte incluir alguna librería o algo así.

EDITO: Ya ví que tu código sí estaba puesto :p , en todo caso puede ser cosa del makefile, asi que si lo pones puede que encontremos porqué da ese error.
#include <pspkernel.h>
#include <pspiofilemgr.h>
#include <psploadexec.h>
#include <pspdebug.h>
#include <pspdisplay.h>
#include <pspctrl.h>
#include <pspkerneltypes.h>

PSP_MODULE_INFO("Pyronhell", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR(0);

#define printf pspDebugScreenPrintf
#define programa "ms0:/PSP/GAME/holamundo/EBOOT.PBP"

struct sceKernelLoadExecParam parametros;
parametros.argp = programa;
parametros.args = strlen(programa) + 1;
parametros.key = "GAME";
parametros.size = sizeof(parametros);



TARGET = menu
OBJS = main.o

CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)

EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Pyronhell - Menu

PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak


También he probado creando una función con un tutorial que he visto en Google y nada...
Pyronhell escribió:#include
#include
#include
#include
#include
#include
#include

PSP_MODULE_INFO("Pyronhell", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR(0);

#define printf pspDebugScreenPrintf
#define programa "ms0:/PSP/GAME/holamundo/EBOOT.PBP"

struct sceKernelLoadExecParam parametros;
parametros.argp = programa;
parametros.args = strlen(programa) + 1;
parametros.key = "GAME";
parametros.size = sizeof(parametros);


Mmmm, ¿el código es literalmente este?

Lo digo porque "struct sceKernelLoadExecParam parametros;" lo puedes declarar fuera de una función como variable global y no pasa nada, pero lo que es el rellenado de la estructura, es decir:

parametros.argp = programa;
parametros.args = strlen(programa) + 1;
parametros.key = "GAME";
parametros.size = sizeof(parametros);

Esto debe hacerse dentro de una función, no debe rellenarse fuera del código.

Por lo demás, el Makefile también parece correcto, pues tampoco usas librerías especiales que tengas que incluir en él.
Lo primero, si es cierto q solo hace dos dias q usas el lenguaje C, es felicitar-te; creo q esta muy bien lo q has echo aunque es ciero que la instruccion switch te facilitaria mucho el echo de los menus. Llevo 6 anyos programando en C, i la verdard es que es un lenguaje muy complejo.Mi objetivo mas inmediato es la programacion de un programa que cree i resuelva sudocus; lo intetare programar para el pc i luego pasarlo a la psp. Espero no pillarme los dedos en ello.Si teneis alguna sujerencia sera bienvenida.
He vuelto a crear la función pero ahora bien hecha:
void cargaeboot(char *programa) {
    struct sceKernelLoadExecParam parametros;
    const u32 peso = strlen(programa)+1; 
    parametros.args = peso;
    parametros.argp = programa;
    parametros.key = NULL;
    parametros.size = sizeof(parametros) + peso;
    sceKernelLoadExec(programa, ¶metros);
}


Y el debugger me dice: Storage size of 'parametros' isn't known (linea 60 -> struct sceKernelLoadExecParam parametros;)
Y no se que quiere decir :S (se la traduccion, lo que no sé es que hago mal)

Lo primero, si es cierto q solo hace dos dias q usas el lenguaje C, es felicitar-te; creo q esta muy bien lo q has echo aunque es ciero que la instruccion switch te facilitaria mucho el echo de los menus. Llevo 6 anyos programando en C, i la verdard es que es un lenguaje muy complejo.Mi objetivo mas inmediato es la programacion de un programa que cree i resuelva sudocus; lo intetare programar para el pc i luego pasarlo a la psp. Espero no pillarme los dedos en ello.Si teneis alguna sujerencia sera bienvenida.

Claro que es cierto, ¿de qué me vale mentir?
Seis años madre de dios... el programita de los sudokus no me veo haciendolo nunca, demasiado complejo para mi :S
A ver si hago el menu este cutrecillo y luego paso a algo más complejo.

Salu2
El error que te da es porque la estructura es SceKernelLoadExecParam y no sceKernelLoadExecParam (la primera letra S en mayuscula ;-) )

Pyronhell escribió:parametros.size = sizeof(parametros) + peso;

Esta línea es incorrecta, parametros.size se refiere al tamaño da la estructura que es sizeof(parametros) a secas, sin contar la cadena de caracteres que les pases a los parametros. La estructura SceKernelLoadExecParam en psploadexec.h es :

struct SceKernelLoadExecParam {
/** Size of the structure */
SceSize size;
/** Size of the arg string */
SceSize args;
/** Pointer to the arg string */
void * argp;
/** Encryption key ? */
const char * key;
};

Como ves, tanto key como argp son punteros, es decir, su tamaño son 4 bytes siempre, apunten a una cadena que contega 100 caracteres o a una cadena vacía o a NULL, por eso no hace falta añadir el tamaño de las cadenas que le pasas. Es decir, la linea debe quedar asi:
"parametros.size = sizeof(parametros);"

Pyronhell escribió:const u32 peso = strlen(programa)+1;

Por otro lado, no entiendo muy bien porque creas esta línea. Y tampoco porque nombras la variable como u32, cuando SceSize es un int, y tampoco porqué la nombras constante. Con poner

"parametros.args = strlen(programa)+1;"

va a ir perfecto.
despues de leer como va la funcion yo lo haria asi, no lo he probado ni nada pq no me acuerdo de hacer el makefile (no es broma xD)

#include <pspkernel.h>
#include <pspdebug.h>
#include <string.h>
#include <psploadexec.h>

PSP_MODULE_INFO("PROGRAMILLA", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR (0);

void cargareboot(const char *pbpath)
{
const u32 pbplen = strlen(pbpath)+1;
struct SceKernelLoadExecParam eboot;
eboot.args = pbplen;
eboot.argp = pbpath;
eboot.key = NULL;
eboot.size = sizeof(eboot) + pbplen;
sceKernelLoadExec(pbpath,&eboot)
}

int main()
{
pspDebugScreenInit();
cargareboot("ms0:/PSP/GAME/holamundo/EBOOT.PBP")
}
Eso viene en los foros de psp-programming xD

Ya lo he hecho, una cosa... para que el eboot arranque, ¿hay que pasarle el KXploit no?

Ya está, le he pasado el KXploit y funciona perfectamente ^^

Ahora a ver si hago funcionar lo de los archivos...
Yo tampoco logro cargar ningun eboot ni siguiendo la logica que pone en la libreria psploadexec.h ni como lo hacen por los foros adelante ( y ademas en ingles que menos me entero )
kYp escribió:Yo tampoco logro cargar ningun eboot ni siguiendo la logica que pone en la libreria psploadexec.h ni como lo hacen por los foros adelante ( y ademas en ingles que menos me entero )

kYp, no se donde has leido, pero ya he conseguido cargar eboots xD
Lo que quiero hacer ahora es crear un archivo de texto en ms0:/, leerlo y borrarlo, todo controlable desde el menú.

Salu2
Este codigo :
#include <pspkernel.h>
#include <pspdebug.h>
#include <string.h>
#include <psploadexec.h>

PSP_MODULE_INFO("PROGRAMILLA", 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR (0);

void cargareboot(const char *pbpath)
{
const u32 pbplen = strlen(pbpath)+1;
struct SceKernelLoadExecParam eboot;
eboot.args = pbplen;
eboot.argp = pbpath;
eboot.key = NULL;
eboot.size = sizeof(eboot) + pbplen;
sceKernelLoadExec(pbpath,&eboot);
}

int main()
{
pspDebugScreenInit();
cargareboot("ms0:/PSP/GAME/holamundo/EBOOT.PBP");
}


Me compila con error pero me carga ( solo modifique la carpeta del eboot y le añadi unos punto y coma al codigo que pegasteis )
pero nunca habria llegado a hacer eso viendo esto en la libreria :
struct SceKernelLoadExecParam {
   /** Size of the structure */
   SceSize     size;
   /** Size of the arg string */
   SceSize     args;
   /** Pointer to the arg string */
   void *  argp;
   /** Encryption key ? */
   const char *    key;
};


Alguien podria explicar por ejemplo por que el argps tiene que ser u32
y en size tiene que llevar el tamaño de la struct mas el tamaño de la direccion del archivo ¿?


PD: Foro de programacion por favor :_)
Mira tio yo he creado al final esta para cargar eboots:
void cargaeboot(char *programa) {
    struct SceKernelLoadExecParam parametros;
    parametros.args = strlen(programa)+1;
    parametros.argp = programa;
    parametros.key = NULL;
    parametros.size = sizeof(parametros);
    if (sceKernelLoadExec(programa,¶metros)<0) {
    pspDebugScreenPrintf("Cara de eboot fallida.\n");
                      printf("Pulsa O para volver al XMB...");   
                                while(1) {
                                sceCtrlReadBufferPositive(&controles, 1);
                                if (controles.Buttons & PSP_CTRL_CIRCLE) {
                                  break;
                                }
                                }
    }
}

No usa nada de lo antes mencionado ahi arriba, y carga perfectamente eboots kxploiteados.


EDIT:
¿Alguna ayudita con fread? A ver si alguien me puede explicar sus parámetros :)
Salu2
size_t fread(void *puntero, size_t tamanyo, size_t nmemb, FILE *stream);

La función fread recibe, en el array apuntado por puntero, hasta nmemb de elementos cuyo tamaño es especificado por tamanyo, desde el stream apuntado por stream. El indicador de posición de ficheros para el stream (si está definido) es avanzado por el número de caracteres leídos correctamente. Si existe un error, el valor resultante del indicador de posición de ficheros para el stream es indeterminado. Si un elemento es parcialmente leído, entonces su valor es indeterminado.

PD:copiado de conclase.net

por cierto si utilizas ficheros de caracteres puedes utilizar fprintf y fscanf que funcionan exactamente igual que printf y scanf solo que debes pasarle el FILE * como primer parametro.
Ante todo un saludo a todos, y en especial a melado y gusvo ;).

Veamos he visto que se ha aceptado generalmente la solucion del sceKernelDelayThread para el menu. Bien eso realmente para el programa en seco. Ahora imaginemos que tenemos un menu grafico mejorado y que mientras se muestra el menu tambien tenemos una animacion o estamos moviendo el fondo, o lo que sea, pasara que cada vez que se pulse una tecla el sceKernelDelayThread parara tambien la animacion. Para que esto no ocurra podemos utilizar el tiempo de repeticion. Se pulsa una tecla, se toma a la hora que se ha tomado, cuando se pulsa otra si no ha pasado el tiempo de repeticion pues no la tengo en cuenta pero el programa no para.

Tu codigo es asi:

if (en_menu) {
        while(1) {
        sceCtrlReadBufferPositive(&controles, 1);
                 if (controles.Buttons & PSP_CTRL_DOWN) {
                   posicion++;
                   if (posicion > posiciones) { posicion = 1; }
                   show_menu();
                   sceKernelDelayThread(180000);
                }
                if (controles.Buttons & PSP_CTRL_UP) {
                    posicion--;
                    if (posicion < 1) { posicion = posiciones; }
                    show_menu();
                    sceKernelDelayThread(180000);
                }
                if (controles.Buttons & PSP_CTRL_CROSS) {
                    launch();
                    sceKernelDelayThread(180000);
                }
          }


Ahora imagina que despues de cerrar el ultimo if vas moviendo una particula por la pantalla. Si pulsamos el movimiento de esta se veria afectada asi que deberiamos hacer algo asi:

.....
if  ((controles.Buttons & PSP_CTRL_DOWN)  &&  ((HoraActual()-HoraUltimaPulsacion)>TIEMPO_DE_REPETICION))
{
           posicion++;
           if (posicion > posiciones) { posicion = 1; }
           show_menu();
           HoraUltimaPulsacion=HoraActual();
}
.....


Haciendo cada if de este modo, tendrias tus pausas en el menu pero el thread no lo paras no es necesario. Defines arriba cual es tu tiempo_de_repeticion ideal y ya esta.

Saludos,
Warrick.
Warrick escribió:Veamos he visto que se ha aceptado generalmente la solucion del sceKernelDelayThread para el menu. Bien eso realmente para el programa en seco. Ahora imaginemos que tenemos un menu grafico mejorado y que mientras se muestra el menu tambien tenemos una animacion o estamos moviendo el fondo, o lo que sea, pasara que cada vez que se pulse una tecla el sceKernelDelayThread parara tambien la animacion.

Hombre, si va a haber animaciones, sonidos etc., la soluciona mas optima, en mi opinion, seria crear distintos threads, ya q en algunas ocasiones es verdaderamente importante pausarlo. D esa manera s podria tener mayor control sobre cada tarea. Aunq para un menu, como tu dices, es mas sencillo utilizar simples contadores.
Salu2
Warrick escribió:Ante todo un saludo a todos, y en especial a melado y gusvo ;).

Veamos he visto que se ha aceptado generalmente la solucion del sceKernelDelayThread para el menu. Bien eso realmente para el programa en seco. Ahora imaginemos que tenemos un menu grafico mejorado y que mientras se muestra el menu tambien tenemos una animacion o estamos moviendo el fondo, o lo que sea, pasara que cada vez que se pulse una tecla el sceKernelDelayThread parara tambien la animacion. Para que esto no ocurra podemos utilizar el tiempo de repeticion. Se pulsa una tecla, se toma a la hora que se ha tomado, cuando se pulsa otra si no ha pasado el tiempo de repeticion pues no la tengo en cuenta pero el programa no para.

Tu codigo es asi:

if (en_menu) {
        while(1) {
        sceCtrlReadBufferPositive(&controles, 1);
                 if (controles.Buttons & PSP_CTRL_DOWN) {
                   posicion++;
                   if (posicion > posiciones) { posicion = 1; }
                   show_menu();
                   sceKernelDelayThread(180000);
                }
                if (controles.Buttons & PSP_CTRL_UP) {
                    posicion--;
                    if (posicion < 1) { posicion = posiciones; }
                    show_menu();
                    sceKernelDelayThread(180000);
                }
                if (controles.Buttons & PSP_CTRL_CROSS) {
                    launch();
                    sceKernelDelayThread(180000);
                }
          }


Ahora imagina que despues de cerrar el ultimo if vas moviendo una particula por la pantalla. Si pulsamos el movimiento de esta se veria afectada asi que deberiamos hacer algo asi:

.....
if  ((controles.Buttons & PSP_CTRL_DOWN)  &&  ((HoraActual()-HoraUltimaPulsacion)>TIEMPO_DE_REPETICION))
{
           posicion++;
           if (posicion > posiciones) { posicion = 1; }
           show_menu();
           HoraUltimaPulsacion=HoraActual();
}
.....


Haciendo cada if de este modo, tendrias tus pausas en el menu pero el thread no lo paras no es necesario. Defines arriba cual es tu tiempo_de_repeticion ideal y ya esta.

Saludos,
Warrick.


Que cosa más ingeniosa ;) No se me habia ocurrido, aunque tampoco me habia comido mucho el tarro para hacer el menú, ya que lo que estoy haciendo es una simple prueba para aprender a programar un poco.
Cuando haga algo, ya mejorado, trataré de usar esa manera.
Salu2

size_t fread(void *puntero, size_t tamanyo, size_t nmemb, FILE *stream);

La función fread recibe, en el array apuntado por puntero, hasta nmemb de [b]elementos[b] cuyo tamaño es especificado por tamanyo, desde el stream apuntado por stream. El indicador de posición de ficheros para el stream (si está definido) es avanzado por el número de caracteres leídos correctamente. Si existe un error, el valor resultante del indicador de posición de ficheros para el stream es indeterminado. Si un elemento es parcialmente leído, entonces su valor es indeterminado.

¿Elementos que son? ¿Carácteres? Es que si en tamano pongo 1, me lee 4 carácteres, ahora tengo puesto en tamaño y nmemb "sizeof(fichero)*4", porque si no no me lee todo el txt, no se si lo coge en bits o algo asi...

La función fread la uso mal, y la fwrite me da error de bus... ¿hay que usar arrays? ¿no se pueden usar simples strings?
elementos son los que tu quieras , si vas a usar char , en tamaño pones sizeof(char) y en el numero el numero de char que quieres leer.

Lo que haces mal es que el numero de caracteres no es sizeof(fichero) , ya que este es un simple puntero , y por tanto ocupa 4 bytes.
Bueno, pues ya he terminado :)
Lo único que no he incluido es el fwrite() porque aún no se usarlo bien, ya crearé otro programa que lea carpetas y eso.
Menú principal
Imagen
Menú de archivos
Imagen
Menú de capturador de botones
Imagen

El fin de semana que viene me pondré con alguna APP nueva, y tengo que estudiar como funcionan los eboots de 1.0 y 1.5 para saber diferenciarlos y poder hacer un cargador.

Si alguien me puede recomendar una web para empollar, eternamente agradecido.

Gracias a todos por vuestra ayuda para este programita, pondré el eboot y el source (si, no se para qué, pero lo pondré) cuando se pueda abrir mi web.

Queremos foro de programación YA
35 respuestas