Adhoc Receiving Data

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

Moderators: cheriff, TyRaNiD

Post Reply
Sp3ct0r
Posts: 3
Joined: Wed Apr 16, 2008 7:19 am

Adhoc Receiving Data

Post by Sp3ct0r »

Hey, I'm creating an Adhoc compatible game for PSP using pspZorba's 3.xx compatible adhoc example. I've got it working right...however I am having trouble sending multiple variables. The PSP's are constantly sending and receiving data from each other, however when you send data, it must be all in a char, and when it is received, it is void type data. So I convert int to char, send it, the other PSP receives it, then converts char to int. This process only allows me to check 1 variable. And of course I need to check things like X, Y, state, current_animation, etc... So I think I need a way to put all these variables into a char array, send them, then receive them and be able to interpret each one as separate variables. I'm not quite sure how to do this...so if anyone can help me I would greatly appreciate it. Thanks. :P

Code: Select all

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

#include "ZBadhoc.h"

#include <oslib/oslib.h>
#include <string>


/* Define the module info section */
#define MY_HOMEBREW_MAJOR_VERSION  0
#define MY_HOMEBREW_MINOR_VERSION  42

//PSP_MODULE_USER
//PSP_MODULE_KERNEL
PSP_MODULE_INFO&#40;"SMBC", PSP_MODULE_USER, MY_HOMEBREW_MAJOR_VERSION, MY_HOMEBREW_MINOR_VERSION&#41;;
PSP_HEAP_SIZE_MAX&#40;&#41;;

PSP_MAIN_THREAD_ATTR&#40;THREAD_ATTR_USER | THREAD_ATTR_VFPU&#41;;

OSL_IMAGE *player_img;

/**Ad-Hoc Only Variables**/
 int sceInit&#40;void&#41;;
 int send;		//Data Sent And Received
 int receive;
 int encore=1;		//Adhoc Enabled
 ZBremotePsp * pPsp;	//Stores Mac Address Of Other PSP
 int user;		//Host = 1	Guest = 2
 int init;		//Mode Initiation Variable

 char buffer&#91;42+1&#93;;
 char data&#91;50&#93;;
 int state = 1;
/**^^^^^^^^^^^^^^^^^^^^^**/


/**OSLIB STUFF**/
int initOSLib&#40;&#41;&#123;
    oslInit&#40;0&#41;;
    oslInitGfx&#40;OSL_PF_8888, 1&#41;;
    oslInitAudio&#40;&#41;;
    oslSetQuitOnLoadFailure&#40;1&#41;;
    oslSetKeyAutorepeatInit&#40;40&#41;;
    oslSetKeyAutorepeatInterval&#40;10&#41;;
    return 0;
&#125;

int endOSLib&#40;&#41;&#123;
    oslEndGfx&#40;&#41;;
    osl_quit = 1;
    return 0;
&#125;
/**^^^^^^^^^^^**/


typedef struct &#123;
	int x,y;
	int state;
	OSL_IMAGE *img;
&#125;Player1;
Player1 p1;

typedef struct &#123;
	int x,y;
	int state;
	OSL_IMAGE *img;
&#125;Player2;
Player2 p2;

void LoadImages&#40;&#41;, DrawImages&#40;&#41;;

//char to int function
bool string2int&#40;char* digit, int& result&#41; &#123;
   result = 0;

   //--- Convert each digit char and add into result.
   while &#40;*digit >= '0' && *digit <='9'&#41; &#123;
      result = &#40;result * 10&#41; + &#40;*digit - '0'&#41;;
      digit++;
   &#125;

   //--- Check that there were no non-digits at end.
   if &#40;*digit != 0&#41; &#123;
      return false;
   &#125;

   return true;
&#125;

