Switch port (wip, squash later)

This commit is contained in:
TuxSH 2018-02-02 15:35:22 +01:00 committed by mtheall
parent d00b1a8c71
commit 7e00ed2054
6 changed files with 397 additions and 14 deletions

4
.gitignore vendored
View File

@ -6,3 +6,7 @@ ftpd
*.cia
*.smdh
*.elf
*.nso
*.pfs0
*.nacp
*.nro

View File

@ -1,4 +1,4 @@
.PHONY: all 3dsx cia clean linux
.PHONY: all switch 3dsx cia clean linux
export GITREV := $(shell git rev-parse HEAD 2>/dev/null | cut -c1-8)
export VERSION_MAJOR := 2
@ -12,15 +12,19 @@ endif
all: 3dsx
switch:
@$(MAKE) -f Makefile.switch all
3dsx:
@$(MAKE) -f Makefile.3ds 3dsx
cia:
@$(MAKE) -f Makefile.3ds cia
linux:
@$(MAKE) -f Makefile.linux
clean:
@$(MAKE) -f Makefile.switch clean
@$(MAKE) -f Makefile.3ds clean
@$(MAKE) -f Makefile.linux clean

184
Makefile.switch Normal file
View File

@ -0,0 +1,184 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITPRO)/libnx/switch_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
# EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm".
#
# NO_ICON: if set to anything, do not use icon.
# NO_NACP: if set to anything, no .nacp file is generated.
# APP_TITLE is the name of the app stored in the .nacp file (Optional)
# APP_AUTHOR is the author of the app stored in the .nacp file (Optional)
# APP_VERSION is the version of the app stored in the .nacp file (Optional)
# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional)
# ICON is the filename of the icon (.jpg), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.jpg
# - icon.jpg
# - <libnx folder>/default_icon.jpg
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
EXEFS_SRC := exefs_src
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv8-a -mtp=soft -fPIE
CFLAGS := -g -Wall -O2 \
-ffast-math \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -DSWITCH -D_SWITCH -DSTATUS_STRING="\"ftpd v$(VERSION)\""
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lnx
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(LIBNX)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC)
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.jpg)
ifneq (,$(findstring $(TARGET).jpg,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).jpg
else
ifneq (,$(findstring icon.jpg,$(icons)))
export APP_ICON := $(TOPDIR)/icon.jpg
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_ICON)),)
export NROFLAGS += --icon=$(APP_ICON)
endif
ifeq ($(strip $(NO_NACP)),)
export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp
endif
ifneq ($(APP_TITLEID),)
export NACPFLAGS += --titleid=$(APP_TITLEID)
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile.switch
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).pfs0 $(TARGET).nso $(TARGET).nro $(TARGET).nacp $(TARGET).elf
#---------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all : $(OUTPUT).pfs0 $(OUTPUT).nro
$(OUTPUT).pfs0 : $(OUTPUT).nso
$(OUTPUT).nso : $(OUTPUT).elf
ifeq ($(strip $(NO_NACP)),)
$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp
else
$(OUTPUT).nro : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -191,6 +191,97 @@ console_render(void)
gspWaitForVBlank();
gfxSwapBuffers();
}
#elif defined(_SWITCH)
#include <switch.h>
static PrintConsole status_console;
static PrintConsole main_console;
#if ENABLE_LOGGING
static bool disable_logging = false;
#endif
/*! initialize console subsystem */
void
console_init(void)
{
consoleInit(&status_console);
consoleSetWindow(&status_console, 0, 0, 50, 1);
consoleInit( &main_console);
consoleSetWindow(&main_console, 0, 1, 50, 29);
consoleSelect(&main_console);
}
/*! set status bar contents
*
* @param[in] fmt format string
* @param[in] ... format arguments
*/
void
console_set_status(const char *fmt, ...)
{
va_list ap;
consoleSelect(&status_console);
va_start(ap, fmt);
vprintf(fmt, ap);
#ifdef ENABLE_LOGGING
vfprintf(stderr, fmt, ap);
#endif
va_end(ap);
consoleSelect(&main_console);
}
/*! add text to the console
*
* @param[in] fmt format string
* @param[in] ... format arguments
*/
void
console_print(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
#ifdef ENABLE_LOGGING
if(!disable_logging)
vfprintf(stderr, fmt, ap);
#endif
va_end(ap);
}
/*! print debug message
*
* @param[in] fmt format string
* @param[in] ... format arguments
*/
void
debug_print(const char *fmt, ...)
{
#ifdef ENABLE_LOGGING
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
#endif
}
/*! draw console to screen */
void
console_render(void)
{
/* flush framebuffer */
gfxFlushBuffers();
gfxSwapBuffers();
gfxWaitForVsync();
}
#else
/* this is a lot easier when you have a real console */

