XBox360 Homebrew Development Wiki
Advertisement

By default, retail consoles don't have a debug option, neither do they have a debug kernel which would allow us to keep track of errors. So team XeLove coded a network based debug assister for XDK programmers. Logging over LAN, Stop/Start XEX, and builtin FTP server.

Basics[]

XeDebug is made up three parts.


1: The Launcher


2: C++ Includes


3: The XeDebug Server

At anytime more information can be found at xboxhacker


[]

Install[]

Xexdebugwin
[]

Simply edit ftpd.conf for your host's IP. Copy the folder XeDebug to the root of HDD1. And run either from XexMenu or build a GoD con.

NOTE** Copy xarialuni.ttf to XeDebug/media/

Debug XEX's are launched as HDD1:/XeDebug/Debug/ and can be FTP'ed username: xbox password: xbox



Sourcecode[]

XeDebug.cpp[]

#include <xtl.h>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

#define DEVICE_NAND_FLASH 0
#define DEVICE_MEMORY_UNIT0 1
#define DEVICE_MEMORY_UNIT1 2
#define DEVICE_CDROM0 3
#define DEVICE_HARDISK0_PART0 4
#define DEVICE_HARDISK0_PART1 5
#define DEVICE_HARDISK0_PART2 6
#define DEVICE_HARDISK0_PART3 7
#define DEVICE_USB0 8
#define DEVICE_USB1 9
#define DEVICE_USB2 10

DWORD dwLaunchDataSize = 0;
DWORD dwStatus;
bool IsDebugging = false;

SOCKET _sClientSocket;

struct CustomLaunchData {
    DWORD dwID;
	char chVersion[6];
	char chHost[24];
	int intPort;
	char DebuggerPath[100];
};
CustomLaunchData* pCustomData = NULL;

typedef struct _STRING {
    USHORT Length;
    USHORT MaximumLength;
    PCHAR Buffer;
} STRING;
    
extern "C" int __stdcall ObCreateSymbolicLink( STRING*, STRING*);
extern "C" int __stdcall ObDeleteSymbolicLink( STRING* );

DWORD WINAPI ThreadDebug(LPVOID lpParam);
void debugLog(char* output);

HRESULT Monter( int periphPhys, char* lettreLecteur ) {
     char lecteurCible[16];
     sprintf_s( lecteurCible,"\\??\\%s", lettreLecteur );

     char * periphOriginal;
     switch(periphPhys) {
		 case DEVICE_NAND_FLASH:
			periphOriginal = "\\Device\\Flash";
			break;
		 case DEVICE_MEMORY_UNIT0:
			periphOriginal = "\\Device\\Mu0";
			break;
		 case DEVICE_MEMORY_UNIT1:
			periphOriginal = "\\Device\\Mu1";
			break;
		 case DEVICE_CDROM0:
			periphOriginal = "\\Device\\Cdrom0";
			break;
		 case DEVICE_HARDISK0_PART0:
			periphOriginal = "\\Device\\Harddisk0\\Partition0";
			break;
		 case DEVICE_HARDISK0_PART1:
			periphOriginal = "\\Device\\Harddisk0\\Partition1";
			break;
		 case DEVICE_HARDISK0_PART2:
			periphOriginal = "\\Device\\Harddisk0\\Partition2";
			break;
		 case DEVICE_HARDISK0_PART3:
			periphOriginal = "\\Device\\Harddisk0\\Partition3";
			break;
		 case DEVICE_USB0:
			periphOriginal = "\\Device\\Mass0";
			break;
		 case DEVICE_USB1:
			periphOriginal = "\\Device\\Mass1";
			break;
		 case DEVICE_USB2:
			periphOriginal = "\\Device\\Mass2";
			break;
	 }
     STRING PeriphOriginal = { (USHORT)strlen( periphOriginal ), (USHORT)strlen( periphOriginal ) + 1, periphOriginal };
     STRING LienSymbolique = { (USHORT)strlen( lecteurCible ), (USHORT)strlen( lecteurCible ) + 1, lecteurCible };
   return ( HRESULT )   ObCreateSymbolicLink( &LienSymbolique, &PeriphOriginal );
}