int main&#40; void&#41;
&#123;
	scePowerSetClockFrequency&#40;333, 333, 166&#41;;	//Overclock to full potential
	sceInit&#40;&#41;;					//set exit callback
	pspDebugScreenInit&#40;&#41;;
	sceKernelDelayThread&#40;1000 * 1000&#41;;	//1 Second Delay

	//init everything
	ZBadhoc&#58;&#58;getSingleton&#40;&#41;;
	SceCtrlData pad;
	pspDebugScreenClear&#40;&#41;;
	while&#40;encore&#41;
	&#123;
	if &#40;!user&#41;	//If The Player Hasn't Chosen To Host Or To Join
		&#123;
			pspDebugScreenSetXY&#40;0, 1&#41;;			//Set Text X & Y
			pspDebugScreenPrintf&#40;"To Host A Game Press &#91;&#93;\n"&#41;;
			pspDebugScreenPrintf&#40;"To Join A Game Press /\\\n"&#41;;
			pspDebugScreenPrintf&#40;"To Quit Press &#40;&#41;"&#41;;
		&#125;
        //what button is pressed
	    sceDisplayWaitVblankStart&#40;&#41;;
		sceCtrlReadBufferPositive&#40;&pad, 1&#41;;


         if&#40;pad.Buttons & PSP_CTRL_SQUARE&#41;
		&#123;
			if &#40;user != 1&#41;
				&#123;
					user = 1;	//Set Player To Host
				&#125;
		&#125;


	if&#40;pad.Buttons & PSP_CTRL_TRIANGLE&#41;
		&#123;
			if &#40;user != 2&#41; &#123;user = 2;&#125;	//Set Player To Guest
		&#125;

	if&#40;pad.Buttons & PSP_CTRL_CIRCLE&#41; &#123;encore = 0; init = 0; pPsp = 0; user = 0; continue;&#125;	//Quit

	/**HOST**/
	if &#40;user == 1&#41;
		&#123;
			if &#40;init == 0&#41;
				&#123;
					pPsp= ZBadhoc&#58;&#58;getSingleton&#40;&#41;.selectAPsp&#40;&#41;;		//Select A PSP
					receive = ZBadhoc&#58;&#58;getSingleton&#40;&#41;.requestConnection&#40;pPsp&#41;;	//Request Connection
					if&#40; pPsp==NULL&#41; &#123;encore = 0; continue;&#125;			//If No PSP Is Chosen then Exit
					initOSLib&#40;&#41;;
					LoadImages&#40;&#41;;	//Load Images
					init = 1;	//End Initiation
				&#125;

			if &#40;init == 1&#41;	//Main Loop After Initiation-
				&#123;
					/**Main Functions**/
					DrawImages&#40;&#41;;
					if &#40;osl_keys->held.right&#41; &#123;p1.x+=4;&#125;
					if &#40;osl_keys->held.left&#41; &#123;p1.x-=4;&#125;
					if &#40;osl_keys->held.up&#41; &#123;p1.y--;&#125;
					if &#40;osl_keys->held.down&#41; &#123;p1.y++;&#125;

					/**Ad-Hoc Functions**/
					if &#40;receive < 0&#41; &#123;continue;&#125;	//If No Signal, then Exit.
					sprintf&#40;data,"%i",p1.x&#41;;	//convert int to char
					send = ZBadhoc&#58;&#58;getSingleton&#40;&#41;.sendData&#40;pPsp,data,strlen&#40;data&#41;&#41;;//send a messge to the other PSP
					receive = ZBadhoc&#58;&#58;getSingleton&#40;&#41;.receiveData&#40; pPsp, buffer, 42&#41;;	//receive data
					if &#40;receive > 0&#41; &#123;buffer&#91;receive&#93;=0; string2int&#40;buffer,p2.x&#41;;&#125;	//convert char to int
					receive = 0;
				&#125;
		&#125;

	/**GUEST**/
	if &#40;user == 2&#41;
		&#123;
			if &#40;init == 0&#41;
				&#123;
					pPsp = ZBadhoc&#58;&#58;getSingleton&#40;&#41;.waitForConnection&#40;&#41;;	//Wait For Connection
					if &#40;pPsp == NULL&#41; &#123;continue;&#125;				//If No PSP Is Chosen Then Exit
					initOSLib&#40;&#41;;	//Initiate Old School Library
					LoadImages&#40;&#41;;	//Load Images
					init = 1;	//End Initiation
				&#125;



			if &#40;init == 1&#41;	//Main Loop After Initiation
				&#123;
					/**Main Functions**/
					DrawImages&#40;&#41;;
					if &#40;osl_keys->held.right&#41; &#123;p2.x+=4;&#125;
					if &#40;osl_keys->held.left&#41; &#123;p2.x-=4;&#125;
					if &#40;osl_keys->held.up&#41; &#123;p2.y--;&#125;
					if &#40;osl_keys->held.down&#41; &#123;p2.y++;&#125;

					/**Ad-Hoc Functions**/
					if &#40;receive < 0&#41; &#123;continue;&#125;	//If No Signal, then Exit.
					sprintf&#40;data,"%i",p2.x&#41;;	//int to char
					send = ZBadhoc&#58;&#58;getSingleton&#40;&#41;.sendData&#40;pPsp,data,strlen&#40;data&#41;&#41;;//send a messge to the other PSP
					receive = ZBadhoc&#58;&#58;getSingleton&#40;&#41;.receiveData&#40; pPsp, buffer, 42&#41;;	//Receive data
					if &#40;receive > 0&#41; &#123;buffer&#91;receive&#93;=0; string2int&#40;buffer,p1.x&#41;;&#125;	//char to int
					receive = 0;
				&#125;
		&#125;



    &#125;//end of main while
	pspDebugScreenClear&#40;&#41;;
	pspDebugScreenPrintf&#40;"Done."&#41;;
	sceKernelSleepThread&#40;&#41;;
