Skip to content

Instantly share code, notes, and snippets.

@smealum
Created July 10, 2014 00:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smealum/249b0e5598409f78b5eb to your computer and use it in GitHub Desktop.
Save smealum/249b0e5598409f78b5eb to your computer and use it in GitHub Desktop.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctr/types.h>
#include <ctr/srv.h>
#include <ctr/APT.h>
#include <ctr/GSP.h>
#include <ctr/HID.h>
#include <ctr/SOC.h>
#include <ctr/FS.h>
#include <ctr/svc.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "costable.h"
#include "text.h"
#define NUM_FILES (12)
s64 DEBUGVAL[5];
u8* gspHeap;
u32* gxCmdBuf;
u8 currentBuffer;
u8* topLeftFramebuffers[2];
Handle gspEvent, gspSharedMemHandle;
void gspGpuInit()
{
gspInit();
GSPGPU_AcquireRight(NULL, 0x0);
GSPGPU_SetLcdForceBlack(NULL, 0x0);
//set subscreen to blue
u32 regData=0x01FF0000;
GSPGPU_WriteHWRegs(NULL, 0x202A04, (u8*)&regData, 4);
//grab main left screen framebuffer addresses
GSPGPU_ReadHWRegs(NULL, 0x400468, (u8*)&topLeftFramebuffers, 8);
//convert PA to VA (assuming FB in VRAM)
topLeftFramebuffers[0]+=0x7000000;
topLeftFramebuffers[1]+=0x7000000;
//setup our gsp shared mem section
u8 threadID;
svc_createEvent(&gspEvent, 0x0);
GSPGPU_RegisterInterruptRelayQueue(NULL, gspEvent, 0x1, &gspSharedMemHandle, &threadID);
svc_mapMemoryBlock(gspSharedMemHandle, 0x10002000, 0x3, 0x10000000);
//commit GSP heap
svc_controlMemory((u32*)&gspHeap, 0x0, 0x0, 0x2000000, 0x10003, 0x3);
//wait until we can write stuff to it
svc_waitSynchronization1(gspEvent, 0x55bcb0);
//GSP shared mem : 0x2779F000
gxCmdBuf=(u32*)(0x10002000+0x800+threadID*0x200);
currentBuffer=0;
}
void gspGpuExit()
{
GSPGPU_UnregisterInterruptRelayQueue(NULL);
//unmap GSP shared mem
svc_unmapMemoryBlock(gspSharedMemHandle, 0x10002000);
svc_closeHandle(gspSharedMemHandle);
svc_closeHandle(gspEvent);
gspExit();
//free GSP heap
svc_controlMemory((u32*)&gspHeap, (u32)gspHeap, 0x0, 0x2000000, MEMOP_FREE, 0x0);
}
void swapBuffers()
{
u32 regData;
GSPGPU_ReadHWRegs(NULL, 0x400478, (u8*)&regData, 4);
regData^=1;
currentBuffer=regData&1;
GSPGPU_WriteHWRegs(NULL, 0x400478, (u8*)&regData, 4);
}
void copyBuffer()
{
//copy topleft FB
u8 copiedBuffer=currentBuffer^1;
u8* bufAdr=&gspHeap[0x46500*copiedBuffer];
GSPGPU_FlushDataCache(NULL, bufAdr, 0x46500);
//GX RequestDma
u32 gxCommand[0x8];
gxCommand[0]=0x00; //CommandID
gxCommand[1]=(u32)bufAdr; //source address
gxCommand[2]=(u32)topLeftFramebuffers[copiedBuffer]; //destination address
gxCommand[3]=0x46500; //size
gxCommand[4]=gxCommand[5]=gxCommand[6]=gxCommand[7]=0x0;
GSPGPU_submitGxCommand(gxCmdBuf, gxCommand, NULL);
}
s32 pcCos(u16 v)
{
return costable[v&0x1FF];
}
u32 cnt;
char superStr[8192];
char testOutput[4096];
void renderEffect()
{
u8* bufAdr=&gspHeap[0x46500*currentBuffer];
int i, j;
for(i=1;i<400;i++)
{
for(j=1;j<240;j++)
{
u32 v=(j+i*240)*3;
bufAdr[v]=(pcCos(i+cnt)+4096)/32;
bufAdr[v+1]=(pcCos(j-256+cnt)+4096)/64;
bufAdr[v+2]=(pcCos(i+128-cnt)+4096)/32;
}
}
drawString(bufAdr, superStr, 0, 0);
cnt++;
}
s32 debugValue=0x0;
void outputMenuString()
{
siprintf(superStr, "crappy FTP 2000 (%08X = %d)\n",debugValue,debugValue);
strcat(superStr, testOutput);
}
typedef void* (*frameHandler)(void);
void* menuHandler();
Handle fsuHandle;
FS_archive sdmcArchive;
u32 testBuffer[0x1000/4];
bool draw=true;
u32 debugBuffer[4];
u32 oldPAD=0;
void* menuHandler()
{
// u32 PAD=hidSharedMem[7];
s64 BASE;
svc_getSystemInfo(&BASE,0,3);
siprintf(testOutput,"\n%08X, %08X, %08X, %08X, %08X\nBASE : %08X", (u32)DEBUGVAL[0], (u32)DEBUGVAL[1], (u32)DEBUGVAL[2], (u32)DEBUGVAL[3], (u32)DEBUGVAL[4], (u32)BASE);
outputMenuString();
// oldPAD=PAD;
return menuHandler;
}
unsigned long htonl(unsigned long v)
{
u8* v2=(u8*)&v;
return (v2[0]<<24)|(v2[1]<<16)|(v2[2]<<8)|(v2[3]);
}
unsigned short htons(unsigned short v)
{
u8* v2=(u8*)&v;
return (v2[0]<<8)|(v2[1]);
}
char tmpBuffer[512];
const int commandPort=5000;
const int dataPort=5001;
#define DATA_BUFFER_SIZE (512*1024)
char currentPath[4096];
char tmpStr[4096];
u32 dataBuffer[DATA_BUFFER_SIZE/4];
int ftp_openCommandChannel()
{
int listenfd;
struct sockaddr_in serv_addr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(commandPort);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
int ret=accept(listenfd, (struct sockaddr*)NULL, NULL);
closesocket(listenfd);
return ret;
}
int ftp_openDataChannel()
{
int listenfd;
struct sockaddr_in serv_addr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(dataPort);
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
listen(listenfd, 10);
int ret=accept(listenfd, (struct sockaddr*)NULL, NULL);
closesocket(listenfd);
return ret;
}
int ftp_sendResponse(int s, int n, char* mes)
{
char data[128];
sprintf(data, "%d %s\r\n", n, mes);
return send(s,data,strlen(data)+1,0);
}
void unicodeToChar(char* dst, u16* src)
{
if(!src || !dst)return;
while(*src)*(dst++)=(*(src++))&0xFF;
*dst=0x00;
}
int linelen(char* str)
{
int i=0; while(*str && *str!='\n' && *str!='\r'){i++;str++;}
*str=0x0;
return i;
}
int ftp_processCommand(int s, char* data)
{
if(!data)return -1;
int n=linelen(data);
char cmd[5];
char arg[256]="";
if(n>2 && (!data[3] || data[3]==' ' || data[3]=='\n' || data[3]=='\r')){memcpy(cmd,data,3);cmd[3]=0x0; if(n>3)memcpy(arg, &data[4], n-4);}
else if(n>3 && (!data[4] || data[4]==' ' || data[4]=='\r' || data[4]=='\n')){memcpy(cmd,data,4);cmd[4]=0x0; if(n>4)memcpy(arg, &data[5], n-5);}
else return -1;
sprintf(tmpBuffer,"\nreceived command : %s (%s)",cmd,arg);
strcat(testOutput, tmpBuffer);
outputMenuString();
renderEffect();
swapBuffers();
copyBuffer();
renderEffect();
swapBuffers();
copyBuffer();
renderEffect();
swapBuffers();
copyBuffer();
if(!strcmp(cmd, "PWD")){
siprintf(tmpStr, "\"%s\"",currentPath);
ftp_sendResponse(s, 257, tmpStr);
}else if(!strcmp(cmd, "PASV")){
char response[32];
sprintf(response, "Entering Passive Mode (192,168,0,17,%d,%d)",(dataPort-(dataPort%256))/256,dataPort%256);
ftp_sendResponse(s, 200, response);
}else if(!strcmp(cmd, "LIST")){
int data_s=ftp_openDataChannel();
ftp_sendResponse(s, 150, "opening ASCII data channel");
//send LIST data
Handle dirHandle;
FS_path dirPath=FS_makePath(PATH_CHAR, currentPath);
FSUSER_OpenDirectory(fsuHandle, &dirHandle, sdmcArchive, dirPath);
u32 entriesRead=0;
do{
u16 entryBuffer[512];
char data[256];
FSDIR_Read(dirHandle, &entriesRead, 1, entryBuffer);
if(!entriesRead)break;
unicodeToChar(data, entryBuffer);
siprintf((char*)entryBuffer, "%crwxrwxrwx 2 3DS %d Feb 1 2009 %s\r\n",entryBuffer[0x21c/2]?'d':'-',entryBuffer[0x220/2]|(entryBuffer[0x222/2]<<16),data);
send(data_s, entryBuffer, strlen((char*)entryBuffer), 0);
}while(entriesRead>0);
u8 endByte=0x0;
send(data_s, &endByte, 1, 0);
FSDIR_Close(dirHandle);
closesocket(data_s);
ftp_sendResponse(s, 226, "transfer complete");
}else if(!strcmp(cmd, "STOR")){
ftp_sendResponse(s, 150, "opening binary data channel");
int data_s=ftp_openDataChannel();
sprintf(tmpStr, "%s%s",currentPath,arg);
Handle fileHandle;
FSUSER_OpenFile(fsuHandle, &fileHandle, sdmcArchive, FS_makePath(PATH_CHAR, tmpStr), FS_OPEN_WRITE|FS_OPEN_CREATE, 0);
int ret;
u32 totalSize=0;
while((ret=recv(data_s, dataBuffer, DATA_BUFFER_SIZE, 0))>0){FSFILE_Write(fileHandle, (u32*)&ret, totalSize, (u32*)dataBuffer, ret, 0x10001);totalSize+=ret;}
FSFILE_Close(fileHandle);
closesocket(data_s);
ftp_sendResponse(s, 226, "transfer complete");
}else if(!strcmp(cmd, "RETR")){
ftp_sendResponse(s, 150, "opening binary data channel");
int data_s=ftp_openDataChannel();
sprintf(tmpStr, "%s%s",currentPath,arg);
sprintf(testOutput, "\n%s",tmpStr);
Handle fileHandle;
FSUSER_OpenFile(fsuHandle, &fileHandle, sdmcArchive, FS_makePath(PATH_CHAR, tmpStr), FS_OPEN_READ, 0);
int ret;
u32 readSize=0;
u32 totalSize=0;
do{
ret=FSFILE_Read(fileHandle, (u32*)&readSize, totalSize, (u32*)dataBuffer, DATA_BUFFER_SIZE);
if(ret || !readSize)break;
ret=send(data_s, dataBuffer, readSize, 0);
totalSize+=readSize;
}while(readSize && ret>0);
FSFILE_Close(fileHandle);
debugValue=ret;
closesocket(data_s);
ftp_sendResponse(s, 226, "transfer complete");
}else if(!strcmp(cmd, "USER")){
ftp_sendResponse(s, 200, "password ?");
}else if(!strcmp(cmd, "PASS")){
ftp_sendResponse(s, 200, "ok");
}else if(!strcmp(cmd, "CWD")){
if(arg[0]=='/')strcpy(currentPath,arg);
else strcat(currentPath,arg);
strcat(currentPath,"/");
ftp_sendResponse(s, 200, "ok");
}else if(!strcmp(cmd, "RETR")){
ftp_sendResponse(s, 200, "ok");
}else if(!strcmp(cmd, "TYPE")){
ftp_sendResponse(s, 200, "changed type");
}else if(!strcmp(cmd, "QUIT")){
ftp_sendResponse(s, 221, "disconnecting");
}else{
ftp_sendResponse(s, 502, "invalid command");
}
return 0;
}
int ftp_frame(int s)
{
char buffer[512];
memset(buffer, 0, 512);
recv(s,buffer,512,0);
return ftp_processCommand(s,buffer);
}
int main()
{
svc_getSystemInfo(&DEBUGVAL[0],0,1);
initSrv();
svc_getSystemInfo(&DEBUGVAL[1],0,1);
aptInit(APPID_APPLICATION);
svc_getSystemInfo(&DEBUGVAL[2],0,1);
gspGpuInit();
svc_getSystemInfo(&DEBUGVAL[3],0,1);
hidInit(NULL);
srv_getServiceHandle(NULL, &fsuHandle, "fs:USER");
FSUSER_Initialize(fsuHandle);
sdmcArchive=(FS_archive){0x9, (FS_path){PATH_EMPTY, 1, (u8*)""}};
FSUSER_OpenArchive(fsuHandle, &sdmcArchive);
u32 blockAddr;
svc_controlMemory(&blockAddr, 0x8000000, 0x0, 0x1910000, MEMOP_COMMIT, 0x3);
debugValue=SOC_Initialize((u32*)0x8bae000, 0x100000);
aptSetupEventHandler();
svc_getSystemInfo(&DEBUGVAL[4],0,1);
sprintf(currentPath, "/");
int connfd = ftp_openCommandChannel();
sprintf(tmpBuffer,"received connection ! %d\ngreeting...",connfd);
strcat(testOutput, tmpBuffer);
ftp_sendResponse(connfd, 200, "hello");
APP_STATUS status;
frameHandler curHandler=menuHandler;
while((status=aptGetStatus())!=APP_EXITING)
{
if(status==APP_RUNNING)
{
ftp_frame(connfd);
if(curHandler)curHandler=(frameHandler)curHandler();
renderEffect();
swapBuffers();
copyBuffer();
// renderEffect();
// swapBuffers();
// copyBuffer();
// renderEffect();
// swapBuffers();
// copyBuffer();
}
svc_sleepThread(16666666);
}
// closesocket(connfd);
// GSPGPU_ReleaseRight(NULL);
svc_controlMemory(&blockAddr, (u32)blockAddr, 0x0, 0x1910000, MEMOP_FREE, 0x0);
FSUSER_CloseArchive(fsuHandle, &sdmcArchive);
SOC_Shutdown();
svc_closeHandle(fsuHandle);
hidExit();
gspGpuExit();
aptExit();
// exitSrv();
*((u32*)0x58000000) = 4;
// svc_exitProcess();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment