Full Code of CTurt/3DSController for AI

master b38db7dcfcb8 cached
41 files
93.4 KB
34.2k tokens
92 symbols
1 requests
Download .txt
Repository: CTurt/3DSController
Branch: master
Commit: b38db7dcfcb8
Files: 41
Total size: 93.4 KB

Directory structure:
gitextract_emw3f_bd/

├── .gitignore
├── 3DS/
│   ├── 3DSController.ini
│   ├── Makefile
│   ├── cxi/
│   │   ├── banner.bnr
│   │   ├── build_cia.rsf
│   │   ├── gw_workaround.rsf
│   │   └── icon.icn
│   ├── include/
│   │   ├── drawing.h
│   │   ├── inet_pton.h
│   │   ├── input.h
│   │   ├── keyboard.h
│   │   ├── settings.h
│   │   └── wireless.h
│   └── source/
│       ├── drawing.c
│       ├── inet_pton.c
│       ├── input.c
│       ├── keyboard.c
│       ├── main.c
│       ├── settings.c
│       └── wireless.c
├── Linux/
│   ├── 3DSController.py
│   └── 3DSController_gamepad.py
├── PC/
│   ├── 3DSController.ini
│   ├── Makefile
│   ├── include/
│   │   ├── general.h
│   │   ├── joystick.h
│   │   ├── keyboard.h
│   │   ├── keys.h
│   │   ├── public.h
│   │   ├── settings.h
│   │   ├── vjoyinterface.h
│   │   └── wireless.h
│   ├── lib/
│   │   └── vJoyInterface.lib
│   └── source/
│       ├── general.c
│       ├── joystick.c
│       ├── keyboard.c
│       ├── keys.c
│       ├── main.c
│       ├── settings.c
│       └── wireless.c
└── README.md

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
3DS/build/
3DS/*.elf
3DS/*stripped.elf
3DS/*.3dsx
3DS/*.smdh
3DS/*.3ds
3DS/*.cia
PC/build/
PC/*.exe

================================================
FILE: 3DS/3DSController.ini
================================================
Change the IP to be your PC's local IP, (run 3DSController.exe to find it),

IP: 192.168.0.4
Port: 8889

================================================
FILE: 3DS/Makefile
================================================
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------

ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif

TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_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
#
# NO_SMDH: if set to anything, no SMDH file is generated.
# APP_TITLE is the name of the app stored in the SMDH file (Optional)
# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)
# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)
# ICON is the filename of the icon (.png), relative to the project folder.
#   If not set, it attempts to use one of the following (in this order):
#     - <Project name>.png
#     - icon.png
#     - <libctru folder>/default_icon.png
#---------------------------------------------------------------------------------
TARGET		:=	3DSController
BUILD		:=	build
SOURCES		:=	source
DATA		:=	data
INCLUDES	:=	include

APP_TITLE		:=	3DS Controller
APP_DESCRIPTION	:=
APP_AUTHOR		:=	CTurt
ICON			:=	cxi/icon48x48.png

#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH	:=	-march=armv6k -mtune=mpcore -mfloat-abi=hard

CFLAGS	:=	-g -Wall -O2 -mword-relocations \
			-fomit-frame-pointer -ffast-math \
			-fms-extensions \
			$(ARCH)

CFLAGS	+=	$(INCLUDE) -DARM11 -D_3DS

CXXFLAGS	:= $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11

ASFLAGS	:=	-g $(ARCH)
LDFLAGS	=	-specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)

LIBS	:= -lctru -lm

#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS	:= $(CTRULIB)


#---------------------------------------------------------------------------------
# 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)

ifeq ($(strip $(ICON)),)
	icons := $(wildcard *.png)
	ifneq (,$(findstring $(TARGET).png,$(icons)))
		export APP_ICON := $(TOPDIR)/$(TARGET).png
	else
		ifneq (,$(findstring icon.png,$(icons)))
			export APP_ICON := $(TOPDIR)/icon.png
		endif
	endif
else
	export APP_ICON := $(TOPDIR)/$(ICON)
endif

.PHONY: $(BUILD) clean all

#---------------------------------------------------------------------------------
all: $(BUILD)

$(BUILD):
	@[ -d $@ ] || mkdir -p $@
	@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile

#---------------------------------------------------------------------------------
clean:
	@echo clean ...
	@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).3ds $(OUTPUT).cia $(OUTPUT).smdh $(TARGET).elf $(OUTPUT)stripped.elf


#---------------------------------------------------------------------------------
else

DEPENDS	:=	$(OFILES:.o=.d)

#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(NO_SMDH)),)
.PHONY: all
all	:	$(OUTPUT).3dsx $(OUTPUT).3ds $(OUTPUT).cia $(OUTPUT).smdh
endif

$(OUTPUT).3dsx	:	$(OUTPUT).elf

$(OUTPUT).3ds	:	$(OUTPUT)stripped.elf
	makerom -f cci -o $(OUTPUT).3ds -rsf "$(TOPDIR)/cxi/gw_workaround.rsf" -target d -exefslogo -elf $(OUTPUT)stripped.elf -icon "$(TOPDIR)/cxi/icon.icn" -banner "$(TOPDIR)/cxi/banner.bnr"

$(OUTPUT).cia	:	$(OUTPUT)stripped.elf
	makerom -f cia -o $(OUTPUT).cia -elf $(OUTPUT)stripped.elf -rsf "$(TOPDIR)/cxi/build_cia.rsf" -icon "$(TOPDIR)/cxi/icon.icn" -banner "$(TOPDIR)/cxi/banner.bnr" -exefslogo -target t

$(OUTPUT).elf	:	$(OFILES)

$(OUTPUT)stripped.elf : $(OUTPUT).elf
	cp -f $(OUTPUT).elf $(OUTPUT)stripped.elf
	@arm-none-eabi-strip $(OUTPUT)stripped.elf

#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o	:	%.bin
#---------------------------------------------------------------------------------
	@echo $(notdir $<)
	@$(bin2o)

# WARNING: This is not the right way to do this! TODO: Do it right!
#---------------------------------------------------------------------------------
%.vsh.o	:	%.vsh
#---------------------------------------------------------------------------------
	@echo $(notdir $<)
	@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin
	@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@
	@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(notdir $<).shbin | tr . _)`.h
	@echo "extern const u8" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(notdir $<).shbin | tr . _)`.h
	@echo "extern const u32" `(echo $(notdir $<).shbin | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(notdir $<).shbin | tr . _)`.h
	@rm ../$(notdir $<).shbin

-include $(DEPENDS)

#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------


================================================
FILE: 3DS/cxi/build_cia.rsf
================================================
BasicInfo:
  Title                   : "3DS Controller"
  CompanyCode             : "00"
  ProductCode             : "CTR-N-3DSC"
  ContentType             : Application # Application / SystemUpdate / Manual / Child / Trial
  Logo                    : Nintendo # Nintendo / Licensed / Distributed / iQue / iQueForSystem

RomFs:
  # Specifies the root path of the file system to include in the ROM.
  # HostRoot                : "$(ROMFS_ROOT)"


TitleInfo:
  UniqueId                : 0xf0fc2 # This was/is the first real homebrew app. I hope this TID range is not used by any retail game/app.
  Category                : Application # Application / SystemApplication / Applet / Firmware / Base / DlpChild / Demo / Contents / SystemContents / SharedContents / AddOnContents / Patch / AutoUpdateContents

CardInfo:
  MediaSize               : 512MB # 128MB / 256MB / 512MB / 1GB / 2GB / 4GB / 8GB / 16GB / 32GB
  MediaType               : Card1 # Card1 / Card2
  CardDevice              : NorFlash # NorFlash / None
  

Option:
  UseOnSD                 : true # true if App is to be installed to SD
  EnableCompress          : true # Compresses exefs code
  FreeProductCode         : true # Removes limitations on ProductCode
  EnableCrypt             : false # Enables encryption for NCCH and CIA
  MediaFootPadding        : false # If true CCI files are created with padding
  
AccessControlInfo:
  # UseOtherVariationSaveData : true
  # UseExtSaveData : true
  # ExtSaveDataId: 0xffffffff
  # SystemSaveDataId1: 0x220
  # SystemSaveDataId2: 0x00040010
  # OtherUserSaveDataId1: 0x220
  # OtherUserSaveDataId2: 0x330
  # OtherUserSaveDataId3: 0x440
  # UseExtendedSaveDataAccessControl: true
  # AccessibleSaveDataIds: [0x101, 0x202, 0x303, 0x404, 0x505, 0x606]
  FileSystemAccess:
   # - CategorySystemApplication
   # - CategoryHardwareCheck
   # - CategoryFileSystemTool
   - Debug
   # - TwlCardBackup
   # - TwlNandData
   # - Boss
   - DirectSdmc
   # - Core
   # - CtrNandRo
   # - CtrNandRw
   # - CtrNandRoWrite
   # - CategorySystemSettings
   # - CardBoard
   # - ExportImportIvs
   # - DirectSdmcWrite
   # - SwitchCleanup
   # - SaveDataMove
   # - Shop
   # - Shell
   # - CategoryHomeMenu
  IoAccessControl:
   # - FsMountNand
   # - FsMountNandRoWrite
   # - FsMountTwln
   # - FsMountWnand
   # - FsMountCardSpi
   # - UseSdif3
   # - CreateSeed
   # - UseCardSpi
   
  IdealProcessor                : 0
  AffinityMask                  : 1
  
  Priority                      : 16
   
  MaxCpu                        : 0x9E # Default
  
  DisableDebug                  : true
  EnableForceDebug              : false
  CanWriteSharedPage            : true
  CanUsePrivilegedPriority      : false
  CanUseNonAlphabetAndNumber    : true
  PermitMainFunctionArgument    : true
  CanShareDeviceMemory          : true
  RunnableOnSleep               : false
  SpecialMemoryArrange          : true
  
  CoreVersion                   : 2
  DescVersion                   : 2
  
  ReleaseKernelMajor            : "02"
  ReleaseKernelMinor            : "33" 
  MemoryType                    : Application # Application / System / Base
  HandleTableSize: 512
  IORegisterMapping: 
   - 1ff50000-1ff57fff
   - 1ff70000-1ff77fff
  MemoryMapping: 
   - 1f000000-1f5fffff:r
  SystemCallAccess: 
    ArbitrateAddress: 34
    Break: 60
    CancelTimer: 28
    ClearEvent: 25
    ClearTimer: 29
    CloseHandle: 35
    ConnectToPort: 45
    ControlMemory: 1
    CreateAddressArbiter: 33
    CreateEvent: 23
    CreateMemoryBlock: 30
    CreateMutex: 19
    CreateSemaphore: 21
    CreateThread: 8
    CreateTimer: 26
    DuplicateHandle: 39
    ExitProcess: 3
    ExitThread: 9
    GetCurrentProcessorNumber: 17
    GetHandleInfo: 41
    GetProcessId: 53
    GetProcessIdOfThread: 54
    GetProcessIdealProcessor: 6
    GetProcessInfo: 43
    GetResourceLimit: 56
    GetResourceLimitCurrentValues: 58
    GetResourceLimitLimitValues: 57
    GetSystemInfo: 42
    GetSystemTick: 40
    GetThreadContext: 59
    GetThreadId: 55
    GetThreadIdealProcessor: 15
    GetThreadInfo: 44
    GetThreadPriority: 11
    MapMemoryBlock: 31
    OutputDebugString: 61
    QueryMemory: 2
    ReleaseMutex: 20
    ReleaseSemaphore: 22
    SendSyncRequest1: 46
    SendSyncRequest2: 47
    SendSyncRequest3: 48
    SendSyncRequest4: 49
    SendSyncRequest: 50
    SetThreadPriority: 12
    SetTimer: 27
    SignalEvent: 24
    SleepThread: 10
    UnmapMemoryBlock: 32
    WaitSynchronization1: 36
    WaitSynchronizationN: 37
  InterruptNumbers:
  ServiceAccessControl: 
   - APT:U
   - $hioFIO
   - $hostio0
   - $hostio1
   - ac:u
   - boss:U
   - cam:u
   - cecd:u
   - cfg:u
   - dlp:FKCL
   - dlp:SRVR
   - dsp::DSP
   - frd:u
   - fs:USER
   - gsp::Gpu
   - hid:USER
   - http:C
   - mic:u
   - ndm:u
   - news:u
   - nwm::UDS
   - ptm:u
   - pxi:dev
   - soc:U
   - ssl:C
   - y2r:u
   - ldr:ro
   - ir:USER
   - ir:u
   - ir:rst
  
   
SystemControlInfo:
  SaveDataSize: 0KB # It doesn't use any save data.
  RemasterVersion: 2
  StackSize: 0x40000
  # JumpId: 0
  Dependency: 
    ac: 0x0004013000002402L
    am: 0x0004013000001502L
    boss: 0x0004013000003402L
    camera: 0x0004013000001602L
    cecd: 0x0004013000002602L
    cfg: 0x0004013000001702L
    codec: 0x0004013000001802L
    csnd: 0x0004013000002702L
    dlp: 0x0004013000002802L
    dsp: 0x0004013000001a02L
    friends: 0x0004013000003202L
    gpio: 0x0004013000001b02L
    gsp: 0x0004013000001c02L
    hid: 0x0004013000001d02L
    http: 0x0004013000002902L
    i2c: 0x0004013000001e02L
    ir: 0x0004013000003302L
    mcu: 0x0004013000001f02L
    mic: 0x0004013000002002L
    ndm: 0x0004013000002b02L
    news: 0x0004013000003502L
    nim: 0x0004013000002c02L
    nwm: 0x0004013000002d02L
    pdn: 0x0004013000002102L
    ps: 0x0004013000003102L
    ptm: 0x0004013000002202L
    ro: 0x0004013000003702L
    socket: 0x0004013000002e02L
    spi: 0x0004013000002302L
    ssl: 0x0004013000002f02L


================================================
FILE: 3DS/cxi/gw_workaround.rsf
================================================
BasicInfo:
  Title                   : "3DS Controller"
  CompanyCode             : "00"
  ProductCode             : "CTR-N-3DSC"
  ContentType             : Application
  Logo                    : Nintendo # Nintendo / Licensed / Distributed / iQue / iQueForSystem

RomFs:
  # Specifies the root path of the file system to include in the ROM.
  #HostRoot                : "romfs"


TitleInfo:
  UniqueId                : 0xf0fc2
  Category                : Application
  
CardInfo:
  MediaSize               : 128MB # 128MB / 256MB / 512MB / 1GB / 2GB / 4GB
  MediaType               : Card1 # Card1 / Card2
  CardDevice              : NorFlash # NorFlash(Pick this if you use savedata) / None
  

Option:
  FreeProductCode         : true # Removes limitations on ProductCode
  MediaFootPadding        : false # If true CCI files are created with padding
  EnableCrypt             : true # Enables encryption for NCCH and CIA
  EnableCompress          : true # Compresses exefs code
  
AccessControlInfo:
  #UseExtSaveData : true
  #ExtSaveDataId: 0xff3ff
  #UseExtendedSaveDataAccessControl: true
  #AccessibleSaveDataIds: [0x101, 0x202, 0x303, 0x404, 0x505, 0x606]

SystemControlInfo:
  SaveDataSize: 128KB
  RemasterVersion: 0
  StackSize: 0x40000
  
# DO NOT EDIT BELOW HERE OR PROGRAMS WILL NOT LAUNCH (most likely)

AccessControlInfo:
  FileSystemAccess:
   - Debug
   - DirectSdmc
   - DirectSdmcWrite
   
  IdealProcessor                : 0
  AffinityMask                  : 1
  
  Priority                      : 16
   
  MaxCpu                        : 0x9E # Default
  
  CoreVersion                   : 2
  DescVersion                   : 2
  
  ReleaseKernelMajor            : "02"
  ReleaseKernelMinor            : "33" 
  MemoryType                    : Application
  HandleTableSize: 512
  IORegisterMapping: 
   - 1ff50000-1ff57fff
   - 1ff70000-1ff77fff
  MemoryMapping: 
   - 1f000000-1f5fffff:r
  SystemCallAccess: 
    ArbitrateAddress: 34
    Break: 60
    CancelTimer: 28
    ClearEvent: 25
    ClearTimer: 29
    CloseHandle: 35
    ConnectToPort: 45
    ControlMemory: 1
    CreateAddressArbiter: 33
    CreateEvent: 23
    CreateMemoryBlock: 30
    CreateMutex: 19
    CreateSemaphore: 21
    CreateThread: 8
    CreateTimer: 26
    DuplicateHandle: 39
    ExitProcess: 3
    ExitThread: 9
    GetCurrentProcessorNumber: 17
    GetHandleInfo: 41
    GetProcessId: 53
    GetProcessIdOfThread: 54
    GetProcessIdealProcessor: 6
    GetProcessInfo: 43
    GetResourceLimit: 56
    GetResourceLimitCurrentValues: 58
    GetResourceLimitLimitValues: 57
    GetSystemInfo: 42
    GetSystemTick: 40
    GetThreadContext: 59
    GetThreadId: 55
    GetThreadIdealProcessor: 15
    GetThreadInfo: 44
    GetThreadPriority: 11
    MapMemoryBlock: 31
    OutputDebugString: 61
    QueryMemory: 2
    ReleaseMutex: 20
    ReleaseSemaphore: 22
    SendSyncRequest1: 46
    SendSyncRequest2: 47
    SendSyncRequest3: 48
    SendSyncRequest4: 49
    SendSyncRequest: 50
    SetThreadPriority: 12
    SetTimer: 27
    SignalEvent: 24
    SleepThread: 10
    UnmapMemoryBlock: 32
    WaitSynchronization1: 36
    WaitSynchronizationN: 37
  InterruptNumbers:
  ServiceAccessControl: 
   - APT:U
   - $hioFIO
   - $hostio0
   - $hostio1
   - ac:u
   - boss:U
   - cam:u
   - cecd:u
   - cfg:u
   - dlp:FKCL
   - dlp:SRVR
   - dsp::DSP
   - frd:u
   - fs:USER
   - gsp::Gpu
   - hid:USER
   - http:C
   - mic:u
   - ndm:u
   - news:u
   - nwm::UDS
   - ptm:u
   - pxi:dev
   - soc:U
   - ssl:C
   - y2r:u
   - ldr:ro
   - ir:USER
  
   
SystemControlInfo:
  Dependency: 
    ac: 0x0004013000002402L
    am: 0x0004013000001502L
    boss: 0x0004013000003402L
    camera: 0x0004013000001602L
    cecd: 0x0004013000002602L
    cfg: 0x0004013000001702L
    codec: 0x0004013000001802L
    csnd: 0x0004013000002702L
    dlp: 0x0004013000002802L
    dsp: 0x0004013000001a02L
    friends: 0x0004013000003202L
    gpio: 0x0004013000001b02L
    gsp: 0x0004013000001c02L
    hid: 0x0004013000001d02L
    http: 0x0004013000002902L
    i2c: 0x0004013000001e02L
    ir: 0x0004013000003302L
    mcu: 0x0004013000001f02L
    mic: 0x0004013000002002L
    ndm: 0x0004013000002b02L
    news: 0x0004013000003502L
    nim: 0x0004013000002c02L
    nwm: 0x0004013000002d02L
    pdn: 0x0004013000002102L
    ps: 0x0004013000003102L
    ptm: 0x0004013000002202L
    ro: 0x0004013000003702L
    socket: 0x0004013000002e02L
    spi: 0x0004013000002302L
    ssl: 0x0004013000002f02L
CommonHeaderKey: 
  D: |
    jL2yO86eUQnYbXIrzgFVMm7FVze0LglZ2f5g+c42hWoEdnb5BOotaMQPBfqt
    aUyAEmzQPaoi/4l4V+hTJRXQfthVRqIEx27B84l8LA6Tl5Fy9PaQaQ+4yRfP
    g6ylH2l0EikrIVjy2uMlFgl0QJCrG+QGKHftxhaGCifdAwFNmiZuyJ/TmktZ
    0RCb66lYcr2h/p2G7SnpKUliS9h9KnpmG+UEgVYQUK+4SCfByUa9PxYGpT0E
    nw1UcRz0gsBmdOqcgzwnAd9vVqgb42hVn6uQZyAl+j1RKiMWywZarazIR/k5
    Lmr4+groimSEa+3ajyoIho9WaWTDmFU3mkhA2tUDIQ==
  Exponent: |
    AQAB
  Modulus: |
    zwCcsyCgMkdlieCgQMVXA6X2jmb1ICjup0Q+jk/AydPkOgsx7I/MjUymFEkU
    vgXBtCKtzh3NKXtFFuW51tJ60GPOabLKuG0Qm5li+UXALrWhzWuvd5vv2FZI
    dTQCbrq/MFS/M02xNtwqzWiBjE/LwqIdbrDAAvX4HGy0ydaQJ1DKYeQeph5D
    lAGBw2nQ4izXhhuLaU3w8VQkIJHdhxIKI5gJY/20AGkG0vHD553Mh5kBINrWp
    CRYmmJS8DCYbAiQtKbkeUfzHViGTZuj6PwaY8Mv39PGO47a++pt45IUyCEs4/
    LjMS72cyfo8tU4twRGp76SFGYejYj3wGC1f/POQw==
  Signature: |
    BOPR0jL0BOV5Zx502BuPbOvi/hvOq5ID8Dz1MQfOjkey6FKP/6cb4f9YXpm6c
    ZCHAZLo0GduKdMepiKPUq1rsbbAxkRdQdjOOusEWoxNA58x3E4373tCAhlqM2
    DvuQERrIIQ/XnYLV9C3uw4efZwhFqog1jvVyoEHpuvs8xnYtGbsKQ8FrgLwXv
    pOZYy9cSgq+jqLy2D9IxiowPcbq2cRlbW9d2xlUfpq0AohyuXQhpxn7d9RUor
    9veoARRAdxRJK12EpcSoEM1LhTRYdJnSRCY3x3p6YIV3c+l1sWvaQwKt0sZ/U
    8TTDx2gb9g7r/+U9icneu/zlqUpSkexCS009Q==
  Descriptor: |
    AP///wAABAACAAAAAAAFGJ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIAAAAAAAABBUFQ6VQAAACRo
    aW9GSU8AJGhvc3RpbzAkaG9zdGlvMWFjOnUAAAAAYm9zczpVAABjYW06dQAA
    AGNlY2Q6dQAAY2ZnOnUAAABkbHA6RktDTGRscDpTUlZSZHNwOjpEU1BmcmQ6
    dQAAAGZzOlVTRVIAZ3NwOjpHcHVoaWQ6VVNFUmh0dHA6QwAAbWljOnUAAABu
    ZG06dQAAAG5ld3M6dQAAbndtOjpVRFNwdG06dQAAAHB4aTpkZXYAc29jOlUA
    AABzc2w6QwAAAHkycjp1AAAAbGRyOnJvAABpcjpVU0VSAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAABOn/rw/7//8ec/APIA8JH/APaR/1D/gf9Y/4H/cP+B/3j/gf8B
    AQD/AAIA/iECAPz/////////////////////////////////////////////
    ////////////////////////////////////////AAAAAAAAAAAAAAAAAAAA
    AAADAAAAAAAAAAAAAAAAAAI=

================================================
FILE: 3DS/include/drawing.h
================================================
#pragma once

#ifndef REG_LCDBACKLIGHTMAIN
#define REG_LCDBACKLIGHTMAIN (u32)(0x1ED02240 - 0x1EB00000)
#endif

#ifndef REG_LCDBACKLIGHTSUB
#define REG_LCDBACKLIGHTSUB (u32)(0x1ED02A40 - 0x1EB00000)
#endif

void clearScreen(void);

#define drawPixelRGB(x, y, r, g, b) drawPixelRGBFramebuffer(0, x, y, r, g, b)
void drawPixelRGBFramebuffer(u8 *fb, int x, int y, u8 r, u8 g, u8 b);

#define drawBox(x, y, width, height, r, g, b) drawBoxFramebuffer(0, x, y, width, height, r, g, b)
void drawBoxFramebuffer(u8 *fb, int x, int y, int width, int height, u8 r, u8 g, u8 b);

#define drawString(sx, sy, text, ...) drawStringFramebuffer(0, sx, sy, text, ##__VA_ARGS__)
void drawStringFramebuffer(u8 *fb, int sx, int sy, char *text, ...);

void disableBacklight();
void enableBacklight();


================================================
FILE: 3DS/include/inet_pton.h
================================================
#pragma once

#define INADDRSZ         4

int inet_pton4(const char *src, unsigned char *dst);


================================================
FILE: 3DS/include/input.h
================================================
#pragma once

int inputIP(void);


================================================
FILE: 3DS/include/keyboard.h
================================================
#pragma once

extern const char keyboardChars[60];

extern unsigned char keyboardActive;
extern unsigned char keyboardToggle;

extern unsigned char keyboardGfx[320 * 240 * 3];

void preRenderKeyboard(void);
extern void drawKeyboard(void);


================================================
FILE: 3DS/include/settings.h
================================================
#pragma once

#include <stdbool.h>

struct settings {
	char IPString[16];
	int port;
};

extern struct settings settings;
extern struct settings defaultSettings;

extern Handle fileHandle;

bool readSettings(void);


================================================
FILE: 3DS/include/wireless.h
================================================
#pragma once

#include <string.h>

#include <3ds.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>

#include "inet_pton.h"

#define SCREENSHOT_CHUNK 4000

#define DEFAULT_PORT 8889

enum NET_COMMANDS {
	CONNECT,
	KEYS,
	SCREENSHOT,
};

// It is deliberately set up to have an anonymous struct as well as a named struct for convenience, not a mistake!
struct packet {
	union {
		struct packetHeader {
			unsigned char command;
			unsigned char keyboardActive;
		};
		struct packetHeader packetHeader;
	};
	
	union {
		// CONNECT
		union {
			struct connectPacket {
			};
			struct connectPacket connectPacket;
		};
		
		// KEYS
		union {
			struct keysPacket {
				unsigned int keys;
				
				struct {
					short x;
					short y;
				} circlePad;
				
				struct {
					unsigned short x;
					unsigned short y;
				} touch;
				
				struct {
					short x;
					short y;
				} cStick;
			};
			struct keysPacket keysPacket;
		};
		
		// SCREENSHOT
		union {
			struct screenshotPacket {
				unsigned short offset;
				unsigned char data[SCREENSHOT_CHUNK];
			};
			struct screenshotPacket screenshotPacket;
		};
	};
};

extern int sock;
extern struct sockaddr_in sain, saout;
extern struct packet outBuf, rcvBuf;

extern socklen_t sockaddr_in_sizePtr;

bool openSocket(int port);
void sendBuf(int length);
int receiveBuffer(int length);
void sendConnectionRequest(void);
void sendKeys(unsigned int keys, circlePosition circlePad, touchPosition touch, circlePosition cStick);


================================================
FILE: 3DS/source/drawing.c
================================================
#include <string.h>
#include <stdio.h>
#include <stdarg.h>

#include <3ds.h>

#include "drawing.h"

static const char fonts[] = { //Fonte 8x8 1BPP
	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 //tile:0
	, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0, 0x18, 0x0 //tile:1
	, 0x6c, 0x6c, 0x6c, 0x0, 0x0, 0x0, 0x0, 0x0 //tile:2
	, 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x0 //tile:3
	, 0x18, 0x7e, 0xc0, 0x7c, 0x6, 0xfc, 0x18, 0x0 //tile:4
	, 0x0, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x0 //tile:5
	, 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x0 //tile:6
	, 0x30, 0x30, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0 //tile:7
	, 0xc, 0x18, 0x30, 0x30, 0x30, 0x18, 0xc, 0x0 //tile:8
	, 0x30, 0x18, 0xc, 0xc, 0xc, 0x18, 0x30, 0x0 //tile:9
	, 0x0, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x0, 0x0 //tile:10
	, 0x0, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x0, 0x0 //tile:11
	, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x18, 0x30 //tile:12
	, 0x0, 0x0, 0x0, 0x7e, 0x0, 0x0, 0x0, 0x0 //tile:13
	, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x18, 0x0 //tile:14
	, 0x6, 0xc, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x0 //tile:15
	, 0x7c, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0x7c, 0x0 //tile:16
	, 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x0 //tile:17
	, 0x7c, 0xc6, 0x6, 0x7c, 0xc0, 0xc0, 0xfe, 0x0 //tile:18
	, 0xfc, 0x6, 0x6, 0x3c, 0x6, 0x6, 0xfc, 0x0 //tile:19
	, 0xc, 0xcc, 0xcc, 0xcc, 0xfe, 0xc, 0xc, 0x0 //tile:20
	, 0xfe, 0xc0, 0xfc, 0x6, 0x6, 0xc6, 0x7c, 0x0 //tile:21
	, 0x7c, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x0 //tile:22
	, 0xfe, 0x6, 0x6, 0xc, 0x18, 0x30, 0x30, 0x0 //tile:23
	, 0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x0 //tile:24
	, 0x7c, 0xc6, 0xc6, 0x7e, 0x6, 0x6, 0x7c, 0x0 //tile:25
	, 0x0, 0x18, 0x18, 0x0, 0x0, 0x18, 0x18, 0x0 //tile:26
	, 0x0, 0x18, 0x18, 0x0, 0x0, 0x18, 0x18, 0x30 //tile:27
	, 0xc, 0x18, 0x30, 0x60, 0x30, 0x18, 0xc, 0x0 //tile:28
	, 0x0, 0x0, 0x7e, 0x0, 0x7e, 0x0, 0x0, 0x0 //tile:29
	, 0x30, 0x18, 0xc, 0x6, 0xc, 0x18, 0x30, 0x0 //tile:30
	, 0x3c, 0x66, 0xc, 0x18, 0x18, 0x0, 0x18, 0x0 //tile:31
	, 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x7e, 0x0 //tile:32
	, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x0 //tile:33
	, 0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0x0 //tile:34
	, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x0 //tile:35
	, 0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x0 //tile:36
	, 0xfe, 0xc0, 0xc0, 0xf8, 0xc0, 0xc0, 0xfe, 0x0 //tile:37
	, 0xfe, 0xc0, 0xc0, 0xf8, 0xc0, 0xc0, 0xc0, 0x0 //tile:38
	, 0x7c, 0xc6, 0xc0, 0xc0, 0xce, 0xc6, 0x7c, 0x0 //tile:39
	, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x0 //tile:40
	, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x0 //tile:41
	, 0x6, 0x6, 0x6, 0x6, 0x6, 0xc6, 0x7c, 0x0 //tile:42
	, 0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0xc6, 0x0 //tile:43
	, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x0 //tile:44
	, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x0 //tile:45
	, 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x0 //tile:46
	, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x0 //tile:47
	, 0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0x0 //tile:48
	, 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x6 //tile:49
	, 0xfc, 0xc6, 0xc6, 0xfc, 0xd8, 0xcc, 0xc6, 0x0 //tile:50
	, 0x7c, 0xc6, 0xc0, 0x7c, 0x6, 0xc6, 0x7c, 0x0 //tile:51
	, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0 //tile:52
	, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x0 //tile:53
	, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x38, 0x0 //tile:54
	, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0x6c, 0x0 //tile:55
	, 0xc6, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0xc6, 0x0 //tile:56
	, 0xc6, 0xc6, 0xc6, 0x7c, 0x18, 0x30, 0xe0, 0x0 //tile:57
	, 0xfe, 0x6, 0xc, 0x18, 0x30, 0x60, 0xfe, 0x0 //tile:58
	, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x0 //tile:59
	, 0xc0, 0x60, 0x30, 0x18, 0xc, 0x6, 0x2, 0x0 //tile:60
	, 0x3c, 0xc, 0xc, 0xc, 0xc, 0xc, 0x3c, 0x0 //tile:61
	, 0x10, 0x38, 0x6c, 0xc6, 0x0, 0x0, 0x0, 0x0 //tile:62
	, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff //tile:63
	, 0x18, 0x18, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0 //tile:64
	, 0x0, 0x0, 0x7c, 0x6, 0x7e, 0xc6, 0x7e, 0x0 //tile:65
	, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xfc, 0x0 //tile:66
	, 0x0, 0x0, 0x7c, 0xc6, 0xc0, 0xc6, 0x7c, 0x0 //tile:67
	, 0x6, 0x6, 0x6, 0x7e, 0xc6, 0xc6, 0x7e, 0x0 //tile:68
	, 0x0, 0x0, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x0 //tile:69
	, 0x1c, 0x36, 0x30, 0x78, 0x30, 0x30, 0x78, 0x0 //tile:70
	, 0x0, 0x0, 0x7e, 0xc6, 0xc6, 0x7e, 0x6, 0xfc //tile:71
	, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x0 //tile:72
	, 0x18, 0x0, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x0 //tile:73
	, 0x6, 0x0, 0x6, 0x6, 0x6, 0x6, 0xc6, 0x7c //tile:74
	, 0xc0, 0xc0, 0xcc, 0xd8, 0xf8, 0xcc, 0xc6, 0x0 //tile:75
	, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x0 //tile:76
	, 0x0, 0x0, 0xcc, 0xfe, 0xfe, 0xd6, 0xd6, 0x0 //tile:77
	, 0x0, 0x0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x0 //tile:78
	, 0x0, 0x0, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x0 //tile:79
	, 0x0, 0x0, 0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0 //tile:80
	, 0x0, 0x0, 0x7e, 0xc6, 0xc6, 0x7e, 0x6, 0x6 //tile:81
	, 0x0, 0x0, 0xfc, 0xc6, 0xc0, 0xc0, 0xc0, 0x0 //tile:82
	, 0x0, 0x0, 0x7e, 0xc0, 0x7c, 0x6, 0xfc, 0x0 //tile:83
	, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0xe, 0x0 //tile:84
	, 0x0, 0x0, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x0 //tile:85
	, 0x0, 0x0, 0xc6, 0xc6, 0xc6, 0x7c, 0x38, 0x0 //tile:86
	, 0x0, 0x0, 0xc6, 0xc6, 0xd6, 0xfe, 0x6c, 0x0 //tile:87
	, 0x0, 0x0, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x0 //tile:88
	, 0x0, 0x0, 0xc6, 0xc6, 0xc6, 0x7e, 0x6, 0xfc //tile:89
	, 0x0, 0x0, 0xfe, 0xc, 0x38, 0x60, 0xfe, 0x0 //tile:90
	, 0xe, 0x18, 0x18, 0x70, 0x18, 0x18, 0xe, 0x0 //tile:91
	, 0x18, 0x18, 0x18, 0x0, 0x18, 0x18, 0x18, 0x0 //tile:92
	, 0x70, 0x18, 0x18, 0xe, 0x18, 0x18, 0x70, 0x0 //tile:93
	, 0x76, 0xdc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 //tile:94
	, 0x0, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x0 //tile:95
};

inline void clearScreen(void) {
	u8 *frame = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
	memset(frame, 0, 320 * 240 * 3);
}

void drawPixelRGBFramebuffer(u8 *fb, int x, int y, u8 r, u8 g, u8 b) {
	y = 240 - y;
	x = x;
	u32 v = (y + x * 240) * 3;
	u8 *topLeftFB = fb ? fb : gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
	topLeftFB[v] = (b >> 3) + ((g & 0x1C) << 3);
	topLeftFB[v+1] = ((g & 0xE0) >> 5) + (r & 0xF8);
}

inline void drawBoxFramebuffer(u8 *fb, int x, int y, int width, int height, u8 r, u8 g, u8 b) {
	int lx, ly;
	for(lx = x; lx < x + width; lx++) {
		for(ly = y; ly < y + height; ly++) {
			drawPixelRGBFramebuffer(fb, lx, ly, r, g, b);
		}
	}
}

void drawStringFramebuffer(u8 *fb, int sx, int sy, char *text, ...) {
	char str[1024];
	va_list args;
	va_start(args, text);
	vsnprintf(str, 1023, text, args);
	va_end(args);
	
	int i;
	for(i = 0; i < strlen(str); i++) {
		int fntnum = (str[i] - 32) & 0xFF;
		int y;
		for(y = 0; y < 8; y++) {
			int currbyte = fonts[(fntnum * 8) + y];
			//Desenha sprite de 1BPP
			int x;
			int mult = 0x80;
			for(x = 0; x < 8; x++) {
				if((currbyte & mult) == mult) {
					drawPixelRGBFramebuffer(fb, sx + x, sy + y, 0xFF, 0xFF, 0xFF);
					drawPixelRGBFramebuffer(fb, sx + x, sy + y + 1, 0, 0, 0); //Sombra
				}
				mult /= 2;
			}
		}
		sx += 8;
	}
}

static u32 brightnessMain;
static u32 brightnessSub;

void disableBacklight() {
	u32 off = 0;
	
	GSPGPU_ReadHWRegs(REG_LCDBACKLIGHTMAIN, &brightnessMain, 4);
	GSPGPU_ReadHWRegs(REG_LCDBACKLIGHTSUB, &brightnessSub, 4);
	
	GSPGPU_WriteHWRegs(REG_LCDBACKLIGHTMAIN, &off, 4);
	GSPGPU_WriteHWRegs(REG_LCDBACKLIGHTSUB, &off, 4);
}

void enableBacklight() {
	GSPGPU_WriteHWRegs(REG_LCDBACKLIGHTMAIN, &brightnessMain, 4);
	GSPGPU_WriteHWRegs(REG_LCDBACKLIGHTSUB, &brightnessSub, 4);
}


================================================
FILE: 3DS/source/inet_pton.c
================================================
#include "wireless.h"

#include "inet_pton.h"

int inet_pton4(const char *src, unsigned char *dst) {
  static const char digits[] = "0123456789";
  int saw_digit, octets, ch;
  unsigned char tmp[INADDRSZ], *tp;

  saw_digit = 0;
  octets = 0;
  tp = tmp;
  *tp = 0;
  while((ch = *src++) != '\0') {
    const char *pch;

    if((pch = strchr(digits, ch)) != NULL) {
      unsigned int val = *tp * 10 + (unsigned int)(pch - digits);

      if(saw_digit && *tp == 0)
        return (0);
      if(val > 255)
        return (0);
      *tp = (unsigned char)val;
      if(! saw_digit) {
        if(++octets > 4)
          return (0);
        saw_digit = 1;
      }
    }
    else if(ch == '.' && saw_digit) {
      if(octets == 4)
        return (0);
      *++tp = 0;
      saw_digit = 0;
    }
    else
      return (0);
  }
  if(octets < 4)
    return (0);
  memcpy(dst, tmp, INADDRSZ);
  return (1);
}


================================================
FILE: 3DS/source/input.c
================================================
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

#include <3ds.h>

#include "drawing.h"

#include "input.h"

int inputIP(void) {
	touchPosition touch;
	hidTouchRead(&touch);
	
	//Draw Keypad
	drawString(160-20,50, "1");
	drawString(160, 50, "2");
	drawString(160+20, 50, "3");
	
	drawString(160-20, 50+20, "4");
	drawString(160, 50+20, "5");
	drawString(160+20, 50+20, "6");
	
	drawString(160-20, 50+40, "7");
	drawString(160, 50+40, "8");
	drawString(160+20, 50+40, "9");
	
	drawString(160-10, 50+60, ".");
	drawString(160+10, 50+60, "0");
	
	//Bottom Strip
	if(touch.py > 50+50 && touch.py < 50+70) {
		if(touch.px < 160 && touch.px > 160-20) return 11; // Dot
		else if(touch.px < 160+20 && touch.px > 160) return 0; // Zero
	}
	
	//First Column
	else if(touch.px < 160-10 && touch.px > 160-30) {
		if(touch.py < 50+10 && touch.py > 50-10) return 1; // One
		else if(touch.py < 50+30 && touch.py > 50+10) return 4; // Four
		else if(touch.py < 50+50 && touch.py > 50+30) return 7; // Seven
	}
	
	// Second Column
	else if(touch.px < 160+10 && touch.px > 160-10) {
		if(touch.py < 50+10 && touch.py > 50-10) return 2; // Two
		else if(touch.py < 50+30 && touch.py > 50+10) return 5; // Five
		else if(touch.py < 50+50 && touch.py > 50+30) return 8; // Eight
	}
	
	// Third Column
	else if(touch.px < 160+30 && touch.px > 160+10) {
		if(touch.py < 50+10 && touch.py > 50-10) return 3; // Three
		else if(touch.py < 50+30 && touch.py > 50+10) return 6; // Six
		else if(touch.py < 50+50 && touch.py > 50+30) return 9; // Nine
	}
	
	return 10;
}

================================================
FILE: 3DS/source/keyboard.c
================================================
#include <3ds.h>
#include <math.h>
#include <string.h>

#include "drawing.h"

#include "keyboard.h"

const char keyboardChars[60] = "!1234567890\x08QWERTYUIOP\13\13ASDFGHJKL-\13\13ZXCVBNM,.?\13\13\0\0\0     \0\0\0\0";

unsigned char keyboardActive = false;
unsigned char keyboardToggle = true;

unsigned char keyboardGfx[320 * 240 * 3];

void preRenderKeyboard(void) {
	const char chars[60] = "!1234567890\x08QWERTYUIOP\13\13ASDFGHJKL-\13\13ZXCVBNM,.?\13\13\0\0\0     \0\0\0\0";
	
	int x, y;
	for(x = 0; x < 12; x++) {
		for(y = 0; y < 4; y++) {
			// Not enter
			if(chars[x + y * 12] != '\13') {
				drawBoxFramebuffer(keyboardGfx, (int)((float)x * 320.0f / 12.0f), (int)(78.0f + (float)y * 320.0f / 12.0f), 25, 25, 31, 31, 31);
				drawBoxFramebuffer(keyboardGfx, (int)((float)x * 320.0f / 12.0f) + 1, (int)(78.0f + (float)y * 320.0f / 12.0f) + 1, 24, 24, 31, 0, 0);
				
				// Backspace
				if(chars[x + y * 12] == '\x08') {
					drawStringFramebuffer(keyboardGfx, (int)((float)x * 320.0f / 12.0f) + 10, (int)(78.0f + (float)y * 320.0f / 12.0f) + 9, "-");
					drawStringFramebuffer(keyboardGfx, (int)((float)x * 320.0f / 12.0f) + 8, (int)(78.0f + (float)y * 320.0f / 12.0f) + 9, "<");
				}
				else drawStringFramebuffer(keyboardGfx, (int)((float)x * 320.0f / 12.0f) + 9, (int)(78.0f + (float)y * 320.0f / 12.0f) + 9, "%c", chars[x + y * 12]);
			}
		}
	}
	
	// Space
	drawBoxFramebuffer(keyboardGfx, (int)((float)3 * 320.0f / 12.0f), (int)(78.0f + (float)4 * 320.0f / 12.0f), (int)(5.0f * 320.0f / 12.0f), 25, 31, 31, 31);
	drawBoxFramebuffer(keyboardGfx, (int)((float)3 * 320.0f / 12.0f) + 1, (int)(78.0f + (float)4 * 320.0f / 12.0f) + 1, (int)(5.0f * 320.0f / 12.0f) - 1, 24, 31, 0, 0);
	
	// Enter
	drawBoxFramebuffer(keyboardGfx, (int)((float)10 * 320.0f / 12.0f), (int)(78.0f + (float)1 * 320.0f / 12.0f), (int)(2.0f * 320.0f / 12.0f), (int)(3.0f * 320.0f / 12.0f), 31, 31, 31);
	drawBoxFramebuffer(keyboardGfx, (int)((float)10 * 320.0f / 12.0f) + 1, (int)(78.0f + (float)1 * 320.0f / 12.0f) + 1, (int)(2.0f * 320.0f / 12.0f) - 1, (int)(3.0f * 320.0f / 12.0f) - 1, 31, 0, 0);
}

inline void drawKeyboard(void) {
	u8 *topLeftFB = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);
	memcpy(topLeftFB, keyboardGfx, sizeof(keyboardGfx));
	
	/*const char chars[60] = "!1234567890\x08QWERTYUIOP\13\13ASDFGHJKL-\13\13ZXCVBNM,.?\13\13\0\0\0     \0\0\0\0";
	
	int x, y;
	for(x = 0; x < 12; x++) {
		for(y = 0; y < 4; y++) {
			// Not enter
			if(chars[x + y * 12] != '\13') {
				drawBox((int)((float)x * 320.0f / 12.0f), (int)(78.0f + (float)y * 320.0f / 12.0f), 25, 25, 31, 31, 31);
				drawBox((int)((float)x * 320.0f / 12.0f) + 1, (int)(78.0f + (float)y * 320.0f / 12.0f) + 1, 24, 24, 31, 0, 0);
				
				// Backspace
				if(chars[x + y * 12] == '\x08') {
					drawString((int)((float)x * 320.0f / 12.0f) + 10, (int)(78.0f + (float)y * 320.0f / 12.0f) + 9, "-");
					drawString((int)((float)x * 320.0f / 12.0f) + 8, (int)(78.0f + (float)y * 320.0f / 12.0f) + 9, "<");
				}
				else drawString((int)((float)x * 320.0f / 12.0f) + 9, (int)(78.0f + (float)y * 320.0f / 12.0f) + 9, "%c", chars[x + y * 12]);
			}
		}
	}
	
	// Space
	drawBox((int)((float)3 * 320.0f / 12.0f), (int)(78.0f + (float)4 * 320.0f / 12.0f), (int)(5.0f * 320.0f / 12.0f), 25, 31, 31, 31);
	drawBox((int)((float)3 * 320.0f / 12.0f) + 1, (int)(78.0f + (float)4 * 320.0f / 12.0f) + 1, (int)(5.0f * 320.0f / 12.0f) - 1, 24, 31, 0, 0);
	
	// Enter
	drawBox((int)((float)10 * 320.0f / 12.0f), (int)(78.0f + (float)1 * 320.0f / 12.0f), (int)(2.0f * 320.0f / 12.0f), (int)(3.0f * 320.0f / 12.0f), 31, 31, 31);
	drawBox((int)((float)10 * 320.0f / 12.0f) + 1, (int)(78.0f + (float)1 * 320.0f / 12.0f) + 1, (int)(2.0f * 320.0f / 12.0f) - 1, (int)(3.0f * 320.0f / 12.0f) - 1, 31, 0, 0);
	*/
}


================================================
FILE: 3DS/source/main.c
================================================
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <setjmp.h>

#include <3ds.h>

#include "wireless.h"
#include "settings.h"
#include "drawing.h"
#include "input.h"
#include "keyboard.h"

static jmp_buf exitJmp;

void hang(char *message) {
	while(aptMainLoop()) {
		hidScanInput();
		
		clearScreen();
		drawString(10, 10, "%s", message);
		drawString(10, 20, "Press Start and Select to exit.");
		
		u32 kHeld = hidKeysHeld();
		if((kHeld & KEY_START) && (kHeld & KEY_SELECT)) longjmp(exitJmp, 1);
		
		gfxFlushBuffers();
		gspWaitForVBlank();
		gfxSwapBuffers();
	}
}

int main(void) {
	acInit();
	gfxInitDefault();
	
	gfxSetDoubleBuffering(GFX_TOP, false);
	gfxSetDoubleBuffering(GFX_BOTTOM, false);
	
	if(setjmp(exitJmp)) goto exit;
	
	preRenderKeyboard();
	
	clearScreen();
	drawString(10, 10, "Initialising FS...");
	gfxFlushBuffers();
	gfxSwapBuffers();
	
	fsInit();
	
	clearScreen();
	drawString(10, 10, "Initialising SOC...");
	gfxFlushBuffers();
	gfxSwapBuffers();
	
	socInit((u32 *)memalign(0x1000, 0x100000), 0x100000);
	
	while(aptMainLoop()) { /* Wait for WiFi; break when WiFiStatus is truthy */
		u32 wifiStatus = 0;
		ACU_GetWifiStatus(&wifiStatus);
		if(wifiStatus) break;
		
		hidScanInput();
		clearScreen();
		drawString(10, 10, "Waiting for WiFi connection...");
		drawString(10, 20, "Ensure you are in range of an access point,");
		drawString(10, 30, "and that wireless communications are enabled.");
		drawString(10, 50, "You can alternatively press Start and Select to exit.");
		
		u32 kHeld = hidKeysHeld();
		if((kHeld & KEY_START) && (kHeld & KEY_SELECT)) longjmp(exitJmp, 1);
		
		gfxFlushBuffers();
		gspWaitForVBlank();
		gfxSwapBuffers();
	}
	
	clearScreen();
	drawString(10, 10, "Reading settings...");
	gfxFlushBuffers();
	gfxSwapBuffers();
	
	if(!readSettings()) {
		hang("Could not read 3DSController.ini!");
	}
	
	clearScreen();
	drawString(10, 10, "Connecting to %s on port %d...", settings.IPString, settings.port);
	gfxFlushBuffers();
	gfxSwapBuffers();
	
	openSocket(settings.port);
	sendConnectionRequest();
	
	clearScreen();
	gfxFlushBuffers();
	gfxSwapBuffers();
	
	disableBacklight();
	
	while(aptMainLoop()) {
		hidScanInput();
		irrstScanInput();
		
		u32 kHeld = hidKeysHeld();
		circlePosition circlePad;
		circlePosition cStick;
		hidCstickRead(&cStick);
		hidCircleRead(&circlePad);
		touchPosition touch;
		touchRead(&touch);
		
		clearScreen();
		
		if((kHeld & KEY_L) && (kHeld & KEY_R) && (kHeld & KEY_X)) {
			if(keyboardToggle) {
				keyboardActive = !keyboardActive;
				keyboardToggle = false;
				
				if(keyboardActive) enableBacklight();
			}
		}
		else keyboardToggle = true;
		
		if(keyboardActive) {
			drawKeyboard();
			
			if(touch.px >= 1 && touch.px <= 312 && touch.py >= 78 && touch.py <= 208) {
				int x = (int)((float)touch.px * 12.0f / 320.0f);
				int y = (int)((float)(touch.py - 78) * 12.0f / 320.0f);
				int width = 24;
				int height = 24;
				
				if(keyboardChars[x + y * 12] == ' ') {
					while(keyboardChars[(x - 1) + y * 12] == ' ') x--;
					
					width = (int)(5.0f * 320.0f / 12.0f) - 1;
				}
				
				else if(keyboardChars[x + y * 12] == '\13') {
					while(keyboardChars[(x - 1) + y * 12] == '\13') x--;
					while(keyboardChars[x + (y - 1) * 12] == '\13') y--;
					
					width = (int)(2.0f * 320.0f / 12.0f) - 1;
					height = (int)(3.0f * 320.0f / 12.0f) - 1;
				}
				
				if(keyboardChars[x + y * 12]) drawBox((int)((float)x * 320.0f / 12.0f) + 1, (int)(78.0f + (float)y * 320.0f / 12.0f) + 1, width, height, 31, 31, 0);
			}
		}
		
		sendKeys(kHeld, circlePad, touch, cStick);
		
		//receiveBuffer(sizeof(struct packet));
		
		if((kHeld & KEY_START) && (kHeld & KEY_SELECT)) longjmp(exitJmp, 1);
		
		gfxFlushBuffers();
		gspWaitForVBlank();
		gfxSwapBuffers();
	}
	
	exit:
	
	enableBacklight();
	
	SOCU_ShutdownSockets();
	
	svcCloseHandle(fileHandle);
	fsExit();
	
	gfxExit();
	acExit();
	
	return 0;
}


================================================
FILE: 3DS/source/settings.c
================================================
#include <stdio.h>
#include <malloc.h>

#include <3ds.h>

#include "wireless.h"

#include "settings.h"

struct settings settings;

struct settings defaultSettings = {
	IPString: "",
	port: DEFAULT_PORT,
};

Handle fileHandle;

static bool getSetting(char *name, char *src, char *dest) {
	char *start = strstr(src, name);
	
	if(start) {
		start += strlen(name);
		
		char *end = start + strlen(start);
		if(strstr(start, "\n") - 1 < end) end = strstr(start, "\n") - 1;
		size_t size = (size_t)end - (size_t)start;
		
		strncpy(dest, start, size);
		dest[size] = '\0';
		
		return true;
	}
	
	return false;
}

bool readSettings(void) {
	char *buffer = NULL;
	u64 size;
	u32 bytesRead;
	
	FS_Path filePath = fsMakePath(PATH_ASCII, "/3DSController.ini");
	
	Result ret = FSUSER_OpenFileDirectly(&fileHandle, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""), filePath, FS_OPEN_READ, 0x00000000);
	if(ret) return false;
	
	ret = FSFILE_GetSize(fileHandle, &size);
	if(ret) return false;
	
	buffer = malloc(size);
	if(!buffer) return false;
	
	ret = FSFILE_Read(fileHandle, &bytesRead, 0x0, buffer, size);
	if(ret || size != bytesRead) return false;
	
	ret = FSFILE_Close(fileHandle);
	if(ret) return false;
	
	memcpy(&settings, &defaultSettings, sizeof(struct settings));
	
	char setting[64] = { '\0' };
	
	if(getSetting("IP: ", buffer, settings.IPString)) {
		//inet_pton(AF_INET, settings.IPString, &(saout.sin_addr));
		inet_pton4(settings.IPString, (unsigned char *)&(saout.sin_addr));
	}
	else {
		free(buffer);
		return false;
	}
	
	if(getSetting("Port: ", buffer, setting)) {
		sscanf(setting, "%d", &settings.port);
	}
	
	free(buffer);
	
	return true;
}


