[
  {
    "path": ".gitignore",
    "content": "3DS/build/\n3DS/*.elf\n3DS/*stripped.elf\n3DS/*.3dsx\n3DS/*.smdh\n3DS/*.3ds\n3DS/*.cia\nPC/build/\nPC/*.exe"
  },
  {
    "path": "3DS/3DSController.ini",
    "content": "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",
    "content": "#---------------------------------------------------------------------------------\n.SUFFIXES:\n#---------------------------------------------------------------------------------\n\nifeq ($(strip $(DEVKITARM)),)\n$(error \"Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM\")\nendif\n\nTOPDIR ?= $(CURDIR)\ninclude $(DEVKITARM)/3ds_rules\n\n#---------------------------------------------------------------------------------\n# TARGET is the name of the output\n# BUILD is the directory where object files & intermediate files will be placed\n# SOURCES is a list of directories containing source code\n# DATA is a list of directories containing data files\n# INCLUDES is a list of directories containing header files\n#\n# NO_SMDH: if set to anything, no SMDH file is generated.\n# APP_TITLE is the name of the app stored in the SMDH file (Optional)\n# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional)\n# APP_AUTHOR is the author of the app stored in the SMDH file (Optional)\n# ICON is the filename of the icon (.png), relative to the project folder.\n#   If not set, it attempts to use one of the following (in this order):\n#     - <Project name>.png\n#     - icon.png\n#     - <libctru folder>/default_icon.png\n#---------------------------------------------------------------------------------\nTARGET\t\t:=\t3DSController\nBUILD\t\t:=\tbuild\nSOURCES\t\t:=\tsource\nDATA\t\t:=\tdata\nINCLUDES\t:=\tinclude\n\nAPP_TITLE\t\t:=\t3DS Controller\nAPP_DESCRIPTION\t:=\nAPP_AUTHOR\t\t:=\tCTurt\nICON\t\t\t:=\tcxi/icon48x48.png\n\n#---------------------------------------------------------------------------------\n# options for code generation\n#---------------------------------------------------------------------------------\nARCH\t:=\t-march=armv6k -mtune=mpcore -mfloat-abi=hard\n\nCFLAGS\t:=\t-g -Wall -O2 -mword-relocations \\\n\t\t\t-fomit-frame-pointer -ffast-math \\\n\t\t\t-fms-extensions \\\n\t\t\t$(ARCH)\n\nCFLAGS\t+=\t$(INCLUDE) -DARM11 -D_3DS\n\nCXXFLAGS\t:= $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11\n\nASFLAGS\t:=\t-g $(ARCH)\nLDFLAGS\t=\t-specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)\n\nLIBS\t:= -lctru -lm\n\n#---------------------------------------------------------------------------------\n# list of directories containing libraries, this must be the top level containing\n# include and lib\n#---------------------------------------------------------------------------------\nLIBDIRS\t:= $(CTRULIB)\n\n\n#---------------------------------------------------------------------------------\n# no real need to edit anything past this point unless you need to add additional\n# rules for different file extensions\n#---------------------------------------------------------------------------------\nifneq ($(BUILD),$(notdir $(CURDIR)))\n#---------------------------------------------------------------------------------\n\nexport OUTPUT\t:=\t$(CURDIR)/$(TARGET)\nexport TOPDIR\t:=\t$(CURDIR)\n\nexport VPATH\t:=\t$(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \\\n\t\t\t$(foreach dir,$(DATA),$(CURDIR)/$(dir))\n\nexport DEPSDIR\t:=\t$(CURDIR)/$(BUILD)\n\nCFILES\t\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))\nCPPFILES\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))\nSFILES\t\t:=\t$(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))\nBINFILES\t:=\t$(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))\n\n#---------------------------------------------------------------------------------\n# use CXX for linking C++ projects, CC for standard C\n#---------------------------------------------------------------------------------\nifeq ($(strip $(CPPFILES)),)\n#---------------------------------------------------------------------------------\n\texport LD\t:=\t$(CC)\n#---------------------------------------------------------------------------------\nelse\n#---------------------------------------------------------------------------------\n\texport LD\t:=\t$(CXX)\n#---------------------------------------------------------------------------------\nendif\n#---------------------------------------------------------------------------------\n\nexport OFILES\t:=\t$(addsuffix .o,$(BINFILES)) \\\n\t\t\t$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)\n\nexport INCLUDE\t:=\t$(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \\\n\t\t\t$(foreach dir,$(LIBDIRS),-I$(dir)/include) \\\n\t\t\t-I$(CURDIR)/$(BUILD)\n\nexport LIBPATHS\t:=\t$(foreach dir,$(LIBDIRS),-L$(dir)/lib)\n\nifeq ($(strip $(ICON)),)\n\ticons := $(wildcard *.png)\n\tifneq (,$(findstring $(TARGET).png,$(icons)))\n\t\texport APP_ICON := $(TOPDIR)/$(TARGET).png\n\telse\n\t\tifneq (,$(findstring icon.png,$(icons)))\n\t\t\texport APP_ICON := $(TOPDIR)/icon.png\n\t\tendif\n\tendif\nelse\n\texport APP_ICON := $(TOPDIR)/$(ICON)\nendif\n\n.PHONY: $(BUILD) clean all\n\n#---------------------------------------------------------------------------------\nall: $(BUILD)\n\n$(BUILD):\n\t@[ -d $@ ] || mkdir -p $@\n\t@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile\n\n#---------------------------------------------------------------------------------\nclean:\n\t@echo clean ...\n\t@rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).3ds $(OUTPUT).cia $(OUTPUT).smdh $(TARGET).elf $(OUTPUT)stripped.elf\n\n\n#---------------------------------------------------------------------------------\nelse\n\nDEPENDS\t:=\t$(OFILES:.o=.d)\n\n#---------------------------------------------------------------------------------\n# main targets\n#---------------------------------------------------------------------------------\nifeq ($(strip $(NO_SMDH)),)\n.PHONY: all\nall\t:\t$(OUTPUT).3dsx $(OUTPUT).3ds $(OUTPUT).cia $(OUTPUT).smdh\nendif\n\n$(OUTPUT).3dsx\t:\t$(OUTPUT).elf\n\n$(OUTPUT).3ds\t:\t$(OUTPUT)stripped.elf\n\tmakerom -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\"\n\n$(OUTPUT).cia\t:\t$(OUTPUT)stripped.elf\n\tmakerom -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\n\n$(OUTPUT).elf\t:\t$(OFILES)\n\n$(OUTPUT)stripped.elf : $(OUTPUT).elf\n\tcp -f $(OUTPUT).elf $(OUTPUT)stripped.elf\n\t@arm-none-eabi-strip $(OUTPUT)stripped.elf\n\n#---------------------------------------------------------------------------------\n# you need a rule like this for each extension you use as binary data\n#---------------------------------------------------------------------------------\n%.bin.o\t:\t%.bin\n#---------------------------------------------------------------------------------\n\t@echo $(notdir $<)\n\t@$(bin2o)\n\n# WARNING: This is not the right way to do this! TODO: Do it right!\n#---------------------------------------------------------------------------------\n%.vsh.o\t:\t%.vsh\n#---------------------------------------------------------------------------------\n\t@echo $(notdir $<)\n\t@python $(AEMSTRO)/aemstro_as.py $< ../$(notdir $<).shbin\n\t@bin2s ../$(notdir $<).shbin | $(PREFIX)as -o $@\n\t@echo \"extern const u8\" `(echo $(notdir $<).shbin | sed -e 's/^\\([0-9]\\)/_\\1/' | tr . _)`\"_end[];\" > `(echo $(notdir $<).shbin | tr . _)`.h\n\t@echo \"extern const u8\" `(echo $(notdir $<).shbin | sed -e 's/^\\([0-9]\\)/_\\1/' | tr . _)`\"[];\" >> `(echo $(notdir $<).shbin | tr . _)`.h\n\t@echo \"extern const u32\" `(echo $(notdir $<).shbin | sed -e 's/^\\([0-9]\\)/_\\1/' | tr . _)`_size\";\" >> `(echo $(notdir $<).shbin | tr . _)`.h\n\t@rm ../$(notdir $<).shbin\n\n-include $(DEPENDS)\n\n#---------------------------------------------------------------------------------------\nendif\n#---------------------------------------------------------------------------------------\n"
  },
  {
    "path": "3DS/cxi/build_cia.rsf",
    "content": "BasicInfo:\n  Title                   : \"3DS Controller\"\n  CompanyCode             : \"00\"\n  ProductCode             : \"CTR-N-3DSC\"\n  ContentType             : Application # Application / SystemUpdate / Manual / Child / Trial\n  Logo                    : Nintendo # Nintendo / Licensed / Distributed / iQue / iQueForSystem\n\nRomFs:\n  # Specifies the root path of the file system to include in the ROM.\n  # HostRoot                : \"$(ROMFS_ROOT)\"\n\n\nTitleInfo:\n  UniqueId                : 0xf0fc2 # This was/is the first real homebrew app. I hope this TID range is not used by any retail game/app.\n  Category                : Application # Application / SystemApplication / Applet / Firmware / Base / DlpChild / Demo / Contents / SystemContents / SharedContents / AddOnContents / Patch / AutoUpdateContents\n\nCardInfo:\n  MediaSize               : 512MB # 128MB / 256MB / 512MB / 1GB / 2GB / 4GB / 8GB / 16GB / 32GB\n  MediaType               : Card1 # Card1 / Card2\n  CardDevice              : NorFlash # NorFlash / None\n  \n\nOption:\n  UseOnSD                 : true # true if App is to be installed to SD\n  EnableCompress          : true # Compresses exefs code\n  FreeProductCode         : true # Removes limitations on ProductCode\n  EnableCrypt             : false # Enables encryption for NCCH and CIA\n  MediaFootPadding        : false # If true CCI files are created with padding\n  \nAccessControlInfo:\n  # UseOtherVariationSaveData : true\n  # UseExtSaveData : true\n  # ExtSaveDataId: 0xffffffff\n  # SystemSaveDataId1: 0x220\n  # SystemSaveDataId2: 0x00040010\n  # OtherUserSaveDataId1: 0x220\n  # OtherUserSaveDataId2: 0x330\n  # OtherUserSaveDataId3: 0x440\n  # UseExtendedSaveDataAccessControl: true\n  # AccessibleSaveDataIds: [0x101, 0x202, 0x303, 0x404, 0x505, 0x606]\n  FileSystemAccess:\n   # - CategorySystemApplication\n   # - CategoryHardwareCheck\n   # - CategoryFileSystemTool\n   - Debug\n   # - TwlCardBackup\n   # - TwlNandData\n   # - Boss\n   - DirectSdmc\n   # - Core\n   # - CtrNandRo\n   # - CtrNandRw\n   # - CtrNandRoWrite\n   # - CategorySystemSettings\n   # - CardBoard\n   # - ExportImportIvs\n   # - DirectSdmcWrite\n   # - SwitchCleanup\n   # - SaveDataMove\n   # - Shop\n   # - Shell\n   # - CategoryHomeMenu\n  IoAccessControl:\n   # - FsMountNand\n   # - FsMountNandRoWrite\n   # - FsMountTwln\n   # - FsMountWnand\n   # - FsMountCardSpi\n   # - UseSdif3\n   # - CreateSeed\n   # - UseCardSpi\n   \n  IdealProcessor                : 0\n  AffinityMask                  : 1\n  \n  Priority                      : 16\n   \n  MaxCpu                        : 0x9E # Default\n  \n  DisableDebug                  : true\n  EnableForceDebug              : false\n  CanWriteSharedPage            : true\n  CanUsePrivilegedPriority      : false\n  CanUseNonAlphabetAndNumber    : true\n  PermitMainFunctionArgument    : true\n  CanShareDeviceMemory          : true\n  RunnableOnSleep               : false\n  SpecialMemoryArrange          : true\n  \n  CoreVersion                   : 2\n  DescVersion                   : 2\n  \n  ReleaseKernelMajor            : \"02\"\n  ReleaseKernelMinor            : \"33\" \n  MemoryType                    : Application # Application / System / Base\n  HandleTableSize: 512\n  IORegisterMapping: \n   - 1ff50000-1ff57fff\n   - 1ff70000-1ff77fff\n  MemoryMapping: \n   - 1f000000-1f5fffff:r\n  SystemCallAccess: \n    ArbitrateAddress: 34\n    Break: 60\n    CancelTimer: 28\n    ClearEvent: 25\n    ClearTimer: 29\n    CloseHandle: 35\n    ConnectToPort: 45\n    ControlMemory: 1\n    CreateAddressArbiter: 33\n    CreateEvent: 23\n    CreateMemoryBlock: 30\n    CreateMutex: 19\n    CreateSemaphore: 21\n    CreateThread: 8\n    CreateTimer: 26\n    DuplicateHandle: 39\n    ExitProcess: 3\n    ExitThread: 9\n    GetCurrentProcessorNumber: 17\n    GetHandleInfo: 41\n    GetProcessId: 53\n    GetProcessIdOfThread: 54\n    GetProcessIdealProcessor: 6\n    GetProcessInfo: 43\n    GetResourceLimit: 56\n    GetResourceLimitCurrentValues: 58\n    GetResourceLimitLimitValues: 57\n    GetSystemInfo: 42\n    GetSystemTick: 40\n    GetThreadContext: 59\n    GetThreadId: 55\n    GetThreadIdealProcessor: 15\n    GetThreadInfo: 44\n    GetThreadPriority: 11\n    MapMemoryBlock: 31\n    OutputDebugString: 61\n    QueryMemory: 2\n    ReleaseMutex: 20\n    ReleaseSemaphore: 22\n    SendSyncRequest1: 46\n    SendSyncRequest2: 47\n    SendSyncRequest3: 48\n    SendSyncRequest4: 49\n    SendSyncRequest: 50\n    SetThreadPriority: 12\n    SetTimer: 27\n    SignalEvent: 24\n    SleepThread: 10\n    UnmapMemoryBlock: 32\n    WaitSynchronization1: 36\n    WaitSynchronizationN: 37\n  InterruptNumbers:\n  ServiceAccessControl: \n   - APT:U\n   - $hioFIO\n   - $hostio0\n   - $hostio1\n   - ac:u\n   - boss:U\n   - cam:u\n   - cecd:u\n   - cfg:u\n   - dlp:FKCL\n   - dlp:SRVR\n   - dsp::DSP\n   - frd:u\n   - fs:USER\n   - gsp::Gpu\n   - hid:USER\n   - http:C\n   - mic:u\n   - ndm:u\n   - news:u\n   - nwm::UDS\n   - ptm:u\n   - pxi:dev\n   - soc:U\n   - ssl:C\n   - y2r:u\n   - ldr:ro\n   - ir:USER\n   - ir:u\n   - ir:rst\n  \n   \nSystemControlInfo:\n  SaveDataSize: 0KB # It doesn't use any save data.\n  RemasterVersion: 2\n  StackSize: 0x40000\n  # JumpId: 0\n  Dependency: \n    ac: 0x0004013000002402L\n    am: 0x0004013000001502L\n    boss: 0x0004013000003402L\n    camera: 0x0004013000001602L\n    cecd: 0x0004013000002602L\n    cfg: 0x0004013000001702L\n    codec: 0x0004013000001802L\n    csnd: 0x0004013000002702L\n    dlp: 0x0004013000002802L\n    dsp: 0x0004013000001a02L\n    friends: 0x0004013000003202L\n    gpio: 0x0004013000001b02L\n    gsp: 0x0004013000001c02L\n    hid: 0x0004013000001d02L\n    http: 0x0004013000002902L\n    i2c: 0x0004013000001e02L\n    ir: 0x0004013000003302L\n    mcu: 0x0004013000001f02L\n    mic: 0x0004013000002002L\n    ndm: 0x0004013000002b02L\n    news: 0x0004013000003502L\n    nim: 0x0004013000002c02L\n    nwm: 0x0004013000002d02L\n    pdn: 0x0004013000002102L\n    ps: 0x0004013000003102L\n    ptm: 0x0004013000002202L\n    ro: 0x0004013000003702L\n    socket: 0x0004013000002e02L\n    spi: 0x0004013000002302L\n    ssl: 0x0004013000002f02L\n"
  },
  {
    "path": "3DS/cxi/gw_workaround.rsf",
    "content": "BasicInfo:\n  Title                   : \"3DS Controller\"\n  CompanyCode             : \"00\"\n  ProductCode             : \"CTR-N-3DSC\"\n  ContentType             : Application\n  Logo                    : Nintendo # Nintendo / Licensed / Distributed / iQue / iQueForSystem\n\nRomFs:\n  # Specifies the root path of the file system to include in the ROM.\n  #HostRoot                : \"romfs\"\n\n\nTitleInfo:\n  UniqueId                : 0xf0fc2\n  Category                : Application\n  \nCardInfo:\n  MediaSize               : 128MB # 128MB / 256MB / 512MB / 1GB / 2GB / 4GB\n  MediaType               : Card1 # Card1 / Card2\n  CardDevice              : NorFlash # NorFlash(Pick this if you use savedata) / None\n  \n\nOption:\n  FreeProductCode         : true # Removes limitations on ProductCode\n  MediaFootPadding        : false # If true CCI files are created with padding\n  EnableCrypt             : true # Enables encryption for NCCH and CIA\n  EnableCompress          : true # Compresses exefs code\n  \nAccessControlInfo:\n  #UseExtSaveData : true\n  #ExtSaveDataId: 0xff3ff\n  #UseExtendedSaveDataAccessControl: true\n  #AccessibleSaveDataIds: [0x101, 0x202, 0x303, 0x404, 0x505, 0x606]\n\nSystemControlInfo:\n  SaveDataSize: 128KB\n  RemasterVersion: 0\n  StackSize: 0x40000\n  \n# DO NOT EDIT BELOW HERE OR PROGRAMS WILL NOT LAUNCH (most likely)\n\nAccessControlInfo:\n  FileSystemAccess:\n   - Debug\n   - DirectSdmc\n   - DirectSdmcWrite\n   \n  IdealProcessor                : 0\n  AffinityMask                  : 1\n  \n  Priority                      : 16\n   \n  MaxCpu                        : 0x9E # Default\n  \n  CoreVersion                   : 2\n  DescVersion                   : 2\n  \n  ReleaseKernelMajor            : \"02\"\n  ReleaseKernelMinor            : \"33\" \n  MemoryType                    : Application\n  HandleTableSize: 512\n  IORegisterMapping: \n   - 1ff50000-1ff57fff\n   - 1ff70000-1ff77fff\n  MemoryMapping: \n   - 1f000000-1f5fffff:r\n  SystemCallAccess: \n    ArbitrateAddress: 34\n    Break: 60\n    CancelTimer: 28\n    ClearEvent: 25\n    ClearTimer: 29\n    CloseHandle: 35\n    ConnectToPort: 45\n    ControlMemory: 1\n    CreateAddressArbiter: 33\n    CreateEvent: 23\n    CreateMemoryBlock: 30\n    CreateMutex: 19\n    CreateSemaphore: 21\n    CreateThread: 8\n    CreateTimer: 26\n    DuplicateHandle: 39\n    ExitProcess: 3\n    ExitThread: 9\n    GetCurrentProcessorNumber: 17\n    GetHandleInfo: 41\n    GetProcessId: 53\n    GetProcessIdOfThread: 54\n    GetProcessIdealProcessor: 6\n    GetProcessInfo: 43\n    GetResourceLimit: 56\n    GetResourceLimitCurrentValues: 58\n    GetResourceLimitLimitValues: 57\n    GetSystemInfo: 42\n    GetSystemTick: 40\n    GetThreadContext: 59\n    GetThreadId: 55\n    GetThreadIdealProcessor: 15\n    GetThreadInfo: 44\n    GetThreadPriority: 11\n    MapMemoryBlock: 31\n    OutputDebugString: 61\n    QueryMemory: 2\n    ReleaseMutex: 20\n    ReleaseSemaphore: 22\n    SendSyncRequest1: 46\n    SendSyncRequest2: 47\n    SendSyncRequest3: 48\n    SendSyncRequest4: 49\n    SendSyncRequest: 50\n    SetThreadPriority: 12\n    SetTimer: 27\n    SignalEvent: 24\n    SleepThread: 10\n    UnmapMemoryBlock: 32\n    WaitSynchronization1: 36\n    WaitSynchronizationN: 37\n  InterruptNumbers:\n  ServiceAccessControl: \n   - APT:U\n   - $hioFIO\n   - $hostio0\n   - $hostio1\n   - ac:u\n   - boss:U\n   - cam:u\n   - cecd:u\n   - cfg:u\n   - dlp:FKCL\n   - dlp:SRVR\n   - dsp::DSP\n   - frd:u\n   - fs:USER\n   - gsp::Gpu\n   - hid:USER\n   - http:C\n   - mic:u\n   - ndm:u\n   - news:u\n   - nwm::UDS\n   - ptm:u\n   - pxi:dev\n   - soc:U\n   - ssl:C\n   - y2r:u\n   - ldr:ro\n   - ir:USER\n  \n   \nSystemControlInfo:\n  Dependency: \n    ac: 0x0004013000002402L\n    am: 0x0004013000001502L\n    boss: 0x0004013000003402L\n    camera: 0x0004013000001602L\n    cecd: 0x0004013000002602L\n    cfg: 0x0004013000001702L\n    codec: 0x0004013000001802L\n    csnd: 0x0004013000002702L\n    dlp: 0x0004013000002802L\n    dsp: 0x0004013000001a02L\n    friends: 0x0004013000003202L\n    gpio: 0x0004013000001b02L\n    gsp: 0x0004013000001c02L\n    hid: 0x0004013000001d02L\n    http: 0x0004013000002902L\n    i2c: 0x0004013000001e02L\n    ir: 0x0004013000003302L\n    mcu: 0x0004013000001f02L\n    mic: 0x0004013000002002L\n    ndm: 0x0004013000002b02L\n    news: 0x0004013000003502L\n    nim: 0x0004013000002c02L\n    nwm: 0x0004013000002d02L\n    pdn: 0x0004013000002102L\n    ps: 0x0004013000003102L\n    ptm: 0x0004013000002202L\n    ro: 0x0004013000003702L\n    socket: 0x0004013000002e02L\n    spi: 0x0004013000002302L\n    ssl: 0x0004013000002f02L\nCommonHeaderKey: \n  D: |\n    jL2yO86eUQnYbXIrzgFVMm7FVze0LglZ2f5g+c42hWoEdnb5BOotaMQPBfqt\n    aUyAEmzQPaoi/4l4V+hTJRXQfthVRqIEx27B84l8LA6Tl5Fy9PaQaQ+4yRfP\n    g6ylH2l0EikrIVjy2uMlFgl0QJCrG+QGKHftxhaGCifdAwFNmiZuyJ/TmktZ\n    0RCb66lYcr2h/p2G7SnpKUliS9h9KnpmG+UEgVYQUK+4SCfByUa9PxYGpT0E\n    nw1UcRz0gsBmdOqcgzwnAd9vVqgb42hVn6uQZyAl+j1RKiMWywZarazIR/k5\n    Lmr4+groimSEa+3ajyoIho9WaWTDmFU3mkhA2tUDIQ==\n  Exponent: |\n    AQAB\n  Modulus: |\n    zwCcsyCgMkdlieCgQMVXA6X2jmb1ICjup0Q+jk/AydPkOgsx7I/MjUymFEkU\n    vgXBtCKtzh3NKXtFFuW51tJ60GPOabLKuG0Qm5li+UXALrWhzWuvd5vv2FZI\n    dTQCbrq/MFS/M02xNtwqzWiBjE/LwqIdbrDAAvX4HGy0ydaQJ1DKYeQeph5D\n    lAGBw2nQ4izXhhuLaU3w8VQkIJHdhxIKI5gJY/20AGkG0vHD553Mh5kBINrWp\n    CRYmmJS8DCYbAiQtKbkeUfzHViGTZuj6PwaY8Mv39PGO47a++pt45IUyCEs4/\n    LjMS72cyfo8tU4twRGp76SFGYejYj3wGC1f/POQw==\n  Signature: |\n    BOPR0jL0BOV5Zx502BuPbOvi/hvOq5ID8Dz1MQfOjkey6FKP/6cb4f9YXpm6c\n    ZCHAZLo0GduKdMepiKPUq1rsbbAxkRdQdjOOusEWoxNA58x3E4373tCAhlqM2\n    DvuQERrIIQ/XnYLV9C3uw4efZwhFqog1jvVyoEHpuvs8xnYtGbsKQ8FrgLwXv\n    pOZYy9cSgq+jqLy2D9IxiowPcbq2cRlbW9d2xlUfpq0AohyuXQhpxn7d9RUor\n    9veoARRAdxRJK12EpcSoEM1LhTRYdJnSRCY3x3p6YIV3c+l1sWvaQwKt0sZ/U\n    8TTDx2gb9g7r/+U9icneu/zlqUpSkexCS009Q==\n  Descriptor: |\n    AP///wAABAACAAAAAAAFGJ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiIAAAAAAAABBUFQ6VQAAACRo\n    aW9GSU8AJGhvc3RpbzAkaG9zdGlvMWFjOnUAAAAAYm9zczpVAABjYW06dQAA\n    AGNlY2Q6dQAAY2ZnOnUAAABkbHA6RktDTGRscDpTUlZSZHNwOjpEU1BmcmQ6\n    dQAAAGZzOlVTRVIAZ3NwOjpHcHVoaWQ6VVNFUmh0dHA6QwAAbWljOnUAAABu\n    ZG06dQAAAG5ld3M6dQAAbndtOjpVRFNwdG06dQAAAHB4aTpkZXYAc29jOlUA\n    AABzc2w6QwAAAHkycjp1AAAAbGRyOnJvAABpcjpVU0VSAAAAAAAAAAAAAAAA\n    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n    AAAAAAAAAABOn/rw/7//8ec/APIA8JH/APaR/1D/gf9Y/4H/cP+B/3j/gf8B\n    AQD/AAIA/iECAPz/////////////////////////////////////////////\n    ////////////////////////////////////////AAAAAAAAAAAAAAAAAAAA\n    AAADAAAAAAAAAAAAAAAAAAI="
  },
  {
    "path": "3DS/include/drawing.h",
    "content": "#pragma once\n\n#ifndef REG_LCDBACKLIGHTMAIN\n#define REG_LCDBACKLIGHTMAIN (u32)(0x1ED02240 - 0x1EB00000)\n#endif\n\n#ifndef REG_LCDBACKLIGHTSUB\n#define REG_LCDBACKLIGHTSUB (u32)(0x1ED02A40 - 0x1EB00000)\n#endif\n\nvoid clearScreen(void);\n\n#define drawPixelRGB(x, y, r, g, b) drawPixelRGBFramebuffer(0, x, y, r, g, b)\nvoid drawPixelRGBFramebuffer(u8 *fb, int x, int y, u8 r, u8 g, u8 b);\n\n#define drawBox(x, y, width, height, r, g, b) drawBoxFramebuffer(0, x, y, width, height, r, g, b)\nvoid drawBoxFramebuffer(u8 *fb, int x, int y, int width, int height, u8 r, u8 g, u8 b);\n\n#define drawString(sx, sy, text, ...) drawStringFramebuffer(0, sx, sy, text, ##__VA_ARGS__)\nvoid drawStringFramebuffer(u8 *fb, int sx, int sy, char *text, ...);\n\nvoid disableBacklight();\nvoid enableBacklight();\n"
  },
  {
    "path": "3DS/include/inet_pton.h",
    "content": "#pragma once\n\n#define INADDRSZ         4\n\nint inet_pton4(const char *src, unsigned char *dst);\n"
  },
  {
    "path": "3DS/include/input.h",
    "content": "#pragma once\n\nint inputIP(void);\n"
  },
  {
    "path": "3DS/include/keyboard.h",
    "content": "#pragma once\n\nextern const char keyboardChars[60];\n\nextern unsigned char keyboardActive;\nextern unsigned char keyboardToggle;\n\nextern unsigned char keyboardGfx[320 * 240 * 3];\n\nvoid preRenderKeyboard(void);\nextern void drawKeyboard(void);\n"
  },
  {
    "path": "3DS/include/settings.h",
    "content": "#pragma once\n\n#include <stdbool.h>\n\nstruct settings {\n\tchar IPString[16];\n\tint port;\n};\n\nextern struct settings settings;\nextern struct settings defaultSettings;\n\nextern Handle fileHandle;\n\nbool readSettings(void);\n"
  },
  {
    "path": "3DS/include/wireless.h",
    "content": "#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#include <arpa/inet.h>\n#include <fcntl.h>\n\n#include \"inet_pton.h\"\n\n#define SCREENSHOT_CHUNK 4000\n\n#define DEFAULT_PORT 8889\n\nenum NET_COMMANDS {\n\tCONNECT,\n\tKEYS,\n\tSCREENSHOT,\n};\n\n// It is deliberately set up to have an anonymous struct as well as a named struct for convenience, not a mistake!\nstruct packet {\n\tunion {\n\t\tstruct packetHeader {\n\t\t\tunsigned char command;\n\t\t\tunsigned char keyboardActive;\n\t\t};\n\t\tstruct packetHeader packetHeader;\n\t};\n\t\n\tunion {\n\t\t// CONNECT\n\t\tunion {\n\t\t\tstruct connectPacket {\n\t\t\t};\n\t\t\tstruct connectPacket connectPacket;\n\t\t};\n\t\t\n\t\t// KEYS\n\t\tunion {\n\t\t\tstruct keysPacket {\n\t\t\t\tunsigned int keys;\n\t\t\t\t\n\t\t\t\tstruct {\n\t\t\t\t\tshort x;\n\t\t\t\t\tshort y;\n\t\t\t\t} circlePad;\n\t\t\t\t\n\t\t\t\tstruct {\n\t\t\t\t\tunsigned short x;\n\t\t\t\t\tunsigned short y;\n\t\t\t\t} touch;\n\t\t\t\t\n\t\t\t\tstruct {\n\t\t\t\t\tshort x;\n\t\t\t\t\tshort y;\n\t\t\t\t} cStick;\n\t\t\t};\n\t\t\tstruct keysPacket keysPacket;\n\t\t};\n\t\t\n\t\t// SCREENSHOT\n\t\tunion {\n\t\t\tstruct screenshotPacket {\n\t\t\t\tunsigned short offset;\n\t\t\t\tunsigned char data[SCREENSHOT_CHUNK];\n\t\t\t};\n\t\t\tstruct screenshotPacket screenshotPacket;\n\t\t};\n\t};\n};\n\nextern int sock;\nextern struct sockaddr_in sain, saout;\nextern struct packet outBuf, rcvBuf;\n\nextern socklen_t sockaddr_in_sizePtr;\n\nbool openSocket(int port);\nvoid sendBuf(int length);\nint receiveBuffer(int length);\nvoid sendConnectionRequest(void);\nvoid sendKeys(unsigned int keys, circlePosition circlePad, touchPosition touch, circlePosition cStick);\n"
  },
  {
    "path": "3DS/source/drawing.c",
    "content": "#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 fonts[] = { //Fonte 8x8 1BPP\n\t0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 //tile:0\n\t, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0, 0x18, 0x0 //tile:1\n\t, 0x6c, 0x6c, 0x6c, 0x0, 0x0, 0x0, 0x0, 0x0 //tile:2\n\t, 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x0 //tile:3\n\t, 0x18, 0x7e, 0xc0, 0x7c, 0x6, 0xfc, 0x18, 0x0 //tile:4\n\t, 0x0, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x0 //tile:5\n\t, 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x0 //tile:6\n\t, 0x30, 0x30, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0 //tile:7\n\t, 0xc, 0x18, 0x30, 0x30, 0x30, 0x18, 0xc, 0x0 //tile:8\n\t, 0x30, 0x18, 0xc, 0xc, 0xc, 0x18, 0x30, 0x0 //tile:9\n\t, 0x0, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x0, 0x0 //tile:10\n\t, 0x0, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x0, 0x0 //tile:11\n\t, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x18, 0x30 //tile:12\n\t, 0x0, 0x0, 0x0, 0x7e, 0x0, 0x0, 0x0, 0x0 //tile:13\n\t, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x18, 0x0 //tile:14\n\t, 0x6, 0xc, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x0 //tile:15\n\t, 0x7c, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0x7c, 0x0 //tile:16\n\t, 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x0 //tile:17\n\t, 0x7c, 0xc6, 0x6, 0x7c, 0xc0, 0xc0, 0xfe, 0x0 //tile:18\n\t, 0xfc, 0x6, 0x6, 0x3c, 0x6, 0x6, 0xfc, 0x0 //tile:19\n\t, 0xc, 0xcc, 0xcc, 0xcc, 0xfe, 0xc, 0xc, 0x0 //tile:20\n\t, 0xfe, 0xc0, 0xfc, 0x6, 0x6, 0xc6, 0x7c, 0x0 //tile:21\n\t, 0x7c, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x0 //tile:22\n\t, 0xfe, 0x6, 0x6, 0xc, 0x18, 0x30, 0x30, 0x0 //tile:23\n\t, 0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x0 //tile:24\n\t, 0x7c, 0xc6, 0xc6, 0x7e, 0x6, 0x6, 0x7c, 0x0 //tile:25\n\t, 0x0, 0x18, 0x18, 0x0, 0x0, 0x18, 0x18, 0x0 //tile:26\n\t, 0x0, 0x18, 0x18, 0x0, 0x0, 0x18, 0x18, 0x30 //tile:27\n\t, 0xc, 0x18, 0x30, 0x60, 0x30, 0x18, 0xc, 0x0 //tile:28\n\t, 0x0, 0x0, 0x7e, 0x0, 0x7e, 0x0, 0x0, 0x0 //tile:29\n\t, 0x30, 0x18, 0xc, 0x6, 0xc, 0x18, 0x30, 0x0 //tile:30\n\t, 0x3c, 0x66, 0xc, 0x18, 0x18, 0x0, 0x18, 0x0 //tile:31\n\t, 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x7e, 0x0 //tile:32\n\t, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x0 //tile:33\n\t, 0xfc, 0xc6, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0x0 //tile:34\n\t, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x0 //tile:35\n\t, 0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x0 //tile:36\n\t, 0xfe, 0xc0, 0xc0, 0xf8, 0xc0, 0xc0, 0xfe, 0x0 //tile:37\n\t, 0xfe, 0xc0, 0xc0, 0xf8, 0xc0, 0xc0, 0xc0, 0x0 //tile:38\n\t, 0x7c, 0xc6, 0xc0, 0xc0, 0xce, 0xc6, 0x7c, 0x0 //tile:39\n\t, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x0 //tile:40\n\t, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x0 //tile:41\n\t, 0x6, 0x6, 0x6, 0x6, 0x6, 0xc6, 0x7c, 0x0 //tile:42\n\t, 0xc6, 0xcc, 0xd8, 0xf0, 0xd8, 0xcc, 0xc6, 0x0 //tile:43\n\t, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0x0 //tile:44\n\t, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x0 //tile:45\n\t, 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x0 //tile:46\n\t, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x0 //tile:47\n\t, 0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0xc0, 0x0 //tile:48\n\t, 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x6 //tile:49\n\t, 0xfc, 0xc6, 0xc6, 0xfc, 0xd8, 0xcc, 0xc6, 0x0 //tile:50\n\t, 0x7c, 0xc6, 0xc0, 0x7c, 0x6, 0xc6, 0x7c, 0x0 //tile:51\n\t, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0 //tile:52\n\t, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0x0 //tile:53\n\t, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x38, 0x0 //tile:54\n\t, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0x6c, 0x0 //tile:55\n\t, 0xc6, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0xc6, 0x0 //tile:56\n\t, 0xc6, 0xc6, 0xc6, 0x7c, 0x18, 0x30, 0xe0, 0x0 //tile:57\n\t, 0xfe, 0x6, 0xc, 0x18, 0x30, 0x60, 0xfe, 0x0 //tile:58\n\t, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x0 //tile:59\n\t, 0xc0, 0x60, 0x30, 0x18, 0xc, 0x6, 0x2, 0x0 //tile:60\n\t, 0x3c, 0xc, 0xc, 0xc, 0xc, 0xc, 0x3c, 0x0 //tile:61\n\t, 0x10, 0x38, 0x6c, 0xc6, 0x0, 0x0, 0x0, 0x0 //tile:62\n\t, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff //tile:63\n\t, 0x18, 0x18, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0 //tile:64\n\t, 0x0, 0x0, 0x7c, 0x6, 0x7e, 0xc6, 0x7e, 0x0 //tile:65\n\t, 0xc0, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xfc, 0x0 //tile:66\n\t, 0x0, 0x0, 0x7c, 0xc6, 0xc0, 0xc6, 0x7c, 0x0 //tile:67\n\t, 0x6, 0x6, 0x6, 0x7e, 0xc6, 0xc6, 0x7e, 0x0 //tile:68\n\t, 0x0, 0x0, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x0 //tile:69\n\t, 0x1c, 0x36, 0x30, 0x78, 0x30, 0x30, 0x78, 0x0 //tile:70\n\t, 0x0, 0x0, 0x7e, 0xc6, 0xc6, 0x7e, 0x6, 0xfc //tile:71\n\t, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x0 //tile:72\n\t, 0x18, 0x0, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x0 //tile:73\n\t, 0x6, 0x0, 0x6, 0x6, 0x6, 0x6, 0xc6, 0x7c //tile:74\n\t, 0xc0, 0xc0, 0xcc, 0xd8, 0xf8, 0xcc, 0xc6, 0x0 //tile:75\n\t, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x0 //tile:76\n\t, 0x0, 0x0, 0xcc, 0xfe, 0xfe, 0xd6, 0xd6, 0x0 //tile:77\n\t, 0x0, 0x0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x0 //tile:78\n\t, 0x0, 0x0, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x0 //tile:79\n\t, 0x0, 0x0, 0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0 //tile:80\n\t, 0x0, 0x0, 0x7e, 0xc6, 0xc6, 0x7e, 0x6, 0x6 //tile:81\n\t, 0x0, 0x0, 0xfc, 0xc6, 0xc0, 0xc0, 0xc0, 0x0 //tile:82\n\t, 0x0, 0x0, 0x7e, 0xc0, 0x7c, 0x6, 0xfc, 0x0 //tile:83\n\t, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0xe, 0x0 //tile:84\n\t, 0x0, 0x0, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x0 //tile:85\n\t, 0x0, 0x0, 0xc6, 0xc6, 0xc6, 0x7c, 0x38, 0x0 //tile:86\n\t, 0x0, 0x0, 0xc6, 0xc6, 0xd6, 0xfe, 0x6c, 0x0 //tile:87\n\t, 0x0, 0x0, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x0 //tile:88\n\t, 0x0, 0x0, 0xc6, 0xc6, 0xc6, 0x7e, 0x6, 0xfc //tile:89\n\t, 0x0, 0x0, 0xfe, 0xc, 0x38, 0x60, 0xfe, 0x0 //tile:90\n\t, 0xe, 0x18, 0x18, 0x70, 0x18, 0x18, 0xe, 0x0 //tile:91\n\t, 0x18, 0x18, 0x18, 0x0, 0x18, 0x18, 0x18, 0x0 //tile:92\n\t, 0x70, 0x18, 0x18, 0xe, 0x18, 0x18, 0x70, 0x0 //tile:93\n\t, 0x76, 0xdc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 //tile:94\n\t, 0x0, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x0 //tile:95\n};\n\ninline void clearScreen(void) {\n\tu8 *frame = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);\n\tmemset(frame, 0, 320 * 240 * 3);\n}\n\nvoid drawPixelRGBFramebuffer(u8 *fb, int x, int y, u8 r, u8 g, u8 b) {\n\ty = 240 - y;\n\tx = x;\n\tu32 v = (y + x * 240) * 3;\n\tu8 *topLeftFB = fb ? fb : gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);\n\ttopLeftFB[v] = (b >> 3) + ((g & 0x1C) << 3);\n\ttopLeftFB[v+1] = ((g & 0xE0) >> 5) + (r & 0xF8);\n}\n\ninline void drawBoxFramebuffer(u8 *fb, int x, int y, int width, int height, u8 r, u8 g, u8 b) {\n\tint lx, ly;\n\tfor(lx = x; lx < x + width; lx++) {\n\t\tfor(ly = y; ly < y + height; ly++) {\n\t\t\tdrawPixelRGBFramebuffer(fb, lx, ly, r, g, b);\n\t\t}\n\t}\n}\n\nvoid drawStringFramebuffer(u8 *fb, int sx, int sy, char *text, ...) {\n\tchar str[1024];\n\tva_list args;\n\tva_start(args, text);\n\tvsnprintf(str, 1023, text, args);\n\tva_end(args);\n\t\n\tint i;\n\tfor(i = 0; i < strlen(str); i++) {\n\t\tint fntnum = (str[i] - 32) & 0xFF;\n\t\tint y;\n\t\tfor(y = 0; y < 8; y++) {\n\t\t\tint currbyte = fonts[(fntnum * 8) + y];\n\t\t\t//Desenha sprite de 1BPP\n\t\t\tint x;\n\t\t\tint mult = 0x80;\n\t\t\tfor(x = 0; x < 8; x++) {\n\t\t\t\tif((currbyte & mult) == mult) {\n\t\t\t\t\tdrawPixelRGBFramebuffer(fb, sx + x, sy + y, 0xFF, 0xFF, 0xFF);\n\t\t\t\t\tdrawPixelRGBFramebuffer(fb, sx + x, sy + y + 1, 0, 0, 0); //Sombra\n\t\t\t\t}\n\t\t\t\tmult /= 2;\n\t\t\t}\n\t\t}\n\t\tsx += 8;\n\t}\n}\n\nstatic u32 brightnessMain;\nstatic u32 brightnessSub;\n\nvoid disableBacklight() {\n\tu32 off = 0;\n\t\n\tGSPGPU_ReadHWRegs(REG_LCDBACKLIGHTMAIN, &brightnessMain, 4);\n\tGSPGPU_ReadHWRegs(REG_LCDBACKLIGHTSUB, &brightnessSub, 4);\n\t\n\tGSPGPU_WriteHWRegs(REG_LCDBACKLIGHTMAIN, &off, 4);\n\tGSPGPU_WriteHWRegs(REG_LCDBACKLIGHTSUB, &off, 4);\n}\n\nvoid enableBacklight() {\n\tGSPGPU_WriteHWRegs(REG_LCDBACKLIGHTMAIN, &brightnessMain, 4);\n\tGSPGPU_WriteHWRegs(REG_LCDBACKLIGHTSUB, &brightnessSub, 4);\n}\n"
  },
  {
    "path": "3DS/source/inet_pton.c",
    "content": "#include \"wireless.h\"\n\n#include \"inet_pton.h\"\n\nint inet_pton4(const char *src, unsigned char *dst) {\n  static const char digits[] = \"0123456789\";\n  int saw_digit, octets, ch;\n  unsigned char tmp[INADDRSZ], *tp;\n\n  saw_digit = 0;\n  octets = 0;\n  tp = tmp;\n  *tp = 0;\n  while((ch = *src++) != '\\0') {\n    const char *pch;\n\n    if((pch = strchr(digits, ch)) != NULL) {\n      unsigned int val = *tp * 10 + (unsigned int)(pch - digits);\n\n      if(saw_digit && *tp == 0)\n        return (0);\n      if(val > 255)\n        return (0);\n      *tp = (unsigned char)val;\n      if(! saw_digit) {\n        if(++octets > 4)\n          return (0);\n        saw_digit = 1;\n      }\n    }\n    else if(ch == '.' && saw_digit) {\n      if(octets == 4)\n        return (0);\n      *++tp = 0;\n      saw_digit = 0;\n    }\n    else\n      return (0);\n  }\n  if(octets < 4)\n    return (0);\n  memcpy(dst, tmp, INADDRSZ);\n  return (1);\n}\n"
  },
  {
    "path": "3DS/source/input.c",
    "content": "#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\nint inputIP(void) {\n\ttouchPosition touch;\n\thidTouchRead(&touch);\n\t\n\t//Draw Keypad\n\tdrawString(160-20,50, \"1\");\n\tdrawString(160, 50, \"2\");\n\tdrawString(160+20, 50, \"3\");\n\t\n\tdrawString(160-20, 50+20, \"4\");\n\tdrawString(160, 50+20, \"5\");\n\tdrawString(160+20, 50+20, \"6\");\n\t\n\tdrawString(160-20, 50+40, \"7\");\n\tdrawString(160, 50+40, \"8\");\n\tdrawString(160+20, 50+40, \"9\");\n\t\n\tdrawString(160-10, 50+60, \".\");\n\tdrawString(160+10, 50+60, \"0\");\n\t\n\t//Bottom Strip\n\tif(touch.py > 50+50 && touch.py < 50+70) {\n\t\tif(touch.px < 160 && touch.px > 160-20) return 11; // Dot\n\t\telse if(touch.px < 160+20 && touch.px > 160) return 0; // Zero\n\t}\n\t\n\t//First Column\n\telse if(touch.px < 160-10 && touch.px > 160-30) {\n\t\tif(touch.py < 50+10 && touch.py > 50-10) return 1; // One\n\t\telse if(touch.py < 50+30 && touch.py > 50+10) return 4; // Four\n\t\telse if(touch.py < 50+50 && touch.py > 50+30) return 7; // Seven\n\t}\n\t\n\t// Second Column\n\telse if(touch.px < 160+10 && touch.px > 160-10) {\n\t\tif(touch.py < 50+10 && touch.py > 50-10) return 2; // Two\n\t\telse if(touch.py < 50+30 && touch.py > 50+10) return 5; // Five\n\t\telse if(touch.py < 50+50 && touch.py > 50+30) return 8; // Eight\n\t}\n\t\n\t// Third Column\n\telse if(touch.px < 160+30 && touch.px > 160+10) {\n\t\tif(touch.py < 50+10 && touch.py > 50-10) return 3; // Three\n\t\telse if(touch.py < 50+30 && touch.py > 50+10) return 6; // Six\n\t\telse if(touch.py < 50+50 && touch.py > 50+30) return 9; // Nine\n\t}\n\t\n\treturn 10;\n}"
  },
  {
    "path": "3DS/source/keyboard.c",
    "content": "#include <3ds.h>\n#include <math.h>\n#include <string.h>\n\n#include \"drawing.h\"\n\n#include \"keyboard.h\"\n\nconst char keyboardChars[60] = \"!1234567890\\x08QWERTYUIOP\\13\\13ASDFGHJKL-\\13\\13ZXCVBNM,.?\\13\\13\\0\\0\\0     \\0\\0\\0\\0\";\n\nunsigned char keyboardActive = false;\nunsigned char keyboardToggle = true;\n\nunsigned char keyboardGfx[320 * 240 * 3];\n\nvoid preRenderKeyboard(void) {\n\tconst char chars[60] = \"!1234567890\\x08QWERTYUIOP\\13\\13ASDFGHJKL-\\13\\13ZXCVBNM,.?\\13\\13\\0\\0\\0     \\0\\0\\0\\0\";\n\t\n\tint x, y;\n\tfor(x = 0; x < 12; x++) {\n\t\tfor(y = 0; y < 4; y++) {\n\t\t\t// Not enter\n\t\t\tif(chars[x + y * 12] != '\\13') {\n\t\t\t\tdrawBoxFramebuffer(keyboardGfx, (int)((float)x * 320.0f / 12.0f), (int)(78.0f + (float)y * 320.0f / 12.0f), 25, 25, 31, 31, 31);\n\t\t\t\tdrawBoxFramebuffer(keyboardGfx, (int)((float)x * 320.0f / 12.0f) + 1, (int)(78.0f + (float)y * 320.0f / 12.0f) + 1, 24, 24, 31, 0, 0);\n\t\t\t\t\n\t\t\t\t// Backspace\n\t\t\t\tif(chars[x + y * 12] == '\\x08') {\n\t\t\t\t\tdrawStringFramebuffer(keyboardGfx, (int)((float)x * 320.0f / 12.0f) + 10, (int)(78.0f + (float)y * 320.0f / 12.0f) + 9, \"-\");\n\t\t\t\t\tdrawStringFramebuffer(keyboardGfx, (int)((float)x * 320.0f / 12.0f) + 8, (int)(78.0f + (float)y * 320.0f / 12.0f) + 9, \"<\");\n\t\t\t\t}\n\t\t\t\telse 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]);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t// Space\n\tdrawBoxFramebuffer(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);\n\tdrawBoxFramebuffer(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);\n\t\n\t// Enter\n\tdrawBoxFramebuffer(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);\n\tdrawBoxFramebuffer(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);\n}\n\ninline void drawKeyboard(void) {\n\tu8 *topLeftFB = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL);\n\tmemcpy(topLeftFB, keyboardGfx, sizeof(keyboardGfx));\n\t\n\t/*const char chars[60] = \"!1234567890\\x08QWERTYUIOP\\13\\13ASDFGHJKL-\\13\\13ZXCVBNM,.?\\13\\13\\0\\0\\0     \\0\\0\\0\\0\";\n\t\n\tint x, y;\n\tfor(x = 0; x < 12; x++) {\n\t\tfor(y = 0; y < 4; y++) {\n\t\t\t// Not enter\n\t\t\tif(chars[x + y * 12] != '\\13') {\n\t\t\t\tdrawBox((int)((float)x * 320.0f / 12.0f), (int)(78.0f + (float)y * 320.0f / 12.0f), 25, 25, 31, 31, 31);\n\t\t\t\tdrawBox((int)((float)x * 320.0f / 12.0f) + 1, (int)(78.0f + (float)y * 320.0f / 12.0f) + 1, 24, 24, 31, 0, 0);\n\t\t\t\t\n\t\t\t\t// Backspace\n\t\t\t\tif(chars[x + y * 12] == '\\x08') {\n\t\t\t\t\tdrawString((int)((float)x * 320.0f / 12.0f) + 10, (int)(78.0f + (float)y * 320.0f / 12.0f) + 9, \"-\");\n\t\t\t\t\tdrawString((int)((float)x * 320.0f / 12.0f) + 8, (int)(78.0f + (float)y * 320.0f / 12.0f) + 9, \"<\");\n\t\t\t\t}\n\t\t\t\telse drawString((int)((float)x * 320.0f / 12.0f) + 9, (int)(78.0f + (float)y * 320.0f / 12.0f) + 9, \"%c\", chars[x + y * 12]);\n\t\t\t}\n\t\t}\n\t}\n\t\n\t// Space\n\tdrawBox((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);\n\tdrawBox((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);\n\t\n\t// Enter\n\tdrawBox((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);\n\tdrawBox((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);\n\t*/\n}\n"
  },
  {
    "path": "3DS/source/main.c",
    "content": "#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\"\n#include \"settings.h\"\n#include \"drawing.h\"\n#include \"input.h\"\n#include \"keyboard.h\"\n\nstatic jmp_buf exitJmp;\n\nvoid hang(char *message) {\n\twhile(aptMainLoop()) {\n\t\thidScanInput();\n\t\t\n\t\tclearScreen();\n\t\tdrawString(10, 10, \"%s\", message);\n\t\tdrawString(10, 20, \"Press Start and Select to exit.\");\n\t\t\n\t\tu32 kHeld = hidKeysHeld();\n\t\tif((kHeld & KEY_START) && (kHeld & KEY_SELECT)) longjmp(exitJmp, 1);\n\t\t\n\t\tgfxFlushBuffers();\n\t\tgspWaitForVBlank();\n\t\tgfxSwapBuffers();\n\t}\n}\n\nint main(void) {\n\tacInit();\n\tgfxInitDefault();\n\t\n\tgfxSetDoubleBuffering(GFX_TOP, false);\n\tgfxSetDoubleBuffering(GFX_BOTTOM, false);\n\t\n\tif(setjmp(exitJmp)) goto exit;\n\t\n\tpreRenderKeyboard();\n\t\n\tclearScreen();\n\tdrawString(10, 10, \"Initialising FS...\");\n\tgfxFlushBuffers();\n\tgfxSwapBuffers();\n\t\n\tfsInit();\n\t\n\tclearScreen();\n\tdrawString(10, 10, \"Initialising SOC...\");\n\tgfxFlushBuffers();\n\tgfxSwapBuffers();\n\t\n\tsocInit((u32 *)memalign(0x1000, 0x100000), 0x100000);\n\t\n\twhile(aptMainLoop()) { /* Wait for WiFi; break when WiFiStatus is truthy */\n\t\tu32 wifiStatus = 0;\n\t\tACU_GetWifiStatus(&wifiStatus);\n\t\tif(wifiStatus) break;\n\t\t\n\t\thidScanInput();\n\t\tclearScreen();\n\t\tdrawString(10, 10, \"Waiting for WiFi connection...\");\n\t\tdrawString(10, 20, \"Ensure you are in range of an access point,\");\n\t\tdrawString(10, 30, \"and that wireless communications are enabled.\");\n\t\tdrawString(10, 50, \"You can alternatively press Start and Select to exit.\");\n\t\t\n\t\tu32 kHeld = hidKeysHeld();\n\t\tif((kHeld & KEY_START) && (kHeld & KEY_SELECT)) longjmp(exitJmp, 1);\n\t\t\n\t\tgfxFlushBuffers();\n\t\tgspWaitForVBlank();\n\t\tgfxSwapBuffers();\n\t}\n\t\n\tclearScreen();\n\tdrawString(10, 10, \"Reading settings...\");\n\tgfxFlushBuffers();\n\tgfxSwapBuffers();\n\t\n\tif(!readSettings()) {\n\t\thang(\"Could not read 3DSController.ini!\");\n\t}\n\t\n\tclearScreen();\n\tdrawString(10, 10, \"Connecting to %s on port %d...\", settings.IPString, settings.port);\n\tgfxFlushBuffers();\n\tgfxSwapBuffers();\n\t\n\topenSocket(settings.port);\n\tsendConnectionRequest();\n\t\n\tclearScreen();\n\tgfxFlushBuffers();\n\tgfxSwapBuffers();\n\t\n\tdisableBacklight();\n\t\n\twhile(aptMainLoop()) {\n\t\thidScanInput();\n\t\tirrstScanInput();\n\t\t\n\t\tu32 kHeld = hidKeysHeld();\n\t\tcirclePosition circlePad;\n\t\tcirclePosition cStick;\n\t\thidCstickRead(&cStick);\n\t\thidCircleRead(&circlePad);\n\t\ttouchPosition touch;\n\t\ttouchRead(&touch);\n\t\t\n\t\tclearScreen();\n\t\t\n\t\tif((kHeld & KEY_L) && (kHeld & KEY_R) && (kHeld & KEY_X)) {\n\t\t\tif(keyboardToggle) {\n\t\t\t\tkeyboardActive = !keyboardActive;\n\t\t\t\tkeyboardToggle = false;\n\t\t\t\t\n\t\t\t\tif(keyboardActive) enableBacklight();\n\t\t\t}\n\t\t}\n\t\telse keyboardToggle = true;\n\t\t\n\t\tif(keyboardActive) {\n\t\t\tdrawKeyboard();\n\t\t\t\n\t\t\tif(touch.px >= 1 && touch.px <= 312 && touch.py >= 78 && touch.py <= 208) {\n\t\t\t\tint x = (int)((float)touch.px * 12.0f / 320.0f);\n\t\t\t\tint y = (int)((float)(touch.py - 78) * 12.0f / 320.0f);\n\t\t\t\tint width = 24;\n\t\t\t\tint height = 24;\n\t\t\t\t\n\t\t\t\tif(keyboardChars[x + y * 12] == ' ') {\n\t\t\t\t\twhile(keyboardChars[(x - 1) + y * 12] == ' ') x--;\n\t\t\t\t\t\n\t\t\t\t\twidth = (int)(5.0f * 320.0f / 12.0f) - 1;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\telse if(keyboardChars[x + y * 12] == '\\13') {\n\t\t\t\t\twhile(keyboardChars[(x - 1) + y * 12] == '\\13') x--;\n\t\t\t\t\twhile(keyboardChars[x + (y - 1) * 12] == '\\13') y--;\n\t\t\t\t\t\n\t\t\t\t\twidth = (int)(2.0f * 320.0f / 12.0f) - 1;\n\t\t\t\t\theight = (int)(3.0f * 320.0f / 12.0f) - 1;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(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);\n\t\t\t}\n\t\t}\n\t\t\n\t\tsendKeys(kHeld, circlePad, touch, cStick);\n\t\t\n\t\t//receiveBuffer(sizeof(struct packet));\n\t\t\n\t\tif((kHeld & KEY_START) && (kHeld & KEY_SELECT)) longjmp(exitJmp, 1);\n\t\t\n\t\tgfxFlushBuffers();\n\t\tgspWaitForVBlank();\n\t\tgfxSwapBuffers();\n\t}\n\t\n\texit:\n\t\n\tenableBacklight();\n\t\n\tSOCU_ShutdownSockets();\n\t\n\tsvcCloseHandle(fileHandle);\n\tfsExit();\n\t\n\tgfxExit();\n\tacExit();\n\t\n\treturn 0;\n}\n"
  },
  {
    "path": "3DS/source/settings.c",
    "content": "#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 settings;\n\nstruct settings defaultSettings = {\n\tIPString: \"\",\n\tport: DEFAULT_PORT,\n};\n\nHandle fileHandle;\n\nstatic bool getSetting(char *name, char *src, char *dest) {\n\tchar *start = strstr(src, name);\n\t\n\tif(start) {\n\t\tstart += strlen(name);\n\t\t\n\t\tchar *end = start + strlen(start);\n\t\tif(strstr(start, \"\\n\") - 1 < end) end = strstr(start, \"\\n\") - 1;\n\t\tsize_t size = (size_t)end - (size_t)start;\n\t\t\n\t\tstrncpy(dest, start, size);\n\t\tdest[size] = '\\0';\n\t\t\n\t\treturn true;\n\t}\n\t\n\treturn false;\n}\n\nbool readSettings(void) {\n\tchar *buffer = NULL;\n\tu64 size;\n\tu32 bytesRead;\n\t\n\tFS_Path filePath = fsMakePath(PATH_ASCII, \"/3DSController.ini\");\n\t\n\tResult ret = FSUSER_OpenFileDirectly(&fileHandle, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, \"\"), filePath, FS_OPEN_READ, 0x00000000);\n\tif(ret) return false;\n\t\n\tret = FSFILE_GetSize(fileHandle, &size);\n\tif(ret) return false;\n\t\n\tbuffer = malloc(size);\n\tif(!buffer) return false;\n\t\n\tret = FSFILE_Read(fileHandle, &bytesRead, 0x0, buffer, size);\n\tif(ret || size != bytesRead) return false;\n\t\n\tret = FSFILE_Close(fileHandle);\n\tif(ret) return false;\n\t\n\tmemcpy(&settings, &defaultSettings, sizeof(struct settings));\n\t\n\tchar setting[64] = { '\\0' };\n\t\n\tif(getSetting(\"IP: \", buffer, settings.IPString)) {\n\t\t//inet_pton(AF_INET, settings.IPString, &(saout.sin_addr));\n\t\tinet_pton4(settings.IPString, (unsigned char *)&(saout.sin_addr));\n\t}\n\telse {\n\t\tfree(buffer);\n\t\treturn false;\n\t}\n\t\n\tif(getSetting(\"Port: \", buffer, setting)) {\n\t\tsscanf(setting, \"%d\", &settings.port);\n\t}\n\t\n\tfree(buffer);\n\t\n\treturn true;\n}\n"
  },
  {
    "path": "3DS/source/wireless.c",
    "content": "#include <stddef.h>\n\n#include \"keyboard.h\"\n\n#include \"wireless.h\"\n\nint sock;\nstruct sockaddr_in sain, saout;\nstruct packet outBuf, rcvBuf;\n\nsocklen_t sockaddr_in_sizePtr = (int)sizeof(struct sockaddr_in);\n\nbool openSocket(int port) {\n\tsock = socket(AF_INET, SOCK_DGRAM, 0);\n\t\n\tsaout.sin_family = sain.sin_family = AF_INET;\n\tsaout.sin_port = sain.sin_port = htons(port);\n\tsain.sin_addr.s_addr = INADDR_ANY;\n\t\n\tbind(sock, (struct sockaddr *)&sain, sizeof(sain));\n\t\n\tfcntl(sock, F_SETFL, O_NONBLOCK);\n\t\n\treturn true;\n}\n\nvoid sendBuf(int length) {\n\tsendto(sock, (char *)&outBuf, length, 0, (struct sockaddr *)&saout, sizeof(saout));\n}\n\nint receiveBuffer(int length) {\n\treturn recvfrom(sock, (char *)&rcvBuf, length, 0, (struct sockaddr *)&sain, &sockaddr_in_sizePtr);\n}\n\nvoid sendConnectionRequest(void) {\n\toutBuf.command = CONNECT;\n\toutBuf.keyboardActive = keyboardActive;\n\tsendBuf(offsetof(struct packet, connectPacket) + sizeof(struct connectPacket));\n}\n\nvoid sendKeys(unsigned int keys, circlePosition circlePad, touchPosition touch, circlePosition cStick) {\n\toutBuf.command = KEYS;\n\toutBuf.keyboardActive = keyboardActive;\n\tmemcpy(&outBuf.keys, &keys, 4);\n\tmemcpy(&outBuf.circlePad, &circlePad, 4);\n\tmemcpy(&outBuf.touch, &touch, 4);\n\tmemcpy(&outBuf.cStick, &cStick, 4);\n\tsendBuf(offsetof(struct packet, keysPacket) + sizeof(struct keysPacket));\n}\n"
  },
  {
    "path": "Linux/3DSController.py",
    "content": "#!/usr/bin/env python\n# Compatible with both Python 2.7.6 and 3.4.3\n\nfrom __future__ import print_function\nimport socket, struct, time\nimport Xlib, Xlib.display, Xlib.XK\nLMouse = []; RMouse = []\nButton = []; MouseAbs = []; MouseRel = []; MouseAbsClick = []; MouseRelClick = []\n\n##########################################################\n# CONFIGURABLE REGION START - Don't touch anything above #\n##########################################################\nport = 8889\n\n#This tells what the touch screen does if touched.\n#Valid values: Button, MouseAbs, MouseRel, MouseRelClick, MouseRelClick\n#Button sends the Tap button.\n#MouseAbs moves your mouse to the same part of the screen as the touch screen was touched.\n#MouseRel moves your mouse by the same distance as you drag across the touch screen.\n#MouseAbsClick and MouseRelClick send the primary mouse button event if the screen is tapped, not held.\ntouch = MouseRelClick\n\nmouse_speed = 4\n# The number of pixels on each side of the 3DS screen which are ignored, since you can't reach the outermost corners.\nabs_deadzone = 10\n\n#Valid values can be found in any of these locations on your Linux system (some may not exist):\n# /usr/include/X11/keysymdef.h\n# /usr/lib/python3/dist-packages/Xlib/keysymdef/\n# /usr/lib/python2.7/dist-packages/Xlib/keysymdef/\n#Additionally, LMouse and RMouse can also be used on any button.\nbtn_map = {\n\t\"A\": \"A\",\n\t\"B\": \"B\",\n\t\"X\": \"X\",\n\t\"Y\": \"Y\",\n\t\"L\": \"L\",\n\t\"R\": \"R\",\n\t\"ZL\": \"Q\",\n\t\"ZR\": \"W\",\n\t\"Left\": Xlib.XK.XK_Left,\n\t\"Right\": Xlib.XK.XK_Right,\n\t\"Up\": Xlib.XK.XK_Up,\n\t\"Down\": Xlib.XK.XK_Down,\n\t\"Start\": Xlib.XK.XK_Return,\n\t\"Select\": Xlib.XK.XK_BackSpace,\n\t\"Tap\": LMouse,\n}\n########################################################\n# CONFIGURABLE REGION END - Don't touch anything below #\n########################################################\n\ndef pprint(obj):\n\timport pprint\n\tpprint.PrettyPrinter().pprint(obj)\n\nclass x: pass\n\ncommand = x()\ncommand.CONNECT = 0\ncommand.KEYS = 1\ncommand.SCREENSHOT = 2\n\nkeynames = [\n\t\"A\", \"B\", \"Select\", \"Start\", \"Right\", \"Left\", \"Up\", \"Down\",\n\t\"R\", \"L\", \"X\", \"Y\", None, None, \"ZL\", \"ZR\",\n\tNone, None, None, None, \"Tap\", None, None, None,\n\t\"CSRight\", \"CSLeft\", \"CSUp\", \"CSDown\", \"CRight\", \"CLeft\", \"CUp\", \"CDown\",\n]\n\nkeys = x()\nkeys.A       = 1<<0\nkeys.B       = 1<<1\nkeys.Select  = 1<<2\nkeys.Start   = 1<<3\nkeys.Right   = 1<<4\nkeys.Left    = 1<<5\nkeys.Up      = 1<<6\nkeys.Down    = 1<<7\nkeys.R       = 1<<8\nkeys.L       = 1<<9\nkeys.X       = 1<<10\nkeys.Y       = 1<<11\nkeys.ZL      = 1<<14 # (new 3DS only)\nkeys.ZR      = 1<<15 # (new 3DS only)\nkeys.Tap     = 1<<20 # Not actually provided by HID\nkeys.CSRight = 1<<24 # c-stick (new 3DS only)\nkeys.CSLeft  = 1<<25 # c-stick (new 3DS only)\nkeys.CSUp    = 1<<26 # c-stick (new 3DS only)\nkeys.CSDown  = 1<<27 # c-stick (new 3DS only)\nkeys.CRight  = 1<<28 # circle pad\nkeys.CLeft   = 1<<29 # circle pad\nkeys.CUp     = 1<<30 # circle pad\nkeys.CDown   = 1<<31 # circle pad\n\ndef currentKeyboardKey(x, y):\n\tchars = (\"!1234567890\\x08\"+\n\t         \"QWERTYUIOP\\13\\13\"+\n\t         \"ASDFGHJKL-\\13\\13\"+\n\t         \"ZXCVBNM,.?\\13\\13\"+\n\t         \"\\0\\0\\0     \\0\\0\\0\\0\")\n\t\n\tif x>=1 and x<=312 and y>=78 and y<=208:\n\t\txi = int(x*12/320)\n\t\tyi = int((y-78)*12/320)\n\t\treturn chars[yi*12 + xi]\n\telse: return None\n\ndef key_to_keysym(key):\n\tif not key: return 0\n\t\n\tif isinstance(key,str):\n\t\tif key==\"\\x08\": return Xlib.XK.XK_BackSpace\n\t\tif key==\"\\13\": return Xlib.XK.XK_Return\n\t\tif key==\" \": return Xlib.XK.XK_space\n\t\treturn Xlib.XK.string_to_keysym(key)\n\t\n\treturn key\n\ndef action_key(key, action):\n\tx_action = Xlib.X.ButtonRelease\n\tx_action2 = Xlib.X.KeyRelease\n\tif action:\n\t\tx_action = Xlib.X.ButtonPress\n\t\tx_action2 = Xlib.X.KeyPress\n    \n\tif key is LMouse or key is RMouse:\n\t\tif key is LMouse: button = 1\n\t\tif key is RMouse: button = 3\n\t\tbutton = disp.get_pointer_mapping()[button-1] # account for left-handed mice\n\t\tdisp.xtest_fake_input(x_action, button)\n\t\tdisp.sync()\n\t\treturn\n\t\n\tkeysym = key_to_keysym(key)\n\tif not keysym: return\n\t\n\tkeycode = disp.keysym_to_keycode(keysym)\n\tdisp.xtest_fake_input(x_action2, keycode)\n\tdisp.sync()\n\t\ndef press_key(key):\n\taction_key(key,True)\n        \ndef release_key(key):\n\taction_key(key,False)\n\ndef move_mouse(x,y):\n\tx=int(x)\n\ty=int(y)\n\tif not x and not y: return\n\t\n\tdisp.warp_pointer(x,y)\n\tdisp.sync()\n\ndef move_mouse_abs_frac(x,y):\n\troot = disp.screen().root\n\tgeom = root.get_geometry()\n\t\n\troot.warp_pointer(int(x*geom.width), int(y*geom.height))\n\tdisp.sync()\n\ndisp = Xlib.display.Display()\n\ntouch_click = (touch is MouseAbsClick or touch is MouseRelClick)\nif touch is MouseAbsClick: touch = MouseAbs\nif touch is MouseRelClick: touch = MouseRel\n\nif touch is MouseAbs and disp.screen_count()!=1:\n\tprint(\"Sorry, but MouseAbs only supports a single monitor. I'll use MouseRel instead.\")\n\ttouch = MouseRel\n\nsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\nsock.bind((\"\", port))\n\nprevkeys = 0\n\ntouch_start = 0\ntouch_last_x = 0\ntouch_last_y = 0\nkeyboard_prevkey = currentKeyboardKey(0, 0)\n\nwhile True:\n\trawdata, addr = sock.recvfrom(4096)\n\trawdata = bytearray(rawdata)\n\t#print(\"received message\", rawdata, \"from\", addr)\n\t\n\tif rawdata[0]==command.CONNECT:\n\t\tpass # CONNECT packets are empty\n\t\n\tif rawdata[0]==command.KEYS:\n\t\tfields = struct.unpack(\"<BBxxIhhHHhh\", rawdata)\n\t\t\n\t\tdata = {\n\t\t\t\"command\": fields[0],\n\t\t\t\"keyboardActive\": fields[1],\n\t\t\t\"keys\": fields[2],\n\t\t\t\"circleX\": fields[3],\n\t\t\t\"circleY\": fields[4],\n\t\t\t\"touchX\": fields[5],\n\t\t\t\"touchY\": fields[6],\n\t\t\t\"cstickX\": fields[7],\n\t\t\t\"cstickY\": fields[8],\n\t\t}\n\t\t#print(data)\n\t\t\n\t\tnewkeys = data[\"keys\"] & ~prevkeys\n\t\toldkeys = ~data[\"keys\"] & prevkeys\n\t\tprevkeys = data[\"keys\"]\n\t\t\n\t\tfor btnid in range(16):\n\t\t\tif newkeys & (1<<btnid):\n\t\t\t\tpress_key(btn_map[keynames[btnid]])\n\t\t\tif oldkeys & (1<<btnid):\n\t\t\t\trelease_key(btn_map[keynames[btnid]])\n\t\tif newkeys & keys.Tap:\n\t\t\tif data[\"keyboardActive\"]:\n\t\t\t\tkeyboard_prevkey = currentKeyboardKey(data[\"touchX\"], data[\"touchY\"])\n\t\t\t\tpress_key(keyboard_prevkey)\n\t\t\telif touch is Button:\n\t\t\t\tpress_key(btn_map[\"Tap\"])\n\t\t\ttouch_start = time.time()\n\t\tif prevkeys & keys.Tap:\n\t\t\tif data[\"keyboardActive\"] & (keyboard_prevkey != currentKeyboardKey(data[\"touchX\"], data[\"touchY\"])):\n\t\t\t\trelease_key(keyboard_prevkey)\n\t\t\t\tkeyboard_prevkey = currentKeyboardKey(data[\"touchX\"], data[\"touchY\"])\n\t\t\t\tpress_key(keyboard_prevkey)\n\t\tif oldkeys & keys.Tap:\n\t\t\tif data[\"keyboardActive\"]:\n\t\t\t\trelease_key(keyboard_prevkey)\n\t\t\telif touch is Button:\n\t\t\t\trelease_key(btn_map[\"Tap\"])\n\t\tif data[\"keys\"] & keys.Tap:\n\t\t\tif touch is MouseAbs:\n\t\t\t\tx = (data[\"touchX\"]-abs_deadzone) / (320.0-abs_deadzone*2)\n\t\t\t\ty = (data[\"touchY\"]-abs_deadzone) / (240.0-abs_deadzone*2)\n\t\t\t\tmove_mouse_abs_frac(x, y)\n\t\t\tif touch is MouseRel and not newkeys & keys.Tap:\n\t\t\t\tx = (data[\"touchX\"]-touch_last_x) * mouse_speed\n\t\t\t\ty = (data[\"touchY\"]-touch_last_y) * mouse_speed\n\t\t\t\tmove_mouse(x, y)\n\t\t\ttouch_last_x = data[\"touchX\"]\n\t\t\ttouch_last_y = data[\"touchY\"]\n\t\t\n\t\tif oldkeys & keys.Tap and touch_click and time.time()-touch_start < 0.1:\n\t\t\tpress_key(LMouse)\n\t\t\trelease_key(LMouse)\n\t\t\n\t\tif abs(data[\"circleX\"])>=16 or abs(data[\"circleY\"])>=16:\n\t\t\tmove_mouse(data[\"circleX\"]*mouse_speed/32.0, -data[\"circleY\"]*mouse_speed/32.0)\n\t\n\tif rawdata[0]==command.SCREENSHOT:\n\t\tpass # unused by both 3DS and PC applications\n"
  },
  {
    "path": "Linux/3DSController_gamepad.py",
    "content": "#!/usr/bin/env python\n# Compatible with both Python 2.7.6 and 3.4.3\n\nfrom __future__ import print_function\nimport socket, struct, time\nimport uinput\n\n##########################################################\n# CONFIGURABLE REGION START - Don't touch anything above #\n##########################################################\nport = 8889\n\n#Valid values can be found in any of these locations on your Linux system (some may not exist):\n# /usr/include/linux/input-event-codes.h\n#The virtual device is defined on the device variable and the mapping of the keys on btn_map\n#RECAP keynames (DO NOT TOUCH) are the keys that we expect commming from the 3ds, device is\n#the virtual device that we define and btn_map maps what we recieve with our virtual device\nbtn_map = {\n\t\"A\": uinput.BTN_A,\n\t\"B\": uinput.BTN_B,\n\t\"X\": uinput.BTN_X,\n\t\"Y\": uinput.BTN_Y,\n\t\"L\": uinput.BTN_TL,\n\t\"R\": uinput.BTN_TR,\n\t\"ZL\": uinput.BTN_THUMBL,\n\t\"ZR\": uinput.BTN_THUMBR,\n\t\"Left\": uinput.BTN_DPAD_LEFT,\n\t\"Right\": uinput.BTN_DPAD_RIGHT,\n\t\"Up\": uinput.BTN_DPAD_UP,\n\t\"Down\": uinput.BTN_DPAD_DOWN,\n\t\"Start\": uinput.BTN_START,\n\t\"Select\": uinput.BTN_SELECT,\n\t\"Tap\": uinput.BTN_MODE,\n}\n\ndevice = uinput.Device([\n\tuinput.ABS_X + (-159, 159, 0, 10),\n\tuinput.ABS_Y + (-159, 159, 0, 10),\n\tuinput.ABS_RX + (-146, 146, 0, 16),\n\tuinput.ABS_RY + (-146, 146, 0, 16),\n\tuinput.BTN_A,\n\tuinput.BTN_B,\n\tuinput.BTN_X,\n\tuinput.BTN_Y,\n\tuinput.BTN_TL,\n\tuinput.BTN_TR,\n\tuinput.BTN_THUMBL,\n\tuinput.BTN_THUMBR,\n\tuinput.BTN_DPAD_LEFT,\n\tuinput.BTN_DPAD_RIGHT,\n\tuinput.BTN_DPAD_UP,\n\tuinput.BTN_DPAD_DOWN,\n\tuinput.BTN_START,\n\tuinput.BTN_SELECT,\n\tuinput.BTN_MODE,\n\t])\n########################################################\n# CONFIGURABLE REGION END - Don't touch anything below #\n########################################################\n\ndef pprint(obj):\n\timport pprint\n\tpprint.PrettyPrinter().pprint(obj)\n\nclass x: pass\n\ncommand = x()\ncommand.CONNECT = 0\ncommand.KEYS = 1\ncommand.SCREENSHOT = 2\n\nkeynames = [\n\t\"A\", \"B\", \"Select\", \"Start\", \"Right\", \"Left\", \"Up\", \"Down\",\n\t\"R\", \"L\", \"X\", \"Y\", None, None, \"ZL\", \"ZR\",\n\tNone, None, None, None, \"Tap\", None, None, None,\n\t\"CSRight\", \"CSLeft\", \"CSUp\", \"CSDown\", \"CRight\", \"CLeft\", \"CUp\", \"CDown\",\n]\n\nkeys = x()\nkeys.A       = 1<<0\nkeys.B       = 1<<1\nkeys.Select  = 1<<2\nkeys.Start   = 1<<3\nkeys.Right   = 1<<4\nkeys.Left    = 1<<5\nkeys.Up      = 1<<6\nkeys.Down    = 1<<7\nkeys.R       = 1<<8\nkeys.L       = 1<<9\nkeys.X       = 1<<10\nkeys.Y       = 1<<11\nkeys.ZL      = 1<<14 # (new 3DS only)\nkeys.ZR      = 1<<15 # (new 3DS only)\nkeys.Tap     = 1<<20 # Not actually provided by HID\nkeys.CSRight = 1<<24 # c-stick (new 3DS only)\nkeys.CSLeft  = 1<<25 # c-stick (new 3DS only)\nkeys.CSUp    = 1<<26 # c-stick (new 3DS only)\nkeys.CSDown  = 1<<27 # c-stick (new 3DS only)\nkeys.CRight  = 1<<28 # circle pad\nkeys.CLeft   = 1<<29 # circle pad\nkeys.CUp     = 1<<30 # circle pad\nkeys.CDown   = 1<<31 # circle pad\n\t\ndef press_key(key):\n\tdevice.emit(key, 1)\n        \ndef release_key(key):\n\tdevice.emit(key,0)\n\nsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)\nsock.bind((\"\", port))\n\nprevkeys = 0\n\ntouch_start = 0\ntouch_last_x = 0\ntouch_last_y = 0\n\nwhile True:\n\trawdata, addr = sock.recvfrom(4096)\n\trawdata = bytearray(rawdata)\n\t#print(\"received message\", rawdata, \"from\", addr)\n\t\n\tif rawdata[0]==command.CONNECT:\n\t\tpass # CONNECT packets are empty\n\t\n\tif rawdata[0]==command.KEYS:\n\t\tfields = struct.unpack(\"<BBxxIhhHHhh\", rawdata)\n\t\t\n\t\tdata = {\n\t\t\t\"command\": fields[0],\n\t\t\t\"keyboardActive\": fields[1],\n\t\t\t\"keys\": fields[2],\n\t\t\t\"circleX\": fields[3],\n\t\t\t\"circleY\": fields[4],\n\t\t\t\"touchX\": fields[5],\n\t\t\t\"touchY\": fields[6],\n\t\t\t\"cstickX\": fields[7],\n\t\t\t\"cstickY\": fields[8],\n\t\t}\n\t\t\n\t\tnewkeys = data[\"keys\"] & ~prevkeys\n\t\toldkeys = ~data[\"keys\"] & prevkeys\n\t\tprevkeys = data[\"keys\"]\n\t\t\n\t\tfor btnid in range(16):\n\t\t\tif newkeys & (1<<btnid):\n\t\t\t\tpress_key(btn_map[keynames[btnid]])\n\t\t\tif oldkeys & (1<<btnid):\n\t\t\t\trelease_key(btn_map[keynames[btnid]])\n\t\tif newkeys & keys.Tap:\n\t\t\tpress_key(btn_map[\"Tap\"])\n\t\tif oldkeys & keys.Tap:\n\t\t\trelease_key(btn_map[\"Tap\"])\n\n\t\tdevice.emit(uinput.ABS_X, data[\"circleX\"], syn=False)\n\t\tdevice.emit(uinput.ABS_Y, 0-data[\"circleY\"])\n\t\tdevice.emit(uinput.ABS_RX, data[\"cstickX\"], syn=False)\n\t\tdevice.emit(uinput.ABS_RY, data[\"cstickY\"])\n\t\n\tif rawdata[0]==command.SCREENSHOT:\n\t\tpass # unused by both 3DS and PC applications\n"
  },
  {
    "path": "PC/3DSController.ini",
    "content": "Default port is 8889, if you change this, you must change it in the 3DS's 3DSController.ini as well,\n\nCircle Pad, C Stick and Touch can be MOUSE, JOYSTICK1 or JOYSTICK2\nJOYSTICK1 uses X and Y. JOYSTICK2 uses Rx and Ry. These are 0, 1, 3 and 4 respectively, leaving 2 and 5 unused.\n\nMouse 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,\n\nButtons 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).\n\nIf you want to use JOY9 through JOY16 you need to reconfigure vJoy. Search for vJoyConf in your start menu and set buttons to 16.\n\nAlternatively, you can disable a key by binding it to NONE,\n\nThrottle 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,\n\nMake sure to use a single space, not a tab for seperating settings,\n\n\n\n\nPort: 8889\nThrottle: 20\nCircle Pad: JOYSTICK1\nC Stick: JOYSTICK2\nTouch: MOUSE\nMouse Speed: 0\n\nA: A\nB: B\nX: X\nY: Y\nL: L\nR: R\nZL: Q\nZR: W\nLeft: LEFT\nRight: RIGHT\nUp: UP\nDown: DOWN\nStart: ENTER\nSelect: BACKSPACE\nTap: SPACE"
  },
  {
    "path": "PC/Makefile",
    "content": "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 -Wall\nLFLAGS\t:=\t$(LDIR)/vJoyInterface.lib -lws2_32 -lGdi32 -lgdiplus -static-libgcc\nCFILES\t:=\t$(wildcard $(SDIR)/*.c)\nOBJS\t:=\t$(patsubst $(SDIR)/%.c, $(ODIR)/%.o, $(wildcard $(SDIR)/*.c))\n\nPLATFORM = $(shell uname)\n\nifeq ($(findstring Linux,$(PLATFORM)),Linux)\n\tTARGET=3DSController\nendif\n\nifeq ($(findstring Darwin,$(PLATFORM)),Darwin)\n\tTARGET=3DSController\nendif\n\nifeq ($(findstring MINGW,$(PLATFORM)),MINGW)\n\tTARGET=3DSController.exe\nendif\n\n$(TARGET): $(ODIR) $(OBJS)\n\t$(LN) $(ODIR)/*.o -o $(TARGET) $(CFLAGS) $(LFLAGS)\n\n$(ODIR)/%.o: $(SDIR)/%.c\n\t$(CC) -c -o $@ $< $(CFLAGS) \n\n$(ODIR):\n\t@mkdir $@\n\n.PHONY: clean\n\nclean:\n\trm -f $(TARGET) $(ODIR)/*.o\n"
  },
  {
    "path": "PC/include/general.h",
    "content": "#pragma once\n\n#include <stdio.h>\n\nvoid error(const char *functionName);\n"
  },
  {
    "path": "PC/include/joystick.h",
    "content": "#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 \"vjoyinterface.h\"\n\n#define joyX iReport.wAxisX\n#define joyY iReport.wAxisY\n#define joyRX iReport.wAxisXRot\n#define joyRY iReport.wAxisYRot\n#define joyButtons iReport.lButtons\n\n#define JOY_MIDDLE (128 * 128)\n\nextern int ContPovNumber;\nextern UINT iInterface;\n//extern BOOL ContinuousPOV;\n\nextern JOYSTICK_POSITION iReport;\n\nBOOL updateJoystick(void);\n"
  },
  {
    "path": "PC/include/keyboard.h",
    "content": "#pragma once\n\nextern unsigned char keyboardActive;\nextern unsigned char keyboardToggle;\n\ninline char currentKeyboardKey(void);\n"
  },
  {
    "path": "PC/include/keys.h",
    "content": "#pragma once\n\n#include <windows.h>\n#include <winable.h>\n#include <winuser.h>\n\n// For some reason, these are not defined in winuser.h like they used to be...\n#ifndef VK_OEM_MINUS\n#define VK_OEM_MINUS 0xBD\n#endif\n#ifndef VK_OEM_COMMA\n#define VK_OEM_COMMA 0xBC\n#endif\n#ifndef KEYEVENTF_SCANCODE\n#define KEYEVENTF_SCANCODE 0x08\n#endif\n\n#ifndef MAPVK_VK_TO_VSC\n#define MAPVK_VK_TO_VSC 0\n#endif\n\n#define newpress(key) ((currentKeys & key) && !(lastKeys & key))\n#define release(key) (!(currentKeys & key) && (lastKeys & key))\n\n#define handleKey(DSKey, PCKey) do {\\\n\tif(!PCKey.useJoypad) {\\\n\t\tif(newpress(DSKey)) simulateKeyNewpress(PCKey.virtualKey);\\\n\t\tif(release(DSKey)) simulateKeyRelease(PCKey.virtualKey);\\\n\t}\\\n\telse if(PCKey.useJoypad == 1) {\\\n\t\tif(currentKeys & DSKey) joyButtons |= PCKey.joypadButton;\\\n\t\telse joyButtons &= ~PCKey.joypadButton;\\\n\t}\\\n\telse if(PCKey.useJoypad == 2) {\\\n\t\tif(currentKeys & DSKey) joyButtons |= PCKey.joypadButton << 8;\\\n\t\telse joyButtons &= ~(PCKey.joypadButton << 8);\\\n\t}\\\n} while(0)\n\n#define BIT(n) (1 << (n))\n\ntypedef enum {\n\tKEY_A = BIT(0),\n\tKEY_B = BIT(1),\n\tKEY_SELECT = BIT(2),\n\tKEY_START = BIT(3),\n\tKEY_DRIGHT = BIT(4),\n\tKEY_DLEFT = BIT(5),\n\tKEY_DUP = BIT(6),\n\tKEY_DDOWN = BIT(7),\n\tKEY_R = BIT(8),\n\tKEY_L = BIT(9),\n\tKEY_X = BIT(10),\n\tKEY_Y = BIT(11),\n\tKEY_ZL = BIT(14), // (new 3DS only)\n\tKEY_ZR = BIT(15), // (new 3DS only)\n\tKEY_TOUCH = BIT(20), // Not actually provided by HID\n\tKEY_CSTICK_RIGHT = BIT(24), // c-stick (new 3DS only)\n\tKEY_CSTICK_LEFT = BIT(25), // c-stick (new 3DS only)\n\tKEY_CSTICK_UP = BIT(26), // c-stick (new 3DS only)\n\tKEY_CSTICK_DOWN = BIT(27), // c-stick (new 3DS only)\n\tKEY_CPAD_RIGHT = BIT(28), // circle pad\n\tKEY_CPAD_LEFT = BIT(29), // circle pad\n\tKEY_CPAD_UP = BIT(30), // circle pad\n\tKEY_CPAD_DOWN = BIT(31), // circle pad\n\t\n\t// Generic catch-all directions\n\tKEY_UP = KEY_DUP | KEY_CPAD_UP,\n\tKEY_DOWN = KEY_DDOWN | KEY_CPAD_DOWN,\n\tKEY_LEFT = KEY_DLEFT | KEY_CPAD_LEFT,\n\tKEY_RIGHT = KEY_DRIGHT | KEY_CPAD_RIGHT,\n} KEYPAD_BITS;\n\nstruct keyMapping {\n\tunsigned char useJoypad; // 0 keyboard key, 1 joypad1-8, 2 joypad9-16\n\tunion {\n\t\tunsigned char virtualKey;\n\t\tunsigned char joypadButton;\n\t};\n};\n\nstruct circlePad {\n\tshort x;\n\tshort y;\n};\n\nstruct cStick {\n\tshort x;\n\tshort y;\n};\n\nstruct touch {\n\tshort x;\n\tshort y;\n};\n\nextern unsigned int lastKeys;\nextern unsigned int currentKeys;\n\nextern struct circlePad circlePad;\nextern struct cStick cStick;\nextern struct touch lastTouch;\nextern struct touch currentTouch;\n\ninline unsigned int mapVirtualKey(unsigned int key);\nvoid simulateKeyNewpress(unsigned int key);\nvoid simulateKeyRelease(unsigned int key);\n"
  },
  {
    "path": "PC/include/public.h",
    "content": "/*++\n\nCopyright (c) Shaul Eizikovich.  All rights reserved.\n\n    THIS CODE AND INFORMATION IS PROVIDED \"AS IS\" WITHOUT WARRANTY OF ANY\n    KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\n    IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR\n    PURPOSE.\n\nModule Name:\n\n    public.h\n    \nAbstract:\n\n    Public header file for the vJoy project\n\tDeveloppers that need to interface with vJoy need to include this file\n\nAuthor:\n\n\nEnvironment:\n\n    kernel mode and User mode\n\nNotes:\n\n\nRevision History:\n\n\n--*/\n#ifndef _PUBLIC_H\n#define _PUBLIC_H\n\n// Compilation directives\n#define PPJOY_MODE\n#undef PPJOY_MODE\t// Comment-out for compatibility mode\n\n#ifdef PPJOY_MODE\n#include \"PPJIoctl.h\"\n#endif\n\n#include <INITGUID.H>\t// Definitions for controlling GUID initialization\n\n//\n// Usage example:\n//\t\tCreateFile(TEXT(\"\\\\\\\\.\\\\vJoy\"), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);\n#ifdef PPJOY_MODE\n#define DEVICENAME_STRING\t\t\t\"PPJoyIOCTL1\"\n#else\n#define DEVICENAME_STRING\t\t\t\"vJoy\"\n#endif\n#define NTDEVICE_NAME_STRING\t\t\"\\\\Device\\\\\"DEVICENAME_STRING\n#define SYMBOLIC_NAME_STRING\t\t\"\\\\DosDevices\\\\\"DEVICENAME_STRING\n#define\tDOS_FILE_NAME\t\t\t\t\"\\\\\\\\.\\\\\"DEVICENAME_STRING\n#define VJOY_INTERFACE\t\t\t\tL\"Device_\"\n\n// Version parts\n#define VER_X_\t0\n#define VER_H_\t2\n#define VER_M_\t0\n#define VER_L_\t5\n\n#define STRINGIFY_1(x)   #x\n#define STRINGIFY(x)     STRINGIFY_1(x)\n#define PASTE(x, y) x##y\n#define MAKEWIDE(x) PASTE(L,x)\n\n// Device Attributes\n//\n#define VENDOR_N_ID\t\t0x1234\n#define\tPRODUCT_N_ID\t0xBEAD\n#define\tVERSION_N\t(VER_L_ + 0x10*VER_M_ + 0x100*VER_H_ + 0x1000*VER_X_)\n\n// Device Strings\n//\n#define VENDOR_STR_ID\t\tL\"Shaul Eizikovich\"\n#define PRODUCT_STR_ID\t\tL\"vJoy - Virtual Joystick\"\n#define\tSERIALNUMBER_STR\tMAKEWIDE(STRINGIFY(VER_H_)) L\".\" MAKEWIDE(STRINGIFY(VER_M_)) L\".\"  MAKEWIDE(STRINGIFY(VER_L_))\n\n// Function codes;\n//#define LOAD_POSITIONS\t0x910\n//#define GETATTRIB\t\t0x911\n// #define GET_FFB_DATA\t0x00222912\t// METHOD_OUT_DIRECT + FILE_DEVICE_UNKNOWN\t+ FILE_ANY_ACCESS\n//#define SET_FFB_STAT\t0x913\t // METHOD_NEITHER\n//#define GET_FFB_STAT\t0x916\n\n#define F_LOAD_POSITIONS\t0x910\n#define F_GETATTRIB\t\t\t0x911\n#define F_GET_FFB_DATA\t\t0x912\n#define F_SET_FFB_STAT\t\t0x913\n#define F_GET_FFB_STAT\t\t0x916\n#define F_GET_DEV_INFO      0x917\n// IO Device Control codes;\n#define IOCTL_VJOY_GET_ATTRIB\t\tCTL_CODE (FILE_DEVICE_UNKNOWN, GETATTRIB, METHOD_BUFFERED, FILE_WRITE_ACCESS)\n#define LOAD_POSITIONS\t            CTL_CODE (FILE_DEVICE_UNKNOWN, F_LOAD_POSITIONS, METHOD_BUFFERED, FILE_WRITE_ACCESS)\n#define GET_FFB_DATA\t            CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_FFB_DATA, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)\n#define SET_FFB_STAT\t            CTL_CODE (FILE_DEVICE_UNKNOWN, F_SET_FFB_STAT, METHOD_NEITHER, FILE_ANY_ACCESS)\n#define GET_FFB_STAT\t            CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_FFB_STAT, METHOD_BUFFERED, FILE_ANY_ACCESS)\n#define GET_DEV_INFO\t\t\t    CTL_CODE (FILE_DEVICE_UNKNOWN, F_GET_DEV_INFO, METHOD_BUFFERED, FILE_ANY_ACCESS)\n\n#ifndef __HIDPORT_H__\n// Copied from hidport.h\n#define IOCTL_HID_SET_FEATURE\t0xB0191\n#define IOCTL_HID_WRITE_REPORT\t0xB000F\n\n#define MAX_N_DEVICES\t16 // Maximum number of vJoy devices\n\n\ntypedef struct _HID_DEVICE_ATTRIBUTES {\n\n    ULONG           Size;\n    //\n    // sizeof (struct _HID_DEVICE_ATTRIBUTES)\n    //\n\n    //\n    // Vendor ids of this hid device\n    //\n    USHORT          VendorID;\n    USHORT          ProductID;\n    USHORT          VersionNumber;\n    USHORT          Reserved[11];\n\n} HID_DEVICE_ATTRIBUTES, * PHID_DEVICE_ATTRIBUTES;\n#endif\n\n// Error levels for status report\nenum ERRLEVEL {INFO, WARN, ERR, FATAL, APP};\n// Status report function prototype\n#ifdef WINAPI\ntypedef BOOL (WINAPI *StatusMessageFunc)(void * output, TCHAR * buffer, enum ERRLEVEL level);\n#endif\n\n///////////////////////////////////////////////////////////////\n\n/////////////////////// Joystick Position ///////////////////////\n//\n// This structure holds data that is passed to the device from\n// an external application such as SmartPropoPlus.\n//\n// Usage example:\n//\tJOYSTICK_POSITION iReport;\n//\t:\n//\tDeviceIoControl (hDevice, 100, &iReport, sizeof(HID_INPUT_REPORT), NULL, 0, &bytes, NULL)\ntypedef struct _JOYSTICK_POSITION\n{\n\tBYTE\tbDevice;\t// Index of device. 1-based.\n\tLONG\twThrottle;\n\tLONG\twRudder;\n\tLONG\twAileron;\n\tLONG\twAxisX;\n\tLONG\twAxisY;\n\tLONG\twAxisZ;\n\tLONG\twAxisXRot;\n\tLONG\twAxisYRot;\n\tLONG\twAxisZRot;\n\tLONG\twSlider;\n\tLONG\twDial;\n\tLONG\twWheel;\n\tLONG\twAxisVX;\n\tLONG\twAxisVY;\n\tLONG\twAxisVZ;\n\tLONG\twAxisVBRX;\n\tLONG\twAxisVBRY;\n\tLONG\twAxisVBRZ;\n\tLONG\tlButtons;\t// 32 buttons: 0x00000001 means button1 is pressed, 0x80000000 -> button32 is pressed\n\tDWORD\tbHats;\t\t// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch\n\tDWORD\tbHatsEx1;\t// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch\n\tDWORD\tbHatsEx2;\t// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch\n\tDWORD\tbHatsEx3;\t// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch\n} JOYSTICK_POSITION, *PJOYSTICK_POSITION;\n\n// Superset of JOYSTICK_POSITION\n// Extension of JOYSTICK_POSITION with Buttons 33-128 appended to the end of the structure.\ntypedef struct _JOYSTICK_POSITION_V2\n{\n\t/// JOYSTICK_POSITION\n\tBYTE\tbDevice;\t// Index of device. 1-based.\n\tLONG\twThrottle;\n\tLONG\twRudder;\n\tLONG\twAileron;\n\tLONG\twAxisX;\n\tLONG\twAxisY;\n\tLONG\twAxisZ;\n\tLONG\twAxisXRot;\n\tLONG\twAxisYRot;\n\tLONG\twAxisZRot;\n\tLONG\twSlider;\n\tLONG\twDial;\n\tLONG\twWheel;\n\tLONG\twAxisVX;\n\tLONG\twAxisVY;\n\tLONG\twAxisVZ;\n\tLONG\twAxisVBRX;\n\tLONG\twAxisVBRY;\n\tLONG\twAxisVBRZ;\n\tLONG\tlButtons;\t// 32 buttons: 0x00000001 means button1 is pressed, 0x80000000 -> button32 is pressed\n\tDWORD\tbHats;\t\t// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch\n\tDWORD\tbHatsEx1;\t// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch\n\tDWORD\tbHatsEx2;\t// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch\n\tDWORD\tbHatsEx3;\t// Lower 4 bits: HAT switch or 16-bit of continuous HAT switch LONG lButtonsEx1; // Buttons 33-64\n\t\n\t/// JOYSTICK_POSITION_V2 Extenssion\n\tLONG lButtonsEx1; // Buttons 33-64\n\tLONG lButtonsEx2; // Buttons 65-96\n\tLONG lButtonsEx3; // Buttons 97-128\n} JOYSTICK_POSITION_V2, *PJOYSTICK_POSITION_V2;\n\n\n// HID Descriptor definitions\n#define HID_USAGE_X\t\t0x30\n#define HID_USAGE_Y\t\t0x31\n#define HID_USAGE_Z\t\t0x32\n#define HID_USAGE_RX\t0x33\n#define HID_USAGE_RY\t0x34\n#define HID_USAGE_RZ\t0x35\n#define HID_USAGE_SL0\t0x36\n#define HID_USAGE_SL1\t0x37\n#define HID_USAGE_WHL\t0x38\n#define HID_USAGE_POV\t0x39\n\n\n#endif\n\n\n"
  },
  {
    "path": "PC/include/settings.h",
    "content": "#pragma once\n\n#include <stdbool.h>\n\n#include \"keys.h\"\n\nenum analogue {\n\tmouse,\n\tjoystick1,\n\tjoystick2,\n};\n\nstruct settings {\n\tint port;\n\tint throttle;\n\tenum analogue circlePad;\n\tenum analogue cStick;\n\tenum analogue touch;\n\tint mouseSpeed;\n\tstruct keyMapping A, B, X, Y, L, R, ZL, ZR, Left, Right, Up, Down, Start, Select, Tap;\n};\n\nextern struct settings settings;\nextern struct settings defaultSettings;\n\nbool readSettings(void);\n"
  },
  {
    "path": "PC/include/vjoyinterface.h",
    "content": "// The following ifdef block is the standard way of creating macros which make exporting \n// from a DLL simpler. All files within this DLL are compiled with the VJOYINTERFACE_EXPORTS\n// symbol defined on the command line. this symbol should not be defined on any project\n// that uses this DLL. This way any other project whose source files include this file see \n// VJOYINTERFACE_API functions as being imported from a DLL, whereas this DLL sees symbols\n// defined with this macro as being exported.\n#ifdef VJOYINTERFACE_EXPORTS\n#define VJOYINTERFACE_API __declspec(dllexport)\n#else\n#define VJOYINTERFACE_API __declspec(dllimport)\n#endif\n\n///////////////////////////// vJoy device (collection) status ////////////////////////////////////////////\n#ifndef VJDSTAT\n#define VJDSTAT\nenum VjdStat  /* Declares an enumeration data type called BOOLEAN */\n{\n\tVJD_STAT_OWN,\t// The  vJoy Device is owned by this application.\n\tVJD_STAT_FREE,\t// The  vJoy Device is NOT owned by any application (including this one).\n\tVJD_STAT_BUSY,\t// The  vJoy Device is owned by another application. It cannot be acquired by this application.\n\tVJD_STAT_MISS,\t// The  vJoy Device is missing. It either does not exist or the driver is down.\n\tVJD_STAT_UNKN\t// Unknown\n}; \n\n/* Error codes for some of the functions */\n#define NO_HANDLE_BY_INDEX\t\t\t\t -1\n#define BAD_PREPARSED_DATA\t\t\t\t -2\n#define NO_CAPS\t\t\t\t \t\t\t -3\n#define BAD_N_BTN_CAPS\t\t\t\t \t -4\n#define BAD_CALLOC\t\t\t\t \t \t -5\n#define BAD_BTN_CAPS\t\t\t\t \t -6\n#define BAD_BTN_RANGE\t\t\t\t \t -7\n#define BAD_N_VAL_CAPS\t\t\t\t \t -8\n#define BAD_ID_RANGE\t\t\t\t \t -9\n#define NO_SUCH_AXIS\t\t\t\t \t -10\n\n/* Environment Variables */\n#define INTERFACE_LOG_LEVEL \"VJOYINTERFACELOGLEVEL\"\n#define INTERFACE_LOG_FILE  \"VJOYINTERFACELOGFILE\"\n#define INTERFACE_DEF_LOG_FILE\t\"vJoyInterface.log\"\n\nstruct DEV_INFO {\n\tBYTE\tDeviceID;\t\t// Device ID: Valid values are 1-16\n\tBYTE\tnImplemented;\t// Number of implemented device: Valid values are 1-16\n\tBYTE\tisImplemented;\t// Is this device implemented?\n\tBYTE\tMaxDevices;\t\t// Maximum number of devices that may be implemented (16)\n\tBYTE\tDriverFFB;\t\t// Does this driver support FFB (False)\n\tBYTE\tDeviceFFB;\t\t// Does this device support FFB (False)\n} ;\n\ntypedef void (CALLBACK *RemovalCB)(BOOL, BOOL, PVOID);\n\n#endif\n///////////////////////////// vJoy device (collection) Control interface /////////////////////////////////\n/*\n\tThese functions allow writing feeders and other applications that interface with vJoy\n\tIt is assumed that only one vJoy top-device (= Raw PDO) exists.\n\tThis top-level device can have up to 16 siblings (=top-level Reports/collections)\n\tEach sibling is refered to as a \"vJoy Device\" and is attributed a unique Report ID (Range: 1-16).\n\n\tNaming convetion:\n\t\tVJD = vJoy Device\n\t\trID = Report ID\n*/\n\n/////\tGeneral driver data\nVJOYINTERFACE_API SHORT __cdecl GetvJoyVersion(void);\nVJOYINTERFACE_API BOOL\t__cdecl vJoyEnabled(void);\nVJOYINTERFACE_API PVOID\t__cdecl\tGetvJoyProductString(void);\nVJOYINTERFACE_API PVOID\t__cdecl\tGetvJoyManufacturerString(void);\nVJOYINTERFACE_API PVOID\t__cdecl\tGetvJoySerialNumberString(void);\nVJOYINTERFACE_API BOOL\t__cdecl\tDriverMatch(WORD * DllVer, WORD * DrvVer);\nVJOYINTERFACE_API VOID\t__cdecl\tRegisterRemovalCB(RemovalCB cb, PVOID data);\n\n\n/////\tvJoy Device properties\nVJOYINTERFACE_API int\t__cdecl  GetVJDButtonNumber(UINT rID);\t// Get the number of buttons defined in the specified VDJ\nVJOYINTERFACE_API int\t__cdecl  GetVJDDiscPovNumber(UINT rID);\t// Get the number of descrete-type POV hats defined in the specified VDJ\nVJOYINTERFACE_API int\t__cdecl  GetVJDContPovNumber(UINT rID);\t// Get the number of descrete-type POV hats defined in the specified VDJ\nVJOYINTERFACE_API BOOL\t__cdecl  GetVJDAxisExist(UINT rID, UINT Axis); // Test if given axis defined in the specified VDJ\nVJOYINTERFACE_API BOOL\t__cdecl  GetVJDAxisMax(UINT rID, UINT Axis, LONG * Max); // Get logical Maximum value for a given axis defined in the specified VDJ\nVJOYINTERFACE_API BOOL\t__cdecl  GetVJDAxisMin(UINT rID, UINT Axis, LONG * Min); // Get logical Minimum value for a given axis defined in the specified VDJ\n\n/////\tWrite access to vJoy Device - Basic\nVJOYINTERFACE_API BOOL\t\t__cdecl\tAcquireVJD(UINT rID);\t\t\t\t// Acquire the specified vJoy Device.\nVJOYINTERFACE_API VOID\t\t__cdecl\tRelinquishVJD(UINT rID);\t\t\t// Relinquish the specified vJoy Device.\nVJOYINTERFACE_API BOOL\t\t__cdecl\tUpdateVJD(UINT rID, PVOID pData);\t// Update the position data of the specified vJoy Device.\nVJOYINTERFACE_API enum VjdStat\t__cdecl\tGetVJDStatus(UINT rID);\t\t\t// Get the status of the specified vJoy Device.\n\n/////\tWrite access to vJoy Device - Modifyiers\n// This group of functions modify the current value of the position data\n// They replace the need to create a structure of position data then call UpdateVJD\n\n//// Reset functions\nVJOYINTERFACE_API BOOL\t\t__cdecl\tResetVJD(UINT rID);\t\t\t// Reset all controls to predefined values in the specified VDJ\nVJOYINTERFACE_API VOID\t\t__cdecl\tResetAll(void);\t\t\t\t// Reset all controls to predefined values in all VDJ\nVJOYINTERFACE_API BOOL\t\t__cdecl\tResetButtons(UINT rID);\t\t// Reset all buttons (To 0) in the specified VDJ\nVJOYINTERFACE_API BOOL\t\t__cdecl\tResetPovs(UINT rID);\t\t// Reset all POV Switches (To -1) in the specified VDJ\n\n// Write data\nVJOYINTERFACE_API BOOL\t\t__cdecl\tSetAxis(LONG Value, UINT rID, UINT Axis);\t\t// Write Value to a given axis defined in the specified VDJ \nVJOYINTERFACE_API BOOL\t\t__cdecl\tSetBtn(BOOL Value, UINT rID, UCHAR nBtn);\t\t// Write Value to a given button defined in the specified VDJ \nVJOYINTERFACE_API BOOL\t\t__cdecl\tSetDiscPov(int Value, UINT rID, UCHAR nPov);\t// Write Value to a given descrete POV defined in the specified VDJ \nVJOYINTERFACE_API BOOL\t\t__cdecl\tSetContPov(DWORD Value, UINT rID, UCHAR nPov);\t// Write Value to a given continuous POV defined in the specified VDJ \n"
  },
  {
    "path": "PC/include/wireless.h",
    "content": "#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.h>\n\n#define SCREENSHOT_CHUNK 4000\n\n#define IP INADDR_ANY\n\nenum NET_COMMANDS {\n\tCONNECT,\n\tKEYS,\n\tSCREENSHOT,\n};\n\n// It is deliberately set up to have an anonymous struct as well as a named struct for convenience, not a mistake!\nstruct packet {\n\tstruct packetHeader {\n\t\tunsigned char command;\n\t\tunsigned char keyboardActive;\n\t};\n\tstruct packetHeader packetHeader;\n\t\n\tunion {\n\t\t// CONNECT\n\t\tstruct connectPacket {\n\t\t};\n\t\tstruct connectPacket connectPacket;\n\t\t\n\t\t// KEYS\n\t\tstruct keysPacket {\n\t\t\tunsigned int keys;\n\t\t\t\n\t\t\tstruct {\n\t\t\t\tshort x;\n\t\t\t\tshort y;\n\t\t\t} circlePad;\n\t\t\t\n\t\t\tstruct {\n\t\t\t\tunsigned short x;\n\t\t\t\tunsigned short y;\n\t\t\t} touch;\n\t\t\t\n\t\t\tstruct {\n\t\t\t\tshort x;\n\t\t\t\tshort y;\n\t\t\t} cStick;\n\t\t};\n\t\tstruct keysPacket keysPacket;\n\t\t\n\t\t// SCREENSHOT\n\t\tstruct screenshotPacket {\n\t\t\tunsigned short offset;\n\t\t\tunsigned char data[SCREENSHOT_CHUNK];\n\t\t};\n\t\tstruct screenshotPacket screenshotPacket;\n\t};\n};\n\nextern SOCKET listener;\nextern SOCKET client;\n\nextern struct sockaddr_in client_in;\n\nextern int sockaddr_in_sizePtr;\n\nextern struct packet buffer;\nextern char hostName[80];\n\nvoid initNetwork(void);\nvoid printIPs(void);\nvoid startListening(void);\nvoid sendBuffer(int length);\nint receiveBuffer(int length);\n\nvoid sendScreenshot(void);\n"
  },
  {
    "path": "PC/source/general.c",
    "content": "#include \"wireless.h\"\n\n#include \"general.h\"\n\nvoid error(const char *functionName) {\n\tchar errorMsg[92];\n\tZeroMemory(errorMsg, 92);\n\t\n\tsprintf(errorMsg, \"Call to %s returned error %d!\", (char *)functionName, WSAGetLastError());\n\t\n\tMessageBox(NULL, errorMsg, \"socketIndication\", MB_OK);\n\t\n\tclosesocket(client);\n\tclosesocket(listener);\n\tWSACleanup();\n\t\n\texit(0);\n}\n"
  },
  {
    "path": "PC/source/joystick.c",
    "content": "#include <stdio.h>\n#include <stdbool.h>\n\n#include \"joystick.h\"\n\nint ContPovNumber;\nUINT iInterface = 1;\n//BOOL ContinuousPOV = FALSE;\n\nJOYSTICK_POSITION iReport;\n\nBOOL updateJoystick(void) {\n\tBYTE id = (BYTE)iInterface;\n\t\n\tiReport.bDevice = id;\n\t\n\tif(!UpdateVJD(iInterface, (PVOID)&iReport)) {\n\t\t/*printf(\"vJoy device %d failed - try to enable device\\n\", iInterface);\n\t\tprintf(\"PRESS ENTER TO CONTINUE\\n\");\n\t\tgetchar();\n\t\tAcquireVJD(iInterface);\n\t\tContinuousPOV = (BOOL)GetVJDContPovNumber(iInterface);*/\n\t\treturn false;\n\t}\n\t\n\treturn true;\n}\n"
  },
  {
    "path": "PC/source/keyboard.c",
    "content": "#include <stdbool.h>\n\n#include \"keys.h\"\n\n#include \"keyboard.h\"\n\nunsigned char keyboardActive = false;\nunsigned char keyboardToggle = true;\n\ninline char currentKeyboardKey(void) {\n\tconst char chars[60] = \"!1234567890\\x08QWERTYUIOP\\13\\13ASDFGHJKL-\\13\\13ZXCVBNM,.?\\13\\13\\0\\0\\0     \\0\\0\\0\\0\";\n\t\n\tif(currentTouch.x >= 1 && currentTouch.x <= 312 && currentTouch.y >= 78 && currentTouch.y <= 208) {\n\t\tint x = (int)((float)currentTouch.x * 12.0f / 320.0f);\n\t\tint y = (int)((float)(currentTouch.y - 78) * 12.0f / 320.0f);\n\t\t\n\t\treturn chars[x + y * 12];\n\t}\n\t\n\telse return 0;\n}\n"
  },
  {
    "path": "PC/source/keys.c",
    "content": "#include \"keys.h\"\n\n// Sideband comunication with vJoy Device\n//{781EF630-72B2-11d2-B852-00C04FAD5101}\nDEFINE_GUID(GUID_DEVINTERFACE_VJOY, 0x781EF630, 0x72B2, 0x11d2, 0xB8, 0x52, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x01);\n\nunsigned int lastKeys;\nunsigned int currentKeys;\n\nstruct circlePad circlePad;\nstruct cStick cStick;\nstruct touch lastTouch;\nstruct touch currentTouch;\n\ninline unsigned int mapVirtualKey(unsigned int key) {\n\treturn MapVirtualKey(key, MAPVK_VK_TO_VSC);\n}\n\nvoid simulateKeyNewpress(unsigned int key) {\n\tif(!key) return;\n\t\n\tunsigned char unshift = 0;\n\t\n\tINPUT ip = { 0 };\n\t\n\tif(key == VK_LBUTTON || key == VK_RBUTTON) {\n\t\tip.type = INPUT_MOUSE;\n\t\tip.mi.dwFlags = key == VK_LBUTTON ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN;\n\t}\n\telse {\n\t\tif(key == '!') {\n\t\t\tkey = '1';\n\t\t\tsimulateKeyNewpress(VK_SHIFT);\n\t\t\tunshift = 1;\n\t\t}\n\t\telse if(key == '?') {\n\t\t\tkey = VK_DIVIDE;\n\t\t\tsimulateKeyNewpress(VK_SHIFT);\n\t\t\tunshift = 1;\n\t\t}\n\t\t\n\t\telse if(key == '-') key = VK_OEM_MINUS;\n\t\telse if(key == ',') key = VK_OEM_COMMA;\n\t\telse if(key == '\\13') key = VK_RETURN;\n\t\t\n\t\tip.type = INPUT_KEYBOARD;\n\t\tip.ki.wScan = mapVirtualKey(key);\n\t\tip.ki.time = 0;\n\t\tip.ki.dwExtraInfo = 0;\n\t\tip.ki.wVk = 0;\n\t\tip.ki.dwFlags = KEYEVENTF_SCANCODE;\n\t}\n\t\n\tSendInput(1, &ip, sizeof(INPUT));\n\t\n\tif(unshift) simulateKeyRelease(VK_SHIFT);\n}\n\nvoid simulateKeyRelease(unsigned int key) {\n\tif(!key) return;\n\t\n\tINPUT ip = { 0 };\n\t\n\tif(key == VK_LBUTTON || key == VK_RBUTTON) {\n\t\tip.type = INPUT_MOUSE;\n\t\tip.mi.dwFlags = key == VK_LBUTTON ? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP;\n\t}\n\telse {\n\t\tip.type = INPUT_KEYBOARD;\n\t\tip.ki.wScan = mapVirtualKey(key);\n\t\tip.ki.time = 0;\n\t\tip.ki.dwExtraInfo = 0;\n\t\tip.ki.wVk = 0;\n\t\tip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;\n\t}\n\t\n\tSendInput(1, &ip, sizeof(INPUT));\n}\n"
  },
  {
    "path": "PC/source/main.c",
    "content": "// 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 \"wireless.h\"\n#include \"keys.h\"\n#include \"general.h\"\n#include \"joystick.h\"\n#include \"settings.h\"\n#include \"keyboard.h\"\n\nint WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow) {\n\tprintf(\"3DS Controller Server %.1f\\n\", VERSION);\n\t\n\tDWORD screenWidth = GetSystemMetrics(SM_CXSCREEN);\n\tDWORD screenHeight = GetSystemMetrics(SM_CYSCREEN);\n\t\n\tdouble widthMultiplier = screenWidth / 320.0;\n\tdouble heightMultiplier = screenHeight / 240.0;\n\t\n\tbool vJoy = true;\n\tUINT iInterface = 1;\n\t\n\tiReport.wAxisX = JOY_MIDDLE;\n\tiReport.wAxisY = JOY_MIDDLE;\n\tiReport.wAxisZ = JOY_MIDDLE;\n\tiReport.wAxisXRot = JOY_MIDDLE;\n\tiReport.wAxisYRot = JOY_MIDDLE;\n\tiReport.wAxisZRot = JOY_MIDDLE;\n\tiReport.wSlider = JOY_MIDDLE;\n\tiReport.wDial = JOY_MIDDLE;\n\tiReport.lButtons = 0;\n\tiReport.bHats = -1;\n\t\n\tif(vJoy && !vJoyEnabled()) {\n\t\tprintf(\"vJoy failed (1)! Buttons will still work, but joy stick won't work.\\n\");\n\t\tvJoy = false;\n\t}\n\t\n\tenum VjdStat status = GetVJDStatus(iInterface);\n\tif(vJoy && (status == VJD_STAT_OWN || (status == VJD_STAT_FREE && !AcquireVJD(iInterface)))) {\n\t\tprintf(\"vJoy failed (2)! Buttons will still work, but joy stick won't work.\\n\");\n\t\tvJoy = false;\n\t}\n\t\n\tContPovNumber = GetVJDContPovNumber(iInterface);\n\t//int DiscPovNumber = GetVJDDiscPovNumber(iInterface);\n\t\n\tif(vJoy && !updateJoystick()) {\n\t\tprintf(\"vJoy failed (3)! Buttons will still work, but joystick won't work.\\n\");\n\t\tvJoy = false;\n\t}\n\t\n\tif(!readSettings()) {\n\t\tprintf(\"Couldn't read settings file, using default key bindings.\\n\");\n\t}\n\t\n\tinitNetwork();\n\t\n\tchar nButtons = GetVJDButtonNumber(iInterface);\n\tif(nButtons <16) printf(\"Your vJoy has less than 16 buttons (8 by default), some may not work!\\n\");\n\t\n\tprintf(\"Port: %d\\n\", settings.port);\n\t\n\tprintf(\"Running on: %s\\n\", hostName);\n\t\n\tprintf(\"Your local IP(s):\\n\");\n\tprintIPs();\n\t\n\tprintf(\"\\n\");\n\t\n\tstartListening();\n\t\n\twhile(1) {\n\t\tmemset(&buffer, 0, sizeof(struct packet));\n\t\t\n\t\twhile(receiveBuffer(sizeof(struct packet)) <= 0) {\n\t\t\t// Waiting\n\t\t\t\n\t\t\tSleep(settings.throttle);\n\t\t}\n\t\t\n\t\tkeyboardActive = buffer.keyboardActive;\n\t\t\n\t\tswitch(buffer.command) {\n\t\t\tcase CONNECT:\n\t\t\t\tlastKeys = 0;\n\t\t\t\tcurrentKeys = 0;\n\t\t\t\tcirclePad.x = 0;\n\t\t\t\tcirclePad.y = 0;\n\t\t\t\tlastTouch.x = 0;\n\t\t\t\tlastTouch.y = 0;\n\t\t\t\tcurrentTouch.x = 0;\n\t\t\t\tcurrentTouch.y = 0;\n\t\t\t\tcStick.x = 0;\n\t\t\t\tcStick.y = 0;\n\t\t\t\t\n\t\t\t\tbuffer.command = CONNECT;\n\t\t\t\tprintf(\"3DS Connected!\\n\");\n\t\t\t\t\n\t\t\t\tSleep(50);\n\t\t\t\tsendBuffer(1);\n\t\t\t\t\n\t\t\t\tSleep(50);\n\t\t\t\tsendBuffer(1);\n\t\t\t\t\n\t\t\t\tSleep(50);\n\t\t\t\tsendBuffer(1);\n\t\t\t\tbreak;\n\t\t\t\n\t\t\tcase KEYS:\n\t\t\t\tlastKeys = currentKeys;\n\t\t\t\tif(currentKeys & KEY_TOUCH) lastTouch = currentTouch;\n\t\t\t\t\n\t\t\t\tmemcpy(&currentKeys, &buffer.keys, 4);\n\t\t\t\tmemcpy(&circlePad, &buffer.circlePad, 4);\n\t\t\t\tmemcpy(&currentTouch, &buffer.touch, 4);\n\t\t\t\tmemcpy(&cStick, &buffer.cStick, 4);\n\t\t\t\t\n\t\t\t\thandleKey(KEY_A, settings.A);\n\t\t\t\thandleKey(KEY_B, settings.B);\n\t\t\t\thandleKey(KEY_SELECT, settings.Select);\n\t\t\t\thandleKey(KEY_START, settings.Start);\n\t\t\t\thandleKey(KEY_DRIGHT, settings.Right);\n\t\t\t\thandleKey(KEY_DLEFT, settings.Left);\n\t\t\t\thandleKey(KEY_DUP, settings.Up);\n\t\t\t\thandleKey(KEY_DDOWN, settings.Down);\n\t\t\t\thandleKey(KEY_R, settings.R);\n\t\t\t\thandleKey(KEY_L, settings.L);\n\t\t\t\thandleKey(KEY_ZR, settings.ZR);\n\t\t\t\thandleKey(KEY_ZL, settings.ZL);\n\t\t\t\thandleKey(KEY_X, settings.X);\n\t\t\t\thandleKey(KEY_Y, settings.Y);\n\t\t\t\t\n\t\t\t\t//handleKey(KEY_LID, 'I');\n\t\t\t\t\n\t\t\t\tif(newpress(KEY_TOUCH)) {\n\t\t\t\t\tlastTouch.x = currentTouch.x;\n\t\t\t\t\tlastTouch.y = currentTouch.y;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif((currentKeys & KEY_TOUCH)) {\n\t\t\t\t\tif(keyboardActive) {\n\t\t\t\t\t\tif(newpress(KEY_TOUCH)) {\n\t\t\t\t\t\t\tchar letter = currentKeyboardKey();\n\t\t\t\t\t\t\tif(letter) {\n\t\t\t\t\t\t\t\tsimulateKeyNewpress(letter);\n\t\t\t\t\t\t\t\tsimulateKeyRelease(letter);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if(settings.touch == mouse) {\n\t\t\t\t\t\tif(settings.mouseSpeed) {\n\t\t\t\t\t\t\tPOINT p;\n\t\t\t\t\t\t\tGetCursorPos(&p);\n\t\t\t\t\t\t\tSetCursorPos(p.x + (currentTouch.x - lastTouch.x) * settings.mouseSpeed, p.y + (currentTouch.y - lastTouch.y) * settings.mouseSpeed);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tSetCursorPos((int)((double)currentTouch.x * widthMultiplier), (int)((double)currentTouch.y * heightMultiplier));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if(settings.touch == joystick1) {\n\t\t\t\t\t\tjoyX = (currentTouch.x) * 128;\n\t\t\t\t\t\tjoyY = (currentTouch.y) * 128;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\telse if(settings.touch == joystick2) {\n\t\t\t\t\t\tjoyRX = (currentTouch.x) * 128;\n\t\t\t\t\t\tjoyRY = (currentTouch.y) * 128;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\thandleKey(KEY_TOUCH, settings.Tap);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(settings.circlePad == mouse) {\n\t\t\t\t\tif(abs(circlePad.x) < settings.mouseSpeed * 3) circlePad.x = 0;\n\t\t\t\t\tif(abs(circlePad.y) < settings.mouseSpeed * 3) circlePad.y = 0;\n\t\t\t\t\t\n\t\t\t\t\tPOINT p;\n\t\t\t\t\tGetCursorPos(&p);\n\t\t\t\t\tSetCursorPos(p.x + (circlePad.x * settings.mouseSpeed) / 32, p.y - (circlePad.y * settings.mouseSpeed) / 32);\n\t\t\t\t}\n\t\t\t\telse if(settings.circlePad == joystick1) {\n\t\t\t\t\tjoyX = (circlePad.x + 128) * 128;\n\t\t\t\t\tjoyY = (128 - circlePad.y) * 128;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\telse if(settings.circlePad == joystick2) {\n\t\t\t\t\tjoyRX = (circlePad.x + 128) * 128;\n\t\t\t\t\tjoyRY = (128 - circlePad.y) * 128;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif(settings.cStick == mouse) {\n\t\t\t\t\tif(abs(cStick.x) < settings.mouseSpeed * 3) cStick.x = 0;\n\t\t\t\t\tif(abs(cStick.y) < settings.mouseSpeed * 3) cStick.y = 0;\n\t\t\t\t\t\n\t\t\t\t\tPOINT p;\n\t\t\t\t\tGetCursorPos(&p);\n\t\t\t\t\tSetCursorPos(p.x + (cStick.x * settings.mouseSpeed) / 32, p.y - (cStick.y * settings.mouseSpeed) / 32);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\telse if(settings.cStick == joystick1) {\n\t\t\t\t\tjoyX = (cStick.x + 128) * 128;\n\t\t\t\t\tjoyY = (128 - cStick.y) * 128;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\telse if(settings.cStick == joystick2) {\n\t\t\t\t\tjoyRX = (cStick.x + 128) * 128;\n\t\t\t\t\tjoyRY = (128 - cStick.y) * 128;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t}\n\t\t\n\t\tif(vJoy) updateJoystick();\n\t}\n\t\n\terror(\"accept()\");\n\treturn 0;\n}\n"
  },
  {
    "path": "PC/source/settings.c",
    "content": "#include <stdio.h>\n#include <string.h>\n#include <windows.h>\n\n#include \"keys.h\"\n#include \"wireless.h\"\n\n#include \"settings.h\"\n\nstruct settings settings;\n\nstruct settings defaultSettings = {\n\tport: 8889,\n\tthrottle: 20,\n\tcirclePad: joystick1,\n\tcStick: joystick2,\n\ttouch: mouse,\n\tmouseSpeed: 4,\n\tA: { 1, {'A'} },\n\tB: { 1, {'B'} },\n\tX: { 1, {'X'} },\n\tY: { 1, {'Y'} },\n\tL: { 1, {'L'} },\n\tR: { 1, {'R'} },\n\tZL: { 1, {'Q'} },\n\tZR: { 1, {'W'} },\n\tLeft: { 1, {VK_LEFT} },\n\tRight: { 1, {VK_RIGHT} },\n\tUp: { 1, {VK_UP} },\n\tDown: { 1, {VK_DOWN} },\n\tStart: { 1, {VK_RETURN} },\n\tSelect: { 1, {VK_BACK} },\n\tTap: { 1, {'T'} },\n};\n\nstatic bool getSetting(char *name, char *src, char *dest) {\n\tchar *start = strstr(src, name);\n\t\n\tif(start) {\n\t\tstart += strlen(name);\n\t\t\n\t\tchar *end = start + strlen(start);\n\t\tif(strstr(start, \"\\n\") - 1 < end) end = strstr(start, \"\\n\") - 1;\n\t\tsize_t size = (size_t)end - (size_t)start;\n\t\t\n\t\tstrncpy(dest, start, size);\n\t\tdest[size] = '\\0';\n\t\t\n\t\treturn true;\n\t}\n\t\n\treturn false;\n}\n\nstatic struct keyMapping getButton(char *string) {\n\tstruct keyMapping k = { 1, {0} };\n\t\n\tk.useJoypad = 0;\n\tif(strcmp(string, \"SPACE\") == 0) k.virtualKey = VK_SPACE;\n\telse if(strcmp(string, \"CLICK\") == 0) k.virtualKey = VK_LBUTTON;\n\telse if(strcmp(string, \"RIGHT CLICK\") == 0) k.virtualKey = VK_RBUTTON;\n\telse if(strcmp(string, \"ENTER\") == 0) k.virtualKey = VK_RETURN;\n\telse if(strcmp(string, \"BACKSPACE\") == 0) k.virtualKey = VK_BACK;\n\telse if(strcmp(string, \"SHIFT\") == 0) k.virtualKey = VK_SHIFT;\n\telse if(strcmp(string, \"TAB\") == 0) k.virtualKey = VK_TAB;\n\telse if(strcmp(string, \"LEFT\") == 0) k.virtualKey = VK_LEFT;\n\telse if(strcmp(string, \"RIGHT\") == 0) k.virtualKey = VK_RIGHT;\n\telse if(strcmp(string, \"UP\") == 0) k.virtualKey = VK_UP;\n\telse if(strcmp(string, \"DOWN\") == 0) k.virtualKey = VK_DOWN;\n\telse if(strcmp(string, \"PAGE UP\") == 0) k.virtualKey = VK_PRIOR;\n\telse if(strcmp(string, \"PAGE DOWN\") == 0) k.virtualKey = VK_NEXT;\n\telse if(strcmp(string, \"WINDOWS\") == 0) k.virtualKey = VK_LWIN;\n\telse if(strcmp(string, \"NONE\") == 0) k.virtualKey = 0;\n\t\n\telse if(strcmp(string, \"JOY1\") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 0; }\n\telse if(strcmp(string, \"JOY2\") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 1; }\n\telse if(strcmp(string, \"JOY3\") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 2; }\n\telse if(strcmp(string, \"JOY4\") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 3; }\n\telse if(strcmp(string, \"JOY5\") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 4; }\n\telse if(strcmp(string, \"JOY6\") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 5; }\n\telse if(strcmp(string, \"JOY7\") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 6; }\n\telse if(strcmp(string, \"JOY8\") == 0) { k.useJoypad = 1; k.joypadButton = 1 << 7; }\n\telse if(strcmp(string, \"JOY9\") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 0; }\n\telse if(strcmp(string, \"JOY10\") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 1; }\n\telse if(strcmp(string, \"JOY11\") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 2; }\n\telse if(strcmp(string, \"JOY12\") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 3; }\n\telse if(strcmp(string, \"JOY13\") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 4; }\n\telse if(strcmp(string, \"JOY14\") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 5; }\n\telse if(strcmp(string, \"JOY15\") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 6; }\n\telse if(strcmp(string, \"JOY16\") == 0) { k.useJoypad = 2; k.joypadButton = 1 << 7; }\n\t\n\telse k.virtualKey = (int)string[0];\n\t\n\treturn k;\n}\n\nbool readSettings(void) {\n\tFILE *f;\n\tsize_t len = 0;\n\tchar *buffer = NULL;\n\t\n\tmemcpy(&settings, &defaultSettings, sizeof(struct settings));\n\t\n\tf = fopen(\"3DSController.ini\", \"rb\");\n\tif(!f) {\n\t\treturn false;\n\t}\n\t\n\tfseek(f, 0, SEEK_END);\n\tlen = ftell(f);\n\trewind(f);\n\t\n\tbuffer = malloc(len);\n\tif(!buffer) {\n\t\tfclose(f);\n\t\treturn false;\n\t}\n\t\n\tfread(buffer, 1, len, f);\n\t\n\tchar setting[64] = { '\\0' };\n\t\n\tif(getSetting(\"Port: \", buffer, setting)) {\n\t\tsscanf(setting, \"%d\", &settings.port);\n\t}\n\t\n\tif(getSetting(\"Throttle: \", buffer, setting)) {\n\t\tsscanf(setting, \"%d\", &settings.throttle);\n\t}\n\t\n\tif(getSetting(\"Circle Pad: \", buffer, setting)) {\n\t\tif(strcmp(setting, \"MOUSE\") == 0) settings.circlePad = mouse;\n\t\telse if(strcmp(setting, \"JOYSTICK1\") == 0) settings.circlePad = joystick1;\n\t\telse if(strcmp(setting, \"JOYSTICK2\") == 0) settings.circlePad = joystick2;\n\t}\n\t\n\tif(getSetting(\"C Stick: \", buffer, setting)) {\n\t\tif(strcmp(setting, \"MOUSE\") == 0) settings.cStick = mouse;\n\t\telse if(strcmp(setting, \"JOYSTICK1\") == 0) settings.cStick = joystick1;\n\t\telse if(strcmp(setting, \"JOYSTICK2\") == 0) settings.cStick = joystick2;\n\t}\n\t\n\tif(getSetting(\"Touch: \", buffer, setting)) {\n\t\tif(strcmp(setting, \"MOUSE\") == 0) settings.touch = mouse;\n\t\telse if(strcmp(setting, \"JOYSTICK1\") == 0) settings.touch = joystick1;\n\t\telse if(strcmp(setting, \"JOYSTICK2\") == 0) settings.touch = joystick2;\n\t}\n\t\n\tif(getSetting(\"Mouse Speed: \", buffer, setting)) {\n\t\tsscanf(setting, \"%d\", &settings.mouseSpeed);\n\t}\n\t\n\tif(getSetting(\"A: \", buffer, setting)) settings.A = getButton(setting);\n\tif(getSetting(\"B: \", buffer, setting)) settings.B = getButton(setting);\n\tif(getSetting(\"X: \", buffer, setting)) settings.X = getButton(setting);\n\tif(getSetting(\"Y: \", buffer, setting)) settings.Y = getButton(setting);\n\tif(getSetting(\"L: \", buffer, setting))\tsettings.L = getButton(setting);\n\tif(getSetting(\"R: \", buffer, setting)) settings.R = getButton(setting);\n\tif(getSetting(\"ZL: \", buffer, setting)) settings.ZL = getButton(setting);\n\tif(getSetting(\"ZR: \", buffer, setting)) settings.ZR = getButton(setting);\n\tif(getSetting(\"Left: \", buffer, setting)) settings.Left = getButton(setting);\n\tif(getSetting(\"Right: \", buffer, setting)) settings.Right = getButton(setting);\n\tif(getSetting(\"Up: \", buffer, setting)) settings.Up = getButton(setting);\n\tif(getSetting(\"Down: \", buffer, setting)) settings.Down = getButton(setting);\n\tif(getSetting(\"Start: \", buffer, setting)) settings.Start = getButton(setting);\n\tif(getSetting(\"Select: \", buffer, setting)) settings.Select = getButton(setting);\n\tif(getSetting(\"Tap: \", buffer, setting)) settings.Tap = getButton(setting);\n\t\n\tfclose(f);\n\t\n\treturn true;\n}\n"
  },
  {
    "path": "PC/source/wireless.c",
    "content": "#include <stddef.h>\n\n#include \"general.h\"\n\n#include \"settings.h\"\n\n#include \"wireless.h\"\n\nSOCKET listener;\nSOCKET client;\n\nstruct sockaddr_in client_in;\n\nint sockaddr_in_sizePtr = (int)sizeof(struct sockaddr_in);\n\nstruct packet buffer;\nchar hostName[80];\n\nvoid initNetwork(void) {\n\tWSADATA wsaData;\n\t\n\tWSAStartup(MAKEWORD(2, 2), &wsaData);\n\t\n\tif(gethostname(hostName, sizeof(hostName)) == SOCKET_ERROR) {\n\t\terror(\"gethostname()\");\n\t}\n}\n\nvoid printIPs(void) {\n\tstruct hostent *phe = gethostbyname(hostName);\n    if(phe == 0) {\n       error(\"gethostbyname()\");\n    }\n\t\n\tint i;\n    for(i = 0; phe->h_addr_list[i] != 0; i++) {\n        struct in_addr addr;\n        memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr));\n        printf(\"%s\\n\", inet_ntoa(addr));\n    }\n\t\n\tif(i) {\n\t\tprintf(\"Usually you want the first one.\\n\");\n\t}\n}\n\nvoid startListening(void) {\n\tint nret;\n\t\n\tlistener = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);\n\t\n\tif(listener == INVALID_SOCKET) {\n\t\terror(\"socket()\");\n\t}\n\t\n\tSOCKADDR_IN serverInfo;\n\t\n\tserverInfo.sin_family = AF_INET;\n\tserverInfo.sin_addr.s_addr = IP;\n\tserverInfo.sin_port = htons(settings.port);\n\t\n\tu_long one = 1;\n\tioctlsocket(listener, FIONBIO, &one);\n\t\n\tnret = bind(listener, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr));\n\t\n\tif(nret == SOCKET_ERROR) {\n\t\terror(\"bind()\");\n\t}\n}\n\nvoid sendBuffer(int length) {\n\tif(sendto(listener, (char *)&buffer, length, 0, (struct sockaddr *)&client_in, sizeof(struct sockaddr_in)) != length) {\n\t\terror(\"sendto\");\n\t}\n}\n\nint receiveBuffer(int length) {\n\treturn recvfrom(listener, (char *)&buffer, length, 0, (struct sockaddr *)&client_in, &sockaddr_in_sizePtr);\n}\n"
  },
  {
    "path": "README.md",
    "content": "3DSController ![](/3DS/cxi/icon48x48.png?raw=true)\n===\nA 3DS homebrew application which allows you to use your 3DS as a wireless controller for Windows.\n\n### Download\nThe latest release will always be downloadable from [here](https://github.com/CTurt/3DSController/releases/).\n\nIf you are updating to 0.6 from an older version, you will need to make sure you update vJoy to the recommended version.\n\n### Setup and Usage\nFirstly, 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.\n\nExtract 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.\n\nCopy 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.\n\nIf you are unsure of your local IP address, run `3DSController.exe` and it will tell you.\n\nRun `3DSController.exe` on your computer. If you are prompted, make sure to allow it through your firewall.\n\nStart the application on your 3DS, there is no GUI, it will automatically try to connect to the IP address you put in `3DSController.ini`.\n\nIf it wasn't able to read the IP from `3DSController.ini`, it will notify you and quit.\n\nOtherwise, 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.\n\nIf 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.\n\nIf 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.\n\nIf using Ninjhax press Start and Select to return to the Homebrew Loader, otherwise you can just exit with the Home button.\n\n### Setup and Usage (Linux)\n-For keyboard emulation\nFollow the Windows instructions, but use `3DSController.py` instead of the EXE.\n\n-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.\n\nMake sure that uinput module is running. You can do it from cosole like so: `#!sudo modprobe uinput`\n\nThen, follow the Windows instructions, but use `3DSController_gamepad.py` instead of the EXE.\n\nMay work on OS X too, but this is not tested.\n\n### Configuration\nFind 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`.\n\nTo use custom key bindings, just change the PC's `3DSController.ini` file, it should be straight forward.\n\n### Configuration (Linux)\nThe configuration for the keyboard emulation is in `3DSController.py`, not the INI.\n\nThe configuration for the joystick emulation is in `3DSController_gamepad.py`, not the INI.\n\n### Troubleshooting\n- Make sure that you are using the 3DS and PC application from the same release,\n- 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,\n- Make sure that the `3DSController.ini` is in the root of your 3DS's SD card (not flashcard micro SD),\n- Make sure that the `3DSController.ini` has the local IP of your computer, not your public IP,\n- Make sure your firewall isn't blocking the application,\n- Try using a different port (change the port for both the 3DS and PC's .ini file),\n"
  }
]