Skip to: Site menu | Main content


Welcome to PSP-Programming.com, a place for developers to get together.

Welcome to the forums. Here you can find other user tutorials as well as homebrew releases and the source code repository. You can also ask for help with your code here and post your own homebrew!

PSP-Programming.com Forums
February 04, 2012, 09:54:27 AM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

News: Join our IRC channel: ##psp-programming on freenode
Home Help Search Shop Login Register
Digg This!
Pages: [1] 2
Print
Author Topic: [C] AdHoc Tutorials/Samples  (Read 15176 times)
BlackPhoenix
Newbie
*

Karma: +1/-0
Offline Offline

Posts: 3
24.80 points

View Inventory
Send Money to BlackPhoenix

View Profile
« on: June 14, 2006, 06:42:50 AM »

Hey guys,

I have two AdHoc examples for 1.5 psps.

Sends
1. the alphabet
2. a stream of character data |. recursively

I was thinking of making a tutorial for these examples and posting them here for the development community.

Would anyone be interested?

*currently writing tutorial* - DONE

Quote from: Ryalla
Wrong forum, but that would be interesting.
Lol, wrong forum.. could a mod make a "Post tutorial" forum then :p how could I have known which one.. I'm inatly thick Rolling Eyes

Okie here is the tutorial.. and could a mod move this to the *correct forum* Wink

#### Adhoc Tutorial, Send Alphabet from one 1.5 PSP to Another

FOR EXPERIENCED USERS: the full source code.. I'm sure you don't want to read the basics, just the comments!

It would be a good idea to have read Yeldarb's tutorials before continuing with this one.

Download the source files..

Okie, this tutorial will help you to understand the fundamentals of getting homebrew adhoc to work with your 1.5 (only) PSPs. I'm not going to go into extreme detail as you really don't need a great deal of background knowledge to get this working. I have taken all of my lib code from SMS 1.2 emulator (thanks AhMan for the heads up).

Right, to start off here is the first part of the code:
HEADER
Code:
/* psp & std libs */
#include <pspkernel.h>
#include <pspmodulemgr.h>
#include <pspdisplay.h>
#include <pspdebug.h>
#include <pspthreadman.h>
#include <pspctrl.h>
#include <pspsdk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define printf pspDebugScreenPrintf

/* 0x1000 = kernel mode set */
PSP_MODULE_INFO("AdHoc", 0x1000, 0, 1);
/* user mode */
PSP_MAIN_THREAD_ATTR(0);

PSP_MODULE_INFO is used to set kernel mode.. this programme NEEDS to be started in kernel mode for this to work. This is because certain modules need to be loaded and kernel mode gives us that ability. PSP_MAIN_THREAD_ATTR is set so we can call it later for our user mode thread.

For those of you asking yourself WTF is a thread.. well you really should have some previous knowledge on this subject.. so read this artical en.wikipedia.org/wiki/Thread_(computer_science)
..just to speed things up!

Here is the next bit of code:
EXIT CALLBACK THREAD
Code:
/* exit callback */
int exit_callback(int arg1, int arg2, void *common){
adhocTerm();
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;
}

/* debug output */
void sdl_psp_exception_handler(PspDebugRegBlock *regs){
pspDebugScreenInit();

pspDebugScreenSetBackColor(0x00FF0000);
pspDebugScreenSetTextColor(0xFFFFFFFF);
pspDebugScreenClear();

printf("oh **** BSOD...\n\n");
printf("Exception Details:\n");
pspDebugDumpException(regs);
printf("\nPut this in your cygwin and smoke it:\n\n"
"\tpsp-addr2line -e target.elf -f -C 0x%x 0x%x 0x%x\n",
regs->epc, regs->badvaddr, regs->r[31]);
}

/* setup the callback thread */
int SetupCallbacks(void){
int thid = 0;
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
if(thid >= 0)
sceKernelStartThread(thid, 0, 0);
return thid;
}

SetupCallbacks() is an example of a thread, remember Yeldbard's second tutorial? All that code that had to go before your main function.. well it helps with exiting the programme.. when you press your home button and quit a homebrew app this thread is called and closes the app properly.. if you didn't add this code into your programme your PSP would crash and turn itself off and you'd be back at the XMB (main PSP menu screen) when you turn it back on.

In the exit_callback function I have added a function called adhocTerm() this will terminate adhoc on exit.

You may be looking at the function sdl_psp_exception_handler() that is amongst the callback thread code.. it was new to me before this, most of you have probably seen the PSP blue screen of death.. well this is a custom one and is called as and when it is needed (on a programme crash mostly).