================================================
FILE: 3DS/source/wireless.c
================================================
#include <stddef.h>

#include "keyboard.h"

#include "wireless.h"

int sock;
struct sockaddr_in sain, saout;
struct packet outBuf, rcvBuf;

socklen_t sockaddr_in_sizePtr = (int)sizeof(struct sockaddr_in);

bool openSocket(int port) {
	sock = socket(AF_INET, SOCK_DGRAM, 0);
	
	saout.sin_family = sain.sin_family = AF_INET;
	saout.sin_port = sain.sin_port = htons(port);
	sain.sin_addr.s_addr = INADDR_ANY;
	
	bind(sock, (struct sockaddr *)&sain, sizeof(sain));
	
	fcntl(sock, F_SETFL, O_NONBLOCK);
	
	return true;
}

void sendBuf(int length) {
	sendto(sock, (char *)&outBuf, length, 0, (struct sockaddr *)&saout, sizeof(saout));
}

int receiveBuffer(int length) {
	return recvfrom(sock, (char *)&rcvBuf, length, 0, (struct sockaddr *)&sain, &sockaddr_in_sizePtr);
}

void sendConnectionRequest(void) {
	outBuf.command = CONNECT;
	outBuf.keyboardActive = keyboardActive;
	sendBuf(offsetof(struct packet, connectPacket) + sizeof(struct connectPacket));
}

void sendKeys(unsigned int keys, circlePosition circlePad, touchPosition touch, circlePosition cStick) {
	outBuf.command = KEYS;
	outBuf.keyboardActive = keyboardActive;
	memcpy(&outBuf.keys, &keys, 4);
	memcpy(&outBuf.circlePad, &circlePad, 4);
	memcpy(&outBuf.touch, &touch, 4);
	memcpy(&outBuf.cStick, &cStick, 4);
	sendBuf(offsetof(struct packet, keysPacket) + sizeof(struct keysPacket));
}


================================================
FILE: Linux/3DSController.py
================================================
#!/usr/bin/env python
# Compatible with both Python 2.7.6 and 3.4.3

from __future__ import print_function
import socket, struct, time
import Xlib, Xlib.display, Xlib.XK
LMouse = []; RMouse = []
Button = []; MouseAbs = []; MouseRel = []; MouseAbsClick = []; MouseRelClick = []

##########################################################
# CONFIGURABLE REGION START - Don't touch anything above #
##########################################################
port = 8889

#This tells what the touch screen does if touched.
#Valid values: Button, MouseAbs, MouseRel, MouseRelClick, MouseRelClick
#Button sends the Tap button.
#MouseAbs moves your mouse to the same part of the screen as the touch screen was touched.
#MouseRel moves your mouse by the same distance as you drag across the touch screen.
#MouseAbsClick and MouseRelClick send the primary mouse button event if the screen is tapped, not held.
touch = MouseRelClick

mouse_speed = 4
# The number of pixels on each side of the 3DS screen which are ignored, since you can't reach the outermost corners.
abs_deadzone = 10

#Valid values can be found in any of these locations on your Linux system (some may not exist):
# /usr/include/X11/keysymdef.h
# /usr/lib/python3/dist-packages/Xlib/keysymdef/
# /usr/lib/python2.7/dist-packages/Xlib/keysymdef/
#Additionally, LMouse and RMouse can also be used on any button.
btn_map = {
	"A": "A",
	"B": "B",
	"X": "X",
	"Y": "Y",
	"L": "L",
	"R": "R",
	"ZL": "Q",
	"ZR": "W",
	"Left": Xlib.XK.XK_Left,
	"Right": Xlib.XK.XK_Right,
	"Up": Xlib.XK.XK_Up,
	"Down": Xlib.XK.XK_Down,
	"Start": Xlib.XK.XK_Return,
	"Select": Xlib.XK.XK_BackSpace,
	"Tap": LMouse,
}
########################################################
# CONFIGURABLE REGION END - Don't touch anything below #
########################################################

def pprint(obj):
	import pprint
	pprint.PrettyPrinter().pprint(obj)

class x: pass

command = x()
command.CONNECT = 0
command.KEYS = 1
command.SCREENSHOT = 2

keynames = [
	"A", "B", "Select", "Start", "Right", "Left", "Up", "Down",
	"R", "L", "X", "Y", None, None, "ZL", "ZR",
	None, None, None, None, "Tap", None, None, None,
	"CSRight", "CSLeft", "CSUp", "CSDown", "CRight", "CLeft", "CUp", "CDown",
]

keys = x()
keys.A       = 1<<0
keys.B       = 1<<1
keys.Select  = 1<<2
keys.Start   = 1<<3
keys.Right   = 1<<4
keys.Left    = 1<<5
keys.Up      = 1<<6
keys.Down    = 1<<7
keys.R       = 1<<8
keys.L       = 1<<9
keys.X       = 1<<10
keys.Y       = 1<<11
keys.ZL      = 1<<14 # (new 3DS only)
keys.ZR      = 1<<15 # (new 3DS only)
keys.Tap     = 1<<20 # Not actually provided by HID
keys.CSRight = 1<<24 # c-stick (new 3DS only)
keys.CSLeft  = 1<<25 # c-stick (new 3DS only)
keys.CSUp    = 1<<26 # c-stick (new 3DS only)
keys.CSDown  = 1<<27 # c-stick (new 3DS only)
keys.CRight  = 1<<28 # circle pad
keys.CLeft   = 1<<29 # circle pad
keys.CUp     = 1<<30 # circle pad
keys.CDown   = 1<<31 # circle pad

def currentKeyboardKey(x, y):
	chars = ("!1234567890\x08"+
	         "QWERTYUIOP\13\13"+
	         "ASDFGHJKL-\13\13"+
	         "ZXCVBNM,.?\13\13"+
	         "\0\0\0     \0\0\0\0")
	
	if x>=1 and x<=312 and y>=78 and y<=208:
		xi = int(x*12/320)
		yi = int((y-78)*12/320)
		return chars[yi*12 + xi]
	else: return None

def key_to_keysym(key):
	if not key: return 0
	
	if isinstance(key,str):
		if key=="\x08": return Xlib.XK.XK_BackSpace
		if key=="\13": return Xlib.XK.XK_Return
		if key==" ": return Xlib.XK.XK_space
		return Xlib.XK.string_to_keysym(key)
	
	return key

def action_key(key, action):
	x_action = Xlib.X.ButtonRelease
	x_action2 = Xlib.X.KeyRelease
	if action:
		x_action = Xlib.X.ButtonPress
		x_action2 = Xlib.X.KeyPress
    
	if key is LMouse or key is RMouse:
		if key is LMouse: button = 1
		if key is RMouse: button = 3
		button = disp.get_pointer_mapping()[button-1] # account for left-handed mice
		disp.xtest_fake_input(x_action, button)
		disp.sync()
		return
	
	keysym = key_to_keysym(key)
	if not keysym: return
	
	keycode = disp.keysym_to_keycode(keysym)
	disp.xtest_fake_input(x_action2, keycode)
	disp.sync()
	
def press_key(key):
	action_key(key,True)
        
def release_key(key):
	action_key(key,False)

def move_mouse(x,y):
	x=int(x)
	y=int(y)
	if not x and not y: return
	
	disp.warp_pointer(x,y)
	disp.sync()

def move_mouse_abs_frac(x,y):
	root = disp.screen().root
	geom = root.get_geometry()
	
	root.warp_pointer(int(x*geom.width), int(y*geom.height))
	disp.sync()

disp = Xlib.display.Display()

touch_click = (touch is MouseAbsClick or touch is MouseRelClick)
if touch is MouseAbsClick: touch = MouseAbs
if touch is MouseRelClick: touch = MouseRel

if touch is MouseAbs and disp.screen_count()!=1:
	print("Sorry, but MouseAbs only supports a single monitor. I'll use MouseRel instead.")
	touch = MouseRel

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("", port))

prevkeys = 0

touch_start = 0
touch_last_x = 0
touch_last_y = 0
keyboard_prevkey = currentKeyboardKey(0, 0)

while True:
	rawdata, addr = sock.recvfrom(4096)
	rawdata = bytearray(rawdata)
	#print("received message", rawdata, "from", addr)
	
	if rawdata[0]==command.CONNECT:
		pass # CONNECT packets are empty
	
	if rawdata[0]==command.KEYS:
		fields = struct.unpack("<BBxxIhhHHhh", rawdata)
		
		data = {
			"command": fields[0],
			"keyboardActive": fields[1],
			"keys": fields[2],
			"circleX": fields[3],
			"circleY": fields[4],
			"touchX": fields[5],
			"touchY": fields[6],
			"cstickX": fields[7],
			"cstickY": fields[8],
		}
		#print(data)
		
		newkeys = data["keys"] & ~prevkeys
		oldkeys = ~data["keys"] & prevkeys
		prevkeys = data["keys"]
		
		for btnid in range(16):
			if newkeys & (1<<btnid):
				press_key(btn_map[keynames[btnid]])
			if oldkeys & (1<<btnid):
				release_key(btn_map[keynames[btnid]])
		if newkeys & keys.Tap:
			if data["keyboardActive"]:
				keyboard_prevkey = currentKeyboardKey(data["touchX"], data["touchY"])
				press_key(keyboard_prevkey)
			elif touch is Button:
				press_key(btn_map["Tap"])
			touch_start = time.time()
		if prevkeys & keys.Tap:
			if data["keyboardActive"] & (keyboard_prevkey != currentKeyboardKey(data["touchX"], data["touchY"])):
				release_key(keyboard_prevkey)
				keyboard_prevkey = currentKeyboardKey(data["touchX"], data["touchY"])
				press_key(keyboard_prevkey)
		if oldkeys & keys.Tap:
			if data["keyboardActive"]:
				release_key(keyboard_prevkey)
			elif touch is Button:
				release_key(btn_map["Tap"])
		if data["keys"] & keys.Tap:
			if touch is MouseAbs:
				x = (data["touchX"]-abs_deadzone) / (320.0-abs_deadzone*2)
				y = (data["touchY"]-abs_deadzone) / (240.0-abs_deadzone*2)
				move_mouse_abs_frac(x, y)
			if touch is MouseRel and not newkeys & keys.Tap:
				x = (data["touchX"]-touch_last_x) * mouse_speed
				y = (data["touchY"]-touch_last_y) * mouse_speed
				move_mouse(x, y)
			touch_last_x = data["touchX"]
			touch_last_y = data["touchY"]
		
		if oldkeys & keys.Tap and touch_click and time.time()-touch_start < 0.1:
			press_key(LMouse)
			release_key(LMouse)
		
		if abs(data["circleX"])>=16 or abs(data["circleY"])>=16:
			move_mouse(data["circleX"]*mouse_speed/32.0, -data["circleY"]*mouse_speed/32.0)
	
	if rawdata[0]==command.SCREENSHOT:
		pass # unused by both 3DS and PC applications


================================================
FILE: Linux/3DSController_gamepad.py
================================================
#!/usr/bin/env python
# Compatible with both Python 2.7.6 and 3.4.3

from __future__ import print_function
import socket, struct, time
import uinput

##########################################################
# CONFIGURABLE REGION START - Don't touch anything above #
##########################################################
port = 8889

#Valid values can be found in any of these locations on your Linux system (some may not exist):
# /usr/include/linux/input-event-codes.h
#The virtual device is defined on the device variable and the mapping of the keys on btn_map
#RECAP keynames (DO NOT TOUCH) are the keys that we expect commming from the 3ds, device is
#the virtual device that we define and btn_map maps what we recieve with our virtual device
btn_map = {
	"A": uinput.BTN_A,
	"B": uinput.BTN_B,
	"X": uinput.BTN_X,
	"Y": uinput.BTN_Y,
	"L": uinput.BTN_TL,
	"R": uinput.BTN_TR,
	"ZL": uinput.BTN_THUMBL,
	"ZR": uinput.BTN_THUMBR,
	"Left": uinput.BTN_DPAD_LEFT,
	"Right": uinput.BTN_DPAD_RIGHT,
	"Up": uinput.BTN_DPAD_UP,
	"Down": uinput.BTN_DPAD_DOWN,
	"Start": uinput.BTN_START,
	"Select": uinput.BTN_SELECT,
	"Tap": uinput.BTN_MODE,
}

device = uinput.Device([
	uinput.ABS_X + (-159, 159, 0, 10),
	uinput.ABS_Y + (-159, 159, 0, 10),
	uinput.ABS_RX + (-146, 146, 0, 16),
	uinput.ABS_RY + (-146, 146, 0, 16),
	uinput.BTN_A,
	uinput.BTN_B,
	uinput.BTN_X,
	uinput.BTN_Y,
	uinput.BTN_TL,
	uinput.BTN_TR,
	uinput.BTN_THUMBL,
	uinput.BTN_THUMBR,
	uinput.BTN_DPAD_LEFT,
	uinput.BTN_DPAD_RIGHT,
	uinput.BTN_DPAD_UP,
	uinput.BTN_DPAD_DOWN,
	uinput.BTN_START,
	uinput.BTN_SELECT,
	uinput.BTN_MODE,
	])
########################################################
# CONFIGURABLE REGION END - Don't touch anything below #
########################################################

def pprint(obj):
	import pprint
	pprint.PrettyPrinter().pprint(obj)

class x: pass

command = x()
command.CONNECT = 0
command.KEYS = 1
command.SCREENSHOT = 2

keynames = [
	"A", "B", "Select", "Start", "Right", "Left", "Up", "Down",
	"R", "L", "X", "Y", None, None, "ZL", "ZR",
	None, None, None, None, "Tap", None, None, None,
	"CSRight", "CSLeft", "CSUp", "CSDown", "CRight", "CLeft", "CUp", "CDown",
]

keys = x()
keys.A       = 1<<0
keys.B       = 1<<1
keys.Select  = 1<<2
keys.Start   = 1<<3
keys.Right   = 1<<4
keys.Left    = 1<<5
keys.Up      = 1<<6
keys.Down    = 1<<7
keys.R       = 1<<8
keys.L       = 1<<9
keys.X       = 1<<10
keys.Y       = 1<<11
keys.ZL      = 1<<14 # (new 3DS only)
keys.ZR      = 1<<15 # (new 3DS only)
keys.Tap     = 1<<20 # Not actually provided by HID
keys.CSRight = 1<<24 # c-stick (new 3DS only)
keys.CSLeft  = 1<<25 # c-stick (new 3DS only)
keys.CSUp    = 1<<26 # c-stick (new 3DS only)
keys.CSDown  = 1<<27 # c-stick (new 3DS only)
keys.CRight  = 1<<28 # circle pad
keys.CLeft   = 1<<29 # circle pad
keys.CUp     = 1<<30 # circle pad
keys.CDown   = 1<<31 # circle pad
	
def press_key(key):
	device.emit(key, 1)
        
def release_key(key):
	device.emit(key,0)

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("", port))

prevkeys = 0

touch_start = 0
touch_last_x = 0
touch_last_y = 0