bool StartDebugger() {
    dwLaunchDataSize = 0;
    dwStatus = XGetLaunchDataSize( &dwLaunchDataSize );
    if( dwStatus == ERROR_SUCCESS ) {
        BYTE* pLaunchData = new BYTE [ dwLaunchDataSize ];
        dwStatus = XGetLaunchData( pLaunchData, dwLaunchDataSize );
 
        pCustomData = ( CustomLaunchData* )( pLaunchData );

		// === Connect to XeDebug Server ================================
		BOOL bBroadcast = TRUE;
		WSADATA	_WSAData;

		DWORD dwStatus = XNetGetEthernetLinkStatus();
		int m_bIsActive = (dwStatus & XNET_ETHERNET_LINK_ACTIVE) != 0;

		if(!m_bIsActive) {
			debugLog("No Ethernet Link Active");
			return false;
		}

		debugLog("Ethernet Link Active");

		XNetStartupParams _XNetStartupParams;
		memset(&_XNetStartupParams, 0, sizeof(_XNetStartupParams));
		_XNetStartupParams.cfgSizeOfStruct = sizeof(XNetStartupParams);
		_XNetStartupParams.cfgSockDefaultRecvBufsizeInK = 128; 
		_XNetStartupParams.cfgSockDefaultSendBufsizeInK = 128;
		_XNetStartupParams.cfgFlags = XNET_STARTUP_BYPASS_SECURITY;

		int iResult = XNetStartup( &_XNetStartupParams );
		if (iResult != NO_ERROR) {
			debugLog("XNetStartup Failed");
			return false;
		}

		iResult = WSAStartup( MAKEWORD(2,2), &_WSAData );
		if (iResult != NO_ERROR) {
			debugLog("WSAStartup Failed");
			return false;
		}

		sockaddr_in _sDestinationAddr;

		memset(&_sDestinationAddr, 0, sizeof(_sDestinationAddr));
		_sDestinationAddr.sin_family = AF_INET;
		_sDestinationAddr.sin_addr.S_un.S_addr = inet_addr(pCustomData->chHost);
		_sDestinationAddr.sin_port = htons(pCustomData->intPort);

		_sClientSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

		if (_sClientSocket == INVALID_SOCKET) {
			debugLog("Error While Creating The Socket");
			return false;
		}

		if( setsockopt(_sClientSocket, SOL_SOCKET, 0x5802, (PCSTR)&bBroadcast, sizeof(BOOL)) != 0 ) {
		   debugLog("Failed to set socket to 5802, error");
		   return false;
		}

		if( setsockopt(_sClientSocket, SOL_SOCKET, 0x5801, (PCSTR)&bBroadcast, sizeof(BOOL)) != 0 ) {
		   debugLog("Failed to set socket to 5801, error");
		   return false;
		}

		if (connect(_sClientSocket, (struct sockaddr *) &_sDestinationAddr, sizeof(_sDestinationAddr)) < 0) {
			debugLog("Connection to XeDebug Server failed");
			return false;
		}
		send(_sClientSocket, "XEDBG|APP", sizeof("XEDBG|APP"), 0);
		Sleep(200);

		DWORD dwThreadId; 
		CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadDebug, 0, 0, &dwThreadId);

		IsDebugging = true;
		return true;
    }
	return false;
}

void EndDebugger() {
	if(!IsDebugging) return;
	if(pCustomData == NULL) return;

	send(_sClientSocket, "XEDISCODBG", (int)strlen("XEDISCODBG"), 0);

	Monter(DEVICE_HARDISK0_PART1, "hdd1:");
	XLaunchNewImage(pCustomData->DebuggerPath, NULL);
}

DWORD WINAPI ThreadDebug(LPVOID lpParam) 
{ 
	XSetThreadProcessor(GetCurrentThread(), 2);

	char recvbuf[1024] = {0};
	int iResult;
	do {
		memset(recvbuf, 0, sizeof(recvbuf));
		iResult = recv(_sClientSocket, recvbuf, sizeof(recvbuf), 0);
		if(strcmp(recvbuf, "/START") == 0) { 
			send(_sClientSocket, "XEDISCODBG", sizeof("XEDISCODBG"), 0);

			Monter(DEVICE_HARDISK0_PART1, "hdd1:");
			XLaunchNewImage(pCustomData->DebuggerPath, 0);
		} else if(strcmp(recvbuf, "/RESTART") == 0) {
			send(_sClientSocket, "XEDISCOAPP", sizeof("XEDISCOAPP"), 0);

			Monter(DEVICE_HARDISK0_PART1, "hdd1:");
			XSetLaunchData(pCustomData, sizeof(pCustomData));
			XLaunchNewImage("hdd1:\\XeDebug\\debug\\default.xex", 0);
		} else {

		}
	} while (iResult > 0);

	IsDebugging = false;
	return 0;
}

void debugLog(char* output) {
    ofstream writeLog;
	if(IsDebugging) {
		char sendbuf[256];
		sprintf_s(sendbuf,sizeof(sendbuf),"LOG|%s", output);
		send(_sClientSocket, sendbuf, (int)strlen(sendbuf), 0);
	} else {
		// Credits to dstruktiv
		writeLog.open("game:\\debug.log",ofstream::app);
		if (writeLog.is_open()) {
		  writeLog.write(output,strlen(output));
		  writeLog.write("\n",1);
		}
		writeLog.close();
	}
}

xedebug.h[]

bool StartDebugger();
void EndDebugger();


Using your debug function[]

Whenever you want an event to get logged, just call your function:

#include <xtl.h>
#include "AtgConsole.h"
#include "AtgUtil.h"
#include "AtgInput.h"

ATG::Console console;
#include "XeDebug.h"

VOID __cdecl main() {
    
    console.Create( "game:\\Media\\Fonts\\Arial_12.xpr", 0x2F0230FF, 0xFFFFFFFF );

	if(StartDebugger())
        console.Format("XeDebug Started\n");
	else 
		console.Format("XeDebug Failed to Start\n");

	debugLog("Hello World");
    DWORD startTime = GetTickCount();
    while(GetTickCount() < startTime + 20000) {
       // Wait 20 seconds then return to XeDebug
    }

	EndDebugger();
}


  • thanks to Team XeLove
Advertisement