Here is the next bit of code for both the alphabet and data stream tutorials:

ALPHABET
Code:
int user_main(SceSize args, void *argp){

/* var init */
int done, err, i, loop, server, size = 0;
unsigned int length;
char *data;
SceCtrlData pad;

pspDebugScreenInit();

/* adhoc initalise functions */
if((adhocInit("") >= 0) && ((server = adhocSelect()) >=0)){
printf("\n\n## AdHoc INITALISED ##\n\n");
sceKernelDelayThread(1000000);

/* Display server, or client */
if(server)
printf("Server Assigned\n\n");
else
printf("Client Assigned\n\n");

/* if this psp is the server */
if(server){
/* client must be waiting for server, so slight delay for server */
sceKernelDelayThread(1000000);
/* alphabet string */
data = "abcdefghijklmnopqrstuvwxyz";
size = sizeof(data);

printf("Sending data to the client.. size: %d \n", size);
err = adhocSendRecvAck(&size, 4); /* let client know the size of data */
printf("Done sending size: %d\ndata: %s\n", size, data);

sceKernelDelayThread(1000000);

err = adhocSendRecvAck(&data, 4);  /* send data as void */
printf("Done sending data: %s\nsize: %d\n", data, size);
} else {
printf("Waiting for data..\n");

/* get data from server */
size = 0;
length = 4;
err = adhocRecvSendAck(&size, &length); /* get size of data */
printf("Done receiving size: %d \nlength: %d \n", size, length);

length = size;
err = adhocRecvSendAck(&data, &length); /* get data */
data = (char *)data; /* type cast received data */
printf("Received data from server: %s \n", data);
}
}
/* terminate adhoc */
adhocTerm();

printf("Press START to exit..\n");
done = 0;
do {
sceCtrlReadBufferPositive(&pad, 1);
if(pad.Buttons != 0)
if(pad.Buttons & PSP_CTRL_START)
done = 1;
} while(!done);

}

DATA STREAM
Code:
int user_main(SceSize args, void *argp){

SetupCallbacks();

static char buffer[0x8000];
unsigned int length;
int err, bD = 0;
int i, done, mainDone, server=0;

char *data;
int size = 0;

SceCtrlData pad;

pspDebugScreenInit();

do {

if((adhocInit("") >= 0) && ((server = adhocSelect()) >=0)){

pspDebugScreenPrintf("\n\n## AdHoc INITALISED ##\n\n");

sceKernelDelayThread(1000000);

if(server)
pspDebugScreenPrintf("Server Assigned\n\n");
else
pspDebugScreenPrintf("Client Assigned\n\n");

if(server){
sceKernelDelayThread(5000000);
done = 0;
do {
sceCtrlReadBufferPositive(&pad, 1);
if(pad.Buttons != 0)
if(pad.Buttons & PSP_CTRL_CROSS)
done = 1;

if((i % 2) == 0){
data = ".";
i = 0;
} else
data = "|";
i++;

if(done == 1)
data = "x";
size = sizeof(data);

err = adhocSendRecvAck(&size, 4);
err = adhocSendRecvAck(&data, 4);  //# send data

pspDebugScreenPrintf("%s", data);
} while(done==0);

} else {
done = 0;
do {
/*sceCtrlReadBufferPositive(&pad, 1);
if(pad.Buttons != 0)
if(pad.Buttons & PSP_CTRL_CROSS)
done = 1;*/

size = 0;
length = 4;
err = adhocRecvSendAck(&size, &length);

length = size;
err = adhocRecvSendAck(&data, &length);
data = (char *)data;

if(data == "x")
done = 1;

pspDebugScreenPrintf("%s", data);
} while(done==0);

}

}

pspDebugScreenPrintf("\n\n");

adhocTerm();

done = 0;
pspDebugScreenInit();
pspDebugScreenPrintf("\n\nPress START to Exit, X to Continue\n\n");
do {
sceCtrlReadBufferPositive(&pad, 1);
if(pad.Buttons != 0){
if(pad.Buttons & PSP_CTRL_START){
done = 1; mainDone=1;
sceKernelExitGame();
}
if(pad.Buttons & PSP_CTRL_CROSS)
done = 1; mainDone=0;
}
} while(!done);

} while(!mainDone);

/* pspDebugScreenPrintf("Press any key to exit..\n");
done = 0;
do {
sceCtrlReadBufferPositive(&pad, 1);
if(pad.Buttons != 0)
done = 1;
} while(!done);*/

sceKernelExitGame();
}