return 0;
&#125;


/* Exit callback */
int exit_callback&#40;int arg1, int arg2, void *common&#41;
&#123;
        sceKernelExitGame&#40;&#41;;
        return &#40;int&#41;0;
&#125;

/* Callback thread */
int CallbackThread&#40;SceSize args, void *argp&#41;
&#123;
        int cbid;

        cbid = sceKernelCreateCallback&#40;"Exit Callback", exit_callback, NULL&#41;;
        sceKernelRegisterExitCallback&#40;cbid&#41;;

        sceKernelSleepThreadCB&#40;&#41;;

        return 0;
&#125;

int sceInit&#40;void&#41;
&#123;
       int thid = 0;

        thid = sceKernelCreateThread&#40;"update_thread", CallbackThread, 0x11, 0xFA0, 0, 0&#41;;
        if&#40;thid >= 0&#41;
        &#123;
                sceKernelStartThread&#40;thid, 0, 0&#41;;
        &#125;

        return thid;
&#125;

void LoadImages&#40;&#41;
&#123;
	p1.img = oslLoadImageFilePNG&#40;"img.png", OSL_IN_RAM,OSL_PF_5551&#41;;
	p2.img = oslLoadImageFilePNG&#40;"img.png", OSL_IN_RAM,OSL_PF_5551&#41;;
&#125;

void DrawImages&#40;&#41;
&#123;
oslStartDrawing&#40;&#41;;	//Start Drawing
oslCls&#40;&#41;;		//Clear Screen
oslReadKeys&#40;&#41;;		//Read Input Keys
	if &#40;user == 1&#41; &#123;oslDrawImageXY&#40;p2.img,p2.x,p2.y&#41;; oslDrawImageXY&#40;p1.img,p1.x,p1.y&#41;;&#125;
	if &#40;user == 2&#41; &#123;oslDrawImageXY&#40;p1.img,p1.x,p1.y&#41;; oslDrawImageXY&#40;p2.img,p2.x,p2.y&#41;;&#125;
oslEndDrawing&#40;&#41;;	//End Drawing
oslAudioVSync&#40;&#41;;	//Synchronize Audio
oslSyncFrame&#40;&#41;;		//Synchronize Screen
&#125;
Smong
Posts: 82
Joined: Tue Sep 04, 2007 4:44 am

Post by Smong »

It would have been helpful if you posted a link to get the pspZorba's adhoc sample, I managed to find ZBadhoc.h in a copy of PSPlorer (link).

This looks like the relevant part of the header.

Code: Select all

    int sendData&#40; ZBremotePsp *pPsp, const void *data, int lenData&#41;;// send data to pPsp
    int receiveData&#40; ZBremotePsp *pPsp, void *data, int maxLen, int debug=0&#41;;// receive data from pPsp
Additionally buried in the .cpp, not in the .h file I found this:

Code: Select all

 * @return&#58; int
 * 0< if error, otherwise the number of bytes that were read
 * *************************************************************/
int ZBadhoc&#58;&#58;receiveData&#40; ZBremotePsp *pPsp, void *data, int maxLen, int debug&#41;

This is just a simple exercise in C/C++ programming. One way to deal with network comm's is to use packets, which are represented in code as structs. So here I'm sending the player 1 struct. You don't have to use char's the header file uses void* which can mean you are allowed to use any data type.

Code: Select all

//sending
sendData&#40;pPsp, &p1, sizeof&#40;Player1&#41;&#41;;

//receiving
receiveData&#40;pPsp, &p1, sizeof&#40;Player1&#41;&#41;;
However this is only good for testing. In reality you will have many different types of packet so you should receive into a temporary buffer and then determine what type the packet is before using it. Also you don't want to send pointers inside the packets, they won't work at the other end (such as images).

Code: Select all

#define MAX_PACKET_LENGTH 500 // may need to increase this
#define PLAYER_PKT 1
#define OTHER_PKT 2
...

typedef struct &#123;
   int packettype;
&#125; EmptyPacket;

typedef struct &#123;
   int packettype;
   int x,y;
   int state;
&#125; PlayerPacket;

//sending
PlayerPacket ppkt;

ppkt.packettype = PLAYER_PKT;
ppkt.x = p1.x;
ppkt.y = p1.y;
ppkt.state = p1.state;

// old&#58; sendData&#40;pPsp, &p1, sizeof&#40;PlayerPacket&#41;&#41;;
sendData&#40;pPsp, &ppkt, sizeof&#40;PlayerPacket&#41;&#41;; // edit&#58; fixed version

//receiving
char buf&#91;MAX_PACKET_LENGTH&#93;;
int len;
EmptyPacket *pkt;

len = receiveData&#40;pPsp, buf, MAX_PACKET_LENGTH&#41;;
pkt = &#40;EmptyPacket*&#41;buf;

if &#40;pkt->packettype == PLAYER_PKT &&
   len == sizeof&#40;PlayerPacket&#41;&#41;
&#123;
   // old&#58; PlayerPacket ppkt = &#40;PlayerPacket*&#41;buf;
   PlayerPacket *ppkt = &#40;PlayerPacket*&#41;buf; // edit&#58; fixed version
   p1.x = ppkt->x;
   p1.y = ppkt->y;
   p1.state = ppkt->state;
&#125;
Edit:
Fixed the PlayerPacket ppkt/PlayerPacket *ppkt in the sample.
Also noticed another error! When sending,

Code: Select all

sendData&#40;pPsp, &p1, sizeof&#40;PlayerPacket&#41;&#41;; // old version
sendData&#40;pPsp, &ppkt, sizeof&#40;PlayerPacket&#41;&#41;; // fixed version
Last edited by Smong on Thu Apr 17, 2008 10:02 pm, edited 1 time in total.
(+[__]%)
Sp3ct0r
Posts: 3
Joined: Wed Apr 16, 2008 7:19 am

Post by Sp3ct0r »

OMG YES!!! Tyvm Smong! :D I was able to send a packet perfectly!!! My only issue was that when i tried to use a temporary buffer to determine the packet type and stuff, it gave me these errors:

error: conversion from ‘PlayerPacket*’ to non-scalar type ‘PlayerPacket’ requested
error: base operand of ‘->’ has non-pointer type ‘PlayerPacket’

however when I just used

Code: Select all

//sending
sendData&#40;pPsp, &p1, sizeof&#40;Player1&#41;&#41;;

//receiving
receiveData&#40;pPsp, &p1, sizeof&#40;Player1&#41;&#41;;
It worked flawlessly.
Smong
Posts: 82
Joined: Tue Sep 04, 2007 4:44 am

Post by Smong »

error: conversion from ‘PlayerPacket*’ to non-scalar type ‘PlayerPacket’ requested
You have to look at the hint. One has a * the other doesn't. Here's the fix:

Code: Select all

//old
PlayerPacket ppkt = &#40;PlayerPacket*&#41;buf;

//fixed
PlayerPacket *ppkt = &#40;PlayerPacket*&#41;buf;
And if anyone else is reading this thread I just found the adhoc code you were referring to here:
http://forums.ps2dev.org/viewtopic.php?p=67549#67549
It's not exactly identical to the PSPlorer version, but similar.
(+[__]%)
pspZorba
Posts: 156
Joined: Sat Sep 22, 2007 11:45 am
Location: NY

Post by pspZorba »

the first thread was some tests I made to understand how it works. The other code (from PSPlorer) is just a little bit more recent.
--pspZorba--
NO to K1.5 !
Smong
Posts: 82
Joined: Tue Sep 04, 2007 4:44 am

Post by Smong »

Thanks for that clarification.

I went back and edited my original example and also fixed another bug I just noticed.
(+[__]%)
Post Reply