while True:
	rawdata, addr = sock.recvfrom(4096)
	rawdata = bytearray(rawdata)
	#print("received message", rawdata, "from", addr)
	
	if rawdata[0]==command.CONNECT:
		pass # CONNECT packets are empty
	
	if rawdata[0]==command.KEYS:
		fields = struct.unpack("<BBxxIhhHHhh", rawdata)
		
		data = {
			"command": fields[0],
			"keyboardActive": fields[1],
			"keys": fields[2],
			"circleX": fields[3],
			"circleY": fields[4],
			"touchX": fields[5],
			"touchY": fields[6],
			"cstickX": fields[7],
			"cstickY": fields[8],
		}
		
		newkeys = data["keys"] & ~prevkeys
		oldkeys = ~data["keys"] & prevkeys
		prevkeys = data["keys"]
		
		for btnid in range(16):
			if newkeys & (1<<btnid):
				press_key(btn_map[keynames[btnid]])
			if oldkeys & (1<<btnid):
				release_key(btn_map[keynames[btnid]])
		if newkeys & keys.Tap:
			press_key(btn_map["Tap"])
		if oldkeys & keys.Tap:
			release_key(btn_map["Tap"])

		device.emit(uinput.ABS_X, data["circleX"], syn=False)
		device.emit(uinput.ABS_Y, 0-data["circleY"])
		device.emit(uinput.ABS_RX, data["cstickX"], syn=False)
		device.emit(uinput.ABS_RY, data["cstickY"])
	
	if rawdata[0]==command.SCREENSHOT:
		pass # unused by both 3DS and PC applications


================================================
FILE: PC/3DSController.ini
================================================
Default port is 8889, if you change this, you must change it in the 3DS's 3DSController.ini as well,

Circle Pad, C Stick and Touch can be MOUSE, JOYSTICK1 or JOYSTICK2
JOYSTICK1 uses X and Y. JOYSTICK2 uses Rx and Ry. These are 0, 1, 3 and 4 respectively, leaving 2 and 5 unused.

Mouse Speed controls how fast the Circle Pad or Touch Screen moves the mouse. If set to 0 and using the Touch Screen, it will set to the absolute position, rather than moving relatively to last position,

Buttons can be a letter for a keyboard key (like Q, W, E, R, T, or Y), a special keyboard key (like SPACE, CLICK, RIGHT CLICK, ENTER, BACKSPACE, SHIFT, TAB, LEFT, RIGHT, UP, DOWN, PAGE UP, PAGE DOWN, or WINDOWS), or a joypad button (JOY1, JOY2, JOY3, to JOY16).

If you want to use JOY9 through JOY16 you need to reconfigure vJoy. Search for vJoyConf in your start menu and set buttons to 16.

Alternatively, you can disable a key by binding it to NONE,

Throttle controls the delay between checking for new packets (in milliseconds), a high number will have slightly more lag between pressing a button on the 3DS and receiving it on the PC, however will make the application use less CPU. In my experience, 20 is a reasonable throttling amount,

Make sure to use a single space, not a tab for seperating settings,




Port: 8889
Throttle: 20
Circle Pad: JOYSTICK1
C Stick: JOYSTICK2
Touch: MOUSE
Mouse Speed: 0

A: A
B: B
X: X
Y: Y
L: L
R: R
ZL: Q
ZR: W
Left: LEFT
Right: RIGHT
Up: UP
Down: DOWN
Start: ENTER
Select: BACKSPACE
Tap: SPACE

