using prx to load values/store values (exports not working)

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

using prx to load values/store values (exports not working)

Post by coolkehon »

i want my initconf prx to do all the parsing for my main and then be unloaded but just getting started i cant figure out why it wont hold varaibles and pass them to main when i call the exports i get nothing here is the prx and its makefile

initconf.cpp

Code: Select all

#include <pspkernel.h>
#include <stdio.h>
#include <libconfig.hh>
#include <libconfig.h>
#include <iostream>
#include <fstream>
#include <sys/unistd.h>
#include <cstdlib>
#include <oslib/oslib.h> //use nothing from here except values
using namespace std;
using namespace libconfig;

#include "../main/global.h"
#include "initconf.h"

PSP_MODULE_INFO&#40;"initconf", 0x0006, 1, 1&#41;;
PSP_HEAP_SIZE_KB&#40;1500&#41;;

Config cfg;

bool loaded = false;
bool finished = false;
bool created = false;

void check_finished&#40;&#41;
&#123;
	while&#40;!finished&#41;
	&#123;
		//just wait till main is finished loading config
	&#125;
&#125;

bool file_exist&#40;string src&#41;
&#123;
	bool r = false;
	ifstream file;
	file.open&#40;src.c_str&#40;&#41;&#41;;
	if&#40;file.is_open&#40;&#41;&#41;
		r = true;
	else
		r = false;
	file.close&#40;&#41;;
	return r;
&#125;

int main&#40;int argc, char * argv&#91;&#93;&#41;
&#123;
	if&#40;argc < 2&#41;
	&#123;
		loaded = false;
		finished = true;
		return 0;
	&#125;
	
	try
	&#123;
		if&#40;file_exist&#40;argv&#91;1&#93;&#41;&#41;
		&#123;
			cfg.readFile&#40;argv&#91;1&#93;&#41;;
			loaded = true;
		&#125;
	&#125;
	catch&#40;FileIOException &e&#41;
	&#123;
		loaded = false;
		debugerr&#40;"FileIOException",__LINE__,__FILE__,__FUNCTION__&#41;;
		
		if&#40;file_exist&#40;argv&#91;1&#93;&#41;&#41;
		&#123;
			string renamed = "~";
			renamed += argv&#91;1&#93;;
			if&#40;file_exist&#40;renamed&#41;&#41;
				remove&#40;renamed.c_str&#40;&#41;&#41;;
			rename&#40;argv&#91;1&#93;,renamed.c_str&#40;&#41;&#41;;
			cfg.writeFile&#40;argv&#91;1&#93;&#41;;
		&#125;
	&#125;
	catch&#40;ParseException &e&#41;
	&#123;
		loaded = false;
		char err&#91;1000&#93;;
		sprintf&#40;err,"ParseException&#58; what = %s, error = %s, line = %d",e.what&#40;&#41;,e.getError&#40;&#41;,e.getLine&#40;&#41;&#41;;
		debugerr&#40;err,__LINE__,__FILE__,__FUNCTION__&#41;;
		
		if&#40;file_exist&#40;argv&#91;1&#93;&#41;&#41;
		&#123;
			string renamed = "~";
			renamed += argv&#91;1&#93;;
			if&#40;file_exist&#40;renamed&#41;&#41;
				remove&#40;renamed.c_str&#40;&#41;&#41;;
			rename&#40;argv&#91;1&#93;,renamed.c_str&#40;&#41;&#41;;
			cfg.writeFile&#40;argv&#91;1&#93;&#41;;
		&#125;
	&#125;
	finished = true;
	return 0;
&#125;
bool initconf_enableHome&#40;&#41;
&#123;
	check_finished&#40;&#41;;
	bool enableHome = false;
	if&#40;!cfg.lookupValue&#40;"enableHome",enableHome&#41;&#41;
		enableHome = true;
	return enableHome;
&#125;
int initconf_getPixelFormat&#40;&#41;
&#123;
	check_finished&#40;&#41;;
	int bpp = 0;
	if&#40;!cfg.lookupValue&#40;"bits_per_pixel",bpp&#41;&#41;
		bpp = 16;
	switch&#40;bpp&#41;
	&#123;
		case 32&#58; return OSL_PF_8888;
		case 16&#58; return OSL_PF_5650;
		case 15&#58; return OSL_PF_5551;
		default&#58; return OSL_PF_4444;
	&#125;
	return OSL_PF_4444;
&#125;
makefile

Code: Select all