View File

@ -26,6 +26,9 @@
#ifdef _3DS
#include <3ds.h>
#define lstat stat
#elif defined(_SWITCH)
#include <switch.h>
#define lstat stat
#else
#include <stdbool.h>
#define BIT(x) (1<<(x))
@ -252,6 +255,10 @@ static bool lcd_power = true;
/*! aptHook cookie */
static aptHookCookie cookie;
#elif defined(_SWITCH)
/*! appletHook cookie */
static AppletHookCookie cookie;
#endif
/*! server listen address */
@ -730,7 +737,7 @@ ftp_session_fill_dirent_type(ftp_session_t *session, const struct stat *st,
type = "file";
else if(S_ISDIR(st->st_mode))
type = "dir";
#ifndef _3DS
#if !defined(_3DS) && !defined(_SWITCH)
else if(S_ISLNK(st->st_mode))
type = "os.unix=symlink";
else if(S_ISCHR(st->st_mode))
@ -842,7 +849,7 @@ ftp_session_fill_dirent_type(ftp_session_t *session, const struct stat *st,
"%c%c%c%c%c%c%c%c%c%c %lu 3DS 3DS %lld ",
S_ISREG(st->st_mode) ? '-' :
S_ISDIR(st->st_mode) ? 'd' :
#ifndef _3DS
#if !defined(_3DS) && !defined(_SWITCH)
S_ISLNK(st->st_mode) ? 'l' :
S_ISCHR(st->st_mode) ? 'c' :
S_ISBLK(st->st_mode) ? 'b' :
@ -1738,7 +1745,7 @@ ftp_session_poll(ftp_session_t *session)
static void
update_free_space(void)
{
#ifdef _3DS
#if defined(_3DS) || defined(_SWITCH)
#define KiB (1024.0)
#define MiB (1024.0*KiB)
#define GiB (1024.0*MiB)
@ -1784,7 +1791,7 @@ update_free_space(void)
static int
update_status(void)
{
#ifdef _3DS
#if defined(_3DS) || defined(_SWITCH)
console_set_status("\n" GREEN STATUS_STRING " "
#ifdef ENABLE_LOGGING
"DEBUG "
@ -1805,12 +1812,13 @@ update_status(void)
return -1;
}
rc = gethostname(hostname, sizeof(hostname));
strcpy(hostname, "banana");
/*rc = gethostname(hostname, sizeof(hostname));
if(rc != 0)
{
console_print(RED "gethostname: %d %s\n" RESET, errno, strerror(errno));
return -1;
}
}*/
console_set_status(GREEN STATUS_STRING " "
#ifdef ENABLE_LOGGING
@ -1862,6 +1870,23 @@ apt_hook(APT_HookType type,
break;
}
}
#elif defined(_SWITCH)
/*! Handle applet events
*
* @param[in] type Event type
* @param[in] closure Callback closure
*/
static void
applet_hook(AppletHookType type,
void *closure)
{
/* stubbed for now */
switch(type)
{
default:
break;
}
}
#endif
/*! initialize ftp subsystem */
@ -1923,9 +1948,34 @@ ftp_init(void)
ret = socInit(SOCU_buffer, SOCU_BUFFERSIZE);
if(ret != 0)
{
console_print(RED "socInit: 0x%08X\n" RESET, (unsigned int)ret);
console_print(RED "socInit: %08X\n" RESET, (unsigned int)ret);
goto soc_fail;
}
#elif defined(_SWITCH)
/* we have a lot of memory available so let's use c.a. 360MB */
static const SocketInitConfig socketInitConfig = {
.bsdsockets_version = 1,
.tcp_tx_buf_size = 20 << 20,
.tcp_rx_buf_size = 20 << 20,
.tcp_tx_buf_max_size = 20 << 20,
.tcp_rx_buf_max_size = 20 << 20,
/* we aren't using UDP at all, let's just use the default sizes */
.udp_tx_buf_size = 0x2400,
.udp_rx_buf_size = 0xA500,
.sb_efficiency = 8,
};
Result ret = socketInitialize(&socketInitConfig);
if(ret != 0)
{
console_print(RED "socketInitialize: %X\n" RESET, (unsigned int)ret);
return -1;
}
/* register applet hook */
appletHook(&cookie, applet_hook, NULL);
#endif
/* allocate socket to listen for clients */
@ -2001,7 +2051,7 @@ memalign_fail:
void
ftp_exit(void)
{
#ifdef _3DS
#if defined(_3DS)
Result ret;
#endif
@ -2027,6 +2077,13 @@ ftp_exit(void)
console_print(RED "socExit: 0x%08X\n" RESET, (unsigned int)ret);
free(SOCU_buffer);
}
#elif defined(_SWITCH)
/* deinitialize socket driver */
console_render();
console_print(CYAN "Waiting for socketExit()...\n" RESET);
socketExit();
#endif
}
@ -2089,6 +2146,13 @@ ftp_loop(void)
lcd_power = !lcd_power;
apt_hook(APTHOOK_ONRESTORE, NULL);
}
#elif defined(_SWITCH)
/* check if the user wants to exit */
hidScanInput();
u32 down = hidKeysDown(CONTROLLER_P1_AUTO);
if(down & KEY_B)
return LOOP_EXIT;
#endif
return LOOP_CONTINUE;
@ -3401,7 +3465,7 @@ FTP_DECLARE(PASV)
/* grab a new port */
session->pasv_addr.sin_port = htons(next_data_port());
#ifdef _3DS
#if defined(_3DS) || defined(_SWITCH)
console_print(YELLOW "binding to %s:%u\n" RESET,
inet_ntoa(session->pasv_addr.sin_addr),
ntohs(session->pasv_addr.sin_port));

View File

@ -1,3 +1,4 @@
#include <errno.h>
#include <malloc.h>
#include <stdarg.h>
@ -5,6 +6,8 @@
#include <unistd.h>
#ifdef _3DS
#include <3ds.h>
#elif defined(_SWITCH)
#include <switch.h>
#endif
#include "console.h"
#include "ftp.h"
@ -28,7 +31,15 @@ loop(loop_status_t (*callback)(void))
if(status != LOOP_CONTINUE)
return status;
}
return LOOP_EXIT;
#elif defined(_SWITCH)
while(appletMainLoop())
{
status = callback();
console_render();
if(status != LOOP_CONTINUE)
return status;
}
return LOOP_EXIT;
#else
while(status == LOOP_CONTINUE)
@ -55,6 +66,24 @@ wait_for_b(void)
/* B was not pressed */
return LOOP_CONTINUE;
}
#elif defined(_SWITCH)
/*! wait until the B button is pressed
*
* @returns loop status
*/
static loop_status_t
wait_for_b(void)
{
/* update button state */
hidScanInput();
/* check if B was pressed */
if(hidKeysDown(CONTROLLER_P1_AUTO) & KEY_B)
return LOOP_EXIT;
/* B was not pressed */
return LOOP_CONTINUE;
}
#endif
/*! entry point
@ -76,6 +105,9 @@ main(int argc,
gfxInitDefault();
gfxSet3D(false);
sdmcWriteSafe(false);
#elif defined(_SWITCH)
gfxInitResolution(644, 480);
gfxInitDefault();
#endif
/* initialize console subsystem */
@ -123,7 +155,7 @@ main(int argc,
status = LOOP_EXIT;
}
#ifdef _3DS
#if defined(_3DS) || defined(_SWITCH)
console_print("Press B to exit\n");
#endif
@ -139,7 +171,11 @@ log_fail:
/* deinitialize 3DS services */
gfxExit();
acExit();
#endif
#elif defined(_SWITCH)
loop(wait_for_b);
/* deinitialize Switch services */
gfxExit();
#endif
return 0;
}