================================================
FILE: PC/Makefile
================================================
CC		:=	gcc
LN		:=	gcc
ODIR	:=	build
SDIR	:=	source
IDIR	:=	include
LDIR	:=	lib
CFLAGS	:=	-I$(IDIR) -fms-extensions -O2 -Wall
LFLAGS	:=	$(LDIR)/vJoyInterface.lib -lws2_32 -lGdi32 -lgdiplus -static-libgcc
CFILES	:=	$(wildcard $(SDIR)/*.c)
OBJS	:=	$(patsubst $(SDIR)/%.c, $(ODIR)/%.o, $(wildcard $(SDIR)/*.c))

PLATFORM = $(shell uname)

ifeq ($(findstring Linux,$(PLATFORM)),Linux)
	TARGET=3DSController
endif

ifeq ($(findstring Darwin,$(PLATFORM)),Darwin)
	TARGET=3DSController
endif

ifeq ($(findstring MINGW,$(PLATFORM)),MINGW)
	TARGET=3DSController.exe
endif

$(TARGET): $(ODIR) $(OBJS)
	$(LN) $(ODIR)/*.o -o $(TARGET) $(CFLAGS) $(LFLAGS)

$(ODIR)/%.o: $(SDIR)/%.c
	$(CC) -c -o $@ $< $(CFLAGS) 

$(ODIR):
	@mkdir $@

.PHONY: clean

clean:
	rm -f $(TARGET) $(ODIR)/*.o


================================================
FILE: PC/include/general.h
================================================
#pragma once

#include <stdio.h>

void error(const char *functionName);


================================================
FILE: PC/include/joystick.h
================================================
#pragma once

#ifndef WINVER
	#define WINVER 0x0500
#endif

#include <windows.h>

#include "public.h"
#include "vjoyinterface.h"

#define joyX iReport.wAxisX
#define joyY iReport.wAxisY
#define joyRX iReport.wAxisXRot
#define joyRY iReport.wAxisYRot
#define joyButtons iReport.lButtons

#define JOY_MIDDLE (128 * 128)

extern int ContPovNumber;
extern UINT iInterface;
//extern BOOL ContinuousPOV;

extern JOYSTICK_POSITION iReport;

BOOL updateJoystick(void);


================================================
FILE: PC/include/keyboard.h
================================================
#pragma once

extern unsigned char keyboardActive;
extern unsigned char keyboardToggle;

inline char currentKeyboardKey(void);


================================================
FILE: PC/include/keys.h
================================================
#pragma once

#include <windows.h>
#include <winable.h>
#include <winuser.h>

// For some reason, these are not defined in winuser.h like they used to be...
#ifndef VK_OEM_MINUS
#define VK_OEM_MINUS 0xBD
#endif
#ifndef VK_OEM_COMMA
#define VK_OEM_COMMA 0xBC
#endif
#ifndef KEYEVENTF_SCANCODE
#define KEYEVENTF_SCANCODE 0x08
#endif

#ifndef MAPVK_VK_TO_VSC
#define MAPVK_VK_TO_VSC 0
#endif

#define newpress(key) ((currentKeys & key) && !(lastKeys & key))
#define release(key) (!(currentKeys & key) && (lastKeys & key))

#define handleKey(DSKey, PCKey) do {\
	if(!PCKey.useJoypad) {\
		if(newpress(DSKey)) simulateKeyNewpress(PCKey.virtualKey);\
		if(release(DSKey)) simulateKeyRelease(PCKey.virtualKey);\
	}\
	else if(PCKey.useJoypad == 1) {\
		if(currentKeys & DSKey) joyButtons |= PCKey.joypadButton;\
		else joyButtons &= ~PCKey.joypadButton;\
	}\
	else if(PCKey.useJoypad == 2) {\
		if(currentKeys & DSKey) joyButtons |= PCKey.joypadButton << 8;\
		else joyButtons &= ~(PCKey.joypadButton << 8);\
	}\
} while(0)

#define BIT(n) (1 << (n))

typedef enum {
	KEY_A = BIT(0),
	KEY_B = BIT(1),
	KEY_SELECT = BIT(2),
	KEY_START = BIT(3),
	KEY_DRIGHT = BIT(4),
	KEY_DLEFT = BIT(5),
	KEY_DUP = BIT(6),
	KEY_DDOWN = BIT(7),
	KEY_R = BIT(8),
	KEY_L = BIT(9),
	KEY_X = BIT(10),
	KEY_Y = BIT(11),
	KEY_ZL = BIT(14), // (new 3DS only)
	KEY_ZR = BIT(15), // (new 3DS only)
	KEY_TOUCH = BIT(20), // Not actually provided by HID
	KEY_CSTICK_RIGHT = BIT(24), // c-stick (new 3DS only)
	KEY_CSTICK_LEFT = BIT(25), // c-stick (new 3DS only)
	KEY_CSTICK_UP = BIT(26), // c-stick (new 3DS only)
	KEY_CSTICK_DOWN = BIT(27), // c-stick (new 3DS only)
	KEY_CPAD_RIGHT = BIT(28), // circle pad
	KEY_CPAD_LEFT = BIT(29), // circle pad
	KEY_CPAD_UP = BIT(30), // circle pad
	KEY_CPAD_DOWN = BIT(31), // circle pad
	
	// Generic catch-all directions
	KEY_UP = KEY_DUP | KEY_CPAD_UP,
	KEY_DOWN = KEY_DDOWN | KEY_CPAD_DOWN,
	KEY_LEFT = KEY_DLEFT | KEY_CPAD_LEFT,
	KEY_RIGHT = KEY_DRIGHT | KEY_CPAD_RIGHT,
} KEYPAD_BITS;

struct keyMapping {
	unsigned char useJoypad; // 0 keyboard key, 1 joypad1-8, 2 joypad9-16
	union {
		unsigned char virtualKey;
		unsigned char joypadButton;
	};
};

struct circlePad {
	short x;
	short y;
};

struct cStick {
	short x;
	short y;
};

struct touch {
	short x;
	short y;
};

extern unsigned int lastKeys;
extern unsigned int currentKeys;

extern struct circlePad circlePad;
extern struct cStick cStick;
extern struct touch lastTouch;
extern struct touch currentTouch;

inline unsigned int mapVirtualKey(unsigned int key);
void simulateKeyNewpress(unsigned int key);
void simulateKeyRelease(unsigned int key);


================================================
FILE: PC/include/public.h
================================================
/*++

Copyright (c) Shaul Eizikovich.  All rights reserved.

    THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
    KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
    PURPOSE.

Module Name:

    public.h
    
Abstract:

    Public header file for the vJoy project
	Developpers that need to interface with vJoy need to include this file

Author:


Environment:

    kernel mode and User mode

Notes:


Revision History:


--*/
#ifndef _PUBLIC_H
#define _PUBLIC_H

// Compilation directives
#define PPJOY_MODE
#undef PPJOY_MODE	// Comment-out for compatibility mode

#ifdef PPJOY_MODE
#include "PPJIoctl.h"
#endif

#include <INITGUID.H>	// Definitions for controlling GUID initialization

//
// Usage example:
//		CreateFile(TEXT("\\\\.\\vJoy"), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
#ifdef PPJOY_MODE
#define DEVICENAME_STRING			"PPJoyIOCTL1"
#else
#define DEVICENAME_STRING			"vJoy"
#endif
#define NTDEVICE_NAME_STRING		"\\Device\\"DEVICENAME_STRING
#define SYMBOLIC_NAME_STRING		"\\DosDevices\\"DEVICENAME_STRING
#define	DOS_FILE_NAME				"\\\\.\\"DEVICENAME_STRING
#define VJOY_INTERFACE				L"Device_"

// Version parts
#define VER_X_	0
#define VER_H_	2
#define VER_M_	0
#define VER_L_	5

#define STRINGIFY_1(x)   #x
#define STRINGIFY(x)     STRINGIFY_1(x)
#define PASTE(x, y) x##y
#define MAKEWIDE(x) PASTE(L,x)

// Device Attributes
//
#define VENDOR_N_ID		0x1234
#define	PRODUCT_N_ID	0xBEAD
#define	VERSION_N	(VER_L_ + 0x10*VER_M_ + 0x100*VER_H_ + 0x1000*VER_X_)

// Device Strings
//
#define VENDOR_STR_ID		L"Shaul Eizikovich"
#define PRODUCT_STR_ID		L"vJoy - Virtual Joystick"
#define	SERIALNUMBER_STR	MAKEWIDE(STRINGIFY(VER_H_)) L"." MAKEWIDE(STRINGIFY(VER_M_)) L"."  MAKEWIDE(STRINGIFY(VER_L_))

// Function codes;
//#define LOAD_POSITIONS	0x910
//#define GETATTRIB		0x911
// #define GET_FFB_DATA	0x00222912	// METHOD_OUT_DIRECT + FILE_DEVICE_UNKNOWN	+ FILE_ANY_ACCESS
//#define SET_FFB_STAT	0x913	 // METHOD_NEITHER
//#define GET_FFB_STAT	0x916

#define F_LOAD_POSITIONS	0x910
#define F_GETATTRIB			0x911
#define F_GET_FFB_DATA		0x912
#define F_SET_FFB_STAT		0x913
#define F_GET_FFB_STAT		0x916
#define F_GET_DEV_INFO      0x917
// IO Device Control codes;
#define IOCTL_VJOY_GET_ATTRIB		CTL_CODE (FILE_DEVICE_UNKNOWN, GETATTRIB, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define LOAD_POSITIONS	            CTL_CODE (FILE_DEVICE_UNKNOWN, F_LOAD_POSITIONS, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define GET_FFB_DATA	            CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_FFB_DATA, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define SET_FFB_STAT	            CTL_CODE (FILE_DEVICE_UNKNOWN, F_SET_FFB_STAT, METHOD_NEITHER, FILE_ANY_ACCESS)
#define GET_FFB_STAT	            CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_FFB_STAT, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define GET_DEV_INFO			    CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_DEV_INFO, METHOD_BUFFERED, FILE_ANY_ACCESS)

#ifndef __HIDPORT_H__
// Copied from hidport.h
#define IOCTL_HID_SET_FEATURE	0xB0191
#define IOCTL_HID_WRITE_REPORT	0xB000F

#define MAX_N_DEVICES	16 // Maximum number of vJoy devices


typedef struct _HID_DEVICE_ATTRIBUTES {

    ULONG           Size;
    //
    // sizeof (struct _HID_DEVICE_ATTRIBUTES)
    //

    //
    // Vendor ids of this hid device
    //
    USHORT          VendorID;
    USHORT          ProductID;
    USHORT          VersionNumber;
    USHORT          Reserved[11];

} HID_DEVICE_ATTRIBUTES, * PHID_DEVICE_ATTRIBUTES;
#endif

// Error levels for status report
enum ERRLEVEL {INFO, WARN, ERR, FATAL, APP};
// Status report function prototype
#ifdef WINAPI
typedef BOOL (WINAPI *StatusMessageFunc)(void * output, TCHAR * buffer, enum ERRLEVEL level);
#endif

///////////////////////////////////////////////////////////////

/////////////////////// Joystick Position ///////////////////////
//
// This structure holds data that is passed to the device from
// an external application such as SmartPropoPlus.
//
// Usage example:
//	JOYSTICK_POSITION iReport;
//	:
//	DeviceIoControl (hDevice, 100, &iReport, sizeof(HID_INPUT_REPORT), NULL, 0, &bytes, NULL)
typedef struct _JOYSTICK_POSITION
{
	BYTE	bDevice;	// Index of device. 1-based.
	LONG	wThrottle;
	LONG	wRudder;
	LONG	wAileron;
	LONG	wAxisX;
	LONG	wAxisY;
	LONG	wAxisZ;
	LONG	wAxisXRot;
	LONG	wAxisYRot;
	LONG	wAxisZRot;
	LONG	wSlider;
	LONG	wDial;
	LONG	wWheel;
	LONG	wAxisVX;
	LONG	wAxisVY;
	LONG	wAxisVZ;
	LONG	wAxisVBRX;
	LONG	wAxisVBRY;
	LONG	wAxisVBRZ;
	LONG	lButtons;	// 32 buttons: 0x00000001 means button1 is pressed, 0x80000000 -> button32 is pressed
	DWORD	bHats;		// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch
	DWORD	bHatsEx1;	// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch
	DWORD	bHatsEx2;	// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch
	DWORD	bHatsEx3;	// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch
} JOYSTICK_POSITION, *PJOYSTICK_POSITION;

// Superset of JOYSTICK_POSITION
// Extension of JOYSTICK_POSITION with Buttons 33-128 appended to the end of the structure.
typedef struct _JOYSTICK_POSITION_V2
{
	/// JOYSTICK_POSITION
	BYTE	bDevice;	// Index of device. 1-based.
	LONG	wThrottle;
	LONG	wRudder;
	LONG	wAileron;
	LONG	wAxisX;
	LONG	wAxisY;
	LONG	wAxisZ;
	LONG	wAxisXRot;
	LONG	wAxisYRot;
	LONG	wAxisZRot;
	LONG	wSlider;
	LONG	wDial;
	LONG	wWheel;
	LONG	wAxisVX;
	LONG	wAxisVY;
	LONG	wAxisVZ;
	LONG	wAxisVBRX;
	LONG	wAxisVBRY;
	LONG	wAxisVBRZ;
	LONG	lButtons;	// 32 buttons: 0x00000001 means button1 is pressed, 0x80000000 -> button32 is pressed
	DWORD	bHats;		// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch
	DWORD	bHatsEx1;	// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch
	DWORD	bHatsEx2;	// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch
	DWORD	bHatsEx3;	// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch LONG lButtonsEx1; // Buttons 33-64
	
	/// JOYSTICK_POSITION_V2 Extenssion
	LONG lButtonsEx1; // Buttons 33-64
	LONG lButtonsEx2; // Buttons 65-96
	LONG lButtonsEx3; // Buttons 97-128
} JOYSTICK_POSITION_V2, *PJOYSTICK_POSITION_V2;


// HID Descriptor definitions
#define HID_USAGE_X		0x30
#define HID_USAGE_Y		0x31
#define HID_USAGE_Z		0x32
#define HID_USAGE_RX	0x33
#define HID_USAGE_RY	0x34
#define HID_USAGE_RZ	0x35
#define HID_USAGE_SL0	0x36
#define HID_USAGE_SL1	0x37
#define HID_USAGE_WHL	0x38
#define HID_USAGE_POV	0x39


#endif




================================================
FILE: PC/include/settings.h
================================================
#pragma once

#include <stdbool.h>

#include "keys.h"

enum analogue {
	mouse,
	joystick1,
	joystick2,
};

struct settings {
	int port;
	int throttle;
	enum analogue circlePad;
	enum analogue cStick;
	enum analogue touch;
	int mouseSpeed;
	struct keyMapping A, B, X, Y, L, R, ZL, ZR, Left, Right, Up, Down, Start, Select, Tap;
};

extern struct settings settings;
extern struct settings defaultSettings;

bool readSettings(void);


================================================
FILE: PC/include/vjoyinterface.h
================================================
// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the VJOYINTERFACE_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// VJOYINTERFACE_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef VJOYINTERFACE_EXPORTS
#define VJOYINTERFACE_API __declspec(dllexport)
#else
#define VJOYINTERFACE_API __declspec(dllimport)
#endif

///////////////////////////// vJoy device (collection) status ////////////////////////////////////////////
#ifndef VJDSTAT
#define VJDSTAT
enum VjdStat  /* Declares an enumeration data type called BOOLEAN */
{
	VJD_STAT_OWN,	// The  vJoy Device is owned by this application.
	VJD_STAT_FREE,	// The  vJoy Device is NOT owned by any application (including this one).
	VJD_STAT_BUSY,	// The  vJoy Device is owned by another application. It cannot be acquired by this application.
	VJD_STAT_MISS,	// The  vJoy Device is missing. It either does not exist or the driver is down.
	VJD_STAT_UNKN	// Unknown
}; 

/* Error codes for some of the functions */
#define NO_HANDLE_BY_INDEX				 -1
#define BAD_PREPARSED_DATA				 -2
#define NO_CAPS				 			 -3
#define BAD_N_BTN_CAPS				 	 -4
#define BAD_CALLOC				 	 	 -5
#define BAD_BTN_CAPS				 	 -6
#define BAD_BTN_RANGE				 	 -7
#define BAD_N_VAL_CAPS				 	 -8
#define BAD_ID_RANGE				 	 -9
#define NO_SUCH_AXIS				 	 -10

/* Environment Variables */
#define INTERFACE_LOG_LEVEL "VJOYINTERFACELOGLEVEL"
#define INTERFACE_LOG_FILE  "VJOYINTERFACELOGFILE"
#define INTERFACE_DEF_LOG_FILE	"vJoyInterface.log"

struct DEV_INFO {
	BYTE	DeviceID;		// Device ID: Valid values are 1-16
	BYTE	nImplemented;	// Number of implemented device: Valid values are 1-16
	BYTE	isImplemented;	// Is this device implemented?
	BYTE	MaxDevices;		// Maximum number of devices that may be implemented (16)
	BYTE	DriverFFB;		// Does this driver support FFB (False)
	BYTE	DeviceFFB;		// Does this device support FFB (False)
} ;

typedef void (CALLBACK *RemovalCB)(BOOL, BOOL, PVOID);

#endif
///////////////////////////// vJoy device (collection) Control interface /////////////////////////////////
/*
	These functions allow writing feeders and other applications that interface with vJoy
	It is assumed that only one vJoy top-device (= Raw PDO) exists.
	This top-level device can have up to 16 siblings (=top-level Reports/collections)
	Each sibling is refered to as a "vJoy Device" and is attributed a unique Report ID (Range: 1-16).

	Naming convetion:
		VJD = vJoy Device
		rID = Report ID
*/

/////	General driver data
VJOYINTERFACE_API SHORT __cdecl GetvJoyVersion(void);
VJOYINTERFACE_API BOOL	__cdecl vJoyEnabled(void);
VJOYINTERFACE_API PVOID	__cdecl	GetvJoyProductString(void);
VJOYINTERFACE_API PVOID	__cdecl	GetvJoyManufacturerString(void);
VJOYINTERFACE_API PVOID	__cdecl	GetvJoySerialNumberString(void);
VJOYINTERFACE_API BOOL	__cdecl	DriverMatch(WORD * DllVer, WORD * DrvVer);
VJOYINTERFACE_API VOID	__cdecl	RegisterRemovalCB(RemovalCB cb, PVOID data);


/////	vJoy Device properties
VJOYINTERFACE_API int	__cdecl  GetVJDButtonNumber(UINT rID);	// Get the number of buttons defined in the specified VDJ
VJOYINTERFACE_API int	__cdecl  GetVJDDiscPovNumber(UINT rID);	// Get the number of descrete-type POV hats defined in the specified VDJ
VJOYINTERFACE_API int	__cdecl  GetVJDContPovNumber(UINT rID);	// Get the number of descrete-type POV hats defined in the specified VDJ
VJOYINTERFACE_API BOOL	__cdecl  GetVJDAxisExist(UINT rID, UINT Axis); // Test if given axis defined in the specified VDJ
VJOYINTERFACE_API BOOL	__cdecl  GetVJDAxisMax(UINT rID, UINT Axis, LONG * Max); // Get logical Maximum value for a given axis defined in the specified VDJ
VJOYINTERFACE_API BOOL	__cdecl  GetVJDAxisMin(UINT rID, UINT Axis, LONG * Min); // Get logical Minimum value for a given axis defined in the specified VDJ

/////	Write access to vJoy Device - Basic
VJOYINTERFACE_API BOOL		__cdecl	AcquireVJD(UINT rID);				// Acquire the specified vJoy Device.
VJOYINTERFACE_API VOID		__cdecl	RelinquishVJD(UINT rID);			// Relinquish the specified vJoy Device.
VJOYINTERFACE_API BOOL		__cdecl	UpdateVJD(UINT rID, PVOID pData);	// Update the position data of the specified vJoy Device.
VJOYINTERFACE_API enum VjdStat	__cdecl	GetVJDStatus(UINT rID);			// Get the status of the specified vJoy Device.

/////	Write access to vJoy Device - Modifyiers
// This group of functions modify the current value of the position data
// They replace the need to create a structure of position data then call UpdateVJD

//// Reset functions
VJOYINTERFACE_API BOOL		__cdecl	ResetVJD(UINT rID);			// Reset all controls to predefined values in the specified VDJ
VJOYINTERFACE_API VOID		__cdecl	ResetAll(void);				// Reset all controls to predefined values in all VDJ
VJOYINTERFACE_API BOOL		__cdecl	ResetButtons(UINT rID);		// Reset all buttons (To 0) in the specified VDJ
VJOYINTERFACE_API BOOL		__cdecl	ResetPovs(UINT rID);		// Reset all POV Switches (To -1) in the specified VDJ

// Write data
VJOYINTERFACE_API BOOL		__cdecl	SetAxis(LONG Value, UINT rID, UINT Axis);		// Write Value to a given axis defined in the specified VDJ 
VJOYINTERFACE_API BOOL		__cdecl	SetBtn(BOOL Value, UINT rID, UCHAR nBtn);		// Write Value to a given button defined in the specified VDJ 
VJOYINTERFACE_API BOOL		__cdecl	SetDiscPov(int Value, UINT rID, UCHAR nPov);	// Write Value to a given descrete POV defined in the specified VDJ 
VJOYINTERFACE_API BOOL		__cdecl	SetContPov(DWORD Value, UINT rID, UCHAR nPov);	// Write Value to a given continuous POV defined in the specified VDJ 


================================================
FILE: PC/include/wireless.h
================================================
#pragma once

#ifndef WINVER
	#define WINVER 0x0500
#endif

#include <windows.h>
#include <winsock.h>

#include <stddef.h>

#define SCREENSHOT_CHUNK 4000

#define IP INADDR_ANY

enum NET_COMMANDS {
	CONNECT,
	KEYS,
	SCREENSHOT,
};

// It is deliberately set up to have an anonymous struct as well as a named struct for convenience, not a mistake!
struct packet {
	struct packetHeader {
		unsigned char command;
		unsigned char keyboardActive;
	};
	struct packetHeader packetHeader;
	
	union {
		// CONNECT
		struct connectPacket {
		};
		struct connectPacket connectPacket;
		
		// KEYS
		struct keysPacket {
			unsigned int keys;
			
			struct {
				short x;
				short y;
			} circlePad;
			
			struct {
				unsigned short x;
				unsigned short y;
			} touch;
			
			struct {
				short x;
				short y;
			} cStick;
		};
		struct keysPacket keysPacket;
		
		// SCREENSHOT
		struct screenshotPacket {
			unsigned short offset;
			unsigned char data[SCREENSHOT_CHUNK];
		};
		struct screenshotPacket screenshotPacket;
	};
};

extern SOCKET listener;
extern SOCKET client;

extern struct sockaddr_in client_in;

extern int sockaddr_in_sizePtr;

extern struct packet buffer;
extern char hostName[80];

void initNetwork(void);
void printIPs(void);
void startListening(void);
void sendBuffer(int length);
int receiveBuffer(int length);

void sendScreenshot(void);


================================================
FILE: PC/source/general.c
================================================
#include "wireless.h"

#include "general.h"

void error(const char *functionName) {
	char errorMsg[92];
	ZeroMemory(errorMsg, 92);
	
	sprintf(errorMsg, "Call to %s returned error %d!", (char *)functionName, WSAGetLastError());
	
	MessageBox(NULL, errorMsg, "socketIndication", MB_OK);
	
	closesocket(client);
	closesocket(listener);
	WSACleanup();
	
	exit(0);
}


================================================
FILE: PC/source/joystick.c
================================================
#include <stdio.h>
#include <stdbool.h>

#include "joystick.h"

int ContPovNumber;
UINT iInterface = 1;
//BOOL ContinuousPOV = FALSE;

JOYSTICK_POSITION iReport;

BOOL updateJoystick(void) {
	BYTE id = (BYTE)iInterface;
	
	iReport.bDevice = id;
	
	if(!UpdateVJD(iInterface, (PVOID)&iReport)) {
		/*printf("vJoy device %d failed - try to enable device\n", iInterface);
		printf("PRESS ENTER TO CONTINUE\n");
		getchar();
		AcquireVJD(iInterface);
		ContinuousPOV = (BOOL)GetVJDContPovNumber(iInterface);*/
		return false;
	}
	
	return true;
}


================================================
FILE: PC/source/keyboard.c
================================================
#include <stdbool.h>

#include "keys.h"

#include "keyboard.h"

unsigned char keyboardActive = false;
unsigned char keyboardToggle = true;

inline char currentKeyboardKey(void) {
	const char chars[60] = "!1234567890\x08QWERTYUIOP\13\13ASDFGHJKL-\13\13ZXCVBNM,.?\13\13\0\0\0     \0\0\0\0";
	
	if(currentTouch.x >= 1 && currentTouch.x <= 312 && currentTouch.y >= 78 && currentTouch.y <= 208) {
		int x = (int)((float)currentTouch.x * 12.0f / 320.0f);
		int y = (int)((float)(currentTouch.y - 78) * 12.0f / 320.0f);
		
		return chars[x + y * 12];
	}
	
	else return 0;
}


================================================
FILE: PC/source/keys.c
================================================
#include "keys.h"

// Sideband comunication with vJoy Device
//{781EF630-72B2-11d2-B852-00C04FAD5101}
DEFINE_GUID(GUID_DEVINTERFACE_VJOY, 0x781EF630, 0x72B2, 0x11d2, 0xB8, 0x52, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x01);

unsigned int lastKeys;
unsigned int currentKeys;

struct circlePad circlePad;
struct cStick cStick;
struct touch lastTouch;
struct touch currentTouch;

inline unsigned int mapVirtualKey(unsigned int key) {
	return MapVirtualKey(key, MAPVK_VK_TO_VSC);
}

void simulateKeyNewpress(unsigned int key) {
	if(!key) return;
	
	unsigned char unshift = 0;
	
	INPUT ip = { 0 };
	
	if(key == VK_LBUTTON || key == VK_RBUTTON) {
		ip.type = INPUT_MOUSE;
		ip.mi.dwFlags = key == VK_LBUTTON ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN;
	}
	else {
		if(key == '!') {
			key = '1';
			simulateKeyNewpress(VK_SHIFT);
			unshift = 1;
		}
		else if(key == '?') {
			key = VK_DIVIDE;
			simulateKeyNewpress(VK_SHIFT);
			unshift = 1;
		}
		
		else if(key == '-') key = VK_OEM_MINUS;
		else if(key == ',') key = VK_OEM_COMMA;
		else if(key == '\13') key = VK_RETURN;
		
		ip.type = INPUT_KEYBOARD;
		ip.ki.wScan = mapVirtualKey(key);
		ip.ki.time = 0;
		ip.ki.dwExtraInfo = 0;
		ip.ki.wVk = 0;
		ip.ki.dwFlags = KEYEVENTF_SCANCODE;
	}
	
	SendInput(1, &ip, sizeof(INPUT));
	
	if(unshift) simulateKeyRelease(VK_SHIFT);
}

void simulateKeyRelease(unsigned int key) {
	if(!key) return;
	
	INPUT ip = { 0 };
	
	if(key == VK_LBUTTON || key == VK_RBUTTON) {
		ip.type = INPUT_MOUSE;
		ip.mi.dwFlags = key == VK_LBUTTON ? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP;
	}
	else {
		ip.type = INPUT_KEYBOARD;
		ip.ki.wScan = mapVirtualKey(key);
		ip.ki.time = 0;
		ip.ki.dwExtraInfo = 0;
		ip.ki.wVk = 0;
		ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
	}
	
	SendInput(1, &ip, sizeof(INPUT));
}


================================================
FILE: PC/source/main.c
================================================
// 3DS Controller Server

#define VERSION 0.6

#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

#include "wireless.h"
#include "keys.h"
#include "general.h"
#include "joystick.h"
#include "settings.h"
#include "keyboard.h"

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow) {
	printf("3DS Controller Server %.1f\n", VERSION);
	
	DWORD screenWidth = GetSystemMetrics(SM_CXSCREEN);
	DWORD screenHeight = GetSystemMetrics(SM_CYSCREEN);
	
	double widthMultiplier = screenWidth / 320.0;
	double heightMultiplier = screenHeight / 240.0;
	
	bool vJoy = true;
	UINT iInterface = 1;
	
	iReport.wAxisX = JOY_MIDDLE;
	iReport.wAxisY = JOY_MIDDLE;
	iReport.wAxisZ = JOY_MIDDLE;
	iReport.wAxisXRot = JOY_MIDDLE;
	iReport.wAxisYRot = JOY_MIDDLE;
	iReport.wAxisZRot = JOY_MIDDLE;
	iReport.wSlider = JOY_MIDDLE;
	iReport.wDial = JOY_MIDDLE;
	iReport.lButtons = 0;
	iReport.bHats = -1;
	
	if(vJoy && !vJoyEnabled()) {
		printf("vJoy failed (1)! Buttons will still work, but joy stick won't work.\n");
		vJoy = false;
	}
	
	enum VjdStat status = GetVJDStatus(iInterface);
	if(vJoy && (status == VJD_STAT_OWN || (status == VJD_STAT_FREE && !AcquireVJD(iInterface)))) {
		printf("vJoy failed (2)! Buttons will still work, but joy stick won't work.\n");
		vJoy = false;
	}
	
	ContPovNumber = GetVJDContPovNumber(iInterface);
	//int DiscPovNumber = GetVJDDiscPovNumber(iInterface);
	
	if(vJoy && !updateJoystick()) {
		printf("vJoy failed (3)! Buttons will still work, but joystick won't work.\n");
		vJoy = false;
	}
	
	if(!readSettings()) {
		printf("Couldn't read settings file, using default key bindings.\n");
	}
	
	initNetwork();
	
	char nButtons = GetVJDButtonNumber(iInterface);
	if(nButtons <16) printf("Your vJoy has less than 16 buttons (8 by default), some may not work!\n");
	
	printf("Port: %d\n", settings.port);
	
	printf("Running on: %s\n", hostName);
	
	printf("Your local IP(s):\n");
	printIPs();
	
	printf("\n");
	
	startListening();
	
	while(1) {
		memset(&buffer, 0, sizeof(struct packet));
		
		while(receiveBuffer(sizeof(struct packet)) <= 0) {
			// Waiting
			
			Sleep(settings.throttle);
		}
		
		keyboardActive = buffer.keyboardActive;
		
		switch(buffer.command) {
			case CONNECT:
				lastKeys = 0;
				currentKeys = 0;
				circlePad.x = 0;
				circlePad.y = 0;
				lastTouch.x = 0;
				lastTouch.y = 0;
				currentTouch.x = 0;
				currentTouch.y = 0;
				cStick.x = 0;
				cStick.y = 0;
				
				buffer.command = CONNECT;
				printf("3DS Connected!\n");
				
				Sleep(50);
				sendBuffer(1);
				
				Sleep(50);
				sendBuffer(1);
				
				Sleep(50);
				sendBuffer(1);
				break;
			
			case KEYS:
				lastKeys = currentKeys;
				if(currentKeys & KEY_TOUCH) lastTouch = currentTouch;
				
				memcpy(&currentKeys, &buffer.keys, 4);
				memcpy(&circlePad, &buffer.circlePad, 4);
				memcpy(&currentTouch, &buffer.touch, 4);
				memcpy(&cStick, &buffer.cStick, 4);
				
				handleKey(KEY_A, settings.A);
				handleKey(KEY_B, settings.B);
				handleKey(KEY_SELECT, settings.Select);
				handleKey(KEY_START, settings.Start);
				handleKey(KEY_DRIGHT, settings.Right);
				handleKey(KEY_DLEFT, settings.Left);
				handleKey(KEY_DUP, settings.Up);
				handleKey(KEY_DDOWN, settings.Down);
				handleKey(KEY_R, settings.R);
				handleKey(KEY_L, settings.L);
				handleKey(KEY_ZR, settings.ZR);
				handleKey(KEY_ZL, settings.ZL);
				handleKey(KEY_X, settings.X);
				handleKey(KEY_Y, settings.Y);
				
				//handleKey(KEY_LID, 'I');
				
				if(newpress(KEY_TOUCH)) {
					lastTouch.x = currentTouch.x;
					lastTouch.y = currentTouch.y;
				}
				
				if((currentKeys & KEY_TOUCH)) {
					if(keyboardActive) {
						if(newpress(KEY_TOUCH)) {
							char letter = currentKeyboardKey();
							if(letter) {
								simulateKeyNewpress(letter);
								simulateKeyRelease(letter);
							}
						}
					}
					else if(settings.touch == mouse) {
						if(settings.mouseSpeed) {
							POINT p;
							GetCursorPos(&p);
							SetCursorPos(p.x + (currentTouch.x - lastTouch.x) * settings.mouseSpeed, p.y + (currentTouch.y - lastTouch.y) * settings.mouseSpeed);
						}
						else {
							SetCursorPos((int)((double)currentTouch.x * widthMultiplier), (int)((double)currentTouch.y * heightMultiplier));
						}
					}
					else if(settings.touch == joystick1) {
						joyX = (currentTouch.x) * 128;
						joyY = (currentTouch.y) * 128;
					}
					
					else if(settings.touch == joystick2) {
						joyRX = (currentTouch.x) * 128;
						joyRY = (currentTouch.y) * 128;
					}
					else {
						handleKey(KEY_TOUCH, settings.Tap);
					}
				}
				
				if(settings.circlePad == mouse) {
					if(abs(circlePad.x) < settings.mouseSpeed * 3) circlePad.x = 0;
					if(abs(circlePad.y) < settings.mouseSpeed * 3) circlePad.y = 0;
					
					POINT p;
					GetCursorPos(&p);
					SetCursorPos(p.x + (circlePad.x * settings.mouseSpeed) / 32, p.y - (circlePad.y * settings.mouseSpeed) / 32);
				}
				else if(settings.circlePad == joystick1) {
					joyX = (circlePad.x + 128) * 128;
					joyY = (128 - circlePad.y) * 128;
				}
				
				else if(settings.circlePad == joystick2) {
					joyRX = (circlePad.x + 128) * 128;
					joyRY = (128 - circlePad.y) * 128;
				}
				
				if(settings.cStick == mouse) {
					if(abs(cStick.x) < settings.mouseSpeed * 3) cStick.x = 0;
					if(abs(cStick.y) < settings.mouseSpeed * 3) cStick.y = 0;
					
					POINT p;
					GetCursorPos(&p);
					SetCursorPos(p.x + (cStick.x * settings.mouseSpeed) / 32, p.y - (cStick.y * settings.mouseSpeed) / 32);
				}
				
				else if(settings.cStick == joystick1) {
					joyX = (cStick.x + 128) * 128;
					joyY = (128 - cStick.y) * 128;
				}
				
				else if(settings.cStick == joystick2) {
					joyRX = (cStick.x + 128) * 128;
					joyRY = (128 - cStick.y) * 128;
				}
				
				break;
		}
		
		if(vJoy) updateJoystick();
	}
	
	error("accept()");
	return 0;
}