PSPSDK=$&#40;shell psp-config --pspsdk-path&#41;

TARGET = initconf
OBJS = main.o ../main/main_exp.o 

CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $&#40;CFLAGS&#41; -fexceptions -fno-rtti
ASFLAGS = $&#40;CFLAGS&#41;

LDFLAGS =
#-mno-crt0 -nostartfiles
INCS = -I/usr/local/pspdev/include \
	   -I/usr/local/pspdev/psp/include \
	   -I/usr/local/pspdev/psp/sdk/include 

CFLAGS &#58;= $&#40;INCS&#41;

INCDIR =
LIBDIR =

STDLIBS = -losl -mp3 -lmikmod -lpng -lz
STDLIBS += -lpspctrl -lpspumd -lpsprtc -lpsppower
STDLIBS += -lpspgu -lpspgum -lpsphprm -lpspaudiolib -lpspaudio
STDLIBS += -lmikmod -lm -lc -lstdc++ -lpspmpeg -lpsprtc
STDLIBS += -lpspaudiocodec -lpspatrac3

YOURLIBS = -lconfig++ -lconfig 

LIBS = $&#40;YOURLIBS&#41; $&#40;STDLIBS&#41; 

BUILD_PRX = 1
PRX_EXPORTS = exports.exp

include ../locations.mak
include $&#40;PSPSDK&#41;/lib/build.mak

s_file&#58;	$&#40;shell psp-build-exports -s exports.exp&#41;

install&#58;
	mkdir -p $&#40;INITCONF_DIR&#41;
	cp -f initconf.prx $&#40;INITCONF_DIR&#41;
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

You need to do a search as that has been discussed before. From my recollection, only functions are supported by the SDK, not variables. So if you wish to access variables, you'll need to make accessor functions. So instead of

y = x;

you need

y = GetX();
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

no what i'm saying there are accessor functions initconf_getXXX but its not giving me the values i always get a negative number and it doesnt return a value
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

I see, that's the prx source above... compare that with the example I made for someone else...

Code: Select all

/*
 * PSP Software Development Kit - http&#58;//www.pspdev.org
 * -----------------------------------------------------------------------
 * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
 *
 * main.c - Basic Kernel PRX template
 *
 * Copyright &#40;c&#41; 2005 Marcus R. Brown <[email protected]>
 * Copyright &#40;c&#41; 2005 James Forshaw <[email protected]>
 * Copyright &#40;c&#41; 2005 John Kelley <[email protected]>
 *
 * $Id$
 * $HeadURL$
 */
#include <pspkernel.h>
#include <stdio.h>
#include <oslib/oslib.h>

PSP_MODULE_INFO&#40;"testlib", 0x0006, 1, 1&#41;;
PSP_NO_CREATE_MAIN_THREAD&#40;&#41;;


extern "C"
&#123;
void startDrawing&#40;&#41;
&#123;
	static int x = 0, y = 0;

	oslInit&#40;0&#41;;

	oslInitGfx&#40;OSL_PF_8888,1&#41;;

	//Make sure default analog handler is disabled!
	oslSetKeyAnalogToDPad&#40;0&#41;;

	oslDebug&#40;"prx loaded and osl inited from main"&#41;;

	while&#40;!osl_quit&#41;
	&#123;
		oslReadKeys&#40;&#41;;
		if &#40;osl_pad.held.up&#41;
			y = &#40;y==0&#41; ? 171 &#58; y-1;
		if &#40;osl_pad.held.down&#41;
			y = &#40;y==172&#41; ? 0 &#58; y+1;
		if &#40;osl_pad.held.left&#41;
			x = &#40;x==0&#41; ? 369 &#58; x-1;
		if &#40;osl_pad.held.right&#41;
			x = &#40;x==370&#41; ? 0 &#58; x+1;

		oslStartDrawing&#40;&#41;;
		oslCls&#40;&#41;;
		oslDrawFillRect&#40;x,y,x+100,y+100,RGB&#40;255,0,0&#41;&#41;;
		oslEndDrawing&#40;&#41;;
		oslEndFrame&#40;&#41;;
		oslSyncFrame&#40;&#41;;
	&#125;
&#125;

/* Entry point */
int module_start&#40;SceSize args, void *argp&#41;
&#123;
	return 0;
&#125;

/* Module stop entry */
int module_stop&#40;SceSize args, void *argp&#41;
&#123;
	return 0;
&#125;