This function will be our user mode thread and is called by our main function (below). It contains the procedural workings for our adhoc communication programme. It starts with initialising the variables we will need.. pad data, character data etc.. pspDebugScreenInit() initialises the debug text that we will need to see what is going on.

The next part: adhocInit() and adhocSelect()
Simply sets up adhoc.. adhocInit will connect using what ever adhoc settings that you have got selected in the XMB "Network Settings > Ad Hoc Mode".. I have only tested this with the Automatic setting, so make sure yours is set to Automatic too before continuing.
The next function adhocSelect will display a list of possible connections that are available and allow you to select which one to connect to.. the possible connections are displayed in green and have the device mac address followed by the name given to its adhoc process. The code for this tutorial has been given the process name "adhoc" (this has been hard coded into the lib file ad-hoc/pspadhoc.c, search for "adhoc\0" if you wanted to change it.. just don't change anything else if you don't know what your doing).

The next part of the code to be executed will depend on whether or not the psp has been assigned as the client or the server. If server is selected then a character string containing the alphabet will be set to the data variable, its size recorded and then sent to the client.. a reply from the client is required before continuing, this is all taken care of by the lib code so don't worry about its inner workings. Once a reply has been received the data is sent and the server waits for a reply.

There are a few more things to remember about this procedure..
  • the client MUST always be waiting for the server to send the data, that is why there is a delay thread call for the server procedure and not for the client.. if the server tries to send data to the client before it is ready then it will get stuck and you may need to reset your psp.
  • the data sent with the function adhocSendRecvAck is actually sent as type void*.. this was new to me, I didn't know you could do something like that.. yet if you send it as a char type and type cast it on receipt there is no problem, it still seems to act as the type you sent it as.. it's just a way of sending whatever data you want without worrying about what type it is.
Once the data has been sent and received the programme will loop round a control input loop waiting for the start button to be pressed so it can exit the programme..

Right to explain the kernel mode to user mode stuff.. here is the final function main()
MAIN
Code:
/* kernel mode thread */
int main(int argc, char *argp[]){

/* exit callback */
SetupCallbacks();

/* load adhoc modules */
    if (adhocLoadDrivers(&module_info) != 0){
        printf("Driver load error\n");
        return 0;
    }

/* setup debug info handler */
pspDebugInstallErrorHandler(sdl_psp_exception_handler);

    /* create user thread */
    SceUID thid = sceKernelCreateThread("User Mode Thread", user_main,
            0x11, // default priority
            256 * 1024, // stack size (256KB is regular default)
            PSP_THREAD_ATTR_USER, NULL); //# user mode

    // start user thread, then wait for it to do everything else
    sceKernelStartThread(thid, 0, 0);
    sceKernelWaitThreadEnd(thid, NULL);

/* quick clean exit */
sceKernelExitGame();

    return 0;
}

This function is the first to be called, and starts with the SetupCallbacks() function.. remember this function sets up the ability to close down our application properly.. which is particularly important as we are using the PSPs adhoc functions that need to be closed before exit.

The next bit of code loads the adhoc driver modules into memory (remember at this point we are still in kernel mode so we can access kernel mode modules).

The next line of code initialises the debug handler or blue screen of death screen.

Now comes the all important create user mode thread.. the function user_main() is called from here. The function is assigned a name "User Mode Thread", a default priority for execution and a set a mount of memory.. along with the user mode assignment "PSP_THREAD_ATTR_USER". After this the thread is destroyed and game exit is called, this invokes the exit callback thread we talked about earlier..

So the user_main() function operates in user mode and the main() function operates in kernel mode.

If you wanted to mod this into your programme you may want to look at the lib files that are in the ad-hoc folder (source file download is at the top of this post)..

Oh yeah.. might want to look at the Makefile:
MAKEFILE
Code:
TARGET = adhoc
PSPSDK=$(shell psp-config --pspsdk-path)
PSPBIN = $(PSPSDK)/../bin

OBJS = main.o

OBJS += ad-hoc/selectorMenu.o \
ad-hoc/loadutil.o \
ad-hoc/pspadhoc.o \
ad-hoc/stubs.o

INCDIR =
CFLAGS = -g -O2 -G0 \
-I. -Icpu -Ipsp -DLSB_FIRST \
-DALIGN_DWORD -DDOS -DPSP -DUSE_ZLIB
CXXFLAGS = -g $(CFLAGS) -fno-exceptions -fno-rtti -Wpointer-arith
ASFLAGS = -c $(CFLAGS)

LIBDIR =
LDFLAGS =
LIBS = -lpspgu -lpspwlan -lpsppower -lz -lstdc++ -lm

#EXTRA_TARGETS = kxploit
PSP_EBOOT_TITLE = Adhoc