================================================
FILE: PC/source/settings.c
================================================
#include <stdio.h>
#include <string.h>
#include <windows.h>

#include "keys.h"
#include "wireless.h"

#include "settings.h"

struct settings settings;

struct settings defaultSettings = {
	port: 8889,
	throttle: 20,
	circlePad: joystick1,
	cStick: joystick2,
	touch: mouse,
	mouseSpeed: 4,
	A: { 1, {'A'} },
	B: { 1, {'B'} },
	X: { 1, {'X'} },
	Y: { 1, {'Y'} },
	L: { 1, {'L'} },
	R: { 1, {'R'} },
	ZL: { 1, {'Q'} },
	ZR: { 1, {'W'} },
	Left: { 1, {VK_LEFT} },
	Right: { 1, {VK_RIGHT} },
	Up: { 1, {VK_UP} },
	Down: { 1, {VK_DOWN} },
	Start: { 1, {VK_RETURN} },
	Select: { 1, {VK_BACK} },
	Tap: { 1, {'T'} },
};

static bool getSetting(char *name, char *src, char *dest) {
	char *start = strstr(src, name);
	
	if(start) {
		start += strlen(name);
		
		char *end = start + strlen(start);
		if(strstr(start, "\n") - 1 < end) end = strstr(start, "\n") - 1;
		size_t size = (size_t)end - (size_t)start;
		
		strncpy(dest, start, size);
		dest[size] = '\0';
		
		return true;
	}
	
	return false;
}

static struct keyMapping getButton(char *string) {
	struct keyMapping k = { 1, {0} };
	
	k.useJoypad = 0;
	if(strcmp(string, "SPACE") == 0) k.virtualKey = VK_SPACE;
	else if(strcmp(string, "CLICK") == 0) k.virtualKey = VK_LBUTTON;
	else if(strcmp(string, "RIGHT CLICK") == 0) k.virtualKey = VK_RBUTTON;
	else if(strcmp(string, "ENTER") == 0) k.virtualKey = VK_RETURN;
	else if(strcmp(string, "BACKSPACE") == 0) k.virtualKey = VK_BACK;
	else if(strcmp(string, "SHIFT") == 0) k.virtualKey = VK_SHIFT;
	else if(strcmp(string, "TAB") == 0) k.virtualKey = VK_TAB;
	else if(strcmp(string, "LEFT") == 0) k.virtualKey = VK_LEFT;
	else if(strcmp(string, "RIGHT") == 0) k.virtualKey = VK_RIGHT;
	else if(strcmp(string, "UP") == 0) k.virtualKey = VK_UP;
	else if(strcmp(string, "DOWN") == 0) k.virtualKey = VK_DOWN;
	else if(strcmp(string, "PAGE UP") == 0) k.virtualKey = VK_PRIOR;
	else if(strcmp(string, "PAGE DOWN") == 0) k.virtualKey = VK_NEXT;
	else if(strcmp(string, "WINDOWS") == 0) k.virtualKey = VK_LWIN;
	else if(strcmp(string, "NONE") == 0) k.virtualKey = 0;
	
	else if(strcmp(string, "JOY1") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 0; }
	else if(strcmp(string, "JOY2") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 1; }
	else if(strcmp(string, "JOY3") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 2; }
	else if(strcmp(string, "JOY4") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 3; }
	else if(strcmp(string, "JOY5") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 4; }
	else if(strcmp(string, "JOY6") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 5; }
	else if(strcmp(string, "JOY7") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 6; }
	else if(strcmp(string, "JOY8") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 7; }
	else if(strcmp(string, "JOY9") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 0; }
	else if(strcmp(string, "JOY10") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 1; }
	else if(strcmp(string, "JOY11") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 2; }
	else if(strcmp(string, "JOY12") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 3; }
	else if(strcmp(string, "JOY13") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 4; }
	else if(strcmp(string, "JOY14") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 5; }
	else if(strcmp(string, "JOY15") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 6; }
	else if(strcmp(string, "JOY16") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 7; }
	
	else k.virtualKey = (int)string[0];
	
	return k;
}

bool readSettings(void) {
	FILE *f;
	size_t len = 0;
	char *buffer = NULL;
	
	memcpy(&settings, &defaultSettings, sizeof(struct settings));
	
	f = fopen("3DSController.ini", "rb");
	if(!f) {
		return false;
	}
	
	fseek(f, 0, SEEK_END);
	len = ftell(f);
	rewind(f);
	
	buffer = malloc(len);
	if(!buffer) {
		fclose(f);
		return false;
	}
	
	fread(buffer, 1, len, f);
	
	char setting[64] = { '\0' };
	
	if(getSetting("Port: ", buffer, setting)) {
		sscanf(setting, "%d", &settings.port);
	}
	
	if(getSetting("Throttle: ", buffer, setting)) {
		sscanf(setting, "%d", &settings.throttle);
	}
	
	if(getSetting("Circle Pad: ", buffer, setting)) {
		if(strcmp(setting, "MOUSE") == 0) settings.circlePad = mouse;
		else if(strcmp(setting, "JOYSTICK1") == 0) settings.circlePad = joystick1;
		else if(strcmp(setting, "JOYSTICK2") == 0) settings.circlePad = joystick2;
	}
	
	if(getSetting("C Stick: ", buffer, setting)) {
		if(strcmp(setting, "MOUSE") == 0) settings.cStick = mouse;
		else if(strcmp(setting, "JOYSTICK1") == 0) settings.cStick = joystick1;
		else if(strcmp(setting, "JOYSTICK2") == 0) settings.cStick = joystick2;
	}
	
	if(getSetting("Touch: ", buffer, setting)) {
		if(strcmp(setting, "MOUSE") == 0) settings.touch = mouse;
		else if(strcmp(setting, "JOYSTICK1") == 0) settings.touch = joystick1;
		else if(strcmp(setting, "JOYSTICK2") == 0) settings.touch = joystick2;
	}
	
	if(getSetting("Mouse Speed: ", buffer, setting)) {
		sscanf(setting, "%d", &settings.mouseSpeed);
	}
	
	if(getSetting("A: ", buffer, setting)) settings.A = getButton(setting);
	if(getSetting("B: ", buffer, setting)) settings.B = getButton(setting);
	if(getSetting("X: ", buffer, setting)) settings.X = getButton(setting);
	if(getSetting("Y: ", buffer, setting)) settings.Y = getButton(setting);
	if(getSetting("L: ", buffer, setting))	settings.L = getButton(setting);
	if(getSetting("R: ", buffer, setting)) settings.R = getButton(setting);
	if(getSetting("ZL: ", buffer, setting)) settings.ZL = getButton(setting);
	if(getSetting("ZR: ", buffer, setting)) settings.ZR = getButton(setting);
	if(getSetting("Left: ", buffer, setting)) settings.Left = getButton(setting);
	if(getSetting("Right: ", buffer, setting)) settings.Right = getButton(setting);
	if(getSetting("Up: ", buffer, setting)) settings.Up = getButton(setting);
	if(getSetting("Down: ", buffer, setting)) settings.Down = getButton(setting);
	if(getSetting("Start: ", buffer, setting)) settings.Start = getButton(setting);
	if(getSetting("Select: ", buffer, setting)) settings.Select = getButton(setting);
	if(getSetting("Tap: ", buffer, setting)) settings.Tap = getButton(setting);
	
	fclose(f);
	
	return true;
}


================================================
FILE: PC/source/wireless.c
================================================
#include <stddef.h>

#include "general.h"

#include "settings.h"

#include "wireless.h"

SOCKET listener;
SOCKET client;

struct sockaddr_in client_in;

int sockaddr_in_sizePtr = (int)sizeof(struct sockaddr_in);

struct packet buffer;
char hostName[80];

void initNetwork(void) {
	WSADATA wsaData;
	
	WSAStartup(MAKEWORD(2, 2), &wsaData);
	
	if(gethostname(hostName, sizeof(hostName)) == SOCKET_ERROR) {
		error("gethostname()");
	}
}

void printIPs(void) {
	struct hostent *phe = gethostbyname(hostName);
    if(phe == 0) {
       error("gethostbyname()");
    }
	
	int i;
    for(i = 0; phe->h_addr_list[i] != 0; i++) {
        struct in_addr addr;
        memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr));
        printf("%s\n", inet_ntoa(addr));
    }
	
	if(i) {
		printf("Usually you want the first one.\n");
	}
}

void startListening(void) {
	int nret;
	
	listener = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	
	if(listener == INVALID_SOCKET) {
		error("socket()");
	}
	
	SOCKADDR_IN serverInfo;
	
	serverInfo.sin_family = AF_INET;
	serverInfo.sin_addr.s_addr = IP;
	serverInfo.sin_port = htons(settings.port);
	
	u_long one = 1;
	ioctlsocket(listener, FIONBIO, &one);
	
	nret = bind(listener, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr));
	
	if(nret == SOCKET_ERROR) {
		error("bind()");
	}
}

void sendBuffer(int length) {
	if(sendto(listener, (char *)&buffer, length, 0, (struct sockaddr *)&client_in, sizeof(struct sockaddr_in)) != length) {
		error("sendto");
	}
}

int receiveBuffer(int length) {
	return recvfrom(listener, (char *)&buffer, length, 0, (struct sockaddr *)&client_in, &sockaddr_in_sizePtr);
}


================================================
FILE: README.md
================================================
3DSController ![](/3DS/cxi/icon48x48.png?raw=true)
===
A 3DS homebrew application which allows you to use your 3DS as a wireless controller for Windows.