&#125;
First, I'm not sure the PSP can export c++ functions. You'd have to talk to moonlight about that. As far as I know, it's c only. Hence the extern "C" {}.

Then we don't see the export file either. My example for the above was

Code: Select all

# Define the exports for the prx
PSP_BEGIN_EXPORTS

# These four lines are mandatory &#40;although you can add other functions like module_stop&#41;
# syslib is a psynonym for the single mandatory export.

PSP_EXPORT_START&#40;syslib, 0, 0x8000&#41;
PSP_EXPORT_FUNC_HASH&#40;module_start&#41;
PSP_EXPORT_FUNC_HASH&#40;module_stop&#41;
PSP_EXPORT_VAR_HASH&#40;module_info&#41;
PSP_EXPORT_END

# Export our function
# flags = 0x0001 => direct jmp
PSP_EXPORT_START&#40;testlib, 0, 0x0001&#41;
PSP_EXPORT_FUNC&#40;startDrawing&#41;
PSP_EXPORT_END

PSP_END_EXPORTS
With the makefile being

Code: Select all

TARGET = testlib
OBJS = main.o

CFLAGS = -O2 -G0 -Wall
CXXFLAGS = $&#40;CFLAGS&#41; -fno-exceptions -fno-rtti
ASFLAGS = $&#40;CFLAGS&#41;

LDFLAGS =
LDFLAGS += -mno-crt0 -nostartfiles

INCDIR =
LIBDIR =

STDLIBS = -losl -mp3 -lmikmod -lpng -lz
STDLIBS += -lpspctrl -lpspumd -lpsprtc -lpsppower
STDLIBS += -lpspgu -lpspaudiolib -lpspaudio
STDLIBS += -lmikmod -lm -lc -lstdc++ -lpspmpeg -lpsprtc
STDLIBS += -lpspaudiocodec -lpspatrac3
YOURLIBS =

LIBS = $&#40;STDLIBS&#41; $&#40;YOURLIBS&#41;

BUILD_PRX = 1
PRX_EXPORTS = exports.exp

PSPSDK=$&#40;shell psp-config --pspsdk-path&#41;
include $&#40;PSPSDK&#41;/lib/build.mak
And then to use the prx, the main.c file was

Code: Select all

#include <pspkernel.h>
#include <pspsdk.h>
#include <pspctrl.h>
#include <pspdebug.h>
#include <pspdisplay.h>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>


PSP_MODULE_INFO&#40;"KJA PDA MAIN", PSP_MODULE_USER ,1,1&#41;;
PSP_MAIN_THREAD_ATTR&#40;THREAD_ATTR_USER | THREAD_ATTR_VFPU&#41;;
PSP_HEAP_SIZE_KB&#40;2500&#41;;

extern "C"
&#123;
void startDrawing&#40;&#41;;
&#125;

int main&#40;int argc, char *argv&#91;&#93;&#41;
&#123;
	pspDebugScreenInit&#40;&#41;;
	pspDebugScreenSetBackColor&#40;0xFF000000&#41;;
	pspDebugScreenSetTextColor&#40;0xFFFFFFFF&#41;;

	SceUID modid = pspSdkLoadStartModule&#40;"testlib.prx", PSP_MEMORY_PARTITION_USER&#41;;
	if &#40;modid < 0&#41;
	&#123;
		pspDebugScreenPrintf&#40;"Error 0x%08X loading/starting testlib.prx.\n", modid&#41;;
        sceKernelDelayThread&#40;5*1000*1000&#41;;
		sceKernelExitGame&#40;&#41;;
	&#125;

	startDrawing&#40;&#41;;

	sceKernelExitGame&#40;&#41;;
	return 0;	// never reaches here - just to supress warning
&#125;
Notice how the function from the prx is prototyped

Code: Select all

extern "C"
&#123;
void startDrawing&#40;&#41;;
&#125;
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

lol that person was me and the exports is here and here is the initconf.h they are externed

exports.exp

Code: Select all

# Define the exports for the prx
PSP_BEGIN_EXPORTS

# These four lines are mandatory &#40;although you can add other functions like module_stop&#41;
# syslib is a psynonym for the single mandatory export.

PSP_EXPORT_START&#40;syslib, 0, 0x8000&#41;
PSP_EXPORT_FUNC_HASH&#40;module_start&#41;
PSP_EXPORT_VAR_HASH&#40;module_info&#41;
PSP_EXPORT_END