include $(PSPSDK)/lib/build.mak

Nothing too fansy, the most important part of this makefile is the -lpspwlan lib and the ad-hoc objects. Some of this makefile and indeed the example has left over code from the SMS 1.2 source code it was derived from.

If you have any questions please ask me (BlackPhoenix) on the relevant forum (qj.net, psp-programming.com).

Please Note: This programme has worked for me on two 1.5 PSPs but I have changed the code a little for this tutorial and I don't have access to a second 1.5 PSP this week (bloody friend went on holiday to Mexico with it). Could someone confirm that this code still works.. if not please give me as much detail so I can fix it Wink
« Last Edit: June 11, 2007, 07:02:07 PM by Ryalla » Logged


Ryalla
harleyg
Hero Member
*****

Karma: +50/-12
Offline Offline

Posts: 813
9999999.99 points

View Inventory
Send Money to Ryalla


View Profile
« Reply #1 on: June 14, 2006, 09:05:52 AM »

Wrong forum, but that would be interesting. Too bad I don't know anybody else with a 1.5 to test it out with. However, I do believe my brother still has a 2.00. Go ahead and post them.
Logged
bronxbomber92
Give miinaturvat Points!
All-Around Dev
Hero Member
*

Karma: +16/-2
Offline Offline

Posts: 663
3689.59 points

View Inventory
Send Money to bronxbomber92

View Profile
« Reply #2 on: June 14, 2006, 10:03:35 AM »

would this be in c? can lua use adhoc?
Logged

BlackPhoenix
Newbie
*

Karma: +1/-0
Offline Offline

Posts: 3
24.80 points

View Inventory
Send Money to BlackPhoenix

View Profile
« Reply #3 on: June 14, 2006, 10:46:40 AM »

Quote from: "bronxbomber92"
would this be in c? can lua use adhoc?


There is already a netlib for lua.. and I think adhoc is supported. Don't quote me on that as I don't use LUA very much.. done a few hours so I could put together the syntax but thats all.

^^ I've just edited my post.. now has the tutorial, enjoy!!
Logged
lokust
Full Member
***

Karma: +1/-0
Offline Offline

Posts: 186
0.00 points

View Inventory
Send Money to lokust


View Profile WWW
« Reply #4 on: June 14, 2006, 10:34:26 PM »

Very nice BlackPhoenix, much appreciated Smile
Logged

<flashram> we just lack the rock ... everbody is stoned already
<whazilla> i'm the dark Yoda but i speak as the one green
whazilla
Sr. Member
****

Karma: +2/-8
Offline Offline

Posts: 377
1793.33 points

View Inventory
Send Money to whazilla


View Profile
« Reply #5 on: June 15, 2006, 12:22:00 AM »

and the phoenix rises once again Very Happy
Logged
JesusXP
Newbie
*

Karma: +0/-0
Offline Offline

Posts: 1
0.00 points

View Inventory
Send Money to JesusXP

View Profile
« Reply #6 on: November 05, 2006, 11:19:37 AM »

Can someone please repost links to the full source, and the other download.... they are unavailable at present time.

Much appreciated.
Logged
Insert_Witty_Name
Global Moderator
Hero Member
*

Karma: +149/-17
Offline Offline

Posts: 1602
1141.66 points

View Inventory
Send Money to Insert_Witty_Name

View Profile WWW
« Reply #7 on: November 05, 2006, 11:36:05 AM »

Here you go:

http://www.psp-programming.com/animate/adhoc-examples.rar
Logged

Coder formerly known as:

Check out my homebrew & C tutorials at http://insomniac.0x89.org
Last updated 6th Oct 06 - Tutorial 2 added.
2.6,CRACKED!
Full Member
***

Karma: +0/-37
Offline Offline

Posts: 111
3864.87 points

View Inventory
Send Money to 2.6,CRACKED!


View Profile
« Reply #8 on: November 08, 2006, 09:46:33 AM »

so if you gave your friend an eboot that sends the text "XYZ", and your one sent "ABC", they would receive them as how we sent them? I thought if you sent them with the same like variable name, then it would just read its own variable, but I know/think thats not true now.
Logged
BlackPhoenix
Newbie
*

Karma: +1/-0
Offline Offline

Posts: 3
24.80 points

View Inventory
Send Money to BlackPhoenix

View Profile
« Reply #9 on: January 21, 2007, 10:24:24 AM »