### Download
The latest release will always be downloadable from [here](https://github.com/CTurt/3DSController/releases/).

If you are updating to 0.6 from an older version, you will need to make sure you update vJoy to the recommended version.

### Setup and Usage
Firstly, if you want to be able to register the circle pad or touch screen as a joystick you will need to install [vJoy (version 2.0.5-120515 is preferable)](http://sourceforge.net/projects/vjoystick/files/Beta%202.x/2.0.5-120515/vJoy_205_050515.exe/download). However, if you just want to use keyboard buttons, this is not necessary.

Extract the archive and copy the executable in the `3DS` directory with the extension that applies to your loader: `3DSController.3dsx` and `3DSController.smdh` for Ninjhax, `3DSController.3ds` for flashcards, or `3DSController.cia` for CFWs, into your 3DS's SD card or flashcard's micro SD card.

Copy the file `3DS/3DSController.ini` to the root of your 3DS's SD card, and change the line that says `IP: 192.168.0.4` to match your computer's local IP.

If you are unsure of your local IP address, run `3DSController.exe` and it will tell you.

Run `3DSController.exe` on your computer. If you are prompted, make sure to allow it through your firewall.

Start the application on your 3DS, there is no GUI, it will automatically try to connect to the IP address you put in `3DSController.ini`.

If it wasn't able to read the IP from `3DSController.ini`, it will notify you and quit.

Otherwise, you should just see a black screen, this is a good sign. To see if it works, open Notepad and press some buttons on the 3DS, they should show up. You can also test if the joystick works by going to Configure USB Game Controllers in Control Panel, it shows up as vJoy.

If using version 0.4 or above you can press L, R and X to bring up the keyboard. Press L, R and X again to close it.

If using version 0.6 or above, up to 16 joystick buttons are available. If you wish to use more than 8, you need to configure vJoy. Search in your start menu for vJoyConfig and set buttons to 16.

If using Ninjhax press Start and Select to return to the Homebrew Loader, otherwise you can just exit with the Home button.

### Setup and Usage (Linux)
-For keyboard emulation
Follow the Windows instructions, but use `3DSController.py` instead of the EXE.

-For Joystick emulation, first, install [python-uinput](https://github.com/tuomasjjrasanen/python-uinput). BEWARE: The latest release of this library as of the writing of this tutorial is 0.10.2 which is broken for most updated systems. Download the master branch directly.

Make sure that uinput module is running. You can do it from cosole like so: `#!sudo modprobe uinput`

Then, follow the Windows instructions, but use `3DSController_gamepad.py` instead of the EXE.

May work on OS X too, but this is not tested.

### Configuration
Find the line `Port: 8889` and change it to your desired port, do this for both the 3DS's `3DSController.ini` and the PC's `3DSController.ini`.

To use custom key bindings, just change the PC's `3DSController.ini` file, it should be straight forward.

### Configuration (Linux)
The configuration for the keyboard emulation is in `3DSController.py`, not the INI.

The configuration for the joystick emulation is in `3DSController_gamepad.py`, not the INI.

### Troubleshooting
- Make sure that you are using the 3DS and PC application from the same release,
- Make sure your 3DS has internet access (turn on the switch on the side of the 3DS so that an orange light shows) and is on the same network as your PC,
- Make sure that the `3DSController.ini` is in the root of your 3DS's SD card (not flashcard micro SD),
- Make sure that the `3DSController.ini` has the local IP of your computer, not your public IP,
- Make sure your firewall isn't blocking the application,
- Try using a different port (change the port for both the 3DS and PC's .ini file),
Download .txt
gitextract_emw3f_bd/

├── .gitignore
├── 3DS/
│   ├── 3DSController.ini
│   ├── Makefile
│   ├── cxi/
│   │   ├── banner.bnr
│   │   ├── build_cia.rsf
│   │   ├── gw_workaround.rsf
│   │   └── icon.icn
│   ├── include/
│   │   ├── drawing.h
│   │   ├── inet_pton.h
│   │   ├── input.h
│   │   ├── keyboard.h
│   │   ├── settings.h
│   │   └── wireless.h
│   └── source/
│       ├── drawing.c
│       ├── inet_pton.c
│       ├── input.c
│       ├── keyboard.c
│       ├── main.c
│       ├── settings.c
│       └── wireless.c
├── Linux/
│   ├── 3DSController.py
│   └── 3DSController_gamepad.py
├── PC/
│   ├── 3DSController.ini
│   ├── Makefile
│   ├── include/
│   │   ├── general.h
│   │   ├── joystick.h
│   │   ├── keyboard.h
│   │   ├── keys.h
│   │   ├── public.h
│   │   ├── settings.h
│   │   ├── vjoyinterface.h
│   │   └── wireless.h
│   ├── lib/
│   │   └── vJoyInterface.lib
│   └── source/
│       ├── general.c
│       ├── joystick.c
│       ├── keyboard.c
│       ├── keys.c
│       ├── main.c
│       ├── settings.c
│       └── wireless.c
└── README.md
Download .txt
SYMBOL INDEX (92 symbols across 23 files)

FILE: 3DS/include/settings.h
  type settings (line 5) | struct settings {
  type settings (line 10) | struct settings
  type settings (line 11) | struct settings

FILE: 3DS/include/wireless.h
  type NET_COMMANDS (line 19) | enum NET_COMMANDS {
  type packet (line 26) | struct packet {
  type sockaddr_in (line 78) | struct sockaddr_in
  type packet (line 79) | struct packet

FILE: 3DS/source/drawing.c
  function clearScreen (line 108) | inline void clearScreen(void) {
  function drawPixelRGBFramebuffer (line 113) | void drawPixelRGBFramebuffer(u8 *fb, int x, int y, u8 r, u8 g, u8 b) {
  function drawBoxFramebuffer (line 122) | inline void drawBoxFramebuffer(u8 *fb, int x, int y, int width, int heig...
  function drawStringFramebuffer (line 131) | void drawStringFramebuffer(u8 *fb, int sx, int sy, char *text, ...) {
  function disableBacklight (line 162) | void disableBacklight() {
  function enableBacklight (line 172) | void enableBacklight() {

FILE: 3DS/source/inet_pton.c
  function inet_pton4 (line 5) | int inet_pton4(const char *src, unsigned char *dst) {

FILE: 3DS/source/input.c
  function inputIP (line 11) | int inputIP(void) {

FILE: 3DS/source/keyboard.c
  function preRenderKeyboard (line 16) | void preRenderKeyboard(void) {
  function drawKeyboard (line 46) | inline void drawKeyboard(void) {

FILE: 3DS/source/main.c
  function hang (line 16) | void hang(char *message) {
  function main (line 33) | int main(void) {

FILE: 3DS/source/settings.c
  type settings (line 10) | struct settings
  type settings (line 12) | struct settings
  function getSetting (line 19) | static bool getSetting(char *name, char *src, char *dest) {
  function readSettings (line 38) | bool readSettings(void) {

FILE: 3DS/source/wireless.c
  type sockaddr_in (line 8) | struct sockaddr_in
  type packet (line 9) | struct packet
  type sockaddr_in (line 11) | struct sockaddr_in
  function openSocket (line 13) | bool openSocket(int port) {
  function sendBuf (line 27) | void sendBuf(int length) {
  function receiveBuffer (line 31) | int receiveBuffer(int length) {
  function sendConnectionRequest (line 35) | void sendConnectionRequest(void) {
  function sendKeys (line 41) | void sendKeys(unsigned int keys, circlePosition circlePad, touchPosition...

FILE: Linux/3DSController.py
  function pprint (line 53) | def pprint(obj):
  class x (line 57) | class x: pass
  function currentKeyboardKey (line 96) | def currentKeyboardKey(x, y):
  function key_to_keysym (line 109) | def key_to_keysym(key):
  function action_key (line 120) | def action_key(key, action):
  function press_key (line 142) | def press_key(key):
  function release_key (line 145) | def release_key(key):
  function move_mouse (line 148) | def move_mouse(x,y):
  function move_mouse_abs_frac (line 156) | def move_mouse_abs_frac(x,y):

FILE: Linux/3DSController_gamepad.py
  function pprint (line 61) | def pprint(obj):
  class x (line 65) | class x: pass
  function press_key (line 104) | def press_key(key):
  function release_key (line 107) | def release_key(key):

FILE: PC/include/keys.h
  type KEYPAD_BITS (line 42) | typedef enum {
  type keyMapping (line 74) | struct keyMapping {
  type circlePad (line 82) | struct circlePad {
  type cStick (line 87) | struct cStick {
  type touch (line 92) | struct touch {
  type circlePad (line 100) | struct circlePad
  type cStick (line 101) | struct cStick
  type touch (line 102) | struct touch
  type touch (line 103) | struct touch

FILE: PC/include/public.h
  type HID_DEVICE_ATTRIBUTES (line 111) | typedef struct _HID_DEVICE_ATTRIBUTES {
  type ERRLEVEL (line 130) | enum ERRLEVEL {INFO, WARN, ERR, FATAL, APP}
  type level (line 133) | typedef BOOL (WINAPI *StatusMessageFunc)(void * output, TCHAR * buffer, ...
  type JOYSTICK_POSITION (line 147) | typedef struct _JOYSTICK_POSITION
  type JOYSTICK_POSITION_V2 (line 177) | typedef struct _JOYSTICK_POSITION_V2

FILE: PC/include/settings.h
  type analogue (line 7) | enum analogue {
  type settings (line 13) | struct settings {
  type settings (line 23) | struct settings
  type settings (line 24) | struct settings

FILE: PC/include/vjoyinterface.h
  type VjdStat (line 16) | enum VjdStat  /* Declares an enumeration data type called BOOLEAN */
  type DEV_INFO (line 42) | struct DEV_INFO {

FILE: PC/include/wireless.h
  type NET_COMMANDS (line 16) | enum NET_COMMANDS {
  type packet (line 23) | struct packet {
  type sockaddr_in (line 69) | struct sockaddr_in
  type packet (line 73) | struct packet

FILE: PC/source/general.c
  function error (line 5) | void error(const char *functionName) {

FILE: PC/source/joystick.c
  function BOOL (line 12) | BOOL updateJoystick(void) {

FILE: PC/source/keyboard.c
  function currentKeyboardKey (line 10) | inline char currentKeyboardKey(void) {

FILE: PC/source/keys.c
  type circlePad (line 10) | struct circlePad
  type cStick (line 11) | struct cStick
  type touch (line 12) | struct touch
  type touch (line 13) | struct touch
  function mapVirtualKey (line 15) | inline unsigned int mapVirtualKey(unsigned int key) {
  function simulateKeyNewpress (line 19) | void simulateKeyNewpress(unsigned int key) {
  function simulateKeyRelease (line 59) | void simulateKeyRelease(unsigned int key) {

FILE: PC/source/main.c
  function WinMain (line 16) | int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, in...

FILE: PC/source/settings.c
  type settings (line 10) | struct settings
  type settings (line 12) | struct settings
  function getSetting (line 36) | static bool getSetting(char *name, char *src, char *dest) {
  function getButton (line 55) | static struct keyMapping getButton(char *string) {
  function readSettings (line 97) | bool readSettings(void) {

FILE: PC/source/wireless.c
  type sockaddr_in (line 12) | struct sockaddr_in
  type sockaddr_in (line 14) | struct sockaddr_in
  type packet (line 16) | struct packet
  function initNetwork (line 19) | void initNetwork(void) {
  function printIPs (line 29) | void printIPs(void) {
  function startListening (line 47) | void startListening(void) {
  function sendBuffer (line 72) | void sendBuffer(int length) {
  function receiveBuffer (line 78) | int receiveBuffer(int length) {
Condensed preview — 41 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (105K chars).
[
  {
    "path": ".gitignore",
    "chars": 99,
    "preview": "3DS/build/\n3DS/*.elf\n3DS/*stripped.elf\n3DS/*.3dsx\n3DS/*.smdh\n3DS/*.3ds\n3DS/*.cia\nPC/build/\nPC/*.exe"
  },
  {
    "path": "3DS/3DSController.ini",
    "chars": 103,
    "preview": "Change the IP to be your PC's local IP, (run 3DSController.exe to find it),\n\nIP: 192.168.0.4\nPort: 8889"
  },
  {
    "path": "3DS/Makefile",
    "chars": 7486,
    "preview": "#---------------------------------------------------------------------------------\n.SUFFIXES:\n#-------------------------"
  },
  {
    "path": "3DS/cxi/build_cia.rsf",
    "chars": 5953,
    "preview": "BasicInfo:\n  Title                   : \"3DS Controller\"\n  CompanyCode             : \"00\"\n  ProductCode             : \"CT"
  },
  {
    "path": "3DS/cxi/gw_workaround.rsf",
    "chars": 6420,
    "preview": "BasicInfo:\n  Title                   : \"3DS Controller\"\n  CompanyCode             : \"00\"\n  ProductCode             : \"CT"
  },
  {
    "path": "3DS/include/drawing.h",
    "chars": 778,
    "preview": "#pragma once\n\n#ifndef REG_LCDBACKLIGHTMAIN\n#define REG_LCDBACKLIGHTMAIN (u32)(0x1ED02240 - 0x1EB00000)\n#endif\n\n#ifndef R"
  },
  {
    "path": "3DS/include/inet_pton.h",
    "chars": 95,
    "preview": "#pragma once\n\n#define INADDRSZ         4\n\nint inet_pton4(const char *src, unsigned char *dst);\n"
  },
  {
    "path": "3DS/include/input.h",
    "chars": 33,
    "preview": "#pragma once\n\nint inputIP(void);\n"
  },
  {
    "path": "3DS/include/keyboard.h",
    "chars": 239,
    "preview": "#pragma once\n\nextern const char keyboardChars[60];\n\nextern unsigned char keyboardActive;\nextern unsigned char keyboardTo"
  },
  {
    "path": "3DS/include/settings.h",
    "chars": 215,
    "preview": "#pragma once\n\n#include <stdbool.h>\n\nstruct settings {\n\tchar IPString[16];\n\tint port;\n};\n\nextern struct settings settings"
  },
  {
    "path": "3DS/include/wireless.h",
    "chars": 1536,
    "preview": "#pragma once\n\n#include <string.h>\n\n#include <3ds.h>\n\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <netdb.h>\n"
  },
  {
    "path": "3DS/source/drawing.c",
    "chars": 7442,
    "preview": "#include <string.h>\n#include <stdio.h>\n#include <stdarg.h>\n\n#include <3ds.h>\n\n#include \"drawing.h\"\n\nstatic const char fo"
  },
  {
    "path": "3DS/source/inet_pton.c",
    "chars": 899,
    "preview": "#include \"wireless.h\"\n\n#include \"inet_pton.h\"\n\nint inet_pton4(const char *src, unsigned char *dst) {\n  static const char"
  },
  {
    "path": "3DS/source/input.c",
    "chars": 1556,
    "preview": "#include <stdlib.h>\n#include <string.h>\n#include <malloc.h>\n\n#include <3ds.h>\n\n#include \"drawing.h\"\n\n#include \"input.h\"\n"
  },
  {
    "path": "3DS/source/keyboard.c",
    "chars": 3763,
    "preview": "#include <3ds.h>\n#include <math.h>\n#include <string.h>\n\n#include \"drawing.h\"\n\n#include \"keyboard.h\"\n\nconst char keyboard"
  },
  {
    "path": "3DS/source/main.c",
    "chars": 3925,
    "preview": "#include <stdlib.h>\n#include <string.h>\n#include <malloc.h>\n#include <setjmp.h>\n\n#include <3ds.h>\n\n#include \"wireless.h\""
  },
  {
    "path": "3DS/source/settings.c",
    "chars": 1648,
    "preview": "#include <stdio.h>\n#include <malloc.h>\n\n#include <3ds.h>\n\n#include \"wireless.h\"\n\n#include \"settings.h\"\n\nstruct settings "
  },
  {
    "path": "3DS/source/wireless.c",
    "chars": 1349,
    "preview": "#include <stddef.h>\n\n#include \"keyboard.h\"\n\n#include \"wireless.h\"\n\nint sock;\nstruct sockaddr_in sain, saout;\nstruct pack"
  },
  {
    "path": "Linux/3DSController.py",
    "chars": 7253,
    "preview": "#!/usr/bin/env python\n# Compatible with both Python 2.7.6 and 3.4.3\n\nfrom __future__ import print_function\nimport socket"
  },
  {
    "path": "Linux/3DSController_gamepad.py",
    "chars": 4321,
    "preview": "#!/usr/bin/env python\n# Compatible with both Python 2.7.6 and 3.4.3\n\nfrom __future__ import print_function\nimport socket"
  },
  {
    "path": "PC/3DSController.ini",
    "chars": 1525,
    "preview": "Default port is 8889, if you change this, you must change it in the 3DS's 3DSController.ini as well,\n\nCircle Pad, C Stic"
  },
  {
    "path": "PC/Makefile",
    "chars": 771,
    "preview": "CC\t\t:=\tgcc\nLN\t\t:=\tgcc\nODIR\t:=\tbuild\nSDIR\t:=\tsource\nIDIR\t:=\tinclude\nLDIR\t:=\tlib\nCFLAGS\t:=\t-I$(IDIR) -fms-extensions -O2 -"
  },
  {
    "path": "PC/include/general.h",
    "chars": 72,
    "preview": "#pragma once\n\n#include <stdio.h>\n\nvoid error(const char *functionName);\n"
  },
  {
    "path": "PC/include/joystick.h",
    "chars": 461,
    "preview": "#pragma once\n\n#ifndef WINVER\n\t#define WINVER 0x0500\n#endif\n\n#include <windows.h>\n\n#include \"public.h\"\n#include \"vjoyinte"
  },
  {
    "path": "PC/include/keyboard.h",
    "chars": 127,
    "preview": "#pragma once\n\nextern unsigned char keyboardActive;\nextern unsigned char keyboardToggle;\n\ninline char currentKeyboardKey("
  },
  {
    "path": "PC/include/keys.h",
    "chars": 2617,
    "preview": "#pragma once\n\n#include <windows.h>\n#include <winable.h>\n#include <winuser.h>\n\n// For some reason, these are not defined "
  },
  {
    "path": "PC/include/public.h",
    "chars": 6448,
    "preview": "/*++\n\nCopyright (c) Shaul Eizikovich.  All rights reserved.\n\n    THIS CODE AND INFORMATION IS PROVIDED \"AS IS\" WITHOUT W"
  },
  {
    "path": "PC/include/settings.h",
    "chars": 430,
    "preview": "#pragma once\n\n#include <stdbool.h>\n\n#include \"keys.h\"\n\nenum analogue {\n\tmouse,\n\tjoystick1,\n\tjoystick2,\n};\n\nstruct settin"
  },
  {
    "path": "PC/include/vjoyinterface.h",
    "chars": 5793,
    "preview": "// The following ifdef block is the standard way of creating macros which make exporting \n// from a DLL simpler. All fil"
  },
  {
    "path": "PC/include/wireless.h",
    "chars": 1358,
    "preview": "#pragma once\n\n#ifndef WINVER\n\t#define WINVER 0x0500\n#endif\n\n#include <windows.h>\n#include <winsock.h>\n\n#include <stddef."
  },
  {
    "path": "PC/source/general.c",
    "chars": 362,
    "preview": "#include \"wireless.h\"\n\n#include \"general.h\"\n\nvoid error(const char *functionName) {\n\tchar errorMsg[92];\n\tZeroMemory(erro"
  },
  {
    "path": "PC/source/joystick.c",
    "chars": 542,
    "preview": "#include <stdio.h>\n#include <stdbool.h>\n\n#include \"joystick.h\"\n\nint ContPovNumber;\nUINT iInterface = 1;\n//BOOL Continuou"
  },
  {
    "path": "PC/source/keyboard.c",
    "chars": 567,
    "preview": "#include <stdbool.h>\n\n#include \"keys.h\"\n\n#include \"keyboard.h\"\n\nunsigned char keyboardActive = false;\nunsigned char keyb"
  },
  {
    "path": "PC/source/keys.c",
    "chars": 1787,
    "preview": "#include \"keys.h\"\n\n// Sideband comunication with vJoy Device\n//{781EF630-72B2-11d2-B852-00C04FAD5101}\nDEFINE_GUID(GUID_D"
  },
  {
    "path": "PC/source/main.c",
    "chars": 5872,
    "preview": "// 3DS Controller Server\n\n#define VERSION 0.6\n\n#include <stdio.h>\n#include <stdbool.h>\n#include <stdlib.h>\n\n#include \"wi"
  },
  {
    "path": "PC/source/settings.c",
    "chars": 6123,
    "preview": "#include <stdio.h>\n#include <string.h>\n#include <windows.h>\n\n#include \"keys.h\"\n#include \"wireless.h\"\n\n#include \"settings"
  },
  {
    "path": "PC/source/wireless.c",
    "chars": 1635,
    "preview": "#include <stddef.h>\n\n#include \"general.h\"\n\n#include \"settings.h\"\n\n#include \"wireless.h\"\n\nSOCKET listener;\nSOCKET client;"
  },
  {
    "path": "README.md",
    "chars": 4083,
    "preview": "3DSController ![](/3DS/cxi/icon48x48.png?raw=true)\n===\nA 3DS homebrew application which allows you to use your 3DS as a "
  }
]

// ... and 3 more files (download for full content)

About this extraction

This page contains the full source code of the CTurt/3DSController GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 41 files (93.4 KB), approximately 34.2k tokens, and a symbol index with 92 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!