diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..711e4ce
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,254 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+[Xx]64/
+[Xx]86/
+[Bb]uild/
+bld/
+[Bb]in/
+[Oo]bj/
+/Tools
+/11.2
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+
+# TODO: Un-comment the next line if you do not want to checkin
+# your web deploy settings because they may include unencrypted
+# passwords
+#*.pubxml
+*.publishproj
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Microsoft Azure ApplicationInsights config file
+ApplicationInsights.config
+
+# Windows Store app package directory
+AppPackages/
+BundleArtifacts/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+[Tt]humbs.db
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# LightSwitch generated files
+GeneratedArtifacts/
+ModelManifest.xml
+
+# Paket dependency manager
+.paket/paket.exe
+
+# FAKE - F# Make
+.fake/
+
+#3DS
+*.elf
+*.cia
+*.3dsx
+output/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..c3e59c5
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "buildtools"]
+ path = buildtools
+ url = git@github.com:Steveice10/buildtools.git
diff --git a/HBDummy.sln b/HBDummy.sln
new file mode 100644
index 0000000..b9ff25b
--- /dev/null
+++ b/HBDummy.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25123.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HBDummy", "HBDummy.vcxproj", "{B2F0601F-BEC5-4653-A44F-BB9617A02F2C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B2F0601F-BEC5-4653-A44F-BB9617A02F2C}.Debug|x64.ActiveCfg = Debug|x64
+ {B2F0601F-BEC5-4653-A44F-BB9617A02F2C}.Debug|x64.Build.0 = Debug|x64
+ {B2F0601F-BEC5-4653-A44F-BB9617A02F2C}.Debug|x86.ActiveCfg = Debug|Win32
+ {B2F0601F-BEC5-4653-A44F-BB9617A02F2C}.Debug|x86.Build.0 = Debug|Win32
+ {B2F0601F-BEC5-4653-A44F-BB9617A02F2C}.Release|x64.ActiveCfg = Release|x64
+ {B2F0601F-BEC5-4653-A44F-BB9617A02F2C}.Release|x64.Build.0 = Release|x64
+ {B2F0601F-BEC5-4653-A44F-BB9617A02F2C}.Release|x86.ActiveCfg = Release|Win32
+ {B2F0601F-BEC5-4653-A44F-BB9617A02F2C}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/HBDummy.vcxproj b/HBDummy.vcxproj
new file mode 100644
index 0000000..6b64e28
--- /dev/null
+++ b/HBDummy.vcxproj
@@ -0,0 +1,179 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {B2F0601F-BEC5-4653-A44F-BB9617A02F2C}
+ HBDummy
+ 8.1
+
+
+
+ Application
+ true
+ v141
+ MultiByte
+
+
+ Application
+ false
+ v141
+ true
+ MultiByte
+
+
+ Makefile
+ true
+ v141
+ MultiByte
+
+
+ Application
+ false
+ v141
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ C:\Users\Nath\Desktop\prog\HBDummy\source;C:\devkitPro\libctru\include;$(IncludePath)
+
+
+ C:\devkitPro\libctru\include;$(ProjectDir)\lib\ctrcommon\include\ctrcommon;$(IncludePath)
+ C:\devkitPro\libctru\include;$(ReferencePath)
+
+
+ make
+ make clean & make
+ make clean
+ C:\devkitPro\libctru\include;$(NMakeForcedIncludes)
+ C:\devkitPro\portlibs\3ds\include;C:\devkitPro\libctru\include;$(IncludePath)
+ C:\devkitPro\libctru\include;
+
+
+
+ Level3
+ Disabled
+ true
+
+
+
+
+ Level3
+ Disabled
+ true
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+
+
+ true
+ true
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HBDummy.vcxproj.filters b/HBDummy.vcxproj.filters
new file mode 100644
index 0000000..d1e62f0
--- /dev/null
+++ b/HBDummy.vcxproj.filters
@@ -0,0 +1,153 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Fichiers de ressources
+
+
+
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+ Fichiers d%27en-tête
+
+
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+ Fichiers sources
+
+
+
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d718acc
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,91 @@
+# TARGET #
+
+TARGET := 3DS
+LIBRARY := 0
+
+ifeq ($(TARGET),$(filter $(TARGET),3DS WIIU))
+ ifeq ($(strip $(DEVKITPRO)),)
+ $(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPro")
+ endif
+endif
+
+# COMMON CONFIGURATION #
+
+NAME := Homebrew_Launcher
+
+
+BUILD_DIR := build
+OUTPUT_DIR := output
+INCLUDE_DIRS := $(SOURCE_DIRS) include
+SOURCE_DIRS := source source/json source/allocator
+
+EXTRA_OUTPUT_FILES :=
+
+LIBRARY_DIRS := $(PORTLIBS) $(CTRULIB)
+LIBRARIES := citro3d ctru png z m
+
+VERSION_MAJOR := 1
+VERSION_MINOR := 0
+VERSION_MICRO := 0
+
+
+BUILD_FLAGS := -march=armv6k -mtune=mpcore -mfloat-abi=hard
+BUILD_FLAGS_CC := -g -Wall -Wno-strict-aliasing -O3 -mword-relocations \
+ -fomit-frame-pointer -ffast-math $(ARCH) $(INCLUDE) -DARM11 -D_3DS $(BUILD_FLAGS) \
+ -DAPP_VERSION_MAJOR=${VERSION_MAJOR} \
+ -DAPP_VERSION_MINOR=${VERSION_MINOR} \
+ -DAPP_VERSION_MICRO=${VERSION_MICRO}
+
+BUILD_FLAGS_CXX := $(COMMON_FLAGS) -std=gnu++11
+RUN_FLAGS :=
+
+
+
+
+
+# 3DS/Wii U CONFIGURATION #
+
+ifeq ($(TARGET),$(filter $(TARGET),3DS WIIU))
+ TITLE := Homebrew Launcher
+ DESCRIPTION := HBL
+ AUTHOR := By Many People
+endif
+
+# 3DS CONFIGURATION #
+
+ifeq ($(TARGET),3DS)
+ LIBRARY_DIRS += $(DEVKITPRO)/libctru $(DEVKITPRO)/portlibs/3ds/
+ LIBRARIES += citro3d ctru png z m
+
+ PRODUCT_CODE := HBL-LDR
+ UNIQUE_ID := 0xd921e
+
+ CATEGORY := Application
+ USE_ON_SD := true
+
+ MEMORY_TYPE := Application
+ SYSTEM_MODE := 64MB
+ SYSTEM_MODE_EXT := Legacy
+ CPU_SPEED := 268MHz
+ ENABLE_L2_CACHE := false
+
+ ICON_FLAGS := --flags visible,ratingrequired,recordusage --cero 153 --esrb 153 --usk 153 --pegigen 153 --pegiptr 153 --pegibbfc 153 --cob 153 --grb 153 --cgsrr 153
+
+ ROMFS_DIR := romfs
+ BANNER_AUDIO := resources/audio.cwav
+
+ BANNER_IMAGE := resources/banner.cgfx
+
+ ICON := resources/icon.png
+
+ LOGO := resources/logo.bcma.lz
+endif
+
+# INTERNAL #
+
+include buildtools/make_base
+
+re:
+ @rm -rf $(BUILD_DIR)
+ echo cleaned build dir
+ make
\ No newline at end of file
diff --git a/buildtools/.buildconfig b/buildtools/.buildconfig
new file mode 100644
index 0000000..116b101
--- /dev/null
+++ b/buildtools/.buildconfig
@@ -0,0 +1,10 @@
+[default]
+name=Default
+runtime=host
+config-opts=
+run-opts=
+prefix=/home/steven/.cache/gnome-builder/install/buildtools/host
+app-id=
+postbuild=
+prebuild=
+default=true
diff --git a/buildtools/3ds/logo.bcma.lz b/buildtools/3ds/logo.bcma.lz
new file mode 100644
index 0000000..dd9db8c
Binary files /dev/null and b/buildtools/3ds/logo.bcma.lz differ
diff --git a/buildtools/3ds/servefiles.py b/buildtools/3ds/servefiles.py
new file mode 100644
index 0000000..549ef3a
--- /dev/null
+++ b/buildtools/3ds/servefiles.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+# coding: utf-8 -*-
+
+import os
+import socket
+import struct
+import sys
+import threading
+import time
+import urllib
+
+try:
+ from SimpleHTTPServer import SimpleHTTPRequestHandler
+ from SocketServer import TCPServer
+ from urlparse import urljoin
+ from urllib import pathname2url, quote
+except ImportError:
+ from http.server import SimpleHTTPRequestHandler
+ from socketserver import TCPServer
+ from urllib.parse import urljoin, quote
+ from urllib.request import pathname2url
+
+if len(sys.argv) < 3 or len(sys.argv) > 5:
+ print('Usage: ' + sys.argv[0] + ' [host ip] [host port]')
+ sys.exit(1)
+
+accepted_extension = ('.cia', '.tik', '.cetk')
+target_ip = sys.argv[1]
+target_path = sys.argv[2]
+hostPort = 8080 # Default value
+
+if not os.path.exists(target_path):
+ print(target_path + ': No such file or directory.')
+ sys.exit(1)
+
+if len(sys.argv) >= 4:
+ hostIp = sys.argv[3]
+ if len(sys.argv) == 5:
+ hostPort = int(sys.argv[4])
+else:
+ print('Detecting host IP...')
+ hostIp = [(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]
+
+print('Preparing data...')
+baseUrl = hostIp + ':' + str(hostPort) + '/'
+
+if os.path.isfile(target_path):
+ if target_path.endswith(accepted_extension):
+ file_list_payload = baseUrl + quote(os.path.basename(target_path))
+ directory = os.path.dirname(target_path) # get file directory
+ else:
+ print('Unsupported file extension. Supported extensions are: ' + accepted_extension)
+ sys.exit(1)
+
+else:
+ directory = target_path # it's a directory
+ file_list_payload = '' # init the payload before adding lines
+ for file in [file for file in next(os.walk(target_path))[2] if file.endswith(accepted_extension)]:
+ file_list_payload += baseUrl + quote(file) + '\n'
+
+if len(file_list_payload) == 0:
+ print('No files to serve.')
+ sys.exit(1)
+
+file_list_payloadBytes = file_list_payload.encode('ascii')
+
+if directory and directory != '.': # doesn't need to move if it's already the current working directory
+ os.chdir(directory) # set working directory to the right folder to be able to serve files
+
+print('\nURLs:')
+print(file_list_payload + '\n')
+
+print('Opening HTTP server on port ' + str(hostPort))
+server = TCPServer(('', hostPort), SimpleHTTPRequestHandler)
+thread = threading.Thread(target=server.serve_forever)
+thread.start()
+
+try:
+ print('Sending URL(s) to ' + target_ip + ' on port 5000...')
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.connect((target_ip, 5000))
+ sock.sendall(struct.pack('!L', len(file_list_payloadBytes)) + file_list_payloadBytes)
+ while len(sock.recv(1)) < 1:
+ time.sleep(0.05)
+ sock.close()
+except Exception as e:
+ print('An error occurred: ' + str(e))
+ server.shutdown()
+ sys.exit(1)
+
+print('Shutting down HTTP server...')
+server.shutdown()
diff --git a/buildtools/3ds/template.rsf b/buildtools/3ds/template.rsf
new file mode 100644
index 0000000..e89849d
--- /dev/null
+++ b/buildtools/3ds/template.rsf
@@ -0,0 +1,286 @@
+BasicInfo:
+ Title : $(APP_TITLE)
+ ProductCode : $(APP_PRODUCT_CODE)
+ Logo : Homebrew
+
+RomFs:
+ RootPath: $(APP_ROMFS)
+
+TitleInfo:
+ Category : $(APP_CATEGORY)
+ UniqueId : $(APP_UNIQUE_ID)
+
+Option:
+ UseOnSD : $(APP_USE_ON_SD) # true if App is to be installed to SD
+ FreeProductCode : true # Removes limitations on ProductCode
+ MediaFootPadding : false # If true CCI files are created with padding
+ EnableCrypt : $(APP_ENCRYPTED) # Enables encryption for NCCH and CIA
+ EnableCompress : true # Compresses where applicable (currently only exefs:/.code)
+
+AccessControlInfo:
+ CoreVersion : 2
+
+ # Exheader Format Version
+ DescVersion : 2
+
+ # Minimum Required Kernel Version (below is for 4.5.0)
+ ReleaseKernelMajor : "02"
+ ReleaseKernelMinor : "33"
+
+ # ExtData
+ UseExtSaveData : false # enables ExtData
+ #ExtSaveDataId : 0x300 # only set this when the ID is different to the UniqueId
+
+ # FS:USER Archive Access Permissions
+ # Uncomment as required
+ FileSystemAccess:
+ - CategorySystemApplication
+ - CategoryHardwareCheck
+ - CategoryFileSystemTool
+ - Debug
+ - TwlCardBackup
+ - TwlNandData
+ - Boss
+ - DirectSdmc
+ - Core
+ - CtrNandRo
+ - CtrNandRw
+ - CtrNandRoWrite
+ - CategorySystemSettings
+ - CardBoard
+ - ExportImportIvs
+ - DirectSdmcWrite
+ - SwitchCleanup
+ - SaveDataMove
+ - Shop
+ - Shell
+ - CategoryHomeMenu
+ - SeedDB
+ IoAccessControl:
+ - FsMountNand
+ - FsMountNandRoWrite
+ - FsMountTwln
+ - FsMountWnand
+ - FsMountCardSpi
+ - UseSdif3
+ - CreateSeed
+ - UseCardSpi
+
+ # Process Settings
+ MemoryType : $(APP_MEMORY_TYPE) # Application/System/Base
+ SystemMode : $(APP_SYSTEM_MODE) # 64MB(Default)/96MB/80MB/72MB/32MB
+ IdealProcessor : 0
+ AffinityMask : 1
+ Priority : 16
+ MaxCpu : 0x9E # Default
+ HandleTableSize : 0x200
+ DisableDebug : false
+ EnableForceDebug : false
+ CanWriteSharedPage : true
+ CanUsePrivilegedPriority : false
+ CanUseNonAlphabetAndNumber : true
+ PermitMainFunctionArgument : true
+ CanShareDeviceMemory : true
+ RunnableOnSleep : false
+ SpecialMemoryArrange : true
+
+ # New3DS Exclusive Process Settings
+ SystemModeExt : $(APP_SYSTEM_MODE_EXT) # Legacy(Default)/124MB/178MB Legacy:Use Old3DS SystemMode
+ CpuSpeed : $(APP_CPU_SPEED) # 268MHz(Default)/804MHz
+ EnableL2Cache : $(APP_ENABLE_L2_CACHE) # false(default)/true
+ CanAccessCore2 : true
+
+ # Virtual Address Mappings
+ IORegisterMapping:
+ - 1ff00000-1ff7ffff # DSP memory
+ MemoryMapping:
+ - 1f000000-1f5fffff:r # VRAM
+
+ # Accessible SVCs, :
+ SystemCallAccess:
+ ControlMemory: 1
+ QueryMemory: 2
+ ExitProcess: 3
+ GetProcessAffinityMask: 4
+ SetProcessAffinityMask: 5
+ GetProcessIdealProcessor: 6
+ SetProcessIdealProcessor: 7
+ CreateThread: 8
+ ExitThread: 9
+ SleepThread: 10
+ GetThreadPriority: 11
+ SetThreadPriority: 12
+ GetThreadAffinityMask: 13
+ SetThreadAffinityMask: 14
+ GetThreadIdealProcessor: 15
+ SetThreadIdealProcessor: 16
+ GetCurrentProcessorNumber: 17
+ Run: 18
+ CreateMutex: 19
+ ReleaseMutex: 20
+ CreateSemaphore: 21
+ ReleaseSemaphore: 22
+ CreateEvent: 23
+ SignalEvent: 24
+ ClearEvent: 25
+ CreateTimer: 26
+ SetTimer: 27
+ CancelTimer: 28
+ ClearTimer: 29
+ CreateMemoryBlock: 30
+ MapMemoryBlock: 31
+ UnmapMemoryBlock: 32
+ CreateAddressArbiter: 33
+ ArbitrateAddress: 34
+ CloseHandle: 35
+ WaitSynchronization1: 36
+ WaitSynchronizationN: 37
+ SignalAndWait: 38
+ DuplicateHandle: 39
+ GetSystemTick: 40
+ GetHandleInfo: 41
+ GetSystemInfo: 42
+ GetProcessInfo: 43
+ GetThreadInfo: 44
+ ConnectToPort: 45
+ SendSyncRequest1: 46
+ SendSyncRequest2: 47
+ SendSyncRequest3: 48
+ SendSyncRequest4: 49
+ SendSyncRequest: 50
+ OpenProcess: 51
+ OpenThread: 52
+ GetProcessId: 53
+ GetProcessIdOfThread: 54
+ GetThreadId: 55
+ GetResourceLimit: 56
+ GetResourceLimitLimitValues: 57
+ GetResourceLimitCurrentValues: 58
+ GetThreadContext: 59
+ Break: 60
+ OutputDebugString: 61
+ ControlPerformanceCounter: 62
+ CreatePort: 71
+ CreateSessionToPort: 72
+ CreateSession: 73
+ AcceptSession: 74
+ ReplyAndReceive1: 75
+ ReplyAndReceive2: 76
+ ReplyAndReceive3: 77
+ ReplyAndReceive4: 78
+ ReplyAndReceive: 79
+ BindInterrupt: 80
+ UnbindInterrupt: 81
+ InvalidateProcessDataCache: 82
+ StoreProcessDataCache: 83
+ FlushProcessDataCache: 84
+ StartInterProcessDma: 85
+ StopDma: 86
+ GetDmaState: 87
+ RestartDma: 88
+ DebugActiveProcess: 96
+ BreakDebugProcess: 97
+ TerminateDebugProcess: 98
+ GetProcessDebugEvent: 99
+ ContinueDebugEvent: 100
+ GetProcessList: 101
+ GetThreadList: 102
+ GetDebugThreadContext: 103
+ SetDebugThreadContext: 104
+ QueryDebugProcessMemory: 105
+ ReadProcessMemory: 106
+ WriteProcessMemory: 107
+ SetHardwareBreakPoint: 108
+ GetDebugThreadParam: 109
+ ControlProcessMemory: 112
+ MapProcessMemory: 113
+ UnmapProcessMemory: 114
+ CreateCodeSet: 115
+ CreateProcess: 117
+ TerminateProcess: 118
+ SetProcessResourceLimits: 119
+ CreateResourceLimit: 120
+ SetResourceLimitValues: 121
+ AddCodeSegment: 122
+ Backdoor: 123
+ KernelSetState: 124
+ QueryProcessMemory: 125
+
+ # Service List
+ # Maximum 34 services (32 if firmware is prior to 9.6.0)
+ ServiceAccessControl:
+ - APT:U
+ - ac:u
+ - am:net
+ - boss:U
+ - cam:u
+ - cecd:u
+ - cfg:nor
+ - cfg:u
+ - csnd:SND
+ - dsp::DSP
+ - frd:u
+ - fs:USER
+ - gsp::Gpu
+ - gsp::Lcd
+ - hid:USER
+ - http:C
+ - ir:rst
+ - ir:u
+ - ir:USER
+ - mic:u
+ - mcu::HWC
+ - ndm:u
+ - news:s
+ - nwm::EXT
+ - nwm::UDS
+ - ptm:sysm
+ - ptm:u
+ - pxi:dev
+ - soc:U
+ - ssl:C
+ - y2r:u
+
+
+SystemControlInfo:
+ SaveDataSize: 0KB # Change if the app uses savedata
+ RemasterVersion: $(APP_VERSION_MAJOR)
+ StackSize: 0x40000
+
+ # Modules that run services listed above should be included below
+ # Maximum 48 dependencies
+ # :
+ Dependency:
+ ac: 0x0004013000002402
+ #act: 0x0004013000003802
+ am: 0x0004013000001502
+ boss: 0x0004013000003402
+ camera: 0x0004013000001602
+ cecd: 0x0004013000002602
+ cfg: 0x0004013000001702
+ codec: 0x0004013000001802
+ csnd: 0x0004013000002702
+ dlp: 0x0004013000002802
+ dsp: 0x0004013000001a02
+ friends: 0x0004013000003202
+ gpio: 0x0004013000001b02
+ gsp: 0x0004013000001c02
+ hid: 0x0004013000001d02
+ http: 0x0004013000002902
+ i2c: 0x0004013000001e02
+ ir: 0x0004013000003302
+ mcu: 0x0004013000001f02
+ mic: 0x0004013000002002
+ ndm: 0x0004013000002b02
+ news: 0x0004013000003502
+ #nfc: 0x0004013000004002
+ nim: 0x0004013000002c02
+ nwm: 0x0004013000002d02
+ pdn: 0x0004013000002102
+ ps: 0x0004013000003102
+ ptm: 0x0004013000002202
+ #qtm: 0x0004013020004202
+ ro: 0x0004013000003702
+ socket: 0x0004013000002e02
+ spi: 0x0004013000002302
+ ssl: 0x0004013000002f02
diff --git a/buildtools/README.md b/buildtools/README.md
new file mode 100644
index 0000000..f6589ee
--- /dev/null
+++ b/buildtools/README.md
@@ -0,0 +1,13 @@
+# buildtools
+
+Common build tools for C/C++ projects. Supports PC and 3DS targets.
+
+Dependencies:
+ * [makerom](https://github.com/profi200/Project_CTR/tree/master/makerom/) - Building 3DS/CIA files.
+ * [bannertool](https://github.com/Steveice10/bannertool/) - Building 3DS/CIA files.
+ * [citra](https://github.com/citra-emu/citra/) - Testing 3DS/CIA builds on a PC.
+ * zip - Zipping up output files.
+ * xxd - Embedding binary files in executables.
+ * python - Installing CIA builds to a 3DS over the network.
+
+Credit for 3DS homebrew logo goes to [PabloMK7](http://gbatemp.net/members/pablomk7.345712/).
diff --git a/buildtools/make_base b/buildtools/make_base
new file mode 100644
index 0000000..48f152b
--- /dev/null
+++ b/buildtools/make_base
@@ -0,0 +1,761 @@
+# Make Variables
+#
+# TARGET: Optional; Platform to build for.
+# - Supported values: NATIVE, NATIVE32, NATIVE64, WIN32, WIN64, MAC32, MAC64, LINUX32, LINUX64, 3DS, WIIU, SWITCH
+# - Default value: NATIVE
+# LIBRARY: Optional; Whether to output a library.
+# - Supported values: 0, 1
+# - Default value: 0
+#
+# All:
+# - NAME: Project name.
+# - INCLUDE_DIRS: Directories containing include headers.
+# - SOURCE_DIRS: Directories containing source files to compile.
+# - BUILD_DIR: Directory to store build files in.
+# - OUTPUT_DIR: Directory to output the final results to.
+# - LIBRARY_DIRS: Optional; Directories containing libraries to compile against.
+# - LIBRARIES: Optional; Libraries to compile against.
+# - EXTRA_OUTPUT_FILES: Optional; Extra files to copy to the output directory.
+# - BUILD_FLAGS: Optional; Shared build flags.
+# - BUILD_FLAGS_CC: Optional; C build flags.
+# - BUILD_FLAGS_CXX: Optional; C++ build flags.
+# - RUN_FLAGS: Optional; Flags to pass when running output executables.
+# - VERSION_MAJOR: Optional; Major version number.
+# - Default value: 0
+# - VERSION_MINOR: Optional; Minor version number.
+# - Default value: 0
+# - VERSION_MICRO: Optional; Micro version number.
+# - Default value: 0
+#
+# 3DS/Wii U/Switch:
+# - TITLE: Optional; Formal application title, used in metadata.
+# - Default value: NAME stripped of spaces.
+# - AUTHOR: Optional; Application author.
+# - Default value: "Unknown"
+# - REMOTE_IP: Optional; IP to send executable to when running on hardware. Intended to be set in command line.
+# - Default value: 127.0.0.1
+#
+# 3DS/Wii U:
+# - DESCRIPTION: Optional; Application description.
+# - Default value: "No description."
+#
+# 3DS:
+# - PRODUCT_CODE: CIA/3DS product code.
+# - UNIQUE_ID: CIA/3DS unique ID.
+# - BANNER_AUDIO: Audio file to use in the CIA/3DS banner.
+# - Supported file types: WAV, CWAV
+# - BANNER_IMAGE: Graphics to use in the CIA/3DS banner.
+# - Supported file types: 256x128 PNG, CGFX
+# - ICON: Application icon.
+# - Supported file types: 48x48 PNG
+# - Category: Optional; CIA/3DS category.
+# - Supported values: Application, SystemApplication, Applet, Firmware, Base, DlpChild, Demo, Contents, SystemContents, SharedContents, AddOnContents, Patch, AutoUpdateContents
+# - Default value: Application
+# - USE_ON_SD: Optional; Whether the CIA/3DS should be installed to the SD card.
+# - Supported values: true, false
+# - Default value: true
+# - MEMORY_TYPE: Optional; CIA/3DS application memory layout.
+# - Supported values: Application, System, Base
+# - Default value: Application
+# - SYSTEM_MODE: Optional; CIA/3DS legacy system mode.
+# - Supported values: 32MB, 64MB, 72MB, 80MB, 96MB
+# - Default value: 64MB
+# - SYSTEM_MODE_EXT: Optional; CIA/3DS extended system mode.
+# - Supported values: Legacy, 124MB, 178MB
+# - Default value: Legacy
+# - CPU_MODE: Optional; CIA/3DS CPU frequency. 804MHz is N3DS-only.
+# - Supported values: 268MHz, 804MHz
+# - Default value: 268MHz
+# - ENABLE_L2_CACHE: Optional; Whether the CIA/3DS should use the N3DS L2 cache.
+# - Supported values: true, false
+# - Default value: false
+# - ICON_FLAGS: Optional; Flags to pass to bannertool when making an SMDH icon.
+# - ROMFS_DIR: Optional; Directory containing RomFS files.
+# - LOGO: Optional; Logo animation to use when launching the CIA/3DS.
+# - Supported file types: BCMA.LZ
+#
+# Wii U:
+# - ICON: Application icon.
+# - Supported file types: 256x96 PNG
+# - LONG_DESCRIPTION: Optional; Long version of the description field.
+# - Default value: Value of DESCRIPTION.
+#
+# Switch:
+# - TITLE_ID: Optional; Application title ID.
+# - ICON: Optional; Application icon.
+# - Supported file types: 256x256 JPEG
+
+# PROLOGUE #
+
+TARGET ?= NATIVE
+LIBRARY ?= 0
+
+ALL_PC_TARGETS := WIN32 WIN64 MAC32 MAC64 LINUX32 LINUX64
+ALL_SPECIFIC_TARGETS := $(ALL_PC_TARGETS) 3DS WIIU SWITCH
+ALL_TARGETS := NATIVE NATIVE32 NATIVE64 $(ALL_SPECIFIC_TARGETS)
+
+TARGETS :=
+
+ifneq (1,$(words $(TARGET)))
+ TARGETS := $(TARGET)
+else ifeq ($(TARGET),ALL)
+ TARGETS := $(ALL_SPECIFIC_TARGETS)
+else ifeq ($(TARGET),PC)
+ TARGETS := $(ALL_PC_TARGETS)
+endif
+
+ifneq ($(TARGETS),)
+
+.PHONY: all clean
+all:
+ @$(foreach target,$(TARGETS),make --no-print-directory TARGET=$(target);)
+
+else
+
+ifneq ($(MAKECMDGOALS),clean)
+ $(info Building for $(TARGET)...)
+endif
+
+ifeq ($(TARGET),$(filter $(TARGET),3DS WIIU SWITCH))
+ ifeq ($(strip $(DEVKITPRO)),)
+ $(error "Please set DEVKITPRO in your environment. export DEVKITPRO=devkitPro")
+ endif
+endif
+
+# TOOLS #
+
+BUILDTOOLS_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
+
+define createdirrule
+$(1): | $(dir $(1))
+
+ifndef $(dir $(1))_DIRECTORY_RULE_IS_DEFINED
+$(dir $(1)):
+ @mkdir -p $$@
+
+$(dir $(1))_DIRECTORY_RULE_IS_DEFINED := 1
+endif
+endef
+
+rwildcard=$(wildcard $1/$2) $(foreach d,$(wildcard $1/*),$(call rwildcard,$d,$2))
+
+# INITIAL COMMON SETUP #
+
+EMPTY :=
+SPACE := $(EMPTY) $(EMPTY)
+STRIPPED_NAME := $(subst $(SPACE),,$(NAME))
+
+ifeq ($(OS),Windows_NT)
+ HOST_OS := windows
+ ifeq ($(PROCESSOR_ARCHITECTURE),AMD64)
+ HOST_ARCH := x86_64
+ else
+ HOST_ARCH := i686
+ endif
+else
+ UNAME_S := $(shell uname -s)
+ ifeq ($(UNAME_S),Darwin)
+ HOST_OS := mac
+ else ifeq ($(UNAME_S),Linux)
+ HOST_OS := linux
+ else
+ $(error "Unsupported host OS.")
+ endif
+
+ UNAME_M := $(shell uname -m)
+ ifeq ($(UNAME_M),$(filter $(UNAME_M),x86_64 amd64))
+ HOST_ARCH := x86_64
+ else ifeq ($(UNAME_M),$(filter $(UNAME_M),i386 i686))
+ HOST_ARCH := i686
+ else
+ $(error "Unsupported host architecture.")
+ endif
+endif
+
+ifeq ($(TARGET),NATIVE)
+ TARGET_OS := $(HOST_OS)
+ TARGET_ARCH := $(HOST_ARCH)
+else ifeq ($(TARGET),NATIVE32)
+ TARGET_OS := $(HOST_OS)
+ TARGET_ARCH := i686
+else ifeq ($(TARGET),NATIVE64)
+ TARGET_OS := $(HOST_OS)
+ TARGET_ARCH := x86_64
+else ifeq ($(TARGET),WIN32)
+ TARGET_OS := windows
+ TARGET_ARCH := i686
+else ifeq ($(TARGET),WIN64)
+ TARGET_OS := windows
+ TARGET_ARCH := x86_64
+else ifeq ($(TARGET),LINUX32)
+ TARGET_OS := linux
+ TARGET_ARCH := i686
+else ifeq ($(TARGET),LINUX64)
+ TARGET_OS := linux
+ TARGET_ARCH := x86_64
+else ifeq ($(TARGET),MAC32)
+ TARGET_OS := mac
+ TARGET_ARCH := i686
+else ifeq ($(TARGET),MAC64)
+ TARGET_OS := mac
+ TARGET_ARCH := x86_64
+else ifeq ($(TARGET),3DS)
+ TARGET_OS := 3ds
+ TARGET_ARCH := arm
+else ifeq ($(TARGET),WIIU)
+ TARGET_OS := wiiu
+ TARGET_ARCH := ppc
+else ifeq ($(TARGET),SWITCH)
+ TARGET_OS := switch
+ TARGET_ARCH := aarch64
+else
+ $(error "Unknown target. Supported targets: $(ALL_TARGETS)")
+endif
+
+TARGET_BUILD_DIR := $(BUILD_DIR)/$(TARGET_OS)-$(TARGET_ARCH)
+TARGET_OUTPUT_DIR := $(OUTPUT_DIR)/$(TARGET_OS)-$(TARGET_ARCH)
+
+BUILT_FILTER := $(patsubst %.bin,$(TARGET_BUILD_DIR)/%.bin.o,$(BUILD_FILTER)) \
+ $(patsubst %.c,$(TARGET_BUILD_DIR)/%.o,$(BUILD_FILTER)) \
+ $(patsubst %.cpp,$(TARGET_BUILD_DIR)/%.o,$(BUILD_FILTER)) \
+ $(patsubst %.s,$(TARGET_BUILD_DIR)/%.o,$(BUILD_FILTER))
+
+OBJECT_FILES := $(foreach dir,$(SOURCE_DIRS), \
+ $(patsubst %.bin,$(TARGET_BUILD_DIR)/%.bin.o,$(call rwildcard,$(dir),*.bin)) \
+ $(patsubst %.c,$(TARGET_BUILD_DIR)/%.o,$(call rwildcard,$(dir),*.c)) \
+ $(patsubst %.cpp,$(TARGET_BUILD_DIR)/%.o,$(call rwildcard,$(dir),*.cpp)) \
+ $(patsubst %.s,$(TARGET_BUILD_DIR)/%.o,$(call rwildcard,$(dir),*.s)) \
+ )
+
+OBJECT_FILES := $(filter-out $(BUILT_FILTER),$(OBJECT_FILES))
+
+OUTPUT_ZIP_FILE ?= $(OUTPUT_DIR)/$(STRIPPED_NAME).zip
+
+ifeq ($(strip $(VERSION_MAJOR)),)
+ VERSION_MAJOR := 0
+endif
+
+ifeq ($(strip $(VERSION_MINOR)),)
+ VERSION_MINOR := 0
+endif
+
+ifeq ($(strip $(VERSION_MICRO)),)
+ VERSION_MICRO := 0
+endif
+
+LD_FLAGS := $(patsubst %,-L%/lib,$(LIBRARY_DIRS)) $(patsubst %,-l%,$(LIBRARIES))
+COMMON_CC_FLAGS := $(sort $(foreach dir,$(SOURCE_DIRS),$(patsubst %,-I$(TARGET_BUILD_DIR)/%,$(dir $(call rwildcard,$(dir),*))))) $(patsubst %,-I%,$(INCLUDE_DIRS)) $(patsubst %,-I%/include,$(LIBRARY_DIRS)) -g -Wall -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_MICRO=$(VERSION_MICRO) $(BUILD_FLAGS)
+COMMON_CXX_FLAGS :=
+
+ifeq ($(findstring -O,$(BUILD_FLAGS)),)
+ COMMON_CC_FLAGS += -O2
+endif
+
+# COMMON LIBRARY SETUP #
+
+ifeq ($(LIBRARY),1)
+ STRIPPED_NAME := lib$(STRIPPED_NAME)
+ EXTRA_OUTPUT_FILES += $(INCLUDE_DIRS)
+endif
+
+# TARGET SETUP #
+
+REMOTE_IP ?= 127.0.0.1 # User-defined
+
+TITLE ?= $(NAME)
+AUTHOR ?= "Unknown"
+DESCRIPTION ?= "No description."
+LONG_DESCRIPTION ?= $(DESCRIPTION)
+
+ifeq ($(TARGET_OS),windows)
+ ifeq ($(HOST_OS),windows)
+ AR := ar
+ AS := as
+ CC := gcc
+ CXX := g++
+ else ifeq ($(TARGET_ARCH),i686)
+ AR := i686-w64-mingw32-ar
+ AS := i686-w64-mingw32-as
+ CC := i686-w64-mingw32-gcc
+ CXX := i686-w64-mingw32-g++
+ else ifeq ($(TARGET_ARCH),x86_64)
+ AR := x86_64-w64-mingw32-ar
+ AS := x86_64-w64-mingw32-as
+ CC := x86_64-w64-mingw32-gcc
+ CXX := x86_64-w64-mingw32-g++
+ endif
+
+ ifeq ($(TARGET_ARCH),i686)
+ COMMON_CC_FLAGS += -m32
+ else ifeq ($(TARGET_ARCH),x86_64)
+ COMMON_CC_FLAGS += -m64
+ endif
+
+ LD_FLAGS += -static-libstdc++ -static-libgcc -static
+
+ ifeq ($(LIBRARY),1)
+ OUTPUT_FILES := $(TARGET_OUTPUT_DIR)/lib/$(STRIPPED_NAME).a $(TARGET_OUTPUT_DIR)/lib/$(STRIPPED_NAME).dll
+ COMMON_CC_FLAGS += -fPIC
+ else
+ OUTPUT_FILES := $(TARGET_OUTPUT_DIR)/$(STRIPPED_NAME).exe
+ endif
+else ifeq ($(TARGET_OS),mac)
+ ifeq ($(HOST_OS),mac)
+ AR := ar
+ AS := as
+ CC := gcc
+ CXX := g++
+ else ifeq ($(TARGET_ARCH),i686)
+ AR := i386-apple-darwin15-ar
+ AS := i386-apple-darwin15-as
+ CC := i386-apple-darwin15-gcc
+ CXX := i386-apple-darwin15-g++
+ else ifeq ($(TARGET_ARCH),x86_64)
+ AR := x86_64-apple-darwin15-ar
+ AS := x86_64-apple-darwin15-as
+ CC := x86_64-apple-darwin15-gcc
+ CXX := x86_64-apple-darwin15-g++
+ endif
+
+ ifeq ($(TARGET_ARCH),i686)
+ COMMON_CC_FLAGS += -m32
+ else ifeq ($(TARGET_ARCH),x86_64)
+ COMMON_CC_FLAGS += -m64
+ endif
+
+ ifeq ($(LIBRARY),1)
+ OUTPUT_FILES := $(TARGET_OUTPUT_DIR)/lib/$(STRIPPED_NAME).a $(TARGET_OUTPUT_DIR)/lib/$(STRIPPED_NAME).so $(TARGET_OUTPUT_DIR)/lib/$(STRIPPED_NAME).dylib
+ COMMON_CC_FLAGS += -fPIC
+ else
+ OUTPUT_FILES := $(TARGET_OUTPUT_DIR)/$(STRIPPED_NAME)
+ endif
+else ifeq ($(TARGET_OS),linux)
+ ifeq ($(HOST_OS),linux)
+ AR := ar
+ AS := as
+ CC := gcc
+ CXX := g++
+ else ifeq ($(TARGET_ARCH),i686)
+ AR := i686-pc-linux-gnu-ar
+ AS := i686-pc-linux-gnu-as
+ CC := i686-pc-linux-gnu-gcc
+ CXX := i686-pc-linux-gnu-g++
+ else ifeq ($(TARGET_ARCH),x86_64)
+ AR := x86_64-pc-linux-gnu-ar
+ AS := x86_64-pc-linux-gnu-as
+ CC := x86_64-pc-linux-gnu-gcc
+ CXX := x86_64-pc-linux-gnu-g++
+ endif
+
+ ifeq ($(TARGET_ARCH),i686)
+ COMMON_CC_FLAGS += -m32
+ else ifeq ($(TARGET_ARCH),x86_64)
+ COMMON_CC_FLAGS += -m64
+ endif
+
+ ifeq ($(LIBRARY),1)
+ OUTPUT_FILES := $(TARGET_OUTPUT_DIR)/lib/$(STRIPPED_NAME).a $(TARGET_OUTPUT_DIR)/lib/$(STRIPPED_NAME).so
+ COMMON_CC_FLAGS += -fPIC
+ else
+ OUTPUT_FILES := $(TARGET_OUTPUT_DIR)/$(STRIPPED_NAME)
+ endif
+else ifeq ($(TARGET_OS),3ds)
+ BUILT_FILTER := $(patsubst %.v.pica,$(TARGET_BUILD_DIR)/%.shbin.o,$(BUILD_FILTER)) \
+ $(patsubst %.shlist,$(TARGET_BUILD_DIR)/%.shbin.o,$(BUILD_FILTER)) \
+
+ OBJECT_FILES := $(foreach dir,$(SOURCE_DIRS), \
+ $(patsubst %.v.pica,$(TARGET_BUILD_DIR)/%.shbin.o,$(call rwildcard,$(dir),*.v.pica)) \
+ $(patsubst %.shlist,$(TARGET_BUILD_DIR)/%.shbin.o,$(call rwildcard,$(dir),*.shlist)) \
+ ) $(OBJECT_FILES)
+
+ OBJECT_FILES := $(filter-out $(BUILT_FILTER),$(OBJECT_FILES))
+
+ DEVKITARM := $(DEVKITPRO)/devkitARM
+
+ AR := $(DEVKITARM)/bin/arm-none-eabi-ar
+ AS := $(DEVKITARM)/bin/arm-none-eabi-as
+ CC := $(DEVKITARM)/bin/arm-none-eabi-gcc
+ CXX := $(DEVKITARM)/bin/arm-none-eabi-g++
+
+ ifeq ($(LIBRARY),1)
+ OUTPUT_FILES := $(TARGET_OUTPUT_DIR)/lib/$(STRIPPED_NAME).a
+ else
+ OUTPUT_FILES := $(TARGET_OUTPUT_DIR)/$(STRIPPED_NAME).elf $(TARGET_OUTPUT_DIR)/3ds/$(STRIPPED_NAME)/$(STRIPPED_NAME).3dsx $(TARGET_OUTPUT_DIR)/$(STRIPPED_NAME).3ds $(TARGET_OUTPUT_DIR)/$(STRIPPED_NAME).cia
+ endif
+
+ LD_FLAGS += -specs=3dsx.specs
+ COMMON_CC_FLAGS += -mword-relocations -ffast-math -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft -DARM11 -D_3DS
+
+ SERVEFILES := python $(BUILDTOOLS_DIR)/3ds/servefiles.py
+
+ CATEGORY ?= Application
+ USE_ON_SD ?= true
+ MEMORY_TYPE ?= Application
+ SYSTEM_MODE ?= 64MB
+ SYSTEM_MODE_EXT ?= Legacy
+ CPU_SPEED ?= 268MHz
+ ENABLE_L2_CACHE ?= false
+
+ _3DSXTOOL_FLAGS :=
+ COMMON_MAKEROM_FLAGS := -rsf $(BUILDTOOLS_DIR)/3ds/template.rsf -target t -exefslogo -icon $(TARGET_BUILD_DIR)/icon.icn -banner $(TARGET_BUILD_DIR)/banner.bnr -major $(VERSION_MAJOR) -minor $(VERSION_MINOR) -micro $(VERSION_MICRO) -DAPP_TITLE="$(TITLE)" -DAPP_PRODUCT_CODE="$(PRODUCT_CODE)" -DAPP_UNIQUE_ID="$(UNIQUE_ID)" -DAPP_SYSTEM_MODE="$(SYSTEM_MODE)" -DAPP_SYSTEM_MODE_EXT="$(SYSTEM_MODE_EXT)" -DAPP_CATEGORY="$(CATEGORY)" -DAPP_USE_ON_SD="$(USE_ON_SD)" -DAPP_MEMORY_TYPE="$(MEMORY_TYPE)" -DAPP_CPU_SPEED="$(CPU_SPEED)" -DAPP_ENABLE_L2_CACHE="$(ENABLE_L2_CACHE)" -DAPP_VERSION_MAJOR="$(VERSION_MAJOR)"
+
+ ifneq ("$(wildcard $(ROMFS_DIR))","")
+ _3DSXTOOL_FLAGS += --romfs=$(ROMFS_DIR)
+ COMMON_MAKEROM_FLAGS += -DAPP_ROMFS="$(ROMFS_DIR)"
+ endif
+
+ ifneq ("$(wildcard $(LOGO))","")
+ COMMON_MAKEROM_FLAGS += -logo "$(LOGO)"
+ else ifneq ($(LOGO),plain)
+ COMMON_MAKEROM_FLAGS += -logo "$(BUILDTOOLS_DIR)/3ds/logo.bcma.lz"
+ endif
+
+ ifeq ($(suffix $(BANNER_IMAGE)),.cgfx)
+ BANNER_IMAGE_ARG := -ci
+ else
+ BANNER_IMAGE_ARG := -i
+ endif
+
+ ifeq ($(suffix $(BANNER_AUDIO)),.cwav)
+ BANNER_AUDIO_ARG := -ca
+ else
+ BANNER_AUDIO_ARG := -a
+ endif
+else ifeq ($(TARGET_OS),wiiu)
+ DEVKITPPC := $(DEVKITPRO)/devkitPPC
+
+ AR := $(DEVKITPPC)/bin/powerpc-eabi-ar
+ AS := $(DEVKITPPC)/bin/powerpc-eabi-as
+ CC := $(DEVKITPPC)/bin/powerpc-eabi-gcc
+ CXX := $(DEVKITPPC)/bin/powerpc-eabi-g++
+
+ ifeq ($(LIBRARY),1)
+ OUTPUT_FILES := $(TARGET_OUTPUT_DIR)/lib/$(STRIPPED_NAME).a
+ else
+ OUTPUT_FILES := $(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/$(STRIPPED_NAME).elf $(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/meta.xml $(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/icon.png
+ endif
+
+ LD_FLAGS += -Wl,-d,--gc-sections
+ COMMON_CC_FLAGS += -mwup -mcpu=750 -meabi -mhard-float -ffast-math -DESPRESSO -DWIIU
+else ifeq ($(TARGET_OS),switch)
+ DEVKITA64 := $(DEVKITPRO)/devkitA64
+
+ AR := $(DEVKITA64)/bin/aarch64-none-elf-ar
+ AS := $(DEVKITA64)/bin/aarch64-none-elf-as
+ CC := $(DEVKITA64)/bin/aarch64-none-elf-gcc
+ CXX := $(DEVKITA64)/bin/aarch64-none-elf-g++
+
+ ifeq ($(LIBRARY),1)
+ OUTPUT_FILES := $(TARGET_OUTPUT_DIR)/lib/$(STRIPPED_NAME).a
+ else
+ OUTPUT_FILES := $(TARGET_OUTPUT_DIR)/$(STRIPPED_NAME).elf $(TARGET_OUTPUT_DIR)/switch/$(STRIPPED_NAME)/$(STRIPPED_NAME).nro
+ endif
+
+ LD_FLAGS += -specs=$(DEVKITPRO)/libnx/switch.specs
+ COMMON_CC_FLAGS += -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE -D__SWITCH__
+ COMMON_CXX_FLAGS += -fno-rtti -fno-exceptions
+
+ NRO_FLAGS :=
+
+ ifneq ("$(wildcard $(ICON))","")
+ NRO_FLAGS += --icon=$(ICON)
+ endif
+
+ NACP_FLAGS :=
+
+ ifneq ($(TITLE_ID),)
+ NACP_FLAGS += --titleid=$(TITLE_ID)
+ endif
+endif
+
+# FINAL COMMON SETUP #
+
+CLANG_CC := $(subst gcc,clang,$(CC))
+CLANG_CC_EXISTS := $(shell which $(CLANG_CC) > /dev/null 2> /dev/null; echo $$?)
+ifeq ($(CLANG_CC_EXISTS),0)
+ CC := $(CLANG_CC)
+endif
+
+CLANG_CXX := $(subst g++,clang++,$(CXX))
+CLANG_CXX_EXISTS := $(shell which $(CLANG_CXX) > /dev/null 2> /dev/null; echo $$?)
+ifeq ($(CLANG_CXX_EXISTS),0)
+ CXX := $(CLANG_CXX)
+endif
+
+CC_FLAGS := $(COMMON_CC_FLAGS) $(BUILD_FLAGS_CC)
+CXX_FLAGS := $(COMMON_CC_FLAGS) $(COMMON_CXX_FLAGS) $(BUILD_FLAGS_CXX)
+
+ifeq ($(findstring -std,$(BUILD_FLAGS_CC)),)
+ CC_FLAGS += -std=gnu11
+endif
+
+ifeq ($(findstring -std,$(BUILD_FLAGS_CXX)),)
+ CXX_FLAGS += -std=gnu++11
+endif
+
+ifneq ($(EXTRA_OUTPUT_FILES),)
+ EXTRA_OUTPUT_COPY_CMD := cp -r $(EXTRA_OUTPUT_FILES) $(OUTPUT_DIR)
+endif
+
+# MAIN RULES #
+
+.PHONY: all run install clean
+
+all: $(OUTPUT_ZIP_FILE)
+
+# TARGET RULES #
+
+ifeq ($(TARGET_OS),3ds)
+
+ifeq ($(LIBRARY),1)
+
+install: $(OUTPUT_ZIP_FILE)
+ @mkdir -p $(DEVKITPRO)/$(STRIPPED_NAME)
+ @cp -r $(TARGET_OUTPUT_DIR)/* $(DEVKITPRO)/$(STRIPPED_NAME)
+ @echo "Installed."
+
+else
+
+run: $(OUTPUT_ZIP_FILE)
+ @echo "Running..."
+ @citra $(RUN_FLAGS) $(TARGET_OUTPUT_DIR)/3ds/$(STRIPPED_NAME)/$(STRIPPED_NAME).3dsx
+
+runhw: $(OUTPUT_ZIP_FILE)
+ @echo "Running..."
+ @3dslink --address $(REMOTE_IP) $(TARGET_OUTPUT_DIR)/3ds/$(STRIPPED_NAME)/$(STRIPPED_NAME).3dsx
+
+install: $(OUTPUT_ZIP_FILE)
+ @echo "Installing..."
+ @$(SERVEFILES) $(REMOTE_IP) $(TARGET_OUTPUT_DIR)/$(STRIPPED_NAME).cia
+ @echo "Installed."
+
+endif
+
+$(TARGET_BUILD_DIR)/%.shbin.o: $(TARGET_BUILD_DIR)/%.shbin.c
+ @echo $@
+ @$(CC) -c $(CC_FLAGS) -MMD -MP -MF $(TARGET_BUILD_DIR)/$*.d $< -o $@
+
+define shader-as
+ $(eval CURBIN := $(patsubst %.shbin.c,%.shbin,$@))
+ @picasso -o $(CURBIN) $1
+ @cd $(dir $(CURBIN)); \
+ xxd -i $(notdir $(CURBIN)) "$(CURDIR)/$@"
+ echo "extern const u8" `(echo $(notdir $(CURBIN)) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h
+ echo "extern const u32" `(echo $(notdir $(CURBIN)) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_len";" >> `(echo $(CURBIN) | tr . _)`.h
+endef
+
+$(TARGET_BUILD_DIR)/%.shbin.c: %.v.pica %.g.pica
+ @echo $@
+ @$(call shader-as,$^)
+
+$(TARGET_BUILD_DIR)/%.shbin.c: %.v.pica
+ @echo $@
+ @$(call shader-as,$<)
+
+$(TARGET_BUILD_DIR)/%.shbin.c: %.shlist
+ @echo $@
+ @$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file)))
+
+%.bnr: $(BANNER_IMAGE) $(BANNER_AUDIO)
+ @echo $@
+ @bannertool makebanner $(BANNER_IMAGE_ARG) $(BANNER_IMAGE) $(BANNER_AUDIO_ARG) $(BANNER_AUDIO) -o $@ > /dev/null
+
+%.icn: $(ICON)
+ @echo $@
+ @bannertool makesmdh -s "$(TITLE)" -l "$(TITLE) - $(DESCRIPTION)" -p "$(AUTHOR)" -i $(ICON) $(ICON_FLAGS) -o $@ > /dev/null
+
+%.smdh: $(ICON)
+ @echo $@
+ @smdhtool --create "$(TITLE)" "$(DESCRIPTION)" "$(AUTHOR)" $(ICON) $@
+
+$(TARGET_OUTPUT_DIR)/3ds/$(STRIPPED_NAME)/%.3dsx: $(TARGET_OUTPUT_DIR)/%.elf $(TARGET_BUILD_DIR)/meta.smdh
+ @echo $@
+ @3dsxtool $< $@ --smdh=$(word 2,$^) $(_3DSXTOOL_FLAGS)
+
+%.3ds: %.elf $(TARGET_BUILD_DIR)/banner.bnr $(TARGET_BUILD_DIR)/icon.icn
+ @echo $@
+ @makerom -f cci -o $@ -elf $< -DAPP_ENCRYPTED=true $(COMMON_MAKEROM_FLAGS)
+
+%.cia: %.elf $(TARGET_BUILD_DIR)/banner.bnr $(TARGET_BUILD_DIR)/icon.icn
+ @echo $@
+ @makerom -f cia -o $@ -elf $< -DAPP_ENCRYPTED=false $(COMMON_MAKEROM_FLAGS)
+
+else ifeq ($(TARGET_OS),wiiu)
+
+ifeq ($(LIBRARY),1)
+
+install: $(OUTPUT_ZIP_FILE)
+ @mkdir -p $(DEVKITPRO)/$(STRIPPED_NAME)
+ @cp -r $(TARGET_OUTPUT_DIR)/* $(DEVKITPRO)/$(STRIPPED_NAME)
+ @echo "Installed."
+
+else
+
+runhw: $(OUTPUT_ZIP_FILE)
+ @echo "Running..."
+ @WIILOAD=tcp:$(REMOTE_IP) wiiload $(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/$(STRIPPED_NAME).elf $(RUN_FLAGS)
+
+endif
+
+$(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/meta.xml:
+ @echo $@
+ @cp $(BUILDTOOLS_DIR)/wiiu/meta_template.xml $(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/meta.xml
+ @sed -i -- 's/$$(TITLE)/$(subst /,\/,$(TITLE))/g' $(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/meta.xml
+ @sed -i -- 's/$$(AUTHOR)/$(subst /,\/,$(AUTHOR))/g' $(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/meta.xml
+ @sed -i -- 's/$$(VERSION)/$(subst /,\/,$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_MICRO))/g' $(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/meta.xml
+ @sed -i -- 's/$$(RELEASE_DATE)/$(subst /,\/,$(shell date +'%Y%m%d%H%M%S'))/g' $(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/meta.xml
+ @sed -i -- 's/$$(SHORT_DESCRIPTION)/$(subst /,\/,$(DESCRIPTION))/g' $(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/meta.xml
+ @sed -i -- 's/$$(LONG_DESCRIPTION)/$(subst /,\/,$(LONG_DESCRIPTION))/g' $(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/meta.xml
+
+$(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/icon.png:
+ @echo $@
+ @cp $(ICON) $(TARGET_OUTPUT_DIR)/wiiu/apps/$(STRIPPED_NAME)/icon.png
+
+else ifeq ($(TARGET_OS),switch)
+
+ifeq ($(LIBRARY),1)
+
+install: $(OUTPUT_ZIP_FILE)
+ @mkdir -p $(DEVKITPRO)/$(STRIPPED_NAME)
+ @cp -r $(TARGET_OUTPUT_DIR)/* $(DEVKITPRO)/$(STRIPPED_NAME)
+ @echo "Installed."
+
+else
+
+run: $(OUTPUT_ZIP_FILE)
+ @echo "Running..."
+ @yuzu-cmd $(RUN_FLAGS) $(TARGET_OUTPUT_DIR)/switch/$(STRIPPED_NAME)/$(STRIPPED_NAME).nro
+
+runhw: $(OUTPUT_ZIP_FILE)
+ @echo "Running..."
+ @nxlink --address $(REMOTE_IP) $(TARGET_OUTPUT_DIR)/switch/$(STRIPPED_NAME)/$(STRIPPED_NAME).nro
+
+endif
+
+%.nacp:
+ @echo $@
+ @nacptool --create "$(TITLE)" "$(AUTHOR)" "$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_MICRO)" $@ $(NACP_FLAGS)
+
+$(TARGET_OUTPUT_DIR)/switch/$(STRIPPED_NAME)/%.nro: $(TARGET_OUTPUT_DIR)/%.elf $(TARGET_BUILD_DIR)/meta.nacp
+ @echo $@
+ @elf2nro $< $@ --nacp=$(word 2,$^) $(NRO_FLAGS)
+
+else ifeq ($(TARGET_OS),windows)
+ ifeq ($(HOST_OS),$(filter $(HOST_OS),linux mac))
+ ifneq ($(LIBRARY),1)
+
+run: $(OUTPUT_FILES) $(OUTPUT_ZIP_FILE)
+ @echo "Running..."
+ @wine ./$< $(RUN_FLAGS)
+
+ endif
+ else ifeq ($(HOST_OS),windows)
+ ifneq ($(LIBRARY),1)
+
+run: $(OUTPUT_FILES) $(OUTPUT_ZIP_FILE)
+ @echo "Running..."
+ @./$< $(RUN_FLAGS)
+
+ endif
+ endif
+else ifeq ($(TARGET_OS),$(filter $(TARGET_OS),mac linux))
+ ifeq ($(HOST_OS),$(TARGET_OS))
+ ifeq ($(LIBRARY),1)
+
+install: $(OUTPUT_ZIP_FILE)
+ @install -m 0755 $(OUTPUT_FILES) /usr/local/lib
+ @install -m 0644 $(foreach dir,$(INCLUDE_DIRS),$(wildcard $(dir)/*)) /usr/local/include
+ @echo "Installed."
+
+ else
+
+run: $(OUTPUT_FILES) $(OUTPUT_ZIP_FILE)
+ @echo "Running..."
+ @./$< $(RUN_FLAGS)
+
+install: $(OUTPUT_ZIP_FILE)
+ @install -m 0755 $(OUTPUT_FILES) /usr/local/bin
+ @echo "Installed."
+
+ endif
+ endif
+endif
+
+# COMMON RULES #
+
+$(OUTPUT_ZIP_FILE): $(OUTPUT_FILES) $(EXTRA_OUTPUT_FILES)
+ @echo $@
+ @$(EXTRA_OUTPUT_COPY_CMD)
+ @cd $(OUTPUT_DIR); \
+ zip -r $(patsubst $(OUTPUT_DIR)/%,%,$@ * -x $(OUTPUT_ZIP_FILE)) > /dev/null
+
+$(TARGET_OUTPUT_DIR)/$(STRIPPED_NAME): $(OBJECT_FILES)
+ @echo $@
+ @$(CXX) $(CXX_FLAGS) $^ -o $@ $(LD_FLAGS)
+
+%.elf: $(OBJECT_FILES)
+ @echo $@
+ @$(CXX) $(CXX_FLAGS) $^ -o $@ $(LD_FLAGS)
+
+%.a: $(OBJECT_FILES)
+ @echo $@
+ @$(AR) -rc $@ $^
+
+%.so: $(OBJECT_FILES)
+ @echo $@
+ @$(CXX) $(CXX_FLAGS) -shared $^ -o $@ $(LD_FLAGS)
+
+%.exe: $(OBJECT_FILES)
+ @echo $@
+ @$(CXX) $(CXX_FLAGS) $^ -o $@ $(LD_FLAGS)
+
+%.dll: $(OBJECT_FILES)
+ @echo $@
+ @$(CXX) $(CXX_FLAGS) -shared $^ -o $@ $(LD_FLAGS)
+
+%.dylib: $(OBJECT_FILES)
+ @echo $@
+ @$(CXX) $(CXX_FLAGS) -dynamiclib -undefined suppress -flat_namespace $^ -o $@ $(LD_FLAGS)
+
+$(TARGET_BUILD_DIR)/%.o: %.c
+ @echo $@
+ @$(CC) -c $(CC_FLAGS) -MMD -MP -MF $(TARGET_BUILD_DIR)/$*.d $< -o $@
+
+$(TARGET_BUILD_DIR)/%.o: %.cpp
+ @echo $@
+ @$(CXX) -c $(CXX_FLAGS) -MMD -MP -MF $(TARGET_BUILD_DIR)/$*.d $< -o $@
+
+$(TARGET_BUILD_DIR)/%.o: %.s
+ @echo $@
+ @$(CC) -c $(CC_FLAGS) -MMD -MP -MF $(TARGET_BUILD_DIR)/$*.d -x assembler-with-cpp $< -o $@
+
+$(TARGET_BUILD_DIR)/%.o: %.S
+ @echo $@
+ @$(CC) -c $(CC_FLAGS) -MMD -MP -MF $(TARGET_BUILD_DIR)/$*.d -x assembler-with-cpp $< -o $@
+
+$(TARGET_BUILD_DIR)/%.bin.o: $(TARGET_BUILD_DIR)/%.bin.c
+ @echo $@
+ @$(CC) -c $(CC_FLAGS) -MMD -MP -MF $(TARGET_BUILD_DIR)/$*.d $< -o $@
+
+$(TARGET_BUILD_DIR)/%.bin.c: %.bin
+ @echo $@
+ @cd $(> `(echo $(TARGET_BUILD_DIR)/$< | tr . _)`.h
+ @echo "extern const u32" `(echo $(> `(echo $(TARGET_BUILD_DIR)/$< | tr . _)`.h
+
+$(foreach file,$(OBJECT_FILES),$(eval $(call createdirrule,$(file))))
+$(foreach file,$(OUTPUT_FILES),$(eval $(call createdirrule,$(file))))
+
+# DEPENDS #
+
+DEPENDS := $(OBJECT_FILES:.o=.d)
+-include $(DEPENDS)
+
+endif
+
+# CLEAN #
+
+clean:
+ @rm -rf $(BUILD_DIR) $(OUTPUT_DIR)
+ @echo "Cleaned."
diff --git a/buildtools/wiiu/meta_template.xml b/buildtools/wiiu/meta_template.xml
new file mode 100644
index 0000000..9e19b88
--- /dev/null
+++ b/buildtools/wiiu/meta_template.xml
@@ -0,0 +1,9 @@
+
+
+ $(TITLE)
+ $(AUTHOR)
+ $(VERSION)
+ $(RELEASE_DATE)
+ $(SHORT_DESCRIPTION)
+ $(LONG_DESCRIPTION)
+
diff --git a/images/bottom.pdn b/images/bottom.pdn
new file mode 100644
index 0000000..6802a35
Binary files /dev/null and b/images/bottom.pdn differ
diff --git a/images/top.pdn b/images/top.pdn
new file mode 100644
index 0000000..3b0fcaa
Binary files /dev/null and b/images/top.pdn differ
diff --git a/resources/audio.cwav b/resources/audio.cwav
new file mode 100644
index 0000000..fd185d2
Binary files /dev/null and b/resources/audio.cwav differ
diff --git a/resources/banner.cgfx b/resources/banner.cgfx
new file mode 100644
index 0000000..68198ff
Binary files /dev/null and b/resources/banner.cgfx differ
diff --git a/resources/icon.png b/resources/icon.png
new file mode 100644
index 0000000..e2210b0
Binary files /dev/null and b/resources/icon.png differ
diff --git a/resources/logo.bcma.lz b/resources/logo.bcma.lz
new file mode 100644
index 0000000..dd9db8c
Binary files /dev/null and b/resources/logo.bcma.lz differ
diff --git a/romfs/bottom.png b/romfs/bottom.png
new file mode 100644
index 0000000..4548415
Binary files /dev/null and b/romfs/bottom.png differ
diff --git a/romfs/top.png b/romfs/top.png
new file mode 100644
index 0000000..3927bc9
Binary files /dev/null and b/romfs/top.png differ
diff --git a/source/allocator/newlibHeap.c b/source/allocator/newlibHeap.c
new file mode 100644
index 0000000..83ee0d0
--- /dev/null
+++ b/source/allocator/newlibHeap.c
@@ -0,0 +1,35 @@
+#include <3ds/types.h>
+#include // for mallinfo()
+#include // for sbrk()
+
+extern u8 *fake_heap_end; // current heap start
+extern u8 *fake_heap_start; // current heap end
+
+u8 *getHeapStart(void)
+{
+ return fake_heap_start;
+}
+
+u8 *getHeapEnd(void)
+{
+ return (u8*)sbrk(0);
+}
+
+u8 *getHeapLimit(void)
+{
+ return fake_heap_end;
+}
+
+// returns the amount of used memory in bytes
+int getMemUsed(void)
+{
+ struct mallinfo mi = mallinfo();
+ return mi.uordblks;
+}
+
+// returns the amount of free memory in bytes
+int getMemFree(void)
+{
+ struct mallinfo mi = mallinfo();
+ return mi.fordblks + (getHeapLimit() - getHeapEnd());
+}
diff --git a/source/allocator/newlibHeap.h b/source/allocator/newlibHeap.h
new file mode 100644
index 0000000..a54c80b
--- /dev/null
+++ b/source/allocator/newlibHeap.h
@@ -0,0 +1,18 @@
+#ifndef NEWLIBHEAP_H
+#define NEWLIBHEAP_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "3ds/types.h"
+
+u8 *getHeapStart(void);
+u8 *getHeapEnd(void);
+u8 *getHeapLimit(void);
+int getMemUsed(void);
+int getMemFree(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/source/clock.c b/source/clock.c
new file mode 100644
index 0000000..651fc19
--- /dev/null
+++ b/source/clock.c
@@ -0,0 +1,26 @@
+#include "clock.h"
+
+#define SYSCLOCK_SOC (16756991)
+#define SYSCLOCK_ARM9 (SYSCLOCK_SOC * 8)
+#define SYSCLOCK_ARM11 (SYSCLOCK_ARM9 * 2)
+#define SYSCLOCK_ARM11_NEW (SYSCLOCK_ARM11 * 3)
+
+#define CPU_TICKS_PER_MSEC (SYSCLOCK_ARM11 / 1000.0)
+#define CPU_TICKS_PER_USEC (SYSCLOCK_ARM11 / 1000000.0)
+
+
+u64 Timer_Restart(void)
+{
+ return (svcGetSystemTick());
+}
+u64 getTimeInMsec(u64 timer) {
+ return timer / CPU_TICKS_PER_MSEC;
+}
+bool Timer_HasTimePassed(float nbmsecToWait, u64 timer)
+{
+ u64 seconds = (u64)(nbmsecToWait * CPU_TICKS_PER_MSEC);
+ u64 current = svcGetSystemTick();
+ u64 diff = current - timer;
+
+ return (diff >= seconds);
+}
\ No newline at end of file
diff --git a/source/clock.h b/source/clock.h
new file mode 100644
index 0000000..b5347d9
--- /dev/null
+++ b/source/clock.h
@@ -0,0 +1,6 @@
+#pragma once
+#include <3ds.h>
+
+u64 Timer_Restart(void);
+bool Timer_HasTimePassed(float nbmsecToWait, u64 timer);
+u64 getTimeInMsec(u64 timer);
\ No newline at end of file
diff --git a/source/draw.c b/source/draw.c
new file mode 100644
index 0000000..746b582
--- /dev/null
+++ b/source/draw.c
@@ -0,0 +1,375 @@
+#include "draw.h"
+
+static DVLB_s *vshader_dvlb;
+static shaderProgram_s program;
+static int uLoc_projection;
+static textVertex_s *textVtxArray;
+static int textVtxArrayPos;
+static drawTarget_t top;
+static drawTarget_t bottom;
+static bool frameStarted = false;
+static gfxScreen_t currentScreen = -1;
+static cursor_t cursor[2] = { { 10, 10 },{ 10, 10 } };
+
+#define TEXT_VTX_ARRAY_COUNT (8 * 1024)
+
+#define TEX_MIN_SIZE 64
+
+//Grabbed from: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
+unsigned int nextPow2(unsigned int v)
+{
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v++;
+ return (v >= TEX_MIN_SIZE ? v : TEX_MIN_SIZE);
+}
+
+static void addTextVertex(float vx, float vy, float vz, float tx, float ty)
+{
+ textVertex_s *vtx;
+
+ vtx = &textVtxArray[textVtxArrayPos++];
+ vtx->position[0] = vx;
+ vtx->position[1] = vy;
+ vtx->position[2] = 0.0f;
+ vtx->texcoord[0] = tx;
+ vtx->texcoord[1] = ty;
+}
+
+void printVertex(textVertex_s *vtx)
+{
+ printf("Vtx: pos[0] %f, pos[1] %f pos[2] %f, tx[0] %f, tx[1] %f\n",
+ vtx->position[0],
+ vtx->position[1],
+ vtx->position[2],
+ vtx->texcoord[0],
+ vtx->texcoord[1]
+ );
+}
+
+static void resetC3Denv() {
+ C3D_TexEnv *env;
+ for (int i = 0; i < 4; i++) {
+ env = C3D_GetTexEnv(i);
+ TexEnv_Init(env);
+ }
+}
+
+static void bindImageGreyScale(C3D_Tex *texture, u32 texture_color) {
+ //((0.3 * R) + (0.59 * G) + (0.11 * B)). -> 0xFF1C964C
+ C3D_TexEnv *env;
+ u32 greyMask = 0xFF1C964C;
+ resetC3Denv();
+
+ C3D_TexBind(0, texture);
+ env = C3D_GetTexEnv(0);
+ C3D_TexEnvSrc(env, C3D_RGB, GPU_TEXTURE0, GPU_CONSTANT, 0);
+ C3D_TexEnvSrc(env, C3D_Alpha, GPU_TEXTURE0, 0, 0);
+ C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
+ C3D_TexEnvFunc(env, C3D_RGB, GPU_MODULATE);
+ C3D_TexEnvFunc(env, C3D_Alpha, GPU_REPLACE);
+ C3D_TexEnvColor(env, texture_color);
+ env = C3D_GetTexEnv(1);
+ C3D_TexEnvSrc(env, C3D_RGB, GPU_PREVIOUS, GPU_CONSTANT, 0);
+ C3D_TexEnvSrc(env, C3D_Alpha, GPU_PREVIOUS, 0, 0);
+ C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
+ C3D_TexEnvFunc(env, C3D_RGB, GPU_MODULATE);
+ C3D_TexEnvFunc(env, C3D_Alpha, GPU_REPLACE);
+ C3D_TexEnvColor(env, greyMask);
+ C3D_TexEnvBufUpdate(C3D_RGB, 0b0010);
+ env = C3D_GetTexEnv(2);
+ C3D_TexEnvSrc(env, C3D_RGB, GPU_PREVIOUS, GPU_PREVIOUS, 0);
+ C3D_TexEnvSrc(env, C3D_Alpha, GPU_PREVIOUS, 0, 0);
+ C3D_TexEnvOp(env, C3D_RGB, GPU_TEVOP_RGB_SRC_R, GPU_TEVOP_RGB_SRC_G, 0);
+ C3D_TexEnvOp(env, C3D_Alpha, 0, 0, 0);
+ C3D_TexEnvFunc(env, C3D_RGB, GPU_ADD);
+ C3D_TexEnvFunc(env, C3D_Alpha, GPU_REPLACE);
+ env = C3D_GetTexEnv(3);
+ C3D_TexEnvSrc(env, C3D_RGB, GPU_PREVIOUS, GPU_PREVIOUS_BUFFER, 0);
+ C3D_TexEnvSrc(env, C3D_Alpha, GPU_PREVIOUS, 0, 0);
+ C3D_TexEnvOp(env, C3D_RGB, 0, GPU_TEVOP_RGB_SRC_B, 0);
+ C3D_TexEnvOp(env, C3D_Alpha, 0, 0, 0);
+ C3D_TexEnvFunc(env, C3D_RGB, GPU_ADD);
+ C3D_TexEnvFunc(env, C3D_Alpha, GPU_REPLACE);
+}
+
+static void bindTexture(C3D_Tex *texture, u32 texture_color)
+{
+ C3D_TexEnv *env;
+ resetC3Denv();
+
+ C3D_TexBind(0, texture);
+ env = C3D_GetTexEnv(0);
+ C3D_TexEnvBufUpdate(C3D_RGB, 0);
+ C3D_TexEnvSrc(env, C3D_RGB, GPU_TEXTURE0, GPU_CONSTANT, 0);
+ C3D_TexEnvSrc(env, C3D_Alpha, GPU_TEXTURE0, 0, 0);
+ C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
+ C3D_TexEnvFunc(env, C3D_RGB, GPU_MODULATE);
+ C3D_TexEnvFunc(env, C3D_Alpha, GPU_REPLACE);
+ C3D_TexEnvColor(env, texture_color);
+}
+
+void setSpritePos(sprite_t *sprite, float posX, float posY)
+{
+ if (!sprite) return;
+ sprite->posX = posX;
+ sprite->posY = posY;
+}
+
+void drawSprite(sprite_t *sprite)
+{
+ float height;
+ float width;
+ float u;
+ float v;
+ float x;
+ float y;
+ int arrayIndex;
+ C3D_Tex *texture;
+
+ if (!sprite || sprite->isHidden) return;
+ texture = &sprite->texture;
+ height = sprite->height;
+ width = sprite->width;
+ x = sprite->posX;
+ y = sprite->posY;
+ u = width / (float)texture->width;
+ v = height / (float)texture->height;
+
+ width = floor(width * sprite->amount);
+ u *= sprite->amount;
+
+ C3D_BufInfo *bufInfo = C3D_GetBufInfo();
+ BufInfo_Init(bufInfo);
+ BufInfo_Add(bufInfo, textVtxArray, sizeof(textVertex_s), 2, 0x10);
+ //Set the vertices
+ arrayIndex = textVtxArrayPos;
+ addTextVertex(x, y + height, sprite->depth, 0.0f, v); //left bottom
+ addTextVertex(x + width, y + height, sprite->depth, u, v); //right bottom
+ addTextVertex(x, y, sprite->depth, 0.0f, 0.0f); //left top
+ addTextVertex(x + width, y, sprite->depth, u, 0.0f); //right top
+
+ //Bind the sprite's texture
+ if (sprite->isGreyedOut) {
+ bindImageGreyScale(texture, sprite->drawColor);
+ }
+ else {
+ bindTexture(texture, sprite->drawColor);
+ }
+
+ //Draw
+ C3D_DrawArrays(GPU_TRIANGLE_STRIP, arrayIndex, 4);
+}
+
+sprite_t *newSprite(int width, int height)
+{
+ sprite_t *sprite;
+ C3D_Tex *texture;
+ bool result;
+
+ //Alloc the sprite
+ sprite = (sprite_t *)calloc(1, sizeof(sprite_t));
+ if (!sprite) goto allocError;
+ texture = &sprite->texture;
+
+ //Create and init the sprite's texture
+ result = C3D_TexInit(texture, nextPow2(width), nextPow2(height), GPU_RGBA8);
+ if (!result) goto texInitError;
+ //C3D_TexSetWrap(texture, GPU_CLAMP_TO_BORDER, GPU_CLAMP_TO_BORDER);
+ texture->param = GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR)
+ | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_BORDER) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_BORDER);
+
+ sprite->width = (float)width;
+ sprite->height = (float)height;
+ sprite->drawColor = 0xFFFFFFFF;
+ sprite->isGreyedOut = false;
+ sprite->isHidden = false;
+ sprite->depth = 0.0f;
+ sprite->amount = 1.f;
+ return (sprite);
+texInitError:
+ free(sprite);
+allocError:
+ return (NULL);
+}
+
+void deleteSprite(sprite_t *sprite)
+{
+ if (!sprite) return;
+ C3D_TexDelete(&sprite->texture);
+ free(sprite);
+ sprite = NULL;
+}
+
+static void sceneInit(void)
+{
+ int i;
+ TGLP_s *glyphInfo;
+ C3D_Tex *tex;
+ C3D_AttrInfo *attrInfo;
+
+ // Load the vertex shader, create a shader program and bind it
+ vshader_dvlb = DVLB_ParseFile((u32*)vshader_shbin, vshader_shbin_len);
+ shaderProgramInit(&program);
+ shaderProgramSetVsh(&program, &vshader_dvlb->DVLE[0]);
+ C3D_BindProgram(&program);
+
+ // Get the location of the uniforms
+ uLoc_projection = shaderInstanceGetUniformLocation(program.vertexShader, "projection");
+
+ // Configure attributes for use with the vertex shader
+ attrInfo = C3D_GetAttrInfo();
+ AttrInfo_Init(attrInfo);
+ AttrInfo_AddLoader(attrInfo, 0, GPU_FLOAT, 3); // v0=position
+ AttrInfo_AddLoader(attrInfo, 1, GPU_FLOAT, 2); // v1=texcoord
+
+ // Compute the projection matrix
+ Mtx_OrthoTilt(&top.projection, 0.0f, 400.0f, 240.0f, 0.0f, 0.0f, 1.0f, true);
+ Mtx_OrthoTilt(&bottom.projection, 0.0f, 320.0f, 240.0f, 0.0f, 0.0f, 1.0f, true);
+
+ // Configure depth test to overwrite pixels with the same depth (needed to draw overlapping glyphs)
+ C3D_DepthTest(true, GPU_GEQUAL, GPU_WRITE_ALL);
+
+ // Create the text vertex array
+ textVtxArray = (textVertex_s*)linearAlloc(sizeof(textVertex_s)*TEXT_VTX_ARRAY_COUNT);
+}
+
+static void sceneExit(void)
+{
+ // Free the textures
+
+ // Free the shader program
+ shaderProgramFree(&program);
+ DVLB_Free(vshader_dvlb);
+}
+
+void drawInit(void)
+{
+ C3D_RenderTarget *target;
+
+ //Init Citro3D
+ C3D_Init(C3D_DEFAULT_CMDBUF_SIZE);
+
+ // Initialize the top render target
+ target = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
+ C3D_RenderTargetSetClear(target, C3D_CLEAR_ALL, CLEAR_COLOR, 0);
+ C3D_RenderTargetSetOutput(target, GFX_TOP, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
+ top.target = target;
+
+ // Initialize the bottom render target
+ target = C3D_RenderTargetCreate(240, 320, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8);
+ C3D_RenderTargetSetClear(target, C3D_CLEAR_ALL, CLEAR_COLOR, 0);
+ C3D_RenderTargetSetOutput(target, GFX_BOTTOM, GFX_LEFT, DISPLAY_TRANSFER_FLAGS);
+ bottom.target = target;
+
+ // Initialize the scene
+ sceneInit();
+}
+
+void drawEndFrame(void)
+{
+ if (frameStarted)
+ {
+ C3D_FrameEnd(0);
+ frameStarted = false;
+ }
+}
+
+void drawExit(void)
+{
+ sceneExit();
+ C3D_Fini();
+}
+
+void setTextColor(u32 color)
+{
+#ifndef CITRA
+ C3D_TexEnv *env;
+
+ env = C3D_GetTexEnv(0);
+ C3D_TexEnvSrc(env, C3D_RGB, GPU_CONSTANT, 0, 0);
+ C3D_TexEnvSrc(env, C3D_Alpha, GPU_TEXTURE0, GPU_CONSTANT, 0);
+ C3D_TexEnvOp(env, C3D_Both, 0, 0, 0);
+ C3D_TexEnvFunc(env, C3D_RGB, GPU_REPLACE);
+ C3D_TexEnvFunc(env, C3D_Alpha, GPU_MODULATE);
+ C3D_TexEnvColor(env, color);
+#endif
+}
+
+void updateScreen(void)
+{
+ if (frameStarted)
+ C3D_FrameEnd(0);
+ else
+ frameStarted = true;
+ C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
+ textVtxArrayPos = 0;
+ cursor[0] = (cursor_t){ 10, 10 };
+ cursor[1] = (cursor_t){ 10, 10 };
+ currentScreen = -1;
+}
+
+void setScreen(gfxScreen_t screen)
+{
+ if (screen == currentScreen) return;
+ currentScreen = screen;
+ if (!frameStarted)
+ {
+ C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
+ frameStarted = true;
+ }
+ if (screen == GFX_TOP)
+ {
+ C3D_FrameDrawOn(top.target);
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &top.projection);
+ }
+ else if (screen == GFX_BOTTOM)
+ {
+ C3D_FrameDrawOn(bottom.target);
+ C3D_FVUnifMtx4x4(GPU_VERTEX_SHADER, uLoc_projection, &bottom.projection);
+ }
+ else return;
+}
+/*
+void Printf(u32 color, u32 flags, char *text, ...)
+{
+ //TODO: Find the best size for BOLD and SKINNY
+ char buf[4096];
+ va_list vaList;
+ float posX;
+ float posY;
+ float sizeX;
+ float sizeY;
+
+ if (flags)
+ {
+ //Set the font size
+ if (flags & BIG) sizeX = sizeY = 1.0f;
+ else if (flags & SMALL) sizeX = sizeY = 0.35f;
+ else sizeX = sizeY = 0.5f;
+ //Set a style
+ if (flags & BOLD)
+ {
+ sizeX = 0.75f;
+ sizeY = 0.5f;
+ }
+ else if (flags & SKINNY)
+ {
+ sizeX = 0.5f;
+ sizeY = 0.75f;
+ }
+ }
+ else
+ sizeX = sizeY = 0.5f;
+ va_start(vaList, text);
+ vsnprintf(buf, 4096, text, vaList);
+ posX = cursor[currentScreen].posX;
+ posY = cursor[currentScreen].posY;
+ setTextColor(color);
+ renderText(posX, posY, sizeX, sizeY, false, buf, &cursor[currentScreen]);
+ va_end(vaList);
+}*/
diff --git a/source/draw.h b/source/draw.h
new file mode 100644
index 0000000..7d90eef
--- /dev/null
+++ b/source/draw.h
@@ -0,0 +1,112 @@
+#ifndef DRAW_H
+#define DRAW_H
+#include
+#include
+#include
+#include
+#include
+#include <3ds.h>
+#include
+
+typedef struct sprite_s
+{
+ C3D_Tex texture;
+ float posX;
+ float posY;
+ float height;
+ float width;
+ u32 drawColor;
+ bool isGreyedOut;
+ bool isHidden;
+ float depth;
+ float amount; // from 0 to 1
+} sprite_t;
+
+typedef struct rectangle_s
+{
+ /* herited from drawableObject_t */
+ bool(*draw)(void *self);
+
+ float posX;
+ float posY;
+ float width;
+ float height;
+ sprite_t* sprite;
+ float amount; //Range from 0 to 1
+ float depth;
+} rectangle_t;
+
+#include "drawableObject.h"
+
+// These headers are generated by the build process
+#include "vshader_shbin.h"
+
+//#define CITRA //Citra doesn't like the setTextColor
+
+#define CLEAR_COLOR 0x68B0D8FF
+#define SCREEN_POS(x, y) (screenPos_t)((x << 16) | (y))
+#define POS_X(screenPos) (float)(screenPos >> 16)
+#define POS_Y(screenPos) (float)(screenPos & 0xFFFF)
+
+// Used to transfer the final rendered display to the framebuffer
+#define DISPLAY_TRANSFER_FLAGS \
+ (GX_TRANSFER_FLIP_VERT(0) | GX_TRANSFER_OUT_TILED(0) | GX_TRANSFER_RAW_COPY(0) | \
+ GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGB8) | \
+ GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
+
+// Used to convert textures to 3DS tiled format
+// Note: vertical flip flag set so 0,0 is top left of texture
+#define TEXTURE_TRANSFER_FLAGS \
+ (GX_TRANSFER_FLIP_VERT(1) | GX_TRANSFER_OUT_TILED(1) | GX_TRANSFER_RAW_COPY(0) | \
+ GX_TRANSFER_IN_FORMAT(GX_TRANSFER_FMT_RGBA8) | GX_TRANSFER_OUT_FORMAT(GX_TRANSFER_FMT_RGBA8) | \
+ GX_TRANSFER_SCALING(GX_TRANSFER_SCALE_NO))
+
+typedef struct
+{
+ float position[3];
+ float texcoord[2];
+} textVertex_s;
+
+typedef struct drawTarget_s
+{
+ C3D_RenderTarget *target;
+ C3D_Mtx projection;
+} drawTarget_t;
+typedef struct
+{
+ float posX;
+ float posY;
+} cursor_t;
+
+
+typedef u32 screenPos_t;
+
+void drawInit(void);
+void drawExit(void);
+void drawEndFrame(void);
+void setScreen(gfxScreen_t screen);
+void updateScreen(void);
+
+sprite_t *newSprite(int width, int height);
+Result newSpriteFromPNG(sprite_t **out, const char *filename);
+void deleteSprite(sprite_t *sprite);
+void setSpritePos(sprite_t *sprite, float posX, float posY);
+void drawSprite(sprite_t *sprite);
+
+#define COLOR_BLUE 0xFFFF0000
+#define COLOR_RED 0xFF0000FF
+#define COLOR_GREEN 0xFF00FF00
+#define COLOR_BLANK 0xFFFFFFFF
+#define COLOR_BLACK 0xFF000000
+#define COLOR_GREY 0xFF989898
+#define COLOR_ORANGE 0xFF00A5FF
+#define COLOR_LIMEGREEN 0xFF32CD32
+#define COLOR_SALMON 0xFF7280FA
+#define COLOR_SILVER 0xFFC0C0C0
+#define COLOR_CORAL 0xFF507FFF
+
+#define COLOR_DARKGREEN 0xFF006400
+
+
+
+#endif
\ No newline at end of file
diff --git a/source/drawableObject.c b/source/drawableObject.c
new file mode 100644
index 0000000..de81e49
--- /dev/null
+++ b/source/drawableObject.c
@@ -0,0 +1,53 @@
+#include "drawableObject.h"
+#include "draw.h"
+
+backgroundScreen_t *newBackgroundObject(sprite_t *background)
+{
+ backgroundScreen_t *ret;
+
+ ret = (backgroundScreen_t *)calloc(1, sizeof(backgroundScreen_t));
+ if (!ret) goto error;
+
+ if (background) ret->background = background;
+ ret->draw = drawBackground;
+ return (ret);
+error:
+ return (NULL);
+}
+
+bool drawBackground(void *self)
+{
+ backgroundScreen_t *bg;
+
+ if (!self) goto error;
+ bg = (backgroundScreen_t *)self;
+ drawSprite(bg->background);
+error:
+ return (false);
+}
+
+drawableScreen_t *newDrawableScreen(backgroundScreen_t *background)
+{
+ drawableScreen_t *ret;
+
+ ret = (drawableScreen_t *)calloc(1, sizeof(drawableScreen_t));
+ if (!ret) goto error;
+ if (background) ret->background = background;
+ ret->draw = drawScreen;
+ return (ret);
+error:
+ return (NULL);
+}
+
+bool drawScreen(void *self)
+{
+ drawableScreen_t *screen;
+
+ if (!self) goto error;
+ screen = (drawableScreen_t *)self;
+ if (screen->background)
+ screen->background->draw(screen->background);
+ return (true);
+error:
+ return (false);
+}
\ No newline at end of file
diff --git a/source/drawableObject.h b/source/drawableObject.h
new file mode 100644
index 0000000..4356f5b
--- /dev/null
+++ b/source/drawableObject.h
@@ -0,0 +1,39 @@
+#ifndef DRAWABLEOBJECT_H
+#define DRAWABLEOBJECT_H
+#define MAX_ELEMENTS 15
+
+#include "draw.h"
+
+typedef struct drawableObject_s
+{
+ bool (*draw)(void *self);
+} drawableObject_t;
+
+typedef struct backgroundScreen_s
+{
+ /* herited from drawableObject_t */
+ bool (*draw)(void *self);
+
+ sprite_t *background;
+ sprite_t *headerText;
+ sprite_t *footerText;
+
+} backgroundScreen_t;
+
+typedef struct drawableScreen_s
+{
+ /* herited from drawableObject_t */
+ bool (*draw)(void *self);
+
+ backgroundScreen_t *background;
+ int elementsCount;
+ int elementList[MAX_ELEMENTS];
+} drawableScreen_t;
+
+backgroundScreen_t *newBackgroundObject(sprite_t *background);
+bool drawBackground(void *self);
+
+drawableScreen_t *newDrawableScreen(backgroundScreen_t *background);
+bool drawScreen(void *self);
+
+#endif
diff --git a/source/graphics.c b/source/graphics.c
new file mode 100644
index 0000000..3ed1253
--- /dev/null
+++ b/source/graphics.c
@@ -0,0 +1,72 @@
+#include "graphics.h"
+#include "drawableObject.h"
+
+
+sprite_t *bottomSprite = NULL;
+sprite_t *topSprite = NULL;
+drawableScreen_t *botScreen = NULL;
+drawableScreen_t *topScreen = NULL;
+
+void initUI(void)
+{
+ backgroundScreen_t *bg;
+
+ newSpriteFromPNG(&topSprite, "romfs:/top.png");
+ newSpriteFromPNG(&bottomSprite, "romfs:/bottom.png");
+
+ setSpritePos(topSprite, 0, 0);
+ setSpritePos(bottomSprite, 0, 0);
+
+ topSprite->drawColor = 0xFF000000;
+ bottomSprite->drawColor = 0xFF000000;
+
+ bg = newBackgroundObject(bottomSprite);
+ botScreen = newDrawableScreen(bg);
+ bg = newBackgroundObject(topSprite);
+ topScreen = newDrawableScreen(bg);
+
+ updateUI();
+}
+
+void setExitMode() {
+ botScreen->background->background->isGreyedOut = true;
+ topScreen->background->background->isGreyedOut = true;
+}
+
+void handleFadeIn(s64 time, u64 tot) {
+ float ratio = (float)(tot - time) / tot;
+ u8 col = (u8)(ratio * 0xff);
+ u32 finalcol = (0xFF << 24) | (col << 16) | (col << 8) | (col);
+ topScreen->background->background->drawColor = finalcol;
+ botScreen->background->background->drawColor = finalcol;
+}
+
+
+void exitUI(void)
+{
+ deleteSprite(bottomSprite);
+ deleteSprite(topSprite);
+}
+
+static inline void drawUITop(void)
+{
+ setScreen(GFX_TOP);
+
+ topScreen->draw(topScreen);
+}
+
+static inline void drawUIBottom(void)
+{
+ setScreen(GFX_BOTTOM);
+
+ botScreen->draw(botScreen);
+}
+
+int updateUI(void)
+{
+ hidScanInput();
+ drawUITop();
+ drawUIBottom();
+ updateScreen();
+ return (1);
+}
\ No newline at end of file
diff --git a/source/graphics.h b/source/graphics.h
new file mode 100644
index 0000000..cd3780a
--- /dev/null
+++ b/source/graphics.h
@@ -0,0 +1,23 @@
+#ifndef GRAPHICS_H
+#define GRAPHICS_H
+
+#include "draw.h"
+#include "main.h"
+
+#define STACKSIZE 0x1000
+
+void initUI(void);
+void exitUI(void);
+int updateUI(void);
+void setExitMode();
+void handleFadeIn(s64 time, u64 tot);
+
+
+#define newAppTop(...) newAppInfoEntry(appTop, __VA_ARGS__)
+#define removeAppTop() removeAppInfoEntry(appTop)
+#define clearTop(update) clearAppInfo(appTop, update)
+
+#define TRACE() {newAppTop(DEFAULT_COLOR, SMALL, "%s:%d",__FUNCTION__, __LINE__); svcSleepThread(1000000000); updateUI(); svcSleepThread(1000000000);}
+#define XTRACE(str, ...) {newAppTop(DEFAULT_COLOR, SMALL, str, __VA_ARGS__); updateUI(); svcSleepThread(500000000);}
+
+#endif
\ No newline at end of file
diff --git a/source/json/LICENSE b/source/json/LICENSE
new file mode 100644
index 0000000..1aee375
--- /dev/null
+++ b/source/json/LICENSE
@@ -0,0 +1,26 @@
+
+ Copyright (C) 2012, 2013 James McLaughlin et al. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
diff --git a/source/json/json.c b/source/json/json.c
new file mode 100644
index 0000000..6012bad
--- /dev/null
+++ b/source/json/json.c
@@ -0,0 +1,1011 @@
+/* vim: set et ts=3 sw=3 sts=3 ft=c:
+ *
+ * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
+ * https://github.com/udp/json-parser
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "json.h"
+
+#ifdef _MSC_VER
+ #ifndef _CRT_SECURE_NO_WARNINGS
+ #define _CRT_SECURE_NO_WARNINGS
+ #endif
+#endif
+
+const struct _json_value json_value_none;
+
+#include
+#include
+#include
+#include
+
+typedef unsigned int json_uchar;
+
+static unsigned char hex_value (json_char c)
+{
+ if (isdigit(c))
+ return c - '0';
+
+ switch (c) {
+ case 'a': case 'A': return 0x0A;
+ case 'b': case 'B': return 0x0B;
+ case 'c': case 'C': return 0x0C;
+ case 'd': case 'D': return 0x0D;
+ case 'e': case 'E': return 0x0E;
+ case 'f': case 'F': return 0x0F;
+ default: return 0xFF;
+ }
+}
+
+typedef struct
+{
+ unsigned long used_memory;
+
+ unsigned int uint_max;
+ unsigned long ulong_max;
+
+ json_settings settings;
+ int first_pass;
+
+ const json_char * ptr;
+ unsigned int cur_line, cur_col;
+
+} json_state;
+
+static void * default_alloc (size_t size, int zero, void * user_data)
+{
+ return zero ? calloc (1, size) : malloc (size);
+}
+
+static void default_free (void * ptr, void * user_data)
+{
+ free (ptr);
+}
+
+static void * json_alloc (json_state * state, unsigned long size, int zero)
+{
+ if ((state->ulong_max - state->used_memory) < size)
+ return 0;
+
+ if (state->settings.max_memory
+ && (state->used_memory += size) > state->settings.max_memory)
+ {
+ return 0;
+ }
+
+ return state->settings.mem_alloc (size, zero, state->settings.user_data);
+}
+
+static int new_value (json_state * state,
+ json_value ** top, json_value ** root, json_value ** alloc,
+ json_type type)
+{
+ json_value * value;
+ int values_size;
+
+ if (!state->first_pass)
+ {
+ value = *top = *alloc;
+ *alloc = (*alloc)->_reserved.next_alloc;
+
+ if (!*root)
+ *root = value;
+
+ switch (value->type)
+ {
+ case json_array:
+
+ if (value->u.array.length == 0)
+ break;
+
+ if (! (value->u.array.values = (json_value **) json_alloc
+ (state, value->u.array.length * sizeof (json_value *), 0)) )
+ {
+ return 0;
+ }
+
+ value->u.array.length = 0;
+ break;
+
+ case json_object:
+
+ if (value->u.object.length == 0)
+ break;
+
+ values_size = sizeof (*value->u.object.values) * value->u.object.length;
+
+ if (! (value->u.object.values = (json_object_entry *) json_alloc
+ (state, values_size + ((unsigned long) value->u.object.values), 0)) )
+ {
+ return 0;
+ }
+
+ value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;
+
+ value->u.object.length = 0;
+ break;
+
+ case json_string:
+
+ if (! (value->u.string.ptr = (json_char *) json_alloc
+ (state, (value->u.string.length + 1) * sizeof (json_char), 0)) )
+ {
+ return 0;
+ }
+
+ value->u.string.length = 0;
+ break;
+
+ default:
+ break;
+ };
+
+ return 1;
+ }
+
+ if (! (value = (json_value *) json_alloc
+ (state, sizeof (json_value) + state->settings.value_extra, 1)))
+ {
+ return 0;
+ }
+
+ if (!*root)
+ *root = value;
+
+ value->type = type;
+ value->parent = *top;
+
+ #ifdef JSON_TRACK_SOURCE
+ value->line = state->cur_line;
+ value->col = state->cur_col;
+ #endif
+
+ if (*alloc)
+ (*alloc)->_reserved.next_alloc = value;
+
+ *alloc = *top = value;
+
+ return 1;
+}
+
+#define whitespace \
+ case '\n': ++ state.cur_line; state.cur_col = 0; \
+ case ' ': case '\t': case '\r'
+
+#define string_add(b) \
+ do { if (!state.first_pass) string [string_length] = b; ++ string_length; } while (0);
+
+#define line_and_col \
+ state.cur_line, state.cur_col
+
+static const long
+ flag_next = 1 << 0,
+ flag_reproc = 1 << 1,
+ flag_need_comma = 1 << 2,
+ flag_seek_value = 1 << 3,
+ flag_escaped = 1 << 4,
+ flag_string = 1 << 5,
+ flag_need_colon = 1 << 6,
+ flag_done = 1 << 7,
+ flag_num_negative = 1 << 8,
+ flag_num_zero = 1 << 9,
+ flag_num_e = 1 << 10,
+ flag_num_e_got_sign = 1 << 11,
+ flag_num_e_negative = 1 << 12,
+ flag_line_comment = 1 << 13,
+ flag_block_comment = 1 << 14;
+
+json_value * json_parse_ex (json_settings * settings,
+ const json_char * json,
+ size_t length,
+ char * error_buf)
+{
+ json_char error [json_error_max];
+ const json_char * end;
+ json_value * top, * root, * alloc = 0;
+ json_state state = { 0 };
+ long flags;
+ long num_digits = 0, num_e = 0;
+ json_int_t num_fraction = 0;
+
+ /* Skip UTF-8 BOM
+ */
+ if (length >= 3 && ((unsigned char) json [0]) == 0xEF
+ && ((unsigned char) json [1]) == 0xBB
+ && ((unsigned char) json [2]) == 0xBF)
+ {
+ json += 3;
+ length -= 3;
+ }
+
+ error[0] = '\0';
+ end = (json + length);
+
+ memcpy (&state.settings, settings, sizeof (json_settings));
+
+ if (!state.settings.mem_alloc)
+ state.settings.mem_alloc = default_alloc;
+
+ if (!state.settings.mem_free)
+ state.settings.mem_free = default_free;
+
+ memset (&state.uint_max, 0xFF, sizeof (state.uint_max));
+ memset (&state.ulong_max, 0xFF, sizeof (state.ulong_max));
+
+ state.uint_max -= 8; /* limit of how much can be added before next check */
+ state.ulong_max -= 8;
+
+ for (state.first_pass = 1; state.first_pass >= 0; -- state.first_pass)
+ {
+ json_uchar uchar;
+ unsigned char uc_b1, uc_b2, uc_b3, uc_b4;
+ json_char * string = 0;
+ unsigned int string_length = 0;
+
+ top = root = 0;
+ flags = flag_seek_value;
+
+ state.cur_line = 1;
+
+ for (state.ptr = json ;; ++ state.ptr)
+ {
+ json_char b = (state.ptr == end ? 0 : *state.ptr);
+
+ if (flags & flag_string)
+ {
+ if (!b)
+ { sprintf (error, "Unexpected EOF in string (at %d:%d)", line_and_col);
+ goto e_failed;
+ }
+
+ if (string_length > state.uint_max)
+ goto e_overflow;
+
+ if (flags & flag_escaped)
+ {
+ flags &= ~ flag_escaped;
+
+ switch (b)
+ {
+ case 'b': string_add ('\b'); break;
+ case 'f': string_add ('\f'); break;
+ case 'n': string_add ('\n'); break;
+ case 'r': string_add ('\r'); break;
+ case 't': string_add ('\t'); break;
+ case 'u':
+
+ if (end - state.ptr < 4 ||
+ (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
+ (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
+ (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
+ (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
+ {
+ sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
+ goto e_failed;
+ }
+
+ uc_b1 = (uc_b1 << 4) | uc_b2;
+ uc_b2 = (uc_b3 << 4) | uc_b4;
+ uchar = (uc_b1 << 8) | uc_b2;
+
+ if ((uchar & 0xF800) == 0xD800) {
+ json_uchar uchar2;
+
+ if (end - state.ptr < 6 || (*++ state.ptr) != '\\' || (*++ state.ptr) != 'u' ||
+ (uc_b1 = hex_value (*++ state.ptr)) == 0xFF ||
+ (uc_b2 = hex_value (*++ state.ptr)) == 0xFF ||
+ (uc_b3 = hex_value (*++ state.ptr)) == 0xFF ||
+ (uc_b4 = hex_value (*++ state.ptr)) == 0xFF)
+ {
+ sprintf (error, "Invalid character value `%c` (at %d:%d)", b, line_and_col);
+ goto e_failed;
+ }
+
+ uc_b1 = (uc_b1 << 4) | uc_b2;
+ uc_b2 = (uc_b3 << 4) | uc_b4;
+ uchar2 = (uc_b1 << 8) | uc_b2;
+
+ uchar = 0x010000 | ((uchar & 0x3FF) << 10) | (uchar2 & 0x3FF);
+ }
+
+ if (sizeof (json_char) >= sizeof (json_uchar) || (uchar <= 0x7F))
+ {
+ string_add ((json_char) uchar);
+ break;
+ }
+
+ if (uchar <= 0x7FF)
+ {
+ if (state.first_pass)
+ string_length += 2;
+ else
+ { string [string_length ++] = 0xC0 | (uchar >> 6);
+ string [string_length ++] = 0x80 | (uchar & 0x3F);
+ }
+
+ break;
+ }
+
+ if (uchar <= 0xFFFF) {
+ if (state.first_pass)
+ string_length += 3;
+ else
+ { string [string_length ++] = 0xE0 | (uchar >> 12);
+ string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
+ string [string_length ++] = 0x80 | (uchar & 0x3F);
+ }
+
+ break;
+ }
+
+ if (state.first_pass)
+ string_length += 4;
+ else
+ { string [string_length ++] = 0xF0 | (uchar >> 18);
+ string [string_length ++] = 0x80 | ((uchar >> 12) & 0x3F);
+ string [string_length ++] = 0x80 | ((uchar >> 6) & 0x3F);
+ string [string_length ++] = 0x80 | (uchar & 0x3F);
+ }
+
+ break;
+
+ default:
+ string_add (b);
+ };
+
+ continue;
+ }
+
+ if (b == '\\')
+ {
+ flags |= flag_escaped;
+ continue;
+ }
+
+ if (b == '"')
+ {
+ if (!state.first_pass)
+ string [string_length] = 0;
+
+ flags &= ~ flag_string;
+ string = 0;
+
+ switch (top->type)
+ {
+ case json_string:
+
+ top->u.string.length = string_length;
+ flags |= flag_next;
+
+ break;
+
+ case json_object:
+
+ if (state.first_pass)
+ (*(json_char **) &top->u.object.values) += string_length + 1;
+ else
+ {
+ top->u.object.values [top->u.object.length].name
+ = (json_char *) top->_reserved.object_mem;
+
+ top->u.object.values [top->u.object.length].name_length
+ = string_length;
+
+ (*(json_char **) &top->_reserved.object_mem) += string_length + 1;
+ }
+
+ flags |= flag_seek_value | flag_need_colon;
+ continue;
+
+ default:
+ break;
+ };
+ }
+ else
+ {
+ string_add (b);
+ continue;
+ }
+ }
+
+ if (state.settings.settings & json_enable_comments)
+ {
+ if (flags & (flag_line_comment | flag_block_comment))
+ {
+ if (flags & flag_line_comment)
+ {
+ if (b == '\r' || b == '\n' || !b)
+ {
+ flags &= ~ flag_line_comment;
+ -- state.ptr; /* so null can be reproc'd */
+ }
+
+ continue;
+ }
+
+ if (flags & flag_block_comment)
+ {
+ if (!b)
+ { sprintf (error, "%d:%d: Unexpected EOF in block comment", line_and_col);
+ goto e_failed;
+ }
+
+ if (b == '*' && state.ptr < (end - 1) && state.ptr [1] == '/')
+ {
+ flags &= ~ flag_block_comment;
+ ++ state.ptr; /* skip closing sequence */
+ }
+
+ continue;
+ }
+ }
+ else if (b == '/')
+ {
+ if (! (flags & (flag_seek_value | flag_done)) && top->type != json_object)
+ { sprintf (error, "%d:%d: Comment not allowed here", line_and_col);
+ goto e_failed;
+ }
+
+ if (++ state.ptr == end)
+ { sprintf (error, "%d:%d: EOF unexpected", line_and_col);
+ goto e_failed;
+ }
+
+ switch (b = *state.ptr)
+ {
+ case '/':
+ flags |= flag_line_comment;
+ continue;
+
+ case '*':
+ flags |= flag_block_comment;
+ continue;
+
+ default:
+ sprintf (error, "%d:%d: Unexpected `%c` in comment opening sequence", line_and_col, b);
+ goto e_failed;
+ };
+ }
+ }
+
+ if (flags & flag_done)
+ {
+ if (!b)
+ break;
+
+ switch (b)
+ {
+ whitespace:
+ continue;
+
+ default:
+
+ sprintf (error, "%d:%d: Trailing garbage: `%c`",
+ state.cur_line, state.cur_col, b);
+
+ goto e_failed;
+ };
+ }
+
+ if (flags & flag_seek_value)
+ {
+ switch (b)
+ {
+ whitespace:
+ continue;
+
+ case ']':
+
+ if (top && top->type == json_array)
+ flags = (flags & ~ (flag_need_comma | flag_seek_value)) | flag_next;
+ else
+ { sprintf (error, "%d:%d: Unexpected ]", line_and_col);
+ goto e_failed;
+ }
+
+ break;
+
+ default:
+
+ if (flags & flag_need_comma)
+ {
+ if (b == ',')
+ { flags &= ~ flag_need_comma;
+ continue;
+ }
+ else
+ {
+ sprintf (error, "%d:%d: Expected , before %c",
+ state.cur_line, state.cur_col, b);
+
+ goto e_failed;
+ }
+ }
+
+ if (flags & flag_need_colon)
+ {
+ if (b == ':')
+ { flags &= ~ flag_need_colon;
+ continue;
+ }
+ else
+ {
+ sprintf (error, "%d:%d: Expected : before %c",
+ state.cur_line, state.cur_col, b);
+
+ goto e_failed;
+ }
+ }
+
+ flags &= ~ flag_seek_value;
+
+ switch (b)
+ {
+ case '{':
+
+ if (!new_value (&state, &top, &root, &alloc, json_object))
+ goto e_alloc_failure;
+
+ continue;
+
+ case '[':
+
+ if (!new_value (&state, &top, &root, &alloc, json_array))
+ goto e_alloc_failure;
+
+ flags |= flag_seek_value;
+ continue;
+
+ case '"':
+
+ if (!new_value (&state, &top, &root, &alloc, json_string))
+ goto e_alloc_failure;
+
+ flags |= flag_string;
+
+ string = top->u.string.ptr;
+ string_length = 0;
+
+ continue;
+
+ case 't':
+
+ if ((end - state.ptr) < 3 || *(++ state.ptr) != 'r' ||
+ *(++ state.ptr) != 'u' || *(++ state.ptr) != 'e')
+ {
+ goto e_unknown_value;
+ }
+
+ if (!new_value (&state, &top, &root, &alloc, json_boolean))
+ goto e_alloc_failure;
+
+ top->u.boolean = 1;
+
+ flags |= flag_next;
+ break;
+
+ case 'f':
+
+ if ((end - state.ptr) < 4 || *(++ state.ptr) != 'a' ||
+ *(++ state.ptr) != 'l' || *(++ state.ptr) != 's' ||
+ *(++ state.ptr) != 'e')
+ {
+ goto e_unknown_value;
+ }
+
+ if (!new_value (&state, &top, &root, &alloc, json_boolean))
+ goto e_alloc_failure;
+
+ flags |= flag_next;
+ break;
+
+ case 'n':
+
+ if ((end - state.ptr) < 3 || *(++ state.ptr) != 'u' ||
+ *(++ state.ptr) != 'l' || *(++ state.ptr) != 'l')
+ {
+ goto e_unknown_value;
+ }
+
+ if (!new_value (&state, &top, &root, &alloc, json_null))
+ goto e_alloc_failure;
+
+ flags |= flag_next;
+ break;
+
+ default:
+
+ if (isdigit (b) || b == '-')
+ {
+ if (!new_value (&state, &top, &root, &alloc, json_integer))
+ goto e_alloc_failure;
+
+ if (!state.first_pass)
+ {
+ while (isdigit (b) || b == '+' || b == '-'
+ || b == 'e' || b == 'E' || b == '.')
+ {
+ if ( (++ state.ptr) == end)
+ {
+ b = 0;
+ break;
+ }
+
+ b = *state.ptr;
+ }
+
+ flags |= flag_next | flag_reproc;
+ break;
+ }
+
+ flags &= ~ (flag_num_negative | flag_num_e |
+ flag_num_e_got_sign | flag_num_e_negative |
+ flag_num_zero);
+
+ num_digits = 0;
+ num_fraction = 0;
+ num_e = 0;
+
+ if (b != '-')
+ {
+ flags |= flag_reproc;
+ break;
+ }
+
+ flags |= flag_num_negative;
+ continue;
+ }
+ else
+ { sprintf (error, "%d:%d: Unexpected %c when seeking value", line_and_col, b);
+ goto e_failed;
+ }
+ };
+ };
+ }
+ else
+ {
+ switch (top->type)
+ {
+ case json_object:
+
+ switch (b)
+ {
+ whitespace:
+ continue;
+
+ case '"':
+
+ if (flags & flag_need_comma)
+ { sprintf (error, "%d:%d: Expected , before \"", line_and_col);
+ goto e_failed;
+ }
+
+ flags |= flag_string;
+
+ string = (json_char *) top->_reserved.object_mem;
+ string_length = 0;
+
+ break;
+
+ case '}':
+
+ flags = (flags & ~ flag_need_comma) | flag_next;
+ break;
+
+ case ',':
+
+ if (flags & flag_need_comma)
+ {
+ flags &= ~ flag_need_comma;
+ break;
+ }
+
+ default:
+ sprintf (error, "%d:%d: Unexpected `%c` in object", line_and_col, b);
+ goto e_failed;
+ };
+
+ break;
+
+ case json_integer:
+ case json_double:
+
+ if (isdigit (b))
+ {
+ ++ num_digits;
+
+ if (top->type == json_integer || flags & flag_num_e)
+ {
+ if (! (flags & flag_num_e))
+ {
+ if (flags & flag_num_zero)
+ { sprintf (error, "%d:%d: Unexpected `0` before `%c`", line_and_col, b);
+ goto e_failed;
+ }
+
+ if (num_digits == 1 && b == '0')
+ flags |= flag_num_zero;
+ }
+ else
+ {
+ flags |= flag_num_e_got_sign;
+ num_e = (num_e * 10) + (b - '0');
+ continue;
+ }
+
+ top->u.integer = (top->u.integer * 10) + (b - '0');
+ continue;
+ }
+
+ num_fraction = (num_fraction * 10) + (b - '0');
+ continue;
+ }
+
+ if (b == '+' || b == '-')
+ {
+ if ( (flags & flag_num_e) && !(flags & flag_num_e_got_sign))
+ {
+ flags |= flag_num_e_got_sign;
+
+ if (b == '-')
+ flags |= flag_num_e_negative;
+
+ continue;
+ }
+ }
+ else if (b == '.' && top->type == json_integer)
+ {
+ if (!num_digits)
+ { sprintf (error, "%d:%d: Expected digit before `.`", line_and_col);
+ goto e_failed;
+ }
+
+ top->type = json_double;
+ top->u.dbl = (double) top->u.integer;
+
+ num_digits = 0;
+ continue;
+ }
+
+ if (! (flags & flag_num_e))
+ {
+ if (top->type == json_double)
+ {
+ if (!num_digits)
+ { sprintf (error, "%d:%d: Expected digit after `.`", line_and_col);
+ goto e_failed;
+ }
+
+ top->u.dbl += ((double) num_fraction) / (pow (10.0, (double) num_digits));
+ }
+
+ if (b == 'e' || b == 'E')
+ {
+ flags |= flag_num_e;
+
+ if (top->type == json_integer)
+ {
+ top->type = json_double;
+ top->u.dbl = (double) top->u.integer;
+ }
+
+ num_digits = 0;
+ flags &= ~ flag_num_zero;
+
+ continue;
+ }
+ }
+ else
+ {
+ if (!num_digits)
+ { sprintf (error, "%d:%d: Expected digit after `e`", line_and_col);
+ goto e_failed;
+ }
+
+ top->u.dbl *= pow (10.0, (double)
+ (flags & flag_num_e_negative ? - num_e : num_e));
+ }
+
+ if (flags & flag_num_negative)
+ {
+ if (top->type == json_integer)
+ top->u.integer = - top->u.integer;
+ else
+ top->u.dbl = - top->u.dbl;
+ }
+
+ flags |= flag_next | flag_reproc;
+ break;
+
+ default:
+ break;
+ };
+ }
+
+ if (flags & flag_reproc)
+ {
+ flags &= ~ flag_reproc;
+ -- state.ptr;
+ }
+
+ if (flags & flag_next)
+ {
+ flags = (flags & ~ flag_next) | flag_need_comma;
+
+ if (!top->parent)
+ {
+ /* root value done */
+
+ flags |= flag_done;
+ continue;
+ }
+
+ if (top->parent->type == json_array)
+ flags |= flag_seek_value;
+
+ if (!state.first_pass)
+ {
+ json_value * parent = top->parent;
+
+ switch (parent->type)
+ {
+ case json_object:
+
+ parent->u.object.values
+ [parent->u.object.length].value = top;
+
+ break;
+
+ case json_array:
+
+ parent->u.array.values
+ [parent->u.array.length] = top;
+
+ break;
+
+ default:
+ break;
+ };
+ }
+
+ if ( (++ top->parent->u.array.length) > state.uint_max)
+ goto e_overflow;
+
+ top = top->parent;
+
+ continue;
+ }
+ }
+
+ alloc = root;
+ }
+
+ return root;
+
+e_unknown_value:
+
+ sprintf (error, "%d:%d: Unknown value", line_and_col);
+ goto e_failed;
+
+e_alloc_failure:
+
+ strcpy (error, "Memory allocation failure");
+ goto e_failed;
+
+e_overflow:
+
+ sprintf (error, "%d:%d: Too long (caught overflow)", line_and_col);
+ goto e_failed;
+
+e_failed:
+
+ if (error_buf)
+ {
+ if (*error)
+ strcpy (error_buf, error);
+ else
+ strcpy (error_buf, "Unknown error");
+ }
+
+ if (state.first_pass)
+ alloc = root;
+
+ while (alloc)
+ {
+ top = alloc->_reserved.next_alloc;
+ state.settings.mem_free (alloc, state.settings.user_data);
+ alloc = top;
+ }
+
+ if (!state.first_pass)
+ json_value_free_ex (&state.settings, root);
+
+ return 0;
+}
+
+json_value * json_parse (const json_char * json, size_t length)
+{
+ json_settings settings = { 0 };
+ return json_parse_ex (&settings, json, length, 0);
+}
+
+void json_value_free_ex (json_settings * settings, json_value * value)
+{
+ json_value * cur_value;
+
+ if (!value)
+ return;
+
+ value->parent = 0;
+
+ while (value)
+ {
+ switch (value->type)
+ {
+ case json_array:
+
+ if (!value->u.array.length)
+ {
+ settings->mem_free (value->u.array.values, settings->user_data);
+ break;
+ }
+
+ value = value->u.array.values [-- value->u.array.length];
+ continue;
+
+ case json_object:
+
+ if (!value->u.object.length)
+ {
+ settings->mem_free (value->u.object.values, settings->user_data);
+ break;
+ }
+
+ value = value->u.object.values [-- value->u.object.length].value;
+ continue;
+
+ case json_string:
+
+ settings->mem_free (value->u.string.ptr, settings->user_data);
+ break;
+
+ default:
+ break;
+ };
+
+ cur_value = value;
+ value = value->parent;
+ settings->mem_free (cur_value, settings->user_data);
+ }
+}
+
+void json_value_free (json_value * value)
+{
+ json_settings settings = { 0 };
+ settings.mem_free = default_free;
+ json_value_free_ex (&settings, value);
+}
+
diff --git a/source/json/json.h b/source/json/json.h
new file mode 100644
index 0000000..f6549ec
--- /dev/null
+++ b/source/json/json.h
@@ -0,0 +1,283 @@
+
+/* vim: set et ts=3 sw=3 sts=3 ft=c:
+ *
+ * Copyright (C) 2012, 2013, 2014 James McLaughlin et al. All rights reserved.
+ * https://github.com/udp/json-parser
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _JSON_H
+#define _JSON_H
+
+#ifndef json_char
+ #define json_char char
+#endif
+
+#ifndef json_int_t
+ #ifndef _MSC_VER
+ #include
+ #define json_int_t int64_t
+ #else
+ #define json_int_t __int64
+ #endif
+#endif
+
+#include
+
+#ifdef __cplusplus
+
+ #include
+
+ extern "C"
+ {
+
+#endif
+
+typedef struct
+{
+ unsigned long max_memory;
+ int settings;
+
+ /* Custom allocator support (leave null to use malloc/free)
+ */
+
+ void * (* mem_alloc) (size_t, int zero, void * user_data);
+ void (* mem_free) (void *, void * user_data);
+
+ void * user_data; /* will be passed to mem_alloc and mem_free */
+
+ size_t value_extra; /* how much extra space to allocate for values? */
+
+} json_settings;
+
+#define json_enable_comments 0x01
+
+typedef enum
+{
+ json_none,
+ json_object,
+ json_array,
+ json_integer,
+ json_double,
+ json_string,
+ json_boolean,
+ json_null
+
+} json_type;
+
+extern const struct _json_value json_value_none;
+
+typedef struct _json_object_entry
+{
+ json_char * name;
+ unsigned int name_length;
+
+ struct _json_value * value;
+
+} json_object_entry;
+
+typedef struct _json_value
+{
+ struct _json_value * parent;
+
+ json_type type;
+
+ union
+ {
+ int boolean;
+ json_int_t integer;
+ double dbl;
+
+ struct
+ {
+ unsigned int length;
+ json_char * ptr; /* null terminated */
+
+ } string;
+
+ struct
+ {
+ unsigned int length;
+
+ json_object_entry * values;
+
+ #if defined(__cplusplus) && __cplusplus >= 201103L
+ decltype(values) begin () const
+ { return values;
+ }
+ decltype(values) end () const
+ { return values + length;
+ }
+ #endif
+
+ } object;
+
+ struct
+ {
+ unsigned int length;
+ struct _json_value ** values;
+
+ #if defined(__cplusplus) && __cplusplus >= 201103L
+ decltype(values) begin () const
+ { return values;
+ }
+ decltype(values) end () const
+ { return values + length;
+ }
+ #endif
+
+ } array;
+
+ } u;
+
+ union
+ {
+ struct _json_value * next_alloc;
+ void * object_mem;
+
+ } _reserved;
+
+ #ifdef JSON_TRACK_SOURCE
+
+ /* Location of the value in the source JSON
+ */
+ unsigned int line, col;
+
+ #endif
+
+
+ /* Some C++ operator sugar */
+
+ #ifdef __cplusplus
+
+ public:
+
+ inline _json_value ()
+ { memset (this, 0, sizeof (_json_value));
+ }
+
+ inline const struct _json_value &operator [] (int index) const
+ {
+ if (type != json_array || index < 0
+ || ((unsigned int) index) >= u.array.length)
+ {
+ return json_value_none;
+ }
+
+ return *u.array.values [index];
+ }
+
+ inline const struct _json_value &operator [] (const char * index) const
+ {
+ if (type != json_object)
+ return json_value_none;
+
+ for (unsigned int i = 0; i < u.object.length; ++ i)
+ if (!strcmp (u.object.values [i].name, index))
+ return *u.object.values [i].value;
+
+ return json_value_none;
+ }
+
+ inline operator const char * () const
+ {
+ switch (type)
+ {
+ case json_string:
+ return u.string.ptr;
+
+ default:
+ return "";
+ };
+ }
+
+ inline operator json_int_t () const
+ {
+ switch (type)
+ {
+ case json_integer:
+ return u.integer;
+
+ case json_double:
+ return (json_int_t) u.dbl;
+
+ default:
+ return 0;
+ };
+ }
+
+ inline operator bool () const
+ {
+ if (type != json_boolean)
+ return false;
+
+ return u.boolean != 0;
+ }
+
+ inline operator double () const
+ {
+ switch (type)
+ {
+ case json_integer:
+ return (double) u.integer;
+
+ case json_double:
+ return u.dbl;
+
+ default:
+ return 0;
+ };
+ }
+
+ #endif
+
+} json_value;
+
+json_value * json_parse (const json_char * json,
+ size_t length);
+
+#define json_error_max 128
+json_value * json_parse_ex (json_settings * settings,
+ const json_char * json,
+ size_t length,
+ char * error);
+
+void json_value_free (json_value *);
+
+
+/* Not usually necessary, unless you used a custom mem_alloc and now want to
+ * use a custom mem_free.
+ */
+void json_value_free_ex (json_settings * settings,
+ json_value *);
+
+
+#ifdef __cplusplus
+ } /* extern "C" */
+#endif
+
+#endif
+
+
diff --git a/source/main.c b/source/main.c
new file mode 100644
index 0000000..26dab60
--- /dev/null
+++ b/source/main.c
@@ -0,0 +1,45 @@
+#include "main.h"
+#include "draw.h"
+#include
+#include "clock.h"
+
+
+
+int main(void)
+{
+ //u32 kernelVersion;
+ gfxInitDefault();
+ romfsInit();
+ drawInit();
+ initUI();
+ bool loop = true;
+ s64 timenow = (s64)getTimeInMsec(Timer_Restart());
+ s64 timefinish = timenow + 500;
+ s64 dif;
+ while (aptMainLoop() && loop)
+ {
+ timenow = (s64)getTimeInMsec(Timer_Restart());
+ if (timefinish - timenow > 0)
+ dif = timefinish - timenow;
+ else
+ dif = 0;
+
+ handleFadeIn(dif, 500);
+
+
+ hidScanInput();
+ u32 kDown = hidKeysDown();
+ if (kDown & KEY_START) {
+ loop = false;
+ setExitMode();
+ }; // break in order to return to hbmenu
+ updateUI();
+ }
+ svcSleepThread(1000000000);
+ drawEndFrame();
+ drawExit();
+ exitUI();
+ romfsExit();
+ gfxExit();
+ return (0);
+}
diff --git a/source/main.h b/source/main.h
new file mode 100644
index 0000000..865d2a8
--- /dev/null
+++ b/source/main.h
@@ -0,0 +1,13 @@
+#ifndef MAIN_H
+#define MAIN_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include <3ds.h>
+#include "graphics.h"
+#include "drawableObject.h"
+#endif
\ No newline at end of file
diff --git a/source/png.c b/source/png.c
new file mode 100644
index 0000000..422d283
--- /dev/null
+++ b/source/png.c
@@ -0,0 +1,165 @@
+#include "draw.h"
+#include
+#include
+#include
+#include
+
+#define PNG_SIGSIZE (8)
+
+Result textureTile32(C3D_Tex *texture)
+{
+ u8 *tmp;
+ int i;
+ int height;
+ int width;
+ u32 pixel;
+ u32 size;
+
+ height = (int)texture->height;
+ width = (int)texture->width;
+ tmp = linearAlloc(width * height * 4);
+ if (!tmp) goto error;
+ size = width * height * 4;
+ for (i = 0; i < size; i += 4)
+ {
+ pixel = *(u32 *)(texture->data + i);
+ *(u32 *)(tmp + i) = __builtin_bswap32(pixel);
+ }
+ GSPGPU_FlushDataCache(tmp, width * height * 4);
+ GSPGPU_FlushDataCache(texture->data, width * height * 4);
+ C3D_SafeDisplayTransfer((u32 *)tmp, GX_BUFFER_DIM(width, height), \
+ (u32*)texture->data, GX_BUFFER_DIM(width, height), TEXTURE_TRANSFER_FLAGS);
+ gspWaitForPPF();
+ linearFree(tmp);
+ return (MAKERESULT(RL_SUCCESS, RS_SUCCESS, RM_COMMON, RD_SUCCESS));
+error:
+ return (MAKERESULT(RL_TEMPORARY, RS_OUTOFRESOURCE, RM_COMMON, RD_OUT_OF_MEMORY));
+}
+
+static void readPNGFile(png_structp pngPtr, png_bytep data, png_size_t length)
+{
+ FILE *file = (FILE *)png_get_io_ptr(pngPtr);
+ fread(data, length, 1, file);
+}
+
+static Result loadPNGGeneric(sprite_t **out, const void *ioPtr)
+{
+ png_structp pngPtr;
+ png_infop infoPtr;
+ png_bytep *rowPtrs;
+ sprite_t *sprite;
+ Result result;
+ unsigned int width;
+ unsigned int height;
+ int bitDepth;
+ int colorType;
+ int stride;
+ int i;
+
+ rowPtrs = NULL;
+ pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (pngPtr == NULL)
+ {
+ result = MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, RD_INVALID_RESULT_VALUE);
+ goto errorCreateRead;
+ }
+ infoPtr = png_create_info_struct(pngPtr);
+ if (infoPtr == NULL)
+ {
+ result = MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, RD_INVALID_RESULT_VALUE);
+ goto errorCreateInfo;
+ }
+ if (setjmp(png_jmpbuf(pngPtr)))
+ {
+ png_destroy_read_struct(&pngPtr, &infoPtr, (png_infopp)0);
+ if (rowPtrs != NULL)
+ free(rowPtrs);
+ result = MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, RD_INVALID_RESULT_VALUE);
+ return (result);
+ }
+ png_set_read_fn(pngPtr, (png_voidp)ioPtr, readPNGFile);
+ png_set_sig_bytes(pngPtr, PNG_SIGSIZE);
+ png_read_info(pngPtr, infoPtr);
+ png_get_IHDR(pngPtr, infoPtr, &width, &height, &bitDepth, &colorType, NULL, NULL, NULL);
+ if ((colorType == PNG_COLOR_TYPE_PALETTE && bitDepth <= 8)
+ || (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8)
+ || png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS)
+ || (bitDepth == 16))
+ {
+ png_set_expand(pngPtr);
+ }
+
+ if (bitDepth == 16) png_set_scale_16(pngPtr);
+ if (bitDepth == 8 && colorType == PNG_COLOR_TYPE_RGB) png_set_filler(pngPtr, 0xFF, PNG_FILLER_AFTER);
+ if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(pngPtr);
+ if (colorType == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_set_palette_to_rgb(pngPtr);
+ png_set_filler(pngPtr, 0xFF, PNG_FILLER_AFTER);
+ }
+ if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8) png_set_expand_gray_1_2_4_to_8(pngPtr);
+ if (png_get_valid(pngPtr, infoPtr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(pngPtr);
+ if (bitDepth < 8) png_set_packing(pngPtr);
+ png_read_update_info(pngPtr, infoPtr);
+ rowPtrs = (png_bytep *)malloc(sizeof(png_bytep) * height);
+ if (!rowPtrs)
+ {
+ result = MAKERESULT(RL_PERMANENT, RS_OUTOFRESOURCE, RM_APPLICATION, RD_OUT_OF_MEMORY);
+ goto errorAllocRows;
+ }
+ sprite = newSprite(width, height);
+ if (!sprite)
+ {
+ result = MAKERESULT(RL_PERMANENT, RS_OUTOFRESOURCE, RM_APPLICATION, RD_OUT_OF_MEMORY);
+ goto errorCreateSprite;
+ }
+ else
+ *out = sprite;
+ stride = sprite->texture.width * 4;
+
+ for (i = 0; i < height; i++)
+ {
+ rowPtrs[i] = (png_bytep)(sprite->texture.data + i * stride);
+ }
+ png_read_image(pngPtr, rowPtrs);
+ textureTile32(&sprite->texture);
+ result = MAKERESULT(RL_SUCCESS, RS_SUCCESS, RM_APPLICATION, RD_SUCCESS);
+errorCreateSprite:
+ free(rowPtrs);
+errorAllocRows:
+ png_destroy_info_struct(pngPtr, &infoPtr);
+errorCreateInfo:
+ png_destroy_read_struct(&pngPtr, (png_infopp)0, (png_infopp)0);
+errorCreateRead:
+ return (result);
+}
+
+
+Result newSpriteFromPNG(sprite_t **out, const char *filename)
+{
+ FILE *file;
+ Result result;
+ png_byte pngsig[PNG_SIGSIZE];
+
+ if (!(file = fopen(filename, "rb")))
+ {
+ result = MAKERESULT(RL_PERMANENT, RS_NOTFOUND, RM_APPLICATION, RD_NOT_FOUND);
+ goto exitError;
+ }
+ if (fread(pngsig, 1, PNG_SIGSIZE, file) != PNG_SIGSIZE)
+ {
+ result = MAKERESULT(RL_PERMANENT, RS_INVALIDARG, RM_APPLICATION, RD_INVALID_SIZE);
+ goto exitClose;
+ }
+ if (png_sig_cmp(pngsig, 0, PNG_SIGSIZE) != 0)
+ {
+ result = MAKERESULT(RL_PERMANENT, RS_INVALIDARG, RM_APPLICATION, RD_INVALID_SELECTION);
+ goto exitClose;
+ }
+ result = loadPNGGeneric(out, (void *)file);
+exitClose:
+ fclose(file);
+exitError:
+ return (result);
+}
diff --git a/source/vshader.v.pica b/source/vshader.v.pica
new file mode 100644
index 0000000..12c673e
--- /dev/null
+++ b/source/vshader.v.pica
@@ -0,0 +1,38 @@
+; Uniforms
+.fvec projection[4]
+
+; Constants
+.constf myconst(0.0, 1.0, -1.0, 0.1)
+.constf RGBA_TO_FLOAT4(0.00392156862, 0, 0, 0)
+.alias ones myconst.yyyy ; Vector full of ones
+.alias zeros myconst.xxxx ; Vector full of zeros
+
+; Outputs
+.out outpos position
+.out outclr color
+.out outtc0 texcoord0
+
+; Inputs (defined as aliases for convenience)
+.alias inpos v0
+.alias intex v1
+
+.proc main
+ ; Force the zw component of inpos to be 1.0
+ mov r0.xy, inpos
+ mov r0.z, zeros
+ mov r0.w, ones
+
+ ; outpos = projectionMatrix * inpos
+ dp4 outpos.x, projection[0], r0
+ dp4 outpos.y, projection[1], r0
+ mov outpos.z, zeros
+ mov outpos.w, ones
+
+ ;outtc0 = intexcoord
+ mov outtc0, intex
+
+ ;outclr
+ mul outclr, RGBA_TO_FLOAT4.xxxx, intex
+
+ end
+.end
\ No newline at end of file