so if you gave your friend an eboot that sends the text "XYZ", and your one sent "ABC", they would receive them as how we sent them? I thought if you sent them with the same like variable name, then it would just read its own variable, but I know/think thats not true now.
The programme will act in a simplex or half-duplex manner, you can only send data in one direction at a time. So you have time to store the received data in a variable of choice and then overwrite the temporary variable used to obtain the data.

Hope that helped.
Logged
2.6,CRACKED!
Full Member
***

Karma: +0/-37
Offline Offline

Posts: 111
3864.87 points

View Inventory
Send Money to 2.6,CRACKED!


View Profile
« Reply #10 on: May 30, 2007, 12:26:32 AM »

BTW i asked this because I was interested doing an adhoc chat (i know thats pointless because you can speak if you are that close, but say if you're in class or something or you need to be silent or whatever)..
Logged
mowglisanu

C/C++ Developer
Hero Member
*

Karma: +36/-11
Offline Offline

Posts: 787
0.00 points

View Inventory
Send Money to mowglisanu


View Profile
« Reply #11 on: April 28, 2008, 09:34:28 AM »

Here is the adhoc example modified to work in 3xx, if anyone is interested.

Edit:updated for latest sdk revision.
« Last Edit: November 26, 2009, 07:09:55 AM by mowglisanu » Logged

Check out my:
 Audio lib
 Pmf Viewer
thecobra
Newbie
*

Karma: +0/-0
Offline Offline

Posts: 4
264.05 points

View Inventory
Send Money to thecobra

View Profile
« Reply #12 on: June 16, 2008, 04:22:12 PM »

Here is the adhoc example modified to work in 3xx, if anyone is interested.

thanks you for the source code and the update
i been looking for this for this.
you a live saver
i will remember to add you to my credit
tanks alot Smile

 Thank You,
         Thecobra [creator of Robot Warrior DC]
Logged
pspjoke
Newbie
*

Karma: +0/-0
Offline Offline

Posts: 10
721.54 points

View Inventory
Send Money to pspjoke

View Profile
« Reply #13 on: October 05, 2008, 12:53:14 PM »

i just got my second psp so im trying to get started on ad-hoc programming, however, using the above example (the 3xx one) i keep getting compiling errors..
i haven't changed anything either, just downloaded, extracted, and attempted a build.

ERROR:
Code:
Christian@PSP-DOC ~/ad3xx
$ make
psp-gcc -I. -I/usr/local/pspdev/psp/sdk/include -g -O2 -G0  -D_PSP_FW_VERSION=15
0   -c -o ad-hoc/pspadhoc.o ad-hoc/pspadhoc.c
ad-hoc/pspadhoc.c: In function 'matchingCallback':
ad-hoc/pspadhoc.c:42: error: 'MATCHING_JOINED' undeclared (first use in this fun
ction)
ad-hoc/pspadhoc.c:42: error: (Each undeclared identifier is reported only once
ad-hoc/pspadhoc.c:42: error: for each function it appears in.)
ad-hoc/pspadhoc.c:46: error: 'MATCHING_DISCONNECT' undeclared (first use in this
 function)
ad-hoc/pspadhoc.c: In function 'adhocSelect':
ad-hoc/pspadhoc.c:293: error: 'MATCHING_SELECTED' undeclared (first use in this
function)
ad-hoc/pspadhoc.c:323: error: 'MATCHING_ESTABLISHED' undeclared (first use in th
is function)
ad-hoc/pspadhoc.c:327: error: 'MATCHING_REJECTED' undeclared (first use in this
function)
ad-hoc/pspadhoc.c:358: error: 'MATCHING_CANCELED' undeclared (first use in this
function)
ad-hoc/pspadhoc.c: In function 'adhocRecvSendAck':
ad-hoc/pspadhoc.c:631: warning: assignment makes integer from pointer without a
cast
make: *** [ad-hoc/pspadhoc.o] Error 1

can anyone help me out?
« Last Edit: October 05, 2008, 12:59:40 PM by pspjoke » Logged
mowglisanu

C/C++ Developer
Hero Member
*

Karma: +36/-11
Offline Offline

Posts: 787
0.00 points

View Inventory
Send Money to mowglisanu


View Profile
« Reply #14 on: October 06, 2008, 07:56:08 AM »

The names of the MATCHING_* enumerations or whatever they are have changed in the updated sdk to something like PSP_ADHOC_* and you cant match them by just looking at them , if you can wait I can post an updated version if not you can do it yourself by checking the original by posted BlackPhoenix and compare the values in the sdk.
Logged

Check out my:
 Audio lib
 Pmf Viewer
Pages: [1] 2
Print
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Page created in 0.396 seconds with 38 queries.
Sister Sites: Guitar Hero 4   BrokeniTouch.com