Compare commits

..

324 Commits

Author SHA1 Message Date
Andrea Ciliberti
1b1762f872 Return sockaddr_in length from functions that have in/out addrlen
Previously the socket funtions did not write the sockaddr_in struct fully and instead always returned
the "internal" length, which did not account for the zeroed padding.
2025-01-20 20:42:21 +01:00
Andrea Ciliberti
04b9418dd9 Use macro expansion for maximum sockaddr storage length rather than hardcoded value 2025-01-20 20:42:21 +01:00
kynex7510
30dc65121d Init gpu interrupt queue header 2024-11-20 19:12:01 +01:00
Dave Murphy
8cbcce773b
fix error language, closes #552 (#553) 2024-11-03 20:31:53 +00:00
fincs
a88b5af7a8
libctru v2.4.0 2024-09-17 00:11:09 +02:00
TuxSH
8e55cdf05d Add full support for all QTM services.
This commit adds support for all service commands of all 4 QTM services
(`qtm:u`, `qtm:s`, `qtm:sp` (which are built on top of one another) and
`qtm:c` ("hardware check")), with precise documentation about each command's
behaviour and about I/O internals.

The existing `qtm:c` code in libctru had a lot of misconceptions; this commit is
a full rewrite with breaking changes.

In particular: QTM does *not* track the position of 4 points on the user's face.
Instead, it tracks the position of the user's eyes (but not the direction they are
looking at) and reports their coordinates in camera space and in world space.
The data is presented in a console/hardware-agnostic way to the user.

QTM is a service process responsible for:

- eye tracking (see above). Head tracking data is available even when "super-stable 3D"
  is disabled
- parallax barrier management through the TI TCA6416A I2C->Parallel expander.
  The parallax barrier hardware on N3DS requires that software (in this case, QTM process)
  alternates between writing the barrier's mask pattern & polarity followed by the bit-negation
  of that pattern on polarity continuously, at all times
- automatic barrier management by adjusting it with the results of eye-tracking ("super-stable 3D")
- automatic (and manual) IR LED emitter management so that eye-tracking can work even in the dark
- fowarding camera brightness information from cam:q. GSP uses this for auto-brightness
2024-09-15 21:53:43 +02:00
Nikki
5f06a037d7
Add MCUHWC_SetInfoLedPattern (#549) 2024-09-15 20:45:49 +02:00
Rambo6Glaz
cc5b884d7d
Fix NDMU_QueryStatus (#543) 2024-09-15 18:13:27 +02:00
TuxSH
c5ecf54d51 Fix cmdbuf->bool conversion
Affected code was previously reading 3 uninitialized bytes, making the
conversion return wrong results.
2024-09-07 19:41:47 +02:00
TuxSH
faf5162b60 Fix PTMSYSM_CheckNew3DS, closes #540 2024-03-13 19:24:54 +01:00
TuxSH
a6a6548348 Fix documentation of two functions in ac.h 2024-02-08 00:25:27 +01:00
Kayden Tran
0da8705527
Added ndspChnGetFormat (#538) 2024-01-29 12:04:08 +00:00
fincs
d0936b879b
shaderInstanceInit: properly initialize structure (fix #535) 2023-12-16 16:25:47 +01:00
Dave Murphy
c579a65655
don't pollute system headers with 3ds headers 2023-11-05 11:39:10 +00:00
Dave Murphy
bf4a24a4e7
Changelog for 2.3.0 2023-10-28 20:08:55 +01:00
Chris Feger
bd69c96b7d
Buffer console control sequences (#522) 2023-10-28 19:48:16 +01:00
Gleb Mazovetskiy
41e31d3921
Add CTR_ prefix to ALIGN,PACKED,DEPRECATED macros (#532)
Co-authored-by: fincs <fincs@devkitpro.org>
2023-10-11 21:57:13 +02:00
Tekito_256
687aaf6cfc
FSUSER_GetLegacyBannerData: Fix documentation typo (#526) 2023-10-11 21:29:38 +02:00
Dave Murphy
4de90c3436
remove extra __libc_fini_array 2023-09-25 18:17:34 +01:00
TuxSH
5b2a9f6136 ac: add SSID-related ac:i functions
ACI_LoadNetworkSetting and ACI_GetNetworkWirelessEssidSecuritySsid, plus acGetSessionHandle.
2023-09-16 21:22:37 +02:00
TuxSH
0f098853f2 Add isb and prevent CPU from postponing threadOnException memory writes 2023-09-15 23:15:58 +02:00
oreo639
a4634c0290 Add GPU_DOT3_RGBA texture combiner function 2023-08-12 16:52:12 +02:00
fincs
e9fa000e94
Implement dkA r60 threading syscalls (pthread, std::thread support) 2023-06-24 16:07:06 +02:00
DeltaF1
0cbae436c8
Fix typo in docs (#525)
s/bufger/buffer
2023-05-15 18:19:35 +01:00
Dave Murphy
a9a9d9ab69
libctru v2.2.2 2023-05-08 00:11:49 +01:00
Dave Murphy
6714c04806
adjust struct hostent for compatibility 2023-05-08 00:09:58 +01:00
oreo639
39a53c4fe5
archive_dev: Ensure path separator for local path (#524)
Fixes issue where fopen("test.txt","r") opens 3dstest.txt instead of test.txt.

Also correct misuse of strncat() as count applies to src not dest.

See:
8136d94657
806a4d34c5
2023-05-07 12:08:13 +01:00
Dave Murphy
8d90551306
add define for curl 2023-04-18 12:03:44 +01:00
Dave Murphy
032f3dad40
libctru v2.2.0 2023-04-03 21:39:43 +01:00
TuxSH
b18f04d887 apt: add deliver arg support to chainloader + minor fixes 2023-02-25 20:39:04 +00:00
fincs
98324d412f
libctru v2.1.2 2023-02-09 20:11:27 +01:00
TuxSH
cd78fb05cb Change arg types of svcCreateCodeSet and improve documentation
Since kernel doesn't directly access the LMA, but just does memory
management on them instead, they should be passed as u32 (uptr) instead
of void *.

Also change CodeSetInfo to CodeSetHeader to avoid confusion with
ExHeader types.
2023-02-08 18:17:59 +00:00
TuxSH
a30628058c Implement cdc:CHK service 2023-02-08 00:26:18 +00:00
TuxSH
cb9d682f65 Fix svcGetDmaState
Kernel and official app stubs are buggy, as they read 4 bytes when the
enum is only one byte (meaning 3 garbage bytes).
2023-02-06 17:44:12 +00:00
TuxSH
1de86ea38a Add mcuHwcGetSessionHandle 2023-01-31 17:11:02 +00:00
TuxSH
e253c2c005 errf: implement ERRF_SetUserString & clarify 2023-01-11 23:49:31 +00:00
TuxSH
08b76e2e17 apt: fix dirty homebrew chainload
Fix chainload method used when HM is not launched.

We now wait for custom PM to change our launch flag and ask us to
terminate. We previously had a few issues:
- a potential race condition where we exit before PM changes our
  runflags (not observed)
- a kernel deadlock between ExitProcess and TerminateProcess (observed,
  this is due to Nintendo's lack of barrier in many of their atomics
  code)
- debuggers reporting that we were terminated, instead of exiting
  gracefully (not desirable)
2023-01-09 23:58:32 +00:00
GaryOderNichts
da323fa50b ir: Add IRU_GetSend/RecvFinishedEvent 2022-12-06 12:45:49 +01:00
TurtleP
af5321c78e spaces to tabs 2022-09-25 18:39:09 +02:00
TurtleP
58719f32ac fix ndspGetMasterVol and ndspChnGetMix 2022-09-14 23:52:19 +02:00
TurtleP
ef806d5bd8
add various ndspChnGet* methods (#506) 2022-09-14 19:35:11 +02:00
TurtleP
e6fcbef36c
add various ndspGet* methods (#505) 2022-09-14 19:34:32 +02:00
Ian Chamberlain
b20ac22ab7
Use __tdata_align to align thread local storage (#504) 2022-09-14 19:26:23 +02:00
csnikki
59cf50c201 Include for size_t 2022-08-12 16:45:58 +02:00
ZeroSkill
607f1d1fb6
Fix FSPXI_CreateFile and FSPXI_WriteFile (#496) 2022-06-29 18:19:50 +02:00
Théo B
10cf9bb95a
Mark svcExitProcess as taking no arguments (#499) 2022-06-29 12:37:10 +01:00
Teodor Spæren
813d28ddc4 Implement clock_gettime syscall
This implements the syscalls for `clock_gettime` and `clock_getres`. We
support two clocks: CLOCK_REALTIME and CLOCK_MONOTONIC. I've opted to
use the existing `osGetTime()` code for the realtime clock, because it's
known to work.

For CLOCK_MONOTONIC I've used `svcGetSystemTick()` directly, as it has a
higher resolution. We can ignore the drift and so on, because it's
supposed to be just the number of ticks since last boot.
2022-06-27 20:50:39 +02:00
Théo B
82f821156a
Minor style consistency fix for svcExitProcess (#498) 2022-06-26 17:57:28 +01:00
TuxSH
59e0d7596f Fix PMAPP_TerminateTitle 2022-05-24 19:51:52 +01:00
fincs
d4e08aa2cc
libctru v2.1.1 2022-05-22 16:35:03 +02:00
Dave Murphy
b76a245b79
disable array bounds checking for __tls_start 2022-05-02 15:10:17 +01:00
TuxSH
11686876ac Make sure FPSCR is properly initialized
This is a potentially breaking change as the register was left with an unpredictable/unspecified value.

Config: default NaN mode enabled, flush-to-zero enabled, and round to nearest.
2022-04-12 22:22:56 +01:00
TuxSH
c36d9cc4a6 Provide gspGetSessionHandle and gspLcdGetSessionHandle 2022-04-11 22:55:53 +01:00
TuxSH
cf538b1fa8 Make sure all data is initialized in srv and errf
Prior to system version 11.0, the kernel filled the resulting handle with junk in case of failure, when calling svcConnectToPort, etc.

In some situations libctru could accidentally close valid handles.
2022-04-11 21:15:08 +01:00
Eli Clark
ebb5305188
Fix a typo (NEOPT_IP_INFO comment) (#492) 2022-02-17 09:14:26 +00:00
fincs
4815537048
Add changelog for v2.1.0 2022-01-28 23:46:47 +01:00
Dave Murphy
4d36c74be4 next release is 2.1.0 2022-01-26 22:45:17 +00:00
Michael Theall
8ad7b5a71a Fix huffman decode 2022-01-26 22:41:22 +00:00
Michael Theall
bb9c49b84d Add support for SGR 38 and 48
This supports the escape sequences used by fmtlib
2022-01-26 22:41:22 +00:00
oreo639
2564d708e6 Add 3dslink stdio redirection 2022-01-26 18:16:03 +00:00
Dave Murphy
c83c12357e rework syscalls for devkitARM r57 2022-01-26 18:11:25 +00:00
Pixel-Pop
982be53414 DSP_WriteProcessPipe: Fix documentation typo 2022-01-21 18:08:04 +01:00
LiquidFenrir
5f13628dac add DLC title content-info count and data accessors
Named specially to indicate they require amAppInit instead of amInit
2021-12-21 23:48:33 +01:00
fincs
6360f4bdb1
VRAM allocator enhancements, see details:
- Added proper handling for VRAM banks (A and B, 3 MiB each)
- Allocations no longer cross VRAM bank boundaries
- Added vramAllocAt, vramMemAlignAt
2021-08-26 23:42:34 +02:00
fincs
48967dc417
Use __3DS__ instead of _3DS 2021-08-07 19:13:15 +02:00
Aly Cerruti
1f4669fa4c
Support replacing files in rename for better compatibility with POSIX (#483) 2021-04-16 23:01:40 +02:00
fincs
2a9f86fcbc
Add return value to gspPresentBuffer 2021-04-02 19:22:20 +02:00
fincs
bf06f27a0e
Add gspIsPresentPending 2021-03-31 14:49:07 +02:00
oreo639
4e25fb1d6c Switch to github actions 2021-03-01 03:20:15 +01:00
oreo639
858ef9408c Generate tagfile for use with c3d documentation 2021-03-01 03:20:15 +01:00
oreo639
1fb16e21c2 Correct malformed documentation in enums.h 2021-03-01 03:20:15 +01:00
TuxSH
75b4d1f563
Add SDMMC speed info types, and more clock rates (#480) 2021-02-01 14:05:04 +00:00
TuxSH
4fdc40228a Add ptm:gets, ptm:sets and more ptm service commands 2021-01-12 00:35:24 +01:00
fincs
e996cef24d
libctru v2.0.1 2020-12-19 17:15:52 +01:00
TuxSH
dcf83900b9 gspgpu: fix const correctness issues 2020-12-19 15:48:32 +01:00
fincs
02f516111f
srvpm: Correct the previous sysver check fix 2020-12-08 23:16:29 +01:00
Juan Antonio Sauceda
3cefb61d91 osGetWifiStrength: Fix typo in os.h 2020-08-03 01:30:13 +02:00
Vicki Pfau
d085de370e
cfgu: Add CFG_SystemModel enum (#472) 2020-08-01 11:51:46 +01:00
fincs
4866df79a5
condvar: fix embarrassing typo that prevented it from actually working 2020-07-23 02:45:39 +02:00
fincs
958e0c74ea
Travis is such a dumpster fire 2020-07-16 16:38:47 +02:00
fincs
e70908afc7
Release v2.0.0 2020-07-16 16:12:40 +02:00
fincs
e7b0b82bf6
osGetSystemVersionData: avoid leaking cfgu service on failure 2020-07-16 16:12:12 +02:00
fincs
5872ad60be
errf: use CUR_PROCESS_HANDLE instead of hardcoded number 2020-07-16 16:11:27 +02:00
Nanquitas
c1c93b0880 LightEvent: remove magic numbers 2020-07-15 00:16:16 +02:00
Nanquitas
bc6c097dbb Add LightEvent_WaitTimeout 2020-07-15 00:16:16 +02:00
fincs
3874788e85
gsplcd: It's 2020 and we still have typos in IPC wrapper code 2020-07-14 00:28:40 +02:00
fincs
846b79e5a6
cfgu: Correct CFG_Get/SetConfigInfoBlk2/4/8 parameter type 2020-07-13 21:56:08 +02:00
fincs
bd9e559309
Add gfxScreenSwapBuffers, see details:
- Added the ability to duplicate the left eye image to the right eye
  (allows apps to skip rendering to the right eye framebuffer when
   the 3d slider is set to 0.0)
- Deprecated gfxConfigScreen
2020-07-07 13:06:28 +02:00
fincs
4a9c547d8b
Add CondVar implementation 2020-07-07 12:44:18 +02:00
TuxSH
ef6289f977 Add svcControlPerformanceCounter 2020-07-07 12:43:41 +02:00
TuxSH
1ba8d40069 Add/update DMA svcs 2020-07-06 13:22:18 +02:00
TuxSH
58b30bad06 Reorder svcs and replace some void* params, see details:
- New category: "device drivers" (svc 0x5x)
- Use u32 instead of void* when process handles are required
2020-07-06 13:22:18 +02:00
fincs
577fe60268
archive_dev: Reduce maximum simultaneous opened archives from 32 to 8 in order to conserve memory 2020-07-03 20:24:11 +02:00
fincs
75a7312e40
Add romfsMountFromTitle and refactor os-versionbin.c to use it 2020-07-03 20:20:26 +02:00
fincs
24dded1c79
Remove long-since obsolete hb:HB code 2020-07-03 18:09:14 +02:00
fincs
33a570b1c3
Refactor default heap allocation code, see details:
- Use reslimit svcs to retrieve free mem (suggested by @TuxSH) - this
  removes the hardcoded assumption that the process is in APPLICATION.
- The algorithm for calculating default app/linear heap sizes has been
  tweaked to ensure 32MB of linear heap are available for normal apps
  running on Old3DS consoles under appmemtype 0 (i.e. the default).
- Misc cleanup and error checking.
2020-07-03 18:07:20 +02:00
fincs
da529aed21
romfs_dev: Backport proper multimount system from libnx with some tweaks 2020-07-03 00:24:32 +02:00
fincs
1c7914e2f4
archive/romfs: Reduce TLS usage by sharing buffers + changed archive_rename to use a VLA 2020-07-03 00:24:32 +02:00
fincs
3e1d03aecd
Fix typo in osKernelConfig_s 2020-07-03 00:23:42 +02:00
fincs
83e1f97b5b
Remove superfluous casts in FS_Path usage 2020-07-02 16:34:37 +02:00
fincs
818931b51c
Remove unmaintained cppcheck files 2020-07-02 16:32:58 +02:00
fincs
976d284f3a
Use MemPerm enum instead of magic numbers in svcMapMemoryBlock calls 2020-07-02 00:13:55 +02:00
fincs
4e387679f7
Add structs for kernel/shared pages + related refactor, see details:
- Added osKernelConfig_s/osSharedConfig_s structs
- Added OS_KernelConfig/OS_SharedConfig macros for accessing the pages
- Replaced 0x1FF8nnnn hardcoded addresses with struct accesses
- Added osIsHeadsetConnected function
- Refactored and rewritten RTC time support with the correct algorithm
  (many thanks to @TuxSH for reverse engineering the PTM sysmodule):
  - Fully added and documented the osTimeRef_s structure
    - This replaces the previous internal datetime_t struct type
  - Added osGetTimeRef function:
    - This replaces the previous internal getSysTime function
    - Added missing barrier to the lock free reading algorithm
  - osGetTime rewritten to implement the drift-correction algorithm
    - **This introduces a dependency to __aeabi_ldivmod**
  - __libctru_gtod rewritten to reuse osGetTime
2020-07-01 21:02:22 +02:00
fincs
53cbfc231f
Replace magic numbers with defines for Arm11 userland memory regions; clean up and enhance osConvertVirtToPhys 2020-07-01 20:48:18 +02:00
fincs
dfbfc1564f
os.h: Move MemRegion to svc.h; move osGetMemRegionUsed to header; correct osGetMemRegionUsed/Free return type 2020-07-01 18:11:31 +02:00
fincs
64f29fa024
Fix osStrError (previously it was completely broken...) 2020-07-01 00:21:40 +02:00
fincs
41d0d615f5
ndm: Add NDM_ prefix to enum members in order to avoid name collisions 2020-07-01 00:20:42 +02:00
fincs
9a707b2269
Improve safety of usermode synchronization primitives, see details:
- Added data memory barriers where required to ensure intercore safety
- Changed LightLock to handle 0 during locking instead of silently failing
  (this means trivially initialized/zerofilled LightLocks are now supported)
2020-07-01 00:17:08 +02:00
fincs
19fd446ac5
Add and use svcArbitrateAddressNoTimeout (minor ABI optimization) 2020-06-30 18:45:03 +02:00
piepie62
9974ed1aa3 Add LightSemaphore_TryAcquire and fix Acquire 2020-06-24 00:03:13 +02:00
fincs
8662687a2a
ndsp: Refactor sleep/wakeup code for maintainability/accuracy reasons 2020-06-23 00:36:21 +02:00
fincs
03c41754e8
ndsp: Make wavebuf handling more robust (and fix glaring omissions...) 2020-06-22 22:47:53 +02:00
fincs
2ff08fbac8
synchronization.h: Add __dmb() intrinsic 2020-06-22 22:08:21 +02:00
fincs
b93e7f19bf
Refactor DSP<->APT interaction, see details:
- DSP wrapper is now in charge of handling sleep/awake/cancel events
  - Added DSP hook mechanism (similar to APT hook)
  - The DSP component now gets automatically unloaded/reloaded as needed
- NDSP now uses DSP hook instead of APT hook to manage lifetime
  - Moved sleep/wakeup component management logic into NDSP
- APT now calls into DSP wrapper in order to arbitrate access to the DSP
  - Launching libapplets no longer relinquishes DSP rights - this means
    music can now be played in the background during libapplet activity
2020-06-22 00:34:38 +02:00
Ezekiel Bethel
b559d93eda
fix return value of romfs_stat for non-existent files/directories (#466) 2020-06-18 10:58:39 +01:00
fincs
bfc6ea48fb
gfx: Avoid graphical glitches after deinitialization 2020-06-14 01:20:46 +02:00
fincs
bf55423903
gspgpu: Add gspHasGpuRight 2020-06-14 01:19:13 +02:00
fincs
5ac710a0a2
console: Adjust for wide mode 2020-06-13 22:49:52 +02:00
fincs
d521c99769
gfx: Add support for the top screen's 800px high resolution mode (!!!) 2020-06-13 22:48:36 +02:00
fincs
09d629aa85
gspPresentBuffer: stride is u32 2020-06-13 21:57:09 +02:00
fincs
6ef91576ae
Overhaul gspgpu/gfx code, see details:
- GSPGPU changes:
  - gspInit now properly initializes the event queue, GSP shared memory
    and first-time initialization - previously this was done in gfxInit.
  - Removed gspInitEventHandler/gspExitEventHandler in line with above.
  - Added gspPresentBuffer for pushing a framebuffer to the internal
    GSP swap queue (previously this was an internal function in gfx.c).
  - Added defines for screen IDs and screen dimensions.
  - Removed sharedGspCmdBuf param from gspSubmitGxCommand (now uses
    the correct GSP shared memory address automatically).
  - Removed gxCmdBuf global variable (no longer needed as per above).
  - Removed GSPGPU_REBASE_REG (leftover from early 3DS homebrew).
- GFX changes:
  - Documentation overhaul and code cleanup.
  - Simplified implementation using the enhanced GSPGPU service wrapper.
  - Top left/right framebuffers now form a single allocation instead of
    being split into two separate allocations.
  - Fixed LCD configuration mode when framebuffers are on VRAM.
  - Removed the ability to forcefully swap the screens: gspPresentBuffer
    is now always used (i.e. GSP shared mem). The 'immediate' parameter
    of gfxConfigScreen now does nothing, and gfxSwapBuffers/Gpu now do
    the same thing.
  - Removed gfx{TopLeft,TopRight,Bottom}Framebuffers global variables
    (please use gfxGetFramebuffer instead as originally intended...)
2020-06-13 20:08:37 +02:00
oreo639
26f5f7eb33 Fix travis 2020-06-13 12:32:24 +02:00
fincs
9c1c847388
Introduce syncArbitrateAddress/WithTimeout (replaces __sync_get_arbiter) 2020-06-12 20:40:47 +02:00
fincs
528f8feb0b
Add gspGetBytesPerPixel (replaces internal function)
Also fixes GSPGPU_FramebufferFormat's name
2020-06-12 19:24:15 +02:00
fincs
6c0f7ac99c
threadCreate: correct misleading parameter name 2020-06-12 14:31:42 +02:00
fincs
f49efc3cc7
Add support for userAppInit/userAppExit (backported from libnx) 2020-06-12 14:16:46 +02:00
fincs
8e3c9f9784
Minor internal cleanup 2020-06-12 14:15:18 +02:00
fincs
1442eef9e4
Update travis config again 2020-06-11 20:01:32 +02:00
fincs
ea57fb8821
apt: Revamp chainload handling, see details:
- Added aptClearChainloader (clears pending chainloads)
- Added aptSetChainloaderToSelf (reboots to self, i.e. "soft-reset")
- Internal refactoring
2020-06-11 16:28:57 +02:00
fincs
80fad02255
Add travis badge 2020-06-11 03:43:39 +02:00
fincs
08bff23736
Attempt to fix travis 2020-06-11 03:38:42 +02:00
fincs
5986713066
apt: Refactor sleep/home state handling to be more intuitive, see details:
- Added functions for checking APT state:
  - aptIsActive
  - aptShouldClose
  - aptShouldJumpToHome
  - aptCheckHomePressRejected (replaces aptIsHomePressed)
- Added functions for handling incoming requests:
  - aptHandleSleep
  - aptHandleJumpToHome
- Added aptJumpToHomeMenu (callable anytime) because why not
- aptMainLoop is now aptHandleSleep/JumpToHome + return !aptShouldClose
- APTHOOK_ONEXIT is now called during aptExit
- Internal refactoring
2020-06-11 03:02:24 +02:00
fincs
b48b5da211
apt: Add APT_LockTransition, use it in aptWaitForWakeUp 2020-06-10 21:46:48 +02:00
fincs
6ce690828c
apt: Remove aptLaunchLibraryApplet's return value/hidden aptMainLoop call 2020-06-10 20:14:01 +02:00
fincs
ac8656f8b2
apt: Implement screen capture for libapplet transitions (+ related cleanup) 2020-06-10 19:47:17 +02:00
fincs
7171a87d53
Miscellaneous APT fixes and cleanup, see details:
- APT parameter handling now follows official sw a bit more closely
  (with the APT thread acting as a filter which then relays the
   status to the main thread using a LightEvent)
- RUNFLAG_APTREINIT (hax 2.x) handling code has been simplified and
  made (hopefully) more robust
- Fixed sleep handling when the app is inactive (i.e. app is suspended)
- APT debug callback now guarded by an #ifdef (LIBCTRU_APT_DEBUG)
- Removed old Citra response cmdheader workaround
- Other miscellaneous fixes I probably forgot to talk about
2020-06-10 02:08:01 +02:00
fincs
59b8fd8283
apt: Simplify event thread exit handling code 2020-06-09 18:01:11 +02:00
fincs
36b618e3bb
ndspChnReset: Bump syncCount in order to force the DSP to reset the channel 2020-06-08 00:24:24 +02:00
fincs
beaebaaf26
Update readme (again) with clarification 2020-06-02 18:01:22 +02:00
fincs
34f690d9d0
Update documentation url 2020-06-02 17:31:47 +02:00
mtheall
80be51e93b
Fix decompress out-of-bounds access (#463) 2020-06-01 09:03:12 +01:00
Dave Murphy
8f06d03ca6 update Changelog and version for next release 2020-05-27 15:41:32 +01:00
Dave Murphy
26e4f20078 increase decompress buffer size
speeds up decompression when user hasn't increased file buffer
2020-05-27 15:41:32 +01:00
Michael Theall
59e12a1b5e Fix stat for romfs:/ 2020-05-27 13:02:35 +02:00
Glazed_Belmont
2e48185aed
Fix the typo for consoleClear() (#460)
Changed screan to screen
2020-05-26 01:48:11 +01:00
Dave Murphy
aefdcf203d implement lstat with stat
fat32 has no symlinks to follow or not follow
2020-05-25 01:37:34 +01:00
TuxSH
0053d8d076 Add ptm rtc time commands 2020-05-17 22:24:15 +02:00
TuxSH
e3be4b8678 Add sleep state FSM handling service commands 2020-05-17 17:45:52 +02:00
TuxSH
1bafb08f34 Add hidKeysDownRepeat 2020-05-14 22:25:16 +02:00
TuxSH
69483a473a Revamp mappableAlloc 2020-05-14 00:30:53 +02:00
TuxSH
c9326f6bce
hid: add hidWaitForAnyEvent, allow user to override irrst usage check (#454) 2020-05-13 23:09:55 +02:00
Dave Murphy
e86e906895 next version is 1.8.0 2020-05-10 00:20:46 +01:00
Dave Murphy
48f330e56a add changelog entry for 1.8.0 2020-05-09 23:49:36 +01:00
Dave Murphy
ed59061172 add changelog entry for 1.7.0 2020-05-09 23:47:43 +01:00
TuxSH
9d27eb80de APT workaround when Home Menu is not launched, etc. 2020-05-10 00:06:50 +02:00
TuxSH
8d64007d70
Weaken more init/env functions (#451) 2020-05-09 18:22:51 +01:00
TuxSH
65ff0a1fcc Change allocateHeaps logic to properly handle appmemtype 5 2020-05-09 17:41:26 +02:00
fincs
1389fcdfcd
gdbhio: Avoid using reserved st_* identifiers for custom types 2020-05-08 03:29:05 +02:00
fincs
b03b64dd09
Add MEMPERM_READWRITE and MEMPERM_READEXECUTE 2020-05-08 03:16:30 +02:00
Chris Feger
750bceebf2
Add FSPXI interfaces (#446) 2020-05-08 02:20:48 +02:00
TuxSH
b161b7e578 Add GSPGPU_ResetGpuCore 2020-05-07 00:14:02 +02:00
TuxSH
51c0bdfc90 Add gpu hw init on (0x2A07) 2020-05-07 00:14:02 +02:00
TuxSH
6f34257b57 Make initSystem and __ctru_exit weak. Use asm macros 2020-05-06 21:50:20 +02:00
fincs
92ddd9e9b3
gfxWriteFramebufferInfo: use correct atomic update code 2020-05-04 21:17:21 +02:00
fincs
98664af53c
Clean up and optimize LightLock_Lock 2020-05-04 18:34:13 +02:00
TuxSH
fddc517a6b Fix srv/srvpm sysver checks:
- Kernel major version is 3 on SAFE_FIRM
- osGetFirmVersion() is not always equal to osGetKernelVersion()
2020-05-02 14:19:48 +02:00
piepie62
1ca796b3a3 Add invalid glyph index protection 2020-04-24 12:36:23 +02:00
Chris Feger
175dd62a90
Add archive STDIO device driver (#443) 2020-04-15 23:06:36 +01:00
zhupengfei
87734ae8d9 cam: Fix CAMU_GetLatestVsyncTiming
The previous implementation was wrong and result in a guaranteed prefetch abort
2020-04-16 00:05:25 +02:00
Lioncash
7956f6ba24 services/mvd: Remove redundant conditional in mvdstdRenderVideoFrame()
This condition is already checked further up in the function.
2020-04-15 09:13:18 +01:00
Lioncash
0e4d8fbd05 servicers/fs: Remove redundant conditional in FSUSER_OpenArchive()
This is already checked against at the beginning of the function.
2020-04-15 09:13:18 +01:00
Patrik Rak
6bca5af849
Make the FIONBIO ioctl actually work. (#441)
The fcntl needs the original `sockfd`, not the remapped one.
2020-04-15 09:09:17 +01:00
Patrik Rak
8566366b02 Fix dspInit() error handling in ndspInit().
The early return after dspInit() failure obviously keeps the refcount increased and the component loaded. This change properly unwinds all state changes.
2019-10-04 14:36:06 +02:00
LiquidFenrir
8acc1871bc Add AC commands that allow forcing a wifi connection (#438) 2019-09-21 02:49:41 +02:00
fincs
751dd3b42d Release 1.6.0 2019-06-28 17:21:14 +02:00
TuxSH
ed7674626e Implement Luma3DS gdb hio (#433) 2019-06-23 18:06:47 +01:00
Dave Murphy
754c334c29
use temp var for misaligned struct member (#437) 2019-06-06 00:08:49 +01:00
WinterMute
e842cfd011 print string when it's not null 2019-06-05 15:30:06 +01:00
Kartik
188d175579 Fix select() 2019-05-16 18:14:54 +02:00
Chris Feger
309c3f1d7b Fix a possible null pointer issue (#434) 2019-05-14 11:03:24 +01:00
Oreo639
d3ea737071 Add miiSelector configuration functions (#429) 2019-05-04 01:40:00 +02:00
Oreo639
c550a22259 Fix macro PACKED being displayed as variable name 2019-05-04 01:38:29 +02:00
Oreo639
67933816ba Improve travis script 2019-04-30 13:56:50 +02:00
Oreo639
59b71196ac Fix blocking and add aptIsHomePressed 2019-04-25 02:52:00 +02:00
Alex Taber
f919af3182 Rename home_allowed to aptHomeAllowed 2019-04-25 02:52:00 +02:00
LiquidFenrir
9b4ac1118d Allow blocking HOME button
Signed-off-by: Alex Taber <alexftaber@gmail.com>
2019-04-25 02:52:00 +02:00
hax0kartik
d0b6343342 Do not include 3ds.h within ctrulib headers 2019-04-01 17:38:14 +02:00
hax0kartik
d4036d97ef Add Mii struct 2019-04-01 17:38:14 +02:00
Oreo639
fd1006b682 Update travis to build Doxygen. 2019-03-28 12:38:40 +01:00
Chris Feger
2750c4a70b Rework font API to support loading fonts other than the shared system font (#416) 2019-03-28 02:32:07 +01:00
TuxSH
09688ea6fc PM services overhaul 2019-03-28 01:04:02 +01:00
TuxSH
8ffc9461ea LOADER_RegisterProgram: use FS_ProgramInfo 2019-03-28 00:44:43 +01:00
TuxSH
0ed1f2beb2 IPC_Desc_CurProcessHandle => IPC_Desc_CurProcessId 2019-03-28 00:44:32 +01:00
TuxSH
7663a701c0 Add undocumented N3DS PM launch flags 2019-03-24 23:26:43 +01:00
TuxSH
0536cc5493 Loader bugfixes 2019-03-22 14:26:51 +01:00
fincs
5fd623da44 Fix typo in svc.s 2019-03-21 23:06:12 +01:00
Dave Murphy
da0af223a2
Update URL for devkitPro installers 2019-03-17 23:38:03 +00:00
TuxSH
ffba52bcd0 Add PM launch flags 2019-03-17 20:46:04 +01:00
TuxSH
79ee260c15 Implement PxiPM 2019-03-11 21:06:34 +01:00
TuxSH
dacacfa403 Implement fs:REG 2019-03-11 21:06:34 +01:00
fincs
550793b262 Minor text fixes 2019-03-10 21:14:25 +01:00
Slattz
67f10f0ba9 Fix frdGetSessionHandle declaration 2019-02-12 12:28:10 +01:00
Dave Murphy
79a77cd862 add SO_BROADCAST 2019-01-18 15:23:53 +00:00
fincs
b9b4d486a3 Fix GPUCMD_Add with more than 256 words (thanks to iMackshun for testing) 2019-01-18 00:38:47 +01:00
fincs
5f3b369a81 Release 1.5.1 2019-01-02 00:36:07 +01:00
Joel
a482822fb8 Fix a few FRD commands and minor consistency changes (#411) 2019-01-02 00:35:12 +01:00
fincs
14fdf2dee4 Update doxygen binary url for Travis 2019-01-02 00:26:28 +01:00
fincs
56d3b0b76e Add gas-related GPU definitions 2019-01-02 00:18:47 +01:00
Sean Purcell
64bdf022a8 Fix missing include <3ds/types.h> (#414) 2018-10-23 16:04:00 +01:00
Lázaro Vieira
3810a5586b FRD update (#409)
Fix Mii struct padding + some changes for consistency
Documentation update
2018-08-09 15:08:41 +02:00
Kartik
c579e745a8 Add more friend functions (#408) 2018-08-05 15:56:26 +02:00
Pirater12
2c1f84406e UTF16-to UTF8 Translation 2018-07-21 17:18:09 +01:00
Joel16
18267ef6fb Initial bring up of the Friend Service 2018-07-21 17:18:09 +01:00
Dave Murphy
d1ca5c4ea6 implement nanosleep for devkitARM r49
(cherry picked from commit fba44c189e568df13573a9e119e63dbd718424c6)
2018-06-13 14:22:50 +01:00
Dave Murphy
510504a853
Use Docker for builds (#405) 2018-05-22 01:35:54 +01:00
Dave Murphy
fcf9ca767b allow parallel build 2018-05-13 00:23:25 +01:00
fincs
5450b2bee5 Release 1.5.0 2018-05-12 21:21:02 +02:00
Michael Theall
cc22550296 Add decompressHeader 2018-05-12 13:56:29 +02:00
Michael Theall
1165b4cb8b Add decompression routines 2018-05-12 13:56:29 +02:00
Dave Murphy
caacf37594 add DESTDIR for packaging 2018-05-11 02:50:58 +01:00
Dave Murphy
f214b2e535 fix for gcc 8.1.0 2018-05-11 02:49:39 +01:00
fincs
74b8aa00cd Const correctness in osTickCounterRead 2018-03-17 18:11:36 +01:00
Sono
c1cee4a115 Added and adjusted clock speed constants 2018-03-17 18:09:14 +01:00
Pirater12
555f31b35e Add more PM:App functions 2018-03-10 17:04:38 +01:00
Joel16
8840ebf813 Add ACU_Proxy* functions as welll as error code functions 2018-03-10 17:03:25 +01:00
Pirater12
a087e33414 Add NS_RebootSystem 2018-03-09 12:22:38 +01:00
fincs
a4210af6c2 Update devkitARMupdate.pl URL for Travis CI 2018-03-02 23:55:31 +01:00
Joel
6dcbee7f4c Add more CFGI SecureInfo functions (#393) 2018-02-16 01:48:31 +01:00
Kartik
29418f4d3d Add NS_TerminateTitle() (#390) 2018-01-22 02:08:36 +01:00
Kartik
2158f71eb2 Add timeout in NS_TerminateProcessTID() (#389) 2018-01-15 12:45:05 +01:00
TuxSH
c598c445cd Implement per-thread non-blocking behavior for srvGetServiceHandle...
implement srvWaitForPortRegistered and srvIsPortRegistered as well.
2018-01-14 21:18:01 +01:00
Joel16
abf8064771 Add missing enums 2018-01-13 18:47:25 +01:00
Joel
52be537b48 Add more ndm:u functions. (#386) 2018-01-12 13:34:56 +01:00
TuxSH
fdf31f7556 Multiple srv:pm bugfixes 2018-01-07 01:35:19 +01:00
Lioncash
4ceebb8b44 gfx: Mark gfxSetFramebufferInfo and gfxWriteFramebufferInfo as static 2018-01-03 17:10:48 +01:00
Joel
3bbd2dca16 MCU service consistency and a couple more functions (#381)
Also added MCUHWC_GetFwVerHigh and MCUHWC_GetFwVerLow
2018-01-01 16:42:46 +01:00
Lioncash
c941b0d2d2 services: Add missing void keyword in parameter lists to signify no arguments 2018-01-01 16:41:45 +01:00
Lioncash
3a1a501867 shaderProgram: correct array index in shaderProgramSetGshInputPermutation() 2017-12-28 21:53:28 +01:00
Joel
6f64dee330 Add a few more ACU functions (#379) 2017-12-01 17:58:08 +01:00
Kartik
65673fd3f3 Added more mcuHwc functions. (#378) 2017-11-16 00:18:07 +01:00
Kartik
8e2d82ae9a Fix page being not built by doxygen 2017-11-16 00:13:41 +01:00
fincs
fc67757066 fontCalcGlyphPos: Correct vertical texture coordinates 2017-11-07 23:06:20 +01:00
Joel
632f9866e6 Add a few more CFGI functions (#380)
* CFGI_SecureInfoGetSerialNumber
* CFGU_IsNFCSupported (IsFangateSupported)
* CFGI_GetLocalFriendCodeSeed
* CFGI_GetLocalFriendCodeSeedData
2017-10-28 12:12:16 +03:00
fincs
53c42003f3 Release 1.4.0 2017-09-23 18:12:36 +02:00
fincs
213f586c7d Update doxygen to 1.8.11 2017-09-23 18:10:46 +02:00
fincs
7c348aa3ad Add missing examples to 3ds.h 2017-09-23 18:10:46 +02:00
Joel
25123ba057 Add more CFGI functions (#376) 2017-09-23 18:07:50 +02:00
Joel
04bde1de19 More AM_Delete functions (#375) 2017-09-23 17:42:37 +02:00
Kartik
d6a628b7d3 Add mcu::HWC service (#373) 2017-09-23 16:03:37 +02:00
phijor
aaa92f619c Add Mii selector applet (appletEd) (#372) 2017-09-23 15:48:08 +02:00
Joel
fa6eb5db9e More GSPLCD and GSPGPU functions. (#371) 2017-09-23 01:59:26 +02:00
LIT
8196e383c3 Typo. 2017-09-13 14:37:17 +01:00
fincs
0d950af680 Remove deprecated GPUCMD functions 2017-08-29 00:39:56 +02:00
fincs
967b0223ad Correct error in GPU_LIGHTPERM (reported by @wwylele) 2017-08-27 12:25:32 +02:00
TuxSH
010dde085b Add Loader service commands (#370) 2017-08-21 15:55:54 +01:00
TuxSH
f132a7a2a9 Implement light semaphores (#369) 2017-08-01 14:35:45 +01:00
TuxSH
4dafd78e26 Fix const-correctness (#368)
make svcWaitSynchronizationN and svcReplyAndReceive const correct
2017-07-31 14:33:20 +01:00
TuxSH
6a6dc3be4a Add and use enum ResourceLimitType (#367) 2017-07-31 14:21:03 +01:00
TuxSH
532fbef44f Fix srv:pm handling for pre-7.x system versions (#365) 2017-07-31 14:12:51 +01:00
TuxSH
e1ddc74c1c Add exheader.h (#366) 2017-07-31 14:12:16 +01:00
Joel
f05c56435d Implement GSPLCD_SetBrightness and GSPLCD_SetBrightnessRaw (#363) 2017-07-29 22:55:52 +01:00
Dave Murphy
57152061b0 remove devkitARM version. Add link to installer 2017-07-28 01:18:03 +01:00
Dave Murphy
46b29af821 fix version title 2017-07-13 21:12:22 +01:00
Dave Murphy
5843fdcc0d release 1.3.0 2017-07-13 21:08:10 +01:00
Dave Murphy
3cea84f315 fix whitespace 2017-07-13 20:59:56 +01:00
Michael Theall
5d245e5cc8 Fix CUP (cursor position) escape code 2017-07-12 23:29:49 -05:00
HiddenRambler
31ca6f5c53 add nfcStartOtherTagScanning Old3DS compatibility. 2017-07-13 18:11:49 +01:00
TuxSH
bc87466400 srv: code bugfixes:
- Fix srvPublishToSubscriber documentation
- Fix handling of service/named port names of length 8
- Fix srvRegisterPort
2017-07-13 16:12:09 +01:00
Michael Theall
41c1fee88e Fix warning when compiling with C89/90 2017-07-10 23:43:10 -05:00
Kartik
8d177742ae Add PTMU_GetAdapterState (#361) 2017-07-10 14:43:24 +02:00
TuxSH
49f99a0650 Implement privileged resource limit SVCs 2017-07-07 13:08:53 +01:00
TuxSH
4d8c2ea9f5 Implement svcSetGpuProt and svcSetWifiEnabled 2017-07-07 13:08:15 +01:00
Thomas Schneider
325dbf02b7 include svc.h for ResetType 2017-07-04 14:02:08 +01:00
fincs
0475b59e12 nfcInit(): wait for NFC sysmodule to initialize 2017-06-29 18:42:08 +02:00
fincs
be79735c31 Update documentation autobuild token, yet again 2017-06-26 17:29:32 +02:00
Yuri Kunde Schlesner
eb062ce0a9 Add svcCreateSessionToPort 2017-06-26 15:51:03 +01:00
Yuri Kunde Schlesner
1e6df47adb Add svcCreateSession 2017-06-26 15:51:03 +01:00
Kartik
ff559d2a90 Fix compilation issue caused due to errorConf. (#355) 2017-05-21 22:07:33 +02:00
fincs
94aabe35f3 Rename debugDevice_3DMOO to debugDevice_SVC 2017-05-14 11:49:21 +02:00
TuxSH
8778d8c5d6 Add support for user-specified exception handlers 2017-05-14 11:41:24 +02:00
Dave Murphy
e43d368fbc PATH_MAX is max length of fixedpath string 2017-05-04 21:33:53 +01:00
fincs
1ed97e8ba2 Implement RUNFLAG_APTCHAINLOAD 2017-04-14 22:01:13 +02:00
fincs
3f7a4d227d Add GPU_FOGMODE, GPU_GASMODE and GPU_GASLUTINPUT 2017-04-08 12:39:37 +02:00
Dave Murphy
e64d859d36 separate release & debug dependencies 2017-04-06 16:23:01 +01:00
fincs
708ece10df Fix makefile dependency rule inclusion 2017-04-05 19:26:27 +02:00
Kartik
8ada484dad Implement HTTPC:AddPostDataBinary (#352) 2017-04-05 15:49:05 +02:00
Kartik
422c3c3272 Implement error applet (#343) 2017-04-04 17:49:37 +02:00
Dave Murphy
82049e7fc2 use debug defines 2017-04-03 19:24:34 +01:00
Dave Murphy
28827803ce build debug and release versions 2017-04-03 16:24:09 +01:00
Dave Murphy
4f98439f86 Merge pull request #350 from TuxSH/patch-cfi
Add call frame information for SVC wrapper, fix build issue in uds.c
2017-04-03 11:16:52 +01:00
Joel
b3742567d4 Implement GSPLCD::GetBrightness (#351)
* Implement GSPLCD::GetBrightness

* Split input and output params
2017-04-02 22:55:37 -05:00
TuxSH
eb681db5af Fix -Werror=maybe-uninitialized in uds.c...
...when building with -Os/-Og
2017-04-02 16:39:54 +02:00
TuxSH
cdababc38d Add call frame information for SVC wrappers 2017-04-02 16:17:10 +02:00
fincs
f4232926c3 Add GX command queue system for batching GX commands 2017-03-26 19:48:34 +02:00
fincs
d9933cb2db Prevent race condition in gfxWriteFramebufferInfo with atomic instructions 2017-03-26 19:39:01 +02:00
fincs
d8374c2883 Refactor gpu.h/gpu.c, see details:
- Added GPUCMD_Split for splitting the command buffer
  (and beginning a new command list within the same buffer)
- Deprecated GPUCMD_Finalize/Run/FlushAndRun:
  - Use GPUCMD_Split + GX_ProcessCommandList instead
- Turned GPUCMD_SetBuffer/SetBufferOffset/GetBuffer into inlines
- GPUCMD_Add: svcBreak on cmdbuf overflow
2017-03-26 19:37:25 +02:00
fincs
929468371a Increase priority of GSP event thread 2017-03-26 19:32:13 +02:00
fincs
c44da0636a Correct GPU_PROCTEX_LUTID definition 2017-03-15 16:40:06 +01:00
TuxSH
10cb9babc9 Fix debug-related definitions in svc.h 2017-03-14 14:07:43 +00:00
TuxSH
064f9fdf9e Implement svc 0x04, 0x06, 0x53 2017-03-14 14:07:43 +00:00
TuxSH
636dfb2f1d Fix typo in definition of struct FpuRegisters 2017-03-06 19:57:04 +01:00
TuxSH
65171be4d8 Fix ThreadContext definition
Its correct size is 0xcc bytes, not the 8-byte aligned 0xd0
2017-03-06 19:57:04 +01:00
TuxSH
e5fc424414 Amend latest PR/commit 2017-03-05 16:48:09 +01:00
TuxSH
cc2928427b Fix svc(Un)mapProcessMemory typo/misconception 2017-03-04 21:55:24 +01:00
FenrirWolf
ec0b9d8033 Return zero when writing zero bytes (#344) 2017-03-02 01:18:58 -06:00
TuxSH
eeacb2faa9 ERRF_ExceptionInfo: fix typo 2017-03-01 20:45:33 +00:00
Fenrir
da97a8802c Add threadDetach function 2017-03-01 20:45:12 +00:00
TuxSH
c6c994ca60 Make ERRF_ExceptionInfo attributes more explicit 2017-03-01 11:33:51 +00:00
TuxSH
2edbc6fe2e Fix typo in errf.h 2017-03-01 10:35:05 +00:00
TuxSH
492fffd445 Fix DebuggerBreakExceptionEvent definition 2017-02-23 21:29:30 +01:00
Dave Murphy
c195a19683 update changelog 2017-02-23 11:49:48 +00:00
Dave Murphy
9b99862696 new version number for next release 2017-02-20 06:47:22 +00:00
Dave Murphy
b3ed60d123 default to "unsafe" file write. Unable to replicate failure conditions. 2017-02-20 06:41:42 +00:00
fincs
112163e580 Clarify threadFree usage in documentation 2017-02-17 16:08:16 +01:00
yellows8
cffb347407 Added support for the NFC functionality implemented with system-version 10.0.0-X. 2017-02-16 20:27:37 -05:00
fincs
991eb2357b Add TickCounter for measuring performance 2017-02-16 14:35:06 +01:00
fincs
97d01a7325 GPUCMD_Add: allow NULL for adding zerofilled parameter data 2017-02-16 13:48:40 +01:00
fincs
093b3441ea Added (linear/vram/mappable)GetSize for retrieving allocated buffer size 2017-02-16 13:44:19 +01:00
TuxSH
95c4a3e6ef Fix ERRF_ExceptionData definition
This "padding" field is not needed (the struct is used within an union when sent to ErrDisp), and is also undesirable as the kernel push an instance of `ERRF_ExceptionData` (which is a struct of size 0x5C, and not 0x60) on the user stack under certain conditions.
2017-02-16 13:39:20 +01:00
FenrirWolf
fb0ef2a459 correct ticks per msec/usec (#336) 2017-02-13 01:02:21 +00:00
fincs
7be0b5b026 Add GPU_TEXFACE enumeration 2017-02-11 23:04:03 +01:00
Michael Theall
97d6149e3e Avoid double promotion 2017-02-08 22:51:57 -06:00
AriA99
e06c8e542f Add nim:s client implementation. 2017-01-27 19:06:28 +01:00
Slimfr01
6eb53df563 update NFC_AmiiboConfig struct
adjust and rename NFC_AmiiboConfig struct members to better reflect their purpose.
2017-01-20 18:14:16 +00:00
200 changed files with 18483 additions and 9202 deletions

21
.github/workflows/build.yaml vendored Normal file
View File

@ -0,0 +1,21 @@
name: Build libctru
on:
push:
branches: [ master ]
pull_request:
jobs:
build:
name: Test build
runs-on: ubuntu-latest
container:
image: 'devkitpro/devkitarm'
steps:
- uses: actions/checkout@v2
with:
persist-credentials: false
- name: build
run: make -C libctru

40
.github/workflows/doxygen.yaml vendored Normal file
View File

@ -0,0 +1,40 @@
name: Build documentation
on:
push:
tags: [ v* ]
jobs:
build:
name: Build documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
persist-credentials: false
- name: Get current tag
id: vars
run: echo ::set-output name=tag::${GITHUB_REF/refs\/tags\//}
- name: Set up Doxygen
run: sudo apt-get install -y doxygen
- name: Display Doxygen version
run: echo "Doxygen version $(doxygen -v)"
- name: Build documentation
run: |
git clone --branch=master --single-branch --depth 1 https://github.com/devkitPro/3ds-examples examples
cd libctru
CTRU_VERSION=${{ steps.vars.outputs.tag }} doxygen Doxyfile
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@3.7.1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages
FOLDER: libctru/docs/html
CLEAN: true
SINGLE_COMMIT: true

View File

@ -1,47 +0,0 @@
language: c
sudo: false
#Cache devkitArm and doxygen
cache:
directories:
- /home/travis/devkitPro
- /home/travis/doxygen/doxygen-1.8.10/bin
before_install:
# Travis has an OLD doxygen build, so we fetch a recent one
- export DOXY_BINPATH=/home/travis/doxygen/doxygen-1.8.10/bin
- if [ ! -e "$DOXY_BINPATH/doxygen" ]; then mkdir -p ~/doxygen && cd ~/doxygen; fi
- if [ ! -e "$DOXY_BINPATH/doxygen" ]; then wget http://ftp.stack.nl/pub/users/dimitri/doxygen-1.8.10.linux.bin.tar.gz; fi
- if [ ! -e "$DOXY_BINPATH/doxygen" ]; then tar xzf doxygen-1.8.10.linux.bin.tar.gz; fi
- export PATH=$PATH:$DOXY_BINPATH
# Prepare devkitArm update
- export DEVKITPRO=/home/travis/devkitPro
- export DEVKITARM=${DEVKITPRO}/devkitARM
- mkdir -p $DEVKITPRO
- cd $DEVKITPRO
- wget -N http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/devkitARMupdate.pl
-
install:
- cd $DEVKITPRO
# Install or update devkitArm if it's cached
- perl devkitARMupdate.pl
- cd $TRAVIS_BUILD_DIR
env:
global:
- secure: "flMuk/VTG6xhMfazYKyIi+0yHceJkPRLg5igm3zuUDPeMhFxYCtwJe44Uu9YrTj5VqXmfbIC27q/I68lia6Q+A/WvlIRYo1BO/Gh8sTT65hYe9KHODdel01tODHe2jmf80fskdowREj60etrwHYdP75O4ntn9A/PI9hZ5s/yrEQ="
script:
- cd $TRAVIS_BUILD_DIR/libctru
- make
after_success:
- cd $TRAVIS_BUILD_DIR
- #Build the doxygen files and upload to GH pages
- git config --global user.email "travis@travis-ci.org"
- git config --global user.name "TravisCI-DocBuilder"
# Build the doxygen documentation and push it to gh-pages if this is a tagged release
- sh exportdoc.sh

View File

@ -1,5 +1,340 @@
# Changelog
## Version 2.4.0
- **Added full support of all QTM services**, with extensive documentation and technical details in `qtm.h` and `qtmc.h`** (breaking change); examples have been updated for this
- Added MCUHWC_SetInfoLedPattern
- Added ndspChnGetFormat
- Fixed PTMSYSM_CheckNew3DS
- Fixed NDMU_QueryStatus
- Fixed a few service commands improperly deserializing boolean output
- Fixed documentation of ACU_GetWifiStatus and ACU_SetAllowApType
- Fixed shaderInstanceInit to initialize all fields
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## Version 2.3.0
- Fix typo in docs by @DeltaF1 in https://github.com/devkitPro/libctru/pull/525
- Add GPU_DOT3_RGBA texture combiner function by @oreo639 in https://github.com/devkitPro/libctru/pull/528
- FSUSER_GetLegacyBannerData: Fix documentation typo by @Tekito-256 in https://github.com/devkitPro/libctru/pull/526
- Add CTR_ prefix to ALIGN,PACKED,DEPRECATED macros by @glebm in https://github.com/devkitPro/libctru/pull/532
- Buffer console control sequences by @piepie62 in https://github.com/devkitPro/libctru/pull/522
- Prevent CPU from postponing threadOnException memory writes
- Add SSID-related ac:i functions
- ACI_LoadNetworkSetting, ACI_GetNetworkWirelessEssidSecuritySsid and acGetSessionHandle.
- Prevent double call of destructors on exit.
- Added experimental support for standard threading APIs (pthread, C threads, C++ std::thread)
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## New Contributors
- @DeltaF1 made their first contribution in https://github.com/devkitPro/libctru/pull/525
- @Tekito-256 made their first contribution in https://github.com/devkitPro/libctru/pull/526
- @glebm made their first contribution in https://github.com/devkitPro/libctru/pull/532
## Version 2.2.2
- archive_dev: Ensure path separator for local path
- adjust struct hostent for compatibilty
## Version 2.2.1
- add `_SOCKLEN_T_DECLARED`
## Version 2.2.0
- apt: add deliver arg support to chainloader
## Version 2.1.2
- Added cdc:CHK service wrappers
- Added support for `clock_gettime` (#495)
- svc: Fixed svcGetDmaState writing out-of-bounds data
- svc: Changed svcCreateCodeSet address parameters to pointer-sized integers, improve documentation
- fspxi: Fixed FSPXI_CreateFile and FSPXI_WriteFile (#496)
- ndsp: Added various ndspGet\* and ndspChnGet\* methods (#505, #506, #507)
- ir: Added IRU_GetSend/RecvFinishedEvent (#513)
- errf: Added ERRF_SetUserString and clarify documentation
- mcuhwc: Added mcuHwcGetSessionHandle
- apt: Fixed dirty homebrew chainload bug (used when Home Menu hasn't been started)
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## Version 2.1.1
- FPSCR is now initialized with a predictable value in all threads (including the main thread).
- Added gspGetSessionHandle and gspLcdGetSessionHandle.
- Fixed bugs related to uninitialized data in srv/errf service wrappers.
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## Version 2.1.0
**The #define for the 3DS platform has been changed to `__3DS__` (previously it was `_3DS`) - please update your Makefiles and your code**
### graphics
- Refactored VRAM allocators:
- Added proper handling for VRAM banks (A and B, 3 MiB each)
- Allocations no longer cross VRAM bank boundaries
- Added vramAllocAt, vramMemAlignAt
- Add gspIsPresentPending.
- Add return value to gspPresentBuffer.
- libctru console now supports SGR 38 and 48 escape sequences (needed by fmtlib).
- Fixed GPU_TEXFACE enum.
### filesystem
- Changed rename to replace existing files, for better compatibility with POSIX (#483)
- Added SDMMC speed info types, and more clock rates (#480).
### miscellaneous
- Added support for 3dslink stdio redirection (#488).
- Added ptm:gets, ptm:sets and more ptm service commands.
- Added AM_ContentInfo, AM_ContentInfoFlags structs.
- Added AMAPP_GetDLCContentInfoCount, AMAPP_ListDLCContentInfos.
- Fixed bug in Huffman decoder.
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## Version 2.0.1
- Added CFG_SystemModel enum.
- Fixed bug in condvar code.
- Fixed bug in srvpm code.
- Fixed const correctness issues in gspgpu code.
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## Version 2.0.0
**This is a major release. Many essential components have been overhauled, although breaking changes are minimal and only affect rarely used functionality.**
### system
- Added support for userAppInit/userAppExit (backported from libnx).
- Changed default heap allocation logic to be more robust:
- Resource limit SVCs are now used to detect available memory.
- The heap size calculation algorithm was tweaked so that 32MB of linear heap are available for normal apps running under the default appmemtype layout on Old 3DS, as it was the case prior to libctru 1.8.0.
- SVC enhancements:
- Added svcControlPerformanceCounter with corresponding enums.
- Overhauled support for DMA related SVCs:
- Added svcRestartDma.
- Added enums and structures needed for DMA SVCs.
- Added dmaDeviceConfigInitDefault, dmaConfigInitDefault.
- Added svcArbitrateAddressNoTimeout (minor ABI optimization for the svcArbitrateAddress syscall when the timeout parameter is not used).
- Changed process memory SVCs to use u32 parameters instead of void\* for foreign-process addresses.
- Major refactor of OS related functions:
- Added defines for Arm11 userland memory region addresses/sizes.
- Added struct definitions for the kernel/system shared config pages: osKernelConfig_s, osSharedConfig_s.
- Added macros to access the kernel/system shared config pages: OS_KernelConfig, OS_SharedConfig.
- Fixed return type of osGetMemRegionUsed, osGetMemRegionFree (s64 -> u32).
- Refactored osConvertVirtToPhys and added support for the missing linearly mapped memory regions.
- Rewritten RTC time reading support to improve accuracy and match official logic more closely.
- Time drift correction is now implemented.
- Added osGetTimeRef function for reading the current reference timepoint published by the PTM sysmodule.
- Fixed osStrError to actually work properly.
- Cleaned up osGetSystemVersionData implementation.
- Other miscellaneous internal cleanup.
### synchronization
- Improved safety of usermode synchronization primitives when used in intercore contexts.
- Added CondVar synchronization primitive implementation.
- Added syncArbitrateAddress, syncArbitrateAddressWithTimeout.
- These functions replace \_\_sync\_get\_arbiter (which has been removed).
- Added \_\_dmb (Data Memory Barrier) intrinsic.
- Added LightEvent_WaitTimeout.
- Added LightSemaphore_TryAcquire.
- Changed LightLock to support 0 as a valid initial (unlocked) state.
- This effectively adds support for trivially initialized/zerofilled locks.
- Fixed bug in LightSemaphore_Acquire.
### graphics
- Major refactor of the GSP service wrapper. It should now be possible to use GSP directly without the gfx API, if the user so desires.
- Major internal refactor of the gfx wrapper API that increases maintainability.
- Added support for 800px wide mode with non-square pixels on the top screen - usable on every 3DS model except for Old 2DS (but *including* New 2DS XL).
- Added support for 800px wide mode to the libctru console.
- Transferred most of the GSP initialization duties to gspInit/gspExit (previously done by the gfx wrapper).
- Added defines for screen IDs and screen dimensions.
- Added gspPresentBuffer for pushing a framebuffer to the internal GSP swap queue (previously this was an internal function in the gfx wrapper).
- Added gspGetBytesPerPixel, gspHasGpuRight.
- Added gfxScreenSwapBuffers, with support for duplicating left->right eye content during stereoscopic 3D mode.
- Fixed LCD configuration mode when using framebuffers on VRAM with the gfx wrapper.
- Changed gfxExit to set LCD force-black status to true.
- Changed the gfx wrapper to always use gspPresentBuffer during swap. This means the immediate parameter of gfxConfigScreen no longer has any effect, and gfxSwapBuffers/gfxSwapBuffersGpu now do the same thing - that is, present the rendered content during the next VBlank.
- Renamed GSPGPU_FramebufferFormats enum to GSPGPU_FramebufferFormat.
- Deprecated gfxConfigScreen (use gfxScreenSwapBuffers instead).
- Removed gspInitEventHandler, gspExitEventHandler (now handled automatically inside gspInit/gspExit).
- Removed sharedGspCmdBuf param from gspSubmitGxCommand (now uses the proper GSP shared memory address automatically).
- Removed GSPGPU_REBASE_REG define (leftover from early 3DS homebrew).
- Removed numerous internal fields that were previously publicly accessible.
### audio
- DSP access rights are now managed using a hook mechanism, similar to the APT hook.
- This fixes audio playback during libapplet invocations, as they no longer relinquish DSP rights.
- Changed NDSP to use the DSP hook instead of the APT hook.
- Added dspIsComponentLoaded, dspHook, dspUnhook.
- Fixed and improved robustness of wavebuf handling in NDSP code.
- Fixed and refactored NDSP sleep/wakeup code to improve accuracy compared to official logic.
### filesystem
- Reduced TLS footprint of the archive/romfs devices by sharing buffers.
- Reduced the maximum number of concurrently registered archive devices from 32 to 8 in order to save memory.
- Backported multi-mount romfs system from libnx, with additional optimizations (breaking API change).
- Added romfsMountFromTitle.
- Fixed stat for romfs device to return -1 for non-existent files/directories.
### applet
- Major internal refactor of the APT service wrapper that should improve accuracy compared to official logic.
- Fixed sleep handling when the app is inactive (i.e. app is suspended).
- Added support for screen capture during libapplet transitions.
- Added support for proper DSP access right management.
- aptLaunchLibraryApplet no longer calls aptMainLoop internally. Library applet calls no longer return a bool value, users are advised to check APT state manually afterwards.
- Added functions for checking APT state: aptIsActive, aptShouldClose, aptShouldJumpToHome, aptCheckHomePressRejected (replaces aptIsHomePressed).
- Added functions for handling incoming requests: aptHandleSleep, aptHandleJumpToHome.
- Added aptJumpToHomeMenu.
- Changed aptMainLoop to use the new wrapper functions (this means aptMainLoop can now be replaced by custom logic if desired).
- Changed APTHOOK_ONEXIT to be invoked during aptExit instead of during aptMainLoop.
- Added aptClearChainloader, aptSetChainloaderToSelf.
### miscellaneous
- Fix decompress out-of-bounds access.
- Added NDM_ prefix to NDM enum members in order to avoid name collisions.
- Corrected parameter type in several CFGU functions.
- Corrected return value of GSPLCD_GetBrightness.
- Removed obsolete support for ninjhax 1.x's fake hb:HB service.
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## Version 1.9.0
- hid: Added hidKeysDownRepeat, hidWaitForAnyEvent. Allow user override of irsst usage.
- Add ptm rtc time commands
- Add sleep state FSM handling service commands
- Revamp mappableAlloc
- Fixed stat on romfs for directories, implemented lstat via stat (FAT32 has no symlinks)
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## Version 1.8.0
- Added support for environments where the home menu is not launched (such as running under SAFE_FIRM)
- Added FSPXI service wrappers
- Changed heap allocation logic to be more flexible; this fixes support for certain system memory layouts
- Cleaned up and optimized light lock locking code
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## Version 1.7.0
- fix FIONBIO ioctl
- Fix CAMU_GetLatestVsyncTiming
- Add archive STDIO device driver
- Add AC commands that allow forcing a wifi connection
- Fix dspInit() error handling in ndspInit()
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## Version 1.6.0
- Major overhaul to font loading code in order to support loading external fonts.
- Major overhaul to PM service wrappers, now with separate support for pm:app and pm:dbg.
- Added Rosalina GDB host IO (gdbhio) support.
- Added support for the fs:REG service.
- Added support for the PxiPM service.
- Added PM launch flag definitions.
- Added SO_BROADCAST.
- Added new APT helper functions: aptIsHomeAllowed, aptSetHomeAllowed, aptIsHomePressed.
- Added support for the Mii selector libapplet, and other improvements to Mii support.
- Renamed IPC_Desc_CurProcessHandle to IPC_Desc_CurProcessId.
- Changed signature of LOADER_RegisterProgram to use FS_ProgramInfo structs.
- Fixed IPC bugs in the Loader service.
- Fixed svcCreateResourceLimit.
- Fixed corner case bug in GPUCMD_Add.
- Fixed bugs in select and herror.
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## Version 1.5.1
- Added support for the FRD service.
- Added gas-related GPU definitions.
- Implemented nanosleep.
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## Version 1.5.0
- Added new decompression API which supports LZSS/LZ10, LZ11, RLE & Huffman formats, and which can read compressed data from memory or from a file.
- Added srvSetBlockingPolicy, which controls whether srvGetServiceHandle blocks when the service isn't yet registered (or returns an error otherwise).
- Added ACU commands: ACU_GetStatus, ACU_GetSecurityMode, ACU_GetSSIDLength, ACU_GetSecurityMode, ACU_GetProxyEnable, ACU_GetProxyPort, ACU_GetProxyUserName, ACU_GetProxyPassword, ACU_GetLastErrorCode, ACU_GetLastDetailErrorCode.
- Added CFGI commands: CFGI_SecureInfoGetSerialNumber, CFGU_IsNFCSupported, CFGI_GetLocalFriendCodeSeed, CFGI_GetLocalFriendCodeSeedData, CFGI_GetSecureInfoData, CFGI_GetSecureInfoSignature.
- Added MCUHWC commands: MCUHWC_SetWifiLedState, MCUHWC_SetPowerLedState, MCUHWC_Get3dSliderLevel, MCUHWC_GetFwVerHigh, MCUHWC_GetFwVerLow.
- Added NS commands: NS_TerminateTitle, NS_TerminateProcessTID (with timeout), NS_RebootSystem.
- Added PM commands: PM_TerminateCurrentApplication, PM_TerminateProcess, PM_UnregisterProcess.
- Overhauled NDMU service support and added many commands that were previously missing.
- Fixed bugs in srv:pm implementation.
- Fixed calculation of vertical texture coordinates in fontCalcGlyphPos.
- Fixed shaderProgramSetGshInputPermutation.
- Fixed and added clock speed constants (affects system clock and NDSP).
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## Version 1.4.0
- Added LightSemaphore synchronization primitive.
- Added exheader definitions.
- Added support for the Loader service.
- Added support for the mcu::HWC service.
- Added support for the Mii selector applet.
- Added ResourceLimitType.
- Added AM commands: AM_DeleteAllTemporaryTitles, AM_DeleteAllExpiredTitles, AM_DeleteAllTwlTitles.
- Added CFGI commands: CFGI_RestoreLocalFriendCodeSeed, CFGI_RestoreSecureInfo, CFGI_DeleteConfigSavefile, CFGI_FormatConfig, CFGI_ClearParentalControls, CFGI_VerifySigLocalFriendCodeSeed, CFGI_VerifySigSecureInfo.
- Added GSPGPU commands: GSPGPU_SetLedForceOff.
- Added GSPLCD commands: GSPLCD_SetBrightness, GSPLCD_SetBrightnessRaw, GSPLCD_PowerOnAllBacklights, GSPLCD_PowerOffAllBacklights, GSPLCD_SetLedForceOff.
- Fixed srv:pm handling in pre-7.x system versions.
- Fixed GPU_LIGHTPERM macro definition.
- Removed the remaining deprecated GPUCMD commands.
- Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.
## Version 1.3.0
- Implement more svc calls
- svcCreateResourceLimit
- svcSetResourceLimitValues
- svcSetProcessResourceLimits
- svcCreateSession
- svcCreateSessionToPort
- svcSetGpuProt
- svcSetWifiEnabled
- Additional functions
- implement httpcAddPostDataBinary
- implement PTMU_GetAdapterState
- implement GSPLCD_GetBrightness
- add threadDetach
- srv fixes
- Fix srvPublishToSubscriber documentation
- Fix handling of service/named port names of length 8
- Fix srvRegisterPort
- debugging support
- Add support for user-specified exception handlers
- Rename debugDevice_3DMOO to debugDevice_SVC
- created debug version of library
- Implement error applet
- GPU updates
- Add GX command queue system for batching GX commands
- Correct GPU_PROCTEX_LUTID definition
- Add GPU_FOGMODE, GPU_GASMODE and GPU_GASLUTINPUT
- Other improvements and minor adjustments for overall system stability to enhance the user experience
## Version 1.2.1
- Added NFC support
- Update and renamed NFC_AmiiboConfig members
- Added TickCounter for measuring performance
- Added (linear/vram/mappable)GetSize for retrieving allocated buffer size
- Added nim:s client implementation.
- Correct bus clock used for time calulations
- Default to file write without internal copy buffer
- GPUCMD_Add: allow NULL for adding zerofilled parameter data
- Clarify threadFree usage in documentation
- Add GPU_TEXFACE enumeration
## Version 1.2.0
* New features:

View File

@ -1,21 +1,25 @@
# libctru - CTR User Library
![Build Status](https://github.com/devkitPro/libctru/actions/workflows/build.yaml/badge.svg)
Library for writing user mode ARM11 code for the 3DS (CTR)
This library aims to provide the foundations necessary to write 3DS Homebrew, and straightforwardly access the different functionalities provided by the 3DS operating system.
It is not meant to provide higher level functions; to put things in perspective, the purpose of libctru would be to sit between the OS and a possible port of SDL rather than replace it.
*(Originally located at github.com/smealum/ctrulib)*
# Setup
libctru is just a library and needs a toolchain to function. devkitARM (created by [devkitPro](http://devkitpro.org)) is the officially supported ARM cross compiling toolchain, which provides the framework necessary to supply a usable POSIX-like environment, with working C and C++ standard libraries; as well as the tools required to compile homebrew in the 3DSX format, and assemble GPU shaders. The use of other ARM toolchains is severely discouraged.
The most recent version of devkitARM (r46 at the time of writing) is always recommended. The installers/setup scripts supplied by devkitPro install a prebuilt copy of the latest stable version of libctru, which is recommended for general use. Please note that devkitPro has a policy of keeping legacy code to a minimum, so a library upgrade may result in older code failing to compile or behave properly. Developers are encouraged to keep their code working with the latest versions of the tools and libraries.
The most recent version of devkitARM is always recommended. The [installers/setup scripts](https://devkitpro.org/wiki/devkitPro_pacman) supplied by devkitPro install a prebuilt copy of the latest stable version of libctru, which is recommended for general use. Please note that devkitPro has a policy of keeping legacy code to a minimum, so a library upgrade may result in older code failing to compile or behave properly. Developers are encouraged to keep their code working with the latest versions of the tools and libraries.
You may find instructions on how to install devkitARM on [the devkitPro Wiki](http://devkitpro.org/wiki/Getting_Started).
# Documentation
The documentation is automatically built upon release and can be found at the following url: [http://smealum.github.io/ctrulib](http://smealum.github.io/ctrulib)
The documentation is automatically built upon release and can be found at the following url: https://devkitpro.github.io/libctru/
# License

View File

@ -1,13 +0,0 @@
#!/bin/sh
if [ "$TRAVIS_REPO_SLUG" = "smealum/ctrulib" ] && [ "$TRAVIS_PULL_REQUEST" = "false" ] && [ -n "$TRAVIS_TAG" ]; then
git clone --branch=gh-pages --single-branch --depth 1 --no-checkout https://${GH_TOKEN}@github.com/$TRAVIS_REPO_SLUG docs
git clone --branch=master --single-branch --depth 1 https://github.com/devkitPro/3ds-examples examples
cd libctru
doxygen Doxyfile
mv ./docs/html/* ../docs
cd ../docs
git add --all
git commit -m"Doc generated from commit $TRAVIS_COMMIT"
git push -f origin gh-pages
fi

7
libctru/.gitignore vendored
View File

@ -1,5 +1,10 @@
debug
release
deps
build
lib
docs
internal_docs
*.bz2
*.bz2
.*/
*.tag

View File

@ -1,4 +1,4 @@
# Doxyfile 1.8.6
# Doxyfile 1.8.11
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
@ -38,7 +38,7 @@ PROJECT_NAME = "libctru"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = "$(TRAVIS_TAG)"
PROJECT_NUMBER = "$(CTRU_VERSION)"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@ -46,10 +46,10 @@ PROJECT_NUMBER = "$(TRAVIS_TAG)"
PROJECT_BRIEF =
# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
# the documentation. The maximum height of the logo should not exceed 55 pixels
# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
# to the output directory.
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
PROJECT_LOGO =
@ -60,7 +60,7 @@ PROJECT_LOGO =
OUTPUT_DIRECTORY = docs
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
@ -70,6 +70,14 @@ OUTPUT_DIRECTORY = docs
CREATE_SUBDIRS = NO
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
# U+3044.
# The default value is: NO.
ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
@ -85,14 +93,14 @@ CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
@ -127,7 +135,7 @@ ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
@ -197,9 +205,9 @@ MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
# new page for each member. If set to NO, the documentation of a member will be
# part of the file/class/namespace that contains it.
# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
# page for each member. If set to NO, the documentation of a member will be part
# of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
@ -261,11 +269,14 @@ OPTIMIZE_OUTPUT_VHDL = NO
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
# (default is Fortran), use: inc=Fortran f=C.
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
# Fortran. In the later case the parser tries to guess whether the code is fixed
# or free formatted code, this is the default for Fortran type files), VHDL. For
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
#
# Note For files without extension you can use no_extension as a placeholder.
# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
@ -284,8 +295,8 @@ MARKDOWN_SUPPORT = YES
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
# be prevented in individual cases by by putting a % sign in front of the word
# or globally by setting AUTOLINK_SUPPORT to NO.
# be prevented in individual cases by putting a % sign in front of the word or
# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
AUTOLINK_SUPPORT = YES
@ -325,13 +336,20 @@ SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = NO
# If one adds a struct or class to a group and this option is enabled, then also
# any nested class or struct is added to the same group. By default this option
# is disabled and one has to add nested compounds explicitly via \ingroup.
# The default value is: NO.
GROUP_NESTED_COMPOUNDS = NO
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
@ -390,7 +408,7 @@ LOOKUP_CACHE_SIZE = 0
# Build related configuration options
#---------------------------------------------------------------------------
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
@ -400,35 +418,35 @@ LOOKUP_CACHE_SIZE = 0
EXTRACT_ALL = NO
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = NO
# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
EXTRACT_PACKAGE = NO
# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
EXTRACT_STATIC = YES
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
# locally in source files will be included in the documentation. If set to NO
# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
EXTRACT_LOCAL_CLASSES = NO
# This flag is only useful for Objective-C code. When set to YES local methods,
# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
# included in the documentation. If set to NO only methods in the interface are
# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
@ -453,21 +471,21 @@ HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
# to NO these classes will be included in the various overviews. This option has
# no effect if EXTRACT_ALL is enabled.
# to NO, these classes will be included in the various overviews. This option
# has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
# (class|struct|union) declarations. If set to NO these declarations will be
# (class|struct|union) declarations. If set to NO, these declarations will be
# included in the documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
# documentation blocks found inside the body of a function. If set to NO these
# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
@ -481,7 +499,7 @@ HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
# names in lower-case letters. If set to YES upper-case letters are also
# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
@ -490,12 +508,19 @@ INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES the
# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = NO
# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
# append additional text to a page's title, such as Class Reference. If set to
# YES the compound reference will be hidden.
# The default value is: NO.
HIDE_COMPOUND_REFERENCE= NO
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
@ -523,14 +548,14 @@ INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
# name. If set to NO the members will appear in declaration order.
# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
# name. If set to NO the members will appear in declaration order. Note that
# name. If set to NO, the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list.
# The default value is: NO.
@ -575,27 +600,25 @@ SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
# todo list. This list is created by putting \todo commands in the
# documentation.
# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
# test list. This list is created by putting \test commands in the
# documentation.
# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
GENERATE_TESTLIST = YES
# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
GENERATE_BUGLIST = YES
# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
@ -620,8 +643,8 @@ ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
# the bottom of the documentation of classes and structs. If set to YES the list
# will mention the files that were used to generate the documentation.
# the bottom of the documentation of classes and structs. If set to YES, the
# list will mention the files that were used to generate the documentation.
# The default value is: YES.
SHOW_USED_FILES = YES
@ -669,8 +692,7 @@ LAYOUT_FILE =
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. Do not use file names with spaces, bibtex cannot handle them. See
# also \cite for info how to create references.
# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
@ -686,7 +708,7 @@ CITE_BIB_FILES =
QUIET = NO
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
@ -694,7 +716,7 @@ QUIET = NO
WARNINGS = YES
# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
@ -711,12 +733,18 @@ WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
# value. If set to NO doxygen will only warn about wrong or incomplete parameter
# documentation, but not about the absence of documentation.
# value. If set to NO, doxygen will only warn about wrong or incomplete
# parameter documentation, but not about the absence of documentation.
# The default value is: NO.
WARN_NO_PARAMDOC = NO
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered.
# The default value is: NO.
WARN_AS_ERROR = NO
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
@ -740,10 +768,12 @@ WARN_LOGFILE =
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
# spaces.
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = include ../README.md ../Changelog.md
INPUT = include \
../README.md \
../Changelog.md
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@ -756,14 +786,22 @@ INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank the
# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
# *.qsf, *.as and *.js.
# *.h) to filter out the source-files in the directories.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# read by doxygen.
#
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl,
# *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.
FILE_PATTERNS = *.h *.c *.cpp *.s
FILE_PATTERNS = *.h \
*.c \
*.cpp \
*.s
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
@ -847,6 +885,10 @@ IMAGE_PATH =
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
INPUT_FILTER =
@ -856,11 +898,15 @@ INPUT_FILTER =
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER ) will also be used to filter the input files that are used for
# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
@ -920,7 +966,7 @@ REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
@ -997,7 +1043,7 @@ IGNORE_PREFIX =
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
GENERATE_HTML = YES
@ -1059,13 +1105,15 @@ HTML_FOOTER =
HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
# defined cascading style sheet that is included after the standard style sheets
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
# standard style sheet and is therefor more robust against future updates.
# Doxygen will copy the style sheet file to the output directory. For an example
# see the documentation.
# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
@ -1081,7 +1129,7 @@ HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the stylesheet and background images according to
# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
@ -1112,8 +1160,9 @@ HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
# to NO can help when comparing the output of multiple runs.
# The default value is: YES.
# to YES can help to show when doxygen was last run and thus if the
# documentation is up to date.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = NO
@ -1209,28 +1258,29 @@ GENERATE_HTMLHELP = NO
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler ( hhc.exe). If non-empty
# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated (
# YES) or that it should be included in the master .chm file ( NO).
# The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
# The BINARY_TOC flag controls whether a binary table of contents is generated (
# YES) or a normal table of contents ( NO) in the .chm file.
# The BINARY_TOC flag controls whether a binary table of contents is generated
# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
@ -1343,7 +1393,7 @@ DISABLE_INDEX = NO
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
@ -1371,7 +1421,7 @@ ENUM_VALUES_PER_LINE = 1
TREEVIEW_WIDTH = 250
# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
@ -1400,7 +1450,7 @@ FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# http://www.mathjax.org) which uses client side Javascript for the rendering
# instead of using prerendered bitmaps. Use this if you do not have LaTeX
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
@ -1470,11 +1520,11 @@ SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript. There
# are two flavours of web server based searching depending on the
# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
# searching and an index file used by the script. When EXTERNAL_SEARCH is
# enabled the indexing and searching needs to be provided by external tools. See
# the section "External Indexing and Searching" for details.
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
# and searching needs to be provided by external tools. See the section
# "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
@ -1486,7 +1536,7 @@ SERVER_BASED_SEARCH = NO
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results.
#
# Doxygen ships with an example indexer ( doxyindexer) and search engine
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/).
#
@ -1499,7 +1549,7 @@ EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
#
# Doxygen ships with an example indexer ( doxyindexer) and search engine
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/). See the section "External Indexing and
# Searching" for details.
@ -1537,7 +1587,7 @@ EXTRA_SEARCH_MAPPINGS =
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = NO
@ -1568,7 +1618,7 @@ LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
@ -1586,9 +1636,12 @@ COMPACT_LATEX = NO
PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
# that should be included in the LaTeX output. To get the times font for
# instance you can specify
# EXTRA_PACKAGES=times
# that should be included in the LaTeX output. The package can be specified just
# by its name or with the correct syntax as to be used with the LaTeX
# \usepackage command. To get the times font for instance you can specify :
# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
# To use the option intlimits with the amsmath package you can specify:
# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@ -1602,23 +1655,36 @@ EXTRA_PACKAGES =
#
# Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title,
# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
# replace them by respectively the title of the page, the current date and time,
# only the current date, the version number of doxygen, the project name (see
# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
# string, for the replacement values of the other commands the user is referred
# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
# chapter. If it is left blank doxygen will generate a standard footer.
# chapter. If it is left blank doxygen will generate a standard footer. See
# LATEX_HEADER for more information on how to generate a default footer and what
# special commands can be used inside the footer.
#
# Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# LaTeX style sheets that are included after the standard style sheets created
# by doxygen. Using this option one can overrule certain style aspects. Doxygen
# will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list).
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_STYLESHEET =
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or
@ -1636,8 +1702,8 @@ LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES to get a
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
# higher quality PDF documentation.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
@ -1678,11 +1744,19 @@ LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
# page will contain the date and time when the page was generated. Setting this
# to NO can help when comparing the output of multiple runs.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_TIMESTAMP = NO
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors.
# The default value is: NO.
@ -1697,7 +1771,7 @@ GENERATE_RTF = NO
RTF_OUTPUT = rtf
# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
@ -1734,11 +1808,21 @@ RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
# with syntax highlighting in the RTF output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
# classes and files.
# The default value is: NO.
@ -1762,6 +1846,13 @@ MAN_OUTPUT = man
MAN_EXTENSION = .3
# The MAN_SUBDIR tag determines the name of the directory created within
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without
@ -1775,7 +1866,7 @@ MAN_LINKS = NO
# Configuration options related to the XML output
#---------------------------------------------------------------------------
# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
# captures the structure of the code including all documentation.
# The default value is: NO.
@ -1789,19 +1880,7 @@ GENERATE_XML = NO
XML_OUTPUT = xml
# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
# validating XML parser to check the syntax of the XML files.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_SCHEMA =
# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
# validating XML parser to check the syntax of the XML files.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_DTD =
# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
# of the XML output.
@ -1814,7 +1893,7 @@ XML_PROGRAMLISTING = YES
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
# The default value is: NO.
@ -1828,14 +1907,23 @@ GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
# program listings (including syntax highlighting and cross-referencing
# information) to the DOCBOOK output. Note that enabling this will significantly
# increase the size of the DOCBOOK output.
# The default value is: NO.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
# Definitions (see http://autogen.sf.net) file that captures the structure of
# the code including all documentation. Note that this feature is still
# experimental and incomplete at the moment.
# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
# AutoGen Definitions (see http://autogen.sf.net) file that captures the
# structure of the code including all documentation. Note that this feature is
# still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
@ -1844,7 +1932,7 @@ GENERATE_AUTOGEN_DEF = NO
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
# file that captures the structure of the code including all documentation.
#
# Note that this feature is still experimental and incomplete at the moment.
@ -1852,7 +1940,7 @@ GENERATE_AUTOGEN_DEF = NO
GENERATE_PERLMOD = NO
# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output.
# The default value is: NO.
@ -1860,9 +1948,9 @@ GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
# understand what is going on. On the other hand, if this tag is set to NO the
# understand what is going on. On the other hand, if this tag is set to NO, the
# size of the Perl module output will be much smaller and Perl will parse it
# just the same.
# The default value is: YES.
@ -1882,20 +1970,20 @@ PERLMOD_MAKEVAR_PREFIX =
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
# in the source code. If set to NO only conditional compilation will be
# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
# in the source code. If set to NO, only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = NO
MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
@ -1903,9 +1991,9 @@ MACRO_EXPANSION = NO
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = NO
EXPAND_ONLY_PREDEF = YES
# If the SEARCH_INCLUDES tag is set to YES the includes files in the
# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
@ -1935,7 +2023,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED =
PREDEFINED = CTR_PACKED
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
@ -1947,9 +2035,9 @@ PREDEFINED =
EXPAND_AS_DEFINED =
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all refrences to function-like macros that are alone on a line, have an
# all uppercase name, and do not end with a semicolon. Such function macros are
# typically used for boiler-plate code, and will confuse the parser if not
# remove all references to function-like macros that are alone on a line, have
# an all uppercase name, and do not end with a semicolon. Such function macros
# are typically used for boiler-plate code, and will confuse the parser if not
# removed.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
@ -1969,7 +2057,7 @@ SKIP_FUNCTION_MACROS = YES
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use
# of tag files.
# Note: Each tag file must have an unique name (where the name does NOT include
# Note: Each tag file must have a unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
@ -1979,22 +2067,23 @@ TAGFILES =
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
GENERATE_TAGFILE =
GENERATE_TAGFILE = libctru.tag
# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
# class index. If set to NO only the inherited external classes will be listed.
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
# the class index. If set to NO, only the inherited external classes will be
# listed.
# The default value is: NO.
ALLEXTERNALS = NO
# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
# the modules index. If set to NO, only the current project's groups will be
# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
EXTERNAL_GROUPS = YES
# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
@ -2011,7 +2100,7 @@ PERL_PATH = /usr/bin/perl
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more
@ -2036,7 +2125,7 @@ MSCGEN_PATH =
DIA_PATH =
# If set to YES, the inheritance and collaboration graphs will hide inheritance
# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
@ -2061,7 +2150,7 @@ HAVE_DOT = NO
DOT_NUM_THREADS = 0
# When you want a differently looking font n the dot files that doxygen
# When you want a differently looking font in the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make
# sure dot is able to find the font, which can be done by putting it in a
# standard location or by setting the DOTFONTPATH environment variable or by
@ -2109,7 +2198,7 @@ COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
# The default value is: NO.
@ -2161,7 +2250,8 @@ INCLUDED_BY_GRAPH = YES
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
# functions only using the \callgraph command.
# functions only using the \callgraph command. Disabling a call graph can be
# accomplished by means of the command \hidecallgraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
@ -2172,7 +2262,8 @@ CALL_GRAPH = NO
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
# functions only using the \callergraph command.
# functions only using the \callergraph command. Disabling a caller graph can be
# accomplished by means of the command \hidecallergraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
@ -2195,11 +2286,15 @@ GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot.
# generated by dot. For an explanation of the image formats see the section
# output formats in the documentation of the dot tool (Graphviz (see:
# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
# Possible values are: png, jpg, gif and svg.
# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
@ -2242,6 +2337,19 @@ MSCFILE_DIRS =
DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
# PlantUML is not used or called during a preprocessing step. Doxygen will
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
PLANTUML_JAR_PATH =
# When using plantuml, the specified paths are searched for files specified by
# the !include statement in a plantuml block.
PLANTUML_INCLUDE_PATH =
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
@ -2278,7 +2386,7 @@ MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
@ -2295,7 +2403,7 @@ DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
# files that are used to generate the various graphs.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.

File diff suppressed because it is too large Load Diff

View File

@ -8,8 +8,8 @@ endif
include $(DEVKITARM)/base_rules
export LIBCTRU_MAJOR := 1
export LIBCTRU_MINOR := 2
export LIBCTRU_MAJOR := 2
export LIBCTRU_MINOR := 4
export LIBCTRU_PATCH := 0
@ -23,7 +23,7 @@ VERSION := $(LIBCTRU_MAJOR).$(LIBCTRU_MINOR).$(LIBCTRU_PATCH)
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := ctru
BUILD := build
#BUILD := build
SOURCES := source \
source/allocator \
source/gpu \
@ -31,6 +31,7 @@ SOURCES := source \
source/services \
source/services/soc \
source/applets \
source/util/decompress \
source/util/rbtree \
source/util/utf \
source/system
@ -43,16 +44,17 @@ INCLUDES := include
#---------------------------------------------------------------------------------
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
CFLAGS := -g -Wall -Werror -O2 -mword-relocations \
CFLAGS := -g -Wall -Werror -mword-relocations \
-ffunction-sections \
-fomit-frame-pointer \
$(ARCH)
-fdata-sections \
$(ARCH) \
$(BUILD_CFLAGS)
CFLAGS += $(INCLUDE) -DARM11 -D_3DS
CFLAGS += $(INCLUDE) -D__3DS__
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
ASFLAGS := -g $(ARCH)
ASFLAGS := -g $(ARCH) $(INCLUDE)
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
@ -67,13 +69,9 @@ LIBDIRS :=
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/lib/lib$(TARGET).a
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
@ -93,45 +91,61 @@ else
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
-I.
.PHONY: $(BUILD) clean all
.PHONY: clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
all: lib/libctru.a lib/libctrud.a
dist-bin: all
@tar --exclude=*~ -cjf libctru-$(VERSION).tar.bz2 include lib default_icon.png
dist-src:
@tar --exclude=*~ -cjf libctru-src-$(VERSION).tar.bz2 include source data Makefile Doxyfile Doxyfile.internal default_icon.png
@tar --exclude=*~ -cjf libctru-src-$(VERSION).tar.bz2 include source data Makefile Doxyfile default_icon.png
dist: dist-src dist-bin
install: dist-bin
mkdir -p $(DEVKITPRO)/libctru
bzip2 -cd libctru-$(VERSION).tar.bz2 | tar -xf - -C $(DEVKITPRO)/libctru
dox:
@doxygen Doxyfile
@doxygen Doxyfile.internal
mkdir -p $(DESTDIR)$(DEVKITPRO)/libctru
bzip2 -cd libctru-$(VERSION).tar.bz2 | tar -xf - -C $(DESTDIR)$(DEVKITPRO)/libctru
lib:
@[ -d $@ ] || mkdir -p $@
$(BUILD): lib
release:
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
debug:
@[ -d $@ ] || mkdir -p $@
lib/libctru.a : lib release $(SOURCES) $(INCLUDES)
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
BUILD_CFLAGS="-DNDEBUG=1 -O2 -fomit-frame-pointer" \
DEPSDIR=$(CURDIR)/release \
--no-print-directory -C release \
-f $(CURDIR)/Makefile
lib/libctrud.a : lib debug $(SOURCES) $(INCLUDES)
@$(MAKE) BUILD=debug OUTPUT=$(CURDIR)/$@ \
BUILD_CFLAGS="-DDEBUG=1 -Og" \
DEPSDIR=$(CURDIR)/debug \
--no-print-directory -C debug \
-f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) lib docs internal_docs
@rm -fr release debug lib docs libctru.tag
#---------------------------------------------------------------------------------
else
@ -143,8 +157,10 @@ DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
$(OUTPUT) : $(OFILES)
$(OFILES_SRC) : $(HFILES_BIN)
#---------------------------------------------------------------------------------
%.bin.o : %.bin
%.bin.o %_bin.h : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)

View File

@ -8,11 +8,17 @@
extern "C" {
#endif
#if defined(_3DS) && !defined(__3DS__)
#warning "Please update your Makefile and replace -DARM11 -D_3DS with -D__3DS__"
#define __3DS__
#endif
//might be missing some
#include <3ds/types.h>
#include <3ds/result.h>
#include <3ds/ipc.h>
#include <3ds/svc.h>
#include <3ds/exheader.h>
#include <3ds/srv.h>
#include <3ds/errf.h>
#include <3ds/os.h>
@ -21,6 +27,7 @@ extern "C" {
#include <3ds/gfx.h>
#include <3ds/console.h>
#include <3ds/env.h>
#include <3ds/util/decompress.h>
#include <3ds/util/utf.h>
#include <3ds/allocator/linear.h>
@ -38,6 +45,9 @@ extern "C" {
#include <3ds/services/csnd.h>
#include <3ds/services/dsp.h>
#include <3ds/services/fs.h>
#include <3ds/services/fspxi.h>
#include <3ds/services/fsreg.h>
#include <3ds/services/frd.h>
#include <3ds/services/gspgpu.h>
#include <3ds/services/gsplcd.h>
#include <3ds/services/hid.h>
@ -46,23 +56,31 @@ extern "C" {
#include <3ds/services/httpc.h>
#include <3ds/services/uds.h>
#include <3ds/services/ndm.h>
#include <3ds/services/nim.h>
#include <3ds/services/nwmext.h>
#include <3ds/services/ir.h>
#include <3ds/services/ns.h>
#include <3ds/services/pm.h>
#include <3ds/services/pmapp.h>
#include <3ds/services/pmdbg.h>
#include <3ds/services/ps.h>
#include <3ds/services/ptmu.h>
#include <3ds/services/ptmsysm.h>
#include <3ds/services/ptmgets.h>
#include <3ds/services/ptmsets.h>
#include <3ds/services/pxidev.h>
#include <3ds/services/pxipm.h>
#include <3ds/services/soc.h>
#include <3ds/services/mic.h>
#include <3ds/services/mvd.h>
#include <3ds/services/nfc.h>
#include <3ds/services/news.h>
#include <3ds/services/qtm.h>
#include <3ds/services/qtmc.h>
#include <3ds/services/srvpm.h>
#include <3ds/services/loader.h>
#include <3ds/services/y2r.h>
#include <3ds/services/hb.h>
#include <3ds/services/mcuhwc.h>
#include <3ds/services/cdcchk.h>
#include <3ds/gpu/gx.h>
#include <3ds/gpu/gpu.h>
@ -73,39 +91,64 @@ extern "C" {
#include <3ds/ndsp/channel.h>
#include <3ds/applets/swkbd.h>
#include <3ds/applets/error.h>
#include <3ds/sdmc.h>
#include <3ds/applets/miiselector.h>
#include <3ds/archive.h>
#include <3ds/romfs.h>
#include <3ds/font.h>
#include <3ds/mii.h>
#include <3ds/gdbhio_dev.h>
#include <3ds/3dslink.h>
#ifdef __cplusplus
}
#endif
/**
* @example app_launch/source/main.c
* @example audio/filters/source/main.c
* @example audio/mic/source/main.c
* @example audio/streaming/source/main.c
* @example camera/image/source/main.c
* @example camera/video/source/main.c
* @example get_system_language/source/main.c
* @example graphics/bitmap/24bit-color/source/main.c
* @example graphics/printing/hello-world/source/main.c
* @example graphics/printing/both-screen-text/source/main.c
* @example graphics/printing/colored-text/source/main.c
* @example graphics/printing/multiple-windows-text/source/main.c
* @example graphics/printing/system-font/source/main.c
* @example graphics/gpu/both_screens/source/main.c
* @example graphics/gpu/fragment_light/source/main.c
* @example graphics/gpu/geoshader/source/main.c
* @example graphics/gpu/gpusprites/source/main.c
* @example graphics/gpu/immediate/source/main.c
* @example graphics/gpu/lenny/source/main.c
* @example graphics/gpu/loop_subdivision/source/main.c
* @example graphics/gpu/mipmap_fog/source/main.c
* @example graphics/gpu/particles/source/main.c
* @example graphics/gpu/proctex/source/main.c
* @example graphics/gpu/simple_tri/source/main.c
* @example graphics/gpu/textured_cube/source/main.c
* @example http/source/main.c
* @example graphics/gpu/toon_shading/source/main.c
* @example graphics/printing/both-screen-text/source/main.c
* @example graphics/printing/colored-text/source/main.c
* @example graphics/printing/hello-world/source/main.c
* @example graphics/printing/multiple-windows-text/source/main.c
* @example graphics/printing/system-font/source/main.c
* @example input/read-controls/source/main.c
* @example input/software-keyboard/source/main.c
* @example input/touch-screen/source/main.c
* @example libapplet_launch/source/main.c
* @example mvd/source/main.c
* @example network/boss/source/main.c
* @example network/http/source/main.c
* @example network/http_post/source/main.c
* @example network/sockets/source/sockets.c
* @example network/sslc/source/ssl.c
* @example network/uds/source/uds.c
* @example nfc/source/main.c
* @example qtm/source/main.c
* @example romfs/source/main.c
* @example sdmc/source/main.c
* @example threads/thread-basic/source/main.c
* @example threads/event/source/main.c
* @example threads/thread-basic/source/main.c
* @example time/rtc/source/main.c
*/

View File

@ -0,0 +1,34 @@
/**
* @file 3dslink.h
* @brief Netloader (3dslink) utilities
*/
#pragma once
#include <stdbool.h>
struct in_addr;
/// Address of the host connected through 3dslink
extern struct in_addr __3dslink_host;
#define LINK3DS_COMM_PORT 17491 ///< 3dslink TCP server port
/**
* @brief Connects to the 3dslink host, setting up an output stream.
* @param[in] redirStdout Whether to redirect stdout to nxlink output.
* @param[in] redirStderr Whether to redirect stderr to nxlink output.
* @return Socket fd on success, negative number on failure.
* @note The socket should be closed with close() during application cleanup.
*/
int link3dsConnectToHost(bool redirStdout, bool redirStderr);
/// Same as \ref link3dsConnectToHost but redirecting both stdout/stderr.
static inline int link3dsStdio(void) {
return link3dsConnectToHost(true, true);
}
/// Same as \ref link3dsConnectToHost but redirecting only stderr.
static inline int link3dsStdioForDebug(void) {
return link3dsConnectToHost(false, true);
}

View File

@ -4,6 +4,8 @@
*/
#pragma once
#include <stddef.h>
/**
* @brief Allocates a 0x80-byte aligned buffer.
* @param size Size of the buffer to allocate.
@ -28,6 +30,12 @@ void* linearMemAlign(size_t size, size_t alignment);
*/
void* linearRealloc(void* mem, size_t size);
/**
* @brief Retrieves the allocated size of a buffer.
* @return The size of the buffer.
*/
size_t linearGetSize(void* mem);
/**
* @brief Frees a buffer.
* @param mem Buffer to free.

View File

@ -4,21 +4,24 @@
*/
#pragma once
#include <3ds/types.h>
/**
* @brief Allocates a page-aligned buffer.
* @param size Size of the buffer to allocate.
* @return The allocated buffer.
* @brief Initializes the mappable allocator.
* @param addrMin Minimum address.
* @param addrMax Maxium address.
*/
void mappableInit(u32 addrMin, u32 addrMax);
/**
* @brief Finds a mappable memory area.
* @param size Size of the area to find.
* @return The mappable area.
*/
void* mappableAlloc(size_t size);
/**
* @brief Frees a buffer.
* @param mem Buffer to free.
* @brief Frees a mappable area (stubbed).
* @param mem Mappable area to free.
*/
void mappableFree(void* mem);
/**
* @brief Gets the current mappable free space.
* @return The current mappable free space.
*/
u32 mappableSpaceFree(void);

View File

@ -4,6 +4,13 @@
*/
#pragma once
typedef enum vramAllocPos
{
VRAM_ALLOC_A = BIT(0),
VRAM_ALLOC_B = BIT(1),
VRAM_ALLOC_ANY = VRAM_ALLOC_A | VRAM_ALLOC_B,
} vramAllocPos;
/**
* @brief Allocates a 0x80-byte aligned buffer.
* @param size Size of the buffer to allocate.
@ -11,6 +18,14 @@
*/
void* vramAlloc(size_t size);
/**
* @brief Allocates a 0x80-byte aligned buffer in the given VRAM bank.
* @param size Size of the buffer to allocate.
* @param pos VRAM bank to use (see \ref vramAllocPos).
* @return The allocated buffer.
*/
void* vramAllocAt(size_t size, vramAllocPos pos);
/**
* @brief Allocates a buffer aligned to the given size.
* @param size Size of the buffer to allocate.
@ -19,6 +34,15 @@ void* vramAlloc(size_t size);
*/
void* vramMemAlign(size_t size, size_t alignment);
/**
* @brief Allocates a buffer aligned to the given size in the given VRAM bank.
* @param size Size of the buffer to allocate.
* @param alignment Alignment to use.
* @param pos VRAM bank to use (see \ref vramAllocPos).
* @return The allocated buffer.
*/
void* vramMemAlignAt(size_t size, size_t alignment, vramAllocPos pos);
/**
* @brief Reallocates a buffer.
* Note: Not implemented yet.
@ -28,6 +52,12 @@ void* vramMemAlign(size_t size, size_t alignment);
*/
void* vramRealloc(void* mem, size_t size);
/**
* @brief Retrieves the allocated size of a buffer.
* @return The size of the buffer.
*/
size_t vramGetSize(void* mem);
/**
* @brief Frees a buffer.
* @param mem Buffer to free.

View File

@ -0,0 +1,91 @@
/**
* @file error.h
* @brief Error applet.
*/
#pragma once
#include <3ds/types.h>
enum
{
ERROR_LANGUAGE_FLAG = 0x100, ///<??-Unknown flag
ERROR_WORD_WRAP_FLAG = 0x200 ///<??-Unknown flag
};
///< Type of Error applet to be called
typedef enum
{
ERROR_CODE = 0, ///< Displays the infrastructure communications-related error message corresponding to the error code.
ERROR_TEXT, ///< Displays text passed to this applet.
ERROR_EULA, ///< Displays the EULA
ERROR_TYPE_EULA_FIRST_BOOT, ///< Use prohibited.
ERROR_TYPE_EULA_DRAW_ONLY, ///< Use prohibited.
ERROR_TYPE_AGREE, ///< Use prohibited.
ERROR_CODE_LANGUAGE = ERROR_CODE | ERROR_LANGUAGE_FLAG, ///< Displays a network error message in a specified language.
ERROR_TEXT_LANGUAGE = ERROR_TEXT | ERROR_LANGUAGE_FLAG, ///< Displays text passed to this applet in a specified language.
ERROR_EULA_LANGUAGE = ERROR_EULA | ERROR_LANGUAGE_FLAG, ///< Displays EULA in a specified language.
ERROR_TEXT_WORD_WRAP = ERROR_TEXT | ERROR_WORD_WRAP_FLAG,///< Displays the custom error message passed to this applet with automatic line wrapping
ERROR_TEXT_LANGUAGE_WORD_WRAP = ERROR_TEXT | ERROR_LANGUAGE_FLAG | ERROR_WORD_WRAP_FLAG ///< Displays the custom error message with automatic line wrapping and in the specified language.
}errorType;
///< Flags for the Upper Screen.Does nothing even if specified.
typedef enum
{
ERROR_NORMAL = 0,
ERROR_STEREO
}errorScreenFlag;
///< Return code of the Error module.Use UNKNOWN for simple apps.
typedef enum
{
ERROR_UNKNOWN = -1,
ERROR_NONE = 0,
ERROR_SUCCESS,
ERROR_NOT_SUPPORTED,
ERROR_HOME_BUTTON = 10,
ERROR_SOFTWARE_RESET,
ERROR_POWER_BUTTON
}errorReturnCode;
///< Structure to be passed to the applet.Shouldn't be modified directly.
typedef struct
{
errorType type;
int errorCode;
errorScreenFlag upperScreenFlag;
u16 useLanguage;
u16 Text[1900];
bool homeButton;
bool softwareReset;
bool appJump;
errorReturnCode returnCode;
u16 eulaVersion;
}errorConf;
/**
* @brief Init the error applet.
* @param err Pointer to errorConf.
* @param type errorType Type of error.
* @param lang CFG_Language Lang of error.
*/
void errorInit(errorConf* err, errorType type, CFG_Language lang);
/**
* @brief Sets error code to display.
* @param err Pointer to errorConf.
* @param error Error-code to display.
*/
void errorCode(errorConf* err, int error);
/**
* @brief Sets error text to display.
* @param err Pointer to errorConf.
* @param text Error-text to display.
*/
void errorText(errorConf* err, const char* text);
/**
* @brief Displays the error applet.
* @param err Pointer to errorConf.
*/
void errorDisp(errorConf* err);

View File

@ -0,0 +1,188 @@
/**
* @file miiselector.h
* @brief Mii Selector Applet (appletEd).
*/
#pragma once
#include <3ds/types.h>
#include <3ds/mii.h>
/// Magic value needed to launch the applet.
#define MIISELECTOR_MAGIC 0x13DE28CF
/// Maximum length of title to be displayed at the top of the Mii selector applet
#define MIISELECTOR_TITLE_LEN 64
/// Number of Guest Miis available for selection
#define MIISELECTOR_GUESTMII_SLOTS 6
/// Maximum number of user Miis available for selection
#define MIISELECTOR_USERMII_SLOTS 100
/// Parameter structure passed to AppletEd
typedef struct
{
u8 enable_cancel_button; ///< Enables canceling of selection if nonzero.
u8 enable_selecting_guests; ///< Makes Guets Miis selectable if nonzero.
u8 show_on_top_screen; ///< Shows applet on top screen if nonzero,
///< otherwise show it on the bottom screen.
u8 _unk0x3[5]; ///< @private
u16 title[MIISELECTOR_TITLE_LEN]; ///< UTF16-LE string displayed at the top of the applet. If
///< set to the empty string, a default title is displayed.
u8 _unk0x88[4]; ///< @private
u8 show_guest_page; ///< If nonzero, the applet shows a page with Guest
///< Miis on launch.
u8 _unk0x8D[3]; ///< @private
u32 initial_index; ///< Index of the initially selected Mii. If
///< @ref MiiSelectorConf.show_guest_page is
///< set, this is the index of a Guest Mii,
///< otherwise that of a user Mii.
u8 mii_guest_whitelist[MIISELECTOR_GUESTMII_SLOTS]; ///< Each byte set to a nonzero value
///< enables its corresponding Guest
///< Mii to be enabled for selection.
u8 mii_whitelist[MIISELECTOR_USERMII_SLOTS]; ///< Each byte set to a nonzero value enables
///< its corresponding user Mii to be enabled
///< for selection.
u16 _unk0xFE; ///< @private
u32 magic; ///< Will be set to @ref MIISELECTOR_MAGIC before launching the
///< applet.
} MiiSelectorConf;
/// Maximum length of the localized name of a Guest Mii
#define MIISELECTOR_GUESTMII_NAME_LEN 12
/// Structure written by AppletEd
typedef struct
{
u32 no_mii_selected; ///< 0 if a Mii was selected, 1 if the selection was
///< canceled.
u32 guest_mii_was_selected; ///< 1 if a Guest Mii was selected, 0 otherwise.
u32 guest_mii_index; ///< Index of the selected Guest Mii,
///< 0xFFFFFFFF if no guest was selected.
MiiData mii; ///< Data of selected Mii.
u16 _pad0x68; ///< @private
u16 checksum; ///< Checksum of the returned Mii data.
///< Stored as a big-endian value; use
///< @ref miiSelectorChecksumIsValid to
///< verify.
u16 guest_mii_name[MIISELECTOR_GUESTMII_NAME_LEN]; ///< Localized name of a Guest Mii,
///< if one was selected (UTF16-LE
///< string). Zeroed otherwise.
} MiiSelectorReturn;
/// AppletEd options
enum
{
MIISELECTOR_CANCEL = BIT(0), ///< Show the cancel button
MIISELECTOR_GUESTS = BIT(1), ///< Make Guets Miis selectable
MIISELECTOR_TOP = BIT(2), ///< Show AppletEd on top screen
MIISELECTOR_GUESTSTART = BIT(3), ///< Start on guest page
};
/**
* @brief Initialize Mii selector config
* @param conf Pointer to Miiselector config.
*/
void miiSelectorInit(MiiSelectorConf *conf);
/**
* @brief Launch the Mii selector library applet
*
* @param conf Configuration determining how the applet should behave
*/
void miiSelectorLaunch(const MiiSelectorConf *conf, MiiSelectorReturn* returnbuf);
/**
* @brief Sets title of the Mii selector library applet
*
* @param conf Pointer to miiSelector configuration
* @param text Title text of Mii selector
*/
void miiSelectorSetTitle(MiiSelectorConf *conf, const char* text);
/**
* @brief Specifies which special options are enabled in the Mii selector
*
* @param conf Pointer to miiSelector configuration
* @param options Options bitmask
*/
void miiSelectorSetOptions(MiiSelectorConf *conf, u32 options);
/**
* @brief Specifies which guest Miis will be selectable
*
* @param conf Pointer to miiSelector configuration
* @param index Index of the guest Miis that will be whitelisted.
* @ref MIISELECTOR_GUESTMII_SLOTS can be used to whitelist all the guest Miis.
*/
void miiSelectorWhitelistGuestMii(MiiSelectorConf *conf, u32 index);
/**
* @brief Specifies which guest Miis will be unselectable
*
* @param conf Pointer to miiSelector configuration
* @param index Index of the guest Miis that will be blacklisted.
* @ref MIISELECTOR_GUESTMII_SLOTS can be used to blacklist all the guest Miis.
*/
void miiSelectorBlacklistGuestMii(MiiSelectorConf *conf, u32 index);
/**
* @brief Specifies which user Miis will be selectable
*
* @param conf Pointer to miiSelector configuration
* @param index Index of the user Miis that will be whitelisted.
* @ref MIISELECTOR_USERMII_SLOTS can be used to whitlist all the user Miis
*/
void miiSelectorWhitelistUserMii(MiiSelectorConf *conf, u32 index);
/**
* @brief Specifies which user Miis will be selectable
*
* @param conf Pointer to miiSelector configuration
* @param index Index of the user Miis that will be blacklisted.
* @ref MIISELECTOR_USERMII_SLOTS can be used to blacklist all the user Miis
*/
void miiSelectorBlacklistUserMii(MiiSelectorConf *conf, u32 index);
/**
* @brief Specifies which Mii the cursor should start from
*
* @param conf Pointer to miiSelector configuration
* @param index Indexed number of the Mii that the cursor will start on.
* If there is no mii with that index, the the cursor will start at the Mii
* with the index 0 (the personal Mii).
*/
static inline void miiSelectorSetInitialIndex(MiiSelectorConf *conf, u32 index)
{
conf->initial_index = index;
}
/**
* @brief Get Mii name
*
* @param returnbuf Pointer to miiSelector return
* @param out String containing a Mii's name
* @param max_size Size of string. Since UTF8 characters range in size from 1-3 bytes
* (assuming that no non-BMP characters are used), this value should be 36 (or 30 if you are not
* dealing with guest miis).
*/
void miiSelectorReturnGetName(const MiiSelectorReturn *returnbuf, char* out, size_t max_size);
/**
* @brief Get Mii Author
*
* @param returnbuf Pointer to miiSelector return
* @param out String containing a Mii's author
* @param max_size Size of string. Since UTF8 characters range in size from 1-3 bytes
* (assuming that no non-BMP characters are used), this value should be 30.
*/
void miiSelectorReturnGetAuthor(const MiiSelectorReturn *returnbuf, char* out, size_t max_size);
/**
* @brief Verifies that the Mii data returned from the applet matches its
* checksum
*
* @param returnbuf Buffer filled by Mii selector applet
* @return `true` if `returnbuf->checksum` is the same as the one computed from `returnbuf`
*/
bool miiSelectorChecksumIsValid(const MiiSelectorReturn *returnbuf);

View File

@ -3,6 +3,7 @@
* @brief Software keyboard applet.
*/
#pragma once
#include <3ds/types.h>
/// Keyboard types.
typedef enum

View File

@ -0,0 +1,43 @@
/**
* @file archive.h
* @brief FS_Archive driver
*/
#pragma once
#include <sys/types.h>
#include <3ds/types.h>
#include <3ds/services/fs.h>
#define ARCHIVE_DIRITER_MAGIC 0x68637261 /* "arch" */
/*! Open directory struct */
typedef struct
{
u32 magic; /*! "arch" */
Handle fd; /*! CTRU handle */
ssize_t index; /*! Current entry index */
size_t size; /*! Current batch size */
FS_DirectoryEntry entry_data[32]; /*! Temporary storage for reading entries */
} archive_dir_t;
/// Mounts the SD
Result archiveMountSdmc(void);
/// Mounts and opens an archive as deviceName
/// Returns either an archive open error code, or -1 for generic failure
Result archiveMount(FS_ArchiveID archiveID, FS_Path archivePath, const char *deviceName);
/// Uses FSUSER_ControlArchive with control action ARCHIVE_ACTION_COMMIT_SAVE_DATA on the opened archive. Not done automatically at unmount.
/// Returns -1 if the specified device is not found
Result archiveCommitSaveData(const char *deviceName);
/// Unmounts the specified device, closing its archive in the process
/// Returns -1 if the specified device was not found
Result archiveUnmount(const char *deviceName);
/// Unmounts all devices and cleans up any resources used by the driver
Result archiveUnmountAll(void);
/// Get a file's mtime
Result archive_getmtime(const char *name, u64 *mtime);

View File

@ -0,0 +1,21 @@
#pragma once
#if !__ASSEMBLER__
#error This header file is only for use in assembly files!
#endif // !__ASSEMBLER__
.macro BEGIN_ASM_FUNC name, linkage=global, section=text
.section .\section\().\name, "ax", %progbits
.align 2
.\linkage \name
.type \name, %function
.func \name
.cfi_sections .debug_frame
.cfi_startproc
\name:
.endm
.macro END_ASM_FUNC
.cfi_endproc
.endfunc
.endm

View File

@ -94,8 +94,8 @@ typedef struct PrintConsole
int windowHeight; ///< Window height in characters (not implemented)
int tabSize; ///< Size of a tab
int fg; ///< Foreground color
int bg; ///< Background color
u16 fg; ///< Foreground color
u16 bg; ///< Background color
int flags; ///< Reverse/bright flags
ConsolePrint PrintChar; ///< Callback for printing a character. Should return true if it has handled rendering the graphics (else the print engine will attempt to render via tiles).
@ -112,12 +112,15 @@ typedef struct PrintConsole
#define CONSOLE_COLOR_REVERSE (1<<6) ///< Reversed color text
#define CONSOLE_CONCEAL (1<<7) ///< Concealed text
#define CONSOLE_CROSSED_OUT (1<<8) ///< Crossed out text
#define CONSOLE_FG_CUSTOM (1<<9) ///< Foreground custom color
#define CONSOLE_BG_CUSTOM (1<<10) ///< Background custom color
/// Console debug devices supported by libnds.
typedef enum {
debugDevice_NULL, ///< Swallows prints to stderr
debugDevice_3DMOO, ///< Directs stderr debug statements to 3dmoo
debugDevice_SVC, ///< Outputs stderr debug statements using svcOutputDebugString, which can then be captured by interactive debuggers
debugDevice_CONSOLE, ///< Directs stderr debug statements to 3DS console window
debugDevice_3DMOO = debugDevice_SVC,
} debugDevice;
/**
@ -165,7 +168,7 @@ PrintConsole* consoleInit(gfxScreen_t screen, PrintConsole* console);
*/
void consoleDebugInit(debugDevice device);
/// Clears the screan by using iprintf("\x1b[2J");
/// Clears the screen by using iprintf("\x1b[2J");
void consoleClear(void);
#ifdef __cplusplus

View File

@ -8,6 +8,7 @@
enum {
RUNFLAG_APTWORKAROUND = BIT(0), ///< Use APT workaround.
RUNFLAG_APTREINIT = BIT(1), ///< Reinitialize APT.
RUNFLAG_APTCHAINLOAD = BIT(2), ///< Chainload APT on return.
};
/**

View File

@ -9,12 +9,12 @@
/// Types of errors that can be thrown by err:f.
typedef enum {
ERRF_ERRTYPE_GENERIC = 0, ///< For generic errors. Shows miscellaneous info.
ERRF_ERRTYPE_MEM_CORRUPT = 1, ///< Same output as generic, but informs the user that "the System Memory has been damaged".
ERRF_ERRTYPE_CARD_REMOVED = 2, ///< Displays the "The Game Card was removed." message.
ERRF_ERRTYPE_EXCEPTION = 3, ///< For exceptions, or more specifically 'crashes'. union data should be exception_data.
ERRF_ERRTYPE_FAILURE = 4, ///< For general failure. Shows a message. union data should have a string set in failure_mesg
ERRF_ERRTYPE_LOGGED = 5, ///< Outputs logs to NAND in some cases.
ERRF_ERRTYPE_GENERIC = 0, ///< Generic fatal error. Shows miscellaneous info, including the address of the caller
ERRF_ERRTYPE_NAND_DAMAGED = 1, ///< Damaged NAND (CC_ERROR after reading CSR)
ERRF_ERRTYPE_CARD_REMOVED = 2, ///< Game content storage medium (cartridge and/or SD card) ejected. Not logged
ERRF_ERRTYPE_EXCEPTION = 3, ///< CPU or VFP exception
ERRF_ERRTYPE_FAILURE = 4, ///< Fatal error with a message instead of the caller's address
ERRF_ERRTYPE_LOG_ONLY = 5, ///< Log-level failure. Does not display the exception and does not force the system to reboot
} ERRF_ErrType;
/// Types of 'Exceptions' thrown for ERRF_ERRTYPE_EXCEPTION
@ -28,17 +28,16 @@ typedef enum {
typedef struct {
ERRF_ExceptionType type; ///< Type of the exception. One of the ERRF_EXCEPTION_* values.
u8 reserved[3];
u32 reg1; ///< If type is prefetch, this should be ifsr, and on data abort dfsr
u32 reg2; ///< If type is prefetch, this should be r15, and dfar on data abort
u32 fsr; ///< ifsr (prefetch abort) / dfsr (data abort)
u32 far; ///< pc = ifar (prefetch abort) / dfar (data abort)
u32 fpexc;
u32 fpinst;
u32 fpint2;
u32 fpinst2;
} ERRF_ExceptionInfo;
typedef struct {
ERRF_ExceptionInfo excep; ///< Exception info struct
CpuRegisters regs; ///< CPU register dump.
u8 pad[4];
} ERRF_ExceptionData;
typedef struct {
@ -47,12 +46,12 @@ typedef struct {
u16 revLow; ///< Low revision ID
u32 resCode; ///< Result code
u32 pcAddr; ///< PC address at exception
u32 procId; ///< Process ID.
u64 titleId; ///< Title ID.
u64 appTitleId; ///< Application Title ID.
u32 procId; ///< Process ID of the caller
u64 titleId; ///< Title ID of the caller
u64 appTitleId; ///< Title ID of the running application
union {
ERRF_ExceptionData exception_data; ///< Data for when type is ERRF_ERRTYPE_EXCEPTION
char failure_mesg[60]; ///< String for when type is ERRF_ERRTYPE_FAILURE
char failure_mesg[0x60]; ///< String for when type is ERRF_ERRTYPE_FAILURE
} data; ///< The different types of data for errors.
} ERRF_FatalErrInfo;
@ -69,13 +68,19 @@ void errfExit(void);
Handle *errfGetSessionHandle(void);
/**
* @brief Throws a system error and possibly results in ErrDisp triggering.
* @brief Throws a system error and possibly logs it.
* @param[in] error Error to throw.
*
* After performing this, the system may panic and need to be rebooted. Extra information will be displayed on the
* top screen with a developer console or the proper patches in a CFW applied.
* ErrDisp may convert the error info to \ref ERRF_ERRTYPE_NAND_DAMAGED or \ref ERRF_ERRTYPE_CARD_REMOVED
* depending on the error code.
*
* The error may not be shown and execution aborted until errfExit(void) is called.
* Except with \ref ERRF_ERRTYPE_LOG_ONLY, the system will panic and will need to be rebooted.
* Fatal error information will also be logged into a file, unless the type either \ref ERRF_ERRTYPE_NAND_DAMAGED
* or \ref ERRF_ERRTYPE_CARD_REMOVED.
*
* No error will be shown if the system is asleep.
*
* On retail units with vanilla firmware, no detailed information will be displayed on screen.
*
* You may wish to use ERRF_ThrowResult() or ERRF_ThrowResultWithMessage() instead of
* constructing the ERRF_FatalErrInfo struct yourself.
@ -83,31 +88,50 @@ Handle *errfGetSessionHandle(void);
Result ERRF_Throw(const ERRF_FatalErrInfo* error);
/**
* @brief Throws a system error with the given Result code.
* @brief Throws (and logs) a system error with the given Result code.
* @param[in] failure Result code to throw.
*
* This calls ERRF_Throw() with error type ERRF_ERRTYPE_GENERIC and fills in the required data.
* This calls \ref ERRF_Throw with error type \ref ERRF_ERRTYPE_GENERIC and fills in the required data.
*
* This function \em does fill in the address where this function was called from.
*
* See https://3dbrew.org/wiki/ERR:Throw#Generic for expected top screen output
* on development units/patched ErrDisp.
*/
Result ERRF_ThrowResult(Result failure);
/**
* @brief Logs a system error with the given Result code.
* @param[in] failure Result code to log.
*
* Similar to \ref ERRF_Throw, except that it does not display anything on the screen,
* nor does it force the system to reboot.
*
* This function \em does fill in the address where this function was called from.
*/
Result ERRF_LogResult(Result failure);
/**
* @brief Throws a system error with the given Result code and message.
* @param[in] failure Result code to throw.
* @param[in] message The message to display.
*
* This calls ERRF_Throw() with error type ERRF_ERRTYPE_FAILURE and fills in the required data.
* This calls \ref ERRF_Throw with error type \ref ERRF_ERRTYPE_FAILURE and fills in the required data.
*
* This function does \em not fill in the address where this function was called from because it
* would not be displayed.
*
* The message is only displayed on development units/patched ErrDisp.
*
* See https://3dbrew.org/wiki/ERR:Throw#Result_Failure for expected top screen output
* on development units/patched ErrDisp.
*/
Result ERRF_ThrowResultWithMessage(Result failure, const char* message);
/**
* @brief Specify an additional user string to use for error reporting.
* @param[in] user_string User string (up to 256 bytes, not including NUL byte)
*/
Result ERRF_SetUserString(const char* user_string);
/**
* @brief Handles an exception using ErrDisp.
* @param excep Exception information
* @param regs CPU registers
*
* You might want to clear ENVINFO's bit0 to be able to see any debugging information.
* @sa threadOnException
*/
void ERRF_ExceptionHandler(ERRF_ExceptionInfo* excep, CpuRegisters* regs) __attribute__((noreturn));

View File

@ -0,0 +1,199 @@
/**
* @file exheader.h
* @brief NCCH extended header definitions.
*/
#pragma once
#include <3ds/types.h>
/// ARM9 descriptor flags
enum
{
ARM9DESC_MOUNT_NAND = BIT(0), ///< Mount "nand:/"
ARM9DESC_MOUNT_NANDRO_RW = BIT(1), ///< Mount nand:/ro/ as read-write
ARM9DESC_MOUNT_TWLN = BIT(2), ///< Mount "twln:/"
ARM9DESC_MOUNT_WNAND = BIT(3), ///< Mount "wnand:/"
ARM9DESC_MOUNT_CARDSPI = BIT(4), ///< Mount "cardspi:/"
ARM9DESC_USE_SDIF3 = BIT(5), ///< Use SDIF3
ARM9DESC_CREATE_SEED = BIT(6), ///< Create seed (movable.sed)
ARM9DESC_USE_CARD_SPI = BIT(7), ///< Use card SPI, required by multiple pxi:dev commands
ARM9DESC_SD_APPLICATION = BIT(8), ///< SD application (not checked)
ARM9DESC_MOUNT_SDMC_RW = BIT(9), ///< Mount "sdmc:/" as read-write
};
/// Filesystem access flags
enum
{
FSACCESS_CATEGORY_SYSTEM_APPLICATION = BIT(0), ///< Category "system application"
FSACCESS_CATEGORY_HARDWARE_CHECK = BIT(1), ///< Category "hardware check"
FSACCESS_CATEGORY_FILESYSTEM_TOOL = BIT(2), ///< Category "filesystem tool"
FSACCESS_DEBUG = BIT(3), ///< Debug
FSACCESS_TWLCARD_BACKUP = BIT(4), ///< TWLCARD backup
FSACCESS_TWLNAND_DATA = BIT(5), ///< TWLNAND data
FSACCESS_BOSS = BIT(6), ///< BOSS (SpotPass)
FSACCESS_SDMC_RW = BIT(7), ///< SDMC (read-write)
FSACCESS_CORE = BIT(8), ///< Core
FSACCESS_NANDRO_RO = BIT(9), ///< nand:/ro/ (read-only)
FSACCESS_NANDRW = BIT(10), ///< nand:/rw/
FSACCESS_NANDRO_RW = BIT(11), ///< nand:/ro/ (read-write)
FSACCESS_CATEGORY_SYSTEM_SETTINGS = BIT(12), ///< Category "System Settings"
FSACCESS_CARDBOARD = BIT(13), ///< Cardboard (System Transfer)
FSACCESS_EXPORT_IMPORT_IVS = BIT(14), ///< Export/Import IVs (movable.sed)
FSACCESS_SDMC_WO = BIT(15), ///< SDMC (write-only)
FSACCESS_SWITCH_CLEANUP = BIT(16), ///< "Switch cleanup" (3.0+)
FSACCESS_SAVEDATA_MOVE = BIT(17), ///< Savedata move (5.0+)
FSACCESS_SHOP = BIT(18), ///< Shop (5.0+)
FSACCESS_SHELL = BIT(19), ///< Shop (5.0+)
FSACCESS_CATEGORY_HOME_MENU = BIT(20), ///< Category "Home Menu" (6.0+)
FSACCESS_SEEDDB = BIT(21), ///< Seed DB (9.6+)
};
/// The resource limit category of a title
typedef enum
{
RESLIMIT_CATEGORY_APPLICATION = 0, ///< Regular application
RESLIMIT_CATEGORY_SYS_APPLET = 1, ///< System applet
RESLIMIT_CATEGORY_LIB_APPLET = 2, ///< Library applet
RESLIMIT_CATEGORY_OTHER = 3, ///< System modules running inside the BASE memregion
} ResourceLimitCategory;
/// The system mode a title should be launched under
typedef enum
{
SYSMODE_O3DS_PROD = 0, ///< 64MB of usable application memory
SYSMODE_N3DS_PROD = 1, ///< 124MB of usable application memory. Unusable on O3DS
SYSMODE_DEV1 = 2, ///< 97MB/178MB of usable application memory
SYSMODE_DEV2 = 3, ///< 80MB/124MB of usable application memory
SYSMODE_DEV3 = 4, ///< 72MB of usable application memory. Same as "Prod" on N3DS
SYSMODE_DEV4 = 5, ///< 32MB of usable application memory. Same as "Prod" on N3DS
} SystemMode;
/// The system info flags and remaster version of a title
typedef struct
{
u8 reserved[5]; ///< Reserved
bool compress_exefs_code : 1; ///< Whether the ExeFS's .code section is compressed
bool is_sd_application : 1; ///< Whether the title is meant to be used on an SD card
u16 remaster_version; ///< Remaster version
} ExHeader_SystemInfoFlags;
/// Information about a title's section
typedef struct
{
u32 address; ///< The address of the section
u32 num_pages; ///< The number of pages the section occupies
u32 size; ///< The size of the section
} ExHeader_CodeSectionInfo;
/// The name of a title and infomation about its section
typedef struct
{
char name[8]; ///< Title name
ExHeader_SystemInfoFlags flags; ///< System info flags, see @ref ExHeader_SystemInfoFlags
ExHeader_CodeSectionInfo text; ///< .text section info, see @ref ExHeader_CodeSectionInfo
u32 stack_size; ///< Stack size
ExHeader_CodeSectionInfo rodata; ///< .rodata section info, see @ref ExHeader_CodeSectionInfo
u32 reserved; ///< Reserved
ExHeader_CodeSectionInfo data; ///< .data section info, see @ref ExHeader_CodeSectionInfo
u32 bss_size; ///< .bss section size
} ExHeader_CodeSetInfo;
/// The savedata size and jump ID of a title
typedef struct
{
u64 savedata_size; ///< Savedata size
u64 jump_id; ///< Jump ID
u8 reserved[0x30]; ///< Reserved
} ExHeader_SystemInfo;
/// The code set info, dependencies and system info of a title (SCI)
typedef struct
{
ExHeader_CodeSetInfo codeset_info; ///< Code set info, see @ref ExHeader_CodeSetInfo
u64 dependencies[48]; ///< Title IDs of the titles that this program depends on
ExHeader_SystemInfo system_info; ///< System info, see @ref ExHeader_SystemInfo
} ExHeader_SystemControlInfo;
/// The ARM11 filesystem info of a title
typedef struct
{
u64 extdata_id; ///< Extdata ID
u32 system_savedata_ids[2]; ///< IDs of the system savedata accessible by the title
u64 accessible_savedata_ids; ///< IDs of the savedata accessible by the title, 20 bits each, followed by "Use other variation savedata"
u32 fs_access_info; ///< FS access flags
u32 reserved : 24; ///< Reserved
bool no_romfs : 1; ///< Don't use any RomFS
bool use_extended_savedata_access : 1; ///< Use the "extdata_id" field to store 3 additional accessible savedata IDs
} ExHeader_Arm11StorageInfo;
/// The CPU-related and memory-layout-related info of a title
typedef struct
{
u32 core_version; ///< The low title ID of the target firmware
bool use_cpu_clockrate_804MHz : 1; ///< Whether to start the title with the 804MHz clock rate
bool enable_l2c : 1; ///< Whether to start the title with the L2C-310 enabled enabled
u8 flag1_unused : 6; ///< Unused
SystemMode n3ds_system_mode : 4; ///< The system mode to use on N3DS
u8 flag2_unused : 4; ///< Unused
u8 ideal_processor : 2; ///< The ideal processor to start the title on
u8 affinity_mask : 2; ///< The affinity mask of the title
SystemMode o3ds_system_mode : 4; ///< The system mode to use on N3DS
u8 priority; ///< The priority of the title's main thread
} ExHeader_Arm11CoreInfo;
/// The ARM11 system-local capabilities of a title
typedef struct
{
u64 title_id; ///< Title ID
ExHeader_Arm11CoreInfo core_info; ///< Core info, see @ref ExHeader_Arm11CoreInfo
u16 reslimits[16]; ///< Resource limit descriptors, only "CpuTime" (first byte) sems to be used
ExHeader_Arm11StorageInfo storage_info; ///< Storage info, see @ref ExHeader_Arm11StorageInfo
char service_access[34][8]; ///< List of the services the title has access to. Limited to 32 prior to system version 9.3
u8 reserved[15]; ///< Reserved
ResourceLimitCategory reslimit_category; ///< Resource limit category, see @ref ExHeader_Arm11SystemLocalCapabilities
} ExHeader_Arm11SystemLocalCapabilities;
/// The ARM11 kernel capabilities of a title
typedef struct
{
u32 descriptors[28]; ///< ARM11 kernel descriptors, see 3dbrew
u8 reserved[16]; ///< Reserved
} ExHeader_Arm11KernelCapabilities;
/// The ARM9 access control of a title
typedef struct
{
u8 descriptors[15]; ///< Process9 FS descriptors, see 3dbrew
u8 descriptor_version; ///< Descriptor version
} ExHeader_Arm9AccessControl;
/// The access control information of a title
typedef struct
{
ExHeader_Arm11SystemLocalCapabilities local_caps; ///< ARM11 system-local capabilities, see @ref ExHeader_Arm11SystemLocalCapabilities
ExHeader_Arm11KernelCapabilities kernel_caps; ///< ARM11 kernel capabilities, see @ref ExHeader_Arm11SystemLocalCapabilities
ExHeader_Arm9AccessControl access_control; ///< ARM9 access control, see @ref ExHeader_Arm9AccessControl
} ExHeader_AccessControlInfo;
/// Main extended header data, as returned by PXIPM, Loader and FSREG service commands
typedef struct
{
ExHeader_SystemControlInfo sci; ///< System control info, see @ref ExHeader_SystemControlInfo
ExHeader_AccessControlInfo aci; ///< Access control info, see @ref ExHeader_AccessControlInfo
} ExHeader_Info;
/// Extended header access descriptor
typedef struct
{
u8 signature[0x100]; ///< The signature of the access descriptor (RSA-2048-SHA256)
u8 ncchModulus[0x100]; ///< The modulus used for the above signature, with 65537 as public exponent
ExHeader_AccessControlInfo acli; ///< This is compared for equality with the first ACI by Process9, see @ref ExHeader_AccessControlInfo
} ExHeader_AccessDescriptor;
/// The NCCH Extended Header of a title
typedef struct
{
ExHeader_Info info; ///< Main extended header data, see @ref ExHeader_Info
ExHeader_AccessDescriptor access_descriptor; ///< Access descriptor, see @ref ExHeader_AccessDescriptor
} ExHeader;

View File

@ -157,49 +157,80 @@ enum
/// Ensures the shared system font is mapped.
Result fontEnsureMapped(void);
/// Retrieves the font information structure of the shared system font.
static inline FINF_s* fontGetInfo(void)
/**
* @brief Fixes the pointers internal to a just-loaded font
* @param font Font to fix
* @remark Should never be run on the system font, and only once on any other font.
*/
void fontFixPointers(CFNT_s* font);
/// Gets the currently loaded system font
static inline CFNT_s* fontGetSystemFont(void)
{
extern CFNT_s* g_sharedFont;
return &g_sharedFont->finf;
if (!g_sharedFont)
fontEnsureMapped();
return g_sharedFont;
}
/// Retrieves the texture sheet information of the shared system font.
static inline TGLP_s* fontGetGlyphInfo(void)
/**
* @brief Retrieves the font information structure of a font.
* @param font Pointer to font structure. If NULL, the shared system font is used.
*/
static inline FINF_s* fontGetInfo(CFNT_s* font)
{
return fontGetInfo()->tglp;
if (!font)
font = fontGetSystemFont();
return &font->finf;
}
/**
* @brief Retrieves the texture sheet information of a font.
* @param font Pointer to font structure. If NULL, the shared system font is used.
*/
static inline TGLP_s* fontGetGlyphInfo(CFNT_s* font)
{
if (!font)
font = fontGetSystemFont();
return fontGetInfo(font)->tglp;
}
/**
* @brief Retrieves the pointer to texture data for the specified texture sheet.
* @param font Pointer to font structure. If NULL, the shared system font is used.
* @param sheetIndex Index of the texture sheet.
*/
static inline void* fontGetGlyphSheetTex(int sheetIndex)
static inline void* fontGetGlyphSheetTex(CFNT_s* font, int sheetIndex)
{
TGLP_s* tglp = fontGetGlyphInfo();
if (!font)
font = fontGetSystemFont();
TGLP_s* tglp = fontGetGlyphInfo(font);
return &tglp->sheetData[sheetIndex*tglp->sheetSize];
}
/**
* @brief Retrieves the glyph index of the specified Unicode codepoint.
* @param font Pointer to font structure. If NULL, the shared system font is used.
* @param codePoint Unicode codepoint.
*/
int fontGlyphIndexFromCodePoint(u32 codePoint);
int fontGlyphIndexFromCodePoint(CFNT_s* font, u32 codePoint);
/**
* @brief Retrieves character width information of the specified glyph.
* @param font Pointer to font structure. If NULL, the shared system font is used.
* @param glyphIndex Index of the glyph.
*/
charWidthInfo_s* fontGetCharWidthInfo(int glyphIndex);
charWidthInfo_s* fontGetCharWidthInfo(CFNT_s* font, int glyphIndex);
/**
* @brief Calculates position information for the specified glyph.
* @param out Output structure in which to write the information.
* @param font Pointer to font structure. If NULL, the shared system font is used.
* @param glyphIndex Index of the glyph.
* @param flags Calculation flags (see GLYPH_POS_* flags).
* @param scaleX Scale factor to apply horizontally.
* @param scaleY Scale factor to apply vertically.
*/
void fontCalcGlyphPos(fontGlyphPos_s* out, int glyphIndex, u32 flags, float scaleX, float scaleY);
void fontCalcGlyphPos(fontGlyphPos_s* out, CFNT_s* font, int glyphIndex, u32 flags, float scaleX, float scaleY);
///@}

View File

@ -0,0 +1,29 @@
/**
* @file gdbhio.h
* @brief Luma3DS GDB HIO (called File I/O in GDB documentation) functions.
*/
#pragma once
#include <fcntl.h>
#include <sys/time.h>
#include <sys/stat.h>
#define GDBHIO_STDIN_FILENO 0
#define GDBHIO_STDOUT_FILENO 1
#define GDBHIO_STDERR_FILENO 2
int gdbHioOpen(const char *pathname, int flags, mode_t mode);
int gdbHioClose(int fd);
int gdbHioRead(int fd, void *buf, unsigned int count);
int gdbHioWrite(int fd, const void *buf, unsigned int count);
off_t gdbHioLseek(int fd, off_t offset, int flag);
int gdbHioRename(const char *oldpath, const char *newpath);
int gdbHioUnlink(const char *pathname);
int gdbHioStat(const char *pathname, struct stat *st);
int gdbHioFstat(int fd, struct stat *st);
int gdbHioGettimeofday(struct timeval *tv, void *tz);
int gdbHioIsatty(int fd);
///< Host I/O 'system' function, requires 'set remote system-call-allowed 1'.
int gdbHioSystem(const char *command);

View File

@ -0,0 +1,37 @@
/**
* @file gdbhio_dev.h
* @brief Luma3DS GDB HIO (called File I/O in GDB documentation) devoptab wrapper.
*/
#pragma once
#include <stdbool.h>
struct timeval;
///< Initializes the GDB HIO devoptab wrapper, returns 0 on success, -1 on failure.
int gdbHioDevInit(void);
///< Deinitializes the GDB HIO devoptab wrapper.
void gdbHioDevExit(void);
///< Returns a file descriptor mapping to the GDB client console's standard input stream.
int gdbHioDevGetStdin(void);
///< Returns a file descriptor mapping to the GDB client console's standard output stream.
int gdbHioDevGetStdout(void);
///< Returns a file descriptor mapping to the GDB client console's standard error stream.
int gdbHioDevGetStderr(void);
///< Redirects 0 to 3 of the application's standard streams to GDB client console's. Returns -1, -2, or -3, resp., on failure; 0 on success.
int gdbHioDevRedirectStdStreams(bool in, bool out, bool err);
///< GDB HIO POSIX function gettimeofday.
int gdbHioDevGettimeofday(struct timeval *tv, void *tz);
///< GDB HIO POSIX function isatty.
int gdbHioDevIsatty(int fd);
///< GDB HIO POSIX function system. Requires 'set remote system-call-allowed 1'.
int gdbHioDevSystem(const char *command);

View File

@ -1,9 +1,14 @@
/**
* @file gfx.h
* @brief LCD Screens manipulation
* @brief Simple framebuffer API
*
* This header provides functions to configure and manipulate the two screens, including double buffering and 3D activation.
* This API provides basic functionality needed to bring up framebuffers for both screens,
* as well as managing display mode (stereoscopic 3D) and double buffering.
* It is mainly an abstraction over the gsp service.
*
* Please note that the 3DS uses *portrait* screens rotated 90 degrees counterclockwise.
* Width/height refer to the physical dimensions of the screen; that is, the top screen
* is 240 pixels wide and 400 pixels tall; while the bottom screen is 240x320.
*/
#pragma once
@ -16,36 +21,29 @@
/// Converts packed RGB8 to packed RGB565.
#define RGB8_to_565(r,g,b) (((b)>>3)&0x1f)|((((g)>>2)&0x3f)<<5)|((((r)>>3)&0x1f)<<11)
/// Available screens.
typedef enum
{
GFX_TOP = 0, ///< Top screen
GFX_BOTTOM = 1 ///< Bottom screen
}gfxScreen_t;
/// Screen IDs.
typedef enum {
GFX_TOP = GSP_SCREEN_TOP, ///< Top screen
GFX_BOTTOM = GSP_SCREEN_BOTTOM, ///< Bottom screen
} gfxScreen_t;
/**
* @brief Side of top screen framebuffer.
* @brief Top screen framebuffer side.
*
* This is to be used only when the 3D is enabled.
* Use only GFX_LEFT if this concerns the bottom screen or if 3D is disabled.
* This is only meaningful when stereoscopic 3D is enabled on the top screen.
* In any other case, use \ref GFX_LEFT.
*/
typedef enum
{
GFX_LEFT = 0, ///< Left eye framebuffer
GFX_RIGHT = 1,///< Right eye framebuffer
}gfx3dSide_t;
typedef enum {
GFX_LEFT = 0, ///< Left eye framebuffer
GFX_RIGHT = 1, ///< Right eye framebuffer
} gfx3dSide_t;
///@name System related
///@name Initialization and deinitialization
///@{
/**
* @brief Initializes the LCD framebuffers with default parameters
*
* By default ctrulib will configure the LCD framebuffers with the @ref GSP_BGR8_OES format in linear memory.
* This is the same as calling : @code gfxInit(GSP_BGR8_OES,GSP_BGR8_OES,false); @endcode
*
* @note You should always call @ref gfxExit once done to free the memory and services
* This is equivalent to calling: @code gfxInit(GSP_BGR8_OES,GSP_BGR8_OES,false); @endcode
*/
void gfxInitDefault(void);
@ -55,117 +53,128 @@ void gfxInitDefault(void);
* @param bottomFormat The format of the bottom screen framebuffers.
* @param vramBuffers Whether to allocate the framebuffers in VRAM.
*
* This function will allocate the memory for the framebuffers and open a gsp service session.
* It will also bind the newly allocated framebuffers to the LCD screen and setup the VBlank event.
* This function allocates memory for the framebuffers in the specified memory region.
* Initially, stereoscopic 3D is disabled and double buffering is enabled.
*
* The 3D stereoscopic display is will be disabled.
*
* @note Even if the double buffering is disabled, it will allocate two buffer per screen.
* @note You should always call @ref gfxExit once done to free the memory and services
* @note This function internally calls \ref gspInit.
*/
void gfxInit(GSPGPU_FramebufferFormats topFormat, GSPGPU_FramebufferFormats bottomFormat, bool vrambuffers);
void gfxInit(GSPGPU_FramebufferFormat topFormat, GSPGPU_FramebufferFormat bottomFormat, bool vrambuffers);
/**
* @brief Closes the gsp service and frees the framebuffers.
*
* Just call it when you're done.
* @brief Deinitializes and frees the LCD framebuffers.
* @note This function internally calls \ref gspExit.
*/
void gfxExit(void);
///@}
///@name Control
///@{
/**
* @brief Enables the 3D stereoscopic effect.
* @param enable Enables the 3D effect if true, disables it if false.
* @brief Enables or disables the 3D stereoscopic effect on the top screen.
* @param enable Pass true to enable, false to disable.
* @note Stereoscopic 3D is disabled by default.
*/
void gfxSet3D(bool enable);
/**
* @brief Retrieves the status of the 3D stereoscopic effect.
* @brief Retrieves the status of the 3D stereoscopic effect on the top screen.
* @return true if 3D enabled, false otherwise.
*/
bool gfxIs3D(void);
/**
* @brief Changes the color format of a screen
* @param screen The screen of which format should be changed
* @param format One of the gsp pixel formats.
* @brief Retrieves the status of the 800px (double-height) high resolution display mode of the top screen.
* @return true if wide mode enabled, false otherwise.
*/
void gfxSetScreenFormat(gfxScreen_t screen, GSPGPU_FramebufferFormats format);
bool gfxIsWide(void);
/**
* @brief Gets a screen pixel format.
* @param screen Screen to get the pixel format of.
* @return the pixel format of the chosen screen set by ctrulib.
* @brief Enables or disables the 800px (double-height) high resolution display mode of the top screen.
* @param enable Pass true to enable, false to disable.
* @note Wide mode is disabled by default.
* @note Wide and stereoscopic 3D modes are mutually exclusive.
* @note In wide mode pixels are not square, since scanlines are half as tall as they normally are.
* @warning Wide mode does not work on Old 2DS consoles (however it does work on New 2DS XL consoles).
*/
GSPGPU_FramebufferFormats gfxGetScreenFormat(gfxScreen_t screen);
void gfxSetWide(bool enable);
/**
* @brief Sets whether to use ctrulib's double buffering
* @param screen Screen to toggle double buffering for.
* @param doubleBuffering Whether to use double buffering.
*
* ctrulib is by default using a double buffering scheme.
* If you do not want to swap one of the screen framebuffers when @ref gfxSwapBuffers or @ref gfxSwapBuffers is called,
* then you have to disable double buffering.
*
* It is however recommended to call @ref gfxSwapBuffers even if double buffering is disabled
* for both screens if you want to keep the gsp configuration up to date.
* @brief Changes the pixel format of a screen.
* @param screen Screen ID (see \ref gfxScreen_t)
* @param format Pixel format (see \ref GSPGPU_FramebufferFormat)
* @note If the currently allocated framebuffers are too small for the specified format,
* they are freed and new ones are reallocated.
*/
void gfxSetDoubleBuffering(gfxScreen_t screen, bool doubleBuffering);
void gfxSetScreenFormat(gfxScreen_t screen, GSPGPU_FramebufferFormat format);
/**
* @brief Flushes the current framebuffers
* @brief Retrieves the current pixel format of a screen.
* @param screen Screen ID (see \ref gfxScreen_t)
* @return Pixel format (see \ref GSPGPU_FramebufferFormat)
*/
GSPGPU_FramebufferFormat gfxGetScreenFormat(gfxScreen_t screen);
/**
* @brief Enables or disables double buffering on a screen.
* @param screen Screen ID (see \ref gfxScreen_t)
* @param enable Pass true to enable, false to disable.
* @note Double buffering is enabled by default.
*/
void gfxSetDoubleBuffering(gfxScreen_t screen, bool enable);
///@}
///@name Rendering and presentation
///@{
/**
* @brief Retrieves the framebuffer of the specified screen to which graphics should be rendered.
* @param screen Screen ID (see \ref gfxScreen_t)
* @param side Framebuffer side (see \ref gfx3dSide_t) (pass \ref GFX_LEFT if not using stereoscopic 3D)
* @param width Pointer that will hold the width of the framebuffer in pixels.
* @param height Pointer that will hold the height of the framebuffer in pixels.
* @return A pointer to the current framebuffer of the chosen screen.
*
* Use this if the data within your framebuffers changes a lot and that you want to make sure everything was updated correctly.
* This shouldn't be needed and has a significant overhead.
* Please remember that the returned pointer will change every frame if double buffering is enabled.
*/
u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height);
/**
* @brief Flushes the data cache for the current framebuffers.
* @warning This is **only used during software rendering**. Since this function has significant overhead,
* it is preferred to call this only once per frame, after all software rendering is completed.
*/
void gfxFlushBuffers(void);
/**
* @brief Updates the configuration of the specified screen (swapping the buffers if double-buffering is enabled).
* @param scr Screen to configure.
* @param immediate Whether to apply the updated configuration immediately or let GSPGPU apply it after the next GX transfer completes.
* @brief Updates the configuration of the specified screen, swapping the buffers if double buffering is enabled.
* @param scr Screen ID (see \ref gfxScreen_t)
* @param hasStereo For the top screen in 3D mode: true if the framebuffer contains individual images
* for both eyes, or false if the left image should be duplicated to the right eye.
* @note Previously rendered content will be displayed on the screen after the next VBlank.
* @note This function is still useful even if double buffering is disabled, as it must be used to commit configuration changes.
* @warning Only call this once per screen per frame, otherwise graphical glitches will occur
* since this API does not implement triple buffering.
*/
void gfxConfigScreen(gfxScreen_t scr, bool immediate);
void gfxScreenSwapBuffers(gfxScreen_t scr, bool hasStereo);
/**
* @brief Swaps the buffers and sets the gsp state
*
* This is to be called to update the gsp state and swap the framebuffers.
* LCD rendering should start as soon as the gsp state is set.
* When using the GPU, call @ref gfxSwapBuffers instead.
* @brief Same as \ref gfxScreenSwapBuffers, but with hasStereo set to true.
* @param scr Screen ID (see \ref gfxScreen_t)
* @param immediate This parameter no longer has any effect and is thus ignored.
* @deprecated This function has been superseded by \ref gfxScreenSwapBuffers, please use that instead.
*/
CTR_DEPRECATED void gfxConfigScreen(gfxScreen_t scr, bool immediate);
/**
* @brief Updates the configuration of both screens.
* @note This function is equivalent to: \code gfxScreenSwapBuffers(GFX_TOP,true); gfxScreenSwapBuffers(GFX_BOTTOM,true); \endcode
*/
void gfxSwapBuffers(void);
/**
* @brief Swaps the framebuffers
*
* This is the version to be used with the GPU since the GPU will use the gsp shared memory,
* so the gsp state mustn't be set directly by the user.
*/
/// Same as \ref gfxSwapBuffers (formerly different).
void gfxSwapBuffersGpu(void);
///@}
///@name Helper
///@{
/**
* @brief Retrieves a framebuffer information.
* @param screen Screen to retrieve framebuffer information for.
* @param side Side of the screen to retrieve framebuffer information for.
* @param width Pointer that will hold the width of the framebuffer in pixels.
* @param height Pointer that will hold the height of the framebuffer in pixels.
* @return A pointer to the current framebuffer of the choosen screen.
*
* Please remember that the returned pointer will change after each call to gfxSwapBuffers if double buffering is enabled.
*/
u8* gfxGetFramebuffer(gfxScreen_t screen, gfx3dSide_t side, u16* width, u16* height);
///@}
//global variables
extern u8* gfxTopLeftFramebuffers[2];
extern u8* gfxTopRightFramebuffers[2];
extern u8* gfxBottomFramebuffers[2];

View File

@ -78,6 +78,18 @@ typedef enum
GPU_ETC1A4 = 0xD, ///< ETC1 texture compression + 4-bit Alpha
} GPU_TEXCOLOR;
/// Texture faces.
typedef enum
{
GPU_TEXFACE_2D = 0, ///< 2D face
GPU_POSITIVE_X = 0, ///< +X face
GPU_NEGATIVE_X = 1, ///< -X face
GPU_POSITIVE_Y = 2, ///< +Y face
GPU_NEGATIVE_Y = 3, ///< -Y face
GPU_POSITIVE_Z = 4, ///< +Z face
GPU_NEGATIVE_Z = 5, ///< -Z face
} GPU_TEXFACE;
/// Procedural texture clamp modes.
typedef enum
{
@ -126,10 +138,10 @@ typedef enum
typedef enum
{
GPU_LUT_NOISE = 0, ///< Noise table
GPU_LUT_RGBMAP = 1, ///< RGB mapping function table
GPU_LUT_ALPHAMAP = 2, ///< Alpha mapping function table
GPU_LUT_COLOR = 3, ///< Color table
GPU_LUT_COLORDIF = 4, ///< Color difference table
GPU_LUT_RGBMAP = 2, ///< RGB mapping function table
GPU_LUT_ALPHAMAP = 3, ///< Alpha mapping function table
GPU_LUT_COLOR = 4, ///< Color table
GPU_LUT_COLORDIF = 5, ///< Color difference table
} GPU_PROCTEX_LUTID;
/// Supported color buffer formats.
@ -172,6 +184,18 @@ typedef enum
GPU_EARLYDEPTH_LESS = 3, ///< Pass if less than.
} GPU_EARLYDEPTHFUNC;
/// Gas depth functions.
typedef enum
{
GPU_GAS_NEVER = 0, ///< Never pass (0).
GPU_GAS_ALWAYS = 1, ///< Always pass (1).
GPU_GAS_GREATER = 2, ///< Pass if greater than (1-X).
GPU_GAS_LESS = 3, ///< Pass if less than (X).
} GPU_GASDEPTHFUNC;
/// Converts \ref GPU_TESTFUNC into \ref GPU_GASDEPTHFUNC.
#define GPU_MAKEGASDEPTHFUNC(n) (GPU_GASDEPTHFUNC)((0xAF02>>((int)(n)<<1))&3)
/// Scissor test modes.
typedef enum
{
@ -344,7 +368,8 @@ typedef enum
GPU_ADD_SIGNED = 0x03, ///< Signed add.
GPU_INTERPOLATE = 0x04, ///< Interpolate.
GPU_SUBTRACT = 0x05, ///< Subtract.
GPU_DOT3_RGB = 0x06, ///< Dot3. RGB only.
GPU_DOT3_RGB = 0x06, ///< Dot3. Scalar result is written to RGB only.
GPU_DOT3_RGBA = 0x07, ///< Dot3. Scalar result is written to RGBA.
GPU_MULTIPLY_ADD = 0x08, ///< Multiply then add.
GPU_ADD_MULTIPLY = 0x09, ///< Add then multiply.
} GPU_COMBINEFUNC;
@ -373,7 +398,7 @@ typedef enum
/// Light distance attenuation disable bits in GPUREG_LIGHT_CONFIG1.
#define GPU_LC1_ATTNBIT(n) BIT((n)+24)
/// Creates a light permutation parameter.
#define GPU_LIGHTPERM(i,n) ((n) << (i))
#define GPU_LIGHTPERM(i,n) ((n) << ((i)*4))
/// Creates a light LUT input parameter.
#define GPU_LIGHTLUTINPUT(i,n) ((n) << ((i)*4))
/// Creates a light LUT index parameter.
@ -441,6 +466,28 @@ typedef enum
GPU_LUTSELECT_DA = 2, ///< Distance attenuation LUT.
} GPU_LIGHTLUTSELECT;
/// Fog modes.
typedef enum
{
GPU_NO_FOG = 0, ///< Fog/Gas unit disabled.
GPU_FOG = 5, ///< Fog/Gas unit configured in Fog mode.
GPU_GAS = 7, ///< Fog/Gas unit configured in Gas mode.
} GPU_FOGMODE;
/// Gas shading density source values.
typedef enum
{
GPU_PLAIN_DENSITY = 0, ///< Plain density.
GPU_DEPTH_DENSITY = 1, ///< Depth density.
} GPU_GASMODE;
/// Gas color LUT inputs.
typedef enum
{
GPU_GAS_DENSITY = 0, ///< Gas density used as input.
GPU_GAS_LIGHT_FACTOR = 1, ///< Light factor used as input.
} GPU_GASLUTINPUT;
/// Supported primitives.
typedef enum
{

View File

@ -20,21 +20,34 @@ extern u32 gpuCmdBufOffset; ///< GPU command buffer offset.
* @param size Size of the command buffer.
* @param offset Offset of the command buffer.
*/
void GPUCMD_SetBuffer(u32* adr, u32 size, u32 offset);
static inline void GPUCMD_SetBuffer(u32* adr, u32 size, u32 offset)
{
gpuCmdBuf=adr;
gpuCmdBufSize=size;
gpuCmdBufOffset=offset;
}
/**
* @brief Sets the offset of the GPU command buffer.
* @param offset Offset of the command buffer.
*/
void GPUCMD_SetBufferOffset(u32 offset);
static inline void GPUCMD_SetBufferOffset(u32 offset)
{
gpuCmdBufOffset=offset;
}
/**
* @brief Gets the current GPU command buffer.
* @param adr Pointer to output the command buffer to.
* @param size Pointer to output the size of the command buffer to.
* @param addr Pointer to output the command buffer to.
* @param size Pointer to output the size (in words) of the command buffer to.
* @param offset Pointer to output the offset of the command buffer to.
*/
void GPUCMD_GetBuffer(u32** adr, u32* size, u32* offset);
static inline void GPUCMD_GetBuffer(u32** addr, u32* size, u32* offset)
{
if(addr)*addr=gpuCmdBuf;
if(size)*size=gpuCmdBufSize;
if(offset)*offset=gpuCmdBufOffset;
}
/**
* @brief Adds raw GPU commands to the current command buffer.
@ -43,12 +56,6 @@ void GPUCMD_GetBuffer(u32** adr, u32* size, u32* offset);
*/
void GPUCMD_AddRawCommands(const u32* cmd, u32 size);
/// Executes the GPU command buffer.
void GPUCMD_Run(void);
/// Flushes linear memory and executes the GPU command buffer.
void GPUCMD_FlushAndRun(void);
/**
* @brief Adds a GPU command to the current command buffer.
* @param header Header of the command.
@ -57,8 +64,12 @@ void GPUCMD_FlushAndRun(void);
*/
void GPUCMD_Add(u32 header, const u32* param, u32 paramlength);
/// Finalizes the GPU command buffer.
void GPUCMD_Finalize(void);
/**
* @brief Splits the current GPU command buffer.
* @param addr Pointer to output the command buffer to.
* @param size Pointer to output the size (in words) of the command buffer to.
*/
void GPUCMD_Split(u32** addr, u32* size);
/**
* @brief Converts a 32-bit float to a 16-bit float.

View File

@ -13,7 +13,7 @@
/**
* @brief Supported transfer pixel formats.
* @sa GSPGPU_FramebufferFormats
* @sa GSPGPU_FramebufferFormat
*/
typedef enum
{
@ -60,12 +60,87 @@ typedef enum
/// Creates a transfer scaling flag.
#define GX_TRANSFER_SCALING(x) ((x)<<24)
/// Command list flag bit 0.
#define GX_CMDLIST_BIT0 BIT(0)
/// Updates gas additive blend results.
#define GX_CMDLIST_UPDATE_GAS_ACC BIT(0)
/// Flushes the command list.
#define GX_CMDLIST_FLUSH BIT(1)
#define GX_CMDLIST_FLUSH BIT(1)
extern u32* gxCmdBuf; ///< GX command buffer.
/// GX command entry
typedef union
{
u32 data[8]; ///< Raw command data
struct
{
u8 type; ///< Command type
u8 unk1;
u8 unk2;
u8 unk3;
u32 args[7]; ///< Command arguments
};
} gxCmdEntry_s;
/// GX command queue structure
typedef struct tag_gxCmdQueue_s
{
gxCmdEntry_s* entries; ///< Pointer to array of GX command entries
u16 maxEntries; ///< Capacity of the command array
u16 numEntries; ///< Number of commands in the queue
u16 curEntry; ///< Index of the first pending command to be submitted to GX
u16 lastEntry; ///< Number of commands completed by GX
void (* callback)(struct tag_gxCmdQueue_s*); ///< User callback
void* user; ///< Data for user callback
} gxCmdQueue_s;
/**
* @brief Clears a GX command queue.
* @param queue The GX command queue.
*/
void gxCmdQueueClear(gxCmdQueue_s* queue);
/**
* @brief Adds a command to a GX command queue.
* @param queue The GX command queue.
* @param entry The GX command to add.
*/
void gxCmdQueueAdd(gxCmdQueue_s* queue, const gxCmdEntry_s* entry);
/**
* @brief Runs a GX command queue, causing it to begin processing incoming commands as they arrive.
* @param queue The GX command queue.
*/
void gxCmdQueueRun(gxCmdQueue_s* queue);
/**
* @brief Stops a GX command queue from processing incoming commands.
* @param queue The GX command queue.
*/
void gxCmdQueueStop(gxCmdQueue_s* queue);
/**
* @brief Waits for a GX command queue to finish executing pending commands.
* @param queue The GX command queue.
* @param timeout Optional timeout (in nanoseconds) to wait (specify -1 for no timeout).
* @return false if timeout expired, true otherwise.
*/
bool gxCmdQueueWait(gxCmdQueue_s* queue, s64 timeout);
/**
* @brief Sets the completion callback for a GX command queue.
* @param queue The GX command queue.
* @param callback The completion callback.
* @param user User data.
*/
static inline void gxCmdQueueSetCallback(gxCmdQueue_s* queue, void (* callback)(gxCmdQueue_s*), void* user)
{
queue->callback = callback;
queue->user = user;
}
/**
* @brief Selects a command queue to which GX_* functions will add commands instead of immediately submitting them to GX.
* @param queue The GX command queue. (Pass NULL to remove the bound command queue)
*/
void GX_BindQueue(gxCmdQueue_s* queue);
/**
* @brief Requests a DMA.
@ -120,7 +195,7 @@ Result GX_DisplayTransfer(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 fl
Result GX_TextureCopy(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 size, u32 flags);
/**
* @brief Flushes the cache regions of three buffers.
* @brief Flushes the cache regions of three buffers. (This command cannot be queued in a GX command queue)
* @param buf0a Address of the first buffer.
* @param buf0s Size of the first buffer.
* @param buf1a Address of the second buffer.

View File

@ -311,7 +311,7 @@
#define GPUREG_GAS_LIGHT_Z_COLOR 0x0122 ///< Unknown.
#define GPUREG_GAS_LUT_INDEX 0x0123 ///< Unknown.
#define GPUREG_GAS_LUT_DATA 0x0124 ///< Unknown.
#define GPUREG_0125 0x0125 ///< Unknown.
#define GPUREG_GAS_ACCMAX_FEEDBACK 0x0125 ///< Unknown.
#define GPUREG_GAS_DELTAZ_DEPTH 0x0126 ///< Unknown.
#define GPUREG_0127 0x0127 ///< Unknown.
#define GPUREG_0128 0x0128 ///< Unknown.

View File

@ -60,16 +60,21 @@ static inline u32 IPC_Desc_MoveHandles(unsigned number)
}
/**
* @brief Returns the code to ask the kernel to fill the handle with the current process handle.
* @return The code to request the current process handle.
* @brief Returns the code to ask the kernel to fill the handle with the current process ID.
* @return The code to request the current process ID.
*
* The next value is a placeholder that will be replaced by the current process handle by the kernel.
* The next value is a placeholder that will be replaced by the current process ID by the kernel.
*/
static inline u32 IPC_Desc_CurProcessHandle(void)
static inline u32 IPC_Desc_CurProcessId(void)
{
return 0x20;
}
static inline CTR_DEPRECATED u32 IPC_Desc_CurProcessHandle(void)
{
return IPC_Desc_CurProcessId();
}
/**
* @brief Creates a header describing a static buffer.
* @param size Size of the buffer. Max ?0x03FFFF?.

159
libctru/include/3ds/mii.h Normal file
View File

@ -0,0 +1,159 @@
/**
* @file mii.h
* @brief Shared Mii struct.
*
* @see https://www.3dbrew.org/wiki/Mii#Mii_format
*/
#pragma once
#include <3ds/types.h>
/// Shared Mii struct
typedef struct
{
u8 magic; ///< Always 3?
/// Mii options
struct
{
bool allow_copying : 1; ///< True if copying is allowed
bool is_private_name : 1; ///< Private name?
u8 region_lock : 2; ///< Region lock (0=no lock, 1=JPN, 2=USA, 3=EUR)
u8 char_set : 2; ///< Character set (0=JPN+USA+EUR, 1=CHN, 2=KOR, 3=TWN)
} mii_options;
/// Mii position in Mii selector or Mii maker
struct
{
u8 page_index : 4; ///< Page index of Mii
u8 slot_index : 4; ///< Slot offset of Mii on its Page
} mii_pos;
/// Console Identity
struct
{
u8 unknown0 : 4; ///< Mabye padding (always seems to be 0)?
u8 origin_console : 3; ///< Console that the Mii was created on (1=WII, 2=DSI, 3=3DS)
} console_identity;
u64 system_id; ///< Identifies the system that the Mii was created on (Determines pants)
u32 mii_id; ///< ID of Mii
u8 mac[6]; ///< Creator's system's full MAC address
u8 pad[2]; ///< Padding
/// Mii details
struct {
bool sex : 1; ///< Sex of Mii (False=Male, True=Female)
u16 bday_month : 4; ///< Month of Mii's birthday
u16 bday_day : 5; ///< Day of Mii's birthday
u16 shirt_color : 4; ///< Color of Mii's shirt
bool favorite : 1; ///< Whether the Mii is one of your 10 favorite Mii's
} mii_details;
u16 mii_name[10]; ///< Name of Mii (Encoded using UTF16)
u8 height; ///< How tall the Mii is
u8 width; ///< How wide the Mii is
/// Face style
struct
{
bool disable_sharing : 1; ///< Whether or not Sharing of the Mii is allowed
u8 shape : 4; ///< Face shape
u8 skinColor : 3; ///< Color of skin
} face_style;
/// Face details
struct
{
u8 wrinkles : 4;
u8 makeup : 4;
} face_details;
u8 hair_style;
/// Hair details
struct
{
u8 color : 3;
bool flip : 1;
} hair_details;
/// Eye details
struct
{
u32 style : 6;
u32 color : 3;
u32 scale : 4;
u32 yscale : 3;
u32 rotation : 5;
u32 xspacing : 4;
u32 yposition : 5;
} eye_details;
/// Eyebrow details
struct
{
u32 style : 5;
u32 color : 3;
u32 scale : 4;
u32 yscale : 3;
u32 pad : 1;
u32 rotation : 5;
u32 xspacing : 4;
u32 yposition : 5;
} eyebrow_details;
/// Nose details
struct
{
u16 style : 5;
u16 scale : 4;
u16 yposition : 5;
} nose_details;
/// Mouth details
struct
{
u16 style : 6;
u16 color : 3;
u16 scale : 4;
u16 yscale : 3;
} mouth_details;
/// Mustache details
struct
{
u16 mouth_yposition : 5;
u16 mustach_style : 3;
u16 pad : 2;
} mustache_details;
/// Beard details
struct
{
u16 style : 3;
u16 color : 3;
u16 scale : 4;
u16 ypos : 5;
} beard_details;
/// Glasses details
struct
{
u16 style : 4;
u16 color : 3;
u16 scale : 4;
u16 ypos : 5;
} glasses_details;
/// Mole details
struct
{
bool enable : 1;
u16 scale : 5;
u16 xpos : 5;
u16 ypos : 5;
} mole_details;
u16 author_name[10]; ///< Name of Mii's author (Encoded using UTF16)
} CTR_PACKED MiiData;

View File

@ -107,6 +107,14 @@ void ndspChnSetPaused(int id, bool paused);
*/
void ndspChnSetFormat(int id, u16 format);
/**
*
* @brief Gets the format of a channel.
* @param id ID of the channel (0..23).
* @return The format of the channel.
*/
u16 ndspChnGetFormat(int id);
/**
* @brief Sets the interpolation type of a channel.
* @param id ID of the channel (0..23).
@ -114,6 +122,13 @@ void ndspChnSetFormat(int id, u16 format);
*/
void ndspChnSetInterp(int id, ndspInterpType type);
/**
* @brief Gets the interpolation type of a channel.
* @param id ID of the channel (0..23).
* @return The interpolation type of the channel.
*/
ndspInterpType ndspChnGetInterp(int id);
/**
* @brief Sets the sample rate of a channel.
* @param id ID of the channel (0..23).
@ -121,6 +136,13 @@ void ndspChnSetInterp(int id, ndspInterpType type);
*/
void ndspChnSetRate(int id, float rate);
/**
* @brief Gets the sample rate of a channel.
* @param id ID of the channel (0..23).
* @return The sample rate of the channel.
*/
float ndspChnGetRate(int id);
/**
* @brief Sets the mix parameters (volumes) of a channel.
* @param id ID of the channel (0..23).
@ -134,6 +156,13 @@ void ndspChnSetRate(int id, float rate);
*/
void ndspChnSetMix(int id, float mix[12]);
/**
* @brief Gets the mix parameters (volumes) of a channel.
* @param id ID of the channel (0..23)
* @param mix Mix parameters to write out to. See \ref ndspChnSetMix.
*/
void ndspChnGetMix(int id, float mix[12]);
/**
* @brief Sets the DSPADPCM coefficients of a channel.
* @param id ID of the channel (0..23).

View File

@ -4,6 +4,10 @@
*/
#pragma once
#include <3ds/os.h>
#define NDSP_SAMPLE_RATE (SYSCLOCK_SOC / 512.0)
///@name Data types
///@{
/// Sound output modes.
@ -114,24 +118,48 @@ u32 ndspGetFrameCount(void);
*/
void ndspSetMasterVol(float volume);
/**
* @brief Gets the master volume.
* @return The master volume.
*/
float ndspGetMasterVol(void);
/**
* @brief Sets the output mode.
* @param mode Output mode to set. Defaults to NDSP_OUTPUT_STEREO.
*/
void ndspSetOutputMode(ndspOutputMode mode);
/**
* @brief Gets the output mode.
* @return The output mode.
*/
ndspOutputMode ndspGetOutputMode(void);
/**
* @brief Sets the clipping mode.
* @param mode Clipping mode to set. Defaults to NDSP_CLIP_SOFT.
*/
void ndspSetClippingMode(ndspClippingMode mode);
/**
* @brief Gets the clipping mode.
* @return The clipping mode.
*/
ndspClippingMode ndspGetClippingMode(void);
/**
* @brief Sets the output count.
* @param count Output count to set. Defaults to 2.
*/
void ndspSetOutputCount(int count);
/**
* @brief Gets the output count.
* @return The output count.
*/
int ndspGetOutputCount(void);
/**
* @brief Sets the wave buffer to capture audio to.
* @param capture Wave buffer to capture to.
@ -154,17 +182,35 @@ void ndspSetCallback(ndspCallback callback, void* data);
*/
void ndspSurroundSetDepth(u16 depth);
/**
* @brief Gets the surround sound depth.
* @return The surround sound depth.
*/
u16 ndspSurroundGetDepth(void);
/**
* @brief Sets the surround sound position.
* @param pos Position to set. Defaults to NDSP_SPKPOS_SQUARE.
*/
void ndspSurroundSetPos(ndspSpeakerPos pos);
/**
* @brief Gets the surround sound position.
* @return The surround sound speaker position.
*/
ndspSpeakerPos ndspSurroundGetPos(void);
/**
* @brief Sets the surround sound rear ratio.
* @param ratio Rear ratio to set. Defaults to 0x8000.
*/
void ndspSurroundSetRearRatio(u16 ratio);
/**
* @brief Gets the surround sound rear ratio.
* @return The rear ratio.
*/
u16 ndspSurroundGetRearRatio(void);
///@}
///@name Auxiliary output
@ -176,6 +222,13 @@ void ndspSurroundSetRearRatio(u16 ratio);
*/
void ndspAuxSetEnable(int id, bool enable);
/**
* @brief Gets whether auxiliary output is enabled.
* @param id ID of the auxiliary output.
* @return Whether auxiliary output is enabled.
*/
bool ndspAuxIsEnabled(int id);
/**
* @brief Configures whether an auxiliary output should use front bypass.
* @param id ID of the auxiliary output.
@ -183,6 +236,13 @@ void ndspAuxSetEnable(int id, bool enable);
*/
void ndspAuxSetFrontBypass(int id, bool bypass);
/**
* @brief Gets whether auxiliary output front bypass is enabled.
* @param id ID of the auxiliary output.
* @return Whether auxiliary output front bypass is enabled.
*/
bool ndspAuxGetFrontBypass(int id);
/**
* @brief Sets the volume of an auxiliary output.
* @param id ID of the auxiliary output.
@ -190,6 +250,13 @@ void ndspAuxSetFrontBypass(int id, bool bypass);
*/
void ndspAuxSetVolume(int id, float volume);
/**
* @brief Gets the volume of an auxiliary output.
* @param id ID of the auxiliary output.
* @return Volume of the auxiliary output.
*/
float ndspAuxGetVolume(int id);
/**
* @brief Sets the callback of an auxiliary output.
* @param id ID of the auxiliary output.

View File

@ -3,6 +3,27 @@
* @brief OS related stuff.
*/
#pragma once
#include "svc.h"
///< The external clock rate for the SoC.
#define SYSCLOCK_SOC (16756991u)
///< The base system clock rate (for I2C, NDMA, etc.).
#define SYSCLOCK_SYS (SYSCLOCK_SOC * 2)
///< The base clock rate for the SDMMC controller (and some other peripherals).
#define SYSCLOCK_SDMMC (SYSCLOCK_SYS * 2)
///< The clock rate for the Arm9.
#define SYSCLOCK_ARM9 (SYSCLOCK_SYS * 4)
///< The clock rate for the Arm11 in CTR mode and in \ref svcGetSystemTick.
#define SYSCLOCK_ARM11 (SYSCLOCK_ARM9 * 2)
///< The clock rate for the Arm11 in LGR1 mode.
#define SYSCLOCK_ARM11_LGR1 (SYSCLOCK_ARM11 * 2)
///< The clock rate for the Arm11 in LGR2 mode.
#define SYSCLOCK_ARM11_LGR2 (SYSCLOCK_ARM11 * 3)
///< The highest possible clock rate for the Arm11 on known New 3DS units.
#define SYSCLOCK_ARM11_NEW SYSCLOCK_ARM11_LGR2
#define CPU_TICKS_PER_MSEC (SYSCLOCK_ARM11 / 1000.0)
#define CPU_TICKS_PER_USEC (SYSCLOCK_ARM11 / 1000000.0)
/// Packs a system version from its components.
#define SYSTEM_VERSION(major, minor, revision) \
@ -17,14 +38,105 @@
/// Retrieves the revision version from a packed system version.
#define GET_VERSION_REVISION(version) (((version)>> 8)&0xFF)
/// Memory regions.
typedef enum
#define OS_HEAP_AREA_BEGIN 0x08000000 ///< Start of the heap area in the virtual address space
#define OS_HEAP_AREA_END 0x0E000000 ///< End of the heap area in the virtual address space
#define OS_MAP_AREA_BEGIN 0x10000000 ///< Start of the mappable area in the virtual address space
#define OS_MAP_AREA_END 0x14000000 ///< End of the mappable area in the virtual address space
#define OS_OLD_FCRAM_VADDR 0x14000000 ///< Old pre-8.x linear FCRAM mapping virtual address
#define OS_OLD_FCRAM_PADDR 0x20000000 ///< Old pre-8.x linear FCRAM mapping physical address
#define OS_OLD_FCRAM_SIZE 0x8000000 ///< Old pre-8.x linear FCRAM mapping size (128 MiB)
#define OS_QTMRAM_VADDR 0x1E800000 ///< New3DS QTM memory virtual address
#define OS_QTMRAM_PADDR 0x1F000000 ///< New3DS QTM memory physical address
#define OS_QTMRAM_SIZE 0x400000 ///< New3DS QTM memory size (4 MiB; last 128 KiB reserved by kernel)
#define OS_MMIO_VADDR 0x1EC00000 ///< Memory mapped IO range virtual address
#define OS_MMIO_PADDR 0x10100000 ///< Memory mapped IO range physical address
#define OS_MMIO_SIZE 0x400000 ///< Memory mapped IO range size (4 MiB)
#define OS_VRAM_VADDR 0x1F000000 ///< VRAM virtual address
#define OS_VRAM_PADDR 0x18000000 ///< VRAM physical address
#define OS_VRAM_SIZE 0x600000 ///< VRAM size (6 MiB)
#define OS_DSPRAM_VADDR 0x1FF00000 ///< DSP memory virtual address
#define OS_DSPRAM_PADDR 0x1FF00000 ///< DSP memory physical address
#define OS_DSPRAM_SIZE 0x80000 ///< DSP memory size (512 KiB)
#define OS_KERNELCFG_VADDR 0x1FF80000 ///< Kernel configuration page virtual address
#define OS_SHAREDCFG_VADDR 0x1FF81000 ///< Shared system configuration page virtual address
#define OS_FCRAM_VADDR 0x30000000 ///< Linear FCRAM mapping virtual address
#define OS_FCRAM_PADDR 0x20000000 ///< Linear FCRAM mapping physical address
#define OS_FCRAM_SIZE 0x10000000 ///< Linear FCRAM mapping size (256 MiB)
#define OS_KernelConfig ((osKernelConfig_s const*)OS_KERNELCFG_VADDR) ///< Pointer to the kernel configuration page (see \ref osKernelConfig_s)
#define OS_SharedConfig ((osSharedConfig_s*)OS_SHAREDCFG_VADDR) ///< Pointer to the shared system configuration page (see \ref osSharedConfig_s)
/// Kernel configuration page (read-only).
typedef struct
{
MEMREGION_ALL = 0, ///< All regions.
MEMREGION_APPLICATION = 1, ///< APPLICATION memory.
MEMREGION_SYSTEM = 2, ///< SYSTEM memory.
MEMREGION_BASE = 3, ///< BASE memory.
} MemRegion;
u32 kernel_ver;
u32 update_flag;
u64 ns_tid;
u32 kernel_syscore_ver;
u8 env_info;
u8 unit_info;
u8 boot_env;
u8 unk_0x17;
u32 kernel_ctrsdk_ver;
u32 unk_0x1c;
u32 firmlaunch_flags;
u8 unk_0x24[0xc];
u32 app_memtype;
u8 unk_0x34[0xc];
u32 memregion_sz[3];
u8 unk_0x4c[0x14];
u32 firm_ver;
u32 firm_syscore_ver;
u32 firm_ctrsdk_ver;
} osKernelConfig_s;
/// Time reference information struct (filled in by PTM).
typedef struct
{
u64 value_ms; ///< Milliseconds elapsed since January 1900 when this structure was last updated
u64 value_tick; ///< System ticks elapsed since boot when this structure was last updated
s64 sysclock_hz;///< System clock frequency in Hz adjusted using RTC measurements (usually around \ref SYSCLOCK_ARM11)
s64 drift_ms; ///< Measured time drift of the system clock (according to the RTC) in milliseconds since the last update
} osTimeRef_s;
/// Shared system configuration page structure (read-only or read-write depending on exheader).
typedef struct
{
vu32 timeref_cnt;
u8 running_hw;
u8 mcu_hwinfo;
u8 unk_0x06[0x1A];
volatile osTimeRef_s timeref[2];
u8 wifi_macaddr[6];
vu8 wifi_strength;
vu8 network_state;
u8 unk_0x68[0x18];
volatile float slider_3d;
vu8 led_3d;
vu8 led_battery;
vu8 unk_flag;
u8 unk_0x87;
u8 unk_0x88[0x18];
vu64 menu_tid;
vu64 cur_menu_tid;
u8 unk_0xB0[0x10];
vu8 headset_connected;
} osSharedConfig_s;
/// Tick counter.
typedef struct
{
u64 elapsed; ///< Elapsed CPU ticks between measurements.
u64 reference; ///< Point in time used as reference.
} TickCounter;
/// OS_VersionBin. Format of the system version: "<major>.<minor>.<build>-<nupver><region>"
typedef struct
@ -59,7 +171,7 @@ void* osConvertOldLINEARMemToNew(const void* vaddr);
*
* This can be used to get some details about an error returned by a service call.
*/
const char* osStrError(u32 error);
const char* osStrError(Result error);
/**
* @brief Gets the system's FIRM version.
@ -69,7 +181,7 @@ const char* osStrError(u32 error);
*/
static inline u32 osGetFirmVersion(void)
{
return (*(vu32*)0x1FF80060) & ~0xFF;
return OS_KernelConfig->firm_ver &~ 0xFF;
}
/**
@ -84,7 +196,19 @@ static inline u32 osGetFirmVersion(void)
*/
static inline u32 osGetKernelVersion(void)
{
return (*(vu32*)0x1FF80000) & ~0xFF;
return OS_KernelConfig->kernel_ver &~ 0xFF;
}
/// Gets the system's "core version" (2 on NATIVE_FIRM, 3 on SAFE_FIRM, etc.)
static inline u32 osGetSystemCoreVersion(void)
{
return OS_KernelConfig->kernel_syscore_ver;
}
/// Gets the system's memory layout ID (0-5 on Old 3DS, 6-8 on New 3DS)
static inline u32 osGetApplicationMemType(void)
{
return OS_KernelConfig->app_memtype;
}
/**
@ -97,7 +221,7 @@ static inline u32 osGetMemRegionSize(MemRegion region)
if(region == MEMREGION_ALL) {
return osGetMemRegionSize(MEMREGION_APPLICATION) + osGetMemRegionSize(MEMREGION_SYSTEM) + osGetMemRegionSize(MEMREGION_BASE);
} else {
return *(vu32*) (0x1FF80040 + (region - 1) * 0x4);
return OS_KernelConfig->memregion_sz[region-1];
}
}
@ -106,30 +230,68 @@ static inline u32 osGetMemRegionSize(MemRegion region)
* @param region Memory region to check.
* @return The number of used bytes of memory.
*/
s64 osGetMemRegionUsed(MemRegion region);
static inline u32 osGetMemRegionUsed(MemRegion region)
{
s64 mem_used;
svcGetSystemInfo(&mem_used, 0, region);
return mem_used;
}
/**
* @brief Gets the number of free bytes within the specified memory region.
* @param region Memory region to check.
* @return The number of free bytes of memory.
*/
static inline s64 osGetMemRegionFree(MemRegion region)
static inline u32 osGetMemRegionFree(MemRegion region)
{
return (s64) osGetMemRegionSize(region) - osGetMemRegionUsed(region);
return osGetMemRegionSize(region) - osGetMemRegionUsed(region);
}
/**
* @brief Reads the latest reference timepoint published by PTM.
* @return Structure (see \ref osTimeRef_s).
*/
osTimeRef_s osGetTimeRef(void);
/**
* @brief Gets the current time.
* @return The number of milliseconds since 1st Jan 1900 00:00.
*/
u64 osGetTime(void);
/**
* @brief Starts a tick counter.
* @param cnt The tick counter.
*/
static inline void osTickCounterStart(TickCounter* cnt)
{
cnt->reference = svcGetSystemTick();
}
/**
* @brief Updates the elapsed time in a tick counter.
* @param cnt The tick counter.
*/
static inline void osTickCounterUpdate(TickCounter* cnt)
{
u64 now = svcGetSystemTick();
cnt->elapsed = now - cnt->reference;
cnt->reference = now;
}
/**
* @brief Reads the elapsed time in a tick counter.
* @param cnt The tick counter.
* @return The number of milliseconds elapsed.
*/
double osTickCounterRead(const TickCounter* cnt);
/**
* @brief Gets the current Wifi signal strength.
* @return The current Wifi signal strength.
*
* Valid values are 0-3:
* - 0 means the singal strength is terrible or the 3DS is disconnected from
* - 0 means the signal strength is terrible or the 3DS is disconnected from
* all networks.
* - 1 means the signal strength is bad.
* - 2 means the signal strength is decent.
@ -141,7 +303,7 @@ u64 osGetTime(void);
*/
static inline u8 osGetWifiStrength(void)
{
return *(vu8*)0x1FF81066;
return OS_SharedConfig->wifi_strength;
}
/**
@ -150,7 +312,16 @@ static inline u8 osGetWifiStrength(void)
*/
static inline float osGet3DSliderState(void)
{
return *(volatile float*)0x1FF81080;
return OS_SharedConfig->slider_3d;
}
/**
* @brief Checks whether a headset is connected.
* @return true or false.
*/
static inline bool osIsHeadsetConnected(void)
{
return OS_SharedConfig->headset_connected != 0;
}
/**

View File

@ -5,6 +5,7 @@
#pragma once
#include <3ds/types.h>
#include <3ds/services/fs.h>
/// RomFS header.
typedef struct
@ -45,36 +46,48 @@ typedef struct
u16 name[]; ///< Name. (UTF-16)
} romfs_file;
struct romfs_mount;
/**
* @brief Mounts the Application's RomFS.
* @param mount Output mount handle
* @param name Device mount name.
* @remark This function is intended to be used to access one's own RomFS.
* If the application is running as 3DSX, it mounts the embedded RomFS section inside the 3DSX.
* If on the other hand it's an NCCH, it behaves identically to \ref romfsMountFromCurrentProcess.
*/
Result romfsMount(struct romfs_mount **mount);
static inline Result romfsInit(void)
{
return romfsMount(NULL);
}
Result romfsMountSelf(const char *name);
/**
* @brief Mounts RomFS from an open file.
* @param file Handle of the RomFS file.
* @param fd FSFILE handle of the RomFS image.
* @param offset Offset of the RomFS within the file.
* @param mount Output mount handle
* @param name Device mount name.
*/
Result romfsMountFromFile(Handle file, u32 offset, struct romfs_mount **mount);
static inline Result romfsInitFromFile(Handle file, u32 offset)
{
return romfsMountFromFile(file, offset, NULL);
}
Result romfsMountFromFile(Handle fd, u32 offset, const char *name);
/// Bind the RomFS mount
Result romfsBind(struct romfs_mount *mount);
/**
* @brief Mounts RomFS using the current process host program RomFS.
* @param name Device mount name.
*/
Result romfsMountFromCurrentProcess(const char *name);
/**
* @brief Mounts RomFS from the specified title.
* @param tid Title ID
* @param mediatype Mediatype
* @param name Device mount name.
*/
Result romfsMountFromTitle(u64 tid, FS_MediaType mediatype, const char* name);
/// Unmounts the RomFS device.
Result romfsUnmount(struct romfs_mount *mount);
Result romfsUnmount(const char *name);
/// Wrapper for \ref romfsMountSelf with the default "romfs" device name.
static inline Result romfsInit(void)
{
return romfsMountSelf("romfs");
}
/// Wrapper for \ref romfsUnmount with the default "romfs" device name.
static inline Result romfsExit(void)
{
return romfsUnmount(NULL);
return romfsUnmount("romfs");
}

View File

@ -1,34 +0,0 @@
/**
* @file sdmc.h
* @brief SDMC driver.
*/
#pragma once
#include <sys/types.h>
#include <3ds/types.h>
#include <3ds/services/fs.h>
#define SDMC_DIRITER_MAGIC 0x73646D63 /* "sdmc" */
/*! Open directory struct */
typedef struct
{
u32 magic; /*! "sdmc" */
Handle fd; /*! CTRU handle */
ssize_t index; /*! Current entry index */
size_t size; /*! Current batch size */
FS_DirectoryEntry entry_data[32]; /*! Temporary storage for reading entries */
} sdmc_dir_t;
/// Initializes the SDMC driver.
Result sdmcInit(void);
/// Enable/disable copy in sdmc_write
void sdmcWriteSafe(bool enable);
/// Exits the SDMC driver.
Result sdmcExit(void);
/// Get a file's mtime
Result sdmc_getmtime(const char *name, u64 *mtime);

View File

@ -4,17 +4,154 @@
*/
#pragma once
#include <3ds/types.h>
/// Wifi security modes.
typedef enum {
AC_OPEN = 0, ///< Open authentication.
AC_WEP_40BIT = 1, ///< WEP 40-bit authentication.
AC_WEP_104BIT = 2, ///< WEP 104-bit authentication.
AC_WEP_128BIT = 3, ///< WEP 128-bit authentication.
AC_WPA_TKIP = 4, ///< WPA TKIP authentication.
AC_WPA2_TKIP = 5, ///< WPA2 TKIP authentication.
AC_WPA_AES = 6, ///< WPA AES authentication.
AC_WPA2_AES = 7, ///< WPA2 AES authentication.
} acSecurityMode;
/// Wifi access point types (bitfield).
enum {
AC_AP_TYPE_NONE = 0, ///< No access point/none allowed.
AC_AP_TYPE_SLOT1 = BIT(1), ///< Slot 1 in System Settings.
AC_AP_TYPE_SLOT2 = BIT(2), ///< Slot 2 in System Settings.
AC_AP_TYPE_SLOT3 = BIT(3), ///< Slot 3 in System Settings.
AC_AP_TYPE_ALL = 0x7FFFFFFF, ///< All access point types allowed.
};
/// Struct to contain the data for connecting to a Wifi network from a stored slot.
typedef struct {
u8 reserved[0x200];
} acuConfig;
/// Initializes AC.
Result acInit(void);
/// Exits AC.
void acExit(void);
/// Gets the current AC session handle.
Handle *acGetSessionHandle(void);
/// Waits for the system to connect to the internet.
Result acWaitInternetConnection(void);
/**
* @brief Gets the current Wifi status.
* @param out Pointer to output the current Wifi status to. (0 = not connected, 1 = O3DS Internet, 2 = N3DS Internet)
* @brief Describes the access point the console is currently connected to with AC_AP_TYPE_* flags.
* @param out Pointer to output the combination of AC_AP_TYPE_* flags describing the AP to.
*/
Result ACU_GetWifiStatus(u32 *out);
/**
* @brief Gets the connected Wifi status.
* @param out Pointer to output the connected Wifi status to. (1 = not connected, 3 = connected)
*/
Result ACU_GetStatus(u32 *out);
/**
* @brief Gets the connected Wifi security mode.
* @param mode Pointer to output the connected Wifi security mode to. (0 = Open Authentication, 1 = WEP 40-bit, 2 = WEP 104-bit, 3 = WEP 128-bit, 4 = WPA TKIP, 5 = WPA2 TKIP, 6 = WPA AES, 7 = WPA2 AES)
*/
Result ACU_GetSecurityMode(acSecurityMode *mode);
/**
* @brief Gets the connected Wifi SSID.
* @param SSID Pointer to output the connected Wifi SSID to.
*/
Result ACU_GetSSID(char *SSID);
/**
* @brief Gets the connected Wifi SSID length.
* @param out Pointer to output the connected Wifi SSID length to.
*/
Result ACU_GetSSIDLength(u32 *out);
/**
* @brief Determines whether proxy is enabled for the connected network.
* @param enable Pointer to output the proxy status to.
*/
Result ACU_GetProxyEnable(bool *enable);
/**
* @brief Gets the connected network's proxy port.
* @param out Pointer to output the proxy port to.
*/
Result ACU_GetProxyPort(u32 *out);
/**
* @brief Gets the connected network's proxy username.
* @param username Pointer to output the proxy username to. (The size must be at least 0x20-bytes)
*/
Result ACU_GetProxyUserName(char *username);
/**
* @brief Gets the connected network's proxy password.
* @param password Pointer to output the proxy password to. (The size must be at least 0x20-bytes)
*/
Result ACU_GetProxyPassword(char *password);
/**
* @brief Gets the last error to occur during a connection.
* @param errorCode Pointer to output the error code to.
*/
Result ACU_GetLastErrorCode(u32* errorCode);
/**
* @brief Gets the last detailed error to occur during a connection.
* @param errorCode Pointer to output the error code to.
*/
Result ACU_GetLastDetailErrorCode(u32* errorCode);
/**
* @brief Prepares a buffer to hold the configuration data to start a connection.
* @param config Pointer to an acuConfig struct to contain the data.
*/
Result ACU_CreateDefaultConfig(acuConfig* config);
/**
* @brief Sets something that makes the connection reliable.
* @param config Pointer to an acuConfig struct used with ACU_CreateDefaultConfig previously.
* @param area Always 2 ?
*/
Result ACU_SetNetworkArea(acuConfig* config, u8 area);
/**
* @brief Sets the slot to use when connecting.
* @param config Pointer to an acuConfig struct used with ACU_CreateDefaultConfig previously.
* @param type Allowed AP types bitmask, a combination of AC_AP_TYPE_* flags.
*/
Result ACU_SetAllowApType(acuConfig* config, u8 type);
/**
* @brief Sets something that makes the connection reliable.
* @param config Pointer to an acuConfig struct used with ACU_CreateDefaultConfig previously.
*/
Result ACU_SetRequestEulaVersion(acuConfig* config);
/**
* @brief Starts the connection procedure.
* @param config Pointer to an acuConfig struct used with ACU_CreateDefaultConfig previously.
* @param connectionHandle Handle created with svcCreateEvent to wait on until the connection succeeds or fails.
*/
Result ACU_ConnectAsync(const acuConfig* config, Handle connectionHandle);
/**
* @brief Selects the WiFi configuration slot for further ac:i operations.
* @param slot WiFi slot (0, 1 or 2).
*/
Result ACI_LoadNetworkSetting(u32 slot);
/**
* @brief Fetches the SSID of the previously selected WiFi configuration slot.
* @param[out] ssid Pointer to the output buffer of size 32B the SSID will be stored in.
*/
Result ACI_GetNetworkWirelessEssidSecuritySsid(void *ssid);

View File

@ -56,6 +56,23 @@ typedef struct {
u64 titlesFreeSpace; ///< Free space for titles.
} AM_TWLPartitionInfo;
/// Contains information about a title's content.
typedef struct {
u16 index; ///< Index of the content in the title.
u16 type; ///< ?
u32 contentId; ///< ID of the content in the title.
u64 size; ///< Size of the content in the title.
u8 flags; ///< @ref AM_ContentInfoFlags
u8 padding[7]; ///< Padding
} AM_ContentInfo;
/// Title ContentInfo flags.
typedef enum
{
AM_CONTENT_DOWNLOADED = BIT(0), ///< ?
AM_CONTENT_OWNED = BIT(1) ///< ?
} AM_ContentInfoFlags;
/// Initializes AM. This doesn't initialize with "am:app", see amAppInit().
Result amInit(void);
@ -374,7 +391,7 @@ Result AM_InstallTicketFinish(Handle ticketHandle);
Result AM_InstallTitleBegin(FS_MediaType mediaType, u64 titleId, bool unk);
/// Stops installing a title, generally to be resumed later.
Result AM_InstallTitleStop();
Result AM_InstallTitleStop(void);
/**
* @brief Resumes installing a title.
@ -384,10 +401,10 @@ Result AM_InstallTitleStop();
Result AM_InstallTitleResume(FS_MediaType mediaType, u64 titleId);
/// Aborts installing a title.
Result AM_InstallTitleAbort();
Result AM_InstallTitleAbort(void);
/// Finishes installing a title.
Result AM_InstallTitleFinish();
Result AM_InstallTitleFinish(void);
/**
* @brief Commits installed titles.
@ -488,3 +505,34 @@ Result AM_CommitImportTitlesAndUpdateFirmwareAuto(FS_MediaType mediaType, u32 ti
/// Resets play count of all installed demos by deleting their launch info.
Result AM_DeleteAllDemoLaunchInfos(void);
/// Deletes temporary titles.
Result AM_DeleteAllTemporaryTitles(void);
/**
* @brief Deletes all expired titles.
* @param mediatype Media type to delete from.
*/
Result AM_DeleteAllExpiredTitles(FS_MediaType mediatype);
/// Deletes all TWL titles.
Result AM_DeleteAllTwlTitles(void);
/**
* @brief Gets the number of content index installed under the specified DLC title.
* @param[out] count Pointer to output the number of content indices to.
* @param mediatype Media type of the title.
* @param titleID Title ID to retrieve the count for (high-id is 0x0004008C).
*/
Result AMAPP_GetDLCContentInfoCount(u32* count, FS_MediaType mediatype, u64 titleID);
/**
* @brief Gets content infos installed under the specified DLC title.
* @param[out] contentInfoRead Pointer to output the number of content infos read to.
* @param mediatype Media type of the title.
* @param titleID Title ID to retrieve the content infos for (high-id is 0x0004008C).
* @param contentInfoCount Number of content infos to retrieve.
* @param offset Offset from the first content index the count starts at.
* @param[out] contentInfos Pointer to output the content infos read to.
*/
Result AMAPP_ListDLCContentInfos(u32* contentInfoRead, FS_MediaType mediatype, u64 titleID, u32 contentInfoCount, u32 offset, AM_ContentInfo* contentInfos);

View File

@ -45,6 +45,8 @@ typedef enum {
typedef u8 APT_AppletAttr;
struct PtmWakeEvents;
/// Create an APT_AppletAttr bitfield from its components.
static inline APT_AppletAttr aptMakeAppletAttr(APT_AppletPos pos, bool manualGpuRights, bool manualDspRights)
{
@ -146,21 +148,52 @@ void aptExit(void);
*/
Result aptSendCommand(u32* aptcmdbuf);
/**
* @brief Gets whether to allow the system to enter sleep mode.
* @return Whether sleep mode is allowed.
*/
/// Returns true if the application is currently in the foreground.
bool aptIsActive(void);
/// Returns true if the system has told the application to close.
bool aptShouldClose(void);
/// Returns true if the system can enter sleep mode while the application is active.
bool aptIsSleepAllowed(void);
/**
* @brief Sets whether to allow the system to enter sleep mode.
* @param allowed Whether to allow sleep mode.
*/
/// Configures whether the system can enter sleep mode while the application is active.
void aptSetSleepAllowed(bool allowed);
/// Handles incoming sleep mode requests.
void aptHandleSleep(void);
/// Returns true if the user can press the HOME button to jump back to the HOME menu while the application is active.
bool aptIsHomeAllowed(void);
/// Configures whether the user can press the HOME button to jump back to the HOME menu while the application is active.
void aptSetHomeAllowed(bool allowed);
/// Returns true if the system requires the application to jump back to the HOME menu.
bool aptShouldJumpToHome(void);
/// Returns true if there is an incoming HOME button press rejected by the policy set by \ref aptSetHomeAllowed (use this to show a "no HOME allowed" icon).
bool aptCheckHomePressRejected(void);
/// \deprecated Alias for \ref aptCheckHomePressRejected.
static inline CTR_DEPRECATED bool aptIsHomePressed(void)
{
return aptCheckHomePressRejected();
}
/// Jumps back to the HOME menu.
void aptJumpToHomeMenu(void);
/// Handles incoming jump-to-HOME requests.
static inline void aptHandleJumpToHome(void)
{
if (aptShouldJumpToHome())
aptJumpToHomeMenu();
}
/**
* @brief Processes the current APT status. Generally used within a main loop.
* @return Whether the application should continue running.
* @brief Main function which handles sleep mode and HOME/power buttons - call this at the beginning of every frame.
* @return true if the application should keep running, false otherwise (see \ref aptShouldClose).
*/
bool aptMainLoop(void);
@ -191,9 +224,34 @@ void aptSetMessageCallback(aptMessageCb callback, void* user);
* @param buf Input/output buffer that contains launch parameters on entry and result data on exit.
* @param bufsize Size of the buffer.
* @param handle Handle to pass to the library applet.
* @return Whether the application should continue running after the library applet launch.
*/
bool aptLaunchLibraryApplet(NS_APPID appId, void* buf, size_t bufsize, Handle handle);
void aptLaunchLibraryApplet(NS_APPID appId, void* buf, size_t bufsize, Handle handle);
/// Clears the chainloader state.
void aptClearChainloader(void);
/**
* @brief Configures the chainloader to launch a specific application.
* @param programID ID of the program to chainload to.
* @param mediatype Media type of the program to chainload to.
*/
void aptSetChainloader(u64 programID, u8 mediatype);
/// Configures the chainloader to launch the previous application.
void aptSetChainloaderToCaller(void);
/// Configures the chainloader to relaunch the current application (i.e. soft-reset)
void aptSetChainloaderToSelf(void);
/**
* @brief Sets the "deliver arg" and HMAC for the chainloader, which will
* be passed to the target 3DS/DS(i) application. The meaning of each
* parameter varies on a per-application basis.
* @param deliverArg Deliver arg to pass to the target application.
* @param deliverArgSize Size of the deliver arg, maximum 0x300 bytes.
* @param hmac HMAC buffer, 32 bytes. Use NULL to pass an all-zero dummy HMAC.
*/
void aptSetChainloaderArgs(const void *deliverArg, size_t deliverArgSize, const void *hmac);
/**
* @brief Gets an APT lock handle.
@ -319,6 +377,13 @@ Result APT_IsRegistered(NS_APPID appID, bool* out);
*/
Result APT_InquireNotification(u32 appID, APT_Signal* signalType);
/**
* @brief Requests to enter sleep mode, and later sets wake events if allowed to.
* @param wakeEvents The wake events. Limited to "shell" (bit 1) for the PDN wake events part
* and "shell opened", "shell closed" and "HOME button pressed" for the MCU interrupts part.
*/
Result APT_SleepSystem(const struct PtmWakeEvents *wakeEvents);
/**
* @brief Notifies an application to wait.
* @param appID ID of the application.
@ -338,6 +403,13 @@ Result APT_AppletUtility(int id, void* out, size_t outSize, const void* in, size
/// Sleeps if shell is closed (?).
Result APT_SleepIfShellClosed(void);
/**
* @brief Locks a transition (?).
* @param transition Transition ID.
* @param flag Flag (?)
*/
Result APT_LockTransition(u32 transition, bool flag);
/**
* @brief Tries to lock a transition (?).
* @param transition Transition ID.
@ -506,4 +578,4 @@ Result APT_GetSharedFont(Handle* fontHandle, u32* mapAddr);
* @param sender Pointer to output the sender's AppID to.
* @param received Pointer to output whether an argument was received to.
*/
Result APT_ReceiveDeliverArg(const void* param, size_t paramSize, const void* hmac, u64* sender, bool* received);
Result APT_ReceiveDeliverArg(void* param, size_t paramSize, void* hmac, u64* sender, bool* received);

View File

@ -0,0 +1,90 @@
/**
* @file cdcchk.h
* @brief CODEC Hardware Check service.
*/
#pragma once
#include <3ds/types.h>
/// I2S line enumeration
typedef enum {
CODEC_I2S_LINE_1, ///< Primary I2S line, used by DSP/Mic (configurable)/GBA sound controller.
CODEC_I2S_LINE_2, ///< Secondary I2S line, used by CSND hardware.
} CodecI2sLine;
/// Initializes CDCCHK.
Result cdcChkInit(void);
/// Exits CDCCHK.
void cdcChkExit(void);
/**
* @brief Gets a pointer to the current cdc:CHK session handle.
* @return A pointer to the current cdc:CHK session handle.
*/
Handle *cdcChkGetSessionHandle(void);
/**
* @brief Reads multiple registers from the CODEC, using the old
* SPI hardware interface and a 4MHz baudrate.
* @param pageId CODEC Page ID.
* @param initialRegAddr Address of the CODEC register to start with.
* @param[out] outData Where to write the read data to.
* @param size Number of registers to read (bytes to read, max. 64).
*/
Result CDCCHK_ReadRegisters1(u8 pageId, u8 initialRegAddr, void *outData, size_t size);
/**
* @brief Reads multiple registers from the CODEC, using the new
* SPI hardware interface and a 16MHz baudrate.
* @param pageId CODEC Page ID.
* @param initialRegAddr Address of the CODEC register to start with.
* @param[out] outData Where to read the data to.
* @param size Number of registers to read (bytes to read, max. 64).
*/
Result CDCCHK_ReadRegisters2(u8 pageId, u8 initialRegAddr, void *outData, size_t size);
/**
* @brief Writes multiple registers to the CODEC, using the old
* SPI hardware interface and a 4MHz baudrate.
* @param pageId CODEC Page ID.
* @param initialRegAddr Address of the CODEC register to start with.
* @param data Where to read the data to write from.
* @param size Number of registers to write (bytes to read, max. 64).
*/
Result CDCCHK_WriteRegisters1(u8 pageId, u8 initialRegAddr, const void *data, size_t size);
/**
* @brief Writes multiple registers to the CODEC, using the new
* SPI hardware interface and a 16MHz baudrate.
* @param pageId CODEC Page ID.
* @param initialRegAddr Address of the CODEC register to start with.
* @param data Where to read the data to write from.
* @param size Number of registers to write (bytes to read, max. 64).
*/
Result CDCCHK_WriteRegisters2(u8 pageId, u8 initialRegAddr, const void *data, size_t size);
/**
* @brief Reads a single register from the NTR PMIC.
* @param[out] outData Where to read the data to (1 byte).
* @param regAddr Register address.
* @note The NTR PMIC is emulated by the CODEC hardware and sends
* IRQs to the MCU when relevant.
*/
Result CDCCHK_ReadNtrPmicRegister(u8 *outData, u8 regAddr);
/**
* @brief Writes a single register from the NTR PMIC.
* @param regAddr Register address.
* @param data Data to write (1 byte).
* @note The NTR PMIC is emulated by the CODEC hardware and sends
* IRQs to the MCU when relevant.
*/
Result CDCCHK_WriteNtrPmicRegister(u8 regAddr, u8 data);
/**
* @brief Sets the DAC volume level for the specified I2S line.
* @param i2sLine I2S line to set the volume for.
* @param volume Volume level (-128 to 0).
*/
Result CDCCHK_SetI2sVolume(CodecI2sLine i2sLine, s8 volume);

View File

@ -3,6 +3,7 @@
* @brief CFGU (Configuration) Service
*/
#pragma once
#include <3ds/types.h>
/// Configuration region values.
typedef enum
@ -19,20 +20,32 @@ typedef enum
/// Configuration language values.
typedef enum
{
CFG_LANGUAGE_JP = 0, ///< Japanese
CFG_LANGUAGE_EN = 1, ///< English
CFG_LANGUAGE_FR = 2, ///< French
CFG_LANGUAGE_DE = 3, ///< German
CFG_LANGUAGE_IT = 4, ///< Italian
CFG_LANGUAGE_ES = 5, ///< Spanish
CFG_LANGUAGE_ZH = 6, ///< Simplified Chinese
CFG_LANGUAGE_KO = 7, ///< Korean
CFG_LANGUAGE_NL = 8, ///< Dutch
CFG_LANGUAGE_PT = 9, ///< Portugese
CFG_LANGUAGE_RU = 10, ///< Russian
CFG_LANGUAGE_TW = 11, ///< Traditional Chinese
CFG_LANGUAGE_DEFAULT = -1, ///< Use system language in errorInit
CFG_LANGUAGE_JP, ///< Japanese
CFG_LANGUAGE_EN, ///< English
CFG_LANGUAGE_FR, ///< French
CFG_LANGUAGE_DE, ///< German
CFG_LANGUAGE_IT, ///< Italian
CFG_LANGUAGE_ES, ///< Spanish
CFG_LANGUAGE_ZH, ///< Simplified Chinese
CFG_LANGUAGE_KO, ///< Korean
CFG_LANGUAGE_NL, ///< Dutch
CFG_LANGUAGE_PT, ///< Portugese
CFG_LANGUAGE_RU, ///< Russian
CFG_LANGUAGE_TW, ///< Traditional Chinese
} CFG_Language;
// Configuration system model values.
typedef enum
{
CFG_MODEL_3DS = 0, ///< Old 3DS (CTR)
CFG_MODEL_3DSXL = 1, ///< Old 3DS XL (SPR)
CFG_MODEL_N3DS = 2, ///< New 3DS (KTR)
CFG_MODEL_2DS = 3, ///< Old 2DS (FTR)
CFG_MODEL_N3DSXL = 4, ///< New 3DS XL (RED)
CFG_MODEL_N2DSXL = 5, ///< New 2DS XL (JAN)
} CFG_SystemModel;
/// Initializes CFGU.
Result cfguInit(void);
@ -60,7 +73,7 @@ Result CFGU_GetRegionCanadaUSA(u8* value);
/**
* @brief Gets the system's model.
* @param model Pointer to output the model to. (0 = O3DS, 1 = O3DSXL, 2 = N3DS, 3 = 2DS, 4 = N3DSXL)
* @param model Pointer to output the model to. (see @ref CFG_SystemModel)
*/
Result CFGU_GetSystemModel(u8* model);
@ -84,13 +97,19 @@ Result CFGU_GetCountryCodeString(u16 code, u16* string);
*/
Result CFGU_GetCountryCodeID(u16 string, u16* code);
/**
* @brief Checks if NFC (code name: fangate) is supported.
* @param isSupported pointer to the output the result to.
*/
Result CFGU_IsNFCSupported(bool* isSupported);
/**
* @brief Gets a config info block with flags = 2.
* @param size Size of the data to retrieve.
* @param blkID ID of the block to retrieve.
* @param outData Pointer to write the block data to.
*/
Result CFGU_GetConfigInfoBlk2(u32 size, u32 blkID, u8* outData);
Result CFGU_GetConfigInfoBlk2(u32 size, u32 blkID, void* outData);
/**
* @brief Gets a config info block with flags = 4.
@ -98,7 +117,7 @@ Result CFGU_GetConfigInfoBlk2(u32 size, u32 blkID, u8* outData);
* @param blkID ID of the block to retrieve.
* @param outData Pointer to write the block data to.
*/
Result CFG_GetConfigInfoBlk4(u32 size, u32 blkID, u8* outData);
Result CFG_GetConfigInfoBlk4(u32 size, u32 blkID, void* outData);
/**
* @brief Gets a config info block with flags = 8.
@ -106,7 +125,7 @@ Result CFG_GetConfigInfoBlk4(u32 size, u32 blkID, u8* outData);
* @param blkID ID of the block to retrieve.
* @param outData Pointer to write the block data to.
*/
Result CFG_GetConfigInfoBlk8(u32 size, u32 blkID, u8* outData);
Result CFG_GetConfigInfoBlk8(u32 size, u32 blkID, void* outData);
/**
* @brief Sets a config info block with flags = 4.
@ -114,7 +133,7 @@ Result CFG_GetConfigInfoBlk8(u32 size, u32 blkID, u8* outData);
* @param blkID ID of the block to retrieve.
* @param inData Pointer to block data to write.
*/
Result CFG_SetConfigInfoBlk4(u32 size, u32 blkID, u8* inData);
Result CFG_SetConfigInfoBlk4(u32 size, u32 blkID, const void* inData);
/**
* @brief Sets a config info block with flags = 8.
@ -122,16 +141,81 @@ Result CFG_SetConfigInfoBlk4(u32 size, u32 blkID, u8* inData);
* @param blkID ID of the block to retrieve.
* @param inData Pointer to block data to write.
*/
Result CFG_SetConfigInfoBlk8(u32 size, u32 blkID, u8* inData);
Result CFG_SetConfigInfoBlk8(u32 size, u32 blkID, const void* inData);
/**
* @brief Writes the CFG buffer in memory to the savegame in NAND.
*/
Result CFG_UpdateConfigNANDSavegame(void);
Result CFG_UpdateConfigSavegame(void);
/**
* @brief Gets the system's language.
* @param language Pointer to write the language to. (see @ref CFG_Language)
*/
Result CFGU_GetSystemLanguage(u8* language);
/**
* @brief Deletes the NAND LocalFriendCodeSeed file, then recreates it using the LocalFriendCodeSeed data stored in memory.
*/
Result CFGI_RestoreLocalFriendCodeSeed(void);
/**
* @brief Deletes the NAND SecureInfo file, then recreates it using the SecureInfo data stored in memory.
*/
Result CFGI_RestoreSecureInfo(void);
/**
* @brief Deletes the "config" file stored in the NAND Config_Savegame.
*/
Result CFGI_DeleteConfigSavefile(void);
/**
* @brief Formats Config_Savegame.
*/
Result CFGI_FormatConfig(void);
/**
* @brief Clears parental controls
*/
Result CFGI_ClearParentalControls(void);
/**
* @brief Verifies the RSA signature for the LocalFriendCodeSeed data already stored in memory.
*/
Result CFGI_VerifySigLocalFriendCodeSeed(void);
/**
* @brief Verifies the RSA signature for the SecureInfo data already stored in memory.
*/
Result CFGI_VerifySigSecureInfo(void);
/**
* @brief Gets the system's serial number.
* @param serial Pointer to output the serial to. (This is normally 0xF)
*/
Result CFGI_SecureInfoGetSerialNumber(u8 *serial);
/**
* @brief Gets the 0x110-byte buffer containing the data for the LocalFriendCodeSeed.
* @param data Pointer to output the buffer. (The size must be at least 0x110-bytes)
*/
Result CFGI_GetLocalFriendCodeSeedData(u8 *data);
/**
* @brief Gets the 64-bit local friend code seed.
* @param seed Pointer to write the friend code seed to.
*/
Result CFGI_GetLocalFriendCodeSeed(u64* seed);
/**
* @brief Gets the 0x11-byte data following the SecureInfo signature.
* @param data Pointer to output the buffer. (The size must be at least 0x11-bytes)
*/
Result CFGI_GetSecureInfoData(u8 *data);
/**
* @brief Gets the 0x100-byte RSA-2048 SecureInfo signature.
* @param data Pointer to output the buffer. (The size must be at least 0x100-bytes)
*/
Result CFGI_GetSecureInfoSignature(u8 *data);

View File

@ -20,15 +20,18 @@
*/
static inline u32 CSND_VOL(float vol, float pan)
{
if (vol < 0.0) vol = 0.0;
else if (vol > 1.0) vol = 1.0;
float rpan;
u32 lvol, rvol;
float rpan = (pan+1) / 2;
if (rpan < 0.0) rpan = 0.0;
else if (rpan > 1.0) rpan = 1.0;
if (vol < 0.0f) vol = 0.0f;
else if (vol > 1.0f) vol = 1.0f;
u32 lvol = vol*(1-rpan) * 0x8000;
u32 rvol = vol*rpan * 0x8000;
rpan = (pan+1) / 2;
if (rpan < 0.0f) rpan = 0.0f;
else if (rpan > 1.0f) rpan = 1.0f;
lvol = vol*(1-rpan) * 0x8000;
rvol = vol*rpan * 0x8000;
return lvol | (rvol << 16);
}

View File

@ -13,12 +13,23 @@ typedef enum
DSP_INTERRUPT_PIPE = 2 ///< Pipe interrupt.
} DSP_InterruptType;
/// DSP pipe directions.
/// DSP hook types.
typedef enum
{
DSP_PIPE_INPUT = 0, ///< DSP to ARM
DSP_PIPE_OUTPUT = 1 ///< ARM to DSP
} DSP_PipeDirection;
DSPHOOK_ONSLEEP = 0, ///< DSP is going to sleep.
DSPHOOK_ONWAKEUP = 1, ///< DSP is waking up.
DSPHOOK_ONCANCEL = 2, ///< DSP was sleeping and the app was cancelled.
} DSP_HookType;
/// DSP hook function.
typedef void (* dspHookFn)(DSP_HookType hook);
/// DSP hook cookie.
typedef struct tag_dspHookCookie
{
struct tag_dspHookCookie* next; ///< Next cookie.
dspHookFn callback; ///< Hook callback.
} dspHookCookie;
/**
* @brief Initializes the dsp service.
@ -35,6 +46,22 @@ Result dspInit(void);
*/
void dspExit(void);
/// Returns true if a component is loaded, false otherwise.
bool dspIsComponentLoaded(void);
/**
* @brief Sets up a DSP status hook.
* @param cookie Hook cookie to use.
* @param callback Function to call when DSP's status changes.
*/
void dspHook(dspHookCookie* cookie, dspHookFn callback);
/**
* @brief Removes a DSP status hook.
* @param cookie Hook cookie to remove.
*/
void dspUnhook(dspHookCookie* cookie);
/**
* @brief Checks if a headphone is inserted.
* @param is_inserted Pointer to output the insertion status to.
@ -114,7 +141,7 @@ Result DSP_RegisterInterruptEvents(Handle handle, u32 interrupt, u32 channel);
Result DSP_ReadPipeIfPossible(u32 channel, u32 peer, void* buffer, u16 length, u16* length_read);
/**
* @param Writes to a pipe.
* @brief Writes to a pipe.
* @param channel unknown. Usually 2
* @param buffer The message to send to the DSP process
* @param length Length of the message

View File

@ -0,0 +1,261 @@
/**
* @file frd.h
* @brief Friend Services
*/
#pragma once
#include <3ds/mii.h>
#define FRIEND_SCREEN_NAME_SIZE 0xB ///< 11-byte UTF-16 screen name
#define FRIEND_COMMENT_SIZE 0x21 ///< 33-byte UTF-16 comment
#define FRIEND_LIST_SIZE 0x64 ///< 100 (Max number of friends)
#pragma pack(push, 1)
/// Friend key data
typedef struct
{
u32 principalId;
u32 padding;
u64 localFriendCode;
} FriendKey;
/// Friend Title data
typedef struct
{
u64 tid;
u32 version;
u32 unk;
} TitleData;
/// Friend profile data
typedef struct
{
u8 region; ///< The region code for the hardware.
u8 country; ///< Country code.
u8 area; ///< Area code.
u8 language; ///< Language code.
u8 platform; ///< Platform code.
u32 padding;
} FriendProfile;
/// Game Description structure
typedef struct
{
TitleData data;
u16 desc[128];
} GameDescription;
/// Friend Notification Event structure
typedef struct
{
u8 type;
u8 padding3[3];
u32 padding;
FriendKey key;
} NotificationEvent;
#pragma pack(pop)
/// Enum to use with FRD_GetNotificationEvent
typedef enum
{
USER_WENT_ONLINE = 1, ///< Self went online
USER_WENT_OFFLINE, ///< Self went offline
FRIEND_WENT_ONLINE, ///< Friend Went Online
FRIEND_UPDATED_PRESENCE, ///< Friend Presence changed
FRIEND_UPDATED_MII, ///< Friend Mii changed
FRIEND_UPDATED_PROFILE, ///< Friend Profile changed
FRIEND_WENT_OFFLINE, ///< Friend went offline
FRIEND_REGISTERED_USER, ///< Friend registered self as friend
FRIEND_SENT_INVITATION ///< Friend Sent invitation
} NotificationTypes;
/// Initializes FRD service.
Result frdInit(void);
/// Exists FRD.
void frdExit(void);
/// Get FRD handle.
Handle *frdGetSessionHandle(void);
/**
* @brief Gets the login status of the current user.
* @param state Pointer to write the current user's login status to.
*/
Result FRDU_HasLoggedIn(bool *state);
/**
* @brief Gets the online status of the current user.
* @param state Pointer to write the current user's online status to.
*/
Result FRDU_IsOnline(bool *state);
/// Logs out of Nintendo's friend server.
Result FRD_Logout(void);
/**
* @brief Log in to Nintendo's friend server.
* @param event Event to signal when Login is done.
*/
Result FRD_Login(Handle event);
/**
* @brief Gets the current user's friend key.
* @param key Pointer to write the current user's friend key to.
*/
Result FRD_GetMyFriendKey(FriendKey *key);
/**
* @brief Gets the current user's privacy information.
* @param isPublicMode Determines whether friends are notified of the current user's online status.
* @param isShowGameName Determines whether friends are notified of the application that the current user is running.
* @param isShowPlayedGame Determiens whether to display the current user's game history.
*/
Result FRD_GetMyPreference(bool *isPublicMode, bool *isShowGameName, bool *isShowPlayedGame);
/**
* @brief Gets the current user's profile information.
* @param profile Pointer to write the current user's profile information to.
*/
Result FRD_GetMyProfile(FriendProfile *profile);
/**
* @brief Gets the current user's screen name.
* @param name Pointer to write the current user's screen name to.
* @param max_size Max size of the screen name.
*/
Result FRD_GetMyScreenName(char *name, size_t max_size);
/**
* @brief Gets the current user's Mii data.
* @param mii Pointer to write the current user's mii data to.
*/
Result FRD_GetMyMii(MiiData *mii);
/**
* @brief Gets the current user's playing game.
* @param titleId Pointer to write the current user's playing game to.
*/
Result FRD_GetMyPlayingGame(u64 *titleId);
/**
* @brief Gets the current user's favourite game.
* @param titleId Pointer to write the title ID of current user's favourite game to.
*/
Result FRD_GetMyFavoriteGame(u64 *titleId);
/**
* @brief Gets the current user's comment on their friend profile.
* @param comment Pointer to write the current user's comment to.
* @param max_size Max size of the comment.
*/
Result FRD_GetMyComment(char *comment, size_t max_size);
/**
* @brief Gets the current user's friend key list.
* @param friendKeyList Pointer to write the friend key list to.
* @param num Stores the number of friend keys obtained.
* @param offset The index of the friend key to start with.
* @param size Size of the friend key list. (FRIEND_LIST_SIZE)
*/
Result FRD_GetFriendKeyList(FriendKey *friendKeyList, u32 *num, u32 offset, u32 size);
/**
* @brief Gets the current user's friends' Mii data.
* @param miiDataList Pointer to write Mii data to.
* @param friendKeyList Pointer to FriendKeys.
* @param size Number of Friendkeys.
*/
Result FRD_GetFriendMii(MiiData *miiDataList, const FriendKey *friendKeyList, size_t size);
/**
* @brief Get the current user's friends' profile data.
* @param profile Pointer to write profile data to.
* @param friendKeyList Pointer to FriendKeys.
* @param size Number of FriendKeys.
*/
Result FRD_GetFriendProfile(FriendProfile *profile, const FriendKey *friendKeyList, size_t size);
/**
* @brief Get the current user's friends' playing game.
* @param desc Pointer to write Game Description data to.
* @param friendKeyList Pointer to FriendKeys,
* @param size Number Of FriendKeys.
*/
Result FRD_GetFriendPlayingGame(GameDescription *desc, const FriendKey *friendKeyList, size_t size);
/**
* @brief Get the current user's friends' favourite game.
* @param desc Pointer to write Game Description data to.
* @param friendKeyList Pointer to FriendKeys,
* @param count Number Of FriendKeys.
*/
Result FRD_GetFriendFavouriteGame(GameDescription *desc, const FriendKey *friendKeyList, u32 count);
/**
* @brief Gets whether a friend key is included in the current user's friend list.
* @param friendKeyList Pointer to a list of friend keys.
* @param isFromList Pointer to a write the friendship status to.
*/
Result FRD_IsInFriendList(FriendKey *friendKeyList, bool *isFromList);
/**
* @brief Updates the game mode description string.
* @param desc Pointer to write the game mode description to.
*/
Result FRD_UpdateGameModeDescription(const char *desc);
/**
* @brief Event which is signaled when friend login states change.
* @param event event which will be signaled.
*/
Result FRD_AttachToEventNotification(Handle event);
/**
* @brief Get Latest Event Notification
* @param event Pointer to write recieved notification event struct to.
* @param count Number of events
* @param recievedNotifCount Number of notification reccieved.
*/
Result FRD_GetEventNotification(NotificationEvent *event, u32 count, u32 *recievedNotifCount);
/**
* @brief Returns the friend code using the given principal ID.
* @param principalId The principal ID being used.
* @param friendCode Pointer to write the friend code to.
*/
Result FRD_PrincipalIdToFriendCode(u32 principalId, u64 *friendCode);
/**
* @brief Returns the principal ID using the given friend code.
* @param friendCode The friend code being used.
* @param principalId Pointer to write the principal ID to.
*/
Result FRD_FriendCodeToPrincipalId(u64 friendCode, u32 *principalId);
/**
* @brief Checks if the friend code is valid.
* @param friendCode The friend code being used.
* @param isValid Pointer to write the validity of the friend code to.
*/
Result FRD_IsValidFriendCode(u64 friendCode, bool *isValid);
/**
* @brief Sets the Friend API to use a specific SDK version.
* @param sdkVer The SDK version needed to be used.
*/
Result FRD_SetClientSdkVersion(u32 sdkVer);
/**
* @brief Add a Friend online.
* @param event Event signaled when friend is registered.
* @param principalId PrincipalId of the friend to add.
*/
Result FRD_AddFriendOnline(Handle event, u32 principalId);
/**
* @brief Remove a Friend.
* @param principalId PrinipalId of the friend code to remove.
* @param localFriendCode LocalFriendCode of the friend code to remove.
*/
Result FRD_RemoveFriend(u32 principalId, u64 localFriendCode);

View File

@ -135,6 +135,7 @@ typedef enum
{
ARCHIVE_ACTION_COMMIT_SAVE_DATA = 0, ///< Commits save data changes. No inputs/outputs.
ARCHIVE_ACTION_GET_TIMESTAMP = 1, ///< Retrieves a file's last-modified timestamp. In: "u16*, UTF-16 Path", Out: "u64, Time Stamp".
ARCHIVE_ACTION_UNKNOWN = 0x789D, //< Unknown action; calls FSPXI command 0x56. In: "FS_Path instance", Out: "u32[4], Unknown"
} FS_ArchiveAction;
/// Secure save control actions.
@ -201,7 +202,7 @@ typedef struct
} FS_IntegrityVerificationSeed;
/// Ext save data information.
typedef struct PACKED
typedef struct CTR_PACKED
{
FS_MediaType mediaType : 8; ///< Media type.
u8 unknown; ///< Unknown.
@ -234,6 +235,14 @@ typedef struct
const void* data; ///< Pointer to FS path data.
} FS_Path;
/// SDMC/NAND speed information
typedef struct
{
bool highSpeedModeEnabled; ///< Whether or not High Speed Mode is enabled.
bool usesHighestClockRate; ///< Whether or not a clock divider of 2 is being used.
u16 sdClkCtrl; ///< The value of the SD_CLK_CTRL register.
} FS_SdMmcSpeedInfo;
/// Filesystem archive handle, providing access to a filesystem's contents.
typedef u64 FS_Archive;
@ -444,7 +453,7 @@ Result FSUSER_IsSdmcDetected(bool *detected);
/**
* @brief Gets whether the SD card is writable.
* @param detected Pointer to output the writable status to.
* @param writable Pointer to output the writable status to.
*/
Result FSUSER_IsSdmcWritable(bool *writable);
@ -466,13 +475,13 @@ Result FSUSER_GetNandCid(u8* out, u32 length);
* @brief Gets the SDMC speed info.
* @param speedInfo Pointer to output the speed info to.
*/
Result FSUSER_GetSdmcSpeedInfo(u32 *speedInfo);
Result FSUSER_GetSdmcSpeedInfo(FS_SdMmcSpeedInfo *speedInfo);
/**
* @brief Gets the NAND speed info.
* @param speedInfo Pointer to output the speed info to.
*/
Result FSUSER_GetNandSpeedInfo(u32 *speedInfo);
Result FSUSER_GetNandSpeedInfo(FS_SdMmcSpeedInfo *speedInfo);
/**
* @brief Gets the SDMC log.
@ -537,7 +546,7 @@ Result FSUSER_CardNorDirectCommandWithAddress(u8 commandId, u32 address);
* @param size Size of the output buffer.
* @param output Output buffer.
*/
Result FSUSER_CardNorDirectRead(u8 commandId, u32 size, u8* output);
Result FSUSER_CardNorDirectRead(u8 commandId, u32 size, void* output);
/**
* @brief Executes a CARDNOR direct read with an address.
@ -546,7 +555,7 @@ Result FSUSER_CardNorDirectRead(u8 commandId, u32 size, u8* output);
* @param size Size of the output buffer.
* @param output Output buffer.
*/
Result FSUSER_CardNorDirectReadWithAddress(u8 commandId, u32 address, u32 size, u8* output);
Result FSUSER_CardNorDirectReadWithAddress(u8 commandId, u32 address, u32 size, void* output);
/**
* @brief Executes a CARDNOR direct write.
@ -554,7 +563,7 @@ Result FSUSER_CardNorDirectReadWithAddress(u8 commandId, u32 address, u32 size,
* @param size Size of the input buffer.
* @param output Input buffer.
*/
Result FSUSER_CardNorDirectWrite(u8 commandId, u32 size, u8* input);
Result FSUSER_CardNorDirectWrite(u8 commandId, u32 size, const void* input);
/**
* @brief Executes a CARDNOR direct write with an address.
@ -563,7 +572,7 @@ Result FSUSER_CardNorDirectWrite(u8 commandId, u32 size, u8* input);
* @param size Size of the input buffer.
* @param input Input buffer.
*/
Result FSUSER_CardNorDirectWriteWithAddress(u8 commandId, u32 address, u32 size, u8* input);
Result FSUSER_CardNorDirectWriteWithAddress(u8 commandId, u32 address, u32 size, const void* input);
/**
* @brief Executes a CARDNOR 4xIO direct read.
@ -572,7 +581,7 @@ Result FSUSER_CardNorDirectWriteWithAddress(u8 commandId, u32 address, u32 size,
* @param size Size of the output buffer.
* @param output Output buffer.
*/
Result FSUSER_CardNorDirectRead_4xIO(u8 commandId, u32 address, u32 size, u8* output);
Result FSUSER_CardNorDirectRead_4xIO(u8 commandId, u32 address, u32 size, void* output);
/**
* @brief Executes a CARDNOR direct CPU write without verify.
@ -580,7 +589,7 @@ Result FSUSER_CardNorDirectRead_4xIO(u8 commandId, u32 address, u32 size, u8* ou
* @param size Size of the input buffer.
* @param output Input buffer.
*/
Result FSUSER_CardNorDirectCpuWriteWithoutVerify(u32 address, u32 size, u8* input);
Result FSUSER_CardNorDirectCpuWriteWithoutVerify(u32 address, u32 size, const void* input);
/**
* @brief Executes a CARDNOR direct sector erase without verify.
@ -610,7 +619,7 @@ Result FSUSER_SetCardSpiBaudRate(FS_CardSpiBaudRate baudRate);
/**
* @brief Sets the CARDSPI bus mode.
* @param baudRate Bus mode to set.
* @param busMode Bus mode to set.
*/
Result FSUSER_SetCardSpiBusMode(FS_CardSpiBusMode busMode);
@ -632,15 +641,15 @@ Result FSUSER_GetSpecialContentIndex(u16* index, FS_MediaType mediaType, u64 pro
* @param programId ID of the program.
* @param header Pointer to output the legacy ROM header to. (size = 0x3B4)
*/
Result FSUSER_GetLegacyRomHeader(FS_MediaType mediaType, u64 programId, u8* header);
Result FSUSER_GetLegacyRomHeader(FS_MediaType mediaType, u64 programId, void* header);
/**
* @brief Gets the legacy banner data of a program.
* @param mediaType Media type of the program.
* @param programId ID of the program.
* @param header Pointer to output the legacy banner data to. (size = 0x23C0)
* @param banner Pointer to output the legacy banner data to. (size = 0x23C0)
*/
Result FSUSER_GetLegacyBannerData(FS_MediaType mediaType, u64 programId, u8* banner);
Result FSUSER_GetLegacyBannerData(FS_MediaType mediaType, u64 programId, void* banner);
/**
* @brief Checks a process's authority to access a save data archive.
@ -697,7 +706,7 @@ Result FSUSER_GetFormatInfo(u32* totalSize, u32* directories, u32* files, bool*
* @param programId ID of the program.
* @param header Pointer to output the legacy ROM header to.
*/
Result FSUSER_GetLegacyRomHeader2(u32 headerSize, FS_MediaType mediaType, u64 programId, u8* header);
Result FSUSER_GetLegacyRomHeader2(u32 headerSize, FS_MediaType mediaType, u64 programId, void* header);
/**
* @brief Gets the CTR SDMC root path.
@ -745,7 +754,7 @@ Result FSUSER_FormatSaveData(FS_ArchiveID archiveId, FS_Path path, u32 blocks, u
* @param programId ID of the program.
* @param header Pointer to output the legacy sub banner data to.
*/
Result FSUSER_GetLegacySubBannerData(u32 bannerSize, FS_MediaType mediaType, u64 programId, u8* banner);
Result FSUSER_GetLegacySubBannerData(u32 bannerSize, FS_MediaType mediaType, u64 programId, void* banner);
/**
* @brief Hashes the given data and outputs a SHA256 hash.
@ -762,7 +771,7 @@ Result FSUSER_UpdateSha256Context(const void* data, u32 inputSize, u8* hash);
* @param size Size of the buffer.
* @param data Buffer to read to.
*/
Result FSUSER_ReadSpecialFile(u32* bytesRead, u64 fileOffset, u32 size, u8* data);
Result FSUSER_ReadSpecialFile(u32* bytesRead, u64 fileOffset, u32 size, void* data);
/**
* @brief Gets the size of a special file.
@ -871,7 +880,7 @@ Result FSUSER_SetCtrCardLatencyParameter(u64 latency, bool emulateEndurance);
/**
* @brief Toggles cleaning up invalid save data.
* @param Whether to enable cleaning up invalid save data.
* @param enable Whether to enable cleaning up invalid save data.
*/
Result FSUSER_SwitchCleanupInvalidSaveData(bool enable);

View File

@ -0,0 +1,613 @@
/**
* @file fspxi.h
* @brief Service interface for PxiFS services. This is normally not accessible to userland apps. https://3dbrew.org/wiki/Filesystem_services_PXI
*/
#pragma once
#include <3ds/services/fs.h>
#include <3ds/types.h>
typedef u64 FSPXI_Archive;
typedef u64 FSPXI_File;
typedef u64 FSPXI_Directory;
/**
* @brief Opens a file.
* @param out Pointer to output the file handle to.
* @param archive Archive containing the file.
* @param path Path of the file.
* @param flags Flags to open the file with.
* @param attributes Attributes of the file.
*/
Result FSPXI_OpenFile(Handle serviceHandle, FSPXI_File* out, FSPXI_Archive archive, FS_Path path, u32 flags, u32 attributes);
/**
* @brief Deletes a file.
* @param archive Archive containing the file.
* @param path Path of the file.
*/
Result FSPXI_DeleteFile(Handle serviceHandle, FSPXI_Archive archive, FS_Path path);
/**
* @brief Renames a file.
* @param srcArchive Archive containing the source file.
* @param srcPath Path of the source file.
* @param dstArchive Archive containing the destination file.
* @param dstPath Path of the destination file.
*/
Result FSPXI_RenameFile(Handle serviceHandle, FSPXI_Archive srcArchive, FS_Path srcPath, FSPXI_Archive dstArchive, FS_Path dstPath);
/**
* @brief Deletes a directory.
* @param archive Archive containing the directory.
* @param path Path of the directory.
*/
Result FSPXI_DeleteDirectory(Handle serviceHandle, FSPXI_Archive archive, FS_Path path);
/**
* @brief Creates a file.
* @param archive Archive to create the file in.
* @param path Path of the file.
* @param attributes Attributes of the file.
* @param size Size of the file.
*/
Result FSPXI_CreateFile(Handle serviceHandle, FSPXI_Archive archive, FS_Path path, u32 attributes, u64 fileSize);
/**
* @brief Creates a directory.
* @param archive Archive to create the directory in.
* @param path Path of the directory.
* @param attributes Attributes of the directory.
*/
Result FSPXI_CreateDirectory(Handle serviceHandle, FSPXI_Archive archive, FS_Path path, u32 attributes);
/**
* @brief Renames a directory.
* @param srcArchive Archive containing the source directory.
* @param srcPath Path of the source directory.
* @param dstArchive Archive containing the destination directory.
* @param dstPath Path of the destination directory.
*/
Result FSPXI_RenameDirectory(Handle serviceHandle, FSPXI_Archive srcArchive, FS_Path srcPath, FSPXI_Archive dstArchive, FS_Path dstPath);
/**
* @brief Opens a directory.
* @param out Pointer to output the directory handle to.
* @param archive Archive containing the directory.
* @param path Path of the directory.
*/
Result FSPXI_OpenDirectory(Handle serviceHandle, FSPXI_Directory* out, FSPXI_Archive archive, FS_Path path);
/**
* @brief Reads from a file.
* @param file File to read from.
* @param bytesRead Pointer to output the number of read bytes to.
* @param offset Offset to read from.
* @param buffer Buffer to read to.
* @param size Size of the buffer.
*/
Result FSPXI_ReadFile(Handle serviceHandle, FSPXI_File file, u32* bytesRead, u64 offset, void* buffer, u32 size);
/**
* @brief Calculate SHA256 of a file.
* @param file File to calculate the hash of.
* @param buffer Buffer to output the hash to.
* @param size Size of the buffer.
*/
Result FSPXI_CalculateFileHashSHA256(Handle serviceHandle, FSPXI_File file, void* buffer, u32 size);
/**
* @brief Writes to a file.
* @param file File to write to.
* @param bytesWritten Pointer to output the number of bytes written to.
* @param offset Offset to write to.
* @param buffer Buffer to write from.
* @param size Size of the buffer.
* @param flags Flags to use when writing.
*/
Result FSPXI_WriteFile(Handle serviceHandle, FSPXI_File file, u32* bytesWritten, u64 offset, const void* buffer, u32 size, u32 flags);
/**
* @brief Calculates the MAC used in a DISA/DIFF header?
* @param file Unsure
* @param inBuffer 0x100-byte DISA/DIFF input buffer.
* @param inSize Size of inBuffer.
* @param outBuffer Buffer to write MAC to.
* @param outSize Size of outBuffer.
*/
Result FSPXI_CalcSavegameMAC(Handle serviceHandle, FSPXI_File file, const void* inBuffer, u32 inSize, void* outBuffer, u32 outSize);
/**
* @brief Get size of a file
* @param file File to get the size of.
* @param size Pointer to output size to.
*/
Result FSPXI_GetFileSize(Handle serviceHandle, FSPXI_File file, u64* size);
/**
* @brief Set size of a file
* @param file File to set the size of
* @param size Size to set the file to
*/
Result FSPXI_SetFileSize(Handle serviceHandle, FSPXI_File file, u64 size);
/**
* @brief Close a file
* @param file File to close
*/
Result FSPXI_CloseFile(Handle serviceHandle, FSPXI_File file);
/**
* @brief Reads one or more directory entries.
* @param directory Directory to read from.
* @param entriesRead Pointer to output the number of entries read to.
* @param entryCount Number of entries to read.
* @param entryOut Pointer to output directory entries to.
*/
Result FSPXI_ReadDirectory(Handle serviceHandle, FSPXI_Directory directory, u32* entriesRead, u32 entryCount, FS_DirectoryEntry* entries);
/**
* @brief Close a directory
* @param directory Directory to close.
*/
Result FSPXI_CloseDirectory(Handle serviceHandle, FSPXI_Directory directory);
/**
* @brief Opens an archive.
* @param archive Pointer to output the opened archive to.
* @param id ID of the archive.
* @param path Path of the archive.
*/
Result FSPXI_OpenArchive(Handle serviceHandle, FSPXI_Archive* archive, FS_ArchiveID archiveID, FS_Path path);
/**
* @brief Checks if the archive contains a file at path.
* @param archive Archive to check.
* @param out Pointer to output existence to.
* @param path Path to check for file
*/
Result FSPXI_HasFile(Handle serviceHandle, FSPXI_Archive archive, bool* out, FS_Path path);
/**
* @brief Checks if the archive contains a directory at path.
* @param archive Archive to check.
* @param out Pointer to output existence to.
* @param path Path to check for directory
*/
Result FSPXI_HasDirectory(Handle serviceHandle, FSPXI_Archive archive, bool* out, FS_Path path);
/**
* @brief Commits an archive's save data.
* @param archive Archive to commit.
* @param id Archive action sent by FSUSER_ControlArchive. Must not be 0 or 0x789D
* @remark Unsure why id is sent. This appears to be the default action for FSUSER_ControlArchive, with every action other than 0 and 0x789D being sent to this command.
*/
Result FSPXI_CommitSaveData(Handle serviceHandle, FSPXI_Archive archive, u32 id);
/**
* @brief Close an archive
* @param archive Archive to close.
*/
Result FSPXI_CloseArchive(Handle serviceHandle, FSPXI_Archive archive);
/**
* @brief Unknown 0x17. Appears to be an "is archive handle valid" command?
* @param archive Archive handle to check validity of.
* @param out Pointer to output validity to.
*/
Result FSPXI_Unknown0x17(Handle serviceHandle, FSPXI_Archive archive, bool* out);
/**
* @brief Gets the inserted card type.
* @param out Pointer to output the card type to.
*/
Result FSPXI_GetCardType(Handle serviceHandle, FS_CardType* out);
/**
* @brief Gets the SDMC archive resource information.
* @param out Pointer to output the archive resource information to.
*/
Result FSPXI_GetSdmcArchiveResource(Handle serviceHandle, FS_ArchiveResource* out);
/**
* @brief Gets the NAND archive resource information.
* @param out Pointer to output the archive resource information to.
*/
Result FSPXI_GetNandArchiveResource(Handle serviceHandle, FS_ArchiveResource* out);
/**
* @brief Gets the error code from the SDMC FatFS driver
* @param out Pointer to output the error code to
*/
Result FSPXI_GetSdmcFatFsError(Handle serviceHandle, u32* out);
/**
* @brief Gets whether PXIFS0 detects the SD
* @param out Pointer to output the detection status to
*/
Result FSPXI_IsSdmcDetected(Handle serviceHandle, bool* out);
/**
* @brief Gets whether PXIFS0 can write to the SD
* @param out Pointer to output the writable status to
*/
Result FSPXI_IsSdmcWritable(Handle serviceHandle, bool* out);
/**
* @brief Gets the SDMC CID
* @param out Buffer to output the CID to.
* @param size Size of buffer.
*/
Result FSPXI_GetSdmcCid(Handle serviceHandle, void* out, u32 size);
/**
* @brief Gets the NAND CID
* @param out Buffer to output the CID to.
* @param size Size of buffer.
*/
Result FSPXI_GetNandCid(Handle serviceHandle, void* out, u32 size);
/**
* @brief Gets the SDMC speed info
* @param out Buffer to output the speed info to.
*/
Result FSPXI_GetSdmcSpeedInfo(Handle serviceHandle, FS_SdMmcSpeedInfo* out);
/**
* @brief Gets the NAND speed info
* @param out Buffer to output the speed info to.
*/
Result FSPXI_GetNandSpeedInfo(Handle serviceHandle, FS_SdMmcSpeedInfo* out);
/**
* @brief Gets the SDMC log
* @param out Buffer to output the log to.
* @param size Size of buffer.
*/
Result FSPXI_GetSdmcLog(Handle serviceHandle, void* out, u32 size);
/**
* @brief Gets the NAND log
* @param out Buffer to output the log to.
* @param size Size of buffer.
*/
Result FSPXI_GetNandLog(Handle serviceHandle, void* out, u32 size);
/// Clears the SDMC log
Result FSPXI_ClearSdmcLog(Handle serviceHandle);
/// Clears the NAND log
Result FSPXI_ClearNandLog(Handle serviceHandle);
/**
* @brief Gets whether a card is inserted.
* @param inserted Pointer to output the insertion status to.
*/
Result FSPXI_CardSlotIsInserted(Handle serviceHandle, bool* inserted);
/**
* @brief Powers on the card slot.
* @param status Pointer to output the power status to.
*/
Result FSPXI_CardSlotPowerOn(Handle serviceHandle, bool* status);
/**
* @brief Powers off the card slot.
* @param status Pointer to output the power status to.
*/
Result FSPXI_CardSlotPowerOff(Handle serviceHandle, bool* status);
/**
* @brief Gets the card's power status.
* @param status Pointer to output the power status to.
*/
Result FSPXI_CardSlotGetCardIFPowerStatus(Handle serviceHandle, bool* status);
/**
* @brief Executes a CARDNOR direct command.
* @param commandId ID of the command.
*/
Result FSPXI_CardNorDirectCommand(Handle serviceHandle, u8 commandId);
/**
* @brief Executes a CARDNOR direct command with an address.
* @param commandId ID of the command.
* @param address Address to provide.
*/
Result FSPXI_CardNorDirectCommandWithAddress(Handle serviceHandle, u8 commandId, u32 address);
/**
* @brief Executes a CARDNOR direct read.
* @param commandId ID of the command.
* @param size Size of the output buffer.
* @param output Output buffer.
*/
Result FSPXI_CardNorDirectRead(Handle serviceHandle, u8 commandId, u32 size, void* output);
/**
* @brief Executes a CARDNOR direct read with an address.
* @param commandId ID of the command.
* @param address Address to provide.
* @param size Size of the output buffer.
* @param output Output buffer.
*/
Result FSPXI_CardNorDirectReadWithAddress(Handle serviceHandle, u8 commandId, u32 address, u32 size, void* output);
/**
* @brief Executes a CARDNOR direct write.
* @param commandId ID of the command.
* @param size Size of the input buffer.
* @param output Input buffer.
* @remark Stubbed in latest firmware, since ?.?.?
*/
Result FSPXI_CardNorDirectWrite(Handle serviceHandle, u8 commandId, u32 size, const void* input);
/**
* @brief Executes a CARDNOR direct write with an address.
* @param commandId ID of the command.
* @param address Address to provide.
* @param size Size of the input buffer.
* @param input Input buffer.
*/
Result FSPXI_CardNorDirectWriteWithAddress(Handle serviceHandle, u8 commandId, u32 address, u32 size, const void* input);
/**
* @brief Executes a CARDNOR 4xIO direct read.
* @param commandId ID of the command.
* @param address Address to provide.
* @param size Size of the output buffer.
* @param output Output buffer.
*/
Result FSPXI_CardNorDirectRead_4xIO(Handle serviceHandle, u8 commandId, u32 address, u32 size, void* output);
/**
* @brief Executes a CARDNOR direct CPU write without verify.
* @param address Address to provide.
* @param size Size of the input buffer.
* @param output Input buffer.
*/
Result FSPXI_CardNorDirectCpuWriteWithoutVerify(Handle serviceHandle, u32 address, u32 size, const void* input);
/**
* @brief Executes a CARDNOR direct sector erase without verify.
* @param address Address to provide.
*/
Result FSPXI_CardNorDirectSectorEraseWithoutVerify(Handle serviceHandle, u32 address);
/**
* @brief Gets an NCCH's product info
* @param info Pointer to output the product info to.
* @param archive Open NCCH content archive
*/
Result FSPXI_GetProductInfo(Handle serviceHandle, FS_ProductInfo* info, FSPXI_Archive archive);
/**
* @brief Sets the CARDSPI baud rate.
* @param baudRate Baud rate to set.
*/
Result FSPXI_SetCardSpiBaudrate(Handle serviceHandle, FS_CardSpiBaudRate baudRate);
/**
* @brief Sets the CARDSPI bus mode.
* @param busMode Bus mode to set.
*/
Result FSPXI_SetCardSpiBusMode(Handle serviceHandle, FS_CardSpiBusMode busMode);
/**
* @brief Sends initialization info to ARM9
* @param unk FS sends *(0x1FF81086)
*/
Result FSPXI_SendInitializeInfoTo9(Handle serviceHandle, u8 unk);
/**
* @brief Creates ext save data.
* @param info Info of the save data.
*/
Result FSPXI_CreateExtSaveData(Handle serviceHandle, FS_ExtSaveDataInfo info);
/**
* @brief Deletes ext save data.
* @param info Info of the save data.
*/
Result FSPXI_DeleteExtSaveData(Handle serviceHandle, FS_ExtSaveDataInfo info);
/**
* @brief Enumerates ext save data.
* @param idsWritten Pointer to output the number of IDs written to.
* @param idsSize Size of the IDs buffer.
* @param mediaType Media type to enumerate over.
* @param idSize Size of each ID element.
* @param shared Whether to enumerate shared ext save data.
* @param ids Pointer to output IDs to.
*/
Result FSPXI_EnumerateExtSaveData(Handle serviceHandle, u32* idsWritten, u32 idsSize, FS_MediaType mediaType, u32 idSize, bool shared, u8* ids);
/**
* @brief Gets a special content's index.
* @param index Pointer to output the index to.
* @param mediaType Media type of the special content.
* @param programId Program ID owning the special content.
* @param type Type of special content.
*/
Result FSPXI_GetSpecialContentIndex(Handle serviceHandle, u16* index, FS_MediaType mediaType, u64 programId, FS_SpecialContentType type);
/**
* @brief Gets the legacy ROM header of a program.
* @param mediaType Media type of the program.
* @param programId ID of the program.
* @param header Pointer to output the legacy ROM header to. (size = 0x3B4)
*/
Result FSPXI_GetLegacyRomHeader(Handle serviceHandle, FS_MediaType mediaType, u64 programId, void* header);
/**
* @brief Gets the legacy banner data of a program.
* @param mediaType Media type of the program.
* @param programId ID of the program.
* @param banner Pointer to output the legacy banner data to. (size = 0x23C0)
* @param unk Unknown. Always 1?
*/
Result FSPXI_GetLegacyBannerData(Handle serviceHandle, FS_MediaType mediaType, u64 programId, void* banner, u8 unk);
/**
* @brief Formats the CARDNOR device.
* @param unk Unknown. Transaction?
*/
Result FSPXI_FormatCardNorDevice(Handle serviceHandle, u32 unk);
/// Deletes the 3DS SDMC root.
Result FSPXI_DeleteSdmcRoot(Handle serviceHandle);
/// Deletes all ext save data on the NAND.
Result FSPXI_DeleteAllExtSaveDataOnNand(Handle serviceHandle);
/// Initializes the CTR file system.
Result FSPXI_InitializeCtrFilesystem(Handle serviceHandle);
/// Creates the FS seed.
Result FSPXI_CreateSeed(Handle serviceHandle);
/**
* @brief Gets the CTR SDMC root path.
* @param out Pointer to output the root path to.
* @param length Length of the output buffer in bytes.
*/
Result FSPXI_GetSdmcCtrRootPath(Handle serviceHandle, u16* out, u32 length);
/**
* @brief Gets an archive's resource information.
* @param archiveResource Pointer to output the archive resource information to.
* @param mediaType System media type to check.
*/
Result FSPXI_GetArchiveResource(Handle serviceHandle, FS_ArchiveResource* archiveResource, FS_SystemMediaType mediaType);
/**
* @brief Exports the integrity verification seed.
* @param seed Pointer to output the seed to.
*/
Result FSPXI_ExportIntegrityVerificationSeed(Handle serviceHandle, FS_IntegrityVerificationSeed* seed);
/**
* @brief Imports an integrity verification seed.
* @param seed Seed to import.
*/
Result FSPXI_ImportIntegrityVerificationSeed(Handle serviceHandle, const FS_IntegrityVerificationSeed* seed);
/**
* @brief Gets the legacy sub banner data of a program.
* @param bannerSize Size of the banner.
* @param mediaType Media type of the program.
* @param programId ID of the program.
* @param header Pointer to output the legacy sub banner data to.
*/
Result FSPXI_GetLegacySubBannerData(Handle serviceHandle, u32 bannerSize, FS_MediaType mediaType, u64 programId, void* banner);
/**
* @brief Generates random bytes. Uses same code as PSPXI_GenerateRandomBytes
* @param buf Buffer to output random bytes to.
* @param size Size of buffer.
*/
Result FSPXI_GenerateRandomBytes(Handle serviceHandle, void* buffer, u32 size);
/**
* @brief Gets the last modified time of a file in an archive.
* @param archive The archive that contains the file.
* @param out The pointer to write the timestamp to.
* @param path The UTF-16 path of the file.
* @param size The size of the path.
*/
Result FSPXI_GetFileLastModified(Handle serviceHandle, FSPXI_Archive archive, u64* out, const u16* path, u32 size);
/**
* @brief Reads from a special file.
* @param bytesRead Pointer to output the number of bytes read to.
* @param fileOffset Offset of the file.
* @param size Size of the buffer.
* @param data Buffer to read to.
*/
Result FSPXI_ReadSpecialFile(Handle serviceHandle, u32* bytesRead, u64 fileOffset, u32 size, void* data);
/**
* @brief Gets the size of a special file.
* @param fileSize Pointer to output the size to.
*/
Result FSPXI_GetSpecialFileSize(Handle serviceHandle, u64* fileSize);
/**
* @brief Initiates a device move as the source device.
* @param context Pointer to output the context to.
*/
Result FSPXI_StartDeviceMoveAsSource(Handle serviceHandle, FS_DeviceMoveContext* context);
/**
* @brief Initiates a device move as the destination device.
* @param context Context to use.
* @param clear Whether to clear the device's data first.
*/
Result FSPXI_StartDeviceMoveAsDestination(Handle serviceHandle, FS_DeviceMoveContext context, bool clear);
/**
* @brief Reads data and stores SHA256 hashes of blocks
* @param file File to read from.
* @param bytesRead Pointer to output the number of read bytes to.
* @param offset Offset to read from.
* @param readBuffer Pointer to store read data in.
* @param readBufferSize Size of readBuffer.
* @param hashtable Pointer to store SHA256 hashes in.
* @param hashtableSize Size of hashtable.
* @param unk Unknown. Always 0x00001000? Possibly block size?
*/
Result FSPXI_ReadFileSHA256(Handle serviceHandle, FSPXI_File file, u32* bytesRead, u64 offset, void* readBuffer, u32 readBufferSize, void* hashtable, u32 hashtableSize, u32 unk);
/**
* @brief Assumedly writes data and stores SHA256 hashes of blocks
* @param file File to write to.
* @param bytesWritten Pointer to output the number of written bytes to.
* @param offset Offset to write to.
* @param writeBuffer Buffer to write from.
* @param writeBufferSize Size of writeBuffer.
* @param hashtable Pointer to store SHA256 hashes in.
* @param hashtableSize Size of hashtable
* @param unk1 Unknown. Might match with ReadFileSHA256's unknown?
* @param unk2 Unknown. Might match with ReadFileSHA256's unknown?
*/
Result FSPXI_WriteFileSHA256(Handle serviceHandle, FSPXI_File file, u32* bytesWritten, u64 offset, const void* writeBuffer, u32 writeBufferSize, void* hashtable, u32 hashtableSize, u32 unk1, u32 unk2);
/**
* @brief Configures CTRCARD latency emulation.
* @param latency Latency to apply.
*/
Result FSPXI_SetCtrCardLatencyParameter(Handle serviceHandle, u64 latency);
/**
* @brief Sets the file system priority.
* @param priority Priority to set.
*/
Result FSPXI_SetPriority(Handle serviceHandle, u32 priority);
/**
* @brief Toggles cleaning up invalid save data.
* @param enable Whether to enable cleaning up invalid save data.
*/
Result FSPXI_SwitchCleanupInvalidSaveData(Handle serviceHandle, bool enable);
/**
* @brief Enumerates system save data.
* @param idsWritten Pointer to output the number of IDs written to.
* @param idsSize Size of the IDs buffer.
* @param ids Pointer to output IDs to.
*/
Result FSPXI_EnumerateSystemSaveData(Handle serviceHandle, u32* idsWritten, u32 idsSize, u32* ids);
/**
* @brief Reads the NAND report.
* @param unk Unknown
* @param buffer Buffer to write the report to.
* @param size Size of buffer
*/
Result FSPXI_ReadNandReport(Handle serviceHandle, void* buffer, u32 size, u32 unk);
/**
* @brief Unknown command 0x56
* @remark Called by FSUSER_ControlArchive with ArchiveAction 0x789D
*/
Result FSPXI_Unknown0x56(Handle serviceHandle, u32 out[4], FS_Archive archive, FS_Path path);

View File

@ -0,0 +1,63 @@
/**
* @file fsReg.h
* @brief Filesystem registry service
*/
#pragma once
#include <3ds/exheader.h>
#include <3ds/services/fs.h>
/// Initializes fs:REG.
Result fsRegInit(void);
/// Exits fs:REG.
void fsRegExit(void);
/**
* @brief Gets the current fs:REG session handle.
* @return The current fs:REG session handle.
*/
Handle *fsRegGetSessionHandle(void);
/**
* @brief Registers a program's storage information.
* @param pid The Process ID of the program.
* @param programHandle The program handle.
* @param programInfo Information about the program.
* @param storageInfo Storage information to register.
*/
Result FSREG_Register(u32 pid, u64 programHandle, const FS_ProgramInfo *programInfo, const ExHeader_Arm11StorageInfo *storageInfo);
/**
* @brief Unregisters a program's storage information.
* @param pid The Process ID of the program.
*/
Result FSREG_Unregister(u32 pid);
/**
* @brief Retrives the exheader information set(s) (SCI+ACI) about a program.
* @param exheaderInfos[out] Pointer to the output exheader information set(s).
* @param maxNumEntries The maximum number of entries.
* @param programHandle The program handle.
*/
Result FSREG_GetProgramInfo(ExHeader_Info *exheaderInfos, u32 maxNumEntries, u64 programHandle);
/**
* @brief Loads a program.
* @param programHandle[out] Pointer to the output the program handle to.
* @param programInfo Information about the program to load.
*/
Result FSREG_LoadProgram(u64 *programHandle, const FS_ProgramInfo *programInfo);
/**
* @brief Unloads a program.
* @param programHandle The program handle.
*/
Result FSREG_UnloadProgram(u64 programHandle);
/**
* @brief Checks if a program has been loaded by fs:REG.
* @param programHandle The program handle.
*/
Result FSREG_CheckHostLoadId(u64 programHandle);

View File

@ -4,7 +4,12 @@
*/
#pragma once
#define GSPGPU_REBASE_REG(r) ((r)-0x1EB00000)
#define GSP_SCREEN_TOP 0 ///< ID of the top screen.
#define GSP_SCREEN_BOTTOM 1 ///< ID of the bottom screen.
#define GSP_SCREEN_WIDTH 240 ///< Width of the top/bottom screens.
#define GSP_SCREEN_HEIGHT_TOP 400 ///< Height of the top screen.
#define GSP_SCREEN_HEIGHT_TOP_2X 800 ///< Height of the top screen (2x).
#define GSP_SCREEN_HEIGHT_BOTTOM 320 ///< Height of the bottom screen.
/// Framebuffer information.
typedef struct
@ -26,7 +31,7 @@ typedef enum
GSP_RGB565_OES=2, ///< RGB565. (2 bytes)
GSP_RGB5_A1_OES=3, ///< RGB5A1. (2 bytes)
GSP_RGBA4_OES=4 ///< RGBA4. (2 bytes)
} GSPGPU_FramebufferFormats;
} GSPGPU_FramebufferFormat;
/// Capture info entry.
typedef struct
@ -57,12 +62,61 @@ typedef enum
GSPGPU_EVENT_MAX, ///< Used to know how many events there are.
} GSPGPU_Event;
/**
* @brief Gets the number of bytes per pixel for the specified format.
* @param format See \ref GSPGPU_FramebufferFormat.
* @return Bytes per pixel.
*/
static inline unsigned gspGetBytesPerPixel(GSPGPU_FramebufferFormat format)
{
switch (format)
{
case GSP_RGBA8_OES:
return 4;
default:
case GSP_BGR8_OES:
return 3;
case GSP_RGB565_OES:
case GSP_RGB5_A1_OES:
case GSP_RGBA4_OES:
return 2;
}
}
/// Initializes GSPGPU.
Result gspInit(void);
/// Exits GSPGPU.
void gspExit(void);
/**
* @brief Gets a pointer to the current gsp::Gpu session handle.
* @return A pointer to the current gsp::Gpu session handle.
*/
Handle *gspGetSessionHandle(void);
/// Returns true if the application currently has GPU rights.
bool gspHasGpuRight(void);
/**
* @brief Presents a buffer to the specified screen.
* @param screen Screen ID (see \ref GSP_SCREEN_TOP and \ref GSP_SCREEN_BOTTOM)
* @param swap Specifies which set of framebuffer registers to configure and activate (0 or 1)
* @param fb_a Pointer to the framebuffer (in stereo mode: left eye)
* @param fb_b Pointer to the secondary framebuffer (only used in stereo mode for the right eye, otherwise pass the same as fb_a)
* @param stride Stride in bytes between scanlines
* @param mode Mode configuration to be written to LCD register
* @return true if a buffer had already been presented to the screen but not processed yet by GSP, false otherwise.
* @note The most recently presented buffer is processed and configured during the specified screen's next VBlank event.
*/
bool gspPresentBuffer(unsigned screen, unsigned swap, const void* fb_a, const void* fb_b, u32 stride, u32 mode);
/**
* @brief Returns true if a prior \ref gspPresentBuffer command is still pending to be processed by GSP.
* @param screen Screen ID (see \ref GSP_SCREEN_TOP and \ref GSP_SCREEN_BOTTOM)
*/
bool gspIsPresentPending(unsigned screen);
/**
* @brief Configures a callback to run when a GSPGPU event occurs.
* @param id ID of the event.
@ -72,17 +126,6 @@ void gspExit(void);
*/
void gspSetEventCallback(GSPGPU_Event id, ThreadFunc cb, void* data, bool oneShot);
/**
* @brief Initializes the GSPGPU event handler.
* @param gspEvent Event handle to use.
* @param gspSharedMem GSP shared memory.
* @param gspThreadId ID of the GSP thread.
*/
Result gspInitEventHandler(Handle gspEvent, vu8* gspSharedMem, u8 gspThreadId);
/// Exits the GSPGPU event handler.
void gspExitEventHandler(void);
/**
* @brief Waits for a GSPGPU event to occur.
* @param id ID of the event.
@ -124,10 +167,9 @@ GSPGPU_Event gspWaitForAnyEvent(void);
/**
* @brief Submits a GX command.
* @param sharedGspCmdBuf Command buffer to use.
* @param gxCommand GX command to execute.
*/
Result gspSubmitGxCommand(u32* sharedGspCmdBuf, u32 gxCommand[0x8]);
Result gspSubmitGxCommand(const u32 gxCommand[0x8]);
/**
* @brief Acquires GPU rights.
@ -142,11 +184,14 @@ Result GSPGPU_ReleaseRight(void);
* @brief Retrieves display capture info.
* @param captureinfo Pointer to output capture info to.
*/
Result GSPGPU_ImportDisplayCaptureInfo(GSPGPU_CaptureInfo*captureinfo);
Result GSPGPU_ImportDisplayCaptureInfo(GSPGPU_CaptureInfo* captureinfo);
/// Sames the VRAM sys area.
/// Saves the VRAM sys area.
Result GSPGPU_SaveVramSysArea(void);
/// Resets the GPU
Result GSPGPU_ResetGpuCore(void);
/// Restores the VRAM sys area.
Result GSPGPU_RestoreVramSysArea(void);
@ -161,7 +206,7 @@ Result GSPGPU_SetLcdForceBlack(u8 flags);
* @param screenid ID of the screen to update.
* @param framebufinfo Framebuffer information to update with.
*/
Result GSPGPU_SetBufferSwap(u32 screenid, GSPGPU_FramebufferInfo*framebufinfo);
Result GSPGPU_SetBufferSwap(u32 screenid, const GSPGPU_FramebufferInfo* framebufinfo);
/**
* @brief Flushes memory from the data cache.
@ -183,7 +228,7 @@ Result GSPGPU_InvalidateDataCache(const void* adr, u32 size);
* @param data Data to write.
* @param size Size of the data to write.
*/
Result GSPGPU_WriteHWRegs(u32 regAddr, u32* data, u8 size);
Result GSPGPU_WriteHWRegs(u32 regAddr, const u32* data, u8 size);
/**
* @brief Writes to GPU hardware registers with a mask.
@ -193,7 +238,7 @@ Result GSPGPU_WriteHWRegs(u32 regAddr, u32* data, u8 size);
* @param maskdata Data of the mask.
* @param masksize Size of the mask.
*/
Result GSPGPU_WriteHWRegsWithMask(u32 regAddr, u32* data, u8 datasize, u32* maskdata, u8 masksize);
Result GSPGPU_WriteHWRegsWithMask(u32 regAddr, const u32* data, u8 datasize, const u32* maskdata, u8 masksize);
/**
* @brief Reads from GPU hardware registers.
@ -218,3 +263,8 @@ Result GSPGPU_UnregisterInterruptRelayQueue(void);
/// Triggers a handling of commands written to shared memory.
Result GSPGPU_TriggerCmdReqQueue(void);
/**
* @brief Sets 3D_LEDSTATE to the input state value.
* @param disable False = 3D LED enable, true = 3D LED disable.
*/
Result GSPGPU_SetLedForceOff(bool disable);

View File

@ -3,13 +3,14 @@
* @brief GSPLCD service.
*/
#pragma once
#include <3ds/gfx.h> // For gfxScreen_t
#include <3ds/types.h>
#include <3ds/services/gspgpu.h>
/// LCD screens.
enum
{
GSPLCD_SCREEN_TOP = BIT(GFX_TOP), ///< Top screen.
GSPLCD_SCREEN_BOTTOM = BIT(GFX_BOTTOM), ///< Bottom screen.
GSPLCD_SCREEN_TOP = BIT(GSP_SCREEN_TOP), ///< Top screen.
GSPLCD_SCREEN_BOTTOM = BIT(GSP_SCREEN_BOTTOM), ///< Bottom screen.
GSPLCD_SCREEN_BOTH = GSPLCD_SCREEN_TOP | GSPLCD_SCREEN_BOTTOM, ///< Both screens.
};
@ -19,6 +20,18 @@ Result gspLcdInit(void);
/// Exits GSPLCD.
void gspLcdExit(void);
/**
* @brief Gets a pointer to the current gsp::Lcd session handle.
* @return A pointer to the current gsp::Lcd session handle.
*/
Handle *gspLcdGetSessionHandle(void);
/// Powers on both backlights.
Result GSPLCD_PowerOnAllBacklights(void);
/// Powers off both backlights.
Result GSPLCD_PowerOffAllBacklights(void);
/**
* @brief Powers on the backlight.
* @param screen Screen to power on.
@ -31,8 +44,35 @@ Result GSPLCD_PowerOnBacklight(u32 screen);
*/
Result GSPLCD_PowerOffBacklight(u32 screen);
/**
* @brief Sets 3D_LEDSTATE to the input state value.
* @param disable False = 3D LED enable, true = 3D LED disable.
*/
Result GSPLCD_SetLedForceOff(bool disable);
/**
* @brief Gets the LCD screens' vendors. Stubbed on old 3ds.
* @param vendor Pointer to output the screen vendors to.
*/
Result GSPLCD_GetVendors(u8 *vendors);
Result GSPLCD_GetVendors(u8 *vendors);
/**
* @brief Gets the LCD screens' brightness. Stubbed on old 3ds.
* @param screen Screen to get the brightness value of.
* @param brightness Brightness value returned.
*/
Result GSPLCD_GetBrightness(u32 screen, u32 *brightness);
/**
* @brief Sets the LCD screens' brightness.
* @param screen Screen to set the brightness value of.
* @param brightness Brightness value set.
*/
Result GSPLCD_SetBrightness(u32 screen, u32 brightness);
/**
* @brief Sets the LCD screens' raw brightness.
* @param screen Screen to set the brightness value of.
* @param brightness Brightness value set.
*/
Result GSPLCD_SetBrightnessRaw(u32 screen, u32 brightness);

View File

@ -1,38 +0,0 @@
/**
* @file hb.h
* @brief HB (Homebrew) service.
*/
#pragma once
// WARNING ! THIS FILE PROVIDES AN INTERFACE TO A NON-OFFICIAL SERVICE PROVIDED BY NINJHAX
// BY USING COMMANDS FROM THIS SERVICE YOU WILL LIKELY MAKE YOUR APPLICATION INCOMPATIBLE WITH OTHER HOMEBREW LAUNCHING METHODS
// A GOOD WAY TO COPE WITH THIS IS TO CHECK THE OUTPUT OF hbInit FOR ERRORS
#include <3ds/types.h>
/// Initializes HB.
Result hbInit(void);
/// Exits HB.
void hbExit(void);
/// Flushes/invalidates the entire data/instruction cache.
Result HB_FlushInvalidateCache(void);
/**
* @brief Fetches the address for Ninjhax 1.x bootloader addresses.
* @param load3dsx void (*callBootloader)(Handle hb, Handle file);
* @param setArgv void (*setArgs)(u32* src, u32 length);
*/
Result HB_GetBootloaderAddresses(void** load3dsx, void** setArgv);
/**
* @brief Changes the permissions of a given number of pages at address addr to mode.
* Should it fail, the appropriate kernel error code will be returned and *reprotectedPages (if not NULL)
* will be set to the number of sequential pages which were successfully reprotected + 1
* @param addr Address to reprotect.
* @param pages Number of pages to reprotect.
* @param mode Mode to reprotect to.
* @param reprotectedPages Number of successfully reprotected pages, on failure.
*/
Result HB_ReprotectMemory(u32* addr, u32 pages, u32 mode, u32* reprotectedPages);

View File

@ -91,6 +91,13 @@ Result hidInit(void);
/// Exits HID.
void hidExit(void);
/**
* @brief Sets the key repeat parameters for @ref hidKeysRepeat.
* @param delay Initial delay.
* @param interval Repeat interval.
*/
void hidSetRepeatParameters(u32 delay, u32 interval);
/// Scans HID for input data.
void hidScanInput(void);
@ -109,7 +116,14 @@ u32 hidKeysHeld(void);
u32 hidKeysDown(void);
/**
* @brief Returns a bitmask of newly released buttons, this frame.
* @brief Returns a bitmask of newly pressed or repeated buttons, this frame.
* Individual buttons can be extracted using binary AND.
* @return 32-bit bitmask of newly pressed or repeated buttons.
*/
u32 hidKeysDownRepeat(void);
/**
* @brief Returns a bitmask of newly released buttons, this frame.
* Individual buttons can be extracted using binary AND.
* @return 32-bit bitmask of newly released buttons.
*/
@ -146,6 +160,14 @@ void hidGyroRead(angularRate* rate);
*/
void hidWaitForEvent(HID_Event id, bool nextEvent);
/**
* @brief Waits for any HID or IRRST event.
* @param nextEvents Whether to discard the current events and wait for the next events.
* @param cancelEvent Optional additional handle to wait on, otherwise 0.
* @param timeout Timeout.
*/
Result hidWaitForAnyEvent(bool nextEvents, Handle cancelEvent, s64 timeout);
/// Compatibility macro for hidScanInput.
#define scanKeys hidScanInput
/// Compatibility macro for hidKeysHeld.

View File

@ -82,6 +82,15 @@ Result httpcAddRequestHeaderField(httpcContext *context, const char* name, const
*/
Result httpcAddPostDataAscii(httpcContext *context, const char* name, const char* value);
/**
* @brief Adds a POST form field with binary data to a HTTP context.
* @param context Context to use.
* @param name Name of the field.
* @param value The binary data to pass as a value.
* @param len Length of the binary data which has been passed.
*/
Result httpcAddPostDataBinary(httpcContext *context, const char* name, const u8* value, u32 len);
/**
* @brief Adds a POST body to a HTTP context.
* @param context Context to use.

View File

@ -87,7 +87,19 @@ Result IRU_GetBitRate(u8 *out);
Result IRU_SetIRLEDState(u32 value);
/**
* @brief Gets the IR KED state.
* @brief Gets the IR LED state.
* @param out Pointer to write the IR LED state to.
*/
Result IRU_GetIRLEDRecvState(u32 *out);
/**
* @brief Gets an event which is signaled once a send finishes.
* @param out Pointer to write the event handle to.
*/
Result IRU_GetSendFinishedEvent(Handle *out);
/**
* @brief Gets an event which is signaled once a receive finishes.
* @param out Pointer to write the event handle to.
*/
Result IRU_GetRecvFinishedEvent(Handle *out);

View File

@ -14,6 +14,9 @@ extern Handle irrstMemHandle;
/// IRRST's shared memory.
extern vu32* irrstSharedMem;
/// IRRST's state update event
extern Handle irrstEvent;
/// Initializes IRRST.
Result irrstInit(void);

View File

@ -0,0 +1,43 @@
/**
* @file loader.h
* @brief LOADER Service
*/
#pragma once
#include <3ds/exheader.h>
#include <3ds/services/fs.h>
/// Initializes LOADER.
Result loaderInit(void);
/// Exits LOADER.
void loaderExit(void);
/**
* @brief Loads a program and returns a process handle to the newly created process.
* @param[out] process Pointer to output the process handle to.
* @param programHandle The handle of the program to load.
*/
Result LOADER_LoadProcess(Handle* process, u64 programHandle);
/**
* @brief Registers a program (along with its update).
* @param[out] programHandle Pointer to output the program handle to.
* @param programInfo The program info.
* @param programInfo The program update info.
*/
Result LOADER_RegisterProgram(u64* programHandle, const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate);
/**
* @brief Unregisters a program (along with its update).
* @param programHandle The handle of the program to unregister.
*/
Result LOADER_UnregisterProgram(u64 programHandle);
/**
* @brief Retrives a program's main NCCH extended header info (SCI + ACI, see @ref ExHeader_Info).
* @param[out] exheaderInfo Pointer to output the main NCCH extended header info.
* @param programHandle The handle of the program to unregister
*/
Result LOADER_GetProgramInfo(ExHeader_Info* exheaderInfo, u64 programHandle);

View File

@ -0,0 +1,107 @@
/**
* @file mcuhwc.h
* @brief mcuHwc service.
*/
#pragma once
typedef enum {
LED_NORMAL = 1, ///< The normal mode of the led
LED_SLEEP_MODE, ///< The led pulses slowly as it does in the sleep mode
LED_OFF, ///< Switch off power led
LED_RED, ///< Red state of the led
LED_BLUE, ///< Blue state of the led
LED_BLINK_RED, ///< Blinking red state of power led and notification led
} powerLedState;
typedef struct InfoLedPattern
{
u8 delay; ///< Delay between pattern values, 1/16th of a second (1 second = 0x10)
u8 smoothing; ///< Smoothing between pattern values (higher = smoother)
u8 loopDelay; ///< Delay between pattern loops, 1/16th of a second (1 second = 0x10, 0xFF = pattern is played only once)
u8 blinkSpeed; ///< Blink speed, when smoothing == 0x00
u8 redPattern[32]; ///< Pattern for red component
u8 greenPattern[32]; ///< Pattern for green component
u8 bluePattern[32]; ///< Pattern for blue component
} InfoLedPattern;
/// Initializes mcuHwc.
Result mcuHwcInit(void);
/// Exits mcuHwc.
void mcuHwcExit(void);
/**
* @brief Gets the current mcuHwc session handle.
* @return A pointer to the current mcuHwc session handle.
*/
Handle* mcuHwcGetSessionHandle(void);
/**
* @brief Reads data from an i2c device3 register
* @param reg Register number. See https://www.3dbrew.org/wiki/I2C_Registers#Device_3 for more info
* @param data Pointer to write the data to.
* @param size Size of data to be read
*/
Result MCUHWC_ReadRegister(u8 reg, void *data, u32 size);
/**
* @brief Writes data to a i2c device3 register
* @param reg Register number. See https://www.3dbrew.org/wiki/I2C_Registers#Device_3 for more info
* @param data Pointer to write the data to.
* @param size Size of data to be written
*/
Result MCUHWC_WriteRegister(u8 reg, const void *data, u32 size);
/**
* @brief Gets the battery voltage
* @param voltage Pointer to write the battery voltage to.
*/
Result MCUHWC_GetBatteryVoltage(u8 *voltage);
/**
* @brief Gets the battery level
* @param level Pointer to write the current battery level to.
*/
Result MCUHWC_GetBatteryLevel(u8 *level);
/**
* @brief Gets the sound slider level
* @param level Pointer to write the slider level to.
*/
Result MCUHWC_GetSoundSliderLevel(u8 *level);
/**
* @brief Sets Wifi LED state
* @param state State of Wifi LED. (True/False)
*/
Result MCUHWC_SetWifiLedState(bool state);
/**
* @brief Sets the notification LED pattern
* @param pattern Pattern for the notification LED.
*/
Result MCUHWC_SetInfoLedPattern(const InfoLedPattern* pattern);
/**
* @brief Sets Power LED state
* @param state powerLedState State of power LED.
*/
Result MCUHWC_SetPowerLedState(powerLedState state);
/**
* @brief Gets 3d slider level
* @param level Pointer to write 3D slider level to.
*/
Result MCUHWC_Get3dSliderLevel(u8 *level);
/**
* @brief Gets the major MCU firmware version
* @param out Pointer to write the major firmware version to.
*/
Result MCUHWC_GetFwVerHigh(u8 *out);
/**
* @brief Gets the minor MCU firmware version
* @param out Pointer to write the minor firmware version to.
*/
Result MCUHWC_GetFwVerLow(u8 *out);

View File

@ -16,10 +16,10 @@ typedef enum
/// Microphone audio sampling rates.
typedef enum
{
MICU_SAMPLE_RATE_32730 = 0, ///< 32730 Hz
MICU_SAMPLE_RATE_16360 = 1, ///< 16360 Hz
MICU_SAMPLE_RATE_10910 = 2, ///< 10910 Hz
MICU_SAMPLE_RATE_8180 = 3, ///< 8180 Hz
MICU_SAMPLE_RATE_32730 = 0, ///< 32728.498 Hz
MICU_SAMPLE_RATE_16360 = 1, ///< 16364.479 Hz
MICU_SAMPLE_RATE_10910 = 2, ///< 10909.499 Hz
MICU_SAMPLE_RATE_8180 = 3, ///< 8182.1245 Hz
} MICU_SampleRate;
/**

View File

@ -4,13 +4,57 @@
*/
#pragma once
/// Exclusive states.
typedef enum {
EXCLUSIVE_STATE_NONE = 0,
EXCLUSIVE_STATE_INFRASTRUCTURE = 1,
EXCLUSIVE_STATE_LOCAL_COMMUNICATIONS = 2,
EXCLUSIVE_STATE_STREETPASS = 3,
EXCLUSIVE_STATE_STREETPASS_DATA = 4,
} NDM_ExclusiveState;
NDM_EXCLUSIVE_STATE_NONE = 0,
NDM_EXCLUSIVE_STATE_INFRASTRUCTURE = 1,
NDM_EXCLUSIVE_STATE_LOCAL_COMMUNICATIONS = 2,
NDM_EXCLUSIVE_STATE_STREETPASS = 3,
NDM_EXCLUSIVE_STATE_STREETPASS_DATA = 4,
} ndmExclusiveState;
/// Current states.
typedef enum {
NDM_STATE_INITIAL = 0,
NDM_STATE_SUSPENDED = 1,
NDM_STATE_INFRASTRUCTURE_CONNECTING = 2,
NDM_STATE_INFRASTRUCTURE_CONNECTED = 3,
NDM_STATE_INFRASTRUCTURE_WORKING = 4,
NDM_STATE_INFRASTRUCTURE_SUSPENDING = 5,
NDM_STATE_INFRASTRUCTURE_FORCE_SUSPENDING = 6,
NDM_STATE_INFRASTRUCTURE_DISCONNECTING = 7,
NDM_STATE_INFRASTRUCTURE_FORCE_DISCONNECTING = 8,
NDM_STATE_CEC_WORKING = 9,
NDM_STATE_CEC_FORCE_SUSPENDING = 10,
NDM_STATE_CEC_SUSPENDING = 11,
} ndmState;
// Daemons.
typedef enum {
NDM_DAEMON_CEC = 0,
NDM_DAEMON_BOSS = 1,
NDM_DAEMON_NIM = 2,
NDM_DAEMON_FRIENDS = 3,
} ndmDaemon;
/// Used to specify multiple daemons.
typedef enum {
NDM_DAEMON_MASK_CEC = BIT(NDM_DAEMON_CEC),
NDM_DAEMON_MASK_BOSS = BIT(NDM_DAEMON_BOSS),
NDM_DAEMON_MASK_NIM = BIT(NDM_DAEMON_NIM),
NDM_DAEMON_MASK_FRIENDS = BIT(NDM_DAEMON_FRIENDS),
NDM_DAEMON_MASK_BACKGROUOND = NDM_DAEMON_MASK_CEC | NDM_DAEMON_MASK_BOSS | NDM_DAEMON_MASK_NIM,
NDM_DAEMON_MASK_ALL = NDM_DAEMON_MASK_CEC | NDM_DAEMON_MASK_BOSS | NDM_DAEMON_MASK_NIM | NDM_DAEMON_MASK_FRIENDS,
NDM_DAEMON_MASK_DEFAULT = NDM_DAEMON_MASK_CEC | NDM_DAEMON_MASK_FRIENDS,
} ndmDaemonMask;
// Daemon status.
typedef enum {
NDM_DAEMON_STATUS_BUSY = 0,
NDM_DAEMON_STATUS_IDLE = 1,
NDM_DAEMON_STATUS_SUSPENDING = 2,
NDM_DAEMON_STATUS_SUSPENDED = 3,
} ndmDaemonStatus;
/// Initializes ndmu.
Result ndmuInit(void);
@ -18,7 +62,88 @@ Result ndmuInit(void);
/// Exits ndmu.
void ndmuExit(void);
Result ndmuEnterExclusiveState(NDM_ExclusiveState state);
/**
* @brief Sets the network daemon to an exclusive state.
* @param state State specified in the ndmExclusiveState enumerator.
*/
Result NDMU_EnterExclusiveState(ndmExclusiveState state);
Result ndmuLeaveExclusiveState(void);
/// Cancels an exclusive state for the network daemon.
Result NDMU_LeaveExclusiveState(void);
/**
* @brief Returns the exclusive state for the network daemon.
* @param state Pointer to write the exclsuive state to.
*/
Result NDMU_GetExclusiveState(ndmExclusiveState *state);
/// Locks the exclusive state.
Result NDMU_LockState(void);
/// Unlocks the exclusive state.
Result NDMU_UnlockState(void);
/**
* @brief Suspends network daemon.
* @param mask The specified daemon.
*/
Result NDMU_SuspendDaemons(ndmDaemonMask mask);
/**
* @brief Resumes network daemon.
* @param mask The specified daemon.
*/
Result NDMU_ResumeDaemons(ndmDaemonMask mask);
/**
* @brief Suspends scheduling for all network daemons.
* @param flag 0 = Wait for completion, 1 = Perform in background.
*/
Result NDMU_SuspendScheduler(u32 flag);
/// Resumes daemon scheduling.
Result NDMU_ResumeScheduler(void);
/**
* @brief Returns the current state for the network daemon.
* @param state Pointer to write the current state to.
*/
Result NDMU_GetCurrentState(ndmState *state);
/**
* @brief Returns a daemon state.
* @param daemon The specified daemon.
* @param state Pointer to write the daemon state to.
*/
Result NDMU_QueryStatus(ndmDaemon daemon, ndmDaemonStatus *status);
/**
* @brief Sets the scan interval.
* @param interval Value to set the scan interval to.
*/
Result NDMU_SetScanInterval(u32 interval);
/**
* @brief Returns the scan interval.
* @param interval Pointer to write the interval value to.
*/
Result NDMU_GetScanInterval(u32 *interval);
/**
* @brief Returns the retry interval.
* @param interval Pointer to write the interval value to.
*/
Result NDMU_GetRetryInterval(u32 *interval);
/// Reverts network daemon to defaults.
Result NDMU_ResetDaemons(void);
/**
* @brief Gets the current default daemon bit mask.
* @param interval Pointer to write the default daemon mask value to. The default value is (DAEMONMASK_CEC | DAEMONMASK_FRIENDS)
*/
Result NDMU_GetDefaultDaemons(ndmDaemonMask *mask);
/// Clears half awake mac filter.
Result NDMU_ClearMacFilter(void);

View File

@ -28,7 +28,8 @@
/// NFC operation type.
typedef enum {
NFC_OpType_1 = 1, /// Unknown.
NFC_OpType_NFCTag = 2 /// This is the default.
NFC_OpType_NFCTag = 2, /// This is the default.
NFC_OpType_RawNFC = 3 /// Use Raw NFC tag commands. Only available with >=10.0.0-X.
} NFC_OpType;
typedef enum {
@ -71,14 +72,13 @@ typedef struct {
u8 lastwritedate_month;
u8 lastwritedate_day;
u16 write_counter;
u16 val_x6;
u8 val_x8;
u8 val_x9;
u16 val_xa;
u8 val_xc;
u8 pagex4_byte3;/// "This is byte[3] from NFC page[0x4]."
u8 appdata_size;/// "NFC module writes hard-coded u8 value 0xD8 here. This is the size of the Amiibo AppData, apps can use this with the AppData R/W commands. ..."
u8 zeros[0x31];/// "Unused / reserved: this is cleared by NFC module but never written after that."
u8 characterID[3];/// the first element is the collection ID, the second the character in this collection, the third the variant
u8 series;/// ID of the series
u16 amiiboID;/// ID shared by all exact same amiibo. Some amiibo are only distinguished by this one like regular SMB Series Mario and the gold one
u8 type;/// Type of amiibo 0 = figure, 1 = card, 2 = plush
u8 pagex4_byte3;
u16 appdata_size;/// "NFC module writes hard-coded u8 value 0xD8 here. This is the size of the Amiibo AppData, apps can use this with the AppData R/W commands. ..."
u8 zeros[0x30];/// "Unused / reserved: this is cleared by NFC module but never written after that."
} NFC_AmiiboConfig;
/// Used by nfcInitializeWriteAppData() internally, see also here: https://3dbrew.org/wiki/NFC:GetAppDataInitStruct
@ -190,3 +190,31 @@ Result nfcGetAmiiboSettings(NFC_AmiiboSettings *out);
*/
Result nfcGetAmiiboConfig(NFC_AmiiboConfig *out);
/**
* @brief Starts scanning for NFC tags when initialized with NFC_OpType_RawNFC. See also: https://www.3dbrew.org/wiki/NFC:StartOtherTagScanning
* @param unk0 Same as nfcStartScanning() input.
* @param unk1 Unknown.
*/
Result nfcStartOtherTagScanning(u16 unk0, u32 unk1);
/**
* @brief This sends a raw NFC command to the tag. This can only be used when initialized with NFC_OpType_RawNFC, and when the TagState is NFC_TagState_InRange. See also: https://www.3dbrew.org/wiki/NFC:SendTagCommand
* @param inbuf Input buffer.
* @param insize Size of the input buffer.
* @param outbuf Output buffer.
* @param outsize Size of the output buffer.
* @param actual_transfer_size Optional output ptr to write the actual output-size to, can be NULL.
* @param microseconds Timing-related field in microseconds.
*/
Result nfcSendTagCommand(const void *inbuf, size_t insize, void *outbuf, size_t outsize, size_t *actual_transfer_size, u64 microseconds);
/**
* @brief Unknown. This can only be used when initialized with NFC_OpType_RawNFC, and when the TagState is NFC_TagState_InRange.
*/
Result nfcCmd21(void);
/**
* @brief Unknown. This can only be used when initialized with NFC_OpType_RawNFC, and when the TagState is NFC_TagState_InRange.
*/
Result nfcCmd22(void);

View File

@ -0,0 +1,151 @@
/**
* @file nim.h
* @brief NIM (network installation management) service.
*
* This service is used to download and install titles from Nintendo's CDN.
*
* We differentiate between two different kinds of downloads:
*
* - "active" downloads, which are downloads started with @ref NIMS_StartDownload or @ref NIMS_StartDownloadSimple. The process must keep polling the current status using @ref NIMS_GetProgress.
* - "tasks", which are downloads started with @ref NIMS_RegisterTask. These are only processed in sleep mode.
*/
#pragma once
// FS_MediaType
#include <3ds/services/fs.h>
/// Mode that NIM downloads/installs a title with.
typedef enum
{
IM_DEFAULT = 0, ///< Initial installation
IM_UNKNOWN1, ///< Unknown
IM_UNKNOWN2, ///< Unknown
IM_REINSTALL, ///< Reinstall currently installed title; use this if the title is already installed (including updates)
} NIM_InstallationMode;
/// Current state of a NIM download/installation.
typedef enum
{
DS_NOT_INITIALIZED = 0, ///< Download not yet initialized
DS_INITIALIZED, ///< Download initialized
DS_DOWNLOAD_TMD, ///< Downloading and installing TMD
DS_PREPARE_SAVE_DATA, ///< Initializing save data
DS_DOWNLOAD_CONTENTS, ///< Downloading and installing contents
DS_WAIT_COMMIT, ///< Waiting before calling AM_CommitImportTitles
DS_COMMITTING, ///< Running AM_CommitImportTitles
DS_FINISHED, ///< Title installation finished
DS_VERSION_ERROR, ///< (unknown error regarding title version)
DS_CREATE_CONTEXT, ///< Creating the .ctx file?
DS_CANNOT_RECOVER, ///< Irrecoverable error encountered (e.g. out of space)
DS_INVALID, ///< Invalid state
} NIM_DownloadState;
/// Input configuration for NIM download/installation tasks.
typedef struct
{
u64 titleId; ///< Title ID
u32 version; ///< Title version
u32 unknown_0; ///< Always 0
u8 ratingAge; ///< Age for the HOME Menu parental controls
u8 mediaType; ///< Media type, see @ref FS_MediaType enum
u8 padding[2]; ///< Padding
u32 unknown_1; ///< Unknown input, seems to be always 0
} NIM_TitleConfig;
/// Output struct for NIM downloads/installations in progress.
typedef struct
{
u32 state; ///< State, see NIM_DownloadState enum
Result lastResult; ///< Last result code in NIM
u64 downloadedSize; ///< Amount of bytes that have been downloaded
u64 totalSize; ///< Amount of bytes that need to be downloaded in total
} NIM_TitleProgress;
/**
* @brief Initializes nim:s. This uses networking and is blocking.
* @param buffer A buffer for internal use. It must be at least 0x20000 bytes long.
* @param buffer_len Length of the passed buffer.
*/
Result nimsInit(void *buffer, size_t buffer_len);
/**
* @brief Initializes nim:s with the given TIN. This uses networking and is blocking.
* @param buffer A buffer for internal use. It must be at least 0x20000 bytes long.
* @param buffer_len Length of the passed buffer.
* @param TIN The TIN to initialize nim:s with. If you do not know what a TIN is or why you would want to change it, use @ref nimsInit instead.
*/
Result nimsInitWithTIN(void *buffer, size_t buffer_len, const char *TIN);
/// Exits nim:s.
void nimsExit(void);
/// Gets the current nim:s session handle.
Handle *nimsGetSessionHandle(void);
/**
* @brief Sets an attribute.
* @param attr Name of the attribute.
* @param val Value of the attribute.
*/
Result NIMS_SetAttribute(const char *attr, const char *val);
/**
* @brief Checks if nim wants a system update.
* @param want_update Set to true if a system update is required. Can be NULL.
*/
Result NIMS_WantUpdate(bool *want_update);
/**
* @brief Makes a TitleConfig struct for use with @ref NIMS_RegisterTask, @ref NIMS_StartDownload or @ref NIMS_StartDownloadSimple.
* @param cfg Struct to initialize.
* @param titleId Title ID to download and install.
* @param version Version of the title to download and install.
* @param ratingAge Age for which the title is aged; used by parental controls in HOME Menu.
* @param mediaType Media type of the title to download and install.
*/
void NIMS_MakeTitleConfig(NIM_TitleConfig *cfg, u64 titleId, u32 version, u8 ratingAge, FS_MediaType mediaType);
/**
* @brief Registers a background download task with NIM. These are processed in sleep mode only.
* @param cfg Title config to use. See @ref NIMS_MakeTitleConfig.
* @param name Name of the title in UTF-8. Will be displayed on the HOME Menu. Maximum 73 characters.
* @param maker Name of the maker/publisher in UTF-8. Will be displayed on the HOME Menu. Maximum 37 characters.
*/
Result NIMS_RegisterTask(const NIM_TitleConfig *cfg, const char *name, const char *maker);
/**
* @brief Checks whether a background download task for the given title is registered with NIM.
* @param titleId Title ID to check for.
* @param registered Whether there is a background download task registered.
*/
Result NIMS_IsTaskRegistered(u64 titleId, bool *registered);
/**
* @brief Unregisters a background download task.
* @param titleId Title ID whose background download task to cancel.
*/
Result NIMS_UnregisterTask(u64 titleId);
/**
* @brief Starts an active download with NIM. Progress can be checked with @ref NIMS_GetProcess. Do not exit the process while a download is in progress without calling @ref NIMS_CancelDownload.
* @param cfg Title config to use. See @ref NIMS_MakeTitleConfig.
* @param mode The installation mode to use. See @ref NIM_InstallationMode.
*/
Result NIMS_StartDownload(const NIM_TitleConfig *cfg, NIM_InstallationMode mode);
/**
* @brief Starts an active download with NIM with default installation mode; cannot reinstall titles. Progress can be checked with @ref NIMS_GetProcess. Do not exit the process while a download is in progress without calling @ref NIMS_CancelDownload.
* @param cfg Title config to use. See @ref NIMS_MakeTitleConfig.
*/
Result NIMS_StartDownloadSimple(const NIM_TitleConfig *cfg);
/**
* @brief Checks the status of the current active download.
* @param tp Title progress struct to write to. See @ref NIM_TitleProgress.
*/
Result NIMS_GetProgress(NIM_TitleProgress *tp);
/**
* @brief Cancels the current active download with NIM.
*/
Result NIMS_CancelDownload(void);

View File

@ -24,6 +24,8 @@ Result NS_LaunchFIRM(u64 titleid);
*/
Result NS_LaunchTitle(u64 titleid, u32 launch_flags, u32 *procid);
/// Terminates the application from which this function is called
Result NS_TerminateTitle(void);
/**
* @brief Launches a title and the required firmware.
* @param titleid ID of the title to launch, 0 for gamecard.
@ -41,5 +43,9 @@ Result NS_RebootToTitle(u8 mediatype, u64 titleid);
/**
* @brief Terminates the process with the specified titleid.
* @param titleid ID of the title to terminate.
* @param timeout Timeout in nanoseconds. Pass 0 if not required.
*/
Result NS_TerminateProcessTID(u64 titleid);
Result NS_TerminateProcessTID(u64 titleid, u64 timeout);
/// Reboots the system
Result NS_RebootSystem(void);

View File

@ -1,49 +0,0 @@
/**
* @file pm.h
* @brief PM (Process Manager) service.
*/
#pragma once
/// Initializes PM.
Result pmInit(void);
/// Exits PM.
void pmExit(void);
/**
* @brief Launches a title.
* @param mediatype Mediatype of the title.
* @param titleid ID of the title.
* @param launch_flags Flags to launch the title with.
*/
Result PM_LaunchTitle(u8 mediatype, u64 titleid, u32 launch_flags);
/**
* @brief Gets launch flags from a title's exheader.
* @param mediatype Mediatype of the title.
* @param titleid ID of the title.
* @param out Pointer to write the launch flags to.
*/
Result PM_GetTitleExheaderFlags(u8 mediatype, u64 titleid, u8* out);
/**
* @brief Sets the current FIRM launch parameters.
* @param size Size of the FIRM launch parameter buffer.
* @param in Buffer to retrieve the launch parameters from.
*/
Result PM_SetFIRMLaunchParams(u32 size, u8* in);
/**
* @brief Gets the current FIRM launch parameters.
* @param size Size of the FIRM launch parameter buffer.
* @param out Buffer to write the launch parameters to.
*/
Result PM_GetFIRMLaunchParams(u32 size, u8* out);
/**
* @brief Sets the current FIRM launch parameters.
* @param firm_titleid_low Low Title ID of the FIRM title to launch.
* @param size Size of the FIRM launch parameter buffer.
* @param in Buffer to retrieve the launch parameters from.
*/
Result PM_LaunchFIRMSetParams(u32 firm_titleid_low, u32 size, u8* in);

View File

@ -0,0 +1,123 @@
/**
* @file pmapp.h
* @brief PM (Process Manager) application service.
*/
#pragma once
#include <3ds/services/fs.h>
#include <3ds/exheader.h>
/// Launch flags for PM launch commands.
enum {
PMLAUNCHFLAG_NORMAL_APPLICATION = BIT(0),
PMLAUNCHFLAG_LOAD_DEPENDENCIES = BIT(1),
PMLAUNCHFLAG_NOTIFY_TERMINATION = BIT(2),
PMLAUNCHFLAG_QUEUE_DEBUG_APPLICATION = BIT(3),
PMLAUNCHFLAG_TERMINATION_NOTIFICATION_MASK = 0xF0,
PMLAUNCHFLAG_FORCE_USE_O3DS_APP_MEM = BIT(8), ///< Forces the usage of the O3DS system mode app memory setting even if N3DS system mode is not "Legacy". Dev4 and Dev5 not supported. N3DS only.
PMLAUNCHFLAG_FORCE_USE_O3DS_MAX_APP_MEM = BIT(9), ///< In conjunction with the above, forces the 96MB app memory setting. N3DS only.
PMLAUNCHFLAG_USE_UPDATE_TITLE = BIT(16),
};
/// Initializes pm:app.
Result pmAppInit(void);
/// Exits pm:app.
void pmAppExit(void);
/**
* @brief Gets the current pm:app session handle.
* @return The current pm:app session handle.
*/
Handle *pmAppGetSessionHandle(void);
/**
* @brief Launches a title.
* @param programInfo Program information of the title.
* @param launchFlags Flags to launch the title with.
*/
Result PMAPP_LaunchTitle(const FS_ProgramInfo *programInfo, u32 launchFlags);
/**
* @brief Launches a title, applying patches.
* @param programInfo Program information of the title.
* @param programInfoUpdate Program information of the update title.
* @param launchFlags Flags to launch the title with.
*/
Result PMAPP_LaunchTitleUpdate(const FS_ProgramInfo *programInfo, const FS_ProgramInfo *programInfoUpdate, u32 launchFlags);
/**
* @brief Gets a title's ExHeader Arm11CoreInfo and SystemInfo flags.
* @param[out] outCoreInfo Pointer to write the ExHeader Arm11CoreInfo to.
* @param[out] outSiFlags Pointer to write the ExHeader SystemInfo flags to.
* @param programInfo Program information of the title.
*/
Result PMAPP_GetTitleExheaderFlags(ExHeader_Arm11CoreInfo* outCoreInfo, ExHeader_SystemInfoFlags* outSiFlags, const FS_ProgramInfo *programInfo);
/**
* @brief Sets the current FIRM launch parameters.
* @param size Size of the FIRM launch parameter buffer.
* @param in Buffer to retrieve the launch parameters from.
*/
Result PMAPP_SetFIRMLaunchParams(u32 size, const void* in);
/**
* @brief Gets the current FIRM launch parameters.
* @param size Size of the FIRM launch parameter buffer.
* @param[out] out Buffer to write the launch parameters to.
*/
Result PMAPP_GetFIRMLaunchParams(void *out, u32 size);
/**
* @brief Sets the current FIRM launch parameters.
* @param firmTidLow Low Title ID of the FIRM title to launch.
* @param size Size of the FIRM launch parameter buffer.
* @param in Buffer to retrieve the launch parameters from.
*/
Result PMAPP_LaunchFIRMSetParams(u32 firmTidLow, u32 size, const void* in);
/**
* @brief Terminate most processes, to prepare for a reboot or a shutdown.
* @param timeout Time limit in ns for process termination, after which the remaining processes are killed.
*/
Result PMAPP_PrepareForReboot(s64 timeout);
/**
* @brief Terminates the current Application
* @param timeout Timeout in nanoseconds
*/
Result PMAPP_TerminateCurrentApplication(s64 timeout);
/**
* @brief Terminates the processes having the specified titleId.
* @param titleId Title ID of the processes to terminate
* @param timeout Timeout in nanoseconds
*/
Result PMAPP_TerminateTitle(u64 titleId, s64 timeout);
/**
* @brief Terminates the specified process
* @param pid Process-ID of the process to terminate
* @param timeout Timeout in nanoseconds
*/
Result PMAPP_TerminateProcess(u32 pid, s64 timeout);
/**
* @brief Unregisters a process
* @param tid TitleID of the process to unregister
*/
Result PMAPP_UnregisterProcess(u64 tid);
/**
* @brief Sets the APPLICATION cputime reslimit.
* @param cpuTime Reslimit value.
* @note cpuTime can be no higher than reslimitdesc[0] & 0x7F in exheader (or 80 if the latter is 0).
*/
Result PMAPP_SetAppResourceLimit(s64 cpuTime);
/**
* @brief Gets the APPLICATION cputime reslimit.
* @param[out] cpuTime Pointer to write the reslimit value to.
*/
Result PMAPP_GetAppResourceLimit(s64 *outCpuTime);

View File

@ -0,0 +1,41 @@
/**
* @file pmdbg.h
* @brief PM (Process Manager) debug service.
*/
#pragma once
#include <3ds/services/pmapp.h>
/// Initializes pm:dbg.
Result pmDbgInit(void);
/// Exits pm:dbg.
void pmDbgExit(void);
/**
* @brief Gets the current pm:dbg session handle.
* @return The current pm:dbg session handle.
*/
Handle *pmDbgGetSessionHandle(void);
/**
* @brief Enqueues an application for debug after setting cpuTime to 0, and returns a debug handle to it.
* If another process was enqueued, this just calls @ref RunQueuedProcess instead.
* @param[out] Pointer to output the debug handle to.
* @param programInfo Program information of the title.
* @param launchFlags Flags to launch the title with.
*/
Result PMDBG_LaunchAppDebug(Handle *outDebug, const FS_ProgramInfo *programInfo, u32 launchFlags);
/**
* @brief Launches an application for debug after setting cpuTime to 0.
* @param programInfo Program information of the title.
* @param launchFlags Flags to launch the title with.
*/
Result PMDBG_LaunchApp(const FS_ProgramInfo *programInfo, u32 launchFlags);
/**
* @brief Runs the queued process and returns a debug handle to it.
* @param[out] Pointer to output the debug handle to.
*/
Result PMDBG_RunQueuedProcess(Handle *outDebug);

View File

@ -51,7 +51,7 @@ Result psInitHandle(Handle handle);
void psExit(void);
/// Returns the PS session handle.
Handle psGetSessionHandle();
Handle psGetSessionHandle(void);
/**
* @brief Signs a RSA signature.

View File

@ -0,0 +1,25 @@
/**
* @file ptmgets.h
* @brief PTMGETS service.
*/
#pragma once
#include <3ds/types.h>
/// Initializes PTMGETS.
Result ptmGetsInit(void);
/// Exits PTMGETS.
void ptmGetsExit(void);
/**
* @brief Gets a pointer to the current ptm:gets session handle.
* @return A pointer to the current ptm:gets session handle.
*/
Handle *ptmGetsGetSessionHandle(void);
/**
* @brief Gets the system time.
* @param[out] outMsY2k The pointer to write the number of milliseconds since 01/01/2000 to.
*/
Result PTMGETS_GetSystemTime(s64 *outMsY2k);

View File

@ -0,0 +1,25 @@
/**
* @file ptmsets.h
* @brief PTMSETS service.
*/
#pragma once
#include <3ds/types.h>
/// Initializes PTMSETS.
Result ptmSetsInit(void);
/// Exits PTMSETS.
void ptmSetsExit(void);
/**
* @brief Gets a pointer to the current ptm:sets session handle.
* @return A pointer to the current ptm:sets session handle.
*/
Handle *ptmSetsGetSessionHandle(void);
/**
* @brief Sets the system time.
* @param msY2k The number of milliseconds since 01/01/2000.
*/
Result PTMSETS_SetSystemTime(s64 msY2k);

View File

@ -4,17 +4,115 @@
*/
#pragma once
#include <3ds/types.h>
/// PDN wake events and MCU interrupts to select, combined with those of other processes
typedef struct PtmWakeEvents {
u32 pdn_wake_events; ///< Written to PDN_WAKE_EVENTS. Don't select bit26 (MCU), PTM will do it automatically.
u32 mcu_interupt_mask; ///< MCU interrupts to check when a MCU wake event happens.
} PtmWakeEvents;
typedef struct {
PtmWakeEvents exit_sleep_events; ///< Wake events for which the system should fully wake up.
PtmWakeEvents continue_sleep_events; ///< Wake events for which the system should return to sleep.
} PtmSleepConfig;
enum {
// Sleep FSM notification IDs
PTMNOTIFID_SLEEP_REQUESTED = 0x101, ///< @ref PTMSYSM_RequestSleep has been called (ack = 3)
PTMNOTIFID_SLEEP_DENIED = 0x102, ///< The sleep request has been denied by @ref PTMSYSM_ReplyToSleepQuery(true) (no ack required).
PTMNOTIFID_SLEEP_ALLOWED = 0x103, ///< The sleep request has been allowed by @ref PTMSYSM_ReplyToSleepQuery(false) (ack = 1).
PTMNOTIFID_GOING_TO_SLEEP = 0x104, ///< All processes not having "RunnableOnSleep" have been paused & the system is about to go to sleep (ack = 0).
PTMNOTIFID_FULLY_WAKING_UP = 0x105, ///< The system has been woken up, and the paused processes are about to be unpaused (ack = 1).
PTMNOTIFID_FULLY_AWAKE = 0x106, ///< The system is fully awake (no ack required).
PTMNOTIFID_HALF_AWAKE = 0x107, ///< The system has been woken up but is about to go to sleep again (ack = 2).
PTMNOTIFID_SHUTDOWN = 0x108, ///< The system is about to power off or reboot.
PTMNOTIFID_BATTERY_VERY_LOW = 0x211, ///< The battery level has reached 5% or below.
PTMNOTIFID_BATTERY_LOW = 0x212, ///< The battery level has reached 10% or below.
};
/// See @ref PTMSYSM_NotifySleepPreparationComplete. Corresponds to the number of potentially remaning notifs. until sleep/wakeup.
static inline s32 ptmSysmGetNotificationAckValue(u32 id)
{
static const s32 values[] = { 3, -1, 1, 0, 0, -1, 2 };
if (id < PTMNOTIFID_SLEEP_REQUESTED || id > PTMNOTIFID_HALF_AWAKE)
return -1;
return values[id - PTMNOTIFID_SLEEP_REQUESTED];
}
/// Initializes ptm:sysm.
Result ptmSysmInit(void);
/// Exits ptm:sysm.
void ptmSysmExit(void);
/**
* @brief Gets a pointer to the current ptm:sysm session handle.
* @return A pointer to the current ptm:sysm session handle.
*/
Handle *ptmSysmGetSessionHandle(void);
/// Requests to enter sleep mode.
Result PTMSYSM_RequestSleep(void);
/**
* @brief return 1 if it's a New 3DS otherwise, return 0 for Old 3DS.
* @brief Accepts or denies the incoming sleep mode request.
* @param deny Whether or not to deny the sleep request.
* @note If deny = false, this is equivalent to calling @ref PTMSYSM_NotifySleepPreparationComplete(3)
*/
Result PTMSYSM_CheckNew3DS(void);
Result PTMSYSM_ReplyToSleepQuery(bool deny);
/**
* @brief Acknowledges the current sleep notification and advance the internal sleep mode FSM. All subscribers must reply.
* @param ackValue Use @ref ptmSysmGetNotificationAckValue
* @note @ref PTMNOTIFID_SLEEP_DENIED and @ref PTMNOTIFID_FULLY_AWAKE don't require this.
*/
Result PTMSYSM_NotifySleepPreparationComplete(s32 ackValue);
/**
* @brief Sets the wake events (two sets: when to fully wake up and when to return to sleep).
* @param sleepConfig Pointer to the two sets of wake events.
* @note Can only be called just before acknowledging @ref PTMNOTIFID_GOING_TO_SLEEP or @ref PTMNOTIFID_HALF_AWAKE.
*/
Result PTMSYSM_SetWakeEvents(const PtmSleepConfig *sleepConfig);
/**
* @brief Gets the wake reason (only the first applicable wake event is taken into account).
* @param sleepConfig Pointer to the two sets of wake events. Only the relevant set will be filled.
*/
Result PTMSYSM_GetWakeReason(PtmSleepConfig *outSleepConfig);
/// Cancels the "half-awake" state and fully wakes up the 3DS after some delay.
Result PTMSYSM_Awaken(void);
/**
* @brief Sets the user time by updating the user time offset.
* @param msY2k The number of milliseconds since 01/01/2000.
*/
Result PTMSYSM_SetUserTime(s64 msY2k);
/// Invalidates the "system time" (cfg block 0x30002)
Result PTMSYSM_InvalidateSystemTime(void);
/**
* @brief Reads the time and date coming from the RTC and converts the result.
* @param[out] outMsY2k The pointer to write the number of milliseconds since 01/01/2000 to.
*/
Result PTMSYSM_GetRtcTime(s64 *outMsY2k);
/**
* @brief Writes the time and date coming to the RTC, after conversion.
* @param msY2k The number of milliseconds since 01/01/2000.
*/
Result PTMSYSM_SetRtcTime(s64 msY2k);
/**
* @brief Checks whether the system is a New 3DS.
* @param[out] out Pointer to write the New 3DS flag to.
*/
Result PTMSYSM_CheckNew3DS(bool *out);
/**
* @brief Configures the New 3DS' CPU clock speed and L2 cache.
@ -23,13 +121,13 @@ Result PTMSYSM_CheckNew3DS(void);
Result PTMSYSM_ConfigureNew3DSCPU(u8 value);
/**
* @brief Trigger a hardware system shutdown via the MCU
* @param timeout: timeout passed to PMApp:TerminateNonEssential.
* @brief Trigger a hardware system shutdown via the MCU.
* @param timeout: timeout passed to PMApp:ShutdownAsync (PrepareForReboot).
*/
Result PTMSYSM_ShutdownAsync(u64 timeout);
/**
* @brief Trigger a hardware system reboot via the MCU.
* @param timeout: timeout passed to PMApp:TerminateNonEssential.
* @param timeout: timeout passed to PMApp:ShutdownAsync (PrepareForReboot).
*/
Result PTMSYSM_RebootAsync(u64 timeout);

View File

@ -10,6 +10,12 @@ Result ptmuInit(void);
/// Exits PTMU.
void ptmuExit(void);
/**
* @brief Gets a pointer to the current ptm:u session handle.
* @return A pointer to the current ptm:u session handle.
*/
Handle *ptmuGetSessionHandle(void);
/**
* @brief Gets the system's current shell state.
* @param out Pointer to write the current shell state to. (0 = closed, 1 = open)
@ -40,3 +46,8 @@ Result PTMU_GetPedometerState(u8 *out);
*/
Result PTMU_GetTotalStepCount(u32 *steps);
/**
* @brief Gets whether the adapter is plugged in or not
* @param out Pointer to write the adapter state to.
*/
Result PTMU_GetAdapterState(bool *out);

View File

@ -0,0 +1,42 @@
/**
* @file pxipm.h
* @brief Process Manager PXI service
*/
#pragma once
#include <3ds/exheader.h>
#include <3ds/services/fs.h>
/// Initializes PxiPM.
Result pxiPmInit(void);
/// Exits PxiPM.
void pxiPmExit(void);
/**
* @brief Gets the current PxiPM session handle.
* @return The current PxiPM session handle.
*/
Handle *pxiPmGetSessionHandle(void);
/**
* @brief Retrives the exheader information set(s) (SCI+ACI) about a program.
* @param exheaderInfos[out] Pointer to the output exheader information set.
* @param programHandle The program handle.
*/
Result PXIPM_GetProgramInfo(ExHeader_Info *exheaderInfo, u64 programHandle);
/**
* @brief Loads a program and registers it to Process9.
* @param programHandle[out] Pointer to the output the program handle to.
* @param programInfo Information about the program to load.
* @param updateInfo Information about the program update to load.
*/
Result PXIPM_RegisterProgram(u64 *programHandle, const FS_ProgramInfo *programInfo, const FS_ProgramInfo *updateInfo);
/**
* @brief Unloads a program and unregisters it from Process9.
* @param programHandle The program handle.
*/
Result PXIPM_UnregisterProgram(u64 programHandle);

View File

@ -1,57 +1,559 @@
/**
* @file qtm.h
* @brief QTM service.
* @brief QTM services.
*
* QTM is responsible for the following:
* - tracking and predicting the position of the user's eyes. This is done by using the inner
* camera sampling at 320x240px at 30 FPS, and by using the gyroscope to predict the position
* of the eyes between two camera samples (effectively doubling the tracking rate).
* The API reporting eye tracking data is actually *console-agnostic*. This concept is most
* likely covered by patent US9098112B2
* - automatically managing the IR LED emitter used for eye tracking in low-light conditions
* - managing the state of the parallax barrier by controlling the positions of the barrier's
* mask (opaque/transparent state by repeating pattern of 12 units, plus polarity). This is
* done via a TI TCA6416A I2C->Parallel expander (highlighted in yellow in this teardown photo:
* https://guide-images.cdn.ifixit.com/igi/IKlW6WTZKKmapYkt.full, with the expected 12 traces
* being clearly visible near the ribbon cable slot)
* - updating the barrier position according to eye tracking data relative to an optimal setting
* stored in calibration data: this is what Nintendo calls "Super Stable 3D" (SS3D); not done
* when in 2D mode
*
* Head-tracking can be used even if SS3D is disabled.
*
* SS3D works as follows:
* - compute the raw X and Y pixel coordinates for the eye midpoint:
* `rawX = (leftEyeRawPxCoords.x + rightEyeRawPxCoords.x) / 2`
* `rawY = (leftEyeRawPxCoords.y + rightEyeRawPxCoords.y) / 2`
* - rotate the value around the optical Z-axis using the optimal eye-to-camera angle from
* calibration data, with a rotation matrix
* - normalize the X value:
* `xC = (rawX / 320) - 0.5`
* - transform into world space coordinate, using fovX from calibration (convert to radians first).
* Note that this fovX doesn't take lens distortion into account and is slightly different from
* the hardcoded angle used in \ref QTMU_GetTrackingData
* `x = xC * tan(fovX/2)`
* - multiply by length of adjacent side (eye-to-camera distance) to get the length of the opposite
* side. This is the eye horizontal deviation to camera lens in mm, which is then converted to
* number of iod/12 units:
* `delta = x * optimalDistance / (iod/12)`
* - we then obtain the new target position of the parallax barrier (expressed in iod/12 units,
* mod iod/12):
* `pos = centerPos + delta`
* - the value is then rounded to nearest integer. To avoid artifacts, if the rounded value is
* going to increase, then 0.01 is subtracted, and if it is going to decrease, then 0.01 is added.
* The value is rounded again to compute the final discrete value written to the expander (barrier
* position).
* - note: all calculation in QTM and otherwise assume interocular distance to be 62mm (the average).
* Assumedly, if the user's IOD is different, then "optimal distance to screen" effectively changes
* for that user.
*
* QTM services are not present on O3DS, thus caller must call \ref qtmCheckServicesRegistered to check
* if the services are registered. Moreover, since QTM functionality might not always be available (due
* to blacklist or console being N2DSXL), `qtm:u` users should check Result return values, and `qtm:s`
* users can call \ref QTMS_SetQtmStatus to check the actual availability status.
*
* Considering that the eye tracking data reporting API is hardware-agnostic, it is advisable to
* hardcode neither camera aspect ratio (even if it is 4/3 on real hardware) and resolution nor
* field-of-view angle.
*
* There is a separate QTM service, `qtm:c` ("hardware check"), that lets you manipulate parallax barrier
* pattern directly. It is covered in \ref qtmc.h instead.
*/
#pragma once
//See also: http://3dbrew.org/wiki/QTM_Services
#include <3ds/types.h>
/// Head tracking coordinate pair.
typedef struct {
float x; ///< X coordinate.
float y; ///< Y coordinate.
} QTM_HeadTrackingInfoCoord;
/// ID of QTM status data (fully enabled/SS3D disabled) in `cfg`
#define QTM_STATUS_CFG_BLK_ID 0x180000u
/// Head tracking info.
typedef struct {
u8 flags[5]; ///< Flags.
u8 padding[3]; ///< Padding.
float floatdata_x08; ///< Unknown. Not used by System_Settings.
QTM_HeadTrackingInfoCoord coords0[4]; ///< Head coordinates.
u32 unk_x2c[5]; ///< Unknown. Not used by System_Settings.
} QTM_HeadTrackingInfo;
/// ID of QTM calibration data in `cfg`
#define QTM_CAL_CFG_BLK_ID 0x180001u
/// Initializes QTM.
Result qtmInit(void);
/**
* @brief QTM enablement status (when cameras not in use by user), set by `qtm:s`.
* @note Manual IR LED control, camera lux, and `qtm:c` commands remain available
* for use on N3DS and N3DSXL regardless.
*/
typedef enum QtmStatus {
QTM_STATUS_ENABLED = 0, ///< QTM is fully enabled.
QTM_STATUS_SS3D_DISABLED = 1, ///< QTM "super stable 3D" feature is disabled. Parallax barrier hardware state is configured to match O3DS.
/**
* @brief QTM is unavailable: either "blacklisted" (usually by NS) for the current title, **or console is a N2DSXL**.
*
* In this state, all QTM functionality is disabled. This includes "super-stable 3D"
* (ie. auto barrier adjustment) including `qtm:s` manual barrier position setting functions,
* head tracking, IR LED control and camera luminance reporting (400.0 is returned instead).
*
* @note `qtm:c` barrier hardware state setting function (\ref blah) bypasses this state.
* @note Due to an oversight, \ref QTMS_SetQtmStatus allows changing QTM state on N2DSXL. This is not intended
* to be done, and is in fact never done by official software.
*/
QTM_STATUS_UNAVAILABLE = 2,
} QtmStatus;
/// QTM status data (fully enabled/SS3D disabled) in `cfg`. Usually all-zero on N2DSXL.
typedef struct QtmStatusCfgData {
QtmStatus defaultStats; ///< QTM status at boot (fully enabled or SS3D disabled).
/**
* @brief "Global variable" (.data) section load mode? Unused.
* From CTRAging:
* - 0: "normal"
* - 1: "single reacq"
* - 2: "double reacq"
- 3/4/5: "w2w copy 1/10/100"
*/
u8 gvLoadMode;
u8 _padding[2]; ///< Padding.
} QtmStatusCfgData;
/// QTM calibration data (fully enabled/SS3D disabled) in `cfg`. Usually all-zero on N2DSXL.
typedef struct QtmCalibrationData {
/**
* @brief Neutral (center) barrier position/offset (with slit width of 6 units), when the user is
* facing directly facing the camera, that is to say, their eye midpoint normalized X coord
* in the camera's plane is 0, assuming the user's head is located at the expected viewing distance
* and at the expected eye-to-camera angle (as per the rest of this structure).
* This is expressed in terms of iod/12 units modulo iod/12 (thus, range is 0 to 11 included),
* with IOD (interocular distance) assumed to be 62mm.
* @note This field is floating-point for QTM auto-adjustment purposes, however the actual barrier
* position in hardware is an integer.
* @note This is the field that System Settings lets you add -1.0 to +1.0 to.
* @note Moreover, this field can be directly changed through \ref QTMS_SetCenterBarrierPosition.
*/
float centerBarrierPosition;
float translationX; ///< Lens X coord in inner camera space? Very low value and seems to be unused.
float translationY; ///< Lens Y coord in inner camera space? Very low value and seems to be unused.
float rotationZ; ///< Optimal eye-to-camera angle, in radians, without accounting for lens distortion.
float fovX; ///< Camera's horizontal FoV in degrees, without accounting for lens distortion.
float viewingDistance; ///< Optimal viewing distance between user and top screen, assuming iod to be 62mm.
} QtmCalibrationData;
/// Left eye or right eye, for \ref QtmTrackingData and \ref QtmRawTrackingData
typedef enum QtmEyeSide {
QTM_EYE_LEFT = 0, ///< Left eye.
QTM_EYE_RIGHT = 1, ///< Right eye.
QTM_EYE_NUM, ///< Number of eyes.
} QtmEyeSide;
/// QTM raw eye tracking data
typedef struct QtmRawTrackingData {
/**
* @brief Eye position detected or predicted, equals (confidenceLevel > 0).
* If false, QTM will attempt to make a guess based on gyro data.
* If the console isn't moving either, then QTM will assume the user's eyes are progressively
* moving back to face the screen.
*/
bool eyesTracked; ///< Eye position detected or predicted, equals (confidenceLevel > 0).
u8 _padding[3]; ///< Padding.
u32 singletonQtmPtr; ///< Pointer to eye-tracking singleton pointer, in QTM's .bss, located in N3DS extra memory.
float confidenceLevel; ///< Eye tracking confidence level (0 to 1).
/**
* @brief Raw predicted or detected eye coordinates. Each eye is represented as one point.
* Fractional part is *not* necessarily zero.
* @note X coord is within 0 to 320.
* @note Y coord is within 0 to 240.
*/
float rawEyeCameraCoordinates[QTM_EYE_NUM][2];
float dPitch; ///< Difference in gyro pitch from position at console boot.
float dYaw; ///< Difference in gyro yaw from position at console boot.
float dRoll; ///< Difference in gyro roll from position at console boot.
s64 samplingTick; ///< Time point the current measurements were made.
} QtmRawTrackingData;
/// QTM processed eye tracking data, suitable for 3D programming
typedef struct QtmTrackingData {
bool eyesTracked; ///< Eye position detected or tracked with some confidence, equals (confidenceLevel > 0). Even if false, QTM may make a guess
bool faceDetected; ///< Whether or not the entirety of the user's face has been detected with good confidence.
bool eyesDetected; ///< Whether or not the user's eyes have actually been detected with full confidence.
u8 _unused; ///< Unused.
bool clamped; ///< Whether or not the normalized eye coordinates have been clamped after accounting for lens distortion.
u8 _padding[3]; ///< Padding.
float confidenceLevel; ///< Eye tracking confidence level (0 to 1).
/**
* @brief Normalized eye coordinates, for each eye, after accounting for lens distortion, centered around camera.
* X coord is in the -1 to 1 range, and Y coord range depends on inverse aspect ratio (-0.75 to 0.75 on real hardware).
* @note On real hardware, X coord equals `((rawX / 160.0) - 1.00) * 1.0639` before clamping.
* @note On real hardware, Y coord equals `((rawY / 160.0) - 0.75) * 1.0637` before clamping.
*/
float eyeCameraCoordinates[QTM_EYE_NUM][2];
/**
* @brief Normalized eye coordinates, for each eye, in world space.
* Corresponds to \ref eyeCameraCoordinates multiplied by tangent of field of view.
* @note On real hardware, X coord equals `eyeCameraCoordinates.x * tan(64.9 deg / 2)`.
* @note On real hardware, Y coord equals `eyeCameraCoordinates.x * tan(51.0 deg / 2)`.
*/
float eyeWorldCoordinates[QTM_EYE_NUM][2];
float dPitch; ///< Difference in gyro pitch from position at console boot.
float dYaw; ///< Difference in gyro yaw from position at console boot.
float dRoll; ///< Difference in gyro roll from position at console boot.
s64 samplingTick; ///< Time point the current measurements were made.
} QtmTrackingData;
/// QTM service name enum, excluding `qtm:c`
typedef enum QtmServiceName {
/**
* @brief `qtm:u`: has eye-tracking commands and IR LED control commands, but for some
* reason cannot fetch ambiant lux data from the camera's luminosity sensor.
*/
QTM_SERVICE_USER = 0,
/**
* @brief `qtm:s`: has access to all `qtm:u` commands, plus luminosity sensor, plus
* manual barrier position setting and calibration adjustment commands.
* Automatic barrier control is reenabled on session exit.
*/
QTM_SERVICE_SYSTEM = 1,
/**
* @brief `qtm:sp`: has access to all `qtm:s` (and `qtm:u`) commands, and merely has a
* few more commands that GSP uses to notify QTM of 2D<>3D mode switches and
* power events. Automatic barrier control is reenabled on session exit.
* GSP always keeps a `qtm:sp` sessions open (at least on latest system version),
* whereas NS opens then immediately closes a `qtm:sp` sessions only when dealing
* with a "blacklisted" application (that is, almost never).
*/
QTM_SERVICE_SYSTEM_PROCESS = 2,
} QtmServiceName;
/**
* @brief Check whether or not QTM services are registered.
* @return True on O3DS systems, false on N3DS systems.
*/
bool qtmCheckServicesRegistered(void);
/**
* @brief Initializes QTM (except `qtm:c`).
* Excluding `qtm:c`, QTM has three main services.
* Only 3 sessions (2 until 9.3.0 sysupdate) for ALL services COMBINED, including `qtm:c`,
* can be open at a time.
* Refer to \ref QtmServiceName enum value descriptions to see which service to choose.
*
* @param serviceName QTM service name enum value (corresponding to `qtm:u`, `qtm:s` and `qtm:sp`
* respectively).
* @note Result of \ref qtmCheckServicesRegistered should be checked before calling this function.
*/
Result qtmInit(QtmServiceName serviceName);
/// Exits QTM.
void qtmExit(void);
/**
* @brief Checks whether QTM is initialized.
* @return Whether QTM is initialized.
*/
bool qtmCheckInitialized(void);
/// Checks whether or not a `qtm:u`, `qtm:s` or `qtm:sp` session is active.
bool qtmIsInitialized(void);
/// Returns a pointer to the current `qtm:u` / `qtm:s` / `qtm:sp` session handle.
Handle *qtmGetSessionHandle(void);
/**
* @brief Checks whether a head is fully detected.
* @param info Tracking info to check.
* @brief Gets the current raw eye tracking data, with an optional prediction made for predictionTimePointOrZero = t+dt,
* or for the current time point (QTM makes predictions based on gyro data since inner camera runs at 30 FPS).
*
* @param[out] outData Where to write the raw tracking data to. Cleared to all-zero on failure (instead of being left uninitialized).
* @param predictionTimePointOrZero Either zero, or the time point (in system ticks) for which to make a prediction for.
* Maximum 1 frame (at 30 FPS) in the past, and up to 5 frames in the future.
* @return `0xC8A18008` if camera is in use by user, or `0xC8A183EF` if QTM is unavailable (in particular, QTM is always
* unavailable on N2DSXL), Otherwise, 0 (success). Return value should be checked by caller.
* @note Consider using \ref QTMU_GetTrackingDataEx instead.
*/
bool qtmCheckHeadFullyDetected(QTM_HeadTrackingInfo *info);
Result QTMU_GetRawTrackingDataEx(QtmRawTrackingData *outData, s64 predictionTimePointOrZero);
/**
* @brief Converts QTM coordinates to screen coordinates.
* @param coord Coordinates to convert.
* @param screen_width Width of the screen. Can be NULL to use the default value for the top screen.
* @param screen_height Height of the screen. Can be NULL to use the default value for the top screen.
* @param x Pointer to output the screen X coordinate to.
* @param y Pointer to output the screen Y coordinate to.
* @brief Gets the current raw eye tracking data.
*
* @param[out] outData Where to write the raw tracking data to. Cleared to all-zero on failure (instead of being left uninitialized).
* @return `0xC8A18008` if camera is in use by user, or `0xC8A183EF` if QTM is unavailable (in particular, QTM is always
* unavailable on N2DSXL), Otherwise, 0 (success). Return value should be checked by caller.
* @note Consider using \ref QTMU_GetTrackingData instead.
*/
Result qtmConvertCoordToScreen(QTM_HeadTrackingInfoCoord *coord, float *screen_width, float *screen_height, u32 *x, u32 *y);
static inline Result QTMU_GetRawTrackingData(QtmRawTrackingData *outData)
{
return QTMU_GetRawTrackingDataEx(outData, 0LL);
}
/**
* @brief Gets the current head tracking info.
* @param val Normally 0.
* @param out Pointer to write head tracking info to.
* @brief Gets the current normalized eye tracking data, made suitable for 3D programming with an optional prediction made
* for predictionTimePointOrZero = t+dt, or for the current time point (QTM makes predictions based on gyro data since
* inner camera runs at 30 FPS).
*
* @param[out] outData Where to write the raw tracking data to. Cleared to all-zero on failure (instead of being left uninitialized).
* @param predictionTimePointOrZero Either zero, or the time point (in system ticks) for which to make a prediction for.
* Maximum 1 frame (at 30 FPS) in the past, and up to 5 frames in the future.
* @return `0xC8A18008` if camera is in use by user, or `0xC8A183EF` if QTM is unavailable (in particular, QTM is always
* unavailable on N2DSXL). Otherwise, 0 (success). Return value should be checked by caller.
* @note This can, for example, be used in games to allow the user to control the scene's camera with their own face.
*/
Result QTM_GetHeadTrackingInfo(u64 val, QTM_HeadTrackingInfo* out);
Result QTMU_GetTrackingDataEx(QtmTrackingData *outData, s64 predictionTimePointOrZero);
/**
* @brief Gets the current normalized eye tracking data, made suitable for 3D programming.
*
* @param[out] outData Where to write the raw tracking data to. Cleared to all-zero on failure (instead of being left uninitialized).
* @return `0xC8A18008` if camera is in use by user, or `0xC8A183EF` if QTM is unavailable (in particular, QTM is always
* unavailable on N2DSXL). Otherwise, 0 (success). Return value should be checked by caller.
* @note This can, for example, be used in games to allow the user to control the scene's camera with their own face.
*/
static inline Result QTMU_GetTrackingData(QtmTrackingData *outData)
{
return QTMU_GetTrackingDataEx(outData, 0LL);
}
/**
* @brief Computes an approximation of the horizontal angular field of view of the camera based on eye tracking data.
*
* @param data Eye tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
* @return Horizontal angular field of view in radians. Corresponds to 64.9 degrees on real hardware.
*/
float qtmComputeFovX(const QtmTrackingData *data);
/**
* @brief Computes an approximation of the vertical angular field of view of the camera based on eye tracking data.
*
* @param data Eye tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
* @return Vertical angular field of view in radians. Corresponds to 51.0 degrees on real hardware.
*/
float qtmComputeFovY(const QtmTrackingData *data);
/**
* @brief Computes a rough approximation of the inverse of the aspect ration of the camera based on eye tracking data.
*
* @param data Eye tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
* @return Rough approximation of the inverse of the aspect ratio of the camera. Aspect ratio is exactly 0.75 on real hardware.
*/
float qtmComputeInverseAspectRatio(const QtmTrackingData *data);
/**
* @brief Computes the user's head tilt angle, that is, the angle between the line through both eyes and the camera's
* horizontal axis in camera space.
*
* @param data Eye tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
* @return Horizontal head angle relative to camera, in radians.
*/
float qtmComputeHeadTiltAngle(const QtmTrackingData *data);
/**
* @brief Estimates the distance between the user's eyes and the camera, based on
* eye tracking data. This may be a little bit inaccurate, as this assumes
* interocular distance of 62mm (like all 3DS software does), and that both
* eyes are at the same distance from the screen.
*
* @param data Eye tracking data, obtained from \ref QTMU_GetTrackingData or \ref QTMU_GetTrackingDataEx.
* @return Eye-to-camera distance in millimeters.
*/
float qtmEstimateEyeToCameraDistance(const QtmTrackingData *data);
/**
* @brief Temporarily enables manual control of the IR LED by user, disabling its automatic control.
* If not already done, this also turns off the IR LED. This setting is cleared when user closes the console's shell.
* @return Always 0 (success).
*/
Result QTMU_EnableManualIrLedControl(void);
/**
* @brief Temporarily disables manual control of the IR LED by user, re-enabling its automatic control.
* If not already done, this also turns off the IR LED.
* @return Always 0 (success).
*/
Result QTMU_DisableManualIrLedControl(void);
/**
* @brief Turns the IR LED on or off during manual control. \ref QTMU_EnableManualIrLedControl must have been called.
*
* @param on Whether to turn the IR LED on or off.
* @return `0xC8A18005` if manual control was not enabled or if the operation failed, `0xC8A18008` if camera is in use
* by user, or `0xC8A18009` if QTM is unavailable (in particular, QTM is always unavailable on N2DSXL).
* Otherwise, 0 (success).
*/
Result QTMU_SetIrLedStatus(bool on);
/**
* @brief Attempts to clear IR LED overrides from any of the relevant commands in `qtm:u`, `qtm:s` (and `qtm:c`) commands
* by calling \ref QTMU_EnableManualIrLedControl followed by \ref QTMU_DisableManualIrLedControl, so that auto IR LED
* management takes place again.
* @return The value returned by \ref QTMU_DisableManualIrLedControl.
*/
Result qtmClearIrLedOverrides(void);
/**
* @brief Checks whether or not QTM has been blacklisted, ie. that it has been made unavailable.
* In detail, this means that the last call to \ref QTMS_SetQtmStatus was made with argument \ref QTM_STATUS_UNAVAILABLE,
* usually by NS. This feature seems to only be used for some internal test titles.
*
* @param[out] outBlacklisted Whether or not QTM is unavailable. Always true on N2DSXL.
* @return Always 0 (success).
* @note On N2DSXL, even though status is always supposed to be \ref QTM_STATUS_UNAVAILABLE, this function often returns true
* (because NS doesn't change QTM's status if title isn't blacklisted). Do not rely on this for N2DSXL detection.
* @note Refer to https://www.3dbrew.org/wiki/NS_CFA for a list of title UIDs this is used for.
*/
Result QTMU_IsCurrentAppBlacklisted(bool *outBlacklisted);
/**
* @brief Sets the neutral (center) barrier position/offset in calibration, _without_ saving it to `cfg`.
* Takes effect immediately. SS3D works by calculating the position of the eye midpoint, rotated
* by the ideal eye-to-camera angle, expressed in (iod/12 units, iod assumed to be 62mm).
*
* @param position Center barrier position, in terms of iod/12 units modulo iod/12.
* @note This field is floating-point for QTM auto-adjustment purposes, however the actual barrier position
* in hardware is an integer.
* @note This is the field that System Settings lets you add -1.0 to +1.0 to.
* @note There is no "get" counterpart for this.
* @return `0xC8A18009` if QTM is unavailable (in particular, QTM is always unavailable on N2DSXL), otherwise
0 (success).
*/
Result QTMS_SetCenterBarrierPosition(float position);
/**
* @brief Gets the average ambient luminance as perceived by the inner camera (in lux).
* If QTM is unavailable (in particular, QTM is always unavailable on N2DSXL), returns 400.0 instead
* of the actual luminance.
*
* @param[out] outLuminanceLux Where to write the luminance to. Always 400.0 on N2DSXL.
* @note Camera exposure, and in particular auto-exposure affects the returned luminance value. This must be
* taken into consideration, because this value can thus surge when user covers the inner camera.
* @return Always 0 (success).
*/
Result QTMS_GetCameraLuminance(float *outLuminanceLux);
/**
* @brief Enables automatic barrier control when in 3D mode with "super stable 3D" enabled.
*
* @note This is automatically called upon `qtm:s` and `qtm:sp` session exit.
* @return `0xC8A18009` if QTM is unavailable (in particular, QTM is always unavailable on N2DSXL), otherwise
0 (success).
* @note Due to an oversight, \ref QTMS_SetQtmStatus allows changing QTM state on N2DSXL. This is not intended
* to be done, and is in fact never done by official software. If that is regardless the case,
* this function here does nothing.
*/
Result QTMS_EnableAutoBarrierControl(void);
/**
* @brief Temporarily disables automatic barrier control (when in 3D mode with "super stable 3D" enabled).
*
* @note This is automatically called upon `qtm:s` and `qtm:sp` session exit.
* @return `0xC8A18009` if QTM is unavailable (in particular, QTM is always unavailable on N2DSXL), otherwise
0 (success).
* @note Due to an oversight, \ref QTMS_SetQtmStatus allows changing QTM state on N2DSXL. This is not intended
* to be done, and is in fact never done by official software. If that is regardless the case,
* this function here does nothing.
*/
Result QTMS_DisableAutoBarrierControl(void);
/**
* @brief Temporarily sets the parallax barrier's position (offset in iod/12 units, assuming slit width of 6 units).
* Does nothing in 2D mode and/or if "super stable 3D" is disabled.
*
* @param position Parallax barrier position (offset in units), must be between 0 and 11 (both included)
* @return `0xC8A18009` if QTM is unavailable (in particular, QTM is always unavailable on N2DSXL), 0xE0E18002
* if \p position is not in range, otherwise 0 (success).
* @note Due to an oversight, \ref QTMS_SetQtmStatus allows changing QTM state on N2DSXL. This is not intended
* to be done, and is in fact never done by official software. If that is regardless the case,
* this function here does nothing.
* @note No effect when the screen is in 2D mode.
* @see QTMC_SetBarrierPattern
*/
Result QTMS_SetBarrierPosition(u8 position);
/**
* @brief Gets the current position of the parallax barrier (offset in iod/12 units, slit width of 6 units).
* When "super stable 3D" is disabled, returns 13 instead.
*
* @param[out] outPosition Where to write the barrier's position to.
* @return `0xC8A18009` if QTM is unavailable (in particular, QTM is always unavailable on N2DSXL), otherwise
0 (success).
* @note When SS3D is disabled, this returns 13 to \p outPosition . When in 2D mode, the returned position is not
updated.
* @note Due to an oversight, \ref QTMS_SetQtmStatus allows changing QTM state on N2DSXL. This is not intended
* to be done, and is in fact never done by official software. If that is regardless the case,
* this function here returns 13 to \p outPosition .
* @see QTMC_SetBarrierPattern
*/
Result QTMS_GetCurrentBarrierPosition(u8 *outPosition);
/**
* @brief Temporarily overrides IR LED state. Requires "manual control" from `qtm:u` to be disabled, and has
* lower priority than it.
*
* @param on Whether to turn the IR LED on or off.
* @return `0xC8A18005` if manual control was enabled or if the operation failed, `0xC8A18008` if camera is in use
* by user (unless "hardware check" API enabled), or `0xC8A18009` if QTM is unavailable (in particular,
* QTM is always unavailable on N2DSXL). Otherwise, 0 (success).
*/
Result QTMS_SetIrLedStatusOverride(bool on);
/**
* @brief Sets calibration data, taking effect immediately, and optionally saves it to `cfg`.
*
* @param cal Pointer to calibration data.
* @param saveCalToCfg Whether or not to persist the calibration data in `cfg`.
* @return `0xC8A18009` if QTM is unavailable (in particular, QTM is always unavailable on N2DSXL), otherwise
whatever `cfg:s` commands return (if used), or 0 (success).
* @note There is no "get" counterpart for this function, and there is no way to see the current calibration data
in use unless it has been saved to `cfg`.
* @note Due to an oversight, \ref QTMS_SetQtmStatus allows changing QTM state on N2DSXL. This is not intended
* to be done, and is in fact never done by official software. If that is regardless the case,
* this function here doesn't apply calibrations parameters (they may still be saved, however,
* even though QTM calibration blocks are always normally 0 on N2DSXL).
*/
Result QTMS_SetCalibrationData(const QtmCalibrationData *cal, bool saveCalToCfg);
/**
* @brief Gets the current QTM status (enabled/ss3d disabled/unavailable).
*
* @param[out] outQtmStatus Where to write the QTM status to.
* @return Always 0.
*/
Result QTMS_GetQtmStatus(QtmStatus *outQtmStatus);
/**
* @brief Gets the current QTM status (enabled/ss3d disabled/unavailable). Also sets or clear the
* "blacklisted" flag returned by \ref QTMU_IsCurrentAppBlacklisted.
*
* @param qtmStatus QTM status to set. If equal to \ref QTM_STATUS_UNAVAILABLE, sets the "blacklisted" flag,
* otherwise clears it.
* @return `0xE0E18002` if enum value is invalid, otherwise 0 (success).
* @note System settings uses this to disable super-stable 3D, and NS to "blacklist" (make QTM unavailable)
* specific applications.
*/
Result QTMS_SetQtmStatus(QtmStatus qtmStatus);
/**
* @brief Called by GSP's LCD driver to signal 2D<>3D mode change
* @param newMode 0 for 2D, 1 for 800px 2D (unused for this function, same as 0), 2 for 3D
* @return Always 0 (success).
*/
Result QTMSP_NotifyTopLcdModeChange(u8 newMode);
/**
* @brief Called by GSP's LCD driver during top LCD power-on to signal to QTM that it may power on
* and/or reconfigure then use the TI TCA6416A expander. In the process, QTM re-creates its
* expander thread.
* @return Always 0 (success).
*/
Result QTMSP_NotifyTopLcdPowerOn(void);
/**
* @brief Called by GSP's LCD driver to know whether or not QTM's expander thread is using
* the TI TCA6416A expander; it is waiting for this to become true/false during LCD
* power on/power off to proceed. Always false on N2DSXL.
* @param[out] outActive Where to write the "in use" status to.
* @return Always 0 (success).
*/
Result QTMSP_IsExpanderInUse(bool *outActive);
/**
* @brief Called by GSP's LCD driver during top LCD power-on to signal to QTM that it needs to
* switch the parallax barrier state to a 2D state (all-transparent mask). Causes QTM's
* expander thread to exit, relinquishing its `i2c::QTM` session with it.
* @return Always 0 (success).
*/
Result QTMSP_NotifyTopLcdPowerOff(void);

View File

@ -0,0 +1,117 @@
/**
* @file qtmc.h
* @brief QTM Hardware Check service.
*
* Allows direct control over the parallax barrier's pattern and polarity phase through the
* TI TCA6416A I2C->Parallel expander, as well as control over IR LED state even when camera
* is used by user.
*
* TI TCA6416A I2C->Parallel expander is located on bus I2C1 (PA 0x10161000) device ID 0x40.
*
* The top screen parallax barrier was covered by patent US20030234980A1.
*/
#pragma once
#include <3ds/types.h>
/**
* @brief Initializes `qtm:c`.
* Only 3 sessions (2 until 9.3.0 sysupdate) for ALL services COMBINED, including the main
* services, can be open at a time.
*/
Result qtmcInit(void);
/// Exits `qtm:c`.
void qtmcExit(void);
/// Returns a pointer to the current `qtm:c` session handle.
Handle *qtmcGetSessionHandle(void);
/**
* @brief Starts the QTM Hardware Check API. This must be called before using any other `qtm:c` command,
* and causes barrier pattern to be overriden by what was last set in \ref QTMC_SetBarrierPattern,
* **even in 2D mode**. Also allows IR LED state to be overridden even if user uses the inner camera.
* @return `0xD82183F9` if already started, otherwise 0 (success).
*/
Result QTMC_StartHardwareCheck(void);
/**
* @brief Stops the QTM Hardware Check API. Restore normal barrier and IR LED management behavior.
* @return `0xD82183F8` if API not started, otherwise 0 (success).
*/
Result QTMC_StopHardwareCheck(void);
/**
* @brief Sets the parallax barrier's mask pattern and polarity phase (12+1 bits).
*
* Bit11 to 0 correspond to a repeating barrier mask pattern, 0 meaning the corresponding mask unit is
* transparent and 1 that it is opaque. The direction is: left->right corresponds to MSB->LSB.
*
* Bit12 is the polarity bit.
*
* QTM's expander management thread repeatedly writes (on every loop iteration) the current mask pattern
* plus polarity bit, whether it is normally set or overridden by `qtm:c`, then on the following set,
* negates both (it writes pattern ^ 0x1FFF). This is done at all times, even it 2D mode.
*
* The register being written to are regId 0x02 and 0x03 (output ports).
* TI TCA6416A I2C->Parallel expander is located on bus I2C1 (PA 0x10161000) device ID 0x40.
*
* This function has no effect on N2DSXL.
*
* @param pattern Barrier mask pattern (bit12: polarity, bit11-0: 12-bit mask pattern)
* @return `0xD82183F8` if API not started, otherwise 0 (success).
* @see Patent US20030234980A1 for a description of parallax barriers.
* @example The mask pattern used for super-stable 3D are as follows (position 0 to 11):
*
* 000011111100
* 000001111110
* 000000111111
* 100000011111
* 110000001111
* 111000000111
* 111100000011
* 111110000001
* 111111000000
* 011111100000
* 001111110000
* 000111111000
*
* When SS3D is disabled (ie. it tries to match O3DS behavior), then pattern becomes:
* 111100000111
* Notice that the slit width is reduced from 6 to 5 units there.
*
* For 2D it is all-zero:
* 000000000000
*
* 2D pattern is automatically set on QTM process init and exit.
*/
Result QTMC_SetBarrierPattern(u32 pattern);
/**
* @brief Waits for the expander management thread to (re)initalize the TI TCA6416A I2C->Parallel expander,
* then checks if that expander is behaving as expected (responds with the port direction config
* it has been configured with): it checks whether all ports have been configured as outputs.
*
* On N2DSXL, this function waits forever and never returns.
*
* In detail, the hardware init procedure for the expander is as follows (as done by the expander mgmt. thread):
* - configure enable expander pin on SoC: set GPIO3.bit11 to OUTPUT, then set to 1
* - on the expander (I2C1 deviceId 0x40), set all ports to OUTPUT (regId 0x06, 0x07)
* - on the expander, write 0 (all-transparent mask/2D) to the data registers (regId 0x02, 0x03)
*
* @param[out] outWorking Where to write the working status to. If true, expander is present working.
* If false, the expander is present but is misbehaving. If the function does not
* return, then expander is missing (e.g. on N2DSXL).
* @return `0xD82183F8` if API not started, otherwise 0 (success).
*/
Result QTMC_WaitAndCheckExpanderWorking(bool *outWorking);
/**
* @brief Temporarily overrides IR LED state. Requires "manual control" from `qtm:u` to be disabled, and has
* lower priority than it. Same implementation as \ref QTMS_SetIrLedStatusOverride.
*
* @param on Whether to turn the IR LED on or off.
* @return `0xD82183F8` if API not started, `0xC8A18005` if manual control was enabled or if the operation failed,
* or `0xC8A18009` if QTM is unavailable (in particular, QTM is always unavailable on N2DSXL). Otherwise, 0 (success).
*/
Result QTMC_SetIrLedStatusOverride(bool on);

View File

@ -16,7 +16,7 @@ typedef enum
{
NETOPT_MAC_ADDRESS = 0x1004, ///< The mac address of the interface (u32 mac[6])
NETOPT_ARP_TABLE = 0x3002, ///< The ARP table @see SOCU_ARPTableEntry
NETOPT_IP_INFO = 0x4003, ///< The cureent IP setup @see SOCU_IPInfo
NETOPT_IP_INFO = 0x4003, ///< The current IP setup @see SOCU_IPInfo
NETOPT_IP_MTU = 0x4004, ///< The value of the IP MTU (u32)
NETOPT_ROUTING_TABLE = 0x4006, ///< The routing table @see SOCU_RoutingTableEntry
NETOPT_UDP_NUMBER = 0x8002, ///< The number of sockets in the UDP table (u32)
@ -120,9 +120,9 @@ long gethostid(void);
// this is supposed to be in unistd.h but newlib only puts it for cygwin, waiting for newlib patch from dkA
int gethostname(char *name, size_t namelen);
int SOCU_ShutdownSockets();
int SOCU_ShutdownSockets(void);
int SOCU_CloseSockets();
int SOCU_CloseSockets(void);
/**
* @brief Retrieves information from the network configuration. Similar to getsockopt().

View File

@ -4,12 +4,18 @@
*/
#pragma once
/// Initializes srv:pm.
/// Initializes srv:pm and the service API.
Result srvPmInit(void);
/// Exits srv:pm.
/// Exits srv:pm and the service API.
void srvPmExit(void);
/**
* @brief Gets the current srv:pm session handle.
* @return The current srv:pm session handle.
*/
Handle *srvPmGetSessionHandle(void);
/**
* @brief Publishes a notification to a process.
* @param notificationId ID of the notification.
@ -25,15 +31,15 @@ Result SRVPM_PublishToAll(u32 notificationId);
/**
* @brief Registers a process with SRV.
* @param procid ID of the process.
* @param pid ID of the process.
* @param count Number of services within the service access control data.
* @param serviceaccesscontrol Service Access Control list.
* @param serviceAccessControlList Service Access Control list.
*/
Result SRVPM_RegisterProcess(u32 procid, u32 count, void* serviceaccesscontrol);
Result SRVPM_RegisterProcess(u32 pid, u32 count, const char (*serviceAccessControlList)[8]);
/**
* @brief Unregisters a process with SRV.
* @param procid ID of the process.
* @param pid ID of the process.
*/
Result SRVPM_UnregisterProcess(u32 procid);
Result SRVPM_UnregisterProcess(u32 pid);

View File

@ -323,7 +323,7 @@ Result udsEjectClient(u16 NetworkNodeID);
/**
* @brief This can be used by the host to force-disconnect the spectators. Afterwards new spectators will not be allowed to connect until udsAllowSpectators() is used.
*/
Result udsEjectSpectator();
Result udsEjectSpectator(void);
/**
* @brief This can be used by the host to update the network attributes. If bitmask 0x4 is clear in the input bitmask, this clears that bit in the value before actually writing the value into state. Normally you should use the below wrapper functions.

View File

@ -10,6 +10,14 @@ Result srvInit(void);
/// Exits the service API.
void srvExit(void);
/**
* @brief Makes srvGetServiceHandle non-blocking for the current thread (or blocking, the default), in case of unavailable (full) requested services.
* @param blocking Whether srvGetServiceHandle should be non-blocking.
* srvGetServiceHandle will always block if the service hasn't been registered yet,
* use srvIsServiceRegistered to check whether that is the case or not.
*/
void srvSetBlockingPolicy(bool nonBlocking);
/**
* @brief Gets the current service API session handle.
* @return The current service API session handle.
@ -20,6 +28,9 @@ Handle *srvGetSessionHandle(void);
* @brief Retrieves a service handle, retrieving from the environment handle list if possible.
* @param out Pointer to write the handle to.
* @param name Name of the service.
* @return 0 if no error occured,
* 0xD8E06406 if the caller has no right to access the service,
* 0xD0401834 if the requested service port is full and srvGetServiceHandle is non-blocking (see @ref srvSetBlockingPolicy).
*/
Result srvGetServiceHandle(Handle* out, const char* name);
@ -50,6 +61,9 @@ Result srvUnregisterService(const char* name);
* @brief Retrieves a service handle.
* @param out Pointer to output the handle to.
* @param name Name of the service.
* * @return 0 if no error occured,
* 0xD8E06406 if the caller has no right to access the service,
* 0xD0401834 if the requested service port is full and srvGetServiceHandle is non-blocking (see @ref srvSetBlockingPolicy).
*/
Result srvGetServiceHandleDirect(Handle* out, const char* name);
@ -73,6 +87,12 @@ Result srvUnregisterPort(const char* name);
*/
Result srvGetPort(Handle* out, const char* name);
/**
* @brief Waits for a port to be registered.
* @param name Name of the port to wait for registration.
*/
Result srvWaitForPortRegistered(const char* name);
/**
* @brief Subscribes to a notification.
* @param notificationId ID of the notification.
@ -94,7 +114,7 @@ Result srvReceiveNotification(u32* notificationIdOut);
/**
* @brief Publishes a notification to subscribers.
* @param notificationId ID of the notification.
* @param flags Flags to publish with. (bit 0 = only fire if not fired, bit 1 = report errors)
* @param flags Flags to publish with. (bit 0 = only fire if not fired, bit 1 = do not report an error if there are more than 16 pending notifications)
*/
Result srvPublishToSubscriber(u32 notificationId, u32 flags);
@ -112,3 +132,10 @@ Result srvPublishAndGetSubscriber(u32* processIdCountOut, u32* processIdsOut, u3
* @param name Name of the service to check.
*/
Result srvIsServiceRegistered(bool* registeredOut, const char* name);
/**
* @brief Checks whether a port is registered.
* @param registeredOut Pointer to output the registration status to.
* @param name Name of the port to check.
*/
Result srvIsPortRegistered(bool* registeredOut, const char* name);

View File

@ -57,20 +57,31 @@ typedef enum {
MEMPERM_READ = 1, ///< Readable
MEMPERM_WRITE = 2, ///< Writable
MEMPERM_EXECUTE = 4, ///< Executable
MEMPERM_READWRITE = MEMPERM_READ | MEMPERM_WRITE, ///< Readable and writable
MEMPERM_READEXECUTE = MEMPERM_READ | MEMPERM_EXECUTE, ///< Readable and executable
MEMPERM_DONTCARE = 0x10000000, ///< Don't care
} MemPerm;
/// Memory regions.
typedef enum
{
MEMREGION_ALL = 0, ///< All regions.
MEMREGION_APPLICATION = 1, ///< APPLICATION memory.
MEMREGION_SYSTEM = 2, ///< SYSTEM memory.
MEMREGION_BASE = 3, ///< BASE memory.
} MemRegion;
/// Memory information.
typedef struct {
u32 base_addr; ///< Base address.
u32 size; ///< Size.
u32 perm; ///< Memory permissions. See @ref MemPerm
u32 state; ///< Memory state. See @ref MemState
u32 base_addr; ///< Base address.
u32 size; ///< Size.
u32 perm; ///< Memory permissions. See @ref MemPerm
u32 state; ///< Memory state. See @ref MemState
} MemInfo;
/// Memory page information.
typedef struct {
u32 flags; ///< Page flags.
u32 flags; ///< Page flags.
} PageInfo;
/// Arbitration modes.
@ -102,15 +113,181 @@ typedef enum {
THREADINFO_TYPE_UNKNOWN ///< Unknown.
} ThreadInfoType;
/// Types of resource limit
typedef enum {
RESLIMIT_PRIORITY = 0, ///< Thread priority
RESLIMIT_COMMIT = 1, ///< Quantity of allocatable memory
RESLIMIT_THREAD = 2, ///< Number of threads
RESLIMIT_EVENT = 3, ///< Number of events
RESLIMIT_MUTEX = 4, ///< Number of mutexes
RESLIMIT_SEMAPHORE = 5, ///< Number of semaphores
RESLIMIT_TIMER = 6, ///< Number of timers
RESLIMIT_SHAREDMEMORY = 7, ///< Number of shared memory objects, see @ref svcCreateMemoryBlock
RESLIMIT_ADDRESSARBITER = 8, ///< Number of address arbiters
RESLIMIT_CPUTIME = 9, ///< CPU time. Value expressed in percentage regular until it reaches 90.
RESLIMIT_BIT = BIT(31), ///< Forces enum size to be 32 bits
} ResourceLimitType;
/// Pseudo handle for the current thread
#define CUR_THREAD_HANDLE 0xFFFF8000
///@}
///@name Device drivers
///@{
/// DMA transfer state.
typedef enum {
DMASTATE_STARTING = 0, ///< DMA transfer involving at least one device is starting and has not reached DMAWFP yet.
DMASTATE_WFP_DST = 1, ///< DMA channel is in WFP state for the destination device (2nd loop iteration onwards).
DMASTATE_WFP_SRC = 2, ///< DMA channel is in WFP state for the source device (2nd loop iteration onwards).
DMASTATE_RUNNING = 3, ///< DMA transfer is running.
DMASTATE_DONE = 4, ///< DMA transfer is done.
} DmaState;
/// Configuration flags for \ref DmaConfig.
enum {
DMACFG_SRC_IS_DEVICE = BIT(0), ///< DMA source is a device/peripheral. Address will not auto-increment.
DMACFG_DST_IS_DEVICE = BIT(1), ///< DMA destination is a device/peripheral. Address will not auto-increment.
DMACFG_WAIT_AVAILABLE = BIT(2), ///< Make \ref svcStartInterProcessDma wait for the channel to be unlocked.
DMACFG_KEEP_LOCKED = BIT(3), ///< Keep the channel locked after the transfer. Required for \ref svcRestartDma.
DMACFG_USE_SRC_CONFIG = BIT(6), ///< Use the provided source device configuration even if the DMA source is not a device.
DMACFG_USE_DST_CONFIG = BIT(7), ///< Use the provided destination device configuration even if the DMA destination is not a device.
};
/// Configuration flags for \ref svcRestartDma.
enum {
DMARST_UNLOCK = BIT(0), ///< Unlock the channel after transfer.
DMARST_RESUME_DEVICE = BIT(1), ///< Replace DMAFLUSHP instructions by NOP (they may not be regenerated even if this flag is not set).
};
/**
* @brief Device configuration structure, part of \ref DmaConfig.
* @note
* - if (and only if) src/dst is a device, then src/dst won't be auto-incremented.
* - the kernel uses DMAMOV instead of DMAADNH, when having to decrement (possibly working around an erratum);
* this forces all loops to be unrolled -- you need to keep that in mind when using negative increments, as the kernel
* uses a limit of 100 DMA instruction bytes per channel.
*/
typedef struct {
s8 deviceId; ///< DMA device ID.
s8 allowedAlignments; ///< Mask of allowed access alignments (8, 4, 2, 1).
s16 burstSize; ///< Number of bytes transferred in a burst loop. Can be 0 (in which case the max allowed alignment is used as unit).
s16 transferSize; ///< Number of bytes transferred in a "transfer" loop (made of burst loops).
s16 burstStride; ///< Burst loop stride, can be <= 0.
s16 transferStride; ///< "Transfer" loop stride, can be <= 0.
} DmaDeviceConfig;
/// Configuration stucture for \ref svcStartInterProcessDma.
typedef struct {
s8 channelId; ///< Channel ID (Arm11: 0-7, Arm9: 0-1). Use -1 to auto-assign to a free channel (Arm11: 3-7, Arm9: 0-1).
s8 endianSwapSize; ///< Endian swap size (can be 0).
u8 flags; ///< DMACFG_* flags.
u8 _padding;
DmaDeviceConfig srcCfg; ///< Source device configuration, read if \ref DMACFG_SRC_IS_DEVICE and/or \ref DMACFG_USE_SRC_CONFIG are set.
DmaDeviceConfig dstCfg; ///< Destination device configuration, read if \ref DMACFG_SRC_IS_DEVICE and/or \ref DMACFG_USE_SRC_CONFIG are set.
} DmaConfig;
///@}
///@name Debugging
///@{
/// Operations for \ref svcControlPerformanceCounter
typedef enum {
PERFCOUNTEROP_ENABLE = 0, ///< Enable and lock perfmon. functionality.
PERFCOUNTEROP_DISABLE = 1, ///< Disable and forcibly unlock perfmon. functionality.
PERFCOUNTEROP_GET_VALUE = 2, ///< Get the value of a counter register.
PERFCOUNTEROP_SET_VALUE = 3, ///< Set the value of a counter register.
PERFCOUNTEROP_GET_OVERFLOW_FLAGS = 4, ///< Get the overflow flags for all CP15 and SCU counters.
PERFCOUNTEROP_RESET = 5, ///< Reset the value and/or overflow flags of selected counters.
PERFCOUNTEROP_GET_EVENT = 6, ///< Get the event ID associated to a particular counter.
PERFCOUNTEROP_SET_EVENT = 7, ///< Set the event ID associated to a paritcular counter.
PERFCOUNTEROP_SET_VIRTUAL_COUNTER_ENABLED = 8, ///< (Dis)allow the kernel to track counter overflows and to use 64-bit counter values.
} PerfCounterOperation;
/// Performance counter register IDs (CP15 and SCU).
typedef enum
{
// CP15 registers:
PERFCOUNTERREG_CORE_BASE = 0,
PERFCOUNTERREG_CORE_COUNT_REG_0 = PERFCOUNTERREG_CORE_BASE, ///< CP15 PMN0.
PERFCOUNTERREG_CORE_COUNT_REG_1, ///< CP15 PMN1.
PERFCOUNTERREG_CORE_CYCLE_COUNTER, ///< CP15 CCNT.
// SCU registers
PERFCOUNTERREG_SCU_BASE = 0x10,
PERFCOUNTERREG_SCU_0 = PERFCOUNTERREG_SCU_BASE, ///< SCU MN0.
PERFCOUNTERREG_SCU_1, ///< SCU MN1.
PERFCOUNTERREG_SCU_2, ///< SCU MN2.
PERFCOUNTERREG_SCU_3, ///< SCU MN3.
PERFCOUNTERREG_SCU_4, ///< SCU MN4. Prod-N3DS only. IRQ line missing.
PERFCOUNTERREG_SCU_5, ///< SCU MN5. Prod-N3DS only. IRQ line missing.
PERFCOUNTERREG_SCU_6, ///< SCU MN6. Prod-N3DS only. IRQ line missing.
PERFCOUNTERREG_SCU_7, ///< SCU MN7. Prod-N3DS only. IRQ line missing.
} PerfCounterRegister;
/**
* @brief Performance counter event IDs (CP15 or SCU).
*
* @note Refer to:
* - CP15: https://developer.arm.com/documentation/ddi0360/e/control-coprocessor-cp15/register-descriptions/c15--performance-monitor-control-register--pmnc-
* - SCU: https://developer.arm.com/documentation/ddi0360/e/mpcore-private-memory-region/about-the-mpcore-private-memory-region/performance-monitor-event-registers
*/
typedef enum
{
// Core events:
PERFCOUNTEREVT_CORE_BASE = 0x0,
PERFCOUNTEREVT_CORE_INST_CACHE_MISS = PERFCOUNTEREVT_CORE_BASE,
PERFCOUNTEREVT_CORE_STALL_BY_LACK_OF_INST,
PERFCOUNTEREVT_CORE_STALL_BY_DATA_HAZARD,
PERFCOUNTEREVT_CORE_INST_MICRO_TLB_MISS,
PERFCOUNTEREVT_CORE_DATA_MICRO_TLB_MISS,
PERFCOUNTEREVT_CORE_BRANCH_INST,
PERFCOUNTEREVT_CORE_BRANCH_NOT_PREDICTED,
PERFCOUNTEREVT_CORE_BRANCH_MISS_PREDICTED,
PERFCOUNTEREVT_CORE_INST_EXECUTED,
PERFCOUNTEREVT_CORE_FOLDED_INST_EXECUTED,
PERFCOUNTEREVT_CORE_DATA_CACHE_READ,
PERFCOUNTEREVT_CORE_DATA_CACHE_READ_MISS,
PERFCOUNTEREVT_CORE_DATA_CACHE_WRITE,
PERFCOUNTEREVT_CORE_DATA_CACHE_WRITE_MISS,
PERFCOUNTEREVT_CORE_DATA_CACHE_LINE_EVICTION,
PERFCOUNTEREVT_CORE_PC_CHANGED,
PERFCOUNTEREVT_CORE_MAIN_TLB_MISS,
PERFCOUNTEREVT_CORE_EXTERNAL_REQUEST,
PERFCOUNTEREVT_CORE_STALL_BY_LSU_FULL,
PERFCOUNTEREVT_CORE_STORE_BUFFER_DRAIN,
PERFCOUNTEREVT_CORE_MERGE_IN_STORE_BUFFER,
PERFCOUNTEREVT_CORE_CYCLE_COUNT = PERFCOUNTEREVT_CORE_BASE + 0xFF, ///< One cycle elapsed.
PERFCOUNTEREVT_CORE_CYCLE_COUNT_64 = PERFCOUNTEREVT_CORE_BASE + 0xFFF, ///< 64 cycles elapsed.
PERFCOUNTEREVT_SCU_BASE = 0x1000,
PERFCOUNTEREVT_SCU_DISABLED = PERFCOUNTEREVT_SCU_BASE,
PERFCOUNTEREVT_SCU_LINEFILL_MISS_FROM_CORE0,
PERFCOUNTEREVT_SCU_LINEFILL_MISS_FROM_CORE1,
PERFCOUNTEREVT_SCU_LINEFILL_MISS_FROM_CORE2,
PERFCOUNTEREVT_SCU_LINEFILL_MISS_FROM_CORE3,
PERFCOUNTEREVT_SCU_LINEFILL_HIT_FROM_CORE0,
PERFCOUNTEREVT_SCU_LINEFILL_HIT_FROM_CORE1,
PERFCOUNTEREVT_SCU_LINEFILL_HIT_FROM_CORE2,
PERFCOUNTEREVT_SCU_LINEFILL_HIT_FROM_CORE3,
PERFCOUNTEREVT_SCU_LINE_MISSING_FROM_CORE0,
PERFCOUNTEREVT_SCU_LINE_MISSING_FROM_CORE1,
PERFCOUNTEREVT_SCU_LINE_MISSING_FROM_CORE2,
PERFCOUNTEREVT_SCU_LINE_MISSING_FROM_CORE3,
PERFCOUNTEREVT_SCU_LINE_MIGRATION,
PERFCOUNTEREVT_SCU_READ_BUSY_PORT0,
PERFCOUNTEREVT_SCU_READ_BUSY_PORT1,
PERFCOUNTEREVT_SCU_WRITE_BUSY_PORT0,
PERFCOUNTEREVT_SCU_WRITE_BUSY_PORT1,
PERFCOUNTEREVT_SCU_EXTERNAL_READ,
PERFCOUNTEREVT_SCU_EXTERNAL_WRITE,
PERFCOUNTEREVT_SCU_CYCLE_COUNT = PERFCOUNTEREVT_SCU_BASE + 0x1F,
} PerfCounterEvent;
/// Event relating to the attachment of a process.
typedef struct {
u64 program_id; ///< ID of the program.
@ -121,9 +298,9 @@ typedef struct {
/// Reasons for an exit process event.
typedef enum {
EXITPROCESS_EVENT_NONE = 0, ///< No reason.
EXITPROCESS_EVENT_TERMINATE = 1, ///< Process terminated.
EXITPROCESS_EVENT_UNHANDLED_EXCEPTION = 2, ///< Unhandled exception occurred.
EXITPROCESS_EVENT_EXIT = 0, ///< Process exited either normally or due to an uncaught exception.
EXITPROCESS_EVENT_TERMINATE = 1, ///< Process has been terminated by @ref svcTerminateProcess.
EXITPROCESS_EVENT_DEBUG_TERMINATE = 2, ///< Process has been terminated by @ref svcTerminateDebugProcess.
} ExitProcessEventReason;
/// Event relating to the exiting of a process.
@ -140,10 +317,10 @@ typedef struct {
/// Reasons for an exit thread event.
typedef enum {
EXITTHREAD_EVENT_NONE = 0, ///< No reason.
EXITTHREAD_EVENT_EXIT = 0, ///< Thread exited.
EXITTHREAD_EVENT_TERMINATE = 1, ///< Thread terminated.
EXITTHREAD_EVENT_UNHANDLED_EXC = 2, ///< Unhandled exception occurred.
EXITTHREAD_EVENT_TERMINATE_PROCESS = 3, ///< Process terminated.
EXITTHREAD_EVENT_EXIT_PROCESS = 2, ///< Process exited either normally or due to an uncaught exception.
EXITTHREAD_EVENT_TERMINATE_PROCESS = 3, ///< Process has been terminated by @ref svcTerminateProcess.
} ExitThreadEventReason;
/// Event relating to the exiting of a thread.
@ -200,7 +377,7 @@ typedef struct {
/// Event relating to @ref svcBreakDebugProcess
typedef struct {
void *threads[4]; ///< KThread instances of the attached process's that were running on each at the time of the function call (only the first 2 values are meaningful on O3DS).
s32 thread_ids[4]; ///< IDs of the attached process's threads that were running on each core at the time of the @ref svcBreakDebugProcess call, or -1 (only the first 2 values are meaningful on O3DS).
} DebuggerBreakExceptionEvent;
/// Event relating to exceptions.
@ -279,11 +456,11 @@ typedef struct {
/// Debug flags for an attached process, set by @ref svcContinueDebugEvent
typedef enum {
DBG_NO_ERRF_CPU_EXCEPTION_DUMPS = BIT(0), ///< Don't produce err:f-format dumps for CPU exceptions (including watchpoints and breakpoints, regardless of any @ref svcKernelSetState call).
DBG_SIGNAL_FAULT_EXCEPTION_EVENTS = BIT(1), ///< Signal fault exception events. See @ref FaultExceptionEvent.
DBG_SIGNAL_SCHEDULE_EVENTS = BIT(2), ///< Signal schedule in/out events. See @ref ScheduleInOutEvent.
DBG_SIGNAL_SYSCALL_EVENTS = BIT(3), ///< Signal syscall in/out events. See @ref SyscallInOutEvent.
DBG_SIGNAL_MAP_EVENTS = BIT(4), ///< Signal map events. See @ref MapEvent.
DBG_INHIBIT_USER_CPU_EXCEPTION_HANDLERS = BIT(0), ///< Inhibit user-defined CPU exception handlers (including watchpoints and breakpoints, regardless of any @ref svcKernelSetState call).
DBG_SIGNAL_FAULT_EXCEPTION_EVENTS = BIT(1), ///< Signal fault exception events. See @ref FaultExceptionEvent.
DBG_SIGNAL_SCHEDULE_EVENTS = BIT(2), ///< Signal schedule in/out events. See @ref ScheduleInOutEvent.
DBG_SIGNAL_SYSCALL_EVENTS = BIT(3), ///< Signal syscall in/out events. See @ref SyscallInOutEvent.
DBG_SIGNAL_MAP_EVENTS = BIT(4), ///< Signal map events. See @ref MapEvent.
} DebugFlags;
typedef struct {
@ -295,7 +472,7 @@ typedef struct {
typedef enum {
THREADCONTEXT_CONTROL_CPU_GPRS = BIT(0), ///< Control r0-r12.
THREADCONTEXT_CONTROL_CPU_SPRS = BIT(1), ///< Control sp, lr, pc, cpsr.
THREADCONTEXT_CONTROL_FPU_GPRS = BIT(2), ///< Control d0-d15 (or f0-f31).
THREADCONTEXT_CONTROL_FPU_GPRS = BIT(2), ///< Control d0-d15 (or s0-s31).
THREADCONTEXT_CONTROL_FPU_SPRS = BIT(3), ///< Control fpscr, fpexc.
THREADCONTEXT_CONTROL_CPU_REGS = BIT(0) | BIT(1), ///< Control r0-r12, sp, lr, pc, cpsr.
@ -320,9 +497,8 @@ typedef enum {
/// Information on address space for process. All sizes are in pages (0x1000 bytes)
typedef struct {
u8 name[8]; ///< ASCII name of codeset
u16 unk1;
u16 unk2;
u32 unk3;
u16 version; ///< Version field of codeset (unused)
u16 padding[3]; ///< Padding
u32 text_addr; ///< .text start address
u32 text_size; ///< .text number of pages
u32 ro_addr; ///< .rodata start address
@ -332,9 +508,9 @@ typedef struct {
u32 text_size_total; ///< total pages for .text (aligned)
u32 ro_size_total; ///< total pages for .rodata (aligned)
u32 rw_size_total; ///< total pages for .data, .bss (aligned)
u32 unk4;
u32 padding2; ///< Padding
u64 program_id; ///< Program ID
} CodeSetInfo;
} CodeSetHeader;
/// Information for the main thread of a process.
typedef struct
@ -350,7 +526,7 @@ typedef struct
/**
* @brief Gets the thread local storage buffer.
* @return The thread local storage bufger.
* @return The thread local storage buffer.
*/
static inline void* getThreadLocalStorage(void)
{
@ -361,7 +537,7 @@ static inline void* getThreadLocalStorage(void)
/**
* @brief Gets the thread command buffer.
* @return The thread command bufger.
* @return The thread command buffer.
*/
static inline u32* getThreadCommandBuffer(void)
{
@ -370,13 +546,45 @@ static inline u32* getThreadCommandBuffer(void)
/**
* @brief Gets the thread static buffer.
* @return The thread static bufger.
* @return The thread static buffer.
*/
static inline u32* getThreadStaticBuffers(void)
{
return (u32*)((u8*)getThreadLocalStorage() + 0x180);
}
///@name Device drivers
///@{
/// Writes the default DMA device config that the kernel uses when DMACFG_*_IS_DEVICE and DMACFG_*_USE_CFG are not set
static inline void dmaDeviceConfigInitDefault(DmaDeviceConfig *cfg)
{
// Kernel uses this default instance if _IS_DEVICE and _USE_CFG are not set
*cfg = (DmaDeviceConfig) {
.deviceId = -1,
.allowedAlignments = 8 | 4 | 2 | 1,
.burstSize = 0x80,
.transferSize = 0,
.burstStride = 0x80,
.transferStride = 0,
};
}
/// Initializes a \ref DmaConfig instance with sane defaults for RAM<>RAM tranfers
static inline void dmaConfigInitDefault(DmaConfig *cfg)
{
*cfg = (DmaConfig) {
.channelId = -1,
.endianSwapSize = 0,
.flags = DMACFG_WAIT_AVAILABLE,
._padding = 0,
.srcCfg = {},
.dstCfg = {},
};
}
///@}
///@name Memory management
///@{
/**
@ -438,20 +646,20 @@ Result svcCreateMemoryBlock(Handle* memblock, u32 addr, u32 size, MemPerm my_per
Result svcMapMemoryBlock(Handle memblock, u32 addr, MemPerm my_perm, MemPerm other_perm);
/**
* @brief Maps a block of process memory.
* @brief Maps a block of process memory, starting from address 0x00100000.
* @param process Handle of the process.
* @param startAddr Start address of the memory to map.
* @param endAddr End address of the memory to map.
* @param destAddress Address of the block of memory to map, in the current (destination) process.
* @param size Size of the block of memory to map (truncated to a multiple of 0x1000 bytes).
*/
Result svcMapProcessMemory(Handle process, u32 startAddr, u32 endAddr);
Result svcMapProcessMemory(Handle process, u32 destAddress, u32 size);
/**
* @brief Unmaps a block of process memory.
* @brief Unmaps a block of process memory, starting from address 0x00100000.
* @param process Handle of the process.
* @param startAddr Start address of the memory to unmap.
* @param endAddr End address of the memory to unmap.
* @param destAddress Address of the block of memory to unmap, in the current (destination) process.
* @param size Size of the block of memory to unmap (truncated to a multiple of 0x1000 bytes).
*/
Result svcUnmapProcessMemory(Handle process, u32 startAddr, u32 endAddr);
Result svcUnmapProcessMemory(Handle process, u32 destAddress, u32 size);
/**
* @brief Unmaps a block of shared memory
@ -460,31 +668,6 @@ Result svcUnmapProcessMemory(Handle process, u32 startAddr, u32 endAddr);
*/
Result svcUnmapMemoryBlock(Handle memblock, u32 addr);
/**
* @brief Begins an inter-process DMA.
* @param[out] dma Pointer to output the handle of the DMA to.
* @param dstProcess Destination process.
* @param dst Buffer to write data to.
* @param srcprocess Source process.
* @param src Buffer to read data from.
* @param size Size of the data to DMA.
* @param dmaConfig DMA configuration data.
*/
Result svcStartInterProcessDma(Handle* dma, Handle dstProcess, void* dst, Handle srcProcess, const void* src, u32 size, void* dmaConfig);
/**
* @brief Terminates an inter-process DMA.
* @param dma Handle of the DMA.
*/
Result svcStopDma(Handle dma);
/**
* @brief Gets the state of an inter-process DMA.
* @param[out] dmaState Pointer to output the state of the DMA to.
* @param dma Handle of the DMA.
*/
Result svcGetDmaState(void* dmaState, Handle dma);
/**
* @brief Queries memory information.
* @param[out] info Pointer to output memory info to.
@ -502,21 +685,6 @@ Result svcQueryMemory(MemInfo* info, PageInfo* out, u32 addr);
*/
Result svcQueryProcessMemory(MemInfo* info, PageInfo* out, Handle process, u32 addr);
/**
* @brief Invalidates a process's data cache.
* @param process Handle of the process.
* @param addr Address to invalidate.
* @param size Size of the memory to invalidate.
*/
Result svcInvalidateProcessDataCache(Handle process, void* addr, u32 size);
/**
* @brief Flushes a process's data cache.
* @param process Handle of the process.
* @param addr Address to flush.
* @param size Size of the memory to flush.
*/
Result svcFlushProcessDataCache(Handle process, void const* addr, u32 size);
///@}
@ -530,7 +698,7 @@ Result svcFlushProcessDataCache(Handle process, void const* addr, u32 size);
Result svcOpenProcess(Handle* process, u32 processId);
/// Exits the current process.
void svcExitProcess() __attribute__((noreturn));
void svcExitProcess(void) __attribute__((noreturn));
/**
* @brief Terminates a process.
@ -587,23 +755,32 @@ Result svcCreatePort(Handle* portServer, Handle* portClient, const char* name, s
Result svcConnectToPort(volatile Handle* out, const char* portName);
/**
* @brief Sets up virtual address space for a new process
* @param[out] out Pointer to output the code set handle to.
* @param info Description for setting up the addresses
* @param code_ptr Pointer to .text in shared memory
* @param ro_ptr Pointer to .rodata in shared memory
* @param data_ptr Pointer to .data in shared memory
* @brief Sets up virtual address space for a new process.
* @param[out] out Pointer to output the codeset handle to.
* @param info Codeset header, contains process name, titleId and segment info.
* @param textSegmentLma Address of executable segment in caller's address space.
* @param roSegmentLma Address of read-only segment in caller's address space.
* @param dataSegmentLma Address of read-write segment in caller's address space.
* @note On success, the provided segments are unmapped from the caller's address space.
*/
Result svcCreateCodeSet(Handle* out, const CodeSetInfo *info, void* code_ptr, void* ro_ptr, void* data_ptr);
Result svcCreateCodeSet(Handle* out, const CodeSetHeader* info, u32 textSegmentLma, u32 roSegmentLma, u32 dataSegmentLma);
/**
* @brief Sets up virtual address space for a new process
* @brief Create a new process.
* @param[out] out Pointer to output the process handle to.
* @param codeset Codeset created for this process
* @param arm11kernelcaps ARM11 Kernel Capabilities from exheader
* @param arm11kernelcaps_num Number of kernel capabilities
* @param codeset Codeset created for this process.
* @param arm11KernelCaps Arm11 Kernel Capabilities from exheader.
* @param numArm11KernelCaps Number of kernel capabilities.
*/
Result svcCreateProcess(Handle* out, Handle codeset, const u32 *arm11kernelcaps, u32 arm11kernelcaps_num);
Result svcCreateProcess(Handle* out, Handle codeset, const u32* arm11KernelCaps, s32 numArm11KernelCaps);
/**
* @brief Gets a process's affinity mask.
* @param[out] affinitymask Pointer to store the affinity masks.
* @param process Handle of the process.
* @param processorcount Number of processors.
*/
Result svcGetProcessAffinityMask(u8* affinitymask, Handle process, s32 processorcount);
/**
* @brief Sets a process's affinity mask.
@ -613,10 +790,17 @@ Result svcCreateProcess(Handle* out, Handle codeset, const u32 *arm11kernelcaps,
*/
Result svcSetProcessAffinityMask(Handle process, const u8* affinitymask, s32 processorcount);
/**
* Gets a process's ideal processor.
* @param[out] processorid Pointer to store the ID of the process's ideal processor.
* @param process Handle of the process.
*/
Result svcGetProcessIdealProcessor(s32 *processorid, Handle process);
/**
* Sets a process's ideal processor.
* @param process Handle of the process.
* @param processorid ID of the thread's ideal processor.
* @param processorid ID of the process's ideal processor.
*/
Result svcSetProcessIdealProcessor(Handle process, s32 processorid);
@ -742,7 +926,7 @@ Result svcGetResourceLimit(Handle* resourceLimit, Handle process);
* @param names Resource limit names to get the limits of.
* @param nameCount Number of resource limit names.
*/
Result svcGetResourceLimitLimitValues(s64* values, Handle resourceLimit, u32* names, s32 nameCount);
Result svcGetResourceLimitLimitValues(s64* values, Handle resourceLimit, ResourceLimitType* names, s32 nameCount);
/**
* @brief Gets the values of a resource limit set.
@ -751,7 +935,30 @@ Result svcGetResourceLimitLimitValues(s64* values, Handle resourceLimit, u32* na
* @param names Resource limit names to get the values of.
* @param nameCount Number of resource limit names.
*/
Result svcGetResourceLimitCurrentValues(s64* values, Handle resourceLimit, u32* names, s32 nameCount);
Result svcGetResourceLimitCurrentValues(s64* values, Handle resourceLimit, ResourceLimitType* names, s32 nameCount);
/**
* @brief Sets the resource limit set of a process.
* @param process Process to set the resource limit set to.
* @param resourceLimit Resource limit set handle.
*/
Result svcSetProcessResourceLimits(Handle process, Handle resourceLimit);
/**
* @brief Creates a resource limit set.
* @param[out] resourceLimit Pointer to output the resource limit set handle to.
*/
Result svcCreateResourceLimit(Handle* resourceLimit);
/**
* @brief Sets the value limits of a resource limit set.
* @param resourceLimit Resource limit set to use.
* @param names Resource limit names to set the limits of.
* @param values Value limits to set. The high 32 bits of RESLIMIT_COMMIT are used to
set APPMEMALLOC in configuration memory, otherwise those bits are unused.
* @param nameCount Number of resource limit names.
*/
Result svcSetResourceLimitValues(Handle resourceLimit, const ResourceLimitType* names, const s64* values, s32 nameCount);
/**
* @brief Gets the process ID of a thread.
@ -836,7 +1043,7 @@ Result svcWaitSynchronization(Handle handle, s64 nanoseconds);
* @param wait_all Whether to wait for synchronization on all handles.
* @param nanoseconds Maximum nanoseconds to wait for.
*/
Result svcWaitSynchronizationN(s32* out, Handle* handles, s32 handles_num, bool wait_all, s64 nanoseconds);
Result svcWaitSynchronizationN(s32* out, const Handle* handles, s32 handles_num, bool wait_all, s64 nanoseconds);
/**
* @brief Creates an address arbiter
@ -851,18 +1058,22 @@ Result svcCreateAddressArbiter(Handle *arbiter);
* @param addr A pointer to a s32 value.
* @param type Type of action to be performed by the arbiter
* @param value Number of threads to signal if using @ref ARBITRATION_SIGNAL, or the value used for comparison.
*
* This will perform an arbitration based on #type. The comparisons are done between #value and the value at the address #addr.
*
* @code
* s32 val=0;
* // Does *nothing* since val >= 0
* svcCreateAddressArbiter(arbiter,&val,ARBITRATION_WAIT_IF_LESS_THAN,0,0);
* // Thread will wait for a signal or wake up after 10000000 nanoseconds because val < 1.
* svcCreateAddressArbiter(arbiter,&val,ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT,1,10000000ULL);
* @endcode
* @param timeout_ns Optional timeout in nanoseconds when using TIMEOUT actions, ignored otherwise. If not needed, use \ref svcArbitrateAddressNoTimeout instead.
* @note Usage of this syscall entails an implicit Data Memory Barrier (dmb).
* @warning Please use \ref syncArbitrateAddressWithTimeout instead.
*/
Result svcArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 nanoseconds);
Result svcArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 value, s64 timeout_ns);
/**
* @brief Same as \ref svcArbitrateAddress but with the timeout_ns parameter undefined.
* @param arbiter Handle of the arbiter
* @param addr A pointer to a s32 value.
* @param type Type of action to be performed by the arbiter
* @param value Number of threads to signal if using @ref ARBITRATION_SIGNAL, or the value used for comparison.
* @note Usage of this syscall entails an implicit Data Memory Barrier (dmb).
* @warning Please use \ref syncArbitrateAddress instead.
*/
Result svcArbitrateAddressNoTimeout(Handle arbiter, u32 addr, ArbitrationType type, s32 value);
/**
* @brief Sends a synchronized request to a session handle.
@ -870,6 +1081,20 @@ Result svcArbitrateAddress(Handle arbiter, u32 addr, ArbitrationType type, s32 v
*/
Result svcSendSyncRequest(Handle session);
/**
* @brief Connects to a port via a handle.
* @param[out] clientSession Pointer to output the client session handle to.
* @param clientPort Port client endpoint to connect to.
*/
Result svcCreateSessionToPort(Handle* clientSession, Handle clientPort);
/**
* @brief Creates a linked pair of session endpoints.
* @param[out] serverSession Pointer to output the created server endpoint handle to.
* @param[out] clientSession Pointer to output the created client endpoint handle to.
*/
Result svcCreateSession(Handle* serverSession, Handle* clientSession);
/**
* @brief Accepts a session.
* @param[out] session Pointer to output the created session handle to.
@ -884,23 +1109,8 @@ Result svcAcceptSession(Handle* session, Handle port);
* @param handleCount Number of handles.
* @param replyTarget Handle of the session to reply to.
*/
Result svcReplyAndReceive(s32* index, Handle* handles, s32 handleCount, Handle replyTarget);
Result svcReplyAndReceive(s32* index, const Handle* handles, s32 handleCount, Handle replyTarget);
/**
* @brief Binds an event or semaphore handle to an ARM11 interrupt.
* @param interruptId Interrupt identfier (see https://www.3dbrew.org/wiki/ARM11_Interrupts).
* @param eventOrSemaphore Event or semaphore handle to bind to the given interrupt.
* @param priority Priority of the interrupt for the current process.
* @param isManualClear Indicates whether the interrupt has to be manually cleared or not (= level-high active).
*/
Result svcBindInterrupt(u32 interruptId, Handle eventOrSemaphore, s32 priority, bool isManualClear);
/**
* @brief Unbinds an event or semaphore handle from an ARM11 interrupt.
* @param interruptId Interrupt identfier, see (see https://www.3dbrew.org/wiki/ARM11_Interrupts).
* @param eventOrSemaphore Event or semaphore handle to unbind from the given interrupt.
*/
Result svcUnbindInterrupt(u32 interruptId, Handle eventOrSemaphore);
///@}
///@name Time
@ -977,6 +1187,100 @@ Result svcGetSystemInfo(s64* out, u32 type, s32 param);
Result svcKernelSetState(u32 type, ...);
///@}
///@name Device drivers
///@{
/**
* @brief Binds an event or semaphore handle to an ARM11 interrupt.
* @param interruptId Interrupt identfier (see https://www.3dbrew.org/wiki/ARM11_Interrupts).
* @param eventOrSemaphore Event or semaphore handle to bind to the given interrupt.
* @param priority Priority of the interrupt for the current process.
* @param isManualClear Indicates whether the interrupt has to be manually cleared or not (= level-high active).
*/
Result svcBindInterrupt(u32 interruptId, Handle eventOrSemaphore, s32 priority, bool isManualClear);
/**
* @brief Unbinds an event or semaphore handle from an ARM11 interrupt.
* @param interruptId Interrupt identfier, see (see https://www.3dbrew.org/wiki/ARM11_Interrupts).
* @param eventOrSemaphore Event or semaphore handle to unbind from the given interrupt.
*/
Result svcUnbindInterrupt(u32 interruptId, Handle eventOrSemaphore);
/**
* @brief Invalidates a process's data cache.
* @param process Handle of the process.
* @param addr Address to invalidate.
* @param size Size of the memory to invalidate.
*/
Result svcInvalidateProcessDataCache(Handle process, u32 addr, u32 size);
/**
* @brief Cleans a process's data cache.
* @param process Handle of the process.
* @param addr Address to clean.
* @param size Size of the memory to clean.
*/
Result svcStoreProcessDataCache(Handle process, u32 addr, u32 size);
/**
* @brief Flushes (cleans and invalidates) a process's data cache.
* @param process Handle of the process.
* @param addr Address to flush.
* @param size Size of the memory to flush.
*/
Result svcFlushProcessDataCache(Handle process, u32 addr, u32 size);
/**
* @brief Begins an inter-process DMA transfer.
* @param[out] dma Pointer to output the handle of the DMA channel object to.
* @param dstProcess Destination process handle.
* @param dstAddr Address in the destination process to write data to.
* @param srcProcess Source process handle.
* @param srcAddr Address in the source to read data from.
* @param size Size of the data to transfer.
* @param cfg Configuration structure.
* @note The handle is signaled when the transfer finishes.
*/
Result svcStartInterProcessDma(Handle *dma, Handle dstProcess, u32 dstAddr, Handle srcProcess, u32 srcAddr, u32 size, const DmaConfig *cfg);
/**
* @brief Stops an inter-process DMA transfer.
* @param dma Handle of the DMA channel object.
*/
Result svcStopDma(Handle dma);
/**
* @brief Gets the state of an inter-process DMA transfer.
* @param[out] state Pointer to output the state of the DMA transfer to.
* @param dma Handle of the DMA channel object.
*/
Result svcGetDmaState(DmaState *state, Handle dma);
/**
* @brief Restarts a DMA transfer, using the same configuration as before.
* @param[out] state Pointer to output the state of the DMA transfer to.
* @param dma Handle of the DMA channel object.
* @param dstAddr Address in the destination process to write data to.
* @param srcAddr Address in the source to read data from.
* @param size Size of the data to transfer.
* @param flags Restart flags, \ref DMARST_UNLOCK and/or \ref DMARST_RESUME_DEVICE.
* @note The first transfer has to be configured with \ref DMACFG_KEEP_LOCKED.
*/
Result svcRestartDma(Handle dma, u32 dstAddr, u32 srcAddr, u32 size, s8 flags);
/**
* @brief Sets the GPU protection register to restrict the range of the GPU DMA. 11.3+ only.
* @param useApplicationRestriction Whether to use the register value used for APPLICATION titles.
*/
Result svcSetGpuProt(bool useApplicationRestriction);
/**
* @brief Enables or disables Wi-Fi. 11.4+ only.
* @param enabled Whether to enable or disable Wi-Fi.
*/
Result svcSetWifiEnabled(bool enabled);
///@}
///@name Debugging
///@{
@ -1000,6 +1304,34 @@ void svcBreakRO(UserBreakType breakReason, const void* croInfo, u32 croInfoSize)
* @param length Length of the string to output, needs to be positive.
*/
Result svcOutputDebugString(const char* str, s32 length);
/**
* @brief Controls performance monitoring on the CP15 interface and the SCU.
* The meaning of the parameters depend on the operation.
* @param[out] out Output.
* @param op Operation, see details.
* @param param1 First parameter.
* @param param2 Second parameter.
* @details The operations are the following:
* - \ref PERFCOUNTEROP_ENABLE (void) -> void, tries to enable and lock perfmon. functionality.
* - \ref PERFCOUNTEROP_DISABLE (void) -> void, disable and forcibly unlocks perfmon. functionality.
* - \ref PERFCOUNTEROP_GET_VALUE (\ref PerfCounterRegister reg) -> u64, gets the value of a particular counter register.
* - \ref PERFCOUNTEROP_SET_VALUE (\ref PerfCounterRegister reg, u64 value) -> void, sets the value of a particular counter register.
* - \ref PERFCOUNTEROP_GET_OVERFLOW_FLAGS (void) -> u32, gets the overflow flags of all CP15 and SCU registers.
* - Format is a bitfield of \ref PerfCounterRegister.
* - \ref PERFCOUNTEROP_RESET (u32 valueResetMask, u32 overflowFlagResetMask) -> void, resets the value and/or
* overflow flags of selected registers.
* - Format is two bitfields of \ref PerfCounterRegister.
* - \ref PERFCOUNTEROP_GET_EVENT (\ref PerfCounterRegister reg) -> \ref PerfCounterEvent, gets the event associated
* to a particular counter register.
* - \ref PERFCOUNTEROP_SET_EVENT (\ref PerfCounterRegister reg, \ref PerfCounterEvent) -> void, sets the event associated
* to a particular counter register.
* - \ref PERFCOUNTEROP_SET_VIRTUAL_COUNTER_ENABLED (bool enabled) -> void, (dis)allows the kernel to track counter overflows
* and to use 64-bit counter values.
*/
Result svcControlPerformanceCounter(u64 *out, PerfCounterOperation op, u32 param1, u64 param2);
/**
* @brief Creates a debug handle for an active process.
* @param[out] debug Pointer to output the created debug handle to.

195
libctru/include/3ds/synchronization.h Normal file → Executable file
View File

@ -4,6 +4,7 @@
*/
#pragma once
#include <sys/lock.h>
#include <3ds/svc.h>
/// A light lock.
typedef _LOCK_T LightLock;
@ -11,6 +12,9 @@ typedef _LOCK_T LightLock;
/// A recursive lock.
typedef _LOCK_RECURSIVE_T RecursiveLock;
/// A condition variable.
typedef s32 CondVar;
/// A light event.
typedef struct
{
@ -18,12 +22,32 @@ typedef struct
LightLock lock; ///< Lock used for sticky timer operation
} LightEvent;
/// A light semaphore.
typedef struct
{
s32 current_count; ///< The current release count of the semaphore
s16 num_threads_acq; ///< Number of threads concurrently acquiring the semaphore
s16 max_count; ///< The maximum release count of the semaphore
} LightSemaphore;
/// Performs a Data Synchronization Barrier operation.
static inline void __dsb(void)
{
__asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 4" :: [val] "r" (0) : "memory");
}
/// Performs a Data Memory Barrier operation.
static inline void __dmb(void)
{
__asm__ __volatile__("mcr p15, 0, %[val], c7, c10, 5" :: [val] "r" (0) : "memory");
}
/// Performs an Instruction Synchronization Barrier (officially "flush prefetch buffer") operation.
static inline void __isb(void)
{
__asm__ __volatile__("mcr p15, 0, %[val], c7, c5, 4" :: [val] "r" (0) : "memory");
}
/// Performs a clrex operation.
static inline void __clrex(void)
{
@ -55,6 +79,56 @@ static inline bool __strex(s32* addr, s32 val)
return res;
}
/**
* @brief Performs a ldrexh operation.
* @param addr Address to perform the operation on.
* @return The resulting value.
*/
static inline u16 __ldrexh(u16* addr)
{
u16 val;
__asm__ __volatile__("ldrexh %[val], %[addr]" : [val] "=r" (val) : [addr] "Q" (*addr));
return val;
}
/**
* @brief Performs a strexh operation.
* @param addr Address to perform the operation on.
* @param val Value to store.
* @return Whether the operation was successful.
*/
static inline bool __strexh(u16* addr, u16 val)
{
bool res;
__asm__ __volatile__("strexh %[res], %[val], %[addr]" : [res] "=&r" (res) : [val] "r" (val), [addr] "Q" (*addr));
return res;
}
/**
* @brief Performs a ldrexb operation.
* @param addr Address to perform the operation on.
* @return The resulting value.
*/
static inline u8 __ldrexb(u8* addr)
{
u8 val;
__asm__ __volatile__("ldrexb %[val], %[addr]" : [val] "=r" (val) : [addr] "Q" (*addr));
return val;
}
/**
* @brief Performs a strexb operation.
* @param addr Address to perform the operation on.
* @param val Value to store.
* @return Whether the operation was successful.
*/
static inline bool __strexb(u8* addr, u8 val)
{
bool res;
__asm__ __volatile__("strexb %[res], %[val], %[addr]" : [res] "=&r" (res) : [val] "r" (val), [addr] "Q" (*addr));
return res;
}
/// Performs an atomic pre-increment operation.
#define AtomicIncrement(ptr) __atomic_add_fetch((u32*)(ptr), 1, __ATOMIC_SEQ_CST)
/// Performs an atomic pre-decrement operation.
@ -67,10 +141,40 @@ static inline bool __strex(s32* addr, s32 val)
#define AtomicSwap(ptr, value) __atomic_exchange_n((u32*)(ptr), (value), __ATOMIC_SEQ_CST)
/**
* @brief Retrieves the synchronization subsystem's address arbiter handle.
* @return The synchronization subsystem's address arbiter handle.
* @brief Function used to implement user-mode synchronization primitives.
* @param addr Pointer to a signed 32-bit value whose address will be used to identify waiting threads.
* @param type Type of action to be performed by the arbiter
* @param value Number of threads to signal if using @ref ARBITRATION_SIGNAL, or the value used for comparison.
*
* This will perform an arbitration based on #type. The comparisons are done between #value and the value at the address #addr.
*
* @code
* s32 val=0;
* // Does *nothing* since val >= 0
* syncArbitrateAddress(&val,ARBITRATION_WAIT_IF_LESS_THAN,0);
* @endcode
*
* @note Usage of this function entails an implicit Data Memory Barrier (dmb).
*/
Handle __sync_get_arbiter(void);
Result syncArbitrateAddress(s32* addr, ArbitrationType type, s32 value);
/**
* @brief Function used to implement user-mode synchronization primitives (with timeout).
* @param addr Pointer to a signed 32-bit value whose address will be used to identify waiting threads.
* @param type Type of action to be performed by the arbiter (must use \ref ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT or \ref ARBITRATION_DECREMENT_AND_WAIT_IF_LESS_THAN_TIMEOUT)
* @param value Number of threads to signal if using @ref ARBITRATION_SIGNAL, or the value used for comparison.
*
* This will perform an arbitration based on #type. The comparisons are done between #value and the value at the address #addr.
*
* @code
* s32 val=0;
* // Thread will wait for a signal or wake up after 10000000 nanoseconds because val < 1.
* syncArbitrateAddressWithTimeout(&val,ARBITRATION_WAIT_IF_LESS_THAN_TIMEOUT,1,10000000LL);
* @endcode
*
* @note Usage of this function entails an implicit Data Memory Barrier (dmb).
*/
Result syncArbitrateAddressWithTimeout(s32* addr, ArbitrationType type, s32 value, s64 timeout_ns);
/**
* @brief Initializes a light lock.
@ -122,6 +226,53 @@ int RecursiveLock_TryLock(RecursiveLock* lock);
*/
void RecursiveLock_Unlock(RecursiveLock* lock);
/**
* @brief Initializes a condition variable.
* @param cv Pointer to the condition variable.
*/
void CondVar_Init(CondVar* cv);
/**
* @brief Waits on a condition variable.
* @param cv Pointer to the condition variable.
* @param lock Pointer to the lock to atomically unlock/relock during the wait.
*/
void CondVar_Wait(CondVar* cv, LightLock* lock);
/**
* @brief Waits on a condition variable with a timeout.
* @param cv Pointer to the condition variable.
* @param lock Pointer to the lock to atomically unlock/relock during the wait.
* @param timeout_ns Timeout in nanoseconds.
* @return Zero on success, non-zero on failure.
*/
int CondVar_WaitTimeout(CondVar* cv, LightLock* lock, s64 timeout_ns);
/**
* @brief Wakes up threads waiting on a condition variable.
* @param cv Pointer to the condition variable.
* @param num_threads Maximum number of threads to wake up (or \ref ARBITRATION_SIGNAL_ALL to wake them all).
*/
void CondVar_WakeUp(CondVar* cv, s32 num_threads);
/**
* @brief Wakes up a single thread waiting on a condition variable.
* @param cv Pointer to the condition variable.
*/
static inline void CondVar_Signal(CondVar* cv)
{
CondVar_WakeUp(cv, 1);
}
/**
* @brief Wakes up all threads waiting on a condition variable.
* @param cv Pointer to the condition variable.
*/
static inline void CondVar_Broadcast(CondVar* cv)
{
CondVar_WakeUp(cv, ARBITRATION_SIGNAL_ALL);
}
/**
* @brief Initializes a light event.
* @param event Pointer to the event.
@ -159,3 +310,41 @@ int LightEvent_TryWait(LightEvent* event);
* @param event Pointer to the event.
*/
void LightEvent_Wait(LightEvent* event);
/**
* @brief Waits on a light event until either the event is signaled or the timeout is reached.
* @param event Pointer to the event.
* @param timeout_ns Timeout in nanoseconds.
* @return Non-zero on timeout, zero otherwise.
*/
int LightEvent_WaitTimeout(LightEvent* event, s64 timeout_ns);
/**
* @brief Initializes a light semaphore.
* @param event Pointer to the semaphore.
* @param max_count Initial count of the semaphore.
* @param max_count Maximum count of the semaphore.
*/
void LightSemaphore_Init(LightSemaphore* semaphore, s16 initial_count, s16 max_count);
/**
* @brief Acquires a light semaphore.
* @param semaphore Pointer to the semaphore.
* @param count Acquire count
*/
void LightSemaphore_Acquire(LightSemaphore* semaphore, s32 count);
/**
* @brief Attempts to acquire a light semaphore.
* @param semaphore Pointer to the semaphore.
* @param count Acquire count
* @return Zero on success, non-zero on failure
*/
int LightSemaphore_TryAcquire(LightSemaphore* semaphore, s32 count);
/**
* @brief Releases a light semaphore.
* @param semaphore Pointer to the semaphore.
* @param count Release count
*/
void LightSemaphore_Release(LightSemaphore* semaphore, s32 count);

View File

@ -7,10 +7,23 @@
#include <3ds/result.h>
#include <3ds/synchronization.h>
#include <3ds/svc.h>
#include <3ds/errf.h>
/// Makes the exception handler reuse the stack of the faulting thread as-is
#define RUN_HANDLER_ON_FAULTING_STACK ((void*)1)
/// Makes the exception handler push the exception data on its stack
#define WRITE_DATA_TO_HANDLER_STACK NULL
/// Makes the exception handler push the exception data on the stack of the faulting thread
#define WRITE_DATA_TO_FAULTING_STACK ((ERRF_ExceptionData*)1)
/// libctru thread handle type
typedef struct Thread_tag* Thread;
/// Exception handler type, necessarily an ARM function that does not return.
typedef void (*ExceptionHandler)(ERRF_ExceptionInfo* excep, CpuRegisters* regs);
/**
* @brief Creates a new libctru thread.
* @param entrypoint The function that will be called first upon thread creation
@ -20,9 +33,9 @@ typedef struct Thread_tag* Thread;
* For userland apps, this has to be within the range [0x18;0x3F].
* The main thread usually has a priority of 0x30, but not always. Use svcGetThreadPriority() if you need
* to create a thread with a priority that is explicitly greater or smaller than that of the main thread.
* @param affinity The ID of the processor the thread should be ran on. Processor IDs are labeled starting from 0.
* On Old3DS it must be <2, and on New3DS it must be <4.
* Pass -1 to execute the thread on all CPUs and -2 to execute the thread on the default CPU (read from the Exheader).
* @param core_id The ID of the processor the thread should be ran on. Processor IDs are labeled starting from 0.
* On Old3DS it must be <2, and on New3DS it must be <4.
* Pass -1 to execute the thread on all CPUs and -2 to execute the thread on the default CPU (read from the Exheader).
* @param detached When set to true, the thread is automatically freed when it finishes.
* @return The libctru thread handle on success, NULL on failure.
*
@ -35,7 +48,7 @@ typedef struct Thread_tag* Thread;
* @note Default exit code of a thread is 0.
* @warning @ref svcExitThread should never be called from the thread, use @ref threadExit instead.
*/
Thread threadCreate(ThreadFunc entrypoint, void* arg, size_t stack_size, int prio, int affinity, bool detached);
Thread threadCreate(ThreadFunc entrypoint, void* arg, size_t stack_size, int prio, int core_id, bool detached);
/**
* @brief Retrieves the OS thread handle of a libctru thread.
@ -54,6 +67,7 @@ int threadGetExitCode(Thread thread);
/**
* @brief Frees a finished libctru thread.
* @param thread libctru thread handle
* @remarks This function should not be called if the thread is detached, as it is freed automatically when it finishes.
*/
void threadFree(Thread thread);
@ -64,6 +78,12 @@ void threadFree(Thread thread);
*/
Result threadJoin(Thread thread, u64 timeout_ns);
/**
* @brief Changes a thread's status from attached to detached.
* @param thread libctru thread handle
*/
void threadDetach(Thread thread);
/**
* @brief Retrieves the libctru thread handle of the current thread.
* @return libctru thread handle of the current thread, or NULL for the main thread
@ -75,3 +95,29 @@ Thread threadGetCurrent(void);
* @param rc Exit code
*/
void threadExit(int rc) __attribute__((noreturn));
/**
* @brief Sets the exception handler for the current thread. Called from the main thread, this sets the default handler.
* @param handler The exception handler, necessarily an ARM function that does not return
* @param stack_top A pointer to the top of the stack that will be used by the handler. See also @ref RUN_HANDLER_ON_FAULTING_STACK
* @param exception_data A pointer to the buffer that will contain the exception data.
See also @ref WRITE_DATA_TO_HANDLER_STACK and @ref WRITE_DATA_TO_FAULTING_STACK
*
* To have CPU exceptions reported through this mechanism, it is normally necessary that UNITINFO is set to a non-zero value when Kernel11 starts,
* and this mechanism is also controlled by @ref svcKernelSetState type 6, see 3dbrew.
*
* VFP exceptions are always reported this way even if the process is being debugged using the debug SVCs.
*
* The current thread need not be a libctru thread.
*/
static inline void threadOnException(ExceptionHandler handler, void* stack_top, ERRF_ExceptionData* exception_data)
{
u8* tls = (u8*)getThreadLocalStorage();
*(u32*)(tls + 0x40) = (u32)handler;
*(u32*)(tls + 0x44) = (u32)stack_top;
*(u32*)(tls + 0x48) = (u32)exception_data;
__dsb();
__isb();
}

View File

@ -47,16 +47,16 @@ typedef void (*voidfn)(void);
#define BIT(n) (1U<<(n))
/// Aligns a struct (and other types?) to m, making sure that the size of the struct is a multiple of m.
#define ALIGN(m) __attribute__((aligned(m)))
#define CTR_ALIGN(m) __attribute__((aligned(m)))
/// Packs a struct (and other types?) so it won't include padding bytes.
#define PACKED __attribute__((packed))
#define CTR_PACKED __attribute__((packed))
#ifndef LIBCTRU_NO_DEPRECATION
#ifndef CTR_NO_DEPRECATION
/// Flags a function as deprecated.
#define DEPRECATED __attribute__ ((deprecated))
#define CTR_DEPRECATED __attribute__ ((deprecated))
#else
/// Flags a function as deprecated.
#define DEPRECATED
#define CTR_DEPRECATED
#endif
/// Structure representing CPU registers
@ -70,9 +70,9 @@ typedef struct {
/// Structure representing FPU registers
typedef struct {
union{
double d[16]; ///< d0-d15.
float f[32]; ///< f0-f31.
union {
struct CTR_PACKED { double d[16]; }; ///< d0-d15.
float s[32]; ///< s0-s31.
};
u32 fpscr; ///< fpscr.
u32 fpexc; ///< fpexc.

View File

@ -0,0 +1,238 @@
/**
* @file decompress.h
* @brief Decompression functions.
*/
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
/** @brief Compression types */
typedef enum
{
DECOMPRESS_DUMMY = 0x00, ///< Dummy compression
DECOMPRESS_LZSS = 0x10, ///< LZSS/LZ10 compression
DECOMPRESS_LZ10 = 0x10, ///< LZSS/LZ10 compression
DECOMPRESS_LZ11 = 0x11, ///< LZ11 compression
DECOMPRESS_HUFF1 = 0x21, ///< Huffman compression with 1-bit data
DECOMPRESS_HUFF2 = 0x22, ///< Huffman compression with 2-bit data
DECOMPRESS_HUFF3 = 0x23, ///< Huffman compression with 3-bit data
DECOMPRESS_HUFF4 = 0x24, ///< Huffman compression with 4-bit data
DECOMPRESS_HUFF5 = 0x25, ///< Huffman compression with 5-bit data
DECOMPRESS_HUFF6 = 0x26, ///< Huffman compression with 6-bit data
DECOMPRESS_HUFF7 = 0x27, ///< Huffman compression with 7-bit data
DECOMPRESS_HUFF8 = 0x28, ///< Huffman compression with 8-bit data
DECOMPRESS_HUFF = 0x28, ///< Huffman compression with 8-bit data
DECOMPRESS_RLE = 0x30, ///< Run-length encoding compression
} decompressType;
/** @brief I/O vector */
typedef struct
{
void *data; ///< I/O buffer
size_t size; ///< Buffer size
} decompressIOVec;
/** @brief Data callback */
typedef ssize_t (*decompressCallback)(void *userdata, void *buffer,
size_t size);
#ifdef __cplusplus
extern "C"
{
#endif
/** @brief Decompression callback for file descriptors
* @param[in] userdata Address of file descriptor
* @param[in] buffer Buffer to write into
* @param[in] size Size to read from file descriptor
* @returns Number of bytes read
*/
ssize_t decompressCallback_FD(void *userdata, void *buffer, size_t size);
/** @brief Decompression callback for stdio FILE*
* @param[in] userdata FILE*
* @param[in] buffer Buffer to write into
* @param[in] size Size to read from file descriptor
* @returns Number of bytes read
*/
ssize_t decompressCallback_Stdio(void *userdata, void *buffer, size_t size);
/** @brief Decode decompression header
* @param[out] type Decompression type
* @param[out] size Decompressed size
* @param[in] callback Data callback (see decompressV())
* @param[in] userdata User data passed to callback (see decompressV())
* @param[in] insize Size of userdata (see decompressV())
* @returns Bytes consumed
* @retval -1 error
*/
ssize_t decompressHeader(decompressType *type, size_t *size,
decompressCallback callback, void *userdata,
size_t insize);
/** @brief Decompress data
* @param[in] iov Output vector
* @param[in] iovcnt Number of buffers
* @param[in] callback Data callback (see note)
* @param[in] userdata User data passed to callback (see note)
* @param[in] insize Size of userdata (see note)
* @returns Whether succeeded
*
* @note If callback is null, userdata is a pointer to memory to read from,
* and insize is the size of that data. If callback is not null,
* userdata is passed to callback to fetch more data, and insize is
* unused.
*/
bool decompressV(const decompressIOVec *iov, size_t iovcnt,
decompressCallback callback, void *userdata, size_t insize);
/** @brief Decompress data
* @param[in] output Output buffer
* @param[in] size Output size limit
* @param[in] callback Data callback (see decompressV())
* @param[in] userdata User data passed to callback (see decompressV())
* @param[in] insize Size of userdata (see decompressV())
* @returns Whether succeeded
*/
static inline bool
decompress(void *output, size_t size, decompressCallback callback,
void *userdata, size_t insize)
{
decompressIOVec iov;
iov.data = output;
iov.size = size;
return decompressV(&iov, 1, callback, userdata, insize);
}
/** @brief Decompress LZSS/LZ10
* @param[in] iov Output vector
* @param[in] iovcnt Number of buffers
* @param[in] callback Data callback (see decompressV())
* @param[in] userdata User data passed to callback (see decompressV())
* @param[in] insize Size of userdata (see decompressV())
* @returns Whether succeeded
*/
bool decompressV_LZSS(const decompressIOVec *iov, size_t iovcnt,
decompressCallback callback, void *userdata,
size_t insize);
/** @brief Decompress LZSS/LZ10
* @param[in] output Output buffer
* @param[in] size Output size limit
* @param[in] callback Data callback (see decompressV())
* @param[in] userdata User data passed to callback (see decompressV())
* @param[in] insize Size of userdata (see decompressV())
* @returns Whether succeeded
*/
static inline bool
decompress_LZSS(void *output, size_t size, decompressCallback callback,
void *userdata, size_t insize)
{
decompressIOVec iov;
iov.data = output;
iov.size = size;
return decompressV_LZSS(&iov, 1, callback, userdata, insize);
}
/** @brief Decompress LZ11
* @param[in] iov Output vector
* @param[in] iovcnt Number of buffers
* @param[in] callback Data callback (see decompressV())
* @param[in] userdata User data passed to callback (see decompressV())
* @param[in] insize Size of userdata (see decompressV())
* @returns Whether succeeded
*/
bool decompressV_LZ11(const decompressIOVec *iov, size_t iovcnt,
decompressCallback callback, void *userdata,
size_t insize);
/** @brief Decompress LZ11
* @param[in] output Output buffer
* @param[in] size Output size limit
* @param[in] callback Data callback (see decompressV())
* @param[in] userdata User data passed to callback (see decompressV())
* @param[in] insize Size of userdata (see decompressV())
* @returns Whether succeeded
*/
static inline bool
decompress_LZ11(void *output, size_t size, decompressCallback callback,
void *userdata, size_t insize)
{
decompressIOVec iov;
iov.data = output;
iov.size = size;
return decompressV_LZ11(&iov, 1, callback, userdata, insize);
}
/** @brief Decompress Huffman
* @param[in] bits Data size in bits (usually 4 or 8)
* @param[in] iov Output vector
* @param[in] iovcnt Number of buffers
* @param[in] callback Data callback (see decompressV())
* @param[in] userdata User data passed to callback (see decompressV())
* @param[in] insize Size of userdata (see decompressV())
* @returns Whether succeeded
*/
bool decompressV_Huff(size_t bits, const decompressIOVec *iov, size_t iovcnt,
decompressCallback callback, void *userdata,
size_t insize);
/** @brief Decompress Huffman
* @param[in] bits Data size in bits (usually 4 or 8)
* @param[in] output Output buffer
* @param[in] size Output size limit
* @param[in] callback Data callback (see decompressV())
* @param[in] userdata User data passed to callback (see decompressV())
* @param[in] insize Size of userdata (see decompressV())
* @returns Whether succeeded
*/
static inline bool
decompress_Huff(size_t bits, void *output, size_t size,
decompressCallback callback, void *userdata, size_t insize)
{
decompressIOVec iov;
iov.data = output;
iov.size = size;
return decompressV_Huff(bits, &iov, 1, callback, userdata, insize);
}
/** @brief Decompress run-length encoding
* @param[in] iov Output vector
* @param[in] iovcnt Number of buffers
* @param[in] callback Data callback (see decompressV())
* @param[in] userdata User data passed to callback (see decompressV())
* @param[in] insize Size of userdata (see decompressV())
* @returns Whether succeeded
*/
bool decompressV_RLE(const decompressIOVec *iov, size_t iovcnt,
decompressCallback callback, void *userdata,
size_t insize);
/** @brief Decompress run-length encoding
* @param[in] output Output buffer
* @param[in] size Output size limit
* @param[in] callback Data callback (see decompressV())
* @param[in] userdata User data passed to callback (see decompressV())
* @param[in] insize Size of userdata (see decompressV())
* @returns Whether succeeded
*/
static inline bool
decompress_RLE(void *output, size_t size, decompressCallback callback,
void *userdata, size_t insize)
{
decompressIOVec iov;
iov.data = output;
iov.size = size;
return decompressV_RLE(&iov, 1, callback, userdata, insize);
}
#ifdef __cplusplus
}
#endif

View File

@ -9,14 +9,13 @@
#define TRY_AGAIN 4
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;
char *h_addr;
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
uint16_t h_addrtype; /* host address type */
uint16_t h_length; /* length of address */
char **h_addr_list; /* list of addresses from name server */
};
#define h_addr h_addr_list[0] /* for backward compatibility */
#define AI_PASSIVE 0x01
#define AI_CANONNAME 0x02

View File

@ -1,7 +1,5 @@
#pragma once
#include <3ds/types.h>
#define POLLIN 0x01
#define POLLPRI 0x02
#define POLLHUP 0x04 // unknown ???
@ -9,7 +7,7 @@
#define POLLOUT 0x10
#define POLLNVAL 0x20
typedef u32 nfds_t;
typedef unsigned int nfds_t;
struct pollfd
{

View File

@ -42,6 +42,10 @@
#define SO_TYPE 0x1008 // get socket type
#define SO_ERROR 0x1009 // get socket error
#define SO_BROADCAST 0x0000 // unrequired, included for compatibility
#define _SOCKLEN_T_DECLARED
typedef uint32_t socklen_t;
typedef uint16_t sa_family_t;

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="1"/>

48
libctru/source/3dslink.c Normal file
View File

@ -0,0 +1,48 @@
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <3ds/3dslink.h>
struct in_addr __3dslink_host = {0};
static int sock = -1;
int link3dsConnectToHost(bool redirStdout, bool redirStderr)
{
int ret = -1;
struct sockaddr_in srv_addr;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (!sock) {
return ret;
}
bzero(&srv_addr, sizeof srv_addr);
srv_addr.sin_family = AF_INET;
srv_addr.sin_addr = __3dslink_host;
srv_addr.sin_port = htons(LINK3DS_COMM_PORT);
ret = connect(sock, (struct sockaddr *) &srv_addr, sizeof(srv_addr));
if (ret != 0) {
close(sock);
return -1;
}
if (redirStdout) {
// redirect stdout
fflush(stdout);
dup2(sock, STDOUT_FILENO);
}
if (redirStderr) {
// redirect stderr
fflush(stderr);
dup2(sock, STDERR_FILENO);
}
return sock;
}

View File

@ -27,18 +27,9 @@ static bool linearInit()
void* linearMemAlign(size_t size, size_t alignment)
{
// Enforce minimum alignment
if (alignment < 16)
alignment = 16;
// Convert alignment to shift amount
int shift;
for (shift = 4; shift < 32; shift ++)
{
if ((1U<<shift) == alignment)
break;
}
if (shift == 32) // Invalid alignment
// Convert alignment to shift
int shift = alignmentToShift(alignment);
if (shift < 0)
return nullptr;
// Initialize the pool if it is not ready
@ -71,6 +62,12 @@ void* linearRealloc(void* mem, size_t size)
return NULL;
}
size_t linearGetSize(void* mem)
{
auto node = getNode(mem);
return node ? node->chunk.size : 0;
}
void linearFree(void* mem)
{
auto node = getNode(mem);

View File

@ -0,0 +1,59 @@
#include <3ds/allocator/mappable.h>
#include <3ds/svc.h>
#include <3ds/result.h>
static u32 minAddr, maxAddr, currentAddr;
void mappableInit(u32 addrMin, u32 addrMax)
{
minAddr = addrMin;
maxAddr = addrMax;
currentAddr = minAddr;
}
static u32 mappableFindAddressWithin(u32 start, u32 end, u32 size)
{
MemInfo info;
PageInfo pgInfo;
u32 addr = start;
while (addr >= start && (addr + size) < end && (addr + size) >= addr)
{
if (R_FAILED(svcQueryMemory(&info, &pgInfo, addr)))
return 0;
if (info.state == MEMSTATE_FREE)
{
u32 sz = info.size - (addr - info.base_addr); // a free block might cover all the memory, etc.
if (sz >= size)
return addr;
}
addr = info.base_addr + info.size;
}
return 0;
}
void* mappableAlloc(size_t size)
{
// Round up, can only allocate in page units
size = (size + 0xFFF) & ~0xFFF;
u32 addr = mappableFindAddressWithin(currentAddr, maxAddr, size);
if (addr == 0)
{
// Need to rollover (maybe)
addr = mappableFindAddressWithin(minAddr, currentAddr, size);
if (addr == 0)
return NULL;
}
currentAddr = addr + size >= maxAddr ? minAddr : addr + size;
return (void *)addr;
}
void mappableFree(void* mem)
{
(void)mem;
}

View File

@ -1,61 +0,0 @@
extern "C"
{
#include <3ds/types.h>
#include <3ds/allocator/mappable.h>
#include <3ds/util/rbtree.h>
}
#include "mem_pool.h"
#include "addrmap.h"
static MemPool sMappablePool;
static bool mappableInit()
{
auto blk = MemBlock::Create((u8*)0x10000000, 0x04000000);
if (blk)
{
sMappablePool.AddBlock(blk);
rbtree_init(&sAddrMap, addrMapNodeComparator);
return true;
}
return false;
}
void* mappableAlloc(size_t size)
{
// Initialize the pool if it is not ready
if (!sMappablePool.Ready() && !mappableInit())
return nullptr;
// Allocate the chunk
MemChunk chunk;
if (!sMappablePool.Allocate(chunk, size, 12))
return nullptr;
auto node = newNode(chunk);
if (!node)
{
sMappablePool.Deallocate(chunk);
return nullptr;
}
if (rbtree_insert(&sAddrMap, &node->node));
return chunk.addr;
}
void mappableFree(void* mem)
{
auto node = getNode(mem);
if (!node) return;
// Free the chunk
sMappablePool.Deallocate(node->chunk);
// Free the node
delNode(node);
}
u32 mappableSpaceFree()
{
return sMappablePool.GetFreeSpace();
}

View File

@ -2,6 +2,15 @@
#include <3ds/types.h>
#include <stdlib.h>
static inline int alignmentToShift(size_t alignment)
{
if (alignment < 16)
alignment = 16;
else if (alignment & (alignment - 1))
return -1; // Not a power of two
return __builtin_ffs(alignment)-1;
}
struct MemChunk
{
u8* addr;

View File

@ -1,6 +1,7 @@
extern "C"
{
#include <3ds/types.h>
#include <3ds/os.h>
#include <3ds/allocator/vram.h>
#include <3ds/util/rbtree.h>
}
@ -8,73 +9,126 @@ extern "C"
#include "mem_pool.h"
#include "addrmap.h"
static MemPool sVramPool;
static MemPool sVramPoolA, sVramPoolB;
static bool vramInit()
{
auto blk = MemBlock::Create((u8*)0x1F000000, 0x00600000);
if (blk)
{
sVramPool.AddBlock(blk);
rbtree_init(&sAddrMap, addrMapNodeComparator);
if (sVramPoolA.Ready() || sVramPoolB.Ready())
return true;
auto blkA = MemBlock::Create((u8*)OS_VRAM_VADDR, OS_VRAM_SIZE/2);
if (!blkA)
return false;
auto blkB = MemBlock::Create((u8*)OS_VRAM_VADDR + OS_VRAM_SIZE/2, OS_VRAM_SIZE/2);
if (!blkB)
{
free(blkA);
return false;
}
return false;
sVramPoolA.AddBlock(blkA);
sVramPoolB.AddBlock(blkB);
rbtree_init(&sAddrMap, addrMapNodeComparator);
return true;
}
static MemPool* vramPoolForAddr(void* addr)
{
uintptr_t addr_ = (uintptr_t)addr;
if (addr_ < OS_VRAM_VADDR)
return nullptr;
if (addr_ < OS_VRAM_VADDR + OS_VRAM_SIZE/2)
return &sVramPoolA;
if (addr_ < OS_VRAM_VADDR + OS_VRAM_SIZE)
return &sVramPoolB;
return nullptr;
}
void* vramAlloc(size_t size)
{
return vramMemAlignAt(size, 0x80, VRAM_ALLOC_ANY);
}
void* vramAllocAt(size_t size, vramAllocPos pos)
{
return vramMemAlignAt(size, 0x80, pos);
}
void* vramMemAlign(size_t size, size_t alignment)
{
// Enforce minimum alignment
if (alignment < 16)
alignment = 16;
return vramMemAlignAt(size, alignment, VRAM_ALLOC_ANY);
}
// Convert alignment to shift amount
int shift;
for (shift = 4; shift < 32; shift ++)
{
if ((1U<<shift) == alignment)
break;
}
if (shift == 32) // Invalid alignment
void* vramMemAlignAt(size_t size, size_t alignment, vramAllocPos pos)
{
// Convert alignment to shift
int shift = alignmentToShift(alignment);
if (shift < 0)
return nullptr;
// Initialize the pool if it is not ready
if (!sVramPool.Ready() && !vramInit())
// Initialize the allocator if it is not ready
if (!vramInit())
return nullptr;
// Allocate the chunk
MemChunk chunk;
if (!sVramPool.Allocate(chunk, size, shift))
bool didAlloc = false;
switch (pos & VRAM_ALLOC_ANY)
{
default:
break;
case VRAM_ALLOC_A:
didAlloc = sVramPoolA.Allocate(chunk, size, shift);
break;
case VRAM_ALLOC_B:
didAlloc = sVramPoolB.Allocate(chunk, size, shift);
break;
case VRAM_ALLOC_ANY:
{
// Crude attempt at "load balancing" VRAM A and B
bool prefer_a = sVramPoolA.GetFreeSpace() >= sVramPoolB.GetFreeSpace();
MemPool& firstPool = prefer_a ? sVramPoolA : sVramPoolB;
MemPool& secondPool = prefer_a ? sVramPoolB : sVramPoolA;
didAlloc = firstPool.Allocate(chunk, size, shift);
if (!didAlloc) didAlloc = secondPool.Allocate(chunk, size, shift);
break;
}
}
if (!didAlloc)
return nullptr;
auto node = newNode(chunk);
if (!node)
{
sVramPool.Deallocate(chunk);
vramPoolForAddr(chunk.addr)->Deallocate(chunk);
return nullptr;
}
if (rbtree_insert(&sAddrMap, &node->node));
return chunk.addr;
}
void* vramAlloc(size_t size)
{
return vramMemAlign(size, 0x80);
}
void* vramRealloc(void* mem, size_t size)
{
// TODO
return NULL;
}
size_t vramGetSize(void* mem)
{
auto node = getNode(mem);
return node ? node->chunk.size : 0;
}
void vramFree(void* mem)
{
auto node = getNode(mem);
if (!node) return;
// Free the chunk
sVramPool.Deallocate(node->chunk);
vramPoolForAddr(mem)->Deallocate(node->chunk);
// Free the node
delNode(node);
@ -82,5 +136,5 @@ void vramFree(void* mem)
u32 vramSpaceFree()
{
return sVramPool.GetFreeSpace();
return sVramPoolA.GetFreeSpace() + sVramPoolB.GetFreeSpace();
}

View File

@ -0,0 +1,53 @@
#include <string.h>
#include <3ds/types.h>
#include <3ds/synchronization.h>
#include <3ds/services/apt.h>
#include <3ds/services/cfgu.h>
#include <3ds/util/utf.h>
#include <3ds/applets/error.h>
void errorInit(errorConf* err, errorType type, CFG_Language lang)
{
memset(err, 0, sizeof(*err));
err->type = type;
err->useLanguage = lang + 1;
err->upperScreenFlag = ERROR_NORMAL;
err->eulaVersion = 0;
err->homeButton = true;
err->softwareReset = false;
err->appJump = false;
err->returnCode = ERROR_UNKNOWN;
}
void errorCode(errorConf* err, int error)
{
err->errorCode = error;
}
static void errorConvertToUTF16(u16* out, const char* in, size_t max)
{
if (!in || !*in)
{
out[0] = 0;
return;
}
ssize_t units = utf8_to_utf16(out, (const uint8_t*)in, max-1);
if (units < 0)
{
out[0] = 0;
return;
}
out[units] = 0;
}
void errorText(errorConf *err, const char* text)
{
errorConvertToUTF16(err->Text, text, 1900);
}
void errorDisp(errorConf* err)
{
aptLaunchLibraryApplet(APPID_ERROR, err, sizeof(*err), 0);
}

View File

@ -0,0 +1,181 @@
#include <3ds/types.h>
#include <3ds/result.h>
#include <3ds/services/apt.h>
#include <3ds/util/utf.h>
#include <3ds/applets/miiselector.h>
#include <string.h> // for memcpy
void miiSelectorInit(MiiSelectorConf *conf)
{
memset(conf, 0, sizeof(*conf));
for (int i = 0; i < MIISELECTOR_GUESTMII_SLOTS; i ++)
conf->mii_guest_whitelist[i] = 1;
for (int i = 0; i < MIISELECTOR_USERMII_SLOTS; i ++)
conf->mii_whitelist[i] = 1;
}
void miiSelectorLaunch(const MiiSelectorConf *conf, MiiSelectorReturn *returnbuf)
{
union {
MiiSelectorConf config;
MiiSelectorReturn ret;
} ctx;
memcpy(&ctx.config, conf, sizeof(MiiSelectorConf));
ctx.config.magic = MIISELECTOR_MAGIC;
aptLaunchLibraryApplet(APPID_APPLETED, &ctx.config, sizeof(MiiSelectorConf), 0);
if(returnbuf)
memcpy(returnbuf, &ctx.ret, sizeof(MiiSelectorReturn));
}
static void miiSelectorConvertToUTF8(char* out, const u16* in, int max)
{
if (!in || !*in)
{
out[0] = 0;
return;
}
ssize_t units = utf16_to_utf8((uint8_t*)out, in, max);
if (units < 0)
{
out[0] = 0;
return;
}
out[units] = 0;
}
static void miiSelectorConvertToUTF16(u16* out, const char* in, int max)
{
if (!in || !*in)
{
out[0] = 0;
return;
}
ssize_t units = utf8_to_utf16(out, (const uint8_t*)in, max);
if (units < 0)
{
out[0] = 0;
return;
}
out[units] = 0;
}
void miiSelectorSetTitle(MiiSelectorConf *conf, const char* text)
{
miiSelectorConvertToUTF16(conf->title, text, MIISELECTOR_TITLE_LEN);
}
void miiSelectorSetOptions(MiiSelectorConf *conf, u32 options)
{
static const u8 miiSelectorOptions[] =
{
offsetof(MiiSelectorConf, enable_cancel_button),
offsetof(MiiSelectorConf, enable_selecting_guests),
offsetof(MiiSelectorConf, show_on_top_screen),
offsetof(MiiSelectorConf, show_guest_page),
};
for (int i = 0; i < sizeof(miiSelectorOptions); i ++)
*((u8*)conf + miiSelectorOptions[i]) = (options & BIT(i)) ? 1 : 0;
}
void miiSelectorWhitelistGuestMii(MiiSelectorConf *conf, u32 index)
{
if (index < MIISELECTOR_GUESTMII_SLOTS)
conf->mii_guest_whitelist[index] = 1;
else if (index == MIISELECTOR_GUESTMII_SLOTS)
for (int i = 0; i < MIISELECTOR_GUESTMII_SLOTS; i ++)
conf->mii_guest_whitelist[i] = 1;
}
void miiSelectorBlacklistGuestMii(MiiSelectorConf *conf, u32 index)
{
if (index < MIISELECTOR_GUESTMII_SLOTS)
conf->mii_guest_whitelist[index] = 0;
else if (index == MIISELECTOR_GUESTMII_SLOTS)
for (int i = 0; i < MIISELECTOR_GUESTMII_SLOTS; i ++)
conf->mii_guest_whitelist[i] = 0;
}
void miiSelectorWhitelistUserMii(MiiSelectorConf *conf, u32 index)
{
if (index < MIISELECTOR_USERMII_SLOTS)
conf->mii_whitelist[index] = 1;
else if (index == MIISELECTOR_USERMII_SLOTS)
for (int i = 0; i < MIISELECTOR_USERMII_SLOTS; i ++)
conf->mii_whitelist[i] = 1;
}
void miiSelectorBlacklistUserMii(MiiSelectorConf *conf, u32 index)
{
if (index < MIISELECTOR_USERMII_SLOTS)
conf->mii_whitelist[index] = 0;
else if (index == MIISELECTOR_USERMII_SLOTS)
for (int i = 0; i < MIISELECTOR_USERMII_SLOTS; i ++)
conf->mii_whitelist[i] = 0;
}
void miiSelectorReturnGetName(const MiiSelectorReturn *returnbuf, char* out, size_t max_size)
{
if (!out)
return;
if (returnbuf->guest_mii_was_selected)
miiSelectorConvertToUTF8(out, returnbuf->guest_mii_name, max_size);
else
{
u16 temp[10];
memcpy(temp, returnbuf->mii.mii_name, sizeof(temp));
miiSelectorConvertToUTF8(out, temp, max_size);
}
}
void miiSelectorReturnGetAuthor(const MiiSelectorReturn *returnbuf, char* out, size_t max_size)
{
if (!out)
return;
u16 temp[10];
memcpy(temp, returnbuf->mii.author_name, sizeof(temp));
miiSelectorConvertToUTF8(out, temp, max_size);
}
static u16 crc16_ccitt(void const *buf, size_t len, uint32_t starting_val)
{
if (!buf)
return -1;
u8 const *cbuf = buf;
u32 crc = starting_val;
static const u16 POLY = 0x1021;
for (size_t i = 0; i < len; i++)
{
for (int bit = 7; bit >= 0; bit--)
crc = ((crc << 1) | ((cbuf[i] >> bit) & 0x1)) ^ (crc & 0x8000 ? POLY : 0);
}
for (int _ = 0; _ < 16; _++)
crc = (crc << 1) ^ (crc & 0x8000 ? POLY : 0);
return (u16)(crc & 0xffff);
}
bool miiSelectorChecksumIsValid(const MiiSelectorReturn *returnbuf)
{
u16 computed =
crc16_ccitt(&returnbuf->mii, sizeof(returnbuf->mii) + sizeof(returnbuf->_pad0x68), 0x0000);
u16 chk_little_endian = __builtin_bswap16(returnbuf->checksum);
return computed == chk_little_endian;
}

View File

@ -238,39 +238,35 @@ SwkbdButton swkbdInputText(SwkbdState* swkbd, char* buf, size_t bufsize)
// Launch swkbd
memset(swkbd->reserved, 0, sizeof(swkbd->reserved));
if (extra.callback) aptSetMessageCallback(swkbdMessageCallback, &extra);
bool ret = aptLaunchLibraryApplet(APPID_SOFTWARE_KEYBOARD, swkbd, sizeof(*swkbd), swkbdSharedMemHandle);
aptLaunchLibraryApplet(APPID_SOFTWARE_KEYBOARD, swkbd, sizeof(*swkbd), swkbdSharedMemHandle);
if (extra.callback) aptSetMessageCallback(NULL, NULL);
svcCloseHandle(swkbdSharedMemHandle);
SwkbdButton button = SWKBD_BUTTON_NONE;
if (ret)
switch (swkbd->result)
{
u16* text16 = (u16*)(swkbdSharedMem+swkbd->text_offset);
text16[swkbd->text_length] = 0;
swkbdConvertToUTF8(buf, text16, bufsize-1);
if (swkbd->save_state_flags & BIT(0)) memcpy(extra.status_data, swkbdSharedMem+swkbd->status_offset, sizeof(SwkbdStatusData));
if (swkbd->save_state_flags & BIT(1)) memcpy(extra.learning_data, swkbdSharedMem+swkbd->learning_offset, sizeof(SwkbdLearningData));
switch (swkbd->result)
{
case SWKBD_D1_CLICK0:
case SWKBD_D2_CLICK0:
button = SWKBD_BUTTON_LEFT;
break;
case SWKBD_D2_CLICK1:
button = SWKBD_BUTTON_MIDDLE;
break;
case SWKBD_D0_CLICK:
case SWKBD_D1_CLICK1:
case SWKBD_D2_CLICK2:
button = SWKBD_BUTTON_RIGHT;
break;
default:
break;
}
case SWKBD_D1_CLICK0:
case SWKBD_D2_CLICK0:
button = SWKBD_BUTTON_LEFT;
break;
case SWKBD_D2_CLICK1:
button = SWKBD_BUTTON_MIDDLE;
break;
case SWKBD_D0_CLICK:
case SWKBD_D1_CLICK1:
case SWKBD_D2_CLICK2:
button = SWKBD_BUTTON_RIGHT;
break;
default:
break;
}
u16* text16 = (u16*)(swkbdSharedMem+swkbd->text_offset);
text16[swkbd->text_length] = 0;
swkbdConvertToUTF8(buf, text16, bufsize-1);
if (swkbd->save_state_flags & BIT(0)) memcpy(extra.status_data, swkbdSharedMem+swkbd->status_offset, sizeof(SwkbdStatusData));
if (swkbd->save_state_flags & BIT(1)) memcpy(extra.learning_data, swkbdSharedMem+swkbd->learning_offset, sizeof(SwkbdLearningData));
free(swkbdSharedMem);
return button;
}

1551
libctru/source/archive_dev.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,16 @@ static u16 colorTable[] = {
RGB8_to_565( 96, 96, 96), // faint white
};
static const u8 colorCube[] = {
0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff,
};
static const u8 grayScale[] = {
0x08, 0x12, 0x1c, 0x26, 0x30, 0x3a, 0x44, 0x4e,
0x58, 0x62, 0x6c, 0x76, 0x80, 0x8a, 0x94, 0x9e,
0xa8, 0xb2, 0xbc, 0xc6, 0xd0, 0xda, 0xe4, 0xee,
};
PrintConsole defaultConsole =
{
//Font:
@ -72,7 +82,7 @@ void consolePrintChar(int c);
void consoleDrawChar(int c);
//---------------------------------------------------------------------------------
static void consoleCls(char mode) {
static void consoleCls(int mode) {
//---------------------------------------------------------------------------------
int i = 0;
@ -80,8 +90,7 @@ static void consoleCls(char mode) {
switch (mode)
{
case '[':
case '0':
case 0:
{
colTemp = currentConsole->cursorX ;
rowTemp = currentConsole->cursorY ;
@ -93,7 +102,7 @@ static void consoleCls(char mode) {
currentConsole->cursorY = rowTemp;
break;
}
case '1':
case 1:
{
colTemp = currentConsole->cursorX ;
rowTemp = currentConsole->cursorY ;
@ -108,7 +117,7 @@ static void consoleCls(char mode) {
currentConsole->cursorY = rowTemp;
break;
}
case '2':
case 2:
{
currentConsole->cursorY = 0;
currentConsole->cursorX = 0;
@ -124,7 +133,7 @@ static void consoleCls(char mode) {
gfxFlushBuffers();
}
//---------------------------------------------------------------------------------
static void consoleClearLine(char mode) {
static void consoleClearLine(int mode) {
//---------------------------------------------------------------------------------
int i = 0;
@ -132,8 +141,7 @@ static void consoleClearLine(char mode) {
switch (mode)
{
case '[':
case '0':
case 0:
{
colTemp = currentConsole->cursorX ;
@ -145,7 +153,7 @@ static void consoleClearLine(char mode) {
break;
}
case '1':
case 1:
{
colTemp = currentConsole->cursorX ;
@ -159,7 +167,7 @@ static void consoleClearLine(char mode) {
break;
}
case '2':
case 2:
{
colTemp = currentConsole->cursorX ;
@ -178,6 +186,297 @@ static void consoleClearLine(char mode) {
}
//---------------------------------------------------------------------------------
static inline void consolePosition(int x, int y) {
//---------------------------------------------------------------------------------
// invalid position
if(x < 0 || y < 0)
return;
// 1-based, but we'll take a 0
if(x < 1)
x = 1;
if(y < 1)
y = 1;
// clip to console edge
if(x > currentConsole->windowWidth)
x = currentConsole->windowWidth;
if(y > currentConsole->windowHeight)
y = currentConsole->windowHeight;
// 1-based adjustment
currentConsole->cursorX = x - 1;
currentConsole->cursorY = y - 1;
}
static struct
{
union
{
struct
{
int movement;
} directional;
struct
{
int y;
int x;
} absolute;
struct
{
int type;
} clear;
struct
{
int args[3];
int flags;
u16 fg;
u16 bg;
} color;
int rawBuf[5];
};
int argIdx;
bool hasArg[3];
enum ESC_STATE
{
ESC_NONE,
ESC_START,
ESC_BUILDING_UNKNOWN,
ESC_BUILDING_FORMAT_UNKNOWN,
ESC_BUILDING_FORMAT_FG,
ESC_BUILDING_FORMAT_BG,
ESC_BUILDING_FORMAT_FG_NONRGB,
ESC_BUILDING_FORMAT_BG_NONRGB,
ESC_BUILDING_FORMAT_FG_RGB,
ESC_BUILDING_FORMAT_BG_RGB,
} state;
} escapeSeq;
static void consoleHandleColorEsc(int code)
{
switch (escapeSeq.state)
{
case ESC_BUILDING_FORMAT_UNKNOWN:
switch (code)
{
case 0: // reset
escapeSeq.color.flags = 0;
escapeSeq.color.bg = 0;
escapeSeq.color.fg = 7;
break;
case 1: // bold
escapeSeq.color.flags &= ~CONSOLE_COLOR_FAINT;
escapeSeq.color.flags |= CONSOLE_COLOR_BOLD;
break;
case 2: // faint
escapeSeq.color.flags &= ~CONSOLE_COLOR_BOLD;
escapeSeq.color.flags |= CONSOLE_COLOR_FAINT;
break;
case 3: // italic
escapeSeq.color.flags |= CONSOLE_ITALIC;
break;
case 4: // underline
escapeSeq.color.flags |= CONSOLE_UNDERLINE;
break;
case 5: // blink slow
escapeSeq.color.flags &= ~CONSOLE_BLINK_FAST;
escapeSeq.color.flags |= CONSOLE_BLINK_SLOW;
break;
case 6: // blink fast
escapeSeq.color.flags &= ~CONSOLE_BLINK_SLOW;
escapeSeq.color.flags |= CONSOLE_BLINK_FAST;
break;
case 7: // reverse video
escapeSeq.color.flags |= CONSOLE_COLOR_REVERSE;
break;
case 8: // conceal
escapeSeq.color.flags |= CONSOLE_CONCEAL;
break;
case 9: // crossed-out
escapeSeq.color.flags |= CONSOLE_CROSSED_OUT;
break;
case 21: // bold off
escapeSeq.color.flags &= ~CONSOLE_COLOR_BOLD;
break;
case 22: // normal color
escapeSeq.color.flags &= ~CONSOLE_COLOR_BOLD;
escapeSeq.color.flags &= ~CONSOLE_COLOR_FAINT;
break;
case 23: // italic off
escapeSeq.color.flags &= ~CONSOLE_ITALIC;
break;
case 24: // underline off
escapeSeq.color.flags &= ~CONSOLE_UNDERLINE;
break;
case 25: // blink off
escapeSeq.color.flags &= ~CONSOLE_BLINK_SLOW;
escapeSeq.color.flags &= ~CONSOLE_BLINK_FAST;
break;
case 27: // reverse off
escapeSeq.color.flags &= ~CONSOLE_COLOR_REVERSE;
break;
case 29: // crossed-out off
escapeSeq.color.flags &= ~CONSOLE_CROSSED_OUT;
break;
case 30 ... 37: // writing color
escapeSeq.color.flags &= ~CONSOLE_FG_CUSTOM;
escapeSeq.color.fg = code - 30;
break;
case 38: // custom foreground color
escapeSeq.state = ESC_BUILDING_FORMAT_FG;
break;
case 39: // reset foreground color
escapeSeq.color.flags &= ~CONSOLE_FG_CUSTOM;
escapeSeq.color.fg = 7;
break;
case 40 ... 47: // screen color
escapeSeq.color.flags &= ~CONSOLE_BG_CUSTOM;
escapeSeq.color.bg = code - 40;
break;
case 48: // custom background color
escapeSeq.state = ESC_BUILDING_FORMAT_BG;
break;
case 49: // reset background color
escapeSeq.color.flags &= ~CONSOLE_BG_CUSTOM;
escapeSeq.color.fg = 0;
break;
}
break;
case ESC_BUILDING_FORMAT_FG:
if (escapeSeq.color.args[0] == 5)
escapeSeq.state = ESC_BUILDING_FORMAT_FG_NONRGB;
else if (escapeSeq.color.args[0] == 2)
escapeSeq.state = ESC_BUILDING_FORMAT_FG_RGB;
else
escapeSeq.state = ESC_BUILDING_FORMAT_UNKNOWN;
break;
case ESC_BUILDING_FORMAT_BG:
if (escapeSeq.color.args[0] == 5)
escapeSeq.state = ESC_BUILDING_FORMAT_BG_NONRGB;
else if (escapeSeq.color.args[0] == 2)
escapeSeq.state = ESC_BUILDING_FORMAT_BG_RGB;
else
escapeSeq.state = ESC_BUILDING_FORMAT_UNKNOWN;
break;
case ESC_BUILDING_FORMAT_FG_NONRGB:
if (code <= 15) {
escapeSeq.color.fg = code;
escapeSeq.color.flags &= ~CONSOLE_FG_CUSTOM;
} else if (code <= 231) {
code -= 16;
unsigned int r = code / 36;
unsigned int g = (code - r * 36) / 6;
unsigned int b = code - r * 36 - g * 6;
escapeSeq.color.fg = RGB8_to_565 (colorCube[r], colorCube[g], colorCube[b]);
escapeSeq.color.flags |= CONSOLE_FG_CUSTOM;
} else if (code <= 255) {
code -= 232;
escapeSeq.color.fg = RGB8_to_565 (grayScale[code], grayScale[code], grayScale[code]);
escapeSeq.color.flags |= CONSOLE_FG_CUSTOM;
}
escapeSeq.state = ESC_BUILDING_FORMAT_UNKNOWN;
break;
case ESC_BUILDING_FORMAT_BG_NONRGB:
if (code <= 15) {
escapeSeq.color.bg = code;
escapeSeq.color.flags &= ~CONSOLE_BG_CUSTOM;
} else if (code <= 231) {
code -= 16;
unsigned int r = code / 36;
unsigned int g = (code - r * 36) / 6;
unsigned int b = code - r * 36 - g * 6;
escapeSeq.color.bg = RGB8_to_565 (colorCube[r], colorCube[g], colorCube[b]);
escapeSeq.color.flags |= CONSOLE_BG_CUSTOM;
} else if (code <= 255) {
code -= 232;
escapeSeq.color.bg = RGB8_to_565 (grayScale[code], grayScale[code], grayScale[code]);
escapeSeq.color.flags |= CONSOLE_BG_CUSTOM;
}
escapeSeq.state = ESC_BUILDING_FORMAT_UNKNOWN;
break;
case ESC_BUILDING_FORMAT_FG_RGB:
escapeSeq.color.fg = RGB8_to_565((unsigned int)escapeSeq.color.args[0], (unsigned int)escapeSeq.color.args[1], (unsigned int)escapeSeq.color.args[2]);
escapeSeq.color.flags |= CONSOLE_FG_CUSTOM;
escapeSeq.state = ESC_BUILDING_FORMAT_UNKNOWN;
break;
case ESC_BUILDING_FORMAT_BG_RGB:
escapeSeq.color.bg = RGB8_to_565((unsigned int)escapeSeq.color.args[0], (unsigned int)escapeSeq.color.args[1], (unsigned int)escapeSeq.color.args[2]);
escapeSeq.color.flags |= CONSOLE_BG_CUSTOM;
escapeSeq.state = ESC_BUILDING_FORMAT_UNKNOWN;
break;
default:
break;
}
escapeSeq.argIdx = 0;
}
static void consoleColorStateShift(void)
{
switch (escapeSeq.state)
{
case ESC_BUILDING_UNKNOWN:
escapeSeq.state = ESC_BUILDING_FORMAT_UNKNOWN;
if (escapeSeq.hasArg[0])
consoleHandleColorEsc(escapeSeq.color.args[0]);
if (escapeSeq.hasArg[1])
consoleHandleColorEsc(escapeSeq.color.args[1]);
escapeSeq.argIdx = 0;
escapeSeq.hasArg[0] = escapeSeq.hasArg[1] = false;
break;
case ESC_BUILDING_FORMAT_BG:
case ESC_BUILDING_FORMAT_FG:
case ESC_BUILDING_FORMAT_FG_NONRGB:
case ESC_BUILDING_FORMAT_BG_NONRGB:
consoleHandleColorEsc(escapeSeq.color.args[0]);
escapeSeq.argIdx = 0;
escapeSeq.hasArg[0] = escapeSeq.hasArg[1] = false;
break;
case ESC_BUILDING_FORMAT_FG_RGB:
case ESC_BUILDING_FORMAT_BG_RGB:
if (escapeSeq.argIdx < 3)
escapeSeq.argIdx++;
else
consoleHandleColorEsc(0); // Nothing passed here because three RGB items
break;
default:
break;
}
}
static void consoleColorApply(void)
{
currentConsole->bg = escapeSeq.color.bg;
currentConsole->fg = escapeSeq.color.fg;
currentConsole->flags = escapeSeq.color.flags;
}
//---------------------------------------------------------------------------------
ssize_t con_write(struct _reent *r,void *fd,const char *ptr, size_t len) {
//---------------------------------------------------------------------------------
@ -187,7 +486,7 @@ ssize_t con_write(struct _reent *r,void *fd,const char *ptr, size_t len) {
int i, count = 0;
char *tmp = (char*)ptr;
if(!tmp || len<=0) return -1;
if(!tmp) return -1;
i = 0;
@ -196,264 +495,165 @@ ssize_t con_write(struct _reent *r,void *fd,const char *ptr, size_t len) {
chr = *(tmp++);
i++; count++;
if ( chr == 0x1b && *tmp == '[' ) {
bool escaping = true;
char *escapeseq = tmp++;
int escapelen = 1;
i++; count++;
do {
chr = *(tmp++);
i++; count++; escapelen++;
int parameter, assigned, consumed;
// make sure parameters are positive values and delimited by semicolon
if((chr >= '0' && chr <= '9') || chr == ';')
continue;
switch (chr) {
switch (escapeSeq.state)
{
case ESC_NONE:
if (chr == 0x1b)
escapeSeq.state = ESC_START;
else
consolePrintChar(chr);
break;
case ESC_START:
if (chr == '[')
{
escapeSeq.state = ESC_BUILDING_UNKNOWN;
memset(escapeSeq.rawBuf, 0, sizeof(escapeSeq.rawBuf));
memset(escapeSeq.hasArg, 0, sizeof(escapeSeq.hasArg));
escapeSeq.color.bg = currentConsole->bg;
escapeSeq.color.fg = currentConsole->fg;
escapeSeq.color.flags = currentConsole->flags;
escapeSeq.argIdx = 0;
}
else
{
consolePrintChar(0x1b);
consolePrintChar(chr);
escapeSeq.state = ESC_NONE;
}
break;
case ESC_BUILDING_UNKNOWN:
switch (chr)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
escapeSeq.hasArg[escapeSeq.argIdx] = true;
escapeSeq.rawBuf[escapeSeq.argIdx] = escapeSeq.rawBuf[escapeSeq.argIdx] * 10 + (chr - '0');
break;
case ';':
if (escapeSeq.argIdx < 2)
escapeSeq.argIdx++;
else
consoleColorStateShift();
break;
//---------------------------------------
// Cursor directional movement
//---------------------------------------
case 'A':
consumed = 0;
assigned = sscanf(escapeseq,"[%dA%n", &parameter, &consumed);
if (assigned==0) parameter = 1;
if (consumed)
currentConsole->cursorY = (currentConsole->cursorY - parameter) < 0 ? 0 : currentConsole->cursorY - parameter;
escaping = false;
if (!escapeSeq.hasArg[0])
escapeSeq.directional.movement = 1;
currentConsole->cursorY = (currentConsole->cursorY - escapeSeq.directional.movement) < 0 ? 0 : currentConsole->cursorY - escapeSeq.directional.movement;
escapeSeq.state = ESC_NONE;
break;
case 'B':
consumed = 0;
assigned = sscanf(escapeseq,"[%dB%n", &parameter, &consumed);
if (assigned==0) parameter = 1;
if (consumed)
currentConsole->cursorY = (currentConsole->cursorY + parameter) > currentConsole->windowHeight - 1 ? currentConsole->windowHeight - 1 : currentConsole->cursorY + parameter;
escaping = false;
if (!escapeSeq.hasArg[0])
escapeSeq.directional.movement = 1;
currentConsole->cursorY = (currentConsole->cursorY + escapeSeq.directional.movement) > currentConsole->windowHeight - 1 ? currentConsole->windowHeight - 1 : currentConsole->cursorY + escapeSeq.directional.movement;
escapeSeq.state = ESC_NONE;
break;
case 'C':
consumed = 0;
assigned = sscanf(escapeseq,"[%dC%n", &parameter, &consumed);
if (assigned==0) parameter = 1;
if (consumed)
currentConsole->cursorX = (currentConsole->cursorX + parameter) > currentConsole->windowWidth - 1 ? currentConsole->windowWidth - 1 : currentConsole->cursorX + parameter;
escaping = false;
if (!escapeSeq.hasArg[0])
escapeSeq.directional.movement = 1;
currentConsole->cursorX = (currentConsole->cursorX + escapeSeq.directional.movement) > currentConsole->windowWidth - 1 ? currentConsole->windowWidth - 1 : currentConsole->cursorX + escapeSeq.directional.movement;
escapeSeq.state = ESC_NONE;
break;
case 'D':
consumed = 0;
assigned = sscanf(escapeseq,"[%dD%n", &parameter, &consumed);
if (assigned==0) parameter = 1;
if (consumed)
currentConsole->cursorX = (currentConsole->cursorX - parameter) < 0 ? 0 : currentConsole->cursorX - parameter;
escaping = false;
if (!escapeSeq.hasArg[0])
escapeSeq.directional.movement = 1;
currentConsole->cursorX = (currentConsole->cursorX - escapeSeq.directional.movement) < 0 ? 0 : currentConsole->cursorX - escapeSeq.directional.movement;
escapeSeq.state = ESC_NONE;
break;
//---------------------------------------
// Cursor position movement
//---------------------------------------
case 'H':
case 'f':
{
int x, y;
char c;
if(sscanf(escapeseq,"[%d;%d%c", &y, &x, &c) == 3 && (c == 'f' || c == 'H')) {
currentConsole->cursorX = x;
currentConsole->cursorY = y;
escaping = false;
break;
}
x = y = 1;
if(sscanf(escapeseq,"[%d;%c", &y, &c) == 2 && (c == 'f' || c == 'H')) {
currentConsole->cursorX = x;
currentConsole->cursorY = y;
escaping = false;
break;
}
x = y = 1;
if(sscanf(escapeseq,"[;%d%c", &x, &c) == 2 && (c == 'f' || c == 'H')) {
currentConsole->cursorX = x;
currentConsole->cursorY = y;
escaping = false;
break;
}
x = y = 1;
if(sscanf(escapeseq,"[;%c", &c) == 1 && (c == 'f' || c == 'H')) {
currentConsole->cursorX = x;
currentConsole->cursorY = y;
escaping = false;
break;
}
// invalid format
escaping = false;
consolePosition(escapeSeq.hasArg[1] ? escapeSeq.absolute.x : 1, escapeSeq.hasArg[0] ? escapeSeq.absolute.y : 1);
escapeSeq.state = ESC_NONE;
break;
}
//---------------------------------------
// Screen clear
//---------------------------------------
case 'J':
if(escapelen <= 3)
consoleCls(escapeseq[escapelen-2]);
escaping = false;
consoleCls(escapeSeq.hasArg[0] ? escapeSeq.clear.type : 0);
escapeSeq.state = ESC_NONE;
break;
//---------------------------------------
// Line clear
//---------------------------------------
case 'K':
if(escapelen <= 3)
consoleClearLine(escapeseq[escapelen-2]);
escaping = false;
consoleClearLine(escapeSeq.hasArg[0] ? escapeSeq.clear.type : 0);
escapeSeq.state = ESC_NONE;
break;
//---------------------------------------
// Save cursor position
//---------------------------------------
case 's':
if(escapelen == 2) {
currentConsole->prevCursorX = currentConsole->cursorX ;
currentConsole->prevCursorY = currentConsole->cursorY ;
}
escaping = false;
currentConsole->prevCursorX = currentConsole->cursorX ;
currentConsole->prevCursorY = currentConsole->cursorY ;
escapeSeq.state = ESC_NONE;
break;
//---------------------------------------
// Load cursor position
//---------------------------------------
case 'u':
if(escapelen == 2) {
currentConsole->cursorX = currentConsole->prevCursorX ;
currentConsole->cursorY = currentConsole->prevCursorY ;
}
escaping = false;
currentConsole->cursorX = currentConsole->prevCursorX ;
currentConsole->cursorY = currentConsole->prevCursorY ;
escapeSeq.state = ESC_NONE;
break;
//---------------------------------------
// Color scan codes
//---------------------------------------
case 'm':
escapeseq++;
escapelen--;
do {
parameter = 0;
if (escapelen == 1) {
consumed = 1;
} else if (memchr(escapeseq,';',escapelen)) {
sscanf(escapeseq,"%d;%n", &parameter, &consumed);
} else {
sscanf(escapeseq,"%dm%n", &parameter, &consumed);
}
escapeseq += consumed;
escapelen -= consumed;
switch(parameter) {
case 0: // reset
currentConsole->flags = 0;
currentConsole->bg = 0;
currentConsole->fg = 7;
break;
case 1: // bold
currentConsole->flags &= ~CONSOLE_COLOR_FAINT;
currentConsole->flags |= CONSOLE_COLOR_BOLD;
break;
case 2: // faint
currentConsole->flags &= ~CONSOLE_COLOR_BOLD;
currentConsole->flags |= CONSOLE_COLOR_FAINT;
break;
case 3: // italic
currentConsole->flags |= CONSOLE_ITALIC;
break;
case 4: // underline
currentConsole->flags |= CONSOLE_UNDERLINE;
break;
case 5: // blink slow
currentConsole->flags &= ~CONSOLE_BLINK_FAST;
currentConsole->flags |= CONSOLE_BLINK_SLOW;
break;
case 6: // blink fast
currentConsole->flags &= ~CONSOLE_BLINK_SLOW;
currentConsole->flags |= CONSOLE_BLINK_FAST;
break;
case 7: // reverse video
currentConsole->flags |= CONSOLE_COLOR_REVERSE;
break;
case 8: // conceal
currentConsole->flags |= CONSOLE_CONCEAL;
break;
case 9: // crossed-out
currentConsole->flags |= CONSOLE_CROSSED_OUT;
break;
case 21: // bold off
currentConsole->flags &= ~CONSOLE_COLOR_BOLD;
break;
case 22: // normal color
currentConsole->flags &= ~CONSOLE_COLOR_BOLD;
currentConsole->flags &= ~CONSOLE_COLOR_FAINT;
break;
case 23: // italic off
currentConsole->flags &= ~CONSOLE_ITALIC;
break;
case 24: // underline off
currentConsole->flags &= ~CONSOLE_UNDERLINE;
break;
case 25: // blink off
currentConsole->flags &= ~CONSOLE_BLINK_SLOW;
currentConsole->flags &= ~CONSOLE_BLINK_FAST;
break;
case 27: // reverse off
currentConsole->flags &= ~CONSOLE_COLOR_REVERSE;
break;
case 29: // crossed-out off
currentConsole->flags &= ~CONSOLE_CROSSED_OUT;
break;
case 30 ... 37: // writing color
currentConsole->fg = parameter - 30;
break;
case 39: // reset foreground color
currentConsole->fg = 7;
break;
case 40 ... 47: // screen color
currentConsole->bg = parameter - 40;
break;
case 49: // reset background color
currentConsole->fg = 0;
break;
}
} while (escapelen > 0);
escaping = false;
consoleColorStateShift();
consoleColorApply();
escapeSeq.state = ESC_NONE;
break;
default:
// some sort of unsupported escape; just gloss over it
escaping = false;
escapeSeq.state = ESC_NONE;
break;
}
} while (escaping);
continue;
}
consolePrintChar(chr);
break;
default:
switch (chr)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
escapeSeq.hasArg[escapeSeq.argIdx] = true;
escapeSeq.rawBuf[escapeSeq.argIdx] = escapeSeq.rawBuf[escapeSeq.argIdx] * 10 + (chr - '0');
break;
case ';':
consoleColorStateShift();
break;
case 'm':
consoleColorStateShift();
consoleColorApply();
escapeSeq.state = ESC_NONE;
break;
default:
// some sort of unsupported escape; just gloss over it
escapeSeq.state = ESC_NONE;
break;
}
}
}
return count;
@ -471,14 +671,14 @@ static const devoptab_t dotab_stdout = {
};
//---------------------------------------------------------------------------------
ssize_t debug_write(struct _reent *r, void *fd, const char *ptr, size_t len) {
static ssize_t debug_write(struct _reent *r, void *fd, const char *ptr, size_t len) {
//---------------------------------------------------------------------------------
svcOutputDebugString(ptr,len);
return len;
}
static const devoptab_t dotab_3dmoo = {
"3dmoo",
static const devoptab_t dotab_svc = {
"svc",
0,
NULL,
NULL,
@ -513,6 +713,8 @@ PrintConsole* consoleInit(gfxScreen_t screen, PrintConsole* console) {
setvbuf(stdout, NULL , _IONBF, 0);
setvbuf(stderr, NULL , _IONBF, 0);
memset(&escapeSeq, 0, sizeof(escapeSeq));
firstConsoleInit = false;
}
@ -534,12 +736,12 @@ PrintConsole* consoleInit(gfxScreen_t screen, PrintConsole* console) {
console->frameBuffer = (u16*)gfxGetFramebuffer(screen, GFX_LEFT, NULL, NULL);
if(screen==GFX_TOP) {
console->consoleWidth = 50;
console->windowWidth = 50;
bool isWide = gfxIsWide();
console->consoleWidth = isWide ? 100 : 50;
console->windowWidth = isWide ? 100 : 50;
}
consoleCls('2');
consoleCls(2);
return currentConsole;
@ -551,18 +753,18 @@ void consoleDebugInit(debugDevice device){
int buffertype = _IONBF;
switch(device) {
case debugDevice_3DMOO:
devoptab_list[STD_ERR] = &dotab_3dmoo;
buffertype = _IOLBF;
break;
case debugDevice_CONSOLE:
devoptab_list[STD_ERR] = &dotab_stdout;
break;
case debugDevice_NULL:
devoptab_list[STD_ERR] = &dotab_null;
break;
switch(device)
{
case debugDevice_SVC:
devoptab_list[STD_ERR] = &dotab_svc;
buffertype = _IOLBF;
break;
case debugDevice_CONSOLE:
devoptab_list[STD_ERR] = &dotab_stdout;
break;
case debugDevice_NULL:
devoptab_list[STD_ERR] = &dotab_null;
break;
}
setvbuf(stderr, NULL , buffertype, 0);
@ -609,7 +811,7 @@ static void newRow() {
src += 240;
}
consoleClearLine('2');
consoleClearLine(2);
}
}
//---------------------------------------------------------------------------------
@ -620,24 +822,29 @@ void consoleDrawChar(int c) {
u8 *fontdata = currentConsole->font.gfx + (8 * c);
int writingColor = currentConsole->fg;
int screenColor = currentConsole->bg;
u16 fg = currentConsole->fg;
u16 bg = currentConsole->bg;
if (currentConsole->flags & CONSOLE_COLOR_BOLD) {
writingColor += 8;
} else if (currentConsole->flags & CONSOLE_COLOR_FAINT) {
writingColor += 16;
if (!(currentConsole->flags & CONSOLE_FG_CUSTOM)) {
if (currentConsole->flags & CONSOLE_COLOR_BOLD) {
fg = colorTable[fg + 8];
} else if (currentConsole->flags & CONSOLE_COLOR_FAINT) {
fg = colorTable[fg + 16];
} else {
fg = colorTable[fg];
}
}
if (!(currentConsole->flags & CONSOLE_BG_CUSTOM)) {
bg = colorTable[bg];
}
if (currentConsole->flags & CONSOLE_COLOR_REVERSE) {
int tmp = writingColor;
writingColor = screenColor;
screenColor = tmp;
u16 tmp = fg;
fg = bg;
bg = tmp;
}
u16 bg = colorTable[screenColor];
u16 fg = colorTable[writingColor];
u8 b1 = *(fontdata++);
u8 b2 = *(fontdata++);
u8 b3 = *(fontdata++);
@ -735,7 +942,7 @@ void consolePrintChar(int c) {
//---------------------------------------------------------------------------------
void consoleClear(void) {
//---------------------------------------------------------------------------------
iprintf("\x1b[2J");
consoleCls(2);
}
//---------------------------------------------------------------------------------
@ -753,5 +960,3 @@ void consoleSetWindow(PrintConsole* console, int x, int y, int width, int height
console->cursorY = 0;
}

Some files were not shown because too many files have changed in this diff Show More