# Export our function
# flags = 0x0001 => direct jmp
PSP_EXPORT_START&#40;initconf, 0, 0x0001&#41;
PSP_EXPORT_FUNC&#40;initconf_enableHome&#41;
PSP_EXPORT_FUNC&#40;initconf_getPixelFormat&#41;
PSP_EXPORT_END

PSP_END_EXPORTS
initconf.h

Code: Select all

/*
 * initconf.h
 *
 *  Created on&#58; May 20, 2009
 *      Author&#58; kurt
 */

#ifndef INITCONF_H_
#define INITCONF_H_

#ifdef __cplusplus
extern "C" &#123;
#endif
	
	#ifndef __cplusplus
		#define bool int
	#endif
	
	bool initconf_enableHome&#40;&#41;;
	int initconf_getPixelFormat&#40;&#41;;
	
#ifdef __cplusplus
&#125;
#endif

#endif /* INITCONF_H_ */
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

so also here is how the module is loaded ass you can see it accepts args

Code: Select all

int argsc = 1;
	char * args&#91;argsc&#93;;
	args&#91;0&#93; = &#40;char *&#41;malloc&#40;&#40;workingDir + "/var/init.cfg"&#41;.length&#40;&#41;&#41;;
	strcpy&#40;args&#91;0&#93;,&#40;workingDir + "/var/init.cfg"&#41;.c_str&#40;&#41;&#41;;
	
	modid = pspSdkLoadStartModuleWithArgs&#40;&#40;workingDir + "/sys/initconf.prx"&#41;.c_str&#40;&#41;,PSP_MEMORY_PARTITION_USER,argsc,args&#41;;
	if &#40;modid < 0&#41;
	&#123;
		pspDebugScreenPrintf&#40;"Error 0x%08X loading/starting %s/sys/initconf.prx.\n", modid,workingDir.c_str&#40;&#41;&#41;;
		sceKernelDelayThread&#40;5*1000*1000&#41;;
		sceKernelExitGame&#40;&#41;;
	&#125;
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

I see you put extern "C" in the h file, but I don't see that in the cpp file.
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

it crashes the whole app and why can i not compile and export c++ functions there isnt much of a difference and also why has the pspsdk stoped being developed as much as getting upgrades such as c++ exports
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

Your problem is you don't understand how c++ works, in theory you can export static/global c++ functions no problem, if you understood what the export builder does and what c++ does. Alas you haven't bothered to try and understand.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

And I can't help with that as I don't care to learn how to export c++ as I don't care for c++. ;)
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

Are the VSH modules' exported functions C++ too or only the internals are C++ and only C functions are exposed?
SilverSpring
Posts: 110
Joined: Tue Feb 27, 2007 9:43 pm
Contact:

Post by SilverSpring »

No, they are C++ too. That is why some of the NID's are so difficult to crack, because of name mangling.

An example (from paf.prx):

0xDB230BE1 _ZN3paf8PhWidget7SetTextERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEi

which demangled becomes:

paf::PhWidget::SetText(paf::basic_string<wchar_t,paf::char_traits<wchar_t>,paf::allocator<wchar_t>> const&,int)


etc. etc.
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

TyRaNiD wrote:Your problem is you don't understand how c++ works, in theory you can export static/global c++ functions no problem, if you understood what the export builder does and what c++ does. Alas you haven't bothered to try and understand.
i actually read you guide for the psp and the module tutorial yesterday and didnt learn much that i understood be it explained some stuff most of those examples are in kernel mode and this is a usermod app also what is the "constructor" for the psp application in usermode for the patches and stuff couldnt find that
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

SilverSpring wrote:No, they are C++ too. That is why some of the NID's are so difficult to crack, because of name mangling.

An example (from paf.prx):

0xDB230BE1 _ZN3paf8PhWidget7SetTextERKNS_12basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEEEi

which demangled becomes:

paf::PhWidget::SetText(paf::basic_string<wchar_t,paf::char_traits<wchar_t>,paf::allocator<wchar_t>> const&,int)


etc. etc.
so how can i use c++ in an exported module

edit: here are some more details on the problem
* c++ functions will not compile unless forward declaired & externed
* when the module is loaded it will not present any error but when i try to call exports i get a return value from which should be an int -2147352262
no matter what
* if i extern the entire function in

Code: Select all

extern "C" &#123;int function&#40;&#41; &#123; do whatever; return whatever;&#125;
it crashes the psp

here is the error when trying to compile exported function note that this is the prx itself not the app that will be using the exported function

Code: Select all

exports.o&#58;&#40;.rodata.sceResident+0x1c&#41;&#58; undefined reference to `initconf_setup'
collect2&#58; ld returned 1 exit status
make&#58; *** &#91;initconf.elf&#93; Error 1
rm exports.c
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

For a start you really should look at what the error code is telling you. If you convert it to hex and look it up in pspkerror (or using the error command in pspsh) you find it is 0x8002013a which just so happens to be SCE_KERNEL_ERROR_LIBRARY_NOT_YET_LINKED. So for some reason you have specified the library wrong or something so the function cannot be found. Have you modified the import assembly code to ensure that it is no longer delay loaded?

As for exporting C++ functions it requires abit extra hassle but it is doable. Mangle the name for the function (e.g. build the code and use objdump to get out the mangled symbol name) then put the mangled symbol name in your exports. In theory you could even export an entire class but it probably isn't recommended :) Maybe I could have made the export process more streamlined but I guess it is too late now.
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

i'm new to programming as advanced as this so it may take some explaing on your behalf of what stuff means because i learned through java the basics then learned c/c++ (self taught) then learned the psp stuff although need to (doing right now) learning the gu but i would not have thought for a second to check the number and convert it to hex and when i did convert to hex i got -0x7FFDFEC6 so how the heck did you get that error code

edit: also how would i go about this name mangling thing you speak of never heard of objdump and dont really know how to use it or mangle the name
TyRaNiD
Posts: 907
Joined: Sun Jan 18, 2004 12:23 am

Post by TyRaNiD »

The simplest way is to put the number into something like windows calc and then change to hex, you will get something like 0xFFFFFFFF8002013A, you only care about the lower 32bits. Or when you print it out of your program use unsigned hex formatting with printf (i.e. %x). Or to be technically correct add one to the number, remove the negative sign and do a bitwise not on the number, re: http://en.wikipedia.org/wiki/Twos_Compliment :)

As for the other stuff, well objdump (actually psp-objdump for the toolchain) is just a tool which can dump things about an object file. If you first build your code, then execute "psp-objdump -t yourprog.elf" (only use the elf, not the prx) it will print a list of symbols. Search for the symbol which contains the name of the function you want, it will probably look like garbage.

For example, I want to export "int exported_func(const char* str)". I compile the code and run psp-objdump to get the symbols. Searching for exported_func in the output gives me the mangled symbol "_Z13exported_funcPKc" now just put that in your exports.exp file as is and you can import functions with C++ prototype forms.
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

how can i tell it to output what it prints to a text file so that i can read it because the terminal buffer isnt long enough

edit:
nvm found it
http://ubuntuforums.org/showthread.php?t=138349

wow all this time and it was that simple man well good to know

edit: lol it compiled i will test when i get time cool thanks hope it works also app that will be using compiled using the old name (initconf_setup) too
p.s: only using initconf_setup so far
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

ok i tryed it and it still doesnt work this time i uploaded as to not clog up the page here is the source also no one ever answered the question what is the psp's "constructor" for a user app that will enable me to install patches at startup and call functions that are kernel

direct from my site
http://kehon.izfree.com/downloads/initconf_help.zip
sendspace
http://www.sendspace.com/file/ezqih9
User avatar
Torch
Posts: 825
Joined: Wed May 28, 2008 2:50 am

Post by Torch »

Its always module_start(...) if you specify mnoctr0 and mnostartfiles.
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

and if i have crto included then what
also i believe i need crto for c++ dont i
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

i got the prx to work with exporting c/c++ functions but it crashes when trying to return strings also what is the constructer i know someone has to know i think i saw it somewhere a long time ago it has something like __atribute__("constructor") but dont know how to use that and what exactly it is
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

You probably want to look at the string.c_str() method. Returning C++ strings back to C land is going to be bad.

The constructor is the method that's called when someone goes
class MYOBJECT {

MYOBJECT()
{
...I am the constructor
};

~MYOBJECT()
{
...I am the destructor
};

...
}
....
int main(void)
{
MYOBJECT *instance_of_class = new MYOBJECT;
...
}

This is really basic stuff you need to know before you mess with PSP.

Jim
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

i know that and i already knew / know why strings crash its because of the allocating of memory and freeing when it gets into a another prx / module it tries to free itself in the deconstructor but the memory is inside of the prx and theorefore is not freed correctly and causes all kinds of errors when accessing memory and stuff
